1 /*-
2 * Copyright (c) 2008-2012 Semihalf.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "opt_platform.h"
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: releng/11.0/sys/powerpc/mpc85xx/platform_mpc85xx.c 298237 2016-04-19 01:48:18Z jhibbits $");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/bus.h>
35 #include <sys/pcpu.h>
36 #include <sys/proc.h>
37 #include <sys/smp.h>
38
39 #include <machine/bus.h>
40 #include <machine/cpu.h>
41 #include <machine/hid.h>
42 #include <machine/machdep.h>
43 #include <machine/platform.h>
44 #include <machine/platformvar.h>
45 #include <machine/smp.h>
46 #include <machine/spr.h>
47 #include <machine/vmparam.h>
48
49 #include <dev/fdt/fdt_common.h>
50 #include <dev/ofw/ofw_bus.h>
51 #include <dev/ofw/ofw_bus_subr.h>
52 #include <dev/ofw/openfirm.h>
53
54 #include <vm/vm.h>
55 #include <vm/pmap.h>
56
57 #include <powerpc/mpc85xx/mpc85xx.h>
58
59 #include "platform_if.h"
60
61 #ifdef SMP
62 extern void *ap_pcpu;
63 extern vm_paddr_t kernload; /* Kernel physical load address */
64 extern uint8_t __boot_page[]; /* Boot page body */
65 extern uint32_t bp_kernload;
66 #endif
67
68 extern uint32_t *bootinfo;
69 vm_offset_t ccsrbar_va;
70
71 static int cpu, maxcpu;
72
73 static int mpc85xx_probe(platform_t);
74 static void mpc85xx_mem_regions(platform_t, struct mem_region *phys,
75 int *physsz, struct mem_region *avail, int *availsz);
76 static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref);
77 static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref);
78 static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref);
79 static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref);
80 static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu);
81 static void mpc85xx_idle(platform_t, int cpu);
82 static int mpc85xx_idle_wakeup(platform_t plat, int cpu);
83
84 static void mpc85xx_reset(platform_t);
85
86 static platform_method_t mpc85xx_methods[] = {
87 PLATFORMMETHOD(platform_probe, mpc85xx_probe),
88 PLATFORMMETHOD(platform_attach, mpc85xx_attach),
89 PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions),
90 PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq),
91
92 PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu),
93 PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu),
94 PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp),
95 PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu),
96
97 PLATFORMMETHOD(platform_reset, mpc85xx_reset),
98 PLATFORMMETHOD(platform_idle, mpc85xx_idle),
99 PLATFORMMETHOD(platform_idle_wakeup, mpc85xx_idle_wakeup),
100
101 PLATFORMMETHOD_END
102 };
103
104 DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0);
105
106 PLATFORM_DEF(mpc85xx_platform);
107
108 static int
109 mpc85xx_probe(platform_t plat)
110 {
111 u_int pvr = mfpvr() >> 16;
112
113 if ((pvr & 0xfff0) == FSL_E500v1)
114 return (BUS_PROBE_DEFAULT);
115
116 return (ENXIO);
117 }
118
119 int
120 mpc85xx_attach(platform_t plat)
121 {
122 phandle_t cpus, child, ccsr;
123 const char *soc_name_guesses[] = {"/soc", "soc", NULL};
124 const char **name;
125 pcell_t ranges[6], acells, pacells, scells;
126 uint32_t sr;
127 uint64_t ccsrbar, ccsrsize;
128 int i, law_max, tgt;
129
130 if ((cpus = OF_finddevice("/cpus")) != -1) {
131 for (maxcpu = 0, child = OF_child(cpus); child != 0;
132 child = OF_peer(child), maxcpu++)
133 ;
134 } else
135 maxcpu = 1;
136
137 /*
138 * Locate CCSR region. Irritatingly, there is no way to find it
139 * unless you already know where it is. Try to infer its location
140 * from the device tree.
141 */
142
143 ccsr = -1;
144 for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++)
145 ccsr = OF_finddevice(*name);
146 if (ccsr == -1) {
147 char type[64];
148
149 /* That didn't work. Search for devices of type "soc" */
150 child = OF_child(OF_peer(0));
151 for (OF_child(child); child != 0; child = OF_peer(child)) {
152 if (OF_getprop(child, "device_type", type, sizeof(type))
153 <= 0)
154 continue;
155
156 if (strcmp(type, "soc") == 0) {
157 ccsr = child;
158 break;
159 }
160 }
161 }
162
163 if (ccsr == -1)
164 panic("Could not locate CCSR window!");
165
166 OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells));
167 OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells));
168 OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells,
169 sizeof(pacells));
170 OF_getprop(ccsr, "ranges", ranges, sizeof(ranges));
171 ccsrbar = ccsrsize = 0;
172 for (i = acells; i < acells + pacells; i++) {
173 ccsrbar <<= 32;
174 ccsrbar |= ranges[i];
175 }
176 for (i = acells + pacells; i < acells + pacells + scells; i++) {
177 ccsrsize <<= 32;
178 ccsrsize |= ranges[i];
179 }
180 ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize);
181
182 mpc85xx_fix_errata(ccsrbar_va);
183 mpc85xx_enable_l3_cache();
184
185 /*
186 * Clear local access windows. Skip DRAM entries, so we don't shoot
187 * ourselves in the foot.
188 */
189 law_max = law_getmax();
190 for (i = 0; i < law_max; i++) {
191 sr = ccsr_read4(OCP85XX_LAWSR(i));
192 if ((sr & OCP85XX_ENA_MASK) == 0)
193 continue;
194 tgt = (sr & 0x01f00000) >> 20;
195 if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 ||
196 tgt == OCP85XX_TGTIF_RAM_INTL)
197 continue;
198
199 ccsr_write4(OCP85XX_LAWSR(i), sr & OCP85XX_DIS_MASK);
200 }
201
202 return (0);
203 }
204
205 void
206 mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
207 struct mem_region *avail, int *availsz)
208 {
209
210 ofw_mem_regions(phys, physsz, avail, availsz);
211 }
212
213 static u_long
214 mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref)
215 {
216 u_long ticks;
217 phandle_t cpus, child;
218 pcell_t freq;
219
220 if (bootinfo != NULL) {
221 if (bootinfo[0] == 1) {
222 /* Backward compatibility. See 8-STABLE. */
223 ticks = bootinfo[3] >> 3;
224 } else {
225 /* Compatibility with Juniper's loader. */
226 ticks = bootinfo[5] >> 3;
227 }
228 } else
229 ticks = 0;
230
231 if ((cpus = OF_finddevice("/cpus")) == -1)
232 goto out;
233
234 if ((child = OF_child(cpus)) == 0)
235 goto out;
236
237 switch (OF_getproplen(child, "timebase-frequency")) {
238 case 4:
239 {
240 uint32_t tbase;
241 OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
242 ticks = tbase;
243 return (ticks);
244 }
245 case 8:
246 {
247 uint64_t tbase;
248 OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
249 ticks = tbase;
250 return (ticks);
251 }
252 default:
253 break;
254 }
255
256 freq = 0;
257 if (OF_getprop(child, "bus-frequency", (void *)&freq,
258 sizeof(freq)) <= 0)
259 goto out;
260
261 /*
262 * Time Base and Decrementer are updated every 8 CCB bus clocks.
263 * HID0[SEL_TBCLK] = 0
264 */
265 if (freq != 0)
266 #ifdef QORIQ_DPAA
267 ticks = freq / 32;
268 #else
269 ticks = freq / 8;
270 #endif
271
272 out:
273 if (ticks <= 0)
274 panic("Unable to determine timebase frequency!");
275
276 return (ticks);
277 }
278
279 static int
280 mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
281 {
282
283 cpu = 0;
284 cpuref->cr_cpuid = cpu;
285 cpuref->cr_hwref = cpuref->cr_cpuid;
286 if (bootverbose)
287 printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid);
288 cpu++;
289
290 return (0);
291 }
292
293 static int
294 mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
295 {
296
297 if (cpu >= maxcpu)
298 return (ENOENT);
299
300 cpuref->cr_cpuid = cpu++;
301 cpuref->cr_hwref = cpuref->cr_cpuid;
302 if (bootverbose)
303 printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid);
304
305 return (0);
306 }
307
308 static int
309 mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
310 {
311
312 cpuref->cr_cpuid = mfspr(SPR_PIR);
313 cpuref->cr_hwref = cpuref->cr_cpuid;
314
315 return (0);
316 }
317
318 static int
319 mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc)
320 {
321 #ifdef SMP
322 vm_paddr_t bptr;
323 uint32_t reg;
324 int timeout;
325 uintptr_t brr;
326 int cpuid;
327
328 #ifdef QORIQ_DPAA
329 uint32_t tgt;
330
331 reg = ccsr_read4(OCP85XX_COREDISR);
332 cpuid = pc->pc_cpuid;
333
334 if ((reg & cpuid) != 0) {
335 printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid);
336 return (-1);
337 }
338
339 brr = OCP85XX_BRR;
340 #else /* QORIQ_DPAA */
341 brr = OCP85XX_EEBPCR;
342 cpuid = pc->pc_cpuid + 24;
343 #endif
344 bp_kernload = kernload;
345 reg = ccsr_read4(brr);
346 if ((reg & (1 << cpuid)) != 0) {
347 printf("SMP: CPU %d already out of hold-off state!\n",
348 pc->pc_cpuid);
349 return (ENXIO);
350 }
351
352 ap_pcpu = pc;
353 __asm __volatile("msync; isync");
354
355 /* Flush caches to have our changes hit DRAM. */
356 cpu_flush_dcache(__boot_page, 4096);
357
358 bptr = ((vm_paddr_t)(uintptr_t)__boot_page - KERNBASE) + kernload;
359 KASSERT((bptr & 0xfff) == 0,
360 ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr));
361 #ifdef QORIQ_DPAA
362
363 /*
364 * Read DDR controller configuration to select proper BPTR target ID.
365 *
366 * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers
367 * interleaving. If this bit is set, we have to use
368 * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs,
369 * this bit is reserved and always 0.
370 */
371
372 reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG);
373 if (reg & (1 << 29))
374 tgt = OCP85XX_TGTIF_RAM_INTL;
375 else
376 tgt = OCP85XX_TGTIF_RAM1;
377
378 /*
379 * Set BSTR to the physical address of the boot page
380 */
381 ccsr_write4(OCP85XX_BSTRH, bptr >> 32);
382 ccsr_write4(OCP85XX_BSTRL, bptr);
383 ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK |
384 (tgt << OCP85XX_TRGT_SHIFT) | (ffsl(PAGE_SIZE) - 2));
385
386 /* Read back OCP85XX_BSTAR to synchronize write */
387 ccsr_read4(OCP85XX_BSTAR);
388
389 /*
390 * Enable and configure time base on new CPU.
391 */
392
393 /* Set TB clock source to platform clock / 32 */
394 reg = ccsr_read4(CCSR_CTBCKSELR);
395 ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid));
396
397 /* Enable TB */
398 reg = ccsr_read4(CCSR_CTBENR);
399 ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid));
400 #else
401
402 /*
403 * Set BPTR to the physical address of the boot page
404 */
405 bptr = (bptr >> 12) | 0x80000000u;
406 ccsr_write4(OCP85XX_BPTR, bptr);
407 __asm __volatile("isync; msync");
408
409 #endif /* QORIQ_DPAA */
410
411 /*
412 * Release AP from hold-off state
413 */
414 reg = ccsr_read4(brr);
415 ccsr_write4(brr, reg | (1 << cpuid));
416 __asm __volatile("isync; msync");
417
418 timeout = 500;
419 while (!pc->pc_awake && timeout--)
420 DELAY(1000); /* wait 1ms */
421
422 /*
423 * Disable boot page translation so that the 4K page at the default
424 * address (= 0xfffff000) isn't permanently remapped and thus not
425 * usable otherwise.
426 */
427 #ifdef QORIQ_DPAA
428 ccsr_write4(OCP85XX_BSTAR, 0);
429 #else
430 ccsr_write4(OCP85XX_BPTR, 0);
431 #endif
432 __asm __volatile("isync; msync");
433
434 if (!pc->pc_awake)
435 printf("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid);
436 return ((pc->pc_awake) ? 0 : EBUSY);
437 #else
438 /* No SMP support */
439 return (ENXIO);
440 #endif
441 }
442
443 static void
444 mpc85xx_reset(platform_t plat)
445 {
446
447 /*
448 * Try the dedicated reset register first.
449 * If the SoC doesn't have one, we'll fall
450 * back to using the debug control register.
451 */
452 ccsr_write4(OCP85XX_RSTCR, 2);
453
454 /* Clear DBCR0, disables debug interrupts and events. */
455 mtspr(SPR_DBCR0, 0);
456 __asm __volatile("isync");
457
458 /* Enable Debug Interrupts in MSR. */
459 mtmsr(mfmsr() | PSL_DE);
460
461 /* Enable debug interrupts and issue reset. */
462 mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM);
463
464 printf("Reset failed...\n");
465 while (1)
466 ;
467 }
468
469 static void
470 mpc85xx_idle(platform_t plat, int cpu)
471 {
472 #ifdef QORIQ_DPAA
473 uint32_t reg;
474
475 reg = ccsr_read4(OCP85XX_RCPM_CDOZCR);
476 ccsr_write4(OCP85XX_RCPM_CDOZCR, reg | (1 << cpu));
477 ccsr_read4(OCP85XX_RCPM_CDOZCR);
478 #else
479 register_t msr;
480
481 msr = mfmsr();
482 /* Freescale E500 core RM section 6.4.1. */
483 __asm __volatile("msync; mtmsr %0; isync" ::
484 "r" (msr | PSL_WE));
485 #endif
486 }
487
488 static int
489 mpc85xx_idle_wakeup(platform_t plat, int cpu)
490 {
491 #ifdef QORIQ_DPAA
492 uint32_t reg;
493
494 reg = ccsr_read4(OCP85XX_RCPM_CDOZCR);
495 ccsr_write4(OCP85XX_RCPM_CDOZCR, reg & ~(1 << cpu));
496 ccsr_read4(OCP85XX_RCPM_CDOZCR);
497
498 return (1);
499 #endif
500 return (0);
501 }
Cache object: 8a6f991b755c538114ca38eed559f7e8
|