diff options
-rw-r--r-- | common/usb_pd_protocol.c | 14 | ||||
-rw-r--r-- | common/usbc/usb_tc_drp_acc_trysrc_sm.c | 15 | ||||
-rw-r--r-- | common/usbc_ppc.c | 28 | ||||
-rw-r--r-- | include/usbc_ppc.h | 30 |
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. |