2023-09-12 04:59:03

by Stanley Chang[昌育德]

[permalink] [raw]
Subject: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP

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 <[email protected]>
---
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


2023-09-12 05:07:17

by Stanley Chang[昌育德]

[permalink] [raw]
Subject: [PATCH v3 2/2] dt-bindings: usb: dwc3: Add DWC_usb3 TX/RX threshold configurable

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 <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
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

2023-09-13 01:30:15

by Thinh Nguyen

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP

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 <[email protected]>
> ---
> 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 <[email protected]>

Thanks,
Thinh

2023-09-13 01:54:52

by Stanley Chang[昌育德]

[permalink] [raw]
Subject: RE: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP

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

2023-09-13 04:13:52

by Thinh Nguyen

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP

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 <[email protected]>
> > ---
> > 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

2023-09-13 04:56:26

by Wesley Cheng

[permalink] [raw]
Subject: Re: [PATCH v3 1/2] usb: dwc3: core: configure TX/RX threshold for DWC3_IP

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 <[email protected]>
> ---
> 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;