xref: /freebsd/sys/powerpc/mpc85xx/platform_mpc85xx.c (revision a0b9e2e854027e6ff61fb075a1309dbc71c42b54)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2008-2012 Semihalf.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "opt_platform.h"
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/module.h>
37 #include <sys/bus.h>
38 #include <sys/pcpu.h>
39 #include <sys/proc.h>
40 #include <sys/smp.h>
41 
42 #include <machine/bus.h>
43 #include <machine/cpu.h>
44 #include <machine/hid.h>
45 #include <machine/_inttypes.h>
46 #include <machine/machdep.h>
47 #include <machine/md_var.h>
48 #include <machine/platform.h>
49 #include <machine/platformvar.h>
50 #include <machine/smp.h>
51 #include <machine/spr.h>
52 #include <machine/vmparam.h>
53 
54 #include <dev/fdt/fdt_common.h>
55 #include <dev/ofw/ofw_bus.h>
56 #include <dev/ofw/ofw_bus_subr.h>
57 #include <dev/ofw/openfirm.h>
58 
59 #include <vm/vm.h>
60 #include <vm/pmap.h>
61 #include <vm/vm_extern.h>
62 
63 #include <powerpc/mpc85xx/mpc85xx.h>
64 
65 #include "platform_if.h"
66 
67 #ifdef SMP
68 extern void *ap_pcpu;
69 extern vm_paddr_t kernload;		/* Kernel physical load address */
70 extern uint8_t __boot_page[];		/* Boot page body */
71 extern vm_paddr_t bp_kernload;		/* Boot page copy of kernload */
72 extern vm_offset_t bp_virtaddr;		/* Virtual address of boot page */
73 extern vm_offset_t __startkernel;
74 
75 struct cpu_release {
76 	uint32_t entry_h;
77 	uint32_t entry_l;
78 	uint32_t r3_h;
79 	uint32_t r3_l;
80 	uint32_t reserved;
81 	uint32_t pir;
82 };
83 #endif
84 
85 extern uint32_t *bootinfo;
86 vm_paddr_t ccsrbar_pa;
87 vm_offset_t ccsrbar_va;
88 vm_size_t ccsrbar_size;
89 
90 static int cpu, maxcpu;
91 
92 static device_t rcpm_dev;
93 static void dummy_freeze(device_t, bool);
94 
95 static void (*freeze_timebase)(device_t, bool) = dummy_freeze;
96 
97 static int mpc85xx_probe(platform_t);
98 static void mpc85xx_mem_regions(platform_t, struct mem_region *phys,
99     int *physsz, struct mem_region *avail, int *availsz);
100 static u_long mpc85xx_timebase_freq(platform_t, struct cpuref *cpuref);
101 static int mpc85xx_smp_first_cpu(platform_t, struct cpuref *cpuref);
102 static int mpc85xx_smp_next_cpu(platform_t, struct cpuref *cpuref);
103 static int mpc85xx_smp_get_bsp(platform_t, struct cpuref *cpuref);
104 static int mpc85xx_smp_start_cpu(platform_t, struct pcpu *cpu);
105 static void mpc85xx_smp_timebase_sync(platform_t, u_long tb, int ap);
106 
107 static void mpc85xx_reset(platform_t);
108 
109 static platform_method_t mpc85xx_methods[] = {
110 	PLATFORMMETHOD(platform_probe,		mpc85xx_probe),
111 	PLATFORMMETHOD(platform_attach,		mpc85xx_attach),
112 	PLATFORMMETHOD(platform_mem_regions,	mpc85xx_mem_regions),
113 	PLATFORMMETHOD(platform_timebase_freq,	mpc85xx_timebase_freq),
114 
115 	PLATFORMMETHOD(platform_smp_first_cpu,	mpc85xx_smp_first_cpu),
116 	PLATFORMMETHOD(platform_smp_next_cpu,	mpc85xx_smp_next_cpu),
117 	PLATFORMMETHOD(platform_smp_get_bsp,	mpc85xx_smp_get_bsp),
118 	PLATFORMMETHOD(platform_smp_start_cpu,	mpc85xx_smp_start_cpu),
119 	PLATFORMMETHOD(platform_smp_timebase_sync, mpc85xx_smp_timebase_sync),
120 
121 	PLATFORMMETHOD(platform_reset,		mpc85xx_reset),
122 
123 	PLATFORMMETHOD_END
124 };
125 
126 DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0);
127 
128 PLATFORM_DEF(mpc85xx_platform);
129 
130 static int
131 mpc85xx_probe(platform_t plat)
132 {
133 	u_int pvr = (mfpvr() >> 16) & 0xFFFF;
134 
135 	switch (pvr) {
136 		case FSL_E500v1:
137 		case FSL_E500v2:
138 		case FSL_E500mc:
139 		case FSL_E5500:
140 		case FSL_E6500:
141 			return (BUS_PROBE_DEFAULT);
142 	}
143 	return (ENXIO);
144 }
145 
146 int
147 mpc85xx_attach(platform_t plat)
148 {
149 	phandle_t cpus, child, ccsr;
150 	const char *soc_name_guesses[] = {"/soc", "soc", NULL};
151 	const char **name;
152 	pcell_t ranges[6], acells, pacells, scells;
153 	uint64_t ccsrbar, ccsrsize;
154 	int i;
155 
156 	if ((cpus = OF_finddevice("/cpus")) != -1) {
157 		for (maxcpu = 0, child = OF_child(cpus); child != 0;
158 		    child = OF_peer(child), maxcpu++)
159 			;
160 	} else
161 		maxcpu = 1;
162 
163 	/*
164 	 * Locate CCSR region. Irritatingly, there is no way to find it
165 	 * unless you already know where it is. Try to infer its location
166 	 * from the device tree.
167 	 */
168 
169 	ccsr = -1;
170 	for (name = soc_name_guesses; *name != NULL && ccsr == -1; name++)
171 		ccsr = OF_finddevice(*name);
172 	if (ccsr == -1) {
173 		char type[64];
174 
175 	 	/* That didn't work. Search for devices of type "soc" */
176 		child = OF_child(OF_peer(0));
177 		for (OF_child(child); child != 0; child = OF_peer(child)) {
178 			if (OF_getprop(child, "device_type", type, sizeof(type))
179 			    <= 0)
180 				continue;
181 
182 			if (strcmp(type, "soc") == 0) {
183 				ccsr = child;
184 				break;
185 			}
186 		}
187 	}
188 
189 	if (ccsr == -1)
190 		panic("Could not locate CCSR window!");
191 
192 	OF_getprop(ccsr, "#size-cells", &scells, sizeof(scells));
193 	OF_getprop(ccsr, "#address-cells", &acells, sizeof(acells));
194 	OF_searchprop(OF_parent(ccsr), "#address-cells", &pacells,
195 	    sizeof(pacells));
196 	OF_getprop(ccsr, "ranges", ranges, sizeof(ranges));
197 	ccsrbar = ccsrsize = 0;
198 	for (i = acells; i < acells + pacells; i++) {
199 		ccsrbar <<= 32;
200 		ccsrbar |= ranges[i];
201 	}
202 	for (i = acells + pacells; i < acells + pacells + scells; i++) {
203 		ccsrsize <<= 32;
204 		ccsrsize |= ranges[i];
205 	}
206 	ccsrbar_va = pmap_early_io_map(ccsrbar, ccsrsize);
207 	ccsrbar_pa = ccsrbar;
208 	ccsrbar_size = ccsrsize;
209 
210 	mpc85xx_enable_l3_cache();
211 
212 	return (0);
213 }
214 
215 void
216 mpc85xx_mem_regions(platform_t plat, struct mem_region *phys, int *physsz,
217     struct mem_region *avail, int *availsz)
218 {
219 
220 	ofw_mem_regions(phys, physsz, avail, availsz);
221 }
222 
223 static u_long
224 mpc85xx_timebase_freq(platform_t plat, struct cpuref *cpuref)
225 {
226 	u_long ticks;
227 	phandle_t cpus, child;
228 	pcell_t freq;
229 
230 	if (bootinfo != NULL) {
231 		if (bootinfo[0] == 1) {
232 			/* Backward compatibility. See 8-STABLE. */
233 			ticks = bootinfo[3] >> 3;
234 		} else {
235 			/* Compatibility with Juniper's loader. */
236 			ticks = bootinfo[5] >> 3;
237 		}
238 	} else
239 		ticks = 0;
240 
241 	if ((cpus = OF_finddevice("/cpus")) == -1)
242 		goto out;
243 
244 	if ((child = OF_child(cpus)) == 0)
245 		goto out;
246 
247 	switch (OF_getproplen(child, "timebase-frequency")) {
248 	case 4:
249 	{
250 		uint32_t tbase;
251 		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
252 		ticks = tbase;
253 		return (ticks);
254 	}
255 	case 8:
256 	{
257 		uint64_t tbase;
258 		OF_getprop(child, "timebase-frequency", &tbase, sizeof(tbase));
259 		ticks = tbase;
260 		return (ticks);
261 	}
262 	default:
263 		break;
264 	}
265 
266 	freq = 0;
267 	if (OF_getprop(child, "bus-frequency", (void *)&freq,
268 	    sizeof(freq)) <= 0)
269 		goto out;
270 
271 	if (freq == 0)
272 		goto out;
273 
274 	/*
275 	 * Time Base and Decrementer are updated every 8 CCB bus clocks.
276 	 * HID0[SEL_TBCLK] = 0
277 	 */
278 	if (mpc85xx_is_qoriq())
279 		ticks = freq / 32;
280 	else
281 		ticks = freq / 8;
282 
283 out:
284 	if (ticks <= 0)
285 		panic("Unable to determine timebase frequency!");
286 
287 	return (ticks);
288 }
289 
290 static int
291 mpc85xx_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
292 {
293 
294 	cpu = 0;
295 	cpuref->cr_cpuid = cpu;
296 	cpuref->cr_hwref = cpuref->cr_cpuid;
297 	if (bootverbose)
298 		printf("powerpc_smp_first_cpu: cpuid %d\n", cpuref->cr_cpuid);
299 	cpu++;
300 
301 	return (0);
302 }
303 
304 static int
305 mpc85xx_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
306 {
307 
308 	if (cpu >= maxcpu)
309 		return (ENOENT);
310 
311 	cpuref->cr_cpuid = cpu++;
312 	cpuref->cr_hwref = cpuref->cr_cpuid;
313 	if (bootverbose)
314 		printf("powerpc_smp_next_cpu: cpuid %d\n", cpuref->cr_cpuid);
315 
316 	return (0);
317 }
318 
319 static int
320 mpc85xx_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
321 {
322 
323 	cpuref->cr_cpuid = mfspr(SPR_PIR);
324 	cpuref->cr_hwref = cpuref->cr_cpuid;
325 
326 	return (0);
327 }
328 
329 #ifdef SMP
330 static int
331 mpc85xx_smp_start_cpu_epapr(platform_t plat, struct pcpu *pc)
332 {
333 	vm_paddr_t rel_pa, bptr;
334 	volatile struct cpu_release *rel;
335 	vm_offset_t rel_va, rel_page;
336 	phandle_t node;
337 	int i;
338 
339 	/* If we're calling this, the node already exists. */
340 	node = OF_finddevice("/cpus");
341 	for (i = 0, node = OF_child(node); i < pc->pc_cpuid;
342 	    i++, node = OF_peer(node))
343 		;
344 	if (OF_getencprop(node, "cpu-release-addr", (pcell_t *)&rel_pa,
345 	    sizeof(rel_pa)) == -1) {
346 		return (ENOENT);
347 	}
348 
349 	rel_page = kva_alloc(PAGE_SIZE);
350 	if (rel_page == 0)
351 		return (ENOMEM);
352 
353 	critical_enter();
354 	rel_va = rel_page + (rel_pa & PAGE_MASK);
355 	pmap_kenter(rel_page, rel_pa & ~PAGE_MASK);
356 	rel = (struct cpu_release *)rel_va;
357 	bptr = pmap_kextract((uintptr_t)__boot_page);
358 
359 	cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel));
360 	rel->pir = pc->pc_cpuid; __asm __volatile("sync" ::: "memory");
361 	rel->entry_h = (bptr >> 32); __asm __volatile("sync" ::: "memory");
362 	cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel));
363 	rel->entry_l = bptr & 0xffffffff; __asm __volatile("sync" ::: "memory");
364 	cpu_flush_dcache(__DEVOLATILE(struct cpu_release *,rel), sizeof(*rel));
365 	if (bootverbose)
366 		printf("Waking up CPU %d via CPU release page %p\n",
367 		    pc->pc_cpuid, rel);
368 	critical_exit();
369 	pmap_kremove(rel_page);
370 	kva_free(rel_page, PAGE_SIZE);
371 
372 	return (0);
373 }
374 #endif
375 
376 static int
377 mpc85xx_smp_start_cpu(platform_t plat, struct pcpu *pc)
378 {
379 #ifdef SMP
380 	vm_paddr_t bptr;
381 	uint32_t reg;
382 	int timeout;
383 	uintptr_t brr;
384 	int cpuid;
385 	int epapr_boot = 0;
386 	uint32_t tgt;
387 
388 	if (mpc85xx_is_qoriq()) {
389 		reg = ccsr_read4(OCP85XX_COREDISR);
390 		cpuid = pc->pc_cpuid;
391 
392 		if ((reg & (1 << cpuid)) != 0) {
393 		    printf("%s: CPU %d is disabled!\n", __func__, pc->pc_cpuid);
394 		    return (-1);
395 		}
396 
397 		brr = OCP85XX_BRR;
398 	} else {
399 		brr = OCP85XX_EEBPCR;
400 		cpuid = pc->pc_cpuid + 24;
401 	}
402 	bp_kernload = kernload;
403 	bp_virtaddr = (vm_offset_t)&__boot_page;
404 	/*
405 	 * bp_kernload and bp_virtaddr are in the boot page.  Sync the cache
406 	 * because ePAPR booting has the other core(s) already running.
407 	 */
408 	cpu_flush_dcache(&bp_kernload, sizeof(bp_kernload));
409 	cpu_flush_dcache(&bp_virtaddr, sizeof(bp_virtaddr));
410 
411 	ap_pcpu = pc;
412 	__asm __volatile("msync; isync");
413 
414 	/* First try the ePAPR way. */
415 	if (mpc85xx_smp_start_cpu_epapr(plat, pc) == 0) {
416 		epapr_boot = 1;
417 		goto spin_wait;
418 	}
419 
420 	reg = ccsr_read4(brr);
421 	if ((reg & (1 << cpuid)) != 0) {
422 		printf("SMP: CPU %d already out of hold-off state!\n",
423 		    pc->pc_cpuid);
424 		return (ENXIO);
425 	}
426 
427 	/* Flush caches to have our changes hit DRAM. */
428 	cpu_flush_dcache(__boot_page, 4096);
429 
430 	bptr = pmap_kextract((uintptr_t)__boot_page);
431 	KASSERT((bptr & 0xfff) == 0,
432 	    ("%s: boot page is not aligned (%#jx)", __func__, (uintmax_t)bptr));
433 	if (mpc85xx_is_qoriq()) {
434 		/*
435 		 * Read DDR controller configuration to select proper BPTR target ID.
436 		 *
437 		 * On P5020 bit 29 of DDR1_CS0_CONFIG enables DDR controllers
438 		 * interleaving. If this bit is set, we have to use
439 		 * OCP85XX_TGTIF_RAM_INTL as BPTR target ID. On other QorIQ DPAA SoCs,
440 		 * this bit is reserved and always 0.
441 		 */
442 
443 		reg = ccsr_read4(OCP85XX_DDR1_CS0_CONFIG);
444 		if (reg & (1 << 29))
445 			tgt = OCP85XX_TGTIF_RAM_INTL;
446 		else
447 			tgt = OCP85XX_TGTIF_RAM1;
448 
449 		/*
450 		 * Set BSTR to the physical address of the boot page
451 		 */
452 		ccsr_write4(OCP85XX_BSTRH, bptr >> 32);
453 		ccsr_write4(OCP85XX_BSTRL, bptr);
454 		ccsr_write4(OCP85XX_BSTAR, OCP85XX_ENA_MASK |
455 		    (tgt << OCP85XX_TRGT_SHIFT_QORIQ) | (ffsl(PAGE_SIZE) - 2));
456 
457 		/* Read back OCP85XX_BSTAR to synchronize write */
458 		ccsr_read4(OCP85XX_BSTAR);
459 
460 		/*
461 		 * Enable and configure time base on new CPU.
462 		 */
463 
464 		/* Set TB clock source to platform clock / 32 */
465 		reg = ccsr_read4(CCSR_CTBCKSELR);
466 		ccsr_write4(CCSR_CTBCKSELR, reg & ~(1 << pc->pc_cpuid));
467 
468 		/* Enable TB */
469 		reg = ccsr_read4(CCSR_CTBENR);
470 		ccsr_write4(CCSR_CTBENR, reg | (1 << pc->pc_cpuid));
471 	} else {
472 		/*
473 		 * Set BPTR to the physical address of the boot page
474 		 */
475 		bptr = (bptr >> 12) | 0x80000000u;
476 		ccsr_write4(OCP85XX_BPTR, bptr);
477 		__asm __volatile("isync; msync");
478 	}
479 
480 	/*
481 	 * Release AP from hold-off state
482 	 */
483 	reg = ccsr_read4(brr);
484 	ccsr_write4(brr, reg | (1 << cpuid));
485 	__asm __volatile("isync; msync");
486 
487 spin_wait:
488 	timeout = 500;
489 	while (!pc->pc_awake && timeout--)
490 		DELAY(1000);	/* wait 1ms */
491 
492 	/*
493 	 * Disable boot page translation so that the 4K page at the default
494 	 * address (= 0xfffff000) isn't permanently remapped and thus not
495 	 * usable otherwise.
496 	 */
497 	if (!epapr_boot) {
498 		if (mpc85xx_is_qoriq())
499 			ccsr_write4(OCP85XX_BSTAR, 0);
500 		else
501 			ccsr_write4(OCP85XX_BPTR, 0);
502 		__asm __volatile("isync; msync");
503 	}
504 
505 	if (!pc->pc_awake)
506 		panic("SMP: CPU %d didn't wake up.\n", pc->pc_cpuid);
507 	return ((pc->pc_awake) ? 0 : EBUSY);
508 #else
509 	/* No SMP support */
510 	return (ENXIO);
511 #endif
512 }
513 
514 static void
515 mpc85xx_reset(platform_t plat)
516 {
517 
518 	/*
519 	 * Try the dedicated reset register first.
520 	 * If the SoC doesn't have one, we'll fall
521 	 * back to using the debug control register.
522 	 */
523 	ccsr_write4(OCP85XX_RSTCR, 2);
524 
525 	mtmsr(mfmsr() & ~PSL_DE);
526 
527 	/* Enable debug interrupts and issue reset. */
528 	mtspr(SPR_DBCR0, DBCR0_IDM | DBCR0_RST_SYSTEM);
529 	__asm __volatile("isync");
530 
531 	/* Enable Debug Interrupts in MSR. */
532 	mtmsr(mfmsr() | PSL_DE);
533 
534 	printf("Reset failed...\n");
535 	while (1)
536 		;
537 }
538 
539 static void
540 mpc85xx_smp_timebase_sync(platform_t plat, u_long tb, int ap)
541 {
542 	static volatile bool tb_ready;
543 	static volatile int cpu_done;
544 
545 	if (ap) {
546 		/* APs.  Hold off until we get a stable timebase. */
547 		while (!tb_ready)
548 			atomic_thread_fence_seq_cst();
549 		mttb(tb);
550 		atomic_add_int(&cpu_done, 1);
551 		while (cpu_done < mp_ncpus)
552 			atomic_thread_fence_seq_cst();
553 	} else {
554 		/* BSP */
555 		freeze_timebase(rcpm_dev, true);
556 		tb_ready = true;
557 		mttb(tb);
558 		atomic_add_int(&cpu_done, 1);
559 		while (cpu_done < mp_ncpus)
560 			atomic_thread_fence_seq_cst();
561 		freeze_timebase(rcpm_dev, false);
562 	}
563 }
564 
565 /* Fallback freeze.  In case no real handler is found in the device tree. */
566 static void
567 dummy_freeze(device_t dev, bool freeze)
568 {
569 	/* Nothing to do here, move along. */
570 }
571 
572 /* QorIQ Run control/power management timebase management. */
573 
574 #define	RCPM_CTBENR	0x00000084
575 struct mpc85xx_rcpm_softc {
576 	struct resource *sc_mem;
577 };
578 
579 static void
580 mpc85xx_rcpm_freeze_timebase(device_t dev, bool freeze)
581 {
582 	struct mpc85xx_rcpm_softc *sc;
583 
584 	sc = device_get_softc(dev);
585 
586 	if (freeze)
587 		bus_write_4(sc->sc_mem, RCPM_CTBENR, 0);
588 	else
589 		bus_write_4(sc->sc_mem, RCPM_CTBENR, (1 << maxcpu) - 1);
590 }
591 
592 static int
593 mpc85xx_rcpm_probe(device_t dev)
594 {
595 	if (!ofw_bus_is_compatible(dev, "fsl,qoriq-rcpm-1.0"))
596 		return (ENXIO);
597 
598 	device_set_desc(dev, "QorIQ Run control and power management");
599 	return (BUS_PROBE_GENERIC);
600 }
601 
602 static int
603 mpc85xx_rcpm_attach(device_t dev)
604 {
605 	struct mpc85xx_rcpm_softc *sc;
606 	int rid;
607 
608 	sc = device_get_softc(dev);
609 	freeze_timebase = mpc85xx_rcpm_freeze_timebase;
610 	rcpm_dev = dev;
611 
612 	rid = 0;
613 	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
614 	    RF_ACTIVE | RF_SHAREABLE);
615 
616 	return (0);
617 }
618 
619 static device_method_t mpc85xx_rcpm_methods[] = {
620 	DEVMETHOD(device_probe,		mpc85xx_rcpm_probe),
621 	DEVMETHOD(device_attach,	mpc85xx_rcpm_attach),
622 	DEVMETHOD_END
623 };
624 
625 static devclass_t mpc85xx_rcpm_devclass;
626 
627 static driver_t mpc85xx_rcpm_driver = {
628 	"rcpm",
629 	mpc85xx_rcpm_methods,
630 	sizeof(struct mpc85xx_rcpm_softc)
631 };
632 
633 EARLY_DRIVER_MODULE(mpc85xx_rcpm, simplebus, mpc85xx_rcpm_driver,
634 	mpc85xx_rcpm_devclass, 0, 0, BUS_PASS_BUS);
635 
636 /* "Global utilities" power management/Timebase management. */
637 
638 #define	GUTS_DEVDISR	0x00000070
639 #define	  DEVDISR_TB0	0x00004000
640 #define	  DEVDISR_TB1	0x00001000
641 
642 struct mpc85xx_guts_softc {
643 	struct resource *sc_mem;
644 };
645 
646 static void
647 mpc85xx_guts_freeze_timebase(device_t dev, bool freeze)
648 {
649 	struct mpc85xx_guts_softc *sc;
650 	uint32_t devdisr;
651 
652 	sc = device_get_softc(dev);
653 
654 	devdisr = bus_read_4(sc->sc_mem, GUTS_DEVDISR);
655 	if (freeze)
656 		bus_write_4(sc->sc_mem, GUTS_DEVDISR,
657 		    devdisr | (DEVDISR_TB0 | DEVDISR_TB1));
658 	else
659 		bus_write_4(sc->sc_mem, GUTS_DEVDISR,
660 		    devdisr & ~(DEVDISR_TB0 | DEVDISR_TB1));
661 }
662 
663 static int
664 mpc85xx_guts_probe(device_t dev)
665 {
666 	if (!ofw_bus_is_compatible(dev, "fsl,mpc8572-guts") &&
667 	    !ofw_bus_is_compatible(dev, "fsl,p1020-guts") &&
668 	    !ofw_bus_is_compatible(dev, "fsl,p1021-guts") &&
669 	    !ofw_bus_is_compatible(dev, "fsl,p1022-guts") &&
670 	    !ofw_bus_is_compatible(dev, "fsl,p1023-guts") &&
671 	    !ofw_bus_is_compatible(dev, "fsl,p2020-guts"))
672 		return (ENXIO);
673 
674 	device_set_desc(dev, "MPC85xx Global Utilities");
675 	return (BUS_PROBE_GENERIC);
676 }
677 
678 static int
679 mpc85xx_guts_attach(device_t dev)
680 {
681 	struct mpc85xx_rcpm_softc *sc;
682 	int rid;
683 
684 	sc = device_get_softc(dev);
685 	freeze_timebase = mpc85xx_guts_freeze_timebase;
686 	rcpm_dev = dev;
687 
688 	rid = 0;
689 	sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
690 	    RF_ACTIVE | RF_SHAREABLE);
691 
692 	return (0);
693 }
694 
695 static device_method_t mpc85xx_guts_methods[] = {
696 	DEVMETHOD(device_probe,		mpc85xx_guts_probe),
697 	DEVMETHOD(device_attach,	mpc85xx_guts_attach),
698 	DEVMETHOD_END
699 };
700 
701 static driver_t mpc85xx_guts_driver = {
702 	"guts",
703 	mpc85xx_guts_methods,
704 	sizeof(struct mpc85xx_guts_softc)
705 };
706 
707 static devclass_t mpc85xx_guts_devclass;
708 
709 EARLY_DRIVER_MODULE(mpc85xx_guts, simplebus, mpc85xx_guts_driver,
710 	mpc85xx_guts_devclass, 0, 0, BUS_PASS_BUS);
711