mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-27 17:18:59 +00:00
86 lines
2.7 KiB
Diff
86 lines
2.7 KiB
Diff
|
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;
|