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 */ 71*ab3f2a38SBrandon Bergren extern vm_paddr_t bp_kernload; /* Boot page copy of kernload */ 72*ab3f2a38SBrandon Bergren extern vm_offset_t bp_virtaddr; /* Virtual address of boot page */ 73ea32838aSJustin Hibbits extern vm_offset_t __startkernel; 74253902b4SJustin Hibbits 75253902b4SJustin Hibbits struct cpu_release { 76253902b4SJustin Hibbits uint32_t entry_h; 77253902b4SJustin Hibbits uint32_t entry_l; 78253902b4SJustin Hibbits uint32_t r3_h; 79253902b4SJustin Hibbits uint32_t r3_l; 80253902b4SJustin Hibbits uint32_t reserved; 81253902b4SJustin Hibbits uint32_t pir; 82253902b4SJustin Hibbits }; 83302acc2eSNathan Whitehorn #endif 84302acc2eSNathan Whitehorn 85302acc2eSNathan Whitehorn extern uint32_t *bootinfo; 86b2f831c0SJustin Hibbits vm_paddr_t ccsrbar_pa; 8752cfe485SNathan Whitehorn vm_offset_t ccsrbar_va; 88b2f831c0SJustin Hibbits vm_size_t ccsrbar_size; 89302acc2eSNathan Whitehorn 90302acc2eSNathan Whitehorn static int cpu, maxcpu; 91302acc2eSNathan Whitehorn 920d69f00bSJustin Hibbits static device_t rcpm_dev; 930d69f00bSJustin Hibbits static void dummy_freeze(device_t, bool); 940d69f00bSJustin Hibbits 950d69f00bSJustin Hibbits static void (*freeze_timebase)(device_t, bool) = dummy_freeze; 960d69f00bSJustin Hibbits 97302acc2eSNathan Whitehorn static int mpc85xx_probe(platform_t); 98c1cb22d7SNathan Whitehorn static void mpc85xx_mem_regions(platform_t, struct mem_region *phys, 99c1cb22d7SNathan Whitehorn int *physsz, struct mem_region *avail, int *availsz); 100302acc2eSNathan Whitehorn static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref); 101302acc2eSNathan Whitehorn static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref); 102302acc2eSNathan Whitehorn static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref); 103302acc2eSNathan Whitehorn static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref); 104302acc2eSNathan Whitehorn static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu); 105de2dd83fSNathan Whitehorn static void mpc85xx_smp_timebase_sync(platform_t, u_long tb, int ap); 106302acc2eSNathan Whitehorn 107302acc2eSNathan Whitehorn static void mpc85xx_reset(platform_t); 108302acc2eSNathan Whitehorn 109302acc2eSNathan Whitehorn static platform_method_t mpc85xx_methods[] = { 110302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_probe, mpc85xx_probe), 111302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_attach, mpc85xx_attach), 112302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, mpc85xx_mem_regions), 113302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, mpc85xx_timebase_freq), 114302acc2eSNathan Whitehorn 115302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, mpc85xx_smp_first_cpu), 116302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, mpc85xx_smp_next_cpu), 117302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, mpc85xx_smp_get_bsp), 118302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, mpc85xx_smp_start_cpu), 119de2dd83fSNathan Whitehorn PLATFORMMETHOD(platform_smp_timebase_sync, mpc85xx_smp_timebase_sync), 120302acc2eSNathan Whitehorn 121302acc2eSNathan Whitehorn PLATFORMMETHOD(platform_reset, mpc85xx_reset), 122302acc2eSNathan Whitehorn 123302acc2eSNathan Whitehorn PLATFORMMETHOD_END 124302acc2eSNathan Whitehorn }; 125302acc2eSNathan Whitehorn 126fa7a1ca7SJustin Hibbits DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0); 127302acc2eSNathan Whitehorn 128302acc2eSNathan Whitehorn PLATFORM_DEF(mpc85xx_platform); 129302acc2eSNathan Whitehorn 130302acc2eSNathan Whitehorn static int 131302acc2eSNathan Whitehorn mpc85xx_probe(platform_t plat) 132302acc2eSNathan Whitehorn { 133adbe2685SJustin Hibbits u_int pvr = (mfpvr() >> 16) & 0xFFFF; 134302acc2eSNathan Whitehorn 135adbe2685SJustin Hibbits switch (pvr) { 136adbe2685SJustin Hibbits case FSL_E500v1: 137adbe2685SJustin Hibbits case FSL_E500v2: 138adbe2685SJustin Hibbits case FSL_E500mc: 139adbe2685SJustin Hibbits case FSL_E5500: 140adbe2685SJustin Hibbits case FSL_E6500: 141302acc2eSNathan Whitehorn return (BUS_PROBE_DEFAULT); 142adbe2685SJustin Hibbits } 143302acc2eSNathan Whitehorn return (ENXIO); 144302acc2eSNathan Whitehorn } 145302acc2eSNathan Whitehorn 146fa7a1ca7SJustin Hibbits int 147302acc2eSNathan Whitehorn mpc85xx_attach(platform_t plat) 148302acc2eSNathan Whitehorn { 14952cfe485SNathan Whitehorn phandle_t cpus, child, ccsr; 15052cfe485SNathan Whitehorn const char *soc_name_guesses[] = {"/soc", "soc", NULL}; 15152cfe485SNathan Whitehorn const char **name; 15252cfe485SNathan Whitehorn pcell_t ranges[6], acells, pacells, scells; 15352cfe485SNathan Whitehorn uint64_t ccsrbar, ccsrsize; 154adbe2685SJustin Hibbits int i; 155302acc2eSNathan Whitehorn 156302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) != -1) { 157302acc2eSNathan Whitehorn for (maxcpu = 0, child = OF_child(cpus); child != 0; 158302acc2eSNathan Whitehorn child = OF_peer(child), maxcpu++) 159302acc2eSNathan Whitehorn ; 160302acc2eSNathan Whitehorn } else 161302acc2eSNathan Whitehorn maxcpu = 1; 162302acc2eSNathan Whitehorn 163302acc2eSNathan Whitehorn /* 16452cfe485SNathan Whitehorn * Locate CCSR region. Irritatingly, there is no way to find it 16552cfe485SNathan Whitehorn * unless you already know where it is. Try to infer its location 16652cfe485SNathan Whitehorn * from the device tree. 16752cfe485SNathan Whitehorn */ 16852cfe485SNathan Whitehorn 16952cfe485SNathan Whitehorn ccsr = -1; 17052cfe485SNathan Whitehorn for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++) 17152cfe485SNathan Whitehorn ccsr = OF_finddevice(*name); 17252cfe485SNathan Whitehorn if (ccsr == -1) { 17352cfe485SNathan Whitehorn char type[64]; 17452cfe485SNathan Whitehorn 17552cfe485SNathan Whitehorn /* That didn't work. Search for devices of type "soc" */ 17652cfe485SNathan Whitehorn child = OF_child(OF_peer(0)); 17752cfe485SNathan Whitehorn for (OF_child(child); child != 0; child = OF_peer(child)) { 17852cfe485SNathan Whitehorn if (OF_getprop(child, "device_type", type, sizeof(type)) 17952cfe485SNathan Whitehorn <= 0) 18052cfe485SNathan Whitehorn continue; 18152cfe485SNathan Whitehorn 18252cfe485SNathan Whitehorn if (strcmp(type, "soc") == 0) { 18352cfe485SNathan Whitehorn ccsr = child; 18452cfe485SNathan Whitehorn break; 18552cfe485SNathan Whitehorn } 18652cfe485SNathan Whitehorn } 18752cfe485SNathan Whitehorn } 18852cfe485SNathan Whitehorn 18952cfe485SNathan Whitehorn if (ccsr == -1) 19052cfe485SNathan Whitehorn panic("Could not locate CCSR window!"); 19152cfe485SNathan Whitehorn 19252cfe485SNathan Whitehorn OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells)); 19352cfe485SNathan Whitehorn OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells)); 19452cfe485SNathan Whitehorn OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells, 19552cfe485SNathan Whitehorn sizeof(pacells)); 19652cfe485SNathan Whitehorn OF_getprop(ccsr, "ranges", ranges, sizeof(ranges)); 19752cfe485SNathan Whitehorn ccsrbar = ccsrsize = 0; 19852cfe485SNathan Whitehorn for (i = acells; i < acells + pacells; i++) { 19952cfe485SNathan Whitehorn ccsrbar <<= 32; 20052cfe485SNathan Whitehorn ccsrbar |= ranges[i]; 20152cfe485SNathan Whitehorn } 20252cfe485SNathan Whitehorn for (i = acells + pacells; i < acells + pacells + scells; i++) { 20352cfe485SNathan Whitehorn ccsrsize <<= 32; 20452cfe485SNathan Whitehorn ccsrsize |= ranges[i]; 20552cfe485SNathan Whitehorn } 20652cfe485SNathan Whitehorn ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize); 207b2f831c0SJustin Hibbits ccsrbar_pa = ccsrbar; 208b2f831c0SJustin Hibbits ccsrbar_size = ccsrsize; 20952cfe485SNathan Whitehorn 2103f068cbfSJustin Hibbits mpc85xx_enable_l3_cache(); 2113f068cbfSJustin Hibbits 212302acc2eSNathan Whitehorn return (0); 213302acc2eSNathan Whitehorn } 214302acc2eSNathan Whitehorn 215302acc2eSNathan Whitehorn void 216c1cb22d7SNathan Whitehorn mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 217c1cb22d7SNathan Whitehorn struct mem_region *avail, int *availsz) 218302acc2eSNathan Whitehorn { 219302acc2eSNathan Whitehorn 220302acc2eSNathan Whitehorn ofw_mem_regions(phys, physsz, avail, availsz); 221302acc2eSNathan Whitehorn } 222302acc2eSNathan Whitehorn 223302acc2eSNathan Whitehorn static u_long 224302acc2eSNathan Whitehorn mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref) 225302acc2eSNathan Whitehorn { 226302acc2eSNathan Whitehorn u_long ticks; 227302acc2eSNathan Whitehorn phandle_t cpus, child; 228302acc2eSNathan Whitehorn pcell_t freq; 229302acc2eSNathan Whitehorn 230302acc2eSNathan Whitehorn if (bootinfo != NULL) { 231302acc2eSNathan Whitehorn if (bootinfo[0] == 1) { 232302acc2eSNathan Whitehorn /* Backward compatibility. See 8-STABLE. */ 233302acc2eSNathan Whitehorn ticks = bootinfo[3] >> 3; 234302acc2eSNathan Whitehorn } else { 235302acc2eSNathan Whitehorn /* Compatibility with Juniper's loader. */ 236302acc2eSNathan Whitehorn ticks = bootinfo[5] >> 3; 237302acc2eSNathan Whitehorn } 238302acc2eSNathan Whitehorn } else 239302acc2eSNathan Whitehorn ticks = 0; 240302acc2eSNathan Whitehorn 241302acc2eSNathan Whitehorn if ((cpus = OF_finddevice("/cpus")) == -1) 242302acc2eSNathan Whitehorn goto out; 243302acc2eSNathan Whitehorn 244302acc2eSNathan Whitehorn if ((child = OF_child(cpus)) == 0) 245302acc2eSNathan Whitehorn goto out; 246302acc2eSNathan Whitehorn 247302acc2eSNathan Whitehorn switch (OF_getproplen(child, "timebase-frequency")) { 248302acc2eSNathan Whitehorn case 4: 249302acc2eSNathan Whitehorn { 250302acc2eSNathan Whitehorn uint32_t tbase; 251302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 252302acc2eSNathan Whitehorn ticks = tbase; 253302acc2eSNathan Whitehorn return (ticks); 254302acc2eSNathan Whitehorn } 255302acc2eSNathan Whitehorn case 8: 256302acc2eSNathan Whitehorn { 257302acc2eSNathan Whitehorn uint64_t tbase; 258302acc2eSNathan Whitehorn OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase)); 259302acc2eSNathan Whitehorn ticks = tbase; 260302acc2eSNathan Whitehorn return (ticks); 261302acc2eSNathan Whitehorn } 262302acc2eSNathan Whitehorn default: 263302acc2eSNathan Whitehorn break; 264302acc2eSNathan Whitehorn } 265302acc2eSNathan Whitehorn 266302acc2eSNathan Whitehorn freq = 0; 267302acc2eSNathan Whitehorn if (OF_getprop(child, "bus-frequency", (void *)&freq, 268302acc2eSNathan Whitehorn sizeof(freq)) <= 0) 269302acc2eSNathan Whitehorn goto out; 270302acc2eSNathan Whitehorn 2716cedae09SJustin Hibbits if (freq == 0) 2726cedae09SJustin Hibbits goto out; 2736cedae09SJustin Hibbits 274302acc2eSNathan Whitehorn /* 275302acc2eSNathan Whitehorn * Time Base and Decrementer are updated every 8 CCB bus clocks. 276302acc2eSNathan Whitehorn * HID0[SEL_TBCLK] = 0 277302acc2eSNathan Whitehorn */ 2786cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) 2793f068cbfSJustin Hibbits ticks = freq / 32; 2806cedae09SJustin Hibbits else 281302acc2eSNathan Whitehorn ticks = freq / 8; 282302acc2eSNathan Whitehorn 283302acc2eSNathan Whitehorn out: 284302acc2eSNathan Whitehorn if (ticks <= 0) 285302acc2eSNathan Whitehorn panic("Unable to determine timebase frequency!"); 286302acc2eSNathan Whitehorn 287302acc2eSNathan Whitehorn return (ticks); 288302acc2eSNathan Whitehorn } 289302acc2eSNathan Whitehorn 290302acc2eSNathan Whitehorn static int 291302acc2eSNathan Whitehorn mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 292302acc2eSNathan Whitehorn { 293302acc2eSNathan Whitehorn 294302acc2eSNathan Whitehorn cpu = 0; 295302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu; 296302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 297302acc2eSNathan Whitehorn if (bootverbose) 298302acc2eSNathan Whitehorn printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid); 299302acc2eSNathan Whitehorn cpu++; 300302acc2eSNathan Whitehorn 301302acc2eSNathan Whitehorn return (0); 302302acc2eSNathan Whitehorn } 303302acc2eSNathan Whitehorn 304302acc2eSNathan Whitehorn static int 305302acc2eSNathan Whitehorn mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 306302acc2eSNathan Whitehorn { 307302acc2eSNathan Whitehorn 308302acc2eSNathan Whitehorn if (cpu >= maxcpu) 309302acc2eSNathan Whitehorn return (ENOENT); 310302acc2eSNathan Whitehorn 311302acc2eSNathan Whitehorn cpuref->cr_cpuid = cpu++; 312302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 313302acc2eSNathan Whitehorn if (bootverbose) 314302acc2eSNathan Whitehorn printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid); 315302acc2eSNathan Whitehorn 316302acc2eSNathan Whitehorn return (0); 317302acc2eSNathan Whitehorn } 318302acc2eSNathan Whitehorn 319302acc2eSNathan Whitehorn static int 320302acc2eSNathan Whitehorn mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 321302acc2eSNathan Whitehorn { 322302acc2eSNathan Whitehorn 323302acc2eSNathan Whitehorn cpuref->cr_cpuid = mfspr(SPR_PIR); 324302acc2eSNathan Whitehorn cpuref->cr_hwref = cpuref->cr_cpuid; 325302acc2eSNathan Whitehorn 326302acc2eSNathan Whitehorn return (0); 327302acc2eSNathan Whitehorn } 328302acc2eSNathan Whitehorn 329253902b4SJustin Hibbits #ifdef SMP 330253902b4SJustin Hibbits static int 331253902b4SJustin Hibbits mpc85xx_smp_start_cpu_epapr(platform_t plat, struct pcpu *pc) 332253902b4SJustin Hibbits { 333253902b4SJustin Hibbits vm_paddr_t rel_pa, bptr; 334253902b4SJustin Hibbits volatile struct cpu_release *rel; 335253902b4SJustin Hibbits vm_offset_t rel_va, rel_page; 336253902b4SJustin Hibbits phandle_t node; 337253902b4SJustin Hibbits int i; 338253902b4SJustin Hibbits 339253902b4SJustin Hibbits /* If we're calling this, the node already exists. */ 340253902b4SJustin Hibbits node = OF_finddevice("/cpus"); 341253902b4SJustin Hibbits for (i = 0, node = OF_child(node); i < pc->pc_cpuid; 342253902b4SJustin Hibbits i++, node = OF_peer(node)) 343253902b4SJustin Hibbits ; 344253902b4SJustin Hibbits if (OF_getencprop(node, "cpu-release-addr", (pcell_t *)&rel_pa, 345253902b4SJustin Hibbits sizeof(rel_pa)) == -1) { 346253902b4SJustin Hibbits return (ENOENT); 347253902b4SJustin Hibbits } 348253902b4SJustin Hibbits 349253902b4SJustin Hibbits rel_page = kva_alloc(PAGE_SIZE); 350253902b4SJustin Hibbits if (rel_page == 0) 351253902b4SJustin Hibbits return (ENOMEM); 352253902b4SJustin Hibbits 353253902b4SJustin Hibbits critical_enter(); 354253902b4SJustin Hibbits rel_va = rel_page + (rel_pa & PAGE_MASK); 355253902b4SJustin Hibbits pmap_kenter(rel_page, rel_pa & ~PAGE_MASK); 356253902b4SJustin Hibbits rel = (struct cpu_release *)rel_va; 357870d94c5SJustin Hibbits bptr = pmap_kextract((uintptr_t)__boot_page); 358*ab3f2a38SBrandon Bergren 359253902b4SJustin Hibbits cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 360*ab3f2a38SBrandon Bergren rel->pir = pc->pc_cpuid; __asm __volatile("sync" ::: "memory"); 361*ab3f2a38SBrandon Bergren rel->entry_h = (bptr >> 32); __asm __volatile("sync" ::: "memory"); 362*ab3f2a38SBrandon Bergren cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 363*ab3f2a38SBrandon Bergren rel->entry_l = bptr & 0xffffffff; __asm __volatile("sync" ::: "memory"); 364253902b4SJustin Hibbits cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel)); 365253902b4SJustin Hibbits if (bootverbose) 366253902b4SJustin Hibbits printf("Waking up CPU %d via CPU release page %p\n", 367253902b4SJustin Hibbits pc->pc_cpuid, rel); 368253902b4SJustin Hibbits critical_exit(); 369253902b4SJustin Hibbits pmap_kremove(rel_page); 370253902b4SJustin Hibbits kva_free(rel_page, PAGE_SIZE); 371253902b4SJustin Hibbits 372253902b4SJustin Hibbits return (0); 373253902b4SJustin Hibbits } 374253902b4SJustin Hibbits #endif 375253902b4SJustin Hibbits 376302acc2eSNathan Whitehorn static int 377302acc2eSNathan Whitehorn mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc) 378302acc2eSNathan Whitehorn { 379302acc2eSNathan Whitehorn #ifdef SMP 3803f068cbfSJustin Hibbits vm_paddr_t bptr; 3813f068cbfSJustin Hibbits uint32_t reg; 382f60708c9SJustin Hibbits int timeout; 3833f068cbfSJustin Hibbits uintptr_t brr; 3843f068cbfSJustin Hibbits int cpuid; 385253902b4SJustin Hibbits int epapr_boot = 0; 3863f068cbfSJustin Hibbits uint32_t tgt; 3873f068cbfSJustin Hibbits 3886cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) { 3893f068cbfSJustin Hibbits reg = ccsr_read4(OCP85XX_COREDISR); 3903f068cbfSJustin Hibbits cpuid = pc->pc_cpuid; 3913f068cbfSJustin Hibbits 3926cedae09SJustin Hibbits if ((reg & (1 << cpuid)) != 0) { 3933f068cbfSJustin Hibbits printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid); 3943f068cbfSJustin Hibbits return (-1); 3953f068cbfSJustin Hibbits } 3963f068cbfSJustin Hibbits 3973f068cbfSJustin Hibbits brr = OCP85XX_BRR; 3986cedae09SJustin Hibbits } else { 3993f068cbfSJustin Hibbits brr = OCP85XX_EEBPCR; 4003f068cbfSJustin Hibbits cpuid = pc->pc_cpuid + 24; 4016cedae09SJustin Hibbits } 402f60708c9SJustin Hibbits bp_kernload = kernload; 403*ab3f2a38SBrandon Bergren bp_virtaddr = (vm_offset_t)&__boot_page; 404253902b4SJustin Hibbits /* 405*ab3f2a38SBrandon Bergren * bp_kernload and bp_virtaddr are in the boot page. Sync the cache 406*ab3f2a38SBrandon Bergren * because ePAPR booting has the other core(s) already running. 407253902b4SJustin Hibbits */ 4087599d2ddSJustin Hibbits cpu_flush_dcache(&bp_kernload, sizeof(bp_kernload)); 409*ab3f2a38SBrandon Bergren cpu_flush_dcache(&bp_virtaddr, sizeof(bp_virtaddr)); 410253902b4SJustin Hibbits 411253902b4SJustin Hibbits ap_pcpu = pc; 412253902b4SJustin Hibbits __asm __volatile("msync; isync"); 413253902b4SJustin Hibbits 414253902b4SJustin Hibbits /* First try the ePAPR way. */ 415253902b4SJustin Hibbits if (mpc85xx_smp_start_cpu_epapr(plat, pc) == 0) { 416253902b4SJustin Hibbits epapr_boot = 1; 417253902b4SJustin Hibbits goto spin_wait; 418253902b4SJustin Hibbits } 4196cedae09SJustin Hibbits 4203f068cbfSJustin Hibbits reg = ccsr_read4(brr); 4213f068cbfSJustin Hibbits if ((reg & (1 << cpuid)) != 0) { 422302acc2eSNathan Whitehorn printf("SMP: CPU %d already out of hold-off state!\n", 423302acc2eSNathan Whitehorn pc->pc_cpuid); 424302acc2eSNathan Whitehorn return (ENXIO); 425302acc2eSNathan Whitehorn } 426302acc2eSNathan Whitehorn 4273f068cbfSJustin Hibbits /* Flush caches to have our changes hit DRAM. */ 4283f068cbfSJustin Hibbits cpu_flush_dcache(__boot_page, 4096); 4293f068cbfSJustin Hibbits 430870d94c5SJustin Hibbits bptr = pmap_kextract((uintptr_t)__boot_page); 4313f068cbfSJustin Hibbits KASSERT((bptr & 0xfff) == 0, 4323f068cbfSJustin Hibbits ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr)); 4336cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) { 4343f068cbfSJustin Hibbits /* 4353f068cbfSJustin Hibbits * Read DDR controller configuration to select proper BPTR target ID. 4363f068cbfSJustin Hibbits * 4373f068cbfSJustin Hibbits * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers 4383f068cbfSJustin Hibbits * interleaving. If this bit is set, we have to use 4393f068cbfSJustin Hibbits * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs, 4403f068cbfSJustin Hibbits * this bit is reserved and always 0. 4413f068cbfSJustin Hibbits */ 4423f068cbfSJustin Hibbits 4433f068cbfSJustin Hibbits reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG); 4443f068cbfSJustin Hibbits if (reg & (1 << 29)) 4453f068cbfSJustin Hibbits tgt = OCP85XX_TGTIF_RAM_INTL; 4463f068cbfSJustin Hibbits else 4473f068cbfSJustin Hibbits tgt = OCP85XX_TGTIF_RAM1; 4483f068cbfSJustin Hibbits 4493f068cbfSJustin Hibbits /* 4503f068cbfSJustin Hibbits * Set BSTR to the physical address of the boot page 4513f068cbfSJustin Hibbits */ 4523f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTRH, bptr >> 32); 4533f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTRL, bptr); 4543f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK | 4556cedae09SJustin Hibbits (tgt << OCP85XX_TRGT_SHIFT_QORIQ) | (ffsl(PAGE_SIZE) - 2)); 4563f068cbfSJustin Hibbits 4573f068cbfSJustin Hibbits /* Read back OCP85XX_BSTAR to synchronize write */ 4583f068cbfSJustin Hibbits ccsr_read4(OCP85XX_BSTAR); 4593f068cbfSJustin Hibbits 4603f068cbfSJustin Hibbits /* 4613f068cbfSJustin Hibbits * Enable and configure time base on new CPU. 4623f068cbfSJustin Hibbits */ 4633f068cbfSJustin Hibbits 4643f068cbfSJustin Hibbits /* Set TB clock source to platform clock / 32 */ 4653f068cbfSJustin Hibbits reg = ccsr_read4(CCSR_CTBCKSELR); 4663f068cbfSJustin Hibbits ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid)); 4673f068cbfSJustin Hibbits 4683f068cbfSJustin Hibbits /* Enable TB */ 4693f068cbfSJustin Hibbits reg = ccsr_read4(CCSR_CTBENR); 4703f068cbfSJustin Hibbits ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid)); 4716cedae09SJustin Hibbits } else { 472302acc2eSNathan Whitehorn /* 473302acc2eSNathan Whitehorn * Set BPTR to the physical address of the boot page 474302acc2eSNathan Whitehorn */ 475302acc2eSNathan Whitehorn bptr = (bptr >> 12) | 0x80000000u; 476302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, bptr); 477302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 4786cedae09SJustin Hibbits } 479302acc2eSNathan Whitehorn 480302acc2eSNathan Whitehorn /* 481302acc2eSNathan Whitehorn * Release AP from hold-off state 482302acc2eSNathan Whitehorn */ 4833f068cbfSJustin Hibbits reg = ccsr_read4(brr); 4843f068cbfSJustin Hibbits ccsr_write4(brr, reg | (1 << cpuid)); 485302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 486302acc2eSNathan Whitehorn 487253902b4SJustin Hibbits spin_wait: 488302acc2eSNathan Whitehorn timeout = 500; 489302acc2eSNathan Whitehorn while (!pc->pc_awake && timeout--) 490302acc2eSNathan Whitehorn DELAY(1000); /* wait 1ms */ 491302acc2eSNathan Whitehorn 492302acc2eSNathan Whitehorn /* 493302acc2eSNathan Whitehorn * Disable boot page translation so that the 4K page at the default 494302acc2eSNathan Whitehorn * address (= 0xfffff000) isn't permanently remapped and thus not 495302acc2eSNathan Whitehorn * usable otherwise. 496302acc2eSNathan Whitehorn */ 497253902b4SJustin Hibbits if (!epapr_boot) { 4986cedae09SJustin Hibbits if (mpc85xx_is_qoriq()) 4993f068cbfSJustin Hibbits ccsr_write4(OCP85XX_BSTAR, 0); 5006cedae09SJustin Hibbits else 501302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_BPTR, 0); 502302acc2eSNathan Whitehorn __asm __volatile("isync; msync"); 503253902b4SJustin Hibbits } 504302acc2eSNathan Whitehorn 505302acc2eSNathan Whitehorn if (!pc->pc_awake) 5066cedae09SJustin Hibbits panic("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid); 507302acc2eSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 508302acc2eSNathan Whitehorn #else 509302acc2eSNathan Whitehorn /* No SMP support */ 510302acc2eSNathan Whitehorn return (ENXIO); 511302acc2eSNathan Whitehorn #endif 512302acc2eSNathan Whitehorn } 513302acc2eSNathan Whitehorn 514302acc2eSNathan Whitehorn static void 515302acc2eSNathan Whitehorn mpc85xx_reset(platform_t plat) 516302acc2eSNathan Whitehorn { 517302acc2eSNathan Whitehorn 518302acc2eSNathan Whitehorn /* 519302acc2eSNathan Whitehorn * Try the dedicated reset register first. 520302acc2eSNathan Whitehorn * If the SoC doesn't have one, we'll fall 521302acc2eSNathan Whitehorn * back to using the debug control register. 522302acc2eSNathan Whitehorn */ 523302acc2eSNathan Whitehorn ccsr_write4(OCP85XX_RSTCR, 2); 524302acc2eSNathan Whitehorn 525702818d2SJustin Hibbits mtmsr(mfmsr() & ~PSL_DE); 526702818d2SJustin Hibbits 527702818d2SJustin Hibbits /* Enable debug interrupts and issue reset. */ 528702818d2SJustin Hibbits mtspr(SPR_DBCR0, DBCR0_IDM | DBCR0_RST_SYSTEM); 529302acc2eSNathan Whitehorn __asm __volatile("isync"); 530302acc2eSNathan Whitehorn 531302acc2eSNathan Whitehorn /* Enable Debug Interrupts in MSR. */ 532302acc2eSNathan Whitehorn mtmsr(mfmsr() | PSL_DE); 533302acc2eSNathan Whitehorn 534302acc2eSNathan Whitehorn printf("Reset failed...\n"); 535302acc2eSNathan Whitehorn while (1) 536302acc2eSNathan Whitehorn ; 537302acc2eSNathan Whitehorn } 538302acc2eSNathan Whitehorn 539637f34cbSJustin Hibbits static void 540de2dd83fSNathan Whitehorn mpc85xx_smp_timebase_sync(platform_t plat, u_long tb, int ap) 541de2dd83fSNathan Whitehorn { 5420d69f00bSJustin Hibbits static volatile bool tb_ready; 5430d69f00bSJustin Hibbits static volatile int cpu_done; 544de2dd83fSNathan Whitehorn 5450d69f00bSJustin Hibbits if (ap) { 5460d69f00bSJustin Hibbits /* APs. Hold off until we get a stable timebase. */ 5470d69f00bSJustin Hibbits while (!tb_ready) 5480d69f00bSJustin Hibbits atomic_thread_fence_seq_cst(); 549de2dd83fSNathan Whitehorn mttb(tb); 5500d69f00bSJustin Hibbits atomic_add_int(&cpu_done, 1); 5510d69f00bSJustin Hibbits while (cpu_done < mp_ncpus) 5520d69f00bSJustin Hibbits atomic_thread_fence_seq_cst(); 5530d69f00bSJustin Hibbits } else { 5540d69f00bSJustin Hibbits /* BSP */ 5550d69f00bSJustin Hibbits freeze_timebase(rcpm_dev, true); 5560d69f00bSJustin Hibbits tb_ready = true; 5570d69f00bSJustin Hibbits mttb(tb); 5580d69f00bSJustin Hibbits atomic_add_int(&cpu_done, 1); 5590d69f00bSJustin Hibbits while (cpu_done < mp_ncpus) 5600d69f00bSJustin Hibbits atomic_thread_fence_seq_cst(); 5610d69f00bSJustin Hibbits freeze_timebase(rcpm_dev, false); 5620d69f00bSJustin Hibbits } 563de2dd83fSNathan Whitehorn } 564de2dd83fSNathan Whitehorn 5650d69f00bSJustin Hibbits /* Fallback freeze. In case no real handler is found in the device tree. */ 5660d69f00bSJustin Hibbits static void 5670d69f00bSJustin Hibbits dummy_freeze(device_t dev, bool freeze) 5680d69f00bSJustin Hibbits { 5690d69f00bSJustin Hibbits /* Nothing to do here, move along. */ 5700d69f00bSJustin Hibbits } 5710d69f00bSJustin Hibbits 5720d69f00bSJustin Hibbits 5730d69f00bSJustin Hibbits /* QorIQ Run control/power management timebase management. */ 5740d69f00bSJustin Hibbits 5750d69f00bSJustin Hibbits #define RCPM_CTBENR 0x00000084 5760d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc { 5770d69f00bSJustin Hibbits struct resource *sc_mem; 5780d69f00bSJustin Hibbits }; 5790d69f00bSJustin Hibbits 5800d69f00bSJustin Hibbits static void 5810d69f00bSJustin Hibbits mpc85xx_rcpm_freeze_timebase(device_t dev, bool freeze) 5820d69f00bSJustin Hibbits { 5830d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc *sc; 5840d69f00bSJustin Hibbits 5850d69f00bSJustin Hibbits sc = device_get_softc(dev); 5860d69f00bSJustin Hibbits 5870d69f00bSJustin Hibbits if (freeze) 5880d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, RCPM_CTBENR, 0); 5890d69f00bSJustin Hibbits else 5900d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, RCPM_CTBENR, (1 << maxcpu) - 1); 5910d69f00bSJustin Hibbits } 5920d69f00bSJustin Hibbits 5930d69f00bSJustin Hibbits static int 5940d69f00bSJustin Hibbits mpc85xx_rcpm_probe(device_t dev) 5950d69f00bSJustin Hibbits { 5960d69f00bSJustin Hibbits if (!ofw_bus_is_compatible(dev, "fsl,qoriq-rcpm-1.0")) 5970d69f00bSJustin Hibbits return (ENXIO); 5980d69f00bSJustin Hibbits 5990d69f00bSJustin Hibbits device_set_desc(dev, "QorIQ Run control and power management"); 6000d69f00bSJustin Hibbits return (BUS_PROBE_GENERIC); 6010d69f00bSJustin Hibbits } 6020d69f00bSJustin Hibbits 6030d69f00bSJustin Hibbits static int 6040d69f00bSJustin Hibbits mpc85xx_rcpm_attach(device_t dev) 6050d69f00bSJustin Hibbits { 6060d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc *sc; 6070d69f00bSJustin Hibbits int rid; 6080d69f00bSJustin Hibbits 6090d69f00bSJustin Hibbits sc = device_get_softc(dev); 6100d69f00bSJustin Hibbits freeze_timebase = mpc85xx_rcpm_freeze_timebase; 6110d69f00bSJustin Hibbits rcpm_dev = dev; 6120d69f00bSJustin Hibbits 6130d69f00bSJustin Hibbits rid = 0; 6140d69f00bSJustin Hibbits sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 6150d69f00bSJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 6160d69f00bSJustin Hibbits 6170d69f00bSJustin Hibbits return (0); 6180d69f00bSJustin Hibbits } 6190d69f00bSJustin Hibbits 6200d69f00bSJustin Hibbits static device_method_t mpc85xx_rcpm_methods[] = { 6210d69f00bSJustin Hibbits DEVMETHOD(device_probe, mpc85xx_rcpm_probe), 6220d69f00bSJustin Hibbits DEVMETHOD(device_attach, mpc85xx_rcpm_attach), 6230d69f00bSJustin Hibbits DEVMETHOD_END 6240d69f00bSJustin Hibbits }; 6250d69f00bSJustin Hibbits 6260d69f00bSJustin Hibbits static devclass_t mpc85xx_rcpm_devclass; 6270d69f00bSJustin Hibbits 6280d69f00bSJustin Hibbits static driver_t mpc85xx_rcpm_driver = { 6290d69f00bSJustin Hibbits "rcpm", 6300d69f00bSJustin Hibbits mpc85xx_rcpm_methods, 6310d69f00bSJustin Hibbits sizeof(struct mpc85xx_rcpm_softc) 6320d69f00bSJustin Hibbits }; 6330d69f00bSJustin Hibbits 6340d69f00bSJustin Hibbits EARLY_DRIVER_MODULE(mpc85xx_rcpm, simplebus, mpc85xx_rcpm_driver, 6350d69f00bSJustin Hibbits mpc85xx_rcpm_devclass, 0, 0, BUS_PASS_BUS); 6360d69f00bSJustin Hibbits 6370d69f00bSJustin Hibbits 6380d69f00bSJustin Hibbits /* "Global utilities" power management/Timebase management. */ 6390d69f00bSJustin Hibbits 6400d69f00bSJustin Hibbits #define GUTS_DEVDISR 0x00000070 6410d69f00bSJustin Hibbits #define DEVDISR_TB0 0x00004000 6420d69f00bSJustin Hibbits #define DEVDISR_TB1 0x00001000 6430d69f00bSJustin Hibbits 6440d69f00bSJustin Hibbits struct mpc85xx_guts_softc { 6450d69f00bSJustin Hibbits struct resource *sc_mem; 6460d69f00bSJustin Hibbits }; 6470d69f00bSJustin Hibbits 6480d69f00bSJustin Hibbits static void 6490d69f00bSJustin Hibbits mpc85xx_guts_freeze_timebase(device_t dev, bool freeze) 6500d69f00bSJustin Hibbits { 6510d69f00bSJustin Hibbits struct mpc85xx_guts_softc *sc; 6520d69f00bSJustin Hibbits uint32_t devdisr; 6530d69f00bSJustin Hibbits 6540d69f00bSJustin Hibbits sc = device_get_softc(dev); 6550d69f00bSJustin Hibbits 6560d69f00bSJustin Hibbits devdisr = bus_read_4(sc->sc_mem, GUTS_DEVDISR); 6570d69f00bSJustin Hibbits if (freeze) 6580d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, GUTS_DEVDISR, 6590d69f00bSJustin Hibbits devdisr | (DEVDISR_TB0 | DEVDISR_TB1)); 6600d69f00bSJustin Hibbits else 6610d69f00bSJustin Hibbits bus_write_4(sc->sc_mem, GUTS_DEVDISR, 6620d69f00bSJustin Hibbits devdisr & ~(DEVDISR_TB0 | DEVDISR_TB1)); 6630d69f00bSJustin Hibbits } 6640d69f00bSJustin Hibbits 6650d69f00bSJustin Hibbits static int 6660d69f00bSJustin Hibbits mpc85xx_guts_probe(device_t dev) 6670d69f00bSJustin Hibbits { 6680d69f00bSJustin Hibbits if (!ofw_bus_is_compatible(dev, "fsl,mpc8572-guts") && 6690d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1020-guts") && 6700d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1021-guts") && 6710d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1022-guts") && 6720d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p1023-guts") && 6730d69f00bSJustin Hibbits !ofw_bus_is_compatible(dev, "fsl,p2020-guts")) 6740d69f00bSJustin Hibbits return (ENXIO); 6750d69f00bSJustin Hibbits 6760d69f00bSJustin Hibbits device_set_desc(dev, "MPC85xx Global Utilities"); 6770d69f00bSJustin Hibbits return (BUS_PROBE_GENERIC); 6780d69f00bSJustin Hibbits } 6790d69f00bSJustin Hibbits 6800d69f00bSJustin Hibbits static int 6810d69f00bSJustin Hibbits mpc85xx_guts_attach(device_t dev) 6820d69f00bSJustin Hibbits { 6830d69f00bSJustin Hibbits struct mpc85xx_rcpm_softc *sc; 6840d69f00bSJustin Hibbits int rid; 6850d69f00bSJustin Hibbits 6860d69f00bSJustin Hibbits sc = device_get_softc(dev); 6870d69f00bSJustin Hibbits freeze_timebase = mpc85xx_guts_freeze_timebase; 6880d69f00bSJustin Hibbits rcpm_dev = dev; 6890d69f00bSJustin Hibbits 6900d69f00bSJustin Hibbits rid = 0; 6910d69f00bSJustin Hibbits sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 6920d69f00bSJustin Hibbits RF_ACTIVE | RF_SHAREABLE); 6930d69f00bSJustin Hibbits 6940d69f00bSJustin Hibbits return (0); 6950d69f00bSJustin Hibbits } 6960d69f00bSJustin Hibbits 6970d69f00bSJustin Hibbits static device_method_t mpc85xx_guts_methods[] = { 6980d69f00bSJustin Hibbits DEVMETHOD(device_probe, mpc85xx_guts_probe), 6990d69f00bSJustin Hibbits DEVMETHOD(device_attach, mpc85xx_guts_attach), 7000d69f00bSJustin Hibbits DEVMETHOD_END 7010d69f00bSJustin Hibbits }; 7020d69f00bSJustin Hibbits 7030d69f00bSJustin Hibbits static driver_t mpc85xx_guts_driver = { 7040d69f00bSJustin Hibbits "guts", 7050d69f00bSJustin Hibbits mpc85xx_guts_methods, 7060d69f00bSJustin Hibbits sizeof(struct mpc85xx_guts_softc) 7070d69f00bSJustin Hibbits }; 7080d69f00bSJustin Hibbits 7090d69f00bSJustin Hibbits static devclass_t mpc85xx_guts_devclass; 7100d69f00bSJustin Hibbits 7110d69f00bSJustin Hibbits EARLY_DRIVER_MODULE(mpc85xx_guts, simplebus, mpc85xx_guts_driver, 7120d69f00bSJustin Hibbits mpc85xx_guts_devclass, 0, 0, BUS_PASS_BUS); 713