From 223f1c46e109a8420765aee099a5d1dc4ab7ee98 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 3 Sep 2013 13:18:12 +0200
Subject: [PATCH 05/36] MIPS: lantiq: add reset-controller api support

Add a reset-controller binding for the reset registers found on the lantiq
SoC.

Signed-off-by: John Crispin <blogic@openwrt.org>
---
 arch/mips/lantiq/xway/reset.c |   61 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
+#include <linux/reset-controller.h>
 
 #include <asm/reboot.h>
 
@@ -113,6 +114,66 @@ void ltq_reset_once(unsigned int module,
 	ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
 }
 
+static int ltq_assert_device(struct reset_controller_dev *rcdev,
+				unsigned long id)
+{
+	u32 val;
+
+	if (id < 8)
+		return -1;
+
+	val = ltq_rcu_r32(RCU_RST_REQ);
+	val |= BIT(id);
+	ltq_rcu_w32(val, RCU_RST_REQ);
+
+	return 0;
+}
+
+static int ltq_deassert_device(struct reset_controller_dev *rcdev,
+				  unsigned long id)
+{
+	u32 val;
+
+	if (id < 8)
+		return -1;
+
+	val = ltq_rcu_r32(RCU_RST_REQ);
+	val &= ~BIT(id);
+	ltq_rcu_w32(val, RCU_RST_REQ);
+
+	return 0;
+}
+
+static int ltq_reset_device(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	ltq_assert_device(rcdev, id);
+	return ltq_deassert_device(rcdev, id);
+}
+
+static struct reset_control_ops reset_ops = {
+	.reset = ltq_reset_device,
+	.assert = ltq_assert_device,
+	.deassert = ltq_deassert_device,
+};
+
+static struct reset_controller_dev reset_dev = {
+	.ops			= &reset_ops,
+	.owner			= THIS_MODULE,
+	.nr_resets		= 32,
+	.of_reset_n_cells	= 1,
+};
+
+void ltq_rst_init(void)
+{
+	reset_dev.of_node = of_find_compatible_node(NULL, NULL,
+						"lantiq,xway-reset");
+	if (!reset_dev.of_node)
+		pr_err("Failed to find reset controller node");
+	else
+		reset_controller_register(&reset_dev);
+}
+
 static void ltq_machine_restart(char *command)
 {
 	local_irq_disable();
