summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJules Maselbas <jmaselbas@kalray.eu>2020-08-11 17:16:31 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2020-08-14 14:05:17 +0200
commit5f5d734a50f3f2cd18b3ed7a18a43757e2b49e9b (patch)
treeef55ab1aa51535408e2b080fab90357432ae3e56 /drivers
parent7fa069b51120b888005dbc81405cd7837c7dcbd0 (diff)
downloadbarebox-5f5d734a50f3f2cd18b3ed7a18a43757e2b49e9b.tar.gz
barebox-5f5d734a50f3f2cd18b3ed7a18a43757e2b49e9b.tar.xz
usb: dwc2: host: Dynamic fifo size support from Linux
Signed-off-by: Jules Maselbas <jmaselbas@kalray.eu> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/dwc2/host.c146
-rw-r--r--drivers/usb/dwc2/regs.h8
2 files changed, 124 insertions, 30 deletions
diff --git a/drivers/usb/dwc2/host.c b/drivers/usb/dwc2/host.c
index 3d135cd6a6..8726f3dad1 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 2170a0eaa3..e842c2c2e0 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__ */