dwusb: fix not send EP0 out status

Duplicated shift on TRBCTL() for EP0StartTransfer.

Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
diff --git a/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.c b/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.c
index 6c77e67..e324f38 100644
--- a/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.c
+++ b/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.c
@@ -279,6 +279,7 @@
     desc->control = DSCCTL_TRBCTL (type);
   }
   desc->control |= DSCCTL_STRMID_SOFN (stream) | ctrlbits;
+  ArmDataSynchronizationBarrier ();
   /* must execute this operation at last */
   if (own) {
     desc->control |= DSCCTL_HWO;
@@ -627,6 +628,7 @@
 
   /* set RUN/STOP bit */
   MmioOr32 (DCTL, DCTL_RUN_STOP);
+DEBUG ((DEBUG_ERROR, "#%a, %d, DCTL:0x%x\n", __func__, __LINE__, MmioRead32 (DCTL)));
 }
 
 #define ALIGN(x, a)     (((x) + ((a) - 1)) & ~((a) - 1))
@@ -704,12 +706,16 @@
   pcd->in_ep.ep_desc = (usb3_dma_desc_t *)ALIGN ((UINTN)pcd->in_ep.epx_desc, 16);
   pcd->out_ep.ep_desc = (usb3_dma_desc_t *)ALIGN ((UINTN)pcd->out_ep.epx_desc, 16);
 #else
-  pcd->ep0_setup_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (32, 16);
-  pcd->ep0_in_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (32, 16);
-  pcd->ep0_out_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (32, 16);
-  pcd->in_ep.ep_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (32, 16);
-  pcd->out_ep.ep_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (32, 16);
+  pcd->ep0_setup_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
+  pcd->ep0_in_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
+  pcd->ep0_out_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
+  pcd->in_ep.ep_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
+  pcd->out_ep.ep_desc = (usb3_dma_desc_t *)UncachedAllocateAlignedZeroPool (64, 64);
 #endif
+DEBUG ((DEBUG_ERROR, "#%a, %d, ep0 setup:0x%x, ep0 in:0x%x, ep0 out:0x%x, epx in:0x%x, epx out:0x%x\n",
+	__func__, __LINE__, pcd->ep0_setup_desc, pcd->ep0_in_desc, pcd->ep0_out_desc, pcd->in_ep.ep_desc, pcd->out_ep.ep_desc));
+DEBUG ((DEBUG_ERROR, "#%a, %d, gEndPoint0SetupPacket:0x%x, gEndPoint0StatusBuf:0x%x\n", __func__, __LINE__,
+	(UINT64)gEndPoint0SetupPacket, (UINT64)gEndPoint0StatusBuf));
 }
 
 STATIC
@@ -876,11 +882,11 @@
 {
   switch (Event & GEVNT_DEVT_MASK) {
   case GEVNT_DEVT_USBRESET:
-DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
+DEBUG ((DEBUG_ERROR, "#%a, %d RST\n", __func__, __LINE__));
     DwUsb3HandleUsbResetInterrupt (pcd);
     break;
   case GEVNT_DEVT_CONNDONE:
-DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
+DEBUG ((DEBUG_ERROR, "#%a, %d CONNDONE\n", __func__, __LINE__));
     DwUsb3HandleConnectDoneInterrupt (pcd);
     break;
   default:
@@ -1034,19 +1040,25 @@
   desc = req->trb;
   desc_dma = req->trbdma;
 
+DEBUG ((DEBUG_ERROR, "#%a, %d, dma:0x%x, dir:%a, state:%d, three_stage:%d\n",
+			__func__, __LINE__, desc_dma, ep0->is_in ? "IN" : "OUT", pcd->ep0state, ep0->three_stage));
   if (ep0->is_in) {
     // start DMA on EP0 IN
     // DMA Descriptor (TRB) setup
     len = req->length;
     if (pcd->ep0state == EP0_IN_STATUS_PHASE) {
       if (ep0->three_stage) {
-        desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_3);
+        desc_type = TRBCTL_STATUS_3;
+        //desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_3);
       } else {
-        desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_2);
+        desc_type = TRBCTL_STATUS_2;
+        //desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_2);
       }
     } else {
-      desc_type = DSCCTL_TRBCTL (TRBCTL_CTLDATA_1ST);
+      desc_type = TRBCTL_CTLDATA_1ST;
+      //desc_type = DSCCTL_TRBCTL (TRBCTL_CTLDATA_1ST);
     }
+DEBUG ((DEBUG_ERROR, "#%a, %d, IN TRB %x\n", __func__, __LINE__, desc_type));
     DwUsb3FillDesc (
       desc,
       (UINT64)req->bufdma,
@@ -1056,21 +1068,35 @@
       DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
       1
       );
+DEBUG ((DEBUG_ERROR, "#%a, %d, IN %x-%x-%x-%x\n", __func__, __LINE__, desc->bptl, desc->bpth, desc->status, desc->control));
     // issue DEPSTRTXFER command to EP0 IN
     ep0->tri_in = DwUsb3DepStartXfer (EP_IN_IDX (0), desc_dma, 0);
+    {
+       UINTN Index;
+       for (Index = 0; Index < 10; Index++) {
+DEBUG ((DEBUG_ERROR, "#%a, %d, OUT %x-%x-%x-%x\n", __func__, __LINE__, desc->bptl, desc->bpth, desc->status, desc->control));
+         MicroSecondDelay (20);
+       }
+    }
   } else {
     // start DMA on EP0 OUT
     // DMA Descriptor (TRB) setup
-    len = (req->length + ep0->maxpacket - 1) & ~(ep0->maxpacket - 1);
+    len = ALIGN (req->length, ep0->maxpacket);
+//DEBUG ((DEBUG_ERROR, "#%a, %d, len:%d\n", __func__, __LINE__, len));
+    //len = (req->length + ep0->maxpacket - 1) & ~(ep0->maxpacket - 1);
     if (pcd->ep0state == EP0_OUT_STATUS_PHASE) {
       if (ep0->three_stage) {
-        desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_3);
+        desc_type = TRBCTL_STATUS_3;
+        //desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_3);
       } else {
-        desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_2);
+        desc_type = TRBCTL_STATUS_2;
+        //desc_type = DSCCTL_TRBCTL (TRBCTL_STATUS_2);
       }
     } else {
-      desc_type = DSCCTL_TRBCTL (TRBCTL_CTLDATA_1ST);
+      desc_type = TRBCTL_CTLDATA_1ST;
+      //desc_type = DSCCTL_TRBCTL (TRBCTL_CTLDATA_1ST);
     }
+DEBUG ((DEBUG_ERROR, "#%a, %d, OUT TRB %x\n", __func__, __LINE__, desc_type));
     DwUsb3FillDesc (
       desc,
       (UINT64)req->bufdma,
@@ -1080,8 +1106,16 @@
       DSCCTL_IOC | DSCCTL_ISP | DSCCTL_LST,
       1
       );
+DEBUG ((DEBUG_ERROR, "#%a, %d, OUT %x-%x-%x-%x\n", __func__, __LINE__, desc->bptl, desc->bpth, desc->status, desc->control));
     // issue DEPSTRTXFER command to EP0 OUT
     ep0->tri_out = DwUsb3DepStartXfer (EP_OUT_IDX (0), desc_dma, 0);
+    {
+       UINTN Index;
+       for (Index = 0; Index < 10; Index++) {
+DEBUG ((DEBUG_ERROR, "#%a, %d, OUT %x-%x-%x-%x\n", __func__, __LINE__, desc->bptl, desc->bpth, desc->status, desc->control));
+         MicroSecondDelay (20);
+       }
+    }
   }
 }
 
@@ -1193,6 +1227,7 @@
   pcd->ep0_req.bufdma = buf;
   pcd->ep0_req.length = 0;
   pcd->ep0_req.actual = 0;
+DEBUG ((DEBUG_ERROR, "#%a, %d, bufdma:0x%x, length:0x%x\n", __func__, __LINE__, pcd->ep0_req.bufdma, pcd->ep0_req.length));
   DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
 }
 
@@ -1208,11 +1243,13 @@
   if (pcd->ep0state == EP0_STALL)
     return;
 
+//DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
   ep0->is_in = 0;
   pcd->ep0state = EP0_OUT_STATUS_PHASE;
   pcd->ep0_req.bufdma = buf;
   pcd->ep0_req.length = 0;
   pcd->ep0_req.actual = 0;
+DEBUG ((DEBUG_ERROR, "#%a, %d, bufdma:0x%x, length:0x%x\n", __func__, __LINE__, pcd->ep0_req.bufdma, pcd->ep0_req.length));
   DwUsb3EndPoint0StartTransfer (pcd, &pcd->ep0_req);
 }
 
@@ -1228,6 +1265,7 @@
   usb3_dma_desc_t     *desc;
   UINT32              byte_count, len;
 
+DEBUG ((DEBUG_ERROR, "#%a, %d, state:%d\n", __func__, __LINE__, pcd->ep0state));
   switch (pcd->ep0state) {
   case EP0_IN_DATA_PHASE:
     if (req == NULL) {
@@ -1290,6 +1328,7 @@
       EndPoint0CompleteRequest (pcd, req, desc);
     }
     break;
+#if 0
   case EP0_IN_WAIT_NRDY:
   case EP0_OUT_WAIT_NRDY:
     if (ep0->is_in) {
@@ -1305,6 +1344,7 @@
     } else {
       desc = pcd->ep0_out_desc;
     }
+//ASSERT (0);
     EndPoint0CompleteRequest (pcd, req, desc);
     // skip test mode
     pcd->ep0state = EP0_IDLE;
@@ -1313,6 +1353,48 @@
     // prepare for more SETUP packets
     DwUsb3Ep0OutStart (pcd);
     break;
+#else
+  case EP0_IN_WAIT_NRDY:
+    if (ep0->is_in) {
+      SetupInStatusPhase (pcd, gEndPoint0SetupPacket);
+    } else {
+      ASSERT (0);
+    }
+    break;
+  case EP0_OUT_WAIT_NRDY:
+    if (!ep0->is_in) {
+      SetupOutStatusPhase (pcd, gEndPoint0SetupPacket);
+    } else {
+      ASSERT (0);
+    }
+    break;
+  case EP0_IN_STATUS_PHASE:
+    if (ep0->is_in) {
+      desc = pcd->ep0_in_desc;
+    } else {
+      ASSERT (0);
+    }
+    EndPoint0CompleteRequest (pcd, req, desc);
+    pcd->ep0state = EP0_IDLE;
+    ep0->stopped = 1;
+    ep0->is_in = 0;  // OUT for next SETUP
+    // prepare for more SETUP packets
+    DwUsb3Ep0OutStart (pcd);
+    break;
+  case EP0_OUT_STATUS_PHASE:
+    if (!ep0->is_in) {
+      desc = pcd->ep0_out_desc;
+    } else {
+      ASSERT (0);
+    }
+    EndPoint0CompleteRequest (pcd, req, desc);
+    pcd->ep0state = EP0_IDLE;
+    ep0->stopped = 1;
+    ep0->is_in = 0;  // OUT for next SETUP
+    // prepare for more SETUP packets
+    DwUsb3Ep0OutStart (pcd);
+    break;
+#endif
   case EP0_STALL:
     break;
   case EP0_IDLE:
@@ -1580,13 +1662,17 @@
 {
   usb_device_request_t *ctrl = &gEndPoint0SetupPacket->req;
 
+DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
   if (ctrl->bmRequestType == UT_DEVICE) {
+DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
     SET_DEVADDR (ctrl->wValue);
     pcd->ep0.is_in = 1;
     pcd->ep0state = EP0_IN_WAIT_NRDY;
     if (ctrl->wValue) {
+DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
       pcd->state = USB3_STATE_ADDRESSED;
     } else {
+DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
       pcd->state = USB3_STATE_DEFAULT;
     }
   }
@@ -1734,6 +1820,7 @@
     return;
   }
 
+DEBUG ((DEBUG_ERROR, "#%a, %d, dt:0x%x\n", __func__, __LINE__, dt));
   switch (dt) {
   case UDESC_DEVICE:
     {
@@ -1925,6 +2012,7 @@
     return;
   }
 
+DEBUG ((DEBUG_ERROR, "#%a, %d, bRequest:0x%x, three stage:%d\n", __func__, __LINE__, ctrl->bRequest, ep0->three_stage));
   switch (ctrl->bRequest) {
   case UR_GET_STATUS:
     DwUsb3DoGetStatus (pcd);
@@ -1949,7 +2037,6 @@
     DwUsb3DoGetConfig (pcd);
     break;
   case UR_GET_DESCRIPTOR:
-    // FIXME
     DwUsb3DoGetDescriptor (pcd);
     break;
   case UR_SET_SEL:
@@ -2058,7 +2145,7 @@
   is_in = (UINT32)PhySep & 1;
   epnum = ((UINT32)PhySep >> 1) & 0xF;
 
-DEBUG ((DEBUG_ERROR, "#%a, %d, dir:%a, epnum:%d\n", __func__, __LINE__, is_in ? "IN" : "OUT", epnum));
+//DEBUG ((DEBUG_ERROR, "#%a, %d, dir:%a, epnum:%d\n", __func__, __LINE__, is_in ? "IN" : "OUT", epnum));
   // Get the EP pointer
   if (is_in) {
     ep = DwUsb3GetInEndPoint (pcd, epnum);
@@ -2068,7 +2155,7 @@
 
   switch (event & GEVNT_DEPEVT_INTTYPE_MASK) {
   case GEVNT_DEPEVT_INTTYPE_XFER_CMPL:
-DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
+DEBUG ((DEBUG_ERROR, "#%a, %d, XFER CMPL, DIR:%a\n", __func__, __LINE__, ep->is_in ? "IN" : "OUT"));
     ep->xfer_started = 0;
     // complete the transfer
     if (epnum == 0) {
@@ -2077,23 +2164,39 @@
       DwUsb3EndPointcompleteRequest (pcd, ep, event);
     }
     break;
+  case GEVNT_DEPEVT_INTTYPE_XFER_IN_PROG:
+DEBUG ((DEBUG_ERROR, "#%a, %d, XFER IN PROG, DIR:%a\n", __func__, __LINE__, ep->is_in ? "IN" : "OUT"));
+    break;
   case GEVNT_DEPEVT_INTTYPE_XFER_NRDY:
-DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
     if (epnum == 0) {
+DEBUG ((DEBUG_ERROR, "#%a, %d, EP0 %a XFER NRDY\n", __func__, __LINE__, ep->is_in ? "IN" : "OUT"));
       switch (pcd->ep0state) {
+#if 1
       case EP0_IN_WAIT_NRDY:
         if (is_in) {
           DwUsb3OsHandleEndPoint0 (pcd, event);
+        } else {
+DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
         }
         break;
       case EP0_OUT_WAIT_NRDY:
         if (!is_in) {
           DwUsb3OsHandleEndPoint0 (pcd, event);
+        } else {
+DEBUG ((DEBUG_ERROR, "#%a, %d\n", __func__, __LINE__));
         }
         break;
+#else
+      case EP0_IN_WAIT_NRDY:
+      case EP0_OUT_WAIT_NRDY:
+        DwUsb3OsHandleEndPoint0 (pcd, event);
+        break;
+#endif
       default:
         break;
       }
+    } else {
+DEBUG ((DEBUG_ERROR, "#%a, %d, EPx XFER NRDY\n", __func__, __LINE__));
     }
     break;
   default:
@@ -2136,7 +2239,7 @@
       }
     } else {
       PhySep = (Event & GEVNT_DEPEVT_EPNUM_MASK) >> GEVNT_DEPEVT_EPNUM_SHIFT;
-DEBUG ((DEBUG_ERROR, "#%a, %d epnum:%d, event:0x%x\n", __func__, __LINE__, PhySep, Event));
+//DEBUG ((DEBUG_ERROR, "#%a, %d epnum:%d, event:0x%x\n", __func__, __LINE__, PhySep, Event));
       DwUsb3HandleEndPointInterrupt (pcd, PhySep, Event);
     }
   }
@@ -2231,7 +2334,7 @@
   if (gEndPoint0SetupPacket == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
-  gEndPoint0StatusBuf = UncachedAllocatePages (EFI_SIZE_TO_PAGES (sizeof (USB3_STATUS_BUF_SIZE)));
+  gEndPoint0StatusBuf = UncachedAllocatePages (EFI_SIZE_TO_PAGES (USB3_STATUS_BUF_SIZE * sizeof (UINT8)));
   if (gEndPoint0StatusBuf == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
diff --git a/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.h b/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.h
index 1856b46..2f3dfed 100644
--- a/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.h
+++ b/Drivers/Usb/DwUsb3Dxe/DwUsb3Dxe.h
@@ -194,6 +194,8 @@
 #define EPCFG1_EP_DIR_IN                 BIT25
 /* Stream Not Ready */
 #define EPCFG1_XFER_NRDY                 BIT10
+/* XferInProgress Enable */
+#define EPCFG1_XFER_IN_PROG              BIT9
 /* Stream Completed */
 #define EPCFG1_XFER_CMPL                 BIT8
 
@@ -232,6 +234,7 @@
 #define TRBCTL_ISOC_1ST                  6
 #define TRBCTL_ISOC                      7
 #define TRBCTL_LINK                      8
+#define TRBCTL_NORMAL_ZLP                9
 
 
 #define UE_DIR_IN                        0x80