@@ -139,6 +139,7 @@ struct udc_dwc2_data {
139
139
unsigned int hibernated : 1 ;
140
140
unsigned int enumdone : 1 ;
141
141
unsigned int enumspd : 2 ;
142
+ unsigned int pending_dout_feed : 1 ;
142
143
enum dwc2_suspend_type suspend_type ;
143
144
/* Number of endpoints including control endpoint */
144
145
uint8_t numdeveps ;
@@ -428,10 +429,28 @@ static void dwc2_ensure_setup_ready(const struct device *dev)
428
429
if (dwc2_in_completer_mode (dev )) {
429
430
/* In Completer mode EP0 can always receive SETUP data */
430
431
return ;
432
+ } else {
433
+ struct udc_dwc2_data * const priv = udc_get_private (dev );
434
+
435
+ /* Enable EP0 OUT only if there is no pending EP0 IN transfer
436
+ * after which the stack has to enable EP0 OUT.
437
+ */
438
+ if (!priv -> pending_dout_feed ) {
439
+ dwc2_ctrl_feed_dout (dev , 8 );
440
+ }
431
441
}
442
+ }
432
443
433
- if (!udc_buf_peek (udc_get_ep_cfg (dev , USB_CONTROL_EP_IN ))) {
434
- dwc2_ctrl_feed_dout (dev , 8 );
444
+ static void dwc2_clear_control_in_nak (const struct device * dev )
445
+ {
446
+ struct usb_dwc2_reg * const base = dwc2_get_base (dev );
447
+ mem_addr_t diepctl_reg = (mem_addr_t )& base -> in_ep [0 ].diepctl ;
448
+ uint32_t diepctl = sys_read32 (diepctl_reg );
449
+
450
+ if (diepctl & USB_DWC2_DEPCTL_NAKSTS ) {
451
+ diepctl &= ~USB_DWC2_DEPCTL_EPENA ;
452
+ diepctl |= USB_DWC2_DEPCTL_CNAK ;
453
+ sys_write32 (diepctl , diepctl_reg );
435
454
}
436
455
}
437
456
@@ -590,7 +609,11 @@ static int dwc2_tx_fifo_write(const struct device *dev,
590
609
}
591
610
592
611
/* Clear NAK and set endpoint enable */
593
- diepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_CNAK ;
612
+ diepctl |= USB_DWC2_DEPCTL_EPENA ;
613
+ if (cfg -> addr != USB_CONTROL_EP_IN ) {
614
+ /* Non-control endpoint, set CNAK for all transfers */
615
+ diepctl |= USB_DWC2_DEPCTL_CNAK ;
616
+ }
594
617
sys_write32 (diepctl , diepctl_reg );
595
618
596
619
/* Clear IN Endpoint NAK Effective interrupt in case it was set */
@@ -776,6 +799,7 @@ static void dwc2_prep_rx(const struct device *dev, struct net_buf *buf,
776
799
static void dwc2_handle_xfer_next (const struct device * dev ,
777
800
struct udc_ep_config * const cfg )
778
801
{
802
+ struct udc_dwc2_data * const priv = udc_get_private (dev );
779
803
struct net_buf * buf ;
780
804
781
805
buf = udc_buf_peek (cfg );
@@ -803,7 +827,8 @@ static void dwc2_handle_xfer_next(const struct device *dev,
803
827
* avoid race condition where the next Control Write
804
828
* Transfer Data Stage is received into the buffer.
805
829
*/
806
- if (dwc2_in_buffer_dma_mode (dev )) {
830
+ if (dwc2_in_buffer_dma_mode (dev ) && priv -> pending_dout_feed ) {
831
+ priv -> pending_dout_feed = 0 ;
807
832
dwc2_ctrl_feed_dout (dev , 8 );
808
833
}
809
834
}
@@ -872,18 +897,39 @@ static int dwc2_handle_evt_setup(const struct device *dev)
872
897
/* Allocate and feed buffer for data OUT stage */
873
898
LOG_DBG ("s:%p|feed for -out-" , buf );
874
899
900
+ priv -> pending_dout_feed = 0 ;
901
+
902
+ if (dwc2_in_completer_mode (dev )) {
903
+ /* Programming Guide does not clearly describe to clear
904
+ * control IN endpoint NAK for Control Write Transfers
905
+ * when operating in Completer mode. Set CNAK here,
906
+ * because IN endpoint is not armed at this point and
907
+ * forced NAKs are not necessary. IN Status stage will
908
+ * only finish after IN endpoint is armed.
909
+ */
910
+ dwc2_clear_control_in_nak (dev );
911
+ }
912
+
875
913
err = dwc2_ctrl_feed_dout (dev , udc_data_stage_length (buf ));
876
914
if (err == - ENOMEM ) {
877
915
err = udc_submit_ep_event (dev , buf , err );
878
916
}
879
917
} else if (udc_ctrl_stage_is_data_in (dev )) {
880
918
LOG_DBG ("s:%p|feed for -in-status" , buf );
881
919
920
+ dwc2_clear_control_in_nak (dev );
921
+
882
922
err = udc_ctrl_submit_s_in_status (dev );
923
+
924
+ priv -> pending_dout_feed = 1 ;
883
925
} else {
884
926
LOG_DBG ("s:%p|feed >setup" , buf );
885
927
928
+ dwc2_clear_control_in_nak (dev );
929
+
886
930
err = udc_ctrl_submit_s_status (dev );
931
+
932
+ priv -> pending_dout_feed = 1 ;
887
933
}
888
934
889
935
return err ;
@@ -892,6 +938,7 @@ static int dwc2_handle_evt_setup(const struct device *dev)
892
938
static inline int dwc2_handle_evt_dout (const struct device * dev ,
893
939
struct udc_ep_config * const cfg )
894
940
{
941
+ struct udc_dwc2_data * const priv = udc_get_private (dev );
895
942
struct udc_data * data = dev -> data ;
896
943
struct net_buf * buf ;
897
944
int err = 0 ;
@@ -924,6 +971,8 @@ static inline int dwc2_handle_evt_dout(const struct device *dev,
924
971
925
972
if (udc_ctrl_stage_is_status_in (dev )) {
926
973
err = udc_ctrl_submit_s_out_status (dev , buf );
974
+
975
+ priv -> pending_dout_feed = 1 ;
927
976
}
928
977
929
978
if (data -> stage == CTRL_PIPE_STAGE_ERROR ) {
@@ -1623,6 +1672,15 @@ static void udc_dwc2_ep_disable(const struct device *dev,
1623
1672
/* For IN endpoints STALL is set in addition to SNAK */
1624
1673
dxepctl |= USB_DWC2_DEPCTL_STALL ;
1625
1674
}
1675
+
1676
+ /* EP0 status stage enabled, but CNAK not yet written.
1677
+ * Set EPDIS to prevent timeout.
1678
+ */
1679
+ if ((dxepctl & USB_DWC2_DEPCTL_NAKSTS ) &&
1680
+ (dxepctl & USB_DWC2_DEPCTL_EPENA )) {
1681
+ dxepctl |= USB_DWC2_DEPCTL_EPDIS ;
1682
+ }
1683
+
1626
1684
sys_write32 (dxepctl , dxepctl_reg );
1627
1685
1628
1686
/* Endpoint gets disabled in INEPNAKEFF handler */
@@ -2751,13 +2809,15 @@ static inline void dwc2_handle_oepint(const struct device *dev)
2751
2809
}
2752
2810
2753
2811
if (status & USB_DWC2_DOEPINT_STSPHSERCVD ) {
2754
- /* Driver doesn't need any special handling, but it is
2755
- * mandatory that the bit is cleared in Buffer DMA mode.
2812
+ /* Allow IN Status stage after control transfer with
2813
+ * data stage from device to host. Clear the CNAK and
2814
+ * this interrupt bit is mandatory in Buffer DMA mode.
2756
2815
* If the bit is not cleared (i.e. when this interrupt
2757
2816
* bit is masked), then SETUP interrupts will cease
2758
2817
* after first control transfer with data stage from
2759
2818
* device to host.
2760
2819
*/
2820
+ dwc2_clear_control_in_nak (dev );
2761
2821
}
2762
2822
2763
2823
if (status & USB_DWC2_DOEPINT_XFERCOMPL ) {
0 commit comments