On 8/22/26 04:30, Yixun Lan wrote:
> 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]>
> 

Acked-by: E Shattow <[email protected]>

Reply via email to