usb: dwc2: Fix control OUT transfer issue
authorChance.Yang <chance.yang@vatics.com>
Tue, 6 Oct 2020 02:55:49 +0000 (10:55 +0800)
committerMarek Vasut <marex@denx.de>
Mon, 19 Oct 2020 22:48:58 +0000 (00:48 +0200)
In buffer DMA mode, gadget should re-configure EP 0 to received SETUP
packets when doeptsiz.xfersize is equal to a setup packet size(8 bytes)
and EP 0 is in WAIT_FOR_SETUP state.

Since EP 0 is not enabled in WAIT_FOR_SETUP state, SETUP packets is NOT
received from RxFifo and wriiten to the external memory.

Signed-off-by: Chance.Yang <chance.yang@vatics.com>
drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c

index 1c0505e..f17009a 100644 (file)
@@ -421,6 +421,9 @@ static void process_ep_out_intr(struct dwc2_udc *dev)
 {
        u32 ep_intr, ep_intr_status;
        u8 ep_num = 0;
+       u32 ep_tsr = 0, xfer_size = 0;
+       u32 epsiz_reg = reg->out_endp[ep_num].doeptsiz;
+       u32 req_size = sizeof(struct usb_ctrlrequest);
 
        ep_intr = readl(&reg->daint);
        debug_cond(DEBUG_OUT_EP != 0,
@@ -441,10 +444,17 @@ static void process_ep_out_intr(struct dwc2_udc *dev)
 
                        if (ep_num == 0) {
                                if (ep_intr_status & TRANSFER_DONE) {
-                                       if (dev->ep0state !=
-                                           WAIT_FOR_OUT_COMPLETE)
+                                       ep_tsr = readl(&epsiz_reg);
+                                       xfer_size = ep_tsr &
+                                                  DOEPT_SIZ_XFER_SIZE_MAX_EP0;
+
+                                       if (xfer_size == req_size &&
+                                           dev->ep0state == WAIT_FOR_SETUP) {
+                                               dwc2_udc_pre_setup();
+                                       } else if (dev->ep0state !=
+                                                  WAIT_FOR_OUT_COMPLETE) {
                                                complete_rx(dev, ep_num);
-                                       else {
+                                       else {
                                                dev->ep0state = WAIT_FOR_SETUP;
                                                dwc2_udc_pre_setup();
                                        }