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:
committed by
Linus Walleij
parent
6685852732
commit
331758eef8
@@ -102,11 +102,19 @@ Device-managed variants of these functions are also defined:
|
|||||||
const char *con_id,
|
const char *con_id,
|
||||||
enum gpiod_flags flags)
|
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,
|
const char *con_id,
|
||||||
unsigned int index,
|
unsigned int index,
|
||||||
enum gpiod_flags flags)
|
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:
|
A GPIO descriptor can be disposed of using the gpiod_put() function:
|
||||||
|
|
||||||
void gpiod_put(struct gpio_desc *desc)
|
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())
|
It is also not allowed to individually release descriptors (using gpiod_put())
|
||||||
from an array acquired with gpiod_get_array().
|
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(struct device *dev, struct gpio_desc *desc)
|
||||||
|
|
||||||
|
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs)
|
||||||
|
|
||||||
|
|
||||||
Using GPIOs
|
Using GPIOs
|
||||||
===========
|
===========
|
||||||
|
|||||||
@@ -35,6 +35,20 @@ static int devm_gpiod_match(struct device *dev, void *res, void *data)
|
|||||||
return *this == *gpio;
|
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()
|
* devm_gpiod_get - Resource-managed gpiod_get()
|
||||||
* @dev: GPIO consumer
|
* @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);
|
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()
|
* devm_gpiod_put - Resource-managed gpiod_put()
|
||||||
* @desc: GPIO descriptor to dispose of
|
* @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);
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,14 @@ struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
|
|||||||
struct gpio_desc *__must_check
|
struct gpio_desc *__must_check
|
||||||
__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
|
__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
|
||||||
unsigned int index, enum gpiod_flags flags);
|
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(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_get_direction(struct gpio_desc *desc);
|
||||||
int gpiod_direction_input(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);
|
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)
|
static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
|
||||||
{
|
{
|
||||||
might_sleep();
|
might_sleep();
|
||||||
@@ -236,6 +257,15 @@ static inline void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
|
|||||||
WARN_ON(1);
|
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)
|
static inline int gpiod_get_direction(const struct gpio_desc *desc)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user