Based on upstream Linux:
  da64eb51595b ("gpio: spacemit: Add GPIO support for K3 SoC")

SpacemiT K3 SoC uses different GPIO register and bank layout compared
to old K1 generation. Refactor the driver by moving hard-coded register
offsets into per-SoC tables and locating them via driver data.

Signed-off-by: Yixun Lan <[email protected]>
---
 drivers/gpio/Kconfig         | 11 ++---
 drivers/gpio/spacemit_gpio.c | 97 ++++++++++++++++++++++++++++++--------------
 2 files changed, 72 insertions(+), 36 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a11f3043670..78b4b45be87 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -450,12 +450,13 @@ config SANDBOX_GPIO_COUNT
          Select a suitable value depending on your needs.
 
 config SPACEMIT_GPIO
-       bool "Spacemit K1 GPIO driver"
-       depends on DM_GPIO && TARGET_SPACEMIT_K1
+       bool "Spacemit K1/K3 GPIO driver"
+       depends on DM_GPIO && (TARGET_SPACEMIT_K1 || TARGET_SPACEMIT_K3)
        help
-         Support the GPIO device in Spacemit SoCs. The GPIOs are arranged
-         into a number of banks (different for each SoC type) each with 32
-         GPIOs.
+         Support the GPIO device in Spacemit K1 and K3 SoCs. The GPIOs are
+         arranged into a number of banks (different for each SoC type) each
+         with 32 GPIOs.
+
 
 config SUNXI_GPIO
        bool "Allwinner GPIO driver"
diff --git a/drivers/gpio/spacemit_gpio.c b/drivers/gpio/spacemit_gpio.c
index de71880df15..e0716a84dfc 100644
--- a/drivers/gpio/spacemit_gpio.c
+++ b/drivers/gpio/spacemit_gpio.c
@@ -19,37 +19,28 @@
 #define GPIO_TO_BANK(pin)      ((pin) / GPIO_BANK_SIZE)
 #define GPIO_TO_BIT(pin)       ((pin) % GPIO_BANK_SIZE)
 
-static inline int gpio_to_reg_offset(unsigned int pin)
-{
-       unsigned int bank = GPIO_TO_BANK(pin);
-
-       if (bank == 0)
-               return 0;
-       else if (bank == 1)
-               return 4;
-       else if (bank == 2)
-               return 8;
-       else if (bank == 3)
-               return 0x100;
-       log_warning("Use default GPIO bank for an invalid GPIO[%d].\n", pin);
-       return 0;
-}
-
-#define REG_PLR(pin)           (0x00 + gpio_to_reg_offset(pin))
-#define REG_PDR(pin)           (0x0c + gpio_to_reg_offset(pin))
-#define REG_PSR(pin)           (0x18 + gpio_to_reg_offset(pin))
-#define REG_PCR(pin)           (0x24 + gpio_to_reg_offset(pin))
-#define REG_SDR(pin)           (0x54 + gpio_to_reg_offset(pin))
-#define REG_CDR(pin)           (0x60 + gpio_to_reg_offset(pin))
+#define to_spacemit_gpio_regs(priv, reg)       ((priv)->data->offsets[reg])
+
+enum spacemit_gpio_registers {
+       SPACEMIT_GPLR,
+       SPACEMIT_GPDR,
+       SPACEMIT_GPSR,
+       SPACEMIT_GPCR,
+       SPACEMIT_GSDR,
+       SPACEMIT_GCDR,
+};
 
 struct spacemit_gpio_data {
        u16     gpio_base;
        u16     gpio_count;
        u8      num_banks;
+       const u16       *bank_offsets;
+       const u16       *offsets;
 };
 
 struct spacemit_gpio_priv {
        void __iomem *regs;
+       const struct spacemit_gpio_data *data;
 };
 
 static int spacemit_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
@@ -85,10 +76,12 @@ static int spacemit_gpio_xlate(struct udevice *dev, struct 
gpio_desc *desc,
 static int spacemit_gpio_get_value(struct udevice *dev, unsigned int offset)
 {
        struct spacemit_gpio_priv *priv = dev_get_priv(dev);
-       void __iomem *addr;
+       void __iomem *base, *addr;
        u32 value, mask;
 
-       addr = priv->regs + REG_PLR(offset);
+       base = priv->regs + priv->data->bank_offsets[GPIO_TO_BANK(offset)];
+
+       addr = base + to_spacemit_gpio_regs(priv, SPACEMIT_GPLR);
        value = readl(addr);
        mask = 1 << GPIO_TO_BIT(offset);
        return !!(value & mask);
@@ -97,10 +90,12 @@ static int spacemit_gpio_get_value(struct udevice *dev, 
unsigned int offset)
 static int spacemit_gpio_get_function(struct udevice *dev, unsigned int offset)
 {
        struct spacemit_gpio_priv *priv = dev_get_priv(dev);
-       void __iomem *addr;
+       void __iomem *base, *addr;
        u32 value, mask;
 
-       addr = priv->regs + REG_PDR(offset);
+       base = priv->regs + priv->data->bank_offsets[GPIO_TO_BANK(offset)];
+
+       addr = base + to_spacemit_gpio_regs(priv, SPACEMIT_GPDR);
        value = readl(addr);
        mask = 1 << GPIO_TO_BIT(offset);
        if (value & mask)
@@ -130,23 +125,25 @@ static int spacemit_gpio_set_flags(struct udevice *dev, 
unsigned int offset,
                                   ulong flags)
 {
        struct spacemit_gpio_priv *priv = dev_get_priv(dev);
-       void __iomem *addr;
+       void __iomem *base, *addr;
        int value;
 
+       base = priv->regs + priv->data->bank_offsets[GPIO_TO_BANK(offset)];
+
        value = (flags & GPIOD_IS_OUT_ACTIVE) ? 1 : 0;
        if (flags & GPIOD_IS_IN) {
-               addr = priv->regs + REG_CDR(offset);
+               addr = base + to_spacemit_gpio_regs(priv, SPACEMIT_GCDR);
                writel(1 << GPIO_TO_BIT(offset), addr);
        }
        if (flags & GPIOD_IS_OUT) {
                if (value) {
-                       addr = priv->regs + REG_PSR(offset);
+                       addr = base + to_spacemit_gpio_regs(priv, 
SPACEMIT_GPSR);
                        writel(1 << GPIO_TO_BIT(offset), addr);
                } else {
-                       addr = priv->regs + REG_PCR(offset);
+                       addr = base + to_spacemit_gpio_regs(priv, 
SPACEMIT_GPCR);
                        writel(1 << GPIO_TO_BIT(offset), addr);
                }
-               addr = priv->regs + REG_SDR(offset);
+               addr = base + to_spacemit_gpio_regs(priv, SPACEMIT_GSDR);
                writel(1 << GPIO_TO_BIT(offset), addr);
        }
        return 0;
@@ -207,6 +204,7 @@ static int spacemit_gpio_probe(struct udevice *dev)
 
        data = (struct spacemit_gpio_data *)dev_get_driver_data(dev);
        priv = dev_get_priv(dev);
+       priv->data = data;
        priv->regs = dev_read_addr_ptr(dev);
        if (!priv->regs) {
                dev_err(dev, "Fail to get base address\n");
@@ -232,14 +230,51 @@ out:
        return ret;
 }
 
+static const u16 spacemit_gpio_k1_offsets[] = {
+       [SPACEMIT_GPLR] = 0x00,
+       [SPACEMIT_GPDR] = 0x0c,
+       [SPACEMIT_GPSR] = 0x18,
+       [SPACEMIT_GPCR] = 0x24,
+       [SPACEMIT_GSDR] = 0x54,
+       [SPACEMIT_GCDR] = 0x60,
+};
+
+static const u16 spacemit_gpio_k1_bank_offsets[] = {
+       0x0, 0x4, 0x8, 0x100,
+};
+
+static const u16 spacemit_gpio_k3_offsets[] = {
+       [SPACEMIT_GPLR] = 0x00,
+       [SPACEMIT_GPDR] = 0x04,
+       [SPACEMIT_GPSR] = 0x08,
+       [SPACEMIT_GPCR] = 0x0c,
+       [SPACEMIT_GSDR] = 0x1c,
+       [SPACEMIT_GCDR] = 0x20,
+};
+
+static const u16 spacemit_gpio_k3_bank_offsets[] = {
+       0x0, 0x40, 0x80, 0x100,
+};
+
 static const struct spacemit_gpio_data k1_gpio_data = {
        .num_banks      = 4,
        .gpio_count     = 128,
        .gpio_base      = 0,
+       .bank_offsets   = spacemit_gpio_k1_bank_offsets,
+       .offsets        = spacemit_gpio_k1_offsets,
+};
+
+static const struct spacemit_gpio_data k3_gpio_data = {
+       .num_banks      = 4,
+       .gpio_count     = 128,
+       .gpio_base      = 0,
+       .bank_offsets   = spacemit_gpio_k3_bank_offsets,
+       .offsets        = spacemit_gpio_k3_offsets,
 };
 
 static const struct udevice_id spacemit_gpio_ids[] = {
        { .compatible = "spacemit,k1-gpio", .data = (uintptr_t)&k1_gpio_data, },
+       { .compatible = "spacemit,k3-gpio", .data = (uintptr_t)&k3_gpio_data, },
        { /* sentinel */ }
 };
 

---
base-commit: 36c377b9859ffb53eb1e39ea31e8d96d1e0fe1e5
change-id: 20260722-01-gpio-pinctrl-support-87d7b153599b

Best regards,
--  
Yixun Lan <[email protected]>

Reply via email to