[PATCH v11 5/6] ARM: hi3xxx: add smp support
Haojian Zhuang
haojian.zhuang at linaro.org
Tue Nov 12 03:49:42 EST 2013
On 7 November 2013 18:30, Dinh Nguyen <dinh.linux at gmail.com> wrote:
>
> On 11/7/13 2:41 AM, Haojian Zhuang wrote:
>> From: Zhangfei Gao <zhangfei.gao at linaro.org>
>>
>> Enable SMP support on hi3xxx platform
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao at linaro.org>
>> Tested-by: Zhang Mingjun <zhang.mingjun at linaro.org>
>> Tested-by: Li Xin <li.xin at linaro.org>
>> Signed-off-by: Haojian Zhuang <haojian.zhuang at linaro.org>
>> ---
>> .../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 at 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 at 1 {
>> + compatible = "arm,cortex-a9";
>> + device_type = "cpu";
>> + reg = <1>;
>> + next-level-cache = <&L2>;
>> + };
>> +
>> + cpu at 2 {
>> + compatible = "arm,cortex-a9";
>> + device_type = "cpu";
>> + reg = <2>;
>> + next-level-cache = <&L2>;
>> + };
>> +
>> + cpu at 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 at 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 at 800000 {
>> compatible = "arm,sp804", "arm,primecell";
>> reg = <0x800000 0x1000>;
>> @@ -115,6 +147,12 @@
>> status = "disabled";
>> };
>>
>> + timer5: timer at 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 at 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,
>> +};
>
More information about the linux-arm-kernel
mailing list