aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc2
diff options
context:
space:
mode:
authorVardan Mikayelyan <mvardan@synopsys.com>2016-05-25 21:07:22 -0400
committerFelipe Balbi <felipe.balbi@linux.intel.com>2016-06-21 03:50:16 -0400
commit837e9f00bf9966d64abc1bce678271099a72423b (patch)
tree40eb40e4097841fded74c0c6e805350b77c3d430 /drivers/usb/dwc2
parentbd9971f0a1efe4b3ac6e2f8ec864c75f73ca7829 (diff)
usb: dwc2: gadget: Final fixes for BDMA ISOC
Done fixes and tested hsotg gadget's BDMA mode. Tested Control, Bulk, Isoc, Inter transfers. Added code for isoc transfers, removed unusable code, done minor fixes. Affected functions and IRQ handlers: - dwc2_hsotg_start_req(), - dwc2_hsotg_ep_enable(), - dwc2_hsotg_ep_queue(), - dwc2_hsotg_handle_outdone(), - GINTSTS_GOUTNAKEFF handler, Removed 'has_correct_parity' flag from 'dwc2_hsotg_ep' struct. Before this patch series, to set the data pid the DWC2 gadget driver was toggling the even/odd until it match, then were leaving it set. But now I have added mechanism to set pid and excluded all code where this flag was set. Tested-by: John Keeping <john@metanate.com> Signed-off-by: Vardan Mikayelyan <mvardan@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.h1
-rw-r--r--drivers/usb/dwc2/gadget.c97
-rw-r--r--drivers/usb/dwc2/hw.h1
3 files changed, 71 insertions, 28 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 0ba359945dbd..9fae0291cd69 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -215,7 +215,6 @@ struct dwc2_hsotg_ep {
215 unsigned int periodic:1; 215 unsigned int periodic:1;
216 unsigned int isochronous:1; 216 unsigned int isochronous:1;
217 unsigned int send_zlp:1; 217 unsigned int send_zlp:1;
218 unsigned int has_correct_parity:1;
219 unsigned int target_frame; 218 unsigned int target_frame;
220#define TARGET_FRAME_INITIAL 0xFFFFFFFF 219#define TARGET_FRAME_INITIAL 0xFFFFFFFF
221 bool frame_overrun; 220 bool frame_overrun;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 4a6074cc8e17..af46adfae41c 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -667,6 +667,16 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
667 __func__, &ureq->dma, dma_reg); 667 __func__, &ureq->dma, dma_reg);
668 } 668 }
669 669
670 if (hs_ep->isochronous && hs_ep->interval == 1) {
671 hs_ep->target_frame = dwc2_hsotg_read_frameno(hsotg);
672 dwc2_gadget_incr_frame_num(hs_ep);
673
674 if (hs_ep->target_frame & 0x1)
675 ctrl |= DXEPCTL_SETODDFR;
676 else
677 ctrl |= DXEPCTL_SETEVENFR;
678 }
679
670 ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */ 680 ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */
671 681
672 dev_dbg(hsotg->dev, "ep0 state:%d\n", hsotg->ep0_state); 682 dev_dbg(hsotg->dev, "ep0 state:%d\n", hsotg->ep0_state);
@@ -863,9 +873,18 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
863 first = list_empty(&hs_ep->queue); 873 first = list_empty(&hs_ep->queue);
864 list_add_tail(&hs_req->queue, &hs_ep->queue); 874 list_add_tail(&hs_req->queue, &hs_ep->queue);
865 875
866 if (first) 876 if (first) {
867 dwc2_hsotg_start_req(hs, hs_ep, hs_req, false); 877 if (!hs_ep->isochronous) {
878 dwc2_hsotg_start_req(hs, hs_ep, hs_req, false);
879 return 0;
880 }
868 881
882 while (dwc2_gadget_target_frame_elapsed(hs_ep))
883 dwc2_gadget_incr_frame_num(hs_ep);
884
885 if (hs_ep->target_frame != TARGET_FRAME_INITIAL)
886 dwc2_hsotg_start_req(hs, hs_ep, hs_req, false);
887 }
869 return 0; 888 return 0;
870} 889}
871 890
@@ -1673,9 +1692,10 @@ static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
1673 * adjust the ISOC parity here. 1692 * adjust the ISOC parity here.
1674 */ 1693 */
1675 if (!using_dma(hsotg)) { 1694 if (!using_dma(hsotg)) {
1676 hs_ep->has_correct_parity = 1;
1677 if (hs_ep->isochronous && hs_ep->interval == 1) 1695 if (hs_ep->isochronous && hs_ep->interval == 1)
1678 dwc2_hsotg_change_ep_iso_parity(hsotg, DOEPCTL(epnum)); 1696 dwc2_hsotg_change_ep_iso_parity(hsotg, DOEPCTL(epnum));
1697 else if (hs_ep->isochronous && hs_ep->interval > 1)
1698 dwc2_gadget_incr_frame_num(hs_ep);
1679 } 1699 }
1680 1700
1681 dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, result); 1701 dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
@@ -2216,11 +2236,10 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
2216 if (idx == 0 && (ints & (DXEPINT_SETUP | DXEPINT_SETUP_RCVD))) 2236 if (idx == 0 && (ints & (DXEPINT_SETUP | DXEPINT_SETUP_RCVD)))
2217 ints &= ~DXEPINT_XFERCOMPL; 2237 ints &= ~DXEPINT_XFERCOMPL;
2218 2238
2219 if (ints & DXEPINT_XFERCOMPL) { 2239 if (ints & DXEPINT_STSPHSERCVD)
2220 hs_ep->has_correct_parity = 1; 2240 dev_dbg(hsotg->dev, "%s: StsPhseRcvd asserted\n", __func__);
2221 if (hs_ep->isochronous && hs_ep->interval == 1)
2222 dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg);
2223 2241
2242 if (ints & DXEPINT_XFERCOMPL) {
2224 dev_dbg(hsotg->dev, 2243 dev_dbg(hsotg->dev,
2225 "%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n", 2244 "%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n",
2226 __func__, dwc2_readl(hsotg->regs + epctl_reg), 2245 __func__, dwc2_readl(hsotg->regs + epctl_reg),
@@ -2231,7 +2250,12 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
2231 * at completing IN requests here 2250 * at completing IN requests here
2232 */ 2251 */
2233 if (dir_in) { 2252 if (dir_in) {
2253 if (hs_ep->isochronous && hs_ep->interval > 1)
2254 dwc2_gadget_incr_frame_num(hs_ep);
2255
2234 dwc2_hsotg_complete_in(hsotg, hs_ep); 2256 dwc2_hsotg_complete_in(hsotg, hs_ep);
2257 if (ints & DXEPINT_NAKINTRPT)
2258 ints &= ~DXEPINT_NAKINTRPT;
2235 2259
2236 if (idx == 0 && !hs_ep->req) 2260 if (idx == 0 && !hs_ep->req)
2237 dwc2_hsotg_enqueue_setup(hsotg); 2261 dwc2_hsotg_enqueue_setup(hsotg);
@@ -2240,6 +2264,8 @@ static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
2240 * We're using DMA, we need to fire an OutDone here 2264 * We're using DMA, we need to fire an OutDone here
2241 * as we ignore the RXFIFO. 2265 * as we ignore the RXFIFO.
2242 */ 2266 */
2267 if (hs_ep->isochronous && hs_ep->interval > 1)
2268 dwc2_gadget_incr_frame_num(hs_ep);
2243 2269
2244 dwc2_hsotg_handle_outdone(hsotg, idx); 2270 dwc2_hsotg_handle_outdone(hsotg, idx);
2245 } 2271 }
@@ -2556,18 +2582,16 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
2556 dwc2_writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ? 2582 dwc2_writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ?
2557 DIEPMSK_TXFIFOEMPTY | DIEPMSK_INTKNTXFEMPMSK : 0) | 2583 DIEPMSK_TXFIFOEMPTY | DIEPMSK_INTKNTXFEMPMSK : 0) |
2558 DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK | 2584 DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK |
2559 DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK | 2585 DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK,
2560 DIEPMSK_INTKNEPMISMSK,
2561 hsotg->regs + DIEPMSK); 2586 hsotg->regs + DIEPMSK);
2562 2587
2563 /* 2588 /*
2564 * don't need XferCompl, we get that from RXFIFO in slave mode. In 2589 * don't need XferCompl, we get that from RXFIFO in slave mode. In
2565 * DMA mode we may need this. 2590 * DMA mode we may need this.
2566 */ 2591 */
2567 dwc2_writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK | 2592 dwc2_writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK) : 0) |
2568 DIEPMSK_TIMEOUTMSK) : 0) |
2569 DOEPMSK_EPDISBLDMSK | DOEPMSK_AHBERRMSK | 2593 DOEPMSK_EPDISBLDMSK | DOEPMSK_AHBERRMSK |
2570 DOEPMSK_SETUPMSK, 2594 DOEPMSK_SETUPMSK | DOEPMSK_STSPHSERCVDMSK,
2571 hsotg->regs + DOEPMSK); 2595 hsotg->regs + DOEPMSK);
2572 2596
2573 dwc2_writel(0, hsotg->regs + DAINTMSK); 2597 dwc2_writel(0, hsotg->regs + DAINTMSK);
@@ -2858,11 +2882,29 @@ irq_retry:
2858 */ 2882 */
2859 2883
2860 if (gintsts & GINTSTS_GOUTNAKEFF) { 2884 if (gintsts & GINTSTS_GOUTNAKEFF) {
2861 dev_info(hsotg->dev, "GOUTNakEff triggered\n"); 2885 u8 idx;
2862 2886 u32 epctrl;
2863 __orr32(hsotg->regs + DCTL, DCTL_CGOUTNAK); 2887 u32 gintmsk;
2888 struct dwc2_hsotg_ep *hs_ep;
2889
2890 /* Mask this interrupt */
2891 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
2892 gintmsk &= ~GINTSTS_GOUTNAKEFF;
2893 dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
2894
2895 dev_dbg(hsotg->dev, "GOUTNakEff triggered\n");
2896 for (idx = 1; idx <= hsotg->num_of_eps; idx++) {
2897 hs_ep = hsotg->eps_out[idx];
2898 epctrl = dwc2_readl(hsotg->regs + DOEPCTL(idx));
2899
2900 if ((epctrl & DXEPCTL_EPENA) && hs_ep->isochronous) {
2901 epctrl |= DXEPCTL_SNAK;
2902 epctrl |= DXEPCTL_EPDIS;
2903 dwc2_writel(epctrl, hsotg->regs + DOEPCTL(idx));
2904 }
2905 }
2864 2906
2865 dwc2_hsotg_dump(hsotg); 2907 /* This interrupt bit is cleared in DXEPINT_EPDISBLD handler */
2866 } 2908 }
2867 2909
2868 if (gintsts & GINTSTS_GINNAKEFF) { 2910 if (gintsts & GINTSTS_GINNAKEFF) {
@@ -2909,6 +2951,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
2909 u32 epctrl_reg; 2951 u32 epctrl_reg;
2910 u32 epctrl; 2952 u32 epctrl;
2911 u32 mps; 2953 u32 mps;
2954 u32 mask;
2912 unsigned int dir_in; 2955 unsigned int dir_in;
2913 unsigned int i, val, size; 2956 unsigned int i, val, size;
2914 int ret = 0; 2957 int ret = 0;
@@ -2951,15 +2994,6 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
2951 */ 2994 */
2952 epctrl |= DXEPCTL_USBACTEP; 2995 epctrl |= DXEPCTL_USBACTEP;
2953 2996
2954 /*
2955 * set the NAK status on the endpoint, otherwise we might try and
2956 * do something with data that we've yet got a request to process
2957 * since the RXFIFO will take data for an endpoint even if the
2958 * size register hasn't been set.
2959 */
2960
2961 epctrl |= DXEPCTL_SNAK;
2962
2963 /* update the endpoint state */ 2997 /* update the endpoint state */
2964 dwc2_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in); 2998 dwc2_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in);
2965 2999
@@ -2975,8 +3009,17 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
2975 epctrl |= DXEPCTL_SETEVENFR; 3009 epctrl |= DXEPCTL_SETEVENFR;
2976 hs_ep->isochronous = 1; 3010 hs_ep->isochronous = 1;
2977 hs_ep->interval = 1 << (desc->bInterval - 1); 3011 hs_ep->interval = 1 << (desc->bInterval - 1);
2978 if (dir_in) 3012 hs_ep->target_frame = TARGET_FRAME_INITIAL;
3013 if (dir_in) {
2979 hs_ep->periodic = 1; 3014 hs_ep->periodic = 1;
3015 mask = dwc2_readl(hsotg->regs + DIEPMSK);
3016 mask |= DIEPMSK_NAKMSK;
3017 dwc2_writel(mask, hsotg->regs + DIEPMSK);
3018 } else {
3019 mask = dwc2_readl(hsotg->regs + DOEPMSK);
3020 mask |= DOEPMSK_OUTTKNEPDISMSK;
3021 dwc2_writel(mask, hsotg->regs + DOEPMSK);
3022 }
2980 break; 3023 break;
2981 3024
2982 case USB_ENDPOINT_XFER_BULK: 3025 case USB_ENDPOINT_XFER_BULK:
@@ -3043,7 +3086,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
3043 } 3086 }
3044 3087
3045 /* for non control endpoints, set PID to D0 */ 3088 /* for non control endpoints, set PID to D0 */
3046 if (index) 3089 if (index && !hs_ep->isochronous)
3047 epctrl |= DXEPCTL_SETD0PID; 3090 epctrl |= DXEPCTL_SETD0PID;
3048 3091
3049 dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n", 3092 dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index 1126141cf47c..efc3bcde2822 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -560,6 +560,7 @@
560#define DXEPINT_INEPNAKEFF (1 << 6) 560#define DXEPINT_INEPNAKEFF (1 << 6)
561#define DXEPINT_BACK2BACKSETUP (1 << 6) 561#define DXEPINT_BACK2BACKSETUP (1 << 6)
562#define DXEPINT_INTKNEPMIS (1 << 5) 562#define DXEPINT_INTKNEPMIS (1 << 5)
563#define DXEPINT_STSPHSERCVD (1 << 5)
563#define DXEPINT_INTKNTXFEMP (1 << 4) 564#define DXEPINT_INTKNTXFEMP (1 << 4)
564#define DXEPINT_OUTTKNEPDIS (1 << 4) 565#define DXEPINT_OUTTKNEPDIS (1 << 4)
565#define DXEPINT_TIMEOUT (1 << 3) 566#define DXEPINT_TIMEOUT (1 << 3)