diff options
Diffstat (limited to 'drivers/gpio/gpiolib-devres.c')
-rw-r--r-- | drivers/gpio/gpiolib-devres.c | 211 |
1 files changed, 72 insertions, 139 deletions
diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c index 4987e62dcb3d..72422c5db364 100644 --- a/drivers/gpio/gpiolib-devres.c +++ b/drivers/gpio/gpiolib-devres.c @@ -6,41 +6,27 @@ * Copyright (c) 2011 John Crispin <john@phrozen.org> */ -#include <linux/module.h> +#include <linux/device/devres.h> #include <linux/err.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h> -#include <linux/device.h> +#include <linux/export.h> #include <linux/gfp.h> +#include <linux/types.h> -#include "gpiolib.h" - -static void devm_gpiod_release(struct device *dev, void *res) -{ - struct gpio_desc **desc = res; - - gpiod_put(*desc); -} +#include <linux/gpio/consumer.h> -static int devm_gpiod_match(struct device *dev, void *res, void *data) -{ - struct gpio_desc **this = res, **gpio = data; +#include "gpiolib.h" - return *this == *gpio; -} +struct fwnode_handle; +struct lock_class_key; -static void devm_gpiod_release_array(struct device *dev, void *res) +static void devm_gpiod_release(void *desc) { - struct gpio_descs **descs = res; - - gpiod_put_array(*descs); + gpiod_put(desc); } -static int devm_gpiod_match_array(struct device *dev, void *res, void *data) +static void devm_gpiod_release_array(void *descs) { - struct gpio_descs **this = res, **gpios = data; - - return *this == *gpios; + gpiod_put_array(descs); } /** @@ -52,6 +38,11 @@ static int devm_gpiod_match_array(struct device *dev, void *res, void *data) * 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. + * + * Returns: + * 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 occurred while trying to acquire the GPIO. */ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, const char *con_id, @@ -70,6 +61,11 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get); * 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. + * + * Returns: + * The GPIO descriptor corresponding to the function @con_id of device + * dev, NULL if no GPIO has been assigned to the requested function, or + * another IS_ERR() code if an error occurred while trying to acquire the GPIO. */ struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, const char *con_id, @@ -89,14 +85,19 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_optional); * 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. + * + * Returns: + * 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 occurred while trying to acquire the GPIO. */ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, const char *con_id, unsigned int idx, enum gpiod_flags flags) { - struct gpio_desc **dr; struct gpio_desc *desc; + int ret; desc = gpiod_get_index(dev, con_id, idx, flags); if (IS_ERR(desc)) @@ -107,23 +108,16 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, * already under resource management by this device. */ if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) { - struct devres *dres; + bool dres; - dres = devres_find(dev, devm_gpiod_release, - devm_gpiod_match, &desc); + dres = devm_is_action_added(dev, devm_gpiod_release, desc); if (dres) return desc; } - dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), - GFP_KERNEL); - if (!dr) { - gpiod_put(desc); - return ERR_PTR(-ENOMEM); - } - - *dr = desc; - devres_add(dev, dr); + ret = devm_add_action_or_reset(dev, devm_gpiod_release, desc); + if (ret) + return ERR_PTR(ret); return desc; } @@ -141,8 +135,10 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_index); * GPIO descriptors returned from this function are automatically disposed on * driver detach. * - * On successful request the GPIO pin is configured in accordance with - * provided @flags. + * Returns: + * 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 occurred while trying to acquire the GPIO. */ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, struct fwnode_handle *fwnode, @@ -150,22 +146,16 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, enum gpiod_flags flags, const char *label) { - struct gpio_desc **dr; struct gpio_desc *desc; - - dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), - GFP_KERNEL); - if (!dr) - return ERR_PTR(-ENOMEM); + int ret; desc = gpiod_find_and_request(dev, fwnode, con_id, index, flags, label, false); - if (IS_ERR(desc)) { - devres_free(dr); + if (IS_ERR(desc)) return desc; - } - *dr = desc; - devres_add(dev, dr); + ret = devm_add_action_or_reset(dev, devm_gpiod_release, desc); + if (ret) + return ERR_PTR(ret); return desc; } @@ -182,6 +172,11 @@ EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index); * function are automatically disposed on driver detach. See * gpiod_get_index_optional() for detailed information about behavior and * return values. + * + * Returns: + * The GPIO descriptor corresponding to the function @con_id of device + * dev, %NULL if no GPIO has been assigned to the requested function, or + * another IS_ERR() code if an error occurred while trying to acquire the GPIO. */ struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, const char *con_id, @@ -207,27 +202,27 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_index_optional); * Managed gpiod_get_array(). GPIO descriptors returned from this function are * automatically disposed on driver detach. See gpiod_get_array() for detailed * information about behavior and return values. + * + * Returns: + * The GPIO descriptors 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 occurred while trying to acquire + * the GPIOs. */ struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev, const char *con_id, enum gpiod_flags flags) { - struct gpio_descs **dr; struct gpio_descs *descs; - - dr = devres_alloc(devm_gpiod_release_array, - sizeof(struct gpio_descs *), GFP_KERNEL); - if (!dr) - return ERR_PTR(-ENOMEM); + int ret; descs = gpiod_get_array(dev, con_id, flags); - if (IS_ERR(descs)) { - devres_free(dr); + if (IS_ERR(descs)) return descs; - } - *dr = descs; - devres_add(dev, dr); + ret = devm_add_action_or_reset(dev, devm_gpiod_release_array, descs); + if (ret) + return ERR_PTR(ret); return descs; } @@ -243,6 +238,12 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_array); * function are automatically disposed on driver detach. * See gpiod_get_array_optional() for detailed information about behavior and * return values. + * + * Returns: + * The GPIO descriptors corresponding to the function @con_id of device + * dev, %NULL if no GPIO has been assigned to the requested function, + * or another IS_ERR() code if an error occurred while trying to acquire + * the GPIOs. */ struct gpio_descs *__must_check devm_gpiod_get_array_optional(struct device *dev, const char *con_id, @@ -269,8 +270,7 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_array_optional); */ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) { - WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match, - &desc)); + devm_release_action(dev, devm_gpiod_release, desc); } EXPORT_SYMBOL_GPL(devm_gpiod_put); @@ -279,24 +279,28 @@ EXPORT_SYMBOL_GPL(devm_gpiod_put); * @dev: GPIO consumer * @desc: GPIO descriptor to remove resource management from * + * *DEPRECATED* + * This function should not be used. It's been provided as a workaround for + * resource ownership issues in the regulator framework and should be replaced + * with a better solution. + * * Remove resource management from a GPIO descriptor. This is needed when * you want to hand over lifecycle management of a descriptor to another * mechanism. */ - void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc) { int ret; if (IS_ERR_OR_NULL(desc)) return; - ret = devres_destroy(dev, devm_gpiod_release, - devm_gpiod_match, &desc); + /* * If the GPIO descriptor is requested as nonexclusive, we * may call this function several times on the same descriptor * so it is OK if devres_destroy() returns -ENOENT. */ + ret = devm_remove_action_nowarn(dev, devm_gpiod_release, desc); if (ret == -ENOENT) return; /* Anything else we should warn about */ @@ -315,81 +319,10 @@ EXPORT_SYMBOL_GPL(devm_gpiod_unhinge); */ void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs) { - WARN_ON(devres_release(dev, devm_gpiod_release_array, - devm_gpiod_match_array, &descs)); + devm_release_action(dev, devm_gpiod_release_array, descs); } EXPORT_SYMBOL_GPL(devm_gpiod_put_array); -static void devm_gpio_release(struct device *dev, void *res) -{ - unsigned *gpio = res; - - gpio_free(*gpio); -} - -/** - * devm_gpio_request - request a GPIO for a managed device - * @dev: device to request the GPIO for - * @gpio: GPIO to allocate - * @label: the name of the requested GPIO - * - * Except for the extra @dev argument, this function takes the - * same arguments and performs the same function as - * gpio_request(). GPIOs requested with this function will be - * automatically freed on driver detach. - */ -int devm_gpio_request(struct device *dev, unsigned gpio, const char *label) -{ - unsigned *dr; - int rc; - - dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - rc = gpio_request(gpio, label); - if (rc) { - devres_free(dr); - return rc; - } - - *dr = gpio; - devres_add(dev, dr); - - return 0; -} -EXPORT_SYMBOL_GPL(devm_gpio_request); - -/** - * devm_gpio_request_one - request a single GPIO with initial setup - * @dev: device to request for - * @gpio: the GPIO number - * @flags: GPIO configuration as specified by GPIOF_* - * @label: a literal description string of this GPIO - */ -int devm_gpio_request_one(struct device *dev, unsigned gpio, - unsigned long flags, const char *label) -{ - unsigned *dr; - int rc; - - dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - rc = gpio_request_one(gpio, flags, label); - if (rc) { - devres_free(dr); - return rc; - } - - *dr = gpio; - devres_add(dev, dr); - - return 0; -} -EXPORT_SYMBOL_GPL(devm_gpio_request_one); - static void devm_gpio_chip_release(void *data) { struct gpio_chip *gc = data; |