30
30
#define CPUID_WR_DATA_LEN 0x8
31
31
#define CPUID_RD_REG_LEN 0xa
32
32
#define CPUID_WR_REG_LEN 0x9
33
+ /* MSR */
34
+ #define MSR_RD_REG_LEN 0xa
35
+ #define MSR_WR_REG_LEN 0x8
36
+ #define MSR_RD_DATA_LEN 0x8
37
+ #define MSR_WR_DATA_LEN 0x7
33
38
34
39
/* CPUID MSR Command Ids */
35
40
#define CPUID_MCA_CMD 0x73
36
41
#define RD_CPUID_CMD 0x91
42
+ #define RD_MCA_CMD 0x86
37
43
38
44
/* CPUID MCAMSR mask & index */
39
45
#define CPUID_MCA_THRD_MASK GENMASK(15, 0)
@@ -76,6 +82,16 @@ static inline void prepare_cpuid_input_message(struct cpu_msr_indata *input,
76
82
input -> ext = ext_func ;
77
83
}
78
84
85
+ static inline void prepare_mca_msr_input_message (struct cpu_msr_indata * input ,
86
+ u8 thread_id , u32 data_in )
87
+ {
88
+ input -> rd_len = MSR_RD_DATA_LEN ;
89
+ input -> wr_len = MSR_WR_DATA_LEN ;
90
+ input -> proto_cmd = RD_MCA_CMD ;
91
+ input -> thread = thread_id << 1 ;
92
+ input -> value = data_in ;
93
+ }
94
+
79
95
static int sbrmi_get_rev (struct sbrmi_data * data )
80
96
{
81
97
unsigned int rev ;
@@ -171,6 +187,85 @@ static int rmi_cpuid_read(struct sbrmi_data *data,
171
187
return ret ;
172
188
}
173
189
190
+ /* MCA MSR protocol */
191
+ static int rmi_mca_msr_read (struct sbrmi_data * data ,
192
+ struct apml_mcamsr_msg * msg )
193
+ {
194
+ struct cpu_msr_outdata output = {0 };
195
+ struct cpu_msr_indata input = {0 };
196
+ int ret , val = 0 ;
197
+ int hw_status ;
198
+ u16 thread ;
199
+
200
+ mutex_lock (& data -> lock );
201
+ /* cache the rev value to identify if protocol is supported or not */
202
+ if (!data -> rev ) {
203
+ ret = sbrmi_get_rev (data );
204
+ if (ret < 0 )
205
+ goto exit_unlock ;
206
+ }
207
+ /* MCA MSR protocol for REV 0x10 is not supported*/
208
+ if (data -> rev == 0x10 ) {
209
+ ret = - EOPNOTSUPP ;
210
+ goto exit_unlock ;
211
+ }
212
+
213
+ thread = msg -> mcamsr_in_out << CPUID_MCA_THRD_INDEX & CPUID_MCA_THRD_MASK ;
214
+
215
+ /* Thread > 127, Thread128 CS register, 1'b1 needs to be set to 1 */
216
+ if (thread > 127 ) {
217
+ thread -= 128 ;
218
+ val = 1 ;
219
+ }
220
+ ret = regmap_write (data -> regmap , SBRMI_THREAD128CS , val );
221
+ if (ret < 0 )
222
+ goto exit_unlock ;
223
+
224
+ prepare_mca_msr_input_message (& input , thread ,
225
+ msg -> mcamsr_in_out & CPUID_MCA_FUNC_MASK );
226
+
227
+ ret = regmap_bulk_write (data -> regmap , CPUID_MCA_CMD ,
228
+ & input , MSR_WR_REG_LEN );
229
+ if (ret < 0 )
230
+ goto exit_unlock ;
231
+
232
+ /*
233
+ * For RMI Rev 0x20, new h/w status bit is introduced. which is used
234
+ * by firmware to indicate completion of commands (0x71, 0x72, 0x73).
235
+ * wait for the status bit to be set by the hardware before
236
+ * reading the data out.
237
+ */
238
+ ret = regmap_read_poll_timeout (data -> regmap , SBRMI_STATUS , hw_status ,
239
+ hw_status & HW_ALERT_MASK , 500 , 2000000 );
240
+ if (ret )
241
+ goto exit_unlock ;
242
+
243
+ ret = regmap_bulk_read (data -> regmap , CPUID_MCA_CMD ,
244
+ & output , MSR_RD_REG_LEN );
245
+ if (ret < 0 )
246
+ goto exit_unlock ;
247
+
248
+ ret = regmap_write (data -> regmap , SBRMI_STATUS ,
249
+ HW_ALERT_MASK );
250
+ if (ret < 0 )
251
+ goto exit_unlock ;
252
+
253
+ if (output .num_bytes != MSR_RD_REG_LEN - 1 ) {
254
+ ret = - EMSGSIZE ;
255
+ goto exit_unlock ;
256
+ }
257
+ if (output .status ) {
258
+ ret = - EPROTOTYPE ;
259
+ msg -> fw_ret_code = output .status ;
260
+ goto exit_unlock ;
261
+ }
262
+ msg -> mcamsr_in_out = output .value ;
263
+
264
+ exit_unlock :
265
+ mutex_unlock (& data -> lock );
266
+ return ret ;
267
+ }
268
+
174
269
int rmi_mailbox_xfer (struct sbrmi_data * data ,
175
270
struct apml_mbox_msg * msg )
176
271
{
@@ -289,6 +384,23 @@ static int apml_cpuid_xfer(struct sbrmi_data *data, struct apml_cpuid_msg __user
289
384
return copy_to_user (arg , & msg , sizeof (struct apml_cpuid_msg ));
290
385
}
291
386
387
+ static int apml_mcamsr_xfer (struct sbrmi_data * data , struct apml_mcamsr_msg __user * arg )
388
+ {
389
+ struct apml_mcamsr_msg msg = { 0 };
390
+ int ret ;
391
+
392
+ /* Copy the structure from user */
393
+ if (copy_from_user (& msg , arg , sizeof (struct apml_mcamsr_msg )))
394
+ return - EFAULT ;
395
+
396
+ /* MCAMSR Protocol */
397
+ ret = rmi_mca_msr_read (data , & msg );
398
+ if (ret && ret != - EPROTOTYPE )
399
+ return ret ;
400
+
401
+ return copy_to_user (arg , & msg , sizeof (struct apml_mcamsr_msg ));
402
+ }
403
+
292
404
static long sbrmi_ioctl (struct file * fp , unsigned int cmd , unsigned long arg )
293
405
{
294
406
void __user * argp = (void __user * )arg ;
@@ -300,6 +412,8 @@ static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
300
412
return apml_mailbox_xfer (data , argp );
301
413
case SBRMI_IOCTL_CPUID_CMD :
302
414
return apml_cpuid_xfer (data , argp );
415
+ case SBRMI_IOCTL_MCAMSR_CMD :
416
+ return apml_mcamsr_xfer (data , argp );
303
417
default :
304
418
return - ENOTTY ;
305
419
}
0 commit comments