xref: /freebsd/sys/powerpc/aim/mp_cpudep.c (revision 12640815)
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