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 80*eaba9848SRui 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 { 94b2a237beSNathan Whitehorn if (OF_finddevice("/memory") != -1 || OF_finddevice("/memory@0") != -1) 95b2a237beSNathan Whitehorn return (BUS_PROBE_GENERIC); 96b2a237beSNathan Whitehorn 97b2a237beSNathan Whitehorn return (ENXIO); 98b2a237beSNathan Whitehorn } 99b2a237beSNathan Whitehorn 100b2a237beSNathan Whitehorn void 101b2a237beSNathan Whitehorn powermac_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, 102b2a237beSNathan Whitehorn struct mem_region **avail, int *availsz) 103b2a237beSNathan Whitehorn { 104b2a237beSNathan Whitehorn ofw_mem_regions(phys,physsz,avail,availsz); 105b2a237beSNathan Whitehorn } 106b2a237beSNathan Whitehorn 107b2a237beSNathan Whitehorn static u_long 108b2a237beSNathan Whitehorn powermac_timebase_freq(platform_t plat, struct cpuref *cpuref) 109b2a237beSNathan Whitehorn { 110b2a237beSNathan Whitehorn phandle_t phandle; 111b2a237beSNathan Whitehorn int32_t ticks = -1; 112b2a237beSNathan Whitehorn 113b2a237beSNathan Whitehorn phandle = cpuref->cr_hwref; 114b2a237beSNathan Whitehorn 115b2a237beSNathan Whitehorn OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); 116b2a237beSNathan Whitehorn 117b2a237beSNathan Whitehorn if (ticks <= 0) 118b2a237beSNathan Whitehorn panic("Unable to determine timebase frequency!"); 119b2a237beSNathan Whitehorn 120b2a237beSNathan Whitehorn return (ticks); 121b2a237beSNathan Whitehorn } 122b2a237beSNathan Whitehorn 123b2a237beSNathan Whitehorn 124b2a237beSNathan Whitehorn static int 125b2a237beSNathan Whitehorn powermac_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) 126b2a237beSNathan Whitehorn { 127b2a237beSNathan Whitehorn cell_t cpuid, res; 128b2a237beSNathan Whitehorn 129b2a237beSNathan Whitehorn cpuref->cr_hwref = cpu; 130b2a237beSNathan Whitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 131b2a237beSNathan Whitehorn 132b2a237beSNathan Whitehorn /* 133b2a237beSNathan Whitehorn * psim doesn't have a reg property, so assume 0 as for the 134b2a237beSNathan Whitehorn * uniprocessor case in the CHRP spec. 135b2a237beSNathan Whitehorn */ 136b2a237beSNathan Whitehorn if (res < 0) { 137b2a237beSNathan Whitehorn cpuid = 0; 138b2a237beSNathan Whitehorn } 139b2a237beSNathan Whitehorn 140b2a237beSNathan Whitehorn cpuref->cr_cpuid = cpuid & 0xff; 141b2a237beSNathan Whitehorn return (0); 142b2a237beSNathan Whitehorn } 143b2a237beSNathan Whitehorn 144b2a237beSNathan Whitehorn static int 145b2a237beSNathan Whitehorn powermac_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 146b2a237beSNathan Whitehorn { 147b2a237beSNathan Whitehorn char buf[8]; 148b2a237beSNathan Whitehorn phandle_t cpu, dev, root; 149b2a237beSNathan Whitehorn int res; 150b2a237beSNathan Whitehorn 151b2a237beSNathan Whitehorn root = OF_peer(0); 152b2a237beSNathan Whitehorn 153b2a237beSNathan Whitehorn dev = OF_child(root); 154b2a237beSNathan Whitehorn while (dev != 0) { 155b2a237beSNathan Whitehorn res = OF_getprop(dev, "name", buf, sizeof(buf)); 156b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpus") == 0) 157b2a237beSNathan Whitehorn break; 158b2a237beSNathan Whitehorn dev = OF_peer(dev); 159b2a237beSNathan Whitehorn } 160b2a237beSNathan Whitehorn if (dev == 0) { 161b2a237beSNathan Whitehorn /* 162b2a237beSNathan Whitehorn * psim doesn't have a name property on the /cpus node, 163b2a237beSNathan Whitehorn * but it can be found directly 164b2a237beSNathan Whitehorn */ 165b2a237beSNathan Whitehorn dev = OF_finddevice("/cpus"); 16607042befSJayachandran C. if (dev == -1) 167b2a237beSNathan Whitehorn return (ENOENT); 168b2a237beSNathan Whitehorn } 169b2a237beSNathan Whitehorn 170b2a237beSNathan Whitehorn cpu = OF_child(dev); 171b2a237beSNathan Whitehorn 172b2a237beSNathan Whitehorn while (cpu != 0) { 173b2a237beSNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 174b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 175b2a237beSNathan Whitehorn break; 176b2a237beSNathan Whitehorn cpu = OF_peer(cpu); 177b2a237beSNathan Whitehorn } 178b2a237beSNathan Whitehorn if (cpu == 0) 179b2a237beSNathan Whitehorn return (ENOENT); 180b2a237beSNathan Whitehorn 181b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, cpu)); 182b2a237beSNathan Whitehorn } 183b2a237beSNathan Whitehorn 184b2a237beSNathan Whitehorn static int 185b2a237beSNathan Whitehorn powermac_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 186b2a237beSNathan Whitehorn { 187b2a237beSNathan Whitehorn char buf[8]; 188b2a237beSNathan Whitehorn phandle_t cpu; 189b2a237beSNathan Whitehorn int res; 190b2a237beSNathan Whitehorn 191b2a237beSNathan Whitehorn cpu = OF_peer(cpuref->cr_hwref); 192b2a237beSNathan Whitehorn while (cpu != 0) { 193b2a237beSNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 194b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 195b2a237beSNathan Whitehorn break; 196b2a237beSNathan Whitehorn cpu = OF_peer(cpu); 197b2a237beSNathan Whitehorn } 198b2a237beSNathan Whitehorn if (cpu == 0) 199b2a237beSNathan Whitehorn return (ENOENT); 200b2a237beSNathan Whitehorn 201b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, cpu)); 202b2a237beSNathan Whitehorn } 203b2a237beSNathan Whitehorn 204b2a237beSNathan Whitehorn static int 205b2a237beSNathan Whitehorn powermac_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 206b2a237beSNathan Whitehorn { 207b2a237beSNathan Whitehorn ihandle_t inst; 208b2a237beSNathan Whitehorn phandle_t bsp, chosen; 209b2a237beSNathan Whitehorn int res; 210b2a237beSNathan Whitehorn 211b2a237beSNathan Whitehorn chosen = OF_finddevice("/chosen"); 21207042befSJayachandran C. if (chosen == -1) 213b2a237beSNathan Whitehorn return (ENXIO); 214b2a237beSNathan Whitehorn 215b2a237beSNathan Whitehorn res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); 216b2a237beSNathan Whitehorn if (res < 0) 217b2a237beSNathan Whitehorn return (ENXIO); 218b2a237beSNathan Whitehorn 219b2a237beSNathan Whitehorn bsp = OF_instance_to_package(inst); 220b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, bsp)); 221b2a237beSNathan Whitehorn } 222b2a237beSNathan Whitehorn 223b2a237beSNathan Whitehorn static int 224b2a237beSNathan Whitehorn powermac_smp_start_cpu(platform_t plat, struct pcpu *pc) 225b2a237beSNathan Whitehorn { 226b2a237beSNathan Whitehorn #ifdef SMP 227b2a237beSNathan Whitehorn phandle_t cpu; 228b2a237beSNathan Whitehorn volatile uint8_t *rstvec; 229b2a237beSNathan Whitehorn static volatile uint8_t *rstvec_virtbase = NULL; 230b2a237beSNathan Whitehorn int res, reset, timeout; 231b2a237beSNathan Whitehorn 232b2a237beSNathan Whitehorn cpu = pc->pc_hwref; 233b2a237beSNathan Whitehorn res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset)); 234b2a237beSNathan Whitehorn if (res < 0) { 235b2a237beSNathan Whitehorn reset = 0x58; 236b2a237beSNathan Whitehorn 237b2a237beSNathan Whitehorn switch (pc->pc_cpuid) { 238b2a237beSNathan Whitehorn case 0: 239b2a237beSNathan Whitehorn reset += 0x03; 240b2a237beSNathan Whitehorn break; 241b2a237beSNathan Whitehorn case 1: 242b2a237beSNathan Whitehorn reset += 0x04; 243b2a237beSNathan Whitehorn break; 244b2a237beSNathan Whitehorn case 2: 245b2a237beSNathan Whitehorn reset += 0x0f; 246b2a237beSNathan Whitehorn break; 247b2a237beSNathan Whitehorn case 3: 248b2a237beSNathan Whitehorn reset += 0x10; 249b2a237beSNathan Whitehorn break; 250b2a237beSNathan Whitehorn default: 251b2a237beSNathan Whitehorn return (ENXIO); 252b2a237beSNathan Whitehorn } 253b2a237beSNathan Whitehorn } 254b2a237beSNathan Whitehorn 255b2a237beSNathan Whitehorn ap_pcpu = pc; 256b2a237beSNathan Whitehorn 257b2a237beSNathan Whitehorn if (rstvec_virtbase == NULL) 258b2a237beSNathan Whitehorn rstvec_virtbase = pmap_mapdev(0x80000000, PAGE_SIZE); 259b2a237beSNathan Whitehorn 260b2a237beSNathan Whitehorn rstvec = rstvec_virtbase + reset; 261b2a237beSNathan Whitehorn 262b2a237beSNathan Whitehorn *rstvec = 4; 263b2a237beSNathan Whitehorn powerpc_sync(); 264b2a237beSNathan Whitehorn (void)(*rstvec); 265b2a237beSNathan Whitehorn powerpc_sync(); 266b2a237beSNathan Whitehorn DELAY(1); 267b2a237beSNathan Whitehorn *rstvec = 0; 268b2a237beSNathan Whitehorn powerpc_sync(); 269b2a237beSNathan Whitehorn (void)(*rstvec); 270b2a237beSNathan Whitehorn powerpc_sync(); 271b2a237beSNathan Whitehorn 272b2a237beSNathan Whitehorn timeout = 10000; 273b2a237beSNathan Whitehorn while (!pc->pc_awake && timeout--) 274b2a237beSNathan Whitehorn DELAY(100); 275b2a237beSNathan Whitehorn 276b2a237beSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 277b2a237beSNathan Whitehorn #else 278b2a237beSNathan Whitehorn /* No SMP support */ 279b2a237beSNathan Whitehorn return (ENXIO); 280b2a237beSNathan Whitehorn #endif 281b2a237beSNathan Whitehorn } 282b2a237beSNathan Whitehorn 283b2a237beSNathan Whitehorn static void 284b2a237beSNathan Whitehorn powermac_reset(platform_t platform) 285b2a237beSNathan Whitehorn { 286b2a237beSNathan Whitehorn OF_reboot(); 287b2a237beSNathan Whitehorn } 288b2a237beSNathan Whitehorn 289