]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
misc: amd-sbi: Extend support for CPUID protocol for rev 0x21
authorAkshay Gupta <akshay.gupta@amd.com>
Mon, 15 Sep 2025 10:36:48 +0000 (10:36 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Oct 2025 05:59:57 +0000 (07:59 +0200)
- CPUID protocol for revision 0x21 is updated to include the
  extended thread supported by the platform.
- This modifies the existing protocol to include additional byte
  to provide high thread number.
- New input structure is defined to address this, as the hardware
  protocol is tightly coupled with the input structure length

Reviewed-by: Naveen Krishna Chatradhi <naveenkrishna.chatradhi@amd.com>
Signed-off-by: Akshay Gupta <akshay.gupta@amd.com>
Link: https://patch.msgid.link/20250915103649.1705078-5-akshay.gupta@amd.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/amd-sbi/rmi-core.c

index bf534ba757dbe4edd70dfee91eeaf8b49be855b5..ef93dce7e038a585712989eb72f85611e1b61671 100644 (file)
 /* CPUID */
 #define CPUID_RD_DATA_LEN      0x8
 #define CPUID_WR_DATA_LEN      0x8
+#define CPUID_WR_DATA_LEN_EXT  0x9
 #define CPUID_RD_REG_LEN       0xa
 #define CPUID_WR_REG_LEN       0x9
+#define CPUID_WR_REG_LEN_EXT   0xa
 /* MSR */
 #define MSR_RD_REG_LEN         0xa
 #define MSR_WR_REG_LEN         0x8
@@ -59,6 +61,20 @@ struct cpu_msr_indata {
        u8 ext; /* extended function */
 };
 
+/* input for bulk write to CPUID protocol for REV 0x21 */
+struct cpu_msr_indata_ext {
+       u8 wr_len;      /* const value */
+       u8 rd_len;      /* const value */
+       u8 proto_cmd;   /* const value */
+       u8 thread_lo;   /* thread number low */
+       u8 thread_hi;   /* thread number high */
+       union {
+               u8 reg_offset[4];       /* input value */
+               u32 value;
+       } __packed;
+       u8 ext; /* extended function */
+};
+
 /* output for bulk read from CPUID protocol */
 struct cpu_msr_outdata {
        u8 num_bytes;   /* number of bytes return */
@@ -81,6 +97,19 @@ static inline void prepare_cpuid_input_message(struct cpu_msr_indata *input,
        input->ext              = ext_func;
 }
 
+static inline void prepare_cpuid_input_message_ext(struct cpu_msr_indata_ext *input,
+                                                  u16 thread_id, u32 func,
+                                                  u8 ext_func)
+{
+       input->rd_len           = CPUID_RD_DATA_LEN;
+       input->wr_len           = CPUID_WR_DATA_LEN_EXT;
+       input->proto_cmd        = RD_CPUID_CMD;
+       input->thread_lo        = (thread_id & 0xFF) << 1;
+       input->thread_hi        = thread_id >> 8;
+       input->value            = func;
+       input->ext              = ext_func;
+}
+
 static inline void prepare_mca_msr_input_message(struct cpu_msr_indata *input,
                                                 u8 thread_id, u32 data_in)
 {
@@ -105,13 +134,48 @@ static int sbrmi_get_rev(struct sbrmi_data *data)
        return 0;
 }
 
+static int rmi_cpuid_input(struct sbrmi_data *data, struct apml_cpuid_msg *msg,
+                          u16 thread)
+{
+       struct cpu_msr_indata input = {0};
+       int val = 0, ret;
+
+       /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */
+       if (thread > 127) {
+               thread -= 128;
+               val = 1;
+       }
+
+       ret = regmap_write(data->regmap, SBRMI_THREAD128CS, val);
+       if (ret < 0)
+               return ret;
+
+       prepare_cpuid_input_message(&input, thread,
+                                   msg->cpu_in_out & CPUID_MCA_FUNC_MASK,
+                                   msg->cpu_in_out >> CPUID_EXT_FUNC_INDEX);
+
+       return regmap_bulk_write(data->regmap, CPUID_MCA_CMD,
+                                &input, CPUID_WR_REG_LEN);
+}
+
+static int rmi_cpuid_input_ext(struct sbrmi_data *data, struct apml_cpuid_msg *msg,
+                              u16 thread)
+{
+       struct cpu_msr_indata_ext input = {0};
+
+       prepare_cpuid_input_message_ext(&input, thread,
+                                       msg->cpu_in_out & CPUID_MCA_FUNC_MASK,
+                                       msg->cpu_in_out >> CPUID_EXT_FUNC_INDEX);
+
+       return regmap_bulk_write(data->regmap, CPUID_MCA_CMD,
+                                &input, CPUID_WR_REG_LEN_EXT);
+}
+
 /* Read CPUID function protocol */
 static int rmi_cpuid_read(struct sbrmi_data *data,
                          struct apml_cpuid_msg *msg)
 {
-       struct cpu_msr_indata input = {0};
        struct cpu_msr_outdata output = {0};
-       int val = 0;
        int ret, hw_status;
        u16 thread;
 
@@ -122,31 +186,29 @@ static int rmi_cpuid_read(struct sbrmi_data *data,
                if (ret < 0)
                        goto exit_unlock;
        }
-       /* CPUID protocol for REV 0x20 is only supported*/
-       if (data->rev != 0x20) {
-               ret = -EOPNOTSUPP;
-               goto exit_unlock;
-       }
 
+       /* Extract thread from the input msg structure */
        thread = msg->cpu_in_out >> CPUID_MCA_THRD_INDEX;
 
-       /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */
-       if (thread > 127) {
-               thread -= 128;
-               val = 1;
-       }
-       ret = regmap_write(data->regmap, SBRMI_THREAD128CS, val);
-       if (ret < 0)
+       switch (data->rev) {
+       case 0x10:
+               /* CPUID protocol for REV 0x10 is not supported*/
+               ret = -EOPNOTSUPP;
                goto exit_unlock;
-
-       prepare_cpuid_input_message(&input, thread,
-                                   msg->cpu_in_out & CPUID_MCA_FUNC_MASK,
-                                   msg->cpu_in_out >> CPUID_EXT_FUNC_INDEX);
-
-       ret = regmap_bulk_write(data->regmap, CPUID_MCA_CMD,
-                               &input, CPUID_WR_REG_LEN);
-       if (ret < 0)
+       case 0x20:
+               ret = rmi_cpuid_input(data, msg, thread);
+               if (ret)
+                       goto exit_unlock;
+               break;
+       case 0x21:
+               ret = rmi_cpuid_input_ext(data, msg, thread);
+               if (ret)
+                       goto exit_unlock;
+               break;
+       default:
+               ret = -EOPNOTSUPP;
                goto exit_unlock;
+       }
 
        /*
         * For RMI Rev 0x20, new h/w status bit is introduced. which is used