summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2019-11-27 12:50:21 +0800
committerCommit Bot <commit-bot@chromium.org>2019-11-29 10:38:09 +0000
commit3a90729933c1fa96662bd1361b5454db0ff3ff54 (patch)
tree864c0cb7aad9e87a9dac1347b945e061a27999b9
parent81d2e72bf6f6d726e49d6683eb40980471dc3052 (diff)
downloadchrome-ec-3a90729933c1fa96662bd1361b5454db0ff3ff54.tar.gz
fusb302: fix lower power mode
CL:1880773 makes board unable to exit low power mode because interrupt is not configured correctly, this CL fixes the problem. BUG=b:142760774,b:145101992 TEST=1) In S0, unplug and replug usb device make sure the device shows up in `lsusb` 2) suspend, unplug and replug usb device, resume make sure the device shows up is `lsusb` 3) make sure toggle is disabled in G3 and force source/sink mode. BRANCH=master Change-Id: Iae8eb7571241ad8364d460fbb516844c7aa8b86a Signed-off-by: Ting Shen <phoenixshen@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1939027 Reviewed-by: Eric Yilun Lin <yllin@chromium.org> Commit-Queue: Ting Shen <phoenixshen@chromium.org> Tested-by: Ting Shen <phoenixshen@chromium.org>
-rw-r--r--driver/tcpm/fusb302.c67
-rw-r--r--driver/tcpm/fusb302.h2
2 files changed, 66 insertions, 3 deletions
diff --git a/driver/tcpm/fusb302.c b/driver/tcpm/fusb302.c
index 66c131fb37..bbb6015e56 100644
--- a/driver/tcpm/fusb302.c
+++ b/driver/tcpm/fusb302.c
@@ -434,7 +434,6 @@ static int fusb302_tcpm_init(int port)
tcpm_set_polarity(port, 0);
tcpm_set_vconn(port, 0);
- /* Turn on the power! */
/* TODO: Reduce power consumption */
tcpc_write(port, TCPC_REG_POWER, TCPC_REG_POWER_PWR_ALL);
@@ -1008,9 +1007,73 @@ void tcpm_set_bist_test_data(int port)
}
#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
+static int fusb302_set_toggle_mode(int port, int mode)
+{
+ int reg, rv;
+
+ rv = i2c_read8(tcpc_config[port].i2c_info.port,
+ tcpc_config[port].i2c_info.addr_flags,
+ TCPC_REG_CONTROL2, &reg);
+ if (rv)
+ return rv;
+
+ reg &= ~TCPC_REG_CONTROL2_MODE_MASK;
+ reg |= mode << TCPC_REG_CONTROL2_MODE_POS;
+ return i2c_write8(tcpc_config[port].i2c_info.port,
+ tcpc_config[port].i2c_info.addr_flags,
+ TCPC_REG_CONTROL2, reg);
+}
+
static int fusb302_tcpm_enter_low_power_mode(int port)
{
- return tcpc_write(port, TCPC_REG_POWER, TCPC_REG_POWER_PWR_LOW);
+ int reg, rv, mode = TCPC_REG_CONTROL2_MODE_DRP;
+
+ /**
+ * vendor's suggested LPM flow:
+ * - enable low power mode and set up other things
+ * - sleep 250 us
+ * - start toggling
+ */
+ rv = i2c_write8(tcpc_config[port].i2c_info.port,
+ tcpc_config[port].i2c_info.addr_flags,
+ TCPC_REG_POWER, TCPC_REG_POWER_PWR_LOW);
+ if (rv)
+ return rv;
+
+ switch (pd_get_dual_role(port)) {
+ case PD_DRP_TOGGLE_ON:
+ mode = TCPC_REG_CONTROL2_MODE_DRP;
+ break;
+ case PD_DRP_TOGGLE_OFF:
+ mode = TCPC_REG_CONTROL2_MODE_UFP;
+ break;
+ case PD_DRP_FREEZE:
+ mode = pd_get_role(port) == PD_ROLE_SINK ?
+ TCPC_REG_CONTROL2_MODE_UFP :
+ TCPC_REG_CONTROL2_MODE_DFP;
+ break;
+ case PD_DRP_FORCE_SINK:
+ mode = TCPC_REG_CONTROL2_MODE_UFP;
+ break;
+ case PD_DRP_FORCE_SOURCE:
+ mode = TCPC_REG_CONTROL2_MODE_DFP;
+ break;
+ }
+ rv = fusb302_set_toggle_mode(port, mode);
+ if (rv)
+ return rv;
+
+ usleep(250);
+
+ rv = i2c_read8(tcpc_config[port].i2c_info.port,
+ tcpc_config[port].i2c_info.addr_flags,
+ TCPC_REG_CONTROL2, &reg);
+ if (rv)
+ return rv;
+ reg |= TCPC_REG_CONTROL2_TOGGLE;
+ return i2c_write8(tcpc_config[port].i2c_info.port,
+ tcpc_config[port].i2c_info.addr_flags,
+ TCPC_REG_CONTROL2, reg);
}
#endif
diff --git a/driver/tcpm/fusb302.h b/driver/tcpm/fusb302.h
index ec418407f7..b4a8599ea8 100644
--- a/driver/tcpm/fusb302.h
+++ b/driver/tcpm/fusb302.h
@@ -76,7 +76,7 @@
#define TCPC_REG_CONTROL2 0x08
/* two-bit field, valid values below */
-#define TCPC_REG_CONTROL2_MODE (1<<1)
+#define TCPC_REG_CONTROL2_MODE_MASK (0x3<<TCPC_REG_CONTROL2_MODE_POS)
#define TCPC_REG_CONTROL2_MODE_DFP (0x3)
#define TCPC_REG_CONTROL2_MODE_UFP (0x2)
#define TCPC_REG_CONTROL2_MODE_DRP (0x1)