diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2014-07-25 23:38:36 +0900 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2014-07-28 12:28:05 +0200 |
commit | 39b2bbe3d715cf5013b5c48695ccdd25bd3bf120 (patch) | |
tree | 019129dbc7b1cc10200342602fe7eac47230219e /drivers/gpio | |
parent | 9b5b33f6256a941d9d34f219b508ba7140a39dba (diff) |
gpio: add flags argument to gpiod_get*() functions
The huge majority of GPIOs have their direction and initial value set
right after being obtained by one of the gpiod_get() functions. The
integer GPIO API had gpio_request_one() that took a convenience flags
parameter allowing to specify an direction and value applied to the
returned GPIO. This feature greatly simplifies client code and ensures
errors are always handled properly.
A similar feature has been requested for the gpiod API. Since setting
the direction of a GPIO is so often the very next action done after
obtaining its descriptor, we prefer to extend the existing functions
instead of introducing new functions that would raise the
number of gpiod getters to 16 (!).
The drawback of this approach is that all gpiod clients need to be
updated. To limit the pain, temporary macros are introduced that allow
gpiod_get*() to be called with or without the extra flags argument. They
will be removed once all consumer code has been updated.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Mark Brown <broonie@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/devres.c | 40 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 67 |
2 files changed, 70 insertions, 37 deletions
diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 65978cf85f79..41b2f40578d5 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -39,47 +39,53 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data) * devm_gpiod_get - Resource-managed gpiod_get() * @dev: GPIO consumer * @con_id: function within the GPIO consumer + * @flags: optional GPIO initialization flags * * Managed gpiod_get(). GPIO descriptors returned from this function are * automatically disposed on driver detach. See gpiod_get() for detailed * information about behavior and return values. */ -struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, - const char *con_id) +struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev, + const char *con_id, + enum gpiod_flags flags) { - return devm_gpiod_get_index(dev, con_id, 0); + return devm_gpiod_get_index(dev, con_id, 0, flags); } -EXPORT_SYMBOL(devm_gpiod_get); +EXPORT_SYMBOL(__devm_gpiod_get); /** * devm_gpiod_get_optional - Resource-managed gpiod_get_optional() * @dev: GPIO consumer * @con_id: function within the GPIO consumer + * @flags: optional GPIO initialization flags * * Managed gpiod_get_optional(). GPIO descriptors returned from this function * are automatically disposed on driver detach. See gpiod_get_optional() for * detailed information about behavior and return values. */ -struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, - const char *con_id) +struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev, + const char *con_id, + enum gpiod_flags flags) { - return devm_gpiod_get_index_optional(dev, con_id, 0); + return devm_gpiod_get_index_optional(dev, con_id, 0, flags); } -EXPORT_SYMBOL(devm_gpiod_get_optional); +EXPORT_SYMBOL(__devm_gpiod_get_optional); /** * devm_gpiod_get_index - Resource-managed gpiod_get_index() * @dev: GPIO consumer * @con_id: function within the GPIO consumer * @idx: index of the GPIO to obtain in the consumer + * @flags: optional GPIO initialization flags * * Managed gpiod_get_index(). GPIO descriptors returned from this function are * automatically disposed on driver detach. See gpiod_get_index() for detailed * information about behavior and return values. */ -struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, +struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, const char *con_id, - unsigned int idx) + unsigned int idx, + enum gpiod_flags flags) { struct gpio_desc **dr; struct gpio_desc *desc; @@ -89,7 +95,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, if (!dr) return ERR_PTR(-ENOMEM); - desc = gpiod_get_index(dev, con_id, idx); + desc = gpiod_get_index(dev, con_id, idx, flags); if (IS_ERR(desc)) { devres_free(dr); return desc; @@ -100,26 +106,28 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, return desc; } -EXPORT_SYMBOL(devm_gpiod_get_index); +EXPORT_SYMBOL(__devm_gpiod_get_index); /** * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() * @dev: GPIO consumer * @con_id: function within the GPIO consumer * @index: index of the GPIO to obtain in the consumer + * @flags: optional GPIO initialization flags * * Managed gpiod_get_index_optional(). GPIO descriptors returned from this * function are automatically disposed on driver detach. See * gpiod_get_index_optional() for detailed information about behavior and * return values. */ -struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, +struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *dev, const char *con_id, - unsigned int index) + unsigned int index, + enum gpiod_flags flags) { struct gpio_desc *desc; - desc = devm_gpiod_get_index(dev, con_id, index); + desc = devm_gpiod_get_index(dev, con_id, index, flags); if (IS_ERR(desc)) { if (PTR_ERR(desc) == -ENOENT) return NULL; @@ -127,7 +135,7 @@ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, return desc; } -EXPORT_SYMBOL(devm_gpiod_get_index_optional); +EXPORT_SYMBOL(__devm_gpiod_get_index_optional); /** * devm_gpiod_put - Resource-managed gpiod_put() diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 330227581a25..15cc0bb65dda 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1582,38 +1582,43 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id, * gpiod_get - obtain a GPIO for a given GPIO function * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer + * @flags: optional GPIO initialization flags * * Return the GPIO descriptor corresponding to the function con_id of device * dev, -ENOENT if no GPIO has been assigned to the requested function, or * another IS_ERR() code if an error occured while trying to acquire the GPIO. */ -struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id) +struct gpio_desc *__must_check __gpiod_get(struct device *dev, const char *con_id, + enum gpiod_flags flags) { - return gpiod_get_index(dev, con_id, 0); + return gpiod_get_index(dev, con_id, 0, flags); } -EXPORT_SYMBOL_GPL(gpiod_get); +EXPORT_SYMBOL_GPL(__gpiod_get); /** * gpiod_get_optional - obtain an optional GPIO for a given GPIO function * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer + * @flags: optional GPIO initialization flags * * This is equivalent to gpiod_get(), except that when no GPIO was assigned to * the requested function it will return NULL. This is convenient for drivers * that need to handle optional GPIOs. */ -struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, - const char *con_id) +struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev, + const char *con_id, + enum gpiod_flags flags) { - return gpiod_get_index_optional(dev, con_id, 0); + return gpiod_get_index_optional(dev, con_id, 0, flags); } -EXPORT_SYMBOL_GPL(gpiod_get_optional); +EXPORT_SYMBOL_GPL(__gpiod_get_optional); /** * gpiod_get_index - obtain a GPIO from a multi-index GPIO function * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * @idx: index of the GPIO to obtain in the consumer + * @flags: optional GPIO initialization flags * * This variant of gpiod_get() allows to access GPIOs other than the first * defined one for functions that define several GPIOs. @@ -1622,23 +1627,24 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional); * requested function and/or index, or another IS_ERR() code if an error * occured while trying to acquire the GPIO. */ -struct gpio_desc *__must_check gpiod_get_index(struct device *dev, +struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, const char *con_id, - unsigned int idx) + unsigned int idx, + enum gpiod_flags flags) { struct gpio_desc *desc = NULL; int status; - enum gpio_lookup_flags flags = 0; + enum gpio_lookup_flags lookupflags = 0; dev_dbg(dev, "GPIO lookup for consumer %s\n", con_id); /* Using device tree? */ if (IS_ENABLED(CONFIG_OF) && dev && dev->of_node) { dev_dbg(dev, "using device tree for GPIO lookup\n"); - desc = of_find_gpio(dev, con_id, idx, &flags); + desc = of_find_gpio(dev, con_id, idx, &lookupflags); } else if (IS_ENABLED(CONFIG_ACPI) && dev && ACPI_HANDLE(dev)) { dev_dbg(dev, "using ACPI for GPIO lookup\n"); - desc = acpi_find_gpio(dev, con_id, idx, &flags); + desc = acpi_find_gpio(dev, con_id, idx, &lookupflags); } /* @@ -1647,7 +1653,7 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, */ if (!desc || desc == ERR_PTR(-ENOENT)) { dev_dbg(dev, "using lookup tables for GPIO lookup"); - desc = gpiod_find(dev, con_id, idx, &flags); + desc = gpiod_find(dev, con_id, idx, &lookupflags); } if (IS_ERR(desc)) { @@ -1660,16 +1666,33 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev, if (status < 0) return ERR_PTR(status); - if (flags & GPIO_ACTIVE_LOW) + if (lookupflags & GPIO_ACTIVE_LOW) set_bit(FLAG_ACTIVE_LOW, &desc->flags); - if (flags & GPIO_OPEN_DRAIN) + if (lookupflags & GPIO_OPEN_DRAIN) set_bit(FLAG_OPEN_DRAIN, &desc->flags); - if (flags & GPIO_OPEN_SOURCE) + if (lookupflags & GPIO_OPEN_SOURCE) set_bit(FLAG_OPEN_SOURCE, &desc->flags); + /* No particular flag request, return here... */ + if (flags & GPIOD_FLAGS_BIT_DIR_SET) + return desc; + + /* Process flags */ + if (flags & GPIOD_FLAGS_BIT_DIR_OUT) + status = gpiod_direction_output(desc, + flags & GPIOD_FLAGS_BIT_DIR_VAL); + else + status = gpiod_direction_input(desc); + + if (status < 0) { + dev_dbg(dev, "setup of GPIO %s failed\n", con_id); + gpiod_put(desc); + return ERR_PTR(status); + } + return desc; } -EXPORT_SYMBOL_GPL(gpiod_get_index); +EXPORT_SYMBOL_GPL(__gpiod_get_index); /** * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO @@ -1677,18 +1700,20 @@ EXPORT_SYMBOL_GPL(gpiod_get_index); * @dev: GPIO consumer, can be NULL for system-global GPIOs * @con_id: function within the GPIO consumer * @index: index of the GPIO to obtain in the consumer + * @flags: optional GPIO initialization flags * * This is equivalent to gpiod_get_index(), except that when no GPIO with the * specified index was assigned to the requested function it will return NULL. * This is convenient for drivers that need to handle optional GPIOs. */ -struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, +struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev, const char *con_id, - unsigned int index) + unsigned int index, + enum gpiod_flags flags) { struct gpio_desc *desc; - desc = gpiod_get_index(dev, con_id, index); + desc = gpiod_get_index(dev, con_id, index, flags); if (IS_ERR(desc)) { if (PTR_ERR(desc) == -ENOENT) return NULL; @@ -1696,7 +1721,7 @@ struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, return desc; } -EXPORT_SYMBOL_GPL(gpiod_get_index_optional); +EXPORT_SYMBOL_GPL(__gpiod_get_index_optional); /** * gpiod_put - dispose of a GPIO descriptor |