uboot-sunxi: add T113-S3 support
[openwrt/staging/wigyori.git] / package / boot / uboot-sunxi / patches / 4010-pinctrl-sunxi-remove-struct-sunxi_gpio.patch
diff --git a/package/boot/uboot-sunxi/patches/4010-pinctrl-sunxi-remove-struct-sunxi_gpio.patch b/package/boot/uboot-sunxi/patches/4010-pinctrl-sunxi-remove-struct-sunxi_gpio.patch
new file mode 100644 (file)
index 0000000..ed0f92e
--- /dev/null
@@ -0,0 +1,347 @@
+From 8e8e3f442213d583fed0d9c7666de7a6c05110a2 Mon Sep 17 00:00:00 2001
+From: Andre Przywara <andre.przywara@arm.com>
+Date: Fri, 21 Jul 2023 14:45:50 +0100
+Subject: [PATCH 4010/4052] pinctrl: sunxi: remove struct sunxi_gpio
+
+So far every Allwinner SoC used the same basic pincontroller/GPIO
+register frame, and just differed by the number of implemented banks and
+pins, plus some special functionality from time to time. However the D1
+and successors use a slightly different pinctrl register layout.
+Use that opportunity to drop "struct sunxi_gpio", that described that
+MMIO frame in a C struct. That approach is somewhat frowned upon in the
+Linux world and rarely used there, though still popular with U-Boot.
+
+Switching from a C struct to a "base address plus offset" approach allows
+to switch between the two models more dynamically, without reverting to
+preprocessor macros and #ifdef's.
+
+Model the pinctrl MMIO register frame in the usual "base address +
+offset" way, and replace a hard-to-parse CPP macro with a more readable
+static function.
+All the users get converted over. There are no functional changes at
+this point, it just prepares the stages for the D1 and friends.
+
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+---
+ arch/arm/include/asm/arch-sunxi/gpio.h | 67 +++++++++++---------------
+ arch/arm/mach-sunxi/pinmux.c           | 66 +++++++++++++------------
+ drivers/pinctrl/sunxi/pinctrl-sunxi.c  | 14 +++---
+ 3 files changed, 71 insertions(+), 76 deletions(-)
+
+diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
+index 2e7c84e410..96a29aa023 100644
+--- a/arch/arm/include/asm/arch-sunxi/gpio.h
++++ b/arch/arm/include/asm/arch-sunxi/gpio.h
+@@ -28,13 +28,6 @@
+ #define SUNXI_GPIO_H  7
+ #define SUNXI_GPIO_I  8
+-/*
+- * This defines the number of GPIO banks for the _main_ GPIO controller.
+- * You should fix up the padding in struct sunxi_gpio_reg below if you
+- * change this.
+- */
+-#define SUNXI_GPIO_BANKS 9
+-
+ /*
+  * sun6i/sun8i and later SoCs have an additional GPIO controller (R_PIO)
+  * at a different register offset.
+@@ -52,46 +45,42 @@
+ #define SUNXI_GPIO_M  12
+ #define SUNXI_GPIO_N  13
+-struct sunxi_gpio {
+-      u32 cfg[4];
+-      u32 dat;
+-      u32 drv[2];
+-      u32 pull[2];
+-};
+-
+-/* gpio interrupt control */
+-struct sunxi_gpio_int {
+-      u32 cfg[3];
+-      u32 ctl;
+-      u32 sta;
+-      u32 deb;                /* interrupt debounce */
+-};
+-
+-struct sunxi_gpio_reg {
+-      struct sunxi_gpio gpio_bank[SUNXI_GPIO_BANKS];
+-      u8 res[0xbc];
+-      struct sunxi_gpio_int gpio_int;
+-};
+-
+ #define SUN50I_H6_GPIO_POW_MOD_SEL    0x340
+ #define SUN50I_H6_GPIO_POW_MOD_VAL    0x348
+-#define BANK_TO_GPIO(bank)    (((bank) < SUNXI_GPIO_L) ? \
+-      &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[bank] : \
+-      &((struct sunxi_gpio_reg *)SUNXI_R_PIO_BASE)->gpio_bank[(bank) - SUNXI_GPIO_L])
+-
+ #define GPIO_BANK(pin)                ((pin) >> 5)
+ #define GPIO_NUM(pin)         ((pin) & 0x1f)
++#define GPIO_CFG_REG_OFFSET   0x00
+ #define GPIO_CFG_INDEX(pin)   (((pin) & 0x1f) >> 3)
+ #define GPIO_CFG_OFFSET(pin)  ((((pin) & 0x1f) & 0x7) << 2)
++#define GPIO_DAT_REG_OFFSET   0x10
++
++#define GPIO_DRV_REG_OFFSET   0x14
+ #define GPIO_DRV_INDEX(pin)   (((pin) & 0x1f) >> 4)
+ #define GPIO_DRV_OFFSET(pin)  ((((pin) & 0x1f) & 0xf) << 1)
++#define GPIO_PULL_REG_OFFSET  0x1c
+ #define GPIO_PULL_INDEX(pin)  (((pin) & 0x1f) >> 4)
+ #define GPIO_PULL_OFFSET(pin) ((((pin) & 0x1f) & 0xf) << 1)
++#define SUNXI_PINCTRL_BANK_SIZE 0x24
++
++static inline void* BANK_TO_GPIO(int bank)
++{
++      void *pio_base;
++
++      if (bank < SUNXI_GPIO_L) {
++              pio_base = (void *)(uintptr_t)SUNXI_PIO_BASE;
++      } else {
++              pio_base = (void *)(uintptr_t)SUNXI_R_PIO_BASE;
++              bank -= SUNXI_GPIO_L;
++      }
++
++      return pio_base + bank * SUNXI_PINCTRL_BANK_SIZE;
++}
++
+ /* GPIO bank sizes */
+ #define SUNXI_GPIOS_PER_BANK  32
+@@ -214,22 +203,22 @@ enum sunxi_gpio_number {
+ #define SUNXI_GPIO_AXP0_GPIO_COUNT    6
+ struct sunxi_gpio_plat {
+-      struct sunxi_gpio       *regs;
++      void                    *regs;
+       char                    bank_name[3];
+ };
+-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
++void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val);
+ void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
+-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset);
++int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset);
+ int sunxi_gpio_get_cfgpin(u32 pin);
+-void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, int pin, bool set);
++void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set);
+ void sunxi_gpio_set_output(u32 pin, bool set);
+-int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin);
++int sunxi_gpio_get_output_bank(void *bank_base, int pin);
+ int sunxi_gpio_get_output(u32 pin);
+ void sunxi_gpio_set_drv(u32 pin, u32 val);
+-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val);
++void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val);
+ void sunxi_gpio_set_pull(u32 pin, u32 val);
+-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val);
++void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val);
+ int sunxi_name_to_gpio(const char *name);
+ #if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO
+diff --git a/arch/arm/mach-sunxi/pinmux.c b/arch/arm/mach-sunxi/pinmux.c
+index 751cac8e09..17d1a7bdb9 100644
+--- a/arch/arm/mach-sunxi/pinmux.c
++++ b/arch/arm/mach-sunxi/pinmux.c
+@@ -9,29 +9,30 @@
+ #include <asm/io.h>
+ #include <asm/arch/gpio.h>
+-void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val)
++void sunxi_gpio_set_cfgbank(void *bank_base, int pin_offset, u32 val)
+ {
+-      u32 index = GPIO_CFG_INDEX(bank_offset);
+-      u32 offset = GPIO_CFG_OFFSET(bank_offset);
++      u32 index = GPIO_CFG_INDEX(pin_offset);
++      u32 offset = GPIO_CFG_OFFSET(pin_offset);
+-      clrsetbits_le32(&pio->cfg[index], 0xf << offset, val << offset);
++      clrsetbits_le32(bank_base + GPIO_CFG_REG_OFFSET + index * 4,
++                      0xfU << offset, val << offset);
+ }
+ void sunxi_gpio_set_cfgpin(u32 pin, u32 val)
+ {
+       u32 bank = GPIO_BANK(pin);
+-      struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++      void *pio = BANK_TO_GPIO(bank);
+-      sunxi_gpio_set_cfgbank(pio, pin, val);
++      sunxi_gpio_set_cfgbank(pio, pin % 32, val);
+ }
+-int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
++int sunxi_gpio_get_cfgbank(void *bank_base, int pin_offset)
+ {
+-      u32 index = GPIO_CFG_INDEX(bank_offset);
+-      u32 offset = GPIO_CFG_OFFSET(bank_offset);
++      u32 index = GPIO_CFG_INDEX(pin_offset);
++      u32 offset = GPIO_CFG_OFFSET(pin_offset);
+       u32 cfg;
+-      cfg = readl(&pio->cfg[index]);
++      cfg = readl(bank_base + GPIO_CFG_REG_OFFSET + index * 4);
+       cfg >>= offset;
+       return cfg & 0xf;
+@@ -40,35 +41,38 @@ int sunxi_gpio_get_cfgbank(struct sunxi_gpio *pio, int bank_offset)
+ int sunxi_gpio_get_cfgpin(u32 pin)
+ {
+       u32 bank = GPIO_BANK(pin);
+-      struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++      void *bank_base = BANK_TO_GPIO(bank);
+-      return sunxi_gpio_get_cfgbank(pio, pin);
++      return sunxi_gpio_get_cfgbank(bank_base, pin % 32);
+ }
+-void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, int pin, bool set)
++void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set)
+ {
+       u32 mask = 1U << GPIO_NUM(pin);
+-      clrsetbits_le32(&pio->dat, set ? 0 : mask, set ? mask : 0);
++      clrsetbits_le32(bank_base + GPIO_DAT_REG_OFFSET,
++                      set ? 0 : mask, set ? mask : 0);
+ }
+ void sunxi_gpio_set_output(u32 pin, bool set)
+ {
+       u32 bank = GPIO_BANK(pin);
+-      struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++      void *pio = BANK_TO_GPIO(bank);
+       sunxi_gpio_set_output_bank(pio, pin, set);
+ }
+-int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin)
++int sunxi_gpio_get_output_bank(void *bank_base, int pin)
+ {
+-      return !!(readl(&pio->dat) & (1U << GPIO_NUM(pin)));
++      u32 mask = 1U << GPIO_NUM(pin);
++
++      return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & mask);
+ }
+ int sunxi_gpio_get_output(u32 pin)
+ {
+       u32 bank = GPIO_BANK(pin);
+-      struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++      void *pio = BANK_TO_GPIO(bank);
+       return sunxi_gpio_get_output_bank(pio, pin);
+ }
+@@ -76,31 +80,33 @@ int sunxi_gpio_get_output(u32 pin)
+ void sunxi_gpio_set_drv(u32 pin, u32 val)
+ {
+       u32 bank = GPIO_BANK(pin);
+-      struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++      void *bank_base = BANK_TO_GPIO(bank);
+-      sunxi_gpio_set_drv_bank(pio, pin, val);
++      sunxi_gpio_set_drv_bank(bank_base, pin % 32, val);
+ }
+-void sunxi_gpio_set_drv_bank(struct sunxi_gpio *pio, u32 bank_offset, u32 val)
++void sunxi_gpio_set_drv_bank(void *bank_base, u32 pin_offset, u32 val)
+ {
+-      u32 index = GPIO_DRV_INDEX(bank_offset);
+-      u32 offset = GPIO_DRV_OFFSET(bank_offset);
++      u32 index = GPIO_DRV_INDEX(pin_offset);
++      u32 offset = GPIO_DRV_OFFSET(pin_offset);
+-      clrsetbits_le32(&pio->drv[index], 0x3 << offset, val << offset);
++      clrsetbits_le32(bank_base + GPIO_DRV_REG_OFFSET + index * 4,
++                      0x3U << offset, val << offset);
+ }
+ void sunxi_gpio_set_pull(u32 pin, u32 val)
+ {
+       u32 bank = GPIO_BANK(pin);
+-      struct sunxi_gpio *pio = BANK_TO_GPIO(bank);
++      void *bank_base = BANK_TO_GPIO(bank);
+-      sunxi_gpio_set_pull_bank(pio, pin, val);
++      sunxi_gpio_set_pull_bank(bank_base, pin % 32, val);
+ }
+-void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val)
++void sunxi_gpio_set_pull_bank(void *bank_base, int pin_offset, u32 val)
+ {
+-      u32 index = GPIO_PULL_INDEX(bank_offset);
+-      u32 offset = GPIO_PULL_OFFSET(bank_offset);
++      u32 index = GPIO_PULL_INDEX(pin_offset);
++      u32 offset = GPIO_PULL_OFFSET(pin_offset);
+-      clrsetbits_le32(&pio->pull[index], 0x3 << offset, val << offset);
++      clrsetbits_le32(bank_base + GPIO_PULL_REG_OFFSET + index * 4,
++                      0x3U << offset, val << offset);
+ }
+diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+index c4fbda7a92..b0144edcf4 100644
+--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
++++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+@@ -35,7 +35,7 @@ struct sunxi_pinctrl_desc {
+ };
+ struct sunxi_pinctrl_plat {
+-      struct sunxi_gpio __iomem *base;
++      void __iomem *base;
+ };
+ static int sunxi_pinctrl_get_pins_count(struct udevice *dev)
+@@ -86,8 +86,8 @@ static int sunxi_pinctrl_pinmux_set(struct udevice *dev, uint pin_selector,
+             sunxi_pinctrl_get_function_name(dev, func_selector),
+             desc->functions[func_selector].mux);
+-      sunxi_gpio_set_cfgbank(plat->base + bank, pin,
+-                             desc->functions[func_selector].mux);
++      sunxi_gpio_set_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE,
++                             pin, desc->functions[func_selector].mux);
+       return 0;
+ }
+@@ -102,7 +102,7 @@ static const struct pinconf_param sunxi_pinctrl_pinconf_params[] = {
+ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
+                                         uint bank, uint pin, uint bias)
+ {
+-      struct sunxi_gpio *regs = &plat->base[bank];
++      void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
+       sunxi_gpio_set_pull_bank(regs, pin, bias);
+@@ -112,7 +112,7 @@ static int sunxi_pinctrl_pinconf_set_pull(struct sunxi_pinctrl_plat *plat,
+ static int sunxi_pinctrl_pinconf_set_drive(struct sunxi_pinctrl_plat *plat,
+                                          uint bank, uint pin, uint drive)
+ {
+-      struct sunxi_gpio *regs = &plat->base[bank];
++      void *regs = plat->base + bank * SUNXI_PINCTRL_BANK_SIZE;
+       if (drive < 10 || drive > 40)
+               return -EINVAL;
+@@ -148,7 +148,7 @@ static int sunxi_pinctrl_get_pin_muxing(struct udevice *dev, uint pin_selector,
+       struct sunxi_pinctrl_plat *plat = dev_get_plat(dev);
+       int bank = pin_selector / SUNXI_GPIOS_PER_BANK;
+       int pin  = pin_selector % SUNXI_GPIOS_PER_BANK;
+-      int mux  = sunxi_gpio_get_cfgbank(plat->base + bank, pin);
++      int mux  = sunxi_gpio_get_cfgbank(plat->base + bank * SUNXI_PINCTRL_BANK_SIZE, pin);
+       switch (mux) {
+       case SUNXI_GPIO_INPUT:
+@@ -206,7 +206,7 @@ static int sunxi_pinctrl_bind(struct udevice *dev)
+               if (!gpio_plat)
+                       return -ENOMEM;
+-              gpio_plat->regs = plat->base + i;
++              gpio_plat->regs = plat->base + i * SUNXI_PINCTRL_BANK_SIZE;
+               gpio_plat->bank_name[0] = 'P';
+               gpio_plat->bank_name[1] = 'A' + desc->first_bank + i;
+               gpio_plat->bank_name[2] = '\0';
+-- 
+2.20.1
+