linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sean Anderson <sean.anderson@seco.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	linux-usb@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
	Robert Hancock <robert.hancock@calian.com>,
	Baruch Siach <baruch@tkos.co.il>, Felipe Balbi <balbi@kernel.org>,
	Balaji Prakash J <bjagadee@codeaurora.org>,
	Sean Anderson <sean.anderson@seco.com>
Subject: [PATCH 4/6] usb: dwc3: Handle fractional reference clocks
Date: Fri, 14 Jan 2022 18:39:02 -0500	[thread overview]
Message-ID: <20220114233904.907918-5-sean.anderson@seco.com> (raw)
In-Reply-To: <20220114233904.907918-1-sean.anderson@seco.com>

GUCTL.REFCLKPER can only account for clock frequencies with integer
periods. To address this, program REFCLK_FLADJ with the relative error
caused by period truncation. The formula given in the register reference
has been rearranged to allow calculation based on rate (instead of
period), and to allow for fixed-point arithmetic.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 drivers/usb/dwc3/core.c | 25 +++++++++++++++++++++++--
 drivers/usb/dwc3/core.h |  1 +
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 5214daceda86..48bb3e42cdd0 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -348,7 +348,7 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc)
 static void dwc3_ref_clk_period(struct dwc3 *dwc)
 {
 	u32 reg;
-	unsigned long rate, period;
+	unsigned long fladj, rate, period;
 
 	if (dwc->ref_clk) {
 		rate = clk_get_rate(dwc->ref_clk);
@@ -357,16 +357,37 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc)
 		period = NSEC_PER_SEC / rate;
 	} else if (dwc->ref_clk_per) {
 		period = dwc->ref_clk_per;
+		rate = NSEC_PER_SEC / period;
 	} else {
 		return;
 	}
 
+	/*
+	 * The calculation below is
+	 *
+	 * 125000 * (NSEC_PER_SEC / (rate * period) - 1)
+	 *
+	 * but rearranged for fixed-point arithmetic.
+	 *
+	 * Note that rate * period ~= NSEC_PER_SECOND, minus the number of
+	 * nanoseconds of error caused by the truncation which happened during
+	 * the division when calculating rate or period (whichever one was
+	 * derived from the other). We first calculate the relative error, then
+	 * scale it to units of 0.08%.
+	 */
+	fladj = div64_u64(125000ULL * NSEC_PER_SEC, (u64)rate * period);
+	fladj -= 125000;
+
 	reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
 	reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
 	reg |=  FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period);
 	dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
-}
 
+	reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
+	reg &= ~DWC3_GFLADJ_REFCLK_FLADJ_MASK;
+	reg |= FIELD_PREP(DWC3_GFLADJ_REFCLK_FLADJ_MASK, fladj);
+	dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
+}
 
 /**
  * dwc3_free_one_event_buffer - Frees one event buffer
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 32dfcf3a83d5..50c094af131d 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -388,6 +388,7 @@
 /* Global Frame Length Adjustment Register */
 #define DWC3_GFLADJ_30MHZ_SDBND_SEL		BIT(7)
 #define DWC3_GFLADJ_30MHZ_MASK			0x3f
+#define DWC3_GFLADJ_REFCLK_FLADJ_MASK		GENMASK(21, 8)
 
 /* Global User Control Register*/
 #define DWC3_GUCTL_REFCLKPER_MASK		0xffc00000
-- 
2.25.1


  parent reply	other threads:[~2022-01-14 23:39 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-14 23:38 [PATCH 0/6] usb: dwc3: Calculate REFCLKPER et. al. from reference clock Sean Anderson
2022-01-14 23:38 ` [PATCH 1/6] dt-bindings: usb: dwc3: Deprecate snps,ref-clock-period-ns Sean Anderson
2022-01-14 23:39 ` [PATCH 2/6] usb: dwc3: Get clocks individually Sean Anderson
2022-01-15  1:04   ` Robert Hancock
2022-01-18 16:53     ` Sean Anderson
2022-01-14 23:39 ` [PATCH 3/6] usb: dwc3: Calculate REFCLKPER based on reference clock Sean Anderson
2022-01-14 23:39 ` Sean Anderson [this message]
2022-01-15  1:09   ` [PATCH 4/6] usb: dwc3: Handle fractional reference clocks Robert Hancock
2022-01-18 23:46     ` Sean Anderson
2022-01-14 23:39 ` [PATCH 5/6] arm64: dts: zynqmp: Move USB clocks to dwc3 node Sean Anderson
2022-01-14 23:39 ` [PATCH 6/6] arm64: dts: ipq6018: Use reference clock to set dwc3 period Sean Anderson
2022-01-17 10:36 ` [PATCH 0/6] usb: dwc3: Calculate REFCLKPER et. al. from reference clock Baruch Siach
2022-01-18 19:46   ` Thinh Nguyen
2022-01-18 19:53     ` Sean Anderson
2022-01-18 20:00       ` Thinh Nguyen
2022-01-18 20:39         ` Robert Hancock
2022-01-18 20:54           ` Thinh Nguyen
2022-01-18 20:59         ` Sean Anderson
2022-01-18 21:10           ` Thinh Nguyen
2022-01-18 23:21             ` Robert Hancock
2022-01-17 12:30 ` Jun Li
2022-01-17 23:49   ` Robert Hancock
2022-01-18 23:15     ` Sean Anderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220114233904.907918-5-sean.anderson@seco.com \
    --to=sean.anderson@seco.com \
    --cc=balbi@kernel.org \
    --cc=baruch@tkos.co.il \
    --cc=bjagadee@codeaurora.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=robert.hancock@calian.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).