From d6dc21d7de70445bf198ba64ceb00a5802b70e0c Mon Sep 17 00:00:00 2001 From: William Wu Date: Mon, 27 Aug 2018 11:43:54 +0800 Subject: [PATCH] usb: dwc3: support global Tx/Rx threshold control According to "TX/RX Data FIFO Sizes and TX/RX Threshold Control Register Settings" section in the DWC SuperSpeed USB 3.0 Controller User Guide, for large latency systems, it may cause unnecessary performance reduction, and having large TX/RX FIFOs alone is not sufficient, to solve this issue, the controller provides a packet threshold feature in the host mode. For example, on rk3399 platforms, if we set aclk_perilp to 100 MHz, the system usb bus latency is larger than 2.2 microseconds to access a 1024-byte packet, to avoid underrun and overrun during the burst, threshold and burst size control must be set through GTXTHRCFG and GRXTHRCFG registers. On rk3399 platforms, only a 4-packet TX FIFO and 3-packet RX FIFO is implemented due to area constraints, so we can program the USB Maximum TX Burst Size to 13 and the USB Transmit Packet Count to 4 to avoid TX FIFO underrun during an OUT burst. Similarly, set the USB Maximum TX Burst Size to 10 and the USB Transmit Packet Count to 2 to avoid RX FIFO overrrun. To enable the threshold control, add "snps,gtx-threshold-cfg = <4>, <13>" in dts dwc3 node for Tx, add "snps,grx-threshold-cfg = <2>, <10>" in dts dwc3 node for Rx. Change-Id: I7535fe72e6527544a20c5921440b4888e1bada22 Signed-off-by: William Wu --- drivers/usb/dwc3/core.c | 21 +++++++++++++++++++++ drivers/usb/dwc3/core.h | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 366738c582bf..2ef7ffdc61df 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -729,6 +729,22 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); + if (dwc->grxthrcfg[0] > 0) { + reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); + reg |= DWC3_GRXTHRCFG_PKTCNTSEL | + DWC3_GRXTHRCFG_RXPKTCNT(dwc->grxthrcfg[0]) | + DWC3_GRXTHRCFG_MAXRXBURSTSIZE(dwc->grxthrcfg[1]); + dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); + } + + if (dwc->gtxthrcfg[0] > 0) { + reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG); + reg |= DWC3_GTXTHRCFG_PKTCNTSEL | + DWC3_GTXTHRCFG_TXPKTCNT(dwc->gtxthrcfg[0]) | + DWC3_GTXTHRCFG_MAXRXBURSTSIZE(dwc->gtxthrcfg[1]); + dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg); + } + return 0; err4: @@ -1023,6 +1039,11 @@ static int dwc3_probe(struct platform_device *pdev) &dwc->hsphy_interface); device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", &dwc->fladj); + device_property_read_u32_array(dev, "snps,gtx-threshold-cfg", + dwc->gtxthrcfg, 2); + + device_property_read_u32_array(dev, "snps,grx-threshold-cfg", + dwc->grxthrcfg, 2); /* default to superspeed if no maximum_speed passed */ if (dwc->maximum_speed == USB_SPEED_UNKNOWN) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 73176a6e2d8f..c025c3c007bc 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -166,6 +166,11 @@ #define DWC3_DESCFETCHQ 13 #define DWC3_EVENTQ 15 +/* Global TX Threshold Configuration Register */ +#define DWC3_GTXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0xff) << 16) +#define DWC3_GTXTHRCFG_TXPKTCNT(n) (((n) & 0xf) << 24) +#define DWC3_GTXTHRCFG_PKTCNTSEL BIT(29) + /* Global RX Threshold Configuration Register */ #define DWC3_GRXTHRCFG_MAXRXBURSTSIZE(n) (((n) & 0x1f) << 19) #define DWC3_GRXTHRCFG_RXPKTCNT(n) (((n) & 0xf) << 24) @@ -785,6 +790,8 @@ struct dwc3_scratchpad_array { * @test_mode_nr: test feature selector * @lpm_nyet_threshold: LPM NYET response threshold * @hird_threshold: HIRD threshold + * @grxthrcfg: global Tx threshold config + * @gtxthrcfg: global Rx threshold config * @hsphy_interface: "utmi" or "ulpi" * @connected: true when we're connected to a host, false otherwise * @delayed_status: true when gadget driver asks for delayed status @@ -943,6 +950,8 @@ struct dwc3 { u8 test_mode_nr; u8 lpm_nyet_threshold; u8 hird_threshold; + u32 grxthrcfg[2]; + u32 gtxthrcfg[2]; const char *hsphy_interface;