diff options
Diffstat (limited to 'arch/arm/mach-hisi/platsmp.c')
-rw-r--r-- | arch/arm/mach-hisi/platsmp.c | 50 |
1 files changed, 47 insertions, 3 deletions
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 @@ | |||
17 | 17 | ||
18 | #include "core.h" | 18 | #include "core.h" |
19 | 19 | ||
20 | #define HIX5HD2_BOOT_ADDRESS 0xffff0000 | ||
21 | |||
20 | static void __iomem *ctrl_base; | 22 | static void __iomem *ctrl_base; |
21 | 23 | ||
22 | void hi3xxx_set_cpu_jump(int cpu, void *jump_addr) | 24 | void hi3xxx_set_cpu_jump(int cpu, void *jump_addr) |
@@ -35,11 +37,9 @@ int hi3xxx_get_cpu_jump(int cpu) | |||
35 | return readl_relaxed(ctrl_base + ((cpu - 1) << 2)); | 37 | return readl_relaxed(ctrl_base + ((cpu - 1) << 2)); |
36 | } | 38 | } |
37 | 39 | ||
38 | static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) | 40 | static void __init hisi_enable_scu_a9(void) |
39 | { | 41 | { |
40 | struct device_node *np = NULL; | ||
41 | unsigned long base = 0; | 42 | unsigned long base = 0; |
42 | u32 offset = 0; | ||
43 | void __iomem *scu_base = NULL; | 43 | void __iomem *scu_base = NULL; |
44 | 44 | ||
45 | if (scu_a9_has_base()) { | 45 | if (scu_a9_has_base()) { |
@@ -52,6 +52,14 @@ static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) | |||
52 | scu_enable(scu_base); | 52 | scu_enable(scu_base); |
53 | iounmap(scu_base); | 53 | iounmap(scu_base); |
54 | } | 54 | } |
55 | } | ||
56 | |||
57 | static void __init hi3xxx_smp_prepare_cpus(unsigned int max_cpus) | ||
58 | { | ||
59 | struct device_node *np = NULL; | ||
60 | u32 offset = 0; | ||
61 | |||
62 | hisi_enable_scu_a9(); | ||
55 | if (!ctrl_base) { | 63 | if (!ctrl_base) { |
56 | np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); | 64 | np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl"); |
57 | if (!np) { | 65 | if (!np) { |
@@ -87,3 +95,39 @@ struct smp_operations hi3xxx_smp_ops __initdata = { | |||
87 | .cpu_kill = hi3xxx_cpu_kill, | 95 | .cpu_kill = hi3xxx_cpu_kill, |
88 | #endif | 96 | #endif |
89 | }; | 97 | }; |
98 | |||
99 | static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus) | ||
100 | { | ||
101 | hisi_enable_scu_a9(); | ||
102 | } | ||
103 | |||
104 | void hix5hd2_set_scu_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr) | ||
105 | { | ||
106 | void __iomem *virt; | ||
107 | |||
108 | virt = ioremap(start_addr, PAGE_SIZE); | ||
109 | |||
110 | writel_relaxed(0xe51ff004, virt); /* ldr pc, [rc, #-4] */ | ||
111 | writel_relaxed(jump_addr, virt + 4); /* pc jump phy address */ | ||
112 | iounmap(virt); | ||
113 | } | ||
114 | |||
115 | static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
116 | { | ||
117 | phys_addr_t jumpaddr; | ||
118 | |||
119 | jumpaddr = virt_to_phys(hix5hd2_secondary_startup); | ||
120 | hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); | ||
121 | hix5hd2_set_cpu(cpu, true); | ||
122 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | |||
127 | struct smp_operations hix5hd2_smp_ops __initdata = { | ||
128 | .smp_prepare_cpus = hix5hd2_smp_prepare_cpus, | ||
129 | .smp_boot_secondary = hix5hd2_boot_secondary, | ||
130 | #ifdef CONFIG_HOTPLUG_CPU | ||
131 | .cpu_die = hix5hd2_cpu_die, | ||
132 | #endif | ||
133 | }; | ||