aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/sunxi_gpio.c88
1 files changed, 53 insertions, 35 deletions
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 3ca833316b..d7f6a266e5 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_value_bank(struct sunxi_gpio *pio,
- int pin, bool set)
+static void sunxi_gpio_set_value_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_value_bank(struct sunxi_gpio *pio, int pin)
+static int sunxi_gpio_get_value_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_value(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_value_bank(pio, GPIO_NUM(pin), set);
}
@@ -141,7 +159,7 @@ static void sunxi_gpio_set_value(u32 pin, bool set)
static int sunxi_gpio_get_value(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_value_bank(pio, GPIO_NUM(pin));
}