|
@@ -20,9 +20,13 @@
|
|
*/
|
|
*/
|
|
#include <common.h>
|
|
#include <common.h>
|
|
#include <dm.h>
|
|
#include <dm.h>
|
|
|
|
+#include <fdtdec.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/gpio.h>
|
|
#include <asm/io.h>
|
|
#include <asm/io.h>
|
|
#include <asm/errno.h>
|
|
#include <asm/errno.h>
|
|
|
|
+#include <malloc.h>
|
|
|
|
+
|
|
|
|
+DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
|
|
#define OMAP_GPIO_DIR_OUT 0
|
|
#define OMAP_GPIO_DIR_OUT 0
|
|
#define OMAP_GPIO_DIR_IN 1
|
|
#define OMAP_GPIO_DIR_IN 1
|
|
@@ -34,7 +38,6 @@
|
|
struct gpio_bank {
|
|
struct gpio_bank {
|
|
/* TODO(sjg@chromium.org): Can we use a struct here? */
|
|
/* TODO(sjg@chromium.org): Can we use a struct here? */
|
|
void *base; /* address of registers in physical memory */
|
|
void *base; /* address of registers in physical memory */
|
|
- enum gpio_method method;
|
|
|
|
};
|
|
};
|
|
|
|
|
|
#endif
|
|
#endif
|
|
@@ -55,13 +58,8 @@ static void _set_gpio_direction(const struct gpio_bank *bank, int gpio,
|
|
void *reg = bank->base;
|
|
void *reg = bank->base;
|
|
u32 l;
|
|
u32 l;
|
|
|
|
|
|
- switch (bank->method) {
|
|
|
|
- case METHOD_GPIO_24XX:
|
|
|
|
- reg += OMAP_GPIO_OE;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ reg += OMAP_GPIO_OE;
|
|
|
|
+
|
|
l = __raw_readl(reg);
|
|
l = __raw_readl(reg);
|
|
if (is_input)
|
|
if (is_input)
|
|
l |= 1 << gpio;
|
|
l |= 1 << gpio;
|
|
@@ -79,13 +77,7 @@ static int _get_gpio_direction(const struct gpio_bank *bank, int gpio)
|
|
void *reg = bank->base;
|
|
void *reg = bank->base;
|
|
u32 v;
|
|
u32 v;
|
|
|
|
|
|
- switch (bank->method) {
|
|
|
|
- case METHOD_GPIO_24XX:
|
|
|
|
- reg += OMAP_GPIO_OE;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
|
|
+ reg += OMAP_GPIO_OE;
|
|
|
|
|
|
v = __raw_readl(reg);
|
|
v = __raw_readl(reg);
|
|
|
|
|
|
@@ -101,19 +93,12 @@ static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio,
|
|
void *reg = bank->base;
|
|
void *reg = bank->base;
|
|
u32 l = 0;
|
|
u32 l = 0;
|
|
|
|
|
|
- switch (bank->method) {
|
|
|
|
- case METHOD_GPIO_24XX:
|
|
|
|
- if (enable)
|
|
|
|
- reg += OMAP_GPIO_SETDATAOUT;
|
|
|
|
- else
|
|
|
|
- reg += OMAP_GPIO_CLEARDATAOUT;
|
|
|
|
- l = 1 << gpio;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- printf("omap3-gpio unknown bank method %s %d\n",
|
|
|
|
- __FILE__, __LINE__);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ if (enable)
|
|
|
|
+ reg += OMAP_GPIO_SETDATAOUT;
|
|
|
|
+ else
|
|
|
|
+ reg += OMAP_GPIO_CLEARDATAOUT;
|
|
|
|
+
|
|
|
|
+ l = 1 << gpio;
|
|
__raw_writel(l, reg);
|
|
__raw_writel(l, reg);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -122,19 +107,13 @@ static int _get_gpio_value(const struct gpio_bank *bank, int gpio)
|
|
void *reg = bank->base;
|
|
void *reg = bank->base;
|
|
int input;
|
|
int input;
|
|
|
|
|
|
- switch (bank->method) {
|
|
|
|
- case METHOD_GPIO_24XX:
|
|
|
|
- input = _get_gpio_direction(bank, gpio);
|
|
|
|
- switch (input) {
|
|
|
|
- case OMAP_GPIO_DIR_IN:
|
|
|
|
- reg += OMAP_GPIO_DATAIN;
|
|
|
|
- break;
|
|
|
|
- case OMAP_GPIO_DIR_OUT:
|
|
|
|
- reg += OMAP_GPIO_DATAOUT;
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
|
|
+ input = _get_gpio_direction(bank, gpio);
|
|
|
|
+ switch (input) {
|
|
|
|
+ case OMAP_GPIO_DIR_IN:
|
|
|
|
+ reg += OMAP_GPIO_DATAIN;
|
|
|
|
+ break;
|
|
|
|
+ case OMAP_GPIO_DIR_OUT:
|
|
|
|
+ reg += OMAP_GPIO_DATAOUT;
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
return -1;
|
|
return -1;
|
|
@@ -310,24 +289,56 @@ static int omap_gpio_probe(struct udevice *dev)
|
|
struct gpio_bank *bank = dev_get_priv(dev);
|
|
struct gpio_bank *bank = dev_get_priv(dev);
|
|
struct omap_gpio_platdata *plat = dev_get_platdata(dev);
|
|
struct omap_gpio_platdata *plat = dev_get_platdata(dev);
|
|
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
|
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
|
|
- char name[18], *str;
|
|
|
|
|
|
|
|
- sprintf(name, "GPIO%d_", plat->bank_index);
|
|
|
|
- str = strdup(name);
|
|
|
|
- if (!str)
|
|
|
|
- return -ENOMEM;
|
|
|
|
- uc_priv->bank_name = str;
|
|
|
|
|
|
+ uc_priv->bank_name = plat->port_name;
|
|
uc_priv->gpio_count = GPIO_PER_BANK;
|
|
uc_priv->gpio_count = GPIO_PER_BANK;
|
|
bank->base = (void *)plat->base;
|
|
bank->base = (void *)plat->base;
|
|
- bank->method = plat->method;
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int omap_gpio_bind(struct udevice *dev)
|
|
|
|
+{
|
|
|
|
+ struct omap_gpio_platdata *plat = dev->platdata;
|
|
|
|
+ fdt_addr_t base_addr;
|
|
|
|
+
|
|
|
|
+ if (plat)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ base_addr = dev_get_addr(dev);
|
|
|
|
+ if (base_addr == FDT_ADDR_T_NONE)
|
|
|
|
+ return -ENODEV;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * TODO:
|
|
|
|
+ * When every board is converted to driver model and DT is
|
|
|
|
+ * supported, this can be done by auto-alloc feature, but
|
|
|
|
+ * not using calloc to alloc memory for platdata.
|
|
|
|
+ */
|
|
|
|
+ plat = calloc(1, sizeof(*plat));
|
|
|
|
+ if (!plat)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ plat->base = base_addr;
|
|
|
|
+ plat->port_name = fdt_get_name(gd->fdt_blob, dev->of_offset, NULL);
|
|
|
|
+ dev->platdata = plat;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const struct udevice_id omap_gpio_ids[] = {
|
|
|
|
+ { .compatible = "ti,omap3-gpio" },
|
|
|
|
+ { .compatible = "ti,omap4-gpio" },
|
|
|
|
+ { .compatible = "ti,am4372-gpio" },
|
|
|
|
+ { }
|
|
|
|
+};
|
|
|
|
+
|
|
U_BOOT_DRIVER(gpio_omap) = {
|
|
U_BOOT_DRIVER(gpio_omap) = {
|
|
.name = "gpio_omap",
|
|
.name = "gpio_omap",
|
|
.id = UCLASS_GPIO,
|
|
.id = UCLASS_GPIO,
|
|
.ops = &gpio_omap_ops,
|
|
.ops = &gpio_omap_ops,
|
|
|
|
+ .of_match = omap_gpio_ids,
|
|
|
|
+ .bind = omap_gpio_bind,
|
|
.probe = omap_gpio_probe,
|
|
.probe = omap_gpio_probe,
|
|
.priv_auto_alloc_size = sizeof(struct gpio_bank),
|
|
.priv_auto_alloc_size = sizeof(struct gpio_bank),
|
|
};
|
|
};
|