From 06cc5c1d4d7313bc864e9aac1d1cbd63d8b9ca4c Mon Sep 17 00:00:00 2001 From: Haifeng Yan Date: Fri, 11 Apr 2014 11:54:11 +0800 Subject: ARM: hisi: enable hix5hd2 SoC Enable support for the Hisilicon HiX5HD2 SoC. This HiX5HD2 SoC series support both single and dual Cortex-A9 cores. Add ARCH_HIX5HD2 to distinguish HiX5HD2 from Hi3xxx. They are different in implementation such as SMP, IPs integarted and earlycon configure. Signed-off-by: Haifeng Yan Signed-off-by: Jiancheng Xue Signed-off-by: Haojian Zhuang Acked-by: Wei Xu Signed-off-by: Olof Johansson --- arch/arm/mach-hisi/platsmp.c | 50 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-hisi/platsmp.c') diff --git a/arch/arm/mach-hisi/platsmp.c b/arch/arm/mach-hisi/platsmp.c index 471f1ee3be2b..ecf7058d5c15 100644 --- a/arch/arm/mach-hisi/platsmp.c +++ b/arch/arm/mach-hisi/platsmp.c @@ -17,6 +17,8 @@ #include "core.h" +#define HIX5HD2_BOOT_ADDRESS 0xffff0000 + static void __iomem *ctrl_base; void hi3xxx_set_cpu_jump(int cpu, void *jump_addr) @@ -35,11 +37,9 @@ int hi3xxx_get_cpu_jump(int cpu) return readl_relaxed(ctrl_base + ((cpu - 1) << 2)); } -static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) +static void __init hisi_enable_scu_a9(void) { - struct device_node *np = NULL; unsigned long base = 0; - u32 offset = 0; void __iomem *scu_base = NULL; if (scu_a9_has_base()) { @@ -52,6 +52,14 @@ static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) scu_enable(scu_base); iounmap(scu_base); } +} + +static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) +{ + struct device_node *np = NULL; + u32 offset = 0; + + hisi_enable_scu_a9(); if (!ctrl_base) { np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); if (!np) { @@ -87,3 +95,39 @@ struct smp_operations hi3xxx_smp_ops __initdata = { .cpu_kill = hi3xxx_cpu_kill, #endif }; + +static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus) +{ + hisi_enable_scu_a9(); +} + +void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr) +{ + void __iomem *virt; + + virt = ioremap(start_addr, PAGE_SIZE); + + writel_relaxed(0xe51ff004, virt); /* ldr pc, [rc, #-4] */ + writel_relaxed(jump_addr, virt + 4); /* pc jump phy address */ + iounmap(virt); +} + +static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + phys_addr_t jumpaddr; + + jumpaddr = virt_to_phys(hix5hd2_secondary_startup); + hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); + hix5hd2_set_cpu(cpu, true); + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + return 0; +} + + +struct smp_operations hix5hd2_smp_ops __initdata = { + .smp_prepare_cpus = hix5hd2_smp_prepare_cpus, + .smp_boot_secondary = hix5hd2_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = hix5hd2_cpu_die, +#endif +}; -- cgit v1.2.3