summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Brockus <dbrockus@google.com>2020-04-14 09:26:17 -0600
committerCommit Bot <commit-bot@chromium.org>2020-04-16 05:42:30 +0000
commit66272422f71c94bb7c5b31830a43e2ce1684a37c (patch)
treed0447638ff6c5466fdc71a536add0b78cdc7a0ed
parent97cc9112a6e986cf71848a8c4f973d42f599465f (diff)
downloadchrome-ec-66272422f71c94bb7c5b31830a43e2ce1684a37c.tar.gz
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 <dbrockus@google.com> Change-Id: Id5233823d873833c21da885a5a13fffe794899f7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2149385 Tested-by: Denis Brockus <dbrockus@chromium.org> Reviewed-by: Denis Brockus <dbrockus@chromium.org> Commit-Queue: Denis Brockus <dbrockus@chromium.org> Auto-Submit: Denis Brockus <dbrockus@chromium.org>
-rw-r--r--driver/tcpm/nct38xx.c43
-rw-r--r--driver/tcpm/tcpci.c44
-rw-r--r--include/usb_pd_tcpm.h10
3 files changed, 73 insertions, 24 deletions
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, &reg);
@@ -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;
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
index 35f9cccb47..1ad9e6b03d 100644
--- a/include/usb_pd_tcpm.h
+++ b/include/usb_pd_tcpm.h
@@ -405,6 +405,16 @@ struct tcpm_drv {
* @param enable FRS enable (true) disable (false)
*/
void (*set_frs_enable)(int port, int enable);
+
+ /**
+ * Handle TCPCI Faults
+ *
+ * @param port Type-C port number
+ * @param fault TCPCI fault status value
+ *
+ * @return EC_SUCCESS or error
+ */
+ int (*handle_fault)(int port, int fault);
};
/*