Message ID | 20230928215455.28094-7-andre.przywara@arm.com |
---|---|
State | Accepted |
Delegated to: | Andre Przywara |
Headers | show |
Series | sunxi: Allwinner T113s support | expand |
Hi Andre, On 9/28/23 16:54, Andre Przywara wrote: > 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 | 40 ++---------- > drivers/gpio/sunxi_gpio.c | 88 ++++++++++++++++---------- > drivers/pinctrl/sunxi/pinctrl-sunxi.c | 14 ++-- > 3 files changed, 66 insertions(+), 76 deletions(-) > > diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h > index 4bc9e8ffcc9..e0fb5b5da63 100644 > --- a/arch/arm/include/asm/arch-sunxi/gpio.h > +++ b/arch/arm/include/asm/arch-sunxi/gpio.h > @@ -31,13 +31,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. > @@ -55,32 +48,11 @@ > #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 > > -/* GPIO bank sizes */ > #define SUNXI_GPIOS_PER_BANK 32 > +#define SUNXI_PINCTRL_BANK_SIZE 0x24 > > #define SUNXI_GPIO_NEXT(__gpio) \ > ((__gpio##_START) + SUNXI_GPIOS_PER_BANK) > @@ -200,19 +172,19 @@ 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]; > }; > > /* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */ > -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_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/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c > index a4b336943b6..fe3f6ed0938 100644 > --- a/drivers/gpio/sunxi_gpio.c > +++ b/drivers/gpio/sunxi_gpio.c > @@ -29,45 +29,61 @@ > * ======================================================================= > */ > > -#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) Now that we've ensured the *_bank functions only get called with pin numbers in the range 0-31, we don't need the masking anymore. But this can be a later cleanup. Reviewed-by: Samuel Holland <samuel@sholland.org> Tested-by: Samuel Holland <samuel@sholland.org> > > -void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val) > +static 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; > +} > + > +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, GPIO_NUM(pin), 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; > @@ -76,54 +92,56 @@ 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, GPIO_NUM(pin)); > } > > -static void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, > - int pin, bool set) > +static void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set) > { > u32 mask = 1U << 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); > } > > -static int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin) > +static int sunxi_gpio_get_output_bank(void *bank_base, int pin) > { > - return !!(readl(&pio->dat) & (1U << pin)); > + return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & (1U << 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, GPIO_NUM(pin), 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, GPIO_NUM(pin), 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); > } > > > @@ -133,7 +151,7 @@ void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val) > static 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, GPIO_NUM(pin), set); > } > @@ -141,7 +159,7 @@ static void sunxi_gpio_set_output(u32 pin, bool set) > static 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, GPIO_NUM(pin)); > } > diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c > index e5102180902..946447e9136 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';
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 4bc9e8ffcc9..e0fb5b5da63 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -31,13 +31,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. @@ -55,32 +48,11 @@ #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 -/* GPIO bank sizes */ #define SUNXI_GPIOS_PER_BANK 32 +#define SUNXI_PINCTRL_BANK_SIZE 0x24 #define SUNXI_GPIO_NEXT(__gpio) \ ((__gpio##_START) + SUNXI_GPIOS_PER_BANK) @@ -200,19 +172,19 @@ 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]; }; /* prototypes for the non-DM GPIO/pinctrl functions, used in the SPL */ -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_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/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index a4b336943b6..fe3f6ed0938 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -29,45 +29,61 @@ * ======================================================================= */ -#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) -void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val) +static 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; +} + +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, GPIO_NUM(pin), 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; @@ -76,54 +92,56 @@ 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, GPIO_NUM(pin)); } -static void sunxi_gpio_set_output_bank(struct sunxi_gpio *pio, - int pin, bool set) +static void sunxi_gpio_set_output_bank(void *bank_base, int pin, bool set) { u32 mask = 1U << 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); } -static int sunxi_gpio_get_output_bank(struct sunxi_gpio *pio, int pin) +static int sunxi_gpio_get_output_bank(void *bank_base, int pin) { - return !!(readl(&pio->dat) & (1U << pin)); + return !!(readl(bank_base + GPIO_DAT_REG_OFFSET) & (1U << 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, GPIO_NUM(pin), 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, GPIO_NUM(pin), 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); } @@ -133,7 +151,7 @@ void sunxi_gpio_set_pull_bank(struct sunxi_gpio *pio, int bank_offset, u32 val) static 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, GPIO_NUM(pin), set); } @@ -141,7 +159,7 @@ static void sunxi_gpio_set_output(u32 pin, bool set) static 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, GPIO_NUM(pin)); } diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index e5102180902..946447e9136 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';
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 | 40 ++---------- drivers/gpio/sunxi_gpio.c | 88 ++++++++++++++++---------- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 14 ++-- 3 files changed, 66 insertions(+), 76 deletions(-)