Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: Add helpers for optional GPIOs

Introduce gpiod_get_optional() and gpiod_get_index_optional() helpers
that make it easier for drivers to handle optional GPIOs.

Currently in order to handle optional GPIOs, a driver needs to special
case error handling for -ENOENT, such as this:

gpio = gpiod_get(dev, "foo");
if (IS_ERR(gpio)) {
if (PTR_ERR(gpio) != -ENOENT)
return PTR_ERR(gpio);

gpio = NULL;
}

if (gpio) {
/* set up GPIO */
}

With these new helpers the above is reduced to:

gpio = gpiod_get_optional(dev, "foo");
if (IS_ERR(gpio))
return PTR_ERR(gpio);

if (gpio) {
/* set up GPIO */
}

While at it, device-managed variants of these functions are also
provided.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Thierry Reding and committed by
Linus Walleij
29a1f233 91329132

+128
+2
Documentation/driver-model/devres.txt
··· 312 312 GPIO 313 313 devm_gpiod_get() 314 314 devm_gpiod_get_index() 315 + devm_gpiod_get_optional() 316 + devm_gpiod_get_index_optional() 315 317 devm_gpiod_put()
+43
drivers/gpio/devres.c
··· 52 52 EXPORT_SYMBOL(devm_gpiod_get); 53 53 54 54 /** 55 + * devm_gpiod_get_optional - Resource-managed gpiod_get_optional() 56 + * @dev: GPIO consumer 57 + * @con_id: function within the GPIO consumer 58 + * 59 + * Managed gpiod_get_optional(). GPIO descriptors returned from this function 60 + * are automatically disposed on driver detach. See gpiod_get_optional() for 61 + * detailed information about behavior and return values. 62 + */ 63 + struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, 64 + const char *con_id) 65 + { 66 + return devm_gpiod_get_index_optional(dev, con_id, 0); 67 + } 68 + EXPORT_SYMBOL(devm_gpiod_get_optional); 69 + 70 + /** 55 71 * devm_gpiod_get_index - Resource-managed gpiod_get_index() 56 72 * @dev: GPIO consumer 57 73 * @con_id: function within the GPIO consumer ··· 101 85 return desc; 102 86 } 103 87 EXPORT_SYMBOL(devm_gpiod_get_index); 88 + 89 + /** 90 + * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() 91 + * @dev: GPIO consumer 92 + * @con_id: function within the GPIO consumer 93 + * @index: index of the GPIO to obtain in the consumer 94 + * 95 + * Managed gpiod_get_index_optional(). GPIO descriptors returned from this 96 + * function are automatically disposed on driver detach. See 97 + * gpiod_get_index_optional() for detailed information about behavior and 98 + * return values. 99 + */ 100 + struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev, 101 + const char *con_id, 102 + unsigned int index) 103 + { 104 + struct gpio_desc *desc; 105 + 106 + desc = devm_gpiod_get_index(dev, con_id, index); 107 + if (IS_ERR(desc)) { 108 + if (PTR_ERR(desc) == -ENOENT) 109 + return NULL; 110 + } 111 + 112 + return desc; 113 + } 114 + EXPORT_SYMBOL(devm_gpiod_get_index_optional); 104 115 105 116 /** 106 117 * devm_gpiod_put - Resource-managed gpiod_put()
+43
drivers/gpio/gpiolib.c
··· 2738 2738 EXPORT_SYMBOL_GPL(gpiod_get); 2739 2739 2740 2740 /** 2741 + * gpiod_get_optional - obtain an optional GPIO for a given GPIO function 2742 + * @dev: GPIO consumer, can be NULL for system-global GPIOs 2743 + * @con_id: function within the GPIO consumer 2744 + * 2745 + * This is equivalent to gpiod_get(), except that when no GPIO was assigned to 2746 + * the requested function it will return NULL. This is convenient for drivers 2747 + * that need to handle optional GPIOs. 2748 + */ 2749 + struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, 2750 + const char *con_id) 2751 + { 2752 + return gpiod_get_index_optional(dev, con_id, 0); 2753 + } 2754 + EXPORT_SYMBOL_GPL(gpiod_get_optional); 2755 + 2756 + /** 2741 2757 * gpiod_get_index - obtain a GPIO from a multi-index GPIO function 2742 2758 * @dev: GPIO consumer, can be NULL for system-global GPIOs 2743 2759 * @con_id: function within the GPIO consumer ··· 2814 2798 return desc; 2815 2799 } 2816 2800 EXPORT_SYMBOL_GPL(gpiod_get_index); 2801 + 2802 + /** 2803 + * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO 2804 + * function 2805 + * @dev: GPIO consumer, can be NULL for system-global GPIOs 2806 + * @con_id: function within the GPIO consumer 2807 + * @index: index of the GPIO to obtain in the consumer 2808 + * 2809 + * This is equivalent to gpiod_get_index(), except that when no GPIO with the 2810 + * specified index was assigned to the requested function it will return NULL. 2811 + * This is convenient for drivers that need to handle optional GPIOs. 2812 + */ 2813 + struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, 2814 + const char *con_id, 2815 + unsigned int index) 2816 + { 2817 + struct gpio_desc *desc; 2818 + 2819 + desc = gpiod_get_index(dev, con_id, index); 2820 + if (IS_ERR(desc)) { 2821 + if (PTR_ERR(desc) == -ENOENT) 2822 + return NULL; 2823 + } 2824 + 2825 + return desc; 2826 + } 2827 + EXPORT_SYMBOL_GPL(gpiod_get_index_optional); 2817 2828 2818 2829 /** 2819 2830 * gpiod_put - dispose of a GPIO descriptor
+40
include/linux/gpio/consumer.h
··· 23 23 struct gpio_desc *__must_check gpiod_get_index(struct device *dev, 24 24 const char *con_id, 25 25 unsigned int idx); 26 + struct gpio_desc *__must_check gpiod_get_optional(struct device *dev, 27 + const char *con_id); 28 + struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev, 29 + const char *con_id, 30 + unsigned int index); 31 + 26 32 void gpiod_put(struct gpio_desc *desc); 27 33 28 34 struct gpio_desc *__must_check devm_gpiod_get(struct device *dev, ··· 36 30 struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev, 37 31 const char *con_id, 38 32 unsigned int idx); 33 + struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev, 34 + const char *con_id); 35 + struct gpio_desc *__must_check 36 + devm_gpiod_get_index_optional(struct device *dev, const char *con_id, 37 + unsigned int index); 38 + 39 39 void devm_gpiod_put(struct device *dev, struct gpio_desc *desc); 40 40 41 41 int gpiod_get_direction(const struct gpio_desc *desc); ··· 85 73 { 86 74 return ERR_PTR(-ENOSYS); 87 75 } 76 + 77 + static inline struct gpio_desc *__must_check 78 + gpiod_get_optional(struct device *dev, const char *con_id) 79 + { 80 + return ERR_PTR(-ENOSYS); 81 + } 82 + 83 + static inline struct gpio_desc *__must_check 84 + gpiod_get_index_optional(struct device *dev, const char *con_id, 85 + unsigned int index) 86 + { 87 + return ERR_PTR(-ENOSYS); 88 + } 89 + 88 90 static inline void gpiod_put(struct gpio_desc *desc) 89 91 { 90 92 might_sleep(); ··· 119 93 { 120 94 return ERR_PTR(-ENOSYS); 121 95 } 96 + 97 + static inline struct gpio_desc *__must_check 98 + devm_gpiod_get_optional(struct device *dev, const char *con_id) 99 + { 100 + return ERR_PTR(-ENOSYS); 101 + } 102 + 103 + static inline struct gpio_desc *__must_check 104 + devm_gpiod_get_index_optional(struct device *dev, const char *con_id, 105 + unsigned int index) 106 + { 107 + return ERR_PTR(-ENOSYS); 108 + } 109 + 122 110 static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc) 123 111 { 124 112 might_sleep();