summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2015-10-27 14:20:03 -0700
committerchrome-bot <chrome-bot@chromium.org>2015-10-30 13:09:32 -0700
commite080de3c488063773c37ac89829996edd5506a49 (patch)
tree8a99d68be177ca50ec6e18a1472dba4dfa2b6061
parent49d4254bd40a81b8f37014400bf5a50e7e581e4d (diff)
downloadchrome-ec-e080de3c488063773c37ac89829996edd5506a49.tar.gz
pd: add more power improvements to PD task
Added more improvements to power consumption when using CONFIG_USB_PD_LOW_POWER. On the TCPC, when this option is defined, then decrease the PD task wake interval when we are presenting Rd, we don't have a connection, AND we haven't dual-role toggled recently. This shouldn't affect connection time because we will get an interrupt when VBUS is detected. Note: we can't use the low power task wake interval when we are connected because we need to monitor CC line for Rp change and we can't do this when we are presenting Rp because we need to quickly detect loss of Rd. BUG=chrome-os-partner:45010 BRANCH=none TEST=tested on glados. verified we connect to a charger in S0 and S5. and verified that in S5, we spend >99% of our time in deepsleep (as measured by idlestats console command). note, that when testing EC and PD must both define CONFIG_USB_PD_LOW_POWER to get maximum power improvements. Change-Id: I661110cc7021f6d17937688787ea4f5f4b82973d Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/309310 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--common/usb_pd_protocol.c4
-rw-r--r--common/usb_pd_tcpc.c42
2 files changed, 43 insertions, 3 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 4cc0e0259a..fc063d24b9 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -1952,8 +1952,8 @@ void pd_task(void)
break;
case PD_STATE_SNK_DISCONNECTED:
#ifdef CONFIG_USB_PD_LOW_POWER
- timeout = drp_state == PD_DRP_TOGGLE_OFF ? MINUTE
- : 10*MSEC;
+ timeout = drp_state != PD_DRP_TOGGLE_ON ? SECOND
+ : 10*MSEC;
#else
timeout = 10*MSEC;
#endif
diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c
index 99867e338a..0b13fb2c77 100644
--- a/common/usb_pd_tcpc.c
+++ b/common/usb_pd_tcpc.c
@@ -198,6 +198,14 @@ enum pd_tx_errors {
};
/*
+ * If TCPM is not on this chip, and PD low power is defined, then use low
+ * power task delay logic.
+ */
+#if !defined(CONFIG_USB_POWER_DELIVERY) && defined(CONFIG_USB_PD_LOW_POWER)
+#define TCPC_LOW_POWER
+#endif
+
+/*
* Receive message buffer size. Buffer physical size is RX_BUFFER_SIZE + 1,
* but only RX_BUFFER_SIZE of that memory is used to store messages that can
* be retrieved from TCPM. The last slot is a temporary buffer for collecting
@@ -229,6 +237,11 @@ static struct pd_port_controller {
uint8_t power_status;
uint8_t power_status_mask;
+#ifdef TCPC_LOW_POWER
+ /* Timestamp beyond which we allow low power task sampling */
+ timestamp_t low_power_ts;
+#endif
+
/* Last received */
int rx_head[RX_BUFFER_SIZE+1];
uint32_t rx_payload[RX_BUFFER_SIZE+1][7];
@@ -821,8 +834,21 @@ int tcpc_run(int port, int evt)
if (pd[port].rx_enabled)
pd_rx_enable_monitoring(port);
- /* TODO: adjust timeout based on how often to sample CC */
+#ifdef TCPC_LOW_POWER
+ /*
+ * If we are presenting Rd with no connection, and timestamp is
+ * past the low power timestamp, then we don't need to sample
+ * CC lines as often. In this case, our connection delay should not
+ * actually increased because we will get an interrupt on VBUS detect.
+ */
+ return (get_time().val >= pd[port].low_power_ts.val &&
+ pd[port].cc_pull == TYPEC_CC_RD &&
+ pd[port].cc_status[0] == TYPEC_CC_VOLT_OPEN &&
+ pd[port].cc_status[1] == TYPEC_CC_VOLT_OPEN) ? 200 * MSEC :
+ 10 * MSEC;
+#else
return 10*MSEC;
+#endif
}
#ifndef CONFIG_USB_POWER_DELIVERY
@@ -906,6 +932,16 @@ int tcpc_set_cc(int port, int pull)
pd_set_host_mode(port, pull == TYPEC_CC_RP);
#endif
+#ifdef TCPC_LOW_POWER
+ /*
+ * Reset the low power timestamp every time CC termination toggles,
+ * because we only want to go into low power mode when we are not
+ * dual-role toggling.
+ */
+ pd[port].low_power_ts.val = get_time().val +
+ 2*(PD_T_DRP_SRC + PD_T_DRP_SNK);
+#endif
+
/*
* Before CC pull can be changed and the task can read the new
* status, we should set the CC status to open, in case TCPM
@@ -1050,6 +1086,10 @@ void tcpc_init(int port)
pd_hw_init(port, PD_ROLE_DEFAULT);
pd[port].cc_pull = PD_ROLE_DEFAULT == PD_ROLE_SOURCE ? TYPEC_CC_RP :
TYPEC_CC_RD;
+#ifdef TCPC_LOW_POWER
+ /* Don't use low power immediately after boot */
+ pd[port].low_power_ts.val = get_time().val + SECOND;
+#endif
/* make sure PD monitoring is disabled initially */
pd[port].rx_enabled = 0;