112640815SMarcel Moolenaar /*- 212640815SMarcel Moolenaar * Copyright (c) 2008 Marcel Moolenaar 312640815SMarcel Moolenaar * All rights reserved. 412640815SMarcel Moolenaar * 512640815SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 612640815SMarcel Moolenaar * modification, are permitted provided that the following conditions 712640815SMarcel Moolenaar * are met: 812640815SMarcel Moolenaar * 912640815SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 1012640815SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 1112640815SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 1212640815SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 1312640815SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 1412640815SMarcel Moolenaar * 1512640815SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1612640815SMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1712640815SMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1812640815SMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1912640815SMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2012640815SMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2112640815SMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2212640815SMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2312640815SMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2412640815SMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2512640815SMarcel Moolenaar */ 2612640815SMarcel Moolenaar 2712640815SMarcel Moolenaar #include <sys/cdefs.h> 2812640815SMarcel Moolenaar __FBSDID("$FreeBSD$"); 2912640815SMarcel Moolenaar 3012640815SMarcel Moolenaar #include <sys/param.h> 3112640815SMarcel Moolenaar #include <sys/systm.h> 3212640815SMarcel Moolenaar #include <sys/kernel.h> 3312640815SMarcel Moolenaar #include <sys/bus.h> 3412640815SMarcel Moolenaar #include <sys/pcpu.h> 3512640815SMarcel Moolenaar #include <sys/proc.h> 3612640815SMarcel Moolenaar #include <sys/smp.h> 3712640815SMarcel Moolenaar 3812640815SMarcel Moolenaar #include <machine/bat.h> 3912640815SMarcel Moolenaar #include <machine/bus.h> 4012640815SMarcel Moolenaar #include <machine/cpu.h> 4112640815SMarcel Moolenaar #include <machine/hid.h> 4212640815SMarcel Moolenaar #include <machine/intr_machdep.h> 4312640815SMarcel Moolenaar #include <machine/pcb.h> 4412640815SMarcel Moolenaar #include <machine/psl.h> 4512640815SMarcel Moolenaar #include <machine/smp.h> 4612640815SMarcel Moolenaar #include <machine/spr.h> 4712640815SMarcel Moolenaar #include <machine/trap_aim.h> 4812640815SMarcel Moolenaar 4912640815SMarcel Moolenaar #include <dev/ofw/openfirm.h> 5012640815SMarcel Moolenaar #include <machine/ofw_machdep.h> 5112640815SMarcel Moolenaar 5212640815SMarcel Moolenaar extern void *rstcode; 5312640815SMarcel Moolenaar 5412640815SMarcel Moolenaar void *ap_pcpu; 5512640815SMarcel Moolenaar 5612640815SMarcel Moolenaar static int 5712640815SMarcel Moolenaar powerpc_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) 5812640815SMarcel Moolenaar { 5912640815SMarcel Moolenaar int cpuid, res; 6012640815SMarcel Moolenaar 6112640815SMarcel Moolenaar cpuref->cr_hwref = cpu; 6212640815SMarcel Moolenaar res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); 6312640815SMarcel Moolenaar if (res < 0) 6412640815SMarcel Moolenaar return (ENOENT); 6512640815SMarcel Moolenaar 6612640815SMarcel Moolenaar cpuref->cr_cpuid = cpuid & 0xff; 6712640815SMarcel Moolenaar return (0); 6812640815SMarcel Moolenaar } 6912640815SMarcel Moolenaar 7012640815SMarcel Moolenaar int 7112640815SMarcel Moolenaar powerpc_smp_first_cpu(struct cpuref *cpuref) 7212640815SMarcel Moolenaar { 7312640815SMarcel Moolenaar char buf[8]; 7412640815SMarcel Moolenaar phandle_t cpu, dev, root; 7512640815SMarcel Moolenaar int res; 7612640815SMarcel Moolenaar 7712640815SMarcel Moolenaar root = OF_peer(0); 7812640815SMarcel Moolenaar 7912640815SMarcel Moolenaar dev = OF_child(root); 8012640815SMarcel Moolenaar while (dev != 0) { 8112640815SMarcel Moolenaar res = OF_getprop(dev, "name", buf, sizeof(buf)); 8212640815SMarcel Moolenaar if (res > 0 && strcmp(buf, "cpus") == 0) 8312640815SMarcel Moolenaar break; 8412640815SMarcel Moolenaar dev = OF_peer(dev); 8512640815SMarcel Moolenaar } 8612640815SMarcel Moolenaar if (dev == 0) 8712640815SMarcel Moolenaar return (ENOENT); 8812640815SMarcel Moolenaar 8912640815SMarcel Moolenaar cpu = OF_child(dev); 9012640815SMarcel Moolenaar while (cpu != 0) { 9112640815SMarcel Moolenaar res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 9212640815SMarcel Moolenaar if (res > 0 && strcmp(buf, "cpu") == 0) 9312640815SMarcel Moolenaar break; 9412640815SMarcel Moolenaar cpu = OF_peer(cpu); 9512640815SMarcel Moolenaar } 9612640815SMarcel Moolenaar if (cpu == 0) 9712640815SMarcel Moolenaar return (ENOENT); 9812640815SMarcel Moolenaar 9912640815SMarcel Moolenaar return (powerpc_smp_fill_cpuref(cpuref, cpu)); 10012640815SMarcel Moolenaar } 10112640815SMarcel Moolenaar 10212640815SMarcel Moolenaar int 10312640815SMarcel Moolenaar powerpc_smp_next_cpu(struct cpuref *cpuref) 10412640815SMarcel Moolenaar { 10512640815SMarcel Moolenaar char buf[8]; 10612640815SMarcel Moolenaar phandle_t cpu; 10712640815SMarcel Moolenaar int res; 10812640815SMarcel Moolenaar 10912640815SMarcel Moolenaar cpu = OF_peer(cpuref->cr_hwref); 11012640815SMarcel Moolenaar while (cpu != 0) { 11112640815SMarcel Moolenaar res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); 11212640815SMarcel Moolenaar if (res > 0 && strcmp(buf, "cpu") == 0) 11312640815SMarcel Moolenaar break; 11412640815SMarcel Moolenaar cpu = OF_peer(cpu); 11512640815SMarcel Moolenaar } 11612640815SMarcel Moolenaar if (cpu == 0) 11712640815SMarcel Moolenaar return (ENOENT); 11812640815SMarcel Moolenaar 11912640815SMarcel Moolenaar return (powerpc_smp_fill_cpuref(cpuref, cpu)); 12012640815SMarcel Moolenaar } 12112640815SMarcel Moolenaar 12212640815SMarcel Moolenaar int 12312640815SMarcel Moolenaar powerpc_smp_get_bsp(struct cpuref *cpuref) 12412640815SMarcel Moolenaar { 12512640815SMarcel Moolenaar ihandle_t inst; 12612640815SMarcel Moolenaar phandle_t bsp, chosen; 12712640815SMarcel Moolenaar int res; 12812640815SMarcel Moolenaar 12912640815SMarcel Moolenaar chosen = OF_finddevice("/chosen"); 13012640815SMarcel Moolenaar if (chosen == 0) 13112640815SMarcel Moolenaar return (ENXIO); 13212640815SMarcel Moolenaar 13312640815SMarcel Moolenaar res = OF_getprop(chosen, "cpu", &inst, sizeof(inst)); 13412640815SMarcel Moolenaar if (res < 0) 13512640815SMarcel Moolenaar return (ENXIO); 13612640815SMarcel Moolenaar 13712640815SMarcel Moolenaar bsp = OF_instance_to_package(inst); 13812640815SMarcel Moolenaar return (powerpc_smp_fill_cpuref(cpuref, bsp)); 13912640815SMarcel Moolenaar } 14012640815SMarcel Moolenaar 14112640815SMarcel Moolenaar uint32_t 14212640815SMarcel Moolenaar cpudep_ap_bootstrap(volatile uint32_t *trcp) 14312640815SMarcel Moolenaar { 14412640815SMarcel Moolenaar uint32_t hid, msr, sp; 14512640815SMarcel Moolenaar 14612640815SMarcel Moolenaar trcp[0] = 0x2000; 14712640815SMarcel Moolenaar trcp[1] = (uint32_t)&cpudep_ap_bootstrap; 14812640815SMarcel Moolenaar 14912640815SMarcel Moolenaar __asm __volatile("mtsprg 0, %0" :: "r"(ap_pcpu)); 15012640815SMarcel Moolenaar __asm __volatile("sync"); 15112640815SMarcel Moolenaar 15212640815SMarcel Moolenaar trcp[0] = 0x2001; 15312640815SMarcel Moolenaar trcp[1] = (uint32_t)pcpup; 15412640815SMarcel Moolenaar 15512640815SMarcel Moolenaar hid = mfspr(SPR_HID0); 15612640815SMarcel Moolenaar hid &= ~(HID0_ICE | HID0_DCE); 15712640815SMarcel Moolenaar hid &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); 15812640815SMarcel Moolenaar mtspr(SPR_HID0, hid); 15912640815SMarcel Moolenaar isync(); 16012640815SMarcel Moolenaar 16112640815SMarcel Moolenaar trcp[0] = 0x2002; 16212640815SMarcel Moolenaar trcp[1] = hid; 16312640815SMarcel Moolenaar 16412640815SMarcel Moolenaar hid |= HID0_ICFI | HID0_DCFI; 16512640815SMarcel Moolenaar hid |= HID0_ICE | HID0_DCE; 16612640815SMarcel Moolenaar mtspr(SPR_HID0, hid); 16712640815SMarcel Moolenaar isync(); 16812640815SMarcel Moolenaar 16912640815SMarcel Moolenaar trcp[0] = 0x2003; 17012640815SMarcel Moolenaar trcp[1] = hid; 17112640815SMarcel Moolenaar 17212640815SMarcel Moolenaar msr = PSL_IR | PSL_DR | PSL_ME; 17312640815SMarcel Moolenaar mtmsr(msr); 17412640815SMarcel Moolenaar isync(); 17512640815SMarcel Moolenaar 17612640815SMarcel Moolenaar trcp[0] = 0x2004; 17712640815SMarcel Moolenaar trcp[1] = msr; 17812640815SMarcel Moolenaar 17912640815SMarcel Moolenaar hid |= HID0_NAP | HID0_DPM; 18012640815SMarcel Moolenaar mtspr(SPR_HID0, hid); 18112640815SMarcel Moolenaar isync(); 18212640815SMarcel Moolenaar 18312640815SMarcel Moolenaar trcp[0] = 0x2005; 18412640815SMarcel Moolenaar trcp[1] = hid; 18512640815SMarcel Moolenaar 18612640815SMarcel Moolenaar pcpup->pc_curthread = pcpup->pc_idlethread; 18712640815SMarcel Moolenaar pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb; 18812640815SMarcel Moolenaar sp = pcpup->pc_curpcb->pcb_sp; 18912640815SMarcel Moolenaar 19012640815SMarcel Moolenaar trcp[0] = 0x2006; 19112640815SMarcel Moolenaar trcp[1] = sp; 19212640815SMarcel Moolenaar 19312640815SMarcel Moolenaar return (sp); 19412640815SMarcel Moolenaar } 19512640815SMarcel Moolenaar 19612640815SMarcel Moolenaar int 19712640815SMarcel Moolenaar powerpc_smp_start_cpu(struct pcpu *pc) 19812640815SMarcel Moolenaar { 19912640815SMarcel Moolenaar phandle_t cpu; 20012640815SMarcel Moolenaar volatile uint32_t *trcp; 20112640815SMarcel Moolenaar volatile uint8_t *rstvec; 20212640815SMarcel Moolenaar uint32_t trace; 20312640815SMarcel Moolenaar int res, reset, timeout; 20412640815SMarcel Moolenaar 20512640815SMarcel Moolenaar cpu = pc->pc_hwref; 20612640815SMarcel Moolenaar res = OF_getprop(cpu, "soft-reset", &reset, sizeof(reset)); 20712640815SMarcel Moolenaar if (res < 0) 20812640815SMarcel Moolenaar return (ENXIO); 20912640815SMarcel Moolenaar 21012640815SMarcel Moolenaar trcp = (uint32_t *)(EXC_RST + 4); 21112640815SMarcel Moolenaar trace = *trcp; 21212640815SMarcel Moolenaar 21312640815SMarcel Moolenaar ap_pcpu = pc; 21412640815SMarcel Moolenaar 21512640815SMarcel Moolenaar rstvec = (uint8_t *)(0x80000000 + reset); 21612640815SMarcel Moolenaar 21712640815SMarcel Moolenaar *rstvec = 4; 21812640815SMarcel Moolenaar __asm __volatile("sync"); 21912640815SMarcel Moolenaar DELAY(1); 22012640815SMarcel Moolenaar *rstvec = 0; 22112640815SMarcel Moolenaar __asm __volatile("sync"); 22212640815SMarcel Moolenaar 22312640815SMarcel Moolenaar timeout = 1000; 22412640815SMarcel Moolenaar while (!pc->pc_awake && timeout--) 22512640815SMarcel Moolenaar DELAY(100); 22612640815SMarcel Moolenaar 22712640815SMarcel Moolenaar if (!pc->pc_awake) 22812640815SMarcel Moolenaar printf("XXX: timeout (trace=%x; data=%x)\n", trcp[0], trcp[1]); 22912640815SMarcel Moolenaar 23012640815SMarcel Moolenaar return (0); 23112640815SMarcel Moolenaar } 232