1 /* $NetBSD: cpu_subr.c,v 1.53 2009/03/18 10:22:34 cegger Exp $ */
4 * Copyright (c) 2001 Matt Thomas.
5 * Copyright (c) 2001 Tsubai Masanari.
6 * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by
20 * Internet Research Institute, Inc.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.53 2009/03/18 10:22:34 cegger Exp $");
39 #include "opt_ppcparam.h"
40 #include "opt_multiprocessor.h"
41 #include "opt_altivec.h"
42 #include "sysmon_envsys.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/device.h>
47 #include <sys/types.h>
49 #include <sys/malloc.h>
51 #include <uvm/uvm_extern.h>
53 #include <powerpc/oea/hid.h>
54 #include <powerpc/oea/hid_601.h>
55 #include <powerpc/spr.h>
56 #include <powerpc/oea/cpufeat.h>
58 #include <dev/sysmon/sysmonvar.h>
60 static void cpu_enable_l2cr(register_t
);
61 static void cpu_enable_l3cr(register_t
);
62 static void cpu_config_l2cr(int);
63 static void cpu_config_l3cr(int);
64 static void cpu_probe_speed(struct cpu_info
*);
65 static void cpu_idlespin(void);
66 #if NSYSMON_ENVSYS > 0
67 static void cpu_tau_setup(struct cpu_info
*);
68 static void cpu_tau_refresh(struct sysmon_envsys
*, envsys_data_t
*);
77 const char *fmt_string
;
81 * This should be one per CPU but since we only support it on 750 variants it
82 * doesn't realy matter since none of them supports SMP
86 static const struct fmttab cpu_7450_l2cr_formats
[] = {
87 { L2CR_L2E
, 0, " disabled" },
88 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
, " data-only" },
89 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2IO
, " instruction-only" },
90 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
|L2CR_L2IO
, " locked" },
91 { L2CR_L2E
, ~0, " 256KB L2 cache" },
92 { L2CR_L2PE
, 0, " no parity" },
93 { L2CR_L2PE
, ~0, " parity enabled" },
97 static const struct fmttab cpu_7448_l2cr_formats
[] = {
98 { L2CR_L2E
, 0, " disabled" },
99 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
, " data-only" },
100 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2IO
, " instruction-only" },
101 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
|L2CR_L2IO
, " locked" },
102 { L2CR_L2E
, ~0, " 1MB L2 cache" },
103 { L2CR_L2PE
, 0, " no parity" },
104 { L2CR_L2PE
, ~0, " parity enabled" },
108 static const struct fmttab cpu_7457_l2cr_formats
[] = {
109 { L2CR_L2E
, 0, " disabled" },
110 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
, " data-only" },
111 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2IO
, " instruction-only" },
112 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
|L2CR_L2IO
, " locked" },
113 { L2CR_L2E
, ~0, " 512KB L2 cache" },
114 { L2CR_L2PE
, 0, " no parity" },
115 { L2CR_L2PE
, ~0, " parity enabled" },
119 static const struct fmttab cpu_7450_l3cr_formats
[] = {
120 { L3CR_L3DO
|L3CR_L3IO
, L3CR_L3DO
, " data-only" },
121 { L3CR_L3DO
|L3CR_L3IO
, L3CR_L3IO
, " instruction-only" },
122 { L3CR_L3DO
|L3CR_L3IO
, L3CR_L3DO
|L3CR_L3IO
, " locked" },
123 { L3CR_L3SIZ
, L3SIZ_2M
, " 2MB" },
124 { L3CR_L3SIZ
, L3SIZ_1M
, " 1MB" },
125 { L3CR_L3PE
|L3CR_L3APE
, L3CR_L3PE
|L3CR_L3APE
, " parity" },
126 { L3CR_L3PE
|L3CR_L3APE
, L3CR_L3PE
, " data-parity" },
127 { L3CR_L3PE
|L3CR_L3APE
, L3CR_L3APE
, " address-parity" },
128 { L3CR_L3PE
|L3CR_L3APE
, 0, " no-parity" },
129 { L3CR_L3SIZ
, ~0, " L3 cache" },
130 { L3CR_L3RT
, L3RT_MSUG2_DDR
, " (DDR SRAM)" },
131 { L3CR_L3RT
, L3RT_PIPELINE_LATE
, " (LW SRAM)" },
132 { L3CR_L3RT
, L3RT_PB2_SRAM
, " (PB2 SRAM)" },
133 { L3CR_L3CLK
, ~0, " at" },
134 { L3CR_L3CLK
, L3CLK_20
, " 2:1" },
135 { L3CR_L3CLK
, L3CLK_25
, " 2.5:1" },
136 { L3CR_L3CLK
, L3CLK_30
, " 3:1" },
137 { L3CR_L3CLK
, L3CLK_35
, " 3.5:1" },
138 { L3CR_L3CLK
, L3CLK_40
, " 4:1" },
139 { L3CR_L3CLK
, L3CLK_50
, " 5:1" },
140 { L3CR_L3CLK
, L3CLK_60
, " 6:1" },
141 { L3CR_L3CLK
, ~0, " ratio" },
145 static const struct fmttab cpu_ibm750_l2cr_formats
[] = {
146 { L2CR_L2E
, 0, " disabled" },
147 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
, " data-only" },
148 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2IO
, " instruction-only" },
149 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
|L2CR_L2IO
, " locked" },
151 { L2CR_L2WT
, L2CR_L2WT
, " WT" },
152 { L2CR_L2WT
, 0, " WB" },
153 { L2CR_L2PE
, L2CR_L2PE
, " with ECC" },
154 { 0, ~0, " L2 cache" },
158 static const struct fmttab cpu_l2cr_formats
[] = {
159 { L2CR_L2E
, 0, " disabled" },
160 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
, " data-only" },
161 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2IO
, " instruction-only" },
162 { L2CR_L2DO
|L2CR_L2IO
, L2CR_L2DO
|L2CR_L2IO
, " locked" },
163 { L2CR_L2PE
, L2CR_L2PE
, " parity" },
164 { L2CR_L2PE
, 0, " no-parity" },
165 { L2CR_L2SIZ
, L2SIZ_2M
, " 2MB" },
166 { L2CR_L2SIZ
, L2SIZ_1M
, " 1MB" },
167 { L2CR_L2SIZ
, L2SIZ_512K
, " 512KB" },
168 { L2CR_L2SIZ
, L2SIZ_256K
, " 256KB" },
169 { L2CR_L2WT
, L2CR_L2WT
, " WT" },
170 { L2CR_L2WT
, 0, " WB" },
171 { L2CR_L2E
, ~0, " L2 cache" },
172 { L2CR_L2RAM
, L2RAM_FLOWTHRU_BURST
, " (FB SRAM)" },
173 { L2CR_L2RAM
, L2RAM_PIPELINE_LATE
, " (LW SRAM)" },
174 { L2CR_L2RAM
, L2RAM_PIPELINE_BURST
, " (PB SRAM)" },
175 { L2CR_L2CLK
, ~0, " at" },
176 { L2CR_L2CLK
, L2CLK_10
, " 1:1" },
177 { L2CR_L2CLK
, L2CLK_15
, " 1.5:1" },
178 { L2CR_L2CLK
, L2CLK_20
, " 2:1" },
179 { L2CR_L2CLK
, L2CLK_25
, " 2.5:1" },
180 { L2CR_L2CLK
, L2CLK_30
, " 3:1" },
181 { L2CR_L2CLK
, L2CLK_35
, " 3.5:1" },
182 { L2CR_L2CLK
, L2CLK_40
, " 4:1" },
183 { L2CR_L2CLK
, ~0, " ratio" },
187 static void cpu_fmttab_print(const struct fmttab
*, register_t
);
194 #define REVFMT_MAJMIN 1 /* %u.%u */
195 #define REVFMT_HEX 2 /* 0x%04x */
196 #define REVFMT_DEC 3 /* %u */
197 static const struct cputab models
[] = {
198 { "601", MPC601
, REVFMT_DEC
},
199 { "602", MPC602
, REVFMT_DEC
},
200 { "603", MPC603
, REVFMT_MAJMIN
},
201 { "603e", MPC603e
, REVFMT_MAJMIN
},
202 { "603ev", MPC603ev
, REVFMT_MAJMIN
},
203 { "G2", MPCG2
, REVFMT_MAJMIN
},
204 { "604", MPC604
, REVFMT_MAJMIN
},
205 { "604e", MPC604e
, REVFMT_MAJMIN
},
206 { "604ev", MPC604ev
, REVFMT_MAJMIN
},
207 { "620", MPC620
, REVFMT_HEX
},
208 { "750", MPC750
, REVFMT_MAJMIN
},
209 { "750FX", IBM750FX
, REVFMT_MAJMIN
},
210 { "7400", MPC7400
, REVFMT_MAJMIN
},
211 { "7410", MPC7410
, REVFMT_MAJMIN
},
212 { "7450", MPC7450
, REVFMT_MAJMIN
},
213 { "7455", MPC7455
, REVFMT_MAJMIN
},
214 { "7457", MPC7457
, REVFMT_MAJMIN
},
215 { "7447A", MPC7447A
, REVFMT_MAJMIN
},
216 { "7448", MPC7448
, REVFMT_MAJMIN
},
217 { "8240", MPC8240
, REVFMT_MAJMIN
},
218 { "8245", MPC8245
, REVFMT_MAJMIN
},
219 { "970", IBM970
, REVFMT_MAJMIN
},
220 { "970FX", IBM970FX
, REVFMT_MAJMIN
},
221 { "970MP", IBM970MP
, REVFMT_MAJMIN
},
222 { "POWER3II", IBMPOWER3II
, REVFMT_MAJMIN
},
223 { "", 0, REVFMT_HEX
}
226 #ifdef MULTIPROCESSOR
227 struct cpu_info cpu_info
[CPU_MAXNUM
] = { { .ci_curlwp
= &lwp0
, }, };
228 volatile struct cpu_hatch_data
*cpu_hatch_data
;
229 volatile int cpu_hatch_stack
;
230 extern int ticks_per_intr
;
231 #include <powerpc/oea/bat.h>
232 #include <arch/powerpc/pic/picvar.h>
233 #include <arch/powerpc/pic/ipivar.h>
234 extern struct bat battable
[];
236 struct cpu_info cpu_info
[1] = { { .ci_curlwp
= &lwp0
, }, };
237 #endif /*MULTIPROCESSOR*/
240 int cpu_psluserset
, cpu_pslusermod
;
243 /* This is to be called from locore.S, and nowhere else. */
255 if ((vers
>= IBMRS64II
&& vers
<= IBM970GX
) || vers
== MPC620
||
256 vers
== IBMCELL
|| vers
== IBMPOWER6P5
)
257 oeacpufeat
|= OEACPU_64
| OEACPU_64_BRIDGE
| OEACPU_NOBAT
;
259 else if (vers
== MPC601
)
260 oeacpufeat
|= OEACPU_601
;
262 else if (MPC745X_P(vers
) && vers
!= MPC7450
)
263 oeacpufeat
|= OEACPU_XBSEN
| OEACPU_HIGHBAT
| OEACPU_HIGHSPRG
;
267 cpu_fmttab_print(const struct fmttab
*fmt
, register_t data
)
269 for (; fmt
->fmt_mask
!= 0 || fmt
->fmt_value
!= 0; fmt
++) {
270 if ((~fmt
->fmt_mask
& fmt
->fmt_value
) != 0 ||
271 (data
& fmt
->fmt_mask
) == fmt
->fmt_value
)
272 aprint_normal("%s", fmt
->fmt_string
);
287 "oris %0,%0,%1@h;" /* enter power saving mode */
295 cpu_probe_cache(void)
297 u_int assoc
, pvr
, vers
;
303 /* Presently common across almost all implementations. */
304 curcpu()->ci_ci
.dcache_line_size
= 32;
305 curcpu()->ci_ci
.icache_line_size
= 32;
319 curcpu()->ci_ci
.dcache_size
= 32 K
;
320 curcpu()->ci_ci
.icache_size
= 32 K
;
324 curcpu()->ci_ci
.dcache_size
= 8 K
;
325 curcpu()->ci_ci
.icache_size
= 8 K
;
334 curcpu()->ci_ci
.dcache_size
= 16 K
;
335 curcpu()->ci_ci
.icache_size
= 16 K
;
340 curcpu()->ci_ci
.dcache_size
= 32 K
;
341 curcpu()->ci_ci
.icache_size
= 32 K
;
345 curcpu()->ci_ci
.dcache_size
= 64 K
;
346 curcpu()->ci_ci
.icache_size
= 32 K
;
347 curcpu()->ci_ci
.dcache_line_size
= 128;
348 curcpu()->ci_ci
.icache_line_size
= 128;
349 assoc
= 128; /* not a typo */
354 curcpu()->ci_ci
.dcache_size
= 32 K
;
355 curcpu()->ci_ci
.icache_size
= 64 K
;
356 curcpu()->ci_ci
.dcache_line_size
= 128;
357 curcpu()->ci_ci
.icache_line_size
= 128;
362 curcpu()->ci_ci
.dcache_size
= PAGE_SIZE
;
363 curcpu()->ci_ci
.icache_size
= PAGE_SIZE
;
371 uvm_page_recolor(atop(curcpu()->ci_ci
.dcache_size
/ assoc
));
375 cpu_attach_common(struct device
*self
, int id
)
381 #ifndef MULTIPROCESSOR
383 * If this isn't the primary CPU, print an error message
387 aprint_normal(": ID %d\n", id
);
388 aprint_normal("%s: processor off-line; multiprocessor support "
389 "not present in kernel\n", self
->dv_xname
);
395 ci
->ci_intrdepth
= -1;
397 ci
->ci_idlespin
= cpu_idlespin
;
400 vers
= (pvr
>> 16) & 0xffff;
404 /* load my cpu_number to PIR */
422 if (id
>= CPU_MAXNUM
) {
423 aprint_normal(": more than %d cpus?\n", CPU_MAXNUM
);
426 #ifndef MULTIPROCESSOR
427 aprint_normal(" not configured\n");
438 cpu_setup(struct device
*self
, struct cpu_info
*ci
)
440 u_int hid0
, hid0_save
, pvr
, vers
;
446 vers
= (pvr
>> 16) & 0xffff;
448 cpu_identify(model
, sizeof(model
));
449 aprint_normal(": %s, ID %d%s\n", model
, cpu_number(),
450 cpu_number() == 0 ? " (primary)" : "");
452 /* set the cpu number */
453 ci
->ci_cpuid
= cpu_number();
454 hid0_save
= hid0
= mfspr(SPR_HID0
);
459 * Configure power-saving mode.
466 * Do not have HID0 support settings, but can support
482 /* Select DOZE mode. */
483 hid0
&= ~(HID0_DOZE
| HID0_NAP
| HID0_SLEEP
);
484 hid0
|= HID0_DOZE
| HID0_DPM
;
493 /* Enable the 7450 branch caches */
494 hid0
|= HID0_SGE
| HID0_BTIC
;
495 hid0
|= HID0_LRSTK
| HID0_FOLD
| HID0_BHT
;
496 /* Enable more and larger BAT registers */
497 if (oeacpufeat
& OEACPU_XBSEN
)
499 if (oeacpufeat
& OEACPU_HIGHBAT
)
500 hid0
|= HID0_HIGH_BAT_EN
;
501 /* Disable BTIC on 7450 Rev 2.0 or earlier */
502 if (vers
== MPC7450
&& (pvr
& 0xFFFF) <= 0x0200)
504 /* Select NAP mode. */
506 hid0
|= HID0_NAP
| HID0_DPM
;
515 /* No power-saving mode is available. */ ;
523 /* Select NAP mode. */
524 hid0
&= ~(HID0_DOZE
| HID0_NAP
| HID0_SLEEP
);
533 hid0
&= ~HID0_DBP
; /* XXX correct? */
534 hid0
|= HID0_EMCP
| HID0_BTIC
| HID0_SGE
| HID0_BHT
;
540 hid0
|= HID0_EMCP
| HID0_BTIC
| HID0_SGE
| HID0_BHT
;
545 if (hid0
!= hid0_save
) {
546 mtspr(SPR_HID0
, hid0
);
547 __asm
volatile("sync;isync");
553 bitmask
= HID0_601_BITMASK
;
558 bitmask
= HID0_7450_BITMASK
;
566 bitmask
= HID0_BITMASK
;
569 snprintb(hidbuf
, sizeof hidbuf
, bitmask
, hid0
);
570 aprint_normal("%s: HID0 %s, powersave: %d\n", self
->dv_xname
, hidbuf
,
576 * Display speed and cache configuration.
591 aprint_normal("%s: ", self
->dv_xname
);
593 aprint_normal("%u.%02u MHz",
594 ci
->ci_khz
/ 1000, (ci
->ci_khz
/ 10) % 100);
596 case MPC7450
: /* 7441 does not have L3! */
597 case MPC7455
: /* 7445 does not have L3! */
598 case MPC7457
: /* 7447 does not have L3! */
599 cpu_config_l3cr(vers
);
607 cpu_config_l2cr(pvr
);
616 #if NSYSMON_ENVSYS > 0
618 * Attach MPC750 temperature sensor to the envsys subsystem.
619 * XXX the 74xx series also has this sensor, but it is not
620 * XXX supported by Motorola and may return values that are off by
621 * XXX 35-55 degrees C.
623 if (vers
== MPC750
|| vers
== IBM750FX
)
627 evcnt_attach_dynamic(&ci
->ci_ev_clock
, EVCNT_TYPE_INTR
,
628 NULL
, self
->dv_xname
, "clock");
629 evcnt_attach_dynamic(&ci
->ci_ev_softclock
, EVCNT_TYPE_INTR
,
630 NULL
, self
->dv_xname
, "soft clock");
631 evcnt_attach_dynamic(&ci
->ci_ev_softnet
, EVCNT_TYPE_INTR
,
632 NULL
, self
->dv_xname
, "soft net");
633 evcnt_attach_dynamic(&ci
->ci_ev_softserial
, EVCNT_TYPE_INTR
,
634 NULL
, self
->dv_xname
, "soft serial");
635 evcnt_attach_dynamic(&ci
->ci_ev_traps
, EVCNT_TYPE_TRAP
,
636 NULL
, self
->dv_xname
, "traps");
637 evcnt_attach_dynamic(&ci
->ci_ev_kdsi
, EVCNT_TYPE_TRAP
,
638 &ci
->ci_ev_traps
, self
->dv_xname
, "kernel DSI traps");
639 evcnt_attach_dynamic(&ci
->ci_ev_udsi
, EVCNT_TYPE_TRAP
,
640 &ci
->ci_ev_traps
, self
->dv_xname
, "user DSI traps");
641 evcnt_attach_dynamic(&ci
->ci_ev_udsi_fatal
, EVCNT_TYPE_TRAP
,
642 &ci
->ci_ev_udsi
, self
->dv_xname
, "user DSI failures");
643 evcnt_attach_dynamic(&ci
->ci_ev_kisi
, EVCNT_TYPE_TRAP
,
644 &ci
->ci_ev_traps
, self
->dv_xname
, "kernel ISI traps");
645 evcnt_attach_dynamic(&ci
->ci_ev_isi
, EVCNT_TYPE_TRAP
,
646 &ci
->ci_ev_traps
, self
->dv_xname
, "user ISI traps");
647 evcnt_attach_dynamic(&ci
->ci_ev_isi_fatal
, EVCNT_TYPE_TRAP
,
648 &ci
->ci_ev_isi
, self
->dv_xname
, "user ISI failures");
649 evcnt_attach_dynamic(&ci
->ci_ev_scalls
, EVCNT_TYPE_TRAP
,
650 &ci
->ci_ev_traps
, self
->dv_xname
, "system call traps");
651 evcnt_attach_dynamic(&ci
->ci_ev_pgm
, EVCNT_TYPE_TRAP
,
652 &ci
->ci_ev_traps
, self
->dv_xname
, "PGM traps");
653 evcnt_attach_dynamic(&ci
->ci_ev_fpu
, EVCNT_TYPE_TRAP
,
654 &ci
->ci_ev_traps
, self
->dv_xname
, "FPU unavailable traps");
655 evcnt_attach_dynamic(&ci
->ci_ev_fpusw
, EVCNT_TYPE_TRAP
,
656 &ci
->ci_ev_fpu
, self
->dv_xname
, "FPU context switches");
657 evcnt_attach_dynamic(&ci
->ci_ev_ali
, EVCNT_TYPE_TRAP
,
658 &ci
->ci_ev_traps
, self
->dv_xname
, "user alignment traps");
659 evcnt_attach_dynamic(&ci
->ci_ev_ali_fatal
, EVCNT_TYPE_TRAP
,
660 &ci
->ci_ev_ali
, self
->dv_xname
, "user alignment traps");
661 evcnt_attach_dynamic(&ci
->ci_ev_umchk
, EVCNT_TYPE_TRAP
,
662 &ci
->ci_ev_umchk
, self
->dv_xname
, "user MCHK failures");
663 evcnt_attach_dynamic(&ci
->ci_ev_vec
, EVCNT_TYPE_TRAP
,
664 &ci
->ci_ev_traps
, self
->dv_xname
, "AltiVec unavailable");
667 evcnt_attach_dynamic(&ci
->ci_ev_vecsw
, EVCNT_TYPE_TRAP
,
668 &ci
->ci_ev_vec
, self
->dv_xname
, "AltiVec context switches");
671 evcnt_attach_dynamic(&ci
->ci_ev_ipi
, EVCNT_TYPE_INTR
,
672 NULL
, self
->dv_xname
, "IPIs");
676 * According to a document labeled "PVR Register Settings":
677 ** For integrated microprocessors the PVR register inside the device
678 ** will identify the version of the microprocessor core. You must also
679 ** read the Device ID, PCI register 02, to identify the part and the
680 ** Revision ID, PCI register 08, to identify the revision of the
681 ** integrated microprocessor.
682 * This apparently applies to 8240/8245/8241, PVR 00810101 and 80811014
686 cpu_identify(char *str
, size_t len
)
688 u_int pvr
, major
, minor
;
689 uint16_t vers
, rev
, revfmt
;
690 const struct cputab
*cp
;
700 minor
= (pvr
>> 0) & 0xff;
701 major
= minor
<= 4 ? 1 : 2;
703 case MPCG2
: /*XXX see note above */
704 major
= (pvr
>> 4) & 0xf;
705 minor
= (pvr
>> 0) & 0xf;
708 major
= (pvr
>> 8) & 0xf;
709 minor
= (pvr
>> 0) & 0xf;
712 for (cp
= models
; cp
->name
[0] != '\0'; cp
++) {
713 if (cp
->version
== vers
)
719 len
= sizeof(cpu_model
);
725 if (rev
== MPC750
&& pvr
== 15) {
730 if (cp
->name
[0] != '\0') {
731 n
= snprintf(str
, len
, "%s (Revision ", cp
->name
);
733 n
= snprintf(str
, len
, "Version %#x (Revision ", vers
);
738 snprintf(str
+ n
, len
- n
, "%u.%u)", major
, minor
);
741 snprintf(str
+ n
, len
- n
, "0x%04x)", rev
);
744 snprintf(str
+ n
, len
- n
, "%u)", rev
);
751 u_int l2cr_config
= L2CR_CONFIG
;
753 u_int l2cr_config
= 0;
757 u_int l3cr_config
= L3CR_CONFIG
;
759 u_int l3cr_config
= 0;
763 cpu_enable_l2cr(register_t l2cr
)
768 vers
= mfpvr() >> 16;
770 /* Disable interrupts and set the cache config bits. */
772 mtmsr(msr
& ~PSL_EE
);
775 __asm
volatile("dssall");
777 __asm
volatile("sync");
778 mtspr(SPR_L2CR
, l2cr
& ~L2CR_L2E
);
779 __asm
volatile("sync");
781 /* Wait for L2 clock to be stable (640 L2 clocks). */
784 /* Invalidate all L2 contents. */
785 if (MPC745X_P(vers
)) {
786 mtspr(SPR_L2CR
, l2cr
| L2CR_L2I
);
789 } while (x
& L2CR_L2I
);
791 mtspr(SPR_L2CR
, l2cr
| L2CR_L2I
);
794 } while (x
& L2CR_L2IP
);
796 /* Enable L2 cache. */
798 mtspr(SPR_L2CR
, l2cr
);
803 cpu_enable_l3cr(register_t l3cr
)
807 /* By The Book (numbered steps from section 3.7.1.3 of MPC7450UM) */
810 * 1: Set all L3CR bits for final config except L3E, L3I, L3PE, and
811 * L3CLKEN. (also mask off reserved bits in case they were included
814 l3cr
&= ~(L3CR_L3E
|L3CR_L3I
|L3CR_L3PE
|L3CR_L3CLKEN
|L3CR_RESERVED
);
815 mtspr(SPR_L3CR
, l3cr
);
817 /* 2: Set L3CR[5] (otherwise reserved bit) to 1 */
819 mtspr(SPR_L3CR
, l3cr
);
821 /* 3: Set L3CLKEN to 1*/
822 l3cr
|= L3CR_L3CLKEN
;
823 mtspr(SPR_L3CR
, l3cr
);
825 /* 4/5: Perform a global cache invalidate (ref section 3.7.3.6) */
826 __asm
volatile("dssall;sync");
827 /* L3 cache is already disabled, no need to clear L3E */
828 mtspr(SPR_L3CR
, l3cr
|L3CR_L3I
);
831 } while (x
& L3CR_L3I
);
833 /* 6: Clear L3CLKEN to 0 */
834 l3cr
&= ~L3CR_L3CLKEN
;
835 mtspr(SPR_L3CR
, l3cr
);
837 /* 7: Perform a 'sync' and wait at least 100 CPU cycles */
838 __asm
volatile("sync");
841 /* 8: Set L3E and L3CLKEN */
842 l3cr
|= (L3CR_L3E
|L3CR_L3CLKEN
);
843 mtspr(SPR_L3CR
, l3cr
);
845 /* 9: Perform a 'sync' and wait at least 100 CPU cycles */
846 __asm
volatile("sync");
851 cpu_config_l2cr(int pvr
)
854 u_int vers
= (pvr
>> 16) & 0xffff;
856 l2cr
= mfspr(SPR_L2CR
);
859 * For MP systems, the firmware may only configure the L2 cache
860 * on the first CPU. In this case, assume that the other CPUs
861 * should use the same value for L2CR.
863 if ((l2cr
& L2CR_L2E
) != 0 && l2cr_config
== 0) {
868 * Configure L2 cache if not enabled.
870 if ((l2cr
& L2CR_L2E
) == 0 && l2cr_config
!= 0) {
871 cpu_enable_l2cr(l2cr_config
);
872 l2cr
= mfspr(SPR_L2CR
);
875 if ((l2cr
& L2CR_L2E
) == 0) {
876 aprint_normal(" L2 cache present but not enabled ");
883 cpu_fmttab_print(cpu_ibm750_l2cr_formats
, l2cr
);
886 if ((pvr
& 0xffffff00) == 0x00082200 /* IBM750CX */ ||
887 (pvr
& 0xffffef00) == 0x00082300 /* IBM750CXe */)
888 cpu_fmttab_print(cpu_ibm750_l2cr_formats
, l2cr
);
890 cpu_fmttab_print(cpu_l2cr_formats
, l2cr
);
894 cpu_fmttab_print(cpu_7457_l2cr_formats
, l2cr
);
897 cpu_fmttab_print(cpu_7448_l2cr_formats
, l2cr
);
901 cpu_fmttab_print(cpu_7450_l2cr_formats
, l2cr
);
904 cpu_fmttab_print(cpu_l2cr_formats
, l2cr
);
910 cpu_config_l3cr(int vers
)
915 l2cr
= mfspr(SPR_L2CR
);
918 * For MP systems, the firmware may only configure the L2 cache
919 * on the first CPU. In this case, assume that the other CPUs
920 * should use the same value for L2CR.
922 if ((l2cr
& L2CR_L2E
) != 0 && l2cr_config
== 0) {
927 * Configure L2 cache if not enabled.
929 if ((l2cr
& L2CR_L2E
) == 0 && l2cr_config
!= 0) {
930 cpu_enable_l2cr(l2cr_config
);
931 l2cr
= mfspr(SPR_L2CR
);
938 cpu_fmttab_print(cpu_7457_l2cr_formats
, l2cr
);
941 cpu_fmttab_print(cpu_7448_l2cr_formats
, l2cr
);
944 cpu_fmttab_print(cpu_7450_l2cr_formats
, l2cr
);
948 l3cr
= mfspr(SPR_L3CR
);
951 * For MP systems, the firmware may only configure the L3 cache
952 * on the first CPU. In this case, assume that the other CPUs
953 * should use the same value for L3CR.
955 if ((l3cr
& L3CR_L3E
) != 0 && l3cr_config
== 0) {
960 * Configure L3 cache if not enabled.
962 if ((l3cr
& L3CR_L3E
) == 0 && l3cr_config
!= 0) {
963 cpu_enable_l3cr(l3cr_config
);
964 l3cr
= mfspr(SPR_L3CR
);
967 if (l3cr
& L3CR_L3E
) {
969 cpu_fmttab_print(cpu_7450_l3cr_formats
, l3cr
);
974 cpu_probe_speed(struct cpu_info
*ci
)
978 mtspr(SPR_MMCR0
, MMCR0_FC
);
980 mtspr(SPR_MMCR0
, MMCR0_PMC1SEL(PMCN_CYCLES
));
982 cps
= (mfspr(SPR_PMC1
) * 10) + 4999;
984 mtspr(SPR_MMCR0
, MMCR0_FC
);
986 ci
->ci_khz
= cps
/ 1000;
989 #if NSYSMON_ENVSYS > 0
991 cpu_tau_setup(struct cpu_info
*ci
)
993 struct sysmon_envsys
*sme
;
994 int error
, therm_delay
;
996 mtspr(SPR_THRM1
, SPR_THRM_VALID
);
1000 * we need to figure out how much 20+us in units of CPU clock cycles
1004 therm_delay
= ci
->ci_khz
/ 40; /* 25us just to be safe */
1006 mtspr(SPR_THRM3
, SPR_THRM_TIMER(therm_delay
) | SPR_THRM_ENABLE
);
1008 sme
= sysmon_envsys_create();
1010 sensor
.units
= ENVSYS_STEMP
;
1011 (void)strlcpy(sensor
.desc
, "CPU Temp", sizeof(sensor
.desc
));
1012 if (sysmon_envsys_sensor_attach(sme
, &sensor
)) {
1013 sysmon_envsys_destroy(sme
);
1017 sme
->sme_name
= ci
->ci_dev
->dv_xname
;
1018 sme
->sme_cookie
= ci
;
1019 sme
->sme_refresh
= cpu_tau_refresh
;
1021 if ((error
= sysmon_envsys_register(sme
)) != 0) {
1022 aprint_error("%s: unable to register with sysmon (%d)\n",
1023 ci
->ci_dev
->dv_xname
, error
);
1024 sysmon_envsys_destroy(sme
);
1029 /* Find the temperature of the CPU. */
1031 cpu_tau_refresh(struct sysmon_envsys
*sme
, envsys_data_t
*edata
)
1033 int i
, threshold
, count
;
1035 threshold
= 64; /* Half of the 7-bit sensor range */
1037 /* Successive-approximation code adapted from Motorola
1038 * application note AN1800/D, "Programming the Thermal Assist
1039 * Unit in the MPC750 Microprocessor".
1041 for (i
= 5; i
>= 0 ; i
--) {
1043 SPR_THRM_THRESHOLD(threshold
) | SPR_THRM_VALID
);
1045 while ((count
< 100000) &&
1046 ((mfspr(SPR_THRM1
) & SPR_THRM_TIV
) == 0)) {
1050 if (mfspr(SPR_THRM1
) & SPR_THRM_TIN
) {
1051 /* The interrupt bit was set, meaning the
1052 * temperature was above the threshold
1054 threshold
+= 1 << i
;
1056 /* Temperature was below the threshold */
1057 threshold
-= 1 << i
;
1063 /* Convert the temperature in degrees C to microkelvin */
1064 edata
->value_cur
= (threshold
* 1000000) + 273150000;
1065 edata
->state
= ENVSYS_SVALID
;
1067 #endif /* NSYSMON_ENVSYS > 0 */
1069 #ifdef MULTIPROCESSOR
1070 extern volatile u_int cpu_spinstart_ack
;
1073 cpu_spinup(struct device
*self
, struct cpu_info
*ci
)
1075 volatile struct cpu_hatch_data hatch_data
, *h
= &hatch_data
;
1076 struct pglist mlist
;
1077 int i
, error
, pvr
, vers
;
1082 KASSERT(ci
!= curcpu());
1085 * Allocate some contiguous pages for the intteup PCB and stack
1086 * from the lowest 256MB (because bat0 always maps it va == pa).
1087 * Must be 16 byte aligned.
1089 error
= uvm_pglistalloc(INTSTK
, 0x10000, 0x10000000, 16, 0,
1092 aprint_error(": unable to allocate idle stack\n");
1096 KASSERT(ci
!= &cpu_info
[0]);
1098 cp
= (void *)VM_PAGE_TO_PHYS(TAILQ_FIRST(&mlist
));
1099 memset(cp
, 0, INTSTK
);
1103 /* Now allocate a hatch stack */
1104 error
= uvm_pglistalloc(0x1000, 0x10000, 0x10000000, 16, 0,
1107 aprint_error(": unable to allocate hatch stack\n");
1111 hp
= (void *)VM_PAGE_TO_PHYS(TAILQ_FIRST(&mlist
));
1112 memset(hp
, 0, 0x1000);
1114 /* Initialize secondary cpu's initial lwp to its idlelwp. */
1115 ci
->ci_curlwp
= ci
->ci_data
.cpu_idlelwp
;
1116 ci
->ci_curpcb
= lwp_getpcb(ci
->ci_curlwp
);
1117 ci
->ci_curpm
= ci
->ci_curpcb
->pcb_pm
;
1123 h
->pir
= ci
->ci_cpuid
;
1125 cpu_hatch_stack
= (uint32_t)hp
;
1126 ci
->ci_lasttb
= cpu_info
[0].ci_lasttb
;
1128 /* copy special registers */
1130 h
->hid0
= mfspr(SPR_HID0
);
1132 __asm
volatile ("mfsdr1 %0" : "=r"(h
->sdr1
));
1133 for (i
= 0; i
< 16; i
++) {
1134 __asm ("mfsrin %0,%1" : "=r"(h
->sr
[i
]) :
1135 "r"(i
<< ADDR_SR_SHFT
));
1137 if (oeacpufeat
& OEACPU_64
)
1138 h
->asr
= mfspr(SPR_ASR
);
1142 /* copy the bat regs */
1143 __asm
volatile ("mfibatu %0,0" : "=r"(h
->batu
[0]));
1144 __asm
volatile ("mfibatl %0,0" : "=r"(h
->batl
[0]));
1145 __asm
volatile ("mfibatu %0,1" : "=r"(h
->batu
[1]));
1146 __asm
volatile ("mfibatl %0,1" : "=r"(h
->batl
[1]));
1147 __asm
volatile ("mfibatu %0,2" : "=r"(h
->batu
[2]));
1148 __asm
volatile ("mfibatl %0,2" : "=r"(h
->batl
[2]));
1149 __asm
volatile ("mfibatu %0,3" : "=r"(h
->batu
[3]));
1150 __asm
volatile ("mfibatl %0,3" : "=r"(h
->batl
[3]));
1151 __asm
volatile ("sync; isync");
1153 if (md_setup_trampoline(h
, ci
) == -1)
1155 md_presync_timebase(h
);
1156 md_start_timebase(h
);
1158 /* wait for secondary printf */
1162 if (h
->running
< 1) {
1163 aprint_error("%d:CPU %d didn't start %d\n", cpu_spinstart_ack
,
1164 ci
->ci_cpuid
, cpu_spinstart_ack
);
1169 /* Register IPI Interrupt */
1170 if (ipiops
.ppc_establish_ipi
)
1171 ipiops
.ppc_establish_ipi(IST_LEVEL
, IPL_HIGH
, NULL
);
1176 static volatile int start_secondary_cpu
;
1177 extern void tlbia(void);
1182 volatile struct cpu_hatch_data
*h
= cpu_hatch_data
;
1183 struct cpu_info
* const ci
= h
->ci
;
1188 /* Initialize timebase. */
1189 __asm ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0));
1192 * Set PIR (Processor Identification Register). i.e. whoami
1193 * Note that PIR is read-only on some CPU versions, so we write to it
1194 * only if it has a different value than we need.
1197 msr
= mfspr(SPR_PIR
);
1199 mtspr(SPR_PIR
, h
->pir
);
1201 __asm
volatile ("mtsprg 0,%0" :: "r"(ci
));
1202 cpu_spinstart_ack
= 0;
1204 /* Initialize MMU. */
1205 __asm ("mtibatu 0,%0" :: "r"(h
->batu
[0]));
1206 __asm ("mtibatl 0,%0" :: "r"(h
->batl
[0]));
1207 __asm ("mtibatu 1,%0" :: "r"(h
->batu
[1]));
1208 __asm ("mtibatl 1,%0" :: "r"(h
->batl
[1]));
1209 __asm ("mtibatu 2,%0" :: "r"(h
->batu
[2]));
1210 __asm ("mtibatl 2,%0" :: "r"(h
->batl
[2]));
1211 __asm ("mtibatu 3,%0" :: "r"(h
->batu
[3]));
1212 __asm ("mtibatl 3,%0" :: "r"(h
->batl
[3]));
1214 mtspr(SPR_HID0
, h
->hid0
);
1216 __asm ("mtibatl 0,%0; mtibatu 0,%1; mtdbatl 0,%0; mtdbatu 0,%1;"
1217 :: "r"(battable
[0].batl
), "r"(battable
[0].batu
));
1219 __asm
volatile ("sync");
1220 for (i
= 0; i
< 16; i
++)
1221 __asm ("mtsrin %0,%1" :: "r"(h
->sr
[i
]), "r"(i
<< ADDR_SR_SHFT
));
1222 __asm
volatile ("sync; isync");
1224 if (oeacpufeat
& OEACPU_64
)
1225 mtspr(SPR_ASR
, h
->asr
);
1227 cpu_spinstart_ack
= 1;
1229 __asm ("mtsdr1 %0" :: "r"(h
->sdr1
));
1230 __asm
volatile ("sync; isync");
1232 cpu_spinstart_ack
= 5;
1233 for (i
= 0; i
< 16; i
++)
1234 __asm ("mfsrin %0,%1" : "=r"(h
->sr
[i
]) :
1235 "r"(i
<< ADDR_SR_SHFT
));
1237 /* Enable I/D address translations. */
1239 msr
|= PSL_IR
|PSL_DR
|PSL_ME
|PSL_RI
;
1241 __asm
volatile ("sync; isync");
1242 cpu_spinstart_ack
= 2;
1244 md_sync_timebase(h
);
1246 cpu_setup(h
->self
, ci
);
1249 __asm
volatile ("sync; isync");
1251 while (start_secondary_cpu
== 0)
1254 __asm
volatile ("sync; isync");
1256 aprint_normal("cpu%d started\n", curcpu()->ci_index
);
1257 __asm
volatile ("mtdec %0" :: "r"(ticks_per_intr
));
1259 md_setup_interrupts();
1261 ci
->ci_ipending
= 0;
1264 mtmsr(mfmsr() | PSL_EE
);
1265 pcb
= lwp_getpcb(ci
->ci_data
.cpu_idlelwp
);
1270 cpu_boot_secondary_processors(void)
1272 start_secondary_cpu
= 1;
1273 __asm
volatile ("sync");
1276 #endif /*MULTIPROCESSOR*/