diff mbox series

[1/8] usb: dwc3: core: Handle fladj becoming zero

Message ID 6f5cd1d796fb7c666348cc611b2f8178c009e2e4.1677749625.git.quic_varada@quicinc.com (mailing list archive)
State Superseded
Headers show
Series Enable IPQ9754 USB | expand

Commit Message

Varadarajan Narayanan March 2, 2023, 9:55 a.m. UTC
In dwc3_ref_clk_period, the computation

	fladj = div64_u64(125000ULL * NSEC_PER_SEC, (u64)rate * period);
	fladj -= 125000;

could turn out to be zero. If fladj is zero, the following
FIELD_PREP clears out that field and the user overridden value
set in the DTS using "snps,quirk-frame-length-adjustment" is
lost. Ensure to retain the user overridden value if the above
evaluates to 0.

Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
---
 drivers/usb/dwc3/core.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 476b636..63af83b 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -401,6 +401,33 @@  static void dwc3_ref_clk_period(struct dwc3 *dwc)
 	fladj -= 125000;
 
 	/*
+	 * Since rate = NSEC_PER_SEC / period and period = NSEC_PER_SEC / rate
+	 * above calculation could turn out to be zero.
+	 *
+	 * if (dwc->ref_clk)
+	 *	125000 * NSEC_PER_SEC    125000 * NSEC_PER_SEC
+	 *	--------------------- => ---------------------
+	 *	    rate * period         rate * NSEC_PER_SEC
+	 *					 ------------
+	 *					     rate
+	 * else
+	 *	125000 * NSEC_PER_SEC    125000 * NSEC_PER_SEC
+	 *	--------------------- => ---------------------
+	 *	    rate * period        NSEC_PER_SEC * period
+	 *				 ------------
+	 *				    period
+	 * Hence, the calculation
+	 *	div64_u64(125000ULL * NSEC_PER_SEC, (u64)rate * period)
+	 * returns 125000ULL and fladj -= 125000 sets fladj to zero.
+	 * If fladj is zero, the following FIELD_PREP clears out that
+	 * field and the user overridden value set in the DTS using
+	 * "snps,quirk-frame-length-adjustment" is lost. Ensure to retain
+	 * the user overridden value if the above calculation evaluates to 0.
+	 */
+	if (fladj == 0)
+		fladj = FIELD_GET(DWC3_GFLADJ_REFCLK_FLADJ_MASK, dwc->fladj);
+
+	/*
 	 * The documented 240MHz constant is scaled by 2 to get PLS1 as well.
 	 */
 	decr = 480000000 / rate;