aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-hs
diff options
context:
space:
mode:
authorZhangfei Gao <zhangfei.gao@linaro.org>2013-08-06 09:46:02 +0800
committerZhangfei Gao <zhangfei.gao@linaro.org>2013-08-13 14:33:20 +0800
commit5829cf8b6b6d88ddec5d9500296c948c64e6f1e5 (patch)
treeca972bbc18dfc45828a42f1a5f58c524f63bba6c /arch/arm/mach-hs
parentb34107f62c3429c00f488d75c3b24c2154c2934a (diff)
ARM: hs: add smp support
Enable SMP support on hi3xxx platform Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org> Tested-by: Zhang Mingjun <zhang.mingjun@linaro.org> Tested-by: Li Xin <li.xin@linaro.org>
Diffstat (limited to 'arch/arm/mach-hs')
-rw-r--r--arch/arm/mach-hs/Makefile3
-rw-r--r--arch/arm/mach-hs/core.h13
-rw-r--r--arch/arm/mach-hs/hs-dt.c5
-rw-r--r--arch/arm/mach-hs/platsmp.c43
-rw-r--r--arch/arm/mach-hs/system.c65
5 files changed, 128 insertions, 1 deletions
diff --git a/arch/arm/mach-hs/Makefile b/arch/arm/mach-hs/Makefile
index d79ecb55a2c9..ce83a4df2472 100644
--- a/arch/arm/mach-hs/Makefile
+++ b/arch/arm/mach-hs/Makefile
@@ -2,4 +2,5 @@
# Makefile for Hisilicon Hi36xx/Hi37xx processors line
#
-obj-$(CONFIG_MACH_HS_DT) += hs-dt.o
+obj-$(CONFIG_MACH_HS_DT) += hs-dt.o system.o
+obj-$(CONFIG_SMP) += platsmp.o
diff --git a/arch/arm/mach-hs/core.h b/arch/arm/mach-hs/core.h
new file mode 100644
index 000000000000..f4c17b8d37f6
--- /dev/null
+++ b/arch/arm/mach-hs/core.h
@@ -0,0 +1,13 @@
+#ifndef __HISILICON_CORE_H
+#define __HISILICON_CORE_H
+
+#include <linux/init.h>
+
+extern void hs_set_cpu_jump(int cpu, void *jump_addr);
+extern int hs_get_cpu_jump(int cpu);
+extern void secondary_startup(void);
+extern void hs_map_io(void);
+extern struct smp_operations hs_smp_ops;
+extern void hs_restart(char mode, const char *cmd);
+
+#endif
diff --git a/arch/arm/mach-hs/hs-dt.c b/arch/arm/mach-hs/hs-dt.c
index 9332610f52ad..16240b029ebb 100644
--- a/arch/arm/mach-hs/hs-dt.c
+++ b/arch/arm/mach-hs/hs-dt.c
@@ -25,6 +25,8 @@
#include <asm/mach/map.h>
#include <asm/mach/time.h>
+#include "core.h"
+
static struct of_device_id hs_timer_match[] __initdata = {
{ .compatible = "arm,sp804", },
{}
@@ -49,6 +51,7 @@ static void __init hs_timer_init(void)
int ret;
u32 data[2];
+ hs_map_io();
of_clk_init(NULL);
node = of_find_matching_node(NULL, hs_timer_match);
@@ -103,4 +106,6 @@ DT_MACHINE_START(HS_DT, "Hisilicon Hi36xx/Hi37xx (Flattened Device Tree)")
.init_time = hs_timer_init,
.init_machine = hs_init,
.dt_compat = hs_compat,
+ .smp = smp_ops(hs_smp_ops),
+ .restart = hs_restart,
MACHINE_END
diff --git a/arch/arm/mach-hs/platsmp.c b/arch/arm/mach-hs/platsmp.c
new file mode 100644
index 000000000000..a76a3cca22e7
--- /dev/null
+++ b/arch/arm/mach-hs/platsmp.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <linux/smp.h>
+#include <linux/io.h>
+#include <asm/smp_scu.h>
+
+#include "core.h"
+
+static void __init hs_smp_prepare_cpus(unsigned int max_cpus)
+{
+ unsigned long base;
+ void __iomem *scu_base;
+
+ if (scu_a9_has_base()) {
+ base = scu_a9_get_base();
+ scu_base = ioremap(base, SZ_4K);
+ if (!scu_base) {
+ pr_err("ioremap(scu_base) failed\n");
+ return;
+ }
+ scu_enable(scu_base);
+ iounmap(scu_base);
+ }
+}
+
+static int hs_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ hs_set_cpu_jump(cpu, secondary_startup);
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+ return 0;
+}
+
+struct smp_operations hs_smp_ops __initdata = {
+ .smp_prepare_cpus = hs_smp_prepare_cpus,
+ .smp_boot_secondary = hs_boot_secondary,
+};
diff --git a/arch/arm/mach-hs/system.c b/arch/arm/mach-hs/system.c
new file mode 100644
index 000000000000..0519a656f9fd
--- /dev/null
+++ b/arch/arm/mach-hs/system.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+#include <asm/proc-fns.h>
+#include <asm/smp_plat.h>
+
+#include "core.h"
+
+static void __iomem *hs_sctrl_base;
+static int hs_smp_reg;
+static int hs_resume_reg;
+static int hs_reboot_reg;
+
+void hs_map_io(void)
+{
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, "hisilicon,sctrl");
+ if (np) {
+ hs_sctrl_base = of_iomap(np, 0);
+ if (!hs_sctrl_base)
+ pr_err("of_iomap(sctrl_base) failed\n");
+ of_property_read_u32(np, "smp_reg", &hs_smp_reg);
+ of_property_read_u32(np, "resume_reg", &hs_resume_reg);
+ of_property_read_u32(np, "reboot_reg", &hs_reboot_reg);
+ }
+}
+
+void hs_set_cpu_jump(int cpu, void *jump_addr)
+{
+ int offset = hs_smp_reg;
+
+ cpu = cpu_logical_map(cpu);
+ if (cpu > 0)
+ offset += 0x04 * (cpu - 1);
+ writel_relaxed(virt_to_phys(jump_addr), hs_sctrl_base + offset);
+}
+
+int hs_get_cpu_jump(int cpu)
+{
+ int offset = hs_smp_reg;
+
+ cpu = cpu_logical_map(cpu);
+ if (cpu > 0)
+ offset += 0x04 * (cpu - 1);
+ return readl_relaxed(hs_sctrl_base + offset);
+}
+
+void hs_restart(char mode, const char *cmd)
+{
+ writel_relaxed(0xdeadbeef, hs_sctrl_base + hs_reboot_reg);
+
+ while (1)
+ cpu_do_idle();
+}
+