summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/usb_pd_protocol.c14
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c15
-rw-r--r--common/usbc_ppc.c28
-rw-r--r--include/usbc_ppc.h30
4 files changed, 65 insertions, 22 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 1fe963f1fc..5b2b344e4d 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -718,7 +718,7 @@ static inline void set_state(int port, enum pd_states next_state)
#if defined(CONFIG_USBC_PPC) && defined(CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE)
/* If we're entering DRP_AUTO_TOGGLE, there is no sink connected. */
if (next_state == PD_STATE_DRP_AUTO_TOGGLE) {
- ppc_sink_is_connected(port, 0);
+ ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED);
/*
* Clear the overcurrent event counter
* since we've detected a disconnect.
@@ -754,10 +754,10 @@ static inline void set_state(int port, enum pd_states next_state)
tcpm_get_cc(port, &cc1, &cc2);
/*
* Neither a debug accessory nor UFP attached.
- * Tell the PPC module that there is no sink connected.
+ * Tell the PPC module that there is no device connected.
*/
if (!cc_is_at_least_one_rd(cc1, cc2)) {
- ppc_sink_is_connected(port, 0);
+ ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED);
/*
* Clear the overcurrent event counter
* since we've detected a disconnect.
@@ -3349,7 +3349,7 @@ void pd_task(void *u)
new_cc_state == PD_CC_UFP_DEBUG_ACC) {
#ifdef CONFIG_USBC_PPC
/* Inform PPC that a sink is connected. */
- ppc_sink_is_connected(port, 1);
+ ppc_dev_is_connected(port, PPC_DEV_SNK);
#endif /* CONFIG_USBC_PPC */
if (new_cc_state == PD_CC_UFP_DEBUG_ACC) {
pd[port].polarity =
@@ -4026,6 +4026,12 @@ void pd_task(void *u)
typec_set_input_current_limit(
port, typec_curr, TYPE_C_VOLTAGE);
#endif
+
+#ifdef CONFIG_USBC_PPC
+ /* Inform PPC that a source is connected. */
+ ppc_dev_is_connected(port, PPC_DEV_SRC);
+#endif /* CONFIG_USBC_PPC */
+
/* If PD comm is enabled, enable TCPC RX */
if (pd_comm_is_enabled(port))
tcpm_set_rx_enable(port, 1);
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index 1756f39c4a..270c7f5f51 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -1985,6 +1985,9 @@ static void tc_unattached_snk_entry(const int port)
charge_manager_update_dualrole(port, CAP_UNKNOWN);
if (IS_ENABLED(CONFIG_USBC_PPC)) {
+ /* There is no source connected. */
+ ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED);
+
/*
* Clear the overcurrent event counter
* since we've detected a disconnect.
@@ -2185,6 +2188,10 @@ static void tc_attached_snk_entry(const int port)
*/
typec_select_pull(port, TYPEC_CC_RD);
+ /* Inform PPC that a source is connected. */
+ if (IS_ENABLED(CONFIG_USBC_PPC))
+ ppc_dev_is_connected(port, PPC_DEV_SRC);
+
#ifdef CONFIG_USB_PE_SM
if (TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) {
/* Flipping power role - Disable AutoDischargeDisconnect */
@@ -2479,7 +2486,7 @@ static void tc_unattached_src_entry(const int port)
if (IS_ENABLED(CONFIG_USBC_PPC)) {
/* There is no sink connected. */
- ppc_sink_is_connected(port, 0);
+ ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED);
/*
* Clear the overcurrent event counter
@@ -2752,7 +2759,7 @@ static void tc_attached_src_entry(const int port)
/* Inform PPC that a sink is connected. */
if (IS_ENABLED(CONFIG_USBC_PPC))
- ppc_sink_is_connected(port, 1);
+ ppc_dev_is_connected(port, PPC_DEV_SNK);
/*
* Only notify if we're not performing a power role swap. During a
@@ -3421,8 +3428,8 @@ static void tc_cc_open_entry(const int port)
typec_update_cc(port);
if (IS_ENABLED(CONFIG_USBC_PPC)) {
- /* There is no sink connected. */
- ppc_sink_is_connected(port, 0);
+ /* There is no device connected. */
+ ppc_dev_is_connected(port, PPC_DEV_DISCONNECTED);
/*
* Clear the overcurrent event counter
diff --git a/common/usbc_ppc.c b/common/usbc_ppc.c
index 7a334ae439..6724d75abf 100644
--- a/common/usbc_ppc.c
+++ b/common/usbc_ppc.c
@@ -10,6 +10,7 @@
#include "console.h"
#include "hooks.h"
#include "timer.h"
+#include "usb_pd.h"
#include "usbc_ppc.h"
#include "util.h"
@@ -46,7 +47,8 @@ int ppc_err_prints(const char *string, int port, int error)
*/
static uint8_t oc_event_cnt_tbl[CONFIG_USB_PD_PORT_MAX_COUNT];
-static uint32_t connected_ports;
+/* A flag for ports with sink device connected. */
+static uint32_t snk_connected_ports;
/* Simple wrappers to dispatch to the drivers. */
@@ -82,7 +84,7 @@ int ppc_add_oc_event(int port)
oc_event_cnt_tbl[port]++;
/* The port overcurrented, so don't clear it's OC events. */
- deprecated_atomic_clear_bits(&connected_ports, 1 << port);
+ deprecated_atomic_clear_bits(&snk_connected_ports, 1 << port);
if (oc_event_cnt_tbl[port] >= PPC_OC_CNT_THRESH)
ppc_prints("OC event limit reached! "
@@ -100,7 +102,7 @@ static void clear_oc_tbl(void)
* Only clear the table if the port partner is no longer
* attached after debouncing.
*/
- if ((!(BIT(port) & connected_ports)) &&
+ if ((!(BIT(port) & snk_connected_ports)) &&
oc_event_cnt_tbl[port]) {
oc_event_cnt_tbl[port] = 0;
ppc_prints("OC events cleared", port);
@@ -256,17 +258,27 @@ int ppc_set_vconn(int port, int enable)
}
#endif
-void ppc_sink_is_connected(int port, int is_connected)
+int ppc_dev_is_connected(int port, enum ppc_device_role dev)
{
+ int rv = EC_SUCCESS;
+ const struct ppc_config_t *ppc;
+
if ((port < 0) || (port >= ppc_cnt)) {
CPRINTS("%s(%d) Invalid port!", __func__, port);
- return;
+ return EC_ERROR_INVAL;
}
- if (is_connected)
- deprecated_atomic_or(&connected_ports, 1 << port);
+ if (dev == PPC_DEV_SNK)
+ deprecated_atomic_or(&snk_connected_ports, 1 << port);
else
- deprecated_atomic_clear_bits(&connected_ports, 1 << port);
+ /* clear flag if it transitions to SRC or disconnected */
+ deprecated_atomic_clear_bits(&snk_connected_ports, 1 << port);
+
+ ppc = &ppc_chips[port];
+ if (ppc->drv->dev_is_connected)
+ rv = ppc->drv->dev_is_connected(port, dev);
+
+ return rv;
}
int ppc_vbus_sink_enable(int port, int enable)
diff --git a/include/usbc_ppc.h b/include/usbc_ppc.h
index 00a2911363..fbff51b596 100644
--- a/include/usbc_ppc.h
+++ b/include/usbc_ppc.h
@@ -23,6 +23,13 @@
*/
#define PPC_OC_COOLDOWN_DELAY_US (2 * SECOND)
+/* The role of connected device. */
+enum ppc_device_role {
+ PPC_DEV_SNK,
+ PPC_DEV_SRC,
+ PPC_DEV_DISCONNECTED,
+};
+
/*
* NOTE: The pointers to functions in the ppc_drv structure can now be NULL
* which will indicate and return NOT_IMPLEMENTED from the main calling
@@ -94,6 +101,17 @@ struct ppc_drv {
*/
int (*discharge_vbus)(int port, int enable);
+ /**
+ * Inform the PPC of the device is connected or disconnected.
+ *
+ * @param port: The Type-C port number.
+ * @param dev: PPC_DEV_SNK if a sink is connected, PPC_DEV_SRC if a
+ * source is connected, PPC_DEV_DISCONNECTED if the device
+ * is disconnected.
+ * @return EC_SUCCESS on success, error otherwise.
+ */
+ int (*dev_is_connected)(int port, enum ppc_device_role dev);
+
#ifdef CONFIG_USBC_PPC_SBU
/**
* Turn on/off the SBU FETs.
@@ -239,15 +257,15 @@ int ppc_is_sourcing_vbus(int port);
int ppc_is_vbus_present(int port);
/**
- * Inform the PPC module that a sink is connected.
+ * Inform the PPC module that a device (either sink or source) is connected.
*
- * This is used such that it can determine when to clear the overcurrent events
- * counter for a port.
+ * This is used such that it can determine when to clear the overcurrent events,
+ * and disable discharge VBUS on a source device connected.
* @param port: The Type-C port number.
- * @param is_connected: 1: if sink is connected on this port, 0: if not
- * connected.
+ * @param dev: PPC_DEV_SNK if a sink is connected, PPC_DEV_SRC if a source is
+ * connected, PPC_DEV_DISCONNECTED if the device is disconnected.
*/
-void ppc_sink_is_connected(int port, int is_connected);
+int ppc_dev_is_connected(int port, enum ppc_device_role dev);
/**
* Inform the PPC of the polarity of the CC pins.