summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/usb_pd_protocol.c20
-rw-r--r--common/usb_pd_tcpc.c51
2 files changed, 66 insertions, 5 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 3b5cd5b445..b124ad0245 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -20,6 +20,7 @@
#include "task.h"
#include "timer.h"
#include "util.h"
+#include "usb_charge.h"
#include "usb_mux.h"
#include "usb_pd.h"
#include "usb_pd_tcpm.h"
@@ -211,6 +212,15 @@ int pd_is_connected(int port)
}
#ifdef CONFIG_USB_PD_DUAL_ROLE
+static inline int pd_is_vbus_present(int port)
+{
+#ifdef CONFIG_USB_PD_TCPM_VBUS
+ return tcpm_get_vbus_level(port);
+#else
+ return pd_snk_is_vbus_provided(port);
+#endif
+}
+
static int pd_snk_debug_acc_toggle(int port)
{
#ifdef CONFIG_CASE_CLOSED_DEBUG
@@ -219,7 +229,7 @@ static int pd_snk_debug_acc_toggle(int port)
* (without having seen Rp before), that might be a powered debug
* accessory, let's toggle to source to try to detect it.
*/
- return pd_snk_is_vbus_provided(port);
+ return pd_is_vbus_present(port);
#else
/* Debug accessories not supported, never toggle */
return 0;
@@ -1966,7 +1976,7 @@ void pd_task(void)
/* Wait for CC debounce and VBUS present */
if (get_time().val < pd[port].cc_debounce ||
- !pd_snk_is_vbus_provided(port))
+ !pd_is_vbus_present(port))
break;
if (pd_try_src_enable &&
@@ -2044,7 +2054,7 @@ void pd_task(void)
PD_STATE_SNK_DISCOVERY);
}
- if (!pd_snk_is_vbus_provided(port) &&
+ if (!pd_is_vbus_present(port) &&
!snk_hard_reset_vbus_off) {
/* VBUS has gone low, reset timeout */
snk_hard_reset_vbus_off = 1;
@@ -2054,7 +2064,7 @@ void pd_task(void)
PD_T_SRC_TURN_ON,
PD_STATE_SNK_DISCONNECTED);
}
- if (pd_snk_is_vbus_provided(port) &&
+ if (pd_is_vbus_present(port) &&
snk_hard_reset_vbus_off) {
/* VBUS went high again */
set_state(port, PD_STATE_SNK_DISCOVERY);
@@ -2503,7 +2513,7 @@ void pd_task(void)
* a hard reset.
*/
if (pd[port].power_role == PD_ROLE_SINK &&
- !pd_snk_is_vbus_provided(port) &&
+ !pd_is_vbus_present(port) &&
pd[port].task_state != PD_STATE_SNK_HARD_RESET_RECOVER &&
pd[port].task_state != PD_STATE_HARD_RESET_EXECUTE) {
/* Sink: detect disconnect by monitoring VBUS */
diff --git a/common/usb_pd_tcpc.c b/common/usb_pd_tcpc.c
index d7314b1a53..5c42640d5b 100644
--- a/common/usb_pd_tcpc.c
+++ b/common/usb_pd_tcpc.c
@@ -227,6 +227,9 @@ static struct pd_port_controller {
uint8_t rx_enabled;
/* TCPC flags */
uint8_t flags;
+ /* Power status */
+ uint8_t power_status;
+ uint8_t power_status_mask;
/* Last received */
int rx_head[RX_BUFFER_SIZE+1];
@@ -958,6 +961,29 @@ int tcpc_set_polarity(int port, int polarity)
return EC_SUCCESS;
}
+#ifdef CONFIG_USB_PD_TCPM_VBUS
+static int tcpc_set_power_status(int port, int vbus_present)
+{
+ /* Update VBUS present bit */
+ if (vbus_present)
+ pd[port].power_status |= TCPC_REG_POWER_VBUS_PRES;
+ else
+ pd[port].power_status &= ~TCPC_REG_POWER_VBUS_PRES;
+
+ /* Set bit Port Power Status bit in Alert register */
+ if (pd[port].power_status_mask & TCPC_REG_POWER_VBUS_PRES)
+ alert(port, TCPC_REG_ALERT_POWER_STATUS);
+
+ return EC_SUCCESS;
+}
+#endif /* CONFIG_USB_PD_TCPM_VBUS */
+
+int tcpc_set_power_status_mask(int port, uint8_t mask)
+{
+ pd[port].power_status_mask = mask;
+ return EC_SUCCESS;
+}
+
int tcpc_set_vconn(int port, int enable)
{
#ifdef CONFIG_USBC_VCONN
@@ -1011,6 +1037,25 @@ int tcpc_get_message(int port, uint32_t *payload, int *head)
return EC_SUCCESS;
}
+
+#ifdef CONFIG_USB_PD_TCPM_VBUS
+void pd_vbus_evt_p0(enum gpio_signal signal)
+{
+ tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C0),
+ !gpio_get_level(GPIO_USB_C0_VBUS_WAKE_L));
+ task_wake(TASK_ID_PD_C0);
+}
+
+#if CONFIG_USB_PD_PORT_COUNT >= 2
+void pd_vbus_evt_p1(enum gpio_signal signal)
+{
+ tcpc_set_power_status(TASK_ID_TO_PD_PORT(TASK_ID_PD_C1),
+ !gpio_get_level(GPIO_USB_C1_VBUS_WAKE_L));
+ task_wake(TASK_ID_PD_C1);
+}
+#endif /* PD_PORT_COUNT >= 2 */
+#endif /* CONFIG_USB_PD_TCPM_VBUS */
+
#ifndef CONFIG_USB_POWER_DELIVERY
static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload)
{
@@ -1044,6 +1089,9 @@ static void tcpc_i2c_write(int port, int reg, int len, uint8_t *payload)
tcpc_set_rx_enable(port, payload[1] &
TCPC_REG_RX_DETECT_SOP_HRST_MASK);
break;
+ case TCPC_REG_POWER_STATUS_MASK:
+ tcpc_set_power_status_mask(port, payload[1]);
+ break;
case TCPC_REG_TX_HDR:
pd[port].tx_head = (payload[2] << 8) | payload[1];
break;
@@ -1114,6 +1162,9 @@ static int tcpc_i2c_read(int port, int reg, uint8_t *payload)
memcpy(payload, pd[port].rx_payload[pd[port].rx_buf_tail],
sizeof(pd[port].rx_payload[pd[port].rx_buf_tail]));
return sizeof(pd[port].rx_payload[pd[port].rx_buf_tail]);
+ case TCPC_REG_POWER_STATUS:
+ payload[0] = pd[port].power_status;
+ return 1;
case TCPC_REG_TX_BYTE_CNT:
payload[0] = PD_HEADER_CNT(pd[port].tx_head);
return 1;