From: Vahram Aharonyan <vahr...@synopsys.com>

Add dwc2_gadget_set_ep0_desc_chain() function to switch between EP0 DDMA
chains depend on the stage of control transfer.

Include EP0 DDMA chain selection during ep_queue called from
dwc2_hsotg_enqueue_setup() for setup stage. Selecting and filling DDMA
chain for status phase as well - add calls of
dwc2_gadget_set_ep0_desc_chain() and
dwc2_gadget_config_nonisoc_xfer_ddma() functions.

Signed-off-by: Vahram Aharonyan <vahr...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 58 +++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 53 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 07b7e5a..8b52a07 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1036,6 +1036,41 @@ static bool dwc2_gadget_target_frame_elapsed(struct 
dwc2_hsotg_ep *hs_ep)
        return false;
 }
 
+/*
+ * dwc2_gadget_set_ep0_desc_chain - Set EP's desc chain pointers
+ * @hsotg: The driver state
+ * @hs_ep: the ep descriptor chain is for
+ *
+ * Called to update EP0 structure's pointers depend on stage of
+ * control transfer.
+ */
+static int dwc2_gadget_set_ep0_desc_chain(struct dwc2_hsotg *hsotg,
+                                         struct dwc2_hsotg_ep *hs_ep)
+{
+       switch (hsotg->ep0_state) {
+       case DWC2_EP0_SETUP:
+       case DWC2_EP0_STATUS_OUT:
+               hs_ep->desc_list = hsotg->setup_desc[0];
+               hs_ep->desc_list_dma = hsotg->setup_desc_dma[0];
+               break;
+       case DWC2_EP0_DATA_IN:
+       case DWC2_EP0_STATUS_IN:
+               hs_ep->desc_list = hsotg->ctrl_in_desc;
+               hs_ep->desc_list_dma = hsotg->ctrl_in_desc_dma;
+               break;
+       case DWC2_EP0_DATA_OUT:
+               hs_ep->desc_list = hsotg->ctrl_out_desc;
+               hs_ep->desc_list_dma = hsotg->ctrl_out_desc_dma;
+               break;
+       default:
+               dev_err(hsotg->dev, "invalid EP 0 state in queue %d\n",
+                       hsotg->ep0_state);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
                              gfp_t gfp_flags)
 {
@@ -1071,6 +1106,12 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct 
usb_request *req,
                if (ret)
                        return ret;
        }
+       /* If using descriptor DMA configure EP0 descriptor chain pointers */
+       if (using_desc_dma(hs) && !hs_ep->index) {
+               ret = dwc2_gadget_set_ep0_desc_chain(hs, hs_ep);
+               if (ret)
+                       return ret;
+       }
 
        first = list_empty(&hs_ep->queue);
        list_add_tail(&hs_req->queue, &hs_ep->queue);
@@ -1639,14 +1680,21 @@ static void dwc2_hsotg_program_zlp(struct dwc2_hsotg 
*hsotg,
 
        if (hs_ep->dir_in)
                dev_dbg(hsotg->dev, "Sending zero-length packet on ep%d\n",
-                                                                       index);
+                       index);
        else
                dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
-                                                                       index);
+                       index);
+       if (using_desc_dma(hsotg)) {
+               /* Not specific buffer needed for ep0 ZLP */
+               dma_addr_t dma = hs_ep->desc_list_dma;
 
-       dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
-                   DXEPTSIZ_XFERSIZE(0), hsotg->regs +
-                   epsiz_reg);
+               dwc2_gadget_set_ep0_desc_chain(hsotg, hs_ep);
+               dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, dma, 0);
+       } else {
+               dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+                           DXEPTSIZ_XFERSIZE(0), hsotg->regs +
+                           epsiz_reg);
+       }
 
        ctrl = dwc2_readl(hsotg->regs + epctl_reg);
        ctrl |= DXEPCTL_CNAK;  /* clear NAK set by core */
-- 
2.10.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to