]> git.karo-electronics.de Git - linux-beck.git/commitdiff
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)
committerFelipe Balbi <felipe.balbi@linux.intel.com>
Mon, 20 Jun 2016 09:30:07 +0000 (12:30 +0300)
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.

Reported-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
drivers/usb/dwc3/core.h
drivers/usb/dwc3/gadget.c

index c881c8232e2165376dbf34ccac617c1645fb2774..f4bec0668877f37654758a9025d356ddb688a7cd 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 bff2c35f37a86bcc6aca5d2b690e2aec04f528b0..eb28326a633db055f9cef37213e551858af2d281 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);
        }
 
@@ -1610,6 +1599,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;
@@ -1670,6 +1700,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);