From 66272422f71c94bb7c5b31830a43e2ce1684a37c Mon Sep 17 00:00:00 2001 From: Denis Brockus Date: Tue, 14 Apr 2020 09:26:17 -0600 Subject: nct38xx: handle TCPCI faults Add chip specific fault handling. This includes the all registers reset to default fault as well as the Vbus OVP fault. BUG=b:152841243 BRANCH=none TEST=switch normal to dev-mode with AC attached Signed-off-by: Denis Brockus Change-Id: Id5233823d873833c21da885a5a13fffe794899f7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2149385 Tested-by: Denis Brockus Reviewed-by: Denis Brockus Commit-Queue: Denis Brockus Auto-Submit: Denis Brockus --- driver/tcpm/nct38xx.c | 43 +++++++++++++++++++++++++++++++++++-------- driver/tcpm/tcpci.c | 44 ++++++++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 24 deletions(-) (limited to 'driver') diff --git a/driver/tcpm/nct38xx.c b/driver/tcpm/nct38xx.c index c9e78935d0..d6ec0f198e 100644 --- a/driver/tcpm/nct38xx.c +++ b/driver/tcpm/nct38xx.c @@ -22,15 +22,11 @@ #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -static int nct38xx_tcpm_init(int port) +static int nct38xx_init(int port) { - int rv = 0; + int rv; int reg; - rv = tcpci_tcpm_init(port); - if (rv) - return rv; - /* * Write to the CONTROL_OUT_EN register to enable: * [6] - CONNDIREN : Connector direction indication output enable @@ -38,8 +34,8 @@ static int nct38xx_tcpm_init(int port) * [0] - SRCEN : VBUS source voltage enable output enable */ reg = NCT38XX_REG_CTRL_OUT_EN_SRCEN | - NCT38XX_REG_CTRL_OUT_EN_SNKEN | - NCT38XX_REG_CTRL_OUT_EN_CONNDIREN; + NCT38XX_REG_CTRL_OUT_EN_SNKEN | + NCT38XX_REG_CTRL_OUT_EN_CONNDIREN; rv = tcpc_write(port, NCT38XX_REG_CTRL_OUT_EN, reg); if (rv) @@ -93,6 +89,16 @@ static int nct38xx_tcpm_init(int port) return rv; } +static int nct38xx_tcpm_init(int port) +{ + int rv; + + rv = tcpci_tcpm_init(port); + if (rv) + return rv; + + return nct38xx_init(port); +} static void nct38xx_tcpc_alert(int port) { @@ -140,6 +146,26 @@ static __maybe_unused int nct3807_tcpc_drp_toggle(int port) return rv; } +static int nct3807_handle_fault(int port, int fault) +{ + int rv = EC_SUCCESS; + + if (fault & TCPC_REG_FAULT_STATUS_ALL_REGS_RESET) { + rv = nct38xx_init(port); + } else { + if (fault & TCPC_REG_FAULT_STATUS_VBUS_OVER_VOLTAGE) { + /* Disable OVP */ + rv = tcpc_update8(port, + TCPC_REG_FAULT_CTRL, + TCPC_REG_FAULT_CTRL_VBUS_OVP_FAULT_DIS, + MASK_SET); + if (rv) + return rv; + } + } + return rv; +} + const struct tcpm_drv nct38xx_tcpm_drv = { .init = &nct38xx_tcpm_init, .release = &tcpci_tcpm_release, @@ -176,4 +202,5 @@ const struct tcpm_drv nct38xx_tcpm_drv = { #ifdef CONFIG_USB_TYPEC_PD_FAST_ROLE_SWAP .set_frs_enable = &tcpci_tcpc_fast_role_swap_enable, #endif + .handle_fault = &nct3807_handle_fault, }; diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 8c7773fba6..29831e6b91 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -938,13 +938,25 @@ static int tcpci_get_fault(int port, int *fault) static int tcpci_handle_fault(int port, int fault) { + int rv = EC_SUCCESS; + CPRINTS("C%d FAULT 0x%02X detected", port, fault); - return EC_SUCCESS; + + if (tcpc_config[port].drv->handle_fault) + rv = tcpc_config[port].drv->handle_fault(port, fault); + + return rv; } static int tcpci_clear_fault(int port, int fault) { - return tcpc_write(port, TCPC_REG_FAULT_STATUS, fault); + int rv; + + rv = tcpc_write(port, TCPC_REG_FAULT_STATUS, fault); + if (rv) + return rv; + + return tcpc_write16(port, TCPC_REG_ALERT, TCPC_REG_ALERT_FAULT); } /* @@ -955,20 +967,20 @@ static int tcpci_clear_fault(int port, int fault) void tcpci_tcpc_alert(int port) { - int status = 0; + int alert = 0; int alert_ext = 0; int failed_attempts; uint32_t pd_event = 0; /* Read the Alert register from the TCPC */ - tcpm_alert_status(port, &status); + tcpm_alert_status(port, &alert); /* Get Extended Alert register if needed */ - if (status & TCPC_REG_ALERT_ALERT_EXT) + if (alert & TCPC_REG_ALERT_ALERT_EXT) tcpm_alert_ext_status(port, &alert_ext); /* Clear any pending faults */ - if (status & TCPC_REG_ALERT_FAULT) { + if (alert & TCPC_REG_ALERT_FAULT) { int fault; if (tcpci_get_fault(port, &fault) == EC_SUCCESS && @@ -983,17 +995,17 @@ void tcpci_tcpc_alert(int port) * completion events. This will send an event to the PD tasks * immediately */ - if (status & TCPC_REG_ALERT_TX_COMPLETE) - pd_transmit_complete(port, status & TCPC_REG_ALERT_TX_SUCCESS ? + if (alert & TCPC_REG_ALERT_TX_COMPLETE) + pd_transmit_complete(port, alert & TCPC_REG_ALERT_TX_SUCCESS ? TCPC_TX_COMPLETE_SUCCESS : TCPC_TX_COMPLETE_FAILED); /* Pull all RX messages from TCPC into EC memory */ failed_attempts = 0; - while (status & TCPC_REG_ALERT_RX_STATUS) { + while (alert & TCPC_REG_ALERT_RX_STATUS) { if (tcpm_enqueue_message(port)) ++failed_attempts; - if (tcpm_alert_status(port, &status)) + if (tcpm_alert_status(port, &alert)) ++failed_attempts; /* Ensure we don't loop endlessly */ @@ -1012,10 +1024,10 @@ void tcpci_tcpc_alert(int port) } /* Clear all pending alert bits */ - if (status) - tcpc_write16(port, TCPC_REG_ALERT, status); + if (alert) + tcpc_write16(port, TCPC_REG_ALERT, alert); - if (status & TCPC_REG_ALERT_CC_STATUS) { + if (alert & TCPC_REG_ALERT_CC_STATUS) { if (IS_ENABLED(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)) { enum tcpc_cc_voltage_status cc1; enum tcpc_cc_voltage_status cc2; @@ -1029,7 +1041,7 @@ void tcpci_tcpc_alert(int port) */ tcpci_tcpm_get_cc(port, &cc1, &cc2); if (cc1 != TYPEC_CC_VOLT_OPEN || - cc2 != TYPEC_CC_VOLT_OPEN) + cc2 != TYPEC_CC_VOLT_OPEN) /* CC status cchanged, wake task */ pd_event |= PD_EVENT_CC; } else { @@ -1037,7 +1049,7 @@ void tcpci_tcpc_alert(int port) pd_event |= PD_EVENT_CC; } } - if (status & TCPC_REG_ALERT_POWER_STATUS) { + if (alert & TCPC_REG_ALERT_POWER_STATUS) { int reg = 0; /* Read Power Status register */ tcpci_tcpm_get_power_status(port, ®); @@ -1050,7 +1062,7 @@ void tcpci_tcpc_alert(int port) pd_event |= TASK_EVENT_WAKE; #endif /* CONFIG_USB_PD_VBUS_DETECT_TCPC && CONFIG_USB_CHARGER */ } - if (status & TCPC_REG_ALERT_RX_HARD_RST) { + if (alert & TCPC_REG_ALERT_RX_HARD_RST) { /* hard reset received */ pd_execute_hard_reset(port); pd_event |= TASK_EVENT_WAKE; -- cgit v1.2.1