summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaveh Jalali <caveh@chromium.org>2019-07-30 17:45:59 -0700
committerCommit Bot <commit-bot@chromium.org>2020-09-01 12:42:22 +0000
commit689e8cdc09254072c0dface2954bc6e87f5ceaf7 (patch)
tree90eaf2adfbc5ff996f63a6cbe51ea657e6e67032
parent9c880833331e25bf436aa6628e837b9c98a47bc2 (diff)
downloadchrome-ec-689e8cdc09254072c0dface2954bc6e87f5ceaf7.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> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2315962 Tested-by: Devin Lu <Devin.Lu@quantatw.com> Reviewed-by: Marco Chen <marcochen@chromium.org> Commit-Queue: Marco Chen <marcochen@chromium.org>
-rw-r--r--driver/tcpm/ps8xxx.c74
-rw-r--r--driver/tcpm/ps8xxx.h22
-rw-r--r--driver/tcpm/tcpci.c8
-rw-r--r--driver/tcpm/tcpm.h24
4 files changed, 110 insertions, 18 deletions
diff --git a/driver/tcpm/ps8xxx.c b/driver/tcpm/ps8xxx.c
index bbdf8f1a82..9cb6e46017 100644
--- a/driver/tcpm/ps8xxx.c
+++ b/driver/tcpm/ps8xxx.c
@@ -168,8 +168,80 @@ static int ps8xxx_get_chip_info(int port, int live,
}
+/*
+ * 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 -
+ (PS8751_I2C_ADDR1 - PS8751_I2C_ADDR1_P1);
+ 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;
+ 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 2d878216e3..99ba60d43c 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 0x16
-#define PS8751_I2C_ADDR2 0x36
-#define PS8751_I2C_ADDR3 0x56
-#define PS8751_I2C_ADDR4 0x96
+#define PS8751_I2C_ADDR1_P1 0x12
+#define PS8751_I2C_ADDR1 0x16
+#define PS8751_I2C_ADDR2 0x36
+#define PS8751_I2C_ADDR3 0x56
+#define PS8751_I2C_ADDR4 0x96
/* 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 (1 << 0)
#define HPD_IRQ (1 << 1)
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 223527fc29..17cb8b08d0 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -30,14 +30,14 @@ static int selected_rp[CONFIG_USB_PD_PORT_MAX_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, reg, val);
+ i2c_addr, reg, val);
pd_device_accessed(port);
return rv;
@@ -56,14 +56,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, 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 186c88a276..3cef4b4b41 100644
--- a/driver/tcpm/tcpm.h
+++ b/driver/tcpm/tcpm.h
@@ -25,10 +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, reg, val);
+ i2c_addr, reg, val);
}
static inline int tcpc_write16(int port, int reg, int val)
@@ -37,10 +37,10 @@ static inline int tcpc_write16(int port, int reg, int val)
tcpc_config[port].i2c_info.addr, 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, reg, val);
+ i2c_addr, reg, val);
}
static inline int tcpc_read16(int port, int reg, int *val)
@@ -79,9 +79,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);
@@ -92,6 +92,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, reg, val);
+}
+
+static inline int tcpc_read(int port, int reg, int *val)
+{
+ return tcpc_addr_read(port,
+ tcpc_config[port].i2c_info.addr, reg, val);
+}
+
static inline void tcpc_lock(int port, int lock)
{
i2c_lock(tcpc_config[port].i2c_info.port, lock);