|
@@ -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);
|