aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorValentine Barshak <vbarshak@ru.mvista.com>2007-10-25 14:16:40 -0400
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2007-11-01 08:13:43 -0400
commitd1dfc35d3a62122b85ca975b80dcbf4a0da0bebc (patch)
tree61a5b0969dc452f77d3ad87ca851f1f4237a2219 /arch/powerpc/kernel
parent1d6b698764084510fe6168bb5b650165dced03ae (diff)
[POWERPC] 4xx: Workaround for the 440EP(x)/GR(x) processors identical PVR issue.
PowerPC 440EP(x) 440GR(x) processors have the same PVR values, since they have identical cores. However, FPU is not supported on GR(x) and enabling APU instruction broadcast in the CCR0 register (to enable FPU) may cause unpredictable results. There's no safe way to detect FPU support at runtime. This patch provides a workarund for the issue. We use a POWER6 "logical PVR approach". First, we identify all EP(x) and GR(x) processors as GR(x) ones (which is safe). Then we check the device tree cpu path. If we have a EP(x) processor entry, we call identify_cpu again with PVR | 0x8. This bit is always 0 in the real PVR. This way we enable FPU only for 440EP(x). Signed-off-by: Valentine Barshak <vbarshak@ru.mvista.com> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/cputable.c36
-rw-r--r--arch/powerpc/kernel/prom.c12
2 files changed, 40 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index d3fb7d0c6c1c..9ed351f3c966 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1104,6 +1104,16 @@ static struct cpu_spec __initdata cpu_specs[] = {
1104 { 1104 {
1105 .pvr_mask = 0xf0000fff, 1105 .pvr_mask = 0xf0000fff,
1106 .pvr_value = 0x40000850, 1106 .pvr_value = 0x40000850,
1107 .cpu_name = "440GR Rev. A",
1108 .cpu_features = CPU_FTRS_44X,
1109 .cpu_user_features = COMMON_USER_BOOKE,
1110 .icache_bsize = 32,
1111 .dcache_bsize = 32,
1112 .platform = "ppc440",
1113 },
1114 { /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
1115 .pvr_mask = 0xf0000fff,
1116 .pvr_value = 0x40000858,
1107 .cpu_name = "440EP Rev. A", 1117 .cpu_name = "440EP Rev. A",
1108 .cpu_features = CPU_FTRS_44X, 1118 .cpu_features = CPU_FTRS_44X,
1109 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, 1119 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
@@ -1115,28 +1125,27 @@ static struct cpu_spec __initdata cpu_specs[] = {
1115 { 1125 {
1116 .pvr_mask = 0xf0000fff, 1126 .pvr_mask = 0xf0000fff,
1117 .pvr_value = 0x400008d3, 1127 .pvr_value = 0x400008d3,
1118 .cpu_name = "440EP Rev. B", 1128 .cpu_name = "440GR Rev. B",
1119 .cpu_features = CPU_FTRS_44X, 1129 .cpu_features = CPU_FTRS_44X,
1120 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, 1130 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
1121 .icache_bsize = 32, 1131 .icache_bsize = 32,
1122 .dcache_bsize = 32, 1132 .dcache_bsize = 32,
1123 .cpu_setup = __setup_cpu_440ep,
1124 .platform = "ppc440", 1133 .platform = "ppc440",
1125 }, 1134 },
1126 { /* 440EPX */ 1135 { /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
1127 .pvr_mask = 0xf0000ffb, 1136 .pvr_mask = 0xf0000fff,
1128 .pvr_value = 0x200008D0, 1137 .pvr_value = 0x400008db,
1129 .cpu_name = "440EPX", 1138 .cpu_name = "440EP Rev. B",
1130 .cpu_features = CPU_FTRS_44X, 1139 .cpu_features = CPU_FTRS_44X,
1131 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, 1140 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
1132 .icache_bsize = 32, 1141 .icache_bsize = 32,
1133 .dcache_bsize = 32, 1142 .dcache_bsize = 32,
1134 .cpu_setup = __setup_cpu_440epx, 1143 .cpu_setup = __setup_cpu_440ep,
1135 .platform = "ppc440", 1144 .platform = "ppc440",
1136 }, 1145 },
1137 { /* 440GRX */ 1146 { /* 440GRX */
1138 .pvr_mask = 0xf0000ffb, 1147 .pvr_mask = 0xf0000ffb,
1139 .pvr_value = 0x200008D8, 1148 .pvr_value = 0x200008D0,
1140 .cpu_name = "440GRX", 1149 .cpu_name = "440GRX",
1141 .cpu_features = CPU_FTRS_44X, 1150 .cpu_features = CPU_FTRS_44X,
1142 .cpu_user_features = COMMON_USER_BOOKE, 1151 .cpu_user_features = COMMON_USER_BOOKE,
@@ -1145,6 +1154,17 @@ static struct cpu_spec __initdata cpu_specs[] = {
1145 .cpu_setup = __setup_cpu_440grx, 1154 .cpu_setup = __setup_cpu_440grx,
1146 .platform = "ppc440", 1155 .platform = "ppc440",
1147 }, 1156 },
1157 { /* Use logical PVR for 440EPx (logical pvr = pvr | 0x8) */
1158 .pvr_mask = 0xf0000ffb,
1159 .pvr_value = 0x200008D8,
1160 .cpu_name = "440EPX",
1161 .cpu_features = CPU_FTRS_44X,
1162 .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
1163 .icache_bsize = 32,
1164 .dcache_bsize = 32,
1165 .cpu_setup = __setup_cpu_440epx,
1166 .platform = "ppc440",
1167 },
1148 { /* 440GP Rev. B */ 1168 { /* 440GP Rev. B */
1149 .pvr_mask = 0xf0000fff, 1169 .pvr_mask = 0xf0000fff,
1150 .pvr_value = 0x40000440, 1170 .pvr_value = 0x40000440,
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9f329a8928ea..acc0d247d3c3 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -697,6 +697,18 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
697 prop = of_get_flat_dt_prop(node, "cpu-version", NULL); 697 prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
698 if (prop && (*prop & 0xff000000) == 0x0f000000) 698 if (prop && (*prop & 0xff000000) == 0x0f000000)
699 identify_cpu(0, *prop); 699 identify_cpu(0, *prop);
700#if defined(CONFIG_44x) && defined(CONFIG_PPC_FPU)
701 /*
702 * Since 440GR(x)/440EP(x) processors have the same pvr,
703 * we check the node path and set bit 28 in the cur_cpu_spec
704 * pvr for EP(x) processor version. This bit is always 0 in
705 * the "real" pvr. Then we call identify_cpu again with
706 * the new logical pvr to enable FPU support.
707 */
708 if (strstr(uname, "440EP")) {
709 identify_cpu(0, cur_cpu_spec->pvr_value | 0x8);
710 }
711#endif
700 } 712 }
701 713
702 check_cpu_feature_properties(node); 714 check_cpu_feature_properties(node);