diff options
author | Rohit Vaswani <rvaswani@codeaurora.org> | 2013-06-21 20:09:13 -0400 |
---|---|---|
committer | Kumar Gala <galak@codeaurora.org> | 2014-02-11 16:00:40 -0500 |
commit | 6990c132abc984bd6e75ac2be1f1d657cd600f63 (patch) | |
tree | 4f9b54c9573b2c0f6008eb4b362b3dbef076fe92 /arch/arm/mach-qcom | |
parent | 6267809f1660cdd72fbb1032ab566facb12a3193 (diff) |
ARM: qcom: Add SMP support for KPSSv2
Implement support for the Krait CPU release sequence when the
CPUs are part of the second version of the Krait processor
subsystem.
Signed-off-by: Rohit Vaswani <rvaswani@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Kumar Gala <galak@codeaurora.org>
Diffstat (limited to 'arch/arm/mach-qcom')
-rw-r--r-- | arch/arm/mach-qcom/platsmp.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c index cb0783f3ed75..d6908569ecaf 100644 --- a/arch/arm/mach-qcom/platsmp.c +++ b/arch/arm/mach-qcom/platsmp.c | |||
@@ -34,7 +34,15 @@ | |||
34 | #define L2DT_SLP BIT(3) | 34 | #define L2DT_SLP BIT(3) |
35 | #define CLAMP BIT(0) | 35 | #define CLAMP BIT(0) |
36 | 36 | ||
37 | #define APC_PWR_GATE_CTL 0x14 | ||
38 | #define BHS_CNT_SHIFT 24 | ||
39 | #define LDO_PWR_DWN_SHIFT 16 | ||
40 | #define LDO_BYP_SHIFT 8 | ||
41 | #define BHS_SEG_SHIFT 1 | ||
42 | #define BHS_EN BIT(0) | ||
43 | |||
37 | #define APCS_SAW2_VCTL 0x14 | 44 | #define APCS_SAW2_VCTL 0x14 |
45 | #define APCS_SAW2_2_VCTL 0x1c | ||
38 | 46 | ||
39 | extern void secondary_startup(void); | 47 | extern void secondary_startup(void); |
40 | 48 | ||
@@ -160,6 +168,106 @@ out_acc: | |||
160 | return ret; | 168 | return ret; |
161 | } | 169 | } |
162 | 170 | ||
171 | static int kpssv2_release_secondary(unsigned int cpu) | ||
172 | { | ||
173 | void __iomem *reg; | ||
174 | struct device_node *cpu_node, *l2_node, *acc_node, *saw_node; | ||
175 | void __iomem *l2_saw_base; | ||
176 | unsigned reg_val; | ||
177 | int ret; | ||
178 | |||
179 | cpu_node = of_get_cpu_node(cpu, NULL); | ||
180 | if (!cpu_node) | ||
181 | return -ENODEV; | ||
182 | |||
183 | acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); | ||
184 | if (!acc_node) { | ||
185 | ret = -ENODEV; | ||
186 | goto out_acc; | ||
187 | } | ||
188 | |||
189 | l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0); | ||
190 | if (!l2_node) { | ||
191 | ret = -ENODEV; | ||
192 | goto out_l2; | ||
193 | } | ||
194 | |||
195 | saw_node = of_parse_phandle(l2_node, "qcom,saw", 0); | ||
196 | if (!saw_node) { | ||
197 | ret = -ENODEV; | ||
198 | goto out_saw; | ||
199 | } | ||
200 | |||
201 | reg = of_iomap(acc_node, 0); | ||
202 | if (!reg) { | ||
203 | ret = -ENOMEM; | ||
204 | goto out_map; | ||
205 | } | ||
206 | |||
207 | l2_saw_base = of_iomap(saw_node, 0); | ||
208 | if (!l2_saw_base) { | ||
209 | ret = -ENOMEM; | ||
210 | goto out_saw_map; | ||
211 | } | ||
212 | |||
213 | /* Turn on the BHS, turn off LDO Bypass and power down LDO */ | ||
214 | reg_val = (64 << BHS_CNT_SHIFT) | (0x3f << LDO_PWR_DWN_SHIFT) | BHS_EN; | ||
215 | writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); | ||
216 | mb(); | ||
217 | /* wait for the BHS to settle */ | ||
218 | udelay(1); | ||
219 | |||
220 | /* Turn on BHS segments */ | ||
221 | reg_val |= 0x3f << BHS_SEG_SHIFT; | ||
222 | writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); | ||
223 | mb(); | ||
224 | /* wait for the BHS to settle */ | ||
225 | udelay(1); | ||
226 | |||
227 | /* Finally turn on the bypass so that BHS supplies power */ | ||
228 | reg_val |= 0x3f << LDO_BYP_SHIFT; | ||
229 | writel_relaxed(reg_val, reg + APC_PWR_GATE_CTL); | ||
230 | |||
231 | /* enable max phases */ | ||
232 | writel_relaxed(0x10003, l2_saw_base + APCS_SAW2_2_VCTL); | ||
233 | mb(); | ||
234 | udelay(50); | ||
235 | |||
236 | reg_val = COREPOR_RST | CLAMP; | ||
237 | writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); | ||
238 | mb(); | ||
239 | udelay(2); | ||
240 | |||
241 | reg_val &= ~CLAMP; | ||
242 | writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); | ||
243 | mb(); | ||
244 | udelay(2); | ||
245 | |||
246 | reg_val &= ~COREPOR_RST; | ||
247 | writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); | ||
248 | mb(); | ||
249 | |||
250 | reg_val |= CORE_PWRD_UP; | ||
251 | writel_relaxed(reg_val, reg + APCS_CPU_PWR_CTL); | ||
252 | mb(); | ||
253 | |||
254 | ret = 0; | ||
255 | |||
256 | iounmap(l2_saw_base); | ||
257 | out_saw_map: | ||
258 | iounmap(reg); | ||
259 | out_map: | ||
260 | of_node_put(saw_node); | ||
261 | out_saw: | ||
262 | of_node_put(l2_node); | ||
263 | out_l2: | ||
264 | of_node_put(acc_node); | ||
265 | out_acc: | ||
266 | of_node_put(cpu_node); | ||
267 | |||
268 | return ret; | ||
269 | } | ||
270 | |||
163 | static DEFINE_PER_CPU(int, cold_boot_done); | 271 | static DEFINE_PER_CPU(int, cold_boot_done); |
164 | 272 | ||
165 | static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) | 273 | static int qcom_boot_secondary(unsigned int cpu, int (*func)(unsigned int)) |
@@ -204,6 +312,11 @@ static int kpssv1_boot_secondary(unsigned int cpu, struct task_struct *idle) | |||
204 | return qcom_boot_secondary(cpu, kpssv1_release_secondary); | 312 | return qcom_boot_secondary(cpu, kpssv1_release_secondary); |
205 | } | 313 | } |
206 | 314 | ||
315 | static int kpssv2_boot_secondary(unsigned int cpu, struct task_struct *idle) | ||
316 | { | ||
317 | return qcom_boot_secondary(cpu, kpssv2_release_secondary); | ||
318 | } | ||
319 | |||
207 | static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) | 320 | static void __init qcom_smp_prepare_cpus(unsigned int max_cpus) |
208 | { | 321 | { |
209 | int cpu, map; | 322 | int cpu, map; |
@@ -253,3 +366,13 @@ static struct smp_operations qcom_smp_kpssv1_ops __initdata = { | |||
253 | #endif | 366 | #endif |
254 | }; | 367 | }; |
255 | CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops); | 368 | CPU_METHOD_OF_DECLARE(qcom_smp_kpssv1, "qcom,kpss-acc-v1", &qcom_smp_kpssv1_ops); |
369 | |||
370 | static struct smp_operations qcom_smp_kpssv2_ops __initdata = { | ||
371 | .smp_prepare_cpus = qcom_smp_prepare_cpus, | ||
372 | .smp_secondary_init = qcom_secondary_init, | ||
373 | .smp_boot_secondary = kpssv2_boot_secondary, | ||
374 | #ifdef CONFIG_HOTPLUG_CPU | ||
375 | .cpu_die = qcom_cpu_die, | ||
376 | #endif | ||
377 | }; | ||
378 | CPU_METHOD_OF_DECLARE(qcom_smp_kpssv2, "qcom,kpss-acc-v2", &qcom_smp_kpssv2_ops); | ||