summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/prom_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r--arch/powerpc/kernel/prom_init.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 53503937de0e..eb9f556b0937 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -86,6 +86,12 @@
*/
#define ADDR(x) (u32)(unsigned long)(x)
+/*
+ * Current Power system firmware caps the PVR list array size at 16 entries
+ * during CAS (Client Architecture Support) negotiation.
+ */
+#define CAS_MAX_PVR_ENTRIES 16
+
#ifdef CONFIG_PPC64
#define OF_WORKAROUNDS 0
#else
@@ -947,7 +953,7 @@ struct option_vector7 {
} __packed;
struct ibm_arch_vec {
- struct { __be32 mask, val; } pvrs[16];
+ struct { __be32 mask, val; } pvrs[18];
u8 num_vectors;
@@ -980,6 +986,10 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.val = cpu_to_be32(0x003a0000),
},
{
+ .mask = cpu_to_be32(0xffffffff), /* all 2.04-compliant and earlier */
+ .val = cpu_to_be32(0x0f000001),
+ },
+ {
.mask = cpu_to_be32(0xffff0000), /* POWER6 */
.val = cpu_to_be32(0x003e0000),
},
@@ -1012,6 +1022,14 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.val = cpu_to_be32(0x00820000),
},
{
+ .mask = cpu_to_be32(0xffff0000), /* POWER12 */
+ .val = cpu_to_be32(0x00830000),
+ },
+ {
+ .mask = cpu_to_be32(0xffffffff), /* all 3.2-compliant */
+ .val = cpu_to_be32(0x0f000008),
+ },
+ {
.mask = cpu_to_be32(0xffffffff), /* P11 compliant */
.val = cpu_to_be32(0x0f000007),
},
@@ -1032,13 +1050,9 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.val = cpu_to_be32(0x0f000003),
},
{
- .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
+ .mask = cpu_to_be32(0xfffffffd), /* all 2.05-compliant */
.val = cpu_to_be32(0x0f000002),
},
- {
- .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
- .val = cpu_to_be32(0x0f000001),
- },
},
.num_vectors = NUM_VECTORS(6),
@@ -1048,7 +1062,7 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.byte1 = 0,
.arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
- .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1,
+ .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1 | OV1_PPC_3_2,
},
.vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
@@ -1403,6 +1417,22 @@ static void __init prom_send_capabilities(void)
ihandle root;
prom_arg_t ret;
u32 cores;
+ int start_index = 0;
+
+ /*
+ * Ensure that when running on Power11 or below hardware, the number
+ * of PVR entries passed during CAS negotiation does not exceed the
+ * firmware-imposed limit of 16.
+ *
+ * Compute the start_index to skip the oldest leading pvrs[] entries
+ * when running on Power11 or below hardware, so that the pointer
+ * passed to ibm,client-architecture-support points to
+ * ibm_architecture_vec.pvrs[start_index], presenting exactly 16
+ * entries to firmware.
+ */
+ if ((ARRAY_SIZE(ibm_architecture_vec_template.pvrs) > CAS_MAX_PVR_ENTRIES) &&
+ (PVR_VER(mfspr(SPRN_PVR)) <= PVR_POWER11))
+ start_index = ARRAY_SIZE(ibm_architecture_vec_template.pvrs) - CAS_MAX_PVR_ENTRIES;
/* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
prom_check_platform_support();
@@ -1427,7 +1457,7 @@ static void __init prom_send_capabilities(void)
if (call_prom_ret("call-method", 3, 2, &ret,
ADDR("ibm,client-architecture-support"),
root,
- ADDR(&ibm_architecture_vec)) == 0) {
+ ADDR(&ibm_architecture_vec.pvrs[start_index])) == 0) {
/* the call exists... */
if (ret)
prom_printf("\nWARNING: ibm,client-architecture"