Linux-RISC-V Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] riscv: spacemit: add gpio support for K3 SoC
@ 2026-01-03 21:33 Yixun Lan
  2026-01-03 21:33 ` [PATCH v2 1/2] dt-bindings: gpio: spacemit: add compatible name " Yixun Lan
  2026-01-03 21:33 ` [PATCH v2 2/2] gpio: spacemit: Add GPIO support " Yixun Lan
  0 siblings, 2 replies; 5+ messages in thread
From: Yixun Lan @ 2026-01-03 21:33 UTC (permalink / raw)
  To: Bartosz Golaszewski, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-gpio, devicetree, linux-riscv, spacemit, linux-kernel,
	Yixun Lan, Krzysztof Kozlowski

Introduce gpio support for SpacemiT K3 SoC, the gpio controller
changes its register layout and bank offset, while mostly shares
other IP logic, so adjust the driver to support this.

Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
Changes in v2:
- collect tags
- refactor gpio register read/write, introduce helper function
- Link to v1: https://lore.kernel.org/r/20251229-02-k3-gpio-v1-0-269e76785abb@gentoo.org

---
Yixun Lan (2):
      dt-bindings: gpio: spacemit: add compatible name for K3 SoC
      gpio: spacemit: Add GPIO support for K3 SoC

 .../devicetree/bindings/gpio/spacemit,k1-gpio.yaml |   4 +-
 drivers/gpio/gpio-spacemit-k1.c                    | 163 +++++++++++++++------
 2 files changed, 120 insertions(+), 47 deletions(-)
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20251229-02-k3-gpio-89b6e95cdf65

Best regards,
-- 
Yixun Lan


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v2 1/2] dt-bindings: gpio: spacemit: add compatible name for K3 SoC
  2026-01-03 21:33 [PATCH v2 0/2] riscv: spacemit: add gpio support for K3 SoC Yixun Lan
@ 2026-01-03 21:33 ` Yixun Lan
  2026-01-03 21:33 ` [PATCH v2 2/2] gpio: spacemit: Add GPIO support " Yixun Lan
  1 sibling, 0 replies; 5+ messages in thread
From: Yixun Lan @ 2026-01-03 21:33 UTC (permalink / raw)
  To: Bartosz Golaszewski, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-gpio, devicetree, linux-riscv, spacemit, linux-kernel,
	Yixun Lan, Krzysztof Kozlowski

Add new compatible string for SpacemiT K3 SoC's GPIO controller.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
 Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
index 83e0b2d14c9f..24d22d95665f 100644
--- a/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
+++ b/Documentation/devicetree/bindings/gpio/spacemit,k1-gpio.yaml
@@ -19,7 +19,9 @@ properties:
     pattern: "^gpio@[0-9a-f]+$"
 
   compatible:
-    const: spacemit,k1-gpio
+    enum:
+      - spacemit,k1-gpio
+      - spacemit,k3-gpio
 
   reg:
     maxItems: 1

-- 
2.52.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* [PATCH v2 2/2] gpio: spacemit: Add GPIO support for K3 SoC
  2026-01-03 21:33 [PATCH v2 0/2] riscv: spacemit: add gpio support for K3 SoC Yixun Lan
  2026-01-03 21:33 ` [PATCH v2 1/2] dt-bindings: gpio: spacemit: add compatible name " Yixun Lan
@ 2026-01-03 21:33 ` Yixun Lan
  2026-01-05  9:23   ` Bartosz Golaszewski
  1 sibling, 1 reply; 5+ messages in thread
From: Yixun Lan @ 2026-01-03 21:33 UTC (permalink / raw)
  To: Bartosz Golaszewski, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: linux-gpio, devicetree, linux-riscv, spacemit, linux-kernel,
	Yixun Lan

SpacemiT K3 SoC has changed gpio register layout while comparing
with previous generation, the register offset and bank offset
need to be adjusted, introduce a compatible data to extend the
driver to support this.

Signed-off-by: Yixun Lan <dlan@gentoo.org>
---
 drivers/gpio/gpio-spacemit-k1.c | 163 ++++++++++++++++++++++++++++------------
 1 file changed, 117 insertions(+), 46 deletions(-)

diff --git a/drivers/gpio/gpio-spacemit-k1.c b/drivers/gpio/gpio-spacemit-k1.c
index eb66a15c002f..bca5c3dc13ca 100644
--- a/drivers/gpio/gpio-spacemit-k1.c
+++ b/drivers/gpio/gpio-spacemit-k1.c
@@ -15,29 +15,37 @@
 #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)
+#define to_spacemit_gpio_regs(gb) ((gb)->sg->data->offsets)
+
+enum spacemit_gpio_registers {
+	SPACEMIT_GPLR = 0,	/* port level - R */
+	SPACEMIT_GPDR,		/* port direction - R/W */
+	SPACEMIT_GPSR,		/* port set - W */
+	SPACEMIT_GPCR,		/* port clear - W */
+	SPACEMIT_GRER,		/* port rising edge R/W */
+	SPACEMIT_GFER,		/* port falling edge R/W */
+	SPACEMIT_GEDR,		/* edge detect status - R/W1C */
+	SPACEMIT_GSDR,		/* (set) direction - W */
+	SPACEMIT_GCDR,		/* (clear) direction - W */
+	SPACEMIT_GSRER,		/* (set) rising edge detect enable - W */
+	SPACEMIT_GCRER,		/* (clear) rising edge detect enable - W */
+	SPACEMIT_GSFER,		/* (set) falling edge detect enable - W */
+	SPACEMIT_GCFER,		/* (clear) falling edge detect enable - W */
+	SPACEMIT_GAPMASK,	/* interrupt mask , 0 disable, 1 enable - R/W */
+	SPACEMIT_GCPMASK,	/* interrupt mask for K3 */
+};
 
 struct spacemit_gpio;
 
+struct spacemit_gpio_data {
+	const unsigned int *offsets;
+	u32 bank_offsets[SPACEMIT_NR_BANKS];
+};
+
 struct spacemit_gpio_bank {
 	struct gpio_generic_chip chip;
 	struct spacemit_gpio *sg;
@@ -49,9 +57,22 @@ struct spacemit_gpio_bank {
 
 struct spacemit_gpio {
 	struct device *dev;
+	const struct spacemit_gpio_data *data;
 	struct spacemit_gpio_bank sgb[SPACEMIT_NR_BANKS];
 };
 
+static u32 spacemit_gpio_read(struct spacemit_gpio_bank *gb,
+			      enum spacemit_gpio_registers reg)
+{
+	return readl(gb->base + to_spacemit_gpio_regs(gb)[reg]);
+}
+
+static void spacemit_gpio_write(struct spacemit_gpio_bank *gb,
+				enum spacemit_gpio_registers reg, u32 val)
+{
+	writel(val, gb->base + to_spacemit_gpio_regs(gb)[reg]);
+}
+
 static u32 spacemit_gpio_bank_index(struct spacemit_gpio_bank *gb)
 {
 	return (u32)(gb - gb->sg->sgb);
@@ -63,10 +84,10 @@ static irqreturn_t spacemit_gpio_irq_handler(int irq, void *dev_id)
 	unsigned long pending;
 	u32 n, gedr;
 
-	gedr = readl(gb->base + SPACEMIT_GEDR);
+	gedr = spacemit_gpio_read(gb, SPACEMIT_GEDR);
 	if (!gedr)
 		return IRQ_NONE;
-	writel(gedr, gb->base + SPACEMIT_GEDR);
+	spacemit_gpio_write(gb, SPACEMIT_GEDR, gedr);
 
 	pending = gedr & gb->irq_mask;
 	if (!pending)
@@ -82,7 +103,7 @@ 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);
+	spacemit_gpio_write(gb, SPACEMIT_GEDR, BIT(irqd_to_hwirq(d)));
 }
 
 static void spacemit_gpio_irq_mask(struct irq_data *d)
@@ -91,13 +112,13 @@ static void spacemit_gpio_irq_mask(struct irq_data *d)
 	u32 bit = BIT(irqd_to_hwirq(d));
 
 	gb->irq_mask &= ~bit;
-	writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
+	spacemit_gpio_write(gb, SPACEMIT_GAPMASK, gb->irq_mask);
 
 	if (bit & gb->irq_rising_edge)
-		writel(bit, gb->base + SPACEMIT_GCRER);
+		spacemit_gpio_write(gb, SPACEMIT_GCRER, bit);
 
 	if (bit & gb->irq_falling_edge)
-		writel(bit, gb->base + SPACEMIT_GCFER);
+		spacemit_gpio_write(gb, SPACEMIT_GCFER, bit);
 }
 
 static void spacemit_gpio_irq_unmask(struct irq_data *d)
@@ -108,12 +129,12 @@ static void spacemit_gpio_irq_unmask(struct irq_data *d)
 	gb->irq_mask |= bit;
 
 	if (bit & gb->irq_rising_edge)
-		writel(bit, gb->base + SPACEMIT_GSRER);
+		spacemit_gpio_write(gb, SPACEMIT_GSRER, bit);
 
 	if (bit & gb->irq_falling_edge)
-		writel(bit, gb->base + SPACEMIT_GSFER);
+		spacemit_gpio_write(gb, SPACEMIT_GSFER, bit);
 
-	writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
+	spacemit_gpio_write(gb, SPACEMIT_GAPMASK, gb->irq_mask);
 }
 
 static int spacemit_gpio_irq_set_type(struct irq_data *d, unsigned int type)
@@ -123,18 +144,18 @@ static int spacemit_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 
 	if (type & IRQ_TYPE_EDGE_RISING) {
 		gb->irq_rising_edge |= bit;
-		writel(bit, gb->base + SPACEMIT_GSRER);
+		spacemit_gpio_write(gb, SPACEMIT_GSRER, bit);
 	} else {
 		gb->irq_rising_edge &= ~bit;
-		writel(bit, gb->base + SPACEMIT_GCRER);
+		spacemit_gpio_write(gb, SPACEMIT_GCRER, bit);
 	}
 
 	if (type & IRQ_TYPE_EDGE_FALLING) {
 		gb->irq_falling_edge |= bit;
-		writel(bit, gb->base + SPACEMIT_GSFER);
+		spacemit_gpio_write(gb, SPACEMIT_GSFER, bit);
 	} else {
 		gb->irq_falling_edge &= ~bit;
-		writel(bit, gb->base + SPACEMIT_GCFER);
+		spacemit_gpio_write(gb, SPACEMIT_GCFER, bit);
 	}
 
 	return 0;
@@ -179,15 +200,16 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
 	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 };
+	int ret;
 
-	gb->base = regs + bank_base[index];
+	gb->base = regs + sg->data->bank_offsets[index];
+	gb->sg = sg;
 
-	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;
+	dat	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPLR];
+	set	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPSR];
+	clr	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPCR];
+	dirin	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GCDR];
+	dirout	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GSDR];
 
 	config = (struct gpio_generic_chip_config) {
 		.dev = dev,
@@ -206,8 +228,6 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
 	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;
@@ -223,13 +243,13 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
 	gpio_irq_chip_set_chip(girq, &spacemit_gpio_chip);
 
 	/* Disable Interrupt */
-	writel(0, gb->base + SPACEMIT_GAPMASK);
+	spacemit_gpio_write(gb, SPACEMIT_GAPMASK, 0);
 	/* Disable Edge Detection Settings */
-	writel(0x0, gb->base + SPACEMIT_GRER);
-	writel(0x0, gb->base + SPACEMIT_GFER);
+	spacemit_gpio_write(gb, SPACEMIT_GRER, 0x0);
+	spacemit_gpio_write(gb, SPACEMIT_GFER, 0x0);
 	/* Clear Interrupt */
-	writel(0xffffffff, gb->base + SPACEMIT_GCRER);
-	writel(0xffffffff, gb->base + SPACEMIT_GCFER);
+	spacemit_gpio_write(gb, SPACEMIT_GCRER, 0xffffffff);
+	spacemit_gpio_write(gb, SPACEMIT_GCFER, 0xffffffff);
 
 	ret = devm_request_threaded_irq(dev, irq, NULL,
 					spacemit_gpio_irq_handler,
@@ -260,6 +280,10 @@ static int spacemit_gpio_probe(struct platform_device *pdev)
 	if (!sg)
 		return -ENOMEM;
 
+	sg->data = of_device_get_match_data(dev);
+	if (!sg->data)
+		return dev_err_probe(dev, -EINVAL, "No available compatible data.");
+
 	regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(regs))
 		return PTR_ERR(regs);
@@ -287,8 +311,55 @@ static int spacemit_gpio_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static const unsigned int spacemit_gpio_k1_offsets[] = {
+	0x00,
+	0x0c,
+	0x18,
+	0x24,
+	0x30,
+	0x3c,
+	0x48,
+	0x54,
+	0x60,
+	0x6c,
+	0x78,
+	0x84,
+	0x90,
+	0x9c,
+	0xA8,
+};
+
+static const unsigned int spacemit_gpio_k3_offsets[] = {
+	0x0,
+	0x4,
+	0x8,
+	0xc,
+	0x10,
+	0x14,
+	0x18,
+	0x1c,
+	0x20,
+	0x24,
+	0x28,
+	0x2c,
+	0x30,
+	0x34,
+	0x38,
+};
+
+static const struct spacemit_gpio_data k1_gpio_data = {
+	.offsets = spacemit_gpio_k1_offsets,
+	.bank_offsets = { 0x0, 0x4, 0x8, 0x100 },
+};
+
+static const struct spacemit_gpio_data k3_gpio_data = {
+	.offsets = spacemit_gpio_k3_offsets,
+	.bank_offsets = { 0x0, 0x40, 0x80, 0x100 },
+};
+
 static const struct of_device_id spacemit_gpio_dt_ids[] = {
-	{ .compatible = "spacemit,k1-gpio" },
+	{ .compatible = "spacemit,k1-gpio", .data = &k1_gpio_data },
+	{ .compatible = "spacemit,k3-gpio", .data = &k3_gpio_data },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, spacemit_gpio_dt_ids);
@@ -296,12 +367,12 @@ MODULE_DEVICE_TABLE(of, spacemit_gpio_dt_ids);
 static struct platform_driver spacemit_gpio_driver = {
 	.probe		= spacemit_gpio_probe,
 	.driver		= {
-		.name	= "k1-gpio",
+		.name	= "spacemit-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_DESCRIPTION("GPIO driver for SpacemiT K1/K3 SoC");
 MODULE_LICENSE("GPL");

-- 
2.52.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v2 2/2] gpio: spacemit: Add GPIO support for K3 SoC
  2026-01-03 21:33 ` [PATCH v2 2/2] gpio: spacemit: Add GPIO support " Yixun Lan
@ 2026-01-05  9:23   ` Bartosz Golaszewski
  2026-01-05  9:41     ` Yixun Lan
  0 siblings, 1 reply; 5+ messages in thread
From: Bartosz Golaszewski @ 2026-01-05  9:23 UTC (permalink / raw)
  To: Yixun Lan
  Cc: linux-gpio, devicetree, linux-riscv, spacemit, linux-kernel,
	Bartosz Golaszewski, Linus Walleij, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley

On Sat, 3 Jan 2026 22:33:39 +0100, Yixun Lan <dlan@gentoo.org> said:
> SpacemiT K3 SoC has changed gpio register layout while comparing
> with previous generation, the register offset and bank offset
> need to be adjusted, introduce a compatible data to extend the
> driver to support this.
>
> Signed-off-by: Yixun Lan <dlan@gentoo.org>
> ---
>  drivers/gpio/gpio-spacemit-k1.c | 163 ++++++++++++++++++++++++++++------------
>  1 file changed, 117 insertions(+), 46 deletions(-)
>
> diff --git a/drivers/gpio/gpio-spacemit-k1.c b/drivers/gpio/gpio-spacemit-k1.c
> index eb66a15c002f..bca5c3dc13ca 100644
> --- a/drivers/gpio/gpio-spacemit-k1.c
> +++ b/drivers/gpio/gpio-spacemit-k1.c
> @@ -15,29 +15,37 @@
>  #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)
> +#define to_spacemit_gpio_regs(gb) ((gb)->sg->data->offsets)
> +
> +enum spacemit_gpio_registers {
> +	SPACEMIT_GPLR = 0,	/* port level - R */

No need for the = 0 here.

> +	SPACEMIT_GPDR,		/* port direction - R/W */
> +	SPACEMIT_GPSR,		/* port set - W */
> +	SPACEMIT_GPCR,		/* port clear - W */
> +	SPACEMIT_GRER,		/* port rising edge R/W */
> +	SPACEMIT_GFER,		/* port falling edge R/W */
> +	SPACEMIT_GEDR,		/* edge detect status - R/W1C */
> +	SPACEMIT_GSDR,		/* (set) direction - W */
> +	SPACEMIT_GCDR,		/* (clear) direction - W */
> +	SPACEMIT_GSRER,		/* (set) rising edge detect enable - W */
> +	SPACEMIT_GCRER,		/* (clear) rising edge detect enable - W */
> +	SPACEMIT_GSFER,		/* (set) falling edge detect enable - W */
> +	SPACEMIT_GCFER,		/* (clear) falling edge detect enable - W */
> +	SPACEMIT_GAPMASK,	/* interrupt mask , 0 disable, 1 enable - R/W */
> +	SPACEMIT_GCPMASK,	/* interrupt mask for K3 */
> +};
>
>  struct spacemit_gpio;
>
> +struct spacemit_gpio_data {
> +	const unsigned int *offsets;
> +	u32 bank_offsets[SPACEMIT_NR_BANKS];
> +};
> +
>  struct spacemit_gpio_bank {
>  	struct gpio_generic_chip chip;
>  	struct spacemit_gpio *sg;
> @@ -49,9 +57,22 @@ struct spacemit_gpio_bank {
>
>  struct spacemit_gpio {
>  	struct device *dev;
> +	const struct spacemit_gpio_data *data;
>  	struct spacemit_gpio_bank sgb[SPACEMIT_NR_BANKS];
>  };
>
> +static u32 spacemit_gpio_read(struct spacemit_gpio_bank *gb,
> +			      enum spacemit_gpio_registers reg)
> +{
> +	return readl(gb->base + to_spacemit_gpio_regs(gb)[reg]);
> +}
> +
> +static void spacemit_gpio_write(struct spacemit_gpio_bank *gb,
> +				enum spacemit_gpio_registers reg, u32 val)
> +{
> +	writel(val, gb->base + to_spacemit_gpio_regs(gb)[reg]);
> +}
> +
>  static u32 spacemit_gpio_bank_index(struct spacemit_gpio_bank *gb)
>  {
>  	return (u32)(gb - gb->sg->sgb);
> @@ -63,10 +84,10 @@ static irqreturn_t spacemit_gpio_irq_handler(int irq, void *dev_id)
>  	unsigned long pending;
>  	u32 n, gedr;
>
> -	gedr = readl(gb->base + SPACEMIT_GEDR);
> +	gedr = spacemit_gpio_read(gb, SPACEMIT_GEDR);
>  	if (!gedr)
>  		return IRQ_NONE;
> -	writel(gedr, gb->base + SPACEMIT_GEDR);
> +	spacemit_gpio_write(gb, SPACEMIT_GEDR, gedr);
>
>  	pending = gedr & gb->irq_mask;
>  	if (!pending)
> @@ -82,7 +103,7 @@ 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);
> +	spacemit_gpio_write(gb, SPACEMIT_GEDR, BIT(irqd_to_hwirq(d)));
>  }
>
>  static void spacemit_gpio_irq_mask(struct irq_data *d)
> @@ -91,13 +112,13 @@ static void spacemit_gpio_irq_mask(struct irq_data *d)
>  	u32 bit = BIT(irqd_to_hwirq(d));
>
>  	gb->irq_mask &= ~bit;
> -	writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
> +	spacemit_gpio_write(gb, SPACEMIT_GAPMASK, gb->irq_mask);
>
>  	if (bit & gb->irq_rising_edge)
> -		writel(bit, gb->base + SPACEMIT_GCRER);
> +		spacemit_gpio_write(gb, SPACEMIT_GCRER, bit);
>
>  	if (bit & gb->irq_falling_edge)
> -		writel(bit, gb->base + SPACEMIT_GCFER);
> +		spacemit_gpio_write(gb, SPACEMIT_GCFER, bit);
>  }
>
>  static void spacemit_gpio_irq_unmask(struct irq_data *d)
> @@ -108,12 +129,12 @@ static void spacemit_gpio_irq_unmask(struct irq_data *d)
>  	gb->irq_mask |= bit;
>
>  	if (bit & gb->irq_rising_edge)
> -		writel(bit, gb->base + SPACEMIT_GSRER);
> +		spacemit_gpio_write(gb, SPACEMIT_GSRER, bit);
>
>  	if (bit & gb->irq_falling_edge)
> -		writel(bit, gb->base + SPACEMIT_GSFER);
> +		spacemit_gpio_write(gb, SPACEMIT_GSFER, bit);
>
> -	writel(gb->irq_mask, gb->base + SPACEMIT_GAPMASK);
> +	spacemit_gpio_write(gb, SPACEMIT_GAPMASK, gb->irq_mask);
>  }
>
>  static int spacemit_gpio_irq_set_type(struct irq_data *d, unsigned int type)
> @@ -123,18 +144,18 @@ static int spacemit_gpio_irq_set_type(struct irq_data *d, unsigned int type)
>
>  	if (type & IRQ_TYPE_EDGE_RISING) {
>  		gb->irq_rising_edge |= bit;
> -		writel(bit, gb->base + SPACEMIT_GSRER);
> +		spacemit_gpio_write(gb, SPACEMIT_GSRER, bit);
>  	} else {
>  		gb->irq_rising_edge &= ~bit;
> -		writel(bit, gb->base + SPACEMIT_GCRER);
> +		spacemit_gpio_write(gb, SPACEMIT_GCRER, bit);
>  	}
>
>  	if (type & IRQ_TYPE_EDGE_FALLING) {
>  		gb->irq_falling_edge |= bit;
> -		writel(bit, gb->base + SPACEMIT_GSFER);
> +		spacemit_gpio_write(gb, SPACEMIT_GSFER, bit);
>  	} else {
>  		gb->irq_falling_edge &= ~bit;
> -		writel(bit, gb->base + SPACEMIT_GCFER);
> +		spacemit_gpio_write(gb, SPACEMIT_GCFER, bit);
>  	}
>
>  	return 0;
> @@ -179,15 +200,16 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
>  	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 };
> +	int ret;
>
> -	gb->base = regs + bank_base[index];
> +	gb->base = regs + sg->data->bank_offsets[index];
> +	gb->sg = sg;
>
> -	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;
> +	dat	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPLR];
> +	set	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPSR];
> +	clr	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GPCR];
> +	dirin	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GCDR];
> +	dirout	= gb->base + to_spacemit_gpio_regs(gb)[SPACEMIT_GSDR];
>
>  	config = (struct gpio_generic_chip_config) {
>  		.dev = dev,
> @@ -206,8 +228,6 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
>  	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;
> @@ -223,13 +243,13 @@ static int spacemit_gpio_add_bank(struct spacemit_gpio *sg,
>  	gpio_irq_chip_set_chip(girq, &spacemit_gpio_chip);
>
>  	/* Disable Interrupt */
> -	writel(0, gb->base + SPACEMIT_GAPMASK);
> +	spacemit_gpio_write(gb, SPACEMIT_GAPMASK, 0);
>  	/* Disable Edge Detection Settings */
> -	writel(0x0, gb->base + SPACEMIT_GRER);
> -	writel(0x0, gb->base + SPACEMIT_GFER);
> +	spacemit_gpio_write(gb, SPACEMIT_GRER, 0x0);
> +	spacemit_gpio_write(gb, SPACEMIT_GFER, 0x0);
>  	/* Clear Interrupt */
> -	writel(0xffffffff, gb->base + SPACEMIT_GCRER);
> -	writel(0xffffffff, gb->base + SPACEMIT_GCFER);
> +	spacemit_gpio_write(gb, SPACEMIT_GCRER, 0xffffffff);
> +	spacemit_gpio_write(gb, SPACEMIT_GCFER, 0xffffffff);
>
>  	ret = devm_request_threaded_irq(dev, irq, NULL,
>  					spacemit_gpio_irq_handler,
> @@ -260,6 +280,10 @@ static int spacemit_gpio_probe(struct platform_device *pdev)
>  	if (!sg)
>  		return -ENOMEM;
>
> +	sg->data = of_device_get_match_data(dev);
> +	if (!sg->data)
> +		return dev_err_probe(dev, -EINVAL, "No available compatible data.");
> +
>  	regs = devm_platform_ioremap_resource(pdev, 0);
>  	if (IS_ERR(regs))
>  		return PTR_ERR(regs);
> @@ -287,8 +311,55 @@ static int spacemit_gpio_probe(struct platform_device *pdev)
>  	return 0;
>  }
>
> +static const unsigned int spacemit_gpio_k1_offsets[] = {
> +	0x00,
> +	0x0c,
> +	0x18,
> +	0x24,
> +	0x30,
> +	0x3c,
> +	0x48,
> +	0x54,
> +	0x60,
> +	0x6c,
> +	0x78,
> +	0x84,
> +	0x90,
> +	0x9c,
> +	0xA8,
> +};
> +
> +static const unsigned int spacemit_gpio_k3_offsets[] = {
> +	0x0,
> +	0x4,
> +	0x8,
> +	0xc,
> +	0x10,
> +	0x14,
> +	0x18,
> +	0x1c,
> +	0x20,
> +	0x24,
> +	0x28,
> +	0x2c,
> +	0x30,
> +	0x34,
> +	0x38,
> +};

I would very much prefer for you to use the

    [ENUM] = 0xVALUE

style of initialization here for better readability.

Otherwise looks good so LGTM on the next iteration.

Bart

> +
> +static const struct spacemit_gpio_data k1_gpio_data = {
> +	.offsets = spacemit_gpio_k1_offsets,
> +	.bank_offsets = { 0x0, 0x4, 0x8, 0x100 },
> +};
> +
> +static const struct spacemit_gpio_data k3_gpio_data = {
> +	.offsets = spacemit_gpio_k3_offsets,
> +	.bank_offsets = { 0x0, 0x40, 0x80, 0x100 },
> +};
> +
>  static const struct of_device_id spacemit_gpio_dt_ids[] = {
> -	{ .compatible = "spacemit,k1-gpio" },
> +	{ .compatible = "spacemit,k1-gpio", .data = &k1_gpio_data },
> +	{ .compatible = "spacemit,k3-gpio", .data = &k3_gpio_data },
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, spacemit_gpio_dt_ids);
> @@ -296,12 +367,12 @@ MODULE_DEVICE_TABLE(of, spacemit_gpio_dt_ids);
>  static struct platform_driver spacemit_gpio_driver = {
>  	.probe		= spacemit_gpio_probe,
>  	.driver		= {
> -		.name	= "k1-gpio",
> +		.name	= "spacemit-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_DESCRIPTION("GPIO driver for SpacemiT K1/K3 SoC");
>  MODULE_LICENSE("GPL");
>
> --
> 2.52.0
>
>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

* Re: [PATCH v2 2/2] gpio: spacemit: Add GPIO support for K3 SoC
  2026-01-05  9:23   ` Bartosz Golaszewski
@ 2026-01-05  9:41     ` Yixun Lan
  0 siblings, 0 replies; 5+ messages in thread
From: Yixun Lan @ 2026-01-05  9:41 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: linux-gpio, devicetree, linux-riscv, spacemit, linux-kernel,
	Linus Walleij, Rob Herring, Krzysztof Kozlowski, Conor Dooley

Hi Bartosz,

On 01:23 Mon 05 Jan     , Bartosz Golaszewski wrote:
> On Sat, 3 Jan 2026 22:33:39 +0100, Yixun Lan <dlan@gentoo.org> said:
> > SpacemiT K3 SoC has changed gpio register layout while comparing
> > with previous generation, the register offset and bank offset
> > need to be adjusted, introduce a compatible data to extend the
> > driver to support this.
> >
> > Signed-off-by: Yixun Lan <dlan@gentoo.org>
> > ---
> >  drivers/gpio/gpio-spacemit-k1.c | 163 ++++++++++++++++++++++++++++------------
> >  1 file changed, 117 insertions(+), 46 deletions(-)
> >
> > diff --git a/drivers/gpio/gpio-spacemit-k1.c b/drivers/gpio/gpio-spacemit-k1.c
> > index eb66a15c002f..bca5c3dc13ca 100644
> > --- a/drivers/gpio/gpio-spacemit-k1.c
> > +++ b/drivers/gpio/gpio-spacemit-k1.c
> > @@ -15,29 +15,37 @@
> >  #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)
> > +#define to_spacemit_gpio_regs(gb) ((gb)->sg->data->offsets)
> > +
> > +enum spacemit_gpio_registers {
> > +	SPACEMIT_GPLR = 0,	/* port level - R */
> 
> No need for the = 0 here.
ok, I will drop it

> > +static const unsigned int spacemit_gpio_k1_offsets[] = {
> > +	0x00,
> > +	0x0c,
> > +	0x18,
> > +	0x24,
> > +	0x30,
> > +	0x3c,
> > +	0x48,
> > +	0x54,
> > +	0x60,
> > +	0x6c,
> > +	0x78,
> > +	0x84,
> > +	0x90,
> > +	0x9c,
> > +	0xA8,
> > +};
> > +
> > +static const unsigned int spacemit_gpio_k3_offsets[] = {
> > +	0x0,
> > +	0x4,
> > +	0x8,
> > +	0xc,
> > +	0x10,
> > +	0x14,
> > +	0x18,
> > +	0x1c,
> > +	0x20,
> > +	0x24,
> > +	0x28,
> > +	0x2c,
> > +	0x30,
> > +	0x34,
> > +	0x38,
> > +};
> 
> I would very much prefer for you to use the
> 
>     [ENUM] = 0xVALUE
> 
> style of initialization here for better readability.
> 
ok, will do

> Otherwise looks good so LGTM on the next iteration.
> 
thanks

-- 
Yixun Lan (dlan)

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

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

end of thread, other threads:[~2026-01-05  9:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-03 21:33 [PATCH v2 0/2] riscv: spacemit: add gpio support for K3 SoC Yixun Lan
2026-01-03 21:33 ` [PATCH v2 1/2] dt-bindings: gpio: spacemit: add compatible name " Yixun Lan
2026-01-03 21:33 ` [PATCH v2 2/2] gpio: spacemit: Add GPIO support " Yixun Lan
2026-01-05  9:23   ` Bartosz Golaszewski
2026-01-05  9:41     ` Yixun Lan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox