summaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpiolib.c
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2016-02-15 12:02:09 +0100
committerLaxman Dewangan <ldewangan@nvidia.com>2016-02-23 15:10:33 +0100
commit0cf3292cde22f8843ae5d1eeb8466d8121243c1a (patch)
tree3bc161eda1d422aa600434e3b03985ff736ea761 /drivers/gpio/gpiolib.c
parentMerge remote-tracking branch 'linusw-gpio/for-next' into devm_gpiochip (diff)
downloadlinux-0cf3292cde22f8843ae5d1eeb8466d8121243c1a.tar.xz
linux-0cf3292cde22f8843ae5d1eeb8466d8121243c1a.zip
gpio: Add devm_ apis for gpiochip_add_data and gpiochip_remove
Add device managed APIs devm_gpiochip_add_data() and devm_gpiochip_remove() for the APIs gpiochip_add_data() and gpiochip_remove(). This helps in reducing code in error path and sometimes removal of .remove callback for driver unbind. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Diffstat (limited to 'drivers/gpio/gpiolib.c')
-rw-r--r--drivers/gpio/gpiolib.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 872774a404f1..e31d0a1e6f7c 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -723,6 +723,80 @@ void gpiochip_remove(struct gpio_chip *chip)
}
EXPORT_SYMBOL_GPL(gpiochip_remove);
+static void devm_gpio_chip_release(struct device *dev, void *res)
+{
+ struct gpio_chip *chip = *(struct gpio_chip **)res;
+
+ gpiochip_remove(chip);
+}
+
+static int devm_gpio_chip_match(struct device *dev, void *res, void *data)
+
+{
+ struct gpio_chip **r = res;
+
+ if (!r || !*r) {
+ WARN_ON(!r || !*r);
+ return 0;
+ }
+
+ return *r == data;
+}
+
+/**
+ * devm_gpiochip_add_data() - Resource manager piochip_add_data()
+ * @dev: the device pointer on which irq_chip belongs to.
+ * @chip: the chip to register, with chip->base initialized
+ * Context: potentially before irqs will work
+ *
+ * Returns a negative errno if the chip can't be registered, such as
+ * because the chip->base is invalid or already associated with a
+ * different chip. Otherwise it returns zero as a success code.
+ *
+ * The gpio chip automatically be released when the device is unbound.
+ */
+int devm_gpiochip_add_data(struct device *dev, struct gpio_chip *chip,
+ void *data)
+{
+ struct gpio_chip **ptr;
+ int ret;
+
+ ptr = devres_alloc(devm_gpio_chip_release, sizeof(*ptr),
+ GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
+ ret = gpiochip_add_data(chip, data);
+ if (ret < 0) {
+ devres_free(ptr);
+ return ret;
+ }
+
+ *ptr = chip;
+ devres_add(dev, ptr);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(devm_gpiochip_add_data);
+
+/**
+ * devm_gpiochip_remove() - Resource manager of gpiochip_remove()
+ * @dev: device for which which resource was allocated
+ * @chip: the chip to remove
+ *
+ * A gpio_chip with any GPIOs still requested may not be removed.
+ */
+void devm_gpiochip_remove(struct device *dev, struct gpio_chip *chip)
+{
+ int ret;
+
+ ret = devres_release(dev, devm_gpio_chip_release,
+ devm_gpio_chip_match, chip);
+ if (!ret)
+ WARN_ON(ret);
+}
+EXPORT_SYMBOL_GPL(devm_gpiochip_remove);
+
/**
* gpiochip_find() - iterator for locating a specific gpio_chip
* @data: data to pass to match function