From 389ee0c2ffedf5819dccc2c67dd15757c4550765 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Fri, 20 Dec 2013 10:52:56 +0800 Subject: ARM: hisi: rename hi3xxx to hisi Since some new Hisilicon SoCs are not named as hi3xxx, rename mach-hi3xxx to mach-hisi instead. And the pronounciation of "hisi" is similar to the chinese pronounciation of Hisilicon. So Hisilicon guys like this name. ARCH_HI3xxx will be renamed later since other drivers are using it and they are still in linux-next git tree. So rename ARCH_HI3xxx later. Signed-off-by: Haojian Zhuang Signed-off-by: Kevin Hilman --- arch/arm/Kconfig | 4 +- arch/arm/Makefile | 2 +- arch/arm/mach-hi3xxx/Kconfig | 17 ---- arch/arm/mach-hi3xxx/Makefile | 7 -- arch/arm/mach-hi3xxx/core.h | 15 ---- arch/arm/mach-hi3xxx/hi3xxx.c | 97 -------------------- arch/arm/mach-hi3xxx/hotplug.c | 200 ----------------------------------------- arch/arm/mach-hi3xxx/platsmp.c | 89 ------------------ arch/arm/mach-hisi/Kconfig | 17 ++++ arch/arm/mach-hisi/Makefile | 7 ++ arch/arm/mach-hisi/core.h | 15 ++++ arch/arm/mach-hisi/hisilicon.c | 97 ++++++++++++++++++++ arch/arm/mach-hisi/hotplug.c | 200 +++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-hisi/platsmp.c | 89 ++++++++++++++++++ 14 files changed, 428 insertions(+), 428 deletions(-) delete mode 100644 arch/arm/mach-hi3xxx/Kconfig delete mode 100644 arch/arm/mach-hi3xxx/Makefile delete mode 100644 arch/arm/mach-hi3xxx/core.h delete mode 100644 arch/arm/mach-hi3xxx/hi3xxx.c delete mode 100644 arch/arm/mach-hi3xxx/hotplug.c delete mode 100644 arch/arm/mach-hi3xxx/platsmp.c create mode 100644 arch/arm/mach-hisi/Kconfig create mode 100644 arch/arm/mach-hisi/Makefile create mode 100644 arch/arm/mach-hisi/core.h create mode 100644 arch/arm/mach-hisi/hisilicon.c create mode 100644 arch/arm/mach-hisi/hotplug.c create mode 100644 arch/arm/mach-hisi/platsmp.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 75eb5323fedd..b7662dfcd847 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -925,10 +925,10 @@ source "arch/arm/mach-footbridge/Kconfig" source "arch/arm/mach-gemini/Kconfig" -source "arch/arm/mach-hi3xxx/Kconfig" - source "arch/arm/mach-highbank/Kconfig" +source "arch/arm/mach-hisi/Kconfig" + source "arch/arm/mach-integrator/Kconfig" source "arch/arm/mach-iop32x/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index dfbafa38b4cd..173ea7b01ff8 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -156,8 +156,8 @@ machine-$(CONFIG_ARCH_EBSA110) += ebsa110 machine-$(CONFIG_ARCH_EP93XX) += ep93xx machine-$(CONFIG_ARCH_EXYNOS) += exynos machine-$(CONFIG_ARCH_GEMINI) += gemini -machine-$(CONFIG_ARCH_HI3xxx) += hi3xxx machine-$(CONFIG_ARCH_HIGHBANK) += highbank +machine-$(CONFIG_ARCH_HI3xxx) += hisi machine-$(CONFIG_ARCH_INTEGRATOR) += integrator machine-$(CONFIG_ARCH_IOP13XX) += iop13xx machine-$(CONFIG_ARCH_IOP32X) += iop32x diff --git a/arch/arm/mach-hi3xxx/Kconfig b/arch/arm/mach-hi3xxx/Kconfig deleted file mode 100644 index 018ad67f1b38..000000000000 --- a/arch/arm/mach-hi3xxx/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -config ARCH_HI3xxx - bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7 - select ARM_AMBA - select ARM_GIC - select ARM_TIMER_SP804 - select ARCH_WANT_OPTIONAL_GPIOLIB - select CACHE_L2X0 - select CLKSRC_OF - select GENERIC_CLOCKEVENTS - select HAVE_ARM_SCU - select HAVE_ARM_TWD - select HAVE_SMP - select PINCTRL - select PINCTRL_SINGLE - select SMP - help - Support for Hisilicon Hi36xx/Hi37xx processor family diff --git a/arch/arm/mach-hi3xxx/Makefile b/arch/arm/mach-hi3xxx/Makefile deleted file mode 100644 index c9919e8e239c..000000000000 --- a/arch/arm/mach-hi3xxx/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# Makefile for Hisilicon Hi36xx/Hi37xx processors line -# - -obj-y += hi3xxx.o -obj-$(CONFIG_SMP) += platsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-hi3xxx/core.h b/arch/arm/mach-hi3xxx/core.h deleted file mode 100644 index af23ec204538..000000000000 --- a/arch/arm/mach-hi3xxx/core.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __HISILICON_CORE_H -#define __HISILICON_CORE_H - -#include - -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; - -extern void hi3xxx_cpu_die(unsigned int cpu); -extern int hi3xxx_cpu_kill(unsigned int cpu); -extern void hi3xxx_set_cpu(int cpu, bool enable); - -#endif diff --git a/arch/arm/mach-hi3xxx/hi3xxx.c b/arch/arm/mach-hi3xxx/hi3xxx.c deleted file mode 100644 index 661a912f1527..000000000000 --- a/arch/arm/mach-hi3xxx/hi3xxx.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * (Hisilicon's Hi36xx/Hi37xx SoC based) flattened device tree enabled machine - * - * Copyright (c) 2012-2013 Hisilicon Ltd. - * Copyright (c) 2012-2013 Linaro Ltd. - * - * Author: Haojian Zhuang - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "core.h" - -#define HI3620_SYSCTRL_PHYS_BASE 0xfc802000 -#define HI3620_SYSCTRL_VIRT_BASE 0xfe802000 - -/* - * This table is only for optimization. Since ioremap() could always share - * the same mapping if it's defined as static IO mapping. - * - * Without this table, system could also work. The cost is some virtual address - * spaces wasted since ioremap() may be called multi times for the same - * IO space. - */ -static struct map_desc hi3620_io_desc[] __initdata = { - { - /* sysctrl */ - .pfn = __phys_to_pfn(HI3620_SYSCTRL_PHYS_BASE), - .virtual = HI3620_SYSCTRL_VIRT_BASE, - .length = 0x1000, - .type = MT_DEVICE, - }, -}; - -static void __init hi3620_map_io(void) -{ - debug_ll_io_init(); - iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc)); -} - -static void __init hi3xxx_timer_init(void) -{ - of_clk_init(NULL); - 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[] __initconst = { - "hisilicon,hi3620-hi4511", - NULL, -}; - -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/hotplug.c b/arch/arm/mach-hi3xxx/hotplug.c deleted file mode 100644 index b909854eee7f..000000000000 --- a/arch/arm/mach-hi3xxx/hotplug.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include -#include "core.h" - -/* Sysctrl registers in Hi3620 SoC */ -#define SCISOEN 0xc0 -#define SCISODIS 0xc4 -#define SCPERPWREN 0xd0 -#define SCPERPWRDIS 0xd4 -#define SCCPUCOREEN 0xf4 -#define SCCPUCOREDIS 0xf8 -#define SCPERCTRL0 0x200 -#define SCCPURSTEN 0x410 -#define SCCPURSTDIS 0x414 - -/* - * bit definition in SCISOEN/SCPERPWREN/... - * - * CPU2_ISO_CTRL (1 << 5) - * CPU3_ISO_CTRL (1 << 6) - * ... - */ -#define CPU2_ISO_CTRL (1 << 5) - -/* - * bit definition in SCPERCTRL0 - * - * CPU0_WFI_MASK_CFG (1 << 28) - * CPU1_WFI_MASK_CFG (1 << 29) - * ... - */ -#define CPU0_WFI_MASK_CFG (1 << 28) - -/* - * bit definition in SCCPURSTEN/... - * - * CPU0_SRST_REQ_EN (1 << 0) - * CPU1_SRST_REQ_EN (1 << 1) - * ... - */ -#define CPU0_HPM_SRST_REQ_EN (1 << 22) -#define CPU0_DBG_SRST_REQ_EN (1 << 12) -#define CPU0_NEON_SRST_REQ_EN (1 << 4) -#define CPU0_SRST_REQ_EN (1 << 0) - -enum { - HI3620_CTRL, - ERROR_CTRL, -}; - -static void __iomem *ctrl_base; -static int id; - -static void set_cpu_hi3620(int cpu, bool enable) -{ - u32 val = 0; - - if (enable) { - /* MTCMOS set */ - if ((cpu == 2) || (cpu == 3)) - writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), - ctrl_base + SCPERPWREN); - udelay(100); - - /* Enable core */ - writel_relaxed(0x01 << cpu, ctrl_base + SCCPUCOREEN); - - /* unreset */ - val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN - | CPU0_SRST_REQ_EN; - writel_relaxed(val << cpu, ctrl_base + SCCPURSTDIS); - /* reset */ - val |= CPU0_HPM_SRST_REQ_EN; - writel_relaxed(val << cpu, ctrl_base + SCCPURSTEN); - - /* ISO disable */ - if ((cpu == 2) || (cpu == 3)) - writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), - ctrl_base + SCISODIS); - udelay(1); - - /* WFI Mask */ - val = readl_relaxed(ctrl_base + SCPERCTRL0); - val &= ~(CPU0_WFI_MASK_CFG << cpu); - writel_relaxed(val, ctrl_base + SCPERCTRL0); - - /* Unreset */ - val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN - | CPU0_SRST_REQ_EN | CPU0_HPM_SRST_REQ_EN; - writel_relaxed(val << cpu, ctrl_base + SCCPURSTDIS); - } else { - /* wfi mask */ - val = readl_relaxed(ctrl_base + SCPERCTRL0); - val |= (CPU0_WFI_MASK_CFG << cpu); - writel_relaxed(val, ctrl_base + SCPERCTRL0); - - /* disable core*/ - writel_relaxed(0x01 << cpu, ctrl_base + SCCPUCOREDIS); - - if ((cpu == 2) || (cpu == 3)) { - /* iso enable */ - writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), - ctrl_base + SCISOEN); - udelay(1); - } - - /* reset */ - val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN - | CPU0_SRST_REQ_EN | CPU0_HPM_SRST_REQ_EN; - writel_relaxed(val << cpu, ctrl_base + SCCPURSTEN); - - if ((cpu == 2) || (cpu == 3)) { - /* MTCMOS unset */ - writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), - ctrl_base + SCPERPWRDIS); - udelay(100); - } - } -} - -static int hi3xxx_hotplug_init(void) -{ - struct device_node *node; - - node = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); - if (node) { - ctrl_base = of_iomap(node, 0); - id = HI3620_CTRL; - return 0; - } - id = ERROR_CTRL; - return -ENOENT; -} - -void hi3xxx_set_cpu(int cpu, bool enable) -{ - if (!ctrl_base) { - if (hi3xxx_hotplug_init() < 0) - return; - } - - if (id == HI3620_CTRL) - set_cpu_hi3620(cpu, enable); -} - -static inline void cpu_enter_lowpower(void) -{ - unsigned int v; - - flush_cache_all(); - - /* - * Turn off coherency and L1 D-cache - */ - asm volatile( - " mrc p15, 0, %0, c1, c0, 1\n" - " bic %0, %0, #0x40\n" - " mcr p15, 0, %0, c1, c0, 1\n" - " mrc p15, 0, %0, c1, c0, 0\n" - " bic %0, %0, #0x04\n" - " mcr p15, 0, %0, c1, c0, 0\n" - : "=&r" (v) - : "r" (0) - : "cc"); -} - -void hi3xxx_cpu_die(unsigned int cpu) -{ - cpu_enter_lowpower(); - hi3xxx_set_cpu_jump(cpu, phys_to_virt(0)); - cpu_do_idle(); - - /* We should have never returned from idle */ - panic("cpu %d unexpectedly exit from shutdown\n", cpu); -} - -int hi3xxx_cpu_kill(unsigned int cpu) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(50); - - while (hi3xxx_get_cpu_jump(cpu)) - if (time_after(jiffies, timeout)) - return 0; - hi3xxx_set_cpu(cpu, false); - return 1; -} diff --git a/arch/arm/mach-hi3xxx/platsmp.c b/arch/arm/mach-hi3xxx/platsmp.c deleted file mode 100644 index 471f1ee3be2b..000000000000 --- a/arch/arm/mach-hi3xxx/platsmp.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2013 Linaro Ltd. - * Copyright (c) 2013 Hisilicon Limited. - * Based on arch/arm/mach-vexpress/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 -#include -#include - -#include -#include -#include - -#include "core.h" - -static void __iomem *ctrl_base; - -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(cpu, true); - 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, -#ifdef CONFIG_HOTPLUG_CPU - .cpu_die = hi3xxx_cpu_die, - .cpu_kill = hi3xxx_cpu_kill, -#endif -}; diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig new file mode 100644 index 000000000000..018ad67f1b38 --- /dev/null +++ b/arch/arm/mach-hisi/Kconfig @@ -0,0 +1,17 @@ +config ARCH_HI3xxx + bool "Hisilicon Hi36xx/Hi37xx family" if ARCH_MULTI_V7 + select ARM_AMBA + select ARM_GIC + select ARM_TIMER_SP804 + select ARCH_WANT_OPTIONAL_GPIOLIB + select CACHE_L2X0 + select CLKSRC_OF + select GENERIC_CLOCKEVENTS + select HAVE_ARM_SCU + select HAVE_ARM_TWD + select HAVE_SMP + select PINCTRL + select PINCTRL_SINGLE + select SMP + help + Support for Hisilicon Hi36xx/Hi37xx processor family diff --git a/arch/arm/mach-hisi/Makefile b/arch/arm/mach-hisi/Makefile new file mode 100644 index 000000000000..6870058d0a48 --- /dev/null +++ b/arch/arm/mach-hisi/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Hisilicon processors family +# + +obj-y += hisilicon.o +obj-$(CONFIG_SMP) += platsmp.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h new file mode 100644 index 000000000000..af23ec204538 --- /dev/null +++ b/arch/arm/mach-hisi/core.h @@ -0,0 +1,15 @@ +#ifndef __HISILICON_CORE_H +#define __HISILICON_CORE_H + +#include + +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; + +extern void hi3xxx_cpu_die(unsigned int cpu); +extern int hi3xxx_cpu_kill(unsigned int cpu); +extern void hi3xxx_set_cpu(int cpu, bool enable); + +#endif diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c new file mode 100644 index 000000000000..685d9ebd612d --- /dev/null +++ b/arch/arm/mach-hisi/hisilicon.c @@ -0,0 +1,97 @@ +/* + * (Hisilicon's SoC based) flattened device tree enabled machine + * + * Copyright (c) 2012-2013 Hisilicon Ltd. + * Copyright (c) 2012-2013 Linaro Ltd. + * + * Author: Haojian Zhuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "core.h" + +#define HI3620_SYSCTRL_PHYS_BASE 0xfc802000 +#define HI3620_SYSCTRL_VIRT_BASE 0xfe802000 + +/* + * This table is only for optimization. Since ioremap() could always share + * the same mapping if it's defined as static IO mapping. + * + * Without this table, system could also work. The cost is some virtual address + * spaces wasted since ioremap() may be called multi times for the same + * IO space. + */ +static struct map_desc hi3620_io_desc[] __initdata = { + { + /* sysctrl */ + .pfn = __phys_to_pfn(HI3620_SYSCTRL_PHYS_BASE), + .virtual = HI3620_SYSCTRL_VIRT_BASE, + .length = 0x1000, + .type = MT_DEVICE, + }, +}; + +static void __init hi3620_map_io(void) +{ + debug_ll_io_init(); + iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc)); +} + +static void __init hi3xxx_timer_init(void) +{ + of_clk_init(NULL); + 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[] __initconst = { + "hisilicon,hi3620-hi4511", + NULL, +}; + +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-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c new file mode 100644 index 000000000000..b909854eee7f --- /dev/null +++ b/arch/arm/mach-hisi/hotplug.c @@ -0,0 +1,200 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include "core.h" + +/* Sysctrl registers in Hi3620 SoC */ +#define SCISOEN 0xc0 +#define SCISODIS 0xc4 +#define SCPERPWREN 0xd0 +#define SCPERPWRDIS 0xd4 +#define SCCPUCOREEN 0xf4 +#define SCCPUCOREDIS 0xf8 +#define SCPERCTRL0 0x200 +#define SCCPURSTEN 0x410 +#define SCCPURSTDIS 0x414 + +/* + * bit definition in SCISOEN/SCPERPWREN/... + * + * CPU2_ISO_CTRL (1 << 5) + * CPU3_ISO_CTRL (1 << 6) + * ... + */ +#define CPU2_ISO_CTRL (1 << 5) + +/* + * bit definition in SCPERCTRL0 + * + * CPU0_WFI_MASK_CFG (1 << 28) + * CPU1_WFI_MASK_CFG (1 << 29) + * ... + */ +#define CPU0_WFI_MASK_CFG (1 << 28) + +/* + * bit definition in SCCPURSTEN/... + * + * CPU0_SRST_REQ_EN (1 << 0) + * CPU1_SRST_REQ_EN (1 << 1) + * ... + */ +#define CPU0_HPM_SRST_REQ_EN (1 << 22) +#define CPU0_DBG_SRST_REQ_EN (1 << 12) +#define CPU0_NEON_SRST_REQ_EN (1 << 4) +#define CPU0_SRST_REQ_EN (1 << 0) + +enum { + HI3620_CTRL, + ERROR_CTRL, +}; + +static void __iomem *ctrl_base; +static int id; + +static void set_cpu_hi3620(int cpu, bool enable) +{ + u32 val = 0; + + if (enable) { + /* MTCMOS set */ + if ((cpu == 2) || (cpu == 3)) + writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), + ctrl_base + SCPERPWREN); + udelay(100); + + /* Enable core */ + writel_relaxed(0x01 << cpu, ctrl_base + SCCPUCOREEN); + + /* unreset */ + val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN + | CPU0_SRST_REQ_EN; + writel_relaxed(val << cpu, ctrl_base + SCCPURSTDIS); + /* reset */ + val |= CPU0_HPM_SRST_REQ_EN; + writel_relaxed(val << cpu, ctrl_base + SCCPURSTEN); + + /* ISO disable */ + if ((cpu == 2) || (cpu == 3)) + writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), + ctrl_base + SCISODIS); + udelay(1); + + /* WFI Mask */ + val = readl_relaxed(ctrl_base + SCPERCTRL0); + val &= ~(CPU0_WFI_MASK_CFG << cpu); + writel_relaxed(val, ctrl_base + SCPERCTRL0); + + /* Unreset */ + val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN + | CPU0_SRST_REQ_EN | CPU0_HPM_SRST_REQ_EN; + writel_relaxed(val << cpu, ctrl_base + SCCPURSTDIS); + } else { + /* wfi mask */ + val = readl_relaxed(ctrl_base + SCPERCTRL0); + val |= (CPU0_WFI_MASK_CFG << cpu); + writel_relaxed(val, ctrl_base + SCPERCTRL0); + + /* disable core*/ + writel_relaxed(0x01 << cpu, ctrl_base + SCCPUCOREDIS); + + if ((cpu == 2) || (cpu == 3)) { + /* iso enable */ + writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), + ctrl_base + SCISOEN); + udelay(1); + } + + /* reset */ + val = CPU0_DBG_SRST_REQ_EN | CPU0_NEON_SRST_REQ_EN + | CPU0_SRST_REQ_EN | CPU0_HPM_SRST_REQ_EN; + writel_relaxed(val << cpu, ctrl_base + SCCPURSTEN); + + if ((cpu == 2) || (cpu == 3)) { + /* MTCMOS unset */ + writel_relaxed(CPU2_ISO_CTRL << (cpu - 2), + ctrl_base + SCPERPWRDIS); + udelay(100); + } + } +} + +static int hi3xxx_hotplug_init(void) +{ + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); + if (node) { + ctrl_base = of_iomap(node, 0); + id = HI3620_CTRL; + return 0; + } + id = ERROR_CTRL; + return -ENOENT; +} + +void hi3xxx_set_cpu(int cpu, bool enable) +{ + if (!ctrl_base) { + if (hi3xxx_hotplug_init() < 0) + return; + } + + if (id == HI3620_CTRL) + set_cpu_hi3620(cpu, enable); +} + +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + flush_cache_all(); + + /* + * Turn off coherency and L1 D-cache + */ + asm volatile( + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x40\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, #0x04\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0) + : "cc"); +} + +void hi3xxx_cpu_die(unsigned int cpu) +{ + cpu_enter_lowpower(); + hi3xxx_set_cpu_jump(cpu, phys_to_virt(0)); + cpu_do_idle(); + + /* We should have never returned from idle */ + panic("cpu %d unexpectedly exit from shutdown\n", cpu); +} + +int hi3xxx_cpu_kill(unsigned int cpu) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(50); + + while (hi3xxx_get_cpu_jump(cpu)) + if (time_after(jiffies, timeout)) + return 0; + hi3xxx_set_cpu(cpu, false); + return 1; +} diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c new file mode 100644 index 000000000000..471f1ee3be2b --- /dev/null +++ b/arch/arm/mach-hisi/platsmp.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Linaro Ltd. + * Copyright (c) 2013 Hisilicon Limited. + * Based on arch/arm/mach-vexpress/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 +#include +#include + +#include +#include +#include + +#include "core.h" + +static void __iomem *ctrl_base; + +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(cpu, true); + 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, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = hi3xxx_cpu_die, + .cpu_kill = hi3xxx_cpu_kill, +#endif +}; -- cgit