1b2a237beSNathan Whitehorn /*- 2b2a237beSNathan Whitehorn * Copyright (c) 2008 Marcel Moolenaar 3b2a237beSNathan Whitehorn * Copyright (c) 2009 Nathan Whitehorn 4b2a237beSNathan Whitehorn * All rights reserved. 5b2a237beSNathan Whitehorn * 6b2a237beSNathan Whitehorn * Redistribution and use in source and binary forms, with or without 7b2a237beSNathan Whitehorn * modification, are permitted provided that the following conditions 8b2a237beSNathan Whitehorn * are met: 9b2a237beSNathan Whitehorn * 10b2a237beSNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 11b2a237beSNathan Whitehorn * notice, this list of conditions and the following disclaimer. 12b2a237beSNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 13b2a237beSNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 14b2a237beSNathan Whitehorn * documentation and/or other materials provided with the distribution. 15b2a237beSNathan Whitehorn * 16b2a237beSNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17b2a237beSNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18b2a237beSNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19b2a237beSNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20b2a237beSNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21b2a237beSNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22b2a237beSNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23b2a237beSNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24b2a237beSNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25b2a237beSNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26b2a237beSNathan Whitehorn */ 27b2a237beSNathan Whitehorn 28b2a237beSNathan Whitehorn #include <sys/cdefs.h> 29b2a237beSNathan Whitehorn __FBSDID("$FreeBSD$"); 30b2a237beSNathan Whitehorn 31b2a237beSNathan Whitehorn #include <sys/param.h> 32b2a237beSNathan Whitehorn #include <sys/systm.h> 33b2a237beSNathan Whitehorn #include <sys/kernel.h> 34b2a237beSNathan Whitehorn #include <sys/bus.h> 35b2a237beSNathan Whitehorn #include <sys/pcpu.h> 36b2a237beSNathan Whitehorn #include <sys/proc.h> 37b2a237beSNathan Whitehorn #include <sys/smp.h> 38b2a237beSNathan Whitehorn #include <vm/vm.h> 39b2a237beSNathan Whitehorn #include <vm/pmap.h> 40b2a237beSNathan Whitehorn 41b2a237beSNathan Whitehorn #include <machine/bus.h> 42b2a237beSNathan Whitehorn #include <machine/cpu.h> 43b2a237beSNathan Whitehorn #include <machine/hid.h> 44b2a237beSNathan Whitehorn #include <machine/platformvar.h> 45b2a237beSNathan Whitehorn #include <machine/pmap.h> 46b2a237beSNathan Whitehorn #include <machine/smp.h> 47b2a237beSNathan Whitehorn #include <machine/spr.h> 48b2a237beSNathan Whitehorn 49b2a237beSNathan Whitehorn #include <dev/ofw/openfirm.h> 50b2a237beSNathan Whitehorn #include <machine/ofw_machdep.h> 51b2a237beSNathan Whitehorn 52b2a237beSNathan Whitehorn #include "platform_if.h" 53b2a237beSNathan Whitehorn 54b2a237beSNathan Whitehorn #ifdef SMP 55b2a237beSNathan Whitehorn extern void *ap_pcpu; 56b2a237beSNathan Whitehorn #endif 57b2a237beSNathan Whitehorn 58b2a237beSNathan Whitehorn static int powermac_probe(platform_t); 59b2a237beSNathan Whitehorn void powermac_mem_regions(platform_t, struct mem_region **phys, int *physsz, 60b2a237beSNathan Whitehorn struct mem_region **avail, int *availsz); 61b2a237beSNathan Whitehorn static u_long powermac_timebase_freq(platform_t, struct cpuref *cpuref); 62b2a237beSNathan Whitehorn static int powermac_smp_first_cpu(platform_t, struct cpuref *cpuref); 63b2a237beSNathan Whitehorn static int powermac_smp_next_cpu(platform_t, struct cpuref *cpuref); 64b2a237beSNathan Whitehorn static int powermac_smp_get_bsp(platform_t, struct cpuref *cpuref); 65b2a237beSNathan Whitehorn static int powermac_smp_start_cpu(platform_t, struct pcpu *cpu); 66b2a237beSNathan Whitehorn static void powermac_reset(platform_t); 67b2a237beSNathan Whitehorn 68b2a237beSNathan Whitehorn static platform_method_t powermac_methods[] = { 69b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_probe, powermac_probe), 70b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, powermac_mem_regions), 71b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, powermac_timebase_freq), 72b2a237beSNathan Whitehorn 73b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, powermac_smp_first_cpu), 74b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, powermac_smp_next_cpu), 75b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, powermac_smp_get_bsp), 76b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, powermac_smp_start_cpu), 77b2a237beSNathan Whitehorn 78b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_reset, powermac_reset), 79b2a237beSNathan Whitehorn 80eaba9848SRui Paulo PLATFORMMETHOD_END 81b2a237beSNathan Whitehorn }; 82b2a237beSNathan Whitehorn 83b2a237beSNathan Whitehorn static platform_def_t powermac_platform = { 84b2a237beSNathan Whitehorn "powermac", 85b2a237beSNathan Whitehorn powermac_methods, 86b2a237beSNathan Whitehorn 0 87b2a237beSNathan Whitehorn }; 88b2a237beSNathan Whitehorn 89b2a237beSNathan Whitehorn PLATFORM_DEF(powermac_platform); 90b2a237beSNathan Whitehorn 91b2a237beSNathan Whitehorn static int 92b2a237beSNathan Whitehorn powermac_probe(platform_t plat) 93b2a237beSNathan Whitehorn { 94*5d46492dSNathan Whitehorn char compat[255]; 95*5d46492dSNathan Whitehorn ssize_t compatlen; 96*5d46492dSNathan Whitehorn char *curstr; 97*5d46492dSNathan Whitehorn phandle_t root; 98*5d46492dSNathan Whitehorn 99*5d46492dSNathan Whitehorn root = OF_peer(0); 100*5d46492dSNathan Whitehorn if (root == 0) 101*5d46492dSNathan Whitehorn return (ENXIO); 102*5d46492dSNathan Whitehorn 103*5d46492dSNathan Whitehorn compatlen = OF_getprop(root, "compatible", compat, sizeof(compat)); 104*5d46492dSNathan Whitehorn 105*5d46492dSNathan Whitehorn for (curstr = compat; curstr < compat + compatlen; 106*5d46492dSNathan Whitehorn curstr += strlen(curstr) + 1) { 107*5d46492dSNathan Whitehorn if (strncmp(curstr, "MacRISC", 7) == 0) 108*5d46492dSNathan Whitehorn return (BUS_PROBE_SPECIFIC); 109*5d46492dSNathan Whitehorn } 110b2a237beSNathan Whitehorn 111b2a237beSNathan Whitehorn return (ENXIO); 112b2a237beSNathan Whitehorn } 113b2a237beSNathan Whitehorn 114b2a237beSNathan Whitehorn void 115b2a237beSNathan Whitehorn powermac_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, 116b2a237beSNathan Whitehorn struct mem_region **avail, int *availsz) 117b2a237beSNathan Whitehorn { 118b2a237beSNathan Whitehorn ofw_mem_regions(phys,physsz,avail,availsz); 119b2a237beSNathan Whitehorn } 120b2a237beSNathan Whitehorn 121b2a237beSNathan Whitehorn static u_long 122b2a237beSNathan Whitehorn powermac_timebase_freq(platform_t plat, struct cpuref *cpuref) 123b2a237beSNathan Whitehorn { 124b2a237beSNathan Whitehorn phandle_t phandle; 125b2a237beSNathan Whitehorn int32_t ticks = -1; 126b2a237beSNathan Whitehorn 127b2a237beSNathan Whitehorn phandle = cpuref->cr_hwref; 128b2a237beSNathan Whitehorn 129b2a237beSNathan Whitehorn OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); 130b2a237beSNathan Whitehorn 131b2a237beSNathan Whitehorn if (ticks <= 0) 132b2a237beSNathan Whitehorn panic("Unable to determine timebase frequency!"); 133b2a237beSNathan Whitehorn 134b2a237beSNathan Whitehorn return (ticks); 135b2a237beSNathan Whitehorn } 136b2a237beSNathan Whitehorn 137b2a237beSNathan Whitehorn 138b2a237beSNathan Whitehorn static int 139b2a237beSNathan Whitehorn powermac_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) 140b2a237beSNathan Whitehorn { 141b2a237beSNathan Whitehorn cell_t cpuid, res; 142b2a237beSNathan Whitehorn 143b2a237beSNathan Whitehorn cpuref->cr_hwref = cpu; 144b2a237beSNathan Whitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 145b2a237beSNathan Whitehorn 146b2a237beSNathan Whitehorn /* 147b2a237beSNathan Whitehorn * psim doesn't have a reg property, so assume 0 as for the 148b2a237beSNathan Whitehorn * uniprocessor case in the CHRP spec. 149b2a237beSNathan Whitehorn */ 150b2a237beSNathan Whitehorn if (res < 0) { 151b2a237beSNathan Whitehorn cpuid = 0; 152b2a237beSNathan Whitehorn } 153b2a237beSNathan Whitehorn 154b2a237beSNathan Whitehorn cpuref->cr_cpuid = cpuid & 0xff; 155b2a237beSNathan Whitehorn return (0); 156b2a237beSNathan Whitehorn } 157b2a237beSNathan Whitehorn 158b2a237beSNathan Whitehorn static int 159b2a237beSNathan Whitehorn powermac_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 160b2a237beSNathan Whitehorn { 161b2a237beSNathan Whitehorn char buf[8]; 162b2a237beSNathan Whitehorn phandle_t cpu, dev, root; 163b2a237beSNathan Whitehorn int res; 164b2a237beSNathan Whitehorn 165b2a237beSNathan Whitehorn root = OF_peer(0); 166b2a237beSNathan Whitehorn 167b2a237beSNathan Whitehorn dev = OF_child(root); 168b2a237beSNathan Whitehorn while (dev != 0) { 169b2a237beSNathan Whitehorn res = OF_getprop(dev, "name", buf, sizeof(buf)); 170b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpus") == 0) 171b2a237beSNathan Whitehorn break; 172b2a237beSNathan Whitehorn dev = OF_peer(dev); 173b2a237beSNathan Whitehorn } 174b2a237beSNathan Whitehorn if (dev == 0) { 175b2a237beSNathan Whitehorn /* 176b2a237beSNathan Whitehorn * psim doesn't have a name property on the /cpus node, 177b2a237beSNathan Whitehorn * but it can be found directly 178b2a237beSNathan Whitehorn */ 179b2a237beSNathan Whitehorn dev = OF_finddevice("/cpus"); 18007042befSJayachandran C. if (dev == -1) 181b2a237beSNathan Whitehorn return (ENOENT); 182b2a237beSNathan Whitehorn } 183b2a237beSNathan Whitehorn 184b2a237beSNathan Whitehorn cpu = OF_child(dev); 185b2a237beSNathan Whitehorn 186b2a237beSNathan Whitehorn while (cpu != 0) { 187b2a237beSNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 188b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 189b2a237beSNathan Whitehorn break; 190b2a237beSNathan Whitehorn cpu = OF_peer(cpu); 191b2a237beSNathan Whitehorn } 192b2a237beSNathan Whitehorn if (cpu == 0) 193b2a237beSNathan Whitehorn return (ENOENT); 194b2a237beSNathan Whitehorn 195b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, cpu)); 196b2a237beSNathan Whitehorn } 197b2a237beSNathan Whitehorn 198b2a237beSNathan Whitehorn static int 199b2a237beSNathan Whitehorn powermac_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 200b2a237beSNathan Whitehorn { 201b2a237beSNathan Whitehorn char buf[8]; 202b2a237beSNathan Whitehorn phandle_t cpu; 203b2a237beSNathan Whitehorn int res; 204b2a237beSNathan Whitehorn 205b2a237beSNathan Whitehorn cpu = OF_peer(cpuref->cr_hwref); 206b2a237beSNathan Whitehorn while (cpu != 0) { 207b2a237beSNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 208b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 209b2a237beSNathan Whitehorn break; 210b2a237beSNathan Whitehorn cpu = OF_peer(cpu); 211b2a237beSNathan Whitehorn } 212b2a237beSNathan Whitehorn if (cpu == 0) 213b2a237beSNathan Whitehorn return (ENOENT); 214b2a237beSNathan Whitehorn 215b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, cpu)); 216b2a237beSNathan Whitehorn } 217b2a237beSNathan Whitehorn 218b2a237beSNathan Whitehorn static int 219b2a237beSNathan Whitehorn powermac_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 220b2a237beSNathan Whitehorn { 221b2a237beSNathan Whitehorn ihandle_t inst; 222b2a237beSNathan Whitehorn phandle_t bsp, chosen; 223b2a237beSNathan Whitehorn int res; 224b2a237beSNathan Whitehorn 225b2a237beSNathan Whitehorn chosen = OF_finddevice("/chosen"); 22607042befSJayachandran C. if (chosen == -1) 227b2a237beSNathan Whitehorn return (ENXIO); 228b2a237beSNathan Whitehorn 229b2a237beSNathan Whitehorn res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); 230b2a237beSNathan Whitehorn if (res < 0) 231b2a237beSNathan Whitehorn return (ENXIO); 232b2a237beSNathan Whitehorn 233b2a237beSNathan Whitehorn bsp = OF_instance_to_package(inst); 234b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, bsp)); 235b2a237beSNathan Whitehorn } 236b2a237beSNathan Whitehorn 237b2a237beSNathan Whitehorn static int 238b2a237beSNathan Whitehorn powermac_smp_start_cpu(platform_t plat, struct pcpu *pc) 239b2a237beSNathan Whitehorn { 240b2a237beSNathan Whitehorn #ifdef SMP 241b2a237beSNathan Whitehorn phandle_t cpu; 242b2a237beSNathan Whitehorn volatile uint8_t *rstvec; 243b2a237beSNathan Whitehorn static volatile uint8_t *rstvec_virtbase = NULL; 244b2a237beSNathan Whitehorn int res, reset, timeout; 245b2a237beSNathan Whitehorn 246b2a237beSNathan Whitehorn cpu = pc->pc_hwref; 247b2a237beSNathan Whitehorn res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset)); 248b2a237beSNathan Whitehorn if (res < 0) { 249b2a237beSNathan Whitehorn reset = 0x58; 250b2a237beSNathan Whitehorn 251b2a237beSNathan Whitehorn switch (pc->pc_cpuid) { 252b2a237beSNathan Whitehorn case 0: 253b2a237beSNathan Whitehorn reset += 0x03; 254b2a237beSNathan Whitehorn break; 255b2a237beSNathan Whitehorn case 1: 256b2a237beSNathan Whitehorn reset += 0x04; 257b2a237beSNathan Whitehorn break; 258b2a237beSNathan Whitehorn case 2: 259b2a237beSNathan Whitehorn reset += 0x0f; 260b2a237beSNathan Whitehorn break; 261b2a237beSNathan Whitehorn case 3: 262b2a237beSNathan Whitehorn reset += 0x10; 263b2a237beSNathan Whitehorn break; 264b2a237beSNathan Whitehorn default: 265b2a237beSNathan Whitehorn return (ENXIO); 266b2a237beSNathan Whitehorn } 267b2a237beSNathan Whitehorn } 268b2a237beSNathan Whitehorn 269b2a237beSNathan Whitehorn ap_pcpu = pc; 270b2a237beSNathan Whitehorn 271b2a237beSNathan Whitehorn if (rstvec_virtbase == NULL) 272b2a237beSNathan Whitehorn rstvec_virtbase = pmap_mapdev(0x80000000, PAGE_SIZE); 273b2a237beSNathan Whitehorn 274b2a237beSNathan Whitehorn rstvec = rstvec_virtbase + reset; 275b2a237beSNathan Whitehorn 276b2a237beSNathan Whitehorn *rstvec = 4; 277b2a237beSNathan Whitehorn powerpc_sync(); 278b2a237beSNathan Whitehorn (void)(*rstvec); 279b2a237beSNathan Whitehorn powerpc_sync(); 280b2a237beSNathan Whitehorn DELAY(1); 281b2a237beSNathan Whitehorn *rstvec = 0; 282b2a237beSNathan Whitehorn powerpc_sync(); 283b2a237beSNathan Whitehorn (void)(*rstvec); 284b2a237beSNathan Whitehorn powerpc_sync(); 285b2a237beSNathan Whitehorn 286b2a237beSNathan Whitehorn timeout = 10000; 287b2a237beSNathan Whitehorn while (!pc->pc_awake && timeout--) 288b2a237beSNathan Whitehorn DELAY(100); 289b2a237beSNathan Whitehorn 290b2a237beSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 291b2a237beSNathan Whitehorn #else 292b2a237beSNathan Whitehorn /* No SMP support */ 293b2a237beSNathan Whitehorn return (ENXIO); 294b2a237beSNathan Whitehorn #endif 295b2a237beSNathan Whitehorn } 296b2a237beSNathan Whitehorn 297b2a237beSNathan Whitehorn static void 298b2a237beSNathan Whitehorn powermac_reset(platform_t platform) 299b2a237beSNathan Whitehorn { 300b2a237beSNathan Whitehorn OF_reboot(); 301b2a237beSNathan Whitehorn } 302b2a237beSNathan Whitehorn 303