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$"); 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/_inttypes.h> 43 #include <machine/machdep.h> 44 #include <machine/md_var.h> 45 #include <machine/platform.h> 46 #include <machine/platformvar.h> 47 #include <machine/smp.h> 48 #include <machine/spr.h> 49 #include <machine/vmparam.h> 50 51 #include <dev/fdt/fdt_common.h> 52 #include <dev/ofw/ofw_bus.h> 53 #include <dev/ofw/ofw_bus_subr.h> 54 #include <dev/ofw/openfirm.h> 55 56 #include <vm/vm.h> 57 #include <vm/pmap.h> 58 #include <vm/vm_extern.h> 59 60 #include <powerpc/mpc85xx/mpc85xx.h> 61 62 #include "platform_if.h" 63 64 #ifdef SMP 65 extern void *ap_pcpu; 66 extern vm_paddr_t kernload; /* Kernel physical load address */ 67 extern uint8_t __boot_page[]; /* Boot page body */ 68 extern uint32_t bp_kernload; 69 70 struct cpu_release { 71 uint32_t entry_h; 72 uint32_t entry_l; 73 uint32_t r3_h; 74 uint32_t r3_l; 75 uint32_t reserved; 76 uint32_t pir; 77 }; 78 #endif 79 80 extern uint32_t *bootinfo; 81 vm_paddr_t ccsrbar_pa; 82 vm_offset_t ccsrbar_va; 83 vm_size_t ccsrbar_size; 84 85 static int cpu, maxcpu; 86 87 static int mpc85xx_probe(platform_t); 88 static void mpc85xx_mem_regions(platform_t, struct mem_region *phys, 89 int *physsz, struct mem_region *avail, int *availsz); 90 static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref); 91 static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref); 92 static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref); 93 static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref); 94 static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu); 95 static void mpc85xx_idle(platform_t, int cpu); 96 static int mpc85xx_idle_wakeup(platform_t plat, int cpu); 97 98 static void mpc85xx_reset(platform_t); 99 100 static platform_method_t mpc85xx_methods[] = { 101 PLATFORMMETHOD(platform_probe, mpc85xx_probe), 102 PLATFORMMETHOD(platform_attach, mpc85xx_attach), 103 PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions), 104 PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq), 105 106 PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu), 107 PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu), 108 PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp), 109 PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), 110 111 PLATFORMMETHOD(platform_reset, mpc85xx_reset), 112 PLATFORMMETHOD(platform_idle, mpc85xx_idle), 113 PLATFORMMETHOD(platform_idle_wakeup, mpc85xx_idle_wakeup), 114 115 PLATFORMMETHOD_END 116 }; 117 118 DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0); 119 120 PLATFORM_DEF(mpc85xx_platform); 121 122 static int 123 mpc85xx_probe(platform_t plat) 124 { 125 u_int pvr = (mfpvr() >> 16) & 0xFFFF; 126 127 switch (pvr) { 128 case FSL_E500v1: 129 case FSL_E500v2: 130 case FSL_E500mc: 131 case FSL_E5500: 132 case FSL_E6500: 133 return (BUS_PROBE_DEFAULT); 134 } 135 return (ENXIO); 136 } 137 138 int 139 mpc85xx_attach(platform_t plat) 140 { 141 phandle_t cpus, child, ccsr; 142 const char *soc_name_guesses[] = {"/soc", "soc", NULL}; 143 const char **name; 144 pcell_t ranges[6], acells, pacells, scells; 145 uint64_t ccsrbar, ccsrsize; 146 int i; 147 148 if ((cpus = OF_finddevice("/cpus")) != -1) { 149 for (maxcpu = 0, child = OF_child(cpus); child != 0; 150 child = OF_peer(child), maxcpu++) 151 ; 152 } else 153 maxcpu = 1; 154 155 /* 156 * Locate CCSR region. Irritatingly, there is no way to find it 157 * unless you already know where it is. Try to infer its location 158 * from the device tree. 159 */ 160 161 ccsr = -1; 162 for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++) 163 ccsr = OF_finddevice(*name); 164 if (ccsr == -1) { 165 char type[64]; 166 167 /* That didn't work. Search for devices of type "soc" */ 168 child = OF_child(OF_peer(0)); 169 for (OF_child(child); child != 0; child = OF_peer(child)) { 170 if (OF_getprop(child, "device_type", type, sizeof(type)) 171 <= 0) 172 continue; 173 174 if (strcmp(type, "soc") == 0) { 175 ccsr = child; 176 break; 177 } 178 } 179 } 180 181 if (ccsr == -1) 182 panic("Could not locate CCSR window!"); 183 184 OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells)); 185 OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells)); 186 OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells, 187 sizeof(pacells)); 188 OF_getprop(ccsr, "ranges", ranges, sizeof(ranges)); 189 ccsrbar = ccsrsize = 0; 190 for (i = acells; i < acells + pacells; i++) { 191 ccsrbar <<= 32; 192 ccsrbar |= ranges[i]; 193 } 194 for (i = acells + pacells; i < acells + pacells + scells; i++) { 195 ccsrsize <<= 32; 196 ccsrsize |= ranges[i]; 197 } 198 ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); 199 ccsrbar_pa = ccsrbar; 200 ccsrbar_size = ccsrsize; 201 202 #if 0 203 mpc85xx_fix_errata(ccsrbar_va); 204 #endif 205 mpc85xx_enable_l3_cache(); 206 207 return (0); 208 } 209 210 void 211 mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 212 struct mem_region *avail, int *availsz) 213 { 214 215 ofw_mem_regions(phys, physsz, avail, availsz); 216 } 217 218 static u_long 219 mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) 220 { 221 u_long ticks; 222 phandle_t cpus, child; 223 pcell_t freq; 224 225 if (bootinfo != NULL) { 226 if (bootinfo[0] == 1) { 227 /* Backward compatibility. See 8-STABLE. */ 228 ticks = bootinfo[3] >> 3; 229 } else { 230 /* Compatibility with Juniper's loader. */ 231 ticks = bootinfo[5] >> 3; 232 } 233 } else 234 ticks = 0; 235 236 if ((cpus = OF_finddevice("/cpus")) == -1) 237 goto out; 238 239 if ((child = OF_child(cpus)) == 0) 240 goto out; 241 242 switch (OF_getproplen(child, "timebase-frequency")) { 243 case 4: 244 { 245 uint32_t tbase; 246 OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 247 ticks = tbase; 248 return (ticks); 249 } 250 case 8: 251 { 252 uint64_t tbase; 253 OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 254 ticks = tbase; 255 return (ticks); 256 } 257 default: 258 break; 259 } 260 261 freq = 0; 262 if (OF_getprop(child, "bus-frequency", (void *)&freq, 263 sizeof(freq)) <= 0) 264 goto out; 265 266 if (freq == 0) 267 goto out; 268 269 /* 270 * Time Base and Decrementer are updated every 8 CCB bus clocks. 271 * HID0[SEL_TBCLK] = 0 272 */ 273 if (mpc85xx_is_qoriq()) 274 ticks = freq / 32; 275 else 276 ticks = freq / 8; 277 278 out: 279 if (ticks <= 0) 280 panic("Unable to determine timebase frequency!"); 281 282 return (ticks); 283 } 284 285 static int 286 mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 287 { 288 289 cpu = 0; 290 cpuref->cr_cpuid = cpu; 291 cpuref->cr_hwref = cpuref->cr_cpuid; 292 if (bootverbose) 293 printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 294 cpu++; 295 296 return (0); 297 } 298 299 static int 300 mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 301 { 302 303 if (cpu >= maxcpu) 304 return (ENOENT); 305 306 cpuref->cr_cpuid = cpu++; 307 cpuref->cr_hwref = cpuref->cr_cpuid; 308 if (bootverbose) 309 printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 310 311 return (0); 312 } 313 314 static int 315 mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 316 { 317 318 cpuref->cr_cpuid = mfspr(SPR_PIR); 319 cpuref->cr_hwref = cpuref->cr_cpuid; 320 321 return (0); 322 } 323 324 #ifdef SMP 325 static int 326 mpc85xx_smp_start_cpu_epapr(platform_t plat, struct pcpu *pc) 327 { 328 vm_paddr_t rel_pa, bptr; 329 volatile struct cpu_release *rel; 330 vm_offset_t rel_va, rel_page; 331 phandle_t node; 332 int i; 333 334 /* If we're calling this, the node already exists. */ 335 node = OF_finddevice("/cpus"); 336 for (i = 0, node = OF_child(node); i < pc->pc_cpuid; 337 i++, node = OF_peer(node)) 338 ; 339 if (OF_getencprop(node, "cpu-release-addr", (pcell_t *)&rel_pa, 340 sizeof(rel_pa)) == -1) { 341 return (ENOENT); 342 } 343 344 rel_page = kva_alloc(PAGE_SIZE); 345 if (rel_page == 0) 346 return (ENOMEM); 347 348 critical_enter(); 349 rel_va = rel_page + (rel_pa & PAGE_MASK); 350 pmap_kenter(rel_page, rel_pa & ~PAGE_MASK); 351 rel = (struct cpu_release *)rel_va; 352 bptr = ((vm_paddr_t)(uintptr_t)__boot_page - KERNBASE) + kernload; 353 cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 354 rel->pir = pc->pc_cpuid; __asm __volatile("sync"); 355 rel->entry_h = (bptr >> 32); 356 rel->entry_l = bptr; __asm __volatile("sync"); 357 cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 358 if (bootverbose) 359 printf("Waking up CPU %d via CPU release page %p\n", 360 pc->pc_cpuid, rel); 361 critical_exit(); 362 pmap_kremove(rel_page); 363 kva_free(rel_page, PAGE_SIZE); 364 365 return (0); 366 } 367 #endif 368 369 static int 370 mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) 371 { 372 #ifdef SMP 373 vm_paddr_t bptr; 374 uint32_t reg; 375 int timeout; 376 uintptr_t brr; 377 int cpuid; 378 int epapr_boot = 0; 379 uint32_t tgt; 380 381 if (mpc85xx_is_qoriq()) { 382 reg = ccsr_read4(OCP85XX_COREDISR); 383 cpuid = pc->pc_cpuid; 384 385 if ((reg & (1 << cpuid)) != 0) { 386 printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid); 387 return (-1); 388 } 389 390 brr = OCP85XX_BRR; 391 } else { 392 brr = OCP85XX_EEBPCR; 393 cpuid = pc->pc_cpuid + 24; 394 } 395 bp_kernload = kernload; 396 /* 397 * bp_kernload is in the boot page. Sync the cache because ePAPR 398 * booting has the other core(s) already running. 399 */ 400 cpu_flush_dcache(&bp_kernload, sizeof(bp_kernload)); 401 402 ap_pcpu = pc; 403 __asm __volatile("msync; isync"); 404 405 /* First try the ePAPR way. */ 406 if (mpc85xx_smp_start_cpu_epapr(plat, pc) == 0) { 407 epapr_boot = 1; 408 goto spin_wait; 409 } 410 411 reg = ccsr_read4(brr); 412 if ((reg & (1 << cpuid)) != 0) { 413 printf("SMP: CPU %d already out of hold-off state!\n", 414 pc->pc_cpuid); 415 return (ENXIO); 416 } 417 418 /* Flush caches to have our changes hit DRAM. */ 419 cpu_flush_dcache(__boot_page, 4096); 420 421 bptr = ((vm_paddr_t)(uintptr_t)__boot_page - KERNBASE) + kernload; 422 KASSERT((bptr & 0xfff) == 0, 423 ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr)); 424 if (mpc85xx_is_qoriq()) { 425 /* 426 * Read DDR controller configuration to select proper BPTR target ID. 427 * 428 * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers 429 * interleaving. If this bit is set, we have to use 430 * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs, 431 * this bit is reserved and always 0. 432 */ 433 434 reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG); 435 if (reg & (1 << 29)) 436 tgt = OCP85XX_TGTIF_RAM_INTL; 437 else 438 tgt = OCP85XX_TGTIF_RAM1; 439 440 /* 441 * Set BSTR to the physical address of the boot page 442 */ 443 ccsr_write4(OCP85XX_BSTRH, bptr >> 32); 444 ccsr_write4(OCP85XX_BSTRL, bptr); 445 ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK | 446 (tgt << OCP85XX_TRGT_SHIFT_QORIQ) | (ffsl(PAGE_SIZE) - 2)); 447 448 /* Read back OCP85XX_BSTAR to synchronize write */ 449 ccsr_read4(OCP85XX_BSTAR); 450 451 /* 452 * Enable and configure time base on new CPU. 453 */ 454 455 /* Set TB clock source to platform clock / 32 */ 456 reg = ccsr_read4(CCSR_CTBCKSELR); 457 ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid)); 458 459 /* Enable TB */ 460 reg = ccsr_read4(CCSR_CTBENR); 461 ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid)); 462 } else { 463 /* 464 * Set BPTR to the physical address of the boot page 465 */ 466 bptr = (bptr >> 12) | 0x80000000u; 467 ccsr_write4(OCP85XX_BPTR, bptr); 468 __asm __volatile("isync; msync"); 469 } 470 471 /* 472 * Release AP from hold-off state 473 */ 474 reg = ccsr_read4(brr); 475 ccsr_write4(brr, reg | (1 << cpuid)); 476 __asm __volatile("isync; msync"); 477 478 spin_wait: 479 timeout = 500; 480 while (!pc->pc_awake && timeout--) 481 DELAY(1000); /* wait 1ms */ 482 483 /* 484 * Disable boot page translation so that the 4K page at the default 485 * address (= 0xfffff000) isn't permanently remapped and thus not 486 * usable otherwise. 487 */ 488 if (!epapr_boot) { 489 if (mpc85xx_is_qoriq()) 490 ccsr_write4(OCP85XX_BSTAR, 0); 491 else 492 ccsr_write4(OCP85XX_BPTR, 0); 493 __asm __volatile("isync; msync"); 494 } 495 496 if (!pc->pc_awake) 497 panic("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); 498 return ((pc->pc_awake) ? 0 : EBUSY); 499 #else 500 /* No SMP support */ 501 return (ENXIO); 502 #endif 503 } 504 505 static void 506 mpc85xx_reset(platform_t plat) 507 { 508 509 /* 510 * Try the dedicated reset register first. 511 * If the SoC doesn't have one, we'll fall 512 * back to using the debug control register. 513 */ 514 ccsr_write4(OCP85XX_RSTCR, 2); 515 516 /* Clear DBCR0, disables debug interrupts and events. */ 517 mtspr(SPR_DBCR0, 0); 518 __asm __volatile("isync"); 519 520 /* Enable Debug Interrupts in MSR. */ 521 mtmsr(mfmsr() | PSL_DE); 522 523 /* Enable debug interrupts and issue reset. */ 524 mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM); 525 526 printf("Reset failed...\n"); 527 while (1) 528 ; 529 } 530 531 static void 532 mpc85xx_idle(platform_t plat, int cpu) 533 { 534 uint32_t reg; 535 536 if (mpc85xx_is_qoriq()) { 537 /* 538 * Base binutils doesn't know what the 'wait' instruction is, so 539 * use the opcode encoding here. 540 */ 541 __asm __volatile("wrteei 1; .long 0x7c00007c"); 542 } else { 543 reg = mfmsr(); 544 /* Freescale E500 core RM section 6.4.1. */ 545 __asm __volatile("msync; mtmsr %0; isync" :: 546 "r" (reg | PSL_WE)); 547 } 548 } 549 550 static int 551 mpc85xx_idle_wakeup(platform_t plat, int cpu) 552 { 553 554 return (0); 555 } 556