On 7 November 2013 18:30, Dinh Nguyen <dinh.linux@xxxxxxxxx> wrote: > > On 11/7/13 2:41 AM, Haojian Zhuang wrote: >> From: Zhangfei Gao <zhangfei.gao@xxxxxxxxxx> >> >> Enable SMP support on hi3xxx platform >> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@xxxxxxxxxx> >> Tested-by: Zhang Mingjun <zhang.mingjun@xxxxxxxxxx> >> Tested-by: Li Xin <li.xin@xxxxxxxxxx> >> Signed-off-by: Haojian Zhuang <haojian.zhuang@xxxxxxxxxx> >> --- >> .../bindings/arm/hisilicon/hisilicon.txt | 30 ++++++-- >> arch/arm/boot/dts/hi3620.dtsi | 38 ++++++++++ >> arch/arm/mach-hi3xxx/Kconfig | 3 + >> arch/arm/mach-hi3xxx/Makefile | 1 + >> arch/arm/mach-hi3xxx/core.h | 11 +++ >> arch/arm/mach-hi3xxx/hi3xxx.c | 34 +++++++++ >> arch/arm/mach-hi3xxx/platsmp.c | 84 ++++++++++++++++++++++ >> 7 files changed, 197 insertions(+), 4 deletions(-) >> create mode 100644 arch/arm/mach-hi3xxx/core.h >> create mode 100644 arch/arm/mach-hi3xxx/platsmp.c >> >> diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt >> index 3be60c8..8c7a465 100644 >> --- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt >> +++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt >> @@ -1,10 +1,32 @@ >> Hisilicon Platforms Device Tree Bindings >> ---------------------------------------------------- >> >> -Hi3716 Development Board >> -Required root node properties: >> - - compatible = "hisilicon,hi3716-dkb"; >> - >> Hi4511 Board >> Required root node properties: >> - compatible = "hisilicon,hi3620-hi4511"; >> + >> +Hisilicon system controller >> + >> +Required properties: >> +- compatible : "hisilicon,sysctrl" >> +- reg : Register address and size >> + >> +Optional properties: >> +- smp-offset : 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-offset : offset in sysctrl for notifying cpu0 when resume >> +- reboot-offset : offset in sysctrl for system reboot >> + >> +Example: >> + >> + /* for Hi3620 */ >> + sysctrl: system-controller@fc802000 { >> + compatible = "hisilicon,sysctrl"; >> + reg = <0xfc802000 0x1000>; >> + smp-offset = <0x31c>; >> + resume-offset = <0x308>; >> + reboot-offset = <0x4>; >> + }; >> diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi >> index b9d8679..e311937 100644 >> --- a/arch/arm/boot/dts/hi3620.dtsi >> +++ b/arch/arm/boot/dts/hi3620.dtsi >> @@ -39,6 +39,27 @@ >> reg = <0x0>; >> 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>; >> + }; >> }; >> >> amba { >> @@ -65,6 +86,17 @@ >> reg = <0x1000 0x1000>, <0x100 0x100>; >> }; >> >> + sysctrl: system-controller@802000 { >> + compatible = "hisilicon,sysctrl"; >> + reg = <0x802000 0x1000>; >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + smp-offset = <0x31c>; >> + resume-offset = <0x308>; >> + reboot-offset = <0x4>; >> + }; >> + >> dual_timer0: dual_timer@800000 { >> compatible = "arm,sp804", "arm,primecell"; >> reg = <0x800000 0x1000>; >> @@ -115,6 +147,12 @@ >> status = "disabled"; >> }; >> >> + timer5: timer@600 { >> + compatible = "arm,cortex-a9-twd-timer"; >> + reg = <0x600 0x20>; >> + interrupts = <1 13 0xf01>; >> + }; > Do you have a clocks node for this timer? As I mentioned in the 0th patch, clock binding are totally removed in this patch. And clock driver will be append in another patch set. >> + >> uart0: uart@b00000 { >> compatible = "arm,pl011", "arm,primecell"; >> reg = <0xb00000 0x1000>; >> diff --git a/arch/arm/mach-hi3xxx/Kconfig b/arch/arm/mach-hi3xxx/Kconfig >> index 68bd26c..d0f298a 100644 >> --- a/arch/arm/mach-hi3xxx/Kconfig >> +++ b/arch/arm/mach-hi3xxx/Kconfig >> @@ -6,6 +6,9 @@ config ARCH_HI3xxx >> select CACHE_L2X0 >> select CLKSRC_OF >> select GENERIC_CLOCKEVENTS >> + select HAVE_ARM_SCU >> + select HAVE_ARM_TWD > Need "if SMP" to avoid a build failure for a non-smp kernel. > ARCH_HI3xxx always need SMP configuration. HAVE_SMP is already required. So it's impossible to build a non-smp kernel with this kernel configuration. > Dinh >> + select HAVE_SMP >> select PINCTRL >> select PINCTRL_SINGLE >> help >> diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile >> index d68ebb3..7a869a7 100644 >> --- a/arch/arm/mach-hi3xxx/Makefile >> +++ b/arch/arm/mach-hi3xxx/Makefile >> @@ -3,3 +3,4 @@ >> # >> >> obj-y += hi3xxx.o >> +obj-$(CONFIG_SMP) += platsmp.o >> diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h >> new file mode 100644 >> index 0000000..226f020 >> --- /dev/null >> +++ b/arch/arm/mach-hi3xxx/core.h >> @@ -0,0 +1,11 @@ >> +#ifndef __HISILICON_CORE_H >> +#define __HISILICON_CORE_H >> + >> +#include <linux/reboot.h> >> + >> +extern void hi3xxx_set_cpu_jump(int cpu, void *jump_addr); >> +extern int hi3xxx_get_cpu_jump(int cpu); >> +extern void secondary_startup(void); >> +extern struct smp_operations hi3xxx_smp_ops; >> + >> +#endif >> diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c >> index 925af13..80990b3 100644 >> --- a/arch/arm/mach-hi3xxx/hi3xxx.c >> +++ b/arch/arm/mach-hi3xxx/hi3xxx.c >> @@ -14,11 +14,16 @@ >> #include <linux/clk-provider.h> >> #include <linux/clocksource.h> >> #include <linux/irqchip.h> >> +#include <linux/of_address.h> >> #include <linux/of_platform.h> >> >> +#include <asm/proc-fns.h> >> + >> #include <asm/mach/arch.h> >> #include <asm/mach/map.h> >> >> +#include "core.h" >> + >> /* >> * This table is only for optimization. Since ioremap() could always share >> * the same mapping if it's defined as static IO mapping. >> @@ -29,6 +34,7 @@ >> */ >> static struct map_desc hi3620_io_desc[] __initdata = { >> { >> + /* sysctrl */ > What's this comment for? >> .pfn = __phys_to_pfn(0xfc802000), >> .virtual = 0xfe802000, >> .length = 0x1000, >> @@ -48,6 +54,32 @@ static void __init hi3xxx_timer_init(void) >> clocksource_of_init(); >> } >> >> +static void hi3xxx_restart(enum reboot_mode mode, const char *cmd) >> +{ >> + struct device_node *np; >> + void __iomem *base; >> + int offset; >> + >> + np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); >> + if (!np) { >> + pr_err("failed to find hisilicon,sysctrl node\n"); >> + return; >> + } >> + base = of_iomap(np, 0); >> + if (!base) { >> + pr_err("failed to map address in hisilicon,sysctrl node\n"); >> + return; >> + } >> + if (of_property_read_u32(np, "reboot-offset", &offset) < 0) { >> + pr_err("failed to find reboot-offset property\n"); >> + return; >> + } >> + writel_relaxed(0xdeadbeef, base + offset); >> + >> + while (1) >> + cpu_do_idle(); >> +} >> + >> static const char *hi3xxx_compat[] __initdata = { >> "hisilicon,hi3620-hi4511", >> NULL, >> @@ -57,4 +89,6 @@ DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)") >> .map_io = hi3620_map_io, >> .init_time = hi3xxx_timer_init, >> .dt_compat = hi3xxx_compat, >> + .smp = smp_ops(hi3xxx_smp_ops), >> + .restart = hi3xxx_restart, >> MACHINE_END >> diff --git a/arch/arm/mach-hi3xxx/platsmp.c b/arch/arm/mach-hi3xxx/platsmp.c >> new file mode 100644 >> index 0000000..a4d04c0 >> --- /dev/null >> +++ b/arch/arm/mach-hi3xxx/platsmp.c >> @@ -0,0 +1,84 @@ >> +/* >> + * 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 <linux/of_address.h> >> + >> +#include <asm/cacheflush.h> >> +#include <asm/smp_plat.h> >> +#include <asm/smp_scu.h> >> + >> +#include "core.h" >> + >> +static void __iomem *ctrl_base = NULL; >> + >> +void hi3xxx_set_cpu_jump(int cpu, void *jump_addr) >> +{ >> + cpu = cpu_logical_map(cpu); >> + if (!cpu || !ctrl_base) >> + return; >> + writel_relaxed(virt_to_phys(jump_addr), ctrl_base + ((cpu - 1) << 2)); >> +} >> + >> +int hi3xxx_get_cpu_jump(int cpu) >> +{ >> + cpu = cpu_logical_map(cpu); >> + if (!cpu || !ctrl_base) >> + return 0; >> + return readl_relaxed(ctrl_base + ((cpu - 1 ) << 2)); >> +} >> + >> +static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) >> +{ >> + struct device_node *np = NULL; >> + unsigned long base = 0; >> + u32 offset = 0; >> + void __iomem *scu_base = NULL; >> + >> + 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); >> + } >> + if (!ctrl_base) { >> + np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); >> + if (!np) { >> + pr_err("failed to find hisilicon,sysctrl node\n"); >> + return; >> + } >> + ctrl_base = of_iomap(np, 0); >> + if (!ctrl_base) { >> + pr_err("failed to map address\n"); >> + return; >> + } >> + if (of_property_read_u32(np, "smp-offset", &offset) < 0) { >> + pr_err("failed to find smp-offset property\n"); >> + return; >> + } >> + ctrl_base += offset; >> + } >> +} >> + >> +static int hi3xxx_boot_secondary(unsigned int cpu, struct task_struct *idle) >> +{ >> + hi3xxx_set_cpu_jump(cpu, secondary_startup); >> + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); >> + return 0; >> +} >> + >> +struct smp_operations hi3xxx_smp_ops __initdata = { >> + .smp_prepare_cpus = hi3xxx_smp_prepare_cpus, >> + .smp_boot_secondary = hi3xxx_boot_secondary, >> +}; > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html