linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] clk: meson: clk-pll driver update
@ 2018-07-17  9:56 Jerome Brunet
  2018-07-17  9:56 ` [PATCH 1/3] clk: meson: clk-pll: add enable bit Jerome Brunet
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Jerome Brunet @ 2018-07-17  9:56 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: Jerome Brunet, linux-amlogic, linux-clk, linux-kernel,
	Kevin Hilman, Martin Blumenstingl

This patchset is yet another round of update to the amlogic pll driver.

 1) Enable bit is added so we don't rely on the bootloader or the init
    value to enable to pll device.
 2) OD post dividers are removed from the pll driver. This simplify the
    driver and let us provide the clocks which exist between those
    dividera. Some device are actually using these clocks.
 3) The rates hard coded in parameter tables are remove. Instead, we
    only rely on the parent rate and the parameters to calculate the
    output rate, which is a lot better.

This series has been tested on the gxl libretech cc and axg s400.
I did not test it on meson8b yet.

Jerome Brunet (3):
  clk: meson: clk-pll: add enable bit
  clk: meson: clk-pll: remove od parameters
  clk: meson: clk-pll: drop hard-coded rates from pll tables

 drivers/clk/meson/axg.c     | 320 ++++++++++++++++------------
 drivers/clk/meson/axg.h     |   8 +-
 drivers/clk/meson/clk-pll.c | 156 +++++++++-----
 drivers/clk/meson/clkc.h    |  16 +-
 drivers/clk/meson/gxbb.c    | 504 ++++++++++++++++++++++----------------------
 drivers/clk/meson/gxbb.h    |  10 +-
 drivers/clk/meson/meson8b.c | 167 ++++++++-------
 drivers/clk/meson/meson8b.h |   5 +-
 8 files changed, 648 insertions(+), 538 deletions(-)

-- 
2.14.4


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

* [PATCH 1/3] clk: meson: clk-pll: add enable bit
  2018-07-17  9:56 [PATCH 0/3] clk: meson: clk-pll driver update Jerome Brunet
@ 2018-07-17  9:56 ` Jerome Brunet
  2018-07-19  8:33   ` Neil Armstrong
  2018-07-21 19:48   ` Martin Blumenstingl
  2018-07-17  9:56 ` [PATCH 2/3] clk: meson: clk-pll: remove od parameters Jerome Brunet
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 20+ messages in thread
From: Jerome Brunet @ 2018-07-17  9:56 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: Jerome Brunet, linux-amlogic, linux-clk, linux-kernel,
	Kevin Hilman, Martin Blumenstingl

Add the enable the bit of the pll clocks.
These pll clocks may be disabled but we can't model this as an external
gate since the pll needs to lock when enabled.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/axg.c     | 28 ++++++++++++++++++++++++---
 drivers/clk/meson/clk-pll.c | 47 ++++++++++++++++++++++++++++++++++++++++-----
 drivers/clk/meson/clkc.h    |  1 +
 drivers/clk/meson/gxbb.c    | 32 ++++++++++++++++++++++++++++--
 drivers/clk/meson/meson8b.c | 15 +++++++++++++++
 5 files changed, 113 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 00ce62ad6416..6d8976554656 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -24,6 +24,11 @@ static DEFINE_SPINLOCK(meson_clk_lock);
 
 static struct clk_regmap axg_fixed_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_MPLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_MPLL_CNTL,
 			.shift   = 0,
@@ -65,6 +70,11 @@ static struct clk_regmap axg_fixed_pll = {
 
 static struct clk_regmap axg_sys_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_SYS_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_SYS_PLL_CNTL,
 			.shift   = 0,
@@ -197,11 +207,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
 	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a59a288 },
 	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0xc000004d },
 	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
-	{ .reg = HHI_GP0_PLL_CNTL,	.def = 0x40010250 },
 };
 
 static struct clk_regmap axg_gp0_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_GP0_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_GP0_PLL_CNTL,
 			.shift   = 0,
@@ -250,11 +264,15 @@ static const struct reg_sequence axg_hifi_init_regs[] = {
 	{ .reg = HHI_HIFI_PLL_CNTL3,	.def = 0x0a6a3a88 },
 	{ .reg = HHI_HIFI_PLL_CNTL4,	.def = 0xc000004d },
 	{ .reg = HHI_HIFI_PLL_CNTL5,	.def = 0x00058000 },
-	{ .reg = HHI_HIFI_PLL_CNTL,	.def = 0x40010250 },
 };
 
 static struct clk_regmap axg_hifi_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_HIFI_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_HIFI_PLL_CNTL,
 			.shift   = 0,
@@ -637,7 +655,6 @@ static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
 };
 
 static const struct reg_sequence axg_pcie_init_regs[] = {
-	{ .reg = HHI_PCIE_PLL_CNTL,	.def = 0x400106c8 },
 	{ .reg = HHI_PCIE_PLL_CNTL1,	.def = 0x0084a2aa },
 	{ .reg = HHI_PCIE_PLL_CNTL2,	.def = 0xb75020be },
 	{ .reg = HHI_PCIE_PLL_CNTL3,	.def = 0x0a47488e },
@@ -648,6 +665,11 @@ static const struct reg_sequence axg_pcie_init_regs[] = {
 
 static struct clk_regmap axg_pcie_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_PCIE_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_PCIE_PLL_CNTL,
 			.shift   = 0,
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 3e04617ac47f..8aaefe67025f 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -185,12 +185,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
 	}
 }
 
+static int meson_clk_pll_enable(struct clk_hw *hw)
+{
+	struct clk_regmap *clk = to_clk_regmap(hw);
+	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+	/* Make sure the pll is in reset */
+	meson_parm_write(clk->map, &pll->rst, 1);
+
+	/* Enable the pll */
+	meson_parm_write(clk->map, &pll->en, 1);
+
+	/* Take the pll out reset */
+	meson_parm_write(clk->map, &pll->rst, 0);
+
+	if (meson_clk_pll_wait_lock(hw))
+		return -EIO;
+
+	return 0;
+}
+
+static void meson_clk_pll_disable(struct clk_hw *hw)
+{
+	struct clk_regmap *clk = to_clk_regmap(hw);
+	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
+
+	/* Put the pll is in reset */
+	meson_parm_write(clk->map, &pll->rst, 1);
+
+	/* Disable the pll */
+	meson_parm_write(clk->map, &pll->en, 0);
+}
+
 static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 				  unsigned long parent_rate)
 {
 	struct clk_regmap *clk = to_clk_regmap(hw);
 	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
 	const struct pll_rate_table *pllt;
+	unsigned int enabled;
 	unsigned long old_rate;
 	u16 frac = 0;
 
@@ -203,8 +236,9 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 	if (!pllt)
 		return -EINVAL;
 
-	/* Put the pll in reset to write the params */
-	meson_parm_write(clk->map, &pll->rst, 1);
+	enabled = meson_parm_read(clk->map, &pll->en);
+	if (enabled)
+		meson_clk_pll_disable(hw);
 
 	meson_parm_write(clk->map, &pll->n, pllt->n);
 	meson_parm_write(clk->map, &pll->m, pllt->m);
@@ -221,10 +255,11 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 		meson_parm_write(clk->map, &pll->frac, frac);
 	}
 
-	/* make sure the reset is cleared at this point */
-	meson_parm_write(clk->map, &pll->rst, 0);
+	/* If the pll is stopped, bail out now */
+	if (!enabled)
+		return 0;
 
-	if (meson_clk_pll_wait_lock(hw)) {
+	if (meson_clk_pll_enable(hw)) {
 		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
 			__func__, old_rate);
 		/*
@@ -244,6 +279,8 @@ const struct clk_ops meson_clk_pll_ops = {
 	.recalc_rate	= meson_clk_pll_recalc_rate,
 	.round_rate	= meson_clk_pll_round_rate,
 	.set_rate	= meson_clk_pll_set_rate,
+	.enable		= meson_clk_pll_enable,
+	.disable	= meson_clk_pll_disable
 };
 
 const struct clk_ops meson_clk_pll_ro_ops = {
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 24cec16b6038..c2ee37a78ceb 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -63,6 +63,7 @@ struct pll_rate_table {
 #define CLK_MESON_PLL_ROUND_CLOSEST	BIT(0)
 
 struct meson_clk_pll_data {
+	struct parm en;
 	struct parm m;
 	struct parm n;
 	struct parm frac;
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 86d3ae58e84c..5ed34566917c 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -177,6 +177,11 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
 
 static struct clk_regmap gxbb_fixed_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_MPLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_MPLL_CNTL,
 			.shift   = 0,
@@ -230,6 +235,11 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
 
 static struct clk_regmap gxbb_hdmi_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_HDMI_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_HDMI_PLL_CNTL,
 			.shift   = 0,
@@ -282,6 +292,11 @@ static struct clk_regmap gxbb_hdmi_pll = {
 
 static struct clk_regmap gxl_hdmi_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_HDMI_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_HDMI_PLL_CNTL,
 			.shift   = 0,
@@ -340,6 +355,11 @@ static struct clk_regmap gxl_hdmi_pll = {
 
 static struct clk_regmap gxbb_sys_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_SYS_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_SYS_PLL_CNTL,
 			.shift   = 0,
@@ -379,11 +399,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = {
 	{ .reg = HHI_GP0_PLL_CNTL2,	.def = 0x69c80000 },
 	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a5590c4 },
 	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0x0000500d },
-	{ .reg = HHI_GP0_PLL_CNTL,	.def = 0x4a000228 },
 };
 
 static struct clk_regmap gxbb_gp0_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_GP0_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_GP0_PLL_CNTL,
 			.shift   = 0,
@@ -428,11 +452,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
 	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a59a288 },
 	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0xc000004d },
 	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
-	{ .reg = HHI_GP0_PLL_CNTL,	.def = 0x40010250 },
 };
 
 static struct clk_regmap gxl_gp0_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_GP0_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_GP0_PLL_CNTL,
 			.shift   = 0,
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 7447d96a265f..fd4c414893f5 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -96,6 +96,11 @@ static struct clk_fixed_rate meson8b_xtal = {
 
 static struct clk_regmap meson8b_fixed_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_MPLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_MPLL_CNTL,
 			.shift   = 0,
@@ -138,6 +143,11 @@ static struct clk_regmap meson8b_fixed_pll = {
 
 static struct clk_regmap meson8b_vid_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_VID_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_VID_PLL_CNTL,
 			.shift   = 0,
@@ -175,6 +185,11 @@ static struct clk_regmap meson8b_vid_pll = {
 
 static struct clk_regmap meson8b_sys_pll = {
 	.data = &(struct meson_clk_pll_data){
+		.en = {
+			.reg_off = HHI_SYS_PLL_CNTL,
+			.shift   = 30,
+			.width   = 1,
+		},
 		.m = {
 			.reg_off = HHI_SYS_PLL_CNTL,
 			.shift   = 0,
-- 
2.14.4


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

* [PATCH 2/3] clk: meson: clk-pll: remove od parameters
  2018-07-17  9:56 [PATCH 0/3] clk: meson: clk-pll driver update Jerome Brunet
  2018-07-17  9:56 ` [PATCH 1/3] clk: meson: clk-pll: add enable bit Jerome Brunet
@ 2018-07-17  9:56 ` Jerome Brunet
  2018-07-19  8:42   ` Neil Armstrong
  2018-07-21 20:01   ` Martin Blumenstingl
  2018-07-17  9:56 ` [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables Jerome Brunet
  2018-07-21 20:17 ` [PATCH 0/3] clk: meson: clk-pll driver update Martin Blumenstingl
  3 siblings, 2 replies; 20+ messages in thread
From: Jerome Brunet @ 2018-07-17  9:56 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: Jerome Brunet, linux-amlogic, linux-clk, linux-kernel,
	Kevin Hilman, Martin Blumenstingl

Remove od parameters from pll clocks and add post dividers clocks
instead. Some clock, especially the one which feature several ods,
may provide output between those ods. Also, some drivers, such
as the hdmi driver, may require a more detailed control of the
clock dividers, compared to what CCF would perform automatically.

One added benefit of removing ods is that it also greatly reduce the
size of the rate parameter tables.

In the future, we could possibly take the predivider 'n' out of this
driver as well. To do so, we will need to understand the constraints
for the PLL to lock and whether or not it depends on the input clock
rate.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/axg.c     | 279 ++++++++++++++------------
 drivers/clk/meson/axg.h     |   8 +-
 drivers/clk/meson/clk-pll.c |  40 ++--
 drivers/clk/meson/clkc.h    |   9 +-
 drivers/clk/meson/gxbb.c    | 474 +++++++++++++++++++++-----------------------
 drivers/clk/meson/gxbb.h    |  10 +-
 drivers/clk/meson/meson8b.c | 148 +++++++-------
 drivers/clk/meson/meson8b.h |   5 +-
 8 files changed, 480 insertions(+), 493 deletions(-)

diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 6d8976554656..572358062459 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -22,7 +22,7 @@
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
-static struct clk_regmap axg_fixed_pll = {
+static struct clk_regmap axg_fixed_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_MPLL_CNTL,
@@ -39,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_MPLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.frac = {
 			.reg_off = HHI_MPLL_CNTL2,
 			.shift   = 0,
@@ -61,14 +56,29 @@ static struct clk_regmap axg_fixed_pll = {
 		},
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "fixed_pll",
+		.name = "fixed_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
 	},
 };
 
-static struct clk_regmap axg_sys_pll = {
+static struct clk_regmap axg_fixed_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_MPLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fixed_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "fixed_pll_dco" },
+		.num_parents = 1,
+	},
+};
+
+static struct clk_regmap axg_sys_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_SYS_PLL_CNTL,
@@ -85,11 +95,6 @@ static struct clk_regmap axg_sys_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_SYS_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.l = {
 			.reg_off = HHI_SYS_PLL_CNTL,
 			.shift   = 31,
@@ -102,7 +107,7 @@ static struct clk_regmap axg_sys_pll = {
 		},
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "sys_pll",
+		.name = "sys_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -110,94 +115,51 @@ static struct clk_regmap axg_sys_pll = {
 	},
 };
 
+static struct clk_regmap axg_sys_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_SYS_PLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "sys_pll_dco" },
+		.num_parents = 1,
+	},
+};
+
 static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
-	PLL_RATE(240000000, 40, 1, 2),
-	PLL_RATE(246000000, 41, 1, 2),
-	PLL_RATE(252000000, 42, 1, 2),
-	PLL_RATE(258000000, 43, 1, 2),
-	PLL_RATE(264000000, 44, 1, 2),
-	PLL_RATE(270000000, 45, 1, 2),
-	PLL_RATE(276000000, 46, 1, 2),
-	PLL_RATE(282000000, 47, 1, 2),
-	PLL_RATE(288000000, 48, 1, 2),
-	PLL_RATE(294000000, 49, 1, 2),
-	PLL_RATE(300000000, 50, 1, 2),
-	PLL_RATE(306000000, 51, 1, 2),
-	PLL_RATE(312000000, 52, 1, 2),
-	PLL_RATE(318000000, 53, 1, 2),
-	PLL_RATE(324000000, 54, 1, 2),
-	PLL_RATE(330000000, 55, 1, 2),
-	PLL_RATE(336000000, 56, 1, 2),
-	PLL_RATE(342000000, 57, 1, 2),
-	PLL_RATE(348000000, 58, 1, 2),
-	PLL_RATE(354000000, 59, 1, 2),
-	PLL_RATE(360000000, 60, 1, 2),
-	PLL_RATE(366000000, 61, 1, 2),
-	PLL_RATE(372000000, 62, 1, 2),
-	PLL_RATE(378000000, 63, 1, 2),
-	PLL_RATE(384000000, 64, 1, 2),
-	PLL_RATE(390000000, 65, 1, 3),
-	PLL_RATE(396000000, 66, 1, 3),
-	PLL_RATE(402000000, 67, 1, 3),
-	PLL_RATE(408000000, 68, 1, 3),
-	PLL_RATE(480000000, 40, 1, 1),
-	PLL_RATE(492000000, 41, 1, 1),
-	PLL_RATE(504000000, 42, 1, 1),
-	PLL_RATE(516000000, 43, 1, 1),
-	PLL_RATE(528000000, 44, 1, 1),
-	PLL_RATE(540000000, 45, 1, 1),
-	PLL_RATE(552000000, 46, 1, 1),
-	PLL_RATE(564000000, 47, 1, 1),
-	PLL_RATE(576000000, 48, 1, 1),
-	PLL_RATE(588000000, 49, 1, 1),
-	PLL_RATE(600000000, 50, 1, 1),
-	PLL_RATE(612000000, 51, 1, 1),
-	PLL_RATE(624000000, 52, 1, 1),
-	PLL_RATE(636000000, 53, 1, 1),
-	PLL_RATE(648000000, 54, 1, 1),
-	PLL_RATE(660000000, 55, 1, 1),
-	PLL_RATE(672000000, 56, 1, 1),
-	PLL_RATE(684000000, 57, 1, 1),
-	PLL_RATE(696000000, 58, 1, 1),
-	PLL_RATE(708000000, 59, 1, 1),
-	PLL_RATE(720000000, 60, 1, 1),
-	PLL_RATE(732000000, 61, 1, 1),
-	PLL_RATE(744000000, 62, 1, 1),
-	PLL_RATE(756000000, 63, 1, 1),
-	PLL_RATE(768000000, 64, 1, 1),
-	PLL_RATE(780000000, 65, 1, 1),
-	PLL_RATE(792000000, 66, 1, 1),
-	PLL_RATE(804000000, 67, 1, 1),
-	PLL_RATE(816000000, 68, 1, 1),
-	PLL_RATE(960000000, 40, 1, 0),
-	PLL_RATE(984000000, 41, 1, 0),
-	PLL_RATE(1008000000, 42, 1, 0),
-	PLL_RATE(1032000000, 43, 1, 0),
-	PLL_RATE(1056000000, 44, 1, 0),
-	PLL_RATE(1080000000, 45, 1, 0),
-	PLL_RATE(1104000000, 46, 1, 0),
-	PLL_RATE(1128000000, 47, 1, 0),
-	PLL_RATE(1152000000, 48, 1, 0),
-	PLL_RATE(1176000000, 49, 1, 0),
-	PLL_RATE(1200000000, 50, 1, 0),
-	PLL_RATE(1224000000, 51, 1, 0),
-	PLL_RATE(1248000000, 52, 1, 0),
-	PLL_RATE(1272000000, 53, 1, 0),
-	PLL_RATE(1296000000, 54, 1, 0),
-	PLL_RATE(1320000000, 55, 1, 0),
-	PLL_RATE(1344000000, 56, 1, 0),
-	PLL_RATE(1368000000, 57, 1, 0),
-	PLL_RATE(1392000000, 58, 1, 0),
-	PLL_RATE(1416000000, 59, 1, 0),
-	PLL_RATE(1440000000, 60, 1, 0),
-	PLL_RATE(1464000000, 61, 1, 0),
-	PLL_RATE(1488000000, 62, 1, 0),
-	PLL_RATE(1512000000, 63, 1, 0),
-	PLL_RATE(1536000000, 64, 1, 0),
-	PLL_RATE(1560000000, 65, 1, 0),
-	PLL_RATE(1584000000, 66, 1, 0),
-	PLL_RATE(1608000000, 67, 1, 0),
-	PLL_RATE(1632000000, 68, 1, 0),
+	PLL_RATE(960000000, 40, 1),
+	PLL_RATE(984000000, 41, 1),
+	PLL_RATE(1008000000, 42, 1),
+	PLL_RATE(1032000000, 43, 1),
+	PLL_RATE(1056000000, 44, 1),
+	PLL_RATE(1080000000, 45, 1),
+	PLL_RATE(1104000000, 46, 1),
+	PLL_RATE(1128000000, 47, 1),
+	PLL_RATE(1152000000, 48, 1),
+	PLL_RATE(1176000000, 49, 1),
+	PLL_RATE(1200000000, 50, 1),
+	PLL_RATE(1224000000, 51, 1),
+	PLL_RATE(1248000000, 52, 1),
+	PLL_RATE(1272000000, 53, 1),
+	PLL_RATE(1296000000, 54, 1),
+	PLL_RATE(1320000000, 55, 1),
+	PLL_RATE(1344000000, 56, 1),
+	PLL_RATE(1368000000, 57, 1),
+	PLL_RATE(1392000000, 58, 1),
+	PLL_RATE(1416000000, 59, 1),
+	PLL_RATE(1440000000, 60, 1),
+	PLL_RATE(1464000000, 61, 1),
+	PLL_RATE(1488000000, 62, 1),
+	PLL_RATE(1512000000, 63, 1),
+	PLL_RATE(1536000000, 64, 1),
+	PLL_RATE(1560000000, 65, 1),
+	PLL_RATE(1584000000, 66, 1),
+	PLL_RATE(1608000000, 67, 1),
+	PLL_RATE(1632000000, 68, 1),
 	{ /* sentinel */ },
 };
 
@@ -209,7 +171,7 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
 	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
 };
 
-static struct clk_regmap axg_gp0_pll = {
+static struct clk_regmap axg_gp0_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_GP0_PLL_CNTL,
@@ -226,11 +188,6 @@ static struct clk_regmap axg_gp0_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_GP0_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.frac = {
 			.reg_off = HHI_GP0_PLL_CNTL1,
 			.shift   = 0,
@@ -251,13 +208,29 @@ static struct clk_regmap axg_gp0_pll = {
 		.init_count = ARRAY_SIZE(axg_gp0_init_regs),
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "gp0_pll",
+		.name = "gp0_pll_dco",
 		.ops = &meson_clk_pll_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
 	},
 };
 
+static struct clk_regmap axg_gp0_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_GP0_PLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "gp0_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_names = (const char *[]){ "gp0_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
 static const struct reg_sequence axg_hifi_init_regs[] = {
 	{ .reg = HHI_HIFI_PLL_CNTL1,	.def = 0xc084b000 },
 	{ .reg = HHI_HIFI_PLL_CNTL2,	.def = 0xb75020be },
@@ -266,7 +239,7 @@ static const struct reg_sequence axg_hifi_init_regs[] = {
 	{ .reg = HHI_HIFI_PLL_CNTL5,	.def = 0x00058000 },
 };
 
-static struct clk_regmap axg_hifi_pll = {
+static struct clk_regmap axg_hifi_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_HIFI_PLL_CNTL,
@@ -283,11 +256,6 @@ static struct clk_regmap axg_hifi_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_HIFI_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.frac = {
 			.reg_off = HHI_HIFI_PLL_CNTL5,
 			.shift   = 0,
@@ -309,13 +277,29 @@ static struct clk_regmap axg_hifi_pll = {
 		.flags = CLK_MESON_PLL_ROUND_CLOSEST,
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "hifi_pll",
+		.name = "hifi_pll_dco",
 		.ops = &meson_clk_pll_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
 	},
 };
 
+static struct clk_regmap axg_hifi_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_HIFI_PLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hifi_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_names = (const char *[]){ "hifi_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
 static struct clk_fixed_factor axg_fclk_div2_div = {
 	.mult = 1,
 	.div = 2,
@@ -645,11 +629,9 @@ static struct clk_regmap axg_mpll3 = {
 
 static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
 	{
-		.rate	= 100000000,
+		.rate	= 1600000000,
 		.m	= 200,
 		.n	= 3,
-		.od	= 1,
-		.od2	= 3,
 	},
 	{ /* sentinel */ },
 };
@@ -661,9 +643,10 @@ static const struct reg_sequence axg_pcie_init_regs[] = {
 	{ .reg = HHI_PCIE_PLL_CNTL4,	.def = 0xc000004d },
 	{ .reg = HHI_PCIE_PLL_CNTL5,	.def = 0x00078000 },
 	{ .reg = HHI_PCIE_PLL_CNTL6,	.def = 0x002323c6 },
+	{ .reg = HHI_PCIE_PLL_CNTL,     .def = 0x400106c8 },
 };
 
-static struct clk_regmap axg_pcie_pll = {
+static struct clk_regmap axg_pcie_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_PCIE_PLL_CNTL,
@@ -680,16 +663,6 @@ static struct clk_regmap axg_pcie_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_PCIE_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
-		.od2 = {
-			.reg_off = HHI_PCIE_PLL_CNTL6,
-			.shift   = 6,
-			.width   = 2,
-		},
 		.frac = {
 			.reg_off = HHI_PCIE_PLL_CNTL1,
 			.shift   = 0,
@@ -710,13 +683,45 @@ static struct clk_regmap axg_pcie_pll = {
 		.init_count = ARRAY_SIZE(axg_pcie_init_regs),
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "pcie_pll",
+		.name = "pcie_pll_dco",
 		.ops = &meson_clk_pll_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
 	},
 };
 
+static struct clk_regmap axg_pcie_pll_od = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_PCIE_PLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pcie_pll_od",
+		.ops = &clk_regmap_divider_ops,
+		.parent_names = (const char *[]){ "pcie_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
+static struct clk_regmap axg_pcie_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_PCIE_PLL_CNTL6,
+		.shift = 6,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "pcie_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_names = (const char *[]){ "pcie_pll_od" },
+		.num_parents = 1,
+		.flags = CLK_SET_RATE_PARENT,
+	},
+};
+
 static struct clk_regmap axg_pcie_mux = {
 	.data = &(struct clk_regmap_mux_data){
 		.offset = HHI_PCIE_PLL_CNTL6,
@@ -1129,6 +1134,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
 		[CLKID_GEN_CLK_SEL]		= &axg_gen_clk_sel.hw,
 		[CLKID_GEN_CLK_DIV]		= &axg_gen_clk_div.hw,
 		[CLKID_GEN_CLK]			= &axg_gen_clk.hw,
+		[CLKID_SYS_PLL_DCO]		= &axg_sys_pll_dco.hw,
+		[CLKID_FIXED_PLL_DCO]		= &axg_fixed_pll_dco.hw,
+		[CLKID_GP0_PLL_DCO]		= &axg_gp0_pll_dco.hw,
+		[CLKID_HIFI_PLL_DCO]		= &axg_hifi_pll_dco.hw,
+		[CLKID_PCIE_PLL_DCO]		= &axg_pcie_pll_dco.hw,
+		[CLKID_PCIE_PLL_OD]		= &axg_pcie_pll_od.hw,
 		[NR_CLKS]			= NULL,
 	},
 	.num = NR_CLKS,
@@ -1207,6 +1218,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
 	&axg_fclk_div4,
 	&axg_fclk_div5,
 	&axg_fclk_div7,
+	&axg_pcie_pll_dco,
+	&axg_pcie_pll_od,
 	&axg_pcie_pll,
 	&axg_pcie_mux,
 	&axg_pcie_ref,
@@ -1216,6 +1229,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
 	&axg_gen_clk_sel,
 	&axg_gen_clk_div,
 	&axg_gen_clk,
+	&axg_fixed_pll_dco,
+	&axg_sys_pll_dco,
+	&axg_gp0_pll_dco,
+	&axg_hifi_pll_dco,
+	&axg_pcie_pll_dco,
+	&axg_pcie_pll_od,
 };
 
 static const struct of_device_id clkc_match_table[] = {
diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
index 1d04144a1b2c..0431dabac629 100644
--- a/drivers/clk/meson/axg.h
+++ b/drivers/clk/meson/axg.h
@@ -133,8 +133,14 @@
 #define CLKID_PCIE_REF				78
 #define CLKID_GEN_CLK_SEL			82
 #define CLKID_GEN_CLK_DIV			83
+#define CLKID_SYS_PLL_DCO			85
+#define CLKID_FIXED_PLL_DCO			86
+#define CLKID_GP0_PLL_DCO			87
+#define CLKID_HIFI_PLL_DCO			88
+#define CLKID_PCIE_PLL_DCO			89
+#define CLKID_PCIE_PLL_OD			90
 
-#define NR_CLKS					85
+#define NR_CLKS					91
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/axg-clkc.h>
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 8aaefe67025f..348a866f09eb 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -11,15 +11,19 @@
  * In the most basic form, a Meson PLL is composed as follows:
  *
  *                     PLL
- *      +------------------------------+
- *      |                              |
- * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
- *      |         ^        ^           |
- *      +------------------------------+
- *                |        |
- *               FREF     VCO
+ *        +--------------------------------+
+ *        |                                |
+ *        |             +--+               |
+ *  in >>-----[ /N ]--->|  |      +-----+  |
+ *        |             |  |------| DCO |---->> out
+ *        |  +--------->|  |      +--v--+  |
+ *        |  |          +--+         |     |
+ *        |  |                       |     |
+ *        |  +--[ *(M + (F/Fmax) ]<--+     |
+ *        |                                |
+ *        +--------------------------------+
  *
- * out = in * (m + frac / frac_max) / (n << sum(ods))
+ * out = in * (m + frac / frac_max) / n
  */
 
 #include <linux/clk-provider.h>
@@ -46,7 +50,6 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
 					  struct meson_clk_pll_data *pll)
 {
 	u64 rate = (u64)parent_rate * pllt->m;
-	unsigned int od = pllt->od + pllt->od2 + pllt->od3;
 
 	if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
 		u64 frac_rate = (u64)parent_rate * frac;
@@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
 					 (1 << pll->frac.width));
 	}
 
-	return DIV_ROUND_UP_ULL(rate, pllt->n << od);
+	return DIV_ROUND_UP_ULL(rate, pllt->n);
 }
 
 static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
@@ -68,15 +71,6 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
 
 	pllt.n = meson_parm_read(clk->map, &pll->n);
 	pllt.m = meson_parm_read(clk->map, &pll->m);
-	pllt.od = meson_parm_read(clk->map, &pll->od);
-
-	pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
-		meson_parm_read(clk->map, &pll->od2) :
-		0;
-
-	pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
-		meson_parm_read(clk->map, &pll->od3) :
-		0;
 
 	frac = MESON_PARM_APPLICABLE(&pll->frac) ?
 		meson_parm_read(clk->map, &pll->frac) :
@@ -93,8 +87,6 @@ static u16 __pll_params_with_frac(unsigned long rate,
 	u16 frac_max = (1 << pll->frac.width);
 	u64 val = (u64)rate * pllt->n;
 
-	val <<= pllt->od + pllt->od2 + pllt->od3;
-
 	if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
 		val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
 	else
@@ -242,13 +234,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	meson_parm_write(clk->map, &pll->n, pllt->n);
 	meson_parm_write(clk->map, &pll->m, pllt->m);
-	meson_parm_write(clk->map, &pll->od, pllt->od);
-
-	if (MESON_PARM_APPLICABLE(&pll->od2))
-		meson_parm_write(clk->map, &pll->od2, pllt->od2);
 
-	if (MESON_PARM_APPLICABLE(&pll->od3))
-		meson_parm_write(clk->map, &pll->od3, pllt->od3);
 
 	if (MESON_PARM_APPLICABLE(&pll->frac)) {
 		frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index c2ee37a78ceb..a2245e857f70 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -47,17 +47,13 @@ struct pll_rate_table {
 	unsigned long	rate;
 	u16		m;
 	u16		n;
-	u16		od;
-	u16		od2;
-	u16		od3;
 };
 
-#define PLL_RATE(_r, _m, _n, _od)					\
+#define PLL_RATE(_r, _m, _n)						\
 	{								\
 		.rate		= (_r),					\
 		.m		= (_m),					\
 		.n		= (_n),					\
-		.od		= (_od),				\
 	}
 
 #define CLK_MESON_PLL_ROUND_CLOSEST	BIT(0)
@@ -67,9 +63,6 @@ struct meson_clk_pll_data {
 	struct parm m;
 	struct parm n;
 	struct parm frac;
-	struct parm od;
-	struct parm od2;
-	struct parm od3;
 	struct parm l;
 	struct parm rst;
 	const struct reg_sequence *init_regs;
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 5ed34566917c..e2d94498f098 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -19,163 +19,70 @@
 static DEFINE_SPINLOCK(meson_clk_lock);
 
 static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
-	PLL_RATE(96000000, 32, 1, 3),
-	PLL_RATE(99000000, 33, 1, 3),
-	PLL_RATE(102000000, 34, 1, 3),
-	PLL_RATE(105000000, 35, 1, 3),
-	PLL_RATE(108000000, 36, 1, 3),
-	PLL_RATE(111000000, 37, 1, 3),
-	PLL_RATE(114000000, 38, 1, 3),
-	PLL_RATE(117000000, 39, 1, 3),
-	PLL_RATE(120000000, 40, 1, 3),
-	PLL_RATE(123000000, 41, 1, 3),
-	PLL_RATE(126000000, 42, 1, 3),
-	PLL_RATE(129000000, 43, 1, 3),
-	PLL_RATE(132000000, 44, 1, 3),
-	PLL_RATE(135000000, 45, 1, 3),
-	PLL_RATE(138000000, 46, 1, 3),
-	PLL_RATE(141000000, 47, 1, 3),
-	PLL_RATE(144000000, 48, 1, 3),
-	PLL_RATE(147000000, 49, 1, 3),
-	PLL_RATE(150000000, 50, 1, 3),
-	PLL_RATE(153000000, 51, 1, 3),
-	PLL_RATE(156000000, 52, 1, 3),
-	PLL_RATE(159000000, 53, 1, 3),
-	PLL_RATE(162000000, 54, 1, 3),
-	PLL_RATE(165000000, 55, 1, 3),
-	PLL_RATE(168000000, 56, 1, 3),
-	PLL_RATE(171000000, 57, 1, 3),
-	PLL_RATE(174000000, 58, 1, 3),
-	PLL_RATE(177000000, 59, 1, 3),
-	PLL_RATE(180000000, 60, 1, 3),
-	PLL_RATE(183000000, 61, 1, 3),
-	PLL_RATE(186000000, 62, 1, 3),
-	PLL_RATE(192000000, 32, 1, 2),
-	PLL_RATE(198000000, 33, 1, 2),
-	PLL_RATE(204000000, 34, 1, 2),
-	PLL_RATE(210000000, 35, 1, 2),
-	PLL_RATE(216000000, 36, 1, 2),
-	PLL_RATE(222000000, 37, 1, 2),
-	PLL_RATE(228000000, 38, 1, 2),
-	PLL_RATE(234000000, 39, 1, 2),
-	PLL_RATE(240000000, 40, 1, 2),
-	PLL_RATE(246000000, 41, 1, 2),
-	PLL_RATE(252000000, 42, 1, 2),
-	PLL_RATE(258000000, 43, 1, 2),
-	PLL_RATE(264000000, 44, 1, 2),
-	PLL_RATE(270000000, 45, 1, 2),
-	PLL_RATE(276000000, 46, 1, 2),
-	PLL_RATE(282000000, 47, 1, 2),
-	PLL_RATE(288000000, 48, 1, 2),
-	PLL_RATE(294000000, 49, 1, 2),
-	PLL_RATE(300000000, 50, 1, 2),
-	PLL_RATE(306000000, 51, 1, 2),
-	PLL_RATE(312000000, 52, 1, 2),
-	PLL_RATE(318000000, 53, 1, 2),
-	PLL_RATE(324000000, 54, 1, 2),
-	PLL_RATE(330000000, 55, 1, 2),
-	PLL_RATE(336000000, 56, 1, 2),
-	PLL_RATE(342000000, 57, 1, 2),
-	PLL_RATE(348000000, 58, 1, 2),
-	PLL_RATE(354000000, 59, 1, 2),
-	PLL_RATE(360000000, 60, 1, 2),
-	PLL_RATE(366000000, 61, 1, 2),
-	PLL_RATE(372000000, 62, 1, 2),
-	PLL_RATE(384000000, 32, 1, 1),
-	PLL_RATE(396000000, 33, 1, 1),
-	PLL_RATE(408000000, 34, 1, 1),
-	PLL_RATE(420000000, 35, 1, 1),
-	PLL_RATE(432000000, 36, 1, 1),
-	PLL_RATE(444000000, 37, 1, 1),
-	PLL_RATE(456000000, 38, 1, 1),
-	PLL_RATE(468000000, 39, 1, 1),
-	PLL_RATE(480000000, 40, 1, 1),
-	PLL_RATE(492000000, 41, 1, 1),
-	PLL_RATE(504000000, 42, 1, 1),
-	PLL_RATE(516000000, 43, 1, 1),
-	PLL_RATE(528000000, 44, 1, 1),
-	PLL_RATE(540000000, 45, 1, 1),
-	PLL_RATE(552000000, 46, 1, 1),
-	PLL_RATE(564000000, 47, 1, 1),
-	PLL_RATE(576000000, 48, 1, 1),
-	PLL_RATE(588000000, 49, 1, 1),
-	PLL_RATE(600000000, 50, 1, 1),
-	PLL_RATE(612000000, 51, 1, 1),
-	PLL_RATE(624000000, 52, 1, 1),
-	PLL_RATE(636000000, 53, 1, 1),
-	PLL_RATE(648000000, 54, 1, 1),
-	PLL_RATE(660000000, 55, 1, 1),
-	PLL_RATE(672000000, 56, 1, 1),
-	PLL_RATE(684000000, 57, 1, 1),
-	PLL_RATE(696000000, 58, 1, 1),
-	PLL_RATE(708000000, 59, 1, 1),
-	PLL_RATE(720000000, 60, 1, 1),
-	PLL_RATE(732000000, 61, 1, 1),
-	PLL_RATE(744000000, 62, 1, 1),
-	PLL_RATE(768000000, 32, 1, 0),
-	PLL_RATE(792000000, 33, 1, 0),
-	PLL_RATE(816000000, 34, 1, 0),
-	PLL_RATE(840000000, 35, 1, 0),
-	PLL_RATE(864000000, 36, 1, 0),
-	PLL_RATE(888000000, 37, 1, 0),
-	PLL_RATE(912000000, 38, 1, 0),
-	PLL_RATE(936000000, 39, 1, 0),
-	PLL_RATE(960000000, 40, 1, 0),
-	PLL_RATE(984000000, 41, 1, 0),
-	PLL_RATE(1008000000, 42, 1, 0),
-	PLL_RATE(1032000000, 43, 1, 0),
-	PLL_RATE(1056000000, 44, 1, 0),
-	PLL_RATE(1080000000, 45, 1, 0),
-	PLL_RATE(1104000000, 46, 1, 0),
-	PLL_RATE(1128000000, 47, 1, 0),
-	PLL_RATE(1152000000, 48, 1, 0),
-	PLL_RATE(1176000000, 49, 1, 0),
-	PLL_RATE(1200000000, 50, 1, 0),
-	PLL_RATE(1224000000, 51, 1, 0),
-	PLL_RATE(1248000000, 52, 1, 0),
-	PLL_RATE(1272000000, 53, 1, 0),
-	PLL_RATE(1296000000, 54, 1, 0),
-	PLL_RATE(1320000000, 55, 1, 0),
-	PLL_RATE(1344000000, 56, 1, 0),
-	PLL_RATE(1368000000, 57, 1, 0),
-	PLL_RATE(1392000000, 58, 1, 0),
-	PLL_RATE(1416000000, 59, 1, 0),
-	PLL_RATE(1440000000, 60, 1, 0),
-	PLL_RATE(1464000000, 61, 1, 0),
-	PLL_RATE(1488000000, 62, 1, 0),
+	PLL_RATE(768000000, 32, 1),
+	PLL_RATE(792000000, 33, 1),
+	PLL_RATE(816000000, 34, 1),
+	PLL_RATE(840000000, 35, 1),
+	PLL_RATE(864000000, 36, 1),
+	PLL_RATE(888000000, 37, 1),
+	PLL_RATE(912000000, 38, 1),
+	PLL_RATE(936000000, 39, 1),
+	PLL_RATE(960000000, 40, 1),
+	PLL_RATE(984000000, 41, 1),
+	PLL_RATE(1008000000, 42, 1),
+	PLL_RATE(1032000000, 43, 1),
+	PLL_RATE(1056000000, 44, 1),
+	PLL_RATE(1080000000, 45, 1),
+	PLL_RATE(1104000000, 46, 1),
+	PLL_RATE(1128000000, 47, 1),
+	PLL_RATE(1152000000, 48, 1),
+	PLL_RATE(1176000000, 49, 1),
+	PLL_RATE(1200000000, 50, 1),
+	PLL_RATE(1224000000, 51, 1),
+	PLL_RATE(1248000000, 52, 1),
+	PLL_RATE(1272000000, 53, 1),
+	PLL_RATE(1296000000, 54, 1),
+	PLL_RATE(1320000000, 55, 1),
+	PLL_RATE(1344000000, 56, 1),
+	PLL_RATE(1368000000, 57, 1),
+	PLL_RATE(1392000000, 58, 1),
+	PLL_RATE(1416000000, 59, 1),
+	PLL_RATE(1440000000, 60, 1),
+	PLL_RATE(1464000000, 61, 1),
+	PLL_RATE(1488000000, 62, 1),
 	{ /* sentinel */ },
 };
 
 static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
-	PLL_RATE(504000000, 42, 1, 1),
-	PLL_RATE(516000000, 43, 1, 1),
-	PLL_RATE(528000000, 44, 1, 1),
-	PLL_RATE(540000000, 45, 1, 1),
-	PLL_RATE(552000000, 46, 1, 1),
-	PLL_RATE(564000000, 47, 1, 1),
-	PLL_RATE(576000000, 48, 1, 1),
-	PLL_RATE(588000000, 49, 1, 1),
-	PLL_RATE(600000000, 50, 1, 1),
-	PLL_RATE(612000000, 51, 1, 1),
-	PLL_RATE(624000000, 52, 1, 1),
-	PLL_RATE(636000000, 53, 1, 1),
-	PLL_RATE(648000000, 54, 1, 1),
-	PLL_RATE(660000000, 55, 1, 1),
-	PLL_RATE(672000000, 56, 1, 1),
-	PLL_RATE(684000000, 57, 1, 1),
-	PLL_RATE(696000000, 58, 1, 1),
-	PLL_RATE(708000000, 59, 1, 1),
-	PLL_RATE(720000000, 60, 1, 1),
-	PLL_RATE(732000000, 61, 1, 1),
-	PLL_RATE(744000000, 62, 1, 1),
-	PLL_RATE(756000000, 63, 1, 1),
-	PLL_RATE(768000000, 64, 1, 1),
-	PLL_RATE(780000000, 65, 1, 1),
-	PLL_RATE(792000000, 66, 1, 1),
+	PLL_RATE(1008000000, 42, 1),
+	PLL_RATE(1032000000, 43, 1),
+	PLL_RATE(1056000000, 44, 1),
+	PLL_RATE(1080000000, 45, 1),
+	PLL_RATE(1104000000, 46, 1),
+	PLL_RATE(1128000000, 47, 1),
+	PLL_RATE(1152000000, 48, 1),
+	PLL_RATE(1176000000, 49, 1),
+	PLL_RATE(1200000000, 50, 1),
+	PLL_RATE(1224000000, 51, 1),
+	PLL_RATE(1248000000, 52, 1),
+	PLL_RATE(1272000000, 53, 1),
+	PLL_RATE(1296000000, 54, 1),
+	PLL_RATE(1320000000, 55, 1),
+	PLL_RATE(1344000000, 56, 1),
+	PLL_RATE(1368000000, 57, 1),
+	PLL_RATE(1392000000, 58, 1),
+	PLL_RATE(1416000000, 59, 1),
+	PLL_RATE(1440000000, 60, 1),
+	PLL_RATE(1464000000, 61, 1),
+	PLL_RATE(1488000000, 62, 1),
+	PLL_RATE(1512000000, 63, 1),
+	PLL_RATE(1536000000, 64, 1),
+	PLL_RATE(1560000000, 65, 1),
+	PLL_RATE(1584000000, 66, 1),
 	{ /* sentinel */ },
 };
 
-static struct clk_regmap gxbb_fixed_pll = {
+static struct clk_regmap gxbb_fixed_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_MPLL_CNTL,
@@ -192,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_MPLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.frac = {
 			.reg_off = HHI_MPLL_CNTL2,
 			.shift   = 0,
@@ -214,7 +116,7 @@ static struct clk_regmap gxbb_fixed_pll = {
 		},
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "fixed_pll",
+		.name = "fixed_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -222,6 +124,21 @@ static struct clk_regmap gxbb_fixed_pll = {
 	},
 };
 
+static struct clk_regmap gxbb_fixed_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_MPLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fixed_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "fixed_pll_dco" },
+		.num_parents = 1,
+	},
+};
+
 static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
 	.mult = 2,
 	.div = 1,
@@ -233,7 +150,7 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
 	},
 };
 
-static struct clk_regmap gxbb_hdmi_pll = {
+static struct clk_regmap gxbb_hdmi_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_HDMI_PLL_CNTL,
@@ -255,21 +172,6 @@ static struct clk_regmap gxbb_hdmi_pll = {
 			.shift   = 0,
 			.width   = 12,
 		},
-		.od = {
-			.reg_off = HHI_HDMI_PLL_CNTL2,
-			.shift   = 16,
-			.width   = 2,
-		},
-		.od2 = {
-			.reg_off = HHI_HDMI_PLL_CNTL2,
-			.shift   = 22,
-			.width   = 2,
-		},
-		.od3 = {
-			.reg_off = HHI_HDMI_PLL_CNTL2,
-			.shift   = 18,
-			.width   = 2,
-		},
 		.l = {
 			.reg_off = HHI_HDMI_PLL_CNTL,
 			.shift   = 31,
@@ -282,7 +184,7 @@ static struct clk_regmap gxbb_hdmi_pll = {
 		},
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "hdmi_pll",
+		.name = "hdmi_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
 		.num_parents = 1,
@@ -290,70 +192,103 @@ static struct clk_regmap gxbb_hdmi_pll = {
 	},
 };
 
+static struct clk_regmap gxbb_hdmi_pll_od = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_HDMI_PLL_CNTL2,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll_od",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "hdmi_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
+static struct clk_regmap gxbb_hdmi_pll_od2 = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_HDMI_PLL_CNTL2,
+		.shift = 22,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll_od2",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "hdmi_pll_od" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
+static struct clk_regmap gxbb_hdmi_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_HDMI_PLL_CNTL2,
+		.shift = 18,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "hdmi_pll_od2" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
+static struct clk_regmap gxl_hdmi_pll_od = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_HDMI_PLL_CNTL + 8,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll_od",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "hdmi_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
+static struct clk_regmap gxl_hdmi_pll_od2 = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_HDMI_PLL_CNTL + 8,
+		.shift = 22,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_pll_od2",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "hdmi_pll_od" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
 static struct clk_regmap gxl_hdmi_pll = {
-	.data = &(struct meson_clk_pll_data){
-		.en = {
-			.reg_off = HHI_HDMI_PLL_CNTL,
-			.shift   = 30,
-			.width   = 1,
-		},
-		.m = {
-			.reg_off = HHI_HDMI_PLL_CNTL,
-			.shift   = 0,
-			.width   = 9,
-		},
-		.n = {
-			.reg_off = HHI_HDMI_PLL_CNTL,
-			.shift   = 9,
-			.width   = 5,
-		},
-		.frac = {
-			/*
-			 * On gxl, there is a register shift due to
-			 * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
-			 * so we compute the register offset based on the PLL
-			 * base to get it right
-			 */
-			.reg_off = HHI_HDMI_PLL_CNTL + 4,
-			.shift   = 0,
-			.width   = 12,
-		},
-		.od = {
-			.reg_off = HHI_HDMI_PLL_CNTL + 8,
-			.shift   = 21,
-			.width   = 2,
-		},
-		.od2 = {
-			.reg_off = HHI_HDMI_PLL_CNTL + 8,
-			.shift   = 23,
-			.width   = 2,
-		},
-		.od3 = {
-			.reg_off = HHI_HDMI_PLL_CNTL + 8,
-			.shift   = 19,
-			.width   = 2,
-		},
-		.l = {
-			.reg_off = HHI_HDMI_PLL_CNTL,
-			.shift   = 31,
-			.width   = 1,
-		},
-		.rst = {
-			.reg_off = HHI_HDMI_PLL_CNTL,
-			.shift   = 29,
-			.width   = 1,
-		},
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_HDMI_PLL_CNTL + 8,
+		.shift = 18,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
 	},
 	.hw.init = &(struct clk_init_data){
 		.name = "hdmi_pll",
-		.ops = &meson_clk_pll_ro_ops,
-		.parent_names = (const char *[]){ "xtal" },
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "hdmi_pll_od2" },
 		.num_parents = 1,
 		.flags = CLK_GET_RATE_NOCACHE,
 	},
 };
 
-static struct clk_regmap gxbb_sys_pll = {
+static struct clk_regmap gxbb_sys_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_SYS_PLL_CNTL,
@@ -370,11 +305,6 @@ static struct clk_regmap gxbb_sys_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_SYS_PLL_CNTL,
-			.shift   = 10,
-			.width   = 2,
-		},
 		.l = {
 			.reg_off = HHI_SYS_PLL_CNTL,
 			.shift   = 31,
@@ -387,7 +317,7 @@ static struct clk_regmap gxbb_sys_pll = {
 		},
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "sys_pll",
+		.name = "sys_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -395,13 +325,29 @@ static struct clk_regmap gxbb_sys_pll = {
 	},
 };
 
+static struct clk_regmap gxbb_sys_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_SYS_PLL_CNTL,
+		.shift = 10,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "sys_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
 static const struct reg_sequence gxbb_gp0_init_regs[] = {
 	{ .reg = HHI_GP0_PLL_CNTL2,	.def = 0x69c80000 },
 	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a5590c4 },
 	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0x0000500d },
 };
 
-static struct clk_regmap gxbb_gp0_pll = {
+static struct clk_regmap gxbb_gp0_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_GP0_PLL_CNTL,
@@ -418,11 +364,6 @@ static struct clk_regmap gxbb_gp0_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_GP0_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.l = {
 			.reg_off = HHI_GP0_PLL_CNTL,
 			.shift   = 31,
@@ -438,7 +379,7 @@ static struct clk_regmap gxbb_gp0_pll = {
 		.init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "gp0_pll",
+		.name = "gp0_pll_dco",
 		.ops = &meson_clk_pll_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -454,7 +395,7 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
 	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
 };
 
-static struct clk_regmap gxl_gp0_pll = {
+static struct clk_regmap gxl_gp0_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_GP0_PLL_CNTL,
@@ -471,11 +412,6 @@ static struct clk_regmap gxl_gp0_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_GP0_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.frac = {
 			.reg_off = HHI_GP0_PLL_CNTL1,
 			.shift   = 0,
@@ -496,7 +432,7 @@ static struct clk_regmap gxl_gp0_pll = {
 		.init_count = ARRAY_SIZE(gxl_gp0_init_regs),
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "gp0_pll",
+		.name = "gp0_pll_dco",
 		.ops = &meson_clk_pll_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -504,6 +440,22 @@ static struct clk_regmap gxl_gp0_pll = {
 	},
 };
 
+static struct clk_regmap gxbb_gp0_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_GP0_PLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "gp0_pll",
+		.ops = &clk_regmap_divider_ops,
+		.parent_names = (const char *[]){ "gp0_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+	},
+};
+
 static struct clk_fixed_factor gxbb_fclk_div2_div = {
 	.mult = 1,
 	.div = 2,
@@ -1961,6 +1913,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
 		[CLKID_GEN_CLK_SEL]	    = &gxbb_gen_clk_sel.hw,
 		[CLKID_GEN_CLK_DIV]	    = &gxbb_gen_clk_div.hw,
 		[CLKID_GEN_CLK]		    = &gxbb_gen_clk.hw,
+		[CLKID_FIXED_PLL_DCO]	    = &gxbb_fixed_pll_dco.hw,
+		[CLKID_HDMI_PLL_DCO]	    = &gxbb_hdmi_pll_dco.hw,
+		[CLKID_HDMI_PLL_OD]	    = &gxbb_hdmi_pll_od.hw,
+		[CLKID_HDMI_PLL_OD2]	    = &gxbb_hdmi_pll_od2.hw,
+		[CLKID_SYS_PLL_DCO]	    = &gxbb_sys_pll_dco.hw,
+		[CLKID_GP0_PLL_DCO]	    = &gxbb_gp0_pll_dco.hw,
 		[NR_CLKS]		    = NULL,
 	},
 	.num = NR_CLKS,
@@ -1976,7 +1934,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
 		[CLKID_FCLK_DIV4]	    = &gxbb_fclk_div4.hw,
 		[CLKID_FCLK_DIV5]	    = &gxbb_fclk_div5.hw,
 		[CLKID_FCLK_DIV7]	    = &gxbb_fclk_div7.hw,
-		[CLKID_GP0_PLL]		    = &gxl_gp0_pll.hw,
+		[CLKID_GP0_PLL]		    = &gxbb_gp0_pll.hw,
 		[CLKID_MPEG_SEL]	    = &gxbb_mpeg_clk_sel.hw,
 		[CLKID_MPEG_DIV]	    = &gxbb_mpeg_clk_div.hw,
 		[CLKID_CLK81]		    = &gxbb_clk81.hw,
@@ -2126,19 +2084,29 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
 		[CLKID_GEN_CLK_SEL]	    = &gxbb_gen_clk_sel.hw,
 		[CLKID_GEN_CLK_DIV]	    = &gxbb_gen_clk_div.hw,
 		[CLKID_GEN_CLK]		    = &gxbb_gen_clk.hw,
+		[CLKID_FIXED_PLL_DCO]	    = &gxbb_fixed_pll_dco.hw,
+		[CLKID_HDMI_PLL_DCO]	    = &gxbb_hdmi_pll_dco.hw,
+		[CLKID_HDMI_PLL_OD]	    = &gxl_hdmi_pll_od.hw,
+		[CLKID_HDMI_PLL_OD2]	    = &gxl_hdmi_pll_od2.hw,
+		[CLKID_SYS_PLL_DCO]	    = &gxbb_sys_pll_dco.hw,
+		[CLKID_GP0_PLL_DCO]	    = &gxl_gp0_pll_dco.hw,
 		[NR_CLKS]		    = NULL,
 	},
 	.num = NR_CLKS,
 };
 
 static struct clk_regmap *const gxbb_clk_regmaps[] = {
-	&gxbb_gp0_pll,
+	&gxbb_gp0_pll_dco,
 	&gxbb_hdmi_pll,
+	&gxbb_hdmi_pll_od,
+	&gxbb_hdmi_pll_od2,
 };
 
 static struct clk_regmap *const gxl_clk_regmaps[] = {
-	&gxl_gp0_pll,
+	&gxl_gp0_pll_dco,
 	&gxl_hdmi_pll,
+	&gxl_hdmi_pll_od,
+	&gxl_hdmi_pll_od2,
 };
 
 static struct clk_regmap *const gx_clk_regmaps[] = {
@@ -2293,6 +2261,10 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
 	&gxbb_gen_clk_sel,
 	&gxbb_gen_clk_div,
 	&gxbb_gen_clk,
+	&gxbb_fixed_pll_dco,
+	&gxbb_hdmi_pll_dco,
+	&gxbb_sys_pll_dco,
+	&gxbb_gp0_pll,
 };
 
 struct clkc_data {
diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index 20dfb1daf5b8..72bc077d9663 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -159,8 +159,14 @@
 #define CLKID_VDEC_HEVC_DIV	  155
 #define CLKID_GEN_CLK_SEL	  157
 #define CLKID_GEN_CLK_DIV	  158
-
-#define NR_CLKS			  160
+#define CLKID_FIXED_PLL_DCO	  160
+#define CLKID_HDMI_PLL_DCO	  161
+#define CLKID_HDMI_PLL_OD	  162
+#define CLKID_HDMI_PLL_OD2	  163
+#define CLKID_SYS_PLL_DCO	  164
+#define CLKID_GP0_PLL_DCO	  165
+
+#define NR_CLKS			  166
 
 /* include the CLKIDs that have been made part of the DT binding */
 #include <dt-bindings/clock/gxbb-clkc.h>
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index fd4c414893f5..17bcf0be56ba 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -30,58 +30,21 @@ struct meson8b_clk_reset {
 };
 
 static const struct pll_rate_table sys_pll_rate_table[] = {
-	PLL_RATE(312000000, 52, 1, 2),
-	PLL_RATE(336000000, 56, 1, 2),
-	PLL_RATE(360000000, 60, 1, 2),
-	PLL_RATE(384000000, 64, 1, 2),
-	PLL_RATE(408000000, 68, 1, 2),
-	PLL_RATE(432000000, 72, 1, 2),
-	PLL_RATE(456000000, 76, 1, 2),
-	PLL_RATE(480000000, 80, 1, 2),
-	PLL_RATE(504000000, 84, 1, 2),
-	PLL_RATE(528000000, 88, 1, 2),
-	PLL_RATE(552000000, 92, 1, 2),
-	PLL_RATE(576000000, 96, 1, 2),
-	PLL_RATE(600000000, 50, 1, 1),
-	PLL_RATE(624000000, 52, 1, 1),
-	PLL_RATE(648000000, 54, 1, 1),
-	PLL_RATE(672000000, 56, 1, 1),
-	PLL_RATE(696000000, 58, 1, 1),
-	PLL_RATE(720000000, 60, 1, 1),
-	PLL_RATE(744000000, 62, 1, 1),
-	PLL_RATE(768000000, 64, 1, 1),
-	PLL_RATE(792000000, 66, 1, 1),
-	PLL_RATE(816000000, 68, 1, 1),
-	PLL_RATE(840000000, 70, 1, 1),
-	PLL_RATE(864000000, 72, 1, 1),
-	PLL_RATE(888000000, 74, 1, 1),
-	PLL_RATE(912000000, 76, 1, 1),
-	PLL_RATE(936000000, 78, 1, 1),
-	PLL_RATE(960000000, 80, 1, 1),
-	PLL_RATE(984000000, 82, 1, 1),
-	PLL_RATE(1008000000, 84, 1, 1),
-	PLL_RATE(1032000000, 86, 1, 1),
-	PLL_RATE(1056000000, 88, 1, 1),
-	PLL_RATE(1080000000, 90, 1, 1),
-	PLL_RATE(1104000000, 92, 1, 1),
-	PLL_RATE(1128000000, 94, 1, 1),
-	PLL_RATE(1152000000, 96, 1, 1),
-	PLL_RATE(1176000000, 98, 1, 1),
-	PLL_RATE(1200000000, 50, 1, 0),
-	PLL_RATE(1224000000, 51, 1, 0),
-	PLL_RATE(1248000000, 52, 1, 0),
-	PLL_RATE(1272000000, 53, 1, 0),
-	PLL_RATE(1296000000, 54, 1, 0),
-	PLL_RATE(1320000000, 55, 1, 0),
-	PLL_RATE(1344000000, 56, 1, 0),
-	PLL_RATE(1368000000, 57, 1, 0),
-	PLL_RATE(1392000000, 58, 1, 0),
-	PLL_RATE(1416000000, 59, 1, 0),
-	PLL_RATE(1440000000, 60, 1, 0),
-	PLL_RATE(1464000000, 61, 1, 0),
-	PLL_RATE(1488000000, 62, 1, 0),
-	PLL_RATE(1512000000, 63, 1, 0),
-	PLL_RATE(1536000000, 64, 1, 0),
+	PLL_RATE(1200000000, 50, 1),
+	PLL_RATE(1224000000, 51, 1),
+	PLL_RATE(1248000000, 52, 1),
+	PLL_RATE(1272000000, 53, 1),
+	PLL_RATE(1296000000, 54, 1),
+	PLL_RATE(1320000000, 55, 1),
+	PLL_RATE(1344000000, 56, 1),
+	PLL_RATE(1368000000, 57, 1),
+	PLL_RATE(1392000000, 58, 1),
+	PLL_RATE(1416000000, 59, 1),
+	PLL_RATE(1440000000, 60, 1),
+	PLL_RATE(1464000000, 61, 1),
+	PLL_RATE(1488000000, 62, 1),
+	PLL_RATE(1512000000, 63, 1),
+	PLL_RATE(1536000000, 64, 1),
 	{ /* sentinel */ },
 };
 
@@ -94,7 +57,7 @@ static struct clk_fixed_rate meson8b_xtal = {
 	},
 };
 
-static struct clk_regmap meson8b_fixed_pll = {
+static struct clk_regmap meson8b_fixed_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_MPLL_CNTL,
@@ -111,11 +74,6 @@ static struct clk_regmap meson8b_fixed_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_MPLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.frac = {
 			.reg_off = HHI_MPLL_CNTL2,
 			.shift   = 0,
@@ -133,7 +91,7 @@ static struct clk_regmap meson8b_fixed_pll = {
 		},
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "fixed_pll",
+		.name = "fixed_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -141,7 +99,23 @@ static struct clk_regmap meson8b_fixed_pll = {
 	},
 };
 
-static struct clk_regmap meson8b_vid_pll = {
+static struct clk_regmap meson8b_fixed_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_MPLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "fixed_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "fixed_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
+static struct clk_regmap meson8b_vid_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_VID_PLL_CNTL,
@@ -158,11 +132,6 @@ static struct clk_regmap meson8b_vid_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_VID_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.l = {
 			.reg_off = HHI_VID_PLL_CNTL,
 			.shift   = 31,
@@ -175,7 +144,7 @@ static struct clk_regmap meson8b_vid_pll = {
 		},
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "vid_pll",
+		.name = "vid_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -183,7 +152,23 @@ static struct clk_regmap meson8b_vid_pll = {
 	},
 };
 
-static struct clk_regmap meson8b_sys_pll = {
+static struct clk_regmap meson8b_vid_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_VID_PLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "vid_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "vid_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
+static struct clk_regmap meson8b_sys_pll_dco = {
 	.data = &(struct meson_clk_pll_data){
 		.en = {
 			.reg_off = HHI_SYS_PLL_CNTL,
@@ -200,11 +185,6 @@ static struct clk_regmap meson8b_sys_pll = {
 			.shift   = 9,
 			.width   = 5,
 		},
-		.od = {
-			.reg_off = HHI_SYS_PLL_CNTL,
-			.shift   = 16,
-			.width   = 2,
-		},
 		.l = {
 			.reg_off = HHI_SYS_PLL_CNTL,
 			.shift   = 31,
@@ -218,7 +198,7 @@ static struct clk_regmap meson8b_sys_pll = {
 		.table = sys_pll_rate_table,
 	},
 	.hw.init = &(struct clk_init_data){
-		.name = "sys_pll",
+		.name = "sys_pll_dco",
 		.ops = &meson_clk_pll_ro_ops,
 		.parent_names = (const char *[]){ "xtal" },
 		.num_parents = 1,
@@ -226,6 +206,22 @@ static struct clk_regmap meson8b_sys_pll = {
 	},
 };
 
+static struct clk_regmap meson8b_sys_pll = {
+	.data = &(struct clk_regmap_div_data){
+		.offset = HHI_SYS_PLL_CNTL,
+		.shift = 16,
+		.width = 2,
+		.flags = CLK_DIVIDER_POWER_OF_TWO,
+	},
+	.hw.init = &(struct clk_init_data){
+		.name = "sys_pll",
+		.ops = &clk_regmap_divider_ro_ops,
+		.parent_names = (const char *[]){ "sys_pll_dco" },
+		.num_parents = 1,
+		.flags = CLK_GET_RATE_NOCACHE,
+	},
+};
+
 static struct clk_fixed_factor meson8b_fclk_div2_div = {
 	.mult = 1,
 	.div = 2,
@@ -894,6 +890,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
 		[CLKID_NAND_SEL]	    = &meson8b_nand_clk_sel.hw,
 		[CLKID_NAND_DIV]	    = &meson8b_nand_clk_div.hw,
 		[CLKID_NAND_CLK]	    = &meson8b_nand_clk_gate.hw,
+		[CLKID_PLL_FIXED_DCO]	    = &meson8b_fixed_pll_dco.hw,
+		[CLKID_PLL_VID_DCO]	    = &meson8b_vid_pll_dco.hw,
+		[CLKID_PLL_SYS_DCO]	    = &meson8b_sys_pll_dco.hw,
 		[CLK_NR_CLKS]		    = NULL,
 	},
 	.num = CLK_NR_CLKS,
@@ -1002,6 +1001,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
 	&meson8b_nand_clk_sel,
 	&meson8b_nand_clk_div,
 	&meson8b_nand_clk_gate,
+	&meson8b_fixed_pll_dco,
+	&meson8b_vid_pll_dco,
+	&meson8b_sys_pll_dco,
 };
 
 static const struct meson8b_clk_reset_line {
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 5d09412b5084..1c6fb180e6a2 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -75,8 +75,11 @@
 #define CLKID_FCLK_DIV7_DIV	109
 #define CLKID_NAND_SEL		110
 #define CLKID_NAND_DIV		111
+#define CLKID_PLL_FIXED_DCO	113
+#define CLKID_PLL_VID_DCO	114
+#define CLKID_PLL_SYS_DCO	115
 
-#define CLK_NR_CLKS		113
+#define CLK_NR_CLKS		116
 
 /*
  * include the CLKID and RESETID that have
-- 
2.14.4


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

* [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables
  2018-07-17  9:56 [PATCH 0/3] clk: meson: clk-pll driver update Jerome Brunet
  2018-07-17  9:56 ` [PATCH 1/3] clk: meson: clk-pll: add enable bit Jerome Brunet
  2018-07-17  9:56 ` [PATCH 2/3] clk: meson: clk-pll: remove od parameters Jerome Brunet
@ 2018-07-17  9:56 ` Jerome Brunet
  2018-07-19  8:44   ` Neil Armstrong
  2018-07-21 20:17 ` [PATCH 0/3] clk: meson: clk-pll driver update Martin Blumenstingl
  3 siblings, 1 reply; 20+ messages in thread
From: Jerome Brunet @ 2018-07-17  9:56 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: Jerome Brunet, linux-amlogic, linux-clk, linux-kernel,
	Kevin Hilman, Martin Blumenstingl

Putting hard-coded rates inside the parameter tables assumes that
the parent is known and will never change. That's a big assumption
we should not make.

We have everything we need to recalculate the output rate using
the parent rate and the rest of the parameters. Let's do so and
drop the rates from the tables.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/axg.c     |  73 +++++++++++++--------------
 drivers/clk/meson/clk-pll.c |  69 ++++++++++++++++---------
 drivers/clk/meson/clkc.h    |   8 ++-
 drivers/clk/meson/gxbb.c    | 120 ++++++++++++++++++++++----------------------
 drivers/clk/meson/meson8b.c |  34 ++++++-------
 5 files changed, 162 insertions(+), 142 deletions(-)

diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 572358062459..d34954bd8c5e 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -130,36 +130,36 @@ static struct clk_regmap axg_sys_pll = {
 	},
 };
 
-static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
-	PLL_RATE(960000000, 40, 1),
-	PLL_RATE(984000000, 41, 1),
-	PLL_RATE(1008000000, 42, 1),
-	PLL_RATE(1032000000, 43, 1),
-	PLL_RATE(1056000000, 44, 1),
-	PLL_RATE(1080000000, 45, 1),
-	PLL_RATE(1104000000, 46, 1),
-	PLL_RATE(1128000000, 47, 1),
-	PLL_RATE(1152000000, 48, 1),
-	PLL_RATE(1176000000, 49, 1),
-	PLL_RATE(1200000000, 50, 1),
-	PLL_RATE(1224000000, 51, 1),
-	PLL_RATE(1248000000, 52, 1),
-	PLL_RATE(1272000000, 53, 1),
-	PLL_RATE(1296000000, 54, 1),
-	PLL_RATE(1320000000, 55, 1),
-	PLL_RATE(1344000000, 56, 1),
-	PLL_RATE(1368000000, 57, 1),
-	PLL_RATE(1392000000, 58, 1),
-	PLL_RATE(1416000000, 59, 1),
-	PLL_RATE(1440000000, 60, 1),
-	PLL_RATE(1464000000, 61, 1),
-	PLL_RATE(1488000000, 62, 1),
-	PLL_RATE(1512000000, 63, 1),
-	PLL_RATE(1536000000, 64, 1),
-	PLL_RATE(1560000000, 65, 1),
-	PLL_RATE(1584000000, 66, 1),
-	PLL_RATE(1608000000, 67, 1),
-	PLL_RATE(1632000000, 68, 1),
+static const struct pll_params_table axg_gp0_pll_params_table[] = {
+	PLL_PARAMS(40, 1),
+	PLL_PARAMS(41, 1),
+	PLL_PARAMS(42, 1),
+	PLL_PARAMS(43, 1),
+	PLL_PARAMS(44, 1),
+	PLL_PARAMS(45, 1),
+	PLL_PARAMS(46, 1),
+	PLL_PARAMS(47, 1),
+	PLL_PARAMS(48, 1),
+	PLL_PARAMS(49, 1),
+	PLL_PARAMS(50, 1),
+	PLL_PARAMS(51, 1),
+	PLL_PARAMS(52, 1),
+	PLL_PARAMS(53, 1),
+	PLL_PARAMS(54, 1),
+	PLL_PARAMS(55, 1),
+	PLL_PARAMS(56, 1),
+	PLL_PARAMS(57, 1),
+	PLL_PARAMS(58, 1),
+	PLL_PARAMS(59, 1),
+	PLL_PARAMS(60, 1),
+	PLL_PARAMS(61, 1),
+	PLL_PARAMS(62, 1),
+	PLL_PARAMS(63, 1),
+	PLL_PARAMS(64, 1),
+	PLL_PARAMS(65, 1),
+	PLL_PARAMS(66, 1),
+	PLL_PARAMS(67, 1),
+	PLL_PARAMS(68, 1),
 	{ /* sentinel */ },
 };
 
@@ -203,7 +203,7 @@ static struct clk_regmap axg_gp0_pll_dco = {
 			.shift   = 29,
 			.width   = 1,
 		},
-		.table = axg_gp0_pll_rate_table,
+		.table = axg_gp0_pll_params_table,
 		.init_regs = axg_gp0_init_regs,
 		.init_count = ARRAY_SIZE(axg_gp0_init_regs),
 	},
@@ -271,7 +271,7 @@ static struct clk_regmap axg_hifi_pll_dco = {
 			.shift   = 29,
 			.width   = 1,
 		},
-		.table = axg_gp0_pll_rate_table,
+		.table = axg_gp0_pll_params_table,
 		.init_regs = axg_hifi_init_regs,
 		.init_count = ARRAY_SIZE(axg_hifi_init_regs),
 		.flags = CLK_MESON_PLL_ROUND_CLOSEST,
@@ -627,11 +627,10 @@ static struct clk_regmap axg_mpll3 = {
 	},
 };
 
-static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
+static const struct pll_params_table axg_pcie_pll_params_table[] = {
 	{
-		.rate	= 1600000000,
-		.m	= 200,
-		.n	= 3,
+		.m = 200,
+		.n = 3,
 	},
 	{ /* sentinel */ },
 };
@@ -678,7 +677,7 @@ static struct clk_regmap axg_pcie_pll_dco = {
 			.shift   = 29,
 			.width   = 1,
 		},
-		.table = axg_pcie_pll_rate_table,
+		.table = axg_pcie_pll_params_table,
 		.init_regs = axg_pcie_init_regs,
 		.init_count = ARRAY_SIZE(axg_pcie_init_regs),
 	},
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 348a866f09eb..f5b5b3fabe3c 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -45,7 +45,7 @@ meson_clk_pll_data(struct clk_regmap *clk)
 }
 
 static unsigned long __pll_params_to_rate(unsigned long parent_rate,
-					  const struct pll_rate_table *pllt,
+					  const struct pll_params_table *pllt,
 					  u16 frac,
 					  struct meson_clk_pll_data *pll)
 {
@@ -66,7 +66,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
 {
 	struct clk_regmap *clk = to_clk_regmap(hw);
 	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-	struct pll_rate_table pllt;
+	struct pll_params_table pllt;
 	u16 frac;
 
 	pllt.n = meson_parm_read(clk->map, &pll->n);
@@ -81,7 +81,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
 
 static u16 __pll_params_with_frac(unsigned long rate,
 				  unsigned long parent_rate,
-				  const struct pll_rate_table *pllt,
+				  const struct pll_params_table *pllt,
 				  struct meson_clk_pll_data *pll)
 {
 	u16 frac_max = (1 << pll->frac.width);
@@ -97,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
 	return min((u16)val, (u16)(frac_max - 1));
 }
 
-static const struct pll_rate_table *
+static bool meson_clk_pll_is_better(unsigned long rate,
+				    unsigned long best,
+				    unsigned long now,
+				    struct meson_clk_pll_data *pll)
+{
+	if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
+	    MESON_PARM_APPLICABLE(&pll->frac)) {
+		/* Round down */
+		if (now < rate && best < now)
+			return true;
+	} else {
+		/* Round Closest */
+		if (abs(now - rate) < abs(best - rate))
+			return true;
+	}
+
+	return false;
+}
+
+static const struct pll_params_table *
 meson_clk_get_pll_settings(unsigned long rate,
+			   unsigned long parent_rate,
 			   struct meson_clk_pll_data *pll)
 {
-	const struct pll_rate_table *table = pll->table;
-	unsigned int i = 0;
+	const struct pll_params_table *table = pll->table;
+	unsigned long best = 0, now = 0;
+	unsigned int i, best_i = 0;
 
 	if (!table)
 		return NULL;
 
-	/* Find the first table element exceeding rate */
-	while (table[i].rate && table[i].rate <= rate)
-		i++;
+	for (i = 0; table[i].n; i++) {
+		now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
 
-	if (i != 0) {
-		if (MESON_PARM_APPLICABLE(&pll->frac) ||
-		    !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
-		    (abs(rate - table[i - 1].rate) <
-		     abs(rate - table[i].rate)))
-			i--;
+		/* If we get an exact match, don't bother any further */
+		if (now == rate) {
+			return &table[i];
+		} else if (meson_clk_pll_is_better(rate, best, now, pll)) {
+			best = now;
+			best_i = i;
+		}
 	}
 
-	return (struct pll_rate_table *)&table[i];
+	return (struct pll_params_table *)&table[best_i];
 }
 
 static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -127,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_regmap *clk = to_clk_regmap(hw);
 	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-	const struct pll_rate_table *pllt =
-		meson_clk_get_pll_settings(rate, pll);
+	const struct pll_params_table *pllt =
+		meson_clk_get_pll_settings(rate, *parent_rate, pll);
+	unsigned long round;
 	u16 frac;
 
 	if (!pllt)
 		return meson_clk_pll_recalc_rate(hw, *parent_rate);
 
-	if (!MESON_PARM_APPLICABLE(&pll->frac)
-	    || rate == pllt->rate)
-		return pllt->rate;
+	round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
+
+	if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
+		return round;
 
 	/*
 	 * The rate provided by the setting is not an exact match, let's
@@ -214,7 +237,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 {
 	struct clk_regmap *clk = to_clk_regmap(hw);
 	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-	const struct pll_rate_table *pllt;
+	const struct pll_params_table *pllt;
 	unsigned int enabled;
 	unsigned long old_rate;
 	u16 frac = 0;
@@ -224,7 +247,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
 	old_rate = rate;
 
-	pllt = meson_clk_get_pll_settings(rate, pll);
+	pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
 	if (!pllt)
 		return -EINVAL;
 
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index a2245e857f70..6b96d55c047d 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -43,15 +43,13 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
 }
 
 
-struct pll_rate_table {
-	unsigned long	rate;
+struct pll_params_table {
 	u16		m;
 	u16		n;
 };
 
-#define PLL_RATE(_r, _m, _n)						\
+#define PLL_PARAMS(_m, _n)						\
 	{								\
-		.rate		= (_r),					\
 		.m		= (_m),					\
 		.n		= (_n),					\
 	}
@@ -67,7 +65,7 @@ struct meson_clk_pll_data {
 	struct parm rst;
 	const struct reg_sequence *init_regs;
 	unsigned int init_count;
-	const struct pll_rate_table *table;
+	const struct pll_params_table *table;
 	u8 flags;
 };
 
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index e2d94498f098..9ac03c7bfbaa 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -18,67 +18,67 @@
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
-static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
-	PLL_RATE(768000000, 32, 1),
-	PLL_RATE(792000000, 33, 1),
-	PLL_RATE(816000000, 34, 1),
-	PLL_RATE(840000000, 35, 1),
-	PLL_RATE(864000000, 36, 1),
-	PLL_RATE(888000000, 37, 1),
-	PLL_RATE(912000000, 38, 1),
-	PLL_RATE(936000000, 39, 1),
-	PLL_RATE(960000000, 40, 1),
-	PLL_RATE(984000000, 41, 1),
-	PLL_RATE(1008000000, 42, 1),
-	PLL_RATE(1032000000, 43, 1),
-	PLL_RATE(1056000000, 44, 1),
-	PLL_RATE(1080000000, 45, 1),
-	PLL_RATE(1104000000, 46, 1),
-	PLL_RATE(1128000000, 47, 1),
-	PLL_RATE(1152000000, 48, 1),
-	PLL_RATE(1176000000, 49, 1),
-	PLL_RATE(1200000000, 50, 1),
-	PLL_RATE(1224000000, 51, 1),
-	PLL_RATE(1248000000, 52, 1),
-	PLL_RATE(1272000000, 53, 1),
-	PLL_RATE(1296000000, 54, 1),
-	PLL_RATE(1320000000, 55, 1),
-	PLL_RATE(1344000000, 56, 1),
-	PLL_RATE(1368000000, 57, 1),
-	PLL_RATE(1392000000, 58, 1),
-	PLL_RATE(1416000000, 59, 1),
-	PLL_RATE(1440000000, 60, 1),
-	PLL_RATE(1464000000, 61, 1),
-	PLL_RATE(1488000000, 62, 1),
+static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
+	PLL_PARAMS(32, 1),
+	PLL_PARAMS(33, 1),
+	PLL_PARAMS(34, 1),
+	PLL_PARAMS(35, 1),
+	PLL_PARAMS(36, 1),
+	PLL_PARAMS(37, 1),
+	PLL_PARAMS(38, 1),
+	PLL_PARAMS(39, 1),
+	PLL_PARAMS(40, 1),
+	PLL_PARAMS(41, 1),
+	PLL_PARAMS(42, 1),
+	PLL_PARAMS(43, 1),
+	PLL_PARAMS(44, 1),
+	PLL_PARAMS(45, 1),
+	PLL_PARAMS(46, 1),
+	PLL_PARAMS(47, 1),
+	PLL_PARAMS(48, 1),
+	PLL_PARAMS(49, 1),
+	PLL_PARAMS(50, 1),
+	PLL_PARAMS(51, 1),
+	PLL_PARAMS(52, 1),
+	PLL_PARAMS(53, 1),
+	PLL_PARAMS(54, 1),
+	PLL_PARAMS(55, 1),
+	PLL_PARAMS(56, 1),
+	PLL_PARAMS(57, 1),
+	PLL_PARAMS(58, 1),
+	PLL_PARAMS(59, 1),
+	PLL_PARAMS(60, 1),
+	PLL_PARAMS(61, 1),
+	PLL_PARAMS(62, 1),
 	{ /* sentinel */ },
 };
 
-static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
-	PLL_RATE(1008000000, 42, 1),
-	PLL_RATE(1032000000, 43, 1),
-	PLL_RATE(1056000000, 44, 1),
-	PLL_RATE(1080000000, 45, 1),
-	PLL_RATE(1104000000, 46, 1),
-	PLL_RATE(1128000000, 47, 1),
-	PLL_RATE(1152000000, 48, 1),
-	PLL_RATE(1176000000, 49, 1),
-	PLL_RATE(1200000000, 50, 1),
-	PLL_RATE(1224000000, 51, 1),
-	PLL_RATE(1248000000, 52, 1),
-	PLL_RATE(1272000000, 53, 1),
-	PLL_RATE(1296000000, 54, 1),
-	PLL_RATE(1320000000, 55, 1),
-	PLL_RATE(1344000000, 56, 1),
-	PLL_RATE(1368000000, 57, 1),
-	PLL_RATE(1392000000, 58, 1),
-	PLL_RATE(1416000000, 59, 1),
-	PLL_RATE(1440000000, 60, 1),
-	PLL_RATE(1464000000, 61, 1),
-	PLL_RATE(1488000000, 62, 1),
-	PLL_RATE(1512000000, 63, 1),
-	PLL_RATE(1536000000, 64, 1),
-	PLL_RATE(1560000000, 65, 1),
-	PLL_RATE(1584000000, 66, 1),
+static const struct pll_params_table gxl_gp0_pll_params_table[] = {
+	PLL_PARAMS(42, 1),
+	PLL_PARAMS(43, 1),
+	PLL_PARAMS(44, 1),
+	PLL_PARAMS(45, 1),
+	PLL_PARAMS(46, 1),
+	PLL_PARAMS(47, 1),
+	PLL_PARAMS(48, 1),
+	PLL_PARAMS(49, 1),
+	PLL_PARAMS(50, 1),
+	PLL_PARAMS(51, 1),
+	PLL_PARAMS(52, 1),
+	PLL_PARAMS(53, 1),
+	PLL_PARAMS(54, 1),
+	PLL_PARAMS(55, 1),
+	PLL_PARAMS(56, 1),
+	PLL_PARAMS(57, 1),
+	PLL_PARAMS(58, 1),
+	PLL_PARAMS(59, 1),
+	PLL_PARAMS(60, 1),
+	PLL_PARAMS(61, 1),
+	PLL_PARAMS(62, 1),
+	PLL_PARAMS(63, 1),
+	PLL_PARAMS(64, 1),
+	PLL_PARAMS(65, 1),
+	PLL_PARAMS(66, 1),
 	{ /* sentinel */ },
 };
 
@@ -374,7 +374,7 @@ static struct clk_regmap gxbb_gp0_pll_dco = {
 			.shift   = 29,
 			.width   = 1,
 		},
-		.table = gxbb_gp0_pll_rate_table,
+		.table = gxbb_gp0_pll_params_table,
 		.init_regs = gxbb_gp0_init_regs,
 		.init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
 	},
@@ -427,7 +427,7 @@ static struct clk_regmap gxl_gp0_pll_dco = {
 			.shift   = 29,
 			.width   = 1,
 		},
-		.table = gxl_gp0_pll_rate_table,
+		.table = gxl_gp0_pll_params_table,
 		.init_regs = gxl_gp0_init_regs,
 		.init_count = ARRAY_SIZE(gxl_gp0_init_regs),
 	},
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 17bcf0be56ba..30ae849ff53f 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -29,22 +29,22 @@ struct meson8b_clk_reset {
 	void __iomem *base;
 };
 
-static const struct pll_rate_table sys_pll_rate_table[] = {
-	PLL_RATE(1200000000, 50, 1),
-	PLL_RATE(1224000000, 51, 1),
-	PLL_RATE(1248000000, 52, 1),
-	PLL_RATE(1272000000, 53, 1),
-	PLL_RATE(1296000000, 54, 1),
-	PLL_RATE(1320000000, 55, 1),
-	PLL_RATE(1344000000, 56, 1),
-	PLL_RATE(1368000000, 57, 1),
-	PLL_RATE(1392000000, 58, 1),
-	PLL_RATE(1416000000, 59, 1),
-	PLL_RATE(1440000000, 60, 1),
-	PLL_RATE(1464000000, 61, 1),
-	PLL_RATE(1488000000, 62, 1),
-	PLL_RATE(1512000000, 63, 1),
-	PLL_RATE(1536000000, 64, 1),
+static const struct pll_params_table sys_pll_params_table[] = {
+	PLL_PARAMS(50, 1),
+	PLL_PARAMS(51, 1),
+	PLL_PARAMS(52, 1),
+	PLL_PARAMS(53, 1),
+	PLL_PARAMS(54, 1),
+	PLL_PARAMS(55, 1),
+	PLL_PARAMS(56, 1),
+	PLL_PARAMS(57, 1),
+	PLL_PARAMS(58, 1),
+	PLL_PARAMS(59, 1),
+	PLL_PARAMS(60, 1),
+	PLL_PARAMS(61, 1),
+	PLL_PARAMS(62, 1),
+	PLL_PARAMS(63, 1),
+	PLL_PARAMS(64, 1),
 	{ /* sentinel */ },
 };
 
@@ -195,7 +195,7 @@ static struct clk_regmap meson8b_sys_pll_dco = {
 			.shift   = 29,
 			.width   = 1,
 		},
-		.table = sys_pll_rate_table,
+		.table = sys_pll_params_table,
 	},
 	.hw.init = &(struct clk_init_data){
 		.name = "sys_pll_dco",
-- 
2.14.4


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

* Re: [PATCH 1/3] clk: meson: clk-pll: add enable bit
  2018-07-17  9:56 ` [PATCH 1/3] clk: meson: clk-pll: add enable bit Jerome Brunet
@ 2018-07-19  8:33   ` Neil Armstrong
  2018-07-21 19:48   ` Martin Blumenstingl
  1 sibling, 0 replies; 20+ messages in thread
From: Neil Armstrong @ 2018-07-19  8:33 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: linux-amlogic, linux-clk, linux-kernel, Kevin Hilman,
	Martin Blumenstingl

On 17/07/2018 11:56, Jerome Brunet wrote:
> Add the enable the bit of the pll clocks.
> These pll clocks may be disabled but we can't model this as an external
> gate since the pll needs to lock when enabled.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/meson/axg.c     | 28 ++++++++++++++++++++++++---
>  drivers/clk/meson/clk-pll.c | 47 ++++++++++++++++++++++++++++++++++++++++-----
>  drivers/clk/meson/clkc.h    |  1 +
>  drivers/clk/meson/gxbb.c    | 32 ++++++++++++++++++++++++++++--
>  drivers/clk/meson/meson8b.c | 15 +++++++++++++++
>  5 files changed, 113 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
> index 00ce62ad6416..6d8976554656 100644
> --- a/drivers/clk/meson/axg.c
> +++ b/drivers/clk/meson/axg.c
> @@ -24,6 +24,11 @@ static DEFINE_SPINLOCK(meson_clk_lock);
>  
>  static struct clk_regmap axg_fixed_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_MPLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_MPLL_CNTL,
>  			.shift   = 0,
> @@ -65,6 +70,11 @@ static struct clk_regmap axg_fixed_pll = {
>  
>  static struct clk_regmap axg_sys_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_SYS_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
>  			.shift   = 0,
> @@ -197,11 +207,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
>  	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a59a288 },
>  	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0xc000004d },
>  	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
> -	{ .reg = HHI_GP0_PLL_CNTL,	.def = 0x40010250 },
>  };
>  
>  static struct clk_regmap axg_gp0_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_GP0_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_GP0_PLL_CNTL,
>  			.shift   = 0,
> @@ -250,11 +264,15 @@ static const struct reg_sequence axg_hifi_init_regs[] = {
>  	{ .reg = HHI_HIFI_PLL_CNTL3,	.def = 0x0a6a3a88 },
>  	{ .reg = HHI_HIFI_PLL_CNTL4,	.def = 0xc000004d },
>  	{ .reg = HHI_HIFI_PLL_CNTL5,	.def = 0x00058000 },
> -	{ .reg = HHI_HIFI_PLL_CNTL,	.def = 0x40010250 },
>  };
>  
>  static struct clk_regmap axg_hifi_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_HIFI_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_HIFI_PLL_CNTL,
>  			.shift   = 0,
> @@ -637,7 +655,6 @@ static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
>  };
>  
>  static const struct reg_sequence axg_pcie_init_regs[] = {
> -	{ .reg = HHI_PCIE_PLL_CNTL,	.def = 0x400106c8 },
>  	{ .reg = HHI_PCIE_PLL_CNTL1,	.def = 0x0084a2aa },
>  	{ .reg = HHI_PCIE_PLL_CNTL2,	.def = 0xb75020be },
>  	{ .reg = HHI_PCIE_PLL_CNTL3,	.def = 0x0a47488e },
> @@ -648,6 +665,11 @@ static const struct reg_sequence axg_pcie_init_regs[] = {
>  
>  static struct clk_regmap axg_pcie_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_PCIE_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_PCIE_PLL_CNTL,
>  			.shift   = 0,
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 3e04617ac47f..8aaefe67025f 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -185,12 +185,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
>  	}
>  }
>  
> +static int meson_clk_pll_enable(struct clk_hw *hw)
> +{
> +	struct clk_regmap *clk = to_clk_regmap(hw);
> +	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> +
> +	/* Make sure the pll is in reset */
> +	meson_parm_write(clk->map, &pll->rst, 1);
> +
> +	/* Enable the pll */
> +	meson_parm_write(clk->map, &pll->en, 1);
> +
> +	/* Take the pll out reset */
> +	meson_parm_write(clk->map, &pll->rst, 0);
> +
> +	if (meson_clk_pll_wait_lock(hw))
> +		return -EIO;
> +
> +	return 0;
> +}
> +
> +static void meson_clk_pll_disable(struct clk_hw *hw)
> +{
> +	struct clk_regmap *clk = to_clk_regmap(hw);
> +	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> +
> +	/* Put the pll is in reset */
> +	meson_parm_write(clk->map, &pll->rst, 1);
> +
> +	/* Disable the pll */
> +	meson_parm_write(clk->map, &pll->en, 0);
> +}
> +
>  static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>  				  unsigned long parent_rate)
>  {
>  	struct clk_regmap *clk = to_clk_regmap(hw);
>  	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
>  	const struct pll_rate_table *pllt;
> +	unsigned int enabled;
>  	unsigned long old_rate;
>  	u16 frac = 0;
>  
> @@ -203,8 +236,9 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>  	if (!pllt)
>  		return -EINVAL;
>  
> -	/* Put the pll in reset to write the params */
> -	meson_parm_write(clk->map, &pll->rst, 1);
> +	enabled = meson_parm_read(clk->map, &pll->en);
> +	if (enabled)
> +		meson_clk_pll_disable(hw);
>  
>  	meson_parm_write(clk->map, &pll->n, pllt->n);
>  	meson_parm_write(clk->map, &pll->m, pllt->m);
> @@ -221,10 +255,11 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>  		meson_parm_write(clk->map, &pll->frac, frac);
>  	}
>  
> -	/* make sure the reset is cleared at this point */
> -	meson_parm_write(clk->map, &pll->rst, 0);
> +	/* If the pll is stopped, bail out now */
> +	if (!enabled)
> +		return 0;
>  
> -	if (meson_clk_pll_wait_lock(hw)) {
> +	if (meson_clk_pll_enable(hw)) {
>  		pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
>  			__func__, old_rate);
>  		/*
> @@ -244,6 +279,8 @@ const struct clk_ops meson_clk_pll_ops = {
>  	.recalc_rate	= meson_clk_pll_recalc_rate,
>  	.round_rate	= meson_clk_pll_round_rate,
>  	.set_rate	= meson_clk_pll_set_rate,
> +	.enable		= meson_clk_pll_enable,
> +	.disable	= meson_clk_pll_disable
>  };
>  
>  const struct clk_ops meson_clk_pll_ro_ops = {
> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> index 24cec16b6038..c2ee37a78ceb 100644
> --- a/drivers/clk/meson/clkc.h
> +++ b/drivers/clk/meson/clkc.h
> @@ -63,6 +63,7 @@ struct pll_rate_table {
>  #define CLK_MESON_PLL_ROUND_CLOSEST	BIT(0)
>  
>  struct meson_clk_pll_data {
> +	struct parm en;
>  	struct parm m;
>  	struct parm n;
>  	struct parm frac;
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index 86d3ae58e84c..5ed34566917c 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -177,6 +177,11 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
>  
>  static struct clk_regmap gxbb_fixed_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_MPLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_MPLL_CNTL,
>  			.shift   = 0,
> @@ -230,6 +235,11 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
>  
>  static struct clk_regmap gxbb_hdmi_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_HDMI_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_HDMI_PLL_CNTL,
>  			.shift   = 0,
> @@ -282,6 +292,11 @@ static struct clk_regmap gxbb_hdmi_pll = {
>  
>  static struct clk_regmap gxl_hdmi_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_HDMI_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_HDMI_PLL_CNTL,
>  			.shift   = 0,
> @@ -340,6 +355,11 @@ static struct clk_regmap gxl_hdmi_pll = {
>  
>  static struct clk_regmap gxbb_sys_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_SYS_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
>  			.shift   = 0,
> @@ -379,11 +399,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = {
>  	{ .reg = HHI_GP0_PLL_CNTL2,	.def = 0x69c80000 },
>  	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a5590c4 },
>  	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0x0000500d },
> -	{ .reg = HHI_GP0_PLL_CNTL,	.def = 0x4a000228 },
>  };
>  
>  static struct clk_regmap gxbb_gp0_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_GP0_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_GP0_PLL_CNTL,
>  			.shift   = 0,
> @@ -428,11 +452,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
>  	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a59a288 },
>  	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0xc000004d },
>  	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
> -	{ .reg = HHI_GP0_PLL_CNTL,	.def = 0x40010250 },
>  };
>  
>  static struct clk_regmap gxl_gp0_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_GP0_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_GP0_PLL_CNTL,
>  			.shift   = 0,
> diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
> index 7447d96a265f..fd4c414893f5 100644
> --- a/drivers/clk/meson/meson8b.c
> +++ b/drivers/clk/meson/meson8b.c
> @@ -96,6 +96,11 @@ static struct clk_fixed_rate meson8b_xtal = {
>  
>  static struct clk_regmap meson8b_fixed_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_MPLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_MPLL_CNTL,
>  			.shift   = 0,
> @@ -138,6 +143,11 @@ static struct clk_regmap meson8b_fixed_pll = {
>  
>  static struct clk_regmap meson8b_vid_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_VID_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_VID_PLL_CNTL,
>  			.shift   = 0,
> @@ -175,6 +185,11 @@ static struct clk_regmap meson8b_vid_pll = {
>  
>  static struct clk_regmap meson8b_sys_pll = {
>  	.data = &(struct meson_clk_pll_data){
> +		.en = {
> +			.reg_off = HHI_SYS_PLL_CNTL,
> +			.shift   = 30,
> +			.width   = 1,
> +		},
>  		.m = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
>  			.shift   = 0,
> 

This makes the pll reset path much clearer !

Acked-by: Neil Armstrong <narmstrong@baylibre.com>

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

* Re: [PATCH 2/3] clk: meson: clk-pll: remove od parameters
  2018-07-17  9:56 ` [PATCH 2/3] clk: meson: clk-pll: remove od parameters Jerome Brunet
@ 2018-07-19  8:42   ` Neil Armstrong
  2018-07-19  8:45     ` Jerome Brunet
  2018-07-21 20:01   ` Martin Blumenstingl
  1 sibling, 1 reply; 20+ messages in thread
From: Neil Armstrong @ 2018-07-19  8:42 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: linux-amlogic, linux-clk, linux-kernel, Kevin Hilman,
	Martin Blumenstingl

On 17/07/2018 11:56, Jerome Brunet wrote:
> Remove od parameters from pll clocks and add post dividers clocks
> instead. Some clock, especially the one which feature several ods,
> may provide output between those ods. Also, some drivers, such
> as the hdmi driver, may require a more detailed control of the
> clock dividers, compared to what CCF would perform automatically.
> 
> One added benefit of removing ods is that it also greatly reduce the
> size of the rate parameter tables.
> 
> In the future, we could possibly take the predivider 'n' out of this
> driver as well. To do so, we will need to understand the constraints
> for the PLL to lock and whether or not it depends on the input clock
> rate.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/meson/axg.c     | 279 ++++++++++++++------------
>  drivers/clk/meson/axg.h     |   8 +-
>  drivers/clk/meson/clk-pll.c |  40 ++--
>  drivers/clk/meson/clkc.h    |   9 +-
>  drivers/clk/meson/gxbb.c    | 474 +++++++++++++++++++++-----------------------
>  drivers/clk/meson/gxbb.h    |  10 +-
>  drivers/clk/meson/meson8b.c | 148 +++++++-------
>  drivers/clk/meson/meson8b.h |   5 +-
>  8 files changed, 480 insertions(+), 493 deletions(-)
> 
> diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
> index 6d8976554656..572358062459 100644
> --- a/drivers/clk/meson/axg.c
> +++ b/drivers/clk/meson/axg.c
> @@ -22,7 +22,7 @@
>  
>  static DEFINE_SPINLOCK(meson_clk_lock);
>  
> -static struct clk_regmap axg_fixed_pll = {
> +static struct clk_regmap axg_fixed_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_MPLL_CNTL,
> @@ -39,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_MPLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.frac = {
>  			.reg_off = HHI_MPLL_CNTL2,
>  			.shift   = 0,
> @@ -61,14 +56,29 @@ static struct clk_regmap axg_fixed_pll = {
>  		},
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "fixed_pll",
> +		.name = "fixed_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
>  	},
>  };
>  
> -static struct clk_regmap axg_sys_pll = {
> +static struct clk_regmap axg_fixed_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_MPLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "fixed_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "fixed_pll_dco" },
> +		.num_parents = 1,
> +	},
> +};
> +
> +static struct clk_regmap axg_sys_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
> @@ -85,11 +95,6 @@ static struct clk_regmap axg_sys_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_SYS_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.l = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
>  			.shift   = 31,
> @@ -102,7 +107,7 @@ static struct clk_regmap axg_sys_pll = {
>  		},
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "sys_pll",
> +		.name = "sys_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -110,94 +115,51 @@ static struct clk_regmap axg_sys_pll = {
>  	},
>  };
>  
> +static struct clk_regmap axg_sys_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_SYS_PLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "sys_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "sys_pll_dco" },
> +		.num_parents = 1,
> +	},
> +};
> +
>  static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
> -	PLL_RATE(240000000, 40, 1, 2),
> -	PLL_RATE(246000000, 41, 1, 2),
> -	PLL_RATE(252000000, 42, 1, 2),
> -	PLL_RATE(258000000, 43, 1, 2),
> -	PLL_RATE(264000000, 44, 1, 2),
> -	PLL_RATE(270000000, 45, 1, 2),
> -	PLL_RATE(276000000, 46, 1, 2),
> -	PLL_RATE(282000000, 47, 1, 2),
> -	PLL_RATE(288000000, 48, 1, 2),
> -	PLL_RATE(294000000, 49, 1, 2),
> -	PLL_RATE(300000000, 50, 1, 2),
> -	PLL_RATE(306000000, 51, 1, 2),
> -	PLL_RATE(312000000, 52, 1, 2),
> -	PLL_RATE(318000000, 53, 1, 2),
> -	PLL_RATE(324000000, 54, 1, 2),
> -	PLL_RATE(330000000, 55, 1, 2),
> -	PLL_RATE(336000000, 56, 1, 2),
> -	PLL_RATE(342000000, 57, 1, 2),
> -	PLL_RATE(348000000, 58, 1, 2),
> -	PLL_RATE(354000000, 59, 1, 2),
> -	PLL_RATE(360000000, 60, 1, 2),
> -	PLL_RATE(366000000, 61, 1, 2),
> -	PLL_RATE(372000000, 62, 1, 2),
> -	PLL_RATE(378000000, 63, 1, 2),
> -	PLL_RATE(384000000, 64, 1, 2),
> -	PLL_RATE(390000000, 65, 1, 3),
> -	PLL_RATE(396000000, 66, 1, 3),
> -	PLL_RATE(402000000, 67, 1, 3),
> -	PLL_RATE(408000000, 68, 1, 3),
> -	PLL_RATE(480000000, 40, 1, 1),
> -	PLL_RATE(492000000, 41, 1, 1),
> -	PLL_RATE(504000000, 42, 1, 1),
> -	PLL_RATE(516000000, 43, 1, 1),
> -	PLL_RATE(528000000, 44, 1, 1),
> -	PLL_RATE(540000000, 45, 1, 1),
> -	PLL_RATE(552000000, 46, 1, 1),
> -	PLL_RATE(564000000, 47, 1, 1),
> -	PLL_RATE(576000000, 48, 1, 1),
> -	PLL_RATE(588000000, 49, 1, 1),
> -	PLL_RATE(600000000, 50, 1, 1),
> -	PLL_RATE(612000000, 51, 1, 1),
> -	PLL_RATE(624000000, 52, 1, 1),
> -	PLL_RATE(636000000, 53, 1, 1),
> -	PLL_RATE(648000000, 54, 1, 1),
> -	PLL_RATE(660000000, 55, 1, 1),
> -	PLL_RATE(672000000, 56, 1, 1),
> -	PLL_RATE(684000000, 57, 1, 1),
> -	PLL_RATE(696000000, 58, 1, 1),
> -	PLL_RATE(708000000, 59, 1, 1),
> -	PLL_RATE(720000000, 60, 1, 1),
> -	PLL_RATE(732000000, 61, 1, 1),
> -	PLL_RATE(744000000, 62, 1, 1),
> -	PLL_RATE(756000000, 63, 1, 1),
> -	PLL_RATE(768000000, 64, 1, 1),
> -	PLL_RATE(780000000, 65, 1, 1),
> -	PLL_RATE(792000000, 66, 1, 1),
> -	PLL_RATE(804000000, 67, 1, 1),
> -	PLL_RATE(816000000, 68, 1, 1),
> -	PLL_RATE(960000000, 40, 1, 0),
> -	PLL_RATE(984000000, 41, 1, 0),
> -	PLL_RATE(1008000000, 42, 1, 0),
> -	PLL_RATE(1032000000, 43, 1, 0),
> -	PLL_RATE(1056000000, 44, 1, 0),
> -	PLL_RATE(1080000000, 45, 1, 0),
> -	PLL_RATE(1104000000, 46, 1, 0),
> -	PLL_RATE(1128000000, 47, 1, 0),
> -	PLL_RATE(1152000000, 48, 1, 0),
> -	PLL_RATE(1176000000, 49, 1, 0),
> -	PLL_RATE(1200000000, 50, 1, 0),
> -	PLL_RATE(1224000000, 51, 1, 0),
> -	PLL_RATE(1248000000, 52, 1, 0),
> -	PLL_RATE(1272000000, 53, 1, 0),
> -	PLL_RATE(1296000000, 54, 1, 0),
> -	PLL_RATE(1320000000, 55, 1, 0),
> -	PLL_RATE(1344000000, 56, 1, 0),
> -	PLL_RATE(1368000000, 57, 1, 0),
> -	PLL_RATE(1392000000, 58, 1, 0),
> -	PLL_RATE(1416000000, 59, 1, 0),
> -	PLL_RATE(1440000000, 60, 1, 0),
> -	PLL_RATE(1464000000, 61, 1, 0),
> -	PLL_RATE(1488000000, 62, 1, 0),
> -	PLL_RATE(1512000000, 63, 1, 0),
> -	PLL_RATE(1536000000, 64, 1, 0),
> -	PLL_RATE(1560000000, 65, 1, 0),
> -	PLL_RATE(1584000000, 66, 1, 0),
> -	PLL_RATE(1608000000, 67, 1, 0),
> -	PLL_RATE(1632000000, 68, 1, 0),
> +	PLL_RATE(960000000, 40, 1),
> +	PLL_RATE(984000000, 41, 1),
> +	PLL_RATE(1008000000, 42, 1),
> +	PLL_RATE(1032000000, 43, 1),
> +	PLL_RATE(1056000000, 44, 1),
> +	PLL_RATE(1080000000, 45, 1),
> +	PLL_RATE(1104000000, 46, 1),
> +	PLL_RATE(1128000000, 47, 1),
> +	PLL_RATE(1152000000, 48, 1),
> +	PLL_RATE(1176000000, 49, 1),
> +	PLL_RATE(1200000000, 50, 1),
> +	PLL_RATE(1224000000, 51, 1),
> +	PLL_RATE(1248000000, 52, 1),
> +	PLL_RATE(1272000000, 53, 1),
> +	PLL_RATE(1296000000, 54, 1),
> +	PLL_RATE(1320000000, 55, 1),
> +	PLL_RATE(1344000000, 56, 1),
> +	PLL_RATE(1368000000, 57, 1),
> +	PLL_RATE(1392000000, 58, 1),
> +	PLL_RATE(1416000000, 59, 1),
> +	PLL_RATE(1440000000, 60, 1),
> +	PLL_RATE(1464000000, 61, 1),
> +	PLL_RATE(1488000000, 62, 1),
> +	PLL_RATE(1512000000, 63, 1),
> +	PLL_RATE(1536000000, 64, 1),
> +	PLL_RATE(1560000000, 65, 1),
> +	PLL_RATE(1584000000, 66, 1),
> +	PLL_RATE(1608000000, 67, 1),
> +	PLL_RATE(1632000000, 68, 1),
>  	{ /* sentinel */ },
>  };
>  
> @@ -209,7 +171,7 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
>  	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
>  };
>  
> -static struct clk_regmap axg_gp0_pll = {
> +static struct clk_regmap axg_gp0_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_GP0_PLL_CNTL,
> @@ -226,11 +188,6 @@ static struct clk_regmap axg_gp0_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_GP0_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.frac = {
>  			.reg_off = HHI_GP0_PLL_CNTL1,
>  			.shift   = 0,
> @@ -251,13 +208,29 @@ static struct clk_regmap axg_gp0_pll = {
>  		.init_count = ARRAY_SIZE(axg_gp0_init_regs),
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "gp0_pll",
> +		.name = "gp0_pll_dco",
>  		.ops = &meson_clk_pll_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
>  	},
>  };
>  
> +static struct clk_regmap axg_gp0_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_GP0_PLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "gp0_pll",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_names = (const char *[]){ "gp0_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
>  static const struct reg_sequence axg_hifi_init_regs[] = {
>  	{ .reg = HHI_HIFI_PLL_CNTL1,	.def = 0xc084b000 },
>  	{ .reg = HHI_HIFI_PLL_CNTL2,	.def = 0xb75020be },
> @@ -266,7 +239,7 @@ static const struct reg_sequence axg_hifi_init_regs[] = {
>  	{ .reg = HHI_HIFI_PLL_CNTL5,	.def = 0x00058000 },
>  };
>  
> -static struct clk_regmap axg_hifi_pll = {
> +static struct clk_regmap axg_hifi_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_HIFI_PLL_CNTL,
> @@ -283,11 +256,6 @@ static struct clk_regmap axg_hifi_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_HIFI_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.frac = {
>  			.reg_off = HHI_HIFI_PLL_CNTL5,
>  			.shift   = 0,
> @@ -309,13 +277,29 @@ static struct clk_regmap axg_hifi_pll = {
>  		.flags = CLK_MESON_PLL_ROUND_CLOSEST,
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "hifi_pll",
> +		.name = "hifi_pll_dco",
>  		.ops = &meson_clk_pll_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
>  	},
>  };
>  
> +static struct clk_regmap axg_hifi_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_HIFI_PLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hifi_pll",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_names = (const char *[]){ "hifi_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
>  static struct clk_fixed_factor axg_fclk_div2_div = {
>  	.mult = 1,
>  	.div = 2,
> @@ -645,11 +629,9 @@ static struct clk_regmap axg_mpll3 = {
>  
>  static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
>  	{
> -		.rate	= 100000000,
> +		.rate	= 1600000000,
>  		.m	= 200,
>  		.n	= 3,
> -		.od	= 1,
> -		.od2	= 3,
>  	},
>  	{ /* sentinel */ },
>  };
> @@ -661,9 +643,10 @@ static const struct reg_sequence axg_pcie_init_regs[] = {
>  	{ .reg = HHI_PCIE_PLL_CNTL4,	.def = 0xc000004d },
>  	{ .reg = HHI_PCIE_PLL_CNTL5,	.def = 0x00078000 },
>  	{ .reg = HHI_PCIE_PLL_CNTL6,	.def = 0x002323c6 },
> +	{ .reg = HHI_PCIE_PLL_CNTL,     .def = 0x400106c8 },
>  };
>  
> -static struct clk_regmap axg_pcie_pll = {
> +static struct clk_regmap axg_pcie_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_PCIE_PLL_CNTL,
> @@ -680,16 +663,6 @@ static struct clk_regmap axg_pcie_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_PCIE_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
> -		.od2 = {
> -			.reg_off = HHI_PCIE_PLL_CNTL6,
> -			.shift   = 6,
> -			.width   = 2,
> -		},
>  		.frac = {
>  			.reg_off = HHI_PCIE_PLL_CNTL1,
>  			.shift   = 0,
> @@ -710,13 +683,45 @@ static struct clk_regmap axg_pcie_pll = {
>  		.init_count = ARRAY_SIZE(axg_pcie_init_regs),
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "pcie_pll",
> +		.name = "pcie_pll_dco",
>  		.ops = &meson_clk_pll_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
>  	},
>  };
>  
> +static struct clk_regmap axg_pcie_pll_od = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_PCIE_PLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "pcie_pll_od",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_names = (const char *[]){ "pcie_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
> +static struct clk_regmap axg_pcie_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_PCIE_PLL_CNTL6,
> +		.shift = 6,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "pcie_pll",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_names = (const char *[]){ "pcie_pll_od" },
> +		.num_parents = 1,
> +		.flags = CLK_SET_RATE_PARENT,
> +	},
> +};
> +
>  static struct clk_regmap axg_pcie_mux = {
>  	.data = &(struct clk_regmap_mux_data){
>  		.offset = HHI_PCIE_PLL_CNTL6,
> @@ -1129,6 +1134,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
>  		[CLKID_GEN_CLK_SEL]		= &axg_gen_clk_sel.hw,
>  		[CLKID_GEN_CLK_DIV]		= &axg_gen_clk_div.hw,
>  		[CLKID_GEN_CLK]			= &axg_gen_clk.hw,
> +		[CLKID_SYS_PLL_DCO]		= &axg_sys_pll_dco.hw,
> +		[CLKID_FIXED_PLL_DCO]		= &axg_fixed_pll_dco.hw,
> +		[CLKID_GP0_PLL_DCO]		= &axg_gp0_pll_dco.hw,
> +		[CLKID_HIFI_PLL_DCO]		= &axg_hifi_pll_dco.hw,
> +		[CLKID_PCIE_PLL_DCO]		= &axg_pcie_pll_dco.hw,
> +		[CLKID_PCIE_PLL_OD]		= &axg_pcie_pll_od.hw,
>  		[NR_CLKS]			= NULL,
>  	},
>  	.num = NR_CLKS,
> @@ -1207,6 +1218,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
>  	&axg_fclk_div4,
>  	&axg_fclk_div5,
>  	&axg_fclk_div7,
> +	&axg_pcie_pll_dco,
> +	&axg_pcie_pll_od,
>  	&axg_pcie_pll,
>  	&axg_pcie_mux,
>  	&axg_pcie_ref,
> @@ -1216,6 +1229,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
>  	&axg_gen_clk_sel,
>  	&axg_gen_clk_div,
>  	&axg_gen_clk,
> +	&axg_fixed_pll_dco,
> +	&axg_sys_pll_dco,
> +	&axg_gp0_pll_dco,
> +	&axg_hifi_pll_dco,
> +	&axg_pcie_pll_dco,
> +	&axg_pcie_pll_od,
>  };
>  
>  static const struct of_device_id clkc_match_table[] = {
> diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
> index 1d04144a1b2c..0431dabac629 100644
> --- a/drivers/clk/meson/axg.h
> +++ b/drivers/clk/meson/axg.h
> @@ -133,8 +133,14 @@
>  #define CLKID_PCIE_REF				78
>  #define CLKID_GEN_CLK_SEL			82
>  #define CLKID_GEN_CLK_DIV			83
> +#define CLKID_SYS_PLL_DCO			85
> +#define CLKID_FIXED_PLL_DCO			86
> +#define CLKID_GP0_PLL_DCO			87
> +#define CLKID_HIFI_PLL_DCO			88
> +#define CLKID_PCIE_PLL_DCO			89
> +#define CLKID_PCIE_PLL_OD			90
>  
> -#define NR_CLKS					85
> +#define NR_CLKS					91
>  
>  /* include the CLKIDs that have been made part of the DT binding */
>  #include <dt-bindings/clock/axg-clkc.h>
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 8aaefe67025f..348a866f09eb 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -11,15 +11,19 @@
>   * In the most basic form, a Meson PLL is composed as follows:
>   *
>   *                     PLL
> - *      +------------------------------+
> - *      |                              |
> - * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
> - *      |         ^        ^           |
> - *      +------------------------------+
> - *                |        |
> - *               FREF     VCO
> + *        +--------------------------------+
> + *        |                                |
> + *        |             +--+               |
> + *  in >>-----[ /N ]--->|  |      +-----+  |
> + *        |             |  |------| DCO |---->> out
> + *        |  +--------->|  |      +--v--+  |
> + *        |  |          +--+         |     |
> + *        |  |                       |     |
> + *        |  +--[ *(M + (F/Fmax) ]<--+     |
> + *        |                                |
> + *        +--------------------------------+
>   *
> - * out = in * (m + frac / frac_max) / (n << sum(ods))
> + * out = in * (m + frac / frac_max) / n
>   */
>  
>  #include <linux/clk-provider.h>
> @@ -46,7 +50,6 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
>  					  struct meson_clk_pll_data *pll)
>  {
>  	u64 rate = (u64)parent_rate * pllt->m;
> -	unsigned int od = pllt->od + pllt->od2 + pllt->od3;
>  
>  	if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
>  		u64 frac_rate = (u64)parent_rate * frac;
> @@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
>  					 (1 << pll->frac.width));
>  	}
>  
> -	return DIV_ROUND_UP_ULL(rate, pllt->n << od);
> +	return DIV_ROUND_UP_ULL(rate, pllt->n);
>  }
>  
>  static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
> @@ -68,15 +71,6 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
>  
>  	pllt.n = meson_parm_read(clk->map, &pll->n);
>  	pllt.m = meson_parm_read(clk->map, &pll->m);
> -	pllt.od = meson_parm_read(clk->map, &pll->od);
> -
> -	pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
> -		meson_parm_read(clk->map, &pll->od2) :
> -		0;
> -
> -	pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
> -		meson_parm_read(clk->map, &pll->od3) :
> -		0;
>  
>  	frac = MESON_PARM_APPLICABLE(&pll->frac) ?
>  		meson_parm_read(clk->map, &pll->frac) :
> @@ -93,8 +87,6 @@ static u16 __pll_params_with_frac(unsigned long rate,
>  	u16 frac_max = (1 << pll->frac.width);
>  	u64 val = (u64)rate * pllt->n;
>  
> -	val <<= pllt->od + pllt->od2 + pllt->od3;
> -
>  	if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
>  		val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
>  	else
> @@ -242,13 +234,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>  
>  	meson_parm_write(clk->map, &pll->n, pllt->n);
>  	meson_parm_write(clk->map, &pll->m, pllt->m);
> -	meson_parm_write(clk->map, &pll->od, pllt->od);
> -
> -	if (MESON_PARM_APPLICABLE(&pll->od2))
> -		meson_parm_write(clk->map, &pll->od2, pllt->od2);
>  
> -	if (MESON_PARM_APPLICABLE(&pll->od3))
> -		meson_parm_write(clk->map, &pll->od3, pllt->od3);
>  
>  	if (MESON_PARM_APPLICABLE(&pll->frac)) {
>  		frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> index c2ee37a78ceb..a2245e857f70 100644
> --- a/drivers/clk/meson/clkc.h
> +++ b/drivers/clk/meson/clkc.h
> @@ -47,17 +47,13 @@ struct pll_rate_table {
>  	unsigned long	rate;
>  	u16		m;
>  	u16		n;
> -	u16		od;
> -	u16		od2;
> -	u16		od3;
>  };
>  
> -#define PLL_RATE(_r, _m, _n, _od)					\
> +#define PLL_RATE(_r, _m, _n)						\
>  	{								\
>  		.rate		= (_r),					\
>  		.m		= (_m),					\
>  		.n		= (_n),					\
> -		.od		= (_od),				\
>  	}
>  
>  #define CLK_MESON_PLL_ROUND_CLOSEST	BIT(0)
> @@ -67,9 +63,6 @@ struct meson_clk_pll_data {
>  	struct parm m;
>  	struct parm n;
>  	struct parm frac;
> -	struct parm od;
> -	struct parm od2;
> -	struct parm od3;
>  	struct parm l;
>  	struct parm rst;
>  	const struct reg_sequence *init_regs;
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index 5ed34566917c..e2d94498f098 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -19,163 +19,70 @@
>  static DEFINE_SPINLOCK(meson_clk_lock);
>  
>  static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
> -	PLL_RATE(96000000, 32, 1, 3),
> -	PLL_RATE(99000000, 33, 1, 3),
> -	PLL_RATE(102000000, 34, 1, 3),
> -	PLL_RATE(105000000, 35, 1, 3),
> -	PLL_RATE(108000000, 36, 1, 3),
> -	PLL_RATE(111000000, 37, 1, 3),
> -	PLL_RATE(114000000, 38, 1, 3),
> -	PLL_RATE(117000000, 39, 1, 3),
> -	PLL_RATE(120000000, 40, 1, 3),
> -	PLL_RATE(123000000, 41, 1, 3),
> -	PLL_RATE(126000000, 42, 1, 3),
> -	PLL_RATE(129000000, 43, 1, 3),
> -	PLL_RATE(132000000, 44, 1, 3),
> -	PLL_RATE(135000000, 45, 1, 3),
> -	PLL_RATE(138000000, 46, 1, 3),
> -	PLL_RATE(141000000, 47, 1, 3),
> -	PLL_RATE(144000000, 48, 1, 3),
> -	PLL_RATE(147000000, 49, 1, 3),
> -	PLL_RATE(150000000, 50, 1, 3),
> -	PLL_RATE(153000000, 51, 1, 3),
> -	PLL_RATE(156000000, 52, 1, 3),
> -	PLL_RATE(159000000, 53, 1, 3),
> -	PLL_RATE(162000000, 54, 1, 3),
> -	PLL_RATE(165000000, 55, 1, 3),
> -	PLL_RATE(168000000, 56, 1, 3),
> -	PLL_RATE(171000000, 57, 1, 3),
> -	PLL_RATE(174000000, 58, 1, 3),
> -	PLL_RATE(177000000, 59, 1, 3),
> -	PLL_RATE(180000000, 60, 1, 3),
> -	PLL_RATE(183000000, 61, 1, 3),
> -	PLL_RATE(186000000, 62, 1, 3),
> -	PLL_RATE(192000000, 32, 1, 2),
> -	PLL_RATE(198000000, 33, 1, 2),
> -	PLL_RATE(204000000, 34, 1, 2),
> -	PLL_RATE(210000000, 35, 1, 2),
> -	PLL_RATE(216000000, 36, 1, 2),
> -	PLL_RATE(222000000, 37, 1, 2),
> -	PLL_RATE(228000000, 38, 1, 2),
> -	PLL_RATE(234000000, 39, 1, 2),
> -	PLL_RATE(240000000, 40, 1, 2),
> -	PLL_RATE(246000000, 41, 1, 2),
> -	PLL_RATE(252000000, 42, 1, 2),
> -	PLL_RATE(258000000, 43, 1, 2),
> -	PLL_RATE(264000000, 44, 1, 2),
> -	PLL_RATE(270000000, 45, 1, 2),
> -	PLL_RATE(276000000, 46, 1, 2),
> -	PLL_RATE(282000000, 47, 1, 2),
> -	PLL_RATE(288000000, 48, 1, 2),
> -	PLL_RATE(294000000, 49, 1, 2),
> -	PLL_RATE(300000000, 50, 1, 2),
> -	PLL_RATE(306000000, 51, 1, 2),
> -	PLL_RATE(312000000, 52, 1, 2),
> -	PLL_RATE(318000000, 53, 1, 2),
> -	PLL_RATE(324000000, 54, 1, 2),
> -	PLL_RATE(330000000, 55, 1, 2),
> -	PLL_RATE(336000000, 56, 1, 2),
> -	PLL_RATE(342000000, 57, 1, 2),
> -	PLL_RATE(348000000, 58, 1, 2),
> -	PLL_RATE(354000000, 59, 1, 2),
> -	PLL_RATE(360000000, 60, 1, 2),
> -	PLL_RATE(366000000, 61, 1, 2),
> -	PLL_RATE(372000000, 62, 1, 2),
> -	PLL_RATE(384000000, 32, 1, 1),
> -	PLL_RATE(396000000, 33, 1, 1),
> -	PLL_RATE(408000000, 34, 1, 1),
> -	PLL_RATE(420000000, 35, 1, 1),
> -	PLL_RATE(432000000, 36, 1, 1),
> -	PLL_RATE(444000000, 37, 1, 1),
> -	PLL_RATE(456000000, 38, 1, 1),
> -	PLL_RATE(468000000, 39, 1, 1),
> -	PLL_RATE(480000000, 40, 1, 1),
> -	PLL_RATE(492000000, 41, 1, 1),
> -	PLL_RATE(504000000, 42, 1, 1),
> -	PLL_RATE(516000000, 43, 1, 1),
> -	PLL_RATE(528000000, 44, 1, 1),
> -	PLL_RATE(540000000, 45, 1, 1),
> -	PLL_RATE(552000000, 46, 1, 1),
> -	PLL_RATE(564000000, 47, 1, 1),
> -	PLL_RATE(576000000, 48, 1, 1),
> -	PLL_RATE(588000000, 49, 1, 1),
> -	PLL_RATE(600000000, 50, 1, 1),
> -	PLL_RATE(612000000, 51, 1, 1),
> -	PLL_RATE(624000000, 52, 1, 1),
> -	PLL_RATE(636000000, 53, 1, 1),
> -	PLL_RATE(648000000, 54, 1, 1),
> -	PLL_RATE(660000000, 55, 1, 1),
> -	PLL_RATE(672000000, 56, 1, 1),
> -	PLL_RATE(684000000, 57, 1, 1),
> -	PLL_RATE(696000000, 58, 1, 1),
> -	PLL_RATE(708000000, 59, 1, 1),
> -	PLL_RATE(720000000, 60, 1, 1),
> -	PLL_RATE(732000000, 61, 1, 1),
> -	PLL_RATE(744000000, 62, 1, 1),
> -	PLL_RATE(768000000, 32, 1, 0),
> -	PLL_RATE(792000000, 33, 1, 0),
> -	PLL_RATE(816000000, 34, 1, 0),
> -	PLL_RATE(840000000, 35, 1, 0),
> -	PLL_RATE(864000000, 36, 1, 0),
> -	PLL_RATE(888000000, 37, 1, 0),
> -	PLL_RATE(912000000, 38, 1, 0),
> -	PLL_RATE(936000000, 39, 1, 0),
> -	PLL_RATE(960000000, 40, 1, 0),
> -	PLL_RATE(984000000, 41, 1, 0),
> -	PLL_RATE(1008000000, 42, 1, 0),
> -	PLL_RATE(1032000000, 43, 1, 0),
> -	PLL_RATE(1056000000, 44, 1, 0),
> -	PLL_RATE(1080000000, 45, 1, 0),
> -	PLL_RATE(1104000000, 46, 1, 0),
> -	PLL_RATE(1128000000, 47, 1, 0),
> -	PLL_RATE(1152000000, 48, 1, 0),
> -	PLL_RATE(1176000000, 49, 1, 0),
> -	PLL_RATE(1200000000, 50, 1, 0),
> -	PLL_RATE(1224000000, 51, 1, 0),
> -	PLL_RATE(1248000000, 52, 1, 0),
> -	PLL_RATE(1272000000, 53, 1, 0),
> -	PLL_RATE(1296000000, 54, 1, 0),
> -	PLL_RATE(1320000000, 55, 1, 0),
> -	PLL_RATE(1344000000, 56, 1, 0),
> -	PLL_RATE(1368000000, 57, 1, 0),
> -	PLL_RATE(1392000000, 58, 1, 0),
> -	PLL_RATE(1416000000, 59, 1, 0),
> -	PLL_RATE(1440000000, 60, 1, 0),
> -	PLL_RATE(1464000000, 61, 1, 0),
> -	PLL_RATE(1488000000, 62, 1, 0),
> +	PLL_RATE(768000000, 32, 1),
> +	PLL_RATE(792000000, 33, 1),
> +	PLL_RATE(816000000, 34, 1),
> +	PLL_RATE(840000000, 35, 1),
> +	PLL_RATE(864000000, 36, 1),
> +	PLL_RATE(888000000, 37, 1),
> +	PLL_RATE(912000000, 38, 1),
> +	PLL_RATE(936000000, 39, 1),
> +	PLL_RATE(960000000, 40, 1),
> +	PLL_RATE(984000000, 41, 1),
> +	PLL_RATE(1008000000, 42, 1),
> +	PLL_RATE(1032000000, 43, 1),
> +	PLL_RATE(1056000000, 44, 1),
> +	PLL_RATE(1080000000, 45, 1),
> +	PLL_RATE(1104000000, 46, 1),
> +	PLL_RATE(1128000000, 47, 1),
> +	PLL_RATE(1152000000, 48, 1),
> +	PLL_RATE(1176000000, 49, 1),
> +	PLL_RATE(1200000000, 50, 1),
> +	PLL_RATE(1224000000, 51, 1),
> +	PLL_RATE(1248000000, 52, 1),
> +	PLL_RATE(1272000000, 53, 1),
> +	PLL_RATE(1296000000, 54, 1),
> +	PLL_RATE(1320000000, 55, 1),
> +	PLL_RATE(1344000000, 56, 1),
> +	PLL_RATE(1368000000, 57, 1),
> +	PLL_RATE(1392000000, 58, 1),
> +	PLL_RATE(1416000000, 59, 1),
> +	PLL_RATE(1440000000, 60, 1),
> +	PLL_RATE(1464000000, 61, 1),
> +	PLL_RATE(1488000000, 62, 1),
>  	{ /* sentinel */ },
>  };
>  
>  static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
> -	PLL_RATE(504000000, 42, 1, 1),
> -	PLL_RATE(516000000, 43, 1, 1),
> -	PLL_RATE(528000000, 44, 1, 1),
> -	PLL_RATE(540000000, 45, 1, 1),
> -	PLL_RATE(552000000, 46, 1, 1),
> -	PLL_RATE(564000000, 47, 1, 1),
> -	PLL_RATE(576000000, 48, 1, 1),
> -	PLL_RATE(588000000, 49, 1, 1),
> -	PLL_RATE(600000000, 50, 1, 1),
> -	PLL_RATE(612000000, 51, 1, 1),
> -	PLL_RATE(624000000, 52, 1, 1),
> -	PLL_RATE(636000000, 53, 1, 1),
> -	PLL_RATE(648000000, 54, 1, 1),
> -	PLL_RATE(660000000, 55, 1, 1),
> -	PLL_RATE(672000000, 56, 1, 1),
> -	PLL_RATE(684000000, 57, 1, 1),
> -	PLL_RATE(696000000, 58, 1, 1),
> -	PLL_RATE(708000000, 59, 1, 1),
> -	PLL_RATE(720000000, 60, 1, 1),
> -	PLL_RATE(732000000, 61, 1, 1),
> -	PLL_RATE(744000000, 62, 1, 1),
> -	PLL_RATE(756000000, 63, 1, 1),
> -	PLL_RATE(768000000, 64, 1, 1),
> -	PLL_RATE(780000000, 65, 1, 1),
> -	PLL_RATE(792000000, 66, 1, 1),
> +	PLL_RATE(1008000000, 42, 1),
> +	PLL_RATE(1032000000, 43, 1),
> +	PLL_RATE(1056000000, 44, 1),
> +	PLL_RATE(1080000000, 45, 1),
> +	PLL_RATE(1104000000, 46, 1),
> +	PLL_RATE(1128000000, 47, 1),
> +	PLL_RATE(1152000000, 48, 1),
> +	PLL_RATE(1176000000, 49, 1),
> +	PLL_RATE(1200000000, 50, 1),
> +	PLL_RATE(1224000000, 51, 1),
> +	PLL_RATE(1248000000, 52, 1),
> +	PLL_RATE(1272000000, 53, 1),
> +	PLL_RATE(1296000000, 54, 1),
> +	PLL_RATE(1320000000, 55, 1),
> +	PLL_RATE(1344000000, 56, 1),
> +	PLL_RATE(1368000000, 57, 1),
> +	PLL_RATE(1392000000, 58, 1),
> +	PLL_RATE(1416000000, 59, 1),
> +	PLL_RATE(1440000000, 60, 1),
> +	PLL_RATE(1464000000, 61, 1),
> +	PLL_RATE(1488000000, 62, 1),
> +	PLL_RATE(1512000000, 63, 1),
> +	PLL_RATE(1536000000, 64, 1),
> +	PLL_RATE(1560000000, 65, 1),
> +	PLL_RATE(1584000000, 66, 1),
>  	{ /* sentinel */ },
>  };
>  
> -static struct clk_regmap gxbb_fixed_pll = {
> +static struct clk_regmap gxbb_fixed_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_MPLL_CNTL,
> @@ -192,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_MPLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.frac = {
>  			.reg_off = HHI_MPLL_CNTL2,
>  			.shift   = 0,
> @@ -214,7 +116,7 @@ static struct clk_regmap gxbb_fixed_pll = {
>  		},
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "fixed_pll",
> +		.name = "fixed_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -222,6 +124,21 @@ static struct clk_regmap gxbb_fixed_pll = {
>  	},
>  };
>  
> +static struct clk_regmap gxbb_fixed_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_MPLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "fixed_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "fixed_pll_dco" },
> +		.num_parents = 1,
> +	},
> +};
> +
>  static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
>  	.mult = 2,
>  	.div = 1,
> @@ -233,7 +150,7 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
>  	},
>  };
>  
> -static struct clk_regmap gxbb_hdmi_pll = {
> +static struct clk_regmap gxbb_hdmi_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_HDMI_PLL_CNTL,
> @@ -255,21 +172,6 @@ static struct clk_regmap gxbb_hdmi_pll = {
>  			.shift   = 0,
>  			.width   = 12,
>  		},
> -		.od = {
> -			.reg_off = HHI_HDMI_PLL_CNTL2,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
> -		.od2 = {
> -			.reg_off = HHI_HDMI_PLL_CNTL2,
> -			.shift   = 22,
> -			.width   = 2,
> -		},
> -		.od3 = {
> -			.reg_off = HHI_HDMI_PLL_CNTL2,
> -			.shift   = 18,
> -			.width   = 2,
> -		},
>  		.l = {
>  			.reg_off = HHI_HDMI_PLL_CNTL,
>  			.shift   = 31,
> @@ -282,7 +184,7 @@ static struct clk_regmap gxbb_hdmi_pll = {
>  		},
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "hdmi_pll",
> +		.name = "hdmi_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
>  		.num_parents = 1,
> @@ -290,70 +192,103 @@ static struct clk_regmap gxbb_hdmi_pll = {
>  	},
>  };
>  
> +static struct clk_regmap gxbb_hdmi_pll_od = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_HDMI_PLL_CNTL2,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmi_pll_od",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "hdmi_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};
> +
> +static struct clk_regmap gxbb_hdmi_pll_od2 = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_HDMI_PLL_CNTL2,
> +		.shift = 22,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmi_pll_od2",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "hdmi_pll_od" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};
> +
> +static struct clk_regmap gxbb_hdmi_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_HDMI_PLL_CNTL2,
> +		.shift = 18,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmi_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "hdmi_pll_od2" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};
> +
> +static struct clk_regmap gxl_hdmi_pll_od = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_HDMI_PLL_CNTL + 8,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmi_pll_od",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "hdmi_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};

In my code, the GXL OD1 is at bit 21

> +
> +static struct clk_regmap gxl_hdmi_pll_od2 = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_HDMI_PLL_CNTL + 8,
> +		.shift = 22,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "hdmi_pll_od2",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "hdmi_pll_od" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};


In my code, the GXL OD3 is at bit 23

> +
>  static struct clk_regmap gxl_hdmi_pll = {
> -	.data = &(struct meson_clk_pll_data){
> -		.en = {
> -			.reg_off = HHI_HDMI_PLL_CNTL,
> -			.shift   = 30,
> -			.width   = 1,
> -		},
> -		.m = {
> -			.reg_off = HHI_HDMI_PLL_CNTL,
> -			.shift   = 0,
> -			.width   = 9,
> -		},
> -		.n = {
> -			.reg_off = HHI_HDMI_PLL_CNTL,
> -			.shift   = 9,
> -			.width   = 5,
> -		},
> -		.frac = {
> -			/*
> -			 * On gxl, there is a register shift due to
> -			 * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
> -			 * so we compute the register offset based on the PLL
> -			 * base to get it right
> -			 */
> -			.reg_off = HHI_HDMI_PLL_CNTL + 4,
> -			.shift   = 0,
> -			.width   = 12,
> -		},
> -		.od = {
> -			.reg_off = HHI_HDMI_PLL_CNTL + 8,
> -			.shift   = 21,
> -			.width   = 2,
> -		},
> -		.od2 = {
> -			.reg_off = HHI_HDMI_PLL_CNTL + 8,
> -			.shift   = 23,
> -			.width   = 2,
> -		},
> -		.od3 = {
> -			.reg_off = HHI_HDMI_PLL_CNTL + 8,
> -			.shift   = 19,
> -			.width   = 2,
> -		},
> -		.l = {
> -			.reg_off = HHI_HDMI_PLL_CNTL,
> -			.shift   = 31,
> -			.width   = 1,
> -		},
> -		.rst = {
> -			.reg_off = HHI_HDMI_PLL_CNTL,
> -			.shift   = 29,
> -			.width   = 1,
> -		},
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_HDMI_PLL_CNTL + 8,
> +		.shift = 18,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,


In my code, the GXL OD3 is at bit 19

It's only a copy/paste error, the original code had the correct shifts.

>  	},
>  	.hw.init = &(struct clk_init_data){
>  		.name = "hdmi_pll",
> -		.ops = &meson_clk_pll_ro_ops,
> -		.parent_names = (const char *[]){ "xtal" },
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "hdmi_pll_od2" },
>  		.num_parents = 1,
>  		.flags = CLK_GET_RATE_NOCACHE,
>  	},
>  };
>  
> -static struct clk_regmap gxbb_sys_pll = {
> +static struct clk_regmap gxbb_sys_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
> @@ -370,11 +305,6 @@ static struct clk_regmap gxbb_sys_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_SYS_PLL_CNTL,
> -			.shift   = 10,
> -			.width   = 2,
> -		},
>  		.l = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
>  			.shift   = 31,
> @@ -387,7 +317,7 @@ static struct clk_regmap gxbb_sys_pll = {
>  		},
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "sys_pll",
> +		.name = "sys_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -395,13 +325,29 @@ static struct clk_regmap gxbb_sys_pll = {
>  	},
>  };
>  
> +static struct clk_regmap gxbb_sys_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_SYS_PLL_CNTL,
> +		.shift = 10,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "sys_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "sys_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};
> +
>  static const struct reg_sequence gxbb_gp0_init_regs[] = {
>  	{ .reg = HHI_GP0_PLL_CNTL2,	.def = 0x69c80000 },
>  	{ .reg = HHI_GP0_PLL_CNTL3,	.def = 0x0a5590c4 },
>  	{ .reg = HHI_GP0_PLL_CNTL4,	.def = 0x0000500d },
>  };
>  
> -static struct clk_regmap gxbb_gp0_pll = {
> +static struct clk_regmap gxbb_gp0_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_GP0_PLL_CNTL,
> @@ -418,11 +364,6 @@ static struct clk_regmap gxbb_gp0_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_GP0_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.l = {
>  			.reg_off = HHI_GP0_PLL_CNTL,
>  			.shift   = 31,
> @@ -438,7 +379,7 @@ static struct clk_regmap gxbb_gp0_pll = {
>  		.init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "gp0_pll",
> +		.name = "gp0_pll_dco",
>  		.ops = &meson_clk_pll_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -454,7 +395,7 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
>  	{ .reg = HHI_GP0_PLL_CNTL5,	.def = 0x00078000 },
>  };
>  
> -static struct clk_regmap gxl_gp0_pll = {
> +static struct clk_regmap gxl_gp0_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_GP0_PLL_CNTL,
> @@ -471,11 +412,6 @@ static struct clk_regmap gxl_gp0_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_GP0_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.frac = {
>  			.reg_off = HHI_GP0_PLL_CNTL1,
>  			.shift   = 0,
> @@ -496,7 +432,7 @@ static struct clk_regmap gxl_gp0_pll = {
>  		.init_count = ARRAY_SIZE(gxl_gp0_init_regs),
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "gp0_pll",
> +		.name = "gp0_pll_dco",
>  		.ops = &meson_clk_pll_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -504,6 +440,22 @@ static struct clk_regmap gxl_gp0_pll = {
>  	},
>  };
>  
> +static struct clk_regmap gxbb_gp0_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_GP0_PLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "gp0_pll",
> +		.ops = &clk_regmap_divider_ops,
> +		.parent_names = (const char *[]){ "gp0_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
> +	},
> +};
> +
>  static struct clk_fixed_factor gxbb_fclk_div2_div = {
>  	.mult = 1,
>  	.div = 2,
> @@ -1961,6 +1913,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
>  		[CLKID_GEN_CLK_SEL]	    = &gxbb_gen_clk_sel.hw,
>  		[CLKID_GEN_CLK_DIV]	    = &gxbb_gen_clk_div.hw,
>  		[CLKID_GEN_CLK]		    = &gxbb_gen_clk.hw,
> +		[CLKID_FIXED_PLL_DCO]	    = &gxbb_fixed_pll_dco.hw,
> +		[CLKID_HDMI_PLL_DCO]	    = &gxbb_hdmi_pll_dco.hw,
> +		[CLKID_HDMI_PLL_OD]	    = &gxbb_hdmi_pll_od.hw,
> +		[CLKID_HDMI_PLL_OD2]	    = &gxbb_hdmi_pll_od2.hw,
> +		[CLKID_SYS_PLL_DCO]	    = &gxbb_sys_pll_dco.hw,
> +		[CLKID_GP0_PLL_DCO]	    = &gxbb_gp0_pll_dco.hw,
>  		[NR_CLKS]		    = NULL,
>  	},
>  	.num = NR_CLKS,
> @@ -1976,7 +1934,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
>  		[CLKID_FCLK_DIV4]	    = &gxbb_fclk_div4.hw,
>  		[CLKID_FCLK_DIV5]	    = &gxbb_fclk_div5.hw,
>  		[CLKID_FCLK_DIV7]	    = &gxbb_fclk_div7.hw,
> -		[CLKID_GP0_PLL]		    = &gxl_gp0_pll.hw,
> +		[CLKID_GP0_PLL]		    = &gxbb_gp0_pll.hw,
>  		[CLKID_MPEG_SEL]	    = &gxbb_mpeg_clk_sel.hw,
>  		[CLKID_MPEG_DIV]	    = &gxbb_mpeg_clk_div.hw,
>  		[CLKID_CLK81]		    = &gxbb_clk81.hw,
> @@ -2126,19 +2084,29 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
>  		[CLKID_GEN_CLK_SEL]	    = &gxbb_gen_clk_sel.hw,
>  		[CLKID_GEN_CLK_DIV]	    = &gxbb_gen_clk_div.hw,
>  		[CLKID_GEN_CLK]		    = &gxbb_gen_clk.hw,
> +		[CLKID_FIXED_PLL_DCO]	    = &gxbb_fixed_pll_dco.hw,
> +		[CLKID_HDMI_PLL_DCO]	    = &gxbb_hdmi_pll_dco.hw,
> +		[CLKID_HDMI_PLL_OD]	    = &gxl_hdmi_pll_od.hw,
> +		[CLKID_HDMI_PLL_OD2]	    = &gxl_hdmi_pll_od2.hw,
> +		[CLKID_SYS_PLL_DCO]	    = &gxbb_sys_pll_dco.hw,
> +		[CLKID_GP0_PLL_DCO]	    = &gxl_gp0_pll_dco.hw,
>  		[NR_CLKS]		    = NULL,
>  	},
>  	.num = NR_CLKS,
>  };
>  
>  static struct clk_regmap *const gxbb_clk_regmaps[] = {
> -	&gxbb_gp0_pll,
> +	&gxbb_gp0_pll_dco,
>  	&gxbb_hdmi_pll,
> +	&gxbb_hdmi_pll_od,
> +	&gxbb_hdmi_pll_od2,
>  };
>  
>  static struct clk_regmap *const gxl_clk_regmaps[] = {
> -	&gxl_gp0_pll,
> +	&gxl_gp0_pll_dco,
>  	&gxl_hdmi_pll,
> +	&gxl_hdmi_pll_od,
> +	&gxl_hdmi_pll_od2,
>  };
>  
>  static struct clk_regmap *const gx_clk_regmaps[] = {
> @@ -2293,6 +2261,10 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
>  	&gxbb_gen_clk_sel,
>  	&gxbb_gen_clk_div,
>  	&gxbb_gen_clk,
> +	&gxbb_fixed_pll_dco,
> +	&gxbb_hdmi_pll_dco,
> +	&gxbb_sys_pll_dco,
> +	&gxbb_gp0_pll,
>  };
>  
>  struct clkc_data {
> diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
> index 20dfb1daf5b8..72bc077d9663 100644
> --- a/drivers/clk/meson/gxbb.h
> +++ b/drivers/clk/meson/gxbb.h
> @@ -159,8 +159,14 @@
>  #define CLKID_VDEC_HEVC_DIV	  155
>  #define CLKID_GEN_CLK_SEL	  157
>  #define CLKID_GEN_CLK_DIV	  158
> -
> -#define NR_CLKS			  160
> +#define CLKID_FIXED_PLL_DCO	  160
> +#define CLKID_HDMI_PLL_DCO	  161
> +#define CLKID_HDMI_PLL_OD	  162
> +#define CLKID_HDMI_PLL_OD2	  163
> +#define CLKID_SYS_PLL_DCO	  164
> +#define CLKID_GP0_PLL_DCO	  165
> +
> +#define NR_CLKS			  166
>  
>  /* include the CLKIDs that have been made part of the DT binding */
>  #include <dt-bindings/clock/gxbb-clkc.h>
> diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
> index fd4c414893f5..17bcf0be56ba 100644
> --- a/drivers/clk/meson/meson8b.c
> +++ b/drivers/clk/meson/meson8b.c
> @@ -30,58 +30,21 @@ struct meson8b_clk_reset {
>  };
>  
>  static const struct pll_rate_table sys_pll_rate_table[] = {
> -	PLL_RATE(312000000, 52, 1, 2),
> -	PLL_RATE(336000000, 56, 1, 2),
> -	PLL_RATE(360000000, 60, 1, 2),
> -	PLL_RATE(384000000, 64, 1, 2),
> -	PLL_RATE(408000000, 68, 1, 2),
> -	PLL_RATE(432000000, 72, 1, 2),
> -	PLL_RATE(456000000, 76, 1, 2),
> -	PLL_RATE(480000000, 80, 1, 2),
> -	PLL_RATE(504000000, 84, 1, 2),
> -	PLL_RATE(528000000, 88, 1, 2),
> -	PLL_RATE(552000000, 92, 1, 2),
> -	PLL_RATE(576000000, 96, 1, 2),
> -	PLL_RATE(600000000, 50, 1, 1),
> -	PLL_RATE(624000000, 52, 1, 1),
> -	PLL_RATE(648000000, 54, 1, 1),
> -	PLL_RATE(672000000, 56, 1, 1),
> -	PLL_RATE(696000000, 58, 1, 1),
> -	PLL_RATE(720000000, 60, 1, 1),
> -	PLL_RATE(744000000, 62, 1, 1),
> -	PLL_RATE(768000000, 64, 1, 1),
> -	PLL_RATE(792000000, 66, 1, 1),
> -	PLL_RATE(816000000, 68, 1, 1),
> -	PLL_RATE(840000000, 70, 1, 1),
> -	PLL_RATE(864000000, 72, 1, 1),
> -	PLL_RATE(888000000, 74, 1, 1),
> -	PLL_RATE(912000000, 76, 1, 1),
> -	PLL_RATE(936000000, 78, 1, 1),
> -	PLL_RATE(960000000, 80, 1, 1),
> -	PLL_RATE(984000000, 82, 1, 1),
> -	PLL_RATE(1008000000, 84, 1, 1),
> -	PLL_RATE(1032000000, 86, 1, 1),
> -	PLL_RATE(1056000000, 88, 1, 1),
> -	PLL_RATE(1080000000, 90, 1, 1),
> -	PLL_RATE(1104000000, 92, 1, 1),
> -	PLL_RATE(1128000000, 94, 1, 1),
> -	PLL_RATE(1152000000, 96, 1, 1),
> -	PLL_RATE(1176000000, 98, 1, 1),
> -	PLL_RATE(1200000000, 50, 1, 0),
> -	PLL_RATE(1224000000, 51, 1, 0),
> -	PLL_RATE(1248000000, 52, 1, 0),
> -	PLL_RATE(1272000000, 53, 1, 0),
> -	PLL_RATE(1296000000, 54, 1, 0),
> -	PLL_RATE(1320000000, 55, 1, 0),
> -	PLL_RATE(1344000000, 56, 1, 0),
> -	PLL_RATE(1368000000, 57, 1, 0),
> -	PLL_RATE(1392000000, 58, 1, 0),
> -	PLL_RATE(1416000000, 59, 1, 0),
> -	PLL_RATE(1440000000, 60, 1, 0),
> -	PLL_RATE(1464000000, 61, 1, 0),
> -	PLL_RATE(1488000000, 62, 1, 0),
> -	PLL_RATE(1512000000, 63, 1, 0),
> -	PLL_RATE(1536000000, 64, 1, 0),
> +	PLL_RATE(1200000000, 50, 1),
> +	PLL_RATE(1224000000, 51, 1),
> +	PLL_RATE(1248000000, 52, 1),
> +	PLL_RATE(1272000000, 53, 1),
> +	PLL_RATE(1296000000, 54, 1),
> +	PLL_RATE(1320000000, 55, 1),
> +	PLL_RATE(1344000000, 56, 1),
> +	PLL_RATE(1368000000, 57, 1),
> +	PLL_RATE(1392000000, 58, 1),
> +	PLL_RATE(1416000000, 59, 1),
> +	PLL_RATE(1440000000, 60, 1),
> +	PLL_RATE(1464000000, 61, 1),
> +	PLL_RATE(1488000000, 62, 1),
> +	PLL_RATE(1512000000, 63, 1),
> +	PLL_RATE(1536000000, 64, 1),
>  	{ /* sentinel */ },
>  };
>  
> @@ -94,7 +57,7 @@ static struct clk_fixed_rate meson8b_xtal = {
>  	},
>  };
>  
> -static struct clk_regmap meson8b_fixed_pll = {
> +static struct clk_regmap meson8b_fixed_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_MPLL_CNTL,
> @@ -111,11 +74,6 @@ static struct clk_regmap meson8b_fixed_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_MPLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.frac = {
>  			.reg_off = HHI_MPLL_CNTL2,
>  			.shift   = 0,
> @@ -133,7 +91,7 @@ static struct clk_regmap meson8b_fixed_pll = {
>  		},
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "fixed_pll",
> +		.name = "fixed_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -141,7 +99,23 @@ static struct clk_regmap meson8b_fixed_pll = {
>  	},
>  };
>  
> -static struct clk_regmap meson8b_vid_pll = {
> +static struct clk_regmap meson8b_fixed_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_MPLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "fixed_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "fixed_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};
> +
> +static struct clk_regmap meson8b_vid_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_VID_PLL_CNTL,
> @@ -158,11 +132,6 @@ static struct clk_regmap meson8b_vid_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_VID_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.l = {
>  			.reg_off = HHI_VID_PLL_CNTL,
>  			.shift   = 31,
> @@ -175,7 +144,7 @@ static struct clk_regmap meson8b_vid_pll = {
>  		},
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "vid_pll",
> +		.name = "vid_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -183,7 +152,23 @@ static struct clk_regmap meson8b_vid_pll = {
>  	},
>  };
>  
> -static struct clk_regmap meson8b_sys_pll = {
> +static struct clk_regmap meson8b_vid_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_VID_PLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "vid_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "vid_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};
> +
> +static struct clk_regmap meson8b_sys_pll_dco = {
>  	.data = &(struct meson_clk_pll_data){
>  		.en = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
> @@ -200,11 +185,6 @@ static struct clk_regmap meson8b_sys_pll = {
>  			.shift   = 9,
>  			.width   = 5,
>  		},
> -		.od = {
> -			.reg_off = HHI_SYS_PLL_CNTL,
> -			.shift   = 16,
> -			.width   = 2,
> -		},
>  		.l = {
>  			.reg_off = HHI_SYS_PLL_CNTL,
>  			.shift   = 31,
> @@ -218,7 +198,7 @@ static struct clk_regmap meson8b_sys_pll = {
>  		.table = sys_pll_rate_table,
>  	},
>  	.hw.init = &(struct clk_init_data){
> -		.name = "sys_pll",
> +		.name = "sys_pll_dco",
>  		.ops = &meson_clk_pll_ro_ops,
>  		.parent_names = (const char *[]){ "xtal" },
>  		.num_parents = 1,
> @@ -226,6 +206,22 @@ static struct clk_regmap meson8b_sys_pll = {
>  	},
>  };
>  
> +static struct clk_regmap meson8b_sys_pll = {
> +	.data = &(struct clk_regmap_div_data){
> +		.offset = HHI_SYS_PLL_CNTL,
> +		.shift = 16,
> +		.width = 2,
> +		.flags = CLK_DIVIDER_POWER_OF_TWO,
> +	},
> +	.hw.init = &(struct clk_init_data){
> +		.name = "sys_pll",
> +		.ops = &clk_regmap_divider_ro_ops,
> +		.parent_names = (const char *[]){ "sys_pll_dco" },
> +		.num_parents = 1,
> +		.flags = CLK_GET_RATE_NOCACHE,
> +	},
> +};
> +
>  static struct clk_fixed_factor meson8b_fclk_div2_div = {
>  	.mult = 1,
>  	.div = 2,
> @@ -894,6 +890,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
>  		[CLKID_NAND_SEL]	    = &meson8b_nand_clk_sel.hw,
>  		[CLKID_NAND_DIV]	    = &meson8b_nand_clk_div.hw,
>  		[CLKID_NAND_CLK]	    = &meson8b_nand_clk_gate.hw,
> +		[CLKID_PLL_FIXED_DCO]	    = &meson8b_fixed_pll_dco.hw,
> +		[CLKID_PLL_VID_DCO]	    = &meson8b_vid_pll_dco.hw,
> +		[CLKID_PLL_SYS_DCO]	    = &meson8b_sys_pll_dco.hw,
>  		[CLK_NR_CLKS]		    = NULL,
>  	},
>  	.num = CLK_NR_CLKS,
> @@ -1002,6 +1001,9 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
>  	&meson8b_nand_clk_sel,
>  	&meson8b_nand_clk_div,
>  	&meson8b_nand_clk_gate,
> +	&meson8b_fixed_pll_dco,
> +	&meson8b_vid_pll_dco,
> +	&meson8b_sys_pll_dco,
>  };
>  
>  static const struct meson8b_clk_reset_line {
> diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
> index 5d09412b5084..1c6fb180e6a2 100644
> --- a/drivers/clk/meson/meson8b.h
> +++ b/drivers/clk/meson/meson8b.h
> @@ -75,8 +75,11 @@
>  #define CLKID_FCLK_DIV7_DIV	109
>  #define CLKID_NAND_SEL		110
>  #define CLKID_NAND_DIV		111
> +#define CLKID_PLL_FIXED_DCO	113
> +#define CLKID_PLL_VID_DCO	114
> +#define CLKID_PLL_SYS_DCO	115
>  
> -#define CLK_NR_CLKS		113
> +#define CLK_NR_CLKS		116
>  
>  /*
>   * include the CLKID and RESETID that have
> 

Apart the small mismatch in the OD GXL bit, this will make this simpler to move the DRM code to CCF :

Acked-by: Neil Armstrong <narmstrong@baylibre.com>

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

* Re: [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables
  2018-07-17  9:56 ` [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables Jerome Brunet
@ 2018-07-19  8:44   ` Neil Armstrong
  2018-07-19  8:59     ` Jerome Brunet
  2018-07-21 20:16     ` Martin Blumenstingl
  0 siblings, 2 replies; 20+ messages in thread
From: Neil Armstrong @ 2018-07-19  8:44 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: linux-amlogic, linux-clk, linux-kernel, Kevin Hilman,
	Martin Blumenstingl

On 17/07/2018 11:56, Jerome Brunet wrote:
> Putting hard-coded rates inside the parameter tables assumes that
> the parent is known and will never change. That's a big assumption
> we should not make.
> 
> We have everything we need to recalculate the output rate using
> the parent rate and the rest of the parameters. Let's do so and
> drop the rates from the tables.
> 
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/meson/axg.c     |  73 +++++++++++++--------------
>  drivers/clk/meson/clk-pll.c |  69 ++++++++++++++++---------
>  drivers/clk/meson/clkc.h    |   8 ++-
>  drivers/clk/meson/gxbb.c    | 120 ++++++++++++++++++++++----------------------
>  drivers/clk/meson/meson8b.c |  34 ++++++-------
>  5 files changed, 162 insertions(+), 142 deletions(-)
> 
> diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
> index 572358062459..d34954bd8c5e 100644
> --- a/drivers/clk/meson/axg.c
> +++ b/drivers/clk/meson/axg.c
> @@ -130,36 +130,36 @@ static struct clk_regmap axg_sys_pll = {
>  	},
>  };
>  
> -static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
> -	PLL_RATE(960000000, 40, 1),
> -	PLL_RATE(984000000, 41, 1),
> -	PLL_RATE(1008000000, 42, 1),
> -	PLL_RATE(1032000000, 43, 1),
> -	PLL_RATE(1056000000, 44, 1),
> -	PLL_RATE(1080000000, 45, 1),
> -	PLL_RATE(1104000000, 46, 1),
> -	PLL_RATE(1128000000, 47, 1),
> -	PLL_RATE(1152000000, 48, 1),
> -	PLL_RATE(1176000000, 49, 1),
> -	PLL_RATE(1200000000, 50, 1),
> -	PLL_RATE(1224000000, 51, 1),
> -	PLL_RATE(1248000000, 52, 1),
> -	PLL_RATE(1272000000, 53, 1),
> -	PLL_RATE(1296000000, 54, 1),
> -	PLL_RATE(1320000000, 55, 1),
> -	PLL_RATE(1344000000, 56, 1),
> -	PLL_RATE(1368000000, 57, 1),
> -	PLL_RATE(1392000000, 58, 1),
> -	PLL_RATE(1416000000, 59, 1),
> -	PLL_RATE(1440000000, 60, 1),
> -	PLL_RATE(1464000000, 61, 1),
> -	PLL_RATE(1488000000, 62, 1),
> -	PLL_RATE(1512000000, 63, 1),
> -	PLL_RATE(1536000000, 64, 1),
> -	PLL_RATE(1560000000, 65, 1),
> -	PLL_RATE(1584000000, 66, 1),
> -	PLL_RATE(1608000000, 67, 1),
> -	PLL_RATE(1632000000, 68, 1),
> +static const struct pll_params_table axg_gp0_pll_params_table[] = {
> +	PLL_PARAMS(40, 1),
> +	PLL_PARAMS(41, 1),
> +	PLL_PARAMS(42, 1),
> +	PLL_PARAMS(43, 1),
> +	PLL_PARAMS(44, 1),
> +	PLL_PARAMS(45, 1),
> +	PLL_PARAMS(46, 1),
> +	PLL_PARAMS(47, 1),
> +	PLL_PARAMS(48, 1),
> +	PLL_PARAMS(49, 1),
> +	PLL_PARAMS(50, 1),
> +	PLL_PARAMS(51, 1),
> +	PLL_PARAMS(52, 1),
> +	PLL_PARAMS(53, 1),
> +	PLL_PARAMS(54, 1),
> +	PLL_PARAMS(55, 1),
> +	PLL_PARAMS(56, 1),
> +	PLL_PARAMS(57, 1),
> +	PLL_PARAMS(58, 1),
> +	PLL_PARAMS(59, 1),
> +	PLL_PARAMS(60, 1),
> +	PLL_PARAMS(61, 1),
> +	PLL_PARAMS(62, 1),
> +	PLL_PARAMS(63, 1),
> +	PLL_PARAMS(64, 1),
> +	PLL_PARAMS(65, 1),
> +	PLL_PARAMS(66, 1),
> +	PLL_PARAMS(67, 1),
> +	PLL_PARAMS(68, 1),
>  	{ /* sentinel */ },
>  };
>  
> @@ -203,7 +203,7 @@ static struct clk_regmap axg_gp0_pll_dco = {
>  			.shift   = 29,
>  			.width   = 1,
>  		},
> -		.table = axg_gp0_pll_rate_table,
> +		.table = axg_gp0_pll_params_table,
>  		.init_regs = axg_gp0_init_regs,
>  		.init_count = ARRAY_SIZE(axg_gp0_init_regs),
>  	},
> @@ -271,7 +271,7 @@ static struct clk_regmap axg_hifi_pll_dco = {
>  			.shift   = 29,
>  			.width   = 1,
>  		},
> -		.table = axg_gp0_pll_rate_table,
> +		.table = axg_gp0_pll_params_table,
>  		.init_regs = axg_hifi_init_regs,
>  		.init_count = ARRAY_SIZE(axg_hifi_init_regs),
>  		.flags = CLK_MESON_PLL_ROUND_CLOSEST,
> @@ -627,11 +627,10 @@ static struct clk_regmap axg_mpll3 = {
>  	},
>  };
>  
> -static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
> +static const struct pll_params_table axg_pcie_pll_params_table[] = {
>  	{
> -		.rate	= 1600000000,
> -		.m	= 200,
> -		.n	= 3,
> +		.m = 200,
> +		.n = 3,
>  	},
>  	{ /* sentinel */ },
>  };
> @@ -678,7 +677,7 @@ static struct clk_regmap axg_pcie_pll_dco = {
>  			.shift   = 29,
>  			.width   = 1,
>  		},
> -		.table = axg_pcie_pll_rate_table,
> +		.table = axg_pcie_pll_params_table,
>  		.init_regs = axg_pcie_init_regs,
>  		.init_count = ARRAY_SIZE(axg_pcie_init_regs),
>  	},
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 348a866f09eb..f5b5b3fabe3c 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -45,7 +45,7 @@ meson_clk_pll_data(struct clk_regmap *clk)
>  }
>  
>  static unsigned long __pll_params_to_rate(unsigned long parent_rate,
> -					  const struct pll_rate_table *pllt,
> +					  const struct pll_params_table *pllt,
>  					  u16 frac,
>  					  struct meson_clk_pll_data *pll)
>  {
> @@ -66,7 +66,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
>  {
>  	struct clk_regmap *clk = to_clk_regmap(hw);
>  	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> -	struct pll_rate_table pllt;
> +	struct pll_params_table pllt;
>  	u16 frac;
>  
>  	pllt.n = meson_parm_read(clk->map, &pll->n);
> @@ -81,7 +81,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
>  
>  static u16 __pll_params_with_frac(unsigned long rate,
>  				  unsigned long parent_rate,
> -				  const struct pll_rate_table *pllt,
> +				  const struct pll_params_table *pllt,
>  				  struct meson_clk_pll_data *pll)
>  {
>  	u16 frac_max = (1 << pll->frac.width);
> @@ -97,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
>  	return min((u16)val, (u16)(frac_max - 1));
>  }
>  
> -static const struct pll_rate_table *
> +static bool meson_clk_pll_is_better(unsigned long rate,
> +				    unsigned long best,
> +				    unsigned long now,
> +				    struct meson_clk_pll_data *pll)
> +{
> +	if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
> +	    MESON_PARM_APPLICABLE(&pll->frac)) {
> +		/* Round down */
> +		if (now < rate && best < now)
> +			return true;
> +	} else {
> +		/* Round Closest */
> +		if (abs(now - rate) < abs(best - rate))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static const struct pll_params_table *
>  meson_clk_get_pll_settings(unsigned long rate,
> +			   unsigned long parent_rate,
>  			   struct meson_clk_pll_data *pll)
>  {
> -	const struct pll_rate_table *table = pll->table;
> -	unsigned int i = 0;
> +	const struct pll_params_table *table = pll->table;
> +	unsigned long best = 0, now = 0;
> +	unsigned int i, best_i = 0;
>  
>  	if (!table)
>  		return NULL;
>  
> -	/* Find the first table element exceeding rate */
> -	while (table[i].rate && table[i].rate <= rate)
> -		i++;
> +	for (i = 0; table[i].n; i++) {
> +		now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
>  
> -	if (i != 0) {
> -		if (MESON_PARM_APPLICABLE(&pll->frac) ||
> -		    !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
> -		    (abs(rate - table[i - 1].rate) <
> -		     abs(rate - table[i].rate)))
> -			i--;
> +		/* If we get an exact match, don't bother any further */
> +		if (now == rate) {
> +			return &table[i];
> +		} else if (meson_clk_pll_is_better(rate, best, now, pll)) {
> +			best = now;
> +			best_i = i;
> +		}
>  	}
>  
> -	return (struct pll_rate_table *)&table[i];
> +	return (struct pll_params_table *)&table[best_i];
>  }
>  
>  static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> @@ -127,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
>  {
>  	struct clk_regmap *clk = to_clk_regmap(hw);
>  	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> -	const struct pll_rate_table *pllt =
> -		meson_clk_get_pll_settings(rate, pll);
> +	const struct pll_params_table *pllt =
> +		meson_clk_get_pll_settings(rate, *parent_rate, pll);
> +	unsigned long round;
>  	u16 frac;
>  
>  	if (!pllt)
>  		return meson_clk_pll_recalc_rate(hw, *parent_rate);
>  
> -	if (!MESON_PARM_APPLICABLE(&pll->frac)
> -	    || rate == pllt->rate)
> -		return pllt->rate;
> +	round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
> +
> +	if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
> +		return round;
>  
>  	/*
>  	 * The rate provided by the setting is not an exact match, let's
> @@ -214,7 +237,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>  {
>  	struct clk_regmap *clk = to_clk_regmap(hw);
>  	struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> -	const struct pll_rate_table *pllt;
> +	const struct pll_params_table *pllt;
>  	unsigned int enabled;
>  	unsigned long old_rate;
>  	u16 frac = 0;
> @@ -224,7 +247,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>  
>  	old_rate = rate;
>  
> -	pllt = meson_clk_get_pll_settings(rate, pll);
> +	pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
>  	if (!pllt)
>  		return -EINVAL;
>  
> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> index a2245e857f70..6b96d55c047d 100644
> --- a/drivers/clk/meson/clkc.h
> +++ b/drivers/clk/meson/clkc.h
> @@ -43,15 +43,13 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
>  }
>  
>  
> -struct pll_rate_table {
> -	unsigned long	rate;
> +struct pll_params_table {
>  	u16		m;
>  	u16		n;
>  };
>  
> -#define PLL_RATE(_r, _m, _n)						\
> +#define PLL_PARAMS(_m, _n)						\
>  	{								\
> -		.rate		= (_r),					\
>  		.m		= (_m),					\
>  		.n		= (_n),					\
>  	}
> @@ -67,7 +65,7 @@ struct meson_clk_pll_data {
>  	struct parm rst;
>  	const struct reg_sequence *init_regs;
>  	unsigned int init_count;
> -	const struct pll_rate_table *table;
> +	const struct pll_params_table *table;
>  	u8 flags;
>  };
>  
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index e2d94498f098..9ac03c7bfbaa 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -18,67 +18,67 @@
>  
>  static DEFINE_SPINLOCK(meson_clk_lock);
>  
> -static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
> -	PLL_RATE(768000000, 32, 1),
> -	PLL_RATE(792000000, 33, 1),
> -	PLL_RATE(816000000, 34, 1),
> -	PLL_RATE(840000000, 35, 1),
> -	PLL_RATE(864000000, 36, 1),
> -	PLL_RATE(888000000, 37, 1),
> -	PLL_RATE(912000000, 38, 1),
> -	PLL_RATE(936000000, 39, 1),
> -	PLL_RATE(960000000, 40, 1),
> -	PLL_RATE(984000000, 41, 1),
> -	PLL_RATE(1008000000, 42, 1),
> -	PLL_RATE(1032000000, 43, 1),
> -	PLL_RATE(1056000000, 44, 1),
> -	PLL_RATE(1080000000, 45, 1),
> -	PLL_RATE(1104000000, 46, 1),
> -	PLL_RATE(1128000000, 47, 1),
> -	PLL_RATE(1152000000, 48, 1),
> -	PLL_RATE(1176000000, 49, 1),
> -	PLL_RATE(1200000000, 50, 1),
> -	PLL_RATE(1224000000, 51, 1),
> -	PLL_RATE(1248000000, 52, 1),
> -	PLL_RATE(1272000000, 53, 1),
> -	PLL_RATE(1296000000, 54, 1),
> -	PLL_RATE(1320000000, 55, 1),
> -	PLL_RATE(1344000000, 56, 1),
> -	PLL_RATE(1368000000, 57, 1),
> -	PLL_RATE(1392000000, 58, 1),
> -	PLL_RATE(1416000000, 59, 1),
> -	PLL_RATE(1440000000, 60, 1),
> -	PLL_RATE(1464000000, 61, 1),
> -	PLL_RATE(1488000000, 62, 1),
> +static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
> +	PLL_PARAMS(32, 1),
> +	PLL_PARAMS(33, 1),
> +	PLL_PARAMS(34, 1),
> +	PLL_PARAMS(35, 1),
> +	PLL_PARAMS(36, 1),
> +	PLL_PARAMS(37, 1),
> +	PLL_PARAMS(38, 1),
> +	PLL_PARAMS(39, 1),
> +	PLL_PARAMS(40, 1),
> +	PLL_PARAMS(41, 1),
> +	PLL_PARAMS(42, 1),
> +	PLL_PARAMS(43, 1),
> +	PLL_PARAMS(44, 1),
> +	PLL_PARAMS(45, 1),
> +	PLL_PARAMS(46, 1),
> +	PLL_PARAMS(47, 1),
> +	PLL_PARAMS(48, 1),
> +	PLL_PARAMS(49, 1),
> +	PLL_PARAMS(50, 1),
> +	PLL_PARAMS(51, 1),
> +	PLL_PARAMS(52, 1),
> +	PLL_PARAMS(53, 1),
> +	PLL_PARAMS(54, 1),
> +	PLL_PARAMS(55, 1),
> +	PLL_PARAMS(56, 1),
> +	PLL_PARAMS(57, 1),
> +	PLL_PARAMS(58, 1),
> +	PLL_PARAMS(59, 1),
> +	PLL_PARAMS(60, 1),
> +	PLL_PARAMS(61, 1),
> +	PLL_PARAMS(62, 1),
>  	{ /* sentinel */ },
>  };
>  
> -static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
> -	PLL_RATE(1008000000, 42, 1),
> -	PLL_RATE(1032000000, 43, 1),
> -	PLL_RATE(1056000000, 44, 1),
> -	PLL_RATE(1080000000, 45, 1),
> -	PLL_RATE(1104000000, 46, 1),
> -	PLL_RATE(1128000000, 47, 1),
> -	PLL_RATE(1152000000, 48, 1),
> -	PLL_RATE(1176000000, 49, 1),
> -	PLL_RATE(1200000000, 50, 1),
> -	PLL_RATE(1224000000, 51, 1),
> -	PLL_RATE(1248000000, 52, 1),
> -	PLL_RATE(1272000000, 53, 1),
> -	PLL_RATE(1296000000, 54, 1),
> -	PLL_RATE(1320000000, 55, 1),
> -	PLL_RATE(1344000000, 56, 1),
> -	PLL_RATE(1368000000, 57, 1),
> -	PLL_RATE(1392000000, 58, 1),
> -	PLL_RATE(1416000000, 59, 1),
> -	PLL_RATE(1440000000, 60, 1),
> -	PLL_RATE(1464000000, 61, 1),
> -	PLL_RATE(1488000000, 62, 1),
> -	PLL_RATE(1512000000, 63, 1),
> -	PLL_RATE(1536000000, 64, 1),
> -	PLL_RATE(1560000000, 65, 1),
> -	PLL_RATE(1584000000, 66, 1),
> +static const struct pll_params_table gxl_gp0_pll_params_table[] = {
> +	PLL_PARAMS(42, 1),
> +	PLL_PARAMS(43, 1),
> +	PLL_PARAMS(44, 1),
> +	PLL_PARAMS(45, 1),
> +	PLL_PARAMS(46, 1),
> +	PLL_PARAMS(47, 1),
> +	PLL_PARAMS(48, 1),
> +	PLL_PARAMS(49, 1),
> +	PLL_PARAMS(50, 1),
> +	PLL_PARAMS(51, 1),
> +	PLL_PARAMS(52, 1),
> +	PLL_PARAMS(53, 1),
> +	PLL_PARAMS(54, 1),
> +	PLL_PARAMS(55, 1),
> +	PLL_PARAMS(56, 1),
> +	PLL_PARAMS(57, 1),
> +	PLL_PARAMS(58, 1),
> +	PLL_PARAMS(59, 1),
> +	PLL_PARAMS(60, 1),
> +	PLL_PARAMS(61, 1),
> +	PLL_PARAMS(62, 1),
> +	PLL_PARAMS(63, 1),
> +	PLL_PARAMS(64, 1),
> +	PLL_PARAMS(65, 1),
> +	PLL_PARAMS(66, 1),
>  	{ /* sentinel */ },
>  };
>  
> @@ -374,7 +374,7 @@ static struct clk_regmap gxbb_gp0_pll_dco = {
>  			.shift   = 29,
>  			.width   = 1,
>  		},
> -		.table = gxbb_gp0_pll_rate_table,
> +		.table = gxbb_gp0_pll_params_table,
>  		.init_regs = gxbb_gp0_init_regs,
>  		.init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
>  	},
> @@ -427,7 +427,7 @@ static struct clk_regmap gxl_gp0_pll_dco = {
>  			.shift   = 29,
>  			.width   = 1,
>  		},
> -		.table = gxl_gp0_pll_rate_table,
> +		.table = gxl_gp0_pll_params_table,
>  		.init_regs = gxl_gp0_init_regs,
>  		.init_count = ARRAY_SIZE(gxl_gp0_init_regs),
>  	},
> diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
> index 17bcf0be56ba..30ae849ff53f 100644
> --- a/drivers/clk/meson/meson8b.c
> +++ b/drivers/clk/meson/meson8b.c
> @@ -29,22 +29,22 @@ struct meson8b_clk_reset {
>  	void __iomem *base;
>  };
>  
> -static const struct pll_rate_table sys_pll_rate_table[] = {
> -	PLL_RATE(1200000000, 50, 1),
> -	PLL_RATE(1224000000, 51, 1),
> -	PLL_RATE(1248000000, 52, 1),
> -	PLL_RATE(1272000000, 53, 1),
> -	PLL_RATE(1296000000, 54, 1),
> -	PLL_RATE(1320000000, 55, 1),
> -	PLL_RATE(1344000000, 56, 1),
> -	PLL_RATE(1368000000, 57, 1),
> -	PLL_RATE(1392000000, 58, 1),
> -	PLL_RATE(1416000000, 59, 1),
> -	PLL_RATE(1440000000, 60, 1),
> -	PLL_RATE(1464000000, 61, 1),
> -	PLL_RATE(1488000000, 62, 1),
> -	PLL_RATE(1512000000, 63, 1),
> -	PLL_RATE(1536000000, 64, 1),
> +static const struct pll_params_table sys_pll_params_table[] = {
> +	PLL_PARAMS(50, 1),
> +	PLL_PARAMS(51, 1),
> +	PLL_PARAMS(52, 1),
> +	PLL_PARAMS(53, 1),
> +	PLL_PARAMS(54, 1),
> +	PLL_PARAMS(55, 1),
> +	PLL_PARAMS(56, 1),
> +	PLL_PARAMS(57, 1),
> +	PLL_PARAMS(58, 1),
> +	PLL_PARAMS(59, 1),
> +	PLL_PARAMS(60, 1),
> +	PLL_PARAMS(61, 1),
> +	PLL_PARAMS(62, 1),
> +	PLL_PARAMS(63, 1),
> +	PLL_PARAMS(64, 1),
>  	{ /* sentinel */ },
>  };
>  
> @@ -195,7 +195,7 @@ static struct clk_regmap meson8b_sys_pll_dco = {
>  			.shift   = 29,
>  			.width   = 1,
>  		},
> -		.table = sys_pll_rate_table,
> +		.table = sys_pll_params_table,
>  	},
>  	.hw.init = &(struct clk_init_data){
>  		.name = "sys_pll_dco",
> 

We could even add ranges instead of table when we know the PLL supports a well-known continuous dividers range.

Acked-by: Neil Armstrong <narmstrong@baylibre.com>

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

* Re: [PATCH 2/3] clk: meson: clk-pll: remove od parameters
  2018-07-19  8:42   ` Neil Armstrong
@ 2018-07-19  8:45     ` Jerome Brunet
  0 siblings, 0 replies; 20+ messages in thread
From: Jerome Brunet @ 2018-07-19  8:45 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-amlogic, linux-clk, linux-kernel, Kevin Hilman,
	Martin Blumenstingl

On Thu, 2018-07-19 at 10:42 +0200, Neil Armstrong wrote:
> > +static struct clk_regmap gxl_hdmi_pll_od = {
> > +     .data = &(struct clk_regmap_div_data){
> > +             .offset = HHI_HDMI_PLL_CNTL + 8,
> > +             .shift = 16,
> > +             .width = 2,
> > +             .flags = CLK_DIVIDER_POWER_OF_TWO,
> > +     },
> > +     .hw.init = &(struct clk_init_data){
> > +             .name = "hdmi_pll_od",
> > +             .ops = &clk_regmap_divider_ro_ops,
> > +             .parent_names = (const char *[]){ "hdmi_pll_dco" },
> > +             .num_parents = 1,
> > +             .flags = CLK_GET_RATE_NOCACHE,
> > +     },
> > +};
> 
> In my code, the GXL OD1 is at bit 21
> 
> > +
> > +static struct clk_regmap gxl_hdmi_pll_od2 = {
> > +     .data = &(struct clk_regmap_div_data){
> > +             .offset = HHI_HDMI_PLL_CNTL + 8,
> > +             .shift = 22,
> > +             .width = 2,
> > +             .flags = CLK_DIVIDER_POWER_OF_TWO,
> > +     },
> > +     .hw.init = &(struct clk_init_data){
> > +             .name = "hdmi_pll_od2",
> > +             .ops = &clk_regmap_divider_ro_ops,
> > +             .parent_names = (const char *[]){ "hdmi_pll_od" },
> > +             .num_parents = 1,
> > +             .flags = CLK_GET_RATE_NOCACHE,
> > +     },
> > +};
> 
> 
> In my code, the GXL OD3 is at bit 23
> 
> > +
> >   static struct clk_regmap gxl_hdmi_pll = {
> > -     .data = &(struct meson_clk_pll_data){
> > -             .en = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL,
> > -                     .shift   = 30,
> > -                     .width   = 1,
> > -             },
> > -             .m = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL,
> > -                     .shift   = 0,
> > -                     .width   = 9,
> > -             },
> > -             .n = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL,
> > -                     .shift   = 9,
> > -                     .width   = 5,
> > -             },
> > -             .frac = {
> > -                     /*
> > -                      * On gxl, there is a register shift due to
> > -                      * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
> > -                      * so we compute the register offset based on the PLL
> > -                      * base to get it right
> > -                      */
> > -                     .reg_off = HHI_HDMI_PLL_CNTL + 4,
> > -                     .shift   = 0,
> > -                     .width   = 12,
> > -             },
> > -             .od = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL + 8,
> > -                     .shift   = 21,
> > -                     .width   = 2,
> > -             },
> > -             .od2 = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL + 8,
> > -                     .shift   = 23,
> > -                     .width   = 2,
> > -             },
> > -             .od3 = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL + 8,
> > -                     .shift   = 19,
> > -                     .width   = 2,
> > -             },
> > -             .l = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL,
> > -                     .shift   = 31,
> > -                     .width   = 1,
> > -             },
> > -             .rst = {
> > -                     .reg_off = HHI_HDMI_PLL_CNTL,
> > -                     .shift   = 29,
> > -                     .width   = 1,
> > -             },
> > +     .data = &(struct clk_regmap_div_data){
> > +             .offset = HHI_HDMI_PLL_CNTL + 8,
> > +             .shift = 18,
> > +             .width = 2,
> > +             .flags = CLK_DIVIDER_POWER_OF_TWO,
> 
> 
> In my code, the GXL OD3 is at bit 19
> 
> It's only a copy/paste error, the original code had the correct shifts.

Absolutely. Good catch. 


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

* Re: [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables
  2018-07-19  8:44   ` Neil Armstrong
@ 2018-07-19  8:59     ` Jerome Brunet
  2018-07-21 20:16     ` Martin Blumenstingl
  1 sibling, 0 replies; 20+ messages in thread
From: Jerome Brunet @ 2018-07-19  8:59 UTC (permalink / raw)
  To: Neil Armstrong
  Cc: linux-amlogic, linux-clk, linux-kernel, Kevin Hilman,
	Martin Blumenstingl

On Thu, 2018-07-19 at 10:44 +0200, Neil Armstrong wrote:
> We could even add ranges instead of table when we know the PLL supports a well-known continuous dividers range.

I was thinking about this too.
I did not went for it because it would mean yet another rework of the pll
driver, which I did not had time to do now.

I suspect that the min and max value of 'm' the pll can lock on might depend on
the input rate of the DCO, so past the 'n' prediv.

So, to replace the tuple (m, n) table with ranges, I think it would be best to
take the predivider 'n' out first and try to clarify the contraints on the input
rate of the DCO with amlogic ... we can also try and see ;)

> 
> Acked-by: Neil Armstrong <narmstrong@baylibre.com>


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

* Re: [PATCH 1/3] clk: meson: clk-pll: add enable bit
  2018-07-17  9:56 ` [PATCH 1/3] clk: meson: clk-pll: add enable bit Jerome Brunet
  2018-07-19  8:33   ` Neil Armstrong
@ 2018-07-21 19:48   ` Martin Blumenstingl
  2018-07-21 20:26     ` Jerome Brunet
  1 sibling, 1 reply; 20+ messages in thread
From: Martin Blumenstingl @ 2018-07-21 19:48 UTC (permalink / raw)
  To: jbrunet; +Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

Hi Jerome,

On Tue, Jul 17, 2018 at 11:56 AM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> Add the enable the bit of the pll clocks.
> These pll clocks may be disabled but we can't model this as an external
> gate since the pll needs to lock when enabled.
>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
I have some questions inline, but with those answered:
Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>

> ---
>  drivers/clk/meson/axg.c     | 28 ++++++++++++++++++++++++---
>  drivers/clk/meson/clk-pll.c | 47 ++++++++++++++++++++++++++++++++++++++++-----
>  drivers/clk/meson/clkc.h    |  1 +
>  drivers/clk/meson/gxbb.c    | 32 ++++++++++++++++++++++++++++--
>  drivers/clk/meson/meson8b.c | 15 +++++++++++++++
>  5 files changed, 113 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
> index 00ce62ad6416..6d8976554656 100644
> --- a/drivers/clk/meson/axg.c
> +++ b/drivers/clk/meson/axg.c
> @@ -24,6 +24,11 @@ static DEFINE_SPINLOCK(meson_clk_lock);
>
>  static struct clk_regmap axg_fixed_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_MPLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_MPLL_CNTL,
>                         .shift   = 0,
> @@ -65,6 +70,11 @@ static struct clk_regmap axg_fixed_pll = {
>
>  static struct clk_regmap axg_sys_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_SYS_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_SYS_PLL_CNTL,
>                         .shift   = 0,
> @@ -197,11 +207,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
>         { .reg = HHI_GP0_PLL_CNTL3,     .def = 0x0a59a288 },
>         { .reg = HHI_GP0_PLL_CNTL4,     .def = 0xc000004d },
>         { .reg = HHI_GP0_PLL_CNTL5,     .def = 0x00078000 },
> -       { .reg = HHI_GP0_PLL_CNTL,      .def = 0x40010250 },
>  };
>
>  static struct clk_regmap axg_gp0_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_GP0_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_GP0_PLL_CNTL,
>                         .shift   = 0,
> @@ -250,11 +264,15 @@ static const struct reg_sequence axg_hifi_init_regs[] = {
>         { .reg = HHI_HIFI_PLL_CNTL3,    .def = 0x0a6a3a88 },
>         { .reg = HHI_HIFI_PLL_CNTL4,    .def = 0xc000004d },
>         { .reg = HHI_HIFI_PLL_CNTL5,    .def = 0x00058000 },
> -       { .reg = HHI_HIFI_PLL_CNTL,     .def = 0x40010250 },
is this change on purpose? this line set en, m, n, l and od before
maybe you can document it in the commit message

>  };
>
>  static struct clk_regmap axg_hifi_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_HIFI_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_HIFI_PLL_CNTL,
>                         .shift   = 0,
> @@ -637,7 +655,6 @@ static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
>  };
>
>  static const struct reg_sequence axg_pcie_init_regs[] = {
> -       { .reg = HHI_PCIE_PLL_CNTL,     .def = 0x400106c8 },
same as above: is this change on purpose?

>         { .reg = HHI_PCIE_PLL_CNTL1,    .def = 0x0084a2aa },
>         { .reg = HHI_PCIE_PLL_CNTL2,    .def = 0xb75020be },
>         { .reg = HHI_PCIE_PLL_CNTL3,    .def = 0x0a47488e },
> @@ -648,6 +665,11 @@ static const struct reg_sequence axg_pcie_init_regs[] = {
>
>  static struct clk_regmap axg_pcie_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_PCIE_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_PCIE_PLL_CNTL,
>                         .shift   = 0,
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 3e04617ac47f..8aaefe67025f 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -185,12 +185,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
>         }
>  }
>
> +static int meson_clk_pll_enable(struct clk_hw *hw)
> +{
> +       struct clk_regmap *clk = to_clk_regmap(hw);
> +       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> +
> +       /* Make sure the pll is in reset */
> +       meson_parm_write(clk->map, &pll->rst, 1);
> +
> +       /* Enable the pll */
> +       meson_parm_write(clk->map, &pll->en, 1);
> +
> +       /* Take the pll out reset */
> +       meson_parm_write(clk->map, &pll->rst, 0);
> +
> +       if (meson_clk_pll_wait_lock(hw))
> +               return -EIO;
> +
> +       return 0;
> +}
> +
> +static void meson_clk_pll_disable(struct clk_hw *hw)
> +{
> +       struct clk_regmap *clk = to_clk_regmap(hw);
> +       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> +
> +       /* Put the pll is in reset */
> +       meson_parm_write(clk->map, &pll->rst, 1);
> +
> +       /* Disable the pll */
> +       meson_parm_write(clk->map, &pll->en, 0);
> +}
> +
>  static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>                                   unsigned long parent_rate)
>  {
>         struct clk_regmap *clk = to_clk_regmap(hw);
>         struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
>         const struct pll_rate_table *pllt;
> +       unsigned int enabled;
>         unsigned long old_rate;
>         u16 frac = 0;
>
> @@ -203,8 +236,9 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>         if (!pllt)
>                 return -EINVAL;
>
> -       /* Put the pll in reset to write the params */
> -       meson_parm_write(clk->map, &pll->rst, 1);
> +       enabled = meson_parm_read(clk->map, &pll->en);
> +       if (enabled)
> +               meson_clk_pll_disable(hw);
>
>         meson_parm_write(clk->map, &pll->n, pllt->n);
>         meson_parm_write(clk->map, &pll->m, pllt->m);
> @@ -221,10 +255,11 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>                 meson_parm_write(clk->map, &pll->frac, frac);
>         }
>
> -       /* make sure the reset is cleared at this point */
> -       meson_parm_write(clk->map, &pll->rst, 0);
> +       /* If the pll is stopped, bail out now */
> +       if (!enabled)
> +               return 0;
>
> -       if (meson_clk_pll_wait_lock(hw)) {
> +       if (meson_clk_pll_enable(hw)) {
>                 pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
>                         __func__, old_rate);
>                 /*
> @@ -244,6 +279,8 @@ const struct clk_ops meson_clk_pll_ops = {
>         .recalc_rate    = meson_clk_pll_recalc_rate,
>         .round_rate     = meson_clk_pll_round_rate,
>         .set_rate       = meson_clk_pll_set_rate,
> +       .enable         = meson_clk_pll_enable,
> +       .disable        = meson_clk_pll_disable
>  };
>
>  const struct clk_ops meson_clk_pll_ro_ops = {
> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> index 24cec16b6038..c2ee37a78ceb 100644
> --- a/drivers/clk/meson/clkc.h
> +++ b/drivers/clk/meson/clkc.h
> @@ -63,6 +63,7 @@ struct pll_rate_table {
>  #define CLK_MESON_PLL_ROUND_CLOSEST    BIT(0)
>
>  struct meson_clk_pll_data {
> +       struct parm en;
>         struct parm m;
>         struct parm n;
>         struct parm frac;
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index 86d3ae58e84c..5ed34566917c 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -177,6 +177,11 @@ static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
>
>  static struct clk_regmap gxbb_fixed_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_MPLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_MPLL_CNTL,
>                         .shift   = 0,
> @@ -230,6 +235,11 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
>
>  static struct clk_regmap gxbb_hdmi_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_HDMI_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_HDMI_PLL_CNTL,
>                         .shift   = 0,
> @@ -282,6 +292,11 @@ static struct clk_regmap gxbb_hdmi_pll = {
>
>  static struct clk_regmap gxl_hdmi_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_HDMI_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_HDMI_PLL_CNTL,
>                         .shift   = 0,
> @@ -340,6 +355,11 @@ static struct clk_regmap gxl_hdmi_pll = {
>
>  static struct clk_regmap gxbb_sys_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_SYS_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_SYS_PLL_CNTL,
>                         .shift   = 0,
> @@ -379,11 +399,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = {
>         { .reg = HHI_GP0_PLL_CNTL2,     .def = 0x69c80000 },
>         { .reg = HHI_GP0_PLL_CNTL3,     .def = 0x0a5590c4 },
>         { .reg = HHI_GP0_PLL_CNTL4,     .def = 0x0000500d },
> -       { .reg = HHI_GP0_PLL_CNTL,      .def = 0x4a000228 },
same as above: is this change on purpose?

>  };
>
>  static struct clk_regmap gxbb_gp0_pll = {
>         .data = &(struct meson_clk_pll_data){
> +               .en = {
> +                       .reg_off = HHI_GP0_PLL_CNTL,
> +                       .shift   = 30,
> +                       .width   = 1,
> +               },
>                 .m = {
>                         .reg_off = HHI_GP0_PLL_CNTL,
>                         .shift   = 0,
> @@ -428,11 +452,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
>         { .reg = HHI_GP0_PLL_CNTL3,     .def = 0x0a59a288 },
>         { .reg = HHI_GP0_PLL_CNTL4,     .def = 0xc000004d },
>         { .reg = HHI_GP0_PLL_CNTL5,     .def = 0x00078000 },
> -       { .reg = HHI_GP0_PLL_CNTL,      .def = 0x40010250 },
same as above: is this change on purpose?


Regards
Martin

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

* Re: [PATCH 2/3] clk: meson: clk-pll: remove od parameters
  2018-07-17  9:56 ` [PATCH 2/3] clk: meson: clk-pll: remove od parameters Jerome Brunet
  2018-07-19  8:42   ` Neil Armstrong
@ 2018-07-21 20:01   ` Martin Blumenstingl
  2018-07-21 20:42     ` Jerome Brunet
  1 sibling, 1 reply; 20+ messages in thread
From: Martin Blumenstingl @ 2018-07-21 20:01 UTC (permalink / raw)
  To: jbrunet; +Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

Hi Jerome,

On Tue, Jul 17, 2018 at 11:56 AM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> Remove od parameters from pll clocks and add post dividers clocks
> instead. Some clock, especially the one which feature several ods,
> may provide output between those ods. Also, some drivers, such
> as the hdmi driver, may require a more detailed control of the
> clock dividers, compared to what CCF would perform automatically.
>
> One added benefit of removing ods is that it also greatly reduce the
> size of the rate parameter tables.
>
> In the future, we could possibly take the predivider 'n' out of this
> driver as well. To do so, we will need to understand the constraints
> for the PLL to lock and whether or not it depends on the input clock
> rate.
>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> ---
>  drivers/clk/meson/axg.c     | 279 ++++++++++++++------------
>  drivers/clk/meson/axg.h     |   8 +-
>  drivers/clk/meson/clk-pll.c |  40 ++--
>  drivers/clk/meson/clkc.h    |   9 +-
>  drivers/clk/meson/gxbb.c    | 474 +++++++++++++++++++++-----------------------
>  drivers/clk/meson/gxbb.h    |  10 +-
>  drivers/clk/meson/meson8b.c | 148 +++++++-------
>  drivers/clk/meson/meson8b.h |   5 +-
>  8 files changed, 480 insertions(+), 493 deletions(-)
>
> diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
> index 6d8976554656..572358062459 100644
> --- a/drivers/clk/meson/axg.c
> +++ b/drivers/clk/meson/axg.c
> @@ -22,7 +22,7 @@
>
>  static DEFINE_SPINLOCK(meson_clk_lock);
>
> -static struct clk_regmap axg_fixed_pll = {
> +static struct clk_regmap axg_fixed_pll_dco = {
>         .data = &(struct meson_clk_pll_data){
>                 .en = {
>                         .reg_off = HHI_MPLL_CNTL,
> @@ -39,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = {
>                         .shift   = 9,
>                         .width   = 5,
>                 },
> -               .od = {
> -                       .reg_off = HHI_MPLL_CNTL,
> -                       .shift   = 16,
> -                       .width   = 2,
> -               },
>                 .frac = {
>                         .reg_off = HHI_MPLL_CNTL2,
>                         .shift   = 0,
> @@ -61,14 +56,29 @@ static struct clk_regmap axg_fixed_pll = {
>                 },
>         },
>         .hw.init = &(struct clk_init_data){
> -               .name = "fixed_pll",
> +               .name = "fixed_pll_dco",
>                 .ops = &meson_clk_pll_ro_ops,
>                 .parent_names = (const char *[]){ "xtal" },
>                 .num_parents = 1,
>         },
>  };
>
> -static struct clk_regmap axg_sys_pll = {
> +static struct clk_regmap axg_fixed_pll = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_MPLL_CNTL,
> +               .shift = 16,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "fixed_pll",
> +               .ops = &clk_regmap_divider_ro_ops,
> +               .parent_names = (const char *[]){ "fixed_pll_dco" },
> +               .num_parents = 1,
> +       },
> +};
> +
> +static struct clk_regmap axg_sys_pll_dco = {
>         .data = &(struct meson_clk_pll_data){
>                 .en = {
>                         .reg_off = HHI_SYS_PLL_CNTL,
> @@ -85,11 +95,6 @@ static struct clk_regmap axg_sys_pll = {
>                         .shift   = 9,
>                         .width   = 5,
>                 },
> -               .od = {
> -                       .reg_off = HHI_SYS_PLL_CNTL,
> -                       .shift   = 16,
> -                       .width   = 2,
> -               },
>                 .l = {
>                         .reg_off = HHI_SYS_PLL_CNTL,
>                         .shift   = 31,
> @@ -102,7 +107,7 @@ static struct clk_regmap axg_sys_pll = {
>                 },
>         },
>         .hw.init = &(struct clk_init_data){
> -               .name = "sys_pll",
> +               .name = "sys_pll_dco",
>                 .ops = &meson_clk_pll_ro_ops,
>                 .parent_names = (const char *[]){ "xtal" },
>                 .num_parents = 1,
> @@ -110,94 +115,51 @@ static struct clk_regmap axg_sys_pll = {
>         },
>  };
>
> +static struct clk_regmap axg_sys_pll = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_SYS_PLL_CNTL,
> +               .shift = 16,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "sys_pll",
> +               .ops = &clk_regmap_divider_ro_ops,
> +               .parent_names = (const char *[]){ "sys_pll_dco" },
> +               .num_parents = 1,
> +       },
> +};
> +
>  static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
> -       PLL_RATE(240000000, 40, 1, 2),
> -       PLL_RATE(246000000, 41, 1, 2),
> -       PLL_RATE(252000000, 42, 1, 2),
> -       PLL_RATE(258000000, 43, 1, 2),
> -       PLL_RATE(264000000, 44, 1, 2),
> -       PLL_RATE(270000000, 45, 1, 2),
> -       PLL_RATE(276000000, 46, 1, 2),
> -       PLL_RATE(282000000, 47, 1, 2),
> -       PLL_RATE(288000000, 48, 1, 2),
> -       PLL_RATE(294000000, 49, 1, 2),
> -       PLL_RATE(300000000, 50, 1, 2),
> -       PLL_RATE(306000000, 51, 1, 2),
> -       PLL_RATE(312000000, 52, 1, 2),
> -       PLL_RATE(318000000, 53, 1, 2),
> -       PLL_RATE(324000000, 54, 1, 2),
> -       PLL_RATE(330000000, 55, 1, 2),
> -       PLL_RATE(336000000, 56, 1, 2),
> -       PLL_RATE(342000000, 57, 1, 2),
> -       PLL_RATE(348000000, 58, 1, 2),
> -       PLL_RATE(354000000, 59, 1, 2),
> -       PLL_RATE(360000000, 60, 1, 2),
> -       PLL_RATE(366000000, 61, 1, 2),
> -       PLL_RATE(372000000, 62, 1, 2),
> -       PLL_RATE(378000000, 63, 1, 2),
> -       PLL_RATE(384000000, 64, 1, 2),
> -       PLL_RATE(390000000, 65, 1, 3),
> -       PLL_RATE(396000000, 66, 1, 3),
> -       PLL_RATE(402000000, 67, 1, 3),
> -       PLL_RATE(408000000, 68, 1, 3),
> -       PLL_RATE(480000000, 40, 1, 1),
> -       PLL_RATE(492000000, 41, 1, 1),
> -       PLL_RATE(504000000, 42, 1, 1),
> -       PLL_RATE(516000000, 43, 1, 1),
> -       PLL_RATE(528000000, 44, 1, 1),
> -       PLL_RATE(540000000, 45, 1, 1),
> -       PLL_RATE(552000000, 46, 1, 1),
> -       PLL_RATE(564000000, 47, 1, 1),
> -       PLL_RATE(576000000, 48, 1, 1),
> -       PLL_RATE(588000000, 49, 1, 1),
> -       PLL_RATE(600000000, 50, 1, 1),
> -       PLL_RATE(612000000, 51, 1, 1),
> -       PLL_RATE(624000000, 52, 1, 1),
> -       PLL_RATE(636000000, 53, 1, 1),
> -       PLL_RATE(648000000, 54, 1, 1),
> -       PLL_RATE(660000000, 55, 1, 1),
> -       PLL_RATE(672000000, 56, 1, 1),
> -       PLL_RATE(684000000, 57, 1, 1),
> -       PLL_RATE(696000000, 58, 1, 1),
> -       PLL_RATE(708000000, 59, 1, 1),
> -       PLL_RATE(720000000, 60, 1, 1),
> -       PLL_RATE(732000000, 61, 1, 1),
> -       PLL_RATE(744000000, 62, 1, 1),
> -       PLL_RATE(756000000, 63, 1, 1),
> -       PLL_RATE(768000000, 64, 1, 1),
> -       PLL_RATE(780000000, 65, 1, 1),
> -       PLL_RATE(792000000, 66, 1, 1),
> -       PLL_RATE(804000000, 67, 1, 1),
> -       PLL_RATE(816000000, 68, 1, 1),
> -       PLL_RATE(960000000, 40, 1, 0),
> -       PLL_RATE(984000000, 41, 1, 0),
> -       PLL_RATE(1008000000, 42, 1, 0),
> -       PLL_RATE(1032000000, 43, 1, 0),
> -       PLL_RATE(1056000000, 44, 1, 0),
> -       PLL_RATE(1080000000, 45, 1, 0),
> -       PLL_RATE(1104000000, 46, 1, 0),
> -       PLL_RATE(1128000000, 47, 1, 0),
> -       PLL_RATE(1152000000, 48, 1, 0),
> -       PLL_RATE(1176000000, 49, 1, 0),
> -       PLL_RATE(1200000000, 50, 1, 0),
> -       PLL_RATE(1224000000, 51, 1, 0),
> -       PLL_RATE(1248000000, 52, 1, 0),
> -       PLL_RATE(1272000000, 53, 1, 0),
> -       PLL_RATE(1296000000, 54, 1, 0),
> -       PLL_RATE(1320000000, 55, 1, 0),
> -       PLL_RATE(1344000000, 56, 1, 0),
> -       PLL_RATE(1368000000, 57, 1, 0),
> -       PLL_RATE(1392000000, 58, 1, 0),
> -       PLL_RATE(1416000000, 59, 1, 0),
> -       PLL_RATE(1440000000, 60, 1, 0),
> -       PLL_RATE(1464000000, 61, 1, 0),
> -       PLL_RATE(1488000000, 62, 1, 0),
> -       PLL_RATE(1512000000, 63, 1, 0),
> -       PLL_RATE(1536000000, 64, 1, 0),
> -       PLL_RATE(1560000000, 65, 1, 0),
> -       PLL_RATE(1584000000, 66, 1, 0),
> -       PLL_RATE(1608000000, 67, 1, 0),
> -       PLL_RATE(1632000000, 68, 1, 0),
> +       PLL_RATE(960000000, 40, 1),
> +       PLL_RATE(984000000, 41, 1),
> +       PLL_RATE(1008000000, 42, 1),
> +       PLL_RATE(1032000000, 43, 1),
> +       PLL_RATE(1056000000, 44, 1),
> +       PLL_RATE(1080000000, 45, 1),
> +       PLL_RATE(1104000000, 46, 1),
> +       PLL_RATE(1128000000, 47, 1),
> +       PLL_RATE(1152000000, 48, 1),
> +       PLL_RATE(1176000000, 49, 1),
> +       PLL_RATE(1200000000, 50, 1),
> +       PLL_RATE(1224000000, 51, 1),
> +       PLL_RATE(1248000000, 52, 1),
> +       PLL_RATE(1272000000, 53, 1),
> +       PLL_RATE(1296000000, 54, 1),
> +       PLL_RATE(1320000000, 55, 1),
> +       PLL_RATE(1344000000, 56, 1),
> +       PLL_RATE(1368000000, 57, 1),
> +       PLL_RATE(1392000000, 58, 1),
> +       PLL_RATE(1416000000, 59, 1),
> +       PLL_RATE(1440000000, 60, 1),
> +       PLL_RATE(1464000000, 61, 1),
> +       PLL_RATE(1488000000, 62, 1),
> +       PLL_RATE(1512000000, 63, 1),
> +       PLL_RATE(1536000000, 64, 1),
> +       PLL_RATE(1560000000, 65, 1),
> +       PLL_RATE(1584000000, 66, 1),
> +       PLL_RATE(1608000000, 67, 1),
> +       PLL_RATE(1632000000, 68, 1),
>         { /* sentinel */ },
>  };
>
> @@ -209,7 +171,7 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
>         { .reg = HHI_GP0_PLL_CNTL5,     .def = 0x00078000 },
>  };
>
> -static struct clk_regmap axg_gp0_pll = {
> +static struct clk_regmap axg_gp0_pll_dco = {
>         .data = &(struct meson_clk_pll_data){
>                 .en = {
>                         .reg_off = HHI_GP0_PLL_CNTL,
> @@ -226,11 +188,6 @@ static struct clk_regmap axg_gp0_pll = {
>                         .shift   = 9,
>                         .width   = 5,
>                 },
> -               .od = {
> -                       .reg_off = HHI_GP0_PLL_CNTL,
> -                       .shift   = 16,
> -                       .width   = 2,
> -               },
>                 .frac = {
>                         .reg_off = HHI_GP0_PLL_CNTL1,
>                         .shift   = 0,
> @@ -251,13 +208,29 @@ static struct clk_regmap axg_gp0_pll = {
>                 .init_count = ARRAY_SIZE(axg_gp0_init_regs),
>         },
>         .hw.init = &(struct clk_init_data){
> -               .name = "gp0_pll",
> +               .name = "gp0_pll_dco",
>                 .ops = &meson_clk_pll_ops,
>                 .parent_names = (const char *[]){ "xtal" },
>                 .num_parents = 1,
>         },
>  };
>
> +static struct clk_regmap axg_gp0_pll = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_GP0_PLL_CNTL,
> +               .shift = 16,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "gp0_pll",
> +               .ops = &clk_regmap_divider_ops,
> +               .parent_names = (const char *[]){ "gp0_pll_dco" },
> +               .num_parents = 1,
> +               .flags = CLK_SET_RATE_PARENT,
> +       },
> +};
> +
>  static const struct reg_sequence axg_hifi_init_regs[] = {
>         { .reg = HHI_HIFI_PLL_CNTL1,    .def = 0xc084b000 },
>         { .reg = HHI_HIFI_PLL_CNTL2,    .def = 0xb75020be },
> @@ -266,7 +239,7 @@ static const struct reg_sequence axg_hifi_init_regs[] = {
>         { .reg = HHI_HIFI_PLL_CNTL5,    .def = 0x00058000 },
>  };
>
> -static struct clk_regmap axg_hifi_pll = {
> +static struct clk_regmap axg_hifi_pll_dco = {
>         .data = &(struct meson_clk_pll_data){
>                 .en = {
>                         .reg_off = HHI_HIFI_PLL_CNTL,
> @@ -283,11 +256,6 @@ static struct clk_regmap axg_hifi_pll = {
>                         .shift   = 9,
>                         .width   = 5,
>                 },
> -               .od = {
> -                       .reg_off = HHI_HIFI_PLL_CNTL,
> -                       .shift   = 16,
> -                       .width   = 2,
> -               },
>                 .frac = {
>                         .reg_off = HHI_HIFI_PLL_CNTL5,
>                         .shift   = 0,
> @@ -309,13 +277,29 @@ static struct clk_regmap axg_hifi_pll = {
>                 .flags = CLK_MESON_PLL_ROUND_CLOSEST,
>         },
>         .hw.init = &(struct clk_init_data){
> -               .name = "hifi_pll",
> +               .name = "hifi_pll_dco",
>                 .ops = &meson_clk_pll_ops,
>                 .parent_names = (const char *[]){ "xtal" },
>                 .num_parents = 1,
>         },
>  };
>
> +static struct clk_regmap axg_hifi_pll = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_HIFI_PLL_CNTL,
> +               .shift = 16,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "hifi_pll",
> +               .ops = &clk_regmap_divider_ops,
> +               .parent_names = (const char *[]){ "hifi_pll_dco" },
> +               .num_parents = 1,
> +               .flags = CLK_SET_RATE_PARENT,
> +       },
> +};
> +
>  static struct clk_fixed_factor axg_fclk_div2_div = {
>         .mult = 1,
>         .div = 2,
> @@ -645,11 +629,9 @@ static struct clk_regmap axg_mpll3 = {
>
>  static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
>         {
> -               .rate   = 100000000,
> +               .rate   = 1600000000,
>                 .m      = 200,
>                 .n      = 3,
> -               .od     = 1,
> -               .od2    = 3,
>         },
>         { /* sentinel */ },
>  };
> @@ -661,9 +643,10 @@ static const struct reg_sequence axg_pcie_init_regs[] = {
>         { .reg = HHI_PCIE_PLL_CNTL4,    .def = 0xc000004d },
>         { .reg = HHI_PCIE_PLL_CNTL5,    .def = 0x00078000 },
>         { .reg = HHI_PCIE_PLL_CNTL6,    .def = 0x002323c6 },
> +       { .reg = HHI_PCIE_PLL_CNTL,     .def = 0x400106c8 },
>  };
>
> -static struct clk_regmap axg_pcie_pll = {
> +static struct clk_regmap axg_pcie_pll_dco = {
>         .data = &(struct meson_clk_pll_data){
>                 .en = {
>                         .reg_off = HHI_PCIE_PLL_CNTL,
> @@ -680,16 +663,6 @@ static struct clk_regmap axg_pcie_pll = {
>                         .shift   = 9,
>                         .width   = 5,
>                 },
> -               .od = {
> -                       .reg_off = HHI_PCIE_PLL_CNTL,
> -                       .shift   = 16,
> -                       .width   = 2,
> -               },
> -               .od2 = {
> -                       .reg_off = HHI_PCIE_PLL_CNTL6,
> -                       .shift   = 6,
> -                       .width   = 2,
> -               },
>                 .frac = {
>                         .reg_off = HHI_PCIE_PLL_CNTL1,
>                         .shift   = 0,
> @@ -710,13 +683,45 @@ static struct clk_regmap axg_pcie_pll = {
>                 .init_count = ARRAY_SIZE(axg_pcie_init_regs),
>         },
>         .hw.init = &(struct clk_init_data){
> -               .name = "pcie_pll",
> +               .name = "pcie_pll_dco",
>                 .ops = &meson_clk_pll_ops,
>                 .parent_names = (const char *[]){ "xtal" },
>                 .num_parents = 1,
>         },
>  };
>
> +static struct clk_regmap axg_pcie_pll_od = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_PCIE_PLL_CNTL,
> +               .shift = 16,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "pcie_pll_od",
> +               .ops = &clk_regmap_divider_ops,
> +               .parent_names = (const char *[]){ "pcie_pll_dco" },
> +               .num_parents = 1,
> +               .flags = CLK_SET_RATE_PARENT,
> +       },
> +};
> +
> +static struct clk_regmap axg_pcie_pll = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_PCIE_PLL_CNTL6,
> +               .shift = 6,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "pcie_pll",
> +               .ops = &clk_regmap_divider_ops,
> +               .parent_names = (const char *[]){ "pcie_pll_od" },
> +               .num_parents = 1,
> +               .flags = CLK_SET_RATE_PARENT,
> +       },
> +};
> +
>  static struct clk_regmap axg_pcie_mux = {
>         .data = &(struct clk_regmap_mux_data){
>                 .offset = HHI_PCIE_PLL_CNTL6,
> @@ -1129,6 +1134,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
>                 [CLKID_GEN_CLK_SEL]             = &axg_gen_clk_sel.hw,
>                 [CLKID_GEN_CLK_DIV]             = &axg_gen_clk_div.hw,
>                 [CLKID_GEN_CLK]                 = &axg_gen_clk.hw,
> +               [CLKID_SYS_PLL_DCO]             = &axg_sys_pll_dco.hw,
> +               [CLKID_FIXED_PLL_DCO]           = &axg_fixed_pll_dco.hw,
> +               [CLKID_GP0_PLL_DCO]             = &axg_gp0_pll_dco.hw,
> +               [CLKID_HIFI_PLL_DCO]            = &axg_hifi_pll_dco.hw,
> +               [CLKID_PCIE_PLL_DCO]            = &axg_pcie_pll_dco.hw,
> +               [CLKID_PCIE_PLL_OD]             = &axg_pcie_pll_od.hw,
>                 [NR_CLKS]                       = NULL,
>         },
>         .num = NR_CLKS,
> @@ -1207,6 +1218,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
>         &axg_fclk_div4,
>         &axg_fclk_div5,
>         &axg_fclk_div7,
> +       &axg_pcie_pll_dco,
> +       &axg_pcie_pll_od,
>         &axg_pcie_pll,
>         &axg_pcie_mux,
>         &axg_pcie_ref,
> @@ -1216,6 +1229,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
>         &axg_gen_clk_sel,
>         &axg_gen_clk_div,
>         &axg_gen_clk,
> +       &axg_fixed_pll_dco,
> +       &axg_sys_pll_dco,
> +       &axg_gp0_pll_dco,
> +       &axg_hifi_pll_dco,
> +       &axg_pcie_pll_dco,
> +       &axg_pcie_pll_od,
>  };
>
>  static const struct of_device_id clkc_match_table[] = {
> diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h
> index 1d04144a1b2c..0431dabac629 100644
> --- a/drivers/clk/meson/axg.h
> +++ b/drivers/clk/meson/axg.h
> @@ -133,8 +133,14 @@
>  #define CLKID_PCIE_REF                         78
>  #define CLKID_GEN_CLK_SEL                      82
>  #define CLKID_GEN_CLK_DIV                      83
> +#define CLKID_SYS_PLL_DCO                      85
> +#define CLKID_FIXED_PLL_DCO                    86
> +#define CLKID_GP0_PLL_DCO                      87
> +#define CLKID_HIFI_PLL_DCO                     88
> +#define CLKID_PCIE_PLL_DCO                     89
> +#define CLKID_PCIE_PLL_OD                      90
>
> -#define NR_CLKS                                        85
> +#define NR_CLKS                                        91
>
>  /* include the CLKIDs that have been made part of the DT binding */
>  #include <dt-bindings/clock/axg-clkc.h>
> diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> index 8aaefe67025f..348a866f09eb 100644
> --- a/drivers/clk/meson/clk-pll.c
> +++ b/drivers/clk/meson/clk-pll.c
> @@ -11,15 +11,19 @@
>   * In the most basic form, a Meson PLL is composed as follows:
>   *
>   *                     PLL
> - *      +------------------------------+
> - *      |                              |
> - * in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
> - *      |         ^        ^           |
> - *      +------------------------------+
> - *                |        |
> - *               FREF     VCO
> + *        +--------------------------------+
> + *        |                                |
> + *        |             +--+               |
> + *  in >>-----[ /N ]--->|  |      +-----+  |
> + *        |             |  |------| DCO |---->> out
> + *        |  +--------->|  |      +--v--+  |
> + *        |  |          +--+         |     |
> + *        |  |                       |     |
> + *        |  +--[ *(M + (F/Fmax) ]<--+     |
> + *        |                                |
> + *        +--------------------------------+
>   *
> - * out = in * (m + frac / frac_max) / (n << sum(ods))
> + * out = in * (m + frac / frac_max) / n
>   */
>
>  #include <linux/clk-provider.h>
> @@ -46,7 +50,6 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
>                                           struct meson_clk_pll_data *pll)
>  {
>         u64 rate = (u64)parent_rate * pllt->m;
> -       unsigned int od = pllt->od + pllt->od2 + pllt->od3;
>
>         if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
>                 u64 frac_rate = (u64)parent_rate * frac;
> @@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
>                                          (1 << pll->frac.width));
>         }
>
> -       return DIV_ROUND_UP_ULL(rate, pllt->n << od);
> +       return DIV_ROUND_UP_ULL(rate, pllt->n);
>  }
>
>  static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
> @@ -68,15 +71,6 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
>
>         pllt.n = meson_parm_read(clk->map, &pll->n);
>         pllt.m = meson_parm_read(clk->map, &pll->m);
> -       pllt.od = meson_parm_read(clk->map, &pll->od);
> -
> -       pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
> -               meson_parm_read(clk->map, &pll->od2) :
> -               0;
> -
> -       pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
> -               meson_parm_read(clk->map, &pll->od3) :
> -               0;
>
>         frac = MESON_PARM_APPLICABLE(&pll->frac) ?
>                 meson_parm_read(clk->map, &pll->frac) :
> @@ -93,8 +87,6 @@ static u16 __pll_params_with_frac(unsigned long rate,
>         u16 frac_max = (1 << pll->frac.width);
>         u64 val = (u64)rate * pllt->n;
>
> -       val <<= pllt->od + pllt->od2 + pllt->od3;
> -
>         if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
>                 val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
>         else
> @@ -242,13 +234,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
>
>         meson_parm_write(clk->map, &pll->n, pllt->n);
>         meson_parm_write(clk->map, &pll->m, pllt->m);
> -       meson_parm_write(clk->map, &pll->od, pllt->od);
> -
> -       if (MESON_PARM_APPLICABLE(&pll->od2))
> -               meson_parm_write(clk->map, &pll->od2, pllt->od2);
>
> -       if (MESON_PARM_APPLICABLE(&pll->od3))
> -               meson_parm_write(clk->map, &pll->od3, pllt->od3);
>
>         if (MESON_PARM_APPLICABLE(&pll->frac)) {
>                 frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> index c2ee37a78ceb..a2245e857f70 100644
> --- a/drivers/clk/meson/clkc.h
> +++ b/drivers/clk/meson/clkc.h
> @@ -47,17 +47,13 @@ struct pll_rate_table {
>         unsigned long   rate;
>         u16             m;
>         u16             n;
> -       u16             od;
> -       u16             od2;
> -       u16             od3;
>  };
>
> -#define PLL_RATE(_r, _m, _n, _od)                                      \
> +#define PLL_RATE(_r, _m, _n)                                           \
>         {                                                               \
>                 .rate           = (_r),                                 \
>                 .m              = (_m),                                 \
>                 .n              = (_n),                                 \
> -               .od             = (_od),                                \
>         }
>
>  #define CLK_MESON_PLL_ROUND_CLOSEST    BIT(0)
> @@ -67,9 +63,6 @@ struct meson_clk_pll_data {
>         struct parm m;
>         struct parm n;
>         struct parm frac;
> -       struct parm od;
> -       struct parm od2;
> -       struct parm od3;
>         struct parm l;
>         struct parm rst;
>         const struct reg_sequence *init_regs;
> diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> index 5ed34566917c..e2d94498f098 100644
> --- a/drivers/clk/meson/gxbb.c
> +++ b/drivers/clk/meson/gxbb.c
> @@ -19,163 +19,70 @@
>  static DEFINE_SPINLOCK(meson_clk_lock);
>
>  static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
> -       PLL_RATE(96000000, 32, 1, 3),
> -       PLL_RATE(99000000, 33, 1, 3),
> -       PLL_RATE(102000000, 34, 1, 3),
> -       PLL_RATE(105000000, 35, 1, 3),
> -       PLL_RATE(108000000, 36, 1, 3),
> -       PLL_RATE(111000000, 37, 1, 3),
> -       PLL_RATE(114000000, 38, 1, 3),
> -       PLL_RATE(117000000, 39, 1, 3),
> -       PLL_RATE(120000000, 40, 1, 3),
> -       PLL_RATE(123000000, 41, 1, 3),
> -       PLL_RATE(126000000, 42, 1, 3),
> -       PLL_RATE(129000000, 43, 1, 3),
> -       PLL_RATE(132000000, 44, 1, 3),
> -       PLL_RATE(135000000, 45, 1, 3),
> -       PLL_RATE(138000000, 46, 1, 3),
> -       PLL_RATE(141000000, 47, 1, 3),
> -       PLL_RATE(144000000, 48, 1, 3),
> -       PLL_RATE(147000000, 49, 1, 3),
> -       PLL_RATE(150000000, 50, 1, 3),
> -       PLL_RATE(153000000, 51, 1, 3),
> -       PLL_RATE(156000000, 52, 1, 3),
> -       PLL_RATE(159000000, 53, 1, 3),
> -       PLL_RATE(162000000, 54, 1, 3),
> -       PLL_RATE(165000000, 55, 1, 3),
> -       PLL_RATE(168000000, 56, 1, 3),
> -       PLL_RATE(171000000, 57, 1, 3),
> -       PLL_RATE(174000000, 58, 1, 3),
> -       PLL_RATE(177000000, 59, 1, 3),
> -       PLL_RATE(180000000, 60, 1, 3),
> -       PLL_RATE(183000000, 61, 1, 3),
> -       PLL_RATE(186000000, 62, 1, 3),
> -       PLL_RATE(192000000, 32, 1, 2),
> -       PLL_RATE(198000000, 33, 1, 2),
> -       PLL_RATE(204000000, 34, 1, 2),
> -       PLL_RATE(210000000, 35, 1, 2),
> -       PLL_RATE(216000000, 36, 1, 2),
> -       PLL_RATE(222000000, 37, 1, 2),
> -       PLL_RATE(228000000, 38, 1, 2),
> -       PLL_RATE(234000000, 39, 1, 2),
> -       PLL_RATE(240000000, 40, 1, 2),
> -       PLL_RATE(246000000, 41, 1, 2),
> -       PLL_RATE(252000000, 42, 1, 2),
> -       PLL_RATE(258000000, 43, 1, 2),
> -       PLL_RATE(264000000, 44, 1, 2),
> -       PLL_RATE(270000000, 45, 1, 2),
> -       PLL_RATE(276000000, 46, 1, 2),
> -       PLL_RATE(282000000, 47, 1, 2),
> -       PLL_RATE(288000000, 48, 1, 2),
> -       PLL_RATE(294000000, 49, 1, 2),
> -       PLL_RATE(300000000, 50, 1, 2),
> -       PLL_RATE(306000000, 51, 1, 2),
> -       PLL_RATE(312000000, 52, 1, 2),
> -       PLL_RATE(318000000, 53, 1, 2),
> -       PLL_RATE(324000000, 54, 1, 2),
> -       PLL_RATE(330000000, 55, 1, 2),
> -       PLL_RATE(336000000, 56, 1, 2),
> -       PLL_RATE(342000000, 57, 1, 2),
> -       PLL_RATE(348000000, 58, 1, 2),
> -       PLL_RATE(354000000, 59, 1, 2),
> -       PLL_RATE(360000000, 60, 1, 2),
> -       PLL_RATE(366000000, 61, 1, 2),
> -       PLL_RATE(372000000, 62, 1, 2),
> -       PLL_RATE(384000000, 32, 1, 1),
> -       PLL_RATE(396000000, 33, 1, 1),
> -       PLL_RATE(408000000, 34, 1, 1),
> -       PLL_RATE(420000000, 35, 1, 1),
> -       PLL_RATE(432000000, 36, 1, 1),
> -       PLL_RATE(444000000, 37, 1, 1),
> -       PLL_RATE(456000000, 38, 1, 1),
> -       PLL_RATE(468000000, 39, 1, 1),
> -       PLL_RATE(480000000, 40, 1, 1),
> -       PLL_RATE(492000000, 41, 1, 1),
> -       PLL_RATE(504000000, 42, 1, 1),
> -       PLL_RATE(516000000, 43, 1, 1),
> -       PLL_RATE(528000000, 44, 1, 1),
> -       PLL_RATE(540000000, 45, 1, 1),
> -       PLL_RATE(552000000, 46, 1, 1),
> -       PLL_RATE(564000000, 47, 1, 1),
> -       PLL_RATE(576000000, 48, 1, 1),
> -       PLL_RATE(588000000, 49, 1, 1),
> -       PLL_RATE(600000000, 50, 1, 1),
> -       PLL_RATE(612000000, 51, 1, 1),
> -       PLL_RATE(624000000, 52, 1, 1),
> -       PLL_RATE(636000000, 53, 1, 1),
> -       PLL_RATE(648000000, 54, 1, 1),
> -       PLL_RATE(660000000, 55, 1, 1),
> -       PLL_RATE(672000000, 56, 1, 1),
> -       PLL_RATE(684000000, 57, 1, 1),
> -       PLL_RATE(696000000, 58, 1, 1),
> -       PLL_RATE(708000000, 59, 1, 1),
> -       PLL_RATE(720000000, 60, 1, 1),
> -       PLL_RATE(732000000, 61, 1, 1),
> -       PLL_RATE(744000000, 62, 1, 1),
> -       PLL_RATE(768000000, 32, 1, 0),
> -       PLL_RATE(792000000, 33, 1, 0),
> -       PLL_RATE(816000000, 34, 1, 0),
> -       PLL_RATE(840000000, 35, 1, 0),
> -       PLL_RATE(864000000, 36, 1, 0),
> -       PLL_RATE(888000000, 37, 1, 0),
> -       PLL_RATE(912000000, 38, 1, 0),
> -       PLL_RATE(936000000, 39, 1, 0),
> -       PLL_RATE(960000000, 40, 1, 0),
> -       PLL_RATE(984000000, 41, 1, 0),
> -       PLL_RATE(1008000000, 42, 1, 0),
> -       PLL_RATE(1032000000, 43, 1, 0),
> -       PLL_RATE(1056000000, 44, 1, 0),
> -       PLL_RATE(1080000000, 45, 1, 0),
> -       PLL_RATE(1104000000, 46, 1, 0),
> -       PLL_RATE(1128000000, 47, 1, 0),
> -       PLL_RATE(1152000000, 48, 1, 0),
> -       PLL_RATE(1176000000, 49, 1, 0),
> -       PLL_RATE(1200000000, 50, 1, 0),
> -       PLL_RATE(1224000000, 51, 1, 0),
> -       PLL_RATE(1248000000, 52, 1, 0),
> -       PLL_RATE(1272000000, 53, 1, 0),
> -       PLL_RATE(1296000000, 54, 1, 0),
> -       PLL_RATE(1320000000, 55, 1, 0),
> -       PLL_RATE(1344000000, 56, 1, 0),
> -       PLL_RATE(1368000000, 57, 1, 0),
> -       PLL_RATE(1392000000, 58, 1, 0),
> -       PLL_RATE(1416000000, 59, 1, 0),
> -       PLL_RATE(1440000000, 60, 1, 0),
> -       PLL_RATE(1464000000, 61, 1, 0),
> -       PLL_RATE(1488000000, 62, 1, 0),
> +       PLL_RATE(768000000, 32, 1),
> +       PLL_RATE(792000000, 33, 1),
> +       PLL_RATE(816000000, 34, 1),
> +       PLL_RATE(840000000, 35, 1),
> +       PLL_RATE(864000000, 36, 1),
> +       PLL_RATE(888000000, 37, 1),
> +       PLL_RATE(912000000, 38, 1),
> +       PLL_RATE(936000000, 39, 1),
> +       PLL_RATE(960000000, 40, 1),
> +       PLL_RATE(984000000, 41, 1),
> +       PLL_RATE(1008000000, 42, 1),
> +       PLL_RATE(1032000000, 43, 1),
> +       PLL_RATE(1056000000, 44, 1),
> +       PLL_RATE(1080000000, 45, 1),
> +       PLL_RATE(1104000000, 46, 1),
> +       PLL_RATE(1128000000, 47, 1),
> +       PLL_RATE(1152000000, 48, 1),
> +       PLL_RATE(1176000000, 49, 1),
> +       PLL_RATE(1200000000, 50, 1),
> +       PLL_RATE(1224000000, 51, 1),
> +       PLL_RATE(1248000000, 52, 1),
> +       PLL_RATE(1272000000, 53, 1),
> +       PLL_RATE(1296000000, 54, 1),
> +       PLL_RATE(1320000000, 55, 1),
> +       PLL_RATE(1344000000, 56, 1),
> +       PLL_RATE(1368000000, 57, 1),
> +       PLL_RATE(1392000000, 58, 1),
> +       PLL_RATE(1416000000, 59, 1),
> +       PLL_RATE(1440000000, 60, 1),
> +       PLL_RATE(1464000000, 61, 1),
> +       PLL_RATE(1488000000, 62, 1),
>         { /* sentinel */ },
>  };
>
>  static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
> -       PLL_RATE(504000000, 42, 1, 1),
> -       PLL_RATE(516000000, 43, 1, 1),
> -       PLL_RATE(528000000, 44, 1, 1),
> -       PLL_RATE(540000000, 45, 1, 1),
> -       PLL_RATE(552000000, 46, 1, 1),
> -       PLL_RATE(564000000, 47, 1, 1),
> -       PLL_RATE(576000000, 48, 1, 1),
> -       PLL_RATE(588000000, 49, 1, 1),
> -       PLL_RATE(600000000, 50, 1, 1),
> -       PLL_RATE(612000000, 51, 1, 1),
> -       PLL_RATE(624000000, 52, 1, 1),
> -       PLL_RATE(636000000, 53, 1, 1),
> -       PLL_RATE(648000000, 54, 1, 1),
> -       PLL_RATE(660000000, 55, 1, 1),
> -       PLL_RATE(672000000, 56, 1, 1),
> -       PLL_RATE(684000000, 57, 1, 1),
> -       PLL_RATE(696000000, 58, 1, 1),
> -       PLL_RATE(708000000, 59, 1, 1),
> -       PLL_RATE(720000000, 60, 1, 1),
> -       PLL_RATE(732000000, 61, 1, 1),
> -       PLL_RATE(744000000, 62, 1, 1),
> -       PLL_RATE(756000000, 63, 1, 1),
> -       PLL_RATE(768000000, 64, 1, 1),
> -       PLL_RATE(780000000, 65, 1, 1),
> -       PLL_RATE(792000000, 66, 1, 1),
> +       PLL_RATE(1008000000, 42, 1),
> +       PLL_RATE(1032000000, 43, 1),
> +       PLL_RATE(1056000000, 44, 1),
> +       PLL_RATE(1080000000, 45, 1),
> +       PLL_RATE(1104000000, 46, 1),
> +       PLL_RATE(1128000000, 47, 1),
> +       PLL_RATE(1152000000, 48, 1),
> +       PLL_RATE(1176000000, 49, 1),
> +       PLL_RATE(1200000000, 50, 1),
> +       PLL_RATE(1224000000, 51, 1),
> +       PLL_RATE(1248000000, 52, 1),
> +       PLL_RATE(1272000000, 53, 1),
> +       PLL_RATE(1296000000, 54, 1),
> +       PLL_RATE(1320000000, 55, 1),
> +       PLL_RATE(1344000000, 56, 1),
> +       PLL_RATE(1368000000, 57, 1),
> +       PLL_RATE(1392000000, 58, 1),
> +       PLL_RATE(1416000000, 59, 1),
> +       PLL_RATE(1440000000, 60, 1),
> +       PLL_RATE(1464000000, 61, 1),
> +       PLL_RATE(1488000000, 62, 1),
> +       PLL_RATE(1512000000, 63, 1),
> +       PLL_RATE(1536000000, 64, 1),
> +       PLL_RATE(1560000000, 65, 1),
> +       PLL_RATE(1584000000, 66, 1),
>         { /* sentinel */ },
>  };
>
> -static struct clk_regmap gxbb_fixed_pll = {
> +static struct clk_regmap gxbb_fixed_pll_dco = {
>         .data = &(struct meson_clk_pll_data){
>                 .en = {
>                         .reg_off = HHI_MPLL_CNTL,
> @@ -192,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = {
>                         .shift   = 9,
>                         .width   = 5,
>                 },
> -               .od = {
> -                       .reg_off = HHI_MPLL_CNTL,
> -                       .shift   = 16,
> -                       .width   = 2,
> -               },
>                 .frac = {
>                         .reg_off = HHI_MPLL_CNTL2,
>                         .shift   = 0,
> @@ -214,7 +116,7 @@ static struct clk_regmap gxbb_fixed_pll = {
>                 },
>         },
>         .hw.init = &(struct clk_init_data){
> -               .name = "fixed_pll",
> +               .name = "fixed_pll_dco",
>                 .ops = &meson_clk_pll_ro_ops,
>                 .parent_names = (const char *[]){ "xtal" },
>                 .num_parents = 1,
> @@ -222,6 +124,21 @@ static struct clk_regmap gxbb_fixed_pll = {
>         },
>  };
>
> +static struct clk_regmap gxbb_fixed_pll = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_MPLL_CNTL,
> +               .shift = 16,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "fixed_pll",
> +               .ops = &clk_regmap_divider_ro_ops,
> +               .parent_names = (const char *[]){ "fixed_pll_dco" },
> +               .num_parents = 1,
> +       },
> +};
> +
>  static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
>         .mult = 2,
>         .div = 1,
> @@ -233,7 +150,7 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
>         },
>  };
>
> -static struct clk_regmap gxbb_hdmi_pll = {
> +static struct clk_regmap gxbb_hdmi_pll_dco = {
>         .data = &(struct meson_clk_pll_data){
>                 .en = {
>                         .reg_off = HHI_HDMI_PLL_CNTL,
> @@ -255,21 +172,6 @@ static struct clk_regmap gxbb_hdmi_pll = {
>                         .shift   = 0,
>                         .width   = 12,
>                 },
> -               .od = {
> -                       .reg_off = HHI_HDMI_PLL_CNTL2,
> -                       .shift   = 16,
> -                       .width   = 2,
> -               },
> -               .od2 = {
> -                       .reg_off = HHI_HDMI_PLL_CNTL2,
> -                       .shift   = 22,
> -                       .width   = 2,
> -               },
> -               .od3 = {
> -                       .reg_off = HHI_HDMI_PLL_CNTL2,
> -                       .shift   = 18,
> -                       .width   = 2,
> -               },
>                 .l = {
>                         .reg_off = HHI_HDMI_PLL_CNTL,
>                         .shift   = 31,
> @@ -282,7 +184,7 @@ static struct clk_regmap gxbb_hdmi_pll = {
>                 },
>         },
>         .hw.init = &(struct clk_init_data){
> -               .name = "hdmi_pll",
> +               .name = "hdmi_pll_dco",
>                 .ops = &meson_clk_pll_ro_ops,
>                 .parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
>                 .num_parents = 1,
> @@ -290,70 +192,103 @@ static struct clk_regmap gxbb_hdmi_pll = {
>         },
>  };
>
> +static struct clk_regmap gxbb_hdmi_pll_od = {
> +       .data = &(struct clk_regmap_div_data){
> +               .offset = HHI_HDMI_PLL_CNTL2,
> +               .shift = 16,
> +               .width = 2,
> +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> +       },
> +       .hw.init = &(struct clk_init_data){
> +               .name = "hdmi_pll_od",
> +               .ops = &clk_regmap_divider_ro_ops,
> +               .parent_names = (const char *[]){ "hdmi_pll_dco" },
> +               .num_parents = 1,
> +               .flags = CLK_GET_RATE_NOCACHE,
why do we need CLK_GET_RATE_NOCACHE here?
also, shouldn't all _od clocks use CLK_SET_RATE_PARENT?
(this applies to all new _od clocks, not just this one)


Regards
Martin

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

* Re: [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables
  2018-07-19  8:44   ` Neil Armstrong
  2018-07-19  8:59     ` Jerome Brunet
@ 2018-07-21 20:16     ` Martin Blumenstingl
  2018-07-21 20:46       ` Jerome Brunet
  1 sibling, 1 reply; 20+ messages in thread
From: Martin Blumenstingl @ 2018-07-21 20:16 UTC (permalink / raw)
  To: Neil Armstrong; +Cc: jbrunet, linux-amlogic, linux-clk, linux-kernel, khilman

On Thu, Jul 19, 2018 at 10:44 AM Neil Armstrong <narmstrong@baylibre.com> wrote:
>
> On 17/07/2018 11:56, Jerome Brunet wrote:
> > Putting hard-coded rates inside the parameter tables assumes that
> > the parent is known and will never change. That's a big assumption
> > we should not make.
> >
> > We have everything we need to recalculate the output rate using
> > the parent rate and the rest of the parameters. Let's do so and
> > drop the rates from the tables.
> >
> > Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
> > ---
> >  drivers/clk/meson/axg.c     |  73 +++++++++++++--------------
> >  drivers/clk/meson/clk-pll.c |  69 ++++++++++++++++---------
> >  drivers/clk/meson/clkc.h    |   8 ++-
> >  drivers/clk/meson/gxbb.c    | 120 ++++++++++++++++++++++----------------------
> >  drivers/clk/meson/meson8b.c |  34 ++++++-------
> >  5 files changed, 162 insertions(+), 142 deletions(-)
> >
> > diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
> > index 572358062459..d34954bd8c5e 100644
> > --- a/drivers/clk/meson/axg.c
> > +++ b/drivers/clk/meson/axg.c
> > @@ -130,36 +130,36 @@ static struct clk_regmap axg_sys_pll = {
> >       },
> >  };
> >
> > -static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
> > -     PLL_RATE(960000000, 40, 1),
> > -     PLL_RATE(984000000, 41, 1),
> > -     PLL_RATE(1008000000, 42, 1),
> > -     PLL_RATE(1032000000, 43, 1),
> > -     PLL_RATE(1056000000, 44, 1),
> > -     PLL_RATE(1080000000, 45, 1),
> > -     PLL_RATE(1104000000, 46, 1),
> > -     PLL_RATE(1128000000, 47, 1),
> > -     PLL_RATE(1152000000, 48, 1),
> > -     PLL_RATE(1176000000, 49, 1),
> > -     PLL_RATE(1200000000, 50, 1),
> > -     PLL_RATE(1224000000, 51, 1),
> > -     PLL_RATE(1248000000, 52, 1),
> > -     PLL_RATE(1272000000, 53, 1),
> > -     PLL_RATE(1296000000, 54, 1),
> > -     PLL_RATE(1320000000, 55, 1),
> > -     PLL_RATE(1344000000, 56, 1),
> > -     PLL_RATE(1368000000, 57, 1),
> > -     PLL_RATE(1392000000, 58, 1),
> > -     PLL_RATE(1416000000, 59, 1),
> > -     PLL_RATE(1440000000, 60, 1),
> > -     PLL_RATE(1464000000, 61, 1),
> > -     PLL_RATE(1488000000, 62, 1),
> > -     PLL_RATE(1512000000, 63, 1),
> > -     PLL_RATE(1536000000, 64, 1),
> > -     PLL_RATE(1560000000, 65, 1),
> > -     PLL_RATE(1584000000, 66, 1),
> > -     PLL_RATE(1608000000, 67, 1),
> > -     PLL_RATE(1632000000, 68, 1),
> > +static const struct pll_params_table axg_gp0_pll_params_table[] = {
> > +     PLL_PARAMS(40, 1),
> > +     PLL_PARAMS(41, 1),
> > +     PLL_PARAMS(42, 1),
> > +     PLL_PARAMS(43, 1),
> > +     PLL_PARAMS(44, 1),
> > +     PLL_PARAMS(45, 1),
> > +     PLL_PARAMS(46, 1),
> > +     PLL_PARAMS(47, 1),
> > +     PLL_PARAMS(48, 1),
> > +     PLL_PARAMS(49, 1),
> > +     PLL_PARAMS(50, 1),
> > +     PLL_PARAMS(51, 1),
> > +     PLL_PARAMS(52, 1),
> > +     PLL_PARAMS(53, 1),
> > +     PLL_PARAMS(54, 1),
> > +     PLL_PARAMS(55, 1),
> > +     PLL_PARAMS(56, 1),
> > +     PLL_PARAMS(57, 1),
> > +     PLL_PARAMS(58, 1),
> > +     PLL_PARAMS(59, 1),
> > +     PLL_PARAMS(60, 1),
> > +     PLL_PARAMS(61, 1),
> > +     PLL_PARAMS(62, 1),
> > +     PLL_PARAMS(63, 1),
> > +     PLL_PARAMS(64, 1),
> > +     PLL_PARAMS(65, 1),
> > +     PLL_PARAMS(66, 1),
> > +     PLL_PARAMS(67, 1),
> > +     PLL_PARAMS(68, 1),
> >       { /* sentinel */ },
> >  };
> >
> > @@ -203,7 +203,7 @@ static struct clk_regmap axg_gp0_pll_dco = {
> >                       .shift   = 29,
> >                       .width   = 1,
> >               },
> > -             .table = axg_gp0_pll_rate_table,
> > +             .table = axg_gp0_pll_params_table,
> >               .init_regs = axg_gp0_init_regs,
> >               .init_count = ARRAY_SIZE(axg_gp0_init_regs),
> >       },
> > @@ -271,7 +271,7 @@ static struct clk_regmap axg_hifi_pll_dco = {
> >                       .shift   = 29,
> >                       .width   = 1,
> >               },
> > -             .table = axg_gp0_pll_rate_table,
> > +             .table = axg_gp0_pll_params_table,
> >               .init_regs = axg_hifi_init_regs,
> >               .init_count = ARRAY_SIZE(axg_hifi_init_regs),
> >               .flags = CLK_MESON_PLL_ROUND_CLOSEST,
> > @@ -627,11 +627,10 @@ static struct clk_regmap axg_mpll3 = {
> >       },
> >  };
> >
> > -static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
> > +static const struct pll_params_table axg_pcie_pll_params_table[] = {
> >       {
> > -             .rate   = 1600000000,
> > -             .m      = 200,
> > -             .n      = 3,
> > +             .m = 200,
> > +             .n = 3,
> >       },
> >       { /* sentinel */ },
> >  };
> > @@ -678,7 +677,7 @@ static struct clk_regmap axg_pcie_pll_dco = {
> >                       .shift   = 29,
> >                       .width   = 1,
> >               },
> > -             .table = axg_pcie_pll_rate_table,
> > +             .table = axg_pcie_pll_params_table,
> >               .init_regs = axg_pcie_init_regs,
> >               .init_count = ARRAY_SIZE(axg_pcie_init_regs),
> >       },
> > diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
> > index 348a866f09eb..f5b5b3fabe3c 100644
> > --- a/drivers/clk/meson/clk-pll.c
> > +++ b/drivers/clk/meson/clk-pll.c
> > @@ -45,7 +45,7 @@ meson_clk_pll_data(struct clk_regmap *clk)
> >  }
> >
> >  static unsigned long __pll_params_to_rate(unsigned long parent_rate,
> > -                                       const struct pll_rate_table *pllt,
> > +                                       const struct pll_params_table *pllt,
> >                                         u16 frac,
> >                                         struct meson_clk_pll_data *pll)
> >  {
> > @@ -66,7 +66,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
> >  {
> >       struct clk_regmap *clk = to_clk_regmap(hw);
> >       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> > -     struct pll_rate_table pllt;
> > +     struct pll_params_table pllt;
> >       u16 frac;
> >
> >       pllt.n = meson_parm_read(clk->map, &pll->n);
> > @@ -81,7 +81,7 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
> >
> >  static u16 __pll_params_with_frac(unsigned long rate,
> >                                 unsigned long parent_rate,
> > -                               const struct pll_rate_table *pllt,
> > +                               const struct pll_params_table *pllt,
> >                                 struct meson_clk_pll_data *pll)
> >  {
> >       u16 frac_max = (1 << pll->frac.width);
> > @@ -97,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
> >       return min((u16)val, (u16)(frac_max - 1));
> >  }
> >
> > -static const struct pll_rate_table *
> > +static bool meson_clk_pll_is_better(unsigned long rate,
> > +                                 unsigned long best,
> > +                                 unsigned long now,
> > +                                 struct meson_clk_pll_data *pll)
> > +{
> > +     if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
> > +         MESON_PARM_APPLICABLE(&pll->frac)) {
> > +             /* Round down */
> > +             if (now < rate && best < now)
> > +                     return true;
> > +     } else {
> > +             /* Round Closest */
> > +             if (abs(now - rate) < abs(best - rate))
> > +                     return true;
> > +     }
> > +
> > +     return false;
> > +}
> > +
> > +static const struct pll_params_table *
> >  meson_clk_get_pll_settings(unsigned long rate,
> > +                        unsigned long parent_rate,
> >                          struct meson_clk_pll_data *pll)
> >  {
> > -     const struct pll_rate_table *table = pll->table;
> > -     unsigned int i = 0;
> > +     const struct pll_params_table *table = pll->table;
> > +     unsigned long best = 0, now = 0;
> > +     unsigned int i, best_i = 0;
> >
> >       if (!table)
> >               return NULL;
> >
> > -     /* Find the first table element exceeding rate */
> > -     while (table[i].rate && table[i].rate <= rate)
> > -             i++;
> > +     for (i = 0; table[i].n; i++) {
> > +             now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
> >
> > -     if (i != 0) {
> > -             if (MESON_PARM_APPLICABLE(&pll->frac) ||
> > -                 !(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
> > -                 (abs(rate - table[i - 1].rate) <
> > -                  abs(rate - table[i].rate)))
> > -                     i--;
> > +             /* If we get an exact match, don't bother any further */
> > +             if (now == rate) {
> > +                     return &table[i];
> > +             } else if (meson_clk_pll_is_better(rate, best, now, pll)) {
> > +                     best = now;
> > +                     best_i = i;
> > +             }
> >       }
> >
> > -     return (struct pll_rate_table *)&table[i];
> > +     return (struct pll_params_table *)&table[best_i];
> >  }
> >
> >  static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> > @@ -127,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
> >  {
> >       struct clk_regmap *clk = to_clk_regmap(hw);
> >       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> > -     const struct pll_rate_table *pllt =
> > -             meson_clk_get_pll_settings(rate, pll);
> > +     const struct pll_params_table *pllt =
> > +             meson_clk_get_pll_settings(rate, *parent_rate, pll);
> > +     unsigned long round;
> >       u16 frac;
> >
> >       if (!pllt)
> >               return meson_clk_pll_recalc_rate(hw, *parent_rate);
> >
> > -     if (!MESON_PARM_APPLICABLE(&pll->frac)
> > -         || rate == pllt->rate)
> > -             return pllt->rate;
> > +     round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
> > +
> > +     if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
> > +             return round;
> >
> >       /*
> >        * The rate provided by the setting is not an exact match, let's
> > @@ -214,7 +237,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> >  {
> >       struct clk_regmap *clk = to_clk_regmap(hw);
> >       struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
> > -     const struct pll_rate_table *pllt;
> > +     const struct pll_params_table *pllt;
> >       unsigned int enabled;
> >       unsigned long old_rate;
> >       u16 frac = 0;
> > @@ -224,7 +247,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
> >
> >       old_rate = rate;
> >
> > -     pllt = meson_clk_get_pll_settings(rate, pll);
> > +     pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
> >       if (!pllt)
> >               return -EINVAL;
> >
> > diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> > index a2245e857f70..6b96d55c047d 100644
> > --- a/drivers/clk/meson/clkc.h
> > +++ b/drivers/clk/meson/clkc.h
> > @@ -43,15 +43,13 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
> >  }
> >
> >
> > -struct pll_rate_table {
> > -     unsigned long   rate;
> > +struct pll_params_table {
> >       u16             m;
> >       u16             n;
> >  };
> >
> > -#define PLL_RATE(_r, _m, _n)                                         \
> > +#define PLL_PARAMS(_m, _n)                                           \
> >       {                                                               \
> > -             .rate           = (_r),                                 \
> >               .m              = (_m),                                 \
> >               .n              = (_n),                                 \
> >       }
> > @@ -67,7 +65,7 @@ struct meson_clk_pll_data {
> >       struct parm rst;
> >       const struct reg_sequence *init_regs;
> >       unsigned int init_count;
> > -     const struct pll_rate_table *table;
> > +     const struct pll_params_table *table;
> >       u8 flags;
> >  };
> >
> > diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
> > index e2d94498f098..9ac03c7bfbaa 100644
> > --- a/drivers/clk/meson/gxbb.c
> > +++ b/drivers/clk/meson/gxbb.c
> > @@ -18,67 +18,67 @@
> >
> >  static DEFINE_SPINLOCK(meson_clk_lock);
> >
> > -static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
> > -     PLL_RATE(768000000, 32, 1),
> > -     PLL_RATE(792000000, 33, 1),
> > -     PLL_RATE(816000000, 34, 1),
> > -     PLL_RATE(840000000, 35, 1),
> > -     PLL_RATE(864000000, 36, 1),
> > -     PLL_RATE(888000000, 37, 1),
> > -     PLL_RATE(912000000, 38, 1),
> > -     PLL_RATE(936000000, 39, 1),
> > -     PLL_RATE(960000000, 40, 1),
> > -     PLL_RATE(984000000, 41, 1),
> > -     PLL_RATE(1008000000, 42, 1),
> > -     PLL_RATE(1032000000, 43, 1),
> > -     PLL_RATE(1056000000, 44, 1),
> > -     PLL_RATE(1080000000, 45, 1),
> > -     PLL_RATE(1104000000, 46, 1),
> > -     PLL_RATE(1128000000, 47, 1),
> > -     PLL_RATE(1152000000, 48, 1),
> > -     PLL_RATE(1176000000, 49, 1),
> > -     PLL_RATE(1200000000, 50, 1),
> > -     PLL_RATE(1224000000, 51, 1),
> > -     PLL_RATE(1248000000, 52, 1),
> > -     PLL_RATE(1272000000, 53, 1),
> > -     PLL_RATE(1296000000, 54, 1),
> > -     PLL_RATE(1320000000, 55, 1),
> > -     PLL_RATE(1344000000, 56, 1),
> > -     PLL_RATE(1368000000, 57, 1),
> > -     PLL_RATE(1392000000, 58, 1),
> > -     PLL_RATE(1416000000, 59, 1),
> > -     PLL_RATE(1440000000, 60, 1),
> > -     PLL_RATE(1464000000, 61, 1),
> > -     PLL_RATE(1488000000, 62, 1),
> > +static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
> > +     PLL_PARAMS(32, 1),
> > +     PLL_PARAMS(33, 1),
> > +     PLL_PARAMS(34, 1),
> > +     PLL_PARAMS(35, 1),
> > +     PLL_PARAMS(36, 1),
> > +     PLL_PARAMS(37, 1),
> > +     PLL_PARAMS(38, 1),
> > +     PLL_PARAMS(39, 1),
> > +     PLL_PARAMS(40, 1),
> > +     PLL_PARAMS(41, 1),
> > +     PLL_PARAMS(42, 1),
> > +     PLL_PARAMS(43, 1),
> > +     PLL_PARAMS(44, 1),
> > +     PLL_PARAMS(45, 1),
> > +     PLL_PARAMS(46, 1),
> > +     PLL_PARAMS(47, 1),
> > +     PLL_PARAMS(48, 1),
> > +     PLL_PARAMS(49, 1),
> > +     PLL_PARAMS(50, 1),
> > +     PLL_PARAMS(51, 1),
> > +     PLL_PARAMS(52, 1),
> > +     PLL_PARAMS(53, 1),
> > +     PLL_PARAMS(54, 1),
> > +     PLL_PARAMS(55, 1),
> > +     PLL_PARAMS(56, 1),
> > +     PLL_PARAMS(57, 1),
> > +     PLL_PARAMS(58, 1),
> > +     PLL_PARAMS(59, 1),
> > +     PLL_PARAMS(60, 1),
> > +     PLL_PARAMS(61, 1),
> > +     PLL_PARAMS(62, 1),
> >       { /* sentinel */ },
> >  };
> >
> > -static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
> > -     PLL_RATE(1008000000, 42, 1),
> > -     PLL_RATE(1032000000, 43, 1),
> > -     PLL_RATE(1056000000, 44, 1),
> > -     PLL_RATE(1080000000, 45, 1),
> > -     PLL_RATE(1104000000, 46, 1),
> > -     PLL_RATE(1128000000, 47, 1),
> > -     PLL_RATE(1152000000, 48, 1),
> > -     PLL_RATE(1176000000, 49, 1),
> > -     PLL_RATE(1200000000, 50, 1),
> > -     PLL_RATE(1224000000, 51, 1),
> > -     PLL_RATE(1248000000, 52, 1),
> > -     PLL_RATE(1272000000, 53, 1),
> > -     PLL_RATE(1296000000, 54, 1),
> > -     PLL_RATE(1320000000, 55, 1),
> > -     PLL_RATE(1344000000, 56, 1),
> > -     PLL_RATE(1368000000, 57, 1),
> > -     PLL_RATE(1392000000, 58, 1),
> > -     PLL_RATE(1416000000, 59, 1),
> > -     PLL_RATE(1440000000, 60, 1),
> > -     PLL_RATE(1464000000, 61, 1),
> > -     PLL_RATE(1488000000, 62, 1),
> > -     PLL_RATE(1512000000, 63, 1),
> > -     PLL_RATE(1536000000, 64, 1),
> > -     PLL_RATE(1560000000, 65, 1),
> > -     PLL_RATE(1584000000, 66, 1),
> > +static const struct pll_params_table gxl_gp0_pll_params_table[] = {
> > +     PLL_PARAMS(42, 1),
> > +     PLL_PARAMS(43, 1),
> > +     PLL_PARAMS(44, 1),
> > +     PLL_PARAMS(45, 1),
> > +     PLL_PARAMS(46, 1),
> > +     PLL_PARAMS(47, 1),
> > +     PLL_PARAMS(48, 1),
> > +     PLL_PARAMS(49, 1),
> > +     PLL_PARAMS(50, 1),
> > +     PLL_PARAMS(51, 1),
> > +     PLL_PARAMS(52, 1),
> > +     PLL_PARAMS(53, 1),
> > +     PLL_PARAMS(54, 1),
> > +     PLL_PARAMS(55, 1),
> > +     PLL_PARAMS(56, 1),
> > +     PLL_PARAMS(57, 1),
> > +     PLL_PARAMS(58, 1),
> > +     PLL_PARAMS(59, 1),
> > +     PLL_PARAMS(60, 1),
> > +     PLL_PARAMS(61, 1),
> > +     PLL_PARAMS(62, 1),
> > +     PLL_PARAMS(63, 1),
> > +     PLL_PARAMS(64, 1),
> > +     PLL_PARAMS(65, 1),
> > +     PLL_PARAMS(66, 1),
> >       { /* sentinel */ },
> >  };
> >
> > @@ -374,7 +374,7 @@ static struct clk_regmap gxbb_gp0_pll_dco = {
> >                       .shift   = 29,
> >                       .width   = 1,
> >               },
> > -             .table = gxbb_gp0_pll_rate_table,
> > +             .table = gxbb_gp0_pll_params_table,
> >               .init_regs = gxbb_gp0_init_regs,
> >               .init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
> >       },
> > @@ -427,7 +427,7 @@ static struct clk_regmap gxl_gp0_pll_dco = {
> >                       .shift   = 29,
> >                       .width   = 1,
> >               },
> > -             .table = gxl_gp0_pll_rate_table,
> > +             .table = gxl_gp0_pll_params_table,
> >               .init_regs = gxl_gp0_init_regs,
> >               .init_count = ARRAY_SIZE(gxl_gp0_init_regs),
> >       },
> > diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
> > index 17bcf0be56ba..30ae849ff53f 100644
> > --- a/drivers/clk/meson/meson8b.c
> > +++ b/drivers/clk/meson/meson8b.c
> > @@ -29,22 +29,22 @@ struct meson8b_clk_reset {
> >       void __iomem *base;
> >  };
> >
> > -static const struct pll_rate_table sys_pll_rate_table[] = {
> > -     PLL_RATE(1200000000, 50, 1),
> > -     PLL_RATE(1224000000, 51, 1),
> > -     PLL_RATE(1248000000, 52, 1),
> > -     PLL_RATE(1272000000, 53, 1),
> > -     PLL_RATE(1296000000, 54, 1),
> > -     PLL_RATE(1320000000, 55, 1),
> > -     PLL_RATE(1344000000, 56, 1),
> > -     PLL_RATE(1368000000, 57, 1),
> > -     PLL_RATE(1392000000, 58, 1),
> > -     PLL_RATE(1416000000, 59, 1),
> > -     PLL_RATE(1440000000, 60, 1),
> > -     PLL_RATE(1464000000, 61, 1),
> > -     PLL_RATE(1488000000, 62, 1),
> > -     PLL_RATE(1512000000, 63, 1),
> > -     PLL_RATE(1536000000, 64, 1),
> > +static const struct pll_params_table sys_pll_params_table[] = {
> > +     PLL_PARAMS(50, 1),
> > +     PLL_PARAMS(51, 1),
> > +     PLL_PARAMS(52, 1),
> > +     PLL_PARAMS(53, 1),
> > +     PLL_PARAMS(54, 1),
> > +     PLL_PARAMS(55, 1),
> > +     PLL_PARAMS(56, 1),
> > +     PLL_PARAMS(57, 1),
> > +     PLL_PARAMS(58, 1),
> > +     PLL_PARAMS(59, 1),
> > +     PLL_PARAMS(60, 1),
> > +     PLL_PARAMS(61, 1),
> > +     PLL_PARAMS(62, 1),
> > +     PLL_PARAMS(63, 1),
> > +     PLL_PARAMS(64, 1),
> >       { /* sentinel */ },
> >  };
> >
> > @@ -195,7 +195,7 @@ static struct clk_regmap meson8b_sys_pll_dco = {
> >                       .shift   = 29,
> >                       .width   = 1,
> >               },
> > -             .table = sys_pll_rate_table,
> > +             .table = sys_pll_params_table,
> >       },
> >       .hw.init = &(struct clk_init_data){
> >               .name = "sys_pll_dco",
> >
>
> We could even add ranges instead of table when we know the PLL supports a well-known continuous dividers range.
I had a look at the sys_pll settings on Meson8b, here's what
Meson8/Meson8b/Meson8m2 support for sys_pll:
- 50..74
- 76
- 78
- 80
- 82
- 84
- 86
- 88
- 90
- 92
- 94
- 96
- 98

(I'm providing this info because it may help finding a decision
whether ranges are good or not. I have no preference)


Regards
Martin


[0] https://github.com/endlessm/linux-meson/blob/master/arch/arm/mach-meson8/clock.c#L140

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

* Re: [PATCH 0/3] clk: meson: clk-pll driver update
  2018-07-17  9:56 [PATCH 0/3] clk: meson: clk-pll driver update Jerome Brunet
                   ` (2 preceding siblings ...)
  2018-07-17  9:56 ` [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables Jerome Brunet
@ 2018-07-21 20:17 ` Martin Blumenstingl
  2018-07-21 20:48   ` Jerome Brunet
  3 siblings, 1 reply; 20+ messages in thread
From: Martin Blumenstingl @ 2018-07-21 20:17 UTC (permalink / raw)
  To: jbrunet; +Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

Hi Jerome,

On Tue, Jul 17, 2018 at 11:56 AM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> This patchset is yet another round of update to the amlogic pll driver.
>
>  1) Enable bit is added so we don't rely on the bootloader or the init
>     value to enable to pll device.
>  2) OD post dividers are removed from the pll driver. This simplify the
>     driver and let us provide the clocks which exist between those
>     dividera. Some device are actually using these clocks.
>  3) The rates hard coded in parameter tables are remove. Instead, we
>     only rely on the parent rate and the parameters to calculate the
>     output rate, which is a lot better.
>
> This series has been tested on the gxl libretech cc and axg s400.
> I did not test it on meson8b yet.
I had some comments on patch #2
once that is fixed I can help testing on Meson8b (if you give me a few days...)


Regards
Martin

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

* Re: [PATCH 1/3] clk: meson: clk-pll: add enable bit
  2018-07-21 19:48   ` Martin Blumenstingl
@ 2018-07-21 20:26     ` Jerome Brunet
  0 siblings, 0 replies; 20+ messages in thread
From: Jerome Brunet @ 2018-07-21 20:26 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

On Sat, 2018-07-21 at 21:48 +0200, Martin Blumenstingl wrote:
> > @@ -250,11 +264,15 @@ static const struct reg_sequence axg_hifi_init_regs[] = {
> >          { .reg = HHI_HIFI_PLL_CNTL3,    .def = 0x0a6a3a88 },
> >          { .reg = HHI_HIFI_PLL_CNTL4,    .def = 0xc000004d },
> >          { .reg = HHI_HIFI_PLL_CNTL5,    .def = 0x00058000 },
> > -       { .reg = HHI_HIFI_PLL_CNTL,     .def = 0x40010250 },
> 
> is this change on purpose? this line set en, m, n, l and od before
> maybe you can document it in the commit message

Yes the change is on purpose, but as you pointed out it is worth a comment

Actually, when taking od out of the pll driver, I remembered this 'initial
setting' and it kinda bothered me

If the od divider registers after the DCO, the value could have changed with it,
which is why I wanted to remove the write on this register

As you pointed out, in this register, we find m, n, od ... and enable. In a way,
removing this register setting was the reason why I wanted to add the enable bit
to begin with :)

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

* Re: [PATCH 2/3] clk: meson: clk-pll: remove od parameters
  2018-07-21 20:01   ` Martin Blumenstingl
@ 2018-07-21 20:42     ` Jerome Brunet
  2018-07-21 21:37       ` Martin Blumenstingl
  0 siblings, 1 reply; 20+ messages in thread
From: Jerome Brunet @ 2018-07-21 20:42 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

On Sat, 2018-07-21 at 22:01 +0200, Martin Blumenstingl wrote:
> > +static struct clk_regmap gxbb_hdmi_pll_od = {
> > +       .data = &(struct clk_regmap_div_data){
> > +               .offset = HHI_HDMI_PLL_CNTL2,
> > +               .shift = 16,
> > +               .width = 2,
> > +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> > +       },
> > +       .hw.init = &(struct clk_init_data){
> > +               .name = "hdmi_pll_od",
> > +               .ops = &clk_regmap_divider_ro_ops,
> > +               .parent_names = (const char *[]){ "hdmi_pll_dco" },
> > +               .num_parents = 1,
> > +               .flags = CLK_GET_RATE_NOCACHE,
> 
> why do we need CLK_GET_RATE_NOCACHE here?
> also, shouldn't all _od clocks use CLK_SET_RATE_PARENT?
> (this applies to all new _od clocks, not just this one)

The goal was to retain the original behavior of the clock.
The pll has CLK_GET_RATE_NOCACHE, which is why I put it again in the od
dividers. Same goes for ro_ops

For the particular case of the HDMI PLL, the display driver still set the pll
parameters m, n and ods directly which justify CLK_GET_RATE_NOCACHE for now.
Of course, the goal is to remove this flag someday. I think there has been some
good progress in the DRM driver to reach this goal.

If we think the use CLK_GET_RATE_NOCACHE is not justified for some other plls, I
would prefer if it was addressed in another patchset.

Regarding SET_RATE_PARENT, with the pll set with ro_ops, it does not change
anything but, I agree, it would be better to set flag for the future.

Cheers
Jerome

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

* Re: [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables
  2018-07-21 20:16     ` Martin Blumenstingl
@ 2018-07-21 20:46       ` Jerome Brunet
  2018-07-21 21:34         ` Martin Blumenstingl
  0 siblings, 1 reply; 20+ messages in thread
From: Jerome Brunet @ 2018-07-21 20:46 UTC (permalink / raw)
  To: Martin Blumenstingl, Neil Armstrong
  Cc: linux-amlogic, linux-clk, linux-kernel, khilman

On Sat, 2018-07-21 at 22:16 +0200, Martin Blumenstingl wrote:
> > We could even add ranges instead of table when we know the PLL supports a well-known continuous dividers range.
> 
> I had a look at the sys_pll settings on Meson8b, here's what
> Meson8/Meson8b/Meson8m2 support for sys_pll:
> - 50..74
> - 76
> - 78
> - 80
> - 82
> - 84
> - 86
> - 88
> - 90
> - 92
> - 94
> - 96
> - 98

Are those values with the same predivider (n) value ?
I suspect the ability of the DCO to lock might depends on its input rate and an
m range

So if n change, it might possible that the m range will be different.

... at least, that's my guess :)

> 
> (I'm providing this info because it may help finding a decision
> whether ranges are good or not. I have no preference)


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

* Re: [PATCH 0/3] clk: meson: clk-pll driver update
  2018-07-21 20:17 ` [PATCH 0/3] clk: meson: clk-pll driver update Martin Blumenstingl
@ 2018-07-21 20:48   ` Jerome Brunet
  0 siblings, 0 replies; 20+ messages in thread
From: Jerome Brunet @ 2018-07-21 20:48 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

On Sat, 2018-07-21 at 22:17 +0200, Martin Blumenstingl wrote:
> > This series has been tested on the gxl libretech cc and axg s400.
> > I did not test it on meson8b yet.
> 
> I had some comments on patch #2
> once that is fixed I can help testing on Meson8b (if you give me a few days...)

I don't intend to make another PR to clk in this cycle, unless something
critical comes up. No rush.

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

* Re: [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables
  2018-07-21 20:46       ` Jerome Brunet
@ 2018-07-21 21:34         ` Martin Blumenstingl
  2018-07-26  8:48           ` jbrunet
  0 siblings, 1 reply; 20+ messages in thread
From: Martin Blumenstingl @ 2018-07-21 21:34 UTC (permalink / raw)
  To: jbrunet; +Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

Hi Jerome,

On Sat, Jul 21, 2018 at 10:46 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> On Sat, 2018-07-21 at 22:16 +0200, Martin Blumenstingl wrote:
> > > We could even add ranges instead of table when we know the PLL supports a well-known continuous dividers range.
> >
> > I had a look at the sys_pll settings on Meson8b, here's what
> > Meson8/Meson8b/Meson8m2 support for sys_pll:
> > - 50..74
> > - 76
> > - 78
> > - 80
> > - 82
> > - 84
> > - 86
> > - 88
> > - 90
> > - 92
> > - 94
> > - 96
> > - 98
>
> Are those values with the same predivider (n) value ?
yes, all are using n = 1

> I suspect the ability of the DCO to lock might depends on its input rate and an
> m range
>
> So if n change, it might possible that the m range will be different.
>
> ... at least, that's my guess :)
for the Meson8b's SYS_PLL Amlogic's GPL kernel is using bits 15:14 in
HHI_SYS_PLL_CNTL for frequencies above 1.64GHz (below that these
reserved bits are always 0).
if the values are useful for you (format is: frequency, m, n, od and
bits 15:14. what's missing here is the "cpu_scale_div" divider which
is for example why you'll see the "56, 1, 2, 0" tuple multiple times):
SYS_PLL(24000, 56, 1, 2, 0)
SYS_PLL(48000, 64, 1, 2, 0)
SYS_PLL(72000, 72, 1, 2, 0)
SYS_PLL(96000, 64, 1, 2, 0)
SYS_PLL(120000, 80, 1, 2, 0)
SYS_PLL(144000, 96, 1, 2, 0)
SYS_PLL(168000, 56, 1, 1, 0)
SYS_PLL(192000, 64, 1, 1, 0)
SYS_PLL(216000, 72, 1, 1, 0)
SYS_PLL(240000, 80, 1, 1, 0)
SYS_PLL(264000, 88, 1, 1, 0)
SYS_PLL(288000, 96, 1, 1, 0)
SYS_PLL(312000, 52, 1, 2, 0)
SYS_PLL(336000, 56, 1, 2, 0)
SYS_PLL(360000, 60, 1, 2, 0)
SYS_PLL(384000, 64, 1, 2, 0)
SYS_PLL(408000, 68, 1, 2, 0)
SYS_PLL(432000, 72, 1, 2, 0)
SYS_PLL(456000, 76, 1, 2, 0)
SYS_PLL(480000, 80, 1, 2, 0)
SYS_PLL(504000, 84, 1, 2, 0)
SYS_PLL(528000, 88, 1, 2, 0)
SYS_PLL(552000, 92, 1, 2, 0)
SYS_PLL(576000, 96, 1, 2, 0)
SYS_PLL(600000, 50, 1, 1, 0)
SYS_PLL(624000, 52, 1, 1, 0)
SYS_PLL(648000, 54, 1, 1, 0)
SYS_PLL(672000, 56, 1, 1, 0)
SYS_PLL(696000, 58, 1, 1, 0)
SYS_PLL(720000, 60, 1, 1, 0)
SYS_PLL(744000, 62, 1, 1, 0)
SYS_PLL(768000, 64, 1, 1, 0)
SYS_PLL(792000, 66, 1, 1, 0)
SYS_PLL(816000, 68, 1, 1, 0)
SYS_PLL(840000, 70, 1, 1, 0)
SYS_PLL(864000, 72, 1, 1, 0)
SYS_PLL(888000, 74, 1, 1, 0)
SYS_PLL(912000, 76, 1, 1, 0)
SYS_PLL(936000, 78, 1, 1, 0)
SYS_PLL(960000, 80, 1, 1, 0)
SYS_PLL(984000, 82, 1, 1, 0)
SYS_PLL(1008000, 84, 1, 1, 0)
SYS_PLL(1032000, 86, 1, 1, 0)
SYS_PLL(1056000, 88, 1, 1, 0)
SYS_PLL(1080000, 90, 1, 1, 0)
SYS_PLL(1104000, 92, 1, 1, 0)
SYS_PLL(1128000, 94, 1, 1, 0)
SYS_PLL(1152000, 96, 1, 1, 0)
SYS_PLL(1176000, 98, 1, 1, 0)
SYS_PLL(1200000, 50, 1, 0, 0)
SYS_PLL(1224000, 51, 1, 0, 0)
SYS_PLL(1248000, 52, 1, 0, 0)
SYS_PLL(1272000, 53, 1, 0, 0)
SYS_PLL(1296000, 54, 1, 0, 0)
SYS_PLL(1320000, 55, 1, 0, 0)
SYS_PLL(1344000, 56, 1, 0, 0)
SYS_PLL(1368000, 57, 1, 0, 0)
SYS_PLL(1392000, 58, 1, 0, 0)
SYS_PLL(1416000, 59, 1, 0, 0)
SYS_PLL(1440000, 60, 1, 0, 0)
SYS_PLL(1464000, 61, 1, 0, 0)
SYS_PLL(1488000, 62, 1, 0, 0)
SYS_PLL(1512000, 63, 1, 0, 0)
SYS_PLL(1536000, 64, 1, 0, 0)
SYS_PLL(1560000, 65, 1, 0, 0)
SYS_PLL(1584000, 66, 1, 0, 0)
SYS_PLL(1608000, 67, 1, 0, 0)
SYS_PLL(1632000, 68, 1, 0, 0)
SYS_PLL(1656000, 68, 1, 0, 1)
SYS_PLL(1680000, 68, 1, 0, 2)
SYS_PLL(1704000, 68, 1, 0, 3)
SYS_PLL(1728000, 69, 1, 0, 0)
SYS_PLL(1752000, 69, 1, 0, 1)
SYS_PLL(1776000, 69, 1, 0, 2)
SYS_PLL(1800000, 69, 1, 0, 3)
SYS_PLL(1824000, 70, 1, 0, 0)
SYS_PLL(1848000, 70, 1, 0, 1)
SYS_PLL(1872000, 70, 1, 0, 2)
SYS_PLL(1896000, 70, 1, 0, 3)
SYS_PLL(1920000, 71, 1, 0, 0)
SYS_PLL(1944000, 71, 1, 0, 1)
SYS_PLL(1968000, 71, 1, 0, 2)
SYS_PLL(1992000, 71, 1, 0, 3)
SYS_PLL(2016000, 72, 1, 0, 0)
SYS_PLL(2040000, 72, 1, 0, 1)
SYS_PLL(2064000, 72, 1, 0, 2)
SYS_PLL(2088000, 72, 1, 0, 3)
SYS_PLL(2112000, 73, 1, 0, 0)


Regards
Martin

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

* Re: [PATCH 2/3] clk: meson: clk-pll: remove od parameters
  2018-07-21 20:42     ` Jerome Brunet
@ 2018-07-21 21:37       ` Martin Blumenstingl
  0 siblings, 0 replies; 20+ messages in thread
From: Martin Blumenstingl @ 2018-07-21 21:37 UTC (permalink / raw)
  To: jbrunet; +Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

Hi Jerome,

On Sat, Jul 21, 2018 at 10:42 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
>
> On Sat, 2018-07-21 at 22:01 +0200, Martin Blumenstingl wrote:
> > > +static struct clk_regmap gxbb_hdmi_pll_od = {
> > > +       .data = &(struct clk_regmap_div_data){
> > > +               .offset = HHI_HDMI_PLL_CNTL2,
> > > +               .shift = 16,
> > > +               .width = 2,
> > > +               .flags = CLK_DIVIDER_POWER_OF_TWO,
> > > +       },
> > > +       .hw.init = &(struct clk_init_data){
> > > +               .name = "hdmi_pll_od",
> > > +               .ops = &clk_regmap_divider_ro_ops,
> > > +               .parent_names = (const char *[]){ "hdmi_pll_dco" },
> > > +               .num_parents = 1,
> > > +               .flags = CLK_GET_RATE_NOCACHE,
> >
> > why do we need CLK_GET_RATE_NOCACHE here?
> > also, shouldn't all _od clocks use CLK_SET_RATE_PARENT?
> > (this applies to all new _od clocks, not just this one)
>
> The goal was to retain the original behavior of the clock.
> The pll has CLK_GET_RATE_NOCACHE, which is why I put it again in the od
> dividers. Same goes for ro_ops
I missed that - thanks for the explanation!

> For the particular case of the HDMI PLL, the display driver still set the pll
> parameters m, n and ods directly which justify CLK_GET_RATE_NOCACHE for now.
> Of course, the goal is to remove this flag someday. I think there has been some
> good progress in the DRM driver to reach this goal.
>
> If we think the use CLK_GET_RATE_NOCACHE is not justified for some other plls, I
> would prefer if it was addressed in another patchset.
now that the reason is clear to me: I fully agree!

> Regarding SET_RATE_PARENT, with the pll set with ro_ops, it does not change
> anything but, I agree, it would be better to set flag for the future.
I see
adding SET_RATE_PARENT will probably save a bit of headache later on
when enabling the write operation of the PLL and then wondering why
the frequency is not changed


Regards
Martin

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

* Re: [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables
  2018-07-21 21:34         ` Martin Blumenstingl
@ 2018-07-26  8:48           ` jbrunet
  0 siblings, 0 replies; 20+ messages in thread
From: jbrunet @ 2018-07-26  8:48 UTC (permalink / raw)
  To: Martin Blumenstingl
  Cc: Neil Armstrong, linux-amlogic, linux-clk, linux-kernel, khilman

On Sat, 2018-07-21 at 23:34 +0200, Martin Blumenstingl wrote:
> On Sat, Jul 21, 2018 at 10:46 PM Jerome Brunet <jbrunet@baylibre.com> wrote:
> > 
> > On Sat, 2018-07-21 at 22:16 +0200, Martin Blumenstingl wrote:
> > > > We could even add ranges instead of table when we know the PLL supports a well-known continuous dividers range.
> > > 
> > > I had a look at the sys_pll settings on Meson8b, here's what
> > > Meson8/Meson8b/Meson8m2 support for sys_pll:
> > > - 50..74
> > > - 76
> > > - 78
> > > - 80
> > > - 82
> > > - 84
> > > - 86
> > > - 88
> > > - 90
> > > - 92
> > > - 94
> > > - 96
> > > - 98
> > 
> > Are those values with the same predivider (n) value ?
> 
> yes, all are using n = 1

The table proposed in this patch keeps things the way they were before the
change. We could extend the table with these values in a follow up patch.

If those value are with n=1, then I would guess that odd values from 75 to 97
work as well. 



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

end of thread, other threads:[~2018-07-26  8:48 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-17  9:56 [PATCH 0/3] clk: meson: clk-pll driver update Jerome Brunet
2018-07-17  9:56 ` [PATCH 1/3] clk: meson: clk-pll: add enable bit Jerome Brunet
2018-07-19  8:33   ` Neil Armstrong
2018-07-21 19:48   ` Martin Blumenstingl
2018-07-21 20:26     ` Jerome Brunet
2018-07-17  9:56 ` [PATCH 2/3] clk: meson: clk-pll: remove od parameters Jerome Brunet
2018-07-19  8:42   ` Neil Armstrong
2018-07-19  8:45     ` Jerome Brunet
2018-07-21 20:01   ` Martin Blumenstingl
2018-07-21 20:42     ` Jerome Brunet
2018-07-21 21:37       ` Martin Blumenstingl
2018-07-17  9:56 ` [PATCH 3/3] clk: meson: clk-pll: drop hard-coded rates from pll tables Jerome Brunet
2018-07-19  8:44   ` Neil Armstrong
2018-07-19  8:59     ` Jerome Brunet
2018-07-21 20:16     ` Martin Blumenstingl
2018-07-21 20:46       ` Jerome Brunet
2018-07-21 21:34         ` Martin Blumenstingl
2018-07-26  8:48           ` jbrunet
2018-07-21 20:17 ` [PATCH 0/3] clk: meson: clk-pll driver update Martin Blumenstingl
2018-07-21 20:48   ` Jerome Brunet

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).