From: Vahram Aharonyan <vahrama@xxxxxxxxxxxx> 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 <vahrama@xxxxxxxxxxxx> Signed-off-by: John Youn <johnyoun@xxxxxxxxxxxx> --- 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 40a6c57..eba0594 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1034,6 +1034,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) { @@ -1069,6 +1104,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); @@ -1637,14 +1678,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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html