Signed-off-by: Jules Maselbas <[email protected]>
---
 drivers/usb/dwc2/host.c | 146 ++++++++++++++++++++++++++++++++++------
 drivers/usb/dwc2/regs.h |   8 ---
 2 files changed, 124 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/dwc2/host.c b/drivers/usb/dwc2/host.c
index 40fc84599..28759a801 100644
--- a/drivers/usb/dwc2/host.c
+++ b/drivers/usb/dwc2/host.c
@@ -453,6 +453,129 @@ static int dwc2_submit_int_msg(struct usb_device *udev, 
unsigned long pipe,
        }
 }
 
+/**
+ * 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.
+ *
+ * @dwc2: Programming view of DWC_otg controller
+ */
+static void dwc2_calculate_dynamic_fifo(struct dwc2 *dwc2)
+{
+       struct dwc2_core_params *params = &dwc2->params;
+       struct dwc2_hw_params *hw = &dwc2->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)))
+               dwc2_err(dwc2, "invalid fifo sizes\n");
+}
+
+static void dwc2_config_fifos(struct dwc2 *dwc2)
+{
+       struct dwc2_core_params *params = &dwc2->params;
+       u32 nptxfsiz, hptxfsiz, dfifocfg, grxfsiz;
+
+       if (!params->enable_dynamic_fifo)
+               return;
+
+       dwc2_calculate_dynamic_fifo(dwc2);
+
+       /* Rx FIFO */
+       grxfsiz = dwc2_readl(dwc2, GRXFSIZ);
+       dwc2_dbg(dwc2, "initial grxfsiz=%08x\n", grxfsiz);
+       grxfsiz &= ~GRXFSIZ_DEPTH_MASK;
+       grxfsiz |= params->host_rx_fifo_size <<
+                  GRXFSIZ_DEPTH_SHIFT & GRXFSIZ_DEPTH_MASK;
+       dwc2_writel(dwc2, grxfsiz, GRXFSIZ);
+       dwc2_dbg(dwc2, "new grxfsiz=%08x\n", dwc2_readl(dwc2, GRXFSIZ));
+
+       /* Non-periodic Tx FIFO */
+       dwc2_dbg(dwc2, "initial gnptxfsiz=%08x\n", dwc2_readl(dwc2, GNPTXFSIZ));
+       nptxfsiz = params->host_nperio_tx_fifo_size <<
+                  FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
+       nptxfsiz |= params->host_rx_fifo_size <<
+                   FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
+       dwc2_writel(dwc2, nptxfsiz, GNPTXFSIZ);
+       dwc2_dbg(dwc2, "new gnptxfsiz=%08x\n", dwc2_readl(dwc2, GNPTXFSIZ));
+
+       /* Periodic Tx FIFO */
+       dwc2_dbg(dwc2, "initial hptxfsiz=%08x\n", dwc2_readl(dwc2, HPTXFSIZ));
+       hptxfsiz = params->host_perio_tx_fifo_size <<
+                  FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
+       hptxfsiz |= (params->host_rx_fifo_size +
+                    params->host_nperio_tx_fifo_size) <<
+                   FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
+       dwc2_writel(dwc2, hptxfsiz, HPTXFSIZ);
+       dwc2_dbg(dwc2, "new hptxfsiz=%08x\n", dwc2_readl(dwc2, HPTXFSIZ));
+
+       if (dwc2->params.en_multiple_tx_fifo &&
+           dwc2->hw_params.snpsid >= DWC2_CORE_REV_2_91a) {
+               /*
+                * This feature was implemented in 2.91a version
+                * Global DFIFOCFG calculation for Host mode -
+                * include RxFIFO, NPTXFIFO and HPTXFIFO
+                */
+               dfifocfg = dwc2_readl(dwc2, GDFIFOCFG);
+               dfifocfg &= ~GDFIFOCFG_EPINFOBASE_MASK;
+               dfifocfg |= (params->host_rx_fifo_size +
+                            params->host_nperio_tx_fifo_size +
+                            params->host_perio_tx_fifo_size) <<
+                           GDFIFOCFG_EPINFOBASE_SHIFT &
+                           GDFIFOCFG_EPINFOBASE_MASK;
+               dwc2_writel(dwc2, dfifocfg, GDFIFOCFG);
+               dwc2_dbg(dwc2, "new dfifocfg=%08x\n", dfifocfg);
+       }
+}
+
 /*
  * This function initializes the DWC2 controller registers for
  * host mode.
@@ -468,8 +591,6 @@ static int dwc2_submit_int_msg(struct usb_device *udev, 
unsigned long pipe,
 static void dwc2_core_host_init(struct device_d *dev,
                                   struct dwc2 *dwc2)
 {
-       uint32_t nptxfifosize = 0;
-       uint32_t ptxfifosize = 0;
        uint32_t hcchar, hcfg, hprt0, hotgctl, usbcfg;
        int i, ret, num_channels;
 
@@ -517,26 +638,7 @@ static void dwc2_core_host_init(struct device_d *dev,
                }
        }
 
-       /* Configure data FIFO sizes */
-       if (dwc2_readl(dwc2, GHWCFG2) & GHWCFG2_DYNAMIC_FIFO) {
-               /* Rx FIFO */
-               dwc2_writel(dwc2, CONFIG_DWC2_HOST_RX_FIFO_SIZE, GRXFSIZ);
-
-               /* Non-periodic Tx FIFO */
-               nptxfifosize |= CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE <<
-                               FIFOSIZE_DEPTH_SHIFT;
-               nptxfifosize |= CONFIG_DWC2_HOST_RX_FIFO_SIZE <<
-                               FIFOSIZE_STARTADDR_SHIFT;
-               dwc2_writel(dwc2, nptxfifosize, GNPTXFSIZ);
-
-               /* Periodic Tx FIFO */
-               ptxfifosize |= CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE <<
-                               FIFOSIZE_DEPTH_SHIFT;
-               ptxfifosize |= (CONFIG_DWC2_HOST_RX_FIFO_SIZE +
-                               CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE) <<
-                               FIFOSIZE_STARTADDR_SHIFT;
-               dwc2_writel(dwc2, ptxfifosize, HPTXFSIZ);
-       }
+       dwc2_config_fifos(dwc2);
 
        /* Clear Host Set HNP Enable in the OTG Control Register */
        hotgctl = dwc2_readl(dwc2, GOTGCTL);
diff --git a/drivers/usb/dwc2/regs.h b/drivers/usb/dwc2/regs.h
index 2170a0eaa..e842c2c2e 100644
--- a/drivers/usb/dwc2/regs.h
+++ b/drivers/usb/dwc2/regs.h
@@ -837,12 +837,4 @@ struct dwc2_dma_desc {
 #define DWC2_FS_IOT_ID         0x55310000
 #define DWC2_HS_IOT_ID         0x55320000
 
-/* ==== u-boot ==== */
-
-/* Default driver configuration */
-#define CONFIG_DWC2_MAX_CHANNELS               DWC2_MAX_EPS_CHANNELS   /* Max 
# of EPs */
-#define CONFIG_DWC2_HOST_RX_FIFO_SIZE          (516 + CONFIG_DWC2_MAX_CHANNELS)
-#define CONFIG_DWC2_HOST_NPERIO_TX_FIFO_SIZE   0x100   /* nPeriodic TX FIFO */
-#define CONFIG_DWC2_HOST_PERIO_TX_FIFO_SIZE    0x200   /* Periodic TX FIFO */
-
 #endif /* __DWC2_H__ */
-- 
2.17.1


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

Reply via email to