From b7e0151f3c1b23e1d6142907b7bd4a61e5755ab9 Mon Sep 17 00:00:00 2001 From: Eric Herrmann Date: Thu, 4 Feb 2021 10:44:26 -0800 Subject: RT1715: Enable power saving modes The RT1715 implements its own low-power mode (LPM) to save power. Switch from using the default I2CIdle LPM to using the RT1715-specific one. Disable the 24MHz oscillator in LPM, and enable the interrupt to wake from LPM. For interrupts, clear the WAKEUP interrupt before checking the TCPCI interrupts. Enable auto-idle to save power with a device connected. Disable when the TCPC is sourcing Vconn. BUG=b:179256608 TEST=On Voxel: while no device attached, make sure both SNK and SRC devices wake up the TCPC from LPM TEST=On Voxel: with no devices connected, measure fake G3 power consuption and make sure it has decreased TEST=On Voxel: with a pass-through hub configured as a sink, check that connecting a charger will prompt Voxel to begin charging TEST=make buildall BRANCH=None Change-Id: Ifb2fa5a7940e5862e217c04c5c1082aae6b43989 Signed-off-by: Eric Herrmann Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2676934 Reviewed-by: Abe Levkoy Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2704622 Tested-by: Abe Levkoy Commit-Queue: Abe Levkoy --- driver/tcpm/rt1715.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++--- driver/tcpm/rt1715.h | 72 ++++++++++++++++++++++++++++--------------------- 2 files changed, 114 insertions(+), 33 deletions(-) diff --git a/driver/tcpm/rt1715.c b/driver/tcpm/rt1715.c index 98084d4c83..5f8c9cde04 100644 --- a/driver/tcpm/rt1715.c +++ b/driver/tcpm/rt1715.c @@ -62,6 +62,11 @@ static int rt1715_tcpci_tcpm_init(int port) if (rv) return rv; + /* Unmask interrupt for LPM wakeup */ + rv = tcpc_write(port, RT1715_REG_RT_MASK, RT1715_REG_RT_MASK_M_WAKEUP); + if (rv) + return rv; + /* * Set tTCPCFilter (CC debounce time) to 400 us * (min 250 us, max 500 us). @@ -138,6 +143,59 @@ static int rt1715_get_cc(int port, enum tcpc_cc_voltage_status *cc1, return rt1715_init_cc_params(port, rt1715_polarity[port] ? *cc2 : *cc1); } +/* + * See b/179256608#comment26 for explanation. + * Disable 24MHz oscillator and enable LPM. Upon exit from LPM, the LPEN will be + * reset to 0. + * + * The exit condition for LPM is CC status change, and the wakeup interrupt will + * be set. + */ +#ifdef CONFIG_USB_PD_TCPC_LOW_POWER +static int rt1715_enter_low_power_mode(int port) +{ + int regval; + int rv; + + rv = tcpc_read(port, RT1715_REG_PWR, ®val); + if (rv) + return rv; + + regval |= RT1715_REG_PWR_BMCIO_LPEN; + regval &= ~RT1715_REG_PWR_BMCIO_OSCEN; + rv = tcpc_write(port, RT1715_REG_PWR, regval); + if (rv) + return rv; + + return tcpci_enter_low_power_mode(port); +} +#endif + +static int rt1715_set_vconn(int port, int enable) +{ + int rv; + int regval; + + /* + * Auto-idle cannot be used while sourcing Vconn. + * See b/179256608#comment26 for explanation. + */ + rv = tcpc_read(port, RT1715_REG_VENDOR_5, ®val); + if (rv) + return rv; + + if (enable) + regval &= ~RT1715_REG_VENDOR_5_AUTOIDLE_EN; + else + regval |= RT1715_REG_VENDOR_5_AUTOIDLE_EN; + + rv = tcpc_write(port, RT1715_REG_VENDOR_5, regval); + if (rv) + return rv; + + return tcpci_tcpm_set_vconn(port, enable); +} + static int rt1715_set_polarity(int port, enum tcpc_cc_polarity polarity) { int rv; @@ -156,6 +214,17 @@ static int rt1715_set_polarity(int port, enum tcpc_cc_polarity polarity) return tcpci_tcpm_set_polarity(port, polarity); } +static void rt1715_alert(int port) +{ + /* + * Make sure the wakeup interrupt is cleared. This bit is set on wakeup + * from LPM. See b/179256608#comment16 for explanation. + */ + tcpc_write(port, RT1715_REG_RT_INT, RT1715_REG_RT_INT_WAKEUP); + + tcpci_tcpc_alert(port); +} + const struct tcpm_drv rt1715_tcpm_drv = { .init = &rt1715_tcpci_tcpm_init, .release = &tcpci_tcpm_release, @@ -169,12 +238,12 @@ const struct tcpm_drv rt1715_tcpm_drv = { #ifdef CONFIG_USB_PD_DECODE_SOP .sop_prime_enable = &tcpci_tcpm_sop_prime_enable, #endif - .set_vconn = &tcpci_tcpm_set_vconn, + .set_vconn = &rt1715_set_vconn, .set_msg_header = &tcpci_tcpm_set_msg_header, .set_rx_enable = &tcpci_tcpm_set_rx_enable, .get_message_raw = &tcpci_tcpm_get_message_raw, .transmit = &tcpci_tcpm_transmit, - .tcpc_alert = &tcpci_tcpc_alert, + .tcpc_alert = &rt1715_alert, #ifdef CONFIG_USB_PD_DISCHARGE_TCPC .tcpc_discharge_vbus = &tcpci_tcpc_discharge_vbus, #endif @@ -189,7 +258,7 @@ const struct tcpm_drv rt1715_tcpm_drv = { #endif .get_chip_info = &tcpci_get_chip_info, #ifdef CONFIG_USB_PD_TCPC_LOW_POWER - .enter_low_power_mode = &tcpci_enter_low_power_mode, + .enter_low_power_mode = &rt1715_enter_low_power_mode, #endif .set_bist_test_mode = &tcpci_set_bist_test_mode, }; diff --git a/driver/tcpm/rt1715.h b/driver/tcpm/rt1715.h index 334ab8f522..dcf2aa28d4 100644 --- a/driver/tcpm/rt1715.h +++ b/driver/tcpm/rt1715.h @@ -7,66 +7,78 @@ #define __CROS_EC_USB_PD_TCPM_RT1715_H /* I2C interface */ -#define RT1715_I2C_ADDR_FLAGS 0x4E +#define RT1715_I2C_ADDR_FLAGS 0x4E -#define RT1715_VENDOR_ID 0x29CF +#define RT1715_VENDOR_ID 0x29CF -#define RT1715_REG_VENDOR_7 0xA0 -#define RT1715_REG_VENDOR_7_SOFT_RESET BIT(0) +#define RT1715_REG_VENDOR_7 0xA0 +#define RT1715_REG_VENDOR_7_SOFT_RESET BIT(0) -#define RT1715_REG_PHY_CTRL1 0x80 +#define RT1715_REG_PHY_CTRL1 0x80 /* Wait for tReceive before retrying transmit in response to a bad GoodCRC */ -#define RT1715_REG_PHY_CTRL1_ENRETRY BIT(7) +#define RT1715_REG_PHY_CTRL1_ENRETRY BIT(7) /* * Bit 6:4 : Consider CC to be idle if there are 7 or fewer BMC * transients observed in <46.67us> */ -#define RT1715_REG_PHY_CTRL1_TRANSCNT_7 0x70 +#define RT1715_REG_PHY_CTRL1_TRANSCNT_7 0x70 /* * Bit 1:0 : RX filter to make sure the stable received PD message. * default value is 01b * The debounce time is (register value + 2) * 41.67ns */ -#define RT1715_REG_PHY_CTRL1_TRXFILTER_125NS 0x01 -#define RT1715_REG_PHY_CTRL2 0x81 +#define RT1715_REG_PHY_CTRL1_TRXFILTER_125NS 0x01 +#define RT1715_REG_PHY_CTRL2 0x81 /* * Decrease the time that the PHY will wait for a second transition to detect * a BMC-encoded 1 bit from 2.67 us to 2.25 us. * Timeout = register value * .04167 us. */ -#define RT1715_REG_PHY_CTRL2_CDRTHRESH_2_25US 54 +#define RT1715_REG_PHY_CTRL2_CDRTHRESH_2_25US 54 #define RT1715_REG_PHY_CTRL2_CDRTHRESH_2_5US 60 #define RT1715_REG_PHY_CTRL2_CDRTHRESH_2_58US 62 -#define RT1715_REG_BMCIO_RXDZSEL 0x93 -#define RT1715_REG_BMCIO_RXDZSEL_OCCTRL_600MA BIT(7) -#define RT1715_REG_BMCIO_RXDZSEL_SEL BIT(0) +#define RT1715_REG_PWR 0x90 +#define RT1715_REG_PWR_BMCIO_LPEN BIT(3) +#define RT1715_REG_PWR_VBUS_DETEN BIT(1) +#define RT1715_REG_PWR_BMCIO_OSCEN BIT(0) -#define RT1715_REG_VENDOR_5 0x9B -#define RT1715_REG_VENDOR_5_SHUTDOWN_OFF BIT(5) -#define RT1715_REG_VENDOR_5_ENEXTMSG BIT(4) +#define RT1715_REG_BMCIO_RXDZSEL 0x93 +#define RT1715_REG_BMCIO_RXDZSEL_OCCTRL_600MA BIT(7) +#define RT1715_REG_BMCIO_RXDZSEL_SEL BIT(0) -#define RT1715_REG_I2CRST_CTRL 0x9E +#define RT1715_REG_RT_INT 0x98 +#define RT1715_REG_RT_INT_WAKEUP BIT(0) + +#define RT1715_REG_RT_MASK 0x99 +#define RT1715_REG_RT_MASK_M_WAKEUP BIT(0) + +#define RT1715_REG_VENDOR_5 0x9B +#define RT1715_REG_VENDOR_5_SHUTDOWN_OFF BIT(5) +#define RT1715_REG_VENDOR_5_ENEXTMSG BIT(4) +#define RT1715_REG_VENDOR_5_AUTOIDLE_EN BIT(3) + +#define RT1715_REG_I2CRST_CTRL 0x9E /* I2C reset : (val + 1) * 12.5ms */ -#define RT1715_REG_I2CRST_CTRL_TOUT_200MS 0x0F -#define RT1715_REG_I2CRST_CTRL_TOUT_150MS 0x0B -#define RT1715_REG_I2CRST_CTRL_TOUT_100MS 0x07 -#define RT1715_REG_I2CRST_CTRL_EN BIT(7) +#define RT1715_REG_I2CRST_CTRL_TOUT_200MS 0x0F +#define RT1715_REG_I2CRST_CTRL_TOUT_150MS 0x0B +#define RT1715_REG_I2CRST_CTRL_TOUT_100MS 0x07 +#define RT1715_REG_I2CRST_CTRL_EN BIT(7) -#define RT1715_REG_TTCPC_FILTER 0xA1 -#define RT1715_REG_TTCPC_FILTER_400US 0x0F +#define RT1715_REG_TTCPC_FILTER 0xA1 +#define RT1715_REG_TTCPC_FILTER_400US 0x0F -#define RT1715_REG_DRP_TOGGLE_CYCLE 0xA2 +#define RT1715_REG_DRP_TOGGLE_CYCLE 0xA2 /* DRP Duty : (51.2 + 6.4 * val) ms */ -#define RT1715_REG_DRP_TOGGLE_CYCLE_76MS 0x04 +#define RT1715_REG_DRP_TOGGLE_CYCLE_76MS 0x04 -#define RT1715_REG_DRP_DUTY_CTRL 0xA3 -#define RT1715_REG_DRP_DUTY_CTRL_40PERCENT 400 +#define RT1715_REG_DRP_DUTY_CTRL 0xA3 +#define RT1715_REG_DRP_DUTY_CTRL_40PERCENT 400 -#define RT1715_REG_BMCIO_RXDZEN 0xAF -#define RT1715_REG_BMCIO_RXDZEN_ENABLE 0x01 -#define RT1715_REG_BMCIO_RXDZEN_DISABLE 0x00 +#define RT1715_REG_BMCIO_RXDZEN 0xAF +#define RT1715_REG_BMCIO_RXDZEN_ENABLE 0x01 +#define RT1715_REG_BMCIO_RXDZEN_DISABLE 0x00 extern const struct tcpm_drv rt1715_tcpm_drv; -- cgit v1.2.1