c6ca7ce
From patchwork Thu Jun  1 14:14:16 2017
c6ca7ce
Content-Type: text/plain; charset="utf-8"
c6ca7ce
MIME-Version: 1.0
c6ca7ce
Content-Transfer-Encoding: 7bit
c6ca7ce
Subject: [v4,1/2] clk: bcm2835: Limit PCM clock to OSC and PLLD_PER
c6ca7ce
From: Phil Elwell <phil@raspberrypi.org>
c6ca7ce
X-Patchwork-Id: 9759641
c6ca7ce
Message-Id: <8cc0ba82-d33e-127b-7b86-ac595ef416d1@raspberrypi.org>
c6ca7ce
To: Michael Turquette <mturquette@baylibre.com>,
c6ca7ce
 Stephen Boyd <sboyd@codeaurora.org>, Eric Anholt <eric@anholt.net>,
c6ca7ce
 Stefan Wahren <stefan.wahren@i2se.com>,
c6ca7ce
 Florian Fainelli <f.fainelli@gmail.com>,
c6ca7ce
 linux-clk@vger.kernel.org, linux-rpi-kernel@lists.infradead.org,
c6ca7ce
 linux-kernel@vger.kernel.org
c6ca7ce
Date: Thu, 1 Jun 2017 15:14:16 +0100
c6ca7ce
c6ca7ce
Restrict clock sources for the PCM peripheral to the oscillator and
c6ca7ce
PLLD_PER because other source may have varying rates or be switched off.
c6ca7ce
Prevent other sources from being selected by replacing their names in
c6ca7ce
the list of potential parents with dummy entries (entry index is
c6ca7ce
significant).
c6ca7ce
c6ca7ce
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
c6ca7ce
Reviewed-by: Eric Anholt <eric@anholt.net>
c6ca7ce
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
c6ca7ce
---
c6ca7ce
 drivers/clk/bcm/clk-bcm2835.c | 27 ++++++++++++++++++++++++++-
c6ca7ce
 1 file changed, 26 insertions(+), 1 deletion(-)
c6ca7ce
c6ca7ce
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
c6ca7ce
index 0258538..49867d2 100644
c6ca7ce
--- a/drivers/clk/bcm/clk-bcm2835.c
c6ca7ce
+++ b/drivers/clk/bcm/clk-bcm2835.c
c6ca7ce
@@ -1516,6 +1516,31 @@ struct bcm2835_clk_desc {
c6ca7ce
 	.parents = bcm2835_clock_per_parents,				\
c6ca7ce
 	__VA_ARGS__)
c6ca7ce
 
c6ca7ce
+/*
c6ca7ce
+ * Restrict clock sources for the PCM peripheral to the oscillator and
c6ca7ce
+ * PLLD_PER because other source may have varying rates or be switched
c6ca7ce
+ * off.
c6ca7ce
+ *
c6ca7ce
+ * Prevent other sources from being selected by replacing their names in
c6ca7ce
+ * the list of potential parents with dummy entries (entry index is
c6ca7ce
+ * significant).
c6ca7ce
+ */
c6ca7ce
+static const char *const bcm2835_pcm_per_parents[] = {
c6ca7ce
+	"-",
c6ca7ce
+	"xosc",
c6ca7ce
+	"-",
c6ca7ce
+	"-",
c6ca7ce
+	"-",
c6ca7ce
+	"-",
c6ca7ce
+	"plld_per",
c6ca7ce
+	"-",
c6ca7ce
+};
c6ca7ce
+
c6ca7ce
+#define REGISTER_PCM_CLK(...)	REGISTER_CLK(				\
c6ca7ce
+	.num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents),		\
c6ca7ce
+	.parents = bcm2835_pcm_per_parents,				\
c6ca7ce
+	__VA_ARGS__)
c6ca7ce
+
c6ca7ce
 /* main vpu parent mux */
c6ca7ce
 static const char *const bcm2835_clock_vpu_parents[] = {
c6ca7ce
 	"gnd",
c6ca7ce
@@ -1993,7 +2018,7 @@ struct bcm2835_clk_desc {
c6ca7ce
 		.int_bits = 4,
c6ca7ce
 		.frac_bits = 8,
c6ca7ce
 		.tcnt_mux = 22),
c6ca7ce
-	[BCM2835_CLOCK_PCM]	= REGISTER_PER_CLK(
c6ca7ce
+	[BCM2835_CLOCK_PCM]	= REGISTER_PCM_CLK(
c6ca7ce
 		.name = "pcm",
c6ca7ce
 		.ctl_reg = CM_PCMCTL,
c6ca7ce
 		.div_reg = CM_PCMDIV,
c6ca7ce
From patchwork Thu Jun  1 14:14:22 2017
c6ca7ce
Content-Type: text/plain; charset="utf-8"
c6ca7ce
MIME-Version: 1.0
c6ca7ce
Content-Transfer-Encoding: 7bit
c6ca7ce
Subject: [v4,2/2] clk: bcm2835: Minimise clock jitter for PCM clock
c6ca7ce
From: Phil Elwell <phil@raspberrypi.org>
c6ca7ce
X-Patchwork-Id: 9759643
c6ca7ce
Message-Id: <9989244b-ca4d-9081-95d9-b24f51099222@raspberrypi.org>
c6ca7ce
To: Michael Turquette <mturquette@baylibre.com>,
c6ca7ce
 Stephen Boyd <sboyd@codeaurora.org>, Eric Anholt <eric@anholt.net>,
c6ca7ce
 Stefan Wahren <stefan.wahren@i2se.com>,
c6ca7ce
 Florian Fainelli <f.fainelli@gmail.com>,
c6ca7ce
 linux-clk@vger.kernel.org, linux-rpi-kernel@lists.infradead.org,
c6ca7ce
 linux-kernel@vger.kernel.org
c6ca7ce
Date: Thu, 1 Jun 2017 15:14:22 +0100
c6ca7ce
c6ca7ce
Fractional clock dividers generate accurate average frequencies but
c6ca7ce
with jitter, particularly when the integer divisor is small.
c6ca7ce
c6ca7ce
Introduce a new metric of clock accuracy to penalise clocks with a good
c6ca7ce
average but worse jitter compared to clocks with an average which is no
c6ca7ce
better but with lower jitter. The metric is the ideal rate minus the
c6ca7ce
worse deviation from that ideal using the nearest integer divisors.
c6ca7ce
c6ca7ce
Use this metric for parent selection for clocks requiring low jitter
c6ca7ce
(currently just PCM).
c6ca7ce
c6ca7ce
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
c6ca7ce
Reviewed-by: Eric Anholt <eric@anholt.net>
c6ca7ce
Acked-by: Stefan Wahren <stefan.wahren@i2se.com>
c6ca7ce
---
c6ca7ce
 drivers/clk/bcm/clk-bcm2835.c | 34 +++++++++++++++++++++++++++++-----
c6ca7ce
 1 file changed, 29 insertions(+), 5 deletions(-)
c6ca7ce
c6ca7ce
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
c6ca7ce
index 49867d2..0bc56a0 100644
c6ca7ce
--- a/drivers/clk/bcm/clk-bcm2835.c
c6ca7ce
+++ b/drivers/clk/bcm/clk-bcm2835.c
c6ca7ce
@@ -530,6 +530,7 @@ struct bcm2835_clock_data {
c6ca7ce
 
c6ca7ce
 	bool is_vpu_clock;
c6ca7ce
 	bool is_mash_clock;
c6ca7ce
+	bool low_jitter;
c6ca7ce
 
c6ca7ce
 	u32 tcnt_mux;
c6ca7ce
 };
c6ca7ce
@@ -1124,7 +1125,8 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
c6ca7ce
 							int parent_idx,
c6ca7ce
 							unsigned long rate,
c6ca7ce
 							u32 *div,
c6ca7ce
-							unsigned long *prate)
c6ca7ce
+							unsigned long *prate,
c6ca7ce
+							unsigned long *avgrate)
c6ca7ce
 {
c6ca7ce
 	struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
c6ca7ce
 	struct bcm2835_cprman *cprman = clock->cprman;
c6ca7ce
@@ -1139,8 +1141,25 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
c6ca7ce
 		*prate = clk_hw_get_rate(parent);
c6ca7ce
 		*div = bcm2835_clock_choose_div(hw, rate, *prate, true);
c6ca7ce
 
c6ca7ce
-		return bcm2835_clock_rate_from_divisor(clock, *prate,
c6ca7ce
-						       *div);
c6ca7ce
+		*avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);
c6ca7ce
+
c6ca7ce
+		if (data->low_jitter && (*div & CM_DIV_FRAC_MASK)) {
c6ca7ce
+			unsigned long high, low;
c6ca7ce
+			u32 int_div = *div & ~CM_DIV_FRAC_MASK;
c6ca7ce
+
c6ca7ce
+			high = bcm2835_clock_rate_from_divisor(clock, *prate,
c6ca7ce
+							       int_div);
c6ca7ce
+			int_div += CM_DIV_FRAC_MASK + 1;
c6ca7ce
+			low = bcm2835_clock_rate_from_divisor(clock, *prate,
c6ca7ce
+							      int_div);
c6ca7ce
+
c6ca7ce
+			/*
c6ca7ce
+			 * Return a value which is the maximum deviation
c6ca7ce
+			 * below the ideal rate, for use as a metric.
c6ca7ce
+			 */
c6ca7ce
+			return *avgrate - max(*avgrate - low, high - *avgrate);
c6ca7ce
+		}
c6ca7ce
+		return *avgrate;
c6ca7ce
 	}
c6ca7ce
 
c6ca7ce
 	if (data->frac_bits)
c6ca7ce
@@ -1167,6 +1186,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
c6ca7ce
 
c6ca7ce
 	*div = curdiv << CM_DIV_FRAC_BITS;
c6ca7ce
 	*prate = curdiv * best_rate;
c6ca7ce
+	*avgrate = best_rate;
c6ca7ce
 
c6ca7ce
 	return best_rate;
c6ca7ce
 }
c6ca7ce
@@ -1178,6 +1198,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
c6ca7ce
 	bool current_parent_is_pllc;
c6ca7ce
 	unsigned long rate, best_rate = 0;
c6ca7ce
 	unsigned long prate, best_prate = 0;
c6ca7ce
+	unsigned long avgrate, best_avgrate = 0;
c6ca7ce
 	size_t i;
c6ca7ce
 	u32 div;
c6ca7ce
 
c6ca7ce
@@ -1202,11 +1223,13 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
c6ca7ce
 			continue;
c6ca7ce
 
c6ca7ce
 		rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
c6ca7ce
-							  &div, &prate);
c6ca7ce
+							  &div, &prate,
c6ca7ce
+							  &avgrate);
c6ca7ce
 		if (rate > best_rate && rate <= req->rate) {
c6ca7ce
 			best_parent = parent;
c6ca7ce
 			best_prate = prate;
c6ca7ce
 			best_rate = rate;
c6ca7ce
+			best_avgrate = avgrate;
c6ca7ce
 		}
c6ca7ce
 	}
c6ca7ce
 
c6ca7ce
@@ -1216,7 +1239,7 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
c6ca7ce
 	req->best_parent_hw = best_parent;
c6ca7ce
 	req->best_parent_rate = best_prate;
c6ca7ce
 
c6ca7ce
-	req->rate = best_rate;
c6ca7ce
+	req->rate = best_avgrate;
c6ca7ce
 
c6ca7ce
 	return 0;
c6ca7ce
 }
c6ca7ce
@@ -2025,6 +2048,7 @@ struct bcm2835_clk_desc {
c6ca7ce
 		.int_bits = 12,
c6ca7ce
 		.frac_bits = 12,
c6ca7ce
 		.is_mash_clock = true,
c6ca7ce
+		.low_jitter = true,
c6ca7ce
 		.tcnt_mux = 23),
c6ca7ce
 	[BCM2835_CLOCK_PWM]	= REGISTER_PER_CLK(
c6ca7ce
 		.name = "pwm",