| @@ -1,1519 +1,1522 @@ | | | @@ -1,1519 +1,1522 @@ |
1 | /* $NetBSD: cpu_subr.c,v 1.95 2018/06/01 18:06:58 macallan Exp $ */ | | 1 | /* $NetBSD: cpu_subr.c,v 1.96 2018/06/08 23:40:44 macallan Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001 Matt Thomas. | | 4 | * Copyright (c) 2001 Matt Thomas. |
5 | * Copyright (c) 2001 Tsubai Masanari. | | 5 | * Copyright (c) 2001 Tsubai Masanari. |
6 | * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc. | | 6 | * Copyright (c) 1998, 1999, 2001 Internet Research Institute, Inc. |
7 | * All rights reserved. | | 7 | * All rights reserved. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. All advertising materials mentioning features or use of this software | | 17 | * 3. All advertising materials mentioning features or use of this software |
18 | * must display the following acknowledgement: | | 18 | * must display the following acknowledgement: |
19 | * This product includes software developed by | | 19 | * This product includes software developed by |
20 | * Internet Research Institute, Inc. | | 20 | * Internet Research Institute, Inc. |
21 | * 4. The name of the author may not be used to endorse or promote products | | 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. | | 22 | * derived from this software without specific prior written permission. |
23 | * | | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 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 | | 25 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 26 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
27 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 27 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 28 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 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 | | 30 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 31 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
32 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | | 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. | | 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | */ | | 34 | */ |
35 | | | 35 | |
36 | #include <sys/cdefs.h> | | 36 | #include <sys/cdefs.h> |
37 | __KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.95 2018/06/01 18:06:58 macallan Exp $"); | | 37 | __KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.96 2018/06/08 23:40:44 macallan Exp $"); |
38 | | | 38 | |
39 | #include "opt_ppcparam.h" | | 39 | #include "opt_ppcparam.h" |
40 | #include "opt_ppccache.h" | | 40 | #include "opt_ppccache.h" |
41 | #include "opt_multiprocessor.h" | | 41 | #include "opt_multiprocessor.h" |
42 | #include "opt_altivec.h" | | 42 | #include "opt_altivec.h" |
43 | #include "sysmon_envsys.h" | | 43 | #include "sysmon_envsys.h" |
44 | | | 44 | |
45 | #include <sys/param.h> | | 45 | #include <sys/param.h> |
46 | #include <sys/systm.h> | | 46 | #include <sys/systm.h> |
47 | #include <sys/device.h> | | 47 | #include <sys/device.h> |
48 | #include <sys/types.h> | | 48 | #include <sys/types.h> |
49 | #include <sys/lwp.h> | | 49 | #include <sys/lwp.h> |
50 | #include <sys/xcall.h> | | 50 | #include <sys/xcall.h> |
51 | | | 51 | |
52 | #include <uvm/uvm.h> | | 52 | #include <uvm/uvm.h> |
53 | | | 53 | |
54 | #include <powerpc/pcb.h> | | 54 | #include <powerpc/pcb.h> |
55 | #include <powerpc/psl.h> | | 55 | #include <powerpc/psl.h> |
56 | #include <powerpc/spr.h> | | 56 | #include <powerpc/spr.h> |
57 | #include <powerpc/oea/hid.h> | | 57 | #include <powerpc/oea/hid.h> |
58 | #include <powerpc/oea/hid_601.h> | | 58 | #include <powerpc/oea/hid_601.h> |
59 | #include <powerpc/oea/spr.h> | | 59 | #include <powerpc/oea/spr.h> |
60 | #include <powerpc/oea/cpufeat.h> | | 60 | #include <powerpc/oea/cpufeat.h> |
61 | | | 61 | |
62 | #include <dev/sysmon/sysmonvar.h> | | 62 | #include <dev/sysmon/sysmonvar.h> |
63 | | | 63 | |
64 | static void cpu_enable_l2cr(register_t); | | 64 | static void cpu_enable_l2cr(register_t); |
65 | static void cpu_enable_l3cr(register_t); | | 65 | static void cpu_enable_l3cr(register_t); |
66 | static void cpu_config_l2cr(int); | | 66 | static void cpu_config_l2cr(int); |
67 | static void cpu_config_l3cr(int); | | 67 | static void cpu_config_l3cr(int); |
68 | static void cpu_probe_speed(struct cpu_info *); | | 68 | static void cpu_probe_speed(struct cpu_info *); |
69 | static void cpu_idlespin(void); | | 69 | static void cpu_idlespin(void); |
70 | static void cpu_set_dfs_xcall(void *, void *); | | 70 | static void cpu_set_dfs_xcall(void *, void *); |
71 | #if NSYSMON_ENVSYS > 0 | | 71 | #if NSYSMON_ENVSYS > 0 |
72 | static void cpu_tau_setup(struct cpu_info *); | | 72 | static void cpu_tau_setup(struct cpu_info *); |
73 | static void cpu_tau_refresh(struct sysmon_envsys *, envsys_data_t *); | | 73 | static void cpu_tau_refresh(struct sysmon_envsys *, envsys_data_t *); |
74 | #endif | | 74 | #endif |
75 | | | 75 | |
76 | extern void init_scom_speedctl(void); | | 76 | extern void init_scom_speedctl(void); |
77 | | | 77 | |
78 | int cpu = -1; | | 78 | int cpu = -1; |
79 | int ncpus; | | 79 | int ncpus; |
80 | | | 80 | |
81 | struct fmttab { | | 81 | struct fmttab { |
82 | register_t fmt_mask; | | 82 | register_t fmt_mask; |
83 | register_t fmt_value; | | 83 | register_t fmt_value; |
84 | const char *fmt_string; | | 84 | const char *fmt_string; |
85 | }; | | 85 | }; |
86 | | | 86 | |
87 | /* | | 87 | /* |
88 | * This should be one per CPU but since we only support it on 750 variants it | | 88 | * This should be one per CPU but since we only support it on 750 variants it |
89 | * doesn't really matter since none of them support SMP | | 89 | * doesn't really matter since none of them support SMP |
90 | */ | | 90 | */ |
91 | envsys_data_t sensor; | | 91 | envsys_data_t sensor; |
92 | | | 92 | |
93 | static const struct fmttab cpu_7450_l2cr_formats[] = { | | 93 | static const struct fmttab cpu_7450_l2cr_formats[] = { |
94 | { L2CR_L2E, 0, " disabled" }, | | 94 | { L2CR_L2E, 0, " disabled" }, |
95 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, | | 95 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, |
96 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, | | 96 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, |
97 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, | | 97 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, |
98 | { L2CR_L2E, ~0, " 256KB L2 cache" }, | | 98 | { L2CR_L2E, ~0, " 256KB L2 cache" }, |
99 | { L2CR_L2PE, 0, " no parity" }, | | 99 | { L2CR_L2PE, 0, " no parity" }, |
100 | { L2CR_L2PE, ~0, " parity enabled" }, | | 100 | { L2CR_L2PE, ~0, " parity enabled" }, |
101 | { 0, 0, NULL } | | 101 | { 0, 0, NULL } |
102 | }; | | 102 | }; |
103 | | | 103 | |
104 | static const struct fmttab cpu_7448_l2cr_formats[] = { | | 104 | static const struct fmttab cpu_7448_l2cr_formats[] = { |
105 | { L2CR_L2E, 0, " disabled" }, | | 105 | { L2CR_L2E, 0, " disabled" }, |
106 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, | | 106 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, |
107 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, | | 107 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, |
108 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, | | 108 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, |
109 | { L2CR_L2E, ~0, " 1MB L2 cache" }, | | 109 | { L2CR_L2E, ~0, " 1MB L2 cache" }, |
110 | { L2CR_L2PE, 0, " no parity" }, | | 110 | { L2CR_L2PE, 0, " no parity" }, |
111 | { L2CR_L2PE, ~0, " parity enabled" }, | | 111 | { L2CR_L2PE, ~0, " parity enabled" }, |
112 | { 0, 0, NULL } | | 112 | { 0, 0, NULL } |
113 | }; | | 113 | }; |
114 | | | 114 | |
115 | static const struct fmttab cpu_7457_l2cr_formats[] = { | | 115 | static const struct fmttab cpu_7457_l2cr_formats[] = { |
116 | { L2CR_L2E, 0, " disabled" }, | | 116 | { L2CR_L2E, 0, " disabled" }, |
117 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, | | 117 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, |
118 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, | | 118 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, |
119 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, | | 119 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, |
120 | { L2CR_L2E, ~0, " 512KB L2 cache" }, | | 120 | { L2CR_L2E, ~0, " 512KB L2 cache" }, |
121 | { L2CR_L2PE, 0, " no parity" }, | | 121 | { L2CR_L2PE, 0, " no parity" }, |
122 | { L2CR_L2PE, ~0, " parity enabled" }, | | 122 | { L2CR_L2PE, ~0, " parity enabled" }, |
123 | { 0, 0, NULL } | | 123 | { 0, 0, NULL } |
124 | }; | | 124 | }; |
125 | | | 125 | |
126 | static const struct fmttab cpu_7450_l3cr_formats[] = { | | 126 | static const struct fmttab cpu_7450_l3cr_formats[] = { |
127 | { L3CR_L3DO|L3CR_L3IO, L3CR_L3DO, " data-only" }, | | 127 | { L3CR_L3DO|L3CR_L3IO, L3CR_L3DO, " data-only" }, |
128 | { L3CR_L3DO|L3CR_L3IO, L3CR_L3IO, " instruction-only" }, | | 128 | { L3CR_L3DO|L3CR_L3IO, L3CR_L3IO, " instruction-only" }, |
129 | { L3CR_L3DO|L3CR_L3IO, L3CR_L3DO|L3CR_L3IO, " locked" }, | | 129 | { L3CR_L3DO|L3CR_L3IO, L3CR_L3DO|L3CR_L3IO, " locked" }, |
130 | { L3CR_L3SIZ, L3SIZ_2M, " 2MB" }, | | 130 | { L3CR_L3SIZ, L3SIZ_2M, " 2MB" }, |
131 | { L3CR_L3SIZ, L3SIZ_1M, " 1MB" }, | | 131 | { L3CR_L3SIZ, L3SIZ_1M, " 1MB" }, |
132 | { L3CR_L3PE|L3CR_L3APE, L3CR_L3PE|L3CR_L3APE, " parity" }, | | 132 | { L3CR_L3PE|L3CR_L3APE, L3CR_L3PE|L3CR_L3APE, " parity" }, |
133 | { L3CR_L3PE|L3CR_L3APE, L3CR_L3PE, " data-parity" }, | | 133 | { L3CR_L3PE|L3CR_L3APE, L3CR_L3PE, " data-parity" }, |
134 | { L3CR_L3PE|L3CR_L3APE, L3CR_L3APE, " address-parity" }, | | 134 | { L3CR_L3PE|L3CR_L3APE, L3CR_L3APE, " address-parity" }, |
135 | { L3CR_L3PE|L3CR_L3APE, 0, " no-parity" }, | | 135 | { L3CR_L3PE|L3CR_L3APE, 0, " no-parity" }, |
136 | { L3CR_L3SIZ, ~0, " L3 cache" }, | | 136 | { L3CR_L3SIZ, ~0, " L3 cache" }, |
137 | { L3CR_L3RT, L3RT_MSUG2_DDR, " (DDR SRAM)" }, | | 137 | { L3CR_L3RT, L3RT_MSUG2_DDR, " (DDR SRAM)" }, |
138 | { L3CR_L3RT, L3RT_PIPELINE_LATE, " (LW SRAM)" }, | | 138 | { L3CR_L3RT, L3RT_PIPELINE_LATE, " (LW SRAM)" }, |
139 | { L3CR_L3RT, L3RT_PB2_SRAM, " (PB2 SRAM)" }, | | 139 | { L3CR_L3RT, L3RT_PB2_SRAM, " (PB2 SRAM)" }, |
140 | { L3CR_L3CLK, ~0, " at" }, | | 140 | { L3CR_L3CLK, ~0, " at" }, |
141 | { L3CR_L3CLK, L3CLK_20, " 2:1" }, | | 141 | { L3CR_L3CLK, L3CLK_20, " 2:1" }, |
142 | { L3CR_L3CLK, L3CLK_25, " 2.5:1" }, | | 142 | { L3CR_L3CLK, L3CLK_25, " 2.5:1" }, |
143 | { L3CR_L3CLK, L3CLK_30, " 3:1" }, | | 143 | { L3CR_L3CLK, L3CLK_30, " 3:1" }, |
144 | { L3CR_L3CLK, L3CLK_35, " 3.5:1" }, | | 144 | { L3CR_L3CLK, L3CLK_35, " 3.5:1" }, |
145 | { L3CR_L3CLK, L3CLK_40, " 4:1" }, | | 145 | { L3CR_L3CLK, L3CLK_40, " 4:1" }, |
146 | { L3CR_L3CLK, L3CLK_50, " 5:1" }, | | 146 | { L3CR_L3CLK, L3CLK_50, " 5:1" }, |
147 | { L3CR_L3CLK, L3CLK_60, " 6:1" }, | | 147 | { L3CR_L3CLK, L3CLK_60, " 6:1" }, |
148 | { L3CR_L3CLK, ~0, " ratio" }, | | 148 | { L3CR_L3CLK, ~0, " ratio" }, |
149 | { 0, 0, NULL }, | | 149 | { 0, 0, NULL }, |
150 | }; | | 150 | }; |
151 | | | 151 | |
152 | static const struct fmttab cpu_ibm750_l2cr_formats[] = { | | 152 | static const struct fmttab cpu_ibm750_l2cr_formats[] = { |
153 | { L2CR_L2E, 0, " disabled" }, | | 153 | { L2CR_L2E, 0, " disabled" }, |
154 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, | | 154 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, |
155 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, | | 155 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, |
156 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, | | 156 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, |
157 | { 0, ~0, " 512KB" }, | | 157 | { 0, ~0, " 512KB" }, |
158 | { L2CR_L2WT, L2CR_L2WT, " WT" }, | | 158 | { L2CR_L2WT, L2CR_L2WT, " WT" }, |
159 | { L2CR_L2WT, 0, " WB" }, | | 159 | { L2CR_L2WT, 0, " WB" }, |
160 | { L2CR_L2PE, L2CR_L2PE, " with ECC" }, | | 160 | { L2CR_L2PE, L2CR_L2PE, " with ECC" }, |
161 | { 0, ~0, " L2 cache" }, | | 161 | { 0, ~0, " L2 cache" }, |
162 | { 0, 0, NULL } | | 162 | { 0, 0, NULL } |
163 | }; | | 163 | }; |
164 | | | 164 | |
165 | static const struct fmttab cpu_l2cr_formats[] = { | | 165 | static const struct fmttab cpu_l2cr_formats[] = { |
166 | { L2CR_L2E, 0, " disabled" }, | | 166 | { L2CR_L2E, 0, " disabled" }, |
167 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, | | 167 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO, " data-only" }, |
168 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, | | 168 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2IO, " instruction-only" }, |
169 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, | | 169 | { L2CR_L2DO|L2CR_L2IO, L2CR_L2DO|L2CR_L2IO, " locked" }, |
170 | { L2CR_L2PE, L2CR_L2PE, " parity" }, | | 170 | { L2CR_L2PE, L2CR_L2PE, " parity" }, |
171 | { L2CR_L2PE, 0, " no-parity" }, | | 171 | { L2CR_L2PE, 0, " no-parity" }, |
172 | { L2CR_L2SIZ, L2SIZ_2M, " 2MB" }, | | 172 | { L2CR_L2SIZ, L2SIZ_2M, " 2MB" }, |
173 | { L2CR_L2SIZ, L2SIZ_1M, " 1MB" }, | | 173 | { L2CR_L2SIZ, L2SIZ_1M, " 1MB" }, |
174 | { L2CR_L2SIZ, L2SIZ_512K, " 512KB" }, | | 174 | { L2CR_L2SIZ, L2SIZ_512K, " 512KB" }, |
175 | { L2CR_L2SIZ, L2SIZ_256K, " 256KB" }, | | 175 | { L2CR_L2SIZ, L2SIZ_256K, " 256KB" }, |
176 | { L2CR_L2WT, L2CR_L2WT, " WT" }, | | 176 | { L2CR_L2WT, L2CR_L2WT, " WT" }, |
177 | { L2CR_L2WT, 0, " WB" }, | | 177 | { L2CR_L2WT, 0, " WB" }, |
178 | { L2CR_L2E, ~0, " L2 cache" }, | | 178 | { L2CR_L2E, ~0, " L2 cache" }, |
179 | { L2CR_L2RAM, L2RAM_FLOWTHRU_BURST, " (FB SRAM)" }, | | 179 | { L2CR_L2RAM, L2RAM_FLOWTHRU_BURST, " (FB SRAM)" }, |
180 | { L2CR_L2RAM, L2RAM_PIPELINE_LATE, " (LW SRAM)" }, | | 180 | { L2CR_L2RAM, L2RAM_PIPELINE_LATE, " (LW SRAM)" }, |
181 | { L2CR_L2RAM, L2RAM_PIPELINE_BURST, " (PB SRAM)" }, | | 181 | { L2CR_L2RAM, L2RAM_PIPELINE_BURST, " (PB SRAM)" }, |
182 | { L2CR_L2CLK, ~0, " at" }, | | 182 | { L2CR_L2CLK, ~0, " at" }, |
183 | { L2CR_L2CLK, L2CLK_10, " 1:1" }, | | 183 | { L2CR_L2CLK, L2CLK_10, " 1:1" }, |
184 | { L2CR_L2CLK, L2CLK_15, " 1.5:1" }, | | 184 | { L2CR_L2CLK, L2CLK_15, " 1.5:1" }, |
185 | { L2CR_L2CLK, L2CLK_20, " 2:1" }, | | 185 | { L2CR_L2CLK, L2CLK_20, " 2:1" }, |
186 | { L2CR_L2CLK, L2CLK_25, " 2.5:1" }, | | 186 | { L2CR_L2CLK, L2CLK_25, " 2.5:1" }, |
187 | { L2CR_L2CLK, L2CLK_30, " 3:1" }, | | 187 | { L2CR_L2CLK, L2CLK_30, " 3:1" }, |
188 | { L2CR_L2CLK, L2CLK_35, " 3.5:1" }, | | 188 | { L2CR_L2CLK, L2CLK_35, " 3.5:1" }, |
189 | { L2CR_L2CLK, L2CLK_40, " 4:1" }, | | 189 | { L2CR_L2CLK, L2CLK_40, " 4:1" }, |
190 | { L2CR_L2CLK, ~0, " ratio" }, | | 190 | { L2CR_L2CLK, ~0, " ratio" }, |
191 | { 0, 0, NULL } | | 191 | { 0, 0, NULL } |
192 | }; | | 192 | }; |
193 | | | 193 | |
194 | static void cpu_fmttab_print(const struct fmttab *, register_t); | | 194 | static void cpu_fmttab_print(const struct fmttab *, register_t); |
195 | | | 195 | |
196 | struct cputab { | | 196 | struct cputab { |
197 | const char name[8]; | | 197 | const char name[8]; |
198 | uint16_t version; | | 198 | uint16_t version; |
199 | uint16_t revfmt; | | 199 | uint16_t revfmt; |
200 | }; | | 200 | }; |
201 | #define REVFMT_MAJMIN 1 /* %u.%u */ | | 201 | #define REVFMT_MAJMIN 1 /* %u.%u */ |
202 | #define REVFMT_HEX 2 /* 0x%04x */ | | 202 | #define REVFMT_HEX 2 /* 0x%04x */ |
203 | #define REVFMT_DEC 3 /* %u */ | | 203 | #define REVFMT_DEC 3 /* %u */ |
204 | static const struct cputab models[] = { | | 204 | static const struct cputab models[] = { |
205 | { "601", MPC601, REVFMT_DEC }, | | 205 | { "601", MPC601, REVFMT_DEC }, |
206 | { "602", MPC602, REVFMT_DEC }, | | 206 | { "602", MPC602, REVFMT_DEC }, |
207 | { "603", MPC603, REVFMT_MAJMIN }, | | 207 | { "603", MPC603, REVFMT_MAJMIN }, |
208 | { "603e", MPC603e, REVFMT_MAJMIN }, | | 208 | { "603e", MPC603e, REVFMT_MAJMIN }, |
209 | { "603ev", MPC603ev, REVFMT_MAJMIN }, | | 209 | { "603ev", MPC603ev, REVFMT_MAJMIN }, |
210 | { "G2", MPCG2, REVFMT_MAJMIN }, | | 210 | { "G2", MPCG2, REVFMT_MAJMIN }, |
211 | { "604", MPC604, REVFMT_MAJMIN }, | | 211 | { "604", MPC604, REVFMT_MAJMIN }, |
212 | { "604e", MPC604e, REVFMT_MAJMIN }, | | 212 | { "604e", MPC604e, REVFMT_MAJMIN }, |
213 | { "604ev", MPC604ev, REVFMT_MAJMIN }, | | 213 | { "604ev", MPC604ev, REVFMT_MAJMIN }, |
214 | { "620", MPC620, REVFMT_HEX }, | | 214 | { "620", MPC620, REVFMT_HEX }, |
215 | { "750", MPC750, REVFMT_MAJMIN }, | | 215 | { "750", MPC750, REVFMT_MAJMIN }, |
216 | { "750FX", IBM750FX, REVFMT_MAJMIN }, | | 216 | { "750FX", IBM750FX, REVFMT_MAJMIN }, |
217 | { "750GX", IBM750GX, REVFMT_MAJMIN }, | | 217 | { "750GX", IBM750GX, REVFMT_MAJMIN }, |
218 | { "7400", MPC7400, REVFMT_MAJMIN }, | | 218 | { "7400", MPC7400, REVFMT_MAJMIN }, |
219 | { "7410", MPC7410, REVFMT_MAJMIN }, | | 219 | { "7410", MPC7410, REVFMT_MAJMIN }, |
220 | { "7450", MPC7450, REVFMT_MAJMIN }, | | 220 | { "7450", MPC7450, REVFMT_MAJMIN }, |
221 | { "7455", MPC7455, REVFMT_MAJMIN }, | | 221 | { "7455", MPC7455, REVFMT_MAJMIN }, |
222 | { "7457", MPC7457, REVFMT_MAJMIN }, | | 222 | { "7457", MPC7457, REVFMT_MAJMIN }, |
223 | { "7447A", MPC7447A, REVFMT_MAJMIN }, | | 223 | { "7447A", MPC7447A, REVFMT_MAJMIN }, |
224 | { "7448", MPC7448, REVFMT_MAJMIN }, | | 224 | { "7448", MPC7448, REVFMT_MAJMIN }, |
225 | { "8240", MPC8240, REVFMT_MAJMIN }, | | 225 | { "8240", MPC8240, REVFMT_MAJMIN }, |
226 | { "8245", MPC8245, REVFMT_MAJMIN }, | | 226 | { "8245", MPC8245, REVFMT_MAJMIN }, |
227 | { "970", IBM970, REVFMT_MAJMIN }, | | 227 | { "970", IBM970, REVFMT_MAJMIN }, |
228 | { "970FX", IBM970FX, REVFMT_MAJMIN }, | | 228 | { "970FX", IBM970FX, REVFMT_MAJMIN }, |
229 | { "970MP", IBM970MP, REVFMT_MAJMIN }, | | 229 | { "970MP", IBM970MP, REVFMT_MAJMIN }, |
230 | { "POWER3II", IBMPOWER3II, REVFMT_MAJMIN }, | | 230 | { "POWER3II", IBMPOWER3II, REVFMT_MAJMIN }, |
231 | { "", 0, REVFMT_HEX } | | 231 | { "", 0, REVFMT_HEX } |
232 | }; | | 232 | }; |
233 | | | 233 | |
234 | #ifdef MULTIPROCESSOR | | 234 | #ifdef MULTIPROCESSOR |
235 | struct cpu_info cpu_info[CPU_MAXNUM] = { | | 235 | struct cpu_info cpu_info[CPU_MAXNUM] = { |
236 | [0] = { | | 236 | [0] = { |
237 | .ci_curlwp = &lwp0, | | 237 | .ci_curlwp = &lwp0, |
238 | }, | | 238 | }, |
239 | }; | | 239 | }; |
240 | volatile struct cpu_hatch_data *cpu_hatch_data; | | 240 | volatile struct cpu_hatch_data *cpu_hatch_data; |
241 | volatile int cpu_hatch_stack; | | 241 | volatile int cpu_hatch_stack; |
242 | #define HATCH_STACK_SIZE 0x1000 | | 242 | #define HATCH_STACK_SIZE 0x1000 |
243 | extern int ticks_per_intr; | | 243 | extern int ticks_per_intr; |
244 | #include <powerpc/oea/bat.h> | | 244 | #include <powerpc/oea/bat.h> |
245 | #include <powerpc/pic/picvar.h> | | 245 | #include <powerpc/pic/picvar.h> |
246 | #include <powerpc/pic/ipivar.h> | | 246 | #include <powerpc/pic/ipivar.h> |
247 | extern struct bat battable[]; | | 247 | extern struct bat battable[]; |
248 | #else | | 248 | #else |
249 | struct cpu_info cpu_info[1] = { | | 249 | struct cpu_info cpu_info[1] = { |
250 | [0] = { | | 250 | [0] = { |
251 | .ci_curlwp = &lwp0, | | 251 | .ci_curlwp = &lwp0, |
252 | }, | | 252 | }, |
253 | }; | | 253 | }; |
254 | #endif /*MULTIPROCESSOR*/ | | 254 | #endif /*MULTIPROCESSOR*/ |
255 | | | 255 | |
256 | int cpu_altivec; | | 256 | int cpu_altivec; |
257 | register_t cpu_psluserset; | | 257 | register_t cpu_psluserset; |
258 | register_t cpu_pslusermod; | | 258 | register_t cpu_pslusermod; |
259 | register_t cpu_pslusermask = 0xffff; | | 259 | register_t cpu_pslusermask = 0xffff; |
260 | | | 260 | |
261 | /* This is to be called from locore.S, and nowhere else. */ | | 261 | /* This is to be called from locore.S, and nowhere else. */ |
262 | | | 262 | |
263 | void | | 263 | void |
264 | cpu_model_init(void) | | 264 | cpu_model_init(void) |
265 | { | | 265 | { |
266 | u_int pvr, vers; | | 266 | u_int pvr, vers; |
267 | | | 267 | |
268 | pvr = mfpvr(); | | 268 | pvr = mfpvr(); |
269 | vers = pvr >> 16; | | 269 | vers = pvr >> 16; |
270 | | | 270 | |
271 | oeacpufeat = 0; | | 271 | oeacpufeat = 0; |
272 | | | 272 | |
273 | if ((vers >= IBMRS64II && vers <= IBM970GX) || vers == MPC620 || | | 273 | if ((vers >= IBMRS64II && vers <= IBM970GX) || vers == MPC620 || |
274 | vers == IBMCELL || vers == IBMPOWER6P5) { | | 274 | vers == IBMCELL || vers == IBMPOWER6P5) { |
275 | oeacpufeat |= OEACPU_64; | | 275 | oeacpufeat |= OEACPU_64; |
276 | oeacpufeat |= OEACPU_64_BRIDGE; | | 276 | oeacpufeat |= OEACPU_64_BRIDGE; |
277 | oeacpufeat |= OEACPU_NOBAT; | | 277 | oeacpufeat |= OEACPU_NOBAT; |
278 | | | 278 | |
279 | } else if (vers == MPC601) { | | 279 | } else if (vers == MPC601) { |
280 | oeacpufeat |= OEACPU_601; | | 280 | oeacpufeat |= OEACPU_601; |
281 | | | 281 | |
282 | } else if (MPC745X_P(vers)) { | | 282 | } else if (MPC745X_P(vers)) { |
283 | register_t hid1 = mfspr(SPR_HID1); | | 283 | register_t hid1 = mfspr(SPR_HID1); |
284 | | | 284 | |
285 | if (vers != MPC7450) { | | 285 | if (vers != MPC7450) { |
286 | register_t hid0 = mfspr(SPR_HID0); | | 286 | register_t hid0 = mfspr(SPR_HID0); |
287 | | | 287 | |
288 | /* Enable more SPRG registers */ | | 288 | /* Enable more SPRG registers */ |
289 | oeacpufeat |= OEACPU_HIGHSPRG; | | 289 | oeacpufeat |= OEACPU_HIGHSPRG; |
290 | | | 290 | |
291 | /* Enable more BAT registers */ | | 291 | /* Enable more BAT registers */ |
292 | oeacpufeat |= OEACPU_HIGHBAT; | | 292 | oeacpufeat |= OEACPU_HIGHBAT; |
293 | hid0 |= HID0_HIGH_BAT_EN; | | 293 | hid0 |= HID0_HIGH_BAT_EN; |
294 | | | 294 | |
295 | /* Enable larger BAT registers */ | | 295 | /* Enable larger BAT registers */ |
296 | oeacpufeat |= OEACPU_XBSEN; | | 296 | oeacpufeat |= OEACPU_XBSEN; |
297 | hid0 |= HID0_XBSEN; | | 297 | hid0 |= HID0_XBSEN; |
298 | | | 298 | |
299 | mtspr(SPR_HID0, hid0); | | 299 | mtspr(SPR_HID0, hid0); |
300 | __asm volatile("sync;isync"); | | 300 | __asm volatile("sync;isync"); |
301 | } | | 301 | } |
302 | | | 302 | |
303 | /* Enable address broadcasting for MP systems */ | | 303 | /* Enable address broadcasting for MP systems */ |
304 | hid1 |= HID1_SYNCBE | HID1_ABE; | | 304 | hid1 |= HID1_SYNCBE | HID1_ABE; |
305 | | | 305 | |
306 | mtspr(SPR_HID1, hid1); | | 306 | mtspr(SPR_HID1, hid1); |
307 | __asm volatile("sync;isync"); | | 307 | __asm volatile("sync;isync"); |
308 | | | 308 | |
309 | } else if (vers == IBM750FX || vers == IBM750GX) { | | 309 | } else if (vers == IBM750FX || vers == IBM750GX) { |
310 | oeacpufeat |= OEACPU_HIGHBAT; | | 310 | oeacpufeat |= OEACPU_HIGHBAT; |
311 | } | | 311 | } |
312 | } | | 312 | } |
313 | | | 313 | |
314 | void | | 314 | void |
315 | cpu_fmttab_print(const struct fmttab *fmt, register_t data) | | 315 | cpu_fmttab_print(const struct fmttab *fmt, register_t data) |
316 | { | | 316 | { |
317 | for (; fmt->fmt_mask != 0 || fmt->fmt_value != 0; fmt++) { | | 317 | for (; fmt->fmt_mask != 0 || fmt->fmt_value != 0; fmt++) { |
318 | if ((~fmt->fmt_mask & fmt->fmt_value) != 0 || | | 318 | if ((~fmt->fmt_mask & fmt->fmt_value) != 0 || |
319 | (data & fmt->fmt_mask) == fmt->fmt_value) | | 319 | (data & fmt->fmt_mask) == fmt->fmt_value) |
320 | aprint_normal("%s", fmt->fmt_string); | | 320 | aprint_normal("%s", fmt->fmt_string); |
321 | } | | 321 | } |
322 | } | | 322 | } |
323 | | | 323 | |
324 | void | | 324 | void |
325 | cpu_idlespin(void) | | 325 | cpu_idlespin(void) |
326 | { | | 326 | { |
327 | register_t msr; | | 327 | register_t msr; |
328 | | | 328 | |
329 | if (powersave <= 0) | | 329 | if (powersave <= 0) |
330 | return; | | 330 | return; |
331 | | | 331 | |
332 | __asm volatile( | | 332 | __asm volatile( |
333 | #if defined(_ARCH_PPC64) || defined (PPC_OEA64_BRIDGE) | | 333 | #if defined(_ARCH_PPC64) || defined (PPC_OEA64_BRIDGE) |
334 | "dssall;" | | 334 | "dssall;" |
335 | #endif | | 335 | #endif |
336 | "sync;" | | 336 | "sync;" |
337 | "mfmsr %0;" | | 337 | "mfmsr %0;" |
338 | "oris %0,%0,%1@h;" /* enter power saving mode */ | | 338 | "oris %0,%0,%1@h;" /* enter power saving mode */ |
339 | "mtmsr %0;" | | 339 | "mtmsr %0;" |
340 | "isync;" | | 340 | "isync;" |
341 | : "=r"(msr) | | 341 | : "=r"(msr) |
342 | : "J"(PSL_POW)); | | 342 | : "J"(PSL_POW)); |
343 | } | | 343 | } |
344 | | | 344 | |
345 | void | | 345 | void |
346 | cpu_probe_cache(void) | | 346 | cpu_probe_cache(void) |
347 | { | | 347 | { |
348 | u_int assoc, pvr, vers; | | 348 | u_int assoc, pvr, vers; |
349 | | | 349 | |
350 | pvr = mfpvr(); | | 350 | pvr = mfpvr(); |
351 | vers = pvr >> 16; | | 351 | vers = pvr >> 16; |
352 | | | 352 | |
353 | | | 353 | |
354 | /* Presently common across almost all implementations. */ | | 354 | /* Presently common across almost all implementations. */ |
355 | curcpu()->ci_ci.dcache_line_size = 32; | | 355 | curcpu()->ci_ci.dcache_line_size = 32; |
356 | curcpu()->ci_ci.icache_line_size = 32; | | 356 | curcpu()->ci_ci.icache_line_size = 32; |
357 | | | 357 | |
358 | | | 358 | |
359 | switch (vers) { | | 359 | switch (vers) { |
360 | #define K *1024 | | 360 | #define K *1024 |
361 | case IBM750FX: | | 361 | case IBM750FX: |
362 | case IBM750GX: | | 362 | case IBM750GX: |
363 | case MPC601: | | 363 | case MPC601: |
364 | case MPC750: | | 364 | case MPC750: |
365 | case MPC7400: | | 365 | case MPC7400: |
366 | case MPC7447A: | | 366 | case MPC7447A: |
367 | case MPC7448: | | 367 | case MPC7448: |
368 | case MPC7450: | | 368 | case MPC7450: |
369 | case MPC7455: | | 369 | case MPC7455: |
370 | case MPC7457: | | 370 | case MPC7457: |
371 | curcpu()->ci_ci.dcache_size = 32 K; | | 371 | curcpu()->ci_ci.dcache_size = 32 K; |
372 | curcpu()->ci_ci.icache_size = 32 K; | | 372 | curcpu()->ci_ci.icache_size = 32 K; |
373 | assoc = 8; | | 373 | assoc = 8; |
374 | break; | | 374 | break; |
375 | case MPC603: | | 375 | case MPC603: |
376 | curcpu()->ci_ci.dcache_size = 8 K; | | 376 | curcpu()->ci_ci.dcache_size = 8 K; |
377 | curcpu()->ci_ci.icache_size = 8 K; | | 377 | curcpu()->ci_ci.icache_size = 8 K; |
378 | assoc = 2; | | 378 | assoc = 2; |
379 | break; | | 379 | break; |
380 | case MPC603e: | | 380 | case MPC603e: |
381 | case MPC603ev: | | 381 | case MPC603ev: |
382 | case MPC604: | | 382 | case MPC604: |
383 | case MPC8240: | | 383 | case MPC8240: |
384 | case MPC8245: | | 384 | case MPC8245: |
385 | case MPCG2: | | 385 | case MPCG2: |
386 | curcpu()->ci_ci.dcache_size = 16 K; | | 386 | curcpu()->ci_ci.dcache_size = 16 K; |
387 | curcpu()->ci_ci.icache_size = 16 K; | | 387 | curcpu()->ci_ci.icache_size = 16 K; |
388 | assoc = 4; | | 388 | assoc = 4; |
389 | break; | | 389 | break; |
390 | case MPC604e: | | 390 | case MPC604e: |
391 | case MPC604ev: | | 391 | case MPC604ev: |
392 | curcpu()->ci_ci.dcache_size = 32 K; | | 392 | curcpu()->ci_ci.dcache_size = 32 K; |
393 | curcpu()->ci_ci.icache_size = 32 K; | | 393 | curcpu()->ci_ci.icache_size = 32 K; |
394 | assoc = 4; | | 394 | assoc = 4; |
395 | break; | | 395 | break; |
396 | case IBMPOWER3II: | | 396 | case IBMPOWER3II: |
397 | curcpu()->ci_ci.dcache_size = 64 K; | | 397 | curcpu()->ci_ci.dcache_size = 64 K; |
398 | curcpu()->ci_ci.icache_size = 32 K; | | 398 | curcpu()->ci_ci.icache_size = 32 K; |
399 | curcpu()->ci_ci.dcache_line_size = 128; | | 399 | curcpu()->ci_ci.dcache_line_size = 128; |
400 | curcpu()->ci_ci.icache_line_size = 128; | | 400 | curcpu()->ci_ci.icache_line_size = 128; |
401 | assoc = 128; /* not a typo */ | | 401 | assoc = 128; /* not a typo */ |
402 | break; | | 402 | break; |
403 | case IBM970: | | 403 | case IBM970: |
404 | case IBM970FX: | | 404 | case IBM970FX: |
405 | case IBM970MP: | | 405 | case IBM970MP: |
406 | curcpu()->ci_ci.dcache_size = 32 K; | | 406 | curcpu()->ci_ci.dcache_size = 32 K; |
407 | curcpu()->ci_ci.icache_size = 64 K; | | 407 | curcpu()->ci_ci.icache_size = 64 K; |
408 | curcpu()->ci_ci.dcache_line_size = 128; | | 408 | curcpu()->ci_ci.dcache_line_size = 128; |
409 | curcpu()->ci_ci.icache_line_size = 128; | | 409 | curcpu()->ci_ci.icache_line_size = 128; |
410 | assoc = 2; | | 410 | assoc = 2; |
411 | break; | | 411 | break; |
412 | | | 412 | |
413 | default: | | 413 | default: |
414 | curcpu()->ci_ci.dcache_size = PAGE_SIZE; | | 414 | curcpu()->ci_ci.dcache_size = PAGE_SIZE; |
415 | curcpu()->ci_ci.icache_size = PAGE_SIZE; | | 415 | curcpu()->ci_ci.icache_size = PAGE_SIZE; |
416 | assoc = 1; | | 416 | assoc = 1; |
417 | #undef K | | 417 | #undef K |
418 | } | | 418 | } |
419 | | | 419 | |
420 | /* | | 420 | /* |
421 | * Possibly recolor. | | 421 | * Possibly recolor. |
422 | */ | | 422 | */ |
423 | uvm_page_recolor(atop(curcpu()->ci_ci.dcache_size / assoc)); | | 423 | uvm_page_recolor(atop(curcpu()->ci_ci.dcache_size / assoc)); |
424 | } | | 424 | } |
425 | | | 425 | |
426 | struct cpu_info * | | 426 | struct cpu_info * |
427 | cpu_attach_common(device_t self, int id) | | 427 | cpu_attach_common(device_t self, int id) |
428 | { | | 428 | { |
429 | struct cpu_info *ci; | | 429 | struct cpu_info *ci; |
430 | u_int pvr, vers; | | 430 | u_int pvr, vers; |
431 | | | 431 | |
432 | ci = &cpu_info[id]; | | 432 | ci = &cpu_info[id]; |
433 | #ifndef MULTIPROCESSOR | | 433 | #ifndef MULTIPROCESSOR |
434 | /* | | 434 | /* |
435 | * If this isn't the primary CPU, print an error message | | 435 | * If this isn't the primary CPU, print an error message |
436 | * and just bail out. | | 436 | * and just bail out. |
437 | */ | | 437 | */ |
438 | if (id != 0) { | | 438 | if (id != 0) { |
439 | aprint_naive("\n"); | | 439 | aprint_naive("\n"); |
440 | aprint_normal(": ID %d\n", id); | | 440 | aprint_normal(": ID %d\n", id); |
441 | aprint_normal_dev(self, | | 441 | aprint_normal_dev(self, |
442 | "processor off-line; " | | 442 | "processor off-line; " |
443 | "multiprocessor support not present in kernel\n"); | | 443 | "multiprocessor support not present in kernel\n"); |
444 | return (NULL); | | 444 | return (NULL); |
445 | } | | 445 | } |
446 | #endif | | 446 | #endif |
447 | | | 447 | |
448 | ci->ci_cpuid = id; | | 448 | ci->ci_cpuid = id; |
449 | ci->ci_idepth = -1; | | 449 | ci->ci_idepth = -1; |
450 | ci->ci_dev = self; | | 450 | ci->ci_dev = self; |
451 | ci->ci_idlespin = cpu_idlespin; | | 451 | ci->ci_idlespin = cpu_idlespin; |
452 | | | 452 | |
453 | pvr = mfpvr(); | | 453 | pvr = mfpvr(); |
454 | vers = (pvr >> 16) & 0xffff; | | 454 | vers = (pvr >> 16) & 0xffff; |
455 | | | 455 | |
456 | switch (id) { | | 456 | switch (id) { |
457 | case 0: | | 457 | case 0: |
458 | /* load my cpu_number to PIR */ | | 458 | /* load my cpu_number to PIR */ |
459 | switch (vers) { | | 459 | switch (vers) { |
460 | case MPC601: | | 460 | case MPC601: |
461 | case MPC604: | | 461 | case MPC604: |
462 | case MPC604e: | | 462 | case MPC604e: |
463 | case MPC604ev: | | 463 | case MPC604ev: |
464 | case MPC7400: | | 464 | case MPC7400: |
465 | case MPC7410: | | 465 | case MPC7410: |
466 | case MPC7447A: | | 466 | case MPC7447A: |
467 | case MPC7448: | | 467 | case MPC7448: |
468 | case MPC7450: | | 468 | case MPC7450: |
469 | case MPC7455: | | 469 | case MPC7455: |
470 | case MPC7457: | | 470 | case MPC7457: |
471 | mtspr(SPR_PIR, id); | | 471 | mtspr(SPR_PIR, id); |
472 | } | | 472 | } |
473 | cpu_setup(self, ci); | | 473 | cpu_setup(self, ci); |
474 | break; | | 474 | break; |
475 | default: | | 475 | default: |
476 | aprint_naive("\n"); | | 476 | aprint_naive("\n"); |
477 | if (id >= CPU_MAXNUM) { | | 477 | if (id >= CPU_MAXNUM) { |
478 | aprint_normal(": more than %d cpus?\n", CPU_MAXNUM); | | 478 | aprint_normal(": more than %d cpus?\n", CPU_MAXNUM); |
479 | panic("cpuattach"); | | 479 | panic("cpuattach"); |
480 | } | | 480 | } |
481 | #ifndef MULTIPROCESSOR | | 481 | #ifndef MULTIPROCESSOR |
482 | aprint_normal(" not configured\n"); | | 482 | aprint_normal(" not configured\n"); |
483 | return NULL; | | 483 | return NULL; |
484 | #else | | 484 | #else |
485 | mi_cpu_attach(ci); | | 485 | mi_cpu_attach(ci); |
486 | break; | | 486 | break; |
487 | #endif | | 487 | #endif |
488 | } | | 488 | } |
489 | return (ci); | | 489 | return (ci); |
490 | } | | 490 | } |
491 | | | 491 | |
492 | void | | 492 | void |
493 | cpu_setup(device_t self, struct cpu_info *ci) | | 493 | cpu_setup(device_t self, struct cpu_info *ci) |
494 | { | | 494 | { |
495 | u_int pvr, vers; | | 495 | u_int pvr, vers; |
496 | const char * const xname = device_xname(self); | | 496 | const char * const xname = device_xname(self); |
497 | const char *bitmask; | | 497 | const char *bitmask; |
498 | char hidbuf[128]; | | 498 | char hidbuf[128]; |
499 | char model[80]; | | 499 | char model[80]; |
500 | #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) | | 500 | #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) |
501 | char hidbuf_u[128]; | | 501 | char hidbuf_u[128]; |
502 | const char *bitmasku = NULL; | | 502 | const char *bitmasku = NULL; |
503 | volatile uint64_t hid64_0, hid64_0_save; | | 503 | volatile uint64_t hid64_0, hid64_0_save; |
504 | #endif | | 504 | #endif |
505 | #if !defined(_ARCH_PPC64) | | 505 | #if !defined(_ARCH_PPC64) |
506 | register_t hid0 = 0, hid0_save = 0; | | 506 | register_t hid0 = 0, hid0_save = 0; |
507 | #endif | | 507 | #endif |
508 | | | 508 | |
509 | pvr = mfpvr(); | | 509 | pvr = mfpvr(); |
510 | vers = (pvr >> 16) & 0xffff; | | 510 | vers = (pvr >> 16) & 0xffff; |
511 | | | 511 | |
512 | cpu_identify(model, sizeof(model)); | | 512 | cpu_identify(model, sizeof(model)); |
513 | aprint_naive("\n"); | | 513 | aprint_naive("\n"); |
514 | aprint_normal(": %s, ID %d%s\n", model, cpu_number(), | | 514 | aprint_normal(": %s, ID %d%s\n", model, cpu_number(), |
515 | cpu_number() == 0 ? " (primary)" : ""); | | 515 | cpu_number() == 0 ? " (primary)" : ""); |
516 | | | 516 | |
517 | /* set the cpu number */ | | 517 | /* set the cpu number */ |
518 | ci->ci_cpuid = cpu_number(); | | 518 | ci->ci_cpuid = cpu_number(); |
519 | #if defined(_ARCH_PPC64) | | 519 | #if defined(_ARCH_PPC64) |
520 | __asm volatile("mfspr %0,%1" : "=r"(hid64_0) : "K"(SPR_HID0)); | | 520 | __asm volatile("mfspr %0,%1" : "=r"(hid64_0) : "K"(SPR_HID0)); |
521 | hid64_0_save = hid64_0; | | 521 | hid64_0_save = hid64_0; |
522 | #else | | 522 | #else |
523 | #if defined(PPC_OEA64_BRIDGE) | | 523 | #if defined(PPC_OEA64_BRIDGE) |
524 | if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) | | 524 | if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) |
525 | hid64_0_save = hid64_0 = mfspr(SPR_HID0); | | 525 | hid64_0_save = hid64_0 = mfspr(SPR_HID0); |
526 | else | | 526 | else |
527 | #endif | | 527 | #endif |
528 | hid0_save = hid0 = mfspr(SPR_HID0); | | 528 | hid0_save = hid0 = mfspr(SPR_HID0); |
529 | #endif | | 529 | #endif |
530 | | | 530 | |
531 | | | 531 | |
532 | cpu_probe_cache(); | | 532 | cpu_probe_cache(); |
533 | | | 533 | |
534 | /* | | 534 | /* |
535 | * Configure power-saving mode. | | 535 | * Configure power-saving mode. |
536 | */ | | 536 | */ |
537 | switch (vers) { | | 537 | switch (vers) { |
538 | #if !defined(_ARCH_PPC64) | | 538 | #if !defined(_ARCH_PPC64) |
539 | case MPC604: | | 539 | case MPC604: |
540 | case MPC604e: | | 540 | case MPC604e: |
541 | case MPC604ev: | | 541 | case MPC604ev: |
542 | /* | | 542 | /* |
543 | * Do not have HID0 support settings, but can support | | 543 | * Do not have HID0 support settings, but can support |
544 | * MSR[POW] off | | 544 | * MSR[POW] off |
545 | */ | | 545 | */ |
546 | powersave = 1; | | 546 | powersave = 1; |
547 | break; | | 547 | break; |
548 | | | 548 | |
549 | case MPC603: | | 549 | case MPC603: |
550 | case MPC603e: | | 550 | case MPC603e: |
551 | case MPC603ev: | | 551 | case MPC603ev: |
552 | case MPC7400: | | 552 | case MPC7400: |
553 | case MPC7410: | | 553 | case MPC7410: |
554 | case MPC8240: | | 554 | case MPC8240: |
555 | case MPC8245: | | 555 | case MPC8245: |
556 | case MPCG2: | | 556 | case MPCG2: |
557 | /* Select DOZE mode. */ | | 557 | /* Select DOZE mode. */ |
558 | hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); | | 558 | hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); |
559 | hid0 |= HID0_DOZE | HID0_DPM; | | 559 | hid0 |= HID0_DOZE | HID0_DPM; |
560 | powersave = 1; | | 560 | powersave = 1; |
561 | break; | | 561 | break; |
562 | | | 562 | |
563 | case MPC750: | | 563 | case MPC750: |
564 | case IBM750FX: | | 564 | case IBM750FX: |
565 | case IBM750GX: | | 565 | case IBM750GX: |
566 | /* Select NAP mode. */ | | 566 | /* Select NAP mode. */ |
567 | hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); | | 567 | hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); |
568 | hid0 |= HID0_NAP | HID0_DPM; | | 568 | hid0 |= HID0_NAP | HID0_DPM; |
569 | powersave = 1; | | 569 | powersave = 1; |
570 | break; | | 570 | break; |
571 | | | 571 | |
572 | case MPC7447A: | | 572 | case MPC7447A: |
573 | case MPC7448: | | 573 | case MPC7448: |
574 | case MPC7457: | | 574 | case MPC7457: |
575 | case MPC7455: | | 575 | case MPC7455: |
576 | case MPC7450: | | 576 | case MPC7450: |
577 | /* Enable the 7450 branch caches */ | | 577 | /* Enable the 7450 branch caches */ |
578 | hid0 |= HID0_SGE | HID0_BTIC; | | 578 | hid0 |= HID0_SGE | HID0_BTIC; |
579 | hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; | | 579 | hid0 |= HID0_LRSTK | HID0_FOLD | HID0_BHT; |
580 | /* Disable BTIC on 7450 Rev 2.0 or earlier */ | | 580 | /* Disable BTIC on 7450 Rev 2.0 or earlier */ |
581 | if (vers == MPC7450 && (pvr & 0xFFFF) <= 0x0200) | | 581 | if (vers == MPC7450 && (pvr & 0xFFFF) <= 0x0200) |
582 | hid0 &= ~HID0_BTIC; | | 582 | hid0 &= ~HID0_BTIC; |
583 | /* Select NAP mode. */ | | 583 | /* Select NAP mode. */ |
584 | hid0 &= ~HID0_SLEEP; | | 584 | hid0 &= ~HID0_SLEEP; |
585 | hid0 |= HID0_NAP | HID0_DPM; | | 585 | hid0 |= HID0_NAP | HID0_DPM; |
586 | powersave = 1; | | 586 | powersave = 1; |
587 | break; | | 587 | break; |
588 | #endif | | 588 | #endif |
589 | | | 589 | |
590 | case IBM970: | | 590 | case IBM970: |
591 | case IBM970FX: | | 591 | case IBM970FX: |
592 | case IBM970MP: | | 592 | case IBM970MP: |
593 | #if defined(_ARCH_PPC64) || defined (PPC_OEA64_BRIDGE) | | 593 | #if defined(_ARCH_PPC64) || defined (PPC_OEA64_BRIDGE) |
594 | #if !defined(_ARCH_PPC64) | | 594 | #if !defined(_ARCH_PPC64) |
595 | KASSERT((oeacpufeat & OEACPU_64_BRIDGE) != 0); | | 595 | KASSERT((oeacpufeat & OEACPU_64_BRIDGE) != 0); |
596 | #endif | | 596 | #endif |
597 | hid64_0 &= ~(HID0_64_DOZE | HID0_64_NAP | HID0_64_DEEPNAP); | | 597 | hid64_0 &= ~(HID0_64_DOZE | HID0_64_NAP | HID0_64_DEEPNAP); |
598 | hid64_0 |= HID0_64_NAP | HID0_64_DPM | HID0_64_EX_TBEN | | | 598 | hid64_0 |= HID0_64_NAP | HID0_64_DPM | HID0_64_EX_TBEN | |
599 | HID0_64_TB_CTRL | HID0_64_EN_MCHK; | | 599 | HID0_64_TB_CTRL | HID0_64_EN_MCHK; |
600 | powersave = 1; | | 600 | powersave = 1; |
601 | break; | | 601 | break; |
602 | #endif | | 602 | #endif |
603 | case IBMPOWER3II: | | 603 | case IBMPOWER3II: |
604 | default: | | 604 | default: |
605 | /* No power-saving mode is available. */ ; | | 605 | /* No power-saving mode is available. */ ; |
606 | } | | 606 | } |
607 | | | 607 | |
608 | #ifdef NAPMODE | | 608 | #ifdef NAPMODE |
609 | switch (vers) { | | 609 | switch (vers) { |
610 | case IBM750FX: | | 610 | case IBM750FX: |
611 | case IBM750GX: | | 611 | case IBM750GX: |
612 | case MPC750: | | 612 | case MPC750: |
613 | case MPC7400: | | 613 | case MPC7400: |
614 | /* Select NAP mode. */ | | 614 | /* Select NAP mode. */ |
615 | hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); | | 615 | hid0 &= ~(HID0_DOZE | HID0_NAP | HID0_SLEEP); |
616 | hid0 |= HID0_NAP; | | 616 | hid0 |= HID0_NAP; |
617 | break; | | 617 | break; |
618 | } | | 618 | } |
619 | #endif | | 619 | #endif |
620 | | | 620 | |
621 | switch (vers) { | | 621 | switch (vers) { |
622 | case IBM750FX: | | 622 | case IBM750FX: |
623 | case IBM750GX: | | 623 | case IBM750GX: |
624 | case MPC750: | | 624 | case MPC750: |
625 | hid0 &= ~HID0_DBP; /* XXX correct? */ | | 625 | hid0 &= ~HID0_DBP; /* XXX correct? */ |
626 | hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; | | 626 | hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; |
627 | break; | | 627 | break; |
628 | | | 628 | |
629 | case MPC7400: | | 629 | case MPC7400: |
630 | case MPC7410: | | 630 | case MPC7410: |
631 | hid0 &= ~HID0_SPD; | | 631 | hid0 &= ~HID0_SPD; |
632 | hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; | | 632 | hid0 |= HID0_EMCP | HID0_BTIC | HID0_SGE | HID0_BHT; |
633 | hid0 |= HID0_EIEC; | | 633 | hid0 |= HID0_EIEC; |
634 | break; | | 634 | break; |
635 | } | | 635 | } |
636 | | | 636 | |
637 | /* | | 637 | /* |
638 | * according to the 603e manual this is necessary for an external L2 | | 638 | * according to the 603e manual this is necessary for an external L2 |
639 | * cache to work properly | | 639 | * cache to work properly |
640 | */ | | 640 | */ |
641 | switch (vers) { | | 641 | switch (vers) { |
642 | case MPC603e: | | 642 | case MPC603e: |
643 | hid0 |= HID0_ABE; | | 643 | hid0 |= HID0_ABE; |
644 | } | | 644 | } |
645 | | | 645 | |
646 | #if defined(_ARCH_PPC64) || defined(PPC_OEA64_BRIDGE) | | 646 | #if defined(_ARCH_PPC64) || defined(PPC_OEA64_BRIDGE) |
647 | #if defined(PPC_OEA64_BRIDGE) | | 647 | #if defined(PPC_OEA64_BRIDGE) |
648 | if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) { | | 648 | if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) { |
649 | #endif | | 649 | #endif |
650 | if (hid64_0 != hid64_0_save) { | | 650 | if (hid64_0 != hid64_0_save) { |
651 | mtspr64(SPR_HID0, hid64_0); | | 651 | mtspr64(SPR_HID0, hid64_0); |
652 | } | | 652 | } |
653 | #if defined(PPC_OEA64_BRIDGE) | | 653 | #if defined(PPC_OEA64_BRIDGE) |
654 | } else { | | 654 | } else { |
655 | #endif | | 655 | #endif |
656 | #endif | | 656 | #endif |
657 | | | 657 | |
658 | #if !defined(_ARCH_PPC64) | | 658 | #if !defined(_ARCH_PPC64) |
659 | if (hid0 != hid0_save) { | | 659 | if (hid0 != hid0_save) { |
660 | mtspr(SPR_HID0, hid0); | | 660 | mtspr(SPR_HID0, hid0); |
661 | __asm volatile("sync;isync"); | | 661 | __asm volatile("sync;isync"); |
662 | } | | 662 | } |
663 | #endif | | 663 | #endif |
664 | #if defined(PPC_OEA64_BRIDGE) | | 664 | #if defined(PPC_OEA64_BRIDGE) |
665 | } | | 665 | } |
666 | #endif | | 666 | #endif |
667 | | | 667 | |
668 | switch (vers) { | | 668 | switch (vers) { |
669 | case MPC601: | | 669 | case MPC601: |
670 | bitmask = HID0_601_BITMASK; | | 670 | bitmask = HID0_601_BITMASK; |
671 | break; | | 671 | break; |
672 | case MPC7447A: | | 672 | case MPC7447A: |
673 | case MPC7448: | | 673 | case MPC7448: |
674 | case MPC7450: | | 674 | case MPC7450: |
675 | case MPC7455: | | 675 | case MPC7455: |
676 | case MPC7457: | | 676 | case MPC7457: |
677 | bitmask = HID0_7450_BITMASK; | | 677 | bitmask = HID0_7450_BITMASK; |
678 | break; | | 678 | break; |
679 | case IBM970: | | 679 | case IBM970: |
680 | case IBM970FX: | | 680 | case IBM970FX: |
681 | case IBM970MP: | | 681 | case IBM970MP: |
682 | bitmask = HID0_970_BITMASK; | | 682 | bitmask = HID0_970_BITMASK; |
683 | #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) | | 683 | #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) |
684 | bitmasku = HID0_970_BITMASK_U; | | 684 | bitmasku = HID0_970_BITMASK_U; |
685 | #endif | | 685 | #endif |
686 | break; | | 686 | break; |
687 | default: | | 687 | default: |
688 | bitmask = HID0_BITMASK; | | 688 | bitmask = HID0_BITMASK; |
689 | break; | | 689 | break; |
690 | } | | 690 | } |
691 | | | 691 | |
692 | #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) | | 692 | #if defined(PPC_OEA64_BRIDGE) || defined(_ARCH_PPC64) |
693 | if (bitmasku != NULL) { | | 693 | if (bitmasku != NULL) { |
694 | snprintb(hidbuf, sizeof hidbuf, bitmask, hid64_0 & 0xffffffff); | | 694 | snprintb(hidbuf, sizeof hidbuf, bitmask, hid64_0 & 0xffffffff); |
695 | snprintb(hidbuf_u, sizeof hidbuf_u, bitmasku, hid64_0 >> 32); | | 695 | snprintb(hidbuf_u, sizeof hidbuf_u, bitmasku, hid64_0 >> 32); |
696 | aprint_normal_dev(self, "HID0 %s %s, powersave: %d\n", | | 696 | aprint_normal_dev(self, "HID0 %s %s, powersave: %d\n", |
697 | hidbuf_u, hidbuf, powersave); | | 697 | hidbuf_u, hidbuf, powersave); |
698 | } else | | 698 | } else |
699 | #endif | | 699 | #endif |
700 | { | | 700 | { |
701 | snprintb(hidbuf, sizeof hidbuf, bitmask, hid0); | | 701 | snprintb(hidbuf, sizeof hidbuf, bitmask, hid0); |
702 | aprint_normal_dev(self, "HID0 %s, powersave: %d\n", | | 702 | aprint_normal_dev(self, "HID0 %s, powersave: %d\n", |
703 | hidbuf, powersave); | | 703 | hidbuf, powersave); |
704 | } | | 704 | } |
705 | | | 705 | |
706 | ci->ci_khz = 0; | | 706 | ci->ci_khz = 0; |
707 | | | 707 | |
708 | /* | | 708 | /* |
709 | * Display speed and cache configuration. | | 709 | * Display speed and cache configuration. |
710 | */ | | 710 | */ |
711 | switch (vers) { | | 711 | switch (vers) { |
712 | case MPC604: | | 712 | case MPC604: |
713 | case MPC604e: | | 713 | case MPC604e: |
714 | case MPC604ev: | | 714 | case MPC604ev: |
715 | case MPC750: | | 715 | case MPC750: |
716 | case IBM750FX: | | 716 | case IBM750FX: |
717 | case IBM750GX: | | 717 | case IBM750GX: |
718 | case MPC7400: | | 718 | case MPC7400: |
719 | case MPC7410: | | 719 | case MPC7410: |
720 | case MPC7447A: | | 720 | case MPC7447A: |
721 | case MPC7448: | | 721 | case MPC7448: |
722 | case MPC7450: | | 722 | case MPC7450: |
723 | case MPC7455: | | 723 | case MPC7455: |
724 | case MPC7457: | | 724 | case MPC7457: |
725 | aprint_normal_dev(self, ""); | | 725 | aprint_normal_dev(self, ""); |
726 | cpu_probe_speed(ci); | | 726 | cpu_probe_speed(ci); |
727 | aprint_normal("%u.%02u MHz", | | 727 | aprint_normal("%u.%02u MHz", |
728 | ci->ci_khz / 1000, (ci->ci_khz / 10) % 100); | | 728 | ci->ci_khz / 1000, (ci->ci_khz / 10) % 100); |
729 | switch (vers) { | | 729 | switch (vers) { |
730 | case MPC7450: /* 7441 does not have L3! */ | | 730 | case MPC7450: /* 7441 does not have L3! */ |
731 | case MPC7455: /* 7445 does not have L3! */ | | 731 | case MPC7455: /* 7445 does not have L3! */ |
732 | case MPC7457: /* 7447 does not have L3! */ | | 732 | case MPC7457: /* 7447 does not have L3! */ |
733 | cpu_config_l3cr(vers); | | 733 | cpu_config_l3cr(vers); |
734 | break; | | 734 | break; |
735 | case IBM750FX: | | 735 | case IBM750FX: |
736 | case IBM750GX: | | 736 | case IBM750GX: |
737 | case MPC750: | | 737 | case MPC750: |
738 | case MPC7400: | | 738 | case MPC7400: |
739 | case MPC7410: | | 739 | case MPC7410: |
740 | case MPC7447A: | | 740 | case MPC7447A: |
741 | case MPC7448: | | 741 | case MPC7448: |
742 | cpu_config_l2cr(pvr); | | 742 | cpu_config_l2cr(pvr); |
743 | break; | | 743 | break; |
744 | default: | | 744 | default: |
745 | break; | | 745 | break; |
746 | } | | 746 | } |
747 | aprint_normal("\n"); | | 747 | aprint_normal("\n"); |
748 | break; | | 748 | break; |
749 | } | | 749 | } |
750 | | | 750 | |
751 | #if NSYSMON_ENVSYS > 0 | | 751 | #if NSYSMON_ENVSYS > 0 |
752 | /* | | 752 | /* |
753 | * Attach MPC750 temperature sensor to the envsys subsystem. | | 753 | * Attach MPC750 temperature sensor to the envsys subsystem. |
754 | * XXX the 74xx series also has this sensor, but it is not | | 754 | * XXX the 74xx series also has this sensor, but it is not |
755 | * XXX supported by Motorola and may return values that are off by | | 755 | * XXX supported by Motorola and may return values that are off by |
756 | * XXX 35-55 degrees C. | | 756 | * XXX 35-55 degrees C. |
757 | */ | | 757 | */ |
758 | if (vers == MPC750 || vers == IBM750FX || vers == IBM750GX) | | 758 | if (vers == MPC750 || vers == IBM750FX || vers == IBM750GX) |
759 | cpu_tau_setup(ci); | | 759 | cpu_tau_setup(ci); |
760 | #endif | | 760 | #endif |
761 | | | 761 | |
762 | #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE) | | 762 | #if defined(PPC_OEA64) || defined(PPC_OEA64_BRIDGE) |
763 | if (vers == IBM970MP) | | 763 | if (vers == IBM970MP) |
764 | init_scom_speedctl(); | | 764 | init_scom_speedctl(); |
765 | #endif | | 765 | #endif |
766 | | | 766 | |
767 | evcnt_attach_dynamic(&ci->ci_ev_clock, EVCNT_TYPE_INTR, | | 767 | evcnt_attach_dynamic(&ci->ci_ev_clock, EVCNT_TYPE_INTR, |
768 | NULL, xname, "clock"); | | 768 | NULL, xname, "clock"); |
769 | evcnt_attach_dynamic(&ci->ci_ev_traps, EVCNT_TYPE_TRAP, | | 769 | evcnt_attach_dynamic(&ci->ci_ev_traps, EVCNT_TYPE_TRAP, |
770 | NULL, xname, "traps"); | | 770 | NULL, xname, "traps"); |
771 | evcnt_attach_dynamic(&ci->ci_ev_kdsi, EVCNT_TYPE_TRAP, | | 771 | evcnt_attach_dynamic(&ci->ci_ev_kdsi, EVCNT_TYPE_TRAP, |
772 | &ci->ci_ev_traps, xname, "kernel DSI traps"); | | 772 | &ci->ci_ev_traps, xname, "kernel DSI traps"); |
773 | evcnt_attach_dynamic(&ci->ci_ev_udsi, EVCNT_TYPE_TRAP, | | 773 | evcnt_attach_dynamic(&ci->ci_ev_udsi, EVCNT_TYPE_TRAP, |
774 | &ci->ci_ev_traps, xname, "user DSI traps"); | | 774 | &ci->ci_ev_traps, xname, "user DSI traps"); |
775 | evcnt_attach_dynamic(&ci->ci_ev_udsi_fatal, EVCNT_TYPE_TRAP, | | 775 | evcnt_attach_dynamic(&ci->ci_ev_udsi_fatal, EVCNT_TYPE_TRAP, |
776 | &ci->ci_ev_udsi, xname, "user DSI failures"); | | 776 | &ci->ci_ev_udsi, xname, "user DSI failures"); |
777 | evcnt_attach_dynamic(&ci->ci_ev_kisi, EVCNT_TYPE_TRAP, | | 777 | evcnt_attach_dynamic(&ci->ci_ev_kisi, EVCNT_TYPE_TRAP, |
778 | &ci->ci_ev_traps, xname, "kernel ISI traps"); | | 778 | &ci->ci_ev_traps, xname, "kernel ISI traps"); |
779 | evcnt_attach_dynamic(&ci->ci_ev_isi, EVCNT_TYPE_TRAP, | | 779 | evcnt_attach_dynamic(&ci->ci_ev_isi, EVCNT_TYPE_TRAP, |
780 | &ci->ci_ev_traps, xname, "user ISI traps"); | | 780 | &ci->ci_ev_traps, xname, "user ISI traps"); |
781 | evcnt_attach_dynamic(&ci->ci_ev_isi_fatal, EVCNT_TYPE_TRAP, | | 781 | evcnt_attach_dynamic(&ci->ci_ev_isi_fatal, EVCNT_TYPE_TRAP, |
782 | &ci->ci_ev_isi, xname, "user ISI failures"); | | 782 | &ci->ci_ev_isi, xname, "user ISI failures"); |
783 | evcnt_attach_dynamic(&ci->ci_ev_scalls, EVCNT_TYPE_TRAP, | | 783 | evcnt_attach_dynamic(&ci->ci_ev_scalls, EVCNT_TYPE_TRAP, |
784 | &ci->ci_ev_traps, xname, "system call traps"); | | 784 | &ci->ci_ev_traps, xname, "system call traps"); |
785 | evcnt_attach_dynamic(&ci->ci_ev_pgm, EVCNT_TYPE_TRAP, | | 785 | evcnt_attach_dynamic(&ci->ci_ev_pgm, EVCNT_TYPE_TRAP, |
786 | &ci->ci_ev_traps, xname, "PGM traps"); | | 786 | &ci->ci_ev_traps, xname, "PGM traps"); |
787 | evcnt_attach_dynamic(&ci->ci_ev_fpu, EVCNT_TYPE_TRAP, | | 787 | evcnt_attach_dynamic(&ci->ci_ev_fpu, EVCNT_TYPE_TRAP, |
788 | &ci->ci_ev_traps, xname, "FPU unavailable traps"); | | 788 | &ci->ci_ev_traps, xname, "FPU unavailable traps"); |
789 | evcnt_attach_dynamic(&ci->ci_ev_fpusw, EVCNT_TYPE_TRAP, | | 789 | evcnt_attach_dynamic(&ci->ci_ev_fpusw, EVCNT_TYPE_TRAP, |
790 | &ci->ci_ev_fpu, xname, "FPU context switches"); | | 790 | &ci->ci_ev_fpu, xname, "FPU context switches"); |
791 | evcnt_attach_dynamic(&ci->ci_ev_ali, EVCNT_TYPE_TRAP, | | 791 | evcnt_attach_dynamic(&ci->ci_ev_ali, EVCNT_TYPE_TRAP, |
792 | &ci->ci_ev_traps, xname, "user alignment traps"); | | 792 | &ci->ci_ev_traps, xname, "user alignment traps"); |
793 | evcnt_attach_dynamic(&ci->ci_ev_ali_fatal, EVCNT_TYPE_TRAP, | | 793 | evcnt_attach_dynamic(&ci->ci_ev_ali_fatal, EVCNT_TYPE_TRAP, |
794 | &ci->ci_ev_ali, xname, "user alignment traps"); | | 794 | &ci->ci_ev_ali, xname, "user alignment traps"); |
795 | evcnt_attach_dynamic(&ci->ci_ev_umchk, EVCNT_TYPE_TRAP, | | 795 | evcnt_attach_dynamic(&ci->ci_ev_umchk, EVCNT_TYPE_TRAP, |
796 | &ci->ci_ev_umchk, xname, "user MCHK failures"); | | 796 | &ci->ci_ev_umchk, xname, "user MCHK failures"); |
797 | evcnt_attach_dynamic(&ci->ci_ev_vec, EVCNT_TYPE_TRAP, | | 797 | evcnt_attach_dynamic(&ci->ci_ev_vec, EVCNT_TYPE_TRAP, |
798 | &ci->ci_ev_traps, xname, "AltiVec unavailable"); | | 798 | &ci->ci_ev_traps, xname, "AltiVec unavailable"); |
799 | #ifdef ALTIVEC | | 799 | #ifdef ALTIVEC |
800 | if (cpu_altivec) { | | 800 | if (cpu_altivec) { |
801 | evcnt_attach_dynamic(&ci->ci_ev_vecsw, EVCNT_TYPE_TRAP, | | 801 | evcnt_attach_dynamic(&ci->ci_ev_vecsw, EVCNT_TYPE_TRAP, |
802 | &ci->ci_ev_vec, xname, "AltiVec context switches"); | | 802 | &ci->ci_ev_vec, xname, "AltiVec context switches"); |
803 | } | | 803 | } |
804 | #endif | | 804 | #endif |
805 | evcnt_attach_dynamic(&ci->ci_ev_ipi, EVCNT_TYPE_INTR, | | 805 | evcnt_attach_dynamic(&ci->ci_ev_ipi, EVCNT_TYPE_INTR, |
806 | NULL, xname, "IPIs"); | | 806 | NULL, xname, "IPIs"); |
807 | } | | 807 | } |
808 | | | 808 | |
809 | /* | | 809 | /* |
810 | * According to a document labeled "PVR Register Settings": | | 810 | * According to a document labeled "PVR Register Settings": |
811 | ** For integrated microprocessors the PVR register inside the device | | 811 | ** For integrated microprocessors the PVR register inside the device |
812 | ** will identify the version of the microprocessor core. You must also | | 812 | ** will identify the version of the microprocessor core. You must also |
813 | ** read the Device ID, PCI register 02, to identify the part and the | | 813 | ** read the Device ID, PCI register 02, to identify the part and the |
814 | ** Revision ID, PCI register 08, to identify the revision of the | | 814 | ** Revision ID, PCI register 08, to identify the revision of the |
815 | ** integrated microprocessor. | | 815 | ** integrated microprocessor. |
816 | * This apparently applies to 8240/8245/8241, PVR 00810101 and 80811014 | | 816 | * This apparently applies to 8240/8245/8241, PVR 00810101 and 80811014 |
817 | */ | | 817 | */ |
818 | | | 818 | |
819 | void | | 819 | void |
820 | cpu_identify(char *str, size_t len) | | 820 | cpu_identify(char *str, size_t len) |
821 | { | | 821 | { |
822 | u_int pvr, major, minor; | | 822 | u_int pvr, major, minor; |
823 | uint16_t vers, rev, revfmt; | | 823 | uint16_t vers, rev, revfmt; |
824 | const struct cputab *cp; | | 824 | const struct cputab *cp; |
825 | size_t n; | | 825 | size_t n; |
826 | | | 826 | |
827 | pvr = mfpvr(); | | 827 | pvr = mfpvr(); |
828 | vers = pvr >> 16; | | 828 | vers = pvr >> 16; |
829 | rev = pvr; | | 829 | rev = pvr; |
830 | | | 830 | |
831 | switch (vers) { | | 831 | switch (vers) { |
832 | case MPC7410: | | 832 | case MPC7410: |
833 | minor = (pvr >> 0) & 0xff; | | 833 | minor = (pvr >> 0) & 0xff; |
834 | major = minor <= 4 ? 1 : 2; | | 834 | major = minor <= 4 ? 1 : 2; |
835 | break; | | 835 | break; |
836 | case MPCG2: /*XXX see note above */ | | 836 | case MPCG2: /*XXX see note above */ |
837 | major = (pvr >> 4) & 0xf; | | 837 | major = (pvr >> 4) & 0xf; |
838 | minor = (pvr >> 0) & 0xf; | | 838 | minor = (pvr >> 0) & 0xf; |
839 | break; | | 839 | break; |
840 | default: | | 840 | default: |
841 | major = (pvr >> 8) & 0xf; | | 841 | major = (pvr >> 8) & 0xf; |
842 | minor = (pvr >> 0) & 0xf; | | 842 | minor = (pvr >> 0) & 0xf; |
843 | } | | 843 | } |
844 | | | 844 | |
845 | for (cp = models; cp->name[0] != '\0'; cp++) { | | 845 | for (cp = models; cp->name[0] != '\0'; cp++) { |
846 | if (cp->version == vers) | | 846 | if (cp->version == vers) |
847 | break; | | 847 | break; |
848 | } | | 848 | } |
849 | | | 849 | |
850 | if (cpu == -1) | | 850 | if (cpu == -1) |
851 | cpu = vers; | | 851 | cpu = vers; |
852 | | | 852 | |
853 | revfmt = cp->revfmt; | | 853 | revfmt = cp->revfmt; |
854 | if (rev == MPC750 && pvr == 15) { | | 854 | if (rev == MPC750 && pvr == 15) { |
855 | revfmt = REVFMT_HEX; | | 855 | revfmt = REVFMT_HEX; |
856 | } | | 856 | } |
857 | | | 857 | |
858 | if (cp->name[0] != '\0') { | | 858 | if (cp->name[0] != '\0') { |
859 | n = snprintf(str, len, "%s (Revision ", cp->name); | | 859 | n = snprintf(str, len, "%s (Revision ", cp->name); |
860 | } else { | | 860 | } else { |
861 | n = snprintf(str, len, "Version %#x (Revision ", vers); | | 861 | n = snprintf(str, len, "Version %#x (Revision ", vers); |
862 | } | | 862 | } |
863 | if (len > n) { | | 863 | if (len > n) { |
864 | switch (revfmt) { | | 864 | switch (revfmt) { |
865 | case REVFMT_MAJMIN: | | 865 | case REVFMT_MAJMIN: |
866 | snprintf(str + n, len - n, "%u.%u)", major, minor); | | 866 | snprintf(str + n, len - n, "%u.%u)", major, minor); |
867 | break; | | 867 | break; |
868 | case REVFMT_HEX: | | 868 | case REVFMT_HEX: |
869 | snprintf(str + n, len - n, "0x%04x)", rev); | | 869 | snprintf(str + n, len - n, "0x%04x)", rev); |
870 | break; | | 870 | break; |
871 | case REVFMT_DEC: | | 871 | case REVFMT_DEC: |
872 | snprintf(str + n, len - n, "%u)", rev); | | 872 | snprintf(str + n, len - n, "%u)", rev); |
873 | break; | | 873 | break; |
874 | } | | 874 | } |
875 | } | | 875 | } |
876 | } | | 876 | } |
877 | | | 877 | |
878 | #ifdef L2CR_CONFIG | | 878 | #ifdef L2CR_CONFIG |
879 | u_int l2cr_config = L2CR_CONFIG; | | 879 | u_int l2cr_config = L2CR_CONFIG; |
880 | #else | | 880 | #else |
881 | u_int l2cr_config = 0; | | 881 | u_int l2cr_config = 0; |
882 | #endif | | 882 | #endif |
883 | | | 883 | |
884 | #ifdef L3CR_CONFIG | | 884 | #ifdef L3CR_CONFIG |
885 | u_int l3cr_config = L3CR_CONFIG; | | 885 | u_int l3cr_config = L3CR_CONFIG; |
886 | #else | | 886 | #else |
887 | u_int l3cr_config = 0; | | 887 | u_int l3cr_config = 0; |
888 | #endif | | 888 | #endif |
889 | | | 889 | |
890 | void | | 890 | void |
891 | cpu_enable_l2cr(register_t l2cr) | | 891 | cpu_enable_l2cr(register_t l2cr) |
892 | { | | 892 | { |
893 | register_t msr, x; | | 893 | register_t msr, x; |
894 | uint16_t vers; | | 894 | uint16_t vers; |
895 | | | 895 | |
896 | vers = mfpvr() >> 16; | | 896 | vers = mfpvr() >> 16; |
897 | | | 897 | |
898 | /* Disable interrupts and set the cache config bits. */ | | 898 | /* Disable interrupts and set the cache config bits. */ |
899 | msr = mfmsr(); | | 899 | msr = mfmsr(); |
900 | mtmsr(msr & ~PSL_EE); | | 900 | mtmsr(msr & ~PSL_EE); |
901 | #ifdef ALTIVEC | | 901 | #ifdef ALTIVEC |
902 | if (cpu_altivec) | | 902 | if (cpu_altivec) |
903 | __asm volatile("dssall"); | | 903 | __asm volatile("dssall"); |
904 | #endif | | 904 | #endif |
905 | __asm volatile("sync"); | | 905 | __asm volatile("sync"); |
906 | mtspr(SPR_L2CR, l2cr & ~L2CR_L2E); | | 906 | mtspr(SPR_L2CR, l2cr & ~L2CR_L2E); |
907 | __asm volatile("sync"); | | 907 | __asm volatile("sync"); |
908 | | | 908 | |
909 | /* Wait for L2 clock to be stable (640 L2 clocks). */ | | 909 | /* Wait for L2 clock to be stable (640 L2 clocks). */ |
910 | delay(100); | | 910 | delay(100); |
911 | | | 911 | |
912 | /* Invalidate all L2 contents. */ | | 912 | /* Invalidate all L2 contents. */ |
913 | if (MPC745X_P(vers)) { | | 913 | if (MPC745X_P(vers)) { |
914 | mtspr(SPR_L2CR, l2cr | L2CR_L2I); | | 914 | mtspr(SPR_L2CR, l2cr | L2CR_L2I); |
915 | do { | | 915 | do { |
916 | x = mfspr(SPR_L2CR); | | 916 | x = mfspr(SPR_L2CR); |
917 | } while (x & L2CR_L2I); | | 917 | } while (x & L2CR_L2I); |
918 | } else { | | 918 | } else { |
919 | mtspr(SPR_L2CR, l2cr | L2CR_L2I); | | 919 | mtspr(SPR_L2CR, l2cr | L2CR_L2I); |
920 | do { | | 920 | do { |
921 | x = mfspr(SPR_L2CR); | | 921 | x = mfspr(SPR_L2CR); |
922 | } while (x & L2CR_L2IP); | | 922 | } while (x & L2CR_L2IP); |
923 | } | | 923 | } |
924 | /* Enable L2 cache. */ | | 924 | /* Enable L2 cache. */ |
925 | l2cr |= L2CR_L2E; | | 925 | l2cr |= L2CR_L2E; |
926 | mtspr(SPR_L2CR, l2cr); | | 926 | mtspr(SPR_L2CR, l2cr); |
927 | mtmsr(msr); | | 927 | mtmsr(msr); |
928 | } | | 928 | } |
929 | | | 929 | |
930 | void | | 930 | void |
931 | cpu_enable_l3cr(register_t l3cr) | | 931 | cpu_enable_l3cr(register_t l3cr) |
932 | { | | 932 | { |
933 | register_t x; | | 933 | register_t x; |
934 | | | 934 | |
935 | /* By The Book (numbered steps from section 3.7.1.3 of MPC7450UM) */ | | 935 | /* By The Book (numbered steps from section 3.7.1.3 of MPC7450UM) */ |
936 | | | 936 | |
937 | /* | | 937 | /* |
938 | * 1: Set all L3CR bits for final config except L3E, L3I, L3PE, and | | 938 | * 1: Set all L3CR bits for final config except L3E, L3I, L3PE, and |
939 | * L3CLKEN. (also mask off reserved bits in case they were included | | 939 | * L3CLKEN. (also mask off reserved bits in case they were included |
940 | * in L3CR_CONFIG) | | 940 | * in L3CR_CONFIG) |
941 | */ | | 941 | */ |
942 | l3cr &= ~(L3CR_L3E|L3CR_L3I|L3CR_L3PE|L3CR_L3CLKEN|L3CR_RESERVED); | | 942 | l3cr &= ~(L3CR_L3E|L3CR_L3I|L3CR_L3PE|L3CR_L3CLKEN|L3CR_RESERVED); |
943 | mtspr(SPR_L3CR, l3cr); | | 943 | mtspr(SPR_L3CR, l3cr); |
944 | | | 944 | |
945 | /* 2: Set L3CR[5] (otherwise reserved bit) to 1 */ | | 945 | /* 2: Set L3CR[5] (otherwise reserved bit) to 1 */ |
946 | l3cr |= 0x04000000; | | 946 | l3cr |= 0x04000000; |
947 | mtspr(SPR_L3CR, l3cr); | | 947 | mtspr(SPR_L3CR, l3cr); |
948 | | | 948 | |
949 | /* 3: Set L3CLKEN to 1*/ | | 949 | /* 3: Set L3CLKEN to 1*/ |
950 | l3cr |= L3CR_L3CLKEN; | | 950 | l3cr |= L3CR_L3CLKEN; |
951 | mtspr(SPR_L3CR, l3cr); | | 951 | mtspr(SPR_L3CR, l3cr); |
952 | | | 952 | |
953 | /* 4/5: Perform a global cache invalidate (ref section 3.7.3.6) */ | | 953 | /* 4/5: Perform a global cache invalidate (ref section 3.7.3.6) */ |
954 | __asm volatile("dssall;sync"); | | 954 | __asm volatile("dssall;sync"); |
955 | /* L3 cache is already disabled, no need to clear L3E */ | | 955 | /* L3 cache is already disabled, no need to clear L3E */ |
956 | mtspr(SPR_L3CR, l3cr|L3CR_L3I); | | 956 | mtspr(SPR_L3CR, l3cr|L3CR_L3I); |
957 | do { | | 957 | do { |
958 | x = mfspr(SPR_L3CR); | | 958 | x = mfspr(SPR_L3CR); |
959 | } while (x & L3CR_L3I); | | 959 | } while (x & L3CR_L3I); |
960 | | | 960 | |
961 | /* 6: Clear L3CLKEN to 0 */ | | 961 | /* 6: Clear L3CLKEN to 0 */ |
962 | l3cr &= ~L3CR_L3CLKEN; | | 962 | l3cr &= ~L3CR_L3CLKEN; |
963 | mtspr(SPR_L3CR, l3cr); | | 963 | mtspr(SPR_L3CR, l3cr); |
964 | | | 964 | |
965 | /* 7: Perform a 'sync' and wait at least 100 CPU cycles */ | | 965 | /* 7: Perform a 'sync' and wait at least 100 CPU cycles */ |
966 | __asm volatile("sync"); | | 966 | __asm volatile("sync"); |
967 | delay(100); | | 967 | delay(100); |
968 | | | 968 | |
969 | /* 8: Set L3E and L3CLKEN */ | | 969 | /* 8: Set L3E and L3CLKEN */ |
970 | l3cr |= (L3CR_L3E|L3CR_L3CLKEN); | | 970 | l3cr |= (L3CR_L3E|L3CR_L3CLKEN); |
971 | mtspr(SPR_L3CR, l3cr); | | 971 | mtspr(SPR_L3CR, l3cr); |
972 | | | 972 | |
973 | /* 9: Perform a 'sync' and wait at least 100 CPU cycles */ | | 973 | /* 9: Perform a 'sync' and wait at least 100 CPU cycles */ |
974 | __asm volatile("sync"); | | 974 | __asm volatile("sync"); |
975 | delay(100); | | 975 | delay(100); |
976 | } | | 976 | } |
977 | | | 977 | |
978 | void | | 978 | void |
979 | cpu_config_l2cr(int pvr) | | 979 | cpu_config_l2cr(int pvr) |
980 | { | | 980 | { |
981 | register_t l2cr; | | 981 | register_t l2cr; |
982 | u_int vers = (pvr >> 16) & 0xffff; | | 982 | u_int vers = (pvr >> 16) & 0xffff; |
983 | | | 983 | |
984 | l2cr = mfspr(SPR_L2CR); | | 984 | l2cr = mfspr(SPR_L2CR); |
985 | | | 985 | |
986 | /* | | 986 | /* |
987 | * For MP systems, the firmware may only configure the L2 cache | | 987 | * For MP systems, the firmware may only configure the L2 cache |
988 | * on the first CPU. In this case, assume that the other CPUs | | 988 | * on the first CPU. In this case, assume that the other CPUs |
989 | * should use the same value for L2CR. | | 989 | * should use the same value for L2CR. |
990 | */ | | 990 | */ |
991 | if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { | | 991 | if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { |
992 | l2cr_config = l2cr; | | 992 | l2cr_config = l2cr; |
993 | } | | 993 | } |
994 | | | 994 | |
995 | /* | | 995 | /* |
996 | * Configure L2 cache if not enabled. | | 996 | * Configure L2 cache if not enabled. |
997 | */ | | 997 | */ |
998 | if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { | | 998 | if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { |
999 | cpu_enable_l2cr(l2cr_config); | | 999 | cpu_enable_l2cr(l2cr_config); |
1000 | l2cr = mfspr(SPR_L2CR); | | 1000 | l2cr = mfspr(SPR_L2CR); |
1001 | } | | 1001 | } |
1002 | | | 1002 | |
1003 | if ((l2cr & L2CR_L2E) == 0) { | | 1003 | if ((l2cr & L2CR_L2E) == 0) { |
1004 | aprint_normal(" L2 cache present but not enabled "); | | 1004 | aprint_normal(" L2 cache present but not enabled "); |
1005 | return; | | 1005 | return; |
1006 | } | | 1006 | } |
1007 | aprint_normal(","); | | 1007 | aprint_normal(","); |
1008 | | | 1008 | |
1009 | switch (vers) { | | 1009 | switch (vers) { |
1010 | case IBM750FX: | | 1010 | case IBM750FX: |
1011 | case IBM750GX: | | 1011 | case IBM750GX: |
1012 | cpu_fmttab_print(cpu_ibm750_l2cr_formats, l2cr); | | 1012 | cpu_fmttab_print(cpu_ibm750_l2cr_formats, l2cr); |
1013 | break; | | 1013 | break; |
1014 | case MPC750: | | 1014 | case MPC750: |
1015 | if ((pvr & 0xffffff00) == 0x00082200 /* IBM750CX */ || | | 1015 | if ((pvr & 0xffffff00) == 0x00082200 /* IBM750CX */ || |
1016 | (pvr & 0xffffef00) == 0x00082300 /* IBM750CXe */) | | 1016 | (pvr & 0xffffef00) == 0x00082300 /* IBM750CXe */) |
1017 | cpu_fmttab_print(cpu_ibm750_l2cr_formats, l2cr); | | 1017 | cpu_fmttab_print(cpu_ibm750_l2cr_formats, l2cr); |
1018 | else | | 1018 | else |
1019 | cpu_fmttab_print(cpu_l2cr_formats, l2cr); | | 1019 | cpu_fmttab_print(cpu_l2cr_formats, l2cr); |
1020 | break; | | 1020 | break; |
1021 | case MPC7447A: | | 1021 | case MPC7447A: |
1022 | case MPC7457: | | 1022 | case MPC7457: |
1023 | cpu_fmttab_print(cpu_7457_l2cr_formats, l2cr); | | 1023 | cpu_fmttab_print(cpu_7457_l2cr_formats, l2cr); |
1024 | return; | | 1024 | return; |
1025 | case MPC7448: | | 1025 | case MPC7448: |
1026 | cpu_fmttab_print(cpu_7448_l2cr_formats, l2cr); | | 1026 | cpu_fmttab_print(cpu_7448_l2cr_formats, l2cr); |
1027 | return; | | 1027 | return; |
1028 | case MPC7450: | | 1028 | case MPC7450: |
1029 | case MPC7455: | | 1029 | case MPC7455: |
1030 | cpu_fmttab_print(cpu_7450_l2cr_formats, l2cr); | | 1030 | cpu_fmttab_print(cpu_7450_l2cr_formats, l2cr); |
1031 | break; | | 1031 | break; |
1032 | default: | | 1032 | default: |
1033 | cpu_fmttab_print(cpu_l2cr_formats, l2cr); | | 1033 | cpu_fmttab_print(cpu_l2cr_formats, l2cr); |
1034 | break; | | 1034 | break; |
1035 | } | | 1035 | } |
1036 | } | | 1036 | } |
1037 | | | 1037 | |
1038 | void | | 1038 | void |
1039 | cpu_config_l3cr(int vers) | | 1039 | cpu_config_l3cr(int vers) |
1040 | { | | 1040 | { |
1041 | register_t l2cr; | | 1041 | register_t l2cr; |
1042 | register_t l3cr; | | 1042 | register_t l3cr; |
1043 | | | 1043 | |
1044 | l2cr = mfspr(SPR_L2CR); | | 1044 | l2cr = mfspr(SPR_L2CR); |
1045 | | | 1045 | |
1046 | /* | | 1046 | /* |
1047 | * For MP systems, the firmware may only configure the L2 cache | | 1047 | * For MP systems, the firmware may only configure the L2 cache |
1048 | * on the first CPU. In this case, assume that the other CPUs | | 1048 | * on the first CPU. In this case, assume that the other CPUs |
1049 | * should use the same value for L2CR. | | 1049 | * should use the same value for L2CR. |
1050 | */ | | 1050 | */ |
1051 | if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { | | 1051 | if ((l2cr & L2CR_L2E) != 0 && l2cr_config == 0) { |
1052 | l2cr_config = l2cr; | | 1052 | l2cr_config = l2cr; |
1053 | } | | 1053 | } |
1054 | | | 1054 | |
1055 | /* | | 1055 | /* |
1056 | * Configure L2 cache if not enabled. | | 1056 | * Configure L2 cache if not enabled. |
1057 | */ | | 1057 | */ |
1058 | if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { | | 1058 | if ((l2cr & L2CR_L2E) == 0 && l2cr_config != 0) { |
1059 | cpu_enable_l2cr(l2cr_config); | | 1059 | cpu_enable_l2cr(l2cr_config); |
1060 | l2cr = mfspr(SPR_L2CR); | | 1060 | l2cr = mfspr(SPR_L2CR); |
1061 | } | | 1061 | } |
1062 | | | 1062 | |
1063 | aprint_normal(","); | | 1063 | aprint_normal(","); |
1064 | switch (vers) { | | 1064 | switch (vers) { |
1065 | case MPC7447A: | | 1065 | case MPC7447A: |
1066 | case MPC7457: | | 1066 | case MPC7457: |
1067 | cpu_fmttab_print(cpu_7457_l2cr_formats, l2cr); | | 1067 | cpu_fmttab_print(cpu_7457_l2cr_formats, l2cr); |
1068 | return; | | 1068 | return; |
1069 | case MPC7448: | | 1069 | case MPC7448: |
1070 | cpu_fmttab_print(cpu_7448_l2cr_formats, l2cr); | | 1070 | cpu_fmttab_print(cpu_7448_l2cr_formats, l2cr); |
1071 | return; | | 1071 | return; |
1072 | default: | | 1072 | default: |
1073 | cpu_fmttab_print(cpu_7450_l2cr_formats, l2cr); | | 1073 | cpu_fmttab_print(cpu_7450_l2cr_formats, l2cr); |
1074 | break; | | 1074 | break; |
1075 | } | | 1075 | } |
1076 | | | 1076 | |
1077 | l3cr = mfspr(SPR_L3CR); | | 1077 | l3cr = mfspr(SPR_L3CR); |
1078 | | | 1078 | |
1079 | /* | | 1079 | /* |
1080 | * For MP systems, the firmware may only configure the L3 cache | | 1080 | * For MP systems, the firmware may only configure the L3 cache |
1081 | * on the first CPU. In this case, assume that the other CPUs | | 1081 | * on the first CPU. In this case, assume that the other CPUs |
1082 | * should use the same value for L3CR. | | 1082 | * should use the same value for L3CR. |
1083 | */ | | 1083 | */ |
1084 | if ((l3cr & L3CR_L3E) != 0 && l3cr_config == 0) { | | 1084 | if ((l3cr & L3CR_L3E) != 0 && l3cr_config == 0) { |
1085 | l3cr_config = l3cr; | | 1085 | l3cr_config = l3cr; |
1086 | } | | 1086 | } |
1087 | | | 1087 | |
1088 | /* | | 1088 | /* |
1089 | * Configure L3 cache if not enabled. | | 1089 | * Configure L3 cache if not enabled. |
1090 | */ | | 1090 | */ |
1091 | if ((l3cr & L3CR_L3E) == 0 && l3cr_config != 0) { | | 1091 | if ((l3cr & L3CR_L3E) == 0 && l3cr_config != 0) { |
1092 | cpu_enable_l3cr(l3cr_config); | | 1092 | cpu_enable_l3cr(l3cr_config); |
1093 | l3cr = mfspr(SPR_L3CR); | | 1093 | l3cr = mfspr(SPR_L3CR); |
1094 | } | | 1094 | } |
1095 | | | 1095 | |
1096 | if (l3cr & L3CR_L3E) { | | 1096 | if (l3cr & L3CR_L3E) { |
1097 | aprint_normal(","); | | 1097 | aprint_normal(","); |
1098 | cpu_fmttab_print(cpu_7450_l3cr_formats, l3cr); | | 1098 | cpu_fmttab_print(cpu_7450_l3cr_formats, l3cr); |
1099 | } | | 1099 | } |
1100 | } | | 1100 | } |
1101 | | | 1101 | |
1102 | void | | 1102 | void |
1103 | cpu_probe_speed(struct cpu_info *ci) | | 1103 | cpu_probe_speed(struct cpu_info *ci) |
1104 | { | | 1104 | { |
1105 | uint64_t cps; | | 1105 | uint64_t cps; |
1106 | | | 1106 | |
1107 | mtspr(SPR_MMCR0, MMCR0_FC); | | 1107 | mtspr(SPR_MMCR0, MMCR0_FC); |
1108 | mtspr(SPR_PMC1, 0); | | 1108 | mtspr(SPR_PMC1, 0); |
1109 | mtspr(SPR_MMCR0, MMCR0_PMC1SEL(PMCN_CYCLES)); | | 1109 | mtspr(SPR_MMCR0, MMCR0_PMC1SEL(PMCN_CYCLES)); |
1110 | delay(100000); | | 1110 | delay(100000); |
1111 | cps = (mfspr(SPR_PMC1) * 10) + 4999; | | 1111 | cps = (mfspr(SPR_PMC1) * 10) + 4999; |
1112 | | | 1112 | |
1113 | mtspr(SPR_MMCR0, MMCR0_FC); | | 1113 | mtspr(SPR_MMCR0, MMCR0_FC); |
1114 | | | 1114 | |
1115 | ci->ci_khz = (cps * cpu_get_dfs()) / 1000; | | 1115 | ci->ci_khz = (cps * cpu_get_dfs()) / 1000; |
1116 | } | | 1116 | } |
1117 | | | 1117 | |
1118 | /* | | 1118 | /* |
1119 | * Read the Dynamic Frequency Switching state and return a divisor for | | 1119 | * Read the Dynamic Frequency Switching state and return a divisor for |
1120 | * the maximum frequency. | | 1120 | * the maximum frequency. |
1121 | */ | | 1121 | */ |
1122 | int | | 1122 | int |
1123 | cpu_get_dfs(void) | | 1123 | cpu_get_dfs(void) |
1124 | { | | 1124 | { |
1125 | u_int pvr, vers; | | 1125 | u_int pvr, vers; |
1126 | | | 1126 | |
1127 | pvr = mfpvr(); | | 1127 | pvr = mfpvr(); |
1128 | vers = pvr >> 16; | | 1128 | vers = pvr >> 16; |
1129 | | | 1129 | |
1130 | switch (vers) { | | 1130 | switch (vers) { |
1131 | case MPC7448: | | 1131 | case MPC7448: |
1132 | if (mfspr(SPR_HID1) & HID1_DFS4) | | 1132 | if (mfspr(SPR_HID1) & HID1_DFS4) |
1133 | return 4; | | 1133 | return 4; |
1134 | case MPC7447A: | | 1134 | case MPC7447A: |
1135 | if (mfspr(SPR_HID1) & HID1_DFS2) | | 1135 | if (mfspr(SPR_HID1) & HID1_DFS2) |
1136 | return 2; | | 1136 | return 2; |
1137 | } | | 1137 | } |
1138 | return 1; | | 1138 | return 1; |
1139 | } | | 1139 | } |
1140 | | | 1140 | |
1141 | /* | | 1141 | /* |
1142 | * Set the Dynamic Frequency Switching divisor the same for all cpus. | | 1142 | * Set the Dynamic Frequency Switching divisor the same for all cpus. |
1143 | */ | | 1143 | */ |
1144 | void | | 1144 | void |
1145 | cpu_set_dfs(int div) | | 1145 | cpu_set_dfs(int div) |
1146 | { | | 1146 | { |
1147 | uint64_t where; | | | |
1148 | u_int dfs_mask, pvr, vers; | | 1147 | u_int dfs_mask, pvr, vers; |
1149 | | | 1148 | |
1150 | pvr = mfpvr(); | | 1149 | pvr = mfpvr(); |
1151 | vers = pvr >> 16; | | 1150 | vers = pvr >> 16; |
1152 | dfs_mask = 0; | | 1151 | dfs_mask = 0; |
1153 | | | 1152 | |
1154 | switch (vers) { | | 1153 | switch (vers) { |
1155 | case MPC7448: | | 1154 | case MPC7448: |
1156 | dfs_mask |= HID1_DFS4; | | 1155 | dfs_mask |= HID1_DFS4; |
1157 | case MPC7447A: | | 1156 | case MPC7447A: |
1158 | dfs_mask |= HID1_DFS2; | | 1157 | dfs_mask |= HID1_DFS2; |
1159 | break; | | 1158 | break; |
1160 | default: | | 1159 | default: |
1161 | printf("cpu_set_dfs: DFS not supported\n"); | | 1160 | printf("cpu_set_dfs: DFS not supported\n"); |
1162 | return; | | 1161 | return; |
1163 | | | 1162 | |
1164 | } | | 1163 | } |
1165 | | | 1164 | #ifdef MULTIPROCESSOR |
| | | 1165 | uint64_t where; |
1166 | where = xc_broadcast(0, (xcfunc_t)cpu_set_dfs_xcall, &div, &dfs_mask); | | 1166 | where = xc_broadcast(0, (xcfunc_t)cpu_set_dfs_xcall, &div, &dfs_mask); |
1167 | xc_wait(where); | | 1167 | xc_wait(where); |
| | | 1168 | #else |
| | | 1169 | cpu_set_dfs_xcall(&div, &dfs_mask); |
| | | 1170 | #endif |
1168 | } | | 1171 | } |
1169 | | | 1172 | |
1170 | static void | | 1173 | static void |
1171 | cpu_set_dfs_xcall(void *arg1, void *arg2) | | 1174 | cpu_set_dfs_xcall(void *arg1, void *arg2) |
1172 | { | | 1175 | { |
1173 | u_int dfs_mask, hid1, old_hid1; | | 1176 | u_int dfs_mask, hid1, old_hid1; |
1174 | int *divisor, s; | | 1177 | int *divisor, s; |
1175 | | | 1178 | |
1176 | divisor = arg1; | | 1179 | divisor = arg1; |
1177 | dfs_mask = *(u_int *)arg2; | | 1180 | dfs_mask = *(u_int *)arg2; |
1178 | | | 1181 | |
1179 | s = splhigh(); | | 1182 | s = splhigh(); |
1180 | hid1 = old_hid1 = mfspr(SPR_HID1); | | 1183 | hid1 = old_hid1 = mfspr(SPR_HID1); |
1181 | | | 1184 | |
1182 | switch (*divisor) { | | 1185 | switch (*divisor) { |
1183 | case 1: | | 1186 | case 1: |
1184 | hid1 &= ~dfs_mask; | | 1187 | hid1 &= ~dfs_mask; |
1185 | break; | | 1188 | break; |
1186 | case 2: | | 1189 | case 2: |
1187 | hid1 &= ~(dfs_mask & HID1_DFS4); | | 1190 | hid1 &= ~(dfs_mask & HID1_DFS4); |
1188 | hid1 |= dfs_mask & HID1_DFS2; | | 1191 | hid1 |= dfs_mask & HID1_DFS2; |
1189 | break; | | 1192 | break; |
1190 | case 4: | | 1193 | case 4: |
1191 | hid1 &= ~(dfs_mask & HID1_DFS2); | | 1194 | hid1 &= ~(dfs_mask & HID1_DFS2); |
1192 | hid1 |= dfs_mask & HID1_DFS4; | | 1195 | hid1 |= dfs_mask & HID1_DFS4; |
1193 | break; | | 1196 | break; |
1194 | } | | 1197 | } |
1195 | | | 1198 | |
1196 | if (hid1 != old_hid1) { | | 1199 | if (hid1 != old_hid1) { |
1197 | __asm volatile("sync"); | | 1200 | __asm volatile("sync"); |
1198 | mtspr(SPR_HID1, hid1); | | 1201 | mtspr(SPR_HID1, hid1); |
1199 | __asm volatile("sync;isync"); | | 1202 | __asm volatile("sync;isync"); |
1200 | } | | 1203 | } |
1201 | | | 1204 | |
1202 | splx(s); | | 1205 | splx(s); |
1203 | } | | 1206 | } |
1204 | | | 1207 | |
1205 | #if NSYSMON_ENVSYS > 0 | | 1208 | #if NSYSMON_ENVSYS > 0 |
1206 | void | | 1209 | void |
1207 | cpu_tau_setup(struct cpu_info *ci) | | 1210 | cpu_tau_setup(struct cpu_info *ci) |
1208 | { | | 1211 | { |
1209 | struct sysmon_envsys *sme; | | 1212 | struct sysmon_envsys *sme; |
1210 | int error, therm_delay; | | 1213 | int error, therm_delay; |
1211 | | | 1214 | |
1212 | mtspr(SPR_THRM1, SPR_THRM_VALID); | | 1215 | mtspr(SPR_THRM1, SPR_THRM_VALID); |
1213 | mtspr(SPR_THRM2, 0); | | 1216 | mtspr(SPR_THRM2, 0); |
1214 | | | 1217 | |
1215 | /* | | 1218 | /* |
1216 | * we need to figure out how much 20+us in units of CPU clock cycles | | 1219 | * we need to figure out how much 20+us in units of CPU clock cycles |
1217 | * are | | 1220 | * are |
1218 | */ | | 1221 | */ |
1219 | | | 1222 | |
1220 | therm_delay = ci->ci_khz / 40; /* 25us just to be safe */ | | 1223 | therm_delay = ci->ci_khz / 40; /* 25us just to be safe */ |
1221 | | | 1224 | |
1222 | mtspr(SPR_THRM3, SPR_THRM_TIMER(therm_delay) | SPR_THRM_ENABLE); | | 1225 | mtspr(SPR_THRM3, SPR_THRM_TIMER(therm_delay) | SPR_THRM_ENABLE); |
1223 | | | 1226 | |
1224 | sme = sysmon_envsys_create(); | | 1227 | sme = sysmon_envsys_create(); |
1225 | | | 1228 | |
1226 | sensor.units = ENVSYS_STEMP; | | 1229 | sensor.units = ENVSYS_STEMP; |
1227 | sensor.state = ENVSYS_SINVALID; | | 1230 | sensor.state = ENVSYS_SINVALID; |
1228 | (void)strlcpy(sensor.desc, "CPU Temp", sizeof(sensor.desc)); | | 1231 | (void)strlcpy(sensor.desc, "CPU Temp", sizeof(sensor.desc)); |
1229 | if (sysmon_envsys_sensor_attach(sme, &sensor)) { | | 1232 | if (sysmon_envsys_sensor_attach(sme, &sensor)) { |
1230 | sysmon_envsys_destroy(sme); | | 1233 | sysmon_envsys_destroy(sme); |
1231 | return; | | 1234 | return; |
1232 | } | | 1235 | } |
1233 | | | 1236 | |
1234 | sme->sme_name = device_xname(ci->ci_dev); | | 1237 | sme->sme_name = device_xname(ci->ci_dev); |
1235 | sme->sme_cookie = ci; | | 1238 | sme->sme_cookie = ci; |
1236 | sme->sme_refresh = cpu_tau_refresh; | | 1239 | sme->sme_refresh = cpu_tau_refresh; |
1237 | | | 1240 | |
1238 | if ((error = sysmon_envsys_register(sme)) != 0) { | | 1241 | if ((error = sysmon_envsys_register(sme)) != 0) { |
1239 | aprint_error_dev(ci->ci_dev, | | 1242 | aprint_error_dev(ci->ci_dev, |
1240 | " unable to register with sysmon (%d)\n", error); | | 1243 | " unable to register with sysmon (%d)\n", error); |
1241 | sysmon_envsys_destroy(sme); | | 1244 | sysmon_envsys_destroy(sme); |
1242 | } | | 1245 | } |
1243 | } | | 1246 | } |
1244 | | | 1247 | |
1245 | /* Find the temperature of the CPU. */ | | 1248 | /* Find the temperature of the CPU. */ |
1246 | void | | 1249 | void |
1247 | cpu_tau_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) | | 1250 | cpu_tau_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) |
1248 | { | | 1251 | { |
1249 | int i, threshold, count; | | 1252 | int i, threshold, count; |
1250 | | | 1253 | |
1251 | threshold = 64; /* Half of the 7-bit sensor range */ | | 1254 | threshold = 64; /* Half of the 7-bit sensor range */ |
1252 | | | 1255 | |
1253 | /* Successive-approximation code adapted from Motorola | | 1256 | /* Successive-approximation code adapted from Motorola |
1254 | * application note AN1800/D, "Programming the Thermal Assist | | 1257 | * application note AN1800/D, "Programming the Thermal Assist |
1255 | * Unit in the MPC750 Microprocessor". | | 1258 | * Unit in the MPC750 Microprocessor". |
1256 | */ | | 1259 | */ |
1257 | for (i = 5; i >= 0 ; i--) { | | 1260 | for (i = 5; i >= 0 ; i--) { |
1258 | mtspr(SPR_THRM1, | | 1261 | mtspr(SPR_THRM1, |
1259 | SPR_THRM_THRESHOLD(threshold) | SPR_THRM_VALID); | | 1262 | SPR_THRM_THRESHOLD(threshold) | SPR_THRM_VALID); |
1260 | count = 0; | | 1263 | count = 0; |
1261 | while ((count < 100000) && | | 1264 | while ((count < 100000) && |
1262 | ((mfspr(SPR_THRM1) & SPR_THRM_TIV) == 0)) { | | 1265 | ((mfspr(SPR_THRM1) & SPR_THRM_TIV) == 0)) { |
1263 | count++; | | 1266 | count++; |
1264 | delay(1); | | 1267 | delay(1); |
1265 | } | | 1268 | } |
1266 | if (mfspr(SPR_THRM1) & SPR_THRM_TIN) { | | 1269 | if (mfspr(SPR_THRM1) & SPR_THRM_TIN) { |
1267 | /* The interrupt bit was set, meaning the | | 1270 | /* The interrupt bit was set, meaning the |
1268 | * temperature was above the threshold | | 1271 | * temperature was above the threshold |
1269 | */ | | 1272 | */ |
1270 | threshold += 1 << i; | | 1273 | threshold += 1 << i; |
1271 | } else { | | 1274 | } else { |
1272 | /* Temperature was below the threshold */ | | 1275 | /* Temperature was below the threshold */ |
1273 | threshold -= 1 << i; | | 1276 | threshold -= 1 << i; |
1274 | } | | 1277 | } |
1275 | } | | 1278 | } |
1276 | threshold += 2; | | 1279 | threshold += 2; |
1277 | | | 1280 | |
1278 | /* Convert the temperature in degrees C to microkelvin */ | | 1281 | /* Convert the temperature in degrees C to microkelvin */ |
1279 | edata->value_cur = (threshold * 1000000) + 273150000; | | 1282 | edata->value_cur = (threshold * 1000000) + 273150000; |
1280 | edata->state = ENVSYS_SVALID; | | 1283 | edata->state = ENVSYS_SVALID; |
1281 | } | | 1284 | } |
1282 | #endif /* NSYSMON_ENVSYS > 0 */ | | 1285 | #endif /* NSYSMON_ENVSYS > 0 */ |
1283 | | | 1286 | |
1284 | #ifdef MULTIPROCESSOR | | 1287 | #ifdef MULTIPROCESSOR |
1285 | volatile u_int cpu_spinstart_ack, cpu_spinstart_cpunum; | | 1288 | volatile u_int cpu_spinstart_ack, cpu_spinstart_cpunum; |
1286 | | | 1289 | |
1287 | int | | 1290 | int |
1288 | cpu_spinup(device_t self, struct cpu_info *ci) | | 1291 | cpu_spinup(device_t self, struct cpu_info *ci) |
1289 | { | | 1292 | { |
1290 | volatile struct cpu_hatch_data hatch_data, *h = &hatch_data; | | 1293 | volatile struct cpu_hatch_data hatch_data, *h = &hatch_data; |
1291 | struct pglist mlist; | | 1294 | struct pglist mlist; |
1292 | int i, error; | | 1295 | int i, error; |
1293 | char *hp; | | 1296 | char *hp; |
1294 | | | 1297 | |
1295 | KASSERT(ci != curcpu()); | | 1298 | KASSERT(ci != curcpu()); |
1296 | | | 1299 | |
1297 | /* Now allocate a hatch stack */ | | 1300 | /* Now allocate a hatch stack */ |
1298 | error = uvm_pglistalloc(HATCH_STACK_SIZE, 0x10000, 0x10000000, 16, 0, | | 1301 | error = uvm_pglistalloc(HATCH_STACK_SIZE, 0x10000, 0x10000000, 16, 0, |
1299 | &mlist, 1, 1); | | 1302 | &mlist, 1, 1); |
1300 | if (error) { | | 1303 | if (error) { |
1301 | aprint_error(": unable to allocate hatch stack\n"); | | 1304 | aprint_error(": unable to allocate hatch stack\n"); |
1302 | return -1; | | 1305 | return -1; |
1303 | } | | 1306 | } |
1304 | | | 1307 | |
1305 | hp = (void *)VM_PAGE_TO_PHYS(TAILQ_FIRST(&mlist)); | | 1308 | hp = (void *)VM_PAGE_TO_PHYS(TAILQ_FIRST(&mlist)); |
1306 | memset(hp, 0, HATCH_STACK_SIZE); | | 1309 | memset(hp, 0, HATCH_STACK_SIZE); |
1307 | | | 1310 | |
1308 | /* Initialize secondary cpu's initial lwp to its idlelwp. */ | | 1311 | /* Initialize secondary cpu's initial lwp to its idlelwp. */ |
1309 | ci->ci_curlwp = ci->ci_data.cpu_idlelwp; | | 1312 | ci->ci_curlwp = ci->ci_data.cpu_idlelwp; |
1310 | ci->ci_curpcb = lwp_getpcb(ci->ci_curlwp); | | 1313 | ci->ci_curpcb = lwp_getpcb(ci->ci_curlwp); |
1311 | ci->ci_curpm = ci->ci_curpcb->pcb_pm; | | 1314 | ci->ci_curpm = ci->ci_curpcb->pcb_pm; |
1312 | | | 1315 | |
1313 | cpu_hatch_data = h; | | 1316 | cpu_hatch_data = h; |
1314 | h->hatch_running = 0; | | 1317 | h->hatch_running = 0; |
1315 | h->hatch_self = self; | | 1318 | h->hatch_self = self; |
1316 | h->hatch_ci = ci; | | 1319 | h->hatch_ci = ci; |
1317 | h->hatch_pir = ci->ci_cpuid; | | 1320 | h->hatch_pir = ci->ci_cpuid; |
1318 | | | 1321 | |
1319 | cpu_hatch_stack = (uint32_t)hp + HATCH_STACK_SIZE - CALLFRAMELEN; | | 1322 | cpu_hatch_stack = (uint32_t)hp + HATCH_STACK_SIZE - CALLFRAMELEN; |
1320 | ci->ci_lasttb = cpu_info[0].ci_lasttb; | | 1323 | ci->ci_lasttb = cpu_info[0].ci_lasttb; |
1321 | | | 1324 | |
1322 | /* copy special registers */ | | 1325 | /* copy special registers */ |
1323 | | | 1326 | |
1324 | h->hatch_hid0 = mfspr(SPR_HID0); | | 1327 | h->hatch_hid0 = mfspr(SPR_HID0); |
1325 | #if defined(PPC_OEA64_BRIDGE) || defined (_ARCH_PPC64) | | 1328 | #if defined(PPC_OEA64_BRIDGE) || defined (_ARCH_PPC64) |
1326 | h->hatch_hid1 = mfspr(SPR_HID1); | | 1329 | h->hatch_hid1 = mfspr(SPR_HID1); |
1327 | h->hatch_hid4 = mfspr(SPR_HID4); | | 1330 | h->hatch_hid4 = mfspr(SPR_HID4); |
1328 | h->hatch_hid5 = mfspr(SPR_HID5); | | 1331 | h->hatch_hid5 = mfspr(SPR_HID5); |
1329 | #endif | | 1332 | #endif |
1330 | | | 1333 | |
1331 | __asm volatile ("mfsdr1 %0" : "=r"(h->hatch_sdr1)); | | 1334 | __asm volatile ("mfsdr1 %0" : "=r"(h->hatch_sdr1)); |
1332 | for (i = 0; i < 16; i++) { | | 1335 | for (i = 0; i < 16; i++) { |
1333 | __asm ("mfsrin %0,%1" : "=r"(h->hatch_sr[i]) : | | 1336 | __asm ("mfsrin %0,%1" : "=r"(h->hatch_sr[i]) : |
1334 | "r"(i << ADDR_SR_SHFT)); | | 1337 | "r"(i << ADDR_SR_SHFT)); |
1335 | } | | 1338 | } |
1336 | if (oeacpufeat & OEACPU_64) | | 1339 | if (oeacpufeat & OEACPU_64) |
1337 | h->hatch_asr = mfspr(SPR_ASR); | | 1340 | h->hatch_asr = mfspr(SPR_ASR); |
1338 | else | | 1341 | else |
1339 | h->hatch_asr = 0; | | 1342 | h->hatch_asr = 0; |
1340 | | | 1343 | |
1341 | if ((oeacpufeat & OEACPU_NOBAT) == 0) { | | 1344 | if ((oeacpufeat & OEACPU_NOBAT) == 0) { |
1342 | /* copy the bat regs */ | | 1345 | /* copy the bat regs */ |
1343 | __asm volatile ("mfibatu %0,0" : "=r"(h->hatch_ibatu[0])); | | 1346 | __asm volatile ("mfibatu %0,0" : "=r"(h->hatch_ibatu[0])); |
1344 | __asm volatile ("mfibatl %0,0" : "=r"(h->hatch_ibatl[0])); | | 1347 | __asm volatile ("mfibatl %0,0" : "=r"(h->hatch_ibatl[0])); |
1345 | __asm volatile ("mfibatu %0,1" : "=r"(h->hatch_ibatu[1])); | | 1348 | __asm volatile ("mfibatu %0,1" : "=r"(h->hatch_ibatu[1])); |
1346 | __asm volatile ("mfibatl %0,1" : "=r"(h->hatch_ibatl[1])); | | 1349 | __asm volatile ("mfibatl %0,1" : "=r"(h->hatch_ibatl[1])); |
1347 | __asm volatile ("mfibatu %0,2" : "=r"(h->hatch_ibatu[2])); | | 1350 | __asm volatile ("mfibatu %0,2" : "=r"(h->hatch_ibatu[2])); |
1348 | __asm volatile ("mfibatl %0,2" : "=r"(h->hatch_ibatl[2])); | | 1351 | __asm volatile ("mfibatl %0,2" : "=r"(h->hatch_ibatl[2])); |
1349 | __asm volatile ("mfibatu %0,3" : "=r"(h->hatch_ibatu[3])); | | 1352 | __asm volatile ("mfibatu %0,3" : "=r"(h->hatch_ibatu[3])); |
1350 | __asm volatile ("mfibatl %0,3" : "=r"(h->hatch_ibatl[3])); | | 1353 | __asm volatile ("mfibatl %0,3" : "=r"(h->hatch_ibatl[3])); |
1351 | __asm volatile ("mfdbatu %0,0" : "=r"(h->hatch_dbatu[0])); | | 1354 | __asm volatile ("mfdbatu %0,0" : "=r"(h->hatch_dbatu[0])); |
1352 | __asm volatile ("mfdbatl %0,0" : "=r"(h->hatch_dbatl[0])); | | 1355 | __asm volatile ("mfdbatl %0,0" : "=r"(h->hatch_dbatl[0])); |
1353 | __asm volatile ("mfdbatu %0,1" : "=r"(h->hatch_dbatu[1])); | | 1356 | __asm volatile ("mfdbatu %0,1" : "=r"(h->hatch_dbatu[1])); |
1354 | __asm volatile ("mfdbatl %0,1" : "=r"(h->hatch_dbatl[1])); | | 1357 | __asm volatile ("mfdbatl %0,1" : "=r"(h->hatch_dbatl[1])); |
1355 | __asm volatile ("mfdbatu %0,2" : "=r"(h->hatch_dbatu[2])); | | 1358 | __asm volatile ("mfdbatu %0,2" : "=r"(h->hatch_dbatu[2])); |
1356 | __asm volatile ("mfdbatl %0,2" : "=r"(h->hatch_dbatl[2])); | | 1359 | __asm volatile ("mfdbatl %0,2" : "=r"(h->hatch_dbatl[2])); |
1357 | __asm volatile ("mfdbatu %0,3" : "=r"(h->hatch_dbatu[3])); | | 1360 | __asm volatile ("mfdbatu %0,3" : "=r"(h->hatch_dbatu[3])); |
1358 | __asm volatile ("mfdbatl %0,3" : "=r"(h->hatch_dbatl[3])); | | 1361 | __asm volatile ("mfdbatl %0,3" : "=r"(h->hatch_dbatl[3])); |
1359 | __asm volatile ("sync; isync"); | | 1362 | __asm volatile ("sync; isync"); |
1360 | } | | 1363 | } |
1361 | | | 1364 | |
1362 | if (md_setup_trampoline(h, ci) == -1) | | 1365 | if (md_setup_trampoline(h, ci) == -1) |
1363 | return -1; | | 1366 | return -1; |
1364 | md_presync_timebase(h); | | 1367 | md_presync_timebase(h); |
1365 | md_start_timebase(h); | | 1368 | md_start_timebase(h); |
1366 | | | 1369 | |
1367 | /* wait for secondary printf */ | | 1370 | /* wait for secondary printf */ |
1368 | | | 1371 | |
1369 | delay(200000); | | 1372 | delay(200000); |
1370 | | | 1373 | |
1371 | #ifdef CACHE_PROTO_MEI | | 1374 | #ifdef CACHE_PROTO_MEI |
1372 | __asm volatile ("dcbi 0,%0"::"r"(&h->hatch_running):"memory"); | | 1375 | __asm volatile ("dcbi 0,%0"::"r"(&h->hatch_running):"memory"); |
1373 | __asm volatile ("sync; isync"); | | 1376 | __asm volatile ("sync; isync"); |
1374 | __asm volatile ("dcbst 0,%0"::"r"(&h->hatch_running):"memory"); | | 1377 | __asm volatile ("dcbst 0,%0"::"r"(&h->hatch_running):"memory"); |
1375 | __asm volatile ("sync; isync"); | | 1378 | __asm volatile ("sync; isync"); |
1376 | #endif | | 1379 | #endif |
1377 | if (h->hatch_running < 1) { | | 1380 | if (h->hatch_running < 1) { |
1378 | #ifdef CACHE_PROTO_MEI | | 1381 | #ifdef CACHE_PROTO_MEI |
1379 | __asm volatile ("dcbi 0,%0"::"r"(&cpu_spinstart_ack):"memory"); | | 1382 | __asm volatile ("dcbi 0,%0"::"r"(&cpu_spinstart_ack):"memory"); |
1380 | __asm volatile ("sync; isync"); | | 1383 | __asm volatile ("sync; isync"); |
1381 | __asm volatile ("dcbst 0,%0"::"r"(&cpu_spinstart_ack):"memory"); | | 1384 | __asm volatile ("dcbst 0,%0"::"r"(&cpu_spinstart_ack):"memory"); |
1382 | __asm volatile ("sync; isync"); | | 1385 | __asm volatile ("sync; isync"); |
1383 | #endif | | 1386 | #endif |
1384 | aprint_error("%d:CPU %d didn't start %d\n", cpu_spinstart_ack, | | 1387 | aprint_error("%d:CPU %d didn't start %d\n", cpu_spinstart_ack, |
1385 | ci->ci_cpuid, cpu_spinstart_ack); | | 1388 | ci->ci_cpuid, cpu_spinstart_ack); |
1386 | Debugger(); | | 1389 | Debugger(); |
1387 | return -1; | | 1390 | return -1; |
1388 | } | | 1391 | } |
1389 | | | 1392 | |
1390 | /* Register IPI Interrupt */ | | 1393 | /* Register IPI Interrupt */ |
1391 | if (ipiops.ppc_establish_ipi) | | 1394 | if (ipiops.ppc_establish_ipi) |
1392 | ipiops.ppc_establish_ipi(IST_LEVEL, IPL_HIGH, NULL); | | 1395 | ipiops.ppc_establish_ipi(IST_LEVEL, IPL_HIGH, NULL); |
1393 | | | 1396 | |
1394 | return 0; | | 1397 | return 0; |
1395 | } | | 1398 | } |
1396 | | | 1399 | |
1397 | static volatile int start_secondary_cpu; | | 1400 | static volatile int start_secondary_cpu; |
1398 | | | 1401 | |
1399 | register_t | | 1402 | register_t |
1400 | cpu_hatch(void) | | 1403 | cpu_hatch(void) |
1401 | { | | 1404 | { |
1402 | volatile struct cpu_hatch_data *h = cpu_hatch_data; | | 1405 | volatile struct cpu_hatch_data *h = cpu_hatch_data; |
1403 | struct cpu_info * const ci = h->hatch_ci; | | 1406 | struct cpu_info * const ci = h->hatch_ci; |
1404 | struct pcb *pcb; | | 1407 | struct pcb *pcb; |
1405 | u_int msr; | | 1408 | u_int msr; |
1406 | int i; | | 1409 | int i; |
1407 | | | 1410 | |
1408 | /* Initialize timebase. */ | | 1411 | /* Initialize timebase. */ |
1409 | __asm ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0)); | | 1412 | __asm ("mttbl %0; mttbu %0; mttbl %0" :: "r"(0)); |
1410 | | | 1413 | |
1411 | /* | | 1414 | /* |
1412 | * Set PIR (Processor Identification Register). i.e. whoami | | 1415 | * Set PIR (Processor Identification Register). i.e. whoami |
1413 | * Note that PIR is read-only on some CPU versions, so we write to it | | 1416 | * Note that PIR is read-only on some CPU versions, so we write to it |
1414 | * only if it has a different value than we need. | | 1417 | * only if it has a different value than we need. |
1415 | */ | | 1418 | */ |
1416 | | | 1419 | |
1417 | msr = mfspr(SPR_PIR); | | 1420 | msr = mfspr(SPR_PIR); |
1418 | if (msr != h->hatch_pir) | | 1421 | if (msr != h->hatch_pir) |
1419 | mtspr(SPR_PIR, h->hatch_pir); | | 1422 | mtspr(SPR_PIR, h->hatch_pir); |
1420 | | | 1423 | |
1421 | __asm volatile ("mtsprg0 %0" :: "r"(ci)); | | 1424 | __asm volatile ("mtsprg0 %0" :: "r"(ci)); |
1422 | curlwp = ci->ci_curlwp; | | 1425 | curlwp = ci->ci_curlwp; |
1423 | cpu_spinstart_ack = 0; | | 1426 | cpu_spinstart_ack = 0; |
1424 | | | 1427 | |
1425 | if ((oeacpufeat & OEACPU_NOBAT) == 0) { | | 1428 | if ((oeacpufeat & OEACPU_NOBAT) == 0) { |
1426 | /* Initialize MMU. */ | | 1429 | /* Initialize MMU. */ |
1427 | __asm ("mtibatu 0,%0" :: "r"(h->hatch_ibatu[0])); | | 1430 | __asm ("mtibatu 0,%0" :: "r"(h->hatch_ibatu[0])); |
1428 | __asm ("mtibatl 0,%0" :: "r"(h->hatch_ibatl[0])); | | 1431 | __asm ("mtibatl 0,%0" :: "r"(h->hatch_ibatl[0])); |
1429 | __asm ("mtibatu 1,%0" :: "r"(h->hatch_ibatu[1])); | | 1432 | __asm ("mtibatu 1,%0" :: "r"(h->hatch_ibatu[1])); |
1430 | __asm ("mtibatl 1,%0" :: "r"(h->hatch_ibatl[1])); | | 1433 | __asm ("mtibatl 1,%0" :: "r"(h->hatch_ibatl[1])); |
1431 | __asm ("mtibatu 2,%0" :: "r"(h->hatch_ibatu[2])); | | 1434 | __asm ("mtibatu 2,%0" :: "r"(h->hatch_ibatu[2])); |
1432 | __asm ("mtibatl 2,%0" :: "r"(h->hatch_ibatl[2])); | | 1435 | __asm ("mtibatl 2,%0" :: "r"(h->hatch_ibatl[2])); |
1433 | __asm ("mtibatu 3,%0" :: "r"(h->hatch_ibatu[3])); | | 1436 | __asm ("mtibatu 3,%0" :: "r"(h->hatch_ibatu[3])); |
1434 | __asm ("mtibatl 3,%0" :: "r"(h->hatch_ibatl[3])); | | 1437 | __asm ("mtibatl 3,%0" :: "r"(h->hatch_ibatl[3])); |
1435 | __asm ("mtdbatu 0,%0" :: "r"(h->hatch_dbatu[0])); | | 1438 | __asm ("mtdbatu 0,%0" :: "r"(h->hatch_dbatu[0])); |
1436 | __asm ("mtdbatl 0,%0" :: "r"(h->hatch_dbatl[0])); | | 1439 | __asm ("mtdbatl 0,%0" :: "r"(h->hatch_dbatl[0])); |
1437 | __asm ("mtdbatu 1,%0" :: "r"(h->hatch_dbatu[1])); | | 1440 | __asm ("mtdbatu 1,%0" :: "r"(h->hatch_dbatu[1])); |
1438 | __asm ("mtdbatl 1,%0" :: "r"(h->hatch_dbatl[1])); | | 1441 | __asm ("mtdbatl 1,%0" :: "r"(h->hatch_dbatl[1])); |
1439 | __asm ("mtdbatu 2,%0" :: "r"(h->hatch_dbatu[2])); | | 1442 | __asm ("mtdbatu 2,%0" :: "r"(h->hatch_dbatu[2])); |
1440 | __asm ("mtdbatl 2,%0" :: "r"(h->hatch_dbatl[2])); | | 1443 | __asm ("mtdbatl 2,%0" :: "r"(h->hatch_dbatl[2])); |
1441 | __asm ("mtdbatu 3,%0" :: "r"(h->hatch_dbatu[3])); | | 1444 | __asm ("mtdbatu 3,%0" :: "r"(h->hatch_dbatu[3])); |
1442 | __asm ("mtdbatl 3,%0" :: "r"(h->hatch_dbatl[3])); | | 1445 | __asm ("mtdbatl 3,%0" :: "r"(h->hatch_dbatl[3])); |
1443 | } | | 1446 | } |
1444 | | | 1447 | |
1445 | #ifdef PPC_OEA64_BRIDGE | | 1448 | #ifdef PPC_OEA64_BRIDGE |
1446 | if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) { | | 1449 | if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) { |
1447 | | | 1450 | |
1448 | mtspr64(SPR_HID0, h->hatch_hid0); | | 1451 | mtspr64(SPR_HID0, h->hatch_hid0); |
1449 | mtspr64(SPR_HID1, h->hatch_hid1); | | 1452 | mtspr64(SPR_HID1, h->hatch_hid1); |
1450 | mtspr64(SPR_HID4, h->hatch_hid4); | | 1453 | mtspr64(SPR_HID4, h->hatch_hid4); |
1451 | mtspr64(SPR_HID5, h->hatch_hid5); | | 1454 | mtspr64(SPR_HID5, h->hatch_hid5); |
1452 | mtspr64(SPR_HIOR, 0); | | 1455 | mtspr64(SPR_HIOR, 0); |
1453 | } else | | 1456 | } else |
1454 | #endif | | 1457 | #endif |
1455 | mtspr(SPR_HID0, h->hatch_hid0); | | 1458 | mtspr(SPR_HID0, h->hatch_hid0); |
1456 | | | 1459 | |
1457 | if ((oeacpufeat & OEACPU_NOBAT) == 0) { | | 1460 | if ((oeacpufeat & OEACPU_NOBAT) == 0) { |
1458 | __asm ("mtibatl 0,%0; mtibatu 0,%1; mtdbatl 0,%0; mtdbatu 0,%1;" | | 1461 | __asm ("mtibatl 0,%0; mtibatu 0,%1; mtdbatl 0,%0; mtdbatu 0,%1;" |
1459 | :: "r"(battable[0].batl), "r"(battable[0].batu)); | | 1462 | :: "r"(battable[0].batl), "r"(battable[0].batu)); |
1460 | } | | 1463 | } |
1461 | | | 1464 | |
1462 | __asm volatile ("sync"); | | 1465 | __asm volatile ("sync"); |
1463 | for (i = 0; i < 16; i++) | | 1466 | for (i = 0; i < 16; i++) |
1464 | __asm ("mtsrin %0,%1" :: "r"(h->hatch_sr[i]), "r"(i << ADDR_SR_SHFT)); | | 1467 | __asm ("mtsrin %0,%1" :: "r"(h->hatch_sr[i]), "r"(i << ADDR_SR_SHFT)); |
1465 | __asm volatile ("sync; isync"); | | 1468 | __asm volatile ("sync; isync"); |
1466 | | | 1469 | |
1467 | if (oeacpufeat & OEACPU_64) | | 1470 | if (oeacpufeat & OEACPU_64) |
1468 | mtspr(SPR_ASR, h->hatch_asr); | | 1471 | mtspr(SPR_ASR, h->hatch_asr); |
1469 | | | 1472 | |
1470 | cpu_spinstart_ack = 1; | | 1473 | cpu_spinstart_ack = 1; |
1471 | __asm ("ptesync"); | | 1474 | __asm ("ptesync"); |
1472 | __asm ("mtsdr1 %0" :: "r"(h->hatch_sdr1)); | | 1475 | __asm ("mtsdr1 %0" :: "r"(h->hatch_sdr1)); |
1473 | __asm volatile ("sync; isync"); | | 1476 | __asm volatile ("sync; isync"); |
1474 | | | 1477 | |
1475 | cpu_spinstart_ack = 5; | | 1478 | cpu_spinstart_ack = 5; |
1476 | for (i = 0; i < 16; i++) | | 1479 | for (i = 0; i < 16; i++) |
1477 | __asm ("mfsrin %0,%1" : "=r"(h->hatch_sr[i]) : | | 1480 | __asm ("mfsrin %0,%1" : "=r"(h->hatch_sr[i]) : |
1478 | "r"(i << ADDR_SR_SHFT)); | | 1481 | "r"(i << ADDR_SR_SHFT)); |
1479 | | | 1482 | |
1480 | /* Enable I/D address translations. */ | | 1483 | /* Enable I/D address translations. */ |
1481 | msr = mfmsr(); | | 1484 | msr = mfmsr(); |
1482 | msr |= PSL_IR|PSL_DR|PSL_ME|PSL_RI; | | 1485 | msr |= PSL_IR|PSL_DR|PSL_ME|PSL_RI; |
1483 | mtmsr(msr); | | 1486 | mtmsr(msr); |
1484 | __asm volatile ("sync; isync"); | | 1487 | __asm volatile ("sync; isync"); |
1485 | cpu_spinstart_ack = 2; | | 1488 | cpu_spinstart_ack = 2; |
1486 | | | 1489 | |
1487 | md_sync_timebase(h); | | 1490 | md_sync_timebase(h); |
1488 | | | 1491 | |
1489 | cpu_setup(h->hatch_self, ci); | | 1492 | cpu_setup(h->hatch_self, ci); |
1490 | | | 1493 | |
1491 | h->hatch_running = 1; | | 1494 | h->hatch_running = 1; |
1492 | __asm volatile ("sync; isync"); | | 1495 | __asm volatile ("sync; isync"); |
1493 | | | 1496 | |
1494 | while (start_secondary_cpu == 0) | | 1497 | while (start_secondary_cpu == 0) |
1495 | ; | | 1498 | ; |
1496 | | | 1499 | |
1497 | __asm volatile ("sync; isync"); | | 1500 | __asm volatile ("sync; isync"); |
1498 | | | 1501 | |
1499 | aprint_normal("cpu%d started\n", curcpu()->ci_index); | | 1502 | aprint_normal("cpu%d started\n", curcpu()->ci_index); |
1500 | __asm volatile ("mtdec %0" :: "r"(ticks_per_intr)); | | 1503 | __asm volatile ("mtdec %0" :: "r"(ticks_per_intr)); |
1501 | | | 1504 | |
1502 | md_setup_interrupts(); | | 1505 | md_setup_interrupts(); |
1503 | | | 1506 | |
1504 | ci->ci_ipending = 0; | | 1507 | ci->ci_ipending = 0; |
1505 | ci->ci_cpl = 0; | | 1508 | ci->ci_cpl = 0; |
1506 | | | 1509 | |
1507 | mtmsr(mfmsr() | PSL_EE); | | 1510 | mtmsr(mfmsr() | PSL_EE); |
1508 | pcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); | | 1511 | pcb = lwp_getpcb(ci->ci_data.cpu_idlelwp); |
1509 | return pcb->pcb_sp; | | 1512 | return pcb->pcb_sp; |
1510 | } | | 1513 | } |
1511 | | | 1514 | |
1512 | void | | 1515 | void |
1513 | cpu_boot_secondary_processors(void) | | 1516 | cpu_boot_secondary_processors(void) |
1514 | { | | 1517 | { |
1515 | start_secondary_cpu = 1; | | 1518 | start_secondary_cpu = 1; |
1516 | __asm volatile ("sync"); | | 1519 | __asm volatile ("sync"); |
1517 | } | | 1520 | } |
1518 | | | 1521 | |
1519 | #endif /*MULTIPROCESSOR*/ | | 1522 | #endif /*MULTIPROCESSOR*/ |