Commit a9701376 authored by Maxime Ripard's avatar Maxime Ripard Committed by Philipp Zabel

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.
Reviewed-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
parent 9357b046
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* Maxime Ripard <maxime.ripard@free-electrons.com> * Maxime Ripard <maxime.ripard@free-electrons.com>
*/ */
#include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -63,6 +64,24 @@ static int reset_simple_deassert(struct reset_controller_dev *rcdev, ...@@ -63,6 +64,24 @@ static int reset_simple_deassert(struct reset_controller_dev *rcdev,
return reset_simple_update(rcdev, id, false); 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);
return reset_simple_deassert(rcdev, id);
}
static int reset_simple_status(struct reset_controller_dev *rcdev, static int reset_simple_status(struct reset_controller_dev *rcdev,
unsigned long id) unsigned long id)
{ {
...@@ -80,6 +99,7 @@ static int reset_simple_status(struct reset_controller_dev *rcdev, ...@@ -80,6 +99,7 @@ static int reset_simple_status(struct reset_controller_dev *rcdev,
const struct reset_control_ops reset_simple_ops = { const struct reset_control_ops reset_simple_ops = {
.assert = reset_simple_assert, .assert = reset_simple_assert,
.deassert = reset_simple_deassert, .deassert = reset_simple_deassert,
.reset = reset_simple_reset,
.status = reset_simple_status, .status = reset_simple_status,
}; };
EXPORT_SYMBOL_GPL(reset_simple_ops); EXPORT_SYMBOL_GPL(reset_simple_ops);
......
...@@ -27,6 +27,12 @@ ...@@ -27,6 +27,12 @@
* @status_active_low: if true, bits read back as cleared while the reset is * @status_active_low: if true, bits read back as cleared while the reset is
* asserted. Otherwise, bits read back as set while the * asserted. Otherwise, bits read back as set while the
* reset is asserted. * 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. 0 means that such a delay is
* unknown and the reset operation is unsupported.
*/ */
struct reset_simple_data { struct reset_simple_data {
spinlock_t lock; spinlock_t lock;
...@@ -34,6 +40,7 @@ struct reset_simple_data { ...@@ -34,6 +40,7 @@ struct reset_simple_data {
struct reset_controller_dev rcdev; struct reset_controller_dev rcdev;
bool active_low; bool active_low;
bool status_active_low; bool status_active_low;
unsigned int reset_us;
}; };
extern const struct reset_control_ops reset_simple_ops; extern const struct reset_control_ops reset_simple_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment