diff --git a/dts/bindings/usb-c/usb-c-connector.yaml b/dts/bindings/usb-c/usb-c-connector.yaml index c5e69653a33..4cbcf3f518c 100644 --- a/dts/bindings/usb-c/usb-c-connector.yaml +++ b/dts/bindings/usb-c/usb-c-connector.yaml @@ -54,6 +54,11 @@ properties: description: | VBUS measurement and control for this port. + ppc: + type: phandle + description: | + Power path controller for this port + power-role: type: string required: true diff --git a/subsys/usb/usb_c/usbc_stack.c b/subsys/usb/usb_c/usbc_stack.c index 08ac7cd3cb7..5cf32b70aa7 100644 --- a/subsys/usb/usb_c/usbc_stack.c +++ b/subsys/usb/usb_c/usbc_stack.c @@ -80,6 +80,8 @@ static ALWAYS_INLINE void usbc_handler(void *port_dev) .prl_hr = &prl_hr_##inst, \ .tcpc = DEVICE_DT_GET(DT_INST_PROP(inst, tcpc)), \ .vbus = DEVICE_DT_GET(DT_INST_PROP(inst, vbus)), \ + .ppc = COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, ppc), \ + (DEVICE_DT_GET(DT_INST_PROP(inst, ppc))), (NULL)), \ }; \ \ static const struct usbc_port_config usbc_port_config_##inst = { \ diff --git a/subsys/usb/usb_c/usbc_stack.h b/subsys/usb/usb_c/usbc_stack.h index ca95f05f317..a7948ee33f3 100644 --- a/subsys/usb/usb_c/usbc_stack.h +++ b/subsys/usb/usb_c/usbc_stack.h @@ -101,6 +101,8 @@ struct usbc_port_data { const struct device *tcpc; /** VBUS Measurement and control device on this port */ const struct device *vbus; + /** Power Path Controller device on this port */ + const struct device *ppc; /** Device Policy Manager Request FIFO */ struct k_fifo request_fifo; diff --git a/subsys/usb/usb_c/usbc_tc_common.c b/subsys/usb/usb_c/usbc_tc_common.c index 94b34edf218..e4a58a24899 100644 --- a/subsys/usb/usb_c/usbc_tc_common.c +++ b/subsys/usb/usb_c/usbc_tc_common.c @@ -11,6 +11,7 @@ LOG_MODULE_DECLARE(usbc_stack, CONFIG_USBC_STACK_LOG_LEVEL); #include "usbc_tc_snk_states_internal.h" #include "usbc_tc_src_states_internal.h" #include "usbc_tc_common_internal.h" +#include static const struct smf_state tc_states[TC_STATE_COUNT]; static int tc_init(const struct device *dev); @@ -152,6 +153,11 @@ static int tc_init(const struct device *dev) return ret; } + /* Disable VBUS sourcing by the PPC */ + if (data->ppc != NULL) { + ppc_set_src_ctrl(data->ppc, false); + } + /* Stop sourcing VCONN */ ret = tcpc_set_vconn(tcpc, false); if (ret != 0 && ret != -ENOTSUP) { diff --git a/subsys/usb/usb_c/usbc_tc_snk_states.c b/subsys/usb/usb_c/usbc_tc_snk_states.c index 11cc456acfb..df89990dec8 100644 --- a/subsys/usb/usb_c/usbc_tc_snk_states.c +++ b/subsys/usb/usb_c/usbc_tc_snk_states.c @@ -10,6 +10,7 @@ LOG_MODULE_DECLARE(usbc_stack, CONFIG_USBC_STACK_LOG_LEVEL); #include "usbc_stack.h" #include "usbc_tc_snk_states_internal.h" #include "usbc_tc_common_internal.h" +#include /** * @brief Sink power sub states. Only called if a PD contract is not in place @@ -214,6 +215,14 @@ void tc_attached_snk_entry(void *obj) /* Enable PD */ tc_pd_enable(dev, true); + + /* Enable sink path for the PPC */ + if (data->ppc != NULL) { + ret = ppc_set_snk_ctrl(data->ppc, true); + if (ret != 0 && ret != -ENOTSUP) { + LOG_ERR("Couldn't enable PPC sink path: %d", ret); + } + } } /** @@ -245,9 +254,19 @@ void tc_attached_snk_exit(void *obj) { struct tc_sm_t *tc = (struct tc_sm_t *)obj; const struct device *dev = tc->dev; + struct usbc_port_data *data = dev->data; + int ret; /* Disable PD */ tc_pd_enable(dev, false); + + /* Disable sink path for the PPC */ + if (data->ppc != NULL) { + ret = ppc_set_snk_ctrl(data->ppc, false); + if (ret != 0 && ret != -ENOTSUP) { + LOG_ERR("Couldn't disable PPC sink path: %d", ret); + } + } } /** diff --git a/subsys/usb/usb_c/usbc_tc_src_states.c b/subsys/usb/usb_c/usbc_tc_src_states.c index 972c7cdef54..f24ba9fe8a0 100644 --- a/subsys/usb/usb_c/usbc_tc_src_states.c +++ b/subsys/usb/usb_c/usbc_tc_src_states.c @@ -9,6 +9,7 @@ LOG_MODULE_DECLARE(usbc_stack, CONFIG_USBC_STACK_LOG_LEVEL); #include "usbc_stack.h" #include "usbc_tc_src_states_internal.h" +#include /** * @brief Spec. Release 1.3, section 4.5.2.2.7 Unattached.SRC State @@ -253,6 +254,16 @@ void tc_attached_src_entry(void *obj) /* Enable PD */ tc_pd_enable(dev, true); + + /* Enable the VBUS sourcing by the PPC */ + if (data->ppc != NULL) { + int ret; + + ret = ppc_set_src_ctrl(data->ppc, true); + if (ret < 0 && ret != -ENOSYS) { + LOG_ERR("Couldn't disable PPC source"); + } + } } void tc_attached_src_run(void *obj) @@ -304,6 +315,16 @@ void tc_attached_src_exit(void *obj) /* Stop sourcing VBUS */ data->policy_cb_src_en(dev, false); + /* Disable the VBUS sourcing by the PPC */ + if (data->ppc != NULL) { + int ret; + + ret = ppc_set_src_ctrl(data->ppc, false); + if (ret < 0 && ret != -ENOSYS) { + LOG_ERR("Couldn't disable PPC source"); + } + } + /* Stop sourcing VCONN */ ret = tcpc_set_vconn(tcpc, false); if (ret != 0 && ret != -ENOSYS) {