diff options
Diffstat (limited to 'arch/arm/mach-hisi')
-rw-r--r-- | arch/arm/mach-hisi/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/mach-hisi/core.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-hisi/headsmp.S | 2 | ||||
-rw-r--r-- | arch/arm/mach-hisi/hisilicon.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-hisi/hotplug.c | 31 | ||||
-rw-r--r-- | arch/arm/mach-hisi/platsmp.c | 56 |
6 files changed, 107 insertions, 5 deletions
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig index cd19433f76d3..83061ad0e282 100644 --- a/arch/arm/mach-hisi/Kconfig +++ b/arch/arm/mach-hisi/Kconfig @@ -22,6 +22,14 @@ config ARCH_HI3xxx help Support for Hisilicon Hi36xx SoC family +config ARCH_HIP01 + bool "Hisilicon HIP01 family" if ARCH_MULTI_V7 + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select ARM_GLOBAL_TIMER + help + Support for Hisilicon HIP01 SoC family + config ARCH_HIP04 bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7 select ARM_ERRATA_798181 if SMP diff --git a/arch/arm/mach-hisi/core.h b/arch/arm/mach-hisi/core.h index 88b1f487d065..92a682d8e939 100644 --- a/arch/arm/mach-hisi/core.h +++ b/arch/arm/mach-hisi/core.h @@ -12,9 +12,12 @@ 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); -extern void hix5hd2_secondary_startup(void); +extern void hisi_secondary_startup(void); extern struct smp_operations hix5hd2_smp_ops; extern void hix5hd2_set_cpu(int cpu, bool enable); extern void hix5hd2_cpu_die(unsigned int cpu); +extern struct smp_operations hip01_smp_ops; +extern void hip01_set_cpu(int cpu, bool enable); +extern void hip01_cpu_die(unsigned int cpu); #endif diff --git a/arch/arm/mach-hisi/headsmp.S b/arch/arm/mach-hisi/headsmp.S index 278889c00b77..81e35b159e75 100644 --- a/arch/arm/mach-hisi/headsmp.S +++ b/arch/arm/mach-hisi/headsmp.S @@ -11,6 +11,6 @@ __CPUINIT -ENTRY(hix5hd2_secondary_startup) +ENTRY(hisi_secondary_startup) bl v7_invalidate_l1 b secondary_startup diff --git a/arch/arm/mach-hisi/hisilicon.c b/arch/arm/mach-hisi/hisilicon.c index 7744c351bbfd..76b907078b58 100644 --- a/arch/arm/mach-hisi/hisilicon.c +++ b/arch/arm/mach-hisi/hisilicon.c @@ -72,3 +72,13 @@ static const char *hip04_compat[] __initconst = { DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)") .dt_compat = hip04_compat, MACHINE_END + +static const char *hip01_compat[] __initconst = { + "hisilicon,hip01", + "hisilicon,hip01-ca9x2", + NULL, +}; + +DT_MACHINE_START(HIP01, "Hisilicon HIP01 (Flattened Device Tree)") + .dt_compat = hip01_compat, +MACHINE_END diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c index 84e6919f68c7..a129aae72602 100644 --- a/arch/arm/mach-hisi/hotplug.c +++ b/arch/arm/mach-hisi/hotplug.c @@ -65,6 +65,9 @@ #define PMC0_CPU1_PMC_ENABLE (1 << 7) #define PMC0_CPU1_POWERDOWN (1 << 3) +#define HIP01_PERI9 0x50 +#define PERI9_CPU1_RESET (1 << 1) + enum { HI3620_CTRL, ERROR_CTRL, @@ -209,6 +212,34 @@ void hix5hd2_set_cpu(int cpu, bool enable) } } +void hip01_set_cpu(int cpu, bool enable) +{ + unsigned int temp; + struct device_node *np; + + if (!ctrl_base) { + np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl"); + if (np) + ctrl_base = of_iomap(np, 0); + else + BUG(); + } + + if (enable) { + /* reset on CPU1 */ + temp = readl_relaxed(ctrl_base + HIP01_PERI9); + temp |= PERI9_CPU1_RESET; + writel_relaxed(temp, ctrl_base + HIP01_PERI9); + + udelay(50); + + /* unreset on CPU1 */ + temp = readl_relaxed(ctrl_base + HIP01_PERI9); + temp &= ~PERI9_CPU1_RESET; + writel_relaxed(temp, ctrl_base + HIP01_PERI9); + } +} + static inline void cpu_enter_lowpower(void) { unsigned int v; diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c index 575dd8285f1f..8880c8e8b296 100644 --- a/arch/arm/mach-hisi/platsmp.c +++ b/arch/arm/mach-hisi/platsmp.c @@ -10,10 +10,12 @@ #include <linux/smp.h> #include <linux/io.h> #include <linux/of_address.h> +#include <linux/delay.h> #include <asm/cacheflush.h> #include <asm/smp_plat.h> #include <asm/smp_scu.h> +#include <asm/mach/map.h> #include "core.h" @@ -96,7 +98,7 @@ struct smp_operations hi3xxx_smp_ops __initdata = { #endif }; -static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus) +static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus) { hisi_enable_scu_a9(); } @@ -116,7 +118,7 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) { phys_addr_t jumpaddr; - jumpaddr = virt_to_phys(hix5hd2_secondary_startup); + jumpaddr = virt_to_phys(hisi_secondary_startup); hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); hix5hd2_set_cpu(cpu, true); arch_send_wakeup_ipi_mask(cpumask_of(cpu)); @@ -125,12 +127,60 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) struct smp_operations hix5hd2_smp_ops __initdata = { - .smp_prepare_cpus = hix5hd2_smp_prepare_cpus, + .smp_prepare_cpus = hisi_common_smp_prepare_cpus, .smp_boot_secondary = hix5hd2_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = hix5hd2_cpu_die, #endif }; + +#define SC_SCTL_REMAP_CLR 0x00000100 +#define HIP01_BOOT_ADDRESS 0x80000000 +#define REG_SC_CTRL 0x000 + +void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr) +{ + void __iomem *virt; + + virt = phys_to_virt(start_addr); + + writel_relaxed(0xe51ff004, virt); + writel_relaxed(jump_addr, virt + 4); +} + +static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + phys_addr_t jumpaddr; + unsigned int remap_reg_value = 0; + struct device_node *node; + + + jumpaddr = virt_to_phys(hisi_secondary_startup); + hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr); + + node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl"); + if (WARN_ON(!node)) + return -1; + ctrl_base = of_iomap(node, 0); + + /* set the secondary core boot from DDR */ + remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL); + barrier(); + remap_reg_value |= SC_SCTL_REMAP_CLR; + barrier(); + writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL); + + hip01_set_cpu(cpu, true); + + return 0; +} + +struct smp_operations hip01_smp_ops __initdata = { + .smp_prepare_cpus = hisi_common_smp_prepare_cpus, + .smp_boot_secondary = hip01_boot_secondary, +}; + CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops); CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops); +CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops); |