All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] clk: meson: update clock controller for audio support
@ 2017-02-28 13:29 ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel, devicetree

This patchset is a first round of update to the meson clock controllers
to bring audio support. The patchset is based on clk-next with two
additional patches from arm-soc next (to avoid conflict later on).
commit d356a86b1b30 ("clk: meson-gxbb: Export HDMI clocks")
commit 7d753a742127 ("clk: gxbb: add the SAR ADC clocks and expose them")

The 2 first patches of the series put the generic muxes and divisors
declaration in tables so the register address fixup works in the same way
as the clock gates. We are going to add more of these clock types for
audio or gpu support, so we can't continue to fix addresses individually
like it is currently done.

Patches 3 to 6 improve the support of the mpll clocks, now allowing the
rate to be set. Among other things, the mplls are the parent clocks of the
i2s and spdif clocks.

Patch 7 expose the clock gates required to power on the i2s output.

These patches have been tested on the meson gxbb p200 board, as part of the
ongoing work to bring audio support for meson SoC family.

Jerome Brunet (7):
  clk: meson8b: put dividers and muxes in tables
  clk: gxbb: put dividers and muxes in tables
  clk: meson: mpll: add rw operation
  clk: meson: gxbb: mpll: use rw operation
  clk: meson8b: add the mplls clocks 0, 1 and 2
  clk: meson: mpll: correct N2 maximum value
  dt-bindings: clk: gxbb: expose i2s output clock gates

 drivers/clk/meson/clk-mpll.c          | 152 ++++++++++++++++++++++++++++++++--
 drivers/clk/meson/clkc.h              |   4 +-
 drivers/clk/meson/gxbb.c              |  64 +++++++++++---
 drivers/clk/meson/gxbb.h              |  10 +--
 drivers/clk/meson/meson8b.c           | 126 +++++++++++++++++++++++++++-
 drivers/clk/meson/meson8b.h           |  20 ++++-
 include/dt-bindings/clock/gxbb-clkc.h |   5 ++
 7 files changed, 354 insertions(+), 27 deletions(-)

-- 
2.9.3

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

* [PATCH 0/7] clk: meson: update clock controller for audio support
@ 2017-02-28 13:29 ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk-u79uwXL29TY76Z2rM5mHXA,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA

This patchset is a first round of update to the meson clock controllers
to bring audio support. The patchset is based on clk-next with two
additional patches from arm-soc next (to avoid conflict later on).
commit d356a86b1b30 ("clk: meson-gxbb: Export HDMI clocks")
commit 7d753a742127 ("clk: gxbb: add the SAR ADC clocks and expose them")

The 2 first patches of the series put the generic muxes and divisors
declaration in tables so the register address fixup works in the same way
as the clock gates. We are going to add more of these clock types for
audio or gpu support, so we can't continue to fix addresses individually
like it is currently done.

Patches 3 to 6 improve the support of the mpll clocks, now allowing the
rate to be set. Among other things, the mplls are the parent clocks of the
i2s and spdif clocks.

Patch 7 expose the clock gates required to power on the i2s output.

These patches have been tested on the meson gxbb p200 board, as part of the
ongoing work to bring audio support for meson SoC family.

Jerome Brunet (7):
  clk: meson8b: put dividers and muxes in tables
  clk: gxbb: put dividers and muxes in tables
  clk: meson: mpll: add rw operation
  clk: meson: gxbb: mpll: use rw operation
  clk: meson8b: add the mplls clocks 0, 1 and 2
  clk: meson: mpll: correct N2 maximum value
  dt-bindings: clk: gxbb: expose i2s output clock gates

 drivers/clk/meson/clk-mpll.c          | 152 ++++++++++++++++++++++++++++++++--
 drivers/clk/meson/clkc.h              |   4 +-
 drivers/clk/meson/gxbb.c              |  64 +++++++++++---
 drivers/clk/meson/gxbb.h              |  10 +--
 drivers/clk/meson/meson8b.c           | 126 +++++++++++++++++++++++++++-
 drivers/clk/meson/meson8b.h           |  20 ++++-
 include/dt-bindings/clock/gxbb-clkc.h |   5 ++
 7 files changed, 354 insertions(+), 27 deletions(-)

-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 0/7] clk: meson: update clock controller for audio support
@ 2017-02-28 13:29 ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: linus-amlogic

This patchset is a first round of update to the meson clock controllers
to bring audio support. The patchset is based on clk-next with two
additional patches from arm-soc next (to avoid conflict later on).
commit d356a86b1b30 ("clk: meson-gxbb: Export HDMI clocks")
commit 7d753a742127 ("clk: gxbb: add the SAR ADC clocks and expose them")

The 2 first patches of the series put the generic muxes and divisors
declaration in tables so the register address fixup works in the same way
as the clock gates. We are going to add more of these clock types for
audio or gpu support, so we can't continue to fix addresses individually
like it is currently done.

Patches 3 to 6 improve the support of the mpll clocks, now allowing the
rate to be set. Among other things, the mplls are the parent clocks of the
i2s and spdif clocks.

Patch 7 expose the clock gates required to power on the i2s output.

These patches have been tested on the meson gxbb p200 board, as part of the
ongoing work to bring audio support for meson SoC family.

Jerome Brunet (7):
  clk: meson8b: put dividers and muxes in tables
  clk: gxbb: put dividers and muxes in tables
  clk: meson: mpll: add rw operation
  clk: meson: gxbb: mpll: use rw operation
  clk: meson8b: add the mplls clocks 0, 1 and 2
  clk: meson: mpll: correct N2 maximum value
  dt-bindings: clk: gxbb: expose i2s output clock gates

 drivers/clk/meson/clk-mpll.c          | 152 ++++++++++++++++++++++++++++++++--
 drivers/clk/meson/clkc.h              |   4 +-
 drivers/clk/meson/gxbb.c              |  64 +++++++++++---
 drivers/clk/meson/gxbb.h              |  10 +--
 drivers/clk/meson/meson8b.c           | 126 +++++++++++++++++++++++++++-
 drivers/clk/meson/meson8b.h           |  20 ++++-
 include/dt-bindings/clock/gxbb-clkc.h |   5 ++
 7 files changed, 354 insertions(+), 27 deletions(-)

-- 
2.9.3

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

* [PATCH 1/7] clk: meson8b: put dividers and muxes in tables
  2017-02-28 13:29 ` Jerome Brunet
@ 2017-02-28 13:29   ` Jerome Brunet
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel

Until now, there was only 1 divider and 1 mux declared for the meson8b
platform. With the ongoing work on various system, including audio, this
is about to change. Use the same approach as gates for dividers and muxes,
putting them in tables to fix the register address at runtime.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/meson8b.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 888494d4fb8a..44c24bf754cd 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -582,6 +582,15 @@ static struct clk_gate *meson8b_clk_gates[] = {
 	&meson8b_ao_iface,
 };
 
+static struct clk_mux *meson8b_clk_muxes[] = {
+	&meson8b_mpeg_clk_sel,
+};
+
+static struct clk_divider *meson8b_clk_dividers[] = {
+	&meson8b_mpeg_clk_div,
+};
+
+
 static int meson8b_clkc_probe(struct platform_device *pdev)
 {
 	void __iomem *clk_base;
@@ -604,15 +613,21 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
 	/* Populate the base address for CPU clk */
 	meson8b_cpu_clk.base = clk_base;
 
-	/* Populate the base address for the MPEG clks */
-	meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg;
-	meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
-
 	/* Populate base address for gates */
 	for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
 		meson8b_clk_gates[i]->reg = clk_base +
 			(u32)meson8b_clk_gates[i]->reg;
 
+	/* Populate base address for muxes */
+	for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
+		meson8b_clk_muxes[i]->reg = clk_base +
+			(u32)meson8b_clk_muxes[i]->reg;
+
+	/* Populate base address for dividers */
+	for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++)
+		meson8b_clk_dividers[i]->reg = clk_base +
+			(u32)meson8b_clk_dividers[i]->reg;
+
 	/*
 	 * register all clks
 	 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
-- 
2.9.3

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

* [PATCH 1/7] clk: meson8b: put dividers and muxes in tables
@ 2017-02-28 13:29   ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: linus-amlogic

Until now, there was only 1 divider and 1 mux declared for the meson8b
platform. With the ongoing work on various system, including audio, this
is about to change. Use the same approach as gates for dividers and muxes,
putting them in tables to fix the register address at runtime.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/meson8b.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 888494d4fb8a..44c24bf754cd 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -582,6 +582,15 @@ static struct clk_gate *meson8b_clk_gates[] = {
 	&meson8b_ao_iface,
 };
 
+static struct clk_mux *meson8b_clk_muxes[] = {
+	&meson8b_mpeg_clk_sel,
+};
+
+static struct clk_divider *meson8b_clk_dividers[] = {
+	&meson8b_mpeg_clk_div,
+};
+
+
 static int meson8b_clkc_probe(struct platform_device *pdev)
 {
 	void __iomem *clk_base;
@@ -604,15 +613,21 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
 	/* Populate the base address for CPU clk */
 	meson8b_cpu_clk.base = clk_base;
 
-	/* Populate the base address for the MPEG clks */
-	meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg;
-	meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
-
 	/* Populate base address for gates */
 	for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
 		meson8b_clk_gates[i]->reg = clk_base +
 			(u32)meson8b_clk_gates[i]->reg;
 
+	/* Populate base address for muxes */
+	for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
+		meson8b_clk_muxes[i]->reg = clk_base +
+			(u32)meson8b_clk_muxes[i]->reg;
+
+	/* Populate base address for dividers */
+	for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++)
+		meson8b_clk_dividers[i]->reg = clk_base +
+			(u32)meson8b_clk_dividers[i]->reg;
+
 	/*
 	 * register all clks
 	 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
-- 
2.9.3

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

* [PATCH 2/7] clk: gxbb: put dividers and muxes in tables
  2017-02-28 13:29 ` Jerome Brunet
@ 2017-02-28 13:29   ` Jerome Brunet
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel

Until now, there was only 2 dividers and 2 muxes declared for the gxbb
platform. With the ongoing work on various subsystem, including audio,
this is about to change. Use the same approach as gates for dividers and
muxes, putting them in tables to fix the register address at runtime.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/gxbb.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 1c1ec137a3cc..388b0c8838af 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -902,6 +902,16 @@ static struct clk_gate *gxbb_clk_gates[] = {
 	&gxbb_sar_adc_clk,
 };
 
+static struct clk_mux *gxbb_clk_muxes[] = {
+	&gxbb_mpeg_clk_sel,
+	&gxbb_sar_adc_clk_sel,
+};
+
+static struct clk_divider *gxbb_clk_dividers[] = {
+	&gxbb_mpeg_clk_div,
+	&gxbb_sar_adc_clk_div,
+};
+
 static int gxbb_clkc_probe(struct platform_device *pdev)
 {
 	void __iomem *clk_base;
@@ -928,19 +938,21 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
 	/* Populate the base address for CPU clk */
 	gxbb_cpu_clk.base = clk_base;
 
-	/* Populate the base address for the MPEG clks */
-	gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
-	gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
-
-	/* Populate the base address for the SAR ADC clks */
-	gxbb_sar_adc_clk_sel.reg = clk_base + (u64)gxbb_sar_adc_clk_sel.reg;
-	gxbb_sar_adc_clk_div.reg = clk_base + (u64)gxbb_sar_adc_clk_div.reg;
-
 	/* Populate base address for gates */
 	for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
 		gxbb_clk_gates[i]->reg = clk_base +
 			(u64)gxbb_clk_gates[i]->reg;
 
+	/* Populate base address for muxes */
+	for (i = 0; i < ARRAY_SIZE(gxbb_clk_muxes); i++)
+		gxbb_clk_muxes[i]->reg = clk_base +
+			(u64)gxbb_clk_muxes[i]->reg;
+
+	/* Populate base address for dividers */
+	for (i = 0; i < ARRAY_SIZE(gxbb_clk_dividers); i++)
+		gxbb_clk_dividers[i]->reg = clk_base +
+			(u64)gxbb_clk_dividers[i]->reg;
+
 	/*
 	 * register all clks
 	 */
-- 
2.9.3

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

* [PATCH 2/7] clk: gxbb: put dividers and muxes in tables
@ 2017-02-28 13:29   ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: linus-amlogic

Until now, there was only 2 dividers and 2 muxes declared for the gxbb
platform. With the ongoing work on various subsystem, including audio,
this is about to change. Use the same approach as gates for dividers and
muxes, putting them in tables to fix the register address at runtime.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/gxbb.c | 28 ++++++++++++++++++++--------
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 1c1ec137a3cc..388b0c8838af 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -902,6 +902,16 @@ static struct clk_gate *gxbb_clk_gates[] = {
 	&gxbb_sar_adc_clk,
 };
 
+static struct clk_mux *gxbb_clk_muxes[] = {
+	&gxbb_mpeg_clk_sel,
+	&gxbb_sar_adc_clk_sel,
+};
+
+static struct clk_divider *gxbb_clk_dividers[] = {
+	&gxbb_mpeg_clk_div,
+	&gxbb_sar_adc_clk_div,
+};
+
 static int gxbb_clkc_probe(struct platform_device *pdev)
 {
 	void __iomem *clk_base;
@@ -928,19 +938,21 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
 	/* Populate the base address for CPU clk */
 	gxbb_cpu_clk.base = clk_base;
 
-	/* Populate the base address for the MPEG clks */
-	gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
-	gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
-
-	/* Populate the base address for the SAR ADC clks */
-	gxbb_sar_adc_clk_sel.reg = clk_base + (u64)gxbb_sar_adc_clk_sel.reg;
-	gxbb_sar_adc_clk_div.reg = clk_base + (u64)gxbb_sar_adc_clk_div.reg;
-
 	/* Populate base address for gates */
 	for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
 		gxbb_clk_gates[i]->reg = clk_base +
 			(u64)gxbb_clk_gates[i]->reg;
 
+	/* Populate base address for muxes */
+	for (i = 0; i < ARRAY_SIZE(gxbb_clk_muxes); i++)
+		gxbb_clk_muxes[i]->reg = clk_base +
+			(u64)gxbb_clk_muxes[i]->reg;
+
+	/* Populate base address for dividers */
+	for (i = 0; i < ARRAY_SIZE(gxbb_clk_dividers); i++)
+		gxbb_clk_dividers[i]->reg = clk_base +
+			(u64)gxbb_clk_dividers[i]->reg;
+
 	/*
 	 * register all clks
 	 */
-- 
2.9.3

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

* [PATCH 3/7] clk: meson: mpll: add rw operation
  2017-02-28 13:29 ` Jerome Brunet
@ 2017-02-28 13:29   ` Jerome Brunet
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel

This patch adds new callbacks to the meson-mpll driver to control
and set the pll rate. For this, we also need to add the enable bit and
sdm enable bit. The corresponding parameters are added to mpll data
structure.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/clk-mpll.c | 152 +++++++++++++++++++++++++++++++++++++++++--
 drivers/clk/meson/clkc.h     |   4 +-
 drivers/clk/meson/gxbb.c     |  30 +++++++++
 3 files changed, 180 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 03af79005ddb..342b85d4e22a 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -64,16 +64,50 @@
 #include <linux/clk-provider.h>
 #include "clkc.h"
 
-#define SDM_MAX 16384
+#define SDM_DEN 16384
+#define SDM_MIN 1
+#define SDM_MAX 16383
+#define N2_MIN	4
+#define N2_MAX	127
 
 #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
 
+static unsigned long rate_from_params(unsigned long parent_rate,
+				      unsigned long sdm,
+				      unsigned long n2)
+{
+	return (parent_rate * SDM_DEN) / ((SDM_DEN * n2) + sdm);
+}
+
+static void params_from_rate(unsigned long requested_rate,
+			     unsigned long parent_rate,
+			     unsigned long *sdm,
+			     unsigned long *n2)
+{
+	uint64_t div = parent_rate;
+	unsigned long rem = do_div(div, requested_rate);
+
+	if (div < N2_MIN) {
+		*n2 = N2_MIN;
+		*sdm = SDM_MIN;
+	} else if (div > N2_MAX) {
+		*n2 = N2_MAX;
+		*sdm = SDM_MAX;
+	} else {
+		*n2 = div;
+		*sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate);
+		if (*sdm < SDM_MIN)
+			*sdm = SDM_MIN;
+		else if (*sdm > SDM_MAX)
+			*sdm = SDM_MAX;
+	}
+}
+
 static unsigned long mpll_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
 	struct parm *p;
-	unsigned long rate = 0;
 	unsigned long reg, sdm, n2;
 
 	p = &mpll->sdm;
@@ -84,11 +118,119 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw,
 	reg = readl(mpll->base + p->reg_off);
 	n2 = PARM_GET(p->width, p->shift, reg);
 
-	rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm);
+	return rate_from_params(parent_rate, sdm, n2);
+}
+
+static long mpll_round_rate(struct clk_hw *hw,
+			    unsigned long rate,
+			    unsigned long *parent_rate)
+{
+	unsigned long sdm, n2;
+
+	params_from_rate(rate, *parent_rate, &sdm, &n2);
+	return rate_from_params(*parent_rate, sdm, n2);
+}
+
+static int mpll_set_rate(struct clk_hw *hw,
+			 unsigned long rate,
+			 unsigned long parent_rate)
+{
+	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+	struct parm *p;
+	unsigned long reg, sdm, n2;
+	unsigned long flags = 0;
+
+	params_from_rate(rate, parent_rate, &sdm, &n2);
+
+	if (mpll->lock)
+		spin_lock_irqsave(mpll->lock, flags);
+	else
+		__acquire(mpll->lock);
+
+	p = &mpll->sdm;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, sdm);
+	writel(reg, mpll->base + p->reg_off);
+
+	p = &mpll->sdm_en;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, 1);
+	writel(reg, mpll->base + p->reg_off);
+
+	p = &mpll->n2;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, n2);
+	writel(reg, mpll->base + p->reg_off);
+
+	if (mpll->lock)
+		spin_unlock_irqrestore(mpll->lock, flags);
+	else
+		__release(mpll->lock);
 
-	return rate;
+	return 0;
+}
+
+static void mpll_enable_core(struct clk_hw *hw, int enable)
+{
+	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+	struct parm *p;
+	unsigned long reg;
+	unsigned long flags = 0;
+
+	if (mpll->lock)
+		spin_lock_irqsave(mpll->lock, flags);
+	else
+		__acquire(mpll->lock);
+
+	p = &mpll->en;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
+	writel(reg, mpll->base + p->reg_off);
+
+	if (mpll->lock)
+		spin_unlock_irqrestore(mpll->lock, flags);
+	else
+		__release(mpll->lock);
+}
+
+
+static int mpll_enable(struct clk_hw *hw)
+{
+	mpll_enable_core(hw, 1);
+
+	return 0;
+}
+
+static void mpll_disable(struct clk_hw *hw)
+{
+	mpll_enable_core(hw, 0);
+}
+
+static int mpll_is_enabled(struct clk_hw *hw)
+{
+	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+	struct parm *p;
+	unsigned long reg;
+	int en;
+
+	p = &mpll->en;
+	reg = readl(mpll->base + p->reg_off);
+	en = PARM_GET(p->width, p->shift, reg);
+
+	return en;
 }
 
 const struct clk_ops meson_clk_mpll_ro_ops = {
-	.recalc_rate = mpll_recalc_rate,
+	.recalc_rate	= mpll_recalc_rate,
+	.round_rate	= mpll_round_rate,
+	.is_enabled	= mpll_is_enabled,
+};
+
+const struct clk_ops meson_clk_mpll_ops = {
+	.recalc_rate	= mpll_recalc_rate,
+	.round_rate	= mpll_round_rate,
+	.set_rate	= mpll_set_rate,
+	.enable		= mpll_enable,
+	.disable	= mpll_disable,
+	.is_enabled	= mpll_is_enabled,
 };
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 9bb70e7a7d6a..54d58a465039 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -92,8 +92,9 @@ struct meson_clk_mpll {
 	struct clk_hw hw;
 	void __iomem *base;
 	struct parm sdm;
+	struct parm sdm_en;
 	struct parm n2;
-	/* FIXME ssen gate control? */
+	struct parm en;
 	spinlock_t *lock;
 };
 
@@ -116,5 +117,6 @@ extern const struct clk_ops meson_clk_pll_ro_ops;
 extern const struct clk_ops meson_clk_pll_ops;
 extern const struct clk_ops meson_clk_cpu_ops;
 extern const struct clk_ops meson_clk_mpll_ro_ops;
+extern const struct clk_ops meson_clk_mpll_ops;
 
 #endif /* __CLKC_H */
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 388b0c8838af..6b97f4da1708 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -441,11 +441,21 @@ static struct meson_clk_mpll gxbb_mpll0 = {
 		.shift   = 0,
 		.width   = 14,
 	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 15,
+		.width	 = 1,
+	},
 	.n2 = {
 		.reg_off = HHI_MPLL_CNTL7,
 		.shift   = 16,
 		.width   = 9,
 	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 14,
+		.width	 = 1,
+	},
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll0",
@@ -461,11 +471,21 @@ static struct meson_clk_mpll gxbb_mpll1 = {
 		.shift   = 0,
 		.width   = 14,
 	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 15,
+		.width	 = 1,
+	},
 	.n2 = {
 		.reg_off = HHI_MPLL_CNTL8,
 		.shift   = 16,
 		.width   = 9,
 	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 14,
+		.width	 = 1,
+	},
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll1",
@@ -481,11 +501,21 @@ static struct meson_clk_mpll gxbb_mpll2 = {
 		.shift   = 0,
 		.width   = 14,
 	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 15,
+		.width	 = 1,
+	},
 	.n2 = {
 		.reg_off = HHI_MPLL_CNTL9,
 		.shift   = 16,
 		.width   = 9,
 	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 14,
+		.width	 = 1,
+	},
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll2",
-- 
2.9.3

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

* [PATCH 3/7] clk: meson: mpll: add rw operation
@ 2017-02-28 13:29   ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: linus-amlogic

This patch adds new callbacks to the meson-mpll driver to control
and set the pll rate. For this, we also need to add the enable bit and
sdm enable bit. The corresponding parameters are added to mpll data
structure.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/clk-mpll.c | 152 +++++++++++++++++++++++++++++++++++++++++--
 drivers/clk/meson/clkc.h     |   4 +-
 drivers/clk/meson/gxbb.c     |  30 +++++++++
 3 files changed, 180 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 03af79005ddb..342b85d4e22a 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -64,16 +64,50 @@
 #include <linux/clk-provider.h>
 #include "clkc.h"
 
-#define SDM_MAX 16384
+#define SDM_DEN 16384
+#define SDM_MIN 1
+#define SDM_MAX 16383
+#define N2_MIN	4
+#define N2_MAX	127
 
 #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
 
+static unsigned long rate_from_params(unsigned long parent_rate,
+				      unsigned long sdm,
+				      unsigned long n2)
+{
+	return (parent_rate * SDM_DEN) / ((SDM_DEN * n2) + sdm);
+}
+
+static void params_from_rate(unsigned long requested_rate,
+			     unsigned long parent_rate,
+			     unsigned long *sdm,
+			     unsigned long *n2)
+{
+	uint64_t div = parent_rate;
+	unsigned long rem = do_div(div, requested_rate);
+
+	if (div < N2_MIN) {
+		*n2 = N2_MIN;
+		*sdm = SDM_MIN;
+	} else if (div > N2_MAX) {
+		*n2 = N2_MAX;
+		*sdm = SDM_MAX;
+	} else {
+		*n2 = div;
+		*sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate);
+		if (*sdm < SDM_MIN)
+			*sdm = SDM_MIN;
+		else if (*sdm > SDM_MAX)
+			*sdm = SDM_MAX;
+	}
+}
+
 static unsigned long mpll_recalc_rate(struct clk_hw *hw,
 		unsigned long parent_rate)
 {
 	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
 	struct parm *p;
-	unsigned long rate = 0;
 	unsigned long reg, sdm, n2;
 
 	p = &mpll->sdm;
@@ -84,11 +118,119 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw,
 	reg = readl(mpll->base + p->reg_off);
 	n2 = PARM_GET(p->width, p->shift, reg);
 
-	rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm);
+	return rate_from_params(parent_rate, sdm, n2);
+}
+
+static long mpll_round_rate(struct clk_hw *hw,
+			    unsigned long rate,
+			    unsigned long *parent_rate)
+{
+	unsigned long sdm, n2;
+
+	params_from_rate(rate, *parent_rate, &sdm, &n2);
+	return rate_from_params(*parent_rate, sdm, n2);
+}
+
+static int mpll_set_rate(struct clk_hw *hw,
+			 unsigned long rate,
+			 unsigned long parent_rate)
+{
+	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+	struct parm *p;
+	unsigned long reg, sdm, n2;
+	unsigned long flags = 0;
+
+	params_from_rate(rate, parent_rate, &sdm, &n2);
+
+	if (mpll->lock)
+		spin_lock_irqsave(mpll->lock, flags);
+	else
+		__acquire(mpll->lock);
+
+	p = &mpll->sdm;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, sdm);
+	writel(reg, mpll->base + p->reg_off);
+
+	p = &mpll->sdm_en;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, 1);
+	writel(reg, mpll->base + p->reg_off);
+
+	p = &mpll->n2;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, n2);
+	writel(reg, mpll->base + p->reg_off);
+
+	if (mpll->lock)
+		spin_unlock_irqrestore(mpll->lock, flags);
+	else
+		__release(mpll->lock);
 
-	return rate;
+	return 0;
+}
+
+static void mpll_enable_core(struct clk_hw *hw, int enable)
+{
+	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+	struct parm *p;
+	unsigned long reg;
+	unsigned long flags = 0;
+
+	if (mpll->lock)
+		spin_lock_irqsave(mpll->lock, flags);
+	else
+		__acquire(mpll->lock);
+
+	p = &mpll->en;
+	reg = readl(mpll->base + p->reg_off);
+	reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
+	writel(reg, mpll->base + p->reg_off);
+
+	if (mpll->lock)
+		spin_unlock_irqrestore(mpll->lock, flags);
+	else
+		__release(mpll->lock);
+}
+
+
+static int mpll_enable(struct clk_hw *hw)
+{
+	mpll_enable_core(hw, 1);
+
+	return 0;
+}
+
+static void mpll_disable(struct clk_hw *hw)
+{
+	mpll_enable_core(hw, 0);
+}
+
+static int mpll_is_enabled(struct clk_hw *hw)
+{
+	struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+	struct parm *p;
+	unsigned long reg;
+	int en;
+
+	p = &mpll->en;
+	reg = readl(mpll->base + p->reg_off);
+	en = PARM_GET(p->width, p->shift, reg);
+
+	return en;
 }
 
 const struct clk_ops meson_clk_mpll_ro_ops = {
-	.recalc_rate = mpll_recalc_rate,
+	.recalc_rate	= mpll_recalc_rate,
+	.round_rate	= mpll_round_rate,
+	.is_enabled	= mpll_is_enabled,
+};
+
+const struct clk_ops meson_clk_mpll_ops = {
+	.recalc_rate	= mpll_recalc_rate,
+	.round_rate	= mpll_round_rate,
+	.set_rate	= mpll_set_rate,
+	.enable		= mpll_enable,
+	.disable	= mpll_disable,
+	.is_enabled	= mpll_is_enabled,
 };
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 9bb70e7a7d6a..54d58a465039 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -92,8 +92,9 @@ struct meson_clk_mpll {
 	struct clk_hw hw;
 	void __iomem *base;
 	struct parm sdm;
+	struct parm sdm_en;
 	struct parm n2;
-	/* FIXME ssen gate control? */
+	struct parm en;
 	spinlock_t *lock;
 };
 
@@ -116,5 +117,6 @@ extern const struct clk_ops meson_clk_pll_ro_ops;
 extern const struct clk_ops meson_clk_pll_ops;
 extern const struct clk_ops meson_clk_cpu_ops;
 extern const struct clk_ops meson_clk_mpll_ro_ops;
+extern const struct clk_ops meson_clk_mpll_ops;
 
 #endif /* __CLKC_H */
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 388b0c8838af..6b97f4da1708 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -441,11 +441,21 @@ static struct meson_clk_mpll gxbb_mpll0 = {
 		.shift   = 0,
 		.width   = 14,
 	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 15,
+		.width	 = 1,
+	},
 	.n2 = {
 		.reg_off = HHI_MPLL_CNTL7,
 		.shift   = 16,
 		.width   = 9,
 	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 14,
+		.width	 = 1,
+	},
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll0",
@@ -461,11 +471,21 @@ static struct meson_clk_mpll gxbb_mpll1 = {
 		.shift   = 0,
 		.width   = 14,
 	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 15,
+		.width	 = 1,
+	},
 	.n2 = {
 		.reg_off = HHI_MPLL_CNTL8,
 		.shift   = 16,
 		.width   = 9,
 	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 14,
+		.width	 = 1,
+	},
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll1",
@@ -481,11 +501,21 @@ static struct meson_clk_mpll gxbb_mpll2 = {
 		.shift   = 0,
 		.width   = 14,
 	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 15,
+		.width	 = 1,
+	},
 	.n2 = {
 		.reg_off = HHI_MPLL_CNTL9,
 		.shift   = 16,
 		.width   = 9,
 	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 14,
+		.width	 = 1,
+	},
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll2",
-- 
2.9.3

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

* [PATCH 4/7] clk: meson: gxbb: mpll: use rw operation
  2017-02-28 13:29 ` Jerome Brunet
@ 2017-02-28 13:29   ` Jerome Brunet
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel

Use read/write operations for the mpll clocks instead of the
read-only ones.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/gxbb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 6b97f4da1708..a52063f57d00 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -459,7 +459,7 @@ static struct meson_clk_mpll gxbb_mpll0 = {
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll0",
-		.ops = &meson_clk_mpll_ro_ops,
+		.ops = &meson_clk_mpll_ops,
 		.parent_names = (const char *[]){ "fixed_pll" },
 		.num_parents = 1,
 	},
@@ -489,7 +489,7 @@ static struct meson_clk_mpll gxbb_mpll1 = {
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll1",
-		.ops = &meson_clk_mpll_ro_ops,
+		.ops = &meson_clk_mpll_ops,
 		.parent_names = (const char *[]){ "fixed_pll" },
 		.num_parents = 1,
 	},
@@ -519,7 +519,7 @@ static struct meson_clk_mpll gxbb_mpll2 = {
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll2",
-		.ops = &meson_clk_mpll_ro_ops,
+		.ops = &meson_clk_mpll_ops,
 		.parent_names = (const char *[]){ "fixed_pll" },
 		.num_parents = 1,
 	},
-- 
2.9.3

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

* [PATCH 4/7] clk: meson: gxbb: mpll: use rw operation
@ 2017-02-28 13:29   ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:29 UTC (permalink / raw)
  To: linus-amlogic

Use read/write operations for the mpll clocks instead of the
read-only ones.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/gxbb.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 6b97f4da1708..a52063f57d00 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -459,7 +459,7 @@ static struct meson_clk_mpll gxbb_mpll0 = {
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll0",
-		.ops = &meson_clk_mpll_ro_ops,
+		.ops = &meson_clk_mpll_ops,
 		.parent_names = (const char *[]){ "fixed_pll" },
 		.num_parents = 1,
 	},
@@ -489,7 +489,7 @@ static struct meson_clk_mpll gxbb_mpll1 = {
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll1",
-		.ops = &meson_clk_mpll_ro_ops,
+		.ops = &meson_clk_mpll_ops,
 		.parent_names = (const char *[]){ "fixed_pll" },
 		.num_parents = 1,
 	},
@@ -519,7 +519,7 @@ static struct meson_clk_mpll gxbb_mpll2 = {
 	.lock = &clk_lock,
 	.hw.init = &(struct clk_init_data){
 		.name = "mpll2",
-		.ops = &meson_clk_mpll_ro_ops,
+		.ops = &meson_clk_mpll_ops,
 		.parent_names = (const char *[]){ "fixed_pll" },
 		.num_parents = 1,
 	},
-- 
2.9.3

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

* [PATCH 5/7] clk: meson8b: add the mplls clocks 0, 1 and 2
  2017-02-28 13:29 ` Jerome Brunet
@ 2017-02-28 13:30   ` Jerome Brunet
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:30 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/meson8b.c | 103 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/meson/meson8b.h |  20 ++++++++-
 2 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 44c24bf754cd..034df7556126 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -245,6 +245,96 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
 	},
 };
 
+static struct meson_clk_mpll meson8b_mpll0 = {
+	.sdm = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 0,
+		.width   = 14,
+	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 15,
+		.width   = 1,
+	},
+	.n2 = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 16,
+		.width   = 9,
+	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 14,
+		.width   = 1,
+	},
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll0",
+		.ops = &meson_clk_mpll_ops,
+		.parent_names = (const char *[]){ "fixed_pll" },
+		.num_parents = 1,
+	},
+};
+
+static struct meson_clk_mpll meson8b_mpll1 = {
+	.sdm = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 0,
+		.width   = 14,
+	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 15,
+		.width   = 1,
+	},
+	.n2 = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 16,
+		.width   = 9,
+	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 14,
+		.width   = 1,
+	},
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll1",
+		.ops = &meson_clk_mpll_ops,
+		.parent_names = (const char *[]){ "fixed_pll" },
+		.num_parents = 1,
+	},
+};
+
+static struct meson_clk_mpll meson8b_mpll2 = {
+	.sdm = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 0,
+		.width   = 14,
+	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 15,
+		.width   = 1,
+	},
+	.n2 = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 16,
+		.width   = 9,
+	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 14,
+		.width   = 1,
+	},
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll2",
+		.ops = &meson_clk_mpll_ops,
+		.parent_names = (const char *[]){ "fixed_pll" },
+		.num_parents = 1,
+	},
+};
+
 /*
  * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
  * post-dividers and should be modeled with their respective PLLs via the
@@ -491,6 +581,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
 		[CLKID_AO_AHB_SRAM]	    = &meson8b_ao_ahb_sram.hw,
 		[CLKID_AO_AHB_BUS]	    = &meson8b_ao_ahb_bus.hw,
 		[CLKID_AO_IFACE]	    = &meson8b_ao_iface.hw,
+		[CLKID_MPLL0]		    = &meson8b_mpll0.hw,
+		[CLKID_MPLL1]		    = &meson8b_mpll1.hw,
+		[CLKID_MPLL2]		    = &meson8b_mpll2.hw,
 	},
 	.num = CLK_NR_CLKS,
 };
@@ -501,6 +594,12 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = {
 	&meson8b_sys_pll,
 };
 
+static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
+	&meson8b_mpll0,
+	&meson8b_mpll1,
+	&meson8b_mpll2,
+};
+
 static struct clk_gate *meson8b_clk_gates[] = {
 	&meson8b_clk81,
 	&meson8b_ddr,
@@ -610,6 +709,10 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
 		meson8b_clk_plls[i]->base = clk_base;
 
+	/* Populate base address for MPLLs */
+	for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
+		meson8b_clk_mplls[i]->base = clk_base;
+
 	/* Populate the base address for CPU clk */
 	meson8b_cpu_clk.base = clk_base;
 
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 010e9582888d..3881defc8644 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -42,6 +42,21 @@
 #define HHI_VID_PLL_CNTL		0x320 /* 0xc8 offset in data sheet */
 
 /*
+ * MPLL register offeset taken from the S905 datasheet. Vendor kernel source
+ * confirm these are the same for the S805.
+ */
+#define HHI_MPLL_CNTL			0x280 /* 0xa0 offset in data sheet */
+#define HHI_MPLL_CNTL2			0x284 /* 0xa1 offset in data sheet */
+#define HHI_MPLL_CNTL3			0x288 /* 0xa2 offset in data sheet */
+#define HHI_MPLL_CNTL4			0x28C /* 0xa3 offset in data sheet */
+#define HHI_MPLL_CNTL5			0x290 /* 0xa4 offset in data sheet */
+#define HHI_MPLL_CNTL6			0x294 /* 0xa5 offset in data sheet */
+#define HHI_MPLL_CNTL7			0x298 /* 0xa6 offset in data sheet */
+#define HHI_MPLL_CNTL8			0x29C /* 0xa7 offset in data sheet */
+#define HHI_MPLL_CNTL9			0x2A0 /* 0xa8 offset in data sheet */
+#define HHI_MPLL_CNTL10			0x2A4 /* 0xa9 offset in data sheet */
+
+/*
  * CLKID index values
  *
  * These indices are entirely contrived and do not map onto the hardware.
@@ -142,8 +157,11 @@
 #define CLKID_AO_AHB_SRAM	90
 #define CLKID_AO_AHB_BUS	91
 #define CLKID_AO_IFACE		92
+#define CLKID_MPLL0		93
+#define CLKID_MPLL1		94
+#define CLKID_MPLL2		95
 
-#define CLK_NR_CLKS		93
+#define CLK_NR_CLKS		96
 
 /* include the CLKIDs that have been made part of the stable DT binding */
 #include <dt-bindings/clock/meson8b-clkc.h>
-- 
2.9.3

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

* [PATCH 5/7] clk: meson8b: add the mplls clocks 0, 1 and 2
@ 2017-02-28 13:30   ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:30 UTC (permalink / raw)
  To: linus-amlogic

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/meson8b.c | 103 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/meson/meson8b.h |  20 ++++++++-
 2 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 44c24bf754cd..034df7556126 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -245,6 +245,96 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
 	},
 };
 
+static struct meson_clk_mpll meson8b_mpll0 = {
+	.sdm = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 0,
+		.width   = 14,
+	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 15,
+		.width   = 1,
+	},
+	.n2 = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 16,
+		.width   = 9,
+	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL7,
+		.shift   = 14,
+		.width   = 1,
+	},
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll0",
+		.ops = &meson_clk_mpll_ops,
+		.parent_names = (const char *[]){ "fixed_pll" },
+		.num_parents = 1,
+	},
+};
+
+static struct meson_clk_mpll meson8b_mpll1 = {
+	.sdm = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 0,
+		.width   = 14,
+	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 15,
+		.width   = 1,
+	},
+	.n2 = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 16,
+		.width   = 9,
+	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL8,
+		.shift   = 14,
+		.width   = 1,
+	},
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll1",
+		.ops = &meson_clk_mpll_ops,
+		.parent_names = (const char *[]){ "fixed_pll" },
+		.num_parents = 1,
+	},
+};
+
+static struct meson_clk_mpll meson8b_mpll2 = {
+	.sdm = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 0,
+		.width   = 14,
+	},
+	.sdm_en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 15,
+		.width   = 1,
+	},
+	.n2 = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 16,
+		.width   = 9,
+	},
+	.en = {
+		.reg_off = HHI_MPLL_CNTL9,
+		.shift   = 14,
+		.width   = 1,
+	},
+	.lock = &clk_lock,
+	.hw.init = &(struct clk_init_data){
+		.name = "mpll2",
+		.ops = &meson_clk_mpll_ops,
+		.parent_names = (const char *[]){ "fixed_pll" },
+		.num_parents = 1,
+	},
+};
+
 /*
  * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
  * post-dividers and should be modeled with their respective PLLs via the
@@ -491,6 +581,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
 		[CLKID_AO_AHB_SRAM]	    = &meson8b_ao_ahb_sram.hw,
 		[CLKID_AO_AHB_BUS]	    = &meson8b_ao_ahb_bus.hw,
 		[CLKID_AO_IFACE]	    = &meson8b_ao_iface.hw,
+		[CLKID_MPLL0]		    = &meson8b_mpll0.hw,
+		[CLKID_MPLL1]		    = &meson8b_mpll1.hw,
+		[CLKID_MPLL2]		    = &meson8b_mpll2.hw,
 	},
 	.num = CLK_NR_CLKS,
 };
@@ -501,6 +594,12 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = {
 	&meson8b_sys_pll,
 };
 
+static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
+	&meson8b_mpll0,
+	&meson8b_mpll1,
+	&meson8b_mpll2,
+};
+
 static struct clk_gate *meson8b_clk_gates[] = {
 	&meson8b_clk81,
 	&meson8b_ddr,
@@ -610,6 +709,10 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
 		meson8b_clk_plls[i]->base = clk_base;
 
+	/* Populate base address for MPLLs */
+	for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
+		meson8b_clk_mplls[i]->base = clk_base;
+
 	/* Populate the base address for CPU clk */
 	meson8b_cpu_clk.base = clk_base;
 
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 010e9582888d..3881defc8644 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -42,6 +42,21 @@
 #define HHI_VID_PLL_CNTL		0x320 /* 0xc8 offset in data sheet */
 
 /*
+ * MPLL register offeset taken from the S905 datasheet. Vendor kernel source
+ * confirm these are the same for the S805.
+ */
+#define HHI_MPLL_CNTL			0x280 /* 0xa0 offset in data sheet */
+#define HHI_MPLL_CNTL2			0x284 /* 0xa1 offset in data sheet */
+#define HHI_MPLL_CNTL3			0x288 /* 0xa2 offset in data sheet */
+#define HHI_MPLL_CNTL4			0x28C /* 0xa3 offset in data sheet */
+#define HHI_MPLL_CNTL5			0x290 /* 0xa4 offset in data sheet */
+#define HHI_MPLL_CNTL6			0x294 /* 0xa5 offset in data sheet */
+#define HHI_MPLL_CNTL7			0x298 /* 0xa6 offset in data sheet */
+#define HHI_MPLL_CNTL8			0x29C /* 0xa7 offset in data sheet */
+#define HHI_MPLL_CNTL9			0x2A0 /* 0xa8 offset in data sheet */
+#define HHI_MPLL_CNTL10			0x2A4 /* 0xa9 offset in data sheet */
+
+/*
  * CLKID index values
  *
  * These indices are entirely contrived and do not map onto the hardware.
@@ -142,8 +157,11 @@
 #define CLKID_AO_AHB_SRAM	90
 #define CLKID_AO_AHB_BUS	91
 #define CLKID_AO_IFACE		92
+#define CLKID_MPLL0		93
+#define CLKID_MPLL1		94
+#define CLKID_MPLL2		95
 
-#define CLK_NR_CLKS		93
+#define CLK_NR_CLKS		96
 
 /* include the CLKIDs that have been made part of the stable DT binding */
 #include <dt-bindings/clock/meson8b-clkc.h>
-- 
2.9.3

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

* [PATCH 6/7] clk: meson: mpll: correct N2 maximum value
  2017-02-28 13:29 ` Jerome Brunet
@ 2017-02-28 13:30   ` Jerome Brunet
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:30 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel

Gxbb datasheet says N2 maximum value is 127 but the register field is
9 bits wide, the maximum value should 511.

Test shows value greater than 127, all the way to 511, works well

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/clk-mpll.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 342b85d4e22a..540dabe5adad 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -68,7 +68,7 @@
 #define SDM_MIN 1
 #define SDM_MAX 16383
 #define N2_MIN	4
-#define N2_MAX	127
+#define N2_MAX	511
 
 #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
 
-- 
2.9.3

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

* [PATCH 6/7] clk: meson: mpll: correct N2 maximum value
@ 2017-02-28 13:30   ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:30 UTC (permalink / raw)
  To: linus-amlogic

Gxbb datasheet says N2 maximum value is 127 but the register field is
9 bits wide, the maximum value should 511.

Test shows value greater than 127, all the way to 511, works well

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/clk-mpll.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 342b85d4e22a..540dabe5adad 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -68,7 +68,7 @@
 #define SDM_MIN 1
 #define SDM_MAX 16383
 #define N2_MIN	4
-#define N2_MAX	127
+#define N2_MAX	511
 
 #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
 
-- 
2.9.3

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

* [PATCH 7/7] dt-bindings: clk: gxbb: expose i2s output clock gates
  2017-02-28 13:29 ` Jerome Brunet
@ 2017-02-28 13:30   ` Jerome Brunet
  -1 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:30 UTC (permalink / raw)
  To: Michael Turquette, Stephen Boyd, Kevin Hilman, Carlo Caione
  Cc: Jerome Brunet, linux-clk, linux-amlogic, linux-kernel, devicetree

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/gxbb.h              | 10 +++++-----
 include/dt-bindings/clock/gxbb-clkc.h |  5 +++++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index dc487180f847..95a83b7709ca 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -206,16 +206,16 @@
 #define CLKID_I2S_SPDIF		  35
 #define CLKID_ETH		  36
 #define CLKID_DEMUX		  37
-#define CLKID_AIU_GLUE		  38
+/* CLKID_AIU_GLUE */
 #define CLKID_IEC958		  39
-#define CLKID_I2S_OUT		  40
+/* CLKID_I2S_OUT */
 #define CLKID_AMCLK		  41
 #define CLKID_AIFIFO2		  42
 #define CLKID_MIXER		  43
-#define CLKID_MIXER_IFACE	  44
+/* CLKID_MIXER_IFACE */
 #define CLKID_ADC		  45
 #define CLKID_BLKMV		  46
-#define CLKID_AIU		  47
+/* CLKID_AIU */
 #define CLKID_UART1		  48
 #define CLKID_G2D		  49
 /* CLKID_USB0 */
@@ -248,7 +248,7 @@
 /* CLKID_GCLK_VENCI_INT0 */
 #define CLKID_GCLK_VENCI_INT	  78
 #define CLKID_DAC_CLK		  79
-#define CLKID_AOCLK_GATE	  80
+/* CLKID_AOCLK_GATE */
 #define CLKID_IEC958_GATE	  81
 #define CLKID_ENC480P		  82
 #define CLKID_RNG1		  83
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index 692846c7941b..f08f06dd7702 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -16,6 +16,10 @@
 #define CLKID_I2C		22
 #define CLKID_SAR_ADC		23
 #define CLKID_ETH		36
+#define CLKID_AIU_GLUE		38
+#define CLKID_I2S_OUT		40
+#define CLKID_MIXER_IFACE	44
+#define CLKID_AIU		47
 #define CLKID_USB0		50
 #define CLKID_USB1		51
 #define CLKID_USB		55
@@ -24,6 +28,7 @@
 #define CLKID_USB0_DDR_BRIDGE	65
 #define CLKID_SANA		69
 #define CLKID_GCLK_VENCI_INT0	77
+#define CLKID_AOCLK_GATE	80
 #define CLKID_AO_I2C		93
 #define CLKID_SD_EMMC_A		94
 #define CLKID_SD_EMMC_B		95
-- 
2.9.3

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

* [PATCH 7/7] dt-bindings: clk: gxbb: expose i2s output clock gates
@ 2017-02-28 13:30   ` Jerome Brunet
  0 siblings, 0 replies; 17+ messages in thread
From: Jerome Brunet @ 2017-02-28 13:30 UTC (permalink / raw)
  To: linus-amlogic

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/meson/gxbb.h              | 10 +++++-----
 include/dt-bindings/clock/gxbb-clkc.h |  5 +++++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/meson/gxbb.h b/drivers/clk/meson/gxbb.h
index dc487180f847..95a83b7709ca 100644
--- a/drivers/clk/meson/gxbb.h
+++ b/drivers/clk/meson/gxbb.h
@@ -206,16 +206,16 @@
 #define CLKID_I2S_SPDIF		  35
 #define CLKID_ETH		  36
 #define CLKID_DEMUX		  37
-#define CLKID_AIU_GLUE		  38
+/* CLKID_AIU_GLUE */
 #define CLKID_IEC958		  39
-#define CLKID_I2S_OUT		  40
+/* CLKID_I2S_OUT */
 #define CLKID_AMCLK		  41
 #define CLKID_AIFIFO2		  42
 #define CLKID_MIXER		  43
-#define CLKID_MIXER_IFACE	  44
+/* CLKID_MIXER_IFACE */
 #define CLKID_ADC		  45
 #define CLKID_BLKMV		  46
-#define CLKID_AIU		  47
+/* CLKID_AIU */
 #define CLKID_UART1		  48
 #define CLKID_G2D		  49
 /* CLKID_USB0 */
@@ -248,7 +248,7 @@
 /* CLKID_GCLK_VENCI_INT0 */
 #define CLKID_GCLK_VENCI_INT	  78
 #define CLKID_DAC_CLK		  79
-#define CLKID_AOCLK_GATE	  80
+/* CLKID_AOCLK_GATE */
 #define CLKID_IEC958_GATE	  81
 #define CLKID_ENC480P		  82
 #define CLKID_RNG1		  83
diff --git a/include/dt-bindings/clock/gxbb-clkc.h b/include/dt-bindings/clock/gxbb-clkc.h
index 692846c7941b..f08f06dd7702 100644
--- a/include/dt-bindings/clock/gxbb-clkc.h
+++ b/include/dt-bindings/clock/gxbb-clkc.h
@@ -16,6 +16,10 @@
 #define CLKID_I2C		22
 #define CLKID_SAR_ADC		23
 #define CLKID_ETH		36
+#define CLKID_AIU_GLUE		38
+#define CLKID_I2S_OUT		40
+#define CLKID_MIXER_IFACE	44
+#define CLKID_AIU		47
 #define CLKID_USB0		50
 #define CLKID_USB1		51
 #define CLKID_USB		55
@@ -24,6 +28,7 @@
 #define CLKID_USB0_DDR_BRIDGE	65
 #define CLKID_SANA		69
 #define CLKID_GCLK_VENCI_INT0	77
+#define CLKID_AOCLK_GATE	80
 #define CLKID_AO_I2C		93
 #define CLKID_SD_EMMC_A		94
 #define CLKID_SD_EMMC_B		95
-- 
2.9.3

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

end of thread, other threads:[~2017-02-28 13:32 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-28 13:29 [PATCH 0/7] clk: meson: update clock controller for audio support Jerome Brunet
2017-02-28 13:29 ` Jerome Brunet
2017-02-28 13:29 ` Jerome Brunet
2017-02-28 13:29 ` [PATCH 1/7] clk: meson8b: put dividers and muxes in tables Jerome Brunet
2017-02-28 13:29   ` Jerome Brunet
2017-02-28 13:29 ` [PATCH 2/7] clk: gxbb: " Jerome Brunet
2017-02-28 13:29   ` Jerome Brunet
2017-02-28 13:29 ` [PATCH 3/7] clk: meson: mpll: add rw operation Jerome Brunet
2017-02-28 13:29   ` Jerome Brunet
2017-02-28 13:29 ` [PATCH 4/7] clk: meson: gxbb: mpll: use " Jerome Brunet
2017-02-28 13:29   ` Jerome Brunet
2017-02-28 13:30 ` [PATCH 5/7] clk: meson8b: add the mplls clocks 0, 1 and 2 Jerome Brunet
2017-02-28 13:30   ` Jerome Brunet
2017-02-28 13:30 ` [PATCH 6/7] clk: meson: mpll: correct N2 maximum value Jerome Brunet
2017-02-28 13:30   ` Jerome Brunet
2017-02-28 13:30 ` [PATCH 7/7] dt-bindings: clk: gxbb: expose i2s output clock gates Jerome Brunet
2017-02-28 13:30   ` Jerome Brunet

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