All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] clk: sunxi-ng: more misc fixes
@ 2017-04-05  6:37 Chen-Yu Tsai
  2017-04-05  6:37 ` [PATCH 1/3] clk: sunxi-ng: mult: Support PLL lock detection Chen-Yu Tsai
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2017-04-05  6:37 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd
  Cc: Chen-Yu Tsai, linux-clk, linux-sunxi

Hi Maxime,

Here are 3 more clk fixes. The first one is needed for the second.
The third is a TODO I spotted while doing the first two.

ChenYu

Chen-Yu Tsai (3):
  clk: sunxi-ng: mult: Support PLL lock detection
  clk: sunxi-ng: a80: Remodel CPU cluster PLLs as N-type multiplier
    clocks
  clk: sunxi-ng: a33: Add offset and minimum value for DDR1 PLL N factor

 drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 18 ++++++----
 drivers/clk/sunxi-ng/ccu-sun9i-a80.c | 70 ++++++++++++++++++++++++++----------
 drivers/clk/sunxi-ng/ccu_mult.c      |  2 ++
 drivers/clk/sunxi-ng/ccu_mult.h      |  2 ++
 4 files changed, 67 insertions(+), 25 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] clk: sunxi-ng: mult: Support PLL lock detection
  2017-04-05  6:37 [PATCH 0/3] clk: sunxi-ng: more misc fixes Chen-Yu Tsai
@ 2017-04-05  6:37 ` Chen-Yu Tsai
  2017-04-05  6:37 ` [PATCH 2/3] clk: sunxi-ng: a80: Remodel CPU cluster PLLs as N-type multiplier clocks Chen-Yu Tsai
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2017-04-05  6:37 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd
  Cc: Chen-Yu Tsai, linux-clk, linux-sunxi

Some PLL clocks are N (multiplier) type clocks, or can be simplified
as such. An example of the former is the DDR1 PLL clock on the A33.
An example of the latter is the CPU PLL clock on the A80, in which
the P divider is only used for low frequencies that are of little
use. Both clocks support PLL lock detection.

The mult clock macro implies support for this, but that is not true.
The field is simply discarded. This patch adds proper support for it.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 drivers/clk/sunxi-ng/ccu_mult.c | 2 ++
 drivers/clk/sunxi-ng/ccu_mult.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c
index 8724c01171b1..671141359895 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.c
+++ b/drivers/clk/sunxi-ng/ccu_mult.c
@@ -137,6 +137,8 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	spin_unlock_irqrestore(cm->common.lock, flags);
 
+	ccu_helper_wait_for_lock(&cm->common, cm->lock);
+
 	return 0;
 }
 
diff --git a/drivers/clk/sunxi-ng/ccu_mult.h b/drivers/clk/sunxi-ng/ccu_mult.h
index 524acddfcb2e..f9c37b987d72 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.h
+++ b/drivers/clk/sunxi-ng/ccu_mult.h
@@ -33,6 +33,7 @@ struct ccu_mult_internal {
 
 struct ccu_mult {
 	u32			enable;
+	u32			lock;
 
 	struct ccu_frac_internal	frac;
 	struct ccu_mult_internal	mult;
@@ -45,6 +46,7 @@ struct ccu_mult {
 				   _flags)				\
 	struct ccu_mult _struct = {					\
 		.enable	= _gate,					\
+		.lock	= _lock,					\
 		.mult	= _SUNXI_CCU_MULT(_mshift, _mwidth),		\
 		.common	= {						\
 			.reg		= _reg,				\
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] clk: sunxi-ng: a80: Remodel CPU cluster PLLs as N-type multiplier clocks
  2017-04-05  6:37 [PATCH 0/3] clk: sunxi-ng: more misc fixes Chen-Yu Tsai
  2017-04-05  6:37 ` [PATCH 1/3] clk: sunxi-ng: mult: Support PLL lock detection Chen-Yu Tsai
@ 2017-04-05  6:37 ` Chen-Yu Tsai
  2017-04-05  6:37 ` [PATCH 3/3] clk: sunxi-ng: a33: Add offset and minimum value for DDR1 PLL N factor Chen-Yu Tsai
  2017-04-05  7:03 ` [PATCH 0/3] clk: sunxi-ng: more misc fixes Maxime Ripard
  3 siblings, 0 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2017-04-05  6:37 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd
  Cc: Chen-Yu Tsai, linux-clk, linux-sunxi

The CPU cluster PLLs on the A80 are NP clocks that are atypical in two ways:

  - The P factor is 1 bit wide, and translates to a /1 or /4 divider.

  - The P factor should only be used for output frequencies lower than
    288 MHz. The N factor has a lower limit of 12, which likely contributed
    to this extra divider.

According to the user manual, the clocks can only go as low as 200 MHz.
The vendor BSP kernel does not even define operating points below 360
MHz for these clocks. The lower end for cpufreq in the vendor kernel is
even higher. The mainline Linux kernel doesn't support cpufreq for the
A80 at the moment. This means the lower frequencies are untested, and
will likely remain unused.

The new sunxi-ng style clocks don't support the quirks listed above.
Instead of trying to work the quirks in for something of little usage,
we re-model the clocks into N-type multipler clocks, with P fixed at 1.
At probe time we check if P is set to 4, and fix it up if needed. This
is highly unlikely though.

Fixes: b8eb71dcdd08 ("clk: sunxi-ng: Add A80 CCU")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 drivers/clk/sunxi-ng/ccu-sun9i-a80.c | 70 ++++++++++++++++++++++++++----------
 1 file changed, 52 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
index a031beefa5b5..8936ef87652c 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
@@ -29,41 +29,41 @@
 
 #define CCU_SUN9I_LOCK_REG	0x09c
 
-static struct clk_div_table pll_cpux_p_div_table[] = {
-	{ .val = 0, .div = 1 },
-	{ .val = 1, .div = 4 },
-	{ /* Sentinel */ },
-};
-
 /*
- * The CPU PLLs are actually NP clocks, but P is /1 or /4, so here we
- * use the NM clocks with a divider table for M.
+ * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
+ * P should only be used for output frequencies lower than 228 MHz.
+ * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
+ *
+ * For now we can just model it as a multiplier clock, and force P to /1.
  */
-static struct ccu_nm pll_c0cpux_clk = {
+#define SUN9I_A80_PLL_C0CPUX_REG	0x000
+#define SUN9I_A80_PLL_C1CPUX_REG	0x004
+
+static struct ccu_mult pll_c0cpux_clk = {
 	.enable		= BIT(31),
 	.lock		= BIT(0),
-	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
-	.m		= _SUNXI_CCU_DIV_TABLE(16, 1, pll_cpux_p_div_table),
+	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 	.common		= {
-		.reg		= 0x000,
+		.reg		= SUN9I_A80_PLL_C0CPUX_REG,
 		.lock_reg	= CCU_SUN9I_LOCK_REG,
 		.features	= CCU_FEATURE_LOCK_REG,
 		.hw.init	= CLK_HW_INIT("pll-c0cpux", "osc24M",
-					      &ccu_nm_ops, CLK_SET_RATE_UNGATE),
+					      &ccu_mult_ops,
+					      CLK_SET_RATE_UNGATE),
 	},
 };
 
-static struct ccu_nm pll_c1cpux_clk = {
+static struct ccu_mult pll_c1cpux_clk = {
 	.enable		= BIT(31),
 	.lock		= BIT(1),
-	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
-	.m		= _SUNXI_CCU_DIV_TABLE(16, 1, pll_cpux_p_div_table),
+	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
 	.common		= {
-		.reg		= 0x004,
+		.reg		= SUN9I_A80_PLL_C1CPUX_REG,
 		.lock_reg	= CCU_SUN9I_LOCK_REG,
 		.features	= CCU_FEATURE_LOCK_REG,
 		.hw.init	= CLK_HW_INIT("pll-c1cpux", "osc24M",
-					      &ccu_nm_ops, CLK_SET_RATE_UNGATE),
+					      &ccu_mult_ops,
+					      CLK_SET_RATE_UNGATE),
 	},
 };
 
@@ -1188,6 +1188,36 @@ static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = {
 	.num_resets	= ARRAY_SIZE(sun9i_a80_ccu_resets),
 };
 
+#define SUN9I_A80_PLL_P_SHIFT	16
+#define SUN9I_A80_PLL_N_SHIFT	8
+#define SUN9I_A80_PLL_N_WIDTH	8
+
+static void sun9i_a80_cpu_pll_fixup(void __iomem *reg)
+{
+	u32 val = readl(reg);
+
+	/* bail out if P divider is not used */
+	if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT)))
+		return;
+
+	/*
+	 * If P is used, output should be less than 288 MHz. When we
+	 * set P to 1, we should also decrease the multiplier so the
+	 * output doesn't go out of range, but not too much such that
+	 * the multiplier stays above 12, the minimal operation value.
+	 *
+	 * To keep it simple, set the multiplier to 17, the reset value.
+	 */
+	val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1,
+			SUN9I_A80_PLL_N_SHIFT);
+	val |= 17 << SUN9I_A80_PLL_N_SHIFT;
+
+	/* And clear P */
+	val &= ~BIT(SUN9I_A80_PLL_P_SHIFT);
+
+	writel(val, reg);
+}
+
 static int sun9i_a80_ccu_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -1204,6 +1234,10 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev)
 	val &= (BIT(16) & BIT(18));
 	writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
 
+	/* Enforce P = 1 for both CPU cluster PLLs */
+	sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
+	sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
+
 	return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc);
 }
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] clk: sunxi-ng: a33: Add offset and minimum value for DDR1 PLL N factor
  2017-04-05  6:37 [PATCH 0/3] clk: sunxi-ng: more misc fixes Chen-Yu Tsai
  2017-04-05  6:37 ` [PATCH 1/3] clk: sunxi-ng: mult: Support PLL lock detection Chen-Yu Tsai
  2017-04-05  6:37 ` [PATCH 2/3] clk: sunxi-ng: a80: Remodel CPU cluster PLLs as N-type multiplier clocks Chen-Yu Tsai
@ 2017-04-05  6:37 ` Chen-Yu Tsai
  2017-04-05  7:03 ` [PATCH 0/3] clk: sunxi-ng: more misc fixes Maxime Ripard
  3 siblings, 0 replies; 5+ messages in thread
From: Chen-Yu Tsai @ 2017-04-05  6:37 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd
  Cc: Chen-Yu Tsai, linux-clk, linux-sunxi

The DDR1 PLL on the A33 is an oddball amongst the A33 CCU clocks.
It is a clock multiplier, with the effective multiplier in the
range of 12 ~ 255 and no offset between the multiplier value and
the value programmed into the register.

Implement the zero offset and minimum value of 12 for this clock.

Fixes: d05c748bd730 ("clk: sunxi-ng: Add A33 CCU support")
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 drivers/clk/sunxi-ng/ccu-sun8i-a33.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
index a7b3c08ed0e2..56370c2c7f98 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
@@ -159,13 +159,17 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
 					BIT(28),	/* lock */
 					CLK_SET_RATE_UNGATE);
 
-/* TODO: Fix N */
-static SUNXI_CCU_N_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
-				  "osc24M", 0x04c,
-				  8, 6,			/* N */
-				  BIT(31),		/* gate */
-				  BIT(28),		/* lock */
-				  CLK_SET_RATE_UNGATE);
+static struct ccu_mult pll_ddr1_clk = {
+	.enable	= BIT(31),
+	.lock	= BIT(28),
+	.mult	= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 6, 0, 12, 0),
+	.common	= {
+		.reg		= 0x04c,
+		.hw.init	= CLK_HW_INIT("pll-ddr1", "osc24M",
+					      &ccu_mult_ops,
+					      CLK_SET_RATE_UNGATE),
+	},
+};
 
 static const char * const cpux_parents[] = { "osc32k", "osc24M",
 					     "pll-cpux" , "pll-cpux" };
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] clk: sunxi-ng: more misc fixes
  2017-04-05  6:37 [PATCH 0/3] clk: sunxi-ng: more misc fixes Chen-Yu Tsai
                   ` (2 preceding siblings ...)
  2017-04-05  6:37 ` [PATCH 3/3] clk: sunxi-ng: a33: Add offset and minimum value for DDR1 PLL N factor Chen-Yu Tsai
@ 2017-04-05  7:03 ` Maxime Ripard
  3 siblings, 0 replies; 5+ messages in thread
From: Maxime Ripard @ 2017-04-05  7:03 UTC (permalink / raw)
  To: Chen-Yu Tsai; +Cc: Michael Turquette, Stephen Boyd, linux-clk, linux-sunxi

[-- Attachment #1: Type: text/plain, Size: 353 bytes --]

On Wed, Apr 05, 2017 at 02:37:41PM +0800, Chen-Yu Tsai wrote:
> Hi Maxime,
> 
> Here are 3 more clk fixes. The first one is needed for the second.
> The third is a TODO I spotted while doing the first two.

Applied all three, thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-04-05  7:03 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-05  6:37 [PATCH 0/3] clk: sunxi-ng: more misc fixes Chen-Yu Tsai
2017-04-05  6:37 ` [PATCH 1/3] clk: sunxi-ng: mult: Support PLL lock detection Chen-Yu Tsai
2017-04-05  6:37 ` [PATCH 2/3] clk: sunxi-ng: a80: Remodel CPU cluster PLLs as N-type multiplier clocks Chen-Yu Tsai
2017-04-05  6:37 ` [PATCH 3/3] clk: sunxi-ng: a33: Add offset and minimum value for DDR1 PLL N factor Chen-Yu Tsai
2017-04-05  7:03 ` [PATCH 0/3] clk: sunxi-ng: more misc fixes Maxime Ripard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.