devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC
@ 2025-02-26  0:41 Yixun Lan
  2025-02-26  0:41 ` [PATCH v7 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Yixun Lan @ 2025-02-26  0:41 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt
  Cc: Alex Elder, 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 correct.
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]
Link: https://lore.kernel.org/all/20250225-gpio-ranges-fourcell-v3-0-860382ba4713@linaro.org [5]
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
Changes in v7:
- dt-binding: fix 80 column, drop unneeded dependencies
- tested with patch v3 of "gpiolib: of: Handle threecell gpios" [5]
- collect review tags
- Link to v6: https://lore.kernel.org/r/20250223-03-k1-gpio-v6-0-db2e4adeef1c@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 |  79 ++++++
 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, 394 insertions(+)
---
base-commit: 3d72d603afa72082501e9076eed61e0531339ef8
change-id: 20240828-03-k1-gpio-61bf92f9032c
prerequisite-change-id: 20250217-gpio-ranges-fourcell-85888ad219da:v3
prerequisite-patch-id: 9d4c8b05cc56d25bfb93f3b06420ba6e93340d31
prerequisite-patch-id: 7949035abd05ec02a9426bb17819d9108e66e0d7

Best regards,
-- 
Yixun Lan


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v7 1/4] dt-bindings: gpio: spacemit: add support for K1 SoC
  2025-02-26  0:41 [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
@ 2025-02-26  0:41 ` Yixun Lan
  2025-02-26 15:55   ` Rob Herring (Arm)
  2025-02-26  0:41 ` [PATCH v7 2/4] " Yixun Lan
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Yixun Lan @ 2025-02-26  0:41 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt
  Cc: Alex Elder, 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.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
 .../devicetree/bindings/gpio/spacemit,k1-gpio.yaml | 79 ++++++++++++++++++++++
 1 file changed, 79 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..dc28135e008a2acaadf0366b9d50d1c2e4954b21
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
@@ -0,0 +1,79 @@
+# 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
+
+examples:
+  - |
+    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] 13+ messages in thread

* [PATCH v7 2/4] gpio: spacemit: add support for K1 SoC
  2025-02-26  0:41 [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
  2025-02-26  0:41 ` [PATCH v7 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
@ 2025-02-26  0:41 ` Yixun Lan
  2025-03-25 10:00   ` Yixun Lan
  2025-02-26  0:41 ` [PATCH v7 3/4] riscv: dts: spacemit: add gpio " Yixun Lan
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Yixun Lan @ 2025-02-26  0:41 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt
  Cc: Alex Elder, 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.

Reviewed-by: Alex Elder <elder@riscstar.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
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..c64ed9628162c46dce7dda59a02ca305facc2917
--- /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] 13+ messages in thread

* [PATCH v7 3/4] riscv: dts: spacemit: add gpio support for K1 SoC
  2025-02-26  0:41 [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
  2025-02-26  0:41 ` [PATCH v7 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
  2025-02-26  0:41 ` [PATCH v7 2/4] " Yixun Lan
@ 2025-02-26  0:41 ` Yixun Lan
  2025-02-26  0:41 ` [PATCH v7 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat Yixun Lan
  2025-02-26  1:01 ` [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
  4 siblings, 0 replies; 13+ messages in thread
From: Yixun Lan @ 2025-02-26  0:41 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt
  Cc: Alex Elder, 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] 13+ messages in thread

* [PATCH v7 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat
  2025-02-26  0:41 [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
                   ` (2 preceding siblings ...)
  2025-02-26  0:41 ` [PATCH v7 3/4] riscv: dts: spacemit: add gpio " Yixun Lan
@ 2025-02-26  0:41 ` Yixun Lan
  2025-02-26  1:01 ` [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
  4 siblings, 0 replies; 13+ messages in thread
From: Yixun Lan @ 2025-02-26  0:41 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt
  Cc: Alex Elder, 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] 13+ messages in thread

* Re: [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC
  2025-02-26  0:41 [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
                   ` (3 preceding siblings ...)
  2025-02-26  0:41 ` [PATCH v7 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat Yixun Lan
@ 2025-02-26  1:01 ` Yixun Lan
  2025-02-26 10:24   ` Linus Walleij
  4 siblings, 1 reply; 13+ messages in thread
From: Yixun Lan @ 2025-02-26  1:01 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt
  Cc: Alex Elder, Yangyu Chen, Jisheng Zhang, Jesse Taube,
	Inochi Amaoto, Icenowy Zheng, Meng Zhang, linux-gpio, devicetree,
	linux-kernel, linux-riscv, spacemit

Hi Linus Walleij:

  I'm quite satisfied with this version, but there is still one problem
of irq parsing that haven't been resolved, although it probably is 
an independent patch that we can submit it later.

  For this, I'm not sure what's the approach we should proceed,
1) if we can get current version merged first then solve it later, or 
2) find a solution now and get it eventually fixed in this cycle

for the detail problem, see comments below

On 08:41 Wed 26 Feb     , Yixun Lan wrote:
> 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 correct.
> but it works if request gpio irq via gpiod_get() + gpiod_to_irq()
> 

Let me iterate a little bit more detail on this..

Current this v7 version work great with request irq from gpio, like:
	pin = devm_gpiod_get_optional(dev, "myirq", GPIOD_IN);
	irq = gpiod_to_irq(pin);
	devm_request_threaded_irq(dev, irq, ..)

but have problem if request irq via of_irq_get(), something like this:
DT part 
	mytst {
		..
		interrupt-parent = <&gpio>;
		interrupts = <1 28 IRQ_TYPE_EDGE_RISING>;
		interrupt-names = "wakeup";
	}

In source code
	irq = of_irq_get_byname(dev->of_node, "wakeup");

I've made an attempt to patch gpiolib to support three cells "interrupts"
syntax, but still fail, it always get last gpio irqchip of four, thus using
the wrong pin (e.g: will always get 3 from gpiochips 0, 1, 2, 3)


> 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]
> Link: https://lore.kernel.org/all/20250225-gpio-ranges-fourcell-v3-0-860382ba4713@linaro.org [5]
> Signed-off-by: Yixun Lan <dlan@gentoo.org>
> ---
> Changes in v7:
> - dt-binding: fix 80 column, drop unneeded dependencies
> - tested with patch v3 of "gpiolib: of: Handle threecell gpios" [5]
> - collect review tags
> - Link to v6: https://lore.kernel.org/r/20250223-03-k1-gpio-v6-0-db2e4adeef1c@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 |  79 ++++++
>  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, 394 insertions(+)
> ---
> base-commit: 3d72d603afa72082501e9076eed61e0531339ef8
> change-id: 20240828-03-k1-gpio-61bf92f9032c
> prerequisite-change-id: 20250217-gpio-ranges-fourcell-85888ad219da:v3
> prerequisite-patch-id: 9d4c8b05cc56d25bfb93f3b06420ba6e93340d31
> prerequisite-patch-id: 7949035abd05ec02a9426bb17819d9108e66e0d7
> 
> Best regards,
> -- 
> Yixun Lan
> 

-- 
Yixun Lan (dlan)
Gentoo Linux Developer
GPG Key ID AABEFD55

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC
  2025-02-26  1:01 ` [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
@ 2025-02-26 10:24   ` Linus Walleij
  2025-02-26 11:59     ` Yixun Lan
  0 siblings, 1 reply; 13+ messages in thread
From: Linus Walleij @ 2025-02-26 10:24 UTC (permalink / raw)
  To: Yixun Lan
  Cc: Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Alex Elder, Yangyu Chen, Jisheng Zhang, Jesse Taube,
	Inochi Amaoto, Icenowy Zheng, Meng Zhang, linux-gpio, devicetree,
	linux-kernel, linux-riscv, spacemit

On Wed, Feb 26, 2025 at 2:01 AM Yixun Lan <dlan@gentoo.org> wrote:

> Current this v7 version work great with request irq from gpio, like:
>         pin = devm_gpiod_get_optional(dev, "myirq", GPIOD_IN);
>         irq = gpiod_to_irq(pin);
>         devm_request_threaded_irq(dev, irq, ..)
>
> but have problem if request irq via of_irq_get(), something like this:
> DT part
>         mytst {
>                 ..
>                 interrupt-parent = <&gpio>;
>                 interrupts = <1 28 IRQ_TYPE_EDGE_RISING>;
>                 interrupt-names = "wakeup";
>         }
>
> In source code
>         irq = of_irq_get_byname(dev->of_node, "wakeup");
>
> I've made an attempt to patch gpiolib to support three cells "interrupts"
> syntax, but still fail, it always get last gpio irqchip of four, thus using
> the wrong pin (e.g: will always get 3 from gpiochips 0, 1, 2, 3)

Right, we need a proper patch to fix this.

Can you paste your patch so I can see if I can spot/fix
the problem?

I think the irq cell parser needs to call out to
of_node_instance_match() - or similar - as well.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC
  2025-02-26 10:24   ` Linus Walleij
@ 2025-02-26 11:59     ` Yixun Lan
  2025-02-26 13:56       ` Yixun Lan
  0 siblings, 1 reply; 13+ messages in thread
From: Yixun Lan @ 2025-02-26 11:59 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Alex Elder, Yangyu Chen, Jisheng Zhang, Jesse Taube,
	Inochi Amaoto, Icenowy Zheng, Meng Zhang, linux-gpio, devicetree,
	linux-kernel, linux-riscv, spacemit

Hi Linus Walleij:

On 11:24 Wed 26 Feb     , Linus Walleij wrote:
> On Wed, Feb 26, 2025 at 2:01 AM Yixun Lan <dlan@gentoo.org> wrote:
> 
> > Current this v7 version work great with request irq from gpio, like:
> >         pin = devm_gpiod_get_optional(dev, "myirq", GPIOD_IN);
> >         irq = gpiod_to_irq(pin);
> >         devm_request_threaded_irq(dev, irq, ..)
> >
> > but have problem if request irq via of_irq_get(), something like this:
> > DT part
> >         mytst {
> >                 ..
> >                 interrupt-parent = <&gpio>;
> >                 interrupts = <1 28 IRQ_TYPE_EDGE_RISING>;
> >                 interrupt-names = "wakeup";
> >         }
> >
> > In source code
> >         irq = of_irq_get_byname(dev->of_node, "wakeup");
> >
> > I've made an attempt to patch gpiolib to support three cells "interrupts"
> > syntax, but still fail, it always get last gpio irqchip of four, thus using
> > the wrong pin (e.g: will always get 3 from gpiochips 0, 1, 2, 3)
> 
> Right, we need a proper patch to fix this.
> 
> Can you paste your patch so I can see if I can spot/fix
> the problem?
> 
> I think the irq cell parser needs to call out to
> of_node_instance_match() - or similar - as well.
do you have any suggestion where to implement this similar function?

I actually miss this logic, the patch here only support parsing
interrupts with 3 cells

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 679ed764cb14..9aa88c3fa485 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1454,6 +1454,10 @@ static int gpiochip_hierarchy_irq_domain_translate(struct irq_domain *d,
 		return irq_domain_translate_twocell(d, fwspec, hwirq, type);
 	}
 
+	if (is_of_node(fwspec->fwnode) && fwspec->param_count == 3) {
+		return irq_domain_translate_threecell(d, fwspec, hwirq, type);
+	}
+
 	/* This is for board files and others not using DT */
 	if (is_fwnode_irqchip(fwspec->fwnode)) {
 		int ret;
@@ -1758,7 +1762,8 @@ static const struct irq_domain_ops gpiochip_domain_ops = {
 	.map	= gpiochip_irq_map,
 	.unmap	= gpiochip_irq_unmap,
 	/* Virtually all GPIO irqchips are twocell:ed */
-	.xlate	= irq_domain_xlate_twocell,
+	/* FIXME: force switch to three cells */
+	.xlate	= irq_domain_xlate_threecell,
 };
 
 static struct irq_domain *gpiochip_simple_create_domain(struct gpio_chip *gc)
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index e432b6a12a32..69a9540ec253 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -568,10 +568,18 @@ int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr,
 int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
 			const u32 *intspec, unsigned int intsize,
 			irq_hw_number_t *out_hwirq, unsigned int *out_type);
+int irq_domain_xlate_threecell(struct irq_domain *d, struct device_node *ctrlr,
+			const u32 *intspec, unsigned int intsize,
+			irq_hw_number_t *out_hwirq, unsigned int *out_type);
 int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
 			const u32 *intspec, unsigned int intsize,
 			irq_hw_number_t *out_hwirq, unsigned int *out_type);
 
+int irq_domain_translate_threecell(struct irq_domain *d,
+				 struct irq_fwspec *fwspec,
+				 unsigned long *out_hwirq,
+				 unsigned int *out_type);
+
 int irq_domain_translate_twocell(struct irq_domain *d,
 				 struct irq_fwspec *fwspec,
 				 unsigned long *out_hwirq,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index ec6d8e72d980..995e5e0ec2db 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1132,6 +1132,17 @@ int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
 }
 EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell);
 
+int irq_domain_xlate_threecell(struct irq_domain *d, struct device_node *ctrlr,
+			const u32 *intspec, unsigned int intsize,
+			irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+	struct irq_fwspec fwspec;
+
+	of_phandle_args_to_fwspec(ctrlr, intspec, intsize, &fwspec);
+	return irq_domain_translate_threecell(d, &fwspec, out_hwirq, out_type);
+}
+EXPORT_SYMBOL_GPL(irq_domain_xlate_threecell);
+
 /**
  * irq_domain_xlate_onetwocell() - Generic xlate for one or two cell bindings
  * @d:		Interrupt domain involved in the translation
@@ -1216,6 +1227,19 @@ int irq_domain_translate_twocell(struct irq_domain *d,
 }
 EXPORT_SYMBOL_GPL(irq_domain_translate_twocell);
 
+int irq_domain_translate_threecell(struct irq_domain *d,
+				 struct irq_fwspec *fwspec,
+				 unsigned long *out_hwirq,
+				 unsigned int *out_type)
+{
+	if (WARN_ON(fwspec->param_count < 3))
+		return -EINVAL;
+	*out_hwirq = fwspec->param[1];
+	*out_type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(irq_domain_translate_threecell);
+
 int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
 			   int node, const struct irq_affinity_desc *affinity)
 {

-- 
Yixun Lan (dlan)
Gentoo Linux Developer
GPG Key ID AABEFD55

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC
  2025-02-26 11:59     ` Yixun Lan
@ 2025-02-26 13:56       ` Yixun Lan
  2025-02-26 15:45         ` Thomas Gleixner
  0 siblings, 1 reply; 13+ messages in thread
From: Yixun Lan @ 2025-02-26 13:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Alex Elder, Yangyu Chen, Jisheng Zhang, Jesse Taube,
	Inochi Amaoto, Icenowy Zheng, Meng Zhang, linux-gpio, devicetree,
	linux-kernel, linux-riscv, spacemit

Hi Linus Walleij:

I went ahead and made further progress on this, and now
the 3 cell interrupts model work fine, although still few issues left

see patch below

On 12:00 Wed 26 Feb     , Yixun Lan wrote:
> Hi Linus Walleij:
> 
> On 11:24 Wed 26 Feb     , Linus Walleij wrote:
> > On Wed, Feb 26, 2025 at 2:01 AM Yixun Lan <dlan@gentoo.org> wrote:
> > 
> > > Current this v7 version work great with request irq from gpio, like:
> > >         pin = devm_gpiod_get_optional(dev, "myirq", GPIOD_IN);
> > >         irq = gpiod_to_irq(pin);
> > >         devm_request_threaded_irq(dev, irq, ..)
> > >
> > > but have problem if request irq via of_irq_get(), something like this:
> > > DT part
> > >         mytst {
> > >                 ..
> > >                 interrupt-parent = <&gpio>;
> > >                 interrupts = <1 28 IRQ_TYPE_EDGE_RISING>;
> > >                 interrupt-names = "wakeup";
> > >         }
> > >
> > > In source code
> > >         irq = of_irq_get_byname(dev->of_node, "wakeup");
> > >
> > > I've made an attempt to patch gpiolib to support three cells "interrupts"
> > > syntax, but still fail, it always get last gpio irqchip of four, thus using
> > > the wrong pin (e.g: will always get 3 from gpiochips 0, 1, 2, 3)
> > 
> > Right, we need a proper patch to fix this.
> > 
> > Can you paste your patch so I can see if I can spot/fix
> > the problem?
> > 
> > I think the irq cell parser needs to call out to
> > of_node_instance_match() - or similar - as well.
> do you have any suggestion where to implement this similar function?
> 
> I actually miss this logic, the patch here only support parsing
> interrupts with 3 cells
> 
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index 679ed764cb14..9aa88c3fa485 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -1454,6 +1454,10 @@ static int gpiochip_hierarchy_irq_domain_translate(struct irq_domain *d,
>  		return irq_domain_translate_twocell(d, fwspec, hwirq, type);
>  	}
>  
> +	if (is_of_node(fwspec->fwnode) && fwspec->param_count == 3) {
> +		return irq_domain_translate_threecell(d, fwspec, hwirq, type);
> +	}
> +
>  	/* This is for board files and others not using DT */
>  	if (is_fwnode_irqchip(fwspec->fwnode)) {
>  		int ret;
> @@ -1758,7 +1762,8 @@ static const struct irq_domain_ops gpiochip_domain_ops = {
>  	.map	= gpiochip_irq_map,
>  	.unmap	= gpiochip_irq_unmap,
>  	/* Virtually all GPIO irqchips are twocell:ed */
> -	.xlate	= irq_domain_xlate_twocell,
> +	/* FIXME: force switch to three cells */
> +	.xlate	= irq_domain_xlate_threecell,
>  };
>  
>  static struct irq_domain *gpiochip_simple_create_domain(struct gpio_chip *gc)
> diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
> index e432b6a12a32..69a9540ec253 100644
> --- a/include/linux/irqdomain.h
> +++ b/include/linux/irqdomain.h
> @@ -568,10 +568,18 @@ int irq_domain_xlate_onecell(struct irq_domain *d, struct device_node *ctrlr,
>  int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
>  			const u32 *intspec, unsigned int intsize,
>  			irq_hw_number_t *out_hwirq, unsigned int *out_type);
> +int irq_domain_xlate_threecell(struct irq_domain *d, struct device_node *ctrlr,
> +			const u32 *intspec, unsigned int intsize,
> +			irq_hw_number_t *out_hwirq, unsigned int *out_type);
>  int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
>  			const u32 *intspec, unsigned int intsize,
>  			irq_hw_number_t *out_hwirq, unsigned int *out_type);
>  
> +int irq_domain_translate_threecell(struct irq_domain *d,
> +				 struct irq_fwspec *fwspec,
> +				 unsigned long *out_hwirq,
> +				 unsigned int *out_type);
> +
>  int irq_domain_translate_twocell(struct irq_domain *d,
>  				 struct irq_fwspec *fwspec,
>  				 unsigned long *out_hwirq,
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index ec6d8e72d980..995e5e0ec2db 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -1132,6 +1132,17 @@ int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
>  }
>  EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell);
>  
> +int irq_domain_xlate_threecell(struct irq_domain *d, struct device_node *ctrlr,
> +			const u32 *intspec, unsigned int intsize,
> +			irq_hw_number_t *out_hwirq, unsigned int *out_type)
> +{
> +	struct irq_fwspec fwspec;
> +
> +	of_phandle_args_to_fwspec(ctrlr, intspec, intsize, &fwspec);
> +	return irq_domain_translate_threecell(d, &fwspec, out_hwirq, out_type);
> +}
> +EXPORT_SYMBOL_GPL(irq_domain_xlate_threecell);
> +
>  /**
>   * irq_domain_xlate_onetwocell() - Generic xlate for one or two cell bindings
>   * @d:		Interrupt domain involved in the translation
> @@ -1216,6 +1227,19 @@ int irq_domain_translate_twocell(struct irq_domain *d,
>  }
>  EXPORT_SYMBOL_GPL(irq_domain_translate_twocell);
>  
> +int irq_domain_translate_threecell(struct irq_domain *d,
> +				 struct irq_fwspec *fwspec,
> +				 unsigned long *out_hwirq,
> +				 unsigned int *out_type)
> +{
> +	if (WARN_ON(fwspec->param_count < 3))
> +		return -EINVAL;
> +	*out_hwirq = fwspec->param[1];
> +	*out_type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(irq_domain_translate_threecell);
> +
>  int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
>  			   int node, const struct irq_affinity_desc *affinity)
>  {
> 

sounds we need to implement .select() or .match() in irq_domain_ops,
then find the irq_domain.. here is a prototype version 

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9aa88c3fa485..73caba47bd2d 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1758,9 +1758,25 @@ static void gpiochip_irq_unmap(struct irq_domain *d, unsigned int irq)
 	irq_set_chip_data(irq, NULL);
 }
 
+static int gpiochip_irq_select(struct irq_domain *d, struct irq_fwspec *fwspec,
+			enum irq_domain_bus_token bus_token)
+{
+	struct fwnode_handle *fwnode = fwspec->fwnode;
+	struct gpio_chip *gc = d->host_data;
+	unsigned int index = fwspec->param[0];
+
+	if (gc->of_gpio_n_cells == 3 && gc->of_node_instance_match)
+		return gc->of_node_instance_match(gc, index);
+
+	return ((fwnode != NULL) && (d->fwnode == fwnode) &&
+		((bus_token == DOMAIN_BUS_ANY) ||
+		(d->bus_token == bus_token)));
+}
+
 static const struct irq_domain_ops gpiochip_domain_ops = {
 	.map	= gpiochip_irq_map,
 	.unmap	= gpiochip_irq_unmap,
+	.select	= gpiochip_irq_select,
 	/* Virtually all GPIO irqchips are twocell:ed */
 	/* FIXME: force switch to three cells */
 	.xlate	= irq_domain_xlate_threecell,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 995e5e0ec2db..c4d18267e86e 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -553,7 +553,7 @@ struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
 	 */
 	mutex_lock(&irq_domain_mutex);
 	list_for_each_entry(h, &irq_domain_list, link) {
-		if (h->ops->select && bus_token != DOMAIN_BUS_ANY)
+		if (h->ops->select /* && bus_token != DOMAIN_BUS_ANY */)
 			rc = h->ops->select(h, fwspec, bus_token);
 		else if (h->ops->match)
 			rc = h->ops->match(h, to_of_node(fwnode), bus_token);
-- 
Yixun Lan (dlan)
Gentoo Linux Developer
GPG Key ID AABEFD55

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC
  2025-02-26 13:56       ` Yixun Lan
@ 2025-02-26 15:45         ` Thomas Gleixner
  2025-02-27  2:12           ` Yixun Lan
  0 siblings, 1 reply; 13+ messages in thread
From: Thomas Gleixner @ 2025-02-26 15:45 UTC (permalink / raw)
  To: Yixun Lan, Linus Walleij
  Cc: Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Conor Dooley, Paul Walmsley, Palmer Dabbelt,
	Alex Elder, Yangyu Chen, Jisheng Zhang, Jesse Taube,
	Inochi Amaoto, Icenowy Zheng, Meng Zhang, linux-gpio, devicetree,
	linux-kernel, linux-riscv, spacemit

On Wed, Feb 26 2025 at 13:56, Yixun Lan wrote:
> sounds we need to implement .select() or .match() in irq_domain_ops,
> then find the irq_domain.. here is a prototype version 
> diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> index 995e5e0ec2db..c4d18267e86e 100644
> --- a/kernel/irq/irqdomain.c
> +++ b/kernel/irq/irqdomain.c
> @@ -553,7 +553,7 @@ struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
>  	 */
>  	mutex_lock(&irq_domain_mutex);
>  	list_for_each_entry(h, &irq_domain_list, link) {
> -		if (h->ops->select && bus_token != DOMAIN_BUS_ANY)
> +		if (h->ops->select /* && bus_token != DOMAIN_BUS_ANY */)

This breaks existing usage and reintroduces the regression, which was
fixed with the commit which added the bus token check....

Thanks,

        tglx

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 1/4] dt-bindings: gpio: spacemit: add support for K1 SoC
  2025-02-26  0:41 ` [PATCH v7 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
@ 2025-02-26 15:55   ` Rob Herring (Arm)
  0 siblings, 0 replies; 13+ messages in thread
From: Rob Herring (Arm) @ 2025-02-26 15:55 UTC (permalink / raw)
  To: Yixun Lan
  Cc: linux-riscv, Palmer Dabbelt, spacemit, Bartosz Golaszewski,
	Paul Walmsley, devicetree, linux-kernel, linux-gpio, Alex Elder,
	Linus Walleij, Krzysztof Kozlowski, Meng Zhang, Icenowy Zheng,
	Inochi Amaoto, Jesse Taube, Yangyu Chen, Conor Dooley,
	Jisheng Zhang, Conor Dooley


On Wed, 26 Feb 2025 08:41:17 +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.
> 
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Yixun Lan <dlan@gentoo.org>
> ---
>  .../devicetree/bindings/gpio/spacemit,k1-gpio.yaml | 79 ++++++++++++++++++++++
>  1 file changed, 79 insertions(+)
> 

Reviewed-by: Rob Herring (Arm) <robh@kernel.org>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC
  2025-02-26 15:45         ` Thomas Gleixner
@ 2025-02-27  2:12           ` Yixun Lan
  0 siblings, 0 replies; 13+ messages in thread
From: Yixun Lan @ 2025-02-27  2:12 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Alex Elder, Yangyu Chen, Jisheng Zhang,
	Jesse Taube, Inochi Amaoto, Icenowy Zheng, Meng Zhang, linux-gpio,
	devicetree, linux-kernel, linux-riscv, spacemit

Hi Thomas Gleixner:

On 16:45 Wed 26 Feb     , Thomas Gleixner wrote:
> On Wed, Feb 26 2025 at 13:56, Yixun Lan wrote:
> > sounds we need to implement .select() or .match() in irq_domain_ops,
> > then find the irq_domain.. here is a prototype version 
> > diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
> > index 995e5e0ec2db..c4d18267e86e 100644
> > --- a/kernel/irq/irqdomain.c
> > +++ b/kernel/irq/irqdomain.c
> > @@ -553,7 +553,7 @@ struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
> >  	 */
> >  	mutex_lock(&irq_domain_mutex);
> >  	list_for_each_entry(h, &irq_domain_list, link) {
> > -		if (h->ops->select && bus_token != DOMAIN_BUS_ANY)
> > +		if (h->ops->select /* && bus_token != DOMAIN_BUS_ANY */)
> 
> This breaks existing usage and reintroduces the regression, which was
> fixed with the commit which added the bus token check....
> 
right, I shouldn't change it.

would setting a bus token explicitly for spacemit gpio be a good idea?
in drivers/gpio/gpio-spacemit-k1.c, something like:

irq_domain_update_bus_token(girq->domain, DOMAIN_BUS_WIRED);

-- 
Yixun Lan (dlan)
Gentoo Linux Developer
GPG Key ID AABEFD55

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v7 2/4] gpio: spacemit: add support for K1 SoC
  2025-02-26  0:41 ` [PATCH v7 2/4] " Yixun Lan
@ 2025-03-25 10:00   ` Yixun Lan
  0 siblings, 0 replies; 13+ messages in thread
From: Yixun Lan @ 2025-03-25 10:00 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt
  Cc: Alex Elder, Yangyu Chen, Jisheng Zhang, Jesse Taube,
	Inochi Amaoto, Icenowy Zheng, Meng Zhang, linux-gpio, devicetree,
	linux-kernel, linux-riscv, spacemit

Hi All:

The gpio controller request clocks to work, I will address this
in next version

also will 
On 08:41 Wed 26 Feb     , 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.
> 
> Reviewed-by: Alex Elder <elder@riscstar.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> 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(+)
> +
...
> +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);
will update to devm_platform_ioremap_resource() to get rid of &res parameter


-- 
Yixun Lan (dlan)
Gentoo Linux Developer
GPG Key ID AABEFD55

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2025-03-25 10:00 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-26  0:41 [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
2025-02-26  0:41 ` [PATCH v7 1/4] dt-bindings: gpio: spacemit: add " Yixun Lan
2025-02-26 15:55   ` Rob Herring (Arm)
2025-02-26  0:41 ` [PATCH v7 2/4] " Yixun Lan
2025-03-25 10:00   ` Yixun Lan
2025-02-26  0:41 ` [PATCH v7 3/4] riscv: dts: spacemit: add gpio " Yixun Lan
2025-02-26  0:41 ` [PATCH v7 4/4] riscv: dts: spacemit: add gpio LED for system heartbeat Yixun Lan
2025-02-26  1:01 ` [PATCH v7 0/4] riscv: spacemit: add gpio support for K1 SoC Yixun Lan
2025-02-26 10:24   ` Linus Walleij
2025-02-26 11:59     ` Yixun Lan
2025-02-26 13:56       ` Yixun Lan
2025-02-26 15:45         ` Thomas Gleixner
2025-02-27  2:12           ` 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).