diff options
author | Vahram Aharonyan <vahrama@synopsys.com> | 2016-11-10 04:27:56 +0100 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2016-11-18 12:54:19 +0100 |
commit | 0f6b80c0dbba7e0a76b6761e0f78d064b2ac9c17 (patch) | |
tree | ee24ce389b1058121e49b79f7a14fee4f5915e00 /drivers/usb/dwc2 | |
parent | usb: dwc2: gadget: Add DMA descriptor status quadlet fields (diff) | |
download | linux-0f6b80c0dbba7e0a76b6761e0f78d064b2ac9c17.tar.xz linux-0f6b80c0dbba7e0a76b6761e0f78d064b2ac9c17.zip |
usb: dwc2: gadget: Add DMA descriptor chains for EP 0
Update dwc2_hsotg structure to add descriptor chains for EP 0: two DMA
descriptors for Setup phase, per one for IN/OUT data and status phases.
Add their allocation function dwc2_gadget_alloc_ctrl_desc_chains() and
its call during gadget probe.
Signed-off-by: Vahram Aharonyan <vahrama@synopsys.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r-- | drivers/usb/dwc2/core.h | 13 | ||||
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 54 |
2 files changed, 67 insertions, 0 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 32a3cfc6f3bf..26d4c1716adf 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -884,6 +884,12 @@ struct dwc2_hregs_backup { * @ctrl_req: Request for EP0 control packets. * @ep0_state: EP0 control transfers state * @test_mode: USB test mode requested by the host + * @setup_desc_dma: EP0 setup stage desc chain DMA address + * @setup_desc: EP0 setup stage desc chain pointer + * @ctrl_in_desc_dma: EP0 IN data phase desc chain DMA address + * @ctrl_in_desc: EP0 IN data phase desc chain pointer + * @ctrl_out_desc_dma: EP0 OUT data phase desc chain DMA address + * @ctrl_out_desc: EP0 OUT data phase desc chain pointer * @eps: The endpoints being supplied to the gadget framework */ struct dwc2_hsotg { @@ -1027,6 +1033,13 @@ struct dwc2_hsotg { enum dwc2_ep0_state ep0_state; u8 test_mode; + dma_addr_t setup_desc_dma[2]; + struct dwc2_dma_desc *setup_desc[2]; + dma_addr_t ctrl_in_desc_dma; + struct dwc2_dma_desc *ctrl_in_desc; + dma_addr_t ctrl_out_desc_dma; + struct dwc2_dma_desc *ctrl_out_desc; + struct usb_gadget gadget; unsigned int enabled:1; unsigned int connected:1; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 4013518265c0..729bc02d0f6e 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -324,6 +324,54 @@ static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg, usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in); } +/* + * dwc2_gadget_alloc_ctrl_desc_chains - allocate DMA descriptor chains + * for Control endpoint + * @hsotg: The device state. + * + * This function will allocate 4 descriptor chains for EP 0: 2 for + * Setup stage, per one for IN and OUT data/status transactions. + */ +static int dwc2_gadget_alloc_ctrl_desc_chains(struct dwc2_hsotg *hsotg) +{ + hsotg->setup_desc[0] = + dmam_alloc_coherent(hsotg->dev, + sizeof(struct dwc2_dma_desc), + &hsotg->setup_desc_dma[0], + GFP_KERNEL); + if (!hsotg->setup_desc[0]) + goto fail; + + hsotg->setup_desc[1] = + dmam_alloc_coherent(hsotg->dev, + sizeof(struct dwc2_dma_desc), + &hsotg->setup_desc_dma[1], + GFP_KERNEL); + if (!hsotg->setup_desc[1]) + goto fail; + + hsotg->ctrl_in_desc = + dmam_alloc_coherent(hsotg->dev, + sizeof(struct dwc2_dma_desc), + &hsotg->ctrl_in_desc_dma, + GFP_KERNEL); + if (!hsotg->ctrl_in_desc) + goto fail; + + hsotg->ctrl_out_desc = + dmam_alloc_coherent(hsotg->dev, + sizeof(struct dwc2_dma_desc), + &hsotg->ctrl_out_desc_dma, + GFP_KERNEL); + if (!hsotg->ctrl_out_desc) + goto fail; + + return 0; + +fail: + return -ENOMEM; +} + /** * dwc2_hsotg_write_fifo - write packet Data to the TxFIFO * @hsotg: The controller state. @@ -3857,6 +3905,12 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq) if (!hsotg->ep0_buff) return -ENOMEM; + if (using_desc_dma(hsotg)) { + ret = dwc2_gadget_alloc_ctrl_desc_chains(hsotg); + if (ret < 0) + return ret; + } + ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED, dev_name(hsotg->dev), hsotg); if (ret < 0) { |