From: Sevak Arakelyan <sev...@synopsys.com>

Remove legacy DWC2_G_P_LEGACY_TX_FIFO_SIZE array for TX FIFOs.
Update dwc2_set_param_tx_fifo_sizes function to calculate
and assign default average FIFO depth to each member of
g_tx_fifo_size array. Total FIFO size, EP Info block's size,
FIFO operation mode and device operation mode are taken into
consideration during the calculation.

Cc: Stefan Wahren <stefan.wah...@i2se.com>
Signed-off-by: Sevak Arakelyan <sev...@synopsys.com>
Signed-off-by: John Youn <johny...@synopsys.com>
---
 drivers/usb/dwc2/core.h   | 16 ++++----
 drivers/usb/dwc2/gadget.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/dwc2/params.c | 12 ++++--
 3 files changed, 110 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 5370e6429f28..f10eca91d2be 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -274,13 +274,6 @@ enum dwc2_lx_state {
        DWC2_L3,        /* Off state */
 };
 
-/*
- * Gadget periodic tx fifo sizes as used by legacy driver
- * EP0 is not included
- */
-#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \
-                                          768, 0, 0, 0, 0, 0, 0, 0}
-
 /* Gadget ep0 states */
 enum dwc2_ep0_state {
        DWC2_EP0_SETUP,
@@ -1180,6 +1173,9 @@ int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, 
int testmode);
 #define dwc2_is_device_connected(hsotg) (hsotg->connected)
 int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg);
 int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg);
+int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg);
+int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg);
+int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg);
 #else
 static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
 { return 0; }
@@ -1201,6 +1197,12 @@ static inline int dwc2_backup_device_registers(struct 
dwc2_hsotg *hsotg)
 { return 0; }
 static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
 { return 0; }
+static inline int dwc2_hsotg_tx_fifo_count(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline int dwc2_hsotg_tx_fifo_average_depth(struct dwc2_hsotg *hsotg)
+{ return 0; }
 #endif
 
 #if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 30ff51eab35c..eb579b6f68f0 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -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.
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 8e5039e2d3fc..016fff0cb887 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -207,12 +207,16 @@ static void dwc2_set_param_phy_utmi_width(struct 
dwc2_hsotg *hsotg)
 static void dwc2_set_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg)
 {
        struct dwc2_core_params *p = &hsotg->params;
-       u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE;
+       int depth_average;
+       int fifo_count;
+       int i;
+
+       fifo_count = dwc2_hsotg_tx_fifo_count(hsotg);
 
        memset(p->g_tx_fifo_size, 0, sizeof(p->g_tx_fifo_size));
-       memcpy(&p->g_tx_fifo_size[1],
-              p_tx_fifo,
-              sizeof(p_tx_fifo));
+       depth_average = dwc2_hsotg_tx_fifo_average_depth(hsotg);
+       for (i = 1; i <= fifo_count; i++)
+               p->g_tx_fifo_size[i] = depth_average;
 }
 
 /**
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to