]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
usb: dwc2: Add function to calculate correct FIFO sizes
authorDinh Nguyen <dinguyen@altera.com>
Wed, 7 May 2014 13:31:29 +0000 (08:31 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 27 May 2014 22:42:42 +0000 (15:42 -0700)
The dwc2 IP on the SOCFPGA cannot use the default HW configured
FIFO sizes. The total FIFO depth as read from GHWCFG3 reports 0x1f80 or 8064
32-bit words. But the GRXFSIZ, GNPTXFSIZ, and HPTXFSIZ register defaults
to 0x2000 or 8192 32-bit words. So the driver cannot just use the fifo sizes
as read from those registers.

For platforms that face the same issue, this commits sets the RX, periodic TX,
and non-periodic TX fifo size to those that are recommended v2.93a spec for
the DWC2 IP. Implements Method #2 from the Synopsys v2.93a spec for the DWC2.

Signed-off-by: Dinh Nguyen <dinguyen@altera.com>
Acked-by: Paul Zimmerman <paulz@synopsys.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc2/core.c

index 1d129884cc39ad71e8fddc34b6dc9715ae679f47..27d2c9b8a0344889089bd302eb469f98381be79d 100644 (file)
@@ -507,6 +507,72 @@ void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
        writel(intmsk, hsotg->regs + GINTMSK);
 }
 
+/*
+ * dwc2_calculate_dynamic_fifo() - Calculates the default fifo size
+ * For system that have a total fifo depth that is smaller than the default
+ * RX + TX fifo size.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg)
+{
+       struct dwc2_core_params *params = hsotg->core_params;
+       struct dwc2_hw_params *hw = &hsotg->hw_params;
+       u32 rxfsiz, nptxfsiz, ptxfsiz, total_fifo_size;
+
+       total_fifo_size = hw->total_fifo_size;
+       rxfsiz = params->host_rx_fifo_size;
+       nptxfsiz = params->host_nperio_tx_fifo_size;
+       ptxfsiz = params->host_perio_tx_fifo_size;
+
+       /*
+        * Will use Method 2 defined in the DWC2 spec: minimum FIFO depth
+        * allocation with support for high bandwidth endpoints. Synopsys
+        * defines MPS(Max Packet size) for a periodic EP=1024, and for
+        * non-periodic as 512.
+        */
+       if (total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)) {
+               /*
+                * For Buffer DMA mode/Scatter Gather DMA mode
+                * 2 * ((Largest Packet size / 4) + 1 + 1) + n
+                * with n = number of host channel.
+                * 2 * ((1024/4) + 2) = 516
+                */
+               rxfsiz = 516 + hw->host_channels;
+
+               /*
+                * min non-periodic tx fifo depth
+                * 2 * (largest non-periodic USB packet used / 4)
+                * 2 * (512/4) = 256
+                */
+               nptxfsiz = 256;
+
+               /*
+                * min periodic tx fifo depth
+                * (largest packet size*MC)/4
+                * (1024 * 3)/4 = 768
+                */
+               ptxfsiz = 768;
+
+               params->host_rx_fifo_size = rxfsiz;
+               params->host_nperio_tx_fifo_size = nptxfsiz;
+               params->host_perio_tx_fifo_size = ptxfsiz;
+       }
+
+       /*
+        * If the summation of RX, NPTX and PTX fifo sizes is still
+        * bigger than the total_fifo_size, then we have a problem.
+        *
+        * We won't be able to allocate as many endpoints. Right now,
+        * we're just printing an error message, but ideally this FIFO
+        * allocation algorithm would be improved in the future.
+        *
+        * FIXME improve this FIFO allocation algorithm.
+        */
+       if (unlikely(total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)))
+               dev_err(hsotg->dev, "invalid fifo sizes\n");
+}
+
 static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
 {
        struct dwc2_core_params *params = hsotg->core_params;
@@ -515,6 +581,8 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
        if (!params->enable_dynamic_fifo)
                return;
 
+       dwc2_calculate_dynamic_fifo(hsotg);
+
        /* Rx FIFO */
        grxfsiz = readl(hsotg->regs + GRXFSIZ);
        dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz);