Add reset_reset() and reset_reset_bulk() functions to the reset controller API. These functions assert and then deassert reset signals in a single call, providing a convenient way to pulse/toggle a reset line.
This mimics the Linux kernel's reset_control_reset() and reset_control_bulk_reset() APIs. The new functions are useful for drivers that need to cycle a reset line during initialization or error recovery but with also passing delay parameter. If a driver implements the rst_reset op, it will be called directly with the delay parameter. Otherwise, the reset core performs reset_assert(), optional udelay(), and reset_deassert() as fallback. Signed-off-by: Michal Simek <[email protected]> --- Changes in v2: - Add delay_us parameter to specify delay between assert and deassert - Pass delay_us to rst_reset op so drivers can use it if needed - Return -ENOSYS in stubs when !CONFIG_DM_RESET (like clk.h) - Fix line length to stay within 80 characters drivers/reset/reset-uclass.c | 34 ++++++++++++++++++++++++++++++ include/reset-uclass.h | 12 +++++++++++ include/reset.h | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) diff --git a/drivers/reset/reset-uclass.c b/drivers/reset/reset-uclass.c index fe4cebf54f15..c199e3e5da71 100644 --- a/drivers/reset/reset-uclass.c +++ b/drivers/reset/reset-uclass.c @@ -13,6 +13,7 @@ #include <reset-uclass.h> #include <dm/devres.h> #include <dm/lists.h> +#include <linux/delay.h> static inline struct reset_ops *reset_dev_ops(struct udevice *dev) { @@ -225,6 +226,39 @@ int reset_deassert_bulk(struct reset_ctl_bulk *bulk) return 0; } +int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us) +{ + struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); + int ret; + + debug("%s(reset_ctl=%p, delay_us=%lu)\n", __func__, reset_ctl, + delay_us); + + if (ops->rst_reset) + return ops->rst_reset(reset_ctl, delay_us); + + ret = reset_assert(reset_ctl); + if (ret < 0) + return ret; + + udelay(delay_us); + + return reset_deassert(reset_ctl); +} + +int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us) +{ + int i, ret; + + for (i = 0; i < bulk->count; i++) { + ret = reset_reset(&bulk->resets[i], delay_us); + if (ret < 0) + return ret; + } + + return 0; +} + int reset_status(struct reset_ctl *reset_ctl) { struct reset_ops *ops = reset_dev_ops(reset_ctl->dev); diff --git a/include/reset-uclass.h b/include/reset-uclass.h index 9a0696dd1e3b..706fcffd234d 100644 --- a/include/reset-uclass.h +++ b/include/reset-uclass.h @@ -76,6 +76,18 @@ struct reset_ops { * @return 0 if OK, or a negative error code. */ int (*rst_deassert)(struct reset_ctl *reset_ctl); + /** + * rst_reset - Reset a HW module. + * + * This optional function triggers a reset pulse on the reset line, + * asserting and then deasserting the reset signal. If not implemented, + * the reset core will use rst_assert followed by rst_deassert. + * + * @reset_ctl: The reset signal to pulse. + * @delay_us: Delay in microseconds between assert and deassert. + * @return 0 if OK, or a negative error code. + */ + int (*rst_reset)(struct reset_ctl *reset_ctl, ulong delay_us); /** * rst_status - Check reset signal status. * diff --git a/include/reset.h b/include/reset.h index 036a786d2ace..a4a6ea962b2b 100644 --- a/include/reset.h +++ b/include/reset.h @@ -320,6 +320,37 @@ int reset_deassert(struct reset_ctl *reset_ctl); */ int reset_deassert_bulk(struct reset_ctl_bulk *bulk); +/** + * reset_reset - Reset a HW module by asserting and deasserting a reset signal. + * + * This function will assert and then deassert the specified reset signal, + * thus resetting the affected HW module. This is a convenience function + * that combines reset_assert() and reset_deassert(). + * + * @reset_ctl: A reset control struct that was previously successfully + * requested by reset_get_by_*(). + * @delay_us: Delay in microseconds between assert and deassert. + * Use 0 for no delay (or when the driver handles the delay + * internally via rst_reset op). + * Return: 0 if OK, or a negative error code. + */ +int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us); + +/** + * reset_reset_bulk - Reset all HW modules in a reset control bulk struct. + * + * This function will assert and then deassert all reset signals in the + * specified reset control bulk struct, thus resetting all affected HW modules. + * + * @bulk: A reset control bulk struct that was previously successfully + * requested by reset_get_bulk(). + * @delay_us: Delay in microseconds between assert and deassert. + * Use 0 for no delay (or when the driver handles the delay + * internally via rst_reset op). + * Return: 0 if OK, or a negative error code. + */ +int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us); + /** * rst_status - Check reset signal status. * @@ -443,6 +474,16 @@ static inline int reset_deassert_bulk(struct reset_ctl_bulk *bulk) return 0; } +static inline int reset_reset(struct reset_ctl *reset_ctl, ulong delay_us) +{ + return -ENOSYS; +} + +static inline int reset_reset_bulk(struct reset_ctl_bulk *bulk, ulong delay_us) +{ + return -ENOSYS; +} + static inline int reset_status(struct reset_ctl *reset_ctl) { return -ENOTSUPP; -- 2.43.0

