Commit d1dfc35d authored by Valentine Barshak's avatar Valentine Barshak Committed by Josh Boyer

[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: default avatarValentine Barshak <vbarshak@ru.mvista.com>
Signed-off-by: default avatarJosh Boyer <jwboyer@linux.vnet.ibm.com>
parent 1d6b6987
...@@ -1104,6 +1104,16 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -1104,6 +1104,16 @@ static struct cpu_spec __initdata cpu_specs[] = {
{ {
.pvr_mask = 0xf0000fff, .pvr_mask = 0xf0000fff,
.pvr_value = 0x40000850, .pvr_value = 0x40000850,
.cpu_name = "440GR Rev. A",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
.platform = "ppc440",
},
{ /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
.pvr_mask = 0xf0000fff,
.pvr_value = 0x40000858,
.cpu_name = "440EP Rev. A", .cpu_name = "440EP Rev. A",
.cpu_features = CPU_FTRS_44X, .cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
...@@ -1115,28 +1125,27 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -1115,28 +1125,27 @@ static struct cpu_spec __initdata cpu_specs[] = {
{ {
.pvr_mask = 0xf0000fff, .pvr_mask = 0xf0000fff,
.pvr_value = 0x400008d3, .pvr_value = 0x400008d3,
.cpu_name = "440EP Rev. B", .cpu_name = "440GR Rev. B",
.cpu_features = CPU_FTRS_44X, .cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.cpu_setup = __setup_cpu_440ep,
.platform = "ppc440", .platform = "ppc440",
}, },
{ /* 440EPX */ { /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
.pvr_mask = 0xf0000ffb, .pvr_mask = 0xf0000fff,
.pvr_value = 0x200008D0, .pvr_value = 0x400008db,
.cpu_name = "440EPX", .cpu_name = "440EP Rev. B",
.cpu_features = CPU_FTRS_44X, .cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32, .icache_bsize = 32,
.dcache_bsize = 32, .dcache_bsize = 32,
.cpu_setup = __setup_cpu_440epx, .cpu_setup = __setup_cpu_440ep,
.platform = "ppc440", .platform = "ppc440",
}, },
{ /* 440GRX */ { /* 440GRX */
.pvr_mask = 0xf0000ffb, .pvr_mask = 0xf0000ffb,
.pvr_value = 0x200008D8, .pvr_value = 0x200008D0,
.cpu_name = "440GRX", .cpu_name = "440GRX",
.cpu_features = CPU_FTRS_44X, .cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE, .cpu_user_features = COMMON_USER_BOOKE,
...@@ -1145,6 +1154,17 @@ static struct cpu_spec __initdata cpu_specs[] = { ...@@ -1145,6 +1154,17 @@ static struct cpu_spec __initdata cpu_specs[] = {
.cpu_setup = __setup_cpu_440grx, .cpu_setup = __setup_cpu_440grx,
.platform = "ppc440", .platform = "ppc440",
}, },
{ /* Use logical PVR for 440EPx (logical pvr = pvr | 0x8) */
.pvr_mask = 0xf0000ffb,
.pvr_value = 0x200008D8,
.cpu_name = "440EPX",
.cpu_features = CPU_FTRS_44X,
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_440epx,
.platform = "ppc440",
},
{ /* 440GP Rev. B */ { /* 440GP Rev. B */
.pvr_mask = 0xf0000fff, .pvr_mask = 0xf0000fff,
.pvr_value = 0x40000440, .pvr_value = 0x40000440,
......
...@@ -697,6 +697,18 @@ static int __init early_init_dt_scan_cpus(unsigned long node, ...@@ -697,6 +697,18 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
prop = of_get_flat_dt_prop(node, "cpu-version", NULL); prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
if (prop && (*prop & 0xff000000) == 0x0f000000) if (prop && (*prop & 0xff000000) == 0x0f000000)
identify_cpu(0, *prop); identify_cpu(0, *prop);
#if defined(CONFIG_44x) && defined(CONFIG_PPC_FPU)
/*
* Since 440GR(x)/440EP(x) processors have the same pvr,
* we check the node path and set bit 28 in the cur_cpu_spec
* pvr for EP(x) processor version. This bit is always 0 in
* the "real" pvr. Then we call identify_cpu again with
* the new logical pvr to enable FPU support.
*/
if (strstr(uname, "440EP")) {
identify_cpu(0, cur_cpu_spec->pvr_value | 0x8);
}
#endif
} }
check_cpu_feature_properties(node); check_cpu_feature_properties(node);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment