UPSTREAM: usb: dwc3: gadget: update DCFG.NumP to max burst size
authorFelipe Balbi <felipe.balbi@linux.intel.com>
Tue, 26 Apr 2016 07:49:07 +0000 (10:49 +0300)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 16 Aug 2016 12:48:19 +0000 (20:48 +0800)
NumP field of DCFG register is used on NumP field of
ACK TP header and it tells the host how many packets
an endpoint can receive before waiting for
synchronization.

Documentation says it should be set to anything
<=bMaxBurst. Interestingly, however, this setting is
not per-endpoint how it should be (different
endpoints could have different burst sizes), but
things seem to work okay right now.

Change-Id: I2fd8e68f88b15e64fc06770ffdc6376fcb4cff62
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
(cherry picked from commit 676e3497448177bdb1934cbc4402f921730a5864)

Conflicts:
drivers/usb/dwc3/gadget.c

drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c

index 4ea20a254dd8ac09f2e89d529e60832dd5db57d8..65df6d2dc5801c1cfa9724bfe0476afc1a3b03de 100644 (file)
 #define DWC3_DCFG_LOWSPEED     (2 << 0)
 #define DWC3_DCFG_FULLSPEED1   (3 << 0)
 
+#define DWC3_DCFG_NUMP_SHIFT   17
+#define DWC3_DCFG_NUMP(n)      (((n) & 0x1f) >> DWC3_DCFG_NUMP_SHIFT)
+#define DWC3_DCFG_NUMP_MASK    (0x1f << DWC3_DCFG_NUMP_SHIFT)
 #define DWC3_DCFG_LPM_CAP      (1 << 22)
 
 /* Device Control Register */
index c285b34af0c5f472a244e9f7d98b0305775af61f..0d3873f7b657a7cc8eea54f777c79c91a0c554e9 100644 (file)
@@ -463,10 +463,20 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
                | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc));
 
        /* Burst size is only needed in SuperSpeed mode */
-       if (dwc->gadget.speed == USB_SPEED_SUPER) {
-               u32 burst = dep->endpoint.maxburst - 1;
+       if (dwc->gadget.speed >= USB_SPEED_SUPER) {
+               u32 burst = dep->endpoint.maxburst;
+               u32 nump;
+               u32 reg;
 
-               params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst);
+               /* update NumP */
+               reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+               nump = DWC3_DCFG_NUMP(reg);
+               nump = max(nump, burst);
+               reg &= ~DWC3_DCFG_NUMP_MASK;
+               reg |= nump << DWC3_DCFG_NUMP_SHIFT;
+               dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+
+               params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst - 1);
        }
 
        if (ignore)