X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fgpio%2Fgpio-uclass.c;h=ba4804083daa6c7c6619eeda9215022d26fe0623;hb=758979101d161704dc9c1e42db98a728724f59d0;hp=4efda311a49e81c8470a23d88f62a09b07f0f5bc;hpb=3c9cc70d7153da442575112d9a2643eecd17d534;p=u-boot diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 4efda311a4..ba4804083d 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -6,10 +6,12 @@ #include #include +#include #include #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -66,7 +68,7 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) if (numeric != -1) { offset = numeric - uc_priv->gpio_base; /* Allow GPIOs to be numbered from 0 */ - if (offset >= 0 && offset < uc_priv->gpio_count) + if (offset < uc_priv->gpio_count) break; } @@ -112,19 +114,33 @@ int gpio_lookup_name(const char *name, struct udevice **devp, return 0; } +int gpio_xlate_offs_flags(struct udevice *dev, + struct gpio_desc *desc, + struct fdtdec_phandle_args *args) +{ + if (args->args_count < 1) + return -EINVAL; + + desc->offset = args->args[0]; + + if (args->args_count < 2) + return 0; + + if (args->args[1] & GPIO_ACTIVE_LOW) + desc->flags = GPIOD_ACTIVE_LOW; + + 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]; + if (ops->xlate) + return ops->xlate(desc->dev, desc, args); else - desc->offset = -1; - desc->flags = 0; - - return ops->xlate ? ops->xlate(desc->dev, desc, args) : 0; + return gpio_xlate_offs_flags(desc->dev, desc, args); } int dm_gpio_request(struct gpio_desc *desc, const char *label) @@ -154,6 +170,7 @@ int dm_gpio_request(struct gpio_desc *desc, const char *label) static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) { +#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) va_list args; char buf[40]; @@ -161,6 +178,9 @@ static int dm_gpio_requestf(struct gpio_desc *desc, const char *fmt, ...) vscnprintf(buf, sizeof(buf), fmt, args); va_end(args); return dm_gpio_request(desc, buf); +#else + return dm_gpio_request(desc, fmt); +#endif } /** @@ -199,6 +219,7 @@ int gpio_request(unsigned gpio, const char *label) */ int gpio_requestf(unsigned gpio, const char *fmt, ...) { +#if !defined(CONFIG_SPL_BUILD) || !defined(CONFIG_USE_TINY_PRINTF) va_list args; char buf[40]; @@ -206,6 +227,9 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...) vscnprintf(buf, sizeof(buf), fmt, args); va_end(args); return gpio_request(gpio, buf); +#else + return gpio_request(gpio, fmt); +#endif } int _dm_gpio_free(struct udevice *dev, uint offset) @@ -248,10 +272,14 @@ int gpio_free(unsigned gpio) return _dm_gpio_free(desc.dev, desc.offset); } -static int check_reserved(struct gpio_desc *desc, const char *func) +static int check_reserved(const struct gpio_desc *desc, const char *func) { - struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(desc->dev); + struct gpio_dev_priv *uc_priv; + + if (!dm_gpio_is_valid(desc)) + return -ENOENT; + uc_priv = dev_get_uclass_priv(desc->dev); if (!uc_priv->name[desc->offset]) { printf("%s: %s: error: gpio %s%d not reserved\n", desc->dev->name, func, @@ -311,7 +339,7 @@ int gpio_direction_output(unsigned gpio, int value) desc.offset, value); } -int dm_gpio_get_value(struct gpio_desc *desc) +int dm_gpio_get_value(const struct gpio_desc *desc) { int value; int ret; @@ -325,7 +353,7 @@ int dm_gpio_get_value(struct gpio_desc *desc) return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; } -int dm_gpio_set_value(struct gpio_desc *desc, int value) +int dm_gpio_set_value(const struct gpio_desc *desc, int value) { int ret; @@ -339,6 +367,38 @@ int dm_gpio_set_value(struct gpio_desc *desc, int value) return 0; } +int dm_gpio_get_open_drain(struct gpio_desc *desc) +{ + struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); + int ret; + + ret = check_reserved(desc, "get_open_drain"); + if (ret) + return ret; + + if (ops->set_open_drain) + return ops->get_open_drain(desc->dev, desc->offset); + else + return -ENOSYS; +} + +int dm_gpio_set_open_drain(struct gpio_desc *desc, int value) +{ + struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); + int ret; + + ret = check_reserved(desc, "set_open_drain"); + if (ret) + return ret; + + if (ops->set_open_drain) + ret = ops->set_open_drain(desc->dev, desc->offset, value); + else + return 0; /* feature not supported -> ignore setting */ + + return ret; +} + int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) { struct udevice *dev = desc->dev; @@ -564,6 +624,24 @@ int gpio_get_values_as_int(const int *gpio_list) return vector; } +int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) +{ + unsigned bitmask = 1; + unsigned vector = 0; + int ret, i; + + for (i = 0; i < count; i++) { + ret = dm_gpio_get_value(&desc_list[i]); + if (ret < 0) + return ret; + else if (ret) + vector |= bitmask; + bitmask <<= 1; + } + + 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, @@ -574,6 +652,7 @@ static int _gpio_request_by_name_nodev(const void *blob, int node, desc->dev = NULL; desc->offset = 0; + desc->flags = 0; ret = fdtdec_parse_phandle_with_args(blob, node, list_name, "#gpio-cells", 0, index, &args); if (ret) { @@ -628,7 +707,7 @@ int gpio_request_by_name(struct udevice *dev, const char *list_name, int index, * 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, + return gpio_request_by_name_nodev(gd->fdt_blob, dev_of_offset(dev), list_name, index, desc, flags); } @@ -667,7 +746,7 @@ int gpio_request_list_by_name(struct udevice *dev, const char *list_name, * 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, + return gpio_request_list_by_name_nodev(gd->fdt_blob, dev_of_offset(dev), list_name, desc, max_count, flags); } @@ -676,7 +755,7 @@ 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, + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), list_name, "#gpio-cells", 0, -1, NULL); if (ret) { @@ -735,7 +814,7 @@ static int gpio_renumber(struct udevice *removed_dev) return 0; } -int gpio_get_number(struct gpio_desc *desc) +int gpio_get_number(const struct gpio_desc *desc) { struct udevice *dev = desc->dev; struct gpio_dev_priv *uc_priv;