@@ -62,6 +62,8 @@ enum dwc2_drv_event_type {
6262 */
6363#define UDC_DWC2_FIFO0_DEPTH (2 * 16U)
6464
65+ #define UDC_DWC2_TARGET_FRAME_INITIAL UINT16_MAX
66+
6567/* Get Data FIFO access register */
6668#define UDC_DWC2_EP_FIFO (base , idx ) ((mem_addr_t)base + 0x1000 * (idx + 1))
6769
@@ -138,6 +140,9 @@ struct udc_dwc2_data {
138140 /* Number of OUT endpoints including control endpoint */
139141 uint8_t outeps ;
140142 uint8_t setup [8 ];
143+ /* Target frame numbers for isochronous endpoints */
144+ uint16_t target_frames [32 ];
145+ uint32_t target_frame_overrun_mask ;
141146};
142147
143148#if defined(CONFIG_PINCTRL )
@@ -381,6 +386,49 @@ static bool dwc2_ep_is_periodic(struct udc_ep_config *const cfg)
381386 }
382387}
383388
389+ static void dwc2_ep_next_target_frame (const struct device * dev , struct udc_ep_config * const cfg ) {
390+ struct udc_dwc2_data * const priv = udc_get_private (dev );
391+ const uint8_t ep_bitmap_idx = USB_EP_GET_BITMAP_IDX (cfg -> addr );
392+ uint16_t limit = USB_DWC2_DSTS_SOFFN_LIMIT ;
393+
394+ if (priv -> enumspd != USB_DWC2_DSTS_ENUMSPD_HS3060 ) {
395+ limit >>= 3 ;
396+ }
397+
398+ priv -> target_frames [ep_bitmap_idx ] += cfg -> interval ;
399+ if (priv -> target_frames [ep_bitmap_idx ] > limit ) {
400+ priv -> target_frames [ep_bitmap_idx ] &= limit ;
401+ priv -> target_frame_overrun_mask &= BIT (ep_bitmap_idx );
402+ } else {
403+ priv -> target_frame_overrun_mask &= ~BIT (ep_bitmap_idx );
404+ }
405+ }
406+
407+ static bool dwc2_target_frame_elapsed (const struct device * dev , struct udc_ep_config * const cfg )
408+ {
409+ struct udc_dwc2_data * const priv = udc_get_private (dev );
410+ const uint8_t ep_bitmap_idx = USB_EP_GET_BITMAP_IDX (cfg -> addr );
411+ const uint16_t target_frame = priv -> target_frames [ep_bitmap_idx ];
412+ const uint16_t current_frame = priv -> sof_num ;
413+ const bool frame_overrun = priv -> target_frame_overrun_mask & BIT (ep_bitmap_idx );
414+ uint16_t limit = USB_DWC2_DSTS_SOFFN_LIMIT ;
415+
416+ if (priv -> enumspd != USB_DWC2_DSTS_ENUMSPD_HS3060 ) {
417+ limit >>= 3 ;
418+ }
419+
420+ if (!frame_overrun && current_frame >= target_frame ) {
421+ return true;
422+ }
423+
424+ if (frame_overrun && current_frame >= target_frame &&
425+ ((current_frame - target_frame ) < limit / 2 )) {
426+ return true;
427+ }
428+
429+ return false;
430+ }
431+
384432static bool dwc2_ep_is_iso (struct udc_ep_config * const cfg )
385433{
386434 return (cfg -> attributes & USB_EP_TRANSFER_TYPE_MASK ) == USB_EP_TYPE_ISO ;
@@ -566,13 +614,14 @@ static int dwc2_tx_fifo_write(const struct device *dev,
566614 }
567615
568616 if (is_iso ) {
569- /* Queue transfer on next SOF. TODO: allow stack to explicitly
570- * specify on which (micro-)frame the data should be sent.
571- */
572- if (priv -> sof_num & 1 ) {
573- diepctl |= USB_DWC2_DEPCTL_SETEVENFR ;
574- } else {
575- diepctl |= USB_DWC2_DEPCTL_SETODDFR ;
617+ if (cfg -> interval == 1 ) {
618+ const uint8_t ep_bitmap_idx = USB_EP_GET_BITMAP_IDX (cfg -> addr );
619+
620+ if (priv -> target_frames [ep_bitmap_idx ] & 1 ) {
621+ diepctl |= USB_DWC2_DEPCTL_SETODDFR ;
622+ } else {
623+ diepctl |= USB_DWC2_DEPCTL_SETEVENFR ;
624+ }
576625 }
577626 }
578627
@@ -706,10 +755,14 @@ static void dwc2_prep_rx(const struct device *dev, struct net_buf *buf,
706755 }
707756
708757 /* Set the Even/Odd (micro-)frame appropriately */
709- if (priv -> sof_num & 1 ) {
710- doepctl |= USB_DWC2_DEPCTL_SETEVENFR ;
711- } else {
712- doepctl |= USB_DWC2_DEPCTL_SETODDFR ;
758+ if (cfg -> interval == 1 ) {
759+ const uint8_t ep_bitmap_idx = USB_EP_GET_BITMAP_IDX (cfg -> addr );
760+
761+ if (priv -> target_frames [ep_bitmap_idx ] & 1 ) {
762+ doepctl |= USB_DWC2_DEPCTL_SETODDFR ;
763+ } else {
764+ doepctl |= USB_DWC2_DEPCTL_SETEVENFR ;
765+ }
713766 }
714767 } else {
715768 xfersize = net_buf_tailroom (buf );
@@ -1363,6 +1416,7 @@ static int dwc2_set_dedicated_fifo(const struct device *dev,
13631416static int dwc2_ep_control_enable (const struct device * dev ,
13641417 struct udc_ep_config * const cfg )
13651418{
1419+ struct udc_dwc2_data * const priv = udc_get_private (dev );
13661420 mem_addr_t dxepctl0_reg ;
13671421 uint32_t dxepctl0 ;
13681422
@@ -1416,6 +1470,12 @@ static int udc_dwc2_ep_activate(const struct device *dev,
14161470 return dwc2_ep_control_enable (dev , cfg );
14171471 }
14181472
1473+ if (dwc2_ep_is_iso (cfg )) {
1474+ const uint8_t ep_bitmap_idx = USB_EP_GET_BITMAP_IDX (cfg -> addr );
1475+
1476+ priv -> target_frames [ep_bitmap_idx ] = UDC_DWC2_TARGET_FRAME_INITIAL ;
1477+ }
1478+
14191479 if (USB_EP_DIR_IS_OUT (cfg -> addr )) {
14201480 /* TODO: use dwc2_get_dxepctl_reg() */
14211481 dxepctl_reg = (mem_addr_t )& base -> out_ep [ep_idx ].doepctl ;
@@ -2417,6 +2477,7 @@ static void dwc2_on_bus_reset(const struct device *dev)
24172477 uint32_t doepmsk ;
24182478
24192479 /* Set the NAK bit for all OUT endpoints */
2480+ sys_clear_bits ((mem_addr_t )& base -> diepmsk , USB_DWC2_DIEPINT_NAKINTRPT );
24202481 for (uint8_t i = 0U ; i < priv -> numdeveps ; i ++ ) {
24212482 uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir (priv -> ghwcfg1 , i );
24222483 mem_addr_t doepctl_reg ;
@@ -2429,13 +2490,13 @@ static void dwc2_on_bus_reset(const struct device *dev)
24292490 }
24302491 }
24312492
2432- doepmsk = USB_DWC2_DOEPINT_SETUP | USB_DWC2_DOEPINT_XFERCOMPL ;
2493+ doepmsk = USB_DWC2_DOEPINT_SETUP | USB_DWC2_DOEPINT_XFERCOMPL | USB_DWC2_DOEPINT_OUTTKNEPDIS ;
24332494 if (dwc2_in_buffer_dma_mode (dev )) {
24342495 doepmsk |= USB_DWC2_DOEPINT_STSPHSERCVD ;
24352496 }
24362497
24372498 sys_write32 (doepmsk , (mem_addr_t )& base -> doepmsk );
2438- sys_set_bits ((mem_addr_t )& base -> diepmsk , USB_DWC2_DIEPINT_XFERCOMPL );
2499+ sys_set_bits ((mem_addr_t )& base -> diepmsk , USB_DWC2_DIEPINT_XFERCOMPL | USB_DWC2_DIEPINT_NAKINTRPT );
24392500
24402501 /* Software has to handle RxFLvl interrupt only in Completer mode */
24412502 if (dwc2_in_completer_mode (dev )) {
@@ -2562,6 +2623,39 @@ static inline void dwc2_handle_in_xfercompl(const struct device *dev,
25622623 k_event_post (& priv -> drv_evt , BIT (DWC2_DRV_EVT_EP_FINISHED ));
25632624}
25642625
2626+ static inline void dwc2_handle_in_nakintrpt (const struct device * dev ,
2627+ const uint8_t ep_idx )
2628+ {
2629+ struct udc_dwc2_data * const priv = udc_get_private (dev );
2630+ mem_addr_t diepctl_reg = dwc2_get_dxepctl_reg (dev , ep_idx | USB_EP_DIR_IN );
2631+ struct udc_ep_config * ep_cfg = udc_get_ep_cfg (dev , ep_idx | USB_EP_DIR_IN );
2632+ const uint8_t ep_bitmap_idx = USB_EP_GET_BITMAP_IDX (ep_cfg -> addr );
2633+ uint32_t diepctl ;
2634+
2635+ if (!dwc2_ep_is_iso (ep_cfg )) {
2636+ return ;
2637+ }
2638+
2639+ if (priv -> target_frames [ep_bitmap_idx ] == UDC_DWC2_TARGET_FRAME_INITIAL ) {
2640+ priv -> target_frames [ep_bitmap_idx ] = priv -> sof_num ;
2641+ if (ep_cfg -> interval > 1 ) {
2642+ diepctl = sys_read32 (diepctl_reg );
2643+ if (priv -> target_frames [ep_bitmap_idx ] & 1 ) {
2644+ diepctl |= USB_DWC2_DEPCTL_SETODDFR ;
2645+ } else {
2646+ diepctl |= USB_DWC2_DEPCTL_SETEVENFR ;
2647+ }
2648+
2649+ sys_write32 (diepctl , diepctl_reg );
2650+ }
2651+ }
2652+
2653+ // TODO this holy fuck
2654+ //diepctl = sys_read32(diepctl_reg);
2655+ //if (diepctl )
2656+ dwc2_ep_next_target_frame (dev , ep_cfg );
2657+ }
2658+
25652659static inline void dwc2_handle_iepint (const struct device * dev )
25662660{
25672661 struct usb_dwc2_reg * const base = dwc2_get_base (dev );
@@ -2590,6 +2684,9 @@ static inline void dwc2_handle_iepint(const struct device *dev)
25902684 dwc2_handle_in_xfercompl (dev , n );
25912685 }
25922686
2687+ if (status & USB_DWC2_DIEPINT_NAKINTRPT ) {
2688+ dwc2_handle_in_nakintrpt (dev , n );
2689+ }
25932690 }
25942691 }
25952692
@@ -2669,6 +2766,33 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev,
26692766 }
26702767}
26712768
2769+ static inline void dwc2_handle_out_token_ep_disabled (const struct device * dev , const uint8_t ep_idx ) {
2770+ struct udc_dwc2_data * const priv = udc_get_private (dev );
2771+ struct udc_ep_config * ep_cfg = udc_get_ep_cfg (dev , ep_idx );
2772+ const uint8_t ep_bitmap_idx = USB_EP_GET_BITMAP_IDX (ep_cfg -> addr );
2773+
2774+ if (!USB_EP_DIR_IS_OUT (ep_cfg -> addr ) || !dwc2_ep_is_iso (ep_cfg )) {
2775+ return ;
2776+ }
2777+
2778+
2779+ if (priv -> target_frames [ep_bitmap_idx ] == UDC_DWC2_TARGET_FRAME_INITIAL ) {
2780+ priv -> target_frames [ep_bitmap_idx ] = priv -> sof_num ;
2781+ if (ep_cfg -> interval > 1 ) {
2782+ mem_addr_t doepctl_reg = dwc2_get_dxepctl_reg (dev , ep_idx );
2783+ uint32_t doepctl = sys_read32 (doepctl_reg );
2784+ if (priv -> target_frames [ep_bitmap_idx ] & 1 ) {
2785+ doepctl |= USB_DWC2_DEPCTL_SETODDFR ;
2786+ } else {
2787+ doepctl |= USB_DWC2_DEPCTL_SETEVENFR ;
2788+ }
2789+ sys_write32 (doepctl , doepctl_reg );
2790+ }
2791+ }
2792+
2793+ dwc2_ep_next_target_frame (dev , ep_cfg );
2794+ }
2795+
26722796static inline void dwc2_handle_oepint (const struct device * dev )
26732797{
26742798 struct usb_dwc2_reg * const base = dwc2_get_base (dev );
@@ -2734,6 +2858,10 @@ static inline void dwc2_handle_oepint(const struct device *dev)
27342858 if (status & USB_DWC2_DOEPINT_XFERCOMPL ) {
27352859 dwc2_handle_out_xfercompl (dev , n );
27362860 }
2861+
2862+ if (status & USB_DWC2_DOEPINT_OUTTKNEPDIS ) {
2863+ dwc2_handle_out_token_ep_disabled (dev , n );
2864+ }
27372865 }
27382866
27392867 /* Clear OEPINT interrupt */
@@ -2768,7 +2896,7 @@ static void dwc2_handle_incompisoin(const struct device *dev)
27682896
27692897 diepctl = sys_read32 (diepctl_reg );
27702898
2771- /* Check if endpoint didn't receive ISO OUT data */
2899+ /* Check if endpoint didn't receive ISO IN data */
27722900 if ((diepctl & mask ) == val ) {
27732901 struct udc_ep_config * cfg ;
27742902 struct net_buf * buf ;
@@ -2777,6 +2905,10 @@ static void dwc2_handle_incompisoin(const struct device *dev)
27772905 __ASSERT_NO_MSG (cfg && cfg -> stat .enabled &&
27782906 dwc2_ep_is_iso (cfg ));
27792907
2908+ if (!dwc2_target_frame_elapsed (dev , cfg )) {
2909+ continue ;
2910+ }
2911+
27802912 udc_dwc2_ep_disable (dev , cfg , false);
27812913
27822914 buf = udc_buf_get (cfg );
@@ -2832,6 +2964,10 @@ static void dwc2_handle_incompisoout(const struct device *dev)
28322964 __ASSERT_NO_MSG (cfg && cfg -> stat .enabled &&
28332965 dwc2_ep_is_iso (cfg ));
28342966
2967+ if (!dwc2_target_frame_elapsed (dev , cfg )) {
2968+ continue ;
2969+ }
2970+
28352971 udc_dwc2_ep_disable (dev , cfg , false);
28362972
28372973 buf = udc_buf_get (cfg );
0 commit comments