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 273f068cbfSJustin Hibbits #include "opt_platform.h" 28302acc2eSNathan Whitehorn #include <sys/cdefs.h> 29302acc2eSNathan Whitehorn __FBSDID("$FreeBSD$"); 30302acc2eSNathan Whitehorn 31302acc2eSNathan Whitehorn #include <sys/param.h> 32302acc2eSNathan Whitehorn #include <sys/systm.h> 33302acc2eSNathan Whitehorn #include <sys/kernel.h> 34302acc2eSNathan Whitehorn #include <sys/bus.h> 35302acc2eSNathan Whitehorn #include <sys/pcpu.h> 36302acc2eSNathan Whitehorn #include <sys/proc.h> 37302acc2eSNathan Whitehorn #include <sys/smp.h> 38302acc2eSNathan Whitehorn 39302acc2eSNathan Whitehorn #include <machine/bus.h> 40302acc2eSNathan Whitehorn #include <machine/cpu.h> 41302acc2eSNathan Whitehorn #include <machine/hid.h> 423f068cbfSJustin Hibbits #include <machine/machdep.h> 43302acc2eSNathan Whitehorn #include <machine/platform.h> 44302acc2eSNathan Whitehorn #include <machine/platformvar.h> 45302acc2eSNathan Whitehorn #include <machine/smp.h> 46302acc2eSNathan Whitehorn #include <machine/spr.h> 47302acc2eSNathan Whitehorn #include <machine/vmparam.h> 48302acc2eSNathan Whitehorn 49302acc2eSNathan Whitehorn #include <dev/fdt/fdt_common.h> 50302acc2eSNathan Whitehorn #include <dev/ofw/ofw_bus.h> 51302acc2eSNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 52302acc2eSNathan Whitehorn #include <dev/ofw/openfirm.h> 53302acc2eSNathan Whitehorn 5452cfe485SNathan Whitehorn #include <vm/vm.h> 5552cfe485SNathan Whitehorn #include <vm/pmap.h> 5652cfe485SNathan Whitehorn 57302acc2eSNathan Whitehorn #include <powerpc/mpc85xx/mpc85xx.h> 58302acc2eSNathan Whitehorn 59302acc2eSNathan Whitehorn #include "platform_if.h" 60302acc2eSNathan Whitehorn 61302acc2eSNathan Whitehorn #ifdef SMP 62302acc2eSNathan Whitehorn extern void *ap_pcpu; 63302acc2eSNathan Whitehorn extern vm_paddr_t kernload; /* Kernel physical load address */ 64302acc2eSNathan Whitehorn extern uint8_t __boot_page[]; /* Boot page body */ 65*f60708c9SJustin Hibbits extern uint32_t bp_kernload; 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); 81637f34cbSJustin Hibbits static void mpc85xx_idle(platform_t, int cpu); 82637f34cbSJustin Hibbits static int mpc85xx_idle_wakeup(platform_t plat, int cpu); 83302acc2eSNathan Whitehorn 84302acc2eSNathan Whitehorn static void mpc85xx_reset(platform_t); 85302acc2eSNathan Whitehorn 86302acc2eSNathan Whitehorn static platform_method_t mpc85xx_methods[] = { 87302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_probe, mpc85xx_probe), 88302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_attach, mpc85xx_attach), 89302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions), 90302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq), 91302acc2eSNathan Whitehorn 92302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu), 93302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu), 94302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp), 95302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), 96302acc2eSNathan Whitehorn 97302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_reset, mpc85xx_reset), 98637f34cbSJustin Hibbits PLATFORMMETHOD(platform_idle, mpc85xx_idle), 99637f34cbSJustin Hibbits PLATFORMMETHOD(platform_idle_wakeup, mpc85xx_idle_wakeup), 100302acc2eSNathan Whitehorn 101302acc2eSNathan Whitehorn PLATFORMMETHOD_END 102302acc2eSNathan Whitehorn }; 103302acc2eSNathan Whitehorn 104fa7a1ca7SJustin Hibbits DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0); 105302acc2eSNathan Whitehorn 106302acc2eSNathan Whitehorn PLATFORM_DEF(mpc85xx_platform); 107302acc2eSNathan Whitehorn 108302acc2eSNathan Whitehorn static int 109302acc2eSNathan Whitehorn mpc85xx_probe(platform_t plat) 110302acc2eSNathan Whitehorn { 111302acc2eSNathan Whitehorn u_int pvr = mfpvr() >> 16; 112302acc2eSNathan Whitehorn 113302acc2eSNathan Whitehorn if ((pvr & 0xfff0) == FSL_E500v1) 114302acc2eSNathan Whitehorn return (BUS_PROBE_DEFAULT); 115302acc2eSNathan Whitehorn 116302acc2eSNathan Whitehorn return (ENXIO); 117302acc2eSNathan Whitehorn } 118302acc2eSNathan Whitehorn 119fa7a1ca7SJustin Hibbits int 120302acc2eSNathan Whitehorn mpc85xx_attach(platform_t plat) 121302acc2eSNathan Whitehorn { 12252cfe485SNathan Whitehorn phandle_t cpus, child, ccsr; 12352cfe485SNathan Whitehorn const char *soc_name_guesses[] = {"/soc", "soc", NULL}; 12452cfe485SNathan Whitehorn const char **name; 12552cfe485SNathan Whitehorn pcell_t ranges[6], acells, pacells, scells; 126302acc2eSNathan Whitehorn uint32_t sr; 12752cfe485SNathan Whitehorn uint64_t ccsrbar, ccsrsize; 128302acc2eSNathan Whitehorn int i, law_max, tgt; 129302acc2eSNathan Whitehorn 130302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) != -1) { 131302acc2eSNathan Whitehorn for (maxcpu = 0, child = OF_child(cpus); child != 0; 132302acc2eSNathan Whitehorn child = OF_peer(child), maxcpu++) 133302acc2eSNathan Whitehorn ; 134302acc2eSNathan Whitehorn } else 135302acc2eSNathan Whitehorn maxcpu = 1; 136302acc2eSNathan Whitehorn 137302acc2eSNathan Whitehorn /* 13852cfe485SNathan Whitehorn * Locate CCSR region. Irritatingly, there is no way to find it 13952cfe485SNathan Whitehorn * unless you already know where it is. Try to infer its location 14052cfe485SNathan Whitehorn * from the device tree. 14152cfe485SNathan Whitehorn */ 14252cfe485SNathan Whitehorn 14352cfe485SNathan Whitehorn ccsr = -1; 14452cfe485SNathan Whitehorn for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++) 14552cfe485SNathan Whitehorn ccsr = OF_finddevice(*name); 14652cfe485SNathan Whitehorn if (ccsr == -1) { 14752cfe485SNathan Whitehorn char type[64]; 14852cfe485SNathan Whitehorn 14952cfe485SNathan Whitehorn /* That didn't work. Search for devices of type "soc" */ 15052cfe485SNathan Whitehorn child = OF_child(OF_peer(0)); 15152cfe485SNathan Whitehorn for (OF_child(child); child != 0; child = OF_peer(child)) { 15252cfe485SNathan Whitehorn if (OF_getprop(child, "device_type", type, sizeof(type)) 15352cfe485SNathan Whitehorn <= 0) 15452cfe485SNathan Whitehorn continue; 15552cfe485SNathan Whitehorn 15652cfe485SNathan Whitehorn if (strcmp(type, "soc") == 0) { 15752cfe485SNathan Whitehorn ccsr = child; 15852cfe485SNathan Whitehorn break; 15952cfe485SNathan Whitehorn } 16052cfe485SNathan Whitehorn } 16152cfe485SNathan Whitehorn } 16252cfe485SNathan Whitehorn 16352cfe485SNathan Whitehorn if (ccsr == -1) 16452cfe485SNathan Whitehorn panic("Could not locate CCSR window!"); 16552cfe485SNathan Whitehorn 16652cfe485SNathan Whitehorn OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells)); 16752cfe485SNathan Whitehorn OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells)); 16852cfe485SNathan Whitehorn OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells, 16952cfe485SNathan Whitehorn sizeof(pacells)); 17052cfe485SNathan Whitehorn OF_getprop(ccsr, "ranges", ranges, sizeof(ranges)); 17152cfe485SNathan Whitehorn ccsrbar = ccsrsize = 0; 17252cfe485SNathan Whitehorn for (i = acells; i < acells + pacells; i++) { 17352cfe485SNathan Whitehorn ccsrbar <<= 32; 17452cfe485SNathan Whitehorn ccsrbar |= ranges[i]; 17552cfe485SNathan Whitehorn } 17652cfe485SNathan Whitehorn for (i = acells + pacells; i < acells + pacells + scells; i++) { 17752cfe485SNathan Whitehorn ccsrsize <<= 32; 17852cfe485SNathan Whitehorn ccsrsize |= ranges[i]; 17952cfe485SNathan Whitehorn } 18052cfe485SNathan Whitehorn ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); 18152cfe485SNathan Whitehorn 1823f068cbfSJustin Hibbits mpc85xx_fix_errata(ccsrbar_va); 1833f068cbfSJustin Hibbits mpc85xx_enable_l3_cache(); 1843f068cbfSJustin Hibbits 18552cfe485SNathan Whitehorn /* 186302acc2eSNathan Whitehorn * Clear local access windows. Skip DRAM entries, so we don't shoot 187302acc2eSNathan Whitehorn * ourselves in the foot. 188302acc2eSNathan Whitehorn */ 189302acc2eSNathan Whitehorn law_max = law_getmax(); 190302acc2eSNathan Whitehorn for (i = 0; i < law_max; i++) { 191302acc2eSNathan Whitehorn sr = ccsr_read4(OCP85XX_LAWSR(i)); 1923f068cbfSJustin Hibbits if ((sr & OCP85XX_ENA_MASK) == 0) 193302acc2eSNathan Whitehorn continue; 194302acc2eSNathan Whitehorn tgt = (sr & 0x01f00000) >> 20; 195302acc2eSNathan Whitehorn if (tgt == OCP85XX_TGTIF_RAM1 || tgt == OCP85XX_TGTIF_RAM2 || 196302acc2eSNathan Whitehorn tgt == OCP85XX_TGTIF_RAM_INTL) 197302acc2eSNathan Whitehorn continue; 198302acc2eSNathan Whitehorn 1993f068cbfSJustin Hibbits ccsr_write4(OCP85XX_LAWSR(i), sr & OCP85XX_DIS_MASK); 200302acc2eSNathan Whitehorn } 201302acc2eSNathan Whitehorn 202302acc2eSNathan Whitehorn return (0); 203302acc2eSNathan Whitehorn } 204302acc2eSNathan Whitehorn 205302acc2eSNathan Whitehorn void 206c1cb22d7SNathan Whitehorn mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 207c1cb22d7SNathan Whitehorn struct mem_region *avail, int *availsz) 208302acc2eSNathan Whitehorn { 209302acc2eSNathan Whitehorn 210302acc2eSNathan Whitehorn ofw_mem_regions(phys, physsz, avail, availsz); 211302acc2eSNathan Whitehorn } 212302acc2eSNathan Whitehorn 213302acc2eSNathan Whitehorn static u_long 214302acc2eSNathan Whitehorn mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) 215302acc2eSNathan Whitehorn { 216302acc2eSNathan Whitehorn u_long ticks; 217302acc2eSNathan Whitehorn phandle_t cpus, child; 218302acc2eSNathan Whitehorn pcell_t freq; 219302acc2eSNathan Whitehorn 220302acc2eSNathan Whitehorn if (bootinfo != NULL) { 221302acc2eSNathan Whitehorn if (bootinfo[0] == 1) { 222302acc2eSNathan Whitehorn /* Backward compatibility. See 8-STABLE. */ 223302acc2eSNathan Whitehorn ticks = bootinfo[3] >> 3; 224302acc2eSNathan Whitehorn } else { 225302acc2eSNathan Whitehorn /* Compatibility with Juniper's loader. */ 226302acc2eSNathan Whitehorn ticks = bootinfo[5] >> 3; 227302acc2eSNathan Whitehorn } 228302acc2eSNathan Whitehorn } else 229302acc2eSNathan Whitehorn ticks = 0; 230302acc2eSNathan Whitehorn 231302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) == -1) 232302acc2eSNathan Whitehorn goto out; 233302acc2eSNathan Whitehorn 234302acc2eSNathan Whitehorn if ((child = OF_child(cpus)) == 0) 235302acc2eSNathan Whitehorn goto out; 236302acc2eSNathan Whitehorn 237302acc2eSNathan Whitehorn switch (OF_getproplen(child, "timebase-frequency")) { 238302acc2eSNathan Whitehorn case 4: 239302acc2eSNathan Whitehorn { 240302acc2eSNathan Whitehorn uint32_t tbase; 241302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 242302acc2eSNathan Whitehorn ticks = tbase; 243302acc2eSNathan Whitehorn return (ticks); 244302acc2eSNathan Whitehorn } 245302acc2eSNathan Whitehorn case 8: 246302acc2eSNathan Whitehorn { 247302acc2eSNathan Whitehorn uint64_t tbase; 248302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 249302acc2eSNathan Whitehorn ticks = tbase; 250302acc2eSNathan Whitehorn return (ticks); 251302acc2eSNathan Whitehorn } 252302acc2eSNathan Whitehorn default: 253302acc2eSNathan Whitehorn break; 254302acc2eSNathan Whitehorn } 255302acc2eSNathan Whitehorn 256302acc2eSNathan Whitehorn freq = 0; 257302acc2eSNathan Whitehorn if (OF_getprop(child, "bus-frequency", (void *)&freq, 258302acc2eSNathan Whitehorn sizeof(freq)) <= 0) 259302acc2eSNathan Whitehorn goto out; 260302acc2eSNathan Whitehorn 261302acc2eSNathan Whitehorn /* 262302acc2eSNathan Whitehorn * Time Base and Decrementer are updated every 8 CCB bus clocks. 263302acc2eSNathan Whitehorn * HID0[SEL_TBCLK] = 0 264302acc2eSNathan Whitehorn */ 265302acc2eSNathan Whitehorn if (freq != 0) 2663f068cbfSJustin Hibbits #ifdef QORIQ_DPAA 2673f068cbfSJustin Hibbits ticks = freq / 32; 2683f068cbfSJustin Hibbits #else 269302acc2eSNathan Whitehorn ticks = freq / 8; 2703f068cbfSJustin Hibbits #endif 271302acc2eSNathan Whitehorn 272302acc2eSNathan Whitehorn out: 273302acc2eSNathan Whitehorn if (ticks <= 0) 274302acc2eSNathan Whitehorn panic("Unable to determine timebase frequency!"); 275302acc2eSNathan Whitehorn 276302acc2eSNathan Whitehorn return (ticks); 277302acc2eSNathan Whitehorn } 278302acc2eSNathan Whitehorn 279302acc2eSNathan Whitehorn static int 280302acc2eSNathan Whitehorn mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 281302acc2eSNathan Whitehorn { 282302acc2eSNathan Whitehorn 283302acc2eSNathan Whitehorn cpu = 0; 284302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu; 285302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 286302acc2eSNathan Whitehorn if (bootverbose) 287302acc2eSNathan Whitehorn printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 288302acc2eSNathan Whitehorn cpu++; 289302acc2eSNathan Whitehorn 290302acc2eSNathan Whitehorn return (0); 291302acc2eSNathan Whitehorn } 292302acc2eSNathan Whitehorn 293302acc2eSNathan Whitehorn static int 294302acc2eSNathan Whitehorn mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 295302acc2eSNathan Whitehorn { 296302acc2eSNathan Whitehorn 297302acc2eSNathan Whitehorn if (cpu >= maxcpu) 298302acc2eSNathan Whitehorn return (ENOENT); 299302acc2eSNathan Whitehorn 300302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu++; 301302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 302302acc2eSNathan Whitehorn if (bootverbose) 303302acc2eSNathan Whitehorn printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 304302acc2eSNathan Whitehorn 305302acc2eSNathan Whitehorn return (0); 306302acc2eSNathan Whitehorn } 307302acc2eSNathan Whitehorn 308302acc2eSNathan Whitehorn static int 309302acc2eSNathan Whitehorn mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 310302acc2eSNathan Whitehorn { 311302acc2eSNathan Whitehorn 312302acc2eSNathan Whitehorn cpuref->cr_cpuid = mfspr(SPR_PIR); 313302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 314302acc2eSNathan Whitehorn 315302acc2eSNathan Whitehorn return (0); 316302acc2eSNathan Whitehorn } 317302acc2eSNathan Whitehorn 318302acc2eSNathan Whitehorn static int 319302acc2eSNathan Whitehorn mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) 320302acc2eSNathan Whitehorn { 321302acc2eSNathan Whitehorn #ifdef SMP 3223f068cbfSJustin Hibbits vm_paddr_t bptr; 3233f068cbfSJustin Hibbits uint32_t reg; 324*f60708c9SJustin Hibbits int timeout; 3253f068cbfSJustin Hibbits uintptr_t brr; 3263f068cbfSJustin Hibbits int cpuid; 327302acc2eSNathan Whitehorn 3283f068cbfSJustin Hibbits #ifdef QORIQ_DPAA 3293f068cbfSJustin Hibbits uint32_t tgt; 3303f068cbfSJustin Hibbits 3313f068cbfSJustin Hibbits reg = ccsr_read4(OCP85XX_COREDISR); 3323f068cbfSJustin Hibbits cpuid = pc->pc_cpuid; 3333f068cbfSJustin Hibbits 3343f068cbfSJustin Hibbits if ((reg & cpuid) != 0) { 3353f068cbfSJustin Hibbits printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid); 3363f068cbfSJustin Hibbits return (-1); 3373f068cbfSJustin Hibbits } 3383f068cbfSJustin Hibbits 3393f068cbfSJustin Hibbits brr = OCP85XX_BRR; 3403f068cbfSJustin Hibbits #else /* QORIQ_DPAA */ 3413f068cbfSJustin Hibbits brr = OCP85XX_EEBPCR; 3423f068cbfSJustin Hibbits cpuid = pc->pc_cpuid + 24; 3433f068cbfSJustin Hibbits #endif 344*f60708c9SJustin Hibbits bp_kernload = kernload; 3453f068cbfSJustin Hibbits reg = ccsr_read4(brr); 3463f068cbfSJustin Hibbits if ((reg & (1 << cpuid)) != 0) { 347302acc2eSNathan Whitehorn printf("SMP: CPU %d already out of hold-off state!\n", 348302acc2eSNathan Whitehorn pc->pc_cpuid); 349302acc2eSNathan Whitehorn return (ENXIO); 350302acc2eSNathan Whitehorn } 351302acc2eSNathan Whitehorn 352302acc2eSNathan Whitehorn ap_pcpu = pc; 3533f068cbfSJustin Hibbits __asm __volatile("msync; isync"); 354302acc2eSNathan Whitehorn 3553f068cbfSJustin Hibbits /* Flush caches to have our changes hit DRAM. */ 3563f068cbfSJustin Hibbits cpu_flush_dcache(__boot_page, 4096); 3573f068cbfSJustin Hibbits 3583f068cbfSJustin Hibbits bptr = ((vm_paddr_t)(uintptr_t)__boot_page - KERNBASE) + kernload; 3593f068cbfSJustin Hibbits KASSERT((bptr & 0xfff) == 0, 3603f068cbfSJustin Hibbits ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr)); 3613f068cbfSJustin Hibbits #ifdef QORIQ_DPAA 3623f068cbfSJustin Hibbits 3633f068cbfSJustin Hibbits /* 3643f068cbfSJustin Hibbits * Read DDR controller configuration to select proper BPTR target ID. 3653f068cbfSJustin Hibbits * 3663f068cbfSJustin Hibbits * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers 3673f068cbfSJustin Hibbits * interleaving. If this bit is set, we have to use 3683f068cbfSJustin Hibbits * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs, 3693f068cbfSJustin Hibbits * this bit is reserved and always 0. 3703f068cbfSJustin Hibbits */ 3713f068cbfSJustin Hibbits 3723f068cbfSJustin Hibbits reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG); 3733f068cbfSJustin Hibbits if (reg & (1 << 29)) 3743f068cbfSJustin Hibbits tgt = OCP85XX_TGTIF_RAM_INTL; 3753f068cbfSJustin Hibbits else 3763f068cbfSJustin Hibbits tgt = OCP85XX_TGTIF_RAM1; 3773f068cbfSJustin Hibbits 3783f068cbfSJustin Hibbits /* 3793f068cbfSJustin Hibbits * Set BSTR to the physical address of the boot page 3803f068cbfSJustin Hibbits */ 3813f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTRH, bptr >> 32); 3823f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTRL, bptr); 3833f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK | 3843f068cbfSJustin Hibbits (tgt << OCP85XX_TRGT_SHIFT) | (ffsl(PAGE_SIZE) - 2)); 3853f068cbfSJustin Hibbits 3863f068cbfSJustin Hibbits /* Read back OCP85XX_BSTAR to synchronize write */ 3873f068cbfSJustin Hibbits ccsr_read4(OCP85XX_BSTAR); 3883f068cbfSJustin Hibbits 3893f068cbfSJustin Hibbits /* 3903f068cbfSJustin Hibbits * Enable and configure time base on new CPU. 3913f068cbfSJustin Hibbits */ 3923f068cbfSJustin Hibbits 3933f068cbfSJustin Hibbits /* Set TB clock source to platform clock / 32 */ 3943f068cbfSJustin Hibbits reg = ccsr_read4(CCSR_CTBCKSELR); 3953f068cbfSJustin Hibbits ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid)); 3963f068cbfSJustin Hibbits 3973f068cbfSJustin Hibbits /* Enable TB */ 3983f068cbfSJustin Hibbits reg = ccsr_read4(CCSR_CTBENR); 3993f068cbfSJustin Hibbits ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid)); 4003f068cbfSJustin Hibbits #else 4013f068cbfSJustin Hibbits 402302acc2eSNathan Whitehorn /* 403302acc2eSNathan Whitehorn * Set BPTR to the physical address of the boot page 404302acc2eSNathan Whitehorn */ 405302acc2eSNathan Whitehorn bptr = (bptr >> 12) | 0x80000000u; 406302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, bptr); 407302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 408302acc2eSNathan Whitehorn 4093f068cbfSJustin Hibbits #endif /* QORIQ_DPAA */ 410302acc2eSNathan Whitehorn 411302acc2eSNathan Whitehorn /* 412302acc2eSNathan Whitehorn * Release AP from hold-off state 413302acc2eSNathan Whitehorn */ 4143f068cbfSJustin Hibbits reg = ccsr_read4(brr); 4153f068cbfSJustin Hibbits ccsr_write4(brr, reg | (1 << cpuid)); 416302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 417302acc2eSNathan Whitehorn 418302acc2eSNathan Whitehorn timeout = 500; 419302acc2eSNathan Whitehorn while (!pc->pc_awake && timeout--) 420302acc2eSNathan Whitehorn DELAY(1000); /* wait 1ms */ 421302acc2eSNathan Whitehorn 422302acc2eSNathan Whitehorn /* 423302acc2eSNathan Whitehorn * Disable boot page translation so that the 4K page at the default 424302acc2eSNathan Whitehorn * address (= 0xfffff000) isn't permanently remapped and thus not 425302acc2eSNathan Whitehorn * usable otherwise. 426302acc2eSNathan Whitehorn */ 4273f068cbfSJustin Hibbits #ifdef QORIQ_DPAA 4283f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTAR, 0); 4293f068cbfSJustin Hibbits #else 430302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, 0); 4313f068cbfSJustin Hibbits #endif 432302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 433302acc2eSNathan Whitehorn 434302acc2eSNathan Whitehorn if (!pc->pc_awake) 435302acc2eSNathan Whitehorn printf("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); 436302acc2eSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 437302acc2eSNathan Whitehorn #else 438302acc2eSNathan Whitehorn /* No SMP support */ 439302acc2eSNathan Whitehorn return (ENXIO); 440302acc2eSNathan Whitehorn #endif 441302acc2eSNathan Whitehorn } 442302acc2eSNathan Whitehorn 443302acc2eSNathan Whitehorn static void 444302acc2eSNathan Whitehorn mpc85xx_reset(platform_t plat) 445302acc2eSNathan Whitehorn { 446302acc2eSNathan Whitehorn 447302acc2eSNathan Whitehorn /* 448302acc2eSNathan Whitehorn * Try the dedicated reset register first. 449302acc2eSNathan Whitehorn * If the SoC doesn't have one, we'll fall 450302acc2eSNathan Whitehorn * back to using the debug control register. 451302acc2eSNathan Whitehorn */ 452302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_RSTCR, 2); 453302acc2eSNathan Whitehorn 454302acc2eSNathan Whitehorn /* Clear DBCR0, disables debug interrupts and events. */ 455302acc2eSNathan Whitehorn mtspr(SPR_DBCR0, 0); 456302acc2eSNathan Whitehorn __asm __volatile("isync"); 457302acc2eSNathan Whitehorn 458302acc2eSNathan Whitehorn /* Enable Debug Interrupts in MSR. */ 459302acc2eSNathan Whitehorn mtmsr(mfmsr() | PSL_DE); 460302acc2eSNathan Whitehorn 461302acc2eSNathan Whitehorn /* Enable debug interrupts and issue reset. */ 462302acc2eSNathan Whitehorn mtspr(SPR_DBCR0, mfspr(SPR_DBCR0) | DBCR0_IDM | DBCR0_RST_SYSTEM); 463302acc2eSNathan Whitehorn 464302acc2eSNathan Whitehorn printf("Reset failed...\n"); 465302acc2eSNathan Whitehorn while (1) 466302acc2eSNathan Whitehorn ; 467302acc2eSNathan Whitehorn } 468302acc2eSNathan Whitehorn 469637f34cbSJustin Hibbits static void 470637f34cbSJustin Hibbits mpc85xx_idle(platform_t plat, int cpu) 471637f34cbSJustin Hibbits { 472637f34cbSJustin Hibbits #ifdef QORIQ_DPAA 473637f34cbSJustin Hibbits uint32_t reg; 474637f34cbSJustin Hibbits 475637f34cbSJustin Hibbits reg = ccsr_read4(OCP85XX_RCPM_CDOZCR); 476637f34cbSJustin Hibbits ccsr_write4(OCP85XX_RCPM_CDOZCR, reg | (1 << cpu)); 477637f34cbSJustin Hibbits ccsr_read4(OCP85XX_RCPM_CDOZCR); 478637f34cbSJustin Hibbits #else 479637f34cbSJustin Hibbits register_t msr; 480637f34cbSJustin Hibbits 481637f34cbSJustin Hibbits msr = mfmsr(); 482637f34cbSJustin Hibbits /* Freescale E500 core RM section 6.4.1. */ 483637f34cbSJustin Hibbits __asm __volatile("msync; mtmsr %0; isync" :: 484637f34cbSJustin Hibbits "r" (msr | PSL_WE)); 485637f34cbSJustin Hibbits #endif 486637f34cbSJustin Hibbits } 487637f34cbSJustin Hibbits 488637f34cbSJustin Hibbits static int 489637f34cbSJustin Hibbits mpc85xx_idle_wakeup(platform_t plat, int cpu) 490637f34cbSJustin Hibbits { 491637f34cbSJustin Hibbits #ifdef QORIQ_DPAA 492637f34cbSJustin Hibbits uint32_t reg; 493637f34cbSJustin Hibbits 494637f34cbSJustin Hibbits reg = ccsr_read4(OCP85XX_RCPM_CDOZCR); 495637f34cbSJustin Hibbits ccsr_write4(OCP85XX_RCPM_CDOZCR, reg & ~(1 << cpu)); 496637f34cbSJustin Hibbits ccsr_read4(OCP85XX_RCPM_CDOZCR); 497637f34cbSJustin Hibbits 498637f34cbSJustin Hibbits return (1); 499637f34cbSJustin Hibbits #endif 500637f34cbSJustin Hibbits return (0); 501637f34cbSJustin Hibbits } 502