@@ -31,6 +31,8 @@ enum dwc2_drv_event_type {
3131 DWC2_DRV_EVT_SETUP ,
3232 /* Transaction on endpoint is finished */
3333 DWC2_DRV_EVT_EP_FINISHED ,
34+ /* Remote Wakeup should be initiated */
35+ DWC2_DRV_EVT_REMOTE_WAKEUP ,
3436 /* Core should enter hibernation */
3537 DWC2_DRV_EVT_ENTER_HIBERNATION ,
3638 /* Core should exit hibernation due to bus reset */
@@ -115,6 +117,7 @@ struct udc_dwc2_data {
115117 /* Configuration flags */
116118 unsigned int dynfifosizing : 1 ;
117119 unsigned int bufferdma : 1 ;
120+ unsigned int syncrst : 1 ;
118121 /* Runtime state flags */
119122 unsigned int hibernated : 1 ;
120123 unsigned int enumdone : 1 ;
@@ -900,7 +903,8 @@ static void dwc2_backup_registers(const struct device *dev)
900903 backup -> pcgcctl = sys_read32 ((mem_addr_t )& base -> pcgcctl );
901904}
902905
903- static void dwc2_restore_essential_registers (const struct device * dev )
906+ static void dwc2_restore_essential_registers (const struct device * dev ,
907+ bool rwup )
904908{
905909 const struct udc_dwc2_config * const config = dev -> config ;
906910 struct usb_dwc2_reg * const base = config -> base ;
@@ -921,15 +925,17 @@ static void dwc2_restore_essential_registers(const struct device *dev)
921925 sys_write32 (backup -> gusbcfg , (mem_addr_t )& base -> gusbcfg );
922926 sys_write32 (backup -> dcfg , (mem_addr_t )& base -> dcfg );
923927
924- pcgcctl |= USB_DWC2_PCGCCTL_RESTOREMODE | USB_DWC2_PCGCCTL_RSTPDWNMODULE ;
928+ if (!rwup ) {
929+ pcgcctl |= USB_DWC2_PCGCCTL_RESTOREMODE | USB_DWC2_PCGCCTL_RSTPDWNMODULE ;
930+ }
925931 sys_write32 (pcgcctl , (mem_addr_t )& base -> pcgcctl );
926932 k_busy_wait (1 );
927933
928934 pcgcctl |= USB_DWC2_PCGCCTL_ESSREGRESTORED ;
929935 sys_write32 (pcgcctl , (mem_addr_t )& base -> pcgcctl );
930936}
931937
932- static void dwc2_restore_device_registers (const struct device * dev )
938+ static void dwc2_restore_device_registers (const struct device * dev , bool rwup )
933939{
934940 const struct udc_dwc2_config * const config = dev -> config ;
935941 struct usb_dwc2_reg * const base = config -> base ;
@@ -948,7 +954,10 @@ static void dwc2_restore_device_registers(const struct device *dev)
948954 sys_write32 (backup -> dieptxf [i - 1 ], (mem_addr_t )& base -> dieptxf [i - 1 ]);
949955 }
950956
951- sys_write32 (backup -> dctl , (mem_addr_t )& base -> dctl );
957+ if (!rwup ) {
958+ sys_write32 (backup -> dctl , (mem_addr_t )& base -> dctl );
959+ }
960+
952961 sys_write32 (backup -> diepmsk , (mem_addr_t )& base -> diepmsk );
953962 sys_write32 (backup -> doepmsk , (mem_addr_t )& base -> doepmsk );
954963 sys_write32 (backup -> daintmsk , (mem_addr_t )& base -> daintmsk );
@@ -1015,7 +1024,7 @@ static void dwc2_enter_hibernation(const struct device *dev)
10151024 LOG_DBG ("Hibernated" );
10161025}
10171026
1018- static void dwc2_exit_hibernation (const struct device * dev )
1027+ static void dwc2_exit_hibernation (const struct device * dev , bool rwup )
10191028{
10201029 const struct udc_dwc2_config * const config = dev -> config ;
10211030 struct usb_dwc2_reg * const base = config -> base ;
@@ -1038,14 +1047,24 @@ static void dwc2_exit_hibernation(const struct device *dev)
10381047 /* Disable power clamps */
10391048 sys_clear_bits (gpwrdn_reg , USB_DWC2_GPWRDN_PWRDNCLMP );
10401049
1050+ if (rwup ) {
1051+ if (priv -> syncrst ) {
1052+ k_busy_wait (1 );
1053+ } else {
1054+ k_busy_wait (50 );
1055+ }
1056+ }
1057+
10411058 /* Remove reset to the controller */
10421059 sys_set_bits (gpwrdn_reg , USB_DWC2_GPWRDN_PWRDNRST_N );
10431060 k_busy_wait (1 );
10441061
10451062 /* Disable PMU interrupt */
10461063 sys_clear_bits (gpwrdn_reg , USB_DWC2_GPWRDN_PMUINTSEL );
10471064
1048- dwc2_restore_essential_registers (dev );
1065+ dwc2_restore_essential_registers (dev , rwup );
1066+
1067+ /* Note: in Remote Wakeup case 15 ms max signaling time starts now */
10491068
10501069 /* Wait for Restore Done Interrupt */
10511070 dwc2_wait_for_bit (dev , (mem_addr_t )& base -> gintsts , USB_DWC2_GINTSTS_RSTRDONEINT );
@@ -1055,8 +1074,10 @@ static void dwc2_exit_hibernation(const struct device *dev)
10551074 sys_clear_bits (gpwrdn_reg , USB_DWC2_GPWRDN_RESTORE );
10561075 k_busy_wait (1 );
10571076
1058- /* Clear reset to power down module */
1059- sys_clear_bits (pcgcctl_reg , USB_DWC2_PCGCCTL_RSTPDWNMODULE );
1077+ if (!rwup ) {
1078+ /* Clear reset to power down module */
1079+ sys_clear_bits (pcgcctl_reg , USB_DWC2_PCGCCTL_RSTPDWNMODULE );
1080+ }
10601081
10611082 /* Restore GUSBCFG, DCFG and DCTL */
10621083 sys_write32 (priv -> backup .gusbcfg , (mem_addr_t )& base -> gusbcfg );
@@ -1065,9 +1086,15 @@ static void dwc2_exit_hibernation(const struct device *dev)
10651086
10661087 /* Disable PMU */
10671088 sys_clear_bits (gpwrdn_reg , USB_DWC2_GPWRDN_PMUACTV );
1068- k_busy_wait (5 );
1089+ if (!rwup ) {
1090+ k_busy_wait (5 );
1091+ sys_set_bits ((mem_addr_t )& base -> dctl , USB_DWC2_DCTL_PWRONPRGDONE );
1092+ } else {
1093+ k_busy_wait (1 );
1094+ sys_write32 (USB_DWC2_DCTL_RMTWKUPSIG | priv -> backup .dctl ,
1095+ (mem_addr_t )& base -> dctl );
1096+ }
10691097
1070- sys_set_bits ((mem_addr_t )& base -> dctl , USB_DWC2_DCTL_PWRONPRGDONE );
10711098 k_msleep (1 );
10721099 sys_write32 (0xFFFFFFFFUL , (mem_addr_t )& base -> gintsts );
10731100}
@@ -1621,9 +1648,13 @@ static int udc_dwc2_test_mode(const struct device *dev,
16211648
16221649static int udc_dwc2_host_wakeup (const struct device * dev )
16231650{
1651+ struct udc_dwc2_data * const priv = udc_get_private (dev );
1652+
16241653 LOG_DBG ("Remote wakeup from %p" , dev );
16251654
1626- return - ENOTSUP ;
1655+ k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_REMOTE_WAKEUP ));
1656+
1657+ return 0 ;
16271658}
16281659
16291660/* Return actual USB device speed */
@@ -1785,6 +1816,10 @@ static int udc_dwc2_init_controller(const struct device *dev)
17851816 LOG_DBG ("LPM mode is %s" ,
17861817 (ghwcfg3 & USB_DWC2_GHWCFG3_LPMMODE ) ? "enabled" : "disabled" );
17871818
1819+ if (ghwcfg3 & USB_DWC2_GHWCFG3_RSTTYPE ) {
1820+ priv -> syncrst = 1 ;
1821+ }
1822+
17881823 /* Configure AHB, select Completer or DMA mode */
17891824 gahbcfg = sys_read32 (gahbcfg_reg );
17901825
@@ -1988,7 +2023,7 @@ static int udc_dwc2_disable(const struct device *dev)
19882023 config -> irq_disable_func (dev );
19892024
19902025 if (priv -> hibernated ) {
1991- dwc2_exit_hibernation (dev );
2026+ dwc2_exit_hibernation (dev , false );
19922027 priv -> hibernated = 0 ;
19932028 }
19942029
@@ -2045,6 +2080,7 @@ static int dwc2_driver_preinit(const struct device *dev)
20452080 k_event_init (& priv -> xfer_new );
20462081 k_event_init (& priv -> xfer_finished );
20472082
2083+ data -> caps .rwup = true;
20482084 data -> caps .addr_before_status = true;
20492085 data -> caps .mps0 = UDC_MPS0_64 ;
20502086
@@ -2704,20 +2740,36 @@ static void udc_dwc2_isr_handler(const struct device *dev)
27042740}
27052741
27062742static void dwc2_handle_hibernation_exit (const struct device * dev ,
2707- bool bus_reset )
2743+ bool rwup , bool bus_reset )
27082744{
2745+ struct usb_dwc2_reg * const base = dwc2_get_base (dev );
27092746 struct udc_dwc2_data * const priv = udc_get_private (dev );
27102747
2711- dwc2_exit_hibernation (dev );
2712- dwc2_restore_device_registers (dev );
2748+ dwc2_exit_hibernation (dev , rwup );
2749+ dwc2_restore_device_registers (dev , rwup );
27132750
27142751 priv -> hibernated = 0 ;
2715- LOG_DBG ("Hibernation exit complete" );
2752+ if (!rwup ) {
2753+ LOG_DBG ("Hibernation exit complete" );
2754+ }
27162755
27172756 /* Let stack know we are no longer suspended */
27182757 udc_set_suspended (dev , false);
27192758 udc_submit_event (dev , UDC_EVT_RESUME , 0 );
27202759
2760+ if (rwup ) {
2761+ /* Resume has been driven for at least 1 ms now, do 1 ms more to
2762+ * have sufficient margin.
2763+ */
2764+ k_msleep (1 );
2765+
2766+ sys_clear_bits ((mem_addr_t )& base -> dctl , USB_DWC2_DCTL_RMTWKUPSIG );
2767+ }
2768+
2769+ if (rwup ) {
2770+ LOG_DBG ("Hibernation exit on Remote Wakeup complete" );
2771+ }
2772+
27212773 if (bus_reset ) {
27222774 /* Clear all pending transfers */
27232775 k_event_clear (& priv -> xfer_new , UINT32_MAX );
@@ -2754,6 +2806,7 @@ static uint8_t pull_next_ep_from_bitmap(uint32_t *bitmap)
27542806static ALWAYS_INLINE void dwc2_thread_handler (void * const arg )
27552807{
27562808 const struct device * dev = (const struct device * )arg ;
2809+ struct usb_dwc2_reg * const base = dwc2_get_base (dev );
27572810 struct udc_dwc2_data * const priv = udc_get_private (dev );
27582811 const struct udc_dwc2_config * const config = dev -> config ;
27592812 struct udc_ep_config * ep_cfg ;
@@ -2833,6 +2886,29 @@ static ALWAYS_INLINE void dwc2_thread_handler(void *const arg)
28332886 dwc2_handle_evt_setup (dev );
28342887 }
28352888
2889+ if (evt & BIT (DWC2_DRV_EVT_REMOTE_WAKEUP )) {
2890+ k_event_clear (& priv -> drv_evt , BIT (DWC2_DRV_EVT_REMOTE_WAKEUP ) |
2891+ BIT (DWC2_DRV_EVT_ENTER_HIBERNATION ));
2892+
2893+ if (priv -> hibernated ) {
2894+ config -> irq_disable_func (dev );
2895+
2896+ dwc2_handle_hibernation_exit (dev , true, false);
2897+
2898+ config -> irq_enable_func (dev );
2899+ } else {
2900+ sys_set_bits ((mem_addr_t )& base -> dctl , USB_DWC2_DCTL_RMTWKUPSIG );
2901+
2902+ udc_set_suspended (dev , false);
2903+ udc_submit_event (dev , UDC_EVT_RESUME , 0 );
2904+
2905+ /* Drive resume for 2 ms to have sufficient margin */
2906+ k_msleep (2 );
2907+
2908+ sys_clear_bits ((mem_addr_t )& base -> dctl , USB_DWC2_DCTL_RMTWKUPSIG );
2909+ }
2910+ }
2911+
28362912 if (evt & BIT (DWC2_DRV_EVT_ENTER_HIBERNATION )) {
28372913 config -> irq_disable_func (dev );
28382914
@@ -2856,7 +2932,7 @@ static ALWAYS_INLINE void dwc2_thread_handler(void *const arg)
28562932 bus_reset = prev & BIT (DWC2_DRV_EVT_HIBERNATION_EXIT_BUS_RESET );
28572933
28582934 if (priv -> hibernated ) {
2859- dwc2_handle_hibernation_exit (dev , bus_reset );
2935+ dwc2_handle_hibernation_exit (dev , false, bus_reset );
28602936 }
28612937
28622938 config -> irq_enable_func (dev );
0 commit comments