gpiolib: add devm_gpiod_get_array and devm_gpiod_put_array functions

Add device managed variants of gpiod_get_array() / gpiod_put_array()
functions for conveniently obtaining and disposing of an entire array
of GPIOs with one function call.

Signed-off-by: Rojhalat Ibrahim <imr@rtschenk.de>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
Rojhalat Ibrahim 2015-02-11 17:28:02 +01:00 committed by Linus Walleij
parent 6685852732
commit 331758eef8
3 changed files with 131 additions and 2 deletions

View File

@ -102,11 +102,19 @@ Device-managed variants of these functions are also defined:
const char *con_id,
enum gpiod_flags flags)
struct gpio_desc * devm_gpiod_get_index_optional(struct device *dev,
struct gpio_desc *devm_gpiod_get_index_optional(struct device *dev,
const char *con_id,
unsigned int index,
enum gpiod_flags flags)
struct gpio_descs *devm_gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
struct gpio_descs *devm_gpiod_get_array_optional(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
A GPIO descriptor can be disposed of using the gpiod_put() function:
void gpiod_put(struct gpio_desc *desc)
@ -119,10 +127,12 @@ It is strictly forbidden to use a descriptor after calling these functions.
It is also not allowed to individually release descriptors (using gpiod_put())
from an array acquired with gpiod_get_array().
The device-managed variant is, unsurprisingly:
The device-managed variants are, unsurprisingly:
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
Using GPIOs
===========

View File

@ -35,6 +35,20 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data)
return *this == *gpio;
}
static void devm_gpiod_release_array(struct device *dev, void *res)
{
struct gpio_descs **descs = res;
gpiod_put_array(*descs);
}
static int devm_gpiod_match_array(struct device *dev, void *res, void *data)
{
struct gpio_descs **this = res, **gpios = data;
return *this == *gpios;
}
/**
* devm_gpiod_get - Resource-managed gpiod_get()
* @dev: GPIO consumer
@ -185,6 +199,66 @@ struct gpio_desc *__must_check __devm_gpiod_get_index_optional(struct device *de
}
EXPORT_SYMBOL(__devm_gpiod_get_index_optional);
/**
* devm_gpiod_get_array - Resource-managed gpiod_get_array()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get_array(). GPIO descriptors returned from this function are
* automatically disposed on driver detach. See gpiod_get_array() for detailed
* information about behavior and return values.
*/
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags)
{
struct gpio_descs **dr;
struct gpio_descs *descs;
dr = devres_alloc(devm_gpiod_release_array,
sizeof(struct gpio_descs *), GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
descs = gpiod_get_array(dev, con_id, flags);
if (IS_ERR(descs)) {
devres_free(dr);
return descs;
}
*dr = descs;
devres_add(dev, dr);
return descs;
}
EXPORT_SYMBOL(devm_gpiod_get_array);
/**
* devm_gpiod_get_array_optional - Resource-managed gpiod_get_array_optional()
* @dev: GPIO consumer
* @con_id: function within the GPIO consumer
* @flags: optional GPIO initialization flags
*
* Managed gpiod_get_array_optional(). GPIO descriptors returned from this
* function are automatically disposed on driver detach.
* See gpiod_get_array_optional() for detailed information about behavior and
* return values.
*/
struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
struct gpio_descs *descs;
descs = devm_gpiod_get_array(dev, con_id, flags);
if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
return NULL;
return descs;
}
EXPORT_SYMBOL(devm_gpiod_get_array_optional);
/**
* devm_gpiod_put - Resource-managed gpiod_put()
* @desc: GPIO descriptor to dispose of
@ -200,6 +274,21 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
}
EXPORT_SYMBOL(devm_gpiod_put);
/**
* devm_gpiod_put_array - Resource-managed gpiod_put_array()
* @descs: GPIO descriptor array to dispose of
*
* Dispose of an array of GPIO descriptors obtained with devm_gpiod_get_array().
* Normally this function will not be called as the GPIOs will be disposed of
* by the resource management code.
*/
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
{
WARN_ON(devres_release(dev, devm_gpiod_release_array,
devm_gpiod_match_array, &descs));
}
EXPORT_SYMBOL(devm_gpiod_put_array);

View File

@ -83,7 +83,14 @@ struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
struct gpio_desc *__must_check
__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
unsigned int index, enum gpiod_flags flags);
struct gpio_descs *__must_check devm_gpiod_get_array(struct device *dev,
const char *con_id,
enum gpiod_flags flags);
struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags);
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
int gpiod_get_direction(struct gpio_desc *desc);
int gpiod_direction_input(struct gpio_desc *desc);
@ -228,6 +235,20 @@ __devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
return ERR_PTR(-ENOSYS);
}
static inline struct gpio_descs *__must_check
devm_gpiod_get_array(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
}
static inline struct gpio_descs *__must_check
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
enum gpiod_flags flags)
{
return ERR_PTR(-ENOSYS);
}
static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
{
might_sleep();
@ -236,6 +257,15 @@ static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
WARN_ON(1);
}
static inline void devm_gpiod_put_array(struct device *dev,
struct gpio_descs *descs)
{
might_sleep();
/* GPIO can never have been requested */
WARN_ON(1);
}
static inline int gpiod_get_direction(const struct gpio_desc *desc)
{