On Thu, Aug 27, 2020 at 9:28 AM Krzysztof Kozlowski <krzk@xxxxxxxxxx> wrote: > > Add devm_fwnode_gpiod_get_optional() and > devm_fwnode_gpiod_get_index_optional() helpers, similar to regular > devm_gpiod optional versions. Drivers getting GPIOs from a firmware > node might use it to remove some boilerplate code. > For both: Reviewed-by: Andy Shevchenko <andy.shevchenko@xxxxxxxxx> > Signed-off-by: Krzysztof Kozlowski <krzk@xxxxxxxxxx> > > --- > > Changes since v2: > 1. Return NULL > > Changes since v1: > 1. New patch > --- > drivers/gpio/gpiolib-devres.c | 71 +++++++++++++++++++++++++++++++++++ > include/linux/gpio/consumer.h | 30 +++++++++++++++ > 2 files changed, 101 insertions(+) > > diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c > index 7dbce4c4ebdf..f8476f6a65cc 100644 > --- a/drivers/gpio/gpiolib-devres.c > +++ b/drivers/gpio/gpiolib-devres.c > @@ -184,6 +184,37 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev, > } > EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node); > > +/** > + * devm_fwnode_gpiod_get_optional - Resource-managed fwnode_gpiod_get_index() > + * for optional GPIO > + * @dev: GPIO consumer > + * @fwnode: firmware node containing GPIO reference > + * @con_id: function within the GPIO consumer > + * @flags: GPIO initialization flags > + * @label: label to attach to the requested GPIO > + * > + * GPIO descriptors returned from this function are automatically disposed on > + * driver detach. > + * > + * This is equivalent to devm_fwnode_gpiod_get_index(), except that when no > + * GPIO with the specified index was assigned to the requested function it will > + * return NULL. This is convenient for drivers that need to handle optional > + * GPIOs. > + * > + * On successful request the GPIO pin is configured in accordance with > + * provided @flags. > + */ > +struct gpio_desc *devm_fwnode_gpiod_get_optional(struct device *dev, > + struct fwnode_handle *fwnode, > + const char *con_id, > + enum gpiod_flags flags, > + const char *label) > +{ > + return devm_fwnode_gpiod_get_index_optional(dev, fwnode, con_id, 0, > + flags, label); > +} > +EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_optional); > + > /** > * devm_fwnode_gpiod_get_index - get a GPIO descriptor from a given node > * @dev: GPIO consumer > @@ -226,6 +257,46 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, > } > EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index); > > +/** > + * devm_fwnode_gpiod_get_index_optional - Resource-managed fwnode_gpiod_get_index() > + * for optional GPIO > + * @dev: GPIO consumer > + * @fwnode: firmware node containing GPIO reference > + * @con_id: function within the GPIO consumer > + * @index: index of the GPIO to obtain in the consumer > + * @flags: GPIO initialization flags > + * @label: label to attach to the requested GPIO > + * > + * GPIO descriptors returned from this function are automatically disposed on > + * driver detach. > + * > + * This is equivalent to devm_fwnode_gpiod_get_index(), except that when no > + * GPIO with the specified index was assigned to the requested function it will > + * return NULL. This is convenient for drivers that need to handle optional > + * GPIOs. > + * > + * On successful request the GPIO pin is configured in accordance with > + * provided @flags. > + */ > +struct gpio_desc *devm_fwnode_gpiod_get_index_optional(struct device *dev, > + struct fwnode_handle *fwnode, > + const char *con_id, int index, > + enum gpiod_flags flags, > + const char *label) > +{ > + struct gpio_desc *desc; > + > + desc = devm_fwnode_gpiod_get_index(dev, fwnode, con_id, index, flags, > + label); > + if (IS_ERR(desc)) { > + if (PTR_ERR(desc) == -ENOENT) > + return NULL; > + } > + > + return desc; > +} > +EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index_optional); > + > /** > * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() > * @dev: GPIO consumer > diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h > index 901aab89d025..7854d80b1e9a 100644 > --- a/include/linux/gpio/consumer.h > +++ b/include/linux/gpio/consumer.h > @@ -183,11 +183,21 @@ struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode, > const char *con_id, int index, > enum gpiod_flags flags, > const char *label); > +struct gpio_desc *devm_fwnode_gpiod_get_optional(struct device *dev, > + struct fwnode_handle *fwnode, > + const char *con_id, > + enum gpiod_flags flags, > + const char *label); > struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, > struct fwnode_handle *child, > const char *con_id, int index, > enum gpiod_flags flags, > const char *label); > +struct gpio_desc *devm_fwnode_gpiod_get_index_optional(struct device *dev, > + struct fwnode_handle *fwnode, > + const char *con_id, int index, > + enum gpiod_flags flags, > + const char *label); > > #else /* CONFIG_GPIOLIB */ > > @@ -562,6 +572,16 @@ struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode, > return ERR_PTR(-ENOSYS); > } > > +static inline > +struct gpio_desc *devm_fwnode_gpiod_get_optional(struct device *dev, > + struct fwnode_handle *fwnode, > + const char *con_id, > + enum gpiod_flags flags, > + const char *label) > +{ > + return NULL; > +} > + > static inline > struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, > struct fwnode_handle *fwnode, > @@ -572,6 +592,16 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, > return ERR_PTR(-ENOSYS); > } > > +static inline > +struct gpio_desc *devm_fwnode_gpiod_get_index_optional(struct device *dev, > + struct fwnode_handle *fwnode, > + const char *con_id, int index, > + enum gpiod_flags flags, > + const char *label) > +{ > + return NULL; > +} > + > #endif /* CONFIG_GPIOLIB */ > > static inline > -- > 2.17.1 > -- With Best Regards, Andy Shevchenko