1302acc2eSNathan Whitehorn /*- 2302acc2eSNathan Whitehorn * Copyright (c) 2008-2012 Semihalf. 3302acc2eSNathan Whitehorn * All rights reserved. 4302acc2eSNathan Whitehorn * 5302acc2eSNathan Whitehorn * Redistribution and use in source and binary forms, with or without 6302acc2eSNathan Whitehorn * modification, are permitted provided that the following conditions 7302acc2eSNathan Whitehorn * are met: 8302acc2eSNathan Whitehorn * 9302acc2eSNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 10302acc2eSNathan Whitehorn * notice, this list of conditions and the following disclaimer. 11302acc2eSNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 12302acc2eSNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 13302acc2eSNathan Whitehorn * documentation and/or other materials provided with the distribution. 14302acc2eSNathan Whitehorn * 15302acc2eSNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16302acc2eSNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17302acc2eSNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18302acc2eSNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19302acc2eSNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20302acc2eSNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21302acc2eSNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22302acc2eSNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23302acc2eSNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24302acc2eSNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25302acc2eSNathan Whitehorn */ 26302acc2eSNathan Whitehorn 27302acc2eSNathan Whitehorn #include <sys/cdefs.h> 28302acc2eSNathan Whitehorn __FBSDID("$FreeBSD$"); 29302acc2eSNathan Whitehorn 30302acc2eSNathan Whitehorn #include <sys/param.h> 31302acc2eSNathan Whitehorn #include <sys/systm.h> 32302acc2eSNathan Whitehorn #include <sys/kernel.h> 33302acc2eSNathan Whitehorn #include <sys/bus.h> 34302acc2eSNathan Whitehorn #include <sys/pcpu.h> 35302acc2eSNathan Whitehorn #include <sys/proc.h> 36302acc2eSNathan Whitehorn #include <sys/smp.h> 37302acc2eSNathan Whitehorn 38302acc2eSNathan Whitehorn #include <machine/bus.h> 39302acc2eSNathan Whitehorn #include <machine/cpu.h> 40302acc2eSNathan Whitehorn #include <machine/hid.h> 41302acc2eSNathan Whitehorn #include <machine/platform.h> 42302acc2eSNathan Whitehorn #include <machine/platformvar.h> 43302acc2eSNathan Whitehorn #include <machine/smp.h> 44302acc2eSNathan Whitehorn #include <machine/spr.h> 45302acc2eSNathan Whitehorn #include <machine/vmparam.h> 46302acc2eSNathan Whitehorn 47302acc2eSNathan Whitehorn #include <dev/fdt/fdt_common.h> 48302acc2eSNathan Whitehorn #include <dev/ofw/ofw_bus.h> 49302acc2eSNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 50302acc2eSNathan Whitehorn #include <dev/ofw/openfirm.h> 51302acc2eSNathan Whitehorn 5252cfe485SNathan Whitehorn #include <vm/vm.h> 5352cfe485SNathan Whitehorn #include <vm/pmap.h> 5452cfe485SNathan Whitehorn 55302acc2eSNathan Whitehorn #include <powerpc/mpc85xx/mpc85xx.h> 56302acc2eSNathan Whitehorn 57302acc2eSNathan Whitehorn #include "platform_if.h" 58302acc2eSNathan Whitehorn 59302acc2eSNathan Whitehorn #ifdef SMP 60302acc2eSNathan Whitehorn extern void *ap_pcpu; 61302acc2eSNathan Whitehorn extern vm_paddr_t kernload; /* Kernel physical load address */ 62302acc2eSNathan Whitehorn extern uint8_t __boot_page[]; /* Boot page body */ 63302acc2eSNathan Whitehorn extern uint32_t bp_ntlb1s; 64302acc2eSNathan Whitehorn extern uint32_t bp_tlb1[]; 65302acc2eSNathan Whitehorn extern uint32_t bp_tlb1_end[]; 66302acc2eSNathan Whitehorn #endif 67302acc2eSNathan Whitehorn 68302acc2eSNathan Whitehorn extern uint32_t *bootinfo; 6952cfe485SNathan Whitehorn vm_offset_t ccsrbar_va; 70302acc2eSNathan Whitehorn 71302acc2eSNathan Whitehorn static int cpu, maxcpu; 72302acc2eSNathan Whitehorn 73302acc2eSNathan Whitehorn static int mpc85xx_probe(platform_t); 74302acc2eSNathan Whitehorn static int mpc85xx_attach(platform_t); 75*c1cb22d7SNathan Whitehorn static void mpc85xx_mem_regions(platform_t, struct mem_region *phys, 76*c1cb22d7SNathan Whitehorn int *physsz, struct mem_region *avail, int *availsz); 77302acc2eSNathan Whitehorn static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref); 78302acc2eSNathan Whitehorn static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref); 79302acc2eSNathan Whitehorn static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref); 80302acc2eSNathan Whitehorn static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref); 81302acc2eSNathan Whitehorn static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu); 82302acc2eSNathan Whitehorn 83302acc2eSNathan Whitehorn static void mpc85xx_reset(platform_t); 84302acc2eSNathan Whitehorn 85302acc2eSNathan Whitehorn static platform_method_t mpc85xx_methods[] = { 86302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_probe, mpc85xx_probe), 87302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_attach, mpc85xx_attach), 88302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions), 89302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq), 90302acc2eSNathan Whitehorn 91302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu), 92302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu), 93302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp), 94302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), 95302acc2eSNathan Whitehorn 96302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_reset, mpc85xx_reset), 97302acc2eSNathan Whitehorn 98302acc2eSNathan Whitehorn PLATFORMMETHOD_END 99302acc2eSNathan Whitehorn }; 100302acc2eSNathan Whitehorn 101302acc2eSNathan Whitehorn static platform_def_t mpc85xx_platform = { 102302acc2eSNathan Whitehorn "mpc85xx", 103302acc2eSNathan Whitehorn mpc85xx_methods, 104302acc2eSNathan Whitehorn 0 105302acc2eSNathan Whitehorn }; 106302acc2eSNathan Whitehorn 107302acc2eSNathan Whitehorn PLATFORM_DEF(mpc85xx_platform); 108302acc2eSNathan Whitehorn 109302acc2eSNathan Whitehorn static int 110302acc2eSNathan Whitehorn mpc85xx_probe(platform_t plat) 111302acc2eSNathan Whitehorn { 112302acc2eSNathan Whitehorn u_int pvr = mfpvr() >> 16; 113302acc2eSNathan Whitehorn 114302acc2eSNathan Whitehorn if ((pvr & 0xfff0) == FSL_E500v1) 115302acc2eSNathan Whitehorn return (BUS_PROBE_DEFAULT); 116302acc2eSNathan Whitehorn 117302acc2eSNathan Whitehorn return (ENXIO); 118302acc2eSNathan Whitehorn } 119302acc2eSNathan Whitehorn 120302acc2eSNathan Whitehorn static int 121302acc2eSNathan Whitehorn mpc85xx_attach(platform_t plat) 122302acc2eSNathan Whitehorn { 12352cfe485SNathan Whitehorn phandle_t cpus, child, ccsr; 12452cfe485SNathan Whitehorn const char *soc_name_guesses[] = {"/soc", "soc", NULL}; 12552cfe485SNathan Whitehorn const char **name; 12652cfe485SNathan Whitehorn pcell_t ranges[6], acells, pacells, scells; 127302acc2eSNathan Whitehorn uint32_t sr; 12852cfe485SNathan Whitehorn uint64_t ccsrbar, ccsrsize; 129302acc2eSNathan Whitehorn int i, law_max, tgt; 130302acc2eSNathan Whitehorn 131302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) != -1) { 132302acc2eSNathan Whitehorn for (maxcpu = 0, child = OF_child(cpus); child != 0; 133302acc2eSNathan Whitehorn child = OF_peer(child), maxcpu++) 134302acc2eSNathan Whitehorn ; 135302acc2eSNathan Whitehorn } else 136302acc2eSNathan Whitehorn maxcpu = 1; 137302acc2eSNathan Whitehorn 138302acc2eSNathan Whitehorn /* 13952cfe485SNathan Whitehorn * Locate CCSR region. Irritatingly, there is no way to find it 14052cfe485SNathan Whitehorn * unless you already know where it is. Try to infer its location 14152cfe485SNathan Whitehorn * from the device tree. 14252cfe485SNathan Whitehorn */ 14352cfe485SNathan Whitehorn 14452cfe485SNathan Whitehorn ccsr = -1; 14552cfe485SNathan Whitehorn for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++) 14652cfe485SNathan Whitehorn ccsr = OF_finddevice(*name); 14752cfe485SNathan Whitehorn if (ccsr == -1) { 14852cfe485SNathan Whitehorn char type[64]; 14952cfe485SNathan Whitehorn 15052cfe485SNathan Whitehorn /* That didn't work. Search for devices of type "soc" */ 15152cfe485SNathan Whitehorn child = OF_child(OF_peer(0)); 15252cfe485SNathan Whitehorn for (OF_child(child); child != 0; child = OF_peer(child)) { 15352cfe485SNathan Whitehorn if (OF_getprop(child, "device_type", type, sizeof(type)) 15452cfe485SNathan Whitehorn <= 0) 15552cfe485SNathan Whitehorn continue; 15652cfe485SNathan Whitehorn 15752cfe485SNathan Whitehorn if (strcmp(type, "soc") == 0) { 15852cfe485SNathan Whitehorn ccsr = child; 15952cfe485SNathan Whitehorn break; 16052cfe485SNathan Whitehorn } 16152cfe485SNathan Whitehorn } 16252cfe485SNathan Whitehorn } 16352cfe485SNathan Whitehorn 16452cfe485SNathan Whitehorn if (ccsr == -1) 16552cfe485SNathan Whitehorn panic("Could not locate CCSR window!"); 16652cfe485SNathan Whitehorn 16752cfe485SNathan Whitehorn OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells)); 16852cfe485SNathan Whitehorn OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells)); 16952cfe485SNathan Whitehorn OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells, 17052cfe485SNathan Whitehorn sizeof(pacells)); 17152cfe485SNathan Whitehorn OF_getprop(ccsr, "ranges", ranges, sizeof(ranges)); 17252cfe485SNathan Whitehorn ccsrbar = ccsrsize = 0; 17352cfe485SNathan Whitehorn for (i = acells; i < acells + pacells; i++) { 17452cfe485SNathan Whitehorn ccsrbar <<= 32; 17552cfe485SNathan Whitehorn ccsrbar |= ranges[i]; 17652cfe485SNathan Whitehorn } 17752cfe485SNathan Whitehorn for (i = acells + pacells; i < acells + pacells + scells; i++) { 17852cfe485SNathan Whitehorn ccsrsize <<= 32; 17952cfe485SNathan Whitehorn ccsrsize |= ranges[i]; 18052cfe485SNathan Whitehorn } 18152cfe485SNathan Whitehorn ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); 18252cfe485SNathan Whitehorn 18352cfe485SNathan Whitehorn /* 184302acc2eSNathan Whitehorn * Clear local access windows. Skip DRAM entries, so we don't shoot 185302acc2eSNathan Whitehorn * ourselves in the foot. 186302acc2eSNathan Whitehorn */ 187302acc2eSNathan Whitehorn law_max = law_getmax(); 188302acc2eSNathan Whitehorn for (i = 0; i < law_max; i++) { 189302acc2eSNathan Whitehorn sr = ccsr_read4(OCP85XX_LAWSR(i)); 190302acc2eSNathan Whitehorn if ((sr & 0x80000000) == 0) 191302acc2eSNathan Whitehorn continue; 192302acc2eSNathan Whitehorn tgt = (sr & 0x01f00000) >> 20; 193302acc2eSNathan Whitehorn if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 || 194302acc2eSNathan Whitehorn tgt == OCP85XX_TGTIF_RAM_INTL) 195302acc2eSNathan Whitehorn continue; 196302acc2eSNathan Whitehorn 197302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff); 198302acc2eSNathan Whitehorn } 199302acc2eSNathan Whitehorn 200302acc2eSNathan Whitehorn return (0); 201302acc2eSNathan Whitehorn } 202302acc2eSNathan Whitehorn 203302acc2eSNathan Whitehorn void 204*c1cb22d7SNathan Whitehorn mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 205*c1cb22d7SNathan Whitehorn struct mem_region *avail, int *availsz) 206302acc2eSNathan Whitehorn { 207302acc2eSNathan Whitehorn 208302acc2eSNathan Whitehorn ofw_mem_regions(phys, physsz, avail, availsz); 209302acc2eSNathan Whitehorn } 210302acc2eSNathan Whitehorn 211302acc2eSNathan Whitehorn static u_long 212302acc2eSNathan Whitehorn mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) 213302acc2eSNathan Whitehorn { 214302acc2eSNathan Whitehorn u_long ticks; 215302acc2eSNathan Whitehorn phandle_t cpus, child; 216302acc2eSNathan Whitehorn pcell_t freq; 217302acc2eSNathan Whitehorn 218302acc2eSNathan Whitehorn if (bootinfo != NULL) { 219302acc2eSNathan Whitehorn if (bootinfo[0] == 1) { 220302acc2eSNathan Whitehorn /* Backward compatibility. See 8-STABLE. */ 221302acc2eSNathan Whitehorn ticks = bootinfo[3] >> 3; 222302acc2eSNathan Whitehorn } else { 223302acc2eSNathan Whitehorn /* Compatibility with Juniper's loader. */ 224302acc2eSNathan Whitehorn ticks = bootinfo[5] >> 3; 225302acc2eSNathan Whitehorn } 226302acc2eSNathan Whitehorn } else 227302acc2eSNathan Whitehorn ticks = 0; 228302acc2eSNathan Whitehorn 229302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) == -1) 230302acc2eSNathan Whitehorn goto out; 231302acc2eSNathan Whitehorn 232302acc2eSNathan Whitehorn if ((child = OF_child(cpus)) == 0) 233302acc2eSNathan Whitehorn goto out; 234302acc2eSNathan Whitehorn 235302acc2eSNathan Whitehorn switch (OF_getproplen(child, "timebase-frequency")) { 236302acc2eSNathan Whitehorn case 4: 237302acc2eSNathan Whitehorn { 238302acc2eSNathan Whitehorn uint32_t tbase; 239302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 240302acc2eSNathan Whitehorn ticks = tbase; 241302acc2eSNathan Whitehorn return (ticks); 242302acc2eSNathan Whitehorn } 243302acc2eSNathan Whitehorn case 8: 244302acc2eSNathan Whitehorn { 245302acc2eSNathan Whitehorn uint64_t tbase; 246302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 247302acc2eSNathan Whitehorn ticks = tbase; 248302acc2eSNathan Whitehorn return (ticks); 249302acc2eSNathan Whitehorn } 250302acc2eSNathan Whitehorn default: 251302acc2eSNathan Whitehorn break; 252302acc2eSNathan Whitehorn } 253302acc2eSNathan Whitehorn 254302acc2eSNathan Whitehorn freq = 0; 255302acc2eSNathan Whitehorn if (OF_getprop(child, "bus-frequency", (void *)&freq, 256302acc2eSNathan Whitehorn sizeof(freq)) <= 0) 257302acc2eSNathan Whitehorn goto out; 258302acc2eSNathan Whitehorn 259302acc2eSNathan Whitehorn /* 260302acc2eSNathan Whitehorn * Time Base and Decrementer are updated every 8 CCB bus clocks. 261302acc2eSNathan Whitehorn * HID0[SEL_TBCLK] = 0 262302acc2eSNathan Whitehorn */ 263302acc2eSNathan Whitehorn if (freq != 0) 264302acc2eSNathan Whitehorn ticks = freq / 8; 265302acc2eSNathan Whitehorn 266302acc2eSNathan Whitehorn out: 267302acc2eSNathan Whitehorn if (ticks <= 0) 268302acc2eSNathan Whitehorn panic("Unable to determine timebase frequency!"); 269302acc2eSNathan Whitehorn 270302acc2eSNathan Whitehorn return (ticks); 271302acc2eSNathan Whitehorn } 272302acc2eSNathan Whitehorn 273302acc2eSNathan Whitehorn static int 274302acc2eSNathan Whitehorn mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 275302acc2eSNathan Whitehorn { 276302acc2eSNathan Whitehorn 277302acc2eSNathan Whitehorn cpu = 0; 278302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu; 279302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 280302acc2eSNathan Whitehorn if (bootverbose) 281302acc2eSNathan Whitehorn printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 282302acc2eSNathan Whitehorn cpu++; 283302acc2eSNathan Whitehorn 284302acc2eSNathan Whitehorn return (0); 285302acc2eSNathan Whitehorn } 286302acc2eSNathan Whitehorn 287302acc2eSNathan Whitehorn static int 288302acc2eSNathan Whitehorn mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 289302acc2eSNathan Whitehorn { 290302acc2eSNathan Whitehorn 291302acc2eSNathan Whitehorn if (cpu >= maxcpu) 292302acc2eSNathan Whitehorn return (ENOENT); 293302acc2eSNathan Whitehorn 294302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu++; 295302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 296302acc2eSNathan Whitehorn if (bootverbose) 297302acc2eSNathan Whitehorn printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 298302acc2eSNathan Whitehorn 299302acc2eSNathan Whitehorn return (0); 300302acc2eSNathan Whitehorn } 301302acc2eSNathan Whitehorn 302302acc2eSNathan Whitehorn static int 303302acc2eSNathan Whitehorn mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 304302acc2eSNathan Whitehorn { 305302acc2eSNathan Whitehorn 306302acc2eSNathan Whitehorn cpuref->cr_cpuid = mfspr(SPR_PIR); 307302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 308302acc2eSNathan Whitehorn 309302acc2eSNathan Whitehorn return (0); 310302acc2eSNathan Whitehorn } 311302acc2eSNathan Whitehorn 312302acc2eSNathan Whitehorn static int 313302acc2eSNathan Whitehorn mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) 314302acc2eSNathan Whitehorn { 315302acc2eSNathan Whitehorn #ifdef SMP 316302acc2eSNathan Whitehorn uint32_t *tlb1; 317302acc2eSNathan Whitehorn uint32_t bptr, eebpcr; 318302acc2eSNathan Whitehorn int i, timeout; 319302acc2eSNathan Whitehorn 320302acc2eSNathan Whitehorn eebpcr = ccsr_read4(OCP85XX_EEBPCR); 321302acc2eSNathan Whitehorn if ((eebpcr & (1 << (pc->pc_cpuid + 24))) != 0) { 322302acc2eSNathan Whitehorn printf("SMP: CPU %d already out of hold-off state!\n", 323302acc2eSNathan Whitehorn pc->pc_cpuid); 324302acc2eSNathan Whitehorn return (ENXIO); 325302acc2eSNathan Whitehorn } 326302acc2eSNathan Whitehorn 327302acc2eSNathan Whitehorn ap_pcpu = pc; 328302acc2eSNathan Whitehorn 329302acc2eSNathan Whitehorn i = 0; 330302acc2eSNathan Whitehorn tlb1 = bp_tlb1; 331302acc2eSNathan Whitehorn while (i < bp_ntlb1s && tlb1 < bp_tlb1_end) { 332302acc2eSNathan Whitehorn mtspr(SPR_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(i)); 333302acc2eSNathan Whitehorn __asm __volatile("isync; tlbre"); 334302acc2eSNathan Whitehorn tlb1[0] = mfspr(SPR_MAS1); 335302acc2eSNathan Whitehorn tlb1[1] = mfspr(SPR_MAS2); 336302acc2eSNathan Whitehorn tlb1[2] = mfspr(SPR_MAS3); 337302acc2eSNathan Whitehorn i++; 338302acc2eSNathan Whitehorn tlb1 += 3; 339302acc2eSNathan Whitehorn } 340302acc2eSNathan Whitehorn if (i < bp_ntlb1s) 341302acc2eSNathan Whitehorn bp_ntlb1s = i; 342302acc2eSNathan Whitehorn 343302acc2eSNathan Whitehorn /* 344302acc2eSNathan Whitehorn * Set BPTR to the physical address of the boot page 345302acc2eSNathan Whitehorn */ 346302acc2eSNathan Whitehorn bptr = ((uint32_t)__boot_page - KERNBASE) + kernload; 347302acc2eSNathan Whitehorn KASSERT((bptr & 0xfff) == 0, 348302acc2eSNathan Whitehorn ("%s: boot page is not aligned (%#x)", __func__, bptr)); 349302acc2eSNathan Whitehorn bptr = (bptr >> 12) | 0x80000000u; 350302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, bptr); 351302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 352302acc2eSNathan Whitehorn 353302acc2eSNathan Whitehorn /* Flush caches to have our changes hit DRAM. */ 354302acc2eSNathan Whitehorn cpu_flush_dcache(__boot_page, 4096); 355302acc2eSNathan Whitehorn 356302acc2eSNathan Whitehorn /* 357302acc2eSNathan Whitehorn * Release AP from hold-off state 358302acc2eSNathan Whitehorn */ 359302acc2eSNathan Whitehorn eebpcr |= (1 << (pc->pc_cpuid + 24)); 360302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_EEBPCR, eebpcr); 361302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 362302acc2eSNathan Whitehorn 363302acc2eSNathan Whitehorn timeout = 500; 364302acc2eSNathan Whitehorn while (!pc->pc_awake && timeout--) 365302acc2eSNathan Whitehorn DELAY(1000); /* wait 1ms */ 366302acc2eSNathan Whitehorn 367302acc2eSNathan Whitehorn /* 368302acc2eSNathan Whitehorn * Disable boot page translation so that the 4K page at the default 369302acc2eSNathan Whitehorn * address (= 0xfffff000) isn't permanently remapped and thus not 370302acc2eSNathan Whitehorn * usable otherwise. 371302acc2eSNathan Whitehorn */ 372302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, 0); 373302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 374302acc2eSNathan Whitehorn 375302acc2eSNathan Whitehorn if (!pc->pc_awake) 376302acc2eSNathan Whitehorn printf("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); 377302acc2eSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 378302acc2eSNathan Whitehorn #else 379302acc2eSNathan Whitehorn /* No SMP support */ 380302acc2eSNathan Whitehorn return (ENXIO); 381302acc2eSNathan Whitehorn #endif 382302acc2eSNathan Whitehorn } 383302acc2eSNathan Whitehorn 384302acc2eSNathan Whitehorn static void 385302acc2eSNathan Whitehorn mpc85xx_reset(platform_t plat) 386302acc2eSNathan Whitehorn { 387302acc2eSNathan Whitehorn 388302acc2eSNathan Whitehorn /* 389302acc2eSNathan Whitehorn * Try the dedicated reset register first. 390302acc2eSNathan Whitehorn * If the SoC doesn't have one, we'll fall 391302acc2eSNathan Whitehorn * back to using the debug control register. 392302acc2eSNathan Whitehorn */ 393302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_RSTCR, 2); 394302acc2eSNathan Whitehorn 395302acc2eSNathan Whitehorn /* Clear DBCR0, disables debug interrupts and events. */ 396302acc2eSNathan Whitehorn mtspr(SPR_DBCR0, 0); 397302acc2eSNathan Whitehorn __asm __volatile("isync"); 398302acc2eSNathan Whitehorn 399302acc2eSNathan Whitehorn /* Enable Debug Interrupts in MSR. */ 400302acc2eSNathan Whitehorn mtmsr(mfmsr() | PSL_DE); 401302acc2eSNathan Whitehorn 402302acc2eSNathan Whitehorn /* Enable debug interrupts and issue reset. */ 403302acc2eSNathan Whitehorn mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM); 404302acc2eSNathan Whitehorn 405302acc2eSNathan Whitehorn printf("Reset failed...\n"); 406302acc2eSNathan Whitehorn while (1) 407302acc2eSNathan Whitehorn ; 408302acc2eSNathan Whitehorn } 409302acc2eSNathan Whitehorn 410