Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29a1f233 authored by Thierry Reding's avatar Thierry Reding Committed by Linus Walleij
Browse files

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: default avatarThierry Reding <treding@nvidia.com>
Reviewed-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 91329132
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -312,4 +312,6 @@ SPI
GPIO
  devm_gpiod_get()
  devm_gpiod_get_index()
  devm_gpiod_get_optional()
  devm_gpiod_get_index_optional()
  devm_gpiod_put()
+43 −0
Original line number Diff line number Diff line
@@ -51,6 +51,22 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
}
EXPORT_SYMBOL(devm_gpiod_get);

/**
 * devm_gpiod_get_optional - Resource-managed gpiod_get_optional()
 * @dev: GPIO consumer
 * @con_id: function within the GPIO consumer
 *
 * Managed gpiod_get_optional(). GPIO descriptors returned from this function
 * are automatically disposed on driver detach. See gpiod_get_optional() for
 * detailed information about behavior and return values.
 */
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
						       const char *con_id)
{
	return devm_gpiod_get_index_optional(dev, con_id, 0);
}
EXPORT_SYMBOL(devm_gpiod_get_optional);

/**
 * devm_gpiod_get_index - Resource-managed gpiod_get_index()
 * @dev:	GPIO consumer
@@ -86,6 +102,33 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
}
EXPORT_SYMBOL(devm_gpiod_get_index);

/**
 * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
 * @dev: GPIO consumer
 * @con_id: function within the GPIO consumer
 * @index: index of the GPIO to obtain in the consumer
 *
 * Managed gpiod_get_index_optional(). GPIO descriptors returned from this
 * function are automatically disposed on driver detach. See
 * gpiod_get_index_optional() for detailed information about behavior and
 * return values.
 */
struct gpio_desc *__must_check devm_gpiod_get_index_optional(struct device *dev,
							     const char *con_id,
							     unsigned int index)
{
	struct gpio_desc *desc;

	desc = devm_gpiod_get_index(dev, con_id, index);
	if (IS_ERR(desc)) {
		if (PTR_ERR(desc) == -ENOENT)
			return NULL;
	}

	return desc;
}
EXPORT_SYMBOL(devm_gpiod_get_index_optional);

/**
 * devm_gpiod_put - Resource-managed gpiod_put()
 * @desc:	GPIO descriptor to dispose of
+43 −0
Original line number Diff line number Diff line
@@ -2737,6 +2737,22 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev, const char *con_id)
}
EXPORT_SYMBOL_GPL(gpiod_get);

/**
 * gpiod_get_optional - obtain an optional GPIO for a given GPIO function
 * @dev: GPIO consumer, can be NULL for system-global GPIOs
 * @con_id: function within the GPIO consumer
 *
 * This is equivalent to gpiod_get(), except that when no GPIO was assigned to
 * the requested function it will return NULL. This is convenient for drivers
 * that need to handle optional GPIOs.
 */
struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
						  const char *con_id)
{
	return gpiod_get_index_optional(dev, con_id, 0);
}
EXPORT_SYMBOL_GPL(gpiod_get_optional);

/**
 * gpiod_get_index - obtain a GPIO from a multi-index GPIO function
 * @dev:	GPIO consumer, can be NULL for system-global GPIOs
@@ -2799,6 +2815,33 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
}
EXPORT_SYMBOL_GPL(gpiod_get_index);

/**
 * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
 *                            function
 * @dev: GPIO consumer, can be NULL for system-global GPIOs
 * @con_id: function within the GPIO consumer
 * @index: index of the GPIO to obtain in the consumer
 *
 * This is equivalent to 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.
 */
struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
							const char *con_id,
							unsigned int index)
{
	struct gpio_desc *desc;

	desc = gpiod_get_index(dev, con_id, index);
	if (IS_ERR(desc)) {
		if (PTR_ERR(desc) == -ENOENT)
			return NULL;
	}

	return desc;
}
EXPORT_SYMBOL_GPL(gpiod_get_index_optional);

/**
 * gpiod_put - dispose of a GPIO descriptor
 * @desc:	GPIO descriptor to dispose of
+40 −0
Original line number Diff line number Diff line
@@ -23,6 +23,12 @@ struct gpio_desc *__must_check gpiod_get(struct device *dev,
struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
					       const char *con_id,
					       unsigned int idx);
struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
						  const char *con_id);
struct gpio_desc *__must_check gpiod_get_index_optional(struct device *dev,
							const char *con_id,
							unsigned int index);

void gpiod_put(struct gpio_desc *desc);

struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
@@ -30,6 +36,12 @@ struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
						    const char *con_id,
						    unsigned int idx);
struct gpio_desc *__must_check devm_gpiod_get_optional(struct device *dev,
						       const char *con_id);
struct gpio_desc *__must_check
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
			      unsigned int index);

void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);

int gpiod_get_direction(const struct gpio_desc *desc);
@@ -73,6 +85,20 @@ static inline struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
{
	return ERR_PTR(-ENOSYS);
}

static inline struct gpio_desc *__must_check
gpiod_get_optional(struct device *dev, const char *con_id)
{
	return ERR_PTR(-ENOSYS);
}

static inline struct gpio_desc *__must_check
gpiod_get_index_optional(struct device *dev, const char *con_id,
			 unsigned int index)
{
	return ERR_PTR(-ENOSYS);
}

static inline void gpiod_put(struct gpio_desc *desc)
{
	might_sleep();
@@ -93,6 +119,20 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
{
	return ERR_PTR(-ENOSYS);
}

static inline struct gpio_desc *__must_check
devm_gpiod_get_optional(struct device *dev, const char *con_id)
{
	return ERR_PTR(-ENOSYS);
}

static inline struct gpio_desc *__must_check
devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
			      unsigned int index)
{
	return ERR_PTR(-ENOSYS);
}

static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
{
	might_sleep();