From: Andre Przywara <andre.przywara@arm.com>
To: Jagan Teki <jagan@amarulasolutions.com>, u-boot@lists.denx.de
Cc: Samuel Holland <samuel@sholland.org>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Icenowy Zheng <uwu@icenowy.me>,
Maxim Kiselev <bigunclemax@gmail.com>,
Sam Edwards <cfsworks@gmail.com>,
Okhunjon Sobirjonov <okhunjon72@gmail.com>,
linux-sunxi@lists.linux.dev, andre.przywara@arm.com,
andre.przywara@foss.arm.com
Subject: [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio
Date: Thu, 28 Sep 2023 22:54:39 +0100 [thread overview]
Message-ID: <20230928215455.28094-7-andre.przywara@arm.com> (raw)
In-Reply-To: <20230928215455.28094-1-andre.przywara@arm.com>
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)
-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';
--
2.35.8
next prev parent reply other threads:[~2023-09-28 21:57 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-28 21:54 [PATCH v2 00/22] sunxi: Allwinner T113s support Andre Przywara
2023-09-28 21:54 ` [PATCH v2 01/22] sunxi: remove CONFIG_SATAPWR Andre Przywara
2023-10-19 23:51 ` Samuel Holland
2023-10-21 23:27 ` Andre Przywara
2023-10-22 3:34 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 02/22] net: sunxi_emac: chase DT nodes to find PHY regulator Andre Przywara
2023-10-20 0:01 ` Samuel Holland
2023-10-21 23:33 ` Andre Przywara
2023-09-28 21:54 ` [PATCH v2 03/22] sunxi: remove CONFIG_MACPWR Andre Przywara
2023-10-21 4:35 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 04/22] pinctrl: sunxi: move pinctrl code Andre Przywara
2023-10-19 0:18 ` Andre Przywara
2023-10-21 8:21 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 05/22] pinctrl: sunxi: add GPIO in/out wrappers Andre Przywara
2023-10-21 8:30 ` Samuel Holland
2023-10-21 23:46 ` Andre Przywara
2023-09-28 21:54 ` Andre Przywara [this message]
2023-10-21 8:37 ` [PATCH v2 06/22] pinctrl: sunxi: remove struct sunxi_gpio Samuel Holland
2023-09-28 21:54 ` [PATCH v2 07/22] pinctrl: sunxi: remove GPIO_EXTRA_HEADER Andre Przywara
2023-10-21 8:57 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 08/22] pinctrl: sunxi: move PIO_BASE into sunxi_gpio.h Andre Przywara
2023-09-28 21:54 ` [PATCH v2 09/22] pinctrl: sunxi: add new D1 pinctrl support Andre Przywara
2023-10-22 3:31 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 10/22] sunxi: introduce NCAT2 generation model Andre Przywara
2023-10-22 3:40 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 11/22] pinctrl: sunxi: add Allwinner D1 pinctrl description Andre Przywara
2023-10-21 4:34 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 12/22] clk: sunxi: Add support for the D1 CCU Andre Przywara
2023-10-19 23:53 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 13/22] sunxi: clock: D1/R528: Enable PLL LDO during PLL1 setup Andre Przywara
2023-09-28 21:54 ` [PATCH v2 14/22] sunxi: clock: support D1/R528 PLL6 clock Andre Przywara
2023-09-28 21:54 ` [PATCH v2 15/22] Kconfig: sunxi: prepare for using drivers/ram/sunxi Andre Przywara
2023-10-22 3:44 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 16/22] sunxi: add R528/T113-s3/D1(s) DRAM initialisation code Andre Przywara
2023-10-22 3:52 ` Samuel Holland
2023-10-22 22:40 ` Andre Przywara
2023-10-23 2:58 ` Samuel Holland
2023-09-28 21:54 ` [PATCH v2 17/22] sunxi: add Allwinner R528/T113 SoC support Andre Przywara
2023-09-28 21:54 ` [PATCH v2 18/22] sunxi: R528: add SMHC2 pin pull ups support Andre Przywara
2023-09-28 21:54 ` [PATCH v2 19/22] sunxi: refactor serial base addresses to avoid asm/arch/cpu.h Andre Przywara
2023-09-28 21:54 ` [PATCH v2 20/22] riscv: dts: allwinner: Add the D1/D1s SoC devicetree Andre Przywara
2023-09-28 21:54 ` [PATCH v2 21/22] ARM: dts: sunxi: add Allwinner T113-s SoC .dtsi Andre Przywara
2023-09-28 21:54 ` [PATCH v2 22/22] sunxi: add MangoPi MQ-R board support Andre Przywara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230928215455.28094-7-andre.przywara@arm.com \
--to=andre.przywara@arm.com \
--cc=andre.przywara@foss.arm.com \
--cc=bigunclemax@gmail.com \
--cc=cfsworks@gmail.com \
--cc=jagan@amarulasolutions.com \
--cc=jernej.skrabec@gmail.com \
--cc=linux-sunxi@lists.linux.dev \
--cc=okhunjon72@gmail.com \
--cc=samuel@sholland.org \
--cc=u-boot@lists.denx.de \
--cc=uwu@icenowy.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox