]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: dwc3: core: configure TX/RX threshold for DWC3_IP
authorStanley Chang <stanley_chang@realtek.com>
Tue, 12 Sep 2023 04:19:02 +0000 (12:19 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 28 Nov 2023 17:07:01 +0000 (17:07 +0000)
[ Upstream commit e72fc8d6a12af7ae8dd1b52cf68ed68569d29f80 ]

In Synopsys's dwc3 data book:
To avoid underrun and overrun during the burst, in a high-latency bus
system (like USB), threshold and burst size control is provided through
GTXTHRCFG and GRXTHRCFG registers.

In Realtek DHC SoC, DWC3 USB 3.0 uses AHB system bus. When dwc3 is
connected with USB 2.5G Ethernet, there will be overrun problem.
Therefore, setting TX/RX thresholds can avoid this issue.

Signed-off-by: Stanley Chang <stanley_chang@realtek.com>
Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/20230912041904.30721-1-stanley_chang@realtek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h

index 57e2f4cc744f72aea877c8b14e517f2020c611ef..a811db88eedae39ecec7b91bf5af1916fa6d6260 100644 (file)
@@ -1111,6 +1111,111 @@ static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc)
        }
 }
 
+static void dwc3_config_threshold(struct dwc3 *dwc)
+{
+       u32 reg;
+       u8 rx_thr_num;
+       u8 rx_maxburst;
+       u8 tx_thr_num;
+       u8 tx_maxburst;
+
+       /*
+        * Must config both number of packets and max burst settings to enable
+        * RX and/or TX threshold.
+        */
+       if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) {
+               rx_thr_num = dwc->rx_thr_num_pkt_prd;
+               rx_maxburst = dwc->rx_max_burst_prd;
+               tx_thr_num = dwc->tx_thr_num_pkt_prd;
+               tx_maxburst = dwc->tx_max_burst_prd;
+
+               if (rx_thr_num && rx_maxburst) {
+                       reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
+                       reg |= DWC31_RXTHRNUMPKTSEL_PRD;
+
+                       reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
+                       reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num);
+
+                       reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
+                       reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
+
+                       dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
+               }
+
+               if (tx_thr_num && tx_maxburst) {
+                       reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
+                       reg |= DWC31_TXTHRNUMPKTSEL_PRD;
+
+                       reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
+                       reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num);
+
+                       reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
+                       reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
+
+                       dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
+               }
+       }
+
+       rx_thr_num = dwc->rx_thr_num_pkt;
+       rx_maxburst = dwc->rx_max_burst;
+       tx_thr_num = dwc->tx_thr_num_pkt;
+       tx_maxburst = dwc->tx_max_burst;
+
+       if (DWC3_IP_IS(DWC3)) {
+               if (rx_thr_num && rx_maxburst) {
+                       reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
+                       reg |= DWC3_GRXTHRCFG_PKTCNTSEL;
+
+                       reg &= ~DWC3_GRXTHRCFG_RXPKTCNT(~0);
+                       reg |= DWC3_GRXTHRCFG_RXPKTCNT(rx_thr_num);
+
+                       reg &= ~DWC3_GRXTHRCFG_MAXRXBURSTSIZE(~0);
+                       reg |= DWC3_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
+
+                       dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
+               }
+
+               if (tx_thr_num && tx_maxburst) {
+                       reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
+                       reg |= DWC3_GTXTHRCFG_PKTCNTSEL;
+
+                       reg &= ~DWC3_GTXTHRCFG_TXPKTCNT(~0);
+                       reg |= DWC3_GTXTHRCFG_TXPKTCNT(tx_thr_num);
+
+                       reg &= ~DWC3_GTXTHRCFG_MAXTXBURSTSIZE(~0);
+                       reg |= DWC3_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
+
+                       dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
+               }
+       } else {
+               if (rx_thr_num && rx_maxburst) {
+                       reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
+                       reg |= DWC31_GRXTHRCFG_PKTCNTSEL;
+
+                       reg &= ~DWC31_GRXTHRCFG_RXPKTCNT(~0);
+                       reg |= DWC31_GRXTHRCFG_RXPKTCNT(rx_thr_num);
+
+                       reg &= ~DWC31_GRXTHRCFG_MAXRXBURSTSIZE(~0);
+                       reg |= DWC31_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
+
+                       dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
+               }
+
+               if (tx_thr_num && tx_maxburst) {
+                       reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
+                       reg |= DWC31_GTXTHRCFG_PKTCNTSEL;
+
+                       reg &= ~DWC31_GTXTHRCFG_TXPKTCNT(~0);
+                       reg |= DWC31_GTXTHRCFG_TXPKTCNT(tx_thr_num);
+
+                       reg &= ~DWC31_GTXTHRCFG_MAXTXBURSTSIZE(~0);
+                       reg |= DWC31_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
+
+                       dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
+               }
+       }
+}
+
 /**
  * dwc3_core_init - Low-level initialization of DWC3 Core
  * @dwc: Pointer to our controller context structure
@@ -1278,42 +1383,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
                dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
        }
 
-       /*
-        * Must config both number of packets and max burst settings to enable
-        * RX and/or TX threshold.
-        */
-       if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) {
-               u8 rx_thr_num = dwc->rx_thr_num_pkt_prd;
-               u8 rx_maxburst = dwc->rx_max_burst_prd;
-               u8 tx_thr_num = dwc->tx_thr_num_pkt_prd;
-               u8 tx_maxburst = dwc->tx_max_burst_prd;
-
-               if (rx_thr_num && rx_maxburst) {
-                       reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
-                       reg |= DWC31_RXTHRNUMPKTSEL_PRD;
-
-                       reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
-                       reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num);
-
-                       reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
-                       reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
-
-                       dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
-               }
-
-               if (tx_thr_num && tx_maxburst) {
-                       reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
-                       reg |= DWC31_TXTHRNUMPKTSEL_PRD;
-
-                       reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
-                       reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num);
-
-                       reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
-                       reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
-
-                       dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
-               }
-       }
+       dwc3_config_threshold(dwc);
 
        return 0;
 
@@ -1462,6 +1532,10 @@ static void dwc3_get_properties(struct dwc3 *dwc)
        u8                      lpm_nyet_threshold;
        u8                      tx_de_emphasis;
        u8                      hird_threshold;
+       u8                      rx_thr_num_pkt = 0;
+       u8                      rx_max_burst = 0;
+       u8                      tx_thr_num_pkt = 0;
+       u8                      tx_max_burst = 0;
        u8                      rx_thr_num_pkt_prd = 0;
        u8                      rx_max_burst_prd = 0;
        u8                      tx_thr_num_pkt_prd = 0;
@@ -1524,6 +1598,14 @@ static void dwc3_get_properties(struct dwc3 *dwc)
                                "snps,usb2-lpm-disable");
        dwc->usb2_gadget_lpm_disable = device_property_read_bool(dev,
                                "snps,usb2-gadget-lpm-disable");
+       device_property_read_u8(dev, "snps,rx-thr-num-pkt",
+                               &rx_thr_num_pkt);
+       device_property_read_u8(dev, "snps,rx-max-burst",
+                               &rx_max_burst);
+       device_property_read_u8(dev, "snps,tx-thr-num-pkt",
+                               &tx_thr_num_pkt);
+       device_property_read_u8(dev, "snps,tx-max-burst",
+                               &tx_max_burst);
        device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd",
                                &rx_thr_num_pkt_prd);
        device_property_read_u8(dev, "snps,rx-max-burst-prd",
@@ -1601,6 +1683,12 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 
        dwc->hird_threshold = hird_threshold;
 
+       dwc->rx_thr_num_pkt = rx_thr_num_pkt;
+       dwc->rx_max_burst = rx_max_burst;
+
+       dwc->tx_thr_num_pkt = tx_thr_num_pkt;
+       dwc->tx_max_burst = tx_max_burst;
+
        dwc->rx_thr_num_pkt_prd = rx_thr_num_pkt_prd;
        dwc->rx_max_burst_prd = rx_max_burst_prd;
 
index 80cc532ba9d553003da7e6e2b73f702417117e56..889c122dad457b3f91958a738d44b286257ed3ff 100644 (file)
 #define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24)
 #define DWC3_GRXTHRCFG_PKTCNTSEL BIT(29)
 
+/* Global TX Threshold Configuration Register */
+#define DWC3_GTXTHRCFG_MAXTXBURSTSIZE(n) (((n) & 0xff) << 16)
+#define DWC3_GTXTHRCFG_TXPKTCNT(n) (((n) & 0xf) << 24)
+#define DWC3_GTXTHRCFG_PKTCNTSEL BIT(29)
+
 /* Global RX Threshold Configuration Register for DWC_usb31 only */
 #define DWC31_GRXTHRCFG_MAXRXBURSTSIZE(n)      (((n) & 0x1f) << 16)
 #define DWC31_GRXTHRCFG_RXPKTCNT(n)            (((n) & 0x1f) << 21)
@@ -1041,6 +1046,10 @@ struct dwc3_scratchpad_array {
  * @test_mode_nr: test feature selector
  * @lpm_nyet_threshold: LPM NYET response threshold
  * @hird_threshold: HIRD threshold
+ * @rx_thr_num_pkt: USB receive packet count
+ * @rx_max_burst: max USB receive burst size
+ * @tx_thr_num_pkt: USB transmit packet count
+ * @tx_max_burst: max USB transmit burst size
  * @rx_thr_num_pkt_prd: periodic ESS receive packet count
  * @rx_max_burst_prd: max periodic ESS receive burst size
  * @tx_thr_num_pkt_prd: periodic ESS transmit packet count
@@ -1268,6 +1277,10 @@ struct dwc3 {
        u8                      test_mode_nr;
        u8                      lpm_nyet_threshold;
        u8                      hird_threshold;
+       u8                      rx_thr_num_pkt;
+       u8                      rx_max_burst;
+       u8                      tx_thr_num_pkt;
+       u8                      tx_max_burst;
        u8                      rx_thr_num_pkt_prd;
        u8                      rx_max_burst_prd;
        u8                      tx_thr_num_pkt_prd;