aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/cputable.c43
-rw-r--r--arch/powerpc/kernel/prom.c110
-rw-r--r--arch/powerpc/kernel/prom_init.c3
-rw-r--r--arch/powerpc/kernel/setup_32.c2
-rw-r--r--arch/powerpc/kernel/setup_64.c2
-rw-r--r--arch/powerpc/platforms/iseries/setup.c2
-rw-r--r--arch/ppc/kernel/setup.c2
-rw-r--r--include/asm-powerpc/cputable.h13
8 files changed, 130 insertions, 47 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index 992121b2d261..911ac442f44a 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -277,10 +277,45 @@ static struct cpu_spec cpu_specs[] = {
277 .oprofile_mmcra_sipr = MMCRA_SIPR, 277 .oprofile_mmcra_sipr = MMCRA_SIPR,
278 .platform = "power5+", 278 .platform = "power5+",
279 }, 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 },
280 { /* Power6 */ 297 { /* Power6 */
281 .pvr_mask = 0xffff0000, 298 .pvr_mask = 0xffff0000,
282 .pvr_value = 0x003e0000, 299 .pvr_value = 0x003e0000,
283 .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)",
284 .cpu_features = CPU_FTRS_POWER6, 319 .cpu_features = CPU_FTRS_POWER6,
285 .cpu_user_features = COMMON_USER_POWER6, 320 .cpu_user_features = COMMON_USER_POWER6,
286 .icache_bsize = 128, 321 .icache_bsize = 128,
@@ -1173,19 +1208,15 @@ static struct cpu_spec cpu_specs[] = {
1173#endif /* CONFIG_PPC32 */ 1208#endif /* CONFIG_PPC32 */
1174}; 1209};
1175 1210
1176struct cpu_spec *identify_cpu(unsigned long offset) 1211struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr)
1177{ 1212{
1178 struct cpu_spec *s = cpu_specs; 1213 struct cpu_spec *s = cpu_specs;
1179 struct cpu_spec **cur = &cur_cpu_spec; 1214 struct cpu_spec **cur = &cur_cpu_spec;
1180 unsigned int pvr = mfspr(SPRN_PVR);
1181 int i; 1215 int i;
1182 1216
1183 s = PTRRELOC(s); 1217 s = PTRRELOC(s);
1184 cur = PTRRELOC(cur); 1218 cur = PTRRELOC(cur);
1185 1219
1186 if (*cur != NULL)
1187 return PTRRELOC(*cur);
1188
1189 for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) 1220 for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++)
1190 if ((pvr & s->pvr_mask) == s->pvr_value) { 1221 if ((pvr & s->pvr_mask) == s->pvr_value) {
1191 *cur = cpu_specs + i; 1222 *cur = cpu_specs + i;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 16d29d16b96f..c18dbe77fdc2 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -538,35 +538,31 @@ static struct ibm_pa_feature {
538 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, 538 {CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
539}; 539};
540 540
541static void __init check_cpu_pa_features(unsigned long node) 541static void __init scan_features(unsigned long node, unsigned char *ftrs,
542 unsigned long tablelen,
543 struct ibm_pa_feature *fp,
544 unsigned long ft_size)
542{ 545{
543 unsigned char *pa_ftrs; 546 unsigned long i, len, bit;
544 unsigned long len, tablelen, i, bit;
545
546 pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
547 if (pa_ftrs == NULL)
548 return;
549 547
550 /* find descriptor with type == 0 */ 548 /* find descriptor with type == 0 */
551 for (;;) { 549 for (;;) {
552 if (tablelen < 3) 550 if (tablelen < 3)
553 return; 551 return;
554 len = 2 + pa_ftrs[0]; 552 len = 2 + ftrs[0];
555 if (tablelen < len) 553 if (tablelen < len)
556 return; /* descriptor 0 not found */ 554 return; /* descriptor 0 not found */
557 if (pa_ftrs[1] == 0) 555 if (ftrs[1] == 0)
558 break; 556 break;
559 tablelen -= len; 557 tablelen -= len;
560 pa_ftrs += len; 558 ftrs += len;
561 } 559 }
562 560
563 /* loop over bits we know about */ 561 /* loop over bits we know about */
564 for (i = 0; i < ARRAY_SIZE(ibm_pa_features); ++i) { 562 for (i = 0; i < ft_size; ++i, ++fp) {
565 struct ibm_pa_feature *fp = &ibm_pa_features[i]; 563 if (fp->pabyte >= ftrs[0])
566
567 if (fp->pabyte >= pa_ftrs[0])
568 continue; 564 continue;
569 bit = (pa_ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1; 565 bit = (ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;
570 if (bit ^ fp->invert) { 566 if (bit ^ fp->invert) {
571 cur_cpu_spec->cpu_features |= fp->cpu_features; 567 cur_cpu_spec->cpu_features |= fp->cpu_features;
572 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs; 568 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;
@@ -577,16 +573,59 @@ static void __init check_cpu_pa_features(unsigned long node)
577 } 573 }
578} 574}
579 575
576static void __init check_cpu_pa_features(unsigned long node)
577{
578 unsigned char *pa_ftrs;
579 unsigned long tablelen;
580
581 pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
582 if (pa_ftrs == NULL)
583 return;
584
585 scan_features(node, pa_ftrs, tablelen,
586 ibm_pa_features, ARRAY_SIZE(ibm_pa_features));
587}
588
589static struct feature_property {
590 const char *name;
591 u32 min_value;
592 unsigned long cpu_feature;
593 unsigned long cpu_user_ftr;
594} feature_properties[] __initdata = {
595#ifdef CONFIG_ALTIVEC
596 {"altivec", 0, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},
597 {"ibm,vmx", 1, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},
598#endif /* CONFIG_ALTIVEC */
599#ifdef CONFIG_PPC64
600 {"ibm,dfp", 1, 0, PPC_FEATURE_HAS_DFP},
601 {"ibm,purr", 1, CPU_FTR_PURR, 0},
602 {"ibm,spurr", 1, CPU_FTR_SPURR, 0},
603#endif /* CONFIG_PPC64 */
604};
605
606static void __init check_cpu_feature_properties(unsigned long node)
607{
608 unsigned long i;
609 struct feature_property *fp = feature_properties;
610 const u32 *prop;
611
612 for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) {
613 prop = of_get_flat_dt_prop(node, fp->name, NULL);
614 if (prop && *prop >= fp->min_value) {
615 cur_cpu_spec->cpu_features |= fp->cpu_feature;
616 cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftr;
617 }
618 }
619}
620
580static int __init early_init_dt_scan_cpus(unsigned long node, 621static int __init early_init_dt_scan_cpus(unsigned long node,
581 const char *uname, int depth, 622 const char *uname, int depth,
582 void *data) 623 void *data)
583{ 624{
584 static int logical_cpuid = 0; 625 static int logical_cpuid = 0;
585 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 626 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
586#ifdef CONFIG_ALTIVEC 627 const u32 *prop;
587 u32 *prop; 628 const u32 *intserv;
588#endif
589 u32 *intserv;
590 int i, nthreads; 629 int i, nthreads;
591 unsigned long len; 630 unsigned long len;
592 int found = 0; 631 int found = 0;
@@ -643,24 +682,27 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
643 intserv[i]); 682 intserv[i]);
644 boot_cpuid = logical_cpuid; 683 boot_cpuid = logical_cpuid;
645 set_hard_smp_processor_id(boot_cpuid, intserv[i]); 684 set_hard_smp_processor_id(boot_cpuid, intserv[i]);
646 }
647 685
648#ifdef CONFIG_ALTIVEC 686 /*
649 /* Check if we have a VMX and eventually update CPU features */ 687 * PAPR defines "logical" PVR values for cpus that
650 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); 688 * meet various levels of the architecture:
651 if (prop && (*prop) > 0) { 689 * 0x0f000001 Architecture version 2.04
652 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; 690 * 0x0f000002 Architecture version 2.05
653 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 691 * If the cpu-version property in the cpu node contains
654 } 692 * such a value, we call identify_cpu again with the
655 693 * logical PVR value in order to use the cpu feature
656 /* Same goes for Apple's "altivec" property */ 694 * bits appropriate for the architecture level.
657 prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); 695 *
658 if (prop) { 696 * A POWER6 partition in "POWER6 architected" mode
659 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; 697 * uses the 0x0f000002 PVR value; in POWER5+ mode
660 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 698 * it uses 0x0f000001.
699 */
700 prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
701 if (prop && (*prop & 0xff000000) == 0x0f000000)
702 identify_cpu(0, *prop);
661 } 703 }
662#endif /* CONFIG_ALTIVEC */
663 704
705 check_cpu_feature_properties(node);
664 check_cpu_pa_features(node); 706 check_cpu_pa_features(node);
665 707
666#ifdef CONFIG_PPC_PSERIES 708#ifdef CONFIG_PPC_PSERIES
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 8671eb634a92..396109a537cd 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -627,6 +627,7 @@ static void __init early_cmdline_parse(void)
627/* Option vector 3: processor options supported */ 627/* Option vector 3: processor options supported */
628#define OV3_FP 0x80 /* floating point */ 628#define OV3_FP 0x80 /* floating point */
629#define OV3_VMX 0x40 /* VMX/Altivec */ 629#define OV3_VMX 0x40 /* VMX/Altivec */
630#define OV3_DFP 0x20 /* decimal FP */
630 631
631/* Option vector 5: PAPR/OF options supported */ 632/* Option vector 5: PAPR/OF options supported */
632#define OV5_LPAR 0x80 /* logical partitioning supported */ 633#define OV5_LPAR 0x80 /* logical partitioning supported */
@@ -668,7 +669,7 @@ static unsigned char ibm_architecture_vec[] = {
668 /* option vector 3: processor options supported */ 669 /* option vector 3: processor options supported */
669 3 - 2, /* length */ 670 3 - 2, /* length */
670 0, /* don't ignore, don't halt */ 671 0, /* don't ignore, don't halt */
671 OV3_FP | OV3_VMX, 672 OV3_FP | OV3_VMX | OV3_DFP,
672 673
673 /* option vector 4: IBM PAPR implementation */ 674 /* option vector 4: IBM PAPR implementation */
674 2 - 2, /* length */ 675 2 - 2, /* length */
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 04df53a3c86d..61c65d19ef06 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -97,7 +97,7 @@ unsigned long __init early_init(unsigned long dt_ptr)
97 * Identify the CPU type and fix up code sections 97 * Identify the CPU type and fix up code sections
98 * that depend on which cpu we have. 98 * that depend on which cpu we have.
99 */ 99 */
100 spec = identify_cpu(offset); 100 spec = identify_cpu(offset, mfspr(SPRN_PVR));
101 101
102 do_feature_fixups(spec->cpu_features, 102 do_feature_fixups(spec->cpu_features,
103 PTRRELOC(&__start___ftr_fixup), 103 PTRRELOC(&__start___ftr_fixup),
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index f602a53b1b79..3733de30e84d 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -171,7 +171,7 @@ void __init setup_paca(int cpu)
171void __init early_setup(unsigned long dt_ptr) 171void __init early_setup(unsigned long dt_ptr)
172{ 172{
173 /* Identify CPU type */ 173 /* Identify CPU type */
174 identify_cpu(0); 174 identify_cpu(0, mfspr(SPRN_PVR));
175 175
176 /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ 176 /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
177 setup_paca(0); 177 setup_paca(0);
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 0f39bdbbf917..1796644ec7dc 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -677,7 +677,7 @@ void * __init iSeries_early_setup(void)
677 /* Identify CPU type. This is done again by the common code later 677 /* Identify CPU type. This is done again by the common code later
678 * on but calling this function multiple times is fine. 678 * on but calling this function multiple times is fine.
679 */ 679 */
680 identify_cpu(0); 680 identify_cpu(0, mfspr(SPRN_PVR));
681 681
682 powerpc_firmware_features |= FW_FEATURE_ISERIES; 682 powerpc_firmware_features |= FW_FEATURE_ISERIES;
683 powerpc_firmware_features |= FW_FEATURE_LPAR; 683 powerpc_firmware_features |= FW_FEATURE_LPAR;
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 27faeca2c7a2..3c506af19880 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -313,7 +313,7 @@ early_init(int r3, int r4, int r5)
313 * Identify the CPU type and fix up code sections 313 * Identify the CPU type and fix up code sections
314 * that depend on which cpu we have. 314 * that depend on which cpu we have.
315 */ 315 */
316 spec = identify_cpu(offset); 316 spec = identify_cpu(offset, mfspr(SPRN_PVR));
317 do_feature_fixups(spec->cpu_features, 317 do_feature_fixups(spec->cpu_features,
318 PTRRELOC(&__start___ftr_fixup), 318 PTRRELOC(&__start___ftr_fixup),
319 PTRRELOC(&__stop___ftr_fixup)); 319 PTRRELOC(&__stop___ftr_fixup));
diff --git a/include/asm-powerpc/cputable.h b/include/asm-powerpc/cputable.h
index 762d15e48879..d06222a5be5e 100644
--- a/include/asm-powerpc/cputable.h
+++ b/include/asm-powerpc/cputable.h
@@ -24,6 +24,8 @@
24#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 24#define PPC_FEATURE_ICACHE_SNOOP 0x00002000
25#define PPC_FEATURE_ARCH_2_05 0x00001000 25#define PPC_FEATURE_ARCH_2_05 0x00001000
26#define PPC_FEATURE_PA6T 0x00000800 26#define PPC_FEATURE_PA6T 0x00000800
27#define PPC_FEATURE_HAS_DFP 0x00000400
28#define PPC_FEATURE_POWER6_EXT 0x00000200
27 29
28#define PPC_FEATURE_TRUE_LE 0x00000002 30#define PPC_FEATURE_TRUE_LE 0x00000002
29#define PPC_FEATURE_PPC_LE 0x00000001 31#define PPC_FEATURE_PPC_LE 0x00000001
@@ -92,7 +94,7 @@ extern struct cpu_spec *cur_cpu_spec;
92 94
93extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; 95extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
94 96
95extern struct cpu_spec *identify_cpu(unsigned long offset); 97extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr);
96extern void do_feature_fixups(unsigned long value, void *fixup_start, 98extern void do_feature_fixups(unsigned long value, void *fixup_start,
97 void *fixup_end); 99 void *fixup_end);
98 100
@@ -149,6 +151,7 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
149#define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) 151#define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000)
150#define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) 152#define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000)
151#define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000) 153#define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000)
154#define CPU_FTR_SPURR LONG_ASM_CONST(0x0001000000000000)
152 155
153#ifndef __ASSEMBLY__ 156#ifndef __ASSEMBLY__
154 157
@@ -333,7 +336,13 @@ extern void do_feature_fixups(unsigned long value, void *fixup_start,
333 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ 336 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
334 CPU_FTR_MMCRA | CPU_FTR_SMT | \ 337 CPU_FTR_MMCRA | CPU_FTR_SMT | \
335 CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ 338 CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
336 CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_REAL_LE) 339 CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE)
340#define CPU_FTRS_POWER6X (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
341 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
342 CPU_FTR_MMCRA | CPU_FTR_SMT | \
343 CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \
344 CPU_FTR_PURR | CPU_FTR_CI_LARGE_PAGE | \
345 CPU_FTR_SPURR | CPU_FTR_REAL_LE)
337#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ 346#define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \
338 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ 347 CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
339 CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ 348 CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \