| From 66deff85fee24ecd7b0ffa2901711aa8f026fcfa Mon Sep 17 00:00:00 2001 |
| From: Maxime Ripard <maxime@cerno.tech> |
| Date: Tue, 28 Jan 2020 16:22:20 +0100 |
| Subject: [PATCH] reset: simple: Add reset callback |
| |
| The reset-simple code lacks a reset callback that is still pretty easy to |
| implement. The only real thing to consider is the delay needed for a device |
| to be reset, so let's expose that as part of the reset-simple driver data. |
| |
| Cc: Philipp Zabel <p.zabel@pengutronix.de> |
| Signed-off-by: Maxime Ripard <maxime@cerno.tech> |
| --- |
| drivers/reset/reset-simple.c | 24 ++++++++++++++++++++++++ |
| include/linux/reset/reset-simple.h | 6 ++++++ |
| 2 files changed, 30 insertions(+) |
| |
| --- a/drivers/reset/reset-simple.c |
| +++ b/drivers/reset/reset-simple.c |
| @@ -11,6 +11,7 @@ |
| * Maxime Ripard <maxime.ripard@free-electrons.com> |
| */ |
| |
| +#include <linux/delay.h> |
| #include <linux/device.h> |
| #include <linux/err.h> |
| #include <linux/io.h> |
| @@ -63,6 +64,28 @@ static int reset_simple_deassert(struct |
| return reset_simple_update(rcdev, id, false); |
| } |
| |
| +static int reset_simple_reset(struct reset_controller_dev *rcdev, |
| + unsigned long id) |
| +{ |
| + struct reset_simple_data *data = to_reset_simple_data(rcdev); |
| + int ret; |
| + |
| + if (!data->reset_us) |
| + return -ENOTSUPP; |
| + |
| + ret = reset_simple_assert(rcdev, id); |
| + if (ret) |
| + return ret; |
| + |
| + usleep_range(data->reset_us, data->reset_us * 2); |
| + |
| + ret = reset_simple_deassert(rcdev, id); |
| + if (ret) |
| + return ret; |
| + |
| + return 0; |
| +} |
| + |
| static int reset_simple_status(struct reset_controller_dev *rcdev, |
| unsigned long id) |
| { |
| @@ -80,6 +103,7 @@ static int reset_simple_status(struct re |
| const struct reset_control_ops reset_simple_ops = { |
| .assert = reset_simple_assert, |
| .deassert = reset_simple_deassert, |
| + .reset = reset_simple_reset, |
| .status = reset_simple_status, |
| }; |
| EXPORT_SYMBOL_GPL(reset_simple_ops); |
| --- a/include/linux/reset/reset-simple.h |
| +++ b/include/linux/reset/reset-simple.h |
| @@ -27,6 +27,11 @@ |
| * @status_active_low: if true, bits read back as cleared while the reset is |
| * asserted. Otherwise, bits read back as set while the |
| * reset is asserted. |
| + * @reset_us: Minimum delay in microseconds needed that needs to be |
| + * waited for between an assert and a deassert to reset the |
| + * device. If multiple consumers with different delay |
| + * requirements are connected to this controller, it must |
| + * be the largest minimum delay. |
| */ |
| struct reset_simple_data { |
| spinlock_t lock; |
| @@ -34,6 +39,7 @@ struct reset_simple_data { |
| struct reset_controller_dev rcdev; |
| bool active_low; |
| bool status_active_low; |
| + unsigned int reset_us; |
| }; |
| |
| extern const struct reset_control_ops reset_simple_ops; |