summaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/mach-mvebu/Makefile2
-rw-r--r--arch/arm/mach-mvebu/common.h1
-rw-r--r--arch/arm/mach-mvebu/cpu-reset.c82
3 files changed, 84 insertions, 1 deletions
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index a63e43b6b451..f9cfab05c5f9 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -3,7 +3,7 @@ ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
-obj-y += system-controller.o mvebu-soc-id.o
+obj-y += system-controller.o mvebu-soc-id.o cpu-reset.o
obj-$(CONFIG_MACH_MVEBU_V7) += board-v7.o
obj-$(CONFIG_MACH_DOVE) += dove.o
obj-$(CONFIG_ARCH_MVEBU) += coherency.o coherency_ll.o pmsu.o
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h
index 55449c487c9e..cfb129b144c0 100644
--- a/arch/arm/mach-mvebu/common.h
+++ b/arch/arm/mach-mvebu/common.h
@@ -18,6 +18,7 @@
#include <linux/reboot.h>
void mvebu_restart(enum reboot_mode mode, const char *cmd);
+int mvebu_cpu_reset_deassert(int cpu);
void armada_xp_cpu_die(unsigned int cpu);
diff --git a/arch/arm/mach-mvebu/cpu-reset.c b/arch/arm/mach-mvebu/cpu-reset.c
new file mode 100644
index 000000000000..4ff4ce77f8b6
--- /dev/null
+++ b/arch/arm/mach-mvebu/cpu-reset.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 Marvell
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "mvebu-cpureset: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/resource.h>
+#include "armada-370-xp.h"
+
+static void __iomem *cpu_reset_base;
+static size_t cpu_reset_size;
+
+#define CPU_RESET_OFFSET(cpu) (cpu * 0x8)
+#define CPU_RESET_ASSERT BIT(0)
+
+int mvebu_cpu_reset_deassert(int cpu)
+{
+ u32 reg;
+
+ if (!cpu_reset_base)
+ return -ENODEV;
+
+ if (CPU_RESET_OFFSET(cpu) >= cpu_reset_size)
+ return -EINVAL;
+
+ reg = readl(cpu_reset_base + CPU_RESET_OFFSET(cpu));
+ reg &= ~CPU_RESET_ASSERT;
+ writel(reg, cpu_reset_base + CPU_RESET_OFFSET(cpu));
+
+ return 0;
+}
+
+static int __init mvebu_cpu_reset_init(void)
+{
+ struct device_node *np;
+ struct resource res;
+ int ret = 0;
+
+ np = of_find_compatible_node(NULL, NULL,
+ "marvell,armada-370-cpu-reset");
+ if (!np)
+ return 0;
+
+ if (of_address_to_resource(np, 0, &res)) {
+ pr_err("unable to get resource\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ if (!request_mem_region(res.start, resource_size(&res),
+ np->full_name)) {
+ pr_err("unable to request region\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ cpu_reset_base = ioremap(res.start, resource_size(&res));
+ if (!cpu_reset_base) {
+ pr_err("unable to map registers\n");
+ release_mem_region(res.start, resource_size(&res));
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cpu_reset_size = resource_size(&res);
+
+out:
+ of_node_put(np);
+ return ret;
+}
+
+early_initcall(mvebu_cpu_reset_init);