diff options
author | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2015-02-24 07:59:38 +0100 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2015-02-24 07:59:38 +0100 |
commit | e1cc4d31f889428a4ca73120951389c756404184 (patch) | |
tree | 4a2028c750e19f5d36d0aa7545bda7cbacea9dd4 /drivers/gpio | |
parent | 23d184d2fbc805bdd9fb41f2370cdce04a7894af (diff) | |
parent | 38dac81b3d0e777f301ca98100bfbcab01d616c2 (diff) | |
download | u-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/Kconfig | 7 | ||||
-rw-r--r-- | drivers/gpio/at91_gpio.c | 10 | ||||
-rw-r--r-- | drivers/gpio/gpio-uclass.c | 396 | ||||
-rw-r--r-- | drivers/gpio/mxc_gpio.c | 84 | ||||
-rw-r--r-- | drivers/gpio/omap_gpio.c | 2 | ||||
-rw-r--r-- | drivers/gpio/s5p_gpio.c | 13 | ||||
-rw-r--r-- | drivers/gpio/sandbox.c | 20 | ||||
-rw-r--r-- | drivers/gpio/tegra_gpio.c | 18 |
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, }; /** |