ret = regmap_read(data->regmap, offset, &rev); if (ret < 0) return ret;
data->rev = rev; return 0;
}
/* Read CPUID function protocol */ staticint 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;
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;
} /* CPUID protocol for REV 0x10 is not supported*/ if (data->rev == 0x10) {
ret = -EOPNOTSUPP; goto exit_unlock;
}
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) goto exit_unlock;
ret = regmap_bulk_write(data->regmap, CPUID_MCA_CMD,
&input, CPUID_WR_REG_LEN); if (ret < 0) goto exit_unlock;
/* * For RMI Rev 0x20, new h/w status bit is introduced. which is used * by firmware to indicate completion of commands (0x71, 0x72, 0x73). * wait for the status bit to be set by the hardware before * reading the data out.
*/
ret = regmap_read_poll_timeout(data->regmap, SBRMI_STATUS, hw_status,
hw_status & HW_ALERT_MASK, 500, 2000000); if (ret) goto exit_unlock;
ret = regmap_bulk_read(data->regmap, CPUID_MCA_CMD,
&output, CPUID_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 != CPUID_RD_REG_LEN - 1) {
ret = -EMSGSIZE; goto exit_unlock;
} if (output.status) {
ret = -EPROTOTYPE;
msg->fw_ret_code = output.status; goto exit_unlock;
}
msg->cpu_in_out = output.value;
exit_unlock: if (ret < 0)
msg->cpu_in_out = 0;
mutex_unlock(&data->lock); return ret;
}
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 > 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;
ret = regmap_bulk_write(data->regmap, CPUID_MCA_CMD,
&input, MSR_WR_REG_LEN); if (ret < 0) goto exit_unlock;
/* * For RMI Rev 0x20, new h/w status bit is introduced. which is used * by firmware to indicate completion of commands (0x71, 0x72, 0x73). * wait for the status bit to be set by the hardware before * reading the data out.
*/
ret = regmap_read_poll_timeout(data->regmap, SBRMI_STATUS, hw_status,
hw_status & HW_ALERT_MASK, 500, 2000000); if (ret) 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->mcamsr_in_out = output.value;
int rmi_mailbox_xfer(struct sbrmi_data *data, struct apml_mbox_msg *msg)
{ unsignedint bytes, ec; int i, ret; int sw_status;
u8 byte;
mutex_lock(&data->lock);
msg->fw_ret_code = 0;
/* Indicate firmware a command is to be serviced */
ret = regmap_write(data->regmap, SBRMI_INBNDMSG7, START_CMD); if (ret < 0) goto exit_unlock;
/* Write the command to SBRMI::InBndMsg_inst0 */
ret = regmap_write(data->regmap, SBRMI_INBNDMSG0, msg->cmd); if (ret < 0) goto exit_unlock;
/* * For both read and write the initiator (BMC) writes * Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1] * SBRMI_x3C(MSB):SBRMI_x39(LSB)
*/ for (i = 0; i < AMD_SBI_MB_DATA_SIZE; i++) {
byte = (msg->mb_in_out >> i * 8) & 0xff;
ret = regmap_write(data->regmap, SBRMI_INBNDMSG1 + i, byte); if (ret < 0) goto exit_unlock;
}
/* * Write 0x01 to SBRMI::SoftwareInterrupt to notify firmware to * perform the requested read or write command
*/
ret = regmap_write(data->regmap, SBRMI_SW_INTERRUPT, TRIGGER_MAILBOX); if (ret < 0) goto exit_unlock;
/* * Firmware will write SBRMI::Status[SwAlertSts]=1 to generate * an ALERT (if enabled) to initiator (BMC) to indicate completion * of the requested command
*/
ret = regmap_read_poll_timeout(data->regmap, SBRMI_STATUS, sw_status,
sw_status & SW_ALERT_MASK, 500, 2000000); if (ret) goto exit_unlock;
ret = regmap_read(data->regmap, SBRMI_OUTBNDMSG7, &ec); if (ret || ec) goto exit_clear_alert;
/* Clear the input value before updating the output data */
msg->mb_in_out = 0;
/* * For a read operation, the initiator (BMC) reads the firmware * response Command Data Out[31:0] from SBRMI::OutBndMsg_inst[4:1] * {SBRMI_x34(MSB):SBRMI_x31(LSB)}.
*/ for (i = 0; i < AMD_SBI_MB_DATA_SIZE; i++) {
ret = regmap_read(data->regmap,
SBRMI_OUTBNDMSG1 + i, &bytes); if (ret < 0) break;
msg->mb_in_out |= bytes << i * 8;
}
exit_clear_alert: /* * BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the * ALERT to initiator
*/
ret = regmap_write(data->regmap, SBRMI_STATUS,
sw_status | SW_ALERT_MASK); if (ec) {
ret = -EPROTOTYPE;
msg->fw_ret_code = ec;
}
exit_unlock:
mutex_unlock(&data->lock); return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.