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