1302acc2eSNathan Whitehorn /*- 271e3c308SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 371e3c308SPedro F. Giffuni * 4302acc2eSNathan Whitehorn * Copyright (c) 2008-2012 Semihalf. 5302acc2eSNathan Whitehorn * All rights reserved. 6302acc2eSNathan Whitehorn * 7302acc2eSNathan Whitehorn * Redistribution and use in source and binary forms, with or without 8302acc2eSNathan Whitehorn * modification, are permitted provided that the following conditions 9302acc2eSNathan Whitehorn * are met: 10302acc2eSNathan Whitehorn * 11302acc2eSNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 12302acc2eSNathan Whitehorn * notice, this list of conditions and the following disclaimer. 13302acc2eSNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 14302acc2eSNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 15302acc2eSNathan Whitehorn * documentation and/or other materials provided with the distribution. 16302acc2eSNathan Whitehorn * 17302acc2eSNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18302acc2eSNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19302acc2eSNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20302acc2eSNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21302acc2eSNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22302acc2eSNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23302acc2eSNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24302acc2eSNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25302acc2eSNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26302acc2eSNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27302acc2eSNathan Whitehorn */ 28302acc2eSNathan Whitehorn 293f068cbfSJustin Hibbits #include "opt_platform.h" 30302acc2eSNathan Whitehorn #include <sys/cdefs.h> 31302acc2eSNathan Whitehorn __FBSDID("$FreeBSD$"); 32302acc2eSNathan Whitehorn 33302acc2eSNathan Whitehorn #include <sys/param.h> 34302acc2eSNathan Whitehorn #include <sys/systm.h> 35302acc2eSNathan Whitehorn #include <sys/kernel.h> 360d69f00bSJustin Hibbits #include <sys/module.h> 37302acc2eSNathan Whitehorn #include <sys/bus.h> 38302acc2eSNathan Whitehorn #include <sys/pcpu.h> 39302acc2eSNathan Whitehorn #include <sys/proc.h> 40302acc2eSNathan Whitehorn #include <sys/smp.h> 41302acc2eSNathan Whitehorn 42302acc2eSNathan Whitehorn #include <machine/bus.h> 43302acc2eSNathan Whitehorn #include <machine/cpu.h> 44302acc2eSNathan Whitehorn #include <machine/hid.h> 45253902b4SJustin Hibbits #include <machine/_inttypes.h> 463f068cbfSJustin Hibbits #include <machine/machdep.h> 47253902b4SJustin Hibbits #include <machine/md_var.h> 48302acc2eSNathan Whitehorn #include <machine/platform.h> 49302acc2eSNathan Whitehorn #include <machine/platformvar.h> 50302acc2eSNathan Whitehorn #include <machine/smp.h> 51302acc2eSNathan Whitehorn #include <machine/spr.h> 52302acc2eSNathan Whitehorn #include <machine/vmparam.h> 53302acc2eSNathan Whitehorn 54302acc2eSNathan Whitehorn #include <dev/fdt/fdt_common.h> 55302acc2eSNathan Whitehorn #include <dev/ofw/ofw_bus.h> 56302acc2eSNathan Whitehorn #include <dev/ofw/ofw_bus_subr.h> 57302acc2eSNathan Whitehorn #include <dev/ofw/openfirm.h> 58302acc2eSNathan Whitehorn 5952cfe485SNathan Whitehorn #include <vm/vm.h> 6052cfe485SNathan Whitehorn #include <vm/pmap.h> 61253902b4SJustin Hibbits #include <vm/vm_extern.h> 6252cfe485SNathan Whitehorn 63302acc2eSNathan Whitehorn #include <powerpc/mpc85xx/mpc85xx.h> 64302acc2eSNathan Whitehorn 65302acc2eSNathan Whitehorn #include "platform_if.h" 66302acc2eSNathan Whitehorn 67302acc2eSNathan Whitehorn #ifdef SMP 68302acc2eSNathan Whitehorn extern void *ap_pcpu; 69302acc2eSNathan Whitehorn extern vm_paddr_t kernload; /* Kernel physical load address */ 70302acc2eSNathan Whitehorn extern uint8_t __boot_page[]; /* Boot page body */ 71f60708c9SJustin Hibbits extern uint32_t bp_kernload; 72ea32838aSJustin Hibbits extern vm_offset_t __startkernel; 73253902b4SJustin Hibbits 74253902b4SJustin Hibbits struct cpu_release { 75253902b4SJustin Hibbits uint32_t entry_h; 76253902b4SJustin Hibbits uint32_t entry_l; 77253902b4SJustin Hibbits uint32_t r3_h; 78253902b4SJustin Hibbits uint32_t r3_l; 79253902b4SJustin Hibbits uint32_t reserved; 80253902b4SJustin Hibbits uint32_t pir; 81253902b4SJustin Hibbits }; 82302acc2eSNathan Whitehorn #endif 83302acc2eSNathan Whitehorn 84302acc2eSNathan Whitehorn extern uint32_t *bootinfo; 85b2f831c0SJustin Hibbits vm_paddr_t ccsrbar_pa; 8652cfe485SNathan Whitehorn vm_offset_t ccsrbar_va; 87b2f831c0SJustin Hibbits vm_size_t ccsrbar_size; 88302acc2eSNathan Whitehorn 89302acc2eSNathan Whitehorn static int cpu, maxcpu; 90302acc2eSNathan Whitehorn 910d69f00bSJustin Hibbits static device_t rcpm_dev; 920d69f00bSJustin Hibbits static void dummy_freeze(device_t, bool); 930d69f00bSJustin Hibbits 940d69f00bSJustin Hibbits static void (*freeze_timebase)(device_t, bool) = dummy_freeze; 950d69f00bSJustin Hibbits 96302acc2eSNathan Whitehorn static int mpc85xx_probe(platform_t); 97c1cb22d7SNathan Whitehorn static void mpc85xx_mem_regions(platform_t, struct mem_region *phys, 98c1cb22d7SNathan Whitehorn int *physsz, struct mem_region *avail, int *availsz); 99302acc2eSNathan Whitehorn static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref); 100302acc2eSNathan Whitehorn static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref); 101302acc2eSNathan Whitehorn static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref); 102302acc2eSNathan Whitehorn static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref); 103302acc2eSNathan Whitehorn static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu); 104de2dd83fSNathan Whitehorn static void mpc85xx_smp_timebase_sync(platform_t, u_long tb, int ap); 105302acc2eSNathan Whitehorn 106302acc2eSNathan Whitehorn static void mpc85xx_reset(platform_t); 107302acc2eSNathan Whitehorn 108302acc2eSNathan Whitehorn static platform_method_t mpc85xx_methods[] = { 109302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_probe, mpc85xx_probe), 110302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_attach, mpc85xx_attach), 111302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions), 112302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq), 113302acc2eSNathan Whitehorn 114302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu), 115302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu), 116302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp), 117302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), 118de2dd83fSNathan Whitehorn PLATFORMMETHOD(platform_smp_timebase_sync, mpc85xx_smp_timebase_sync), 119302acc2eSNathan Whitehorn 120302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_reset, mpc85xx_reset), 121302acc2eSNathan Whitehorn 122302acc2eSNathan Whitehorn PLATFORMMETHOD_END 123302acc2eSNathan Whitehorn }; 124302acc2eSNathan Whitehorn 125fa7a1ca7SJustin Hibbits DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0); 126302acc2eSNathan Whitehorn 127302acc2eSNathan Whitehorn PLATFORM_DEF(mpc85xx_platform); 128302acc2eSNathan Whitehorn 129302acc2eSNathan Whitehorn static int 130302acc2eSNathan Whitehorn mpc85xx_probe(platform_t plat) 131302acc2eSNathan Whitehorn { 132adbe2685SJustin Hibbits u_int pvr = (mfpvr() >> 16) & 0xFFFF; 133302acc2eSNathan Whitehorn 134adbe2685SJustin Hibbits switch (pvr) { 135adbe2685SJustin Hibbits case FSL_E500v1: 136adbe2685SJustin Hibbits case FSL_E500v2: 137adbe2685SJustin Hibbits case FSL_E500mc: 138adbe2685SJustin Hibbits case FSL_E5500: 139adbe2685SJustin Hibbits case FSL_E6500: 140302acc2eSNathan Whitehorn return (BUS_PROBE_DEFAULT); 141adbe2685SJustin Hibbits } 142302acc2eSNathan Whitehorn return (ENXIO); 143302acc2eSNathan Whitehorn } 144302acc2eSNathan Whitehorn 145fa7a1ca7SJustin Hibbits int 146302acc2eSNathan Whitehorn mpc85xx_attach(platform_t plat) 147302acc2eSNathan Whitehorn { 14852cfe485SNathan Whitehorn phandle_t cpus, child, ccsr; 14952cfe485SNathan Whitehorn const char *soc_name_guesses[] = {"/soc", "soc", NULL}; 15052cfe485SNathan Whitehorn const char **name; 15152cfe485SNathan Whitehorn pcell_t ranges[6], acells, pacells, scells; 15252cfe485SNathan Whitehorn uint64_t ccsrbar, ccsrsize; 153adbe2685SJustin Hibbits int i; 154302acc2eSNathan Whitehorn 155302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) != -1) { 156302acc2eSNathan Whitehorn for (maxcpu = 0, child = OF_child(cpus); child != 0; 157302acc2eSNathan Whitehorn child = OF_peer(child), maxcpu++) 158302acc2eSNathan Whitehorn ; 159302acc2eSNathan Whitehorn } else 160302acc2eSNathan Whitehorn maxcpu = 1; 161302acc2eSNathan Whitehorn 162302acc2eSNathan Whitehorn /* 16352cfe485SNathan Whitehorn * Locate CCSR region. Irritatingly, there is no way to find it 16452cfe485SNathan Whitehorn * unless you already know where it is. Try to infer its location 16552cfe485SNathan Whitehorn * from the device tree. 16652cfe485SNathan Whitehorn */ 16752cfe485SNathan Whitehorn 16852cfe485SNathan Whitehorn ccsr = -1; 16952cfe485SNathan Whitehorn for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++) 17052cfe485SNathan Whitehorn ccsr = OF_finddevice(*name); 17152cfe485SNathan Whitehorn if (ccsr == -1) { 17252cfe485SNathan Whitehorn char type[64]; 17352cfe485SNathan Whitehorn 17452cfe485SNathan Whitehorn /* That didn't work. Search for devices of type "soc" */ 17552cfe485SNathan Whitehorn child = OF_child(OF_peer(0)); 17652cfe485SNathan Whitehorn for (OF_child(child); child != 0; child = OF_peer(child)) { 17752cfe485SNathan Whitehorn if (OF_getprop(child, "device_type", type, sizeof(type)) 17852cfe485SNathan Whitehorn <= 0) 17952cfe485SNathan Whitehorn continue; 18052cfe485SNathan Whitehorn 18152cfe485SNathan Whitehorn if (strcmp(type, "soc") == 0) { 18252cfe485SNathan Whitehorn ccsr = child; 18352cfe485SNathan Whitehorn break; 18452cfe485SNathan Whitehorn } 18552cfe485SNathan Whitehorn } 18652cfe485SNathan Whitehorn } 18752cfe485SNathan Whitehorn 18852cfe485SNathan Whitehorn if (ccsr == -1) 18952cfe485SNathan Whitehorn panic("Could not locate CCSR window!"); 19052cfe485SNathan Whitehorn 19152cfe485SNathan Whitehorn OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells)); 19252cfe485SNathan Whitehorn OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells)); 19352cfe485SNathan Whitehorn OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells, 19452cfe485SNathan Whitehorn sizeof(pacells)); 19552cfe485SNathan Whitehorn OF_getprop(ccsr, "ranges", ranges, sizeof(ranges)); 19652cfe485SNathan Whitehorn ccsrbar = ccsrsize = 0; 19752cfe485SNathan Whitehorn for (i = acells; i < acells + pacells; i++) { 19852cfe485SNathan Whitehorn ccsrbar <<= 32; 19952cfe485SNathan Whitehorn ccsrbar |= ranges[i]; 20052cfe485SNathan Whitehorn } 20152cfe485SNathan Whitehorn for (i = acells + pacells; i < acells + pacells + scells; i++) { 20252cfe485SNathan Whitehorn ccsrsize <<= 32; 20352cfe485SNathan Whitehorn ccsrsize |= ranges[i]; 20452cfe485SNathan Whitehorn } 20552cfe485SNathan Whitehorn ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); 206b2f831c0SJustin Hibbits ccsrbar_pa = ccsrbar; 207b2f831c0SJustin Hibbits ccsrbar_size = ccsrsize; 20852cfe485SNathan Whitehorn 2093f068cbfSJustin Hibbits mpc85xx_enable_l3_cache(); 2103f068cbfSJustin Hibbits 211302acc2eSNathan Whitehorn return (0); 212302acc2eSNathan Whitehorn } 213302acc2eSNathan Whitehorn 214302acc2eSNathan Whitehorn void 215c1cb22d7SNathan Whitehorn mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 216c1cb22d7SNathan Whitehorn struct mem_region *avail, int *availsz) 217302acc2eSNathan Whitehorn { 218302acc2eSNathan Whitehorn 219302acc2eSNathan Whitehorn ofw_mem_regions(phys, physsz, avail, availsz); 220302acc2eSNathan Whitehorn } 221302acc2eSNathan Whitehorn 222302acc2eSNathan Whitehorn static u_long 223302acc2eSNathan Whitehorn mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) 224302acc2eSNathan Whitehorn { 225302acc2eSNathan Whitehorn u_long ticks; 226302acc2eSNathan Whitehorn phandle_t cpus, child; 227302acc2eSNathan Whitehorn pcell_t freq; 228302acc2eSNathan Whitehorn 229302acc2eSNathan Whitehorn if (bootinfo != NULL) { 230302acc2eSNathan Whitehorn if (bootinfo[0] == 1) { 231302acc2eSNathan Whitehorn /* Backward compatibility. See 8-STABLE. */ 232302acc2eSNathan Whitehorn ticks = bootinfo[3] >> 3; 233302acc2eSNathan Whitehorn } else { 234302acc2eSNathan Whitehorn /* Compatibility with Juniper's loader. */ 235302acc2eSNathan Whitehorn ticks = bootinfo[5] >> 3; 236302acc2eSNathan Whitehorn } 237302acc2eSNathan Whitehorn } else 238302acc2eSNathan Whitehorn ticks = 0; 239302acc2eSNathan Whitehorn 240302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) == -1) 241302acc2eSNathan Whitehorn goto out; 242302acc2eSNathan Whitehorn 243302acc2eSNathan Whitehorn if ((child = OF_child(cpus)) == 0) 244302acc2eSNathan Whitehorn goto out; 245302acc2eSNathan Whitehorn 246302acc2eSNathan Whitehorn switch (OF_getproplen(child, "timebase-frequency")) { 247302acc2eSNathan Whitehorn case 4: 248302acc2eSNathan Whitehorn { 249302acc2eSNathan Whitehorn uint32_t tbase; 250302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 251302acc2eSNathan Whitehorn ticks = tbase; 252302acc2eSNathan Whitehorn return (ticks); 253302acc2eSNathan Whitehorn } 254302acc2eSNathan Whitehorn case 8: 255302acc2eSNathan Whitehorn { 256302acc2eSNathan Whitehorn uint64_t tbase; 257302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 258302acc2eSNathan Whitehorn ticks = tbase; 259302acc2eSNathan Whitehorn return (ticks); 260302acc2eSNathan Whitehorn } 261302acc2eSNathan Whitehorn default: 262302acc2eSNathan Whitehorn break; 263302acc2eSNathan Whitehorn } 264302acc2eSNathan Whitehorn 265302acc2eSNathan Whitehorn freq = 0; 266302acc2eSNathan Whitehorn if (OF_getprop(child, "bus-frequency", (void *)&freq, 267302acc2eSNathan Whitehorn sizeof(freq)) <= 0) 268302acc2eSNathan Whitehorn goto out; 269302acc2eSNathan Whitehorn 2706cedae09SJustin Hibbits if (freq == 0) 2716cedae09SJustin Hibbits goto out; 2726cedae09SJustin Hibbits 273302acc2eSNathan Whitehorn /* 274302acc2eSNathan Whitehorn * Time Base and Decrementer are updated every 8 CCB bus clocks. 275302acc2eSNathan Whitehorn * HID0[SEL_TBCLK] = 0 276302acc2eSNathan Whitehorn */ 2776cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) 2783f068cbfSJustin Hibbits ticks = freq / 32; 2796cedae09SJustin Hibbits else 280302acc2eSNathan Whitehorn ticks = freq / 8; 281302acc2eSNathan Whitehorn 282302acc2eSNathan Whitehorn out: 283302acc2eSNathan Whitehorn if (ticks <= 0) 284302acc2eSNathan Whitehorn panic("Unable to determine timebase frequency!"); 285302acc2eSNathan Whitehorn 286302acc2eSNathan Whitehorn return (ticks); 287302acc2eSNathan Whitehorn } 288302acc2eSNathan Whitehorn 289302acc2eSNathan Whitehorn static int 290302acc2eSNathan Whitehorn mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 291302acc2eSNathan Whitehorn { 292302acc2eSNathan Whitehorn 293302acc2eSNathan Whitehorn cpu = 0; 294302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu; 295302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 296302acc2eSNathan Whitehorn if (bootverbose) 297302acc2eSNathan Whitehorn printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 298302acc2eSNathan Whitehorn cpu++; 299302acc2eSNathan Whitehorn 300302acc2eSNathan Whitehorn return (0); 301302acc2eSNathan Whitehorn } 302302acc2eSNathan Whitehorn 303302acc2eSNathan Whitehorn static int 304302acc2eSNathan Whitehorn mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 305302acc2eSNathan Whitehorn { 306302acc2eSNathan Whitehorn 307302acc2eSNathan Whitehorn if (cpu >= maxcpu) 308302acc2eSNathan Whitehorn return (ENOENT); 309302acc2eSNathan Whitehorn 310302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu++; 311302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 312302acc2eSNathan Whitehorn if (bootverbose) 313302acc2eSNathan Whitehorn printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 314302acc2eSNathan Whitehorn 315302acc2eSNathan Whitehorn return (0); 316302acc2eSNathan Whitehorn } 317302acc2eSNathan Whitehorn 318302acc2eSNathan Whitehorn static int 319302acc2eSNathan Whitehorn mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 320302acc2eSNathan Whitehorn { 321302acc2eSNathan Whitehorn 322302acc2eSNathan Whitehorn cpuref->cr_cpuid = mfspr(SPR_PIR); 323302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 324302acc2eSNathan Whitehorn 325302acc2eSNathan Whitehorn return (0); 326302acc2eSNathan Whitehorn } 327302acc2eSNathan Whitehorn 328253902b4SJustin Hibbits #ifdef SMP 329253902b4SJustin Hibbits static int 330253902b4SJustin Hibbits mpc85xx_smp_start_cpu_epapr(platform_t plat, struct pcpu *pc) 331253902b4SJustin Hibbits { 332253902b4SJustin Hibbits vm_paddr_t rel_pa, bptr; 333253902b4SJustin Hibbits volatile struct cpu_release *rel; 334253902b4SJustin Hibbits vm_offset_t rel_va, rel_page; 335253902b4SJustin Hibbits phandle_t node; 336253902b4SJustin Hibbits int i; 337253902b4SJustin Hibbits 338253902b4SJustin Hibbits /* If we're calling this, the node already exists. */ 339253902b4SJustin Hibbits node = OF_finddevice("/cpus"); 340253902b4SJustin Hibbits for (i = 0, node = OF_child(node); i < pc->pc_cpuid; 341253902b4SJustin Hibbits i++, node = OF_peer(node)) 342253902b4SJustin Hibbits ; 343253902b4SJustin Hibbits if (OF_getencprop(node, "cpu-release-addr", (pcell_t *)&rel_pa, 344253902b4SJustin Hibbits sizeof(rel_pa)) == -1) { 345253902b4SJustin Hibbits return (ENOENT); 346253902b4SJustin Hibbits } 347253902b4SJustin Hibbits 348253902b4SJustin Hibbits rel_page = kva_alloc(PAGE_SIZE); 349253902b4SJustin Hibbits if (rel_page == 0) 350253902b4SJustin Hibbits return (ENOMEM); 351253902b4SJustin Hibbits 352253902b4SJustin Hibbits critical_enter(); 353253902b4SJustin Hibbits rel_va = rel_page + (rel_pa & PAGE_MASK); 354253902b4SJustin Hibbits pmap_kenter(rel_page, rel_pa & ~PAGE_MASK); 355253902b4SJustin Hibbits rel = (struct cpu_release *)rel_va; 356870d94c5SJustin Hibbits bptr = pmap_kextract((uintptr_t)__boot_page); 357253902b4SJustin Hibbits cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 358253902b4SJustin Hibbits rel->pir = pc->pc_cpuid; __asm __volatile("sync"); 359253902b4SJustin Hibbits rel->entry_h = (bptr >> 32); 360253902b4SJustin Hibbits rel->entry_l = bptr; __asm __volatile("sync"); 361253902b4SJustin Hibbits cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 362253902b4SJustin Hibbits if (bootverbose) 363253902b4SJustin Hibbits printf("Waking up CPU %d via CPU release page %p\n", 364253902b4SJustin Hibbits pc->pc_cpuid, rel); 365253902b4SJustin Hibbits critical_exit(); 366253902b4SJustin Hibbits pmap_kremove(rel_page); 367253902b4SJustin Hibbits kva_free(rel_page, PAGE_SIZE); 368253902b4SJustin Hibbits 369253902b4SJustin Hibbits return (0); 370253902b4SJustin Hibbits } 371253902b4SJustin Hibbits #endif 372253902b4SJustin Hibbits 373302acc2eSNathan Whitehorn static int 374302acc2eSNathan Whitehorn mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) 375302acc2eSNathan Whitehorn { 376302acc2eSNathan Whitehorn #ifdef SMP 3773f068cbfSJustin Hibbits vm_paddr_t bptr; 3783f068cbfSJustin Hibbits uint32_t reg; 379f60708c9SJustin Hibbits int timeout; 3803f068cbfSJustin Hibbits uintptr_t brr; 3813f068cbfSJustin Hibbits int cpuid; 382253902b4SJustin Hibbits int epapr_boot = 0; 3833f068cbfSJustin Hibbits uint32_t tgt; 3843f068cbfSJustin Hibbits 3856cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) { 3863f068cbfSJustin Hibbits reg = ccsr_read4(OCP85XX_COREDISR); 3873f068cbfSJustin Hibbits cpuid = pc->pc_cpuid; 3883f068cbfSJustin Hibbits 3896cedae09SJustin Hibbits if ((reg & (1 << cpuid)) != 0) { 3903f068cbfSJustin Hibbits printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid); 3913f068cbfSJustin Hibbits return (-1); 3923f068cbfSJustin Hibbits } 3933f068cbfSJustin Hibbits 3943f068cbfSJustin Hibbits brr = OCP85XX_BRR; 3956cedae09SJustin Hibbits } else { 3963f068cbfSJustin Hibbits brr = OCP85XX_EEBPCR; 3973f068cbfSJustin Hibbits cpuid = pc->pc_cpuid + 24; 3986cedae09SJustin Hibbits } 399f60708c9SJustin Hibbits bp_kernload = kernload; 400253902b4SJustin Hibbits /* 401253902b4SJustin Hibbits * bp_kernload is in the boot page. Sync the cache because ePAPR 402253902b4SJustin Hibbits * booting has the other core(s) already running. 403253902b4SJustin Hibbits */ 4047599d2ddSJustin Hibbits cpu_flush_dcache(&bp_kernload, sizeof(bp_kernload)); 405253902b4SJustin Hibbits 406253902b4SJustin Hibbits ap_pcpu = pc; 407253902b4SJustin Hibbits __asm __volatile("msync; isync"); 408253902b4SJustin Hibbits 409253902b4SJustin Hibbits /* First try the ePAPR way. */ 410253902b4SJustin Hibbits if (mpc85xx_smp_start_cpu_epapr(plat, pc) == 0) { 411253902b4SJustin Hibbits epapr_boot = 1; 412253902b4SJustin Hibbits goto spin_wait; 413253902b4SJustin Hibbits } 4146cedae09SJustin Hibbits 4153f068cbfSJustin Hibbits reg = ccsr_read4(brr); 4163f068cbfSJustin Hibbits if ((reg & (1 << cpuid)) != 0) { 417302acc2eSNathan Whitehorn printf("SMP: CPU %d already out of hold-off state!\n", 418302acc2eSNathan Whitehorn pc->pc_cpuid); 419302acc2eSNathan Whitehorn return (ENXIO); 420302acc2eSNathan Whitehorn } 421302acc2eSNathan Whitehorn 4223f068cbfSJustin Hibbits /* Flush caches to have our changes hit DRAM. */ 4233f068cbfSJustin Hibbits cpu_flush_dcache(__boot_page, 4096); 4243f068cbfSJustin Hibbits 425870d94c5SJustin Hibbits bptr = pmap_kextract((uintptr_t)__boot_page); 4263f068cbfSJustin Hibbits KASSERT((bptr & 0xfff) == 0, 4273f068cbfSJustin Hibbits ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr)); 4286cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) { 4293f068cbfSJustin Hibbits /* 4303f068cbfSJustin Hibbits * Read DDR controller configuration to select proper BPTR target ID. 4313f068cbfSJustin Hibbits * 4323f068cbfSJustin Hibbits * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers 4333f068cbfSJustin Hibbits * interleaving. If this bit is set, we have to use 4343f068cbfSJustin Hibbits * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs, 4353f068cbfSJustin Hibbits * this bit is reserved and always 0. 4363f068cbfSJustin Hibbits */ 4373f068cbfSJustin Hibbits 4383f068cbfSJustin Hibbits reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG); 4393f068cbfSJustin Hibbits if (reg & (1 << 29)) 4403f068cbfSJustin Hibbits tgt = OCP85XX_TGTIF_RAM_INTL; 4413f068cbfSJustin Hibbits else 4423f068cbfSJustin Hibbits tgt = OCP85XX_TGTIF_RAM1; 4433f068cbfSJustin Hibbits 4443f068cbfSJustin Hibbits /* 4453f068cbfSJustin Hibbits * Set BSTR to the physical address of the boot page 4463f068cbfSJustin Hibbits */ 4473f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTRH, bptr >> 32); 4483f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTRL, bptr); 4493f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK | 4506cedae09SJustin Hibbits (tgt << OCP85XX_TRGT_SHIFT_QORIQ) | (ffsl(PAGE_SIZE) - 2)); 4513f068cbfSJustin Hibbits 4523f068cbfSJustin Hibbits /* Read back OCP85XX_BSTAR to synchronize write */ 4533f068cbfSJustin Hibbits ccsr_read4(OCP85XX_BSTAR); 4543f068cbfSJustin Hibbits 4553f068cbfSJustin Hibbits /* 4563f068cbfSJustin Hibbits * Enable and configure time base on new CPU. 4573f068cbfSJustin Hibbits */ 4583f068cbfSJustin Hibbits 4593f068cbfSJustin Hibbits /* Set TB clock source to platform clock / 32 */ 4603f068cbfSJustin Hibbits reg = ccsr_read4(CCSR_CTBCKSELR); 4613f068cbfSJustin Hibbits ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid)); 4623f068cbfSJustin Hibbits 4633f068cbfSJustin Hibbits /* Enable TB */ 4643f068cbfSJustin Hibbits reg = ccsr_read4(CCSR_CTBENR); 4653f068cbfSJustin Hibbits ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid)); 4666cedae09SJustin Hibbits } else { 467302acc2eSNathan Whitehorn /* 468302acc2eSNathan Whitehorn * Set BPTR to the physical address of the boot page 469302acc2eSNathan Whitehorn */ 470302acc2eSNathan Whitehorn bptr = (bptr >> 12) | 0x80000000u; 471302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, bptr); 472302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 4736cedae09SJustin Hibbits } 474302acc2eSNathan Whitehorn 475302acc2eSNathan Whitehorn /* 476302acc2eSNathan Whitehorn * Release AP from hold-off state 477302acc2eSNathan Whitehorn */ 4783f068cbfSJustin Hibbits reg = ccsr_read4(brr); 4793f068cbfSJustin Hibbits ccsr_write4(brr, reg | (1 << cpuid)); 480302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 481302acc2eSNathan Whitehorn 482253902b4SJustin Hibbits spin_wait: 483302acc2eSNathan Whitehorn timeout = 500; 484302acc2eSNathan Whitehorn while (!pc->pc_awake && timeout--) 485302acc2eSNathan Whitehorn DELAY(1000); /* wait 1ms */ 486302acc2eSNathan Whitehorn 487302acc2eSNathan Whitehorn /* 488302acc2eSNathan Whitehorn * Disable boot page translation so that the 4K page at the default 489302acc2eSNathan Whitehorn * address (= 0xfffff000) isn't permanently remapped and thus not 490302acc2eSNathan Whitehorn * usable otherwise. 491302acc2eSNathan Whitehorn */ 492253902b4SJustin Hibbits if (!epapr_boot) { 4936cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) 4943f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTAR, 0); 4956cedae09SJustin Hibbits else 496302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, 0); 497302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 498253902b4SJustin Hibbits } 499302acc2eSNathan Whitehorn 500302acc2eSNathan Whitehorn if (!pc->pc_awake) 5016cedae09SJustin Hibbits panic("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); 502302acc2eSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 503302acc2eSNathan Whitehorn #else 504302acc2eSNathan Whitehorn /* No SMP support */ 505302acc2eSNathan Whitehorn return (ENXIO); 506302acc2eSNathan Whitehorn #endif 507302acc2eSNathan Whitehorn } 508302acc2eSNathan Whitehorn 509302acc2eSNathan Whitehorn static void 510302acc2eSNathan Whitehorn mpc85xx_reset(platform_t plat) 511302acc2eSNathan Whitehorn { 512302acc2eSNathan Whitehorn 513302acc2eSNathan Whitehorn /* 514302acc2eSNathan Whitehorn * Try the dedicated reset register first. 515302acc2eSNathan Whitehorn * If the SoC doesn't have one, we'll fall 516302acc2eSNathan Whitehorn * back to using the debug control register. 517302acc2eSNathan Whitehorn */ 518302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_RSTCR, 2); 519302acc2eSNathan Whitehorn 520*702818d2SJustin Hibbits mtmsr(mfmsr() & ~PSL_DE); 521*702818d2SJustin Hibbits 522*702818d2SJustin Hibbits /* Enable debug interrupts and issue reset. */ 523*702818d2SJustin Hibbits mtspr(SPR_DBCR0, DBCR0_IDM | DBCR0_RST_SYSTEM); 524302acc2eSNathan Whitehorn __asm __volatile("isync"); 525302acc2eSNathan Whitehorn 526302acc2eSNathan Whitehorn /* Enable Debug Interrupts in MSR. */ 527302acc2eSNathan Whitehorn mtmsr(mfmsr() | PSL_DE); 528302acc2eSNathan Whitehorn 529302acc2eSNathan Whitehorn printf("Reset failed...\n"); 530302acc2eSNathan Whitehorn while (1) 531302acc2eSNathan Whitehorn ; 532302acc2eSNathan Whitehorn } 533302acc2eSNathan Whitehorn 534637f34cbSJustin Hibbits static void 535de2dd83fSNathan Whitehorn mpc85xx_smp_timebase_sync(platform_t plat, u_long tb, int ap) 536de2dd83fSNathan Whitehorn { 5370d69f00bSJustin Hibbits static volatile bool tb_ready; 5380d69f00bSJustin Hibbits static volatile int cpu_done; 539de2dd83fSNathan Whitehorn 5400d69f00bSJustin Hibbits if (ap) { 5410d69f00bSJustin Hibbits /* APs. Hold off until we get a stable timebase. */ 5420d69f00bSJustin Hibbits while (!tb_ready) 5430d69f00bSJustin Hibbits atomic_thread_fence_seq_cst(); 544de2dd83fSNathan Whitehorn mttb(tb); 5450d69f00bSJustin Hibbits atomic_add_int(&cpu_done, 1); 5460d69f00bSJustin Hibbits while (cpu_done < mp_ncpus) 5470d69f00bSJustin Hibbits atomic_thread_fence_seq_cst(); 5480d69f00bSJustin Hibbits } else { 5490d69f00bSJustin Hibbits /* BSP */ 5500d69f00bSJustin Hibbits freeze_timebase(rcpm_dev, true); 5510d69f00bSJustin Hibbits tb_ready = true; 5520d69f00bSJustin Hibbits mttb(tb); 5530d69f00bSJustin Hibbits atomic_add_int(&cpu_done, 1); 5540d69f00bSJustin Hibbits while (cpu_done < mp_ncpus) 5550d69f00bSJustin Hibbits atomic_thread_fence_seq_cst(); 5560d69f00bSJustin Hibbits freeze_timebase(rcpm_dev, false); 5570d69f00bSJustin Hibbits } 558de2dd83fSNathan Whitehorn } 559de2dd83fSNathan Whitehorn 5600d69f00bSJustin Hibbits /* Fallback freeze. In case no real handler is found in the device tree. */ 5610d69f00bSJustin Hibbits static void 5620d69f00bSJustin Hibbits dummy_freeze(device_t dev, bool freeze) 5630d69f00bSJustin Hibbits { 5640d69f00bSJustin Hibbits /* Nothing to do here, move along. */ 5650d69f00bSJustin Hibbits } 5660d69f00bSJustin Hibbits 5670d69f00bSJustin Hibbits 5680d69f00bSJustin Hibbits /* QorIQ Run control/power management timebase management. */ 5690d69f00bSJustin Hibbits 5700d69f00bSJustin Hibbits #define RCPM_CTBENR 0x00000084 5710d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc { 5720d69f00bSJustin Hibbits struct resource *sc_mem; 5730d69f00bSJustin Hibbits }; 5740d69f00bSJustin Hibbits 5750d69f00bSJustin Hibbits static void 5760d69f00bSJustin Hibbits mpc85xx_rcpm_freeze_timebase(device_t dev, bool freeze) 5770d69f00bSJustin Hibbits { 5780d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc *sc; 5790d69f00bSJustin Hibbits 5800d69f00bSJustin Hibbits sc = device_get_softc(dev); 5810d69f00bSJustin Hibbits 5820d69f00bSJustin Hibbits if (freeze) 5830d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, RCPM_CTBENR, 0); 5840d69f00bSJustin Hibbits else 5850d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, RCPM_CTBENR, (1 << maxcpu) - 1); 5860d69f00bSJustin Hibbits } 5870d69f00bSJustin Hibbits 5880d69f00bSJustin Hibbits static int 5890d69f00bSJustin Hibbits mpc85xx_rcpm_probe(device_t dev) 5900d69f00bSJustin Hibbits { 5910d69f00bSJustin Hibbits if (!ofw_bus_is_compatible(dev, "fsl,qoriq-rcpm-1.0")) 5920d69f00bSJustin Hibbits return (ENXIO); 5930d69f00bSJustin Hibbits 5940d69f00bSJustin Hibbits device_set_desc(dev, "QorIQ Run control and power management"); 5950d69f00bSJustin Hibbits return (BUS_PROBE_GENERIC); 5960d69f00bSJustin Hibbits } 5970d69f00bSJustin Hibbits 5980d69f00bSJustin Hibbits static int 5990d69f00bSJustin Hibbits mpc85xx_rcpm_attach(device_t dev) 6000d69f00bSJustin Hibbits { 6010d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc *sc; 6020d69f00bSJustin Hibbits int rid; 6030d69f00bSJustin Hibbits 6040d69f00bSJustin Hibbits sc = device_get_softc(dev); 6050d69f00bSJustin Hibbits freeze_timebase = mpc85xx_rcpm_freeze_timebase; 6060d69f00bSJustin Hibbits rcpm_dev = dev; 6070d69f00bSJustin Hibbits 6080d69f00bSJustin Hibbits rid = 0; 6090d69f00bSJustin Hibbits sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 6100d69f00bSJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 6110d69f00bSJustin Hibbits 6120d69f00bSJustin Hibbits return (0); 6130d69f00bSJustin Hibbits } 6140d69f00bSJustin Hibbits 6150d69f00bSJustin Hibbits static device_method_t mpc85xx_rcpm_methods[] = { 6160d69f00bSJustin Hibbits DEVMETHOD(device_probe, mpc85xx_rcpm_probe), 6170d69f00bSJustin Hibbits DEVMETHOD(device_attach, mpc85xx_rcpm_attach), 6180d69f00bSJustin Hibbits DEVMETHOD_END 6190d69f00bSJustin Hibbits }; 6200d69f00bSJustin Hibbits 6210d69f00bSJustin Hibbits static devclass_t mpc85xx_rcpm_devclass; 6220d69f00bSJustin Hibbits 6230d69f00bSJustin Hibbits static driver_t mpc85xx_rcpm_driver = { 6240d69f00bSJustin Hibbits "rcpm", 6250d69f00bSJustin Hibbits mpc85xx_rcpm_methods, 6260d69f00bSJustin Hibbits sizeof(struct mpc85xx_rcpm_softc) 6270d69f00bSJustin Hibbits }; 6280d69f00bSJustin Hibbits 6290d69f00bSJustin Hibbits EARLY_DRIVER_MODULE(mpc85xx_rcpm, simplebus, mpc85xx_rcpm_driver, 6300d69f00bSJustin Hibbits mpc85xx_rcpm_devclass, 0, 0, BUS_PASS_BUS); 6310d69f00bSJustin Hibbits 6320d69f00bSJustin Hibbits 6330d69f00bSJustin Hibbits /* "Global utilities" power management/Timebase management. */ 6340d69f00bSJustin Hibbits 6350d69f00bSJustin Hibbits #define GUTS_DEVDISR 0x00000070 6360d69f00bSJustin Hibbits #define DEVDISR_TB0 0x00004000 6370d69f00bSJustin Hibbits #define DEVDISR_TB1 0x00001000 6380d69f00bSJustin Hibbits 6390d69f00bSJustin Hibbits struct mpc85xx_guts_softc { 6400d69f00bSJustin Hibbits struct resource *sc_mem; 6410d69f00bSJustin Hibbits }; 6420d69f00bSJustin Hibbits 6430d69f00bSJustin Hibbits static void 6440d69f00bSJustin Hibbits mpc85xx_guts_freeze_timebase(device_t dev, bool freeze) 6450d69f00bSJustin Hibbits { 6460d69f00bSJustin Hibbits struct mpc85xx_guts_softc *sc; 6470d69f00bSJustin Hibbits uint32_t devdisr; 6480d69f00bSJustin Hibbits 6490d69f00bSJustin Hibbits sc = device_get_softc(dev); 6500d69f00bSJustin Hibbits 6510d69f00bSJustin Hibbits devdisr = bus_read_4(sc->sc_mem, GUTS_DEVDISR); 6520d69f00bSJustin Hibbits if (freeze) 6530d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, GUTS_DEVDISR, 6540d69f00bSJustin Hibbits devdisr | (DEVDISR_TB0 | DEVDISR_TB1)); 6550d69f00bSJustin Hibbits else 6560d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, GUTS_DEVDISR, 6570d69f00bSJustin Hibbits devdisr & ~(DEVDISR_TB0 | DEVDISR_TB1)); 6580d69f00bSJustin Hibbits } 6590d69f00bSJustin Hibbits 6600d69f00bSJustin Hibbits static int 6610d69f00bSJustin Hibbits mpc85xx_guts_probe(device_t dev) 6620d69f00bSJustin Hibbits { 6630d69f00bSJustin Hibbits if (!ofw_bus_is_compatible(dev, "fsl,mpc8572-guts") && 6640d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1020-guts") && 6650d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1021-guts") && 6660d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1022-guts") && 6670d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1023-guts") && 6680d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p2020-guts")) 6690d69f00bSJustin Hibbits return (ENXIO); 6700d69f00bSJustin Hibbits 6710d69f00bSJustin Hibbits device_set_desc(dev, "MPC85xx Global Utilities"); 6720d69f00bSJustin Hibbits return (BUS_PROBE_GENERIC); 6730d69f00bSJustin Hibbits } 6740d69f00bSJustin Hibbits 6750d69f00bSJustin Hibbits static int 6760d69f00bSJustin Hibbits mpc85xx_guts_attach(device_t dev) 6770d69f00bSJustin Hibbits { 6780d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc *sc; 6790d69f00bSJustin Hibbits int rid; 6800d69f00bSJustin Hibbits 6810d69f00bSJustin Hibbits sc = device_get_softc(dev); 6820d69f00bSJustin Hibbits freeze_timebase = mpc85xx_guts_freeze_timebase; 6830d69f00bSJustin Hibbits rcpm_dev = dev; 6840d69f00bSJustin Hibbits 6850d69f00bSJustin Hibbits rid = 0; 6860d69f00bSJustin Hibbits sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 6870d69f00bSJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 6880d69f00bSJustin Hibbits 6890d69f00bSJustin Hibbits return (0); 6900d69f00bSJustin Hibbits } 6910d69f00bSJustin Hibbits 6920d69f00bSJustin Hibbits static device_method_t mpc85xx_guts_methods[] = { 6930d69f00bSJustin Hibbits DEVMETHOD(device_probe, mpc85xx_guts_probe), 6940d69f00bSJustin Hibbits DEVMETHOD(device_attach, mpc85xx_guts_attach), 6950d69f00bSJustin Hibbits DEVMETHOD_END 6960d69f00bSJustin Hibbits }; 6970d69f00bSJustin Hibbits 6980d69f00bSJustin Hibbits static driver_t mpc85xx_guts_driver = { 6990d69f00bSJustin Hibbits "guts", 7000d69f00bSJustin Hibbits mpc85xx_guts_methods, 7010d69f00bSJustin Hibbits sizeof(struct mpc85xx_guts_softc) 7020d69f00bSJustin Hibbits }; 7030d69f00bSJustin Hibbits 7040d69f00bSJustin Hibbits static devclass_t mpc85xx_guts_devclass; 7050d69f00bSJustin Hibbits 7060d69f00bSJustin Hibbits EARLY_DRIVER_MODULE(mpc85xx_guts, simplebus, mpc85xx_guts_driver, 7070d69f00bSJustin Hibbits mpc85xx_guts_devclass, 0, 0, BUS_PASS_BUS); 708