aboutsummaryrefslogtreecommitdiff
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
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>
-rw-r--r--Documentation/devicetree/bindings/arm/hs/hisilicon.txt32
-rw-r--r--arch/arm/boot/dts/hi3620.dtsi14
-rw-r--r--arch/arm/boot/dts/hi4511.dts33
-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
8 files changed, 207 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/arm/hs/hisilicon.txt b/Documentation/devicetree/bindings/arm/hs/hisilicon.txt
index 3be60c861dd2..41ac783542e1 100644
--- a/Documentation/devicetree/bindings/arm/hs/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hs/hisilicon.txt
@@ -8,3 +8,35 @@ Required root node properties:
Hi4511 Board
Required root node properties:
- compatible = "hisilicon,hi3620-hi4511";
+
+
+Hisilicon sctrl resiter description
+
+Required properties:
+- compatible : "hisilicon,sctrl"
+- reg : Address and size of sysctrl.
+- smp_reg : offset in sysctrl for notifying slave cpu booting
+ cpu 1, reg;
+ cpu 2, reg + 0x4;
+ cpu 3, reg + 0x8;
+ If reg value is not zero, cpun exit wfi and go
+- resume_reg : offset in sysctrl for notifying cpu0 when resume
+- reset_reg : offset in sysctrl for system reset
+
+Example:
+ hi3716:
+ sctrl@f8000000 {
+ compatible = "hisilicon,sctrl";
+ reg = <0xf8000000 0x1000>;
+ smp_reg = <0xc0>;
+ reboot_reg = <0x4>;
+ };
+
+ hi3620:
+ sctrl@fc802000 {
+ compatible = "hisilicon,sctrl";
+ reg = <0xfc802000 0x1000>;
+ smp_reg = <0x31c>;
+ resume_reg = <0x308>;
+ reboot_reg = <0x4>;
+ };
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
index 37f047b3d995..8edada1e4fd5 100644
--- a/arch/arm/boot/dts/hi3620.dtsi
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -24,6 +24,14 @@
interrupt-parent = <&intc>;
ranges;
+ sctrl: sctrl@fc802000 {
+ compatible = "hisilicon,sctrl";
+ reg = <0xfc802000 0x1000>;
+ smp_reg = <0x31c>;
+ resume_reg = <0x308>;
+ reboot_reg = <0x4>;
+ };
+
osc32k: osc@0 {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -140,6 +148,12 @@
status = "disabled";
};
+ timer5: timer@fc000600 {
+ compatible = "arm,cortex-a9-twd-timer";
+ reg = <0xfc000600 0x20>;
+ interrupts = <1 13 0xf01>;
+ };
+
uart0: uart@fcb00000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0xfcb00000 0x1000>;
diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
index 718df1e72b62..cf90d4254fb8 100644
--- a/arch/arm/boot/dts/hi4511.dts
+++ b/arch/arm/boot/dts/hi4511.dts
@@ -18,6 +18,39 @@
bootargs = "console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on mem=512m earlyprintk";
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <0>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu@1 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <1>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu@2 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <2>;
+ next-level-cache = <&l2>;
+ };
+
+ cpu@3 {
+ compatible = "arm,cortex-a9";
+ device_type = "cpu";
+ reg = <3>;
+ next-level-cache = <&l2>;
+ };
+ };
+
memory {
reg = <0x00000000 0x20000000>;
};
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();
+}
+