diff options
author | Jett Rink <jettrink@chromium.org> | 2018-07-27 15:14:21 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-08-15 16:37:13 -0700 |
commit | 5b417bf12ec07042bb79341b5aeb69320041f1bb (patch) | |
tree | 8e11dc968c753977a79ab370d512c06da2b0c06f | |
parent | bddf57fa4be379a3e3fe0028df011ac6027a2f67 (diff) | |
download | chrome-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>
-rw-r--r-- | driver/tcpm/tcpci.c | 94 |
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 */ |