diff options
author | Rob Barnes <robbarnes@google.com> | 2021-08-06 11:31:11 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-08-16 22:45:32 +0000 |
commit | 7e84bc29b291e4d7456783754cdf84dbd056ef34 (patch) | |
tree | 70ef69610d36ec7fb84633a0a1352ad3c0886176 | |
parent | 1d05e965306e0575021ab3a369d7aae6f3fb1590 (diff) | |
download | chrome-ec-7e84bc29b291e4d7456783754cdf84dbd056ef34.tar.gz |
driver/sb_rmi: Add AMD SB-RMI driver
Add Side-Band Remote Management Interface driver. SB-RMI can be used to
manage power limits of the SOC. SB-RMI uses a soft mail box for
executing transactions.
BUG=b:176994331
TEST=Build
BRANCH=None
Change-Id: Ie185985e4c8d2c2d915b2ae2447709ddc16adda6
Signed-off-by: Rob Barnes <robbarnes@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3078049
Tested-by: Rob Barnes <robcb85@gmail.com>
Commit-Queue: Raul E Rangel <rrangel@chromium.org>
Reviewed-by: Fanli Zhou <fanliccc@gmail.com>
Reviewed-by: Raul E Rangel <rrangel@chromium.org>
-rw-r--r-- | driver/build.mk | 3 | ||||
-rw-r--r-- | driver/sb_rmi.c | 187 | ||||
-rw-r--r-- | driver/sb_rmi.h | 58 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | zephyr/Kconfig | 8 | ||||
-rw-r--r-- | zephyr/shim/include/config_chip.h | 5 |
6 files changed, 264 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index 0c7a183a1f..0bc42fca47 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -220,3 +220,6 @@ driver-$(CONFIG_MP4245)+=mp4245.o # Power Management ICs driver-$(CONFIG_MP2964)+=mp2964.o + +# SOC Interface +driver-$(CONFIG_AMD_SB_RMI)+=sb_rmi.o diff --git a/driver/sb_rmi.c b/driver/sb_rmi.c new file mode 100644 index 0000000000..448e149456 --- /dev/null +++ b/driver/sb_rmi.c @@ -0,0 +1,187 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* AMD SB-RMI (Side-band Remote Management Interface) Driver */ + +#include "common.h" +#include "i2c.h" +#include "sb_rmi.h" +#include "stdbool.h" +#include "time.h" +#include "util.h" + +/* Console output macros */ +#define CPUTS(outstr) cputs(CC_SYSTEM, outstr) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) + +#define SB_RMI_MAILBOX_TIMEOUT_MS 10 +#define SB_RMI_MAILBOX_RETRY_DELAY_US 200 + +/** + * Write an SB-RMI register + */ +static int sb_rmi_write(const int reg, int data) +{ + return i2c_write8(I2C_PORT_THERMAL_AP, SB_RMI_I2C_ADDR_FLAGS0, reg, + data); +} + +/** + * Read an SB-RMI register + */ +static int sb_rmi_read(const int reg, int *data) +{ + return i2c_read8(I2C_PORT_THERMAL_AP, SB_RMI_I2C_ADDR_FLAGS0, reg, + data); +} + +/** + * Set SB-RMI software interrupt + */ +static int sb_rmi_assert_interrupt(bool assert) +{ + return sb_rmi_write(SB_RMI_SW_INTR_REG, assert ? 0x1 : 0x0); +} + + +/** + * Execute a SB-RMI mailbox transaction + * + * cmd: + * See "SB-RMI Soft Mailbox Message" table in PPR for command id + * msg_in: + * Message In buffer + * msg_out: + * Message Out buffer + */ +int sb_rmi_mailbox_xfer(int cmd, uint32_t msg_in, uint32_t *msg_out_ptr) +{ + /** + * The sequence is as follows: + * 1. The initiator (BMC) indicates that command is to be serviced by + * firmware by writing 0x80 to SBRMI::InBndMsg_inst7 (SBRMI_x3F). This + * register must be set to 0x80 after reset. + * 2. The initiator (BMC) writes the command to SBRMI::InBndMsg_inst0 + * (SBRMI_x38). + * 3. For write operations or read operations which require additional + * addressing information as shown in the table above, the initiator + * (BMC) writes Command Data In[31:0] to SBRMI::InBndMsg_inst[4:1] + * {SBRMI_x3C(MSB):SBRMI_x39(LSB)}. + * 4. The initiator (BMC) writes 0x01 to SBRMI::SoftwareInterrupt to + * notify firmware to perform the requested read or write command. + * 5. Firmware reads the message and performs the defined action. + * 6. Firmware writes the original command to outbound message register + * SBRMI::OutBndMsg_inst0 (SBRMI_x30). + * 7. Firmware will write SBRMI::Status[SwAlertSts]=1 to generate an + * ALERT (if enabled) to initiator (BMC) to indicate completion of the + * requested command. Firmware must (if applicable) put the message + * data into the message registers SBRMI::OutBndMsg_inst[4:1] + * {SBRMI_x34(MSB):SBRMI_x31(LSB)}. + * 8. 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)}. + * 9. Firmware clears the interrupt on SBRMI::SoftwareInterrupt. + * 10. BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear the + * ALERT to initiator (BMC). It is recommended to clear the ALERT + * upon completion of the current mailbox command. + */ + int val; + bool alerted; + timestamp_t start; + /** + * Step 1: writing 0x80 to SBRMI::InBndMsg_inst7 (SBRMI_x3F) to + * indicate that command is to be serviced and to make sure + * SBRMIx40[Software Interrupt] is cleared + */ + RETURN_ERROR(sb_rmi_write(SB_RMI_IN_BND_MSG7_REG, 0x80)); + RETURN_ERROR(sb_rmi_assert_interrupt(0)); + + /* Step 2: writes the command to SBRMI::InBndMsg_inst0 (SBRMI_x38) */ + RETURN_ERROR(sb_rmi_write(SB_RMI_IN_BND_MSG0_REG, cmd)); + /* Step 3: msgIn to {SBRMI_x3C(MSB):SBRMI_x39(LSB)} */ + RETURN_ERROR(sb_rmi_write(SB_RMI_IN_BND_MSG1_REG, msg_in & 0xFF)); + RETURN_ERROR( + sb_rmi_write(SB_RMI_IN_BND_MSG2_REG, (msg_in >> 8) & 0xFF)); + RETURN_ERROR( + sb_rmi_write(SB_RMI_IN_BND_MSG3_REG, (msg_in >> 16) & 0xFF)); + RETURN_ERROR( + sb_rmi_write(SB_RMI_IN_BND_MSG4_REG, (msg_in >> 24) & 0xFF)); + + /** + * Step 4: writes 0x01 to SBRMIx40[Software Interrupt] to notify + * firmware to start service. + */ + RETURN_ERROR(sb_rmi_assert_interrupt(1)); + + /** + * Step 5: SoC do the service + * Step 6: The original command will be copied to SBRMI::OutBndMsg_inst0 + * (SBRMI_x30) + * Step 7: wait SBRMIx02[SwAlertSts] to 1 which indicate the completion + * of a mailbox operation + */ + alerted = false; + start = get_time(); + do { + if (sb_rmi_read(SB_RMI_STATUS_REG, &val)) + break; + if (val & 0x02) { + alerted = true; + break; + } + msleep(1); + } while (time_since32(start) < SB_RMI_MAILBOX_TIMEOUT_MS * MSEC); + + if (!alerted) { + CPRINTS("SB-SMI: Mailbox transfer timeout"); + /* Clear interrupt */ + sb_rmi_assert_interrupt(0); + return EC_ERROR_TIMEOUT; + } + + RETURN_ERROR(sb_rmi_read(SB_RMI_OUT_BND_MSG0_REG, &val)); + if (val != cmd) { + CPRINTS("RMI: Unexpected command value in out bound message"); + sb_rmi_assert_interrupt(0); + return EC_ERROR_UNKNOWN; + } + + /* Step 8: read msgOut from {SBRMI_x34(MSB):SBRMI_x31(LSB)} */ + *msg_out_ptr = 0; + RETURN_ERROR(sb_rmi_read(SB_RMI_OUT_BND_MSG1_REG, &val)); + *msg_out_ptr |= val; + RETURN_ERROR(sb_rmi_read(SB_RMI_OUT_BND_MSG2_REG, &val)); + *msg_out_ptr |= val << 8; + RETURN_ERROR(sb_rmi_read(SB_RMI_OUT_BND_MSG3_REG, &val)); + *msg_out_ptr |= val << 16; + RETURN_ERROR(sb_rmi_read(SB_RMI_OUT_BND_MSG4_REG, &val)); + *msg_out_ptr |= val << 24; + + /* Step 9: clear SBRMIx40[Software Interrupt] */ + RETURN_ERROR(sb_rmi_assert_interrupt(0)); + + /** + * Step 10: BMC must write 1'b1 to SBRMI::Status[SwAlertSts] to clear + * the ALERT to initiator (BMC). It is recommended to clear the + * ALERT upon completion of the current mailbox command. + */ + RETURN_ERROR(sb_rmi_write(SB_RMI_STATUS_REG, 0x2)); + + /* Step 11: read the return code from OutBndMsg_inst7 (SBRMI_x37) */ + RETURN_ERROR(sb_rmi_read(SB_RMI_OUT_BND_MSG7_REG, &val)); + + switch (val) { + case SB_RMI_MAILBOX_SUCCESS: + return EC_SUCCESS; + case SB_RMI_MAILBOX_ERROR_ABORTED: + return EC_ERROR_UNKNOWN; + case SB_RMI_MAILBOX_ERROR_UNKNOWN_CMD: + return EC_ERROR_INVAL; + case SB_RMI_MAILBOX_ERROR_INVALID_CORE: + return EC_ERROR_PARAM1; + default: + return EC_ERROR_UNKNOWN; + } +} diff --git a/driver/sb_rmi.h b/driver/sb_rmi.h new file mode 100644 index 0000000000..132af0e70a --- /dev/null +++ b/driver/sb_rmi.h @@ -0,0 +1,58 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* AMD SB-RMI (Side-band Remote Management Interface) Driver */ + +#ifndef __CROS_EC_SB_RMI_H +#define __CROS_EC_SB_RMI_H + +#include "common.h" + +#define SB_RMI_OUT_BND_MSG0_REG 0x30 +#define SB_RMI_OUT_BND_MSG1_REG 0x31 +#define SB_RMI_OUT_BND_MSG2_REG 0x32 +#define SB_RMI_OUT_BND_MSG3_REG 0x33 +#define SB_RMI_OUT_BND_MSG4_REG 0x34 +#define SB_RMI_OUT_BND_MSG5_REG 0x35 +#define SB_RMI_OUT_BND_MSG6_REG 0x36 +#define SB_RMI_OUT_BND_MSG7_REG 0x37 + +#define SB_RMI_IN_BND_MSG0_REG 0x38 +#define SB_RMI_IN_BND_MSG1_REG 0x39 +#define SB_RMI_IN_BND_MSG2_REG 0x3a +#define SB_RMI_IN_BND_MSG3_REG 0x3b +#define SB_RMI_IN_BND_MSG4_REG 0x3c +#define SB_RMI_IN_BND_MSG5_REG 0x3d +#define SB_RMI_IN_BND_MSG6_REG 0x3e +#define SB_RMI_IN_BND_MSG7_REG 0x3f + +#define SB_RMI_SW_INTR_REG 0x40 +#define SB_RMI_STATUS_REG 0x02 + +#define SB_RMI_WRITE_STT_SENSOR_CMD 0x3A + +#define SB_RMI_MAILBOX_SUCCESS 0x0 +#define SB_RMI_MAILBOX_ERROR_ABORTED 0x1 +#define SB_RMI_MAILBOX_ERROR_UNKNOWN_CMD 0x2 +#define SB_RMI_MAILBOX_ERROR_INVALID_CORE 0x3 + +/* Socket ID 0 */ +#define SB_RMI_I2C_ADDR_FLAGS0 0x3c +/* Socket ID 1 */ +#define SB_RMI_I2C_ADDR_FLAGS1 0x30 + +/** + * Execute a SB-RMI mailbox transaction + * + * cmd: + * See "SB-RMI Soft Mailbox Message" table in PPR for command id + * msg_in: + * Message In buffer + * msg_out: + * Message Out buffer + */ +int sb_rmi_mailbox_xfer(int cmd, uint32_t msg_in, uint32_t *msg_out_ptr); + +#endif /* __CROS_EC_SB_RMI_H */ diff --git a/include/config.h b/include/config.h index 43df9737fd..a6bd31276d 100644 --- a/include/config.h +++ b/include/config.h @@ -1296,6 +1296,9 @@ /* Redefine when we need a different power-on sequence on the same chipset. */ #define CONFIG_CHIPSET_POWER_SEQ_VERSION 0 +/* AMD Side-Band Remote Management Interface (SB-RMI) support */ +#undef CONFIG_AMD_SB_RMI + /*****************************************************************************/ /* * Chip config for clock circuitry diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 05b9d5d055..b11031b8b4 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -794,4 +794,12 @@ config PLATFORM_EC_HOST_COMMAND_STATUS command finishes processing, and the AP may then inquire the status of the current command and/or the result of the previous command. +config PLATFORM_EC_AMD_SB_RMI + bool "Enable driver for AMD SB-RMI interface" + help + AMD platforms provide the Side-Band Remote Management Interface. + SB-RMI provides an interface for an external SMBus master to perform + tasks such as managing power consumption and power limits of the CPU + socket. + endif # PLATFORM_EC diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h index 639f71b266..d8bb7c27ac 100644 --- a/zephyr/shim/include/config_chip.h +++ b/zephyr/shim/include/config_chip.h @@ -1755,4 +1755,9 @@ #define CONFIG_HOSTCMD_DEBUG_MODE 3 #endif +#undef CONFIG_AMD_SB_RMI +#ifdef CONFIG_PLATFORM_EC_AMD_SB_RMI +#define CONFIG_AMD_SB_RMI +#endif + #endif /* __CROS_EC_CONFIG_CHIP_H */ |