2323#include "usb_phy.h"
2424
2525#include <zephyr/logging/log.h>
26+ #include <zephyr/pm/device.h>
27+ #include <zephyr/pm/policy.h>
2628LOG_MODULE_REGISTER (udc_mcux , CONFIG_UDC_DRIVER_LOG_LEVEL );
2729
2830/*
@@ -34,6 +36,7 @@ LOG_MODULE_REGISTER(udc_mcux, CONFIG_UDC_DRIVER_LOG_LEVEL);
3436
3537#define PRV_DATA_HANDLE (_handle ) CONTAINER_OF(_handle, struct udc_mcux_data, mcux_device)
3638
39+
3740struct udc_mcux_config {
3841 const usb_device_controller_interface_struct_t * mcux_if ;
3942 void (* irq_enable_func )(const struct device * dev );
@@ -51,6 +54,8 @@ struct udc_mcux_data {
5154 usb_device_struct_t mcux_device ;
5255 struct k_work work ;
5356 struct k_fifo fifo ;
57+ volatile bool enabled ;
58+ volatile bool vbus_present ;
5459 uint8_t controller_id ; /* 0xFF is invalid value */
5560};
5661
@@ -92,6 +97,41 @@ static int udc_mcux_control(const struct device *dev, usb_device_control_type_t
9297 return 0 ;
9398}
9499
100+ static void udc_mcux_change_state (const struct device * dev , const bool enabled ,
101+ const bool vbus_present )
102+ {
103+ struct udc_mcux_data * data = udc_get_private (dev );
104+
105+ if (data -> enabled == enabled && data -> vbus_present == vbus_present ) {
106+ return ;
107+ }
108+
109+ if (vbus_present != data -> vbus_present ) {
110+ udc_submit_event (data -> dev ,
111+ vbus_present ? UDC_EVT_VBUS_READY : UDC_EVT_VBUS_REMOVED , 0 );
112+ }
113+
114+ if (enabled && vbus_present ) {
115+
116+ /*
117+ * Block PM when usb is receives VBUS signal or device
118+ * is explicitly told to be enabled.
119+ */
120+ pm_policy_device_power_lock_get (dev );
121+ } else if (data -> enabled && data -> vbus_present ) {
122+
123+ /*
124+ * USB was previously busy, but now has either lost
125+ * VBUS signal or application has disabled udc.
126+ * UDC will now unblock PM.
127+ */
128+ pm_policy_device_power_lock_put (dev );
129+ }
130+
131+ data -> enabled = enabled ;
132+ data -> vbus_present = vbus_present ;
133+ }
134+
95135/* If ep is busy, return busy. Otherwise feed the buf to controller */
96136static int udc_mcux_ep_feed (const struct device * dev ,
97137 struct udc_ep_config * const cfg ,
@@ -525,10 +565,10 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
525565 case kUSB_DeviceNotifyLPMSleep :
526566 break ;
527567 case kUSB_DeviceNotifyDetach :
528- udc_submit_event (dev , UDC_EVT_VBUS_REMOVED , 0 );
568+ udc_mcux_change_state (dev , priv -> enabled , 0 );
529569 break ;
530570 case kUSB_DeviceNotifyAttach :
531- udc_submit_event (dev , UDC_EVT_VBUS_READY , 0 );
571+ udc_mcux_change_state (dev , priv -> enabled , 1 );
532572 break ;
533573 case kUSB_DeviceNotifySOF :
534574 udc_submit_event (dev , UDC_EVT_SOF , 0 );
@@ -676,11 +716,19 @@ static int udc_mcux_set_address(const struct device *dev, const uint8_t addr)
676716
677717static int udc_mcux_enable (const struct device * dev )
678718{
719+ struct udc_mcux_data * priv = udc_get_private (dev );
720+
721+ udc_mcux_change_state (dev , 1 , priv -> vbus_present );
722+
679723 return udc_mcux_control (dev , kUSB_DeviceControlRun , NULL );
680724}
681725
682726static int udc_mcux_disable (const struct device * dev )
683727{
728+ struct udc_mcux_data * priv = udc_get_private (dev );
729+
730+ udc_mcux_change_state (dev , 0 , priv -> vbus_present );
731+
684732 return udc_mcux_control (dev , kUSB_DeviceControlStop , NULL );
685733}
686734
@@ -759,7 +807,9 @@ static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv,
759807 }
760808}
761809
762- static int udc_mcux_driver_preinit (const struct device * dev )
810+
811+
812+ static int udc_mcux_init_common (const struct device * dev )
763813{
764814 const struct udc_mcux_config * config = dev -> config ;
765815 struct udc_data * data = dev -> data ;
@@ -771,10 +821,6 @@ static int udc_mcux_driver_preinit(const struct device *dev)
771821 return - ENOMEM ;
772822 }
773823
774- k_mutex_init (& data -> mutex );
775- k_fifo_init (& priv -> fifo );
776- k_work_init (& priv -> work , udc_mcux_work_handler );
777-
778824 for (int i = 0 ; i < config -> num_of_eps ; i ++ ) {
779825 config -> ep_cfg_out [i ].caps .out = 1 ;
780826 if (i == 0 ) {
@@ -823,11 +869,48 @@ static int udc_mcux_driver_preinit(const struct device *dev)
823869 data -> caps .hs = true;
824870 priv -> dev = dev ;
825871
872+
826873 pinctrl_apply_state (config -> pincfg , PINCTRL_STATE_DEFAULT );
827874
828875 return 0 ;
829876}
830877
878+ static int udc_mcux_driver_preinit (const struct device * dev )
879+ {
880+ struct udc_data * data = dev -> data ;
881+ struct udc_mcux_data * priv = data -> priv ;
882+
883+ k_mutex_init (& data -> mutex );
884+ k_fifo_init (& priv -> fifo );
885+ k_work_init (& priv -> work , udc_mcux_work_handler );
886+ return udc_mcux_init_common (dev );
887+ }
888+
889+ #ifdef CONFIG_PM_DEVICE
890+ static int udc_mcux_pm_action (const struct device * dev , enum pm_device_action action )
891+ {
892+ struct udc_mcux_data * priv = udc_get_private (dev );
893+
894+ switch (action ) {
895+ case PM_DEVICE_ACTION_RESUME :
896+ case PM_DEVICE_ACTION_SUSPEND :
897+ break ;
898+ case PM_DEVICE_ACTION_TURN_OFF :
899+ udc_mcux_shutdown (dev );
900+ break ;
901+ case PM_DEVICE_ACTION_TURN_ON :
902+ udc_mcux_init_common (dev );
903+ if (priv -> enabled ) {
904+ udc_mcux_control (dev , kUSB_DeviceControlRun , NULL );
905+ }
906+ break ;
907+ default :
908+ return - ENOTSUP ;
909+ }
910+ return 0 ;
911+ }
912+ #endif /* CONFIG_PM_DEVICE */
913+
831914static const struct udc_api udc_mcux_api = {
832915 .device_speed = udc_mcux_device_speed ,
833916 .ep_enqueue = udc_mcux_ep_enqueue ,
@@ -917,7 +1000,8 @@ static usb_phy_config_struct_t phy_config_##n = { \
9171000 .priv = &priv_data_##n, \
9181001 }; \
9191002 \
920- DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, NULL, \
1003+ PM_DEVICE_DT_INST_DEFINE(n, udc_mcux_pm_action); \
1004+ DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, PM_DEVICE_DT_INST_GET(n), \
9211005 &udc_data_##n, &priv_config_##n, \
9221006 POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
9231007 &udc_mcux_api);
0 commit comments