1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/stddef.h>
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/of.h>
18#include <linux/kexec.h>
19#include <linux/highmem.h>
20#include <linux/cpu.h>
21
22#include <asm/machdep.h>
23#include <asm/pgtable.h>
24#include <asm/page.h>
25#include <asm/mpic.h>
26#include <asm/cacheflush.h>
27#include <asm/dbell.h>
28#include <asm/fsl_guts.h>
29
30#include <sysdev/fsl_soc.h>
31#include <sysdev/mpic.h>
32#include "smp.h"
33
34struct epapr_spin_table {
35 u32 addr_h;
36 u32 addr_l;
37 u32 r3_h;
38 u32 r3_l;
39 u32 reserved;
40 u32 pir;
41};
42
43static struct ccsr_guts __iomem *guts;
44static u64 timebase;
45static int tb_req;
46static int tb_valid;
47
48static void mpc85xx_timebase_freeze(int freeze)
49{
50 uint32_t mask;
51
52 mask = CCSR_GUTS_DEVDISR_TB0 | CCSR_GUTS_DEVDISR_TB1;
53 if (freeze)
54 setbits32(&guts->devdisr, mask);
55 else
56 clrbits32(&guts->devdisr, mask);
57
58 in_be32(&guts->devdisr);
59}
60
61static void mpc85xx_give_timebase(void)
62{
63 unsigned long flags;
64
65 local_irq_save(flags);
66
67 while (!tb_req)
68 barrier();
69 tb_req = 0;
70
71 mpc85xx_timebase_freeze(1);
72 timebase = get_tb();
73 mb();
74 tb_valid = 1;
75
76 while (tb_valid)
77 barrier();
78
79 mpc85xx_timebase_freeze(0);
80
81 local_irq_restore(flags);
82}
83
84static void mpc85xx_take_timebase(void)
85{
86 unsigned long flags;
87
88 local_irq_save(flags);
89
90 tb_req = 1;
91 while (!tb_valid)
92 barrier();
93
94 set_tb(timebase >> 32, timebase & 0xffffffff);
95 isync();
96 tb_valid = 0;
97
98 local_irq_restore(flags);
99}
100
101#ifdef CONFIG_HOTPLUG_CPU
102static void __cpuinit smp_85xx_mach_cpu_die(void)
103{
104 unsigned int cpu = smp_processor_id();
105 u32 tmp;
106
107 local_irq_disable();
108 idle_task_exit();
109 generic_set_cpu_dead(cpu);
110 mb();
111
112 mtspr(SPRN_TCR, 0);
113
114 __flush_disable_L1();
115 tmp = (mfspr(SPRN_HID0) & ~(HID0_DOZE|HID0_SLEEP)) | HID0_NAP;
116 mtspr(SPRN_HID0, tmp);
117 isync();
118
119
120 tmp = mfmsr();
121 tmp |= MSR_WE;
122 mb();
123 mtmsr(tmp);
124 isync();
125
126 while (1)
127 ;
128}
129#endif
130
131static inline void flush_spin_table(void *spin_table)
132{
133 flush_dcache_range((ulong)spin_table,
134 (ulong)spin_table + sizeof(struct epapr_spin_table));
135}
136
137static inline u32 read_spin_table_addr_l(void *spin_table)
138{
139 flush_dcache_range((ulong)spin_table,
140 (ulong)spin_table + sizeof(struct epapr_spin_table));
141 return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l);
142}
143
144static int __cpuinit smp_85xx_kick_cpu(int nr)
145{
146 unsigned long flags;
147 const u64 *cpu_rel_addr;
148 __iomem struct epapr_spin_table *spin_table;
149 struct device_node *np;
150 int hw_cpu = get_hard_smp_processor_id(nr);
151 int ioremappable;
152 int ret = 0;
153
154 WARN_ON(nr < 0 || nr >= NR_CPUS);
155 WARN_ON(hw_cpu < 0 || hw_cpu >= NR_CPUS);
156
157 pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr);
158
159 np = of_get_cpu_node(nr, NULL);
160 cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL);
161
162 if (cpu_rel_addr == NULL) {
163 printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr);
164 return -ENOENT;
165 }
166
167
168
169
170
171
172
173 ioremappable = *cpu_rel_addr > virt_to_phys(high_memory);
174
175
176 if (ioremappable)
177 spin_table = ioremap_prot(*cpu_rel_addr,
178 sizeof(struct epapr_spin_table), _PAGE_COHERENT);
179 else
180 spin_table = phys_to_virt(*cpu_rel_addr);
181
182 local_irq_save(flags);
183#ifdef CONFIG_PPC32
184#ifdef CONFIG_HOTPLUG_CPU
185
186 generic_set_cpu_up(nr);
187
188 if (system_state == SYSTEM_RUNNING) {
189
190
191
192
193
194
195
196 flush_spin_table(spin_table);
197 out_be32(&spin_table->addr_l, 0);
198 flush_spin_table(spin_table);
199
200
201
202
203
204 mpic_reset_core(hw_cpu);
205
206
207
208
209
210
211 if (!spin_event_timeout(
212 read_spin_table_addr_l(spin_table) == 1,
213 10000, 100)) {
214 pr_err("%s: timeout waiting for core %d to reset\n",
215 __func__, hw_cpu);
216 ret = -ENOENT;
217 goto out;
218 }
219
220
221 __secondary_hold_acknowledge = -1;
222 }
223#endif
224 flush_spin_table(spin_table);
225 out_be32(&spin_table->pir, hw_cpu);
226 out_be32(&spin_table->addr_l, __pa(__early_start));
227 flush_spin_table(spin_table);
228
229
230 if (!spin_event_timeout(__secondary_hold_acknowledge == hw_cpu,
231 10000, 100)) {
232 pr_err("%s: timeout waiting for core %d to ack\n",
233 __func__, hw_cpu);
234 ret = -ENOENT;
235 goto out;
236 }
237out:
238#else
239 smp_generic_kick_cpu(nr);
240
241 flush_spin_table(spin_table);
242 out_be32(&spin_table->pir, hw_cpu);
243 out_be64((u64 *)(&spin_table->addr_h),
244 __pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
245 flush_spin_table(spin_table);
246#endif
247
248 local_irq_restore(flags);
249
250 if (ioremappable)
251 iounmap(spin_table);
252
253 return ret;
254}
255
256struct smp_ops_t smp_85xx_ops = {
257 .kick_cpu = smp_85xx_kick_cpu,
258#ifdef CONFIG_HOTPLUG_CPU
259 .cpu_disable = generic_cpu_disable,
260 .cpu_die = generic_cpu_die,
261#endif
262#ifdef CONFIG_KEXEC
263 .give_timebase = smp_generic_give_timebase,
264 .take_timebase = smp_generic_take_timebase,
265#endif
266};
267
268#ifdef CONFIG_KEXEC
269atomic_t kexec_down_cpus = ATOMIC_INIT(0);
270
271void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
272{
273 local_irq_disable();
274
275 if (secondary) {
276 atomic_inc(&kexec_down_cpus);
277
278 while (1);
279 }
280}
281
282static void mpc85xx_smp_kexec_down(void *arg)
283{
284 if (ppc_md.kexec_cpu_down)
285 ppc_md.kexec_cpu_down(0,1);
286}
287
288static void map_and_flush(unsigned long paddr)
289{
290 struct page *page = pfn_to_page(paddr >> PAGE_SHIFT);
291 unsigned long kaddr = (unsigned long)kmap(page);
292
293 flush_dcache_range(kaddr, kaddr + PAGE_SIZE);
294 kunmap(page);
295}
296
297
298
299
300
301
302
303static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image)
304{
305 kimage_entry_t *ptr, entry;
306 unsigned long paddr;
307 int i;
308
309 if (image->type == KEXEC_TYPE_DEFAULT) {
310
311 for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
312 ptr = (entry & IND_INDIRECTION) ?
313 phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
314 if (!(entry & IND_DESTINATION)) {
315 map_and_flush(entry);
316 }
317 }
318
319 map_and_flush(entry);
320 } else {
321
322 for (i = 0; i < image->nr_segments; i++) {
323 struct kexec_segment *seg = &image->segment[i];
324 for (paddr = seg->mem; paddr < seg->mem + seg->memsz;
325 paddr += PAGE_SIZE) {
326 map_and_flush(paddr);
327 }
328 }
329 }
330
331
332 flush_dcache_range((unsigned long)image,
333 (unsigned long)image + sizeof(*image));
334}
335
336static void mpc85xx_smp_machine_kexec(struct kimage *image)
337{
338 int timeout = INT_MAX;
339 int i, num_cpus = num_present_cpus();
340
341 mpc85xx_smp_flush_dcache_kexec(image);
342
343 if (image->type == KEXEC_TYPE_DEFAULT)
344 smp_call_function(mpc85xx_smp_kexec_down, NULL, 0);
345
346 while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) &&
347 ( timeout > 0 ) )
348 {
349 timeout--;
350 }
351
352 if ( !timeout )
353 printk(KERN_ERR "Unable to bring down secondary cpu(s)");
354
355 for_each_online_cpu(i)
356 {
357 if ( i == smp_processor_id() ) continue;
358 mpic_reset_core(i);
359 }
360
361 default_machine_kexec(image);
362}
363#endif
364
365static void __cpuinit smp_85xx_setup_cpu(int cpu_nr)
366{
367 if (smp_85xx_ops.probe == smp_mpic_probe)
368 mpic_setup_this_cpu();
369
370 if (cpu_has_feature(CPU_FTR_DBELL))
371 doorbell_setup_this_cpu();
372}
373
374static const struct of_device_id mpc85xx_smp_guts_ids[] = {
375 { .compatible = "fsl,mpc8572-guts", },
376 { .compatible = "fsl,p1020-guts", },
377 { .compatible = "fsl,p1021-guts", },
378 { .compatible = "fsl,p1022-guts", },
379 { .compatible = "fsl,p1023-guts", },
380 { .compatible = "fsl,p2020-guts", },
381 {},
382};
383
384void __init mpc85xx_smp_init(void)
385{
386 struct device_node *np;
387
388 smp_85xx_ops.setup_cpu = smp_85xx_setup_cpu;
389
390 np = of_find_node_by_type(NULL, "open-pic");
391 if (np) {
392 smp_85xx_ops.probe = smp_mpic_probe;
393 smp_85xx_ops.message_pass = smp_mpic_message_pass;
394 }
395
396 if (cpu_has_feature(CPU_FTR_DBELL)) {
397
398
399
400
401 smp_85xx_ops.message_pass = NULL;
402 smp_85xx_ops.cause_ipi = doorbell_cause_ipi;
403 }
404
405 np = of_find_matching_node(NULL, mpc85xx_smp_guts_ids);
406 if (np) {
407 guts = of_iomap(np, 0);
408 of_node_put(np);
409 if (!guts) {
410 pr_err("%s: Could not map guts node address\n",
411 __func__);
412 return;
413 }
414 smp_85xx_ops.give_timebase = mpc85xx_give_timebase;
415 smp_85xx_ops.take_timebase = mpc85xx_take_timebase;
416#ifdef CONFIG_HOTPLUG_CPU
417 ppc_md.cpu_die = smp_85xx_mach_cpu_die;
418#endif
419 }
420
421 smp_ops = &smp_85xx_ops;
422
423#ifdef CONFIG_KEXEC
424 ppc_md.kexec_cpu_down = mpc85xx_smp_kexec_cpu_down;
425 ppc_md.machine_kexec = mpc85xx_smp_machine_kexec;
426#endif
427}
428