398 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * devres.c - managed gpio resources4 * This file is based on kernel/irq/devres.c5 *6 * Copyright (c) 2011 John Crispin <john@phrozen.org>7 */8 9#include <linux/device.h>10#include <linux/err.h>11#include <linux/export.h>12#include <linux/gfp.h>13#include <linux/types.h>14 15#include <linux/gpio/consumer.h>16 17#include "gpiolib.h"18 19struct fwnode_handle;20struct lock_class_key;21 22static void devm_gpiod_release(struct device *dev, void *res)23{24 struct gpio_desc **desc = res;25 26 gpiod_put(*desc);27}28 29static int devm_gpiod_match(struct device *dev, void *res, void *data)30{31 struct gpio_desc **this = res, **gpio = data;32 33 return *this == *gpio;34}35 36static void devm_gpiod_release_array(struct device *dev, void *res)37{38 struct gpio_descs **descs = res;39 40 gpiod_put_array(*descs);41}42 43static int devm_gpiod_match_array(struct device *dev, void *res, void *data)44{45 struct gpio_descs **this = res, **gpios = data;46 47 return *this == *gpios;48}49 50/**51 * devm_gpiod_get - Resource-managed gpiod_get()52 * @dev: GPIO consumer53 * @con_id: function within the GPIO consumer54 * @flags: optional GPIO initialization flags55 *56 * Managed gpiod_get(). GPIO descriptors returned from this function are57 * automatically disposed on driver detach. See gpiod_get() for detailed58 * information about behavior and return values.59 *60 * Returns:61 * The GPIO descriptor corresponding to the function @con_id of device62 * dev, %-ENOENT if no GPIO has been assigned to the requested function, or63 * another IS_ERR() code if an error occurred while trying to acquire the GPIO.64 */65struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,66 const char *con_id,67 enum gpiod_flags flags)68{69 return devm_gpiod_get_index(dev, con_id, 0, flags);70}71EXPORT_SYMBOL_GPL(devm_gpiod_get);72 73/**74 * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()75 * @dev: GPIO consumer76 * @con_id: function within the GPIO consumer77 * @flags: optional GPIO initialization flags78 *79 * Managed gpiod_get_optional(). GPIO descriptors returned from this function80 * are automatically disposed on driver detach. See gpiod_get_optional() for81 * detailed information about behavior and return values.82 *83 * Returns:84 * The GPIO descriptor corresponding to the function @con_id of device85 * dev, NULL if no GPIO has been assigned to the requested function, or86 * another IS_ERR() code if an error occurred while trying to acquire the GPIO.87 */88struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,89 const char *con_id,90 enum gpiod_flags flags)91{92 return devm_gpiod_get_index_optional(dev, con_id, 0, flags);93}94EXPORT_SYMBOL_GPL(devm_gpiod_get_optional);95 96/**97 * devm_gpiod_get_index - Resource-managed gpiod_get_index()98 * @dev: GPIO consumer99 * @con_id: function within the GPIO consumer100 * @idx: index of the GPIO to obtain in the consumer101 * @flags: optional GPIO initialization flags102 *103 * Managed gpiod_get_index(). GPIO descriptors returned from this function are104 * automatically disposed on driver detach. See gpiod_get_index() for detailed105 * information about behavior and return values.106 *107 * Returns:108 * The GPIO descriptor corresponding to the function @con_id of device109 * dev, %-ENOENT if no GPIO has been assigned to the requested function, or110 * another IS_ERR() code if an error occurred while trying to acquire the GPIO.111 */112struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,113 const char *con_id,114 unsigned int idx,115 enum gpiod_flags flags)116{117 struct gpio_desc **dr;118 struct gpio_desc *desc;119 120 desc = gpiod_get_index(dev, con_id, idx, flags);121 if (IS_ERR(desc))122 return desc;123 124 /*125 * For non-exclusive GPIO descriptors, check if this descriptor is126 * already under resource management by this device.127 */128 if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {129 struct devres *dres;130 131 dres = devres_find(dev, devm_gpiod_release,132 devm_gpiod_match, &desc);133 if (dres)134 return desc;135 }136 137 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),138 GFP_KERNEL);139 if (!dr) {140 gpiod_put(desc);141 return ERR_PTR(-ENOMEM);142 }143 144 *dr = desc;145 devres_add(dev, dr);146 147 return desc;148}149EXPORT_SYMBOL_GPL(devm_gpiod_get_index);150 151/**152 * devm_fwnode_gpiod_get_index - get a GPIO descriptor from a given node153 * @dev: GPIO consumer154 * @fwnode: firmware node containing GPIO reference155 * @con_id: function within the GPIO consumer156 * @index: index of the GPIO to obtain in the consumer157 * @flags: GPIO initialization flags158 * @label: label to attach to the requested GPIO159 *160 * GPIO descriptors returned from this function are automatically disposed on161 * driver detach.162 *163 * Returns:164 * The GPIO descriptor corresponding to the function @con_id of device165 * dev, %-ENOENT if no GPIO has been assigned to the requested function, or166 * another IS_ERR() code if an error occurred while trying to acquire the GPIO.167 */168struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,169 struct fwnode_handle *fwnode,170 const char *con_id, int index,171 enum gpiod_flags flags,172 const char *label)173{174 struct gpio_desc **dr;175 struct gpio_desc *desc;176 177 dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),178 GFP_KERNEL);179 if (!dr)180 return ERR_PTR(-ENOMEM);181 182 desc = gpiod_find_and_request(dev, fwnode, con_id, index, flags, label, false);183 if (IS_ERR(desc)) {184 devres_free(dr);185 return desc;186 }187 188 *dr = desc;189 devres_add(dev, dr);190 191 return desc;192}193EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index);194 195/**196 * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()197 * @dev: GPIO consumer198 * @con_id: function within the GPIO consumer199 * @index: index of the GPIO to obtain in the consumer200 * @flags: optional GPIO initialization flags201 *202 * Managed gpiod_get_index_optional(). GPIO descriptors returned from this203 * function are automatically disposed on driver detach. See204 * gpiod_get_index_optional() for detailed information about behavior and205 * return values.206 *207 * Returns:208 * The GPIO descriptor corresponding to the function @con_id of device209 * dev, %NULL if no GPIO has been assigned to the requested function, or210 * another IS_ERR() code if an error occurred while trying to acquire the GPIO.211 */212struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,213 const char *con_id,214 unsigned int index,215 enum gpiod_flags flags)216{217 struct gpio_desc *desc;218 219 desc = devm_gpiod_get_index(dev, con_id, index, flags);220 if (gpiod_not_found(desc))221 return NULL;222 223 return desc;224}225EXPORT_SYMBOL_GPL(devm_gpiod_get_index_optional);226 227/**228 * devm_gpiod_get_array - Resource-managed gpiod_get_array()229 * @dev: GPIO consumer230 * @con_id: function within the GPIO consumer231 * @flags: optional GPIO initialization flags232 *233 * Managed gpiod_get_array(). GPIO descriptors returned from this function are234 * automatically disposed on driver detach. See gpiod_get_array() for detailed235 * information about behavior and return values.236 *237 * Returns:238 * The GPIO descriptors corresponding to the function @con_id of device239 * dev, %-ENOENT if no GPIO has been assigned to the requested function,240 * or another IS_ERR() code if an error occurred while trying to acquire241 * the GPIOs.242 */243struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,244 const char *con_id,245 enum gpiod_flags flags)246{247 struct gpio_descs **dr;248 struct gpio_descs *descs;249 250 dr = devres_alloc(devm_gpiod_release_array,251 sizeof(struct gpio_descs *), GFP_KERNEL);252 if (!dr)253 return ERR_PTR(-ENOMEM);254 255 descs = gpiod_get_array(dev, con_id, flags);256 if (IS_ERR(descs)) {257 devres_free(dr);258 return descs;259 }260 261 *dr = descs;262 devres_add(dev, dr);263 264 return descs;265}266EXPORT_SYMBOL_GPL(devm_gpiod_get_array);267 268/**269 * devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional()270 * @dev: GPIO consumer271 * @con_id: function within the GPIO consumer272 * @flags: optional GPIO initialization flags273 *274 * Managed gpiod_get_array_optional(). GPIO descriptors returned from this275 * function are automatically disposed on driver detach.276 * See gpiod_get_array_optional() for detailed information about behavior and277 * return values.278 *279 * Returns:280 * The GPIO descriptors corresponding to the function @con_id of device281 * dev, %NULL if no GPIO has been assigned to the requested function,282 * or another IS_ERR() code if an error occurred while trying to acquire283 * the GPIOs.284 */285struct gpio_descs *__must_check286devm_gpiod_get_array_optional(struct device *dev, const char *con_id,287 enum gpiod_flags flags)288{289 struct gpio_descs *descs;290 291 descs = devm_gpiod_get_array(dev, con_id, flags);292 if (gpiod_not_found(descs))293 return NULL;294 295 return descs;296}297EXPORT_SYMBOL_GPL(devm_gpiod_get_array_optional);298 299/**300 * devm_gpiod_put - Resource-managed gpiod_put()301 * @dev: GPIO consumer302 * @desc: GPIO descriptor to dispose of303 *304 * Dispose of a GPIO descriptor obtained with devm_gpiod_get() or305 * devm_gpiod_get_index(). Normally this function will not be called as the GPIO306 * will be disposed of by the resource management code.307 */308void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)309{310 WARN_ON(devres_release(dev, devm_gpiod_release, devm_gpiod_match,311 &desc));312}313EXPORT_SYMBOL_GPL(devm_gpiod_put);314 315/**316 * devm_gpiod_unhinge - Remove resource management from a gpio descriptor317 * @dev: GPIO consumer318 * @desc: GPIO descriptor to remove resource management from319 *320 * Remove resource management from a GPIO descriptor. This is needed when321 * you want to hand over lifecycle management of a descriptor to another322 * mechanism.323 */324 325void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)326{327 int ret;328 329 if (IS_ERR_OR_NULL(desc))330 return;331 ret = devres_destroy(dev, devm_gpiod_release,332 devm_gpiod_match, &desc);333 /*334 * If the GPIO descriptor is requested as nonexclusive, we335 * may call this function several times on the same descriptor336 * so it is OK if devres_destroy() returns -ENOENT.337 */338 if (ret == -ENOENT)339 return;340 /* Anything else we should warn about */341 WARN_ON(ret);342}343EXPORT_SYMBOL_GPL(devm_gpiod_unhinge);344 345/**346 * devm_gpiod_put_array - Resource-managed gpiod_put_array()347 * @dev: GPIO consumer348 * @descs: GPIO descriptor array to dispose of349 *350 * Dispose of an array of GPIO descriptors obtained with devm_gpiod_get_array().351 * Normally this function will not be called as the GPIOs will be disposed of352 * by the resource management code.353 */354void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)355{356 WARN_ON(devres_release(dev, devm_gpiod_release_array,357 devm_gpiod_match_array, &descs));358}359EXPORT_SYMBOL_GPL(devm_gpiod_put_array);360 361static void devm_gpio_chip_release(void *data)362{363 struct gpio_chip *gc = data;364 365 gpiochip_remove(gc);366}367 368/**369 * devm_gpiochip_add_data_with_key() - Resource managed gpiochip_add_data_with_key()370 * @dev: pointer to the device that gpio_chip belongs to.371 * @gc: the GPIO chip to register372 * @data: driver-private data associated with this chip373 * @lock_key: lockdep class for IRQ lock374 * @request_key: lockdep class for IRQ request375 *376 * Context: potentially before irqs will work377 *378 * The gpio chip automatically be released when the device is unbound.379 *380 * Returns:381 * A negative errno if the chip can't be registered, such as because the382 * gc->base is invalid or already associated with a different chip.383 * Otherwise it returns zero as a success code.384 */385int devm_gpiochip_add_data_with_key(struct device *dev, struct gpio_chip *gc, void *data,386 struct lock_class_key *lock_key,387 struct lock_class_key *request_key)388{389 int ret;390 391 ret = gpiochip_add_data_with_key(gc, data, lock_key, request_key);392 if (ret < 0)393 return ret;394 395 return devm_add_action_or_reset(dev, devm_gpio_chip_release, gc);396}397EXPORT_SYMBOL_GPL(devm_gpiochip_add_data_with_key);398