1b2a237beSNathan Whitehorn /*- 271e3c308SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 371e3c308SPedro F. Giffuni * 4b2a237beSNathan Whitehorn * Copyright (c) 2008 Marcel Moolenaar 5b2a237beSNathan Whitehorn * Copyright (c) 2009 Nathan Whitehorn 6b2a237beSNathan Whitehorn * All rights reserved. 7b2a237beSNathan Whitehorn * 8b2a237beSNathan Whitehorn * Redistribution and use in source and binary forms, with or without 9b2a237beSNathan Whitehorn * modification, are permitted provided that the following conditions 10b2a237beSNathan Whitehorn * are met: 11b2a237beSNathan Whitehorn * 12b2a237beSNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 13b2a237beSNathan Whitehorn * notice, this list of conditions and the following disclaimer. 14b2a237beSNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 15b2a237beSNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 16b2a237beSNathan Whitehorn * documentation and/or other materials provided with the distribution. 17b2a237beSNathan Whitehorn * 18b2a237beSNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19b2a237beSNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20b2a237beSNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21b2a237beSNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22b2a237beSNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23b2a237beSNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24b2a237beSNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25b2a237beSNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26b2a237beSNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27b2a237beSNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28b2a237beSNathan Whitehorn */ 29b2a237beSNathan Whitehorn 30b2a237beSNathan Whitehorn #include <sys/cdefs.h> 31b2a237beSNathan Whitehorn __FBSDID("$FreeBSD$"); 32b2a237beSNathan Whitehorn 33b2a237beSNathan Whitehorn #include <sys/param.h> 34b2a237beSNathan Whitehorn #include <sys/systm.h> 35b2a237beSNathan Whitehorn #include <sys/kernel.h> 36b2a237beSNathan Whitehorn #include <sys/bus.h> 37b2a237beSNathan Whitehorn #include <sys/pcpu.h> 38b2a237beSNathan Whitehorn #include <sys/proc.h> 39b2a237beSNathan Whitehorn #include <sys/smp.h> 40b2a237beSNathan Whitehorn #include <vm/vm.h> 41b2a237beSNathan Whitehorn #include <vm/pmap.h> 42b2a237beSNathan Whitehorn 43e1c161e7SJustin Hibbits #include <machine/altivec.h> /* For save_vec() */ 44b2a237beSNathan Whitehorn #include <machine/bus.h> 45b2a237beSNathan Whitehorn #include <machine/cpu.h> 46e1c161e7SJustin Hibbits #include <machine/fpu.h> /* For save_fpu() */ 47b2a237beSNathan Whitehorn #include <machine/hid.h> 48b2a237beSNathan Whitehorn #include <machine/platformvar.h> 49e1c161e7SJustin Hibbits #include <machine/setjmp.h> 50b2a237beSNathan Whitehorn #include <machine/smp.h> 51b2a237beSNathan Whitehorn #include <machine/spr.h> 52b2a237beSNathan Whitehorn 53b2a237beSNathan Whitehorn #include <dev/ofw/openfirm.h> 54b2a237beSNathan Whitehorn #include <machine/ofw_machdep.h> 55b2a237beSNathan Whitehorn 56b2a237beSNathan Whitehorn #include "platform_if.h" 57b2a237beSNathan Whitehorn 58b2a237beSNathan Whitehorn extern void *ap_pcpu; 59b2a237beSNathan Whitehorn 60b2a237beSNathan Whitehorn static int powermac_probe(platform_t); 619f706727SNathan Whitehorn static int powermac_attach(platform_t); 62c1cb22d7SNathan Whitehorn void powermac_mem_regions(platform_t, struct mem_region *phys, int *physsz, 63c1cb22d7SNathan Whitehorn struct mem_region *avail, int *availsz); 64b2a237beSNathan Whitehorn static u_long powermac_timebase_freq(platform_t, struct cpuref *cpuref); 65b2a237beSNathan Whitehorn static int powermac_smp_first_cpu(platform_t, struct cpuref *cpuref); 66b2a237beSNathan Whitehorn static int powermac_smp_next_cpu(platform_t, struct cpuref *cpuref); 67b2a237beSNathan Whitehorn static int powermac_smp_get_bsp(platform_t, struct cpuref *cpuref); 68b2a237beSNathan Whitehorn static int powermac_smp_start_cpu(platform_t, struct pcpu *cpu); 69de2dd83fSNathan Whitehorn static void powermac_smp_timebase_sync(platform_t, u_long tb, int ap); 70b2a237beSNathan Whitehorn static void powermac_reset(platform_t); 71*b6d8f3b5SJustin Hibbits #ifndef __powerpc64__ 72e1c161e7SJustin Hibbits static void powermac_sleep(platform_t); 73*b6d8f3b5SJustin Hibbits #endif 74b2a237beSNathan Whitehorn 75b2a237beSNathan Whitehorn static platform_method_t powermac_methods[] = { 76b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_probe, powermac_probe), 779f706727SNathan Whitehorn PLATFORMMETHOD(platform_attach, powermac_attach), 78b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_mem_regions, powermac_mem_regions), 79b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_timebase_freq, powermac_timebase_freq), 80b2a237beSNathan Whitehorn 81b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_first_cpu, powermac_smp_first_cpu), 82b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_next_cpu, powermac_smp_next_cpu), 83b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_get_bsp, powermac_smp_get_bsp), 84b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_smp_start_cpu, powermac_smp_start_cpu), 85de2dd83fSNathan Whitehorn PLATFORMMETHOD(platform_smp_timebase_sync, powermac_smp_timebase_sync), 86b2a237beSNathan Whitehorn 87b2a237beSNathan Whitehorn PLATFORMMETHOD(platform_reset, powermac_reset), 88*b6d8f3b5SJustin Hibbits #ifndef __powerpc64__ 89e1c161e7SJustin Hibbits PLATFORMMETHOD(platform_sleep, powermac_sleep), 90*b6d8f3b5SJustin Hibbits #endif 91b2a237beSNathan Whitehorn 92eaba9848SRui Paulo PLATFORMMETHOD_END 93b2a237beSNathan Whitehorn }; 94b2a237beSNathan Whitehorn 95b2a237beSNathan Whitehorn static platform_def_t powermac_platform = { 96b2a237beSNathan Whitehorn "powermac", 97b2a237beSNathan Whitehorn powermac_methods, 98b2a237beSNathan Whitehorn 0 99b2a237beSNathan Whitehorn }; 100b2a237beSNathan Whitehorn 101b2a237beSNathan Whitehorn PLATFORM_DEF(powermac_platform); 102b2a237beSNathan Whitehorn 103b2a237beSNathan Whitehorn static int 104b2a237beSNathan Whitehorn powermac_probe(platform_t plat) 105b2a237beSNathan Whitehorn { 1065d46492dSNathan Whitehorn char compat[255]; 1075d46492dSNathan Whitehorn ssize_t compatlen; 1085d46492dSNathan Whitehorn char *curstr; 1095d46492dSNathan Whitehorn phandle_t root; 1105d46492dSNathan Whitehorn 1115d46492dSNathan Whitehorn root = OF_peer(0); 1125d46492dSNathan Whitehorn if (root == 0) 1135d46492dSNathan Whitehorn return (ENXIO); 1145d46492dSNathan Whitehorn 1155d46492dSNathan Whitehorn compatlen = OF_getprop(root, "compatible", compat, sizeof(compat)); 1165d46492dSNathan Whitehorn 1175d46492dSNathan Whitehorn for (curstr = compat; curstr < compat + compatlen; 1185d46492dSNathan Whitehorn curstr += strlen(curstr) + 1) { 1195d46492dSNathan Whitehorn if (strncmp(curstr, "MacRISC", 7) == 0) 1205d46492dSNathan Whitehorn return (BUS_PROBE_SPECIFIC); 1215d46492dSNathan Whitehorn } 122b2a237beSNathan Whitehorn 123b2a237beSNathan Whitehorn return (ENXIO); 124b2a237beSNathan Whitehorn } 125b2a237beSNathan Whitehorn 126b2a237beSNathan Whitehorn void 127c1cb22d7SNathan Whitehorn powermac_mem_regions(platform_t plat, struct mem_region *phys, int *physsz, 128c1cb22d7SNathan Whitehorn struct mem_region *avail, int *availsz) 129b2a237beSNathan Whitehorn { 130c1cb22d7SNathan Whitehorn phandle_t memory; 131c1cb22d7SNathan Whitehorn cell_t memoryprop[PHYS_AVAIL_SZ * 2]; 132c1cb22d7SNathan Whitehorn ssize_t propsize, i, j; 133c1cb22d7SNathan Whitehorn int physacells = 1; 134c1cb22d7SNathan Whitehorn 135c1cb22d7SNathan Whitehorn memory = OF_finddevice("/memory"); 136276df218SNathan Whitehorn if (memory == -1) 137276df218SNathan Whitehorn memory = OF_finddevice("/memory@0"); 138c1cb22d7SNathan Whitehorn 139c1cb22d7SNathan Whitehorn /* "reg" has variable #address-cells, but #size-cells is always 1 */ 140c1cb22d7SNathan Whitehorn OF_getprop(OF_parent(memory), "#address-cells", &physacells, 141c1cb22d7SNathan Whitehorn sizeof(physacells)); 142c1cb22d7SNathan Whitehorn 143c1cb22d7SNathan Whitehorn propsize = OF_getprop(memory, "reg", memoryprop, sizeof(memoryprop)); 144c1cb22d7SNathan Whitehorn propsize /= sizeof(cell_t); 145c1cb22d7SNathan Whitehorn for (i = 0, j = 0; i < propsize; i += physacells+1, j++) { 146c1cb22d7SNathan Whitehorn phys[j].mr_start = memoryprop[i]; 147c1cb22d7SNathan Whitehorn if (physacells == 2) { 148c1cb22d7SNathan Whitehorn #ifndef __powerpc64__ 149c1cb22d7SNathan Whitehorn /* On 32-bit PPC, ignore regions starting above 4 GB */ 150c1cb22d7SNathan Whitehorn if (memoryprop[i] != 0) { 151c1cb22d7SNathan Whitehorn j--; 152c1cb22d7SNathan Whitehorn continue; 153c1cb22d7SNathan Whitehorn } 154c1cb22d7SNathan Whitehorn #else 155c1cb22d7SNathan Whitehorn phys[j].mr_start <<= 32; 156c1cb22d7SNathan Whitehorn #endif 157c1cb22d7SNathan Whitehorn phys[j].mr_start |= memoryprop[i+1]; 158c1cb22d7SNathan Whitehorn } 159c1cb22d7SNathan Whitehorn phys[j].mr_size = memoryprop[i + physacells]; 160c1cb22d7SNathan Whitehorn } 161c1cb22d7SNathan Whitehorn *physsz = j; 162c1cb22d7SNathan Whitehorn 163c1cb22d7SNathan Whitehorn /* "available" always has #address-cells = 1 */ 164c1cb22d7SNathan Whitehorn propsize = OF_getprop(memory, "available", memoryprop, 165c1cb22d7SNathan Whitehorn sizeof(memoryprop)); 166276df218SNathan Whitehorn if (propsize <= 0) { 167276df218SNathan Whitehorn for (i = 0; i < *physsz; i++) { 168276df218SNathan Whitehorn avail[i].mr_start = phys[i].mr_start; 169276df218SNathan Whitehorn avail[i].mr_size = phys[i].mr_size; 170276df218SNathan Whitehorn } 171276df218SNathan Whitehorn 172276df218SNathan Whitehorn *availsz = *physsz; 173276df218SNathan Whitehorn } else { 174c1cb22d7SNathan Whitehorn propsize /= sizeof(cell_t); 175c1cb22d7SNathan Whitehorn for (i = 0, j = 0; i < propsize; i += 2, j++) { 176c1cb22d7SNathan Whitehorn avail[j].mr_start = memoryprop[i]; 177c1cb22d7SNathan Whitehorn avail[j].mr_size = memoryprop[i + 1]; 178c1cb22d7SNathan Whitehorn } 179c1cb22d7SNathan Whitehorn 180c1cb22d7SNathan Whitehorn #ifdef __powerpc64__ 181c1cb22d7SNathan Whitehorn /* Add in regions above 4 GB to the available list */ 182c1cb22d7SNathan Whitehorn for (i = 0; i < *physsz; i++) { 183c1cb22d7SNathan Whitehorn if (phys[i].mr_start > BUS_SPACE_MAXADDR_32BIT) { 184c1cb22d7SNathan Whitehorn avail[j].mr_start = phys[i].mr_start; 185c1cb22d7SNathan Whitehorn avail[j].mr_size = phys[i].mr_size; 186c1cb22d7SNathan Whitehorn j++; 187c1cb22d7SNathan Whitehorn } 188c1cb22d7SNathan Whitehorn } 189c1cb22d7SNathan Whitehorn #endif 190c1cb22d7SNathan Whitehorn *availsz = j; 191b2a237beSNathan Whitehorn } 192276df218SNathan Whitehorn } 193b2a237beSNathan Whitehorn 1949f706727SNathan Whitehorn static int 1959f706727SNathan Whitehorn powermac_attach(platform_t plat) 1969f706727SNathan Whitehorn { 1979f706727SNathan Whitehorn phandle_t rootnode; 1989f706727SNathan Whitehorn char model[32]; 1999f706727SNathan Whitehorn 2009f706727SNathan Whitehorn /* 2019f706727SNathan Whitehorn * Quiesce Open Firmware on PowerMac11,2 and 12,1. It is 2029f706727SNathan Whitehorn * necessary there to shut down a background thread doing fan 2039f706727SNathan Whitehorn * management, and is harmful on other machines (it will make OF 2049f706727SNathan Whitehorn * shut off power to various system components it had turned on). 2059f706727SNathan Whitehorn * 2069f706727SNathan Whitehorn * Note: we don't need to worry about which OF module we are 2079f706727SNathan Whitehorn * using since this is called only from very early boot, within 2089f706727SNathan Whitehorn * OF's boot context. 2099f706727SNathan Whitehorn */ 2109f706727SNathan Whitehorn 2119f706727SNathan Whitehorn rootnode = OF_finddevice("/"); 2129f706727SNathan Whitehorn if (OF_getprop(rootnode, "model", model, sizeof(model)) > 0) { 2139f706727SNathan Whitehorn if (strcmp(model, "PowerMac11,2") == 0 || 2149f706727SNathan Whitehorn strcmp(model, "PowerMac12,1") == 0) { 2159f706727SNathan Whitehorn ofw_quiesce(); 2169f706727SNathan Whitehorn } 2179f706727SNathan Whitehorn } 2189f706727SNathan Whitehorn 2199f706727SNathan Whitehorn return (0); 2209f706727SNathan Whitehorn } 2219f706727SNathan Whitehorn 222b2a237beSNathan Whitehorn static u_long 223b2a237beSNathan Whitehorn powermac_timebase_freq(platform_t plat, struct cpuref *cpuref) 224b2a237beSNathan Whitehorn { 225b2a237beSNathan Whitehorn phandle_t phandle; 226b2a237beSNathan Whitehorn int32_t ticks = -1; 227b2a237beSNathan Whitehorn 228b2a237beSNathan Whitehorn phandle = cpuref->cr_hwref; 229b2a237beSNathan Whitehorn 230b2a237beSNathan Whitehorn OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); 231b2a237beSNathan Whitehorn 232b2a237beSNathan Whitehorn if (ticks <= 0) 233b2a237beSNathan Whitehorn panic("Unable to determine timebase frequency!"); 234b2a237beSNathan Whitehorn 235b2a237beSNathan Whitehorn return (ticks); 236b2a237beSNathan Whitehorn } 237b2a237beSNathan Whitehorn 238b2a237beSNathan Whitehorn static int 239b2a237beSNathan Whitehorn powermac_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) 240b2a237beSNathan Whitehorn { 241e17bec91SJustin Hibbits cell_t cpuid; 242e17bec91SJustin Hibbits int res; 243b2a237beSNathan Whitehorn 244b2a237beSNathan Whitehorn cpuref->cr_hwref = cpu; 245b2a237beSNathan Whitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 246b2a237beSNathan Whitehorn 247b2a237beSNathan Whitehorn /* 248b2a237beSNathan Whitehorn * psim doesn't have a reg property, so assume 0 as for the 249b2a237beSNathan Whitehorn * uniprocessor case in the CHRP spec. 250b2a237beSNathan Whitehorn */ 251b2a237beSNathan Whitehorn if (res < 0) { 252b2a237beSNathan Whitehorn cpuid = 0; 253b2a237beSNathan Whitehorn } 254b2a237beSNathan Whitehorn 255b2a237beSNathan Whitehorn cpuref->cr_cpuid = cpuid & 0xff; 256b2a237beSNathan Whitehorn return (0); 257b2a237beSNathan Whitehorn } 258b2a237beSNathan Whitehorn 259b2a237beSNathan Whitehorn static int 260b2a237beSNathan Whitehorn powermac_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 261b2a237beSNathan Whitehorn { 262b2a237beSNathan Whitehorn char buf[8]; 263b2a237beSNathan Whitehorn phandle_t cpu, dev, root; 264b2a237beSNathan Whitehorn int res; 265b2a237beSNathan Whitehorn 266b2a237beSNathan Whitehorn root = OF_peer(0); 267b2a237beSNathan Whitehorn 268b2a237beSNathan Whitehorn dev = OF_child(root); 269b2a237beSNathan Whitehorn while (dev != 0) { 270b2a237beSNathan Whitehorn res = OF_getprop(dev, "name", buf, sizeof(buf)); 271b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpus") == 0) 272b2a237beSNathan Whitehorn break; 273b2a237beSNathan Whitehorn dev = OF_peer(dev); 274b2a237beSNathan Whitehorn } 275b2a237beSNathan Whitehorn if (dev == 0) { 276b2a237beSNathan Whitehorn /* 277b2a237beSNathan Whitehorn * psim doesn't have a name property on the /cpus node, 278b2a237beSNathan Whitehorn * but it can be found directly 279b2a237beSNathan Whitehorn */ 280b2a237beSNathan Whitehorn dev = OF_finddevice("/cpus"); 28107042befSJayachandran C. if (dev == -1) 282b2a237beSNathan Whitehorn return (ENOENT); 283b2a237beSNathan Whitehorn } 284b2a237beSNathan Whitehorn 285b2a237beSNathan Whitehorn cpu = OF_child(dev); 286b2a237beSNathan Whitehorn 287b2a237beSNathan Whitehorn while (cpu != 0) { 288b2a237beSNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 289b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 290b2a237beSNathan Whitehorn break; 291b2a237beSNathan Whitehorn cpu = OF_peer(cpu); 292b2a237beSNathan Whitehorn } 293b2a237beSNathan Whitehorn if (cpu == 0) 294b2a237beSNathan Whitehorn return (ENOENT); 295b2a237beSNathan Whitehorn 296b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, cpu)); 297b2a237beSNathan Whitehorn } 298b2a237beSNathan Whitehorn 299b2a237beSNathan Whitehorn static int 300b2a237beSNathan Whitehorn powermac_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 301b2a237beSNathan Whitehorn { 302b2a237beSNathan Whitehorn char buf[8]; 303b2a237beSNathan Whitehorn phandle_t cpu; 304b2a237beSNathan Whitehorn int res; 305b2a237beSNathan Whitehorn 306b2a237beSNathan Whitehorn cpu = OF_peer(cpuref->cr_hwref); 307b2a237beSNathan Whitehorn while (cpu != 0) { 308b2a237beSNathan Whitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 309b2a237beSNathan Whitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 310b2a237beSNathan Whitehorn break; 311b2a237beSNathan Whitehorn cpu = OF_peer(cpu); 312b2a237beSNathan Whitehorn } 313b2a237beSNathan Whitehorn if (cpu == 0) 314b2a237beSNathan Whitehorn return (ENOENT); 315b2a237beSNathan Whitehorn 316b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, cpu)); 317b2a237beSNathan Whitehorn } 318b2a237beSNathan Whitehorn 319b2a237beSNathan Whitehorn static int 320b2a237beSNathan Whitehorn powermac_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 321b2a237beSNathan Whitehorn { 322b2a237beSNathan Whitehorn ihandle_t inst; 323b2a237beSNathan Whitehorn phandle_t bsp, chosen; 324b2a237beSNathan Whitehorn int res; 325b2a237beSNathan Whitehorn 326b2a237beSNathan Whitehorn chosen = OF_finddevice("/chosen"); 32707042befSJayachandran C. if (chosen == -1) 328b2a237beSNathan Whitehorn return (ENXIO); 329b2a237beSNathan Whitehorn 330b2a237beSNathan Whitehorn res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); 331b2a237beSNathan Whitehorn if (res < 0) 332b2a237beSNathan Whitehorn return (ENXIO); 333b2a237beSNathan Whitehorn 334b2a237beSNathan Whitehorn bsp = OF_instance_to_package(inst); 335b2a237beSNathan Whitehorn return (powermac_smp_fill_cpuref(cpuref, bsp)); 336b2a237beSNathan Whitehorn } 337b2a237beSNathan Whitehorn 338b2a237beSNathan Whitehorn static int 339b2a237beSNathan Whitehorn powermac_smp_start_cpu(platform_t plat, struct pcpu *pc) 340b2a237beSNathan Whitehorn { 341b2a237beSNathan Whitehorn #ifdef SMP 342b2a237beSNathan Whitehorn phandle_t cpu; 343b2a237beSNathan Whitehorn volatile uint8_t *rstvec; 344b2a237beSNathan Whitehorn static volatile uint8_t *rstvec_virtbase = NULL; 345b2a237beSNathan Whitehorn int res, reset, timeout; 346b2a237beSNathan Whitehorn 347b2a237beSNathan Whitehorn cpu = pc->pc_hwref; 348b2a237beSNathan Whitehorn res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset)); 349b2a237beSNathan Whitehorn if (res < 0) { 350b2a237beSNathan Whitehorn reset = 0x58; 351b2a237beSNathan Whitehorn 352b2a237beSNathan Whitehorn switch (pc->pc_cpuid) { 353b2a237beSNathan Whitehorn case 0: 354b2a237beSNathan Whitehorn reset += 0x03; 355b2a237beSNathan Whitehorn break; 356b2a237beSNathan Whitehorn case 1: 357b2a237beSNathan Whitehorn reset += 0x04; 358b2a237beSNathan Whitehorn break; 359b2a237beSNathan Whitehorn case 2: 360b2a237beSNathan Whitehorn reset += 0x0f; 361b2a237beSNathan Whitehorn break; 362b2a237beSNathan Whitehorn case 3: 363b2a237beSNathan Whitehorn reset += 0x10; 364b2a237beSNathan Whitehorn break; 365b2a237beSNathan Whitehorn default: 366b2a237beSNathan Whitehorn return (ENXIO); 367b2a237beSNathan Whitehorn } 368b2a237beSNathan Whitehorn } 369b2a237beSNathan Whitehorn 370b2a237beSNathan Whitehorn ap_pcpu = pc; 371b2a237beSNathan Whitehorn 372b2a237beSNathan Whitehorn if (rstvec_virtbase == NULL) 373b2a237beSNathan Whitehorn rstvec_virtbase = pmap_mapdev(0x80000000, PAGE_SIZE); 374b2a237beSNathan Whitehorn 375b2a237beSNathan Whitehorn rstvec = rstvec_virtbase + reset; 376b2a237beSNathan Whitehorn 377b2a237beSNathan Whitehorn *rstvec = 4; 378b2a237beSNathan Whitehorn powerpc_sync(); 379b2a237beSNathan Whitehorn (void)(*rstvec); 380b2a237beSNathan Whitehorn powerpc_sync(); 381b2a237beSNathan Whitehorn DELAY(1); 382b2a237beSNathan Whitehorn *rstvec = 0; 383b2a237beSNathan Whitehorn powerpc_sync(); 384b2a237beSNathan Whitehorn (void)(*rstvec); 385b2a237beSNathan Whitehorn powerpc_sync(); 386b2a237beSNathan Whitehorn 387b2a237beSNathan Whitehorn timeout = 10000; 388b2a237beSNathan Whitehorn while (!pc->pc_awake && timeout--) 389b2a237beSNathan Whitehorn DELAY(100); 390b2a237beSNathan Whitehorn 391b2a237beSNathan Whitehorn return ((pc->pc_awake) ? 0 : EBUSY); 392b2a237beSNathan Whitehorn #else 393b2a237beSNathan Whitehorn /* No SMP support */ 394b2a237beSNathan Whitehorn return (ENXIO); 395b2a237beSNathan Whitehorn #endif 396b2a237beSNathan Whitehorn } 397b2a237beSNathan Whitehorn 398b2a237beSNathan Whitehorn static void 399de2dd83fSNathan Whitehorn powermac_smp_timebase_sync(platform_t plat, u_long tb, int ap) 400de2dd83fSNathan Whitehorn { 401de2dd83fSNathan Whitehorn 402de2dd83fSNathan Whitehorn mttb(tb); 403de2dd83fSNathan Whitehorn } 404de2dd83fSNathan Whitehorn 405de2dd83fSNathan Whitehorn static void 406b2a237beSNathan Whitehorn powermac_reset(platform_t platform) 407b2a237beSNathan Whitehorn { 408b2a237beSNathan Whitehorn OF_reboot(); 409b2a237beSNathan Whitehorn } 410b2a237beSNathan Whitehorn 411*b6d8f3b5SJustin Hibbits #ifndef __powerpc64__ 412e1c161e7SJustin Hibbits void 413e1c161e7SJustin Hibbits powermac_sleep(platform_t platform) 414e1c161e7SJustin Hibbits { 415*b6d8f3b5SJustin Hibbits /* Only supports MPC745x for now. */ 416*b6d8f3b5SJustin Hibbits if (!MPC745X_P(mfspr(SPR_PVR) >> 16)) { 417*b6d8f3b5SJustin Hibbits printf("sleep only supported for G4 PowerMac hardware.\n"); 418*b6d8f3b5SJustin Hibbits return; 419*b6d8f3b5SJustin Hibbits } 420e1c161e7SJustin Hibbits 421e1c161e7SJustin Hibbits *(unsigned long *)0x80 = 0x100; 422*b6d8f3b5SJustin Hibbits mpc745x_sleep(); 423e1c161e7SJustin Hibbits } 424*b6d8f3b5SJustin Hibbits #endif 425