diff options
author | Vijay Hiremath <vijay.p.hiremath@intel.com> | 2023-04-13 18:25:45 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-04-19 23:40:20 +0000 |
commit | c4a67f5298a5a3f402bf9f4bc5505b5c4f02f557 (patch) | |
tree | bde985f9dc9af8adaf68ec8106678e35c82e882a | |
parent | 806b88d2cd803e2f3ff8b10ef5aed1e265bbebf8 (diff) | |
download | chrome-ec-c4a67f5298a5a3f402bf9f4bc5505b5c4f02f557.tar.gz |
retimer: Use common console command for all Retimers
BUG=b:278138274
BRANCH=none
TEST=Tested on ADL-RVP, retimer console command works
./twister -T zephyr/test/drivers
./twister -T zephyr/test/drivers -s drivers.default
./firmware_builder.py --metrics /tmp/tmp_pc1rc15 build
Change-Id: Idaec9b41f550ad6aafa34400e95ebf00b9c11348
Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4426790
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r-- | docs/reducing_ec_image_size.md | 2 | ||||
-rw-r--r-- | driver/retimer/bb_retimer.c | 95 | ||||
-rw-r--r-- | driver/retimer/kb800x.c | 102 | ||||
-rw-r--r-- | driver/usb_mux/usb_mux.c | 66 | ||||
-rw-r--r-- | include/config.h | 8 | ||||
-rw-r--r-- | include/usb_mux.h | 24 | ||||
-rw-r--r-- | zephyr/Kconfig.retimer | 9 | ||||
-rw-r--r-- | zephyr/shim/include/config_chip.h | 10 | ||||
-rw-r--r-- | zephyr/test/drivers/default/src/bb_retimer.c | 18 |
9 files changed, 169 insertions, 165 deletions
diff --git a/docs/reducing_ec_image_size.md b/docs/reducing_ec_image_size.md index 85a15a3f3c..dc04605dda 100644 --- a/docs/reducing_ec_image_size.md +++ b/docs/reducing_ec_image_size.md @@ -244,7 +244,7 @@ prj.conf file to disable the console command. | | CONFIG_CMD_RAND | `rand` | Used only on STM32 | | | CONFIG_CMD_REGULATOR | `ir357x` | | | | CONFIG_CMD_RESET_FLAGS | `rflags` | | -| | CONFIG_CMD_RETIMER | `bb`<br>`kbxfer` | | +| | CONFIG_CMD_RETIMER | `retimer` | | | | CONFIG_CMD_RTC | `rtc` | | | | CONFIG_CMD_RTC_ALARM | `rtc_alarm` | | | | CONFIG_CMD_RW | `rw` | | diff --git a/driver/retimer/bb_retimer.c b/driver/retimer/bb_retimer.c index cd18a7a6ef..5571b666d4 100644 --- a/driver/retimer/bb_retimer.c +++ b/driver/retimer/bb_retimer.c @@ -37,6 +37,7 @@ #define CPRINTF(format, args...) cprintf(CC_USBCHARGE, format, ##args) #define BB_RETIMER_I2C_RETRY 5 +#define BB_RETIMER_REG_OFFSET_MAX UINT8_MAX /* * Mutex for BB_RETIMER_REG_CONNECTION_STATE register, which can be @@ -51,12 +52,16 @@ static mux_state_t bb_mux_state[CONFIG_USB_PD_PORT_MAX_COUNT]; /** * Utility functions */ -static int bb_retimer_read(const struct usb_mux *me, const uint8_t offset, +static int bb_retimer_read(const struct usb_mux *me, const uint32_t offset, uint32_t *data) { int rv, retry = 0; uint8_t buf[BB_RETIMER_READ_SIZE]; + /* Validate the register address */ + if (offset > BB_RETIMER_REG_OFFSET_MAX) + return EC_ERROR_INVAL; + /* * This I2C message will trigger retimer's internal read sequence * if its a NAK, sleep and resend same I2C @@ -69,7 +74,8 @@ static int bb_retimer_read(const struct usb_mux *me, const uint8_t offset, * byte[1:4] : Data [LSB -> MSB] * Stop */ - rv = i2c_xfer(me->i2c_port, me->i2c_addr_flags, &offset, 1, buf, + rv = i2c_xfer(me->i2c_port, me->i2c_addr_flags, + (const uint8_t *)&offset, 1, buf, BB_RETIMER_READ_SIZE); if (rv == EC_SUCCESS) @@ -91,12 +97,16 @@ static int bb_retimer_read(const struct usb_mux *me, const uint8_t offset, return EC_SUCCESS; } -static int bb_retimer_write(const struct usb_mux *me, const uint8_t offset, +static int bb_retimer_write(const struct usb_mux *me, const uint32_t offset, uint32_t data) { int rv, retry = 0; uint8_t buf[BB_RETIMER_WRITE_SIZE]; + /* Validate the register address */ + if (offset > BB_RETIMER_REG_OFFSET_MAX) + return EC_ERROR_INVAL; + /* * Write sequence * Addr flags(w) @@ -105,7 +115,7 @@ static int bb_retimer_write(const struct usb_mux *me, const uint8_t offset, * byte[2:5] : Data [LSB -> MSB] * stop */ - buf[0] = offset; + buf[0] = (uint8_t)offset; buf[1] = BB_RETIMER_REG_SIZE; buf[2] = data & 0xFF; buf[3] = (data >> 8) & 0xFF; @@ -670,79 +680,8 @@ const struct usb_mux_driver bb_usb_retimer = { .set_idle_mode = bb_set_idle_mode, .enter_low_power_mode = retimer_low_power_mode, .is_retimer_fw_update_capable = is_retimer_fw_update_capable, -}; - #ifdef CONFIG_CMD_RETIMER -static int console_command_bb_retimer(int argc, const char **argv) -{ - char rw, *e; - int port; - uint8_t reg; - uint32_t data, val = 0; - int rv = EC_SUCCESS; - const struct usb_mux *mux; - const struct usb_mux_chain *mux_chain; - - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - /* Get port number */ - port = strtoi(argv[1], &e, 0); - if (*e || !board_is_usb_pd_port_present(port)) - return EC_ERROR_PARAM1; - - mux_chain = &usb_muxes[port]; - while (mux_chain) { - mux = mux_chain->mux; - if (mux->driver == &bb_usb_retimer) - break; - mux_chain = mux_chain->next; - } - - if (!mux_chain) - return EC_ERROR_PARAM1; - - /* Validate r/w selection */ - rw = argv[2][0]; - if (rw != 'w' && rw != 'r') - return EC_ERROR_PARAM2; - - /* Get register address */ - reg = (uint8_t)strtoull(argv[3], &e, 0); - if (*e) - return EC_ERROR_PARAM3; - - /* Get value to be written */ - if (rw == 'w') { - val = strtoull(argv[4], &e, 0); - if (*e) - return EC_ERROR_PARAM4; - } - - for (; mux_chain != NULL; mux_chain = mux_chain->next) { - mux = mux_chain->mux; - if (mux->driver == &bb_usb_retimer) { - if (rw == 'r') - rv = bb_retimer_read(mux, reg, &data); - else { - rv = bb_retimer_write(mux, reg, val); - if (rv == EC_SUCCESS) { - rv = bb_retimer_read(mux, reg, &data); - if (rv == EC_SUCCESS && data != val) - rv = EC_ERROR_UNKNOWN; - } - } - if (rv == EC_SUCCESS) - CPRINTS("Addr 0x%x register %d = 0x%x", - mux->i2c_addr_flags, reg, data); - } - } - - return rv; -} -/* TODO(b/278138274): Use common console command for all Retimers */ -DECLARE_CONSOLE_COMMAND(bb, console_command_bb_retimer, - "<port> r <reg>" - "\n<port> w <reg> <val>", - "Read or write to BB retimer register"); + .retimer_read = bb_retimer_read, + .retimer_write = bb_retimer_write, #endif /* CONFIG_CMD_RETIMER */ +}; diff --git a/driver/retimer/kb800x.c b/driver/retimer/kb800x.c index 35ab5b183d..2ca4b062bb 100644 --- a/driver/retimer/kb800x.c +++ b/driver/retimer/kb800x.c @@ -14,30 +14,44 @@ /* Time between load switch enable and the reset being de-asserted */ #define KB800X_POWER_ON_DELAY_MS 20 +#define KB800X_REG_OFFSET_MAX UINT16_MAX +#define KB800X_REG_DATA_MAX UINT8_MAX static mux_state_t cached_mux_state[CONFIG_USB_PD_PORT_MAX_COUNT]; -static int kb800x_write(const struct usb_mux *me, uint16_t address, - uint8_t data) +static int kb800x_write(const struct usb_mux *me, uint32_t address, + uint32_t data) { uint8_t kb800x_config[3] = { 0x00, 0x00, 0x00 }; + /* Validate the register address */ + if (address > KB800X_REG_OFFSET_MAX) + return EC_ERROR_INVAL; + + /* Validate the writeable data */ + if (data > KB800X_REG_DATA_MAX) + return EC_ERROR_INVAL; + kb800x_config[0] = (address >> 8) & 0xff; kb800x_config[1] = address & 0xff; - kb800x_config[2] = data; + kb800x_config[2] = (uint8_t)data; return i2c_xfer(me->i2c_port, me->i2c_addr_flags, kb800x_config, sizeof(kb800x_config), NULL, 0); } -static int kb800x_read(const struct usb_mux *me, uint16_t address, - uint8_t *data) +static int kb800x_read(const struct usb_mux *me, uint32_t address, + uint32_t *data) { uint8_t kb800x_config[2] = { 0x00, 0x00 }; + /* Validate the register address */ + if (address > KB800X_REG_OFFSET_MAX) + return EC_ERROR_INVAL; + kb800x_config[0] = (address >> 8) & 0xff; kb800x_config[1] = address & 0xff; return i2c_xfer(me->i2c_port, me->i2c_addr_flags, kb800x_config, - sizeof(kb800x_config), data, 1); + sizeof(kb800x_config), (uint8_t *)data, 1); } #ifdef CONFIG_KB800X_CUSTOM_XBAR @@ -83,7 +97,7 @@ static int kb800x_assign_tx_to_eb(const struct usb_mux *me, enum kb800x_eb eb) { uint8_t field_value = 0; - uint8_t regval; + uint32_t regval; int rv; field_value = KB800X_PHY_IS_AB(phy_lane) ? tx_eb_to_field_ab[eb] : @@ -106,7 +120,7 @@ static int kb800x_assign_rx_to_eb(const struct usb_mux *me, { uint16_t address = 0; uint8_t field_value = 0; - uint8_t regval = 0; + uint32_t regval = 0; int rv; field_value = rx_phy_lane_to_field[phy_lane]; @@ -472,76 +486,12 @@ static int kb800x_enter_low_power_mode(const struct usb_mux *me) return EC_SUCCESS; } -#ifdef CONFIG_CMD_RETIMER - -static int console_command_kb800x_xfer(int argc, const char **argv) -{ - char rw, *e; - int rv, port, reg, val; - uint8_t data; - const struct usb_mux_chain *mux_chain; - const struct usb_mux *mux; - - if (argc < 4) - return EC_ERROR_PARAM_COUNT; - - /* Get port number */ - port = strtoi(argv[1], &e, 0); - if (*e || !board_is_usb_pd_port_present(port)) - return EC_ERROR_PARAM1; - - mux_chain = &usb_muxes[port]; - while (mux_chain) { - if (mux_chain->mux->driver == &kb800x_usb_mux_driver) - break; - mux_chain = mux_chain->next; - } - - if (!mux_chain) - return EC_ERROR_PARAM1; - - mux = mux_chain->mux; - - /* Validate r/w selection */ - rw = argv[2][0]; - if (rw != 'w' && rw != 'r') - return EC_ERROR_PARAM2; - - /* Get register address */ - reg = strtoi(argv[3], &e, 0); - if (*e || reg < 0) - return EC_ERROR_PARAM3; - rv = EC_SUCCESS; - if (rw == 'r') - rv = kb800x_read(mux, reg, &data); - else { - if (argc < 5) - return EC_ERROR_PARAM_COUNT; - /* Get value to be written */ - val = strtoi(argv[4], &e, 0); - if (*e || val < 0) - return EC_ERROR_PARAM4; - rv = kb800x_write(mux, reg, val); - if (rv == EC_SUCCESS) { - rv = kb800x_read(mux, reg, &data); - if (rv == EC_SUCCESS && data != val) - rv = EC_ERROR_UNKNOWN; - } - } - - if (rv == EC_SUCCESS) - ccprintf("register 0x%x [%d] = 0x%x [%d]\n", reg, reg, data, - data); - - return rv; -} -DECLARE_CONSOLE_COMMAND(kbxfer, console_command_kb800x_xfer, - "<port> <r/w> <reg> | <val>", - "Read or write to KB retimer register"); -#endif /* CONFIG_CMD_RETIMER */ - const struct usb_mux_driver kb800x_usb_mux_driver = { .init = kb800x_init, .set = kb800x_set_state, .enter_low_power_mode = kb800x_enter_low_power_mode, +#ifdef CONFIG_CMD_RETIMER + .retimer_read = kb800x_read, + .retimer_write = kb800x_write, +#endif /* CONFIG_CMD_RETIMER */ }; diff --git a/driver/usb_mux/usb_mux.c b/driver/usb_mux/usb_mux.c index bf1a61c0b3..334b7f2f2d 100644 --- a/driver/usb_mux/usb_mux.c +++ b/driver/usb_mux/usb_mux.c @@ -851,3 +851,69 @@ static enum ec_status hc_usb_pd_mux_ack(struct host_cmd_handler_args *args) return EC_RES_SUCCESS; } DECLARE_HOST_COMMAND(EC_CMD_USB_PD_MUX_ACK, hc_usb_pd_mux_ack, EC_VER_MASK(0)); + +#ifdef CONFIG_CMD_RETIMER +static int console_command_retimer(int argc, const char **argv) +{ + char rw, *e; + uint32_t reg, data, val = 0; + int port, rv = EC_ERROR_UNIMPLEMENTED; + const struct usb_mux *mux; + const struct usb_mux_chain *mux_chain; + + if (argc < 4 || argc > 5) + return EC_ERROR_PARAM_COUNT; + + /* Get port number */ + port = strtoi(argv[1], &e, 0); + if (*e || !board_is_usb_pd_port_present(port)) + return EC_ERROR_PARAM1; + + mux_chain = &usb_muxes[port]; + if (!mux_chain) + return EC_ERROR_PARAM1; + + /* Validate r/w selection */ + rw = argv[2][0]; + if (rw != 'w' && rw != 'r') + return EC_ERROR_PARAM2; + + /* Get register address */ + reg = strtoull(argv[3], &e, 0); + if (*e) + return EC_ERROR_PARAM3; + + /* Get value to be written */ + if (rw == 'w') { + val = strtoull(argv[4], &e, 0); + if (*e) + return EC_ERROR_PARAM4; + } + + /* + * It is assumed that similar chips are connected in chain and the + * same set of data is written to all the chained chips. + */ + for (; mux_chain != NULL; mux_chain = mux_chain->next) { + mux = mux_chain->mux; + if (mux->driver && mux->driver->retimer_read && + mux->driver->retimer_write) { + if (rw == 'r') { + rv = mux->driver->retimer_read(mux, reg, &data); + if (rv == EC_SUCCESS) { + CPRINTS("Addr 0x%x register %d = 0x%x", + mux->i2c_addr_flags, reg, data); + } + } else { + rv = mux->driver->retimer_write(mux, reg, val); + } + } + } + + return rv; +} +DECLARE_CONSOLE_COMMAND(retimer, console_command_retimer, + "<port> r <reg>" + "\n<port> w <reg> <val>", + "Read or write to retimer register"); +#endif /* CONFIG_CMD_RETIMER */ diff --git a/include/config.h b/include/config.h index b0a809af7f..ee212a8fdc 100644 --- a/include/config.h +++ b/include/config.h @@ -1704,7 +1704,7 @@ #undef CONFIG_CMD_RAND #define CONFIG_CMD_REGULATOR #undef CONFIG_CMD_RESET_FLAGS -#define CONFIG_CMD_RETIMER +#undef CONFIG_CMD_RETIMER #undef CONFIG_CMD_RTC #undef CONFIG_CMD_RTC_ALARM #define CONFIG_CMD_RW @@ -6714,6 +6714,12 @@ #define CONFIG_USB_MUX_AP_ACK_REQUEST #endif /* CONFIG_USBC_RETIMER_INTEL_BB || CONFIG_USBC_RETIMER_INTEL_HB */ +/* Enable retimer console command */ +#if (defined(CONFIG_USBC_RETIMER_INTEL_BB) || \ + defined(CONFIG_USBC_RETIMER_KB800X)) +#define CONFIG_CMD_RETIMER +#endif + /*****************************************************************************/ /* diff --git a/include/usb_mux.h b/include/usb_mux.h index 90edbb98d7..8d3dbc2f7e 100644 --- a/include/usb_mux.h +++ b/include/usb_mux.h @@ -121,6 +121,30 @@ struct usb_mux_driver { * @return EC_SUCCESS on success, non-zero error code on failure. */ int (*set_idle_mode)(const struct usb_mux *me, bool idle); + +#ifdef CONFIG_CMD_RETIMER + /** + * Console command to read the retimer registers + * + * @param me usb_mux + * @param offset Register offset + * @param data Data to be read + * @return EC_SUCCESS on success, non-zero error code on failure. + */ + int (*retimer_read)(const struct usb_mux *me, const uint32_t offset, + uint32_t *data); + + /** + * Console command to write to the retimer registers + * + * @param me usb_mux + * @param offset Register offset + * @param data Data to be written + * @return EC_SUCCESS on success, non-zero error code on failure. + */ + int (*retimer_write)(const struct usb_mux *me, const uint32_t offset, + uint32_t data); +#endif /* CONFIG_CMD_RETIMER */ }; /* Describes a USB mux present in the system */ diff --git a/zephyr/Kconfig.retimer b/zephyr/Kconfig.retimer index 70ee06499e..9c15a7a6f0 100644 --- a/zephyr/Kconfig.retimer +++ b/zephyr/Kconfig.retimer @@ -9,6 +9,7 @@ config PLATFORM_EC_USBC_RETIMER_INTEL_BB default y depends on PLATFORM_EC_USB_MUX depends on DT_HAS_INTEL_JHL8040R_ENABLED + select PLATFORM_EC_CONSOLE_CMD_RETIMER select PLATFORM_EC_USB_PD_USB4 select PLATFORM_EC_USB_PD_TBT_COMPAT_MODE select PLATFORM_EC_USBC_RETIMER_FW_UPDATE @@ -36,6 +37,7 @@ config PLATFORM_EC_USBC_RETIMER_INTEL_HB default y depends on PLATFORM_EC_USB_MUX depends on DT_HAS_INTEL_JHL9040R_ENABLED + select PLATFORM_EC_CONSOLE_CMD_RETIMER select PLATFORM_EC_USB_PD_USB4 select PLATFORM_EC_USB_PD_TBT_COMPAT_MODE select PLATFORM_EC_USBC_RETIMER_FW_UPDATE @@ -98,6 +100,7 @@ config PLATFORM_EC_USBC_RETIMER_PS8818 config PLATFORM_EC_USBC_RETIMER_KB800X bool "Enable KB800X retimer" + select PLATFORM_EC_CONSOLE_CMD_RETIMER help The KB8001 is a Universal Serial Bus (USB) Type-C 40 Gb/s multiprotocol switch and bidirectional Bit-Level Retimer (BLR) which supports: @@ -115,6 +118,12 @@ config PLATFORM_EC_KB800X_CUSTOM_XBAR Enable this to allow using a custom crossbar configuration for the HSIO lanes. +config PLATFORM_EC_CONSOLE_CMD_RETIMER + bool "Console command: retimer" + help + This console command allows read or write to the retimer registers + connected in a chain. + endif # PLATFORM_EC_USBC config PLATFORM_EC_USBC_RETIMER_ANX7483 diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h index 08bb52acc9..b46ca76cb1 100644 --- a/zephyr/shim/include/config_chip.h +++ b/zephyr/shim/include/config_chip.h @@ -1857,6 +1857,11 @@ extern char mock_jump_data[CONFIG_PLATFORM_EC_PRESERVED_END_OF_RAM_SIZE]; #define CONFIG_USBC_RETIMER_ANX7452 #endif +#undef CONFIG_USBC_RETIMER_KB800X +#ifdef CONFIG_PLATFORM_EC_USBC_RETIMER_KB800X +#define CONFIG_USBC_RETIMER_KB800X +#endif + #undef CONFIG_USBC_RETIMER_PS8811 #ifdef CONFIG_PLATFORM_EC_USBC_RETIMER_PS8811 #define CONFIG_USBC_RETIMER_PS8811 @@ -1867,6 +1872,11 @@ extern char mock_jump_data[CONFIG_PLATFORM_EC_PRESERVED_END_OF_RAM_SIZE]; #define CONFIG_USBC_RETIMER_PS8818 #endif +#undef CONFIG_CMD_RETIMER +#ifdef CONFIG_PLATFORM_EC_CONSOLE_CMD_RETIMER +#define CONFIG_CMD_RETIMER +#endif + #undef CONFIG_USBC_SS_MUX #ifdef CONFIG_PLATFORM_EC_USBC_SS_MUX #define CONFIG_USBC_SS_MUX diff --git a/zephyr/test/drivers/default/src/bb_retimer.c b/zephyr/test/drivers/default/src/bb_retimer.c index aa31dbceed..ea335c2965 100644 --- a/zephyr/test/drivers/default/src/bb_retimer.c +++ b/zephyr/test/drivers/default/src/bb_retimer.c @@ -628,23 +628,23 @@ ZTEST_USER(bb_retimer, test_bb_console_cmd) int rv; /* Validate well formed shell commands */ - rv = shell_execute_cmd(get_ec_shell(), "bb 1 r 2"); + rv = shell_execute_cmd(get_ec_shell(), "retimer 1 r 2"); zassert_ok(rv, "rv=%d", rv); - rv = shell_execute_cmd(get_ec_shell(), "bb 1 w 2 0"); + rv = shell_execute_cmd(get_ec_shell(), "retimer 1 w 2 0"); zassert_ok(rv, "rv=%d", rv); /* Validate errors for malformed shell commands */ - rv = shell_execute_cmd(get_ec_shell(), "bb x"); + rv = shell_execute_cmd(get_ec_shell(), "retimer x"); zassert_equal(EC_ERROR_PARAM_COUNT, rv, "rv=%d", rv); - rv = shell_execute_cmd(get_ec_shell(), "bb x r 2"); + rv = shell_execute_cmd(get_ec_shell(), "retimer x r 2"); zassert_equal(EC_ERROR_PARAM1, rv, "rv=%d", rv); - rv = shell_execute_cmd(get_ec_shell(), "bb 0 r 2"); - zassert_equal(EC_ERROR_PARAM1, rv, "rv=%d", rv); - rv = shell_execute_cmd(get_ec_shell(), "bb 1 x 2"); + rv = shell_execute_cmd(get_ec_shell(), "retimer 0 r 2"); + zassert_equal(EC_ERROR_UNIMPLEMENTED, rv, "rv=%d", rv); + rv = shell_execute_cmd(get_ec_shell(), "retimer 1 x 2"); zassert_equal(EC_ERROR_PARAM2, rv, "rv=%d", rv); - rv = shell_execute_cmd(get_ec_shell(), "bb 1 r x"); + rv = shell_execute_cmd(get_ec_shell(), "retimer 1 r x"); zassert_equal(EC_ERROR_PARAM3, rv, "rv=%d", rv); - rv = shell_execute_cmd(get_ec_shell(), "bb 1 w 2 x"); + rv = shell_execute_cmd(get_ec_shell(), "retimer 1 w 2 x"); zassert_equal(EC_ERROR_PARAM4, rv, "rv=%d", rv); } |