3030#define CPUID_WR_DATA_LEN 0x8
3131#define CPUID_RD_REG_LEN 0xa
3232#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
3338
3439/* CPUID MSR Command Ids */
3540#define CPUID_MCA_CMD 0x73
3641#define RD_CPUID_CMD 0x91
42+ #define RD_MCA_CMD 0x86
3743
3844/* CPUID MCAMSR mask & index */
3945#define CPUID_MCA_THRD_MASK GENMASK(15, 0)
@@ -76,6 +82,16 @@ static inline void prepare_cpuid_input_message(struct cpu_msr_indata *input,
7682 input -> ext = ext_func ;
7783}
7884
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+
7995static int sbrmi_get_rev (struct sbrmi_data * data )
8096{
8197 unsigned int rev ;
@@ -171,6 +187,85 @@ static int rmi_cpuid_read(struct sbrmi_data *data,
171187 return ret ;
172188}
173189
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+
174269int rmi_mailbox_xfer (struct sbrmi_data * data ,
175270 struct apml_mbox_msg * msg )
176271{
@@ -289,6 +384,23 @@ static int apml_cpuid_xfer(struct sbrmi_data *data, struct apml_cpuid_msg __user
289384 return copy_to_user (arg , & msg , sizeof (struct apml_cpuid_msg ));
290385}
291386
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+
292404static long sbrmi_ioctl (struct file * fp , unsigned int cmd , unsigned long arg )
293405{
294406 void __user * argp = (void __user * )arg ;
@@ -300,6 +412,8 @@ static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
300412 return apml_mailbox_xfer (data , argp );
301413 case SBRMI_IOCTL_CPUID_CMD :
302414 return apml_cpuid_xfer (data , argp );
415+ case SBRMI_IOCTL_MCAMSR_CMD :
416+ return apml_mcamsr_xfer (data , argp );
303417 default :
304418 return - ENOTTY ;
305419 }
0 commit comments