summaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorAlbert ARIBAUD <albert.u.boot@aribaud.net>2015-02-24 07:59:38 +0100
committerAlbert ARIBAUD <albert.u.boot@aribaud.net>2015-02-24 07:59:38 +0100
commite1cc4d31f889428a4ca73120951389c756404184 (patch)
tree4a2028c750e19f5d36d0aa7545bda7cbacea9dd4 /drivers/gpio
parent23d184d2fbc805bdd9fb41f2370cdce04a7894af (diff)
parent38dac81b3d0e777f301ca98100bfbcab01d616c2 (diff)
downloadu-boot-imx-e1cc4d31f889428a4ca73120951389c756404184.zip
u-boot-imx-e1cc4d31f889428a4ca73120951389c756404184.tar.gz
u-boot-imx-e1cc4d31f889428a4ca73120951389c756404184.tar.bz2
Merge remote-tracking branch 'u-boot/master' into 'u-boot-arm/master'
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/at91_gpio.c10
-rw-r--r--drivers/gpio/gpio-uclass.c396
-rw-r--r--drivers/gpio/mxc_gpio.c84
-rw-r--r--drivers/gpio/omap_gpio.c2
-rw-r--r--drivers/gpio/s5p_gpio.c13
-rw-r--r--drivers/gpio/sandbox.c20
-rw-r--r--drivers/gpio/tegra_gpio.c18
8 files changed, 452 insertions, 98 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d21302f..b609e73 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -2,5 +2,8 @@ config DM_GPIO
bool "Enable Driver Model for GPIO drivers"
depends on DM
help
- If you want to use driver model for GPIO drivers, say Y.
- To use legacy GPIO drivers, say N.
+ Enable driver model for GPIO access. The standard GPIO
+ interface (gpio_get_value(), etc.) is then implemented by
+ the GPIO uclass. Drivers provide methods to query the
+ particular GPIOs that they provide. The uclass interface
+ is defined in include/asm-generic/gpio.h.
diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c
index 6129c02..22fbd63 100644
--- a/drivers/gpio/at91_gpio.c
+++ b/drivers/gpio/at91_gpio.c
@@ -451,7 +451,7 @@ struct at91_port_priv {
/* set GPIO pin 'gpio' as an input */
static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
{
- struct at91_port_priv *port = dev_get_platdata(dev);
+ struct at91_port_priv *port = dev_get_priv(dev);
at91_set_port_input(port->regs, offset, 0);
@@ -462,7 +462,7 @@ static int at91_gpio_direction_input(struct udevice *dev, unsigned offset)
static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
int value)
{
- struct at91_port_priv *port = dev_get_platdata(dev);
+ struct at91_port_priv *port = dev_get_priv(dev);
at91_set_port_output(port->regs, offset, value);
@@ -472,7 +472,7 @@ static int at91_gpio_direction_output(struct udevice *dev, unsigned offset,
/* read GPIO IN value of pin 'gpio' */
static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
{
- struct at91_port_priv *port = dev_get_platdata(dev);
+ struct at91_port_priv *port = dev_get_priv(dev);
return at91_get_port_value(port->regs, offset);
}
@@ -481,7 +481,7 @@ static int at91_gpio_get_value(struct udevice *dev, unsigned offset)
static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
- struct at91_port_priv *port = dev_get_platdata(dev);
+ struct at91_port_priv *port = dev_get_priv(dev);
at91_set_port_value(port->regs, offset, value);
@@ -490,7 +490,7 @@ static int at91_gpio_set_value(struct udevice *dev, unsigned offset,
static int at91_gpio_get_function(struct udevice *dev, unsigned offset)
{
- struct at91_port_priv *port = dev_get_platdata(dev);
+ struct at91_port_priv *port = dev_get_priv(dev);
/* GPIOF_FUNC is not implemented yet */
if (at91_get_port_output(port->regs, offset))
diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 255700a..a69bbd2 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -7,20 +7,25 @@
#include <common.h>
#include <dm.h>
#include <errno.h>
+#include <fdtdec.h>
#include <malloc.h>
#include <asm/gpio.h>
#include <linux/ctype.h>
+DECLARE_GLOBAL_DATA_PTR;
+
/**
* gpio_to_device() - Convert global GPIO number to device, number
- * gpio: The numeric representation of the GPIO
*
* Convert the GPIO number to an entry in the list of GPIOs
* or GPIO blocks registered with the GPIO controller. Returns
* entry on success, NULL on error.
+ *
+ * @gpio: The numeric representation of the GPIO
+ * @desc: Returns description (desc->flags will always be 0)
+ * @return 0 if found, -ENOENT if not found
*/
-static int gpio_to_device(unsigned int gpio, struct udevice **devp,
- unsigned int *offset)
+static int gpio_to_device(unsigned int gpio, struct gpio_desc *desc)
{
struct gpio_dev_priv *uc_priv;
struct udevice *dev;
@@ -32,14 +37,15 @@ static int gpio_to_device(unsigned int gpio, struct udevice **devp,
uc_priv = dev->uclass_priv;
if (gpio >= uc_priv->gpio_base &&
gpio < uc_priv->gpio_base + uc_priv->gpio_count) {
- *devp = dev;
- *offset = gpio - uc_priv->gpio_base;
+ desc->dev = dev;
+ desc->offset = gpio - uc_priv->gpio_base;
+ desc->flags = 0;
return 0;
}
}
/* No such GPIO */
- return ret ? ret : -EINVAL;
+ return ret ? ret : -ENOENT;
}
int gpio_lookup_name(const char *name, struct udevice **devp,
@@ -88,6 +94,57 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
return 0;
}
+static int gpio_find_and_xlate(struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args)
+{
+ struct dm_gpio_ops *ops = gpio_get_ops(desc->dev);
+
+ /* Use the first argument as the offset by default */
+ if (args->args_count > 0)
+ desc->offset = args->args[0];
+ else
+ desc->offset = -1;
+ desc->flags = 0;
+
+ return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0;
+}
+
+static int dm_gpio_request(struct gpio_desc *desc, const char *label)
+{
+ struct udevice *dev = desc->dev;
+ struct gpio_dev_priv *uc_priv;
+ char *str;
+ int ret;
+
+ uc_priv = dev->uclass_priv;
+ if (uc_priv->name[desc->offset])
+ return -EBUSY;
+ str = strdup(label);
+ if (!str)
+ return -ENOMEM;
+ if (gpio_get_ops(dev)->request) {
+ ret = gpio_get_ops(dev)->request(dev, desc->offset, label);
+ if (ret) {
+ free(str);
+ return ret;
+ }
+ }
+ uc_priv->name[desc->offset] = str;
+
+ return 0;
+}
+
+static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...)
+{
+ va_list args;
+ char buf[40];
+
+ va_start(args, fmt);
+ vscnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ return dm_gpio_request(desc, buf);
+}
+
/**
* gpio_request() - [COMPAT] Request GPIO
* gpio: GPIO number
@@ -102,32 +159,14 @@ int gpio_lookup_name(const char *name, struct udevice **devp,
*/
int gpio_request(unsigned gpio, const char *label)
{
- struct gpio_dev_priv *uc_priv;
- unsigned int offset;
- struct udevice *dev;
- char *str;
+ struct gpio_desc desc;
int ret;
- ret = gpio_to_device(gpio, &dev, &offset);
+ ret = gpio_to_device(gpio, &desc);
if (ret)
return ret;
- uc_priv = dev->uclass_priv;
- if (uc_priv->name[offset])
- return -EBUSY;
- str = strdup(label);
- if (!str)
- return -ENOMEM;
- if (gpio_get_ops(dev)->request) {
- ret = gpio_get_ops(dev)->request(dev, offset, label);
- if (ret) {
- free(str);
- return ret;
- }
- }
- uc_priv->name[offset] = str;
-
- return 0;
+ return dm_gpio_request(&desc, label);
}
/**
@@ -151,25 +190,11 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...)
return gpio_request(gpio, buf);
}
-/**
- * gpio_free() - [COMPAT] Relinquish GPIO
- * gpio: GPIO number
- *
- * This function implements the API that's compatible with current
- * GPIO API used in U-Boot. The request is forwarded to particular
- * GPIO driver. Returns 0 on success, negative value on error.
- */
-int gpio_free(unsigned gpio)
+int _dm_gpio_free(struct udevice *dev, uint offset)
{
struct gpio_dev_priv *uc_priv;
- unsigned int offset;
- struct udevice *dev;
int ret;
- ret = gpio_to_device(gpio, &dev, &offset);
- if (ret)
- return ret;
-
uc_priv = dev->uclass_priv;
if (!uc_priv->name[offset])
return -ENXIO;
@@ -185,15 +210,35 @@ int gpio_free(unsigned gpio)
return 0;
}
-static int check_reserved(struct udevice *dev, unsigned offset,
- const char *func)
+/**
+ * gpio_free() - [COMPAT] Relinquish GPIO
+ * gpio: GPIO number
+ *
+ * This function implements the API that's compatible with current
+ * GPIO API used in U-Boot. The request is forwarded to particular
+ * GPIO driver. Returns 0 on success, negative value on error.
+ */
+int gpio_free(unsigned gpio)
{
- struct gpio_dev_priv *uc_priv = dev->uclass_priv;
+ struct gpio_desc desc;
+ int ret;
+
+ ret = gpio_to_device(gpio, &desc);
+ if (ret)
+ return ret;
+
+ return _dm_gpio_free(desc.dev, desc.offset);
+}
+
+static int check_reserved(struct gpio_desc *desc, const char *func)
+{
+ struct gpio_dev_priv *uc_priv = desc->dev->uclass_priv;
- if (!uc_priv->name[offset]) {
+ if (!uc_priv->name[desc->offset]) {
printf("%s: %s: error: gpio %s%d not reserved\n",
- dev->name, func,
- uc_priv->bank_name ? uc_priv->bank_name : "", offset);
+ desc->dev->name, func,
+ uc_priv->bank_name ? uc_priv->bank_name : "",
+ desc->offset);
return -EBUSY;
}
@@ -210,16 +255,17 @@ static int check_reserved(struct udevice *dev, unsigned offset,
*/
int gpio_direction_input(unsigned gpio)
{
- unsigned int offset;
- struct udevice *dev;
+ struct gpio_desc desc;
int ret;
- ret = gpio_to_device(gpio, &dev, &offset);
+ ret = gpio_to_device(gpio, &desc);
+ if (ret)
+ return ret;
+ ret = check_reserved(&desc, "dir_input");
if (ret)
return ret;
- ret = check_reserved(dev, offset, "dir_input");
- return ret ? ret : gpio_get_ops(dev)->direction_input(dev, offset);
+ return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset);
}
/**
@@ -233,17 +279,81 @@ int gpio_direction_input(unsigned gpio)
*/
int gpio_direction_output(unsigned gpio, int value)
{
- unsigned int offset;
- struct udevice *dev;
+ struct gpio_desc desc;
+ int ret;
+
+ ret = gpio_to_device(gpio, &desc);
+ if (ret)
+ return ret;
+ ret = check_reserved(&desc, "dir_output");
+ if (ret)
+ return ret;
+
+ return gpio_get_ops(desc.dev)->direction_output(desc.dev,
+ desc.offset, value);
+}
+
+int dm_gpio_get_value(struct gpio_desc *desc)
+{
+ int value;
+ int ret;
+
+ ret = check_reserved(desc, "get_value");
+ if (ret)
+ return ret;
+
+ value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset);
+
+ return desc->flags & GPIOD_ACTIVE_LOW ? !value : value;
+}
+
+int dm_gpio_set_value(struct gpio_desc *desc, int value)
+{
+ int ret;
+
+ ret = check_reserved(desc, "set_value");
+ if (ret)
+ return ret;
+
+ if (desc->flags & GPIOD_ACTIVE_LOW)
+ value = !value;
+ gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
+ return 0;
+}
+
+int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
+{
+ struct udevice *dev = desc->dev;
+ struct dm_gpio_ops *ops = gpio_get_ops(dev);
int ret;
- ret = gpio_to_device(gpio, &dev, &offset);
+ ret = check_reserved(desc, "set_dir");
+ if (ret)
+ return ret;
+
+ if (flags & GPIOD_IS_OUT) {
+ int value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0;
+
+ if (flags & GPIOD_ACTIVE_LOW)
+ value = !value;
+ ret = ops->direction_output(dev, desc->offset, value);
+ } else if (flags & GPIOD_IS_IN) {
+ ret = ops->direction_input(dev, desc->offset);
+ }
if (ret)
return ret;
- ret = check_reserved(dev, offset, "dir_output");
+ /*
+ * Update desc->flags here, so that GPIO_ACTIVE_LOW is honoured in
+ * futures
+ */
+ desc->flags = flags;
+
+ return 0;
+}
- return ret ? ret :
- gpio_get_ops(dev)->direction_output(dev, offset, value);
+int dm_gpio_set_dir(struct gpio_desc *desc)
+{
+ return dm_gpio_set_dir_flags(desc, desc->flags);
}
/**
@@ -257,16 +367,14 @@ int gpio_direction_output(unsigned gpio, int value)
*/
int gpio_get_value(unsigned gpio)
{
- unsigned int offset;
- struct udevice *dev;
int ret;
- ret = gpio_to_device(gpio, &dev, &offset);
+ struct gpio_desc desc;
+
+ ret = gpio_to_device(gpio, &desc);
if (ret)
return ret;
- ret = check_reserved(dev, offset, "get_value");
-
- return ret ? ret : gpio_get_ops(dev)->get_value(dev, offset);
+ return dm_gpio_get_value(&desc);
}
/**
@@ -280,16 +388,13 @@ int gpio_get_value(unsigned gpio)
*/
int gpio_set_value(unsigned gpio, int value)
{
- unsigned int offset;
- struct udevice *dev;
+ struct gpio_desc desc;
int ret;
- ret = gpio_to_device(gpio, &dev, &offset);
+ ret = gpio_to_device(gpio, &desc);
if (ret)
return ret;
- ret = check_reserved(dev, offset, "set_value");
-
- return ret ? ret : gpio_get_ops(dev)->set_value(dev, offset, value);
+ return dm_gpio_set_value(&desc, value);
}
const char *gpio_get_bank_info(struct udevice *dev, int *bit_count)
@@ -409,6 +514,155 @@ unsigned gpio_get_values_as_int(const int *gpio_num_array)
return vector;
}
+static int _gpio_request_by_name_nodev(const void *blob, int node,
+ const char *list_name, int index,
+ struct gpio_desc *desc, int flags,
+ bool add_index)
+{
+ struct fdtdec_phandle_args args;
+ int ret;
+
+ desc->dev = NULL;
+ desc->offset = 0;
+ ret = fdtdec_parse_phandle_with_args(blob, node, list_name,
+ "#gpio-cells", 0, index, &args);
+ if (ret) {
+ debug("%s: fdtdec_parse_phandle_with_args failed\n", __func__);
+ goto err;
+ }
+
+ ret = uclass_get_device_by_of_offset(UCLASS_GPIO, args.node,
+ &desc->dev);
+ if (ret) {
+ debug("%s: uclass_get_device_by_of_offset failed\n", __func__);
+ goto err;
+ }
+ ret = gpio_find_and_xlate(desc, &args);
+ if (ret) {
+ debug("%s: gpio_find_and_xlate failed\n", __func__);
+ goto err;
+ }
+ ret = dm_gpio_requestf(desc, add_index ? "%s.%s%d" : "%s.%s",
+ fdt_get_name(blob, node, NULL),
+ list_name, index);
+ if (ret) {
+ debug("%s: dm_gpio_requestf failed\n", __func__);
+ goto err;
+ }
+ ret = dm_gpio_set_dir_flags(desc, flags | desc->flags);
+ if (ret) {
+ debug("%s: dm_gpio_set_dir failed\n", __func__);
+ goto err;
+ }
+
+ return 0;
+err:
+ debug("%s: Node '%s', property '%s', failed to request GPIO index %d: %d\n",
+ __func__, fdt_get_name(blob, node, NULL), list_name, index, ret);
+ return ret;
+}
+
+int gpio_request_by_name_nodev(const void *blob, int node,
+ const char *list_name, int index,
+ struct gpio_desc *desc, int flags)
+{
+ return _gpio_request_by_name_nodev(blob, node, list_name, index, desc,
+ flags, index > 0);
+}
+
+int gpio_request_by_name(struct udevice *dev, const char *list_name, int index,
+ struct gpio_desc *desc, int flags)
+{
+ /*
+ * This isn't ideal since we don't use dev->name in the debug()
+ * calls in gpio_request_by_name(), but we can do this until
+ * gpio_request_by_name_nodev() can be dropped.
+ */
+ return gpio_request_by_name_nodev(gd->fdt_blob, dev->of_offset,
+ list_name, index, desc, flags);
+}
+
+int gpio_request_list_by_name_nodev(const void *blob, int node,
+ const char *list_name,
+ struct gpio_desc *desc, int max_count,
+ int flags)
+{
+ int count;
+ int ret;
+
+ for (count = 0; ; count++) {
+ if (count >= max_count) {
+ ret = -ENOSPC;
+ goto err;
+ }
+ ret = _gpio_request_by_name_nodev(blob, node, list_name, count,
+ &desc[count], flags, true);
+ if (ret == -ENOENT)
+ break;
+ else if (ret)
+ goto err;
+ }
+
+ /* We ran out of GPIOs in the list */
+ return count;
+
+err:
+ gpio_free_list_nodev(desc, count - 1);
+
+ return ret;
+}
+
+int gpio_request_list_by_name(struct udevice *dev, const char *list_name,
+ struct gpio_desc *desc, int max_count,
+ int flags)
+{
+ /*
+ * This isn't ideal since we don't use dev->name in the debug()
+ * calls in gpio_request_by_name(), but we can do this until
+ * gpio_request_list_by_name_nodev() can be dropped.
+ */
+ return gpio_request_list_by_name_nodev(gd->fdt_blob, dev->of_offset,
+ list_name, desc, max_count,
+ flags);
+}
+
+int gpio_get_list_count(struct udevice *dev, const char *list_name)
+{
+ int ret;
+
+ ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+ list_name, "#gpio-cells", 0, -1,
+ NULL);
+ if (ret) {
+ debug("%s: Node '%s', property '%s', GPIO count failed: %d\n",
+ __func__, dev->name, list_name, ret);
+ }
+
+ return ret;
+}
+
+int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc)
+{
+ /* For now, we don't do any checking of dev */
+ return _dm_gpio_free(desc->dev, desc->offset);
+}
+
+int gpio_free_list(struct udevice *dev, struct gpio_desc *desc, int count)
+{
+ int i;
+
+ /* For now, we don't do any checking of dev */
+ for (i = 0; i < count; i++)
+ dm_gpio_free(dev, &desc[i]);
+
+ return 0;
+}
+
+int gpio_free_list_nodev(struct gpio_desc *desc, int count)
+{
+ return gpio_free_list(NULL, desc, count);
+}
+
/* We need to renumber the GPIOs when any driver is probed/removed */
static int gpio_renumber(struct udevice *removed_dev)
{
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 8bb9e39..815407b 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -23,6 +23,7 @@ enum mxc_gpio_direction {
#define GPIO_PER_BANK 32
struct mxc_gpio_plat {
+ int bank_index;
struct gpio_regs *regs;
};
@@ -150,6 +151,9 @@ int gpio_direction_output(unsigned gpio, int value)
#endif
#ifdef CONFIG_DM_GPIO
+#include <fdtdec.h>
+DECLARE_GLOBAL_DATA_PTR;
+
static int mxc_gpio_is_output(struct gpio_regs *regs, int offset)
{
u32 val;
@@ -258,23 +262,6 @@ static const struct dm_gpio_ops gpio_mxc_ops = {
.get_function = mxc_gpio_get_function,
};
-static const struct mxc_gpio_plat mxc_plat[] = {
- { (struct gpio_regs *)GPIO1_BASE_ADDR },
- { (struct gpio_regs *)GPIO2_BASE_ADDR },
- { (struct gpio_regs *)GPIO3_BASE_ADDR },
-#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
- defined(CONFIG_MX53) || defined(CONFIG_MX6)
- { (struct gpio_regs *)GPIO4_BASE_ADDR },
-#endif
-#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
- { (struct gpio_regs *)GPIO5_BASE_ADDR },
- { (struct gpio_regs *)GPIO6_BASE_ADDR },
-#endif
-#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
- { (struct gpio_regs *)GPIO7_BASE_ADDR },
-#endif
-};
-
static int mxc_gpio_probe(struct udevice *dev)
{
struct mxc_bank_info *bank = dev_get_priv(dev);
@@ -283,7 +270,7 @@ static int mxc_gpio_probe(struct udevice *dev)
int banknum;
char name[18], *str;
- banknum = plat - mxc_plat;
+ banknum = plat->bank_index;
sprintf(name, "GPIO%d_", banknum + 1);
str = strdup(name);
if (!str)
@@ -295,12 +282,72 @@ static int mxc_gpio_probe(struct udevice *dev)
return 0;
}
+static int mxc_gpio_bind(struct udevice *dev)
+{
+ struct mxc_gpio_plat *plat = dev->platdata;
+ fdt_addr_t addr;
+
+ /*
+ * If platdata already exsits, directly return.
+ * Actually only when DT is not supported, platdata
+ * is statically initialized in U_BOOT_DEVICES.Here
+ * will return.
+ */
+ if (plat)
+ return 0;
+
+ addr = dev_get_addr(dev);
+ if (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->regs = (struct gpio_regs *)addr;
+ plat->bank_index = dev->req_seq;
+ dev->platdata = plat;
+
+ return 0;
+}
+
+static const struct udevice_id mxc_gpio_ids[] = {
+ { .compatible = "fsl,imx35-gpio" },
+ { }
+};
+
U_BOOT_DRIVER(gpio_mxc) = {
.name = "gpio_mxc",
.id = UCLASS_GPIO,
.ops = &gpio_mxc_ops,
.probe = mxc_gpio_probe,
.priv_auto_alloc_size = sizeof(struct mxc_bank_info),
+ .of_match = mxc_gpio_ids,
+ .bind = mxc_gpio_bind,
+};
+
+#ifndef CONFIG_OF_CONTROL
+static const struct mxc_gpio_plat mxc_plat[] = {
+ { 0, (struct gpio_regs *)GPIO1_BASE_ADDR },
+ { 1, (struct gpio_regs *)GPIO2_BASE_ADDR },
+ { 2, (struct gpio_regs *)GPIO3_BASE_ADDR },
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
+ defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { 3, (struct gpio_regs *)GPIO4_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { 4, (struct gpio_regs *)GPIO5_BASE_ADDR },
+ { 5, (struct gpio_regs *)GPIO6_BASE_ADDR },
+#endif
+#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ { 6, (struct gpio_regs *)GPIO7_BASE_ADDR },
+#endif
};
U_BOOT_DEVICES(mxc_gpios) = {
@@ -320,3 +367,4 @@ U_BOOT_DEVICES(mxc_gpios) = {
#endif
};
#endif
+#endif
diff --git a/drivers/gpio/omap_gpio.c b/drivers/gpio/omap_gpio.c
index f3a7ccb..19fc451 100644
--- a/drivers/gpio/omap_gpio.c
+++ b/drivers/gpio/omap_gpio.c
@@ -291,7 +291,7 @@ static int omap_gpio_get_function(struct udevice *dev, unsigned offset)
struct gpio_bank *bank = dev_get_priv(dev);
/* GPIOF_FUNC is not implemented yet */
- if (_get_gpio_direction(bank->base, offset) == OMAP_GPIO_DIR_OUT)
+ if (_get_gpio_direction(bank, offset) == OMAP_GPIO_DIR_OUT)
return GPIOF_OUTPUT;
else
return GPIOF_INPUT;
diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c
index 6c41a42..0a245ba 100644
--- a/drivers/gpio/s5p_gpio.c
+++ b/drivers/gpio/s5p_gpio.c
@@ -13,6 +13,7 @@
#include <asm/io.h>
#include <asm/gpio.h>
#include <dm/device-internal.h>
+#include <dt-bindings/gpio/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -275,12 +276,22 @@ static int exynos_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_FUNC;
}
+static int exynos_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args)
+{
+ desc->offset = args->args[0];
+ desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+ return 0;
+}
+
static const struct dm_gpio_ops gpio_exynos_ops = {
.direction_input = exynos_gpio_direction_input,
.direction_output = exynos_gpio_direction_output,
.get_value = exynos_gpio_get_value,
.set_value = exynos_gpio_set_value,
.get_function = exynos_gpio_get_function,
+ .xlate = exynos_gpio_xlate,
};
static int gpio_exynos_probe(struct udevice *dev)
@@ -342,7 +353,7 @@ static int gpio_exynos_bind(struct udevice *parent)
plat->bank_name, plat, -1, &dev);
if (ret)
return ret;
- dev->of_offset = parent->of_offset;
+ dev->of_offset = node;
}
return 0;
diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c
index 53c80d5..d564c25 100644
--- a/drivers/gpio/sandbox.c
+++ b/drivers/gpio/sandbox.c
@@ -8,6 +8,7 @@
#include <fdtdec.h>
#include <malloc.h>
#include <asm/gpio.h>
+#include <dt-bindings/gpio/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -130,12 +131,31 @@ static int sb_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
+static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args)
+{
+ desc->offset = args->args[0];
+ if (args->args_count < 2)
+ return 0;
+ if (args->args[1] & GPIO_ACTIVE_LOW)
+ desc->flags |= GPIOD_ACTIVE_LOW;
+ if (args->args[1] & 2)
+ desc->flags |= GPIOD_IS_IN;
+ if (args->args[1] & 4)
+ desc->flags |= GPIOD_IS_OUT;
+ if (args->args[1] & 8)
+ desc->flags |= GPIOD_IS_OUT_ACTIVE;
+
+ return 0;
+}
+
static const struct dm_gpio_ops gpio_sandbox_ops = {
.direction_input = sb_gpio_direction_input,
.direction_output = sb_gpio_direction_output,
.get_value = sb_gpio_get_value,
.set_value = sb_gpio_set_value,
.get_function = sb_gpio_get_function,
+ .xlate = sb_gpio_xlate,
};
static int sandbox_gpio_ofdata_to_platdata(struct udevice *dev)
diff --git a/drivers/gpio/tegra_gpio.c b/drivers/gpio/tegra_gpio.c
index 88f7ef5..43928b8 100644
--- a/drivers/gpio/tegra_gpio.c
+++ b/drivers/gpio/tegra_gpio.c
@@ -21,6 +21,7 @@
#include <asm/arch/tegra.h>
#include <asm/gpio.h>
#include <dm/device-internal.h>
+#include <dt-bindings/gpio/gpio.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -251,6 +252,22 @@ static int tegra_gpio_get_function(struct udevice *dev, unsigned offset)
return GPIOF_INPUT;
}
+static int tegra_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+ struct fdtdec_phandle_args *args)
+{
+ int gpio, port, ret;
+
+ gpio = args->args[0];
+ port = gpio / TEGRA_GPIOS_PER_PORT;
+ ret = device_get_child(dev, port, &desc->dev);
+ if (ret)
+ return ret;
+ desc->offset = gpio % TEGRA_GPIOS_PER_PORT;
+ desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+ return 0;
+}
+
static const struct dm_gpio_ops gpio_tegra_ops = {
.request = tegra_gpio_request,
.direction_input = tegra_gpio_direction_input,
@@ -258,6 +275,7 @@ static const struct dm_gpio_ops gpio_tegra_ops = {
.get_value = tegra_gpio_get_value,
.set_value = tegra_gpio_set_value,
.get_function = tegra_gpio_get_function,
+ .xlate = tegra_gpio_xlate,
};
/**