platform_powermac.c revision 198378
1192067Snwhitehorn/*- 2192067Snwhitehorn * Copyright (c) 2008 Marcel Moolenaar 3192067Snwhitehorn * Copyright (c) 2009 Nathan Whitehorn 4192067Snwhitehorn * All rights reserved. 5192067Snwhitehorn * 6192067Snwhitehorn * Redistribution and use in source and binary forms, with or without 7192067Snwhitehorn * modification, are permitted provided that the following conditions 8192067Snwhitehorn * are met: 9192067Snwhitehorn * 10192067Snwhitehorn * 1. Redistributions of source code must retain the above copyright 11192067Snwhitehorn * notice, this list of conditions and the following disclaimer. 12192067Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 13192067Snwhitehorn * notice, this list of conditions and the following disclaimer in the 14192067Snwhitehorn * documentation and/or other materials provided with the distribution. 15192067Snwhitehorn * 16192067Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17192067Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18192067Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19192067Snwhitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20192067Snwhitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21192067Snwhitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22192067Snwhitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23192067Snwhitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24192067Snwhitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25192067Snwhitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26192067Snwhitehorn */ 27192067Snwhitehorn 28192067Snwhitehorn#include <sys/cdefs.h> 29192067Snwhitehorn__FBSDID("$FreeBSD: head/sys/powerpc/aim/platform_chrp.c 198378 2009-10-23 03:17:02Z nwhitehorn $"); 30192067Snwhitehorn 31192067Snwhitehorn#include <sys/param.h> 32192067Snwhitehorn#include <sys/systm.h> 33192067Snwhitehorn#include <sys/kernel.h> 34192067Snwhitehorn#include <sys/bus.h> 35192067Snwhitehorn#include <sys/pcpu.h> 36192067Snwhitehorn#include <sys/proc.h> 37192067Snwhitehorn#include <sys/smp.h> 38198212Snwhitehorn#include <vm/vm.h> 39198212Snwhitehorn#include <vm/pmap.h> 40192067Snwhitehorn 41192067Snwhitehorn#include <machine/bus.h> 42192067Snwhitehorn#include <machine/cpu.h> 43192067Snwhitehorn#include <machine/hid.h> 44192067Snwhitehorn#include <machine/platformvar.h> 45198212Snwhitehorn#include <machine/pmap.h> 46192067Snwhitehorn#include <machine/smp.h> 47192067Snwhitehorn#include <machine/spr.h> 48192067Snwhitehorn 49192067Snwhitehorn#include <dev/ofw/openfirm.h> 50192067Snwhitehorn#include <machine/ofw_machdep.h> 51192067Snwhitehorn 52192067Snwhitehorn#include "platform_if.h" 53192067Snwhitehorn 54192067Snwhitehorn#ifdef SMP 55192067Snwhitehornextern void *ap_pcpu; 56192067Snwhitehorn#endif 57192067Snwhitehorn 58192067Snwhitehornstatic int chrp_probe(platform_t); 59192067Snwhitehornvoid chrp_mem_regions(platform_t, struct mem_region **phys, int *physsz, 60192067Snwhitehorn struct mem_region **avail, int *availsz); 61192067Snwhitehornstatic u_long chrp_timebase_freq(platform_t, struct cpuref *cpuref); 62192067Snwhitehornstatic int chrp_smp_first_cpu(platform_t, struct cpuref *cpuref); 63192067Snwhitehornstatic int chrp_smp_next_cpu(platform_t, struct cpuref *cpuref); 64192067Snwhitehornstatic int chrp_smp_get_bsp(platform_t, struct cpuref *cpuref); 65192067Snwhitehornstatic int chrp_smp_start_cpu(platform_t, struct pcpu *cpu); 66192067Snwhitehorn 67192067Snwhitehornstatic platform_method_t chrp_methods[] = { 68192067Snwhitehorn PLATFORMMETHOD(platform_probe, chrp_probe), 69192067Snwhitehorn PLATFORMMETHOD(platform_mem_regions, chrp_mem_regions), 70192067Snwhitehorn PLATFORMMETHOD(platform_timebase_freq, chrp_timebase_freq), 71192067Snwhitehorn 72192067Snwhitehorn PLATFORMMETHOD(platform_smp_first_cpu, chrp_smp_first_cpu), 73192067Snwhitehorn PLATFORMMETHOD(platform_smp_next_cpu, chrp_smp_next_cpu), 74192067Snwhitehorn PLATFORMMETHOD(platform_smp_get_bsp, chrp_smp_get_bsp), 75192067Snwhitehorn PLATFORMMETHOD(platform_smp_start_cpu, chrp_smp_start_cpu), 76192067Snwhitehorn 77192067Snwhitehorn { 0, 0 } 78192067Snwhitehorn}; 79192067Snwhitehorn 80192067Snwhitehornstatic platform_def_t chrp_platform = { 81192067Snwhitehorn "chrp", 82192067Snwhitehorn chrp_methods, 83192067Snwhitehorn 0 84192067Snwhitehorn}; 85192067Snwhitehorn 86192067SnwhitehornPLATFORM_DEF(chrp_platform); 87192067Snwhitehorn 88192067Snwhitehornstatic int 89192067Snwhitehornchrp_probe(platform_t plat) 90192067Snwhitehorn{ 91192067Snwhitehorn if (OF_finddevice("/memory") != -1) 92192067Snwhitehorn return (BUS_PROBE_GENERIC); 93192067Snwhitehorn 94192067Snwhitehorn return (ENXIO); 95192067Snwhitehorn} 96192067Snwhitehorn 97192067Snwhitehornvoid 98192067Snwhitehornchrp_mem_regions(platform_t plat, struct mem_region **phys, int *physsz, 99192067Snwhitehorn struct mem_region **avail, int *availsz) 100192067Snwhitehorn{ 101192067Snwhitehorn ofw_mem_regions(phys,physsz,avail,availsz); 102192067Snwhitehorn} 103192067Snwhitehorn 104192067Snwhitehornstatic u_long 105192067Snwhitehornchrp_timebase_freq(platform_t plat, struct cpuref *cpuref) 106192067Snwhitehorn{ 107192067Snwhitehorn phandle_t phandle; 108193909Sgrehan long ticks = -1; 109192067Snwhitehorn 110192067Snwhitehorn phandle = cpuref->cr_hwref; 111192067Snwhitehorn 112192067Snwhitehorn OF_getprop(phandle, "timebase-frequency", &ticks, sizeof(ticks)); 113192067Snwhitehorn 114192067Snwhitehorn if (ticks <= 0) 115192067Snwhitehorn panic("Unable to determine timebase frequency!"); 116192067Snwhitehorn 117192067Snwhitehorn return (ticks); 118192067Snwhitehorn} 119192067Snwhitehorn 120192067Snwhitehorn 121192067Snwhitehornstatic int 122192067Snwhitehornchrp_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) 123192067Snwhitehorn{ 124192067Snwhitehorn int cpuid, res; 125192067Snwhitehorn 126192067Snwhitehorn cpuref->cr_hwref = cpu; 127192067Snwhitehorn res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 128192067Snwhitehorn 129193909Sgrehan /* 130193909Sgrehan * psim doesn't have a reg property, so assume 0 as for the 131193909Sgrehan * uniprocessor case in the CHRP spec. 132193909Sgrehan */ 133193909Sgrehan if (res < 0) { 134193909Sgrehan cpuid = 0; 135193909Sgrehan } 136193909Sgrehan 137192067Snwhitehorn cpuref->cr_cpuid = cpuid & 0xff; 138192067Snwhitehorn return (0); 139192067Snwhitehorn} 140192067Snwhitehorn 141192067Snwhitehornstatic int 142192067Snwhitehornchrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref) 143192067Snwhitehorn{ 144192067Snwhitehorn char buf[8]; 145192067Snwhitehorn phandle_t cpu, dev, root; 146192067Snwhitehorn int res; 147192067Snwhitehorn 148192067Snwhitehorn root = OF_peer(0); 149192067Snwhitehorn 150192067Snwhitehorn dev = OF_child(root); 151192067Snwhitehorn while (dev != 0) { 152192067Snwhitehorn res = OF_getprop(dev, "name", buf, sizeof(buf)); 153192067Snwhitehorn if (res > 0 && strcmp(buf, "cpus") == 0) 154192067Snwhitehorn break; 155192067Snwhitehorn dev = OF_peer(dev); 156192067Snwhitehorn } 157193909Sgrehan if (dev == 0) { 158193909Sgrehan /* 159193909Sgrehan * psim doesn't have a name property on the /cpus node, 160193909Sgrehan * but it can be found directly 161193909Sgrehan */ 162193909Sgrehan dev = OF_finddevice("/cpus"); 163193909Sgrehan if (dev == 0) 164193909Sgrehan return (ENOENT); 165193909Sgrehan } 166192067Snwhitehorn 167192067Snwhitehorn cpu = OF_child(dev); 168193909Sgrehan 169192067Snwhitehorn while (cpu != 0) { 170192067Snwhitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 171192067Snwhitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 172192067Snwhitehorn break; 173192067Snwhitehorn cpu = OF_peer(cpu); 174192067Snwhitehorn } 175192067Snwhitehorn if (cpu == 0) 176192067Snwhitehorn return (ENOENT); 177192067Snwhitehorn 178192067Snwhitehorn return (chrp_smp_fill_cpuref(cpuref, cpu)); 179192067Snwhitehorn} 180192067Snwhitehorn 181192067Snwhitehornstatic int 182192067Snwhitehornchrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref) 183192067Snwhitehorn{ 184192067Snwhitehorn char buf[8]; 185192067Snwhitehorn phandle_t cpu; 186192067Snwhitehorn int res; 187192067Snwhitehorn 188192067Snwhitehorn cpu = OF_peer(cpuref->cr_hwref); 189192067Snwhitehorn while (cpu != 0) { 190192067Snwhitehorn res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 191192067Snwhitehorn if (res > 0 && strcmp(buf, "cpu") == 0) 192192067Snwhitehorn break; 193192067Snwhitehorn cpu = OF_peer(cpu); 194192067Snwhitehorn } 195192067Snwhitehorn if (cpu == 0) 196192067Snwhitehorn return (ENOENT); 197192067Snwhitehorn 198192067Snwhitehorn return (chrp_smp_fill_cpuref(cpuref, cpu)); 199192067Snwhitehorn} 200192067Snwhitehorn 201192067Snwhitehornstatic int 202192067Snwhitehornchrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref) 203192067Snwhitehorn{ 204192067Snwhitehorn ihandle_t inst; 205192067Snwhitehorn phandle_t bsp, chosen; 206192067Snwhitehorn int res; 207192067Snwhitehorn 208192067Snwhitehorn chosen = OF_finddevice("/chosen"); 209192067Snwhitehorn if (chosen == 0) 210192067Snwhitehorn return (ENXIO); 211192067Snwhitehorn 212192067Snwhitehorn res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); 213192067Snwhitehorn if (res < 0) 214192067Snwhitehorn return (ENXIO); 215192067Snwhitehorn 216192067Snwhitehorn bsp = OF_instance_to_package(inst); 217192067Snwhitehorn return (chrp_smp_fill_cpuref(cpuref, bsp)); 218192067Snwhitehorn} 219192067Snwhitehorn 220192067Snwhitehornstatic int 221192067Snwhitehornchrp_smp_start_cpu(platform_t plat, struct pcpu *pc) 222192067Snwhitehorn{ 223192067Snwhitehorn#ifdef SMP 224192067Snwhitehorn phandle_t cpu; 225192067Snwhitehorn volatile uint8_t *rstvec; 226198212Snwhitehorn static volatile uint8_t *rstvec_virtbase = NULL; 227192067Snwhitehorn int res, reset, timeout; 228192067Snwhitehorn 229192067Snwhitehorn cpu = pc->pc_hwref; 230192067Snwhitehorn res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset)); 231192067Snwhitehorn if (res < 0) 232192067Snwhitehorn return (ENXIO); 233192067Snwhitehorn 234192067Snwhitehorn ap_pcpu = pc; 235192067Snwhitehorn 236198212Snwhitehorn if (rstvec_virtbase == NULL) 237198212Snwhitehorn rstvec_virtbase = pmap_mapdev(0x80000000, PAGE_SIZE); 238192067Snwhitehorn 239198212Snwhitehorn rstvec = rstvec_virtbase + reset; 240198212Snwhitehorn 241192067Snwhitehorn *rstvec = 4; 242198378Snwhitehorn (void)(*rstvec); 243192067Snwhitehorn powerpc_sync(); 244192067Snwhitehorn DELAY(1); 245192067Snwhitehorn *rstvec = 0; 246198378Snwhitehorn (void)(*rstvec); 247192067Snwhitehorn powerpc_sync(); 248192067Snwhitehorn 249198378Snwhitehorn timeout = 10000; 250192067Snwhitehorn while (!pc->pc_awake && timeout--) 251192067Snwhitehorn DELAY(100); 252192067Snwhitehorn 253192067Snwhitehorn return ((pc->pc_awake) ? 0 : EBUSY); 254192067Snwhitehorn#else 255192067Snwhitehorn /* No SMP support */ 256192067Snwhitehorn return (ENXIO); 257192067Snwhitehorn#endif 258192067Snwhitehorn} 259192067Snwhitehorn 260