diff options
author | Caveh Jalali <caveh@chromium.org> | 2019-07-30 17:45:59 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-08-14 10:23:31 +0000 |
commit | ce1a0c9bdfa0b35455b9619fdb1b5794caa63894 (patch) | |
tree | fbb49c617b1dac9c031dcf826259a08bdccbd914 | |
parent | 1da01c3a7a5d57bf3618deba20e424ae409f7d6c (diff) | |
download | chrome-ec-ce1a0c9bdfa0b35455b9619fdb1b5794caa63894.tar.gz |
ps8xxx: disable DCI mode
DCI mode is auto-enabled by default. we don't actually support DCI
(intel specific SoC debug path), so we can explicitly disable DCI
mode. doing so, saves about 40mW on the 3.3v rail when USB2 devices
or USB-C to USB-A dongles are left plugged in. this is particulary
relevant in sleep mode as this accounts for a significant portion
of the system power consumption.
BUG=b:119875949
BRANCH=none
TEST=verified power consumption drops using sweetberry, USB devices
still functional across suspend/resume.
Change-Id: Id13630425c78965d2ac4f2e97715374ae0640d23
Signed-off-by: Caveh Jalali <caveh@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1732231
Reviewed-by: Edward Hill <ecgh@chromium.org>
Commit-Queue: Caveh Jalali <caveh@google.com>
-rw-r--r-- | driver/tcpm/ps8xxx.c | 74 | ||||
-rw-r--r-- | driver/tcpm/ps8xxx.h | 22 | ||||
-rw-r--r-- | driver/tcpm/tcpci.c | 10 | ||||
-rw-r--r-- | driver/tcpm/tcpm.h | 26 |
4 files changed, 110 insertions, 22 deletions
diff --git a/driver/tcpm/ps8xxx.c b/driver/tcpm/ps8xxx.c index 9526887b66..9740933eeb 100644 --- a/driver/tcpm/ps8xxx.c +++ b/driver/tcpm/ps8xxx.c @@ -174,8 +174,80 @@ static int ps8xxx_enter_low_power_mode(int port) } #endif +/* + * DCI is enabled by default and burns about 40 mW when the port is in + * USB2 mode or when a C-to-A dongle is attached, so force it off. + */ + +static int ps8xxx_addr_dci_disable(int port, int i2c_addr, int i2c_reg) +{ + int status; + int dci; + + status = tcpc_addr_read(port, i2c_addr, i2c_reg, &dci); + if (status != EC_SUCCESS) + return status; + if ((dci & PS8XXX_REG_MUX_USB_DCI_CFG_MODE_MASK) != + PS8XXX_REG_MUX_USB_DCI_CFG_MODE_OFF) { + dci &= ~PS8XXX_REG_MUX_USB_DCI_CFG_MODE_MASK; + dci |= PS8XXX_REG_MUX_USB_DCI_CFG_MODE_OFF; + if (tcpc_addr_write(port, i2c_addr, i2c_reg, dci) != EC_SUCCESS) + return status; + } + return EC_SUCCESS; +} + +#ifdef CONFIG_USB_PD_TCPM_PS8805 +static int ps8xxx_dci_disable(int port) +{ + int status, e; + int p1_addr; + + status = tcpc_write(port, PS8XXX_REG_I2C_DEBUGGING_ENABLE, + PS8XXX_REG_I2C_DEBUGGING_ENABLE_ON); + if (status != EC_SUCCESS) + return status; + + p1_addr = tcpc_config[port].i2c_info.addr_flags - + (PS8751_I2C_ADDR1_FLAGS - PS8751_I2C_ADDR1_P1_FLAGS); + status = ps8xxx_addr_dci_disable(port, p1_addr, + PS8805_P1_REG_MUX_USB_DCI_CFG); + + e = tcpc_write(port, PS8XXX_REG_I2C_DEBUGGING_ENABLE, + PS8XXX_REG_I2C_DEBUGGING_ENABLE_OFF); + if (e != EC_SUCCESS) { + if (status == EC_SUCCESS) + status = e; + } + + return status; +} +#endif /* CONFIG_USB_PD_TCPM_PS8805 */ + +#ifdef CONFIG_USB_PD_TCPM_PS8751 +static int ps8xxx_dci_disable(int port) +{ + int p3_addr; + + p3_addr = tcpc_config[port].i2c_info.addr_flags; + return ps8xxx_addr_dci_disable(port, p3_addr, + PS8751_REG_MUX_USB_DCI_CFG); +} +#endif /* CONFIG_USB_PD_TCPM_PS8751 */ + +static int ps8xxx_tcpm_init(int port) +{ + int status; + + status = tcpci_tcpm_init(port); + if (status != EC_SUCCESS) + return status; + + return ps8xxx_dci_disable(port); +} + const struct tcpm_drv ps8xxx_tcpm_drv = { - .init = &tcpci_tcpm_init, + .init = &ps8xxx_tcpm_init, .release = &ps8xxx_tcpm_release, .get_cc = &tcpci_tcpm_get_cc, #ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC diff --git a/driver/tcpm/ps8xxx.h b/driver/tcpm/ps8xxx.h index b94156652d..e2927c8531 100644 --- a/driver/tcpm/ps8xxx.h +++ b/driver/tcpm/ps8xxx.h @@ -9,10 +9,11 @@ #define __CROS_EC_USB_PD_TCPM_PS8XXX_H /* I2C interface */ -#define PS8751_I2C_ADDR1_FLAGS 0x0B -#define PS8751_I2C_ADDR2_FLAGS 0x1B -#define PS8751_I2C_ADDR3_FLAGS 0x2B -#define PS8751_I2C_ADDR4_FLAGS 0x4B +#define PS8751_I2C_ADDR1_P1_FLAGS 0x09 +#define PS8751_I2C_ADDR1_FLAGS 0x0B +#define PS8751_I2C_ADDR2_FLAGS 0x1B +#define PS8751_I2C_ADDR3_FLAGS 0x2B +#define PS8751_I2C_ADDR4_FLAGS 0x4B /* Minimum Delay for reset assertion */ #define PS8XXX_RESET_DELAY_MS 1 @@ -29,12 +30,17 @@ #define PS8XXX_VENDOR_ID 0x1DA0 #define PS8XXX_REG_I2C_DEBUGGING_ENABLE 0xA0 +#define PS8XXX_REG_I2C_DEBUGGING_ENABLE_ON 0x30 +#define PS8XXX_REG_I2C_DEBUGGING_ENABLE_OFF 0x31 /* default */ #define PS8XXX_REG_BIST_CONT_MODE_BYTE0 0xBC #define PS8XXX_REG_BIST_CONT_MODE_BYTE1 0xBD #define PS8XXX_REG_BIST_CONT_MODE_BYTE2 0xBE -#define PS8XXX_REG_BIST_CONT_MODE_CTR 0XBF +#define PS8XXX_REG_BIST_CONT_MODE_CTR 0xBF #define PS8XXX_REG_DET_CTRL0 0x08 +#define PS8XXX_REG_MUX_USB_DCI_CFG_MODE_MASK 0xC0 +#define PS8XXX_REG_MUX_USB_DCI_CFG_MODE_OFF 0x80 + #if defined(CONFIG_USB_PD_TCPM_PS8751) /* Vendor defined registers */ #define PS8XXX_PRODUCT_ID 0x8751 @@ -49,13 +55,15 @@ #define PS8XXX_REG_MUX_DP_OUTPUT_CONFIGURATION 0xD4 #define PS8XXX_REG_MUX_USB_C2SS_EQ 0xE7 #define PS8XXX_REG_MUX_USB_C2SS_HS_THRESHOLD 0xE8 +#define PS8751_REG_MUX_USB_DCI_CFG 0xED #elif defined(CONFIG_USB_PD_TCPM_PS8805) /* Vendor defined registers */ #define PS8XXX_PRODUCT_ID 0x8805 -#define FW_VER_REG 0x82 -#define MUX_IN_HPD_ASSERTION_REG 0xD0 +#define PS8805_P1_REG_MUX_USB_DCI_CFG 0x4B +#define FW_VER_REG 0x82 +#define MUX_IN_HPD_ASSERTION_REG 0xD0 #define IN_HPD BIT(0) #define HPD_IRQ BIT(1) diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c index 829f636cff..fb0faee0ce 100644 --- a/driver/tcpm/tcpci.c +++ b/driver/tcpm/tcpci.c @@ -34,15 +34,14 @@ static int selected_rp[CONFIG_USB_PD_PORT_COUNT]; #ifdef CONFIG_USB_PD_TCPC_LOW_POWER -int tcpc_write(int port, int reg, int val) +int tcpc_addr_write(int port, int i2c_addr, int reg, int val) { int rv; pd_wait_exit_low_power(port); rv = i2c_write8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - reg, val); + i2c_addr, reg, val); pd_device_accessed(port); return rv; @@ -62,15 +61,14 @@ int tcpc_write16(int port, int reg, int val) return rv; } -int tcpc_read(int port, int reg, int *val) +int tcpc_addr_read(int port, int i2c_addr, int reg, int *val) { int rv; pd_wait_exit_low_power(port); rv = i2c_read8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - reg, val); + i2c_addr, reg, val); pd_device_accessed(port); return rv; diff --git a/driver/tcpm/tcpm.h b/driver/tcpm/tcpm.h index 1ef4073211..a5b029d700 100644 --- a/driver/tcpm/tcpm.h +++ b/driver/tcpm/tcpm.h @@ -25,11 +25,10 @@ /* I2C wrapper functions - get I2C port / slave addr from config struct. */ #ifndef CONFIG_USB_PD_TCPC_LOW_POWER -static inline int tcpc_write(int port, int reg, int val) +static inline int tcpc_addr_write(int port, int i2c_addr, int reg, int val) { return i2c_write8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - reg, val); + i2c_addr, reg, val); } static inline int tcpc_write16(int port, int reg, int val) @@ -39,11 +38,10 @@ static inline int tcpc_write16(int port, int reg, int val) reg, val); } -static inline int tcpc_read(int port, int reg, int *val) +static inline int tcpc_addr_read(int port, int i2c_addr, int reg, int *val) { return i2c_read8(tcpc_config[port].i2c_info.port, - tcpc_config[port].i2c_info.addr_flags, - reg, val); + i2c_addr, reg, val); } static inline int tcpc_read16(int port, int reg, int *val) @@ -85,9 +83,9 @@ static inline int tcpc_write_block(int port, int reg, } #else /* !CONFIG_USB_PD_TCPC_LOW_POWER */ -int tcpc_write(int port, int reg, int val); +int tcpc_addr_write(int port, int i2c_addr, int reg, int val); int tcpc_write16(int port, int reg, int val); -int tcpc_read(int port, int reg, int *val); +int tcpc_addr_read(int port, int i2c_addr, int reg, int *val); int tcpc_read16(int port, int reg, int *val); int tcpc_read_block(int port, int reg, uint8_t *in, int size); int tcpc_write_block(int port, int reg, const uint8_t *out, int size); @@ -98,6 +96,18 @@ int tcpc_xfer_unlocked(int port, const uint8_t *out, int out_size, #endif /* CONFIG_USB_PD_TCPC_LOW_POWER */ +static inline int tcpc_write(int port, int reg, int val) +{ + return tcpc_addr_write(port, + tcpc_config[port].i2c_info.addr_flags, reg, val); +} + +static inline int tcpc_read(int port, int reg, int *val) +{ + return tcpc_addr_read(port, + tcpc_config[port].i2c_info.addr_flags, reg, val); +} + static inline void tcpc_lock(int port, int lock) { i2c_lock(tcpc_config[port].i2c_info.port, lock); |