xref: /freebsd/sys/powerpc/booke/platform_bare.c (revision 2b7b2d7952afef181f77eded6d846bb68d10e002)
1b40ce02aSNathan Whitehorn /*-
2b40ce02aSNathan Whitehorn  * Copyright (c) 2008-2009 Semihalf, Rafal Jaworowski
3b40ce02aSNathan Whitehorn  * All rights reserved.
4b40ce02aSNathan Whitehorn  *
5b40ce02aSNathan Whitehorn  * Redistribution and use in source and binary forms, with or without
6b40ce02aSNathan Whitehorn  * modification, are permitted provided that the following conditions
7b40ce02aSNathan Whitehorn  * are met:
8b40ce02aSNathan Whitehorn  *
9b40ce02aSNathan Whitehorn  * 1. Redistributions of source code must retain the above copyright
10b40ce02aSNathan Whitehorn  *    notice, this list of conditions and the following disclaimer.
11b40ce02aSNathan Whitehorn  * 2. Redistributions in binary form must reproduce the above copyright
12b40ce02aSNathan Whitehorn  *    notice, this list of conditions and the following disclaimer in the
13b40ce02aSNathan Whitehorn  *    documentation and/or other materials provided with the distribution.
14b40ce02aSNathan Whitehorn  *
15b40ce02aSNathan Whitehorn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16b40ce02aSNathan Whitehorn  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17b40ce02aSNathan Whitehorn  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18b40ce02aSNathan Whitehorn  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19b40ce02aSNathan Whitehorn  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20b40ce02aSNathan Whitehorn  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21b40ce02aSNathan Whitehorn  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22b40ce02aSNathan Whitehorn  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23b40ce02aSNathan Whitehorn  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24b40ce02aSNathan Whitehorn  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25b40ce02aSNathan Whitehorn  */
26b40ce02aSNathan Whitehorn 
27b40ce02aSNathan Whitehorn #include <sys/cdefs.h>
28b40ce02aSNathan Whitehorn __FBSDID("$FreeBSD$");
29b40ce02aSNathan Whitehorn 
30b40ce02aSNathan Whitehorn #include <sys/param.h>
31b40ce02aSNathan Whitehorn #include <sys/systm.h>
32b40ce02aSNathan Whitehorn #include <sys/kernel.h>
33b40ce02aSNathan Whitehorn #include <sys/bus.h>
34b40ce02aSNathan Whitehorn #include <sys/pcpu.h>
35b40ce02aSNathan Whitehorn #include <sys/proc.h>
36b40ce02aSNathan Whitehorn #include <sys/smp.h>
37b40ce02aSNathan Whitehorn 
38b40ce02aSNathan Whitehorn #include <machine/bootinfo.h>
39b40ce02aSNathan Whitehorn #include <machine/bus.h>
40b40ce02aSNathan Whitehorn #include <machine/cpu.h>
41b40ce02aSNathan Whitehorn #include <machine/hid.h>
42b40ce02aSNathan Whitehorn #include <machine/platform.h>
43b40ce02aSNathan Whitehorn #include <machine/platformvar.h>
44b40ce02aSNathan Whitehorn #include <machine/smp.h>
45b40ce02aSNathan Whitehorn #include <machine/spr.h>
46b40ce02aSNathan Whitehorn #include <machine/vmparam.h>
47b40ce02aSNathan Whitehorn 
48b40ce02aSNathan Whitehorn #include <powerpc/mpc85xx/mpc85xx.h>
49b40ce02aSNathan Whitehorn #include <powerpc/mpc85xx/ocpbus.h>
50b40ce02aSNathan Whitehorn 
51b40ce02aSNathan Whitehorn #include "platform_if.h"
52b40ce02aSNathan Whitehorn 
5328bb01e5SRafal Jaworowski #ifdef SMP
5428bb01e5SRafal Jaworowski extern void *ap_pcpu;
5528bb01e5SRafal Jaworowski extern uint8_t __boot_page[];		/* Boot page body */
5628bb01e5SRafal Jaworowski extern uint32_t kernload;		/* Kernel physical load address */
5728bb01e5SRafal Jaworowski #endif
5828bb01e5SRafal Jaworowski 
592b7b2d79SRafal Jaworowski static int cpu, maxcpu;
60b40ce02aSNathan Whitehorn 
61b40ce02aSNathan Whitehorn static int bare_probe(platform_t);
62b40ce02aSNathan Whitehorn static void bare_mem_regions(platform_t, struct mem_region **phys, int *physsz,
63b40ce02aSNathan Whitehorn     struct mem_region **avail, int *availsz);
64b40ce02aSNathan Whitehorn static u_long bare_timebase_freq(platform_t, struct cpuref *cpuref);
65b40ce02aSNathan Whitehorn static int bare_smp_first_cpu(platform_t, struct cpuref *cpuref);
66b40ce02aSNathan Whitehorn static int bare_smp_next_cpu(platform_t, struct cpuref *cpuref);
67b40ce02aSNathan Whitehorn static int bare_smp_get_bsp(platform_t, struct cpuref *cpuref);
68b40ce02aSNathan Whitehorn static int bare_smp_start_cpu(platform_t, struct pcpu *cpu);
69b40ce02aSNathan Whitehorn 
70b40ce02aSNathan Whitehorn static platform_method_t bare_methods[] = {
71b40ce02aSNathan Whitehorn 	PLATFORMMETHOD(platform_probe, 		bare_probe),
72b40ce02aSNathan Whitehorn 	PLATFORMMETHOD(platform_mem_regions,	bare_mem_regions),
73b40ce02aSNathan Whitehorn 	PLATFORMMETHOD(platform_timebase_freq,	bare_timebase_freq),
74b40ce02aSNathan Whitehorn 
75b40ce02aSNathan Whitehorn 	PLATFORMMETHOD(platform_smp_first_cpu,	bare_smp_first_cpu),
76b40ce02aSNathan Whitehorn 	PLATFORMMETHOD(platform_smp_next_cpu,	bare_smp_next_cpu),
77b40ce02aSNathan Whitehorn 	PLATFORMMETHOD(platform_smp_get_bsp,	bare_smp_get_bsp),
78b40ce02aSNathan Whitehorn 	PLATFORMMETHOD(platform_smp_start_cpu,	bare_smp_start_cpu),
79b40ce02aSNathan Whitehorn 
80b40ce02aSNathan Whitehorn 	{ 0, 0 }
81b40ce02aSNathan Whitehorn };
82b40ce02aSNathan Whitehorn 
83b40ce02aSNathan Whitehorn static platform_def_t bare_platform = {
84b40ce02aSNathan Whitehorn 	"bare metal",
85b40ce02aSNathan Whitehorn 	bare_methods,
86b40ce02aSNathan Whitehorn 	0
87b40ce02aSNathan Whitehorn };
88b40ce02aSNathan Whitehorn 
89b40ce02aSNathan Whitehorn PLATFORM_DEF(bare_platform);
90b40ce02aSNathan Whitehorn 
91b40ce02aSNathan Whitehorn static int
92b40ce02aSNathan Whitehorn bare_probe(platform_t plat)
93b40ce02aSNathan Whitehorn {
942b7b2d79SRafal Jaworowski 	uint32_t ver;
952b7b2d79SRafal Jaworowski 
962b7b2d79SRafal Jaworowski 	ver = SVR_VER(mfspr(SPR_SVR));
972b7b2d79SRafal Jaworowski 	if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
982b7b2d79SRafal Jaworowski 		maxcpu = 2;
992b7b2d79SRafal Jaworowski 	else
1002b7b2d79SRafal Jaworowski 		maxcpu = 1;
101b40ce02aSNathan Whitehorn 
102b40ce02aSNathan Whitehorn 	return (BUS_PROBE_GENERIC);
103b40ce02aSNathan Whitehorn }
104b40ce02aSNathan Whitehorn 
105b40ce02aSNathan Whitehorn #define MEM_REGIONS	8
106b40ce02aSNathan Whitehorn static struct mem_region avail_regions[MEM_REGIONS];
107b40ce02aSNathan Whitehorn 
108b40ce02aSNathan Whitehorn void
109b40ce02aSNathan Whitehorn bare_mem_regions(platform_t plat, struct mem_region **phys, int *physsz,
110b40ce02aSNathan Whitehorn     struct mem_region **avail, int *availsz)
111b40ce02aSNathan Whitehorn {
112b40ce02aSNathan Whitehorn 	struct bi_mem_region *mr;
113b40ce02aSNathan Whitehorn 	int i;
114b40ce02aSNathan Whitehorn 
115b40ce02aSNathan Whitehorn 	/* Initialize memory regions table */
116b40ce02aSNathan Whitehorn 	mr = bootinfo_mr();
117b40ce02aSNathan Whitehorn 	for (i = 0; i < bootinfo->bi_mem_reg_no; i++, mr++) {
118b40ce02aSNathan Whitehorn 		if (i == MEM_REGIONS)
119b40ce02aSNathan Whitehorn 			break;
120b40ce02aSNathan Whitehorn 		if (mr->mem_base < 1048576) {
121b40ce02aSNathan Whitehorn 			avail_regions[i].mr_start = 1048576;
122b40ce02aSNathan Whitehorn 			avail_regions[i].mr_size = mr->mem_size -
123b40ce02aSNathan Whitehorn 			    (1048576 - mr->mem_base);
124b40ce02aSNathan Whitehorn 		} else {
125b40ce02aSNathan Whitehorn 			avail_regions[i].mr_start = mr->mem_base;
126b40ce02aSNathan Whitehorn 			avail_regions[i].mr_size = mr->mem_size;
127b40ce02aSNathan Whitehorn 		}
128b40ce02aSNathan Whitehorn 	}
129b40ce02aSNathan Whitehorn 	*availsz = i;
130b40ce02aSNathan Whitehorn 	*avail = avail_regions;
131b40ce02aSNathan Whitehorn 
132b40ce02aSNathan Whitehorn 	/* On the bare metal platform phys == avail memory */
133b40ce02aSNathan Whitehorn 	*physsz = *availsz;
134b40ce02aSNathan Whitehorn 	*phys = *avail;
135b40ce02aSNathan Whitehorn }
136b40ce02aSNathan Whitehorn 
137b40ce02aSNathan Whitehorn static u_long
138b40ce02aSNathan Whitehorn bare_timebase_freq(platform_t plat, struct cpuref *cpuref)
139b40ce02aSNathan Whitehorn {
140b40ce02aSNathan Whitehorn 	u_long ticks = -1;
141b40ce02aSNathan Whitehorn 
142b40ce02aSNathan Whitehorn 	/*
143b40ce02aSNathan Whitehorn 	 * Time Base and Decrementer are updated every 8 CCB bus clocks.
144b40ce02aSNathan Whitehorn 	 * HID0[SEL_TBCLK] = 0
145b40ce02aSNathan Whitehorn 	 */
146b40ce02aSNathan Whitehorn 	ticks = bootinfo->bi_bus_clk / 8;
147b40ce02aSNathan Whitehorn 	if (ticks <= 0)
148b40ce02aSNathan Whitehorn 		panic("Unable to determine timebase frequency!");
149b40ce02aSNathan Whitehorn 
150b40ce02aSNathan Whitehorn 	return (ticks);
151b40ce02aSNathan Whitehorn }
152b40ce02aSNathan Whitehorn 
153b40ce02aSNathan Whitehorn static int
154b40ce02aSNathan Whitehorn bare_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
155b40ce02aSNathan Whitehorn {
156b40ce02aSNathan Whitehorn 
157b40ce02aSNathan Whitehorn 	cpu = 0;
158b40ce02aSNathan Whitehorn 	cpuref->cr_cpuid = cpu;
159b40ce02aSNathan Whitehorn 	cpuref->cr_hwref = cpuref->cr_cpuid;
160b40ce02aSNathan Whitehorn 	if (bootverbose)
161b40ce02aSNathan Whitehorn 		printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid);
162b40ce02aSNathan Whitehorn 	cpu++;
163b40ce02aSNathan Whitehorn 
164b40ce02aSNathan Whitehorn 	return (0);
165b40ce02aSNathan Whitehorn }
166b40ce02aSNathan Whitehorn 
167b40ce02aSNathan Whitehorn static int
168b40ce02aSNathan Whitehorn bare_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
169b40ce02aSNathan Whitehorn {
170b40ce02aSNathan Whitehorn 
1712b7b2d79SRafal Jaworowski 	if (cpu >= maxcpu)
172b40ce02aSNathan Whitehorn 		return (ENOENT);
173b40ce02aSNathan Whitehorn 
174b40ce02aSNathan Whitehorn 	cpuref->cr_cpuid = cpu++;
175b40ce02aSNathan Whitehorn 	cpuref->cr_hwref = cpuref->cr_cpuid;
176b40ce02aSNathan Whitehorn 	if (bootverbose)
177b40ce02aSNathan Whitehorn 		printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid);
178b40ce02aSNathan Whitehorn 
179b40ce02aSNathan Whitehorn 	return (0);
180b40ce02aSNathan Whitehorn }
181b40ce02aSNathan Whitehorn 
182b40ce02aSNathan Whitehorn static int
183b40ce02aSNathan Whitehorn bare_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
184b40ce02aSNathan Whitehorn {
185b40ce02aSNathan Whitehorn 
186b40ce02aSNathan Whitehorn 	cpuref->cr_cpuid = mfspr(SPR_PIR);
187b40ce02aSNathan Whitehorn 	cpuref->cr_hwref = cpuref->cr_cpuid;
188b40ce02aSNathan Whitehorn 
189b40ce02aSNathan Whitehorn 	return (0);
190b40ce02aSNathan Whitehorn }
191b40ce02aSNathan Whitehorn 
192b40ce02aSNathan Whitehorn static int
193b40ce02aSNathan Whitehorn bare_smp_start_cpu(platform_t plat, struct pcpu *pc)
194b40ce02aSNathan Whitehorn {
19528bb01e5SRafal Jaworowski #ifdef SMP
19628bb01e5SRafal Jaworowski 	uint32_t bptr, eebpcr;
19728bb01e5SRafal Jaworowski 	int timeout;
198b40ce02aSNathan Whitehorn 
19928bb01e5SRafal Jaworowski 	eebpcr = ccsr_read4(OCP85XX_EEBPCR);
20028bb01e5SRafal Jaworowski 	if ((eebpcr & (pc->pc_cpumask << 24)) != 0) {
20128bb01e5SRafal Jaworowski 		printf("%s: CPU=%d already out of hold-off state!\n",
20228bb01e5SRafal Jaworowski 		    __func__, pc->pc_cpuid);
20328bb01e5SRafal Jaworowski 		return (ENXIO);
20428bb01e5SRafal Jaworowski 	}
20528bb01e5SRafal Jaworowski 
20628bb01e5SRafal Jaworowski 	ap_pcpu = pc;
20728bb01e5SRafal Jaworowski 	__asm __volatile("msync; isync");
20828bb01e5SRafal Jaworowski 
20928bb01e5SRafal Jaworowski 	/*
21028bb01e5SRafal Jaworowski 	 * Set BPTR to the physical address of the boot page
21128bb01e5SRafal Jaworowski 	 */
21228bb01e5SRafal Jaworowski 	bptr = ((uint32_t)__boot_page - KERNBASE) + kernload;
21328bb01e5SRafal Jaworowski 	ccsr_write4(OCP85XX_BPTR, (bptr >> 12) | 0x80000000);
21428bb01e5SRafal Jaworowski 
21528bb01e5SRafal Jaworowski 	/*
21628bb01e5SRafal Jaworowski 	 * Release AP from hold-off state
21728bb01e5SRafal Jaworowski 	 */
21828bb01e5SRafal Jaworowski 	eebpcr |= (pc->pc_cpumask << 24);
21928bb01e5SRafal Jaworowski 	ccsr_write4(OCP85XX_EEBPCR, eebpcr);
22028bb01e5SRafal Jaworowski 	__asm __volatile("isync; msync");
22128bb01e5SRafal Jaworowski 
22228bb01e5SRafal Jaworowski 	timeout = 500;
22328bb01e5SRafal Jaworowski 	while (!pc->pc_awake && timeout--)
22428bb01e5SRafal Jaworowski 		DELAY(1000);	/* wait 1ms */
22528bb01e5SRafal Jaworowski 
22628bb01e5SRafal Jaworowski 	return ((pc->pc_awake) ? 0 : EBUSY);
22728bb01e5SRafal Jaworowski #else
228b40ce02aSNathan Whitehorn 	/* No SMP support */
229b40ce02aSNathan Whitehorn 	return (ENXIO);
23028bb01e5SRafal Jaworowski #endif
231b40ce02aSNathan Whitehorn }
232