diff options
author | Tomasz Michalec <tm@semihalf.com> | 2022-03-10 13:07:21 +0100 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-03-18 14:20:55 +0000 |
commit | b2bf76967bf2a96294aad933449bc0b3bfd12cce (patch) | |
tree | 90a00fc820a093cd25041dda22c3d7a1fb767c15 | |
parent | 521ffdd6f204d289888820036568ee1b15efdd17 (diff) | |
download | chrome-ec-b2bf76967bf2a96294aad933449bc0b3bfd12cce.tar.gz |
zephyr: emul: Fix sending Hard and Cable reset in TCPCI emulator
Transmitting Hard or Cable reset should alywas set
TransmitSOP*MessageSuccessful and TransmitSOP*MessageFailed bits in
ALERT register. Now partner emulators aren't reporting message status
using tcpci_emul_partner_msg_status() when receive Hard or Cable reset.
Instead TCPCI emulator transmit handler set correct ALERT state.
Additionally transmitting Hard Reset sets RECEIVE_DETECT register to 0,
clears receive buffer and resets mask registers.
BUG=b:223766685
BRANCH=none
TEST=zmake configure --test test-drivers
Signed-off-by: Tomasz Michalec <tm@semihalf.com>
Change-Id: I686e4001b65cc05621563861903c76e620224e3e
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3515940
Tested-by: Tomasz Michalec <tmichalec@google.com>
Reviewed-by: Denis Brockus <dbrockus@chromium.org>
Commit-Queue: Tomasz Michalec <tmichalec@google.com>
-rw-r--r-- | zephyr/emul/tcpc/emul_tcpci.c | 109 | ||||
-rw-r--r-- | zephyr/emul/tcpc/emul_tcpci_partner_common.c | 9 | ||||
-rw-r--r-- | zephyr/include/emul/tcpc/emul_tcpci.h | 3 |
3 files changed, 90 insertions, 31 deletions
diff --git a/zephyr/emul/tcpc/emul_tcpci.c b/zephyr/emul/tcpc/emul_tcpci.c index 61f9cc7f0d..c16e99d4c4 100644 --- a/zephyr/emul/tcpc/emul_tcpci.c +++ b/zephyr/emul/tcpc/emul_tcpci.c @@ -524,6 +524,10 @@ void tcpci_emul_partner_msg_status(const struct emul *emul, case TCPCI_EMUL_TX_FAILED: tx_status_alert = TCPC_REG_ALERT_TX_FAILED; break; + case TCPCI_EMUL_TX_CABLE_HARD_RESET: + tx_status_alert = TCPC_REG_ALERT_TX_SUCCESS | + TCPC_REG_ALERT_TX_FAILED; + break; default: __ASSERT(0, "Invalid partner TX status 0x%x", status); return; @@ -638,6 +642,23 @@ static void tcpci_emul_reset_role_ctrl(const struct emul *emul) } /** + * @brief Reset mask registers that are reset upon receiving or transmitting + * Hard Reset message. + * + * @param emul Pointer to TCPCI emulator + */ +static void tcpci_emul_reset_mask_regs(const struct emul *emul) +{ + struct tcpci_emul_data *data = emul->data; + + data->reg[TCPC_REG_ALERT_MASK] = 0xff; + data->reg[TCPC_REG_ALERT_MASK + 1] = 0x7f; + data->reg[TCPC_REG_POWER_STATUS_MASK] = 0xff; + data->reg[TCPC_REG_EXT_STATUS_MASK] = 0x01; + data->reg[TCPC_REG_ALERT_EXTENDED_MASK] = 0x07; +} + +/** * @brief Reset registers to default values. Vendor and reserved registers * are not changed. * @@ -650,12 +671,7 @@ static int tcpci_emul_reset(const struct emul *emul) data->reg[TCPC_REG_ALERT] = 0x00; data->reg[TCPC_REG_ALERT + 1] = 0x00; - data->reg[TCPC_REG_ALERT_MASK] = 0xff; - data->reg[TCPC_REG_ALERT_MASK + 1] = 0x7f; - data->reg[TCPC_REG_POWER_STATUS_MASK] = 0xff; data->reg[TCPC_REG_FAULT_STATUS_MASK] = 0xff; - data->reg[TCPC_REG_EXT_STATUS_MASK] = 0x01; - data->reg[TCPC_REG_ALERT_EXTENDED_MASK] = 0x07; data->reg[TCPC_REG_CONFIG_STD_OUTPUT] = 0x60; data->reg[TCPC_REG_TCPC_CTRL] = 0x00; data->reg[TCPC_REG_FAULT_CTRL] = 0x00; @@ -683,6 +699,7 @@ static int tcpci_emul_reset(const struct emul *emul) data->reg[TCPC_REG_VBUS_NONDEFAULT_TARGET] = 0x00; data->reg[TCPC_REG_VBUS_NONDEFAULT_TARGET + 1] = 0x00; + tcpci_emul_reset_mask_regs(emul); tcpci_emul_reset_role_ctrl(emul); if (data->dev_ops && data->dev_ops->reset) { @@ -1097,30 +1114,6 @@ static int tcpci_emul_handle_command(const struct emul *emul) } /** - * @brief Handle write to transmit register - * - * @param emul Pointer to TCPCI emulator - * - * @return 0 on success - */ -static int tcpci_emul_handle_transmit(const struct emul *emul) -{ - struct tcpci_emul_data *data = emul->data; - - data->tx_msg->cnt = data->tx_msg->idx; - data->tx_msg->type = TCPC_REG_TRANSMIT_TYPE(data->write_data); - data->tx_msg->idx = 0; - - if (data->partner && data->partner->transmit) { - data->partner->transmit(emul, data->partner, data->tx_msg, - TCPC_REG_TRANSMIT_TYPE(data->write_data), - TCPC_REG_TRANSMIT_RETRY(data->write_data)); - } - - return 0; -} - -/** * @brief Load next rx message and inform partner which message was consumed * by TCPC * @@ -1157,6 +1150,64 @@ static int tcpci_emul_get_next_rx_msg(const struct emul *emul) } /** + * @brief Perform actions that are expected by TCPC on disabling PD message + * delivery (clear RECEIVE_DETECT register, clear already received + * messages in buffer and reset mask registers) + * + * @param emul Pointer to TCPCI emulator + */ +static void tcpci_emul_disable_pd_msg_delivery(const struct emul *emul) +{ + tcpci_emul_set_reg(emul, TCPC_REG_RX_DETECT, 0); + /* Clear received messages */ + while (tcpci_emul_get_next_rx_msg(emul)) + ; + tcpci_emul_reset_mask_regs(emul); +} + +/** + * @brief Handle write to transmit register + * + * @param emul Pointer to TCPCI emulator + * + * @return 0 on success + */ +static int tcpci_emul_handle_transmit(const struct emul *emul) +{ + struct tcpci_emul_data *data = emul->data; + enum tcpci_msg_type type; + + data->tx_msg->cnt = data->tx_msg->idx; + data->tx_msg->type = TCPC_REG_TRANSMIT_TYPE(data->write_data); + data->tx_msg->idx = 0; + + type = TCPC_REG_TRANSMIT_TYPE(data->write_data); + + if (data->partner && data->partner->transmit) { + data->partner->transmit(emul, data->partner, data->tx_msg, type, + TCPC_REG_TRANSMIT_RETRY(data->write_data)); + } + + switch (type) { + case TCPCI_MSG_TX_HARD_RESET: + tcpci_emul_disable_pd_msg_delivery(emul); + /* fallthrough */ + case TCPCI_MSG_CABLE_RESET: + /* + * Cable and Hard reset are special and set success and fail + * in Alert reg regardless of the outcome of the transmission + */ + tcpci_emul_partner_msg_status(emul, + TCPCI_EMUL_TX_CABLE_HARD_RESET); + break; + default: + break; + } + + return 0; +} + +/** * @brief Handle I2C write message. It is checked if accessed register isn't RO * and reserved bits are set to 0. * diff --git a/zephyr/emul/tcpc/emul_tcpci_partner_common.c b/zephyr/emul/tcpc/emul_tcpci_partner_common.c index e3805c1cd2..affde1225f 100644 --- a/zephyr/emul/tcpc/emul_tcpci_partner_common.c +++ b/zephyr/emul/tcpc/emul_tcpci_partner_common.c @@ -440,7 +440,14 @@ enum tcpci_partner_handler_res tcpci_partner_common_msg_handler( tcpci_partner_log_msg(data, tx_msg, TCPCI_PARTNER_SENDER_TCPM, tx_status); - tcpci_emul_partner_msg_status(data->tcpci_emul, tx_status); + /* + * Do not change alert register in TCPCI emulator upon receiving + * hard reset or cable reset + */ + if (type != TCPCI_MSG_TX_HARD_RESET && type != TCPCI_MSG_CABLE_RESET) { + tcpci_emul_partner_msg_status(data->tcpci_emul, tx_status); + } + /* If receiving message was unsuccessful, abandon processing message */ if (tx_status != TCPCI_EMUL_TX_SUCCESS) { return TCPCI_PARTNER_COMMON_MSG_NOT_HANDLED; diff --git a/zephyr/include/emul/tcpc/emul_tcpci.h b/zephyr/include/emul/tcpc/emul_tcpci.h index 3a50481054..41e15203c7 100644 --- a/zephyr/include/emul/tcpc/emul_tcpci.h +++ b/zephyr/include/emul/tcpc/emul_tcpci.h @@ -81,7 +81,8 @@ enum tcpci_emul_rev { enum tcpci_emul_tx_status { TCPCI_EMUL_TX_SUCCESS, TCPCI_EMUL_TX_DISCARDED, - TCPCI_EMUL_TX_FAILED + TCPCI_EMUL_TX_FAILED, + TCPCI_EMUL_TX_CABLE_HARD_RESET }; /** TCPCI specific device operations. Not all of them need to be implemented. */ |