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); 74c1cb22d7SNathan Whitehorn static void mpc85xx_mem_regions(platform_t, struct mem_region *phys, 75c1cb22d7SNathan Whitehorn int *physsz, struct mem_region *avail, int *availsz); 76302acc2eSNathan Whitehorn static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref); 77302acc2eSNathan Whitehorn static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref); 78302acc2eSNathan Whitehorn static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref); 79302acc2eSNathan Whitehorn static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref); 80302acc2eSNathan Whitehorn static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu); 81302acc2eSNathan Whitehorn 82302acc2eSNathan Whitehorn static void mpc85xx_reset(platform_t); 83302acc2eSNathan Whitehorn 84302acc2eSNathan Whitehorn static platform_method_t mpc85xx_methods[] = { 85302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_probe, mpc85xx_probe), 86302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_attach, mpc85xx_attach), 87302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions), 88302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq), 89302acc2eSNathan Whitehorn 90302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu), 91302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu), 92302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp), 93302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), 94302acc2eSNathan Whitehorn 95302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_reset, mpc85xx_reset), 96302acc2eSNathan Whitehorn 97302acc2eSNathan Whitehorn PLATFORMMETHOD_END 98302acc2eSNathan Whitehorn }; 99302acc2eSNathan Whitehorn 100*fa7a1ca7SJustin Hibbits DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0); 101302acc2eSNathan Whitehorn 102302acc2eSNathan Whitehorn PLATFORM_DEF(mpc85xx_platform); 103302acc2eSNathan Whitehorn 104302acc2eSNathan Whitehorn static int 105302acc2eSNathan Whitehorn mpc85xx_probe(platform_t plat) 106302acc2eSNathan Whitehorn { 107302acc2eSNathan Whitehorn u_int pvr = mfpvr() >> 16; 108302acc2eSNathan Whitehorn 109302acc2eSNathan Whitehorn if ((pvr & 0xfff0) == FSL_E500v1) 110302acc2eSNathan Whitehorn return (BUS_PROBE_DEFAULT); 111302acc2eSNathan Whitehorn 112302acc2eSNathan Whitehorn return (ENXIO); 113302acc2eSNathan Whitehorn } 114302acc2eSNathan Whitehorn 115*fa7a1ca7SJustin Hibbits int 116302acc2eSNathan Whitehorn mpc85xx_attach(platform_t plat) 117302acc2eSNathan Whitehorn { 11852cfe485SNathan Whitehorn phandle_t cpus, child, ccsr; 11952cfe485SNathan Whitehorn const char *soc_name_guesses[] = {"/soc", "soc", NULL}; 12052cfe485SNathan Whitehorn const char **name; 12152cfe485SNathan Whitehorn pcell_t ranges[6], acells, pacells, scells; 122302acc2eSNathan Whitehorn uint32_t sr; 12352cfe485SNathan Whitehorn uint64_t ccsrbar, ccsrsize; 124302acc2eSNathan Whitehorn int i, law_max, tgt; 125302acc2eSNathan Whitehorn 126302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) != -1) { 127302acc2eSNathan Whitehorn for (maxcpu = 0, child = OF_child(cpus); child != 0; 128302acc2eSNathan Whitehorn child = OF_peer(child), maxcpu++) 129302acc2eSNathan Whitehorn ; 130302acc2eSNathan Whitehorn } else 131302acc2eSNathan Whitehorn maxcpu = 1; 132302acc2eSNathan Whitehorn 133302acc2eSNathan Whitehorn /* 13452cfe485SNathan Whitehorn * Locate CCSR region. Irritatingly, there is no way to find it 13552cfe485SNathan Whitehorn * unless you already know where it is. Try to infer its location 13652cfe485SNathan Whitehorn * from the device tree. 13752cfe485SNathan Whitehorn */ 13852cfe485SNathan Whitehorn 13952cfe485SNathan Whitehorn ccsr = -1; 14052cfe485SNathan Whitehorn for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++) 14152cfe485SNathan Whitehorn ccsr = OF_finddevice(*name); 14252cfe485SNathan Whitehorn if (ccsr == -1) { 14352cfe485SNathan Whitehorn char type[64]; 14452cfe485SNathan Whitehorn 14552cfe485SNathan Whitehorn /* That didn't work. Search for devices of type "soc" */ 14652cfe485SNathan Whitehorn child = OF_child(OF_peer(0)); 14752cfe485SNathan Whitehorn for (OF_child(child); child != 0; child = OF_peer(child)) { 14852cfe485SNathan Whitehorn if (OF_getprop(child, "device_type", type, sizeof(type)) 14952cfe485SNathan Whitehorn <= 0) 15052cfe485SNathan Whitehorn continue; 15152cfe485SNathan Whitehorn 15252cfe485SNathan Whitehorn if (strcmp(type, "soc") == 0) { 15352cfe485SNathan Whitehorn ccsr = child; 15452cfe485SNathan Whitehorn break; 15552cfe485SNathan Whitehorn } 15652cfe485SNathan Whitehorn } 15752cfe485SNathan Whitehorn } 15852cfe485SNathan Whitehorn 15952cfe485SNathan Whitehorn if (ccsr == -1) 16052cfe485SNathan Whitehorn panic("Could not locate CCSR window!"); 16152cfe485SNathan Whitehorn 16252cfe485SNathan Whitehorn OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells)); 16352cfe485SNathan Whitehorn OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells)); 16452cfe485SNathan Whitehorn OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells, 16552cfe485SNathan Whitehorn sizeof(pacells)); 16652cfe485SNathan Whitehorn OF_getprop(ccsr, "ranges", ranges, sizeof(ranges)); 16752cfe485SNathan Whitehorn ccsrbar = ccsrsize = 0; 16852cfe485SNathan Whitehorn for (i = acells; i < acells + pacells; i++) { 16952cfe485SNathan Whitehorn ccsrbar <<= 32; 17052cfe485SNathan Whitehorn ccsrbar |= ranges[i]; 17152cfe485SNathan Whitehorn } 17252cfe485SNathan Whitehorn for (i = acells + pacells; i < acells + pacells + scells; i++) { 17352cfe485SNathan Whitehorn ccsrsize <<= 32; 17452cfe485SNathan Whitehorn ccsrsize |= ranges[i]; 17552cfe485SNathan Whitehorn } 17652cfe485SNathan Whitehorn ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); 17752cfe485SNathan Whitehorn 17852cfe485SNathan Whitehorn /* 179302acc2eSNathan Whitehorn * Clear local access windows. Skip DRAM entries, so we don't shoot 180302acc2eSNathan Whitehorn * ourselves in the foot. 181302acc2eSNathan Whitehorn */ 182302acc2eSNathan Whitehorn law_max = law_getmax(); 183302acc2eSNathan Whitehorn for (i = 0; i < law_max; i++) { 184302acc2eSNathan Whitehorn sr = ccsr_read4(OCP85XX_LAWSR(i)); 185302acc2eSNathan Whitehorn if ((sr & 0x80000000) == 0) 186302acc2eSNathan Whitehorn continue; 187302acc2eSNathan Whitehorn tgt = (sr & 0x01f00000) >> 20; 188302acc2eSNathan Whitehorn if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 || 189302acc2eSNathan Whitehorn tgt == OCP85XX_TGTIF_RAM_INTL) 190302acc2eSNathan Whitehorn continue; 191302acc2eSNathan Whitehorn 192302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_LAWSR(i), sr & 0x7fffffff); 193302acc2eSNathan Whitehorn } 194302acc2eSNathan Whitehorn 195302acc2eSNathan Whitehorn return (0); 196302acc2eSNathan Whitehorn } 197302acc2eSNathan Whitehorn 198302acc2eSNathan Whitehorn void 199c1cb22d7SNathan Whitehorn mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 200c1cb22d7SNathan Whitehorn struct mem_region *avail, int *availsz) 201302acc2eSNathan Whitehorn { 202302acc2eSNathan Whitehorn 203302acc2eSNathan Whitehorn ofw_mem_regions(phys, physsz, avail, availsz); 204302acc2eSNathan Whitehorn } 205302acc2eSNathan Whitehorn 206302acc2eSNathan Whitehorn static u_long 207302acc2eSNathan Whitehorn mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) 208302acc2eSNathan Whitehorn { 209302acc2eSNathan Whitehorn u_long ticks; 210302acc2eSNathan Whitehorn phandle_t cpus, child; 211302acc2eSNathan Whitehorn pcell_t freq; 212302acc2eSNathan Whitehorn 213302acc2eSNathan Whitehorn if (bootinfo != NULL) { 214302acc2eSNathan Whitehorn if (bootinfo[0] == 1) { 215302acc2eSNathan Whitehorn /* Backward compatibility. See 8-STABLE. */ 216302acc2eSNathan Whitehorn ticks = bootinfo[3] >> 3; 217302acc2eSNathan Whitehorn } else { 218302acc2eSNathan Whitehorn /* Compatibility with Juniper's loader. */ 219302acc2eSNathan Whitehorn ticks = bootinfo[5] >> 3; 220302acc2eSNathan Whitehorn } 221302acc2eSNathan Whitehorn } else 222302acc2eSNathan Whitehorn ticks = 0; 223302acc2eSNathan Whitehorn 224302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) == -1) 225302acc2eSNathan Whitehorn goto out; 226302acc2eSNathan Whitehorn 227302acc2eSNathan Whitehorn if ((child = OF_child(cpus)) == 0) 228302acc2eSNathan Whitehorn goto out; 229302acc2eSNathan Whitehorn 230302acc2eSNathan Whitehorn switch (OF_getproplen(child, "timebase-frequency")) { 231302acc2eSNathan Whitehorn case 4: 232302acc2eSNathan Whitehorn { 233302acc2eSNathan Whitehorn uint32_t tbase; 234302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 235302acc2eSNathan Whitehorn ticks = tbase; 236302acc2eSNathan Whitehorn return (ticks); 237302acc2eSNathan Whitehorn } 238302acc2eSNathan Whitehorn case 8: 239302acc2eSNathan Whitehorn { 240302acc2eSNathan Whitehorn uint64_t tbase; 241302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 242302acc2eSNathan Whitehorn ticks = tbase; 243302acc2eSNathan Whitehorn return (ticks); 244302acc2eSNathan Whitehorn } 245302acc2eSNathan Whitehorn default: 246302acc2eSNathan Whitehorn break; 247302acc2eSNathan Whitehorn } 248302acc2eSNathan Whitehorn 249302acc2eSNathan Whitehorn freq = 0; 250302acc2eSNathan Whitehorn if (OF_getprop(child, "bus-frequency", (void *)&freq, 251302acc2eSNathan Whitehorn sizeof(freq)) <= 0) 252302acc2eSNathan Whitehorn goto out; 253302acc2eSNathan Whitehorn 254302acc2eSNathan Whitehorn /* 255302acc2eSNathan Whitehorn * Time Base and Decrementer are updated every 8 CCB bus clocks. 256302acc2eSNathan Whitehorn * HID0[SEL_TBCLK] = 0 257302acc2eSNathan Whitehorn */ 258302acc2eSNathan Whitehorn if (freq != 0) 259302acc2eSNathan Whitehorn ticks = freq / 8; 260302acc2eSNathan Whitehorn 261302acc2eSNathan Whitehorn out: 262302acc2eSNathan Whitehorn if (ticks <= 0) 263302acc2eSNathan Whitehorn panic("Unable to determine timebase frequency!"); 264302acc2eSNathan Whitehorn 265302acc2eSNathan Whitehorn return (ticks); 266302acc2eSNathan Whitehorn } 267302acc2eSNathan Whitehorn 268302acc2eSNathan Whitehorn static int 269302acc2eSNathan Whitehorn mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 270302acc2eSNathan Whitehorn { 271302acc2eSNathan Whitehorn 272302acc2eSNathan Whitehorn cpu = 0; 273302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu; 274302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 275302acc2eSNathan Whitehorn if (bootverbose) 276302acc2eSNathan Whitehorn printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 277302acc2eSNathan Whitehorn cpu++; 278302acc2eSNathan Whitehorn 279302acc2eSNathan Whitehorn return (0); 280302acc2eSNathan Whitehorn } 281302acc2eSNathan Whitehorn 282302acc2eSNathan Whitehorn static int 283302acc2eSNathan Whitehorn mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 284302acc2eSNathan Whitehorn { 285302acc2eSNathan Whitehorn 286302acc2eSNathan Whitehorn if (cpu >= maxcpu) 287302acc2eSNathan Whitehorn return (ENOENT); 288302acc2eSNathan Whitehorn 289302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu++; 290302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 291302acc2eSNathan Whitehorn if (bootverbose) 292302acc2eSNathan Whitehorn printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 293302acc2eSNathan Whitehorn 294302acc2eSNathan Whitehorn return (0); 295302acc2eSNathan Whitehorn } 296302acc2eSNathan Whitehorn 297302acc2eSNathan Whitehorn static int 298302acc2eSNathan Whitehorn mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 299302acc2eSNathan Whitehorn { 300302acc2eSNathan Whitehorn 301302acc2eSNathan Whitehorn cpuref->cr_cpuid = mfspr(SPR_PIR); 302302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 303302acc2eSNathan Whitehorn 304302acc2eSNathan Whitehorn return (0); 305302acc2eSNathan Whitehorn } 306302acc2eSNathan Whitehorn 307302acc2eSNathan Whitehorn static int 308302acc2eSNathan Whitehorn mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) 309302acc2eSNathan Whitehorn { 310302acc2eSNathan Whitehorn #ifdef SMP 311302acc2eSNathan Whitehorn uint32_t *tlb1; 312302acc2eSNathan Whitehorn uint32_t bptr, eebpcr; 313302acc2eSNathan Whitehorn int i, timeout; 314302acc2eSNathan Whitehorn 315302acc2eSNathan Whitehorn eebpcr = ccsr_read4(OCP85XX_EEBPCR); 316302acc2eSNathan Whitehorn if ((eebpcr & (1 << (pc->pc_cpuid + 24))) != 0) { 317302acc2eSNathan Whitehorn printf("SMP: CPU %d already out of hold-off state!\n", 318302acc2eSNathan Whitehorn pc->pc_cpuid); 319302acc2eSNathan Whitehorn return (ENXIO); 320302acc2eSNathan Whitehorn } 321302acc2eSNathan Whitehorn 322302acc2eSNathan Whitehorn ap_pcpu = pc; 323302acc2eSNathan Whitehorn 324302acc2eSNathan Whitehorn i = 0; 325302acc2eSNathan Whitehorn tlb1 = bp_tlb1; 326302acc2eSNathan Whitehorn while (i < bp_ntlb1s && tlb1 < bp_tlb1_end) { 327302acc2eSNathan Whitehorn mtspr(SPR_MAS0, MAS0_TLBSEL(1) | MAS0_ESEL(i)); 328302acc2eSNathan Whitehorn __asm __volatile("isync; tlbre"); 329302acc2eSNathan Whitehorn tlb1[0] = mfspr(SPR_MAS1); 330302acc2eSNathan Whitehorn tlb1[1] = mfspr(SPR_MAS2); 331302acc2eSNathan Whitehorn tlb1[2] = mfspr(SPR_MAS3); 332302acc2eSNathan Whitehorn i++; 333302acc2eSNathan Whitehorn tlb1 += 3; 334302acc2eSNathan Whitehorn } 335302acc2eSNathan Whitehorn if (i < bp_ntlb1s) 336302acc2eSNathan Whitehorn bp_ntlb1s = i; 337302acc2eSNathan Whitehorn 338302acc2eSNathan Whitehorn /* 339302acc2eSNathan Whitehorn * Set BPTR to the physical address of the boot page 340302acc2eSNathan Whitehorn */ 341302acc2eSNathan Whitehorn bptr = ((uint32_t)__boot_page - KERNBASE) + kernload; 342302acc2eSNathan Whitehorn KASSERT((bptr & 0xfff) == 0, 343302acc2eSNathan Whitehorn ("%s: boot page is not aligned (%#x)", __func__, bptr)); 344302acc2eSNathan Whitehorn bptr = (bptr >> 12) | 0x80000000u; 345302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, bptr); 346302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 347302acc2eSNathan Whitehorn 348302acc2eSNathan Whitehorn /* Flush caches to have our changes hit DRAM. */ 349302acc2eSNathan Whitehorn cpu_flush_dcache(__boot_page, 4096); 350302acc2eSNathan Whitehorn 351302acc2eSNathan Whitehorn /* 352302acc2eSNathan Whitehorn * Release AP from hold-off state 353302acc2eSNathan Whitehorn */ 354302acc2eSNathan Whitehorn eebpcr |= (1 << (pc->pc_cpuid + 24)); 355302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_EEBPCR, eebpcr); 356302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 357302acc2eSNathan Whitehorn 358302acc2eSNathan Whitehorn timeout = 500; 359302acc2eSNathan Whitehorn while (!pc->pc_awake && timeout--) 360302acc2eSNathan Whitehorn DELAY(1000); /* wait 1ms */ 361302acc2eSNathan Whitehorn 362302acc2eSNathan Whitehorn /* 363302acc2eSNathan Whitehorn * Disable boot page translation so that the 4K page at the default 364302acc2eSNathan Whitehorn * address (= 0xfffff000) isn't permanently remapped and thus not 365302acc2eSNathan Whitehorn * usable otherwise. 366302acc2eSNathan Whitehorn */ 367302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, 0); 368302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 369302acc2eSNathan Whitehorn 370302acc2eSNathan Whitehorn if (!pc->pc_awake) 371302acc2eSNathan Whitehorn printf("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); 372302acc2eSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 373302acc2eSNathan Whitehorn #else 374302acc2eSNathan Whitehorn /* No SMP support */ 375302acc2eSNathan Whitehorn return (ENXIO); 376302acc2eSNathan Whitehorn #endif 377302acc2eSNathan Whitehorn } 378302acc2eSNathan Whitehorn 379302acc2eSNathan Whitehorn static void 380302acc2eSNathan Whitehorn mpc85xx_reset(platform_t plat) 381302acc2eSNathan Whitehorn { 382302acc2eSNathan Whitehorn 383302acc2eSNathan Whitehorn /* 384302acc2eSNathan Whitehorn * Try the dedicated reset register first. 385302acc2eSNathan Whitehorn * If the SoC doesn't have one, we'll fall 386302acc2eSNathan Whitehorn * back to using the debug control register. 387302acc2eSNathan Whitehorn */ 388302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_RSTCR, 2); 389302acc2eSNathan Whitehorn 390302acc2eSNathan Whitehorn /* Clear DBCR0, disables debug interrupts and events. */ 391302acc2eSNathan Whitehorn mtspr(SPR_DBCR0, 0); 392302acc2eSNathan Whitehorn __asm __volatile("isync"); 393302acc2eSNathan Whitehorn 394302acc2eSNathan Whitehorn /* Enable Debug Interrupts in MSR. */ 395302acc2eSNathan Whitehorn mtmsr(mfmsr() | PSL_DE); 396302acc2eSNathan Whitehorn 397302acc2eSNathan Whitehorn /* Enable debug interrupts and issue reset. */ 398302acc2eSNathan Whitehorn mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM); 399302acc2eSNathan Whitehorn 400302acc2eSNathan Whitehorn printf("Reset failed...\n"); 401302acc2eSNathan Whitehorn while (1) 402302acc2eSNathan Whitehorn ; 403302acc2eSNathan Whitehorn } 404302acc2eSNathan Whitehorn 405