aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r--arch/powerpc/kernel/prom.c110
1 files changed, 76 insertions, 34 deletions
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