* [PATCH v6 0/4] riscv: spacemit: add gpio support for K1 SoC
@ 2025-02-23 11:49 Yixun Lan
2025-02-23 11:49 ` [PATCH v6 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Yixun Lan @ 2025-02-23 11:49 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
Palmer Dabbelt
Cc: Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit, Yixun Lan
The gpio controller of K1 support basic GPIO functions,
which capable of enabling as input, output. It can also be used
as GPIO interrupt which able to detect rising edge, falling edge,
or both. There are four GPIO ports, each consisting of 32 pins and
has indepedent register sets, while still sharing IRQ line and clocks.
The GPIO controller request the clock source from APBC block,
In this series, I haven't added the clock support, but plan
to fix it after clock driver is merged.
Due to first three GPIO ports has interleave register settings, some
resources (IRQ, clock) are shared by all pins.
The GPIO docs of K1 SoC can be found here, chapter 16.4 GPIO [1]
Note, this patch is rebased to v6.14-rc1.
This patch series has been tested on Bananapi-F3 board,
with following GPIO cases passed:
1) gpio input
2) gpio output - set to high, low
3) gpio interrupt - rising trigger, falling trigger, both edge trigger
This version should resolve DT related concern in V4, and register each bank as
indepedent gpio chip in driver, no more sub children gpio DT node needed.
One problem is still not resolved, the interrupt cells parsing isn't corect.
but it works if request gpio irq via gpiod_get() + gpiod_to_irq()
Link: https://developer.spacemit.com/documentation?token=Rn9Kw3iFHirAMgkIpTAcV2Arnkf [1]
Link: https://lore.kernel.org/all/20240730-k1-01-basic-dt-v5-0-98263aae83be@gentoo.org [2]
Link: https://lore.kernel.org/all/20241016-02-k1-pinctrl-v5-0-03d395222e4f@gentoo.org/ [3]
Link: https://lore.kernel.org/all/20250218-gpio-ranges-fourcell-v1-0-b1f3db6c8036@linaro.org [4]
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
Changes in v6:
- rebase to threecell gpio patch which proposed by LinusW at [4],
drop unneeded *xlate(), *add_pin_range() function
- add SPACEMIT prefix to macro
- adjust register comments
- drop 'index' member, instead calculate from offset
- add IRQCHIP_SKIP_SET_WAKE as gpio doesn't support irq wake up
- drop #ifdef CONFIG_OF_GPIO
- move interrupt mask disabling/enabling into irq_*mask()
- Link to v5: https://lore.kernel.org/r/20250217-03-k1-gpio-v5-0-2863ec3e7b67@gentoo.org
Changes in v5:
- export add_pin_range() from gpio core, support to add custom version
- change to 3 gpio cells, model to <bank number>, <bank offset>, <gpio flag>
- fold children DT nodes into parent
- Link to v4: https://lore.kernel.org/r/20250121-03-k1-gpio-v4-0-4641c95c0194@gentoo.org
Changes in v4:
- gpio: re-construct gpio as four independent ports, also leverage gpio mmio API
- gpio interrupt: convert to generic gpio irqchip
- Link to v3: https://lore.kernel.org/r/20241225-03-k1-gpio-v3-0-27bb7b441d62@gentoo.org
Changes in v3:
- dt: drop ranges, interrupt-names property
- Link to v2: https://lore.kernel.org/r/20241219-03-k1-gpio-v2-0-28444fd221cd@gentoo.org
Changes in v2:
- address dt-bindings comments, simplify example
- rebase to 6.13-rc3
- Link to v1: https://lore.kernel.org/r/20240904-03-k1-gpio-v1-0-6072ebeecae0@gentoo.org
---
Yixun Lan (4):
dt-bindings: gpio: spacemit: add support for K1 SoC
gpio: spacemit: add support for K1 SoC
riscv: dts: spacemit: add gpio support for K1 SoC
riscv: dts: spacemit: add gpio LED for system heartbeat
.../devicetree/bindings/gpio/spacemit,k1-gpio.yaml | 81 ++++++
arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts | 11 +
arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi | 3 +
arch/riscv/boot/dts/spacemit/k1.dtsi | 15 ++
drivers/gpio/Kconfig | 8 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-spacemit-k1.c | 277 +++++++++++++++++++++
7 files changed, 396 insertions(+)
---
base-commit: 3d72d603afa72082501e9076eed61e0531339ef8
change-id: 20240828-03-k1-gpio-61bf92f9032c
prerequisite-change-id: 20250217-gpio-ranges-fourcell-85888ad219da:v1
prerequisite-patch-id: 9d4c8b05cc56d25bfb93f3b06420ba6e93340d31
prerequisite-patch-id: a166abd76d3f29768856440830c081bf40511a98
Best regards,
--
Yixun Lan
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 1/4] dt-bindings: gpio: spacemit: add support for K1 SoC
2025-02-23 11:49 [PATCH v6 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
@ 2025-02-23 11:49 ` Yixun Lan
2025-02-24 20:06 ` Rob Herring
2025-02-23 11:49 ` [PATCH v6 2/4] " Yixun Lan
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Yixun Lan @ 2025-02-23 11:49 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
Palmer Dabbelt
Cc: Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit, Yixun Lan
The GPIO controller of K1 support basic functions as input/output,
all pins can be used as interrupt which route to one IRQ line,
trigger type can be select between rising edge, falling edge, or both.
There are four GPIO banks, each consisting of 32 pins.
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
.../devicetree/bindings/gpio/spacemit,k1-gpio.yaml | 81 ++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..017165d325565a6868700a9ac8298b61dffcfef4
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/spacemit,k1-gpio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SpacemiT K1 GPIO controller
+
+maintainers:
+ - Yixun Lan <dlan@gentoo.org>
+
+description:
+ The controller's registers are organized as sets of eight 32-bit
+ registers with each set of port controlling 32 pins. A single
+ interrupt line is shared for all of the pins by the controller.
+
+properties:
+ $nodename:
+ pattern: "^gpio@[0-9a-f]+$"
+
+ compatible:
+ const: spacemit,k1-gpio
+
+ reg:
+ maxItems: 1
+
+ gpio-controller: true
+
+ "#gpio-cells":
+ const: 3
+ description:
+ The first two cells are the GPIO bank index and offset inside the bank,
+ the third cell should specify GPIO flag.
+
+ gpio-ranges: true
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 3
+ description:
+ The first two cells are the GPIO bank index and offset inside the bank,
+ the third cell should specify interrupt flag. The controller does not
+ support level interrupts, so flags of IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW
+ should not be used. Refer <dt-bindings/interrupt-controller/irq.h> for valid flags.
+
+required:
+ - compatible
+ - reg
+ - gpio-controller
+ - "#gpio-cells"
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
+ - gpio-ranges
+
+additionalProperties: false
+
+dependencies:
+ interrupt-controller: [ interrupts ]
+
+examples:
+ - |
+ gpio: gpio@d4019000 {
+ compatible = "spacemit,k1-gpio";
+ reg = <0xd4019000 0x800>;
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupts = <58>;
+ interrupt-controller;
+ interrupt-parent = <&plic>;
+ #interrupt-cells = <3>;
+ gpio-ranges = <&pinctrl 0 0 0 32>,
+ <&pinctrl 1 0 32 32>,
+ <&pinctrl 2 0 64 32>,
+ <&pinctrl 3 0 96 32>;
+ };
+...
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 2/4] gpio: spacemit: add support for K1 SoC
2025-02-23 11:49 [PATCH v6 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
2025-02-23 11:49 ` [PATCH v6 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
@ 2025-02-23 11:49 ` Yixun Lan
2025-02-25 16:19 ` Linus Walleij
2025-02-25 23:41 ` Alex Elder
2025-02-23 11:49 ` [PATCH v6 3/4] riscv: dts: spacemit: add gpio " Yixun Lan
2025-02-23 11:49 ` [PATCH v6 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat Yixun Lan
3 siblings, 2 replies; 8+ messages in thread
From: Yixun Lan @ 2025-02-23 11:49 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
Palmer Dabbelt
Cc: Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit, Yixun Lan
Implement GPIO functionality which capable of setting pin as
input, output. Also, each pin can be used as interrupt which
support rising, falling, or both edge type trigger.
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
drivers/gpio/Kconfig | 8 ++
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-spacemit-k1.c | 277 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 286 insertions(+)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index add5ad29a673c09082a913cb2404073b2034af48..eaae729eec00a3d6d2b83769aed3e2b0ca9927e5 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -655,6 +655,14 @@ config GPIO_SNPS_CREG
where only several fields in register belong to GPIO lines and
each GPIO line owns a field with different length and on/off value.
+config GPIO_SPACEMIT_K1
+ bool "SPACEMIT K1 GPIO support"
+ depends on ARCH_SPACEMIT || COMPILE_TEST
+ depends on OF_GPIO
+ select GPIOLIB_IRQCHIP
+ help
+ Say yes here to support the SpacemiT's K1 GPIO device.
+
config GPIO_SPEAR_SPICS
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
depends on PLAT_SPEAR
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index af3ba4d81b583842893ea69e677fbe2abf31bc7b..6709ce511a0cf10310a94521c85a2d382dcfa696 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -156,6 +156,7 @@ obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
obj-$(CONFIG_GPIO_SLOPPY_LOGIC_ANALYZER) += gpio-sloppy-logic-analyzer.o
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
+obj-$(CONFIG_GPIO_SPACEMIT_K1) += gpio-spacemit-k1.o
obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
diff --git a/drivers/gpio/gpio-spacemit-k1.c b/drivers/gpio/gpio-spacemit-k1.c
new file mode 100644
index 0000000000000000000000000000000000000000..d9a0a10cf76d9b886970753296ce7f4174246f8c
--- /dev/null
+++ b/drivers/gpio/gpio-spacemit-k1.c
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2023-2025 SpacemiT (Hangzhou) Technology Co. Ltd
+ * Copyright (C) 2025 Yixun Lan <dlan@gentoo.org>
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+/* register offset */
+#define SPACEMIT_GPLR 0x00 /* port level - R */
+#define SPACEMIT_GPDR 0x0c /* port direction - R/W */
+#define SPACEMIT_GPSR 0x18 /* port set - W */
+#define SPACEMIT_GPCR 0x24 /* port clear - W */
+#define SPACEMIT_GRER 0x30 /* port rising edge R/W */
+#define SPACEMIT_GFER 0x3c /* port falling edge R/W */
+#define SPACEMIT_GEDR 0x48 /* edge detect status - R/W1C */
+#define SPACEMIT_GSDR 0x54 /* (set) direction - W */
+#define SPACEMIT_GCDR 0x60 /* (clear) direction - W */
+#define SPACEMIT_GSRER 0x6c /* (set) rising edge detect enable - W */
+#define SPACEMIT_GCRER 0x78 /* (clear) rising edge detect enable - W */
+#define SPACEMIT_GSFER 0x84 /* (set) falling edge detect enable - W */
+#define SPACEMIT_GCFER 0x90 /* (clear) falling edge detect enable - W */
+#define SPACEMIT_GAPMASK 0x9c /* interrupt mask , 0 disable, 1 enable - R/W */
+
+#define SPACEMIT_NR_BANKS 4
+#define SPACEMIT_NR_GPIOS_PER_BANK 32
+
+#define to_spacemit_gpio_bank(x) container_of((x), struct spacemit_gpio_bank, gc)
+
+struct spacemit_gpio;
+
+struct spacemit_gpio_bank {
+ struct gpio_chip gc;
+ struct spacemit_gpio *sg;
+ void __iomem *base;
+ u32 irq_mask;
+ u32 irq_rising_edge;
+ u32 irq_falling_edge;
+};
+
+struct spacemit_gpio {
+ struct device *dev;
+ struct spacemit_gpio_bank sgb[SPACEMIT_NR_BANKS];
+};
+
+static u32 spacemit_gpio_bank_index(struct spacemit_gpio_bank *gb)
+{
+ return (u32)(gb - gb->sg->sgb);
+}
+
+static irqreturn_t spacemit_gpio_irq_handler(int irq, void *dev_id)
+{
+ struct spacemit_gpio_bank *gb = dev_id;
+ unsigned long pending;
+ u32 n, gedr;
+
+ gedr = readl(gb->base + SPACEMIT_GEDR);
+ if (!gedr)
+ return IRQ_NONE;
+ writel(gedr, gb->base + SPACEMIT_GEDR);
+
+ pending = gedr & gb->irq_mask;
+ if (!pending)
+ return IRQ_NONE;
+
+ for_each_set_bit(n, &pending, BITS_PER_LONG)
+ handle_nested_irq(irq_find_mapping(gb->gc.irq.domain, n));
+
+ return IRQ_HANDLED;
+}
+
+static void spacemit_gpio_irq_ack(struct irq_data *d)
+{
+ struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
+
+ writel(BIT(irqd_to_hwirq(d)), gb->base + SPACEMIT_GEDR);
+}
+
+static void spacemit_gpio_irq_mask(struct irq_data *d)
+{
+ struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
+ u32 bit = BIT(irqd_to_hwirq(d));
+
+ gb->irq_mask &= ~bit;
+ writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
+
+ if (bit & gb->irq_rising_edge)
+ writel(bit, gb->base + SPACEMIT_GCRER);
+
+ if (bit & gb->irq_falling_edge)
+ writel(bit, gb->base + SPACEMIT_GCFER);
+}
+
+static void spacemit_gpio_irq_unmask(struct irq_data *d)
+{
+ struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
+ u32 bit = BIT(irqd_to_hwirq(d));
+
+ gb->irq_mask |= bit;
+
+ if (bit & gb->irq_rising_edge)
+ writel(bit, gb->base + SPACEMIT_GSRER);
+
+ if (bit & gb->irq_falling_edge)
+ writel(bit, gb->base + SPACEMIT_GSFER);
+
+ writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
+}
+
+static int spacemit_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
+ u32 bit = BIT(irqd_to_hwirq(d));
+
+ if (type & IRQ_TYPE_EDGE_RISING) {
+ gb->irq_rising_edge |= bit;
+ writel(bit, gb->base + SPACEMIT_GSRER);
+ } else {
+ gb->irq_rising_edge &= ~bit;
+ writel(bit, gb->base + SPACEMIT_GCRER);
+ }
+
+ if (type & IRQ_TYPE_EDGE_FALLING) {
+ gb->irq_falling_edge |= bit;
+ writel(bit, gb->base + SPACEMIT_GSFER);
+ } else {
+ gb->irq_falling_edge &= ~bit;
+ writel(bit, gb->base + SPACEMIT_GCFER);
+ }
+
+ return 0;
+}
+
+static void spacemit_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
+{
+ struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(data);
+
+ seq_printf(p, "%s-%d", dev_name(gb->gc.parent), spacemit_gpio_bank_index(gb));
+}
+
+static struct irq_chip spacemit_gpio_chip = {
+ .name = "k1-gpio-irqchip",
+ .irq_ack = spacemit_gpio_irq_ack,
+ .irq_mask = spacemit_gpio_irq_mask,
+ .irq_unmask = spacemit_gpio_irq_unmask,
+ .irq_set_type = spacemit_gpio_irq_set_type,
+ .irq_print_chip = spacemit_gpio_irq_print_chip,
+ .flags = IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE,
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static bool spacemit_of_node_instance_match(struct gpio_chip *gc, unsigned int i)
+{
+ struct spacemit_gpio_bank *gb = gpiochip_get_data(gc);
+ struct spacemit_gpio *sg = gb->sg;
+
+ if (i >= SPACEMIT_NR_BANKS)
+ return false;
+
+ return gc == &sg->sgb[i].gc;
+}
+
+static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
+ void __iomem *regs,
+ int index, int irq)
+{
+ struct spacemit_gpio_bank *gb = &sg->sgb[index];
+ struct gpio_chip *gc = &gb->gc;
+ struct device *dev = sg->dev;
+ struct gpio_irq_chip *girq;
+ void __iomem *dat, *set, *clr, *dirin, *dirout;
+ int ret, bank_base[] = { 0x0, 0x4, 0x8, 0x100 };
+
+ gb->base = regs + bank_base[index];
+
+ dat = gb->base + SPACEMIT_GPLR;
+ set = gb->base + SPACEMIT_GPSR;
+ clr = gb->base + SPACEMIT_GPCR;
+ dirin = gb->base + SPACEMIT_GCDR;
+ dirout = gb->base + SPACEMIT_GSDR;
+
+ /* This registers 32 GPIO lines per bank */
+ ret = bgpio_init(gc, dev, 4, dat, set, clr, dirout, dirin,
+ BGPIOF_UNREADABLE_REG_SET | BGPIOF_UNREADABLE_REG_DIR);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init gpio chip\n");
+
+ gb->sg = sg;
+
+ gc->label = dev_name(dev);
+ gc->request = gpiochip_generic_request;
+ gc->free = gpiochip_generic_free;
+ gc->ngpio = SPACEMIT_NR_GPIOS_PER_BANK;
+ gc->base = -1;
+ gc->of_gpio_n_cells = 3;
+ gc->of_node_instance_match = spacemit_of_node_instance_match;
+
+ girq = &gc->irq;
+ girq->threaded = true;
+ girq->handler = handle_simple_irq;
+
+ gpio_irq_chip_set_chip(girq, &spacemit_gpio_chip);
+
+ /* Disable Interrupt */
+ writel(0, gb->base + SPACEMIT_GAPMASK);
+ /* Disable Edge Detection Settings */
+ writel(0x0, gb->base + SPACEMIT_GRER);
+ writel(0x0, gb->base + SPACEMIT_GFER);
+ /* Clear Interrupt */
+ writel(0xffffffff, gb->base + SPACEMIT_GCRER);
+ writel(0xffffffff, gb->base + SPACEMIT_GCFER);
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ spacemit_gpio_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ gb->gc.label, gb);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to register IRQ\n");
+
+ return devm_gpiochip_add_data(dev, gc, gb);
+}
+
+static int spacemit_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct spacemit_gpio *sg;
+ struct resource *res;
+ void __iomem *regs;
+ int i, irq, ret;
+
+ sg = devm_kzalloc(dev, sizeof(*sg), GFP_KERNEL);
+ if (!sg)
+ return -ENOMEM;
+
+ regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ sg->dev = dev;
+
+ for (i = 0; i < SPACEMIT_NR_BANKS; i++) {
+ ret = spacemit_gpio_add_bank(sg, regs, i, irq);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id spacemit_gpio_dt_ids[] = {
+ { .compatible = "spacemit,k1-gpio" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver spacemit_gpio_driver = {
+ .probe = spacemit_gpio_probe,
+ .driver = {
+ .name = "k1-gpio",
+ .of_match_table = spacemit_gpio_dt_ids,
+ },
+};
+module_platform_driver(spacemit_gpio_driver);
+
+MODULE_AUTHOR("Yixun Lan <dlan@gentoo.org>");
+MODULE_DESCRIPTION("GPIO driver for SpacemiT K1 SoC");
+MODULE_LICENSE("GPL");
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 3/4] riscv: dts: spacemit: add gpio support for K1 SoC
2025-02-23 11:49 [PATCH v6 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
2025-02-23 11:49 ` [PATCH v6 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
2025-02-23 11:49 ` [PATCH v6 2/4] " Yixun Lan
@ 2025-02-23 11:49 ` Yixun Lan
2025-02-23 11:49 ` [PATCH v6 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat Yixun Lan
3 siblings, 0 replies; 8+ messages in thread
From: Yixun Lan @ 2025-02-23 11:49 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
Palmer Dabbelt
Cc: Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit, Yixun Lan
Populate the GPIO node in the device tree for SpacemiT K1 SoC.
Each of 32 pins will act as one bank and map pins to pinctrl controller.
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi | 3 +++
arch/riscv/boot/dts/spacemit/k1.dtsi | 15 +++++++++++++++
2 files changed, 18 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
index a8eac5517f8578d60cb45214589ccb45ac376b9a..283663647a86ff137917ced8bfe79a129c86342a 100644
--- a/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1-pinctrl.dtsi
@@ -7,6 +7,9 @@
#define K1_PADCONF(pin, func) (((pin) << 16) | (func))
+/* Map GPIO pin to each bank's <index, offset> */
+#define K1_GPIO(x) (x / 32) (x % 32)
+
&pinctrl {
uart0_2_cfg: uart0-2-cfg {
uart0-2-pins {
diff --git a/arch/riscv/boot/dts/spacemit/k1.dtsi b/arch/riscv/boot/dts/spacemit/k1.dtsi
index c670ebf8fa12917aa6493fcd89fdd1409529538b..ff86a02c25f2e0818a48ed56c75e911d8612f6d1 100644
--- a/arch/riscv/boot/dts/spacemit/k1.dtsi
+++ b/arch/riscv/boot/dts/spacemit/k1.dtsi
@@ -404,6 +404,21 @@ uart9: serial@d4017800 {
status = "disabled";
};
+ gpio: gpio@d4019000 {
+ compatible = "spacemit,k1-gpio";
+ reg = <0x0 0xd4019000 0x0 0x100>;
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupts = <58>;
+ interrupt-parent = <&plic>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ gpio-ranges = <&pinctrl 0 0 0 32>,
+ <&pinctrl 1 0 32 32>,
+ <&pinctrl 2 0 64 32>,
+ <&pinctrl 3 0 96 32>;
+ };
+
pinctrl: pinctrl@d401e000 {
compatible = "spacemit,k1-pinctrl";
reg = <0x0 0xd401e000 0x0 0x400>;
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v6 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat
2025-02-23 11:49 [PATCH v6 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
` (2 preceding siblings ...)
2025-02-23 11:49 ` [PATCH v6 3/4] riscv: dts: spacemit: add gpio " Yixun Lan
@ 2025-02-23 11:49 ` Yixun Lan
3 siblings, 0 replies; 8+ messages in thread
From: Yixun Lan @ 2025-02-23 11:49 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
Palmer Dabbelt
Cc: Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit, Yixun Lan
Leverage GPIO to support system LED to indicate activity of CPUs.
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
index 1d617b40a2d51ee464b57234d248798aeb218643..816ef1bc358ec490aff184d5915d680dbd9f00cb 100644
--- a/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
+++ b/arch/riscv/boot/dts/spacemit/k1-bananapi-f3.dts
@@ -17,6 +17,17 @@ aliases {
chosen {
stdout-path = "serial0";
};
+
+ leds {
+ compatible = "gpio-leds";
+
+ led1 {
+ label = "sys-led";
+ gpios = <&gpio K1_GPIO(96) GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ default-state = "on";
+ };
+ };
};
&uart0 {
--
2.48.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v6 1/4] dt-bindings: gpio: spacemit: add support for K1 SoC
2025-02-23 11:49 ` [PATCH v6 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
@ 2025-02-24 20:06 ` Rob Herring
0 siblings, 0 replies; 8+ messages in thread
From: Rob Herring @ 2025-02-24 20:06 UTC (permalink / raw)
To: Yixun Lan
Cc: Linus Walleij, Bartosz Golaszewski, Krzysztof Kozlowski,
Conor Dooley, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit
On Sun, Feb 23, 2025 at 07:49:32PM +0800, Yixun Lan wrote:
> The GPIO controller of K1 support basic functions as input/output,
> all pins can be used as interrupt which route to one IRQ line,
> trigger type can be select between rising edge, falling edge, or both.
> There are four GPIO banks, each consisting of 32 pins.
>
> Signed-off-by: Yixun Lan <dlan@gentoo.org>
> ---
> .../devicetree/bindings/gpio/spacemit,k1-gpio.yaml | 81 ++++++++++++++++++++++
> 1 file changed, 81 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..017165d325565a6868700a9ac8298b61dffcfef4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
> @@ -0,0 +1,81 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/gpio/spacemit,k1-gpio.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: SpacemiT K1 GPIO controller
> +
> +maintainers:
> + - Yixun Lan <dlan@gentoo.org>
> +
> +description:
> + The controller's registers are organized as sets of eight 32-bit
> + registers with each set of port controlling 32 pins. A single
> + interrupt line is shared for all of the pins by the controller.
> +
> +properties:
> + $nodename:
> + pattern: "^gpio@[0-9a-f]+$"
> +
> + compatible:
> + const: spacemit,k1-gpio
> +
> + reg:
> + maxItems: 1
> +
> + gpio-controller: true
> +
> + "#gpio-cells":
> + const: 3
> + description:
> + The first two cells are the GPIO bank index and offset inside the bank,
> + the third cell should specify GPIO flag.
> +
> + gpio-ranges: true
> +
> + interrupts:
> + maxItems: 1
> +
> + interrupt-controller: true
> +
> + "#interrupt-cells":
> + const: 3
> + description:
> + The first two cells are the GPIO bank index and offset inside the bank,
> + the third cell should specify interrupt flag. The controller does not
> + support level interrupts, so flags of IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW
> + should not be used. Refer <dt-bindings/interrupt-controller/irq.h> for valid flags.
Wrap lines at 80 chars.
> +
> +required:
> + - compatible
> + - reg
> + - gpio-controller
> + - "#gpio-cells"
> + - interrupts
> + - interrupt-controller
> + - "#interrupt-cells"
> + - gpio-ranges
> +
> +additionalProperties: false
> +
> +dependencies:
> + interrupt-controller: [ interrupts ]
You made 'interrupts' always required, so this is redundant.
> +
> +examples:
> + - |
> + gpio: gpio@d4019000 {
Drop unused labels.
> + compatible = "spacemit,k1-gpio";
> + reg = <0xd4019000 0x800>;
> + gpio-controller;
> + #gpio-cells = <3>;
> + interrupts = <58>;
> + interrupt-controller;
> + interrupt-parent = <&plic>;
> + #interrupt-cells = <3>;
> + gpio-ranges = <&pinctrl 0 0 0 32>,
> + <&pinctrl 1 0 32 32>,
> + <&pinctrl 2 0 64 32>,
> + <&pinctrl 3 0 96 32>;
> + };
> +...
>
> --
> 2.48.1
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 2/4] gpio: spacemit: add support for K1 SoC
2025-02-23 11:49 ` [PATCH v6 2/4] " Yixun Lan
@ 2025-02-25 16:19 ` Linus Walleij
2025-02-25 23:41 ` Alex Elder
1 sibling, 0 replies; 8+ messages in thread
From: Linus Walleij @ 2025-02-25 16:19 UTC (permalink / raw)
To: Yixun Lan
Cc: Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit
On Sun, Feb 23, 2025 at 12:50 PM Yixun Lan <dlan@gentoo.org> wrote:
> Implement GPIO functionality which capable of setting pin as
> input, output. Also, each pin can be used as interrupt which
> support rising, falling, or both edge type trigger.
>
> Signed-off-by: Yixun Lan <dlan@gentoo.org>
I really like how this turned out! :)
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 2/4] gpio: spacemit: add support for K1 SoC
2025-02-23 11:49 ` [PATCH v6 2/4] " Yixun Lan
2025-02-25 16:19 ` Linus Walleij
@ 2025-02-25 23:41 ` Alex Elder
1 sibling, 0 replies; 8+ messages in thread
From: Alex Elder @ 2025-02-25 23:41 UTC (permalink / raw)
To: Yixun Lan, Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
Palmer Dabbelt
Cc: Yangyu Chen, Jisheng Zhang, Jesse Taube, Inochi Amaoto,
Icenowy Zheng, Meng Zhang, linux-gpio, devicetree, linux-kernel,
linux-riscv, spacemit
On 2/23/25 5:49 AM, Yixun Lan wrote:
> Implement GPIO functionality which capable of setting pin as
> input, output. Also, each pin can be used as interrupt which
> support rising, falling, or both edge type trigger.
>
> Signed-off-by: Yixun Lan <dlan@gentoo.org>
This looks very good.
Reviewed-by: Alex Elder <elder@riscstar.com>
> ---
> drivers/gpio/Kconfig | 8 ++
> drivers/gpio/Makefile | 1 +
> drivers/gpio/gpio-spacemit-k1.c | 277 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 286 insertions(+)
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index add5ad29a673c09082a913cb2404073b2034af48..eaae729eec00a3d6d2b83769aed3e2b0ca9927e5 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -655,6 +655,14 @@ config GPIO_SNPS_CREG
> where only several fields in register belong to GPIO lines and
> each GPIO line owns a field with different length and on/off value.
>
> +config GPIO_SPACEMIT_K1
> + bool "SPACEMIT K1 GPIO support"
> + depends on ARCH_SPACEMIT || COMPILE_TEST
> + depends on OF_GPIO
> + select GPIOLIB_IRQCHIP
> + help
> + Say yes here to support the SpacemiT's K1 GPIO device.
> +
> config GPIO_SPEAR_SPICS
> bool "ST SPEAr13xx SPI Chip Select as GPIO support"
> depends on PLAT_SPEAR
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index af3ba4d81b583842893ea69e677fbe2abf31bc7b..6709ce511a0cf10310a94521c85a2d382dcfa696 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -156,6 +156,7 @@ obj-$(CONFIG_GPIO_SIOX) += gpio-siox.o
> obj-$(CONFIG_GPIO_SL28CPLD) += gpio-sl28cpld.o
> obj-$(CONFIG_GPIO_SLOPPY_LOGIC_ANALYZER) += gpio-sloppy-logic-analyzer.o
> obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
> +obj-$(CONFIG_GPIO_SPACEMIT_K1) += gpio-spacemit-k1.o
> obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
> obj-$(CONFIG_GPIO_SPRD) += gpio-sprd.o
> obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
> diff --git a/drivers/gpio/gpio-spacemit-k1.c b/drivers/gpio/gpio-spacemit-k1.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..d9a0a10cf76d9b886970753296ce7f4174246f8c
> --- /dev/null
> +++ b/drivers/gpio/gpio-spacemit-k1.c
> @@ -0,0 +1,277 @@
> +// SPDX-License-Identifier: GPL-2.0 OR MIT
> +/*
> + * Copyright (C) 2023-2025 SpacemiT (Hangzhou) Technology Co. Ltd
> + * Copyright (C) 2025 Yixun Lan <dlan@gentoo.org>
> + */
> +
> +#include <linux/gpio/driver.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/seq_file.h>
> +
> +/* register offset */
> +#define SPACEMIT_GPLR 0x00 /* port level - R */
> +#define SPACEMIT_GPDR 0x0c /* port direction - R/W */
> +#define SPACEMIT_GPSR 0x18 /* port set - W */
> +#define SPACEMIT_GPCR 0x24 /* port clear - W */
> +#define SPACEMIT_GRER 0x30 /* port rising edge R/W */
> +#define SPACEMIT_GFER 0x3c /* port falling edge R/W */
> +#define SPACEMIT_GEDR 0x48 /* edge detect status - R/W1C */
> +#define SPACEMIT_GSDR 0x54 /* (set) direction - W */
> +#define SPACEMIT_GCDR 0x60 /* (clear) direction - W */
> +#define SPACEMIT_GSRER 0x6c /* (set) rising edge detect enable - W */
> +#define SPACEMIT_GCRER 0x78 /* (clear) rising edge detect enable - W */
> +#define SPACEMIT_GSFER 0x84 /* (set) falling edge detect enable - W */
> +#define SPACEMIT_GCFER 0x90 /* (clear) falling edge detect enable - W */
> +#define SPACEMIT_GAPMASK 0x9c /* interrupt mask , 0 disable, 1 enable - R/W */
> +
> +#define SPACEMIT_NR_BANKS 4
> +#define SPACEMIT_NR_GPIOS_PER_BANK 32
> +
> +#define to_spacemit_gpio_bank(x) container_of((x), struct spacemit_gpio_bank, gc)
> +
> +struct spacemit_gpio;
> +
> +struct spacemit_gpio_bank {
> + struct gpio_chip gc;
> + struct spacemit_gpio *sg;
> + void __iomem *base;
> + u32 irq_mask;
> + u32 irq_rising_edge;
> + u32 irq_falling_edge;
> +};
> +
> +struct spacemit_gpio {
> + struct device *dev;
> + struct spacemit_gpio_bank sgb[SPACEMIT_NR_BANKS];
> +};
> +
> +static u32 spacemit_gpio_bank_index(struct spacemit_gpio_bank *gb)
> +{
> + return (u32)(gb - gb->sg->sgb);
> +}
> +
> +static irqreturn_t spacemit_gpio_irq_handler(int irq, void *dev_id)
> +{
> + struct spacemit_gpio_bank *gb = dev_id;
> + unsigned long pending;
> + u32 n, gedr;
> +
> + gedr = readl(gb->base + SPACEMIT_GEDR);
> + if (!gedr)
> + return IRQ_NONE;
> + writel(gedr, gb->base + SPACEMIT_GEDR);
> +
> + pending = gedr & gb->irq_mask;
> + if (!pending)
> + return IRQ_NONE;
> +
> + for_each_set_bit(n, &pending, BITS_PER_LONG)
> + handle_nested_irq(irq_find_mapping(gb->gc.irq.domain, n));
> +
> + return IRQ_HANDLED;
> +}
> +
> +static void spacemit_gpio_irq_ack(struct irq_data *d)
> +{
> + struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
> +
> + writel(BIT(irqd_to_hwirq(d)), gb->base + SPACEMIT_GEDR);
> +}
> +
> +static void spacemit_gpio_irq_mask(struct irq_data *d)
> +{
> + struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
> + u32 bit = BIT(irqd_to_hwirq(d));
> +
> + gb->irq_mask &= ~bit;
> + writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
> +
> + if (bit & gb->irq_rising_edge)
> + writel(bit, gb->base + SPACEMIT_GCRER);
> +
> + if (bit & gb->irq_falling_edge)
> + writel(bit, gb->base + SPACEMIT_GCFER);
> +}
> +
> +static void spacemit_gpio_irq_unmask(struct irq_data *d)
> +{
> + struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
> + u32 bit = BIT(irqd_to_hwirq(d));
> +
> + gb->irq_mask |= bit;
> +
> + if (bit & gb->irq_rising_edge)
> + writel(bit, gb->base + SPACEMIT_GSRER);
> +
> + if (bit & gb->irq_falling_edge)
> + writel(bit, gb->base + SPACEMIT_GSFER);
> +
> + writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
> +}
> +
> +static int spacemit_gpio_irq_set_type(struct irq_data *d, unsigned int type)
> +{
> + struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(d);
> + u32 bit = BIT(irqd_to_hwirq(d));
> +
> + if (type & IRQ_TYPE_EDGE_RISING) {
> + gb->irq_rising_edge |= bit;
> + writel(bit, gb->base + SPACEMIT_GSRER);
> + } else {
> + gb->irq_rising_edge &= ~bit;
> + writel(bit, gb->base + SPACEMIT_GCRER);
> + }
> +
> + if (type & IRQ_TYPE_EDGE_FALLING) {
> + gb->irq_falling_edge |= bit;
> + writel(bit, gb->base + SPACEMIT_GSFER);
> + } else {
> + gb->irq_falling_edge &= ~bit;
> + writel(bit, gb->base + SPACEMIT_GCFER);
> + }
> +
> + return 0;
> +}
> +
> +static void spacemit_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
> +{
> + struct spacemit_gpio_bank *gb = irq_data_get_irq_chip_data(data);
> +
> + seq_printf(p, "%s-%d", dev_name(gb->gc.parent), spacemit_gpio_bank_index(gb));
> +}
> +
> +static struct irq_chip spacemit_gpio_chip = {
> + .name = "k1-gpio-irqchip",
> + .irq_ack = spacemit_gpio_irq_ack,
> + .irq_mask = spacemit_gpio_irq_mask,
> + .irq_unmask = spacemit_gpio_irq_unmask,
> + .irq_set_type = spacemit_gpio_irq_set_type,
> + .irq_print_chip = spacemit_gpio_irq_print_chip,
> + .flags = IRQCHIP_IMMUTABLE | IRQCHIP_SKIP_SET_WAKE,
> + GPIOCHIP_IRQ_RESOURCE_HELPERS,
> +};
> +
> +static bool spacemit_of_node_instance_match(struct gpio_chip *gc, unsigned int i)
> +{
> + struct spacemit_gpio_bank *gb = gpiochip_get_data(gc);
> + struct spacemit_gpio *sg = gb->sg;
> +
> + if (i >= SPACEMIT_NR_BANKS)
> + return false;
> +
> + return gc == &sg->sgb[i].gc;
> +}
> +
> +static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
> + void __iomem *regs,
> + int index, int irq)
> +{
> + struct spacemit_gpio_bank *gb = &sg->sgb[index];
> + struct gpio_chip *gc = &gb->gc;
> + struct device *dev = sg->dev;
> + struct gpio_irq_chip *girq;
> + void __iomem *dat, *set, *clr, *dirin, *dirout;
> + int ret, bank_base[] = { 0x0, 0x4, 0x8, 0x100 };
> +
> + gb->base = regs + bank_base[index];
> +
> + dat = gb->base + SPACEMIT_GPLR;
> + set = gb->base + SPACEMIT_GPSR;
> + clr = gb->base + SPACEMIT_GPCR;
> + dirin = gb->base + SPACEMIT_GCDR;
> + dirout = gb->base + SPACEMIT_GSDR;
> +
> + /* This registers 32 GPIO lines per bank */
> + ret = bgpio_init(gc, dev, 4, dat, set, clr, dirout, dirin,
> + BGPIOF_UNREADABLE_REG_SET | BGPIOF_UNREADABLE_REG_DIR);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to init gpio chip\n");
> +
> + gb->sg = sg;
> +
> + gc->label = dev_name(dev);
> + gc->request = gpiochip_generic_request;
> + gc->free = gpiochip_generic_free;
> + gc->ngpio = SPACEMIT_NR_GPIOS_PER_BANK;
> + gc->base = -1;
> + gc->of_gpio_n_cells = 3;
> + gc->of_node_instance_match = spacemit_of_node_instance_match;
> +
> + girq = &gc->irq;
> + girq->threaded = true;
> + girq->handler = handle_simple_irq;
> +
> + gpio_irq_chip_set_chip(girq, &spacemit_gpio_chip);
> +
> + /* Disable Interrupt */
> + writel(0, gb->base + SPACEMIT_GAPMASK);
> + /* Disable Edge Detection Settings */
> + writel(0x0, gb->base + SPACEMIT_GRER);
> + writel(0x0, gb->base + SPACEMIT_GFER);
> + /* Clear Interrupt */
> + writel(0xffffffff, gb->base + SPACEMIT_GCRER);
> + writel(0xffffffff, gb->base + SPACEMIT_GCFER);
> +
> + ret = devm_request_threaded_irq(dev, irq, NULL,
> + spacemit_gpio_irq_handler,
> + IRQF_ONESHOT | IRQF_SHARED,
> + gb->gc.label, gb);
> + if (ret < 0)
> + return dev_err_probe(dev, ret, "failed to register IRQ\n");
> +
> + return devm_gpiochip_add_data(dev, gc, gb);
> +}
> +
> +static int spacemit_gpio_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct spacemit_gpio *sg;
> + struct resource *res;
> + void __iomem *regs;
> + int i, irq, ret;
> +
> + sg = devm_kzalloc(dev, sizeof(*sg), GFP_KERNEL);
> + if (!sg)
> + return -ENOMEM;
> +
> + regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
> + if (IS_ERR(regs))
> + return PTR_ERR(regs);
> +
> + irq = platform_get_irq(pdev, 0);
> + if (irq < 0)
> + return irq;
> +
> + sg->dev = dev;
> +
> + for (i = 0; i < SPACEMIT_NR_BANKS; i++) {
> + ret = spacemit_gpio_add_bank(sg, regs, i, irq);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id spacemit_gpio_dt_ids[] = {
> + { .compatible = "spacemit,k1-gpio" },
> + { /* sentinel */ }
> +};
> +
> +static struct platform_driver spacemit_gpio_driver = {
> + .probe = spacemit_gpio_probe,
> + .driver = {
> + .name = "k1-gpio",
> + .of_match_table = spacemit_gpio_dt_ids,
> + },
> +};
> +module_platform_driver(spacemit_gpio_driver);
> +
> +MODULE_AUTHOR("Yixun Lan <dlan@gentoo.org>");
> +MODULE_DESCRIPTION("GPIO driver for SpacemiT K1 SoC");
> +MODULE_LICENSE("GPL");
>
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-02-25 23:41 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-23 11:49 [PATCH v6 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
2025-02-23 11:49 ` [PATCH v6 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
2025-02-24 20:06 ` Rob Herring
2025-02-23 11:49 ` [PATCH v6 2/4] " Yixun Lan
2025-02-25 16:19 ` Linus Walleij
2025-02-25 23:41 ` Alex Elder
2025-02-23 11:49 ` [PATCH v6 3/4] riscv: dts: spacemit: add gpio " Yixun Lan
2025-02-23 11:49 ` [PATCH v6 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat Yixun Lan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).