summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorJett Rink <jettrink@chromium.org>2018-07-27 15:14:21 -0600
committerchrome-bot <chrome-bot@chromium.org>2018-08-15 16:37:13 -0700
commit5b417bf12ec07042bb79341b5aeb69320041f1bb (patch)
tree8e11dc968c753977a79ab370d512c06da2b0c06f /driver
parentbddf57fa4be379a3e3fe0028df011ac6027a2f67 (diff)
downloadchrome-ec-5b417bf12ec07042bb79341b5aeb69320041f1bb.tar.gz
ps8751: add low power mode for PS8751 when only MUX
Enter lower power mode for PS8751 when acting as mux only. BRANCH=none BUG=b:111664205,b:111876407,b:10937880 TEST=PS8751 as MUX on C1 Bip goes into low power mode after disconnect. Change-Id: Ifac3b76556069e1e5f6acae550d8076c29d5f1cd Signed-off-by: Jett Rink <jettrink@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1153835 Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/tcpm/tcpci.c94
1 files changed, 75 insertions, 19 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index a2562d48c2..f9760a0aed 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -541,6 +541,28 @@ int tcpci_get_chip_info(int port, int renew,
}
/*
+ * 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;
+}
+
+/*
* On TCPC i2c failure, make 30 tries (at least 300ms) before giving up
* in order to allow the TCPC time to boot / reset.
*/
@@ -582,35 +604,62 @@ int tcpci_tcpm_init(int port)
return EC_SUCCESS;
}
+#ifdef CONFIG_USB_PD_TCPM_MUX
+
+#ifdef CONFIG_USB_PD_TCPM_TCPCI_MUX_ONLY
+
/*
- * Dissociate from the TCPC.
+ * Since the TCPC/MUX device is only used for the MUX, we need to initialize it
+ * via mux init because tcpc_init won't run for the device. This is borrowed
+ * from tcpc_init.
*/
-
-int tcpci_tcpm_release(int port)
+int tcpci_tcpm_mux_init(int i2c_port_addr)
{
int error;
+ int power_status;
+ int tries = TCPM_INIT_TRIES;
- 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;
+ /* Wait for the device to exit low power state */
+ while (1) {
+ error = i2c_read8(MUX_PORT(i2c_port_addr),
+ MUX_ADDR(i2c_port_addr),
+ TCPC_REG_POWER_STATUS, &power_status);
+ /*
+ * If read succeeds and the uninitialized bit is clear, then
+ * initialization is complete.
+ */
+ if (!error && !(power_status & TCPC_REG_POWER_STATUS_UNINIT))
+ break;
+ else if (error && --tries == 0)
+ return error;
+ msleep(10);
+ }
- return EC_SUCCESS;
+ /* Turn off all alerts and acknowledge any pending IRQ */
+ error = i2c_write16(MUX_PORT(i2c_port_addr), MUX_ADDR(i2c_port_addr),
+ TCPC_REG_ALERT_MASK, 0);
+ error |= i2c_write16(MUX_PORT(i2c_port_addr), MUX_ADDR(i2c_port_addr),
+ TCPC_REG_ALERT, 0xffff);
+
+ return error ? EC_ERROR_UNKNOWN : EC_SUCCESS;
}
-#ifdef CONFIG_USB_PD_TCPM_MUX
+static int tcpci_tcpm_mux_enter_low_power(int i2c_port_addr)
+{
+ return i2c_write8(MUX_PORT(i2c_port_addr), MUX_ADDR(i2c_port_addr),
+ TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE);
+}
+
+#else /* !CONFIG_USB_PD_TCPM_TCPCI_MUX_ONLY */
+/* Nothing to init for mux since TCPC init will take care of it. */
int tcpci_tcpm_mux_init(int i2c_addr)
{
return EC_SUCCESS;
}
+#endif /* CONFIG_USB_PD_TCPM_TCPCI_MUX_ONLY */
+
int tcpci_tcpm_mux_set(int i2c_port_addr, mux_state_t mux_state)
{
int reg = 0;
@@ -675,11 +724,18 @@ int tcpci_tcpm_mux_get(int i2c_port_addr, mux_state_t *mux_state)
return EC_SUCCESS;
}
-
const struct usb_mux_driver tcpci_tcpm_usb_mux_driver = {
- .init = tcpci_tcpm_mux_init,
- .set = tcpci_tcpm_mux_set,
- .get = tcpci_tcpm_mux_get,
+ .init = &tcpci_tcpm_mux_init,
+ .set = &tcpci_tcpm_mux_set,
+ .get = &tcpci_tcpm_mux_get,
+#ifdef CONFIG_USB_PD_TCPM_TCPCI_MUX_ONLY
+ /*
+ * This method is only needed when the TCPC/MUX device is acting solely
+ * as a MUX (and not the TCPC). In that case, we need to put the device
+ * into LPM via the mux path since the TCPC path won't do it for us.
+ */
+ .enter_low_power_mode = &tcpci_tcpm_mux_enter_low_power,
+#endif
};
#endif /* CONFIG_USB_PD_TCPM_MUX */