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