summary refs log tree commit diff
path: root/arch/arm/mach-mvebu/system-controller.c
diff options
context:
space:
mode:
authorGregory CLEMENT <gregory.clement@free-electrons.com>2012-06-01 18:21:46 +0200
committerArnd Bergmann <arnd@arndb.de>2012-07-10 15:47:48 +0200
commit31af49db7b2d700fdaf26ab55ca96428bc2e8b06 (patch)
treeccd77c9f062178dc90d70072c320b6e3990106a5 /arch/arm/mach-mvebu/system-controller.c
parentbf54439c34689f53409a066452e58a0533880473 (diff)
downloadlinux-31af49db7b2d700fdaf26ab55ca96428bc2e8b06.tar.gz
arm: mach-mvebu: add source files
[ben.dooks@codethink.co.uk: fixup style error in system-controller]
[ben.dooks@codethink.co.uk: check result of of_match_node()]

Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Lior Amsalem <alior@marvell.com>
Acked-by: Andrew Lunn <andrew@lunn.ch>
Tested-by: Yehuda Yitschak <yehuday@marvell.com>
Tested-by: Lior Amsalem <alior@marvell.com>
Tested-by: Andrew Lunn <andrew@lunn.ch>
Diffstat (limited to 'arch/arm/mach-mvebu/system-controller.c')
-rw-r--r--arch/arm/mach-mvebu/system-controller.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
new file mode 100644
index 000000000000..b8079df8c986
--- /dev/null
+++ b/arch/arm/mach-mvebu/system-controller.c
@@ -0,0 +1,105 @@
+/*
+ * System controller support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The Armada 370 and Armada XP SoCs both have a range of
+ * miscellaneous registers, that do not belong to a particular device,
+ * but rather provide system-level features. This basic
+ * system-controller driver provides a device tree binding for those
+ * registers, and implements utility functions offering various
+ * features related to those registers.
+ *
+ * For now, the feature set is limited to restarting the platform by a
+ * soft-reset, but it might be extended in the future.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+static void __iomem *system_controller_base;
+
+struct mvebu_system_controller {
+	u32 rstoutn_mask_offset;
+	u32 system_soft_reset_offset;
+
+	u32 rstoutn_mask_reset_out_en;
+	u32 system_soft_reset;
+};
+static struct mvebu_system_controller *mvebu_sc;
+
+const struct mvebu_system_controller armada_370_xp_system_controller = {
+	.rstoutn_mask_offset = 0x60,
+	.system_soft_reset_offset = 0x64,
+	.rstoutn_mask_reset_out_en = 0x1,
+	.system_soft_reset = 0x1,
+};
+
+const struct mvebu_system_controller orion_system_controller = {
+	.rstoutn_mask_offset = 0x108,
+	.system_soft_reset_offset = 0x10c,
+	.rstoutn_mask_reset_out_en = 0x4,
+	.system_soft_reset = 0x1,
+};
+
+static struct of_device_id of_system_controller_table[] = {
+	{
+		.compatible = "marvell,orion-system-controller",
+		.data = (void *) &orion_system_controller,
+	}, {
+		.compatible = "marvell,armada-370-xp-system-controller",
+		.data = (void *) &armada_370_xp_system_controller,
+	},
+	{ /* end of list */ },
+};
+
+void mvebu_restart(char mode, const char *cmd)
+{
+	if (!system_controller_base) {
+		pr_err("Cannot restart, system-controller not available: check the device tree\n");
+	} else {
+		/*
+		 * Enable soft reset to assert RSTOUTn.
+		 */
+		writel(mvebu_sc->rstoutn_mask_reset_out_en,
+			system_controller_base +
+			mvebu_sc->rstoutn_mask_offset);
+		/*
+		 * Assert soft reset.
+		 */
+		writel(mvebu_sc->system_soft_reset,
+			system_controller_base +
+			mvebu_sc->system_soft_reset_offset);
+	}
+
+	while (1)
+		;
+}
+
+static int __init mvebu_system_controller_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, of_system_controller_table);
+	if (np) {
+		const struct of_device_id *match =
+		    of_match_node(of_system_controller_table, np);
+		BUG_ON(!match);
+		system_controller_base = of_iomap(np, 0);
+		mvebu_sc = (struct mvebu_system_controller *)match->data;
+	}
+
+	return 0;
+}
+
+arch_initcall(mvebu_system_controller_init);