aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/cputable.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/cputable.c')
-rw-r--r--arch/powerpc/kernel/cputable.c143
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
22struct cpu_spec* cur_cpu_spec = NULL; 23struct cpu_spec* cur_cpu_spec = NULL;
23EXPORT_SYMBOL(cur_cpu_spec); 24EXPORT_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
43extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); 44extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
45extern void __setup_cpu_ppc970MP(unsigned long offset, struct cpu_spec* spec);
44extern void __restore_cpu_ppc970(void); 46extern 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
76struct cpu_spec cpu_specs[] = { 78static 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
1221struct 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
1250void 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}