diff options
Diffstat (limited to 'arch/powerpc/kernel/cputable.c')
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 143 |
1 files changed, 136 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 47a613cdd775..b742013bb9da 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <asm/oprofile_impl.h> | 19 | #include <asm/oprofile_impl.h> |
20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
21 | #include <asm/prom.h> /* for PTRRELOC on ARCH=ppc */ | ||
21 | 22 | ||
22 | struct cpu_spec* cur_cpu_spec = NULL; | 23 | struct cpu_spec* cur_cpu_spec = NULL; |
23 | EXPORT_SYMBOL(cur_cpu_spec); | 24 | EXPORT_SYMBOL(cur_cpu_spec); |
@@ -41,6 +42,7 @@ extern void __setup_cpu_745x(unsigned long offset, struct cpu_spec* spec); | |||
41 | #endif /* CONFIG_PPC32 */ | 42 | #endif /* CONFIG_PPC32 */ |
42 | #ifdef CONFIG_PPC64 | 43 | #ifdef CONFIG_PPC64 |
43 | extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); | 44 | extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); |
45 | extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec); | ||
44 | extern void __restore_cpu_ppc970(void); | 46 | extern void __restore_cpu_ppc970(void); |
45 | #endif /* CONFIG_PPC64 */ | 47 | #endif /* CONFIG_PPC64 */ |
46 | 48 | ||
@@ -73,7 +75,7 @@ extern void __restore_cpu_ppc970(void); | |||
73 | #define PPC_FEATURE_SPE_COMP 0 | 75 | #define PPC_FEATURE_SPE_COMP 0 |
74 | #endif | 76 | #endif |
75 | 77 | ||
76 | struct cpu_spec cpu_specs[] = { | 78 | static struct cpu_spec cpu_specs[] = { |
77 | #ifdef CONFIG_PPC64 | 79 | #ifdef CONFIG_PPC64 |
78 | { /* Power3 */ | 80 | { /* Power3 */ |
79 | .pvr_mask = 0xffff0000, | 81 | .pvr_mask = 0xffff0000, |
@@ -221,8 +223,23 @@ struct cpu_spec cpu_specs[] = { | |||
221 | .icache_bsize = 128, | 223 | .icache_bsize = 128, |
222 | .dcache_bsize = 128, | 224 | .dcache_bsize = 128, |
223 | .num_pmcs = 8, | 225 | .num_pmcs = 8, |
224 | .cpu_setup = __setup_cpu_ppc970, | 226 | .cpu_setup = __setup_cpu_ppc970MP, |
225 | .cpu_restore = __restore_cpu_ppc970, | 227 | .cpu_restore = __restore_cpu_ppc970, |
228 | .oprofile_cpu_type = "ppc64/970MP", | ||
229 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
230 | .platform = "ppc970", | ||
231 | }, | ||
232 | { /* PPC970GX */ | ||
233 | .pvr_mask = 0xffff0000, | ||
234 | .pvr_value = 0x00450000, | ||
235 | .cpu_name = "PPC970GX", | ||
236 | .cpu_features = CPU_FTRS_PPC970, | ||
237 | .cpu_user_features = COMMON_USER_POWER4 | | ||
238 | PPC_FEATURE_HAS_ALTIVEC_COMP, | ||
239 | .icache_bsize = 128, | ||
240 | .dcache_bsize = 128, | ||
241 | .num_pmcs = 8, | ||
242 | .cpu_setup = __setup_cpu_ppc970, | ||
226 | .oprofile_cpu_type = "ppc64/970", | 243 | .oprofile_cpu_type = "ppc64/970", |
227 | .oprofile_type = PPC_OPROFILE_POWER4, | 244 | .oprofile_type = PPC_OPROFILE_POWER4, |
228 | .platform = "ppc970", | 245 | .platform = "ppc970", |
@@ -260,15 +277,50 @@ struct cpu_spec cpu_specs[] = { | |||
260 | .oprofile_mmcra_sipr = MMCRA_SIPR, | 277 | .oprofile_mmcra_sipr = MMCRA_SIPR, |
261 | .platform = "power5+", | 278 | .platform = "power5+", |
262 | }, | 279 | }, |
280 | { /* POWER6 in P5+ mode; 2.04-compliant processor */ | ||
281 | .pvr_mask = 0xffffffff, | ||
282 | .pvr_value = 0x0f000001, | ||
283 | .cpu_name = "POWER5+", | ||
284 | .cpu_features = CPU_FTRS_POWER5, | ||
285 | .cpu_user_features = COMMON_USER_POWER5_PLUS, | ||
286 | .icache_bsize = 128, | ||
287 | .dcache_bsize = 128, | ||
288 | .num_pmcs = 6, | ||
289 | .oprofile_cpu_type = "ppc64/power6", | ||
290 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
291 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
292 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
293 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
294 | POWER6_MMCRA_OTHER, | ||
295 | .platform = "power5+", | ||
296 | }, | ||
263 | { /* Power6 */ | 297 | { /* Power6 */ |
264 | .pvr_mask = 0xffff0000, | 298 | .pvr_mask = 0xffff0000, |
265 | .pvr_value = 0x003e0000, | 299 | .pvr_value = 0x003e0000, |
266 | .cpu_name = "POWER6", | 300 | .cpu_name = "POWER6 (raw)", |
301 | .cpu_features = CPU_FTRS_POWER6, | ||
302 | .cpu_user_features = COMMON_USER_POWER6 | | ||
303 | PPC_FEATURE_POWER6_EXT, | ||
304 | .icache_bsize = 128, | ||
305 | .dcache_bsize = 128, | ||
306 | .num_pmcs = 6, | ||
307 | .oprofile_cpu_type = "ppc64/power6", | ||
308 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
309 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
310 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
311 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
312 | POWER6_MMCRA_OTHER, | ||
313 | .platform = "power6x", | ||
314 | }, | ||
315 | { /* 2.05-compliant processor, i.e. Power6 "architected" mode */ | ||
316 | .pvr_mask = 0xffffffff, | ||
317 | .pvr_value = 0x0f000002, | ||
318 | .cpu_name = "POWER6 (architected)", | ||
267 | .cpu_features = CPU_FTRS_POWER6, | 319 | .cpu_features = CPU_FTRS_POWER6, |
268 | .cpu_user_features = COMMON_USER_POWER6, | 320 | .cpu_user_features = COMMON_USER_POWER6, |
269 | .icache_bsize = 128, | 321 | .icache_bsize = 128, |
270 | .dcache_bsize = 128, | 322 | .dcache_bsize = 128, |
271 | .num_pmcs = 8, | 323 | .num_pmcs = 6, |
272 | .oprofile_cpu_type = "ppc64/power6", | 324 | .oprofile_cpu_type = "ppc64/power6", |
273 | .oprofile_type = PPC_OPROFILE_POWER4, | 325 | .oprofile_type = PPC_OPROFILE_POWER4, |
274 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | 326 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, |
@@ -287,6 +339,9 @@ struct cpu_spec cpu_specs[] = { | |||
287 | PPC_FEATURE_SMT, | 339 | PPC_FEATURE_SMT, |
288 | .icache_bsize = 128, | 340 | .icache_bsize = 128, |
289 | .dcache_bsize = 128, | 341 | .dcache_bsize = 128, |
342 | .num_pmcs = 4, | ||
343 | .oprofile_cpu_type = "ppc64/cell-be", | ||
344 | .oprofile_type = PPC_OPROFILE_CELL, | ||
290 | .platform = "ppc-cell-be", | 345 | .platform = "ppc-cell-be", |
291 | }, | 346 | }, |
292 | { /* PA Semi PA6T */ | 347 | { /* PA Semi PA6T */ |
@@ -778,13 +833,24 @@ struct cpu_spec cpu_specs[] = { | |||
778 | .pvr_mask = 0x7fff0000, | 833 | .pvr_mask = 0x7fff0000, |
779 | .pvr_value = 0x00840000, | 834 | .pvr_value = 0x00840000, |
780 | .cpu_name = "e300c2", | 835 | .cpu_name = "e300c2", |
781 | .cpu_features = CPU_FTRS_E300, | 836 | .cpu_features = CPU_FTRS_E300C2, |
782 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 837 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, |
783 | .icache_bsize = 32, | 838 | .icache_bsize = 32, |
784 | .dcache_bsize = 32, | 839 | .dcache_bsize = 32, |
785 | .cpu_setup = __setup_cpu_603, | 840 | .cpu_setup = __setup_cpu_603, |
786 | .platform = "ppc603", | 841 | .platform = "ppc603", |
787 | }, | 842 | }, |
843 | { /* e300c3 on 83xx */ | ||
844 | .pvr_mask = 0x7fff0000, | ||
845 | .pvr_value = 0x00850000, | ||
846 | .cpu_name = "e300c3", | ||
847 | .cpu_features = CPU_FTRS_E300, | ||
848 | .cpu_user_features = COMMON_USER, | ||
849 | .icache_bsize = 32, | ||
850 | .dcache_bsize = 32, | ||
851 | .cpu_setup = __setup_cpu_603, | ||
852 | .platform = "ppc603", | ||
853 | }, | ||
788 | { /* default match, we assume split I/D cache & TB (non-601)... */ | 854 | { /* default match, we assume split I/D cache & TB (non-601)... */ |
789 | .pvr_mask = 0x00000000, | 855 | .pvr_mask = 0x00000000, |
790 | .pvr_value = 0x00000000, | 856 | .pvr_value = 0x00000000, |
@@ -1070,8 +1136,7 @@ struct cpu_spec cpu_specs[] = { | |||
1070 | .pvr_mask = 0xff000fff, | 1136 | .pvr_mask = 0xff000fff, |
1071 | .pvr_value = 0x53000890, | 1137 | .pvr_value = 0x53000890, |
1072 | .cpu_name = "440SPe Rev. A", | 1138 | .cpu_name = "440SPe Rev. A", |
1073 | .cpu_features = CPU_FTR_SPLIT_ID_CACHE | | 1139 | .cpu_features = CPU_FTRS_44X, |
1074 | CPU_FTR_USE_TB, | ||
1075 | .cpu_user_features = COMMON_USER_BOOKE, | 1140 | .cpu_user_features = COMMON_USER_BOOKE, |
1076 | .icache_bsize = 32, | 1141 | .icache_bsize = 32, |
1077 | .dcache_bsize = 32, | 1142 | .dcache_bsize = 32, |
@@ -1152,3 +1217,67 @@ struct cpu_spec cpu_specs[] = { | |||
1152 | #endif /* !CLASSIC_PPC */ | 1217 | #endif /* !CLASSIC_PPC */ |
1153 | #endif /* CONFIG_PPC32 */ | 1218 | #endif /* CONFIG_PPC32 */ |
1154 | }; | 1219 | }; |
1220 | |||
1221 | struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr) | ||
1222 | { | ||
1223 | struct cpu_spec *s = cpu_specs; | ||
1224 | struct cpu_spec **cur = &cur_cpu_spec; | ||
1225 | int i; | ||
1226 | |||
1227 | s = PTRRELOC(s); | ||
1228 | cur = PTRRELOC(cur); | ||
1229 | |||
1230 | for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) | ||
1231 | if ((pvr & s->pvr_mask) == s->pvr_value) { | ||
1232 | *cur = cpu_specs + i; | ||
1233 | #ifdef CONFIG_PPC64 | ||
1234 | /* ppc64 expects identify_cpu to also call setup_cpu | ||
1235 | * for that processor. I will consolidate that at a | ||
1236 | * later time, for now, just use our friend #ifdef. | ||
1237 | * we also don't need to PTRRELOC the function pointer | ||
1238 | * on ppc64 as we are running at 0 in real mode. | ||
1239 | */ | ||
1240 | if (s->cpu_setup) { | ||
1241 | s->cpu_setup(offset, s); | ||
1242 | } | ||
1243 | #endif /* CONFIG_PPC64 */ | ||
1244 | return s; | ||
1245 | } | ||
1246 | BUG(); | ||
1247 | return NULL; | ||
1248 | } | ||
1249 | |||
1250 | void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) | ||
1251 | { | ||
1252 | struct fixup_entry { | ||
1253 | unsigned long mask; | ||
1254 | unsigned long value; | ||
1255 | long start_off; | ||
1256 | long end_off; | ||
1257 | } *fcur, *fend; | ||
1258 | |||
1259 | fcur = fixup_start; | ||
1260 | fend = fixup_end; | ||
1261 | |||
1262 | for (; fcur < fend; fcur++) { | ||
1263 | unsigned int *pstart, *pend, *p; | ||
1264 | |||
1265 | if ((value & fcur->mask) == fcur->value) | ||
1266 | continue; | ||
1267 | |||
1268 | /* These PTRRELOCs will disappear once the new scheme for | ||
1269 | * modules and vdso is implemented | ||
1270 | */ | ||
1271 | pstart = ((unsigned int *)fcur) + (fcur->start_off / 4); | ||
1272 | pend = ((unsigned int *)fcur) + (fcur->end_off / 4); | ||
1273 | |||
1274 | for (p = pstart; p < pend; p++) { | ||
1275 | *p = 0x60000000u; | ||
1276 | asm volatile ("dcbst 0, %0" : : "r" (p)); | ||
1277 | } | ||
1278 | asm volatile ("sync" : : : "memory"); | ||
1279 | for (p = pstart; p < pend; p++) | ||
1280 | asm volatile ("icbi 0,%0" : : "r" (p)); | ||
1281 | asm volatile ("sync; isync" : : : "memory"); | ||
1282 | } | ||
1283 | } | ||