@@ -32,10 +32,16 @@
#define CPUID_WR_DATA_LEN 0x8
#define CPUID_RD_REG_LEN 0xa
#define CPUID_WR_REG_LEN 0x9
+/* MSR */
+#define MSR_RD_REG_LEN 0xa
+#define MSR_WR_REG_LEN 0x8
+#define MSR_RD_DATA_LEN 0x8
+#define MSR_WR_DATA_LEN 0x7
/* CPUID MSR Command Ids */
#define CPUID_MCA_CMD 0x73
#define RD_CPUID_CMD 0x91
+#define RD_MCA_CMD 0x86
/* input for bulk write to CPUID protocol */
struct cpu_msr_indata {
@@ -68,6 +74,13 @@ struct cpu_msr_outdata {
input.value = func, \
input.ext = ext_func
+#define prepare_mca_msr_input_message(input, thread_id, data_in) \
+ input.rd_len = MSR_RD_DATA_LEN, \
+ input.wr_len = MSR_WR_DATA_LEN, \
+ input.proto_cmd = RD_MCA_CMD, \
+ input.thread = thread_id << 1, \
+ input.value = data_in
+
/*
* For Mailbox command software alert status bit is set by firmware
* to indicate command completion
@@ -191,6 +204,79 @@ static int rmi_cpuid_read(struct sbrmi_data *data,
return ret;
}
+/* MCA MSR protocol */
+static int rmi_mca_msr_read(struct sbrmi_data *data,
+ struct apml_message *msg)
+{
+ struct cpu_msr_outdata output = {0};
+ struct cpu_msr_indata input = {0};
+ int ret, val = 0;
+ int hw_status;
+ u16 thread;
+
+ mutex_lock(&data->lock);
+ /* cache the rev value to identify if protocol is supported or not */
+ if (!data->rev) {
+ ret = sbrmi_get_rev(data);
+ if (ret < 0)
+ goto exit_unlock;
+ }
+ /* MCA MSR protocol for REV 0x10 is not supported*/
+ if (data->rev == 0x10) {
+ ret = -EOPNOTSUPP;
+ goto exit_unlock;
+ }
+
+ thread = msg->data_in.reg_in[THREAD_LOW_INDEX] |
+ msg->data_in.reg_in[THREAD_HI_INDEX] << 8;
+
+ /* 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)
+ goto exit_unlock;
+
+ prepare_mca_msr_input_message(input, thread,
+ msg->data_in.mb_in[RD_WR_DATA_INDEX]);
+
+ ret = regmap_bulk_write(data->regmap, CPUID_MCA_CMD,
+ &input, MSR_WR_REG_LEN);
+ if (ret < 0)
+ goto exit_unlock;
+
+ ret = sbrmi_wait_status(data, &hw_status, HW_ALERT_MASK);
+ if (ret < 0)
+ goto exit_unlock;
+
+ ret = regmap_bulk_read(data->regmap, CPUID_MCA_CMD,
+ &output, MSR_RD_REG_LEN);
+ if (ret < 0)
+ goto exit_unlock;
+
+ ret = regmap_write(data->regmap, SBRMI_STATUS,
+ HW_ALERT_MASK);
+ if (ret < 0)
+ goto exit_unlock;
+
+ if (output.num_bytes != MSR_RD_REG_LEN - 1) {
+ ret = -EMSGSIZE;
+ goto exit_unlock;
+ }
+ if (output.status) {
+ ret = -EPROTOTYPE;
+ msg->fw_ret_code = output.status;
+ goto exit_unlock;
+ }
+ msg->data_out.cpu_msr_out = output.value;
+
+exit_unlock:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
int rmi_mailbox_xfer(struct sbrmi_data *data,
struct apml_message *msg)
{
@@ -317,6 +403,10 @@ static long sbrmi_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
case APML_CPUID:
ret = rmi_cpuid_read(data, &msg);
break;
+ case APML_MCA_MSR:
+ /* MCAMSR protocol */
+ ret = rmi_mca_msr_read(data, &msg);
+ break;
default:
pr_err("Command:0x%x not recognized\n", msg.cmd);
break;
@@ -7,8 +7,11 @@
#include <linux/types.h>
-/* command ID to identify CPUID protocol */
-#define APML_CPUID 0x1000
+enum apml_protocol {
+ APML_CPUID = 0x1000,
+ APML_MCA_MSR,
+};
+
/* These are byte indexes into data_in and data_out arrays */
#define RD_WR_DATA_INDEX 0
#define REG_OFF_INDEX 0
@@ -24,13 +27,14 @@ struct apml_message {
/* message ids:
* Mailbox Messages: 0x0 ... 0x999
* APML_CPUID: 0x1000
+ * APML_MCA_MSR: 0x1001
*/
__u32 cmd;
/*
* 8 bit data for reg read,
* 32 bit data in case of mailbox,
- * up to 64 bit in case of cpuid
+ * up to 64 bit in case of cpuid and mca msr
*/
union {
__u64 cpu_msr_out;
@@ -40,8 +44,9 @@ struct apml_message {
/*
* [0]...[3] mailbox 32bit input
- * cpuid,
- * [4][5] cpuid: thread
+ * cpuid & mca msr,
+ * [4][5] cpuid & mca msr: thread
+ * [4] rmi reg wr: value
* [6] cpuid: ext function & read eax/ebx or ecx/edx
* [7:0] -> bits [7:4] -> ext function &
* bit [0] read eax/ebx or ecx/edx
@@ -53,7 +58,7 @@ struct apml_message {
__u8 reg_in[8];
} data_in;
/*
- * Status code is returned in case of CPUID access
+ * Status code is returned in case of CPUID/MCA access
* Error code is returned in case of soft mailbox
*/
__u32 fw_ret_code;