|
@@ -191,6 +191,99 @@ static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
|
|
|
local_irq_restore(flags);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * dwc2_hsotg_tx_fifo_count - return count of TX FIFOs in device mode
|
|
|
+ */
|
|
|
+int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
|
|
|
+{
|
|
|
+ if (hsotg->hw_params.en_multiple_tx_fifo)
|
|
|
+ /* In dedicated FIFO mode we need count of IN EPs */
|
|
|
+ return (dwc2_readl(hsotg->regs + GHWCFG4) &
|
|
|
+ GHWCFG4_NUM_IN_EPS_MASK) >> GHWCFG4_NUM_IN_EPS_SHIFT;
|
|
|
+ else
|
|
|
+ /* In shared FIFO mode we need count of Periodic IN EPs */
|
|
|
+ return hsotg->hw_params.num_dev_perio_in_ep;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dwc2_hsotg_ep_info_size - return Endpoint Info Control block size in DWORDs
|
|
|
+ */
|
|
|
+static int dwc2_hsotg_ep_info_size(struct dwc2_hsotg *hsotg)
|
|
|
+{
|
|
|
+ int val = 0;
|
|
|
+ int i;
|
|
|
+ u32 ep_dirs;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Don't need additional space for ep info control registers in
|
|
|
+ * slave mode.
|
|
|
+ */
|
|
|
+ if (!using_dma(hsotg)) {
|
|
|
+ dev_dbg(hsotg->dev, "Buffer DMA ep info size 0\n");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Buffer DMA mode - 1 location per endpoit
|
|
|
+ * Descriptor DMA mode - 4 locations per endpoint
|
|
|
+ */
|
|
|
+ ep_dirs = hsotg->hw_params.dev_ep_dirs;
|
|
|
+
|
|
|
+ for (i = 0; i <= hsotg->hw_params.num_dev_ep; i++) {
|
|
|
+ val += ep_dirs & 3 ? 1 : 2;
|
|
|
+ ep_dirs >>= 2;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (using_desc_dma(hsotg))
|
|
|
+ val = val * 4;
|
|
|
+
|
|
|
+ return val;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dwc2_hsotg_tx_fifo_total_depth - return total FIFO depth available for
|
|
|
+ * device mode TX FIFOs
|
|
|
+ */
|
|
|
+int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
|
|
|
+{
|
|
|
+ int ep_info_size;
|
|
|
+ int addr;
|
|
|
+ int tx_addr_max;
|
|
|
+ u32 np_tx_fifo_size;
|
|
|
+
|
|
|
+ np_tx_fifo_size = min_t(u32, hsotg->hw_params.dev_nperio_tx_fifo_size,
|
|
|
+ hsotg->params.g_np_tx_fifo_size);
|
|
|
+
|
|
|
+ /* Get Endpoint Info Control block size in DWORDs. */
|
|
|
+ ep_info_size = dwc2_hsotg_ep_info_size(hsotg);
|
|
|
+ tx_addr_max = hsotg->hw_params.total_fifo_size - ep_info_size;
|
|
|
+
|
|
|
+ addr = hsotg->params.g_rx_fifo_size + np_tx_fifo_size;
|
|
|
+ if (tx_addr_max <= addr)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return tx_addr_max - addr;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * dwc2_hsotg_tx_fifo_average_depth - returns average depth of device mode
|
|
|
+ * TX FIFOs
|
|
|
+ */
|
|
|
+int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
|
|
|
+{
|
|
|
+ int tx_fifo_count;
|
|
|
+ int tx_fifo_depth;
|
|
|
+
|
|
|
+ tx_fifo_depth = dwc2_hsotg_tx_fifo_total_depth(hsotg);
|
|
|
+
|
|
|
+ tx_fifo_count = dwc2_hsotg_tx_fifo_count(hsotg);
|
|
|
+
|
|
|
+ if (!tx_fifo_count)
|
|
|
+ return tx_fifo_depth;
|
|
|
+ else
|
|
|
+ return tx_fifo_depth / tx_fifo_count;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* dwc2_hsotg_init_fifo - initialise non-periodic FIFOs
|
|
|
* @hsotg: The device instance.
|