summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Michalec <tm@semihalf.com>2022-03-10 13:07:21 +0100
committerCommit Bot <commit-bot@chromium.org>2022-03-18 14:20:55 +0000
commitb2bf76967bf2a96294aad933449bc0b3bfd12cce (patch)
tree90a00fc820a093cd25041dda22c3d7a1fb767c15
parent521ffdd6f204d289888820036568ee1b15efdd17 (diff)
downloadchrome-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.c109
-rw-r--r--zephyr/emul/tcpc/emul_tcpci_partner_common.c9
-rw-r--r--zephyr/include/emul/tcpc/emul_tcpci.h3
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. */