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+ 	bool  enabled ;
58+ 	bool  vbus_present ;
5459	uint8_t  controller_id ; /* 0xFF is invalid value */ 
5560};
5661
@@ -92,6 +97,50 @@ static int udc_mcux_control(const struct device *dev, usb_device_control_type_t
9297	return  0 ;
9398}
9499
100+ /* Helper function to keep track of the activity state for the udc */ 
101+ static  void  udc_mcux_change_state (const  struct  device  * dev , bool  enabled , 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  &&  enabled ) {
110+ 		udc_submit_event (data -> dev ,
111+ 				 vbus_present  ? UDC_EVT_VBUS_READY  : UDC_EVT_VBUS_REMOVED , 0 );
112+ 	}
113+ 	if  (enabled  &&  vbus_present ) {
114+ 		data -> enabled  =  true;
115+ 		data -> vbus_present  =  true;
116+ 
117+ 		/* 
118+ 		 * Block PM when usb is active. 
119+ 		 */ 
120+ #if  defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS )
121+ 		pm_policy_device_power_lock_get (dev );
122+ #endif 
123+ 	} else  if  (data -> enabled  &&  data -> vbus_present ) {
124+ 		/* 
125+ 		 * USB was previously busy, but now has either lost 
126+ 		 * VBUS signal or application has disabled udc. 
127+ 		 */ 
128+ 		data -> enabled  =  enabled ;
129+ 		data -> vbus_present  =  vbus_present ;
130+ 
131+ 		/* 
132+ 		 * UDC will now unblock PM 
133+ 		 */ 
134+ #if  defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS )
135+ 		pm_policy_device_power_lock_put (dev );
136+ #endif 
137+ 	} else  {
138+ 		/* USB still not activated, keep track of what's on and off */ 
139+ 		data -> enabled  =  enabled ;
140+ 		data -> vbus_present  =  vbus_present ;
141+ 	}
142+ }
143+ 
95144/* If ep is busy, return busy. Otherwise feed the buf to controller */ 
96145static  int  udc_mcux_ep_feed (const  struct  device  * dev ,
97146			struct  udc_ep_config  * const  cfg ,
@@ -525,10 +574,10 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg)
525574	case  kUSB_DeviceNotifyLPMSleep :
526575		break ;
527576	case  kUSB_DeviceNotifyDetach :
528- 		udc_submit_event (dev , UDC_EVT_VBUS_REMOVED , 0 );
577+ 		udc_mcux_change_state (dev , priv -> enabled , 0 );
529578		break ;
530579	case  kUSB_DeviceNotifyAttach :
531- 		udc_submit_event (dev , UDC_EVT_VBUS_READY ,  0 );
580+ 		udc_mcux_change_state (dev , priv -> enabled ,  1 );
532581		break ;
533582	case  kUSB_DeviceNotifySOF :
534583		udc_submit_event (dev , UDC_EVT_SOF , 0 );
@@ -676,11 +725,19 @@ static int udc_mcux_set_address(const struct device *dev, const uint8_t addr)
676725
677726static  int  udc_mcux_enable (const  struct  device  * dev )
678727{
728+ 	struct  udc_mcux_data  * priv  =  udc_get_private (dev );
729+ 
730+ 	udc_mcux_change_state (dev , 1 , priv -> vbus_present );
731+ 
679732	return  udc_mcux_control (dev , kUSB_DeviceControlRun , NULL );
680733}
681734
682735static  int  udc_mcux_disable (const  struct  device  * dev )
683736{
737+ 	struct  udc_mcux_data  * priv  =  udc_get_private (dev );
738+ 
739+ 	udc_mcux_change_state (dev , 0 , priv -> vbus_present );
740+ 
684741	return  udc_mcux_control (dev , kUSB_DeviceControlStop , NULL );
685742}
686743
@@ -759,7 +816,9 @@ static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv,
759816	}
760817}
761818
762- static  int  udc_mcux_driver_preinit (const  struct  device  * dev )
819+ 
820+ 
821+ static  int  udc_mcux_init_common (const  struct  device  * dev )
763822{
764823	const  struct  udc_mcux_config  * config  =  dev -> config ;
765824	struct  udc_data  * data  =  dev -> data ;
@@ -771,9 +830,6 @@ static int udc_mcux_driver_preinit(const struct device *dev)
771830		return  - ENOMEM ;
772831	}
773832
774- 	k_mutex_init (& data -> mutex );
775- 	k_fifo_init (& priv -> fifo );
776- 	k_work_init (& priv -> work , udc_mcux_work_handler );
777833
778834	for  (int  i  =  0 ; i  <  config -> num_of_eps ; i ++ ) {
779835		config -> ep_cfg_out [i ].caps .out  =  1 ;
@@ -823,11 +879,52 @@ static int udc_mcux_driver_preinit(const struct device *dev)
823879	data -> caps .hs  =  true;
824880	priv -> dev  =  dev ;
825881
882+ 
826883	pinctrl_apply_state (config -> pincfg , PINCTRL_STATE_DEFAULT );
827884
828885	return  0 ;
829886}
830887
888+ static  int  udc_mcux_driver_preinit (const  struct  device  * dev )
889+ {
890+ 	const  struct  udc_mcux_config  * config  =  dev -> config ;
891+ 	struct  udc_data  * data  =  dev -> data ;
892+ 	struct  udc_mcux_data  * priv  =  data -> priv ;
893+ 
894+ 	udc_mcux_get_hal_driver_id (priv , config );
895+ 	if  (priv -> controller_id  ==  0xFFu ) {
896+ 		return  - ENOMEM ;
897+ 	}
898+ 
899+ 	k_mutex_init (& data -> mutex );
900+ 	k_fifo_init (& priv -> fifo );
901+ 	k_work_init (& priv -> work , udc_mcux_work_handler );
902+ 	return  udc_mcux_init_common (dev );
903+ }
904+ 
905+ #ifdef  CONFIG_PM 
906+ static  int  udc_mcux_pm_action (const  struct  device  * dev , enum  pm_device_action  action )
907+ {
908+ 	struct  udc_mcux_data  * priv  =  udc_get_private (dev );
909+ 
910+ 	switch  (action ) {
911+ 	case  PM_DEVICE_ACTION_RESUME :
912+ 	case  PM_DEVICE_ACTION_SUSPEND :
913+ 	case  PM_DEVICE_ACTION_TURN_OFF :
914+ 		break ;
915+ 	case  PM_DEVICE_ACTION_TURN_ON :
916+ 		udc_mcux_init_common (dev );
917+ 		if  (priv -> enabled ) {
918+ 			udc_mcux_control (dev , kUSB_DeviceControlRun , NULL );
919+ 		}
920+ 		break ;
921+ 	default :
922+ 		return  - ENOTSUP ;
923+ 	}
924+ 	return  0 ;
925+ }
926+ #endif  /* CONFIG_PM */ 
927+ 
831928static  const  struct  udc_api  udc_mcux_api  =  {
832929	.device_speed  =  udc_mcux_device_speed ,
833930	.ep_enqueue  =  udc_mcux_ep_enqueue ,
@@ -913,7 +1010,8 @@ static usb_phy_config_struct_t phy_config_##n = {					\
9131010		.priv = &priv_data_##n,							\
9141011	};										\
9151012											\
916- 	DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, NULL,				\
1013+ 	PM_DEVICE_DT_INST_DEFINE(n, udc_mcux_pm_action);				\
1014+ 	DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, PM_DEVICE_DT_INST_GET(n),	\
9171015			      &udc_data_##n, &priv_config_##n,				\
9181016			      POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,		\
9191017			      &udc_mcux_api);
0 commit comments