[U-Boot] [PATCH 11/21] sunxi: gpio: Add support for AXP gpios to the dm gpio code

Hans de Goede
2015-04-24T13:48:20Z

This really should be part of the axp pmic driver, but that is not converted
yet to device-model, and the upstream kernel does not support axp gpios
yet so there is no devicetree binding for them yet.

So for now bolt on the axp gpio support to the SoC's own gpio support like
we've been doing for the non dm case. This allows boards using axp gpios
to be converted to dm.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
arch/arm/include/asm/arch-sunxi/gpio.h | 6 ++--
drivers/gpio/sunxi_gpio.c | 64 +++++++++++++++++++++++++++++-----
2 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index c9bfb4c..cbb3328 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.h
@@ -204,8 +204,10 @@ enum sunxi_gpio_number {
#define SUNXI_GPIO_PULL_DOWN 2

/* Virtual AXP0 GPIOs */
-#define SUNXI_GPIO_AXP0_VBUS_DETECT 8
-#define SUNXI_GPIO_AXP0_VBUS_ENABLE 9
+#define SUNXI_GPIO_AXP0_PREFIX "AXP0-"
+#define SUNXI_GPIO_AXP0_VBUS_DETECT 4
+#define SUNXI_GPIO_AXP0_VBUS_ENABLE 5
+#define SUNXI_GPIO_AXP0_GPIO_COUNT 6

void sunxi_gpio_set_cfgbank(struct sunxi_gpio *pio, int bank_offset, u32 val);
void sunxi_gpio_set_cfgpin(u32 pin, u32 val);
diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c
index 0774b70..38d72b7 100644
--- a/drivers/gpio/sunxi_gpio.c
+++ b/drivers/gpio/sunxi_gpio.c
@@ -126,7 +126,7 @@ int sunxi_name_to_gpio(const char *name)
char *eptr;

#ifdef AXP_GPIO
- if (strncasecmp(name, "AXP0-", 5) == 0) {
+ if (strncasecmp(name, SUNXI_GPIO_AXP0_PREFIX, 5) == 0) {
name += 5;
if (strcmp(name, "VBUS-DETECT") == 0)
return SUNXI_GPIO_AXP0_START +
@@ -172,12 +172,56 @@ int sunxi_name_to_gpio_bank(const char *name)
}

#ifdef CONFIG_DM_GPIO
+
+#ifdef AXP_GPIO
+/* FIXME this should be part of the axp drivers */
+static const struct dm_gpio_ops gpio_axp_ops = {
+ .direction_input = axp_gpio_direction_input,
+ .direction_output = axp_gpio_direction_output,
+ .get_value = axp_gpio_get_value,
+ .set_value = axp_gpio_set_value,
+};
+
+static int gpio_axp_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+
+ /* Tell the uclass how many GPIOs we have */
+ uc_priv->bank_name = strdup(SUNXI_GPIO_AXP0_PREFIX);
+ uc_priv->gpio_count = SUNXI_GPIO_AXP0_GPIO_COUNT;
+
+ return 0;
+}
+
+struct driver gpio_axp_driver = {
+ .name = "gpio_axp",
+ .id = UCLASS_GPIO,
+ .ops = &gpio_axp_ops,
+ .probe = gpio_axp_probe,
+};
+#endif
+
/* TODO(sjg at chromium.org): Remove this function and use device tree */
int sunxi_name_to_gpio(const char *name)
{
unsigned int gpio;
int ret;
-
+#ifdef AXP_GPIO
+ char lookup[8];
+
+ if (strncasecmp(name, SUNXI_GPIO_AXP0_PREFIX, 5) == 0) {
+ int len = strlen(SUNXI_GPIO_AXP0_PREFIX);
+ if (strcmp(name + len, "VBUS-DETECT") == 0) {
+ sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d",
+ SUNXI_GPIO_AXP0_VBUS_DETECT);
+ name = lookup;
+ } else if (strcmp(name + len, "VBUS-ENABLE") == 0) {
+ sprintf(lookup, "AXP0-%d\n",
+ SUNXI_GPIO_AXP0_VBUS_ENABLE);
+ name = lookup;
+ }
+ }
+#endif
ret = gpio_lookup_name(name, NULL, NULL, &gpio);

return ret ? ret : gpio;
@@ -222,7 +266,7 @@ static int sunxi_gpio_set_value(struct udevice *dev, unsigned offset,
struct sunxi_gpio_platdata *plat = dev_get_platdata(dev);
u32 num = GPIO_NUM(offset);

- clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
+; clrsetbits_le32(&plat->regs->dat, 1 << num, value ? (1 << num) : 0);
return 0;
}

@@ -289,21 +333,19 @@ static int gpio_sunxi_probe(struct udevice *dev)
*/
static int gpio_sunxi_bind(struct udevice *parent)
{
- struct sunxi_gpio_platdata *plat = parent->platdata;
+ struct sunxi_gpio_platdata *plat;
struct sunxi_gpio_reg *ctlr;
+ struct udevice *dev;
int bank;
int ret;

/* If this is a child device, there is nothing to do here */
- if (plat)
+ if (parent->platdata)
return 0;

ctlr = (struct sunxi_gpio_reg *)fdtdec_get_addr(gd->fdt_blob,
parent->of_offset, "reg");
for (bank = 0; bank < SUNXI_GPIO_BANKS; bank++) {
- struct sunxi_gpio_platdata *plat;
- struct udevice *dev;
-
plat = calloc(1, sizeof(*plat));
if (!plat)
return -ENOMEM;
@@ -318,6 +360,12 @@ static int gpio_sunxi_bind(struct udevice *parent)
dev->of_offset = parent->of_offset;
}

+#ifdef AXP_GPIO
+ /* FIXME this should be a child of the axp device */
+ ret = device_bind(parent, &gpio_axp_driver, "AXP", NULL, -1, &dev);
+ if (ret)
+ return ret;
+#endif
return 0;
}

--
2.3.5