All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP
@ 2023-09-12  4:19 Stanley Chang
  2023-09-12  4:19 ` [PATCH v3 2/2] dt-bindings: usb: dwc3: Add DWC_usb3 TX/RX threshold configurable Stanley Chang
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Stanley Chang @ 2023-09-12  4:19 UTC (permalink / raw)
  To: Thinh Nguyen
  Cc: Stanley Chang, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Felipe Balbi, linux-usb,
	devicetree, linux-kernel

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>
---
v2 to v3 change:
    Move the threshold setting to new function dwc3_config_threshold.
    Add the threshold setting for usb31 and usb32
v1 to v2 change:
    Add the properties for TX/RX threshold setting
---
 drivers/usb/dwc3/core.c | 160 +++++++++++++++++++++++++++++++---------
 drivers/usb/dwc3/core.h |  13 ++++
 2 files changed, 137 insertions(+), 36 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 9c6bf054f15d..44ee8526dc28 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1057,6 +1057,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
@@ -1209,42 +1314,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;
 
@@ -1380,6 +1450,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;
@@ -1442,6 +1516,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",
@@ -1523,6 +1605,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;
 
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index a69ac67d89fe..6782ec8bfd64 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -211,6 +211,11 @@
 #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)
@@ -1045,6 +1050,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
@@ -1273,6 +1282,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;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v3 2/2] dt-bindings: usb: dwc3: Add DWC_usb3 TX/RX threshold configurable
  2023-09-12  4:19 [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Stanley Chang
@ 2023-09-12  4:19 ` Stanley Chang
  2023-09-12 23:39 ` [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Wesley Cheng
  2023-09-13  1:14 ` Thinh Nguyen
  2 siblings, 0 replies; 6+ messages in thread
From: Stanley Chang @ 2023-09-12  4:19 UTC (permalink / raw)
  To: Thinh Nguyen
  Cc: Stanley Chang, Rob Herring, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Felipe Balbi, linux-usb,
	devicetree, linux-kernel

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.
By default, USB TX and RX threshold are not enabled. To enable
TX or RX threshold, both packet threshold count and max burst size
properties must be set to a valid non-zero value.

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>
Reviewed-by: Rob Herring <robh@kernel.org>
---
v2 to v3 change:
    No change
v1 to v2 change:
    Add the properties for TX/RX threshold setting
---
 .../devicetree/bindings/usb/snps,dwc3.yaml    | 56 +++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
index a696f23730d3..ee5af4b381b1 100644
--- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml
@@ -310,6 +310,62 @@ properties:
     maximum: 62
     deprecated: true
 
+  snps,rx-thr-num-pkt:
+    description:
+      USB RX packet threshold count. In host mode, this field specifies
+      the space that must be available in the RX FIFO before the core can
+      start the corresponding USB RX transaction (burst).
+      In device mode, this field specifies the space that must be
+      available in the RX FIFO before the core can send ERDY for a
+      flow-controlled endpoint. It is only used for SuperSpeed.
+      The valid values for this field are from 1 to 15. (DWC3 SuperSpeed
+      USB 3.0 Controller Databook)
+    $ref: /schemas/types.yaml#/definitions/uint8
+    minimum: 1
+    maximum: 15
+
+  snps,rx-max-burst:
+    description:
+      Max USB RX burst size. In host mode, this field specifies the
+      Maximum Bulk IN burst the DWC_usb3 core can perform. When the system
+      bus is slower than the USB, RX FIFO can overrun during a long burst.
+      You can program a smaller value to this field to limit the RX burst
+      size that the core can perform. It only applies to SS Bulk,
+      Isochronous, and Interrupt IN endpoints in the host mode.
+      In device mode, this field specifies the NUMP value that is sent in
+      ERDY for an OUT endpoint.
+      The valid values for this field are from 1 to 16. (DWC3 SuperSpeed
+      USB 3.0 Controller Databook)
+    $ref: /schemas/types.yaml#/definitions/uint8
+    minimum: 1
+    maximum: 16
+
+  snps,tx-thr-num-pkt:
+    description:
+      USB TX packet threshold count. This field specifies the number of
+      packets that must be in the TXFIFO before the core can start
+      transmission for the corresponding USB transaction (burst).
+      This count is valid in both host and device modes. It is only used
+      for SuperSpeed operation.
+      Valid values are from 1 to 15. (DWC3 SuperSpeed USB 3.0 Controller
+      Databook)
+    $ref: /schemas/types.yaml#/definitions/uint8
+    minimum: 1
+    maximum: 15
+
+  snps,tx-max-burst:
+    description:
+      Max USB TX burst size. When the system bus is slower than the USB,
+      TX FIFO can underrun during a long burst. Program a smaller value
+      to this field to limit the TX burst size that the core can execute.
+      In Host mode, it only applies to SS Bulk, Isochronous, and Interrupt
+      OUT endpoints. This value is not used in device mode.
+      Valid values are from 1 to 16. (DWC3 SuperSpeed USB 3.0 Controller
+      Databook)
+    $ref: /schemas/types.yaml#/definitions/uint8
+    minimum: 1
+    maximum: 16
+
   snps,rx-thr-num-pkt-prd:
     description:
       Periodic ESS RX packet threshold count (host mode only). Set this and
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP
  2023-09-12  4:19 [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Stanley Chang
  2023-09-12  4:19 ` [PATCH v3 2/2] dt-bindings: usb: dwc3: Add DWC_usb3 TX/RX threshold configurable Stanley Chang
@ 2023-09-12 23:39 ` Wesley Cheng
  2023-09-13  1:06   ` Thinh Nguyen
  2023-09-13  1:14 ` Thinh Nguyen
  2 siblings, 1 reply; 6+ messages in thread
From: Wesley Cheng @ 2023-09-12 23:39 UTC (permalink / raw)
  To: Stanley Chang, Thinh Nguyen
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Felipe Balbi, linux-usb, devicetree, linux-kernel

Hi,

On 9/11/2023 9:19 PM, Stanley Chang wrote:
> 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>
> ---
> v2 to v3 change:
>      Move the threshold setting to new function dwc3_config_threshold.
>      Add the threshold setting for usb31 and usb32
> v1 to v2 change:
>      Add the properties for TX/RX threshold setting
> ---
>   drivers/usb/dwc3/core.c | 160 +++++++++++++++++++++++++++++++---------
>   drivers/usb/dwc3/core.h |  13 ++++
>   2 files changed, 137 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 9c6bf054f15d..44ee8526dc28 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -1057,6 +1057,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
> @@ -1209,42 +1314,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;
>   
> @@ -1380,6 +1450,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;
> @@ -1442,6 +1516,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);

Aren't there value limitations for some of these (if not all) settings? 
  For example, in the DWC3 programming guide, the max burst fields say 
(for DWC31):
	"Note: This field can only be set to 2, 4, 8 or 16."

And for the packet threshold count:
	"Valid values are from 1 to 16."

Thanks
Wesley Cheng

>   	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",
> @@ -1523,6 +1605,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;
>   
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index a69ac67d89fe..6782ec8bfd64 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -211,6 +211,11 @@
>   #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)
> @@ -1045,6 +1050,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
> @@ -1273,6 +1282,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;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP
  2023-09-12 23:39 ` [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Wesley Cheng
@ 2023-09-13  1:06   ` Thinh Nguyen
  2023-09-13  1:54     ` Stanley Chang[昌育德]
  0 siblings, 1 reply; 6+ messages in thread
From: Thinh Nguyen @ 2023-09-13  1:06 UTC (permalink / raw)
  To: Wesley Cheng
  Cc: Stanley Chang, Thinh Nguyen, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Felipe Balbi, linux-usb,
	devicetree, linux-kernel

On Tue, Sep 12, 2023, Wesley Cheng wrote:
> Hi,
> 
> On 9/11/2023 9:19 PM, Stanley Chang wrote:
> > 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>
> > ---
> > v2 to v3 change:
> >      Move the threshold setting to new function dwc3_config_threshold.
> >      Add the threshold setting for usb31 and usb32
> > v1 to v2 change:
> >      Add the properties for TX/RX threshold setting
> > ---
> >   drivers/usb/dwc3/core.c | 160 +++++++++++++++++++++++++++++++---------
> >   drivers/usb/dwc3/core.h |  13 ++++
> >   2 files changed, 137 insertions(+), 36 deletions(-)
> > 
> > diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> > index 9c6bf054f15d..44ee8526dc28 100644
> > --- a/drivers/usb/dwc3/core.c
> > +++ b/drivers/usb/dwc3/core.c
> > @@ -1057,6 +1057,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
> > @@ -1209,42 +1314,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;
> > @@ -1380,6 +1450,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;
> > @@ -1442,6 +1516,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);
> 
> Aren't there value limitations for some of these (if not all) settings?  For
> example, in the DWC3 programming guide, the max burst fields say (for
> DWC31):
> 	"Note: This field can only be set to 2, 4, 8 or 16."
> 
> And for the packet threshold count:
> 	"Valid values are from 1 to 16."
> 

Stanley documented this in the dt binding. I think what he had written
there is fine.

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP
  2023-09-12  4:19 [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Stanley Chang
  2023-09-12  4:19 ` [PATCH v3 2/2] dt-bindings: usb: dwc3: Add DWC_usb3 TX/RX threshold configurable Stanley Chang
  2023-09-12 23:39 ` [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Wesley Cheng
@ 2023-09-13  1:14 ` Thinh Nguyen
  2 siblings, 0 replies; 6+ messages in thread
From: Thinh Nguyen @ 2023-09-13  1:14 UTC (permalink / raw)
  To: Stanley Chang
  Cc: Thinh Nguyen, Greg Kroah-Hartman, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Felipe Balbi, linux-usb,
	devicetree, linux-kernel

On Tue, Sep 12, 2023, Stanley Chang wrote:
> 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>
> ---
> v2 to v3 change:
>     Move the threshold setting to new function dwc3_config_threshold.
>     Add the threshold setting for usb31 and usb32
> v1 to v2 change:
>     Add the properties for TX/RX threshold setting
> ---
>  drivers/usb/dwc3/core.c | 160 +++++++++++++++++++++++++++++++---------
>  drivers/usb/dwc3/core.h |  13 ++++
>  2 files changed, 137 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index 9c6bf054f15d..44ee8526dc28 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -1057,6 +1057,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
> @@ -1209,42 +1314,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;
>  
> @@ -1380,6 +1450,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;
> @@ -1442,6 +1516,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",
> @@ -1523,6 +1605,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;
>  
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index a69ac67d89fe..6782ec8bfd64 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -211,6 +211,11 @@
>  #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)
> @@ -1045,6 +1050,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
> @@ -1273,6 +1282,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;
> -- 
> 2.34.1
> 

Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>

Thanks,
Thinh

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP
  2023-09-13  1:06   ` Thinh Nguyen
@ 2023-09-13  1:54     ` Stanley Chang[昌育德]
  0 siblings, 0 replies; 6+ messages in thread
From: Stanley Chang[昌育德] @ 2023-09-13  1:54 UTC (permalink / raw)
  To: Thinh Nguyen, Wesley Cheng
  Cc: Greg Kroah-Hartman, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Felipe Balbi, linux-usb, devicetree, linux-kernel

Hi Wesley and Thinh,

> > Aren't there value limitations for some of these (if not all)
> > settings?  For example, in the DWC3 programming guide, the max burst
> > fields say (for
> > DWC31):
> >       "Note: This field can only be set to 2, 4, 8 or 16."
> >
> > And for the packet threshold count:
> >       "Valid values are from 1 to 16."
> >
> 
> Stanley documented this in the dt binding. I think what he had written there is
> fine.
> 

Thanks for Thinh's response.

Stanley

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-09-13  1:54 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-12  4:19 [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Stanley Chang
2023-09-12  4:19 ` [PATCH v3 2/2] dt-bindings: usb: dwc3: Add DWC_usb3 TX/RX threshold configurable Stanley Chang
2023-09-12 23:39 ` [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP Wesley Cheng
2023-09-13  1:06   ` Thinh Nguyen
2023-09-13  1:54     ` Stanley Chang[昌育德]
2023-09-13  1:14 ` Thinh Nguyen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.