backports: add devm_gpio_request{_one}()
authorHauke Mehrtens <hauke@hauke-m.de>
Sat, 31 May 2014 15:18:28 +0000 (17:18 +0200)
committerHauke Mehrtens <hauke@hauke-m.de>
Sun, 1 Jun 2014 22:16:18 +0000 (00:16 +0200)
These two functions are used by some drivers, but not available in all
kernel versions.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
backport/backport-include/linux/gpio.h [new file with mode: 0644]
backport/compat/compat-3.5.c

diff --git a/backport/backport-include/linux/gpio.h b/backport/backport-include/linux/gpio.h
new file mode 100644 (file)
index 0000000..8fb7211
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __BACKPORT_LINUX_GPIO_H
+#define __BACKPORT_LINUX_GPIO_H
+#include_next <linux/gpio.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
+#define devm_gpio_request_one LINUX_BACKPORT(devm_gpio_request_one)
+#define devm_gpio_request LINUX_BACKPORT(devm_gpio_request)
+#ifdef CONFIG_GPIOLIB
+int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
+int devm_gpio_request_one(struct device *dev, unsigned gpio,
+                         unsigned long flags, const char *label);
+#else
+static inline int devm_gpio_request(struct device *dev, unsigned gpio,
+                                   const char *label)
+{
+       WARN_ON(1);
+       return -EINVAL;
+}
+
+static inline int devm_gpio_request_one(struct device *dev, unsigned gpio,
+                                       unsigned long flags, const char *label)
+{
+       WARN_ON(1);
+       return -EINVAL;
+}
+#endif /* CONFIG_GPIOLIB */
+#endif
+
+#endif /* __BACKPORT_LINUX_GPIO_H */
index 2727eb323b9c801d0a4978f1568ba6d8bb895daa..13f64768ccaed674a0fd188b541aec620bdc52a4 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/highuid.h>
 #include <linux/ktime.h>
 #include <linux/hrtimer.h>
+#include <linux/gpio.h>
 #include <linux/ptp_clock_kernel.h>
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0))
@@ -73,3 +74,79 @@ int ptp_clock_index(struct ptp_clock *ptp)
 }
 EXPORT_SYMBOL(ptp_clock_index);
 #endif /* CONFIG_PTP_1588_CLOCK */
+
+#ifdef CONFIG_GPIOLIB
+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.
+ *
+ *      If an GPIO allocated with this function needs to be freed
+ *      separately, devm_gpio_free() must be used.
+ */
+
+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);
+#endif /* CONFIG_GPIOLIB */