UPSTREAM: usb: dwc3: gadget: initialize NUMP based on RxFIFO Size
authorFelipe Balbi <felipe.balbi@linux.intel.com>
Fri, 13 May 2016 11:09:59 +0000 (14:09 +0300)
committerHuang, Tao <huangtao@rock-chips.com>
Tue, 16 Aug 2016 12:48:19 +0000 (20:48 +0800)
Instead of using burst size to configure NUMP, we
should be using RxFIFO Size instead. DWC3 is smart
enough to know that it shouldn't burst in case burst
size is 0.

Change-Id: I03b0290e19ed204047ff35fdf7383f57bf3566df
Reported-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: Wu Liang feng <wulf@rock-chips.com>
(cherry picked from commit 4e99472bc10bda9906526d725ff6d5f27b4ddca1)

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

index 8098d31f116dcbc128ad726dcbed8b9bfe13a7cf..8de871f44adf52fe055377b1421cb334c995d36e 100644 (file)
 #define DWC3_GEVNTSIZ_INTMASK          (1 << 31)
 #define DWC3_GEVNTSIZ_SIZE(n)          ((n) & 0xffff)
 
+/* Global HWPARAMS0 Register */
+#define DWC3_GHWPARAMS0_USB3_MODE(n)   ((n) & 0x3)
+#define DWC3_GHWPARAMS0_MBUS_TYPE(n)   (((n) >> 3) & 0x7)
+#define DWC3_GHWPARAMS0_SBUS_TYPE(n)   (((n) >> 6) & 0x3)
+#define DWC3_GHWPARAMS0_MDWIDTH(n)     (((n) >> 8) & 0xff)
+#define DWC3_GHWPARAMS0_SDWIDTH(n)     (((n) >> 16) & 0xff)
+#define DWC3_GHWPARAMS0_AWIDTH(n)      (((n) >> 24) & 0xff)
+
 /* Global HWPARAMS1 Register */
 #define DWC3_GHWPARAMS1_EN_PWROPT(n)   (((n) & (3 << 24)) >> 24)
 #define DWC3_GHWPARAMS1_EN_PWROPT_NO   0
 /* Global HWPARAMS6 Register */
 #define DWC3_GHWPARAMS6_EN_FPGA                        (1 << 7)
 
+/* Global HWPARAMS7 Register */
+#define DWC3_GHWPARAMS7_RAM1_DEPTH(n)  ((n) & 0xffff)
+#define DWC3_GHWPARAMS7_RAM2_DEPTH(n)  (((n) >> 16) & 0xffff)
+
 /* Global Frame Length Adjustment Register */
 #define DWC3_GFLADJ_30MHZ_SDBND_SEL            (1 << 7)
 #define DWC3_GFLADJ_30MHZ_MASK                 0x3f
index a7c40a7aa018d466a567d317433dc35067a2ed7f..ca7a21f1c61c1f6284e0999fc77d95c40e88cef8 100644 (file)
@@ -485,17 +485,6 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
        /* Burst size is only needed in SuperSpeed mode */
        if (dwc->gadget.speed >= USB_SPEED_SUPER) {
                u32 burst = dep->endpoint.maxburst;
-               u32 nump;
-               u32 reg;
-
-               /* 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);
        }
 
@@ -1620,6 +1609,47 @@ static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
 static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
 static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
 
+/**
+ * dwc3_gadget_setup_nump - Calculate and initialize NUMP field of DCFG
+ * dwc: pointer to our context structure
+ *
+ * The following looks like complex but it's actually very simple. In order to
+ * calculate the number of packets we can burst at once on OUT transfers, we're
+ * gonna use RxFIFO size.
+ *
+ * To calculate RxFIFO size we need two numbers:
+ * MDWIDTH = size, in bits, of the internal memory bus
+ * RAM2_DEPTH = depth, in MDWIDTH, of internal RAM2 (where RxFIFO sits)
+ *
+ * Given these two numbers, the formula is simple:
+ *
+ * RxFIFO Size = (RAM2_DEPTH * MDWIDTH / 8) - 24 - 16;
+ *
+ * 24 bytes is for 3x SETUP packets
+ * 16 bytes is a clock domain crossing tolerance
+ *
+ * Given RxFIFO Size, NUMP = RxFIFOSize / 1024;
+ */
+static void dwc3_gadget_setup_nump(struct dwc3 *dwc)
+{
+       u32 ram2_depth;
+       u32 mdwidth;
+       u32 nump;
+       u32 reg;
+
+       ram2_depth = DWC3_GHWPARAMS7_RAM2_DEPTH(dwc->hwparams.hwparams7);
+       mdwidth = DWC3_GHWPARAMS0_MDWIDTH(dwc->hwparams.hwparams0);
+
+       nump = ((ram2_depth * mdwidth / 8) - 24 - 16) / 1024;
+       nump = min_t(u32, nump, 16);
+
+       /* update NumP */
+       reg = dwc3_readl(dwc->regs, DWC3_DCFG);
+       reg &= ~DWC3_DCFG_NUMP_MASK;
+       reg |= nump << DWC3_DCFG_NUMP_SHIFT;
+       dwc3_writel(dwc->regs, DWC3_DCFG, reg);
+}
+
 static int __dwc3_gadget_start(struct dwc3 *dwc)
 {
        struct dwc3_ep          *dep;
@@ -1674,6 +1704,8 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
        reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL;
        dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
 
+       dwc3_gadget_setup_nump(dwc);
+
        /* Start with SuperSpeed Default */
        dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);