summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaveh Jalali <caveh@google.com>2017-06-20 18:20:00 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-02-12 19:49:32 +0000
commitc8ed615adfb7ca4847b05fab39ffc5e457490341 (patch)
tree083912add229ae2cffaa5e31484037e23c8a9143
parent22a571f8fd974e7ab21104f6235f7231feb283a5 (diff)
downloadchrome-ec-c8ed615adfb7ca4847b05fab39ffc5e457490341.tar.gz
tcpm: add .release driver operation.
similar to the USB_PD_TCPC case, add release/init operations when the pd_task enters/leaves the PD_STATE_SUSPENDED state. one use case for PD_SUSPEND is to get exlusive access to the TCPC for things like firmware update, so the release/init operation is needed to get the TCPC and driver into a good state. updated all tcpm_drv style drivers. for backward compatibility, "old" drivers that may not handle init/release properly simply return EC_ERROR_UNIMPLEMENTED for tcpm_release(). pd_task() uses this as a signal that it should not try to re-init() the driver. TEST=tested in combination with follow-on CLs to do TCPC firmware update on electro. also built for kevin, eve, sand which are some of the other boards using these drivers. "make buildall -j" passes. BRANCH=none BUG=b:35586896 Change-Id: I8cc98b488c5ee96cf4f0b07518aa58d3e224ff5c Signed-off-by: Duncan Laurie <dlaurie@google.com> Original-Commit-Id: c74c0785927ab7770143d5ff503b4c0ca9df9ff1 Original-Change-Id: I3d2964a79e710428f7a6e7004d68ab424af85be8 Original-Signed-off-by: Caveh Jalali <caveh@google.com> Original-Reviewed-on: https://chromium-review.googlesource.com/544660 Original-Reviewed-by: Shawn N <shawnn@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/914654
-rw-r--r--common/usb_pd_protocol.c21
-rw-r--r--driver/tcpm/anx74xx.c6
-rw-r--r--driver/tcpm/anx7688.c7
-rw-r--r--driver/tcpm/fusb302.c6
-rw-r--r--driver/tcpm/fusb302.h1
-rw-r--r--driver/tcpm/it83xx.c6
-rw-r--r--driver/tcpm/tcpci.c33
-rw-r--r--driver/tcpm/tcpm.h5
-rw-r--r--include/usb_pd_tcpm.h10
9 files changed, 91 insertions, 4 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 9f6bf2a1ea..2505fdb7ad 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -2234,21 +2234,38 @@ void pd_task(void *u)
PD_STATE_SNK_DISCONNECTED);
}
break;
- case PD_STATE_SUSPENDED:
+ case PD_STATE_SUSPENDED: {
+#ifndef CONFIG_USB_PD_TCPC
+ int rstatus;
+#endif
CPRINTS("TCPC p%d suspended!", port);
#ifdef CONFIG_USB_PD_TCPC
pd_rx_disable_monitoring(port);
pd_hw_release(port);
pd_power_supply_reset(port);
+#else
+ rstatus = tcpm_release(port);
+ if (rstatus != 0 && rstatus != EC_ERROR_UNIMPLEMENTED)
+ CPRINTS("TCPC p%d release failed!", port);
#endif
/* Wait for resume */
while (pd[port].task_state == PD_STATE_SUSPENDED)
task_wait_event(-1);
#ifdef CONFIG_USB_PD_TCPC
pd_hw_init(port, PD_ROLE_DEFAULT(port));
-#endif
CPRINTS("TCPC p%d resumed!", port);
+#else
+ if (rstatus != EC_ERROR_UNIMPLEMENTED &&
+ tcpm_init(port) != 0) {
+ /* stay in PD_STATE_SUSPENDED */
+ CPRINTS("TCPC p%d init failed!", port);
+ break;
+ }
+ set_state(port, PD_DEFAULT_STATE(port));
+ CPRINTS("TCPC p%d resumed!", port);
+#endif
break;
+ }
case PD_STATE_SNK_DISCONNECTED:
#ifdef CONFIG_USB_PD_LOW_POWER
timeout = drp_state != PD_DRP_TOGGLE_ON ? SECOND
diff --git a/driver/tcpm/anx74xx.c b/driver/tcpm/anx74xx.c
index 4c3fd41410..461242d79f 100644
--- a/driver/tcpm/anx74xx.c
+++ b/driver/tcpm/anx74xx.c
@@ -1060,8 +1060,14 @@ static int anx74xx_tcpm_init(int port)
return EC_SUCCESS;
}
+static int anx74xx_tcpm_release(int port)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
const struct tcpm_drv anx74xx_tcpm_drv = {
.init = &anx74xx_tcpm_init,
+ .release = &anx74xx_tcpm_release,
.get_cc = &anx74xx_tcpm_get_cc,
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &anx74xx_tcpm_get_vbus_level,
diff --git a/driver/tcpm/anx7688.c b/driver/tcpm/anx7688.c
index 7dda345302..6b73108739 100644
--- a/driver/tcpm/anx7688.c
+++ b/driver/tcpm/anx7688.c
@@ -61,6 +61,11 @@ static int anx7688_init(int port)
return rv;
}
+static int anx7688_release(int port)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
static void anx7688_update_hpd_enable(int port)
{
int status, reg, rv;
@@ -178,6 +183,7 @@ static int anx7688_tcpm_get_vbus_level(int port)
/* ANX7688 is a TCPCI compatible port controller */
const struct tcpm_drv anx7688_tcpm_drv = {
.init = &anx7688_init,
+ .release = &anx7688_release,
.get_cc = &tcpci_tcpm_get_cc,
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &anx7688_tcpm_get_vbus_level,
@@ -200,4 +206,3 @@ const struct usb_mux_driver anx7688_usb_mux_driver = {
.get = tcpci_tcpm_mux_get,
};
#endif /* CONFIG_USB_PD_TCPM_MUX */
-
diff --git a/driver/tcpm/fusb302.c b/driver/tcpm/fusb302.c
index 9bdde5e591..3be0288bf1 100644
--- a/driver/tcpm/fusb302.c
+++ b/driver/tcpm/fusb302.c
@@ -428,6 +428,11 @@ static int fusb302_tcpm_init(int port)
return 0;
}
+static int fusb302_tcpm_release(int port)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
static int fusb302_tcpm_get_cc(int port, int *cc1, int *cc2)
{
if (state[port].pulling_up) {
@@ -926,6 +931,7 @@ void tcpm_set_bist_test_data(int port)
const struct tcpm_drv fusb302_tcpm_drv = {
.init = &fusb302_tcpm_init,
+ .release = &fusb302_tcpm_release,
.get_cc = &fusb302_tcpm_get_cc,
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &fusb302_tcpm_get_vbus_level,
diff --git a/driver/tcpm/fusb302.h b/driver/tcpm/fusb302.h
index dc191bee5a..1773645e91 100644
--- a/driver/tcpm/fusb302.h
+++ b/driver/tcpm/fusb302.h
@@ -206,4 +206,3 @@ enum fusb302_txfifo_tokens {
extern const struct tcpm_drv fusb302_tcpm_drv;
#endif /* __CROS_EC_DRIVER_TCPM_FUSB302_H */
-
diff --git a/driver/tcpm/it83xx.c b/driver/tcpm/it83xx.c
index e30c73bac8..f5e78bbbb9 100644
--- a/driver/tcpm/it83xx.c
+++ b/driver/tcpm/it83xx.c
@@ -351,6 +351,11 @@ static int it83xx_tcpm_init(int port)
return EC_SUCCESS;
}
+static int it83xx_tcpm_release(int port)
+{
+ return EC_ERROR_UNIMPLEMENTED;
+}
+
static int it83xx_tcpm_get_cc(int port, int *cc1, int *cc2)
{
*cc2 = it83xx_get_cc(port, USBPD_CC_PIN_2);
@@ -504,6 +509,7 @@ static int it83xx_tcpm_get_chip_info(int port, int renew,
const struct tcpm_drv it83xx_tcpm_drv = {
.init = &it83xx_tcpm_init,
+ .release = &it83xx_tcpm_release,
.get_cc = &it83xx_tcpm_get_cc,
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = NULL,
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 8da8bdd532..c7cdad4390 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -42,6 +42,11 @@ static int init_alert_mask(int port)
return tcpc_write16(port, TCPC_REG_ALERT_MASK, mask);
}
+static int clear_alert_mask(int port)
+{
+ return tcpc_write16(port, TCPC_REG_ALERT_MASK, 0);
+}
+
static int init_power_status_mask(int port)
{
uint8_t mask;
@@ -57,6 +62,11 @@ static int init_power_status_mask(int port)
return rv;
}
+static int clear_power_status_mask(int port)
+{
+ return tcpc_write(port, TCPC_REG_POWER_STATUS_MASK, 0);
+}
+
int tcpci_tcpm_get_cc(int port, int *cc1, int *cc2)
{
int status;
@@ -436,6 +446,28 @@ int tcpci_tcpm_init(int port)
return EC_SUCCESS;
}
+/*
+ * Dissociate from the TCPC.
+ */
+
+int tcpci_tcpm_release(int port)
+{
+ int error;
+
+ error = clear_alert_mask(port);
+ if (error)
+ return error;
+ error = clear_power_status_mask(port);
+ if (error)
+ return error;
+ /* Clear pending interrupts */
+ error = tcpc_write16(port, TCPC_REG_ALERT, 0xffff);
+ if (error)
+ return error;
+
+ return EC_SUCCESS;
+}
+
#ifdef CONFIG_USB_PD_TCPM_MUX
int tcpci_tcpm_mux_init(int i2c_addr)
@@ -498,6 +530,7 @@ const struct usb_mux_driver tcpci_tcpm_usb_mux_driver = {
const struct tcpm_drv tcpci_tcpm_drv = {
.init = &tcpci_tcpm_init,
+ .release = &tcpci_tcpm_release,
.get_cc = &tcpci_tcpm_get_cc,
#ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
.get_vbus_level = &tcpci_tcpm_get_vbus_level,
diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h
index 71af9361f9..b2d8aef2ea 100644
--- a/driver/tcpm/tcpm.h
+++ b/driver/tcpm/tcpm.h
@@ -75,6 +75,11 @@ static inline int tcpm_init(int port)
return tcpc_config[port].drv->init(port);
}
+static inline int tcpm_release(int port)
+{
+ return tcpc_config[port].drv->release(port);
+}
+
static inline int tcpm_get_cc(int port, int *cc1, int *cc2)
{
return tcpc_config[port].drv->get_cc(port, cc1, cc2);
diff --git a/include/usb_pd_tcpm.h b/include/usb_pd_tcpm.h
index fe5d6232e6..3f231fb3f7 100644
--- a/include/usb_pd_tcpm.h
+++ b/include/usb_pd_tcpm.h
@@ -67,6 +67,16 @@ struct tcpm_drv {
int (*init)(int port);
/**
+ * Release the TCPM hardware and disconnect the driver.
+ * Only .init() can be called after .release().
+ *
+ * @param port Type-C port number
+ *
+ * @return EC_SUCCESS or error
+ */
+ int (*release)(int port);
+
+ /**
* Read the CC line status.
*
* @param port Type-C port number