summaryrefslogtreecommitdiff
path: root/common/usb_pd_tcpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/usb_pd_tcpc.c')
-rw-r--r--common/usb_pd_tcpc.c42
1 files changed, 41 insertions, 1 deletions
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;