From e5e5f8843baeac7e5aec82d3fba7d2739f669f11 Mon Sep 17 00:00:00 2001 From: Tomasz Michalec Date: Wed, 5 Jan 2022 16:50:39 +0100 Subject: zephyr: emul: Fix TCPCI alert on power status change Fix TCPCI emulator to generate alert when power status change while connecting or disconnecting TCPCI emulator partners. Now setting POWER_STATUS, FAULT_STATUS, EXT_STATUS or ALERT_EXT register using tcpci_emul_set_reg() will also set corresponding bit in ALERT register. BUG=none BRANCH=none TEST=make configure --test zephyr/test/drivers Signed-off-by: Tomasz Michalec Change-Id: I79a61866fad69253ced9c468d301988e270cc793 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3368262 Reviewed-by: Denis Brockus Reviewed-by: Keith Short Tested-by: Tomasz Michalec Commit-Queue: Tomasz Michalec --- zephyr/emul/tcpc/emul_tcpci.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/zephyr/emul/tcpc/emul_tcpci.c b/zephyr/emul/tcpc/emul_tcpci.c index 660f62ead0..18249bed55 100644 --- a/zephyr/emul/tcpc/emul_tcpci.c +++ b/zephyr/emul/tcpc/emul_tcpci.c @@ -104,12 +104,35 @@ static int tcpci_emul_reg_bytes(int reg) int tcpci_emul_set_reg(const struct emul *emul, int reg, uint16_t val) { struct tcpci_emul_data *data = emul->data; + uint16_t update_alert = 0; + uint16_t alert; int byte; if (reg < 0 || reg > TCPCI_EMUL_REG_COUNT) { return -EINVAL; } + /* Changing some registers has impact on alert register */ + switch (reg) { + case TCPC_REG_POWER_STATUS: + update_alert = TCPC_REG_ALERT_POWER_STATUS; + break; + case TCPC_REG_FAULT_STATUS: + update_alert = TCPC_REG_ALERT_FAULT; + break; + case TCPC_REG_EXT_STATUS: + update_alert = TCPC_REG_ALERT_EXT_STATUS; + break; + case TCPC_REG_ALERT_EXT: + update_alert = TCPC_REG_ALERT_ALERT_EXT; + break; + } + + if (update_alert != 0) { + tcpci_emul_get_reg(emul, TCPC_REG_ALERT, &alert); + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, alert | update_alert); + } + for (byte = tcpci_emul_reg_bytes(reg); byte > 0; byte--) { data->reg[reg] = val & 0xff; val >>= 8; @@ -179,7 +202,7 @@ static bool tcpci_emul_check_int(const struct emul *emul) return true; } - if (alert & alert_mask & TCPC_REG_POWER_STATUS && + if (alert & alert_mask & TCPC_REG_ALERT_POWER_STATUS && data->reg[TCPC_REG_POWER_STATUS] & data->reg[TCPC_REG_POWER_STATUS_MASK]) { return true; @@ -475,8 +498,10 @@ int tcpci_emul_disconnect_partner(const struct emul *emul) /* Clear VBUS present in case if source partner is disconnected */ tcpci_emul_get_reg(emul, TCPC_REG_POWER_STATUS, &power_status); - tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, - power_status & ~TCPC_REG_POWER_STATUS_VBUS_PRES); + if (power_status & TCPC_REG_POWER_STATUS_VBUS_PRES) { + power_status &= ~TCPC_REG_POWER_STATUS_VBUS_PRES; + tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, power_status); + } return 0; } @@ -674,11 +699,11 @@ static int tcpci_emul_reset(const struct emul *emul) */ static int tcpci_emul_set_i2c_interface_err(const struct emul *emul) { - struct tcpci_emul_data *data = emul->data; + uint16_t fault_status; - data->reg[TCPC_REG_FAULT_STATUS] |= - TCPC_REG_FAULT_STATUS_I2C_INTERFACE_ERR; - data->reg[TCPC_REG_ALERT + 1] |= TCPC_REG_ALERT_FAULT >> 8; + tcpci_emul_get_reg(emul, TCPC_REG_FAULT_STATUS, &fault_status); + fault_status |= TCPC_REG_FAULT_STATUS_I2C_INTERFACE_ERR; + tcpci_emul_set_reg(emul, TCPC_REG_FAULT_STATUS, fault_status); return tcpci_emul_alert_changed(emul); } -- cgit v1.2.1