brintos

brintos / linux-shallow public Read only

0
0
Text · 11.6 KiB · 08205f3 Raw
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