mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2024-12-29 09:13:38 +00:00
reset: Add devres helpers to request pre-deasserted reset controls
Add devres helpers - devm_reset_control_bulk_get_exclusive_deasserted - devm_reset_control_bulk_get_optional_exclusive_deasserted - devm_reset_control_bulk_get_optional_shared_deasserted - devm_reset_control_bulk_get_shared_deasserted - devm_reset_control_get_exclusive_deasserted - devm_reset_control_get_optional_exclusive_deasserted - devm_reset_control_get_optional_shared_deasserted - devm_reset_control_get_shared_deasserted to request and immediately deassert reset controls. During cleanup, reset_control_assert() will be called automatically on the returned reset controls. Acked-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> Link: https://lore.kernel.org/r/20240925-reset-get-deasserted-v2-2-b3601bbd0458@pengutronix.de Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
This commit is contained in:
parent
dad35f7d2f
commit
d872bed850
@ -1236,23 +1236,46 @@ static void devm_reset_control_release(struct device *dev, void *res)
|
||||
reset_control_put(*(struct reset_control **)res);
|
||||
}
|
||||
|
||||
static void devm_reset_control_release_deasserted(struct device *dev, void *res)
|
||||
{
|
||||
struct reset_control *rstc = *(struct reset_control **)res;
|
||||
|
||||
reset_control_assert(rstc);
|
||||
reset_control_put(rstc);
|
||||
}
|
||||
|
||||
struct reset_control *
|
||||
__devm_reset_control_get(struct device *dev, const char *id, int index,
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
struct reset_control **ptr, *rstc;
|
||||
bool deasserted = flags & RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
|
||||
ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr),
|
||||
ptr = devres_alloc(deasserted ? devm_reset_control_release_deasserted :
|
||||
devm_reset_control_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
flags &= ~RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
|
||||
rstc = __reset_control_get(dev, id, index, flags);
|
||||
if (IS_ERR_OR_NULL(rstc)) {
|
||||
devres_free(ptr);
|
||||
return rstc;
|
||||
}
|
||||
|
||||
if (deasserted) {
|
||||
int ret;
|
||||
|
||||
ret = reset_control_deassert(rstc);
|
||||
if (ret) {
|
||||
reset_control_put(rstc);
|
||||
devres_free(ptr);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
*ptr = rstc;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
@ -1272,24 +1295,45 @@ static void devm_reset_control_bulk_release(struct device *dev, void *res)
|
||||
reset_control_bulk_put(devres->num_rstcs, devres->rstcs);
|
||||
}
|
||||
|
||||
static void devm_reset_control_bulk_release_deasserted(struct device *dev, void *res)
|
||||
{
|
||||
struct reset_control_bulk_devres *devres = res;
|
||||
|
||||
reset_control_bulk_assert(devres->num_rstcs, devres->rstcs);
|
||||
reset_control_bulk_put(devres->num_rstcs, devres->rstcs);
|
||||
}
|
||||
|
||||
int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs,
|
||||
enum reset_control_flags flags)
|
||||
{
|
||||
struct reset_control_bulk_devres *ptr;
|
||||
bool deasserted = flags & RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
int ret;
|
||||
|
||||
ptr = devres_alloc(devm_reset_control_bulk_release, sizeof(*ptr),
|
||||
ptr = devres_alloc(deasserted ? devm_reset_control_bulk_release_deasserted :
|
||||
devm_reset_control_bulk_release, sizeof(*ptr),
|
||||
GFP_KERNEL);
|
||||
if (!ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
flags &= ~RESET_CONTROL_FLAGS_BIT_DEASSERTED;
|
||||
|
||||
ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, flags);
|
||||
if (ret < 0) {
|
||||
devres_free(ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (deasserted) {
|
||||
ret = reset_control_bulk_deassert(num_rstcs, rstcs);
|
||||
if (ret) {
|
||||
reset_control_bulk_put(num_rstcs, rstcs);
|
||||
devres_free(ptr);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ptr->num_rstcs = num_rstcs;
|
||||
ptr->rstcs = rstcs;
|
||||
devres_add(dev, ptr);
|
||||
|
@ -28,6 +28,7 @@ struct reset_control_bulk_data {
|
||||
#define RESET_CONTROL_FLAGS_BIT_SHARED BIT(0) /* not exclusive */
|
||||
#define RESET_CONTROL_FLAGS_BIT_OPTIONAL BIT(1)
|
||||
#define RESET_CONTROL_FLAGS_BIT_ACQUIRED BIT(2) /* iff exclusive, not released */
|
||||
#define RESET_CONTROL_FLAGS_BIT_DEASSERTED BIT(3)
|
||||
|
||||
/**
|
||||
* enum reset_control_flags - Flags that can be passed to the reset_control_get functions
|
||||
@ -35,21 +36,35 @@ struct reset_control_bulk_data {
|
||||
* These values cannot be OR'd.
|
||||
*
|
||||
* @RESET_CONTROL_EXCLUSIVE: exclusive, acquired,
|
||||
* @RESET_CONTROL_EXCLUSIVE_DEASSERTED: exclusive, acquired, deasserted
|
||||
* @RESET_CONTROL_EXCLUSIVE_RELEASED: exclusive, released,
|
||||
* @RESET_CONTROL_SHARED: shared
|
||||
* @RESET_CONTROL_SHARED_DEASSERTED: shared, deasserted
|
||||
* @RESET_CONTROL_OPTIONAL_EXCLUSIVE: optional, exclusive, acquired
|
||||
* @RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED: optional, exclusive, acquired, deasserted
|
||||
* @RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED: optional, exclusive, released
|
||||
* @RESET_CONTROL_OPTIONAL_SHARED: optional, shared
|
||||
* @RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED: optional, shared, deasserted
|
||||
*/
|
||||
enum reset_control_flags {
|
||||
RESET_CONTROL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_ACQUIRED,
|
||||
RESET_CONTROL_EXCLUSIVE_DEASSERTED = RESET_CONTROL_FLAGS_BIT_ACQUIRED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
RESET_CONTROL_EXCLUSIVE_RELEASED = 0,
|
||||
RESET_CONTROL_SHARED = RESET_CONTROL_FLAGS_BIT_SHARED,
|
||||
RESET_CONTROL_SHARED_DEASSERTED = RESET_CONTROL_FLAGS_BIT_SHARED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_ACQUIRED,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_ACQUIRED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
RESET_CONTROL_OPTIONAL_EXCLUSIVE_RELEASED = RESET_CONTROL_FLAGS_BIT_OPTIONAL,
|
||||
RESET_CONTROL_OPTIONAL_SHARED = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_SHARED,
|
||||
RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED = RESET_CONTROL_FLAGS_BIT_OPTIONAL |
|
||||
RESET_CONTROL_FLAGS_BIT_SHARED |
|
||||
RESET_CONTROL_FLAGS_BIT_DEASSERTED,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_RESET_CONTROLLER
|
||||
@ -596,6 +611,25 @@ __must_check devm_reset_control_get_exclusive(struct device *dev,
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_exclusive_deasserted - resource managed
|
||||
* reset_control_get_exclusive() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_exclusive() + reset_control_deassert(). For reset
|
||||
* controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See reset_control_get_exclusive() for more information.
|
||||
*/
|
||||
static inline struct reset_control * __must_check
|
||||
devm_reset_control_get_exclusive_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_EXCLUSIVE_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_exclusive - resource managed
|
||||
* reset_control_bulk_get_exclusive()
|
||||
@ -712,6 +746,25 @@ static inline struct reset_control *devm_reset_control_get_shared(
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_shared_deasserted - resource managed
|
||||
* reset_control_get_shared() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_shared() + reset_control_deassert(). For reset
|
||||
* controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_get_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control * __must_check
|
||||
devm_reset_control_get_shared_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_SHARED_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_shared - resource managed
|
||||
* reset_control_bulk_get_shared()
|
||||
@ -732,6 +785,28 @@ devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs,
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, RESET_CONTROL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_shared_deasserted - resource managed
|
||||
* reset_control_bulk_get_shared() +
|
||||
* reset_control_bulk_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @num_rstcs: number of entries in rstcs array
|
||||
* @rstcs: array of struct reset_control_bulk_data with reset line names set
|
||||
*
|
||||
* Managed reset_control_bulk_get_shared() + reset_control_bulk_deassert(). For
|
||||
* reset controllers returned from this function, reset_control_bulk_assert() +
|
||||
* reset_control_bulk_put() are called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_bulk_get_shared() for more information.
|
||||
*/
|
||||
static inline int __must_check
|
||||
devm_reset_control_bulk_get_shared_deasserted(struct device *dev, int num_rstcs,
|
||||
struct reset_control_bulk_data *rstcs)
|
||||
{
|
||||
return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs,
|
||||
RESET_CONTROL_SHARED_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_exclusive - resource managed
|
||||
* reset_control_get_optional_exclusive()
|
||||
@ -750,6 +825,25 @@ static inline struct reset_control *devm_reset_control_get_optional_exclusive(
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_exclusive_deasserted - resource managed
|
||||
* reset_control_get_optional_exclusive() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_optional_exclusive() + reset_control_deassert().
|
||||
* For reset controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_get_optional_exclusive() for more information.
|
||||
*/
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_get_optional_exclusive_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_EXCLUSIVE_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_optional_exclusive - resource managed
|
||||
* reset_control_bulk_get_optional_exclusive()
|
||||
@ -789,6 +883,25 @@ static inline struct reset_control *devm_reset_control_get_optional_shared(
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_get_optional_shared_deasserted - resource managed
|
||||
* reset_control_get_optional_shared() +
|
||||
* reset_control_deassert()
|
||||
* @dev: device to be reset by the controller
|
||||
* @id: reset line name
|
||||
*
|
||||
* Managed reset_control_get_optional_shared() + reset_control_deassert(). For
|
||||
* reset controllers returned from this function, reset_control_assert() +
|
||||
* reset_control_put() is called automatically on driver detach.
|
||||
*
|
||||
* See devm_reset_control_get_optional_shared() for more information.
|
||||
*/
|
||||
static inline struct reset_control *
|
||||
devm_reset_control_get_optional_shared_deasserted(struct device *dev, const char *id)
|
||||
{
|
||||
return __devm_reset_control_get(dev, id, 0, RESET_CONTROL_OPTIONAL_SHARED_DEASSERTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_reset_control_bulk_get_optional_shared - resource managed
|
||||
* reset_control_bulk_get_optional_shared()
|
||||
|
Loading…
Reference in New Issue
Block a user