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 | |||
22 | help | 22 | help |
23 | Support for Hisilicon Hi36xx SoC family | 23 | Support for Hisilicon Hi36xx SoC family |
24 | 24 | ||
25 | config ARCH_HIP01 | ||
26 | bool "Hisilicon HIP01 family" if ARCH_MULTI_V7 | ||
27 | select HAVE_ARM_SCU if SMP | ||
28 | select HAVE_ARM_TWD if SMP | ||
29 | select ARM_GLOBAL_TIMER | ||
30 | help | ||
31 | Support for Hisilicon HIP01 SoC family | ||
32 | |||
25 | config ARCH_HIP04 | 33 | config ARCH_HIP04 |
26 | bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7 | 34 | bool "Hisilicon HiP04 Cortex A15 family" if ARCH_MULTI_V7 |
27 | select ARM_ERRATA_798181 if SMP | 35 | 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); | |||
12 | extern int hi3xxx_cpu_kill(unsigned int cpu); | 12 | extern int hi3xxx_cpu_kill(unsigned int cpu); |
13 | extern void hi3xxx_set_cpu(int cpu, bool enable); | 13 | extern void hi3xxx_set_cpu(int cpu, bool enable); |
14 | 14 | ||
15 | extern void hix5hd2_secondary_startup(void); | 15 | extern void hisi_secondary_startup(void); |
16 | extern struct smp_operations hix5hd2_smp_ops; | 16 | extern struct smp_operations hix5hd2_smp_ops; |
17 | extern void hix5hd2_set_cpu(int cpu, bool enable); | 17 | extern void hix5hd2_set_cpu(int cpu, bool enable); |
18 | extern void hix5hd2_cpu_die(unsigned int cpu); | 18 | extern void hix5hd2_cpu_die(unsigned int cpu); |
19 | 19 | ||
20 | extern struct smp_operations hip01_smp_ops; | ||
21 | extern void hip01_set_cpu(int cpu, bool enable); | ||
22 | extern void hip01_cpu_die(unsigned int cpu); | ||
20 | #endif | 23 | #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 @@ | |||
11 | 11 | ||
12 | __CPUINIT | 12 | __CPUINIT |
13 | 13 | ||
14 | ENTRY(hix5hd2_secondary_startup) | 14 | ENTRY(hisi_secondary_startup) |
15 | bl v7_invalidate_l1 | 15 | bl v7_invalidate_l1 |
16 | b secondary_startup | 16 | 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 = { | |||
72 | DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)") | 72 | DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)") |
73 | .dt_compat = hip04_compat, | 73 | .dt_compat = hip04_compat, |
74 | MACHINE_END | 74 | MACHINE_END |
75 | |||
76 | static const char *hip01_compat[] __initconst = { | ||
77 | "hisilicon,hip01", | ||
78 | "hisilicon,hip01-ca9x2", | ||
79 | NULL, | ||
80 | }; | ||
81 | |||
82 | DT_MACHINE_START(HIP01, "Hisilicon HIP01 (Flattened Device Tree)") | ||
83 | .dt_compat = hip01_compat, | ||
84 | 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 @@ | |||
65 | #define PMC0_CPU1_PMC_ENABLE (1 << 7) | 65 | #define PMC0_CPU1_PMC_ENABLE (1 << 7) |
66 | #define PMC0_CPU1_POWERDOWN (1 << 3) | 66 | #define PMC0_CPU1_POWERDOWN (1 << 3) |
67 | 67 | ||
68 | #define HIP01_PERI9 0x50 | ||
69 | #define PERI9_CPU1_RESET (1 << 1) | ||
70 | |||
68 | enum { | 71 | enum { |
69 | HI3620_CTRL, | 72 | HI3620_CTRL, |
70 | ERROR_CTRL, | 73 | ERROR_CTRL, |
@@ -209,6 +212,34 @@ void hix5hd2_set_cpu(int cpu, bool enable) | |||
209 | } | 212 | } |
210 | } | 213 | } |
211 | 214 | ||
215 | void hip01_set_cpu(int cpu, bool enable) | ||
216 | { | ||
217 | unsigned int temp; | ||
218 | struct device_node *np; | ||
219 | |||
220 | if (!ctrl_base) { | ||
221 | np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl"); | ||
222 | if (np) | ||
223 | ctrl_base = of_iomap(np, 0); | ||
224 | else | ||
225 | BUG(); | ||
226 | } | ||
227 | |||
228 | if (enable) { | ||
229 | /* reset on CPU1 */ | ||
230 | temp = readl_relaxed(ctrl_base + HIP01_PERI9); | ||
231 | temp |= PERI9_CPU1_RESET; | ||
232 | writel_relaxed(temp, ctrl_base + HIP01_PERI9); | ||
233 | |||
234 | udelay(50); | ||
235 | |||
236 | /* unreset on CPU1 */ | ||
237 | temp = readl_relaxed(ctrl_base + HIP01_PERI9); | ||
238 | temp &= ~PERI9_CPU1_RESET; | ||
239 | writel_relaxed(temp, ctrl_base + HIP01_PERI9); | ||
240 | } | ||
241 | } | ||
242 | |||
212 | static inline void cpu_enter_lowpower(void) | 243 | static inline void cpu_enter_lowpower(void) |
213 | { | 244 | { |
214 | unsigned int v; | 245 | 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 @@ | |||
10 | #include <linux/smp.h> | 10 | #include <linux/smp.h> |
11 | #include <linux/io.h> | 11 | #include <linux/io.h> |
12 | #include <linux/of_address.h> | 12 | #include <linux/of_address.h> |
13 | #include <linux/delay.h> | ||
13 | 14 | ||
14 | #include <asm/cacheflush.h> | 15 | #include <asm/cacheflush.h> |
15 | #include <asm/smp_plat.h> | 16 | #include <asm/smp_plat.h> |
16 | #include <asm/smp_scu.h> | 17 | #include <asm/smp_scu.h> |
18 | #include <asm/mach/map.h> | ||
17 | 19 | ||
18 | #include "core.h" | 20 | #include "core.h" |
19 | 21 | ||
@@ -96,7 +98,7 @@ struct smp_operations hi3xxx_smp_ops __initdata = { | |||
96 | #endif | 98 | #endif |
97 | }; | 99 | }; |
98 | 100 | ||
99 | static void __init hix5hd2_smp_prepare_cpus(unsigned int max_cpus) | 101 | static void __init hisi_common_smp_prepare_cpus(unsigned int max_cpus) |
100 | { | 102 | { |
101 | hisi_enable_scu_a9(); | 103 | hisi_enable_scu_a9(); |
102 | } | 104 | } |
@@ -116,7 +118,7 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
116 | { | 118 | { |
117 | phys_addr_t jumpaddr; | 119 | phys_addr_t jumpaddr; |
118 | 120 | ||
119 | jumpaddr = virt_to_phys(hix5hd2_secondary_startup); | 121 | jumpaddr = virt_to_phys(hisi_secondary_startup); |
120 | hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); | 122 | hix5hd2_set_scu_boot_addr(HIX5HD2_BOOT_ADDRESS, jumpaddr); |
121 | hix5hd2_set_cpu(cpu, true); | 123 | hix5hd2_set_cpu(cpu, true); |
122 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); | 124 | arch_send_wakeup_ipi_mask(cpumask_of(cpu)); |
@@ -125,12 +127,60 @@ static int hix5hd2_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
125 | 127 | ||
126 | 128 | ||
127 | struct smp_operations hix5hd2_smp_ops __initdata = { | 129 | struct smp_operations hix5hd2_smp_ops __initdata = { |
128 | .smp_prepare_cpus = hix5hd2_smp_prepare_cpus, | 130 | .smp_prepare_cpus = hisi_common_smp_prepare_cpus, |
129 | .smp_boot_secondary = hix5hd2_boot_secondary, | 131 | .smp_boot_secondary = hix5hd2_boot_secondary, |
130 | #ifdef CONFIG_HOTPLUG_CPU | 132 | #ifdef CONFIG_HOTPLUG_CPU |
131 | .cpu_die = hix5hd2_cpu_die, | 133 | .cpu_die = hix5hd2_cpu_die, |
132 | #endif | 134 | #endif |
133 | }; | 135 | }; |
134 | 136 | ||
137 | |||
138 | #define SC_SCTL_REMAP_CLR 0x00000100 | ||
139 | #define HIP01_BOOT_ADDRESS 0x80000000 | ||
140 | #define REG_SC_CTRL 0x000 | ||
141 | |||
142 | void hip01_set_boot_addr(phys_addr_t start_addr, phys_addr_t jump_addr) | ||
143 | { | ||
144 | void __iomem *virt; | ||
145 | |||
146 | virt = phys_to_virt(start_addr); | ||
147 | |||
148 | writel_relaxed(0xe51ff004, virt); | ||
149 | writel_relaxed(jump_addr, virt + 4); | ||
150 | } | ||
151 | |||
152 | static int hip01_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
153 | { | ||
154 | phys_addr_t jumpaddr; | ||
155 | unsigned int remap_reg_value = 0; | ||
156 | struct device_node *node; | ||
157 | |||
158 | |||
159 | jumpaddr = virt_to_phys(hisi_secondary_startup); | ||
160 | hip01_set_boot_addr(HIP01_BOOT_ADDRESS, jumpaddr); | ||
161 | |||
162 | node = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl"); | ||
163 | if (WARN_ON(!node)) | ||
164 | return -1; | ||
165 | ctrl_base = of_iomap(node, 0); | ||
166 | |||
167 | /* set the secondary core boot from DDR */ | ||
168 | remap_reg_value = readl_relaxed(ctrl_base + REG_SC_CTRL); | ||
169 | barrier(); | ||
170 | remap_reg_value |= SC_SCTL_REMAP_CLR; | ||
171 | barrier(); | ||
172 | writel_relaxed(remap_reg_value, ctrl_base + REG_SC_CTRL); | ||
173 | |||
174 | hip01_set_cpu(cpu, true); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | struct smp_operations hip01_smp_ops __initdata = { | ||
180 | .smp_prepare_cpus = hisi_common_smp_prepare_cpus, | ||
181 | .smp_boot_secondary = hip01_boot_secondary, | ||
182 | }; | ||
183 | |||
135 | CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops); | 184 | CPU_METHOD_OF_DECLARE(hi3xxx_smp, "hisilicon,hi3620-smp", &hi3xxx_smp_ops); |
136 | CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops); | 185 | CPU_METHOD_OF_DECLARE(hix5hd2_smp, "hisilicon,hix5hd2-smp", &hix5hd2_smp_ops); |
186 | CPU_METHOD_OF_DECLARE(hip01_smp, "hisilicon,hip01-smp", &hip01_smp_ops); | ||