linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes
@ 2015-08-21 17:46 Heiko Stuebner
  2015-08-21 17:47 ` [PATCH 2/3] clk: rockchip: handle mux dependency of fractional dividers Heiko Stuebner
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Heiko Stuebner @ 2015-08-21 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

Some clocks need to be enabled to accept rate changes. This patch adds a
new flag CLK_SET_RATE_UNGATE that lets clk_change_rate enable the clock
before trying to change the rate and disable it again afterwards.
This of course doesn't effect clocks that are already running at that
point, as their refcount will only temporarily increase.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/clk/clk.c            | 18 ++++++++++++++++++
 include/linux/clk-provider.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 28cd923..564f11e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1438,6 +1438,15 @@ static void clk_change_rate(struct clk_core *core)
 	else if (core->parent)
 		best_parent_rate = core->parent->rate;
 
+	if (core->flags & CLK_SET_RATE_UNGATE) {
+		unsigned long flags;
+
+		clk_core_prepare(core);
+		flags = clk_enable_lock();
+		clk_core_enable(core);
+		clk_enable_unlock(flags);
+	}
+
 	if (core->new_parent && core->new_parent != core->parent) {
 		old_parent = __clk_set_parent_before(core, core->new_parent);
 		trace_clk_set_parent(core, core->new_parent);
@@ -1464,6 +1473,15 @@ static void clk_change_rate(struct clk_core *core)
 
 	core->rate = clk_recalc(core, best_parent_rate);
 
+	if (core->flags & CLK_SET_RATE_UNGATE) {
+		unsigned long flags;
+
+		flags = clk_enable_lock();
+		clk_core_disable(core);
+		clk_enable_unlock(flags);
+		clk_core_unprepare(core);
+	}
+
 	if (core->notifier_count && old_rate != core->rate)
 		__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
 
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 3ecc07d..21e0025 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -31,6 +31,7 @@
 #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */
 #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
 #define CLK_RECALC_NEW_RATES	BIT(9) /* recalc rates after notifications */
+#define CLK_SET_RATE_UNGATE	BIT(10) /* clock needs to run to set rate */
 
 struct clk;
 struct clk_hw;
-- 
2.1.4

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

* [PATCH 2/3] clk: rockchip: handle mux dependency of fractional dividers
  2015-08-21 17:46 [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stuebner
@ 2015-08-21 17:47 ` Heiko Stuebner
  2015-10-05 19:09   ` Sjoerd Simons
  2015-08-21 17:48 ` [PATCH 3/3] clk: rockchip: include downstream muxes into " Heiko Stuebner
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 12+ messages in thread
From: Heiko Stuebner @ 2015-08-21 17:47 UTC (permalink / raw)
  To: linux-arm-kernel

The fractional dividers of Rockchip SoCs contain an "auto-gating-feature"
that requires the downstream mux to actually point to the fractional
divider and the fractional divider gate to be enabled, for it to really
accept changes to the divider ratio.

The downstream muxes themselfs are not generic enough to include them
directly into the fractional divider, as they have varying sources of
parent clocks including not only clocks related to the fractional
dividers but other clocks as well.

To solve this, allow our clock branches to specify direct child clock-
branches in the new child property, let the fractional divider register
its downstream mux through this and add a clock notifier that temporarily
switches the mux setting when it notices rate changes to the fractional
divider.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/clk/rockchip/clk.c | 137 ++++++++++++++++++++++++++++++++++++++++-----
 drivers/clk/rockchip/clk.h |  19 +++++++
 2 files changed, 142 insertions(+), 14 deletions(-)

diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index 2493881..8c7fd2b 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -102,22 +102,82 @@ static struct clk *rockchip_clk_register_branch(const char *name,
 	return clk;
 }
 
+struct rockchip_clk_frac {
+	struct notifier_block			clk_nb;
+	struct clk_fractional_divider		div;
+	struct clk_gate				gate;
+
+	struct clk_mux				mux;
+	const struct clk_ops			*mux_ops;
+	int					mux_frac_idx;
+
+	bool					rate_change_remuxed;
+	int					rate_change_idx;
+};
+
+#define to_rockchip_clk_frac_nb(nb) \
+			container_of(nb, struct rockchip_clk_frac, clk_nb)
+
+static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
+					 unsigned long event, void *data)
+{
+	struct clk_notifier_data *ndata = data;
+	struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb);
+	struct clk_mux *frac_mux = &frac->mux;
+	int ret = 0;
+
+	pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
+		 __func__, event, ndata->old_rate, ndata->new_rate);
+	if (event == PRE_RATE_CHANGE) {
+		frac->rate_change_idx = frac->mux_ops->get_parent(&frac_mux->hw);
+		if (frac->rate_change_idx != frac->mux_frac_idx) {
+			frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx);
+			frac->rate_change_remuxed = 1;
+		}
+	} else if (event == POST_RATE_CHANGE) {
+		/*
+		 * The POST_RATE_CHANGE notifier runs directly after the
+		 * divider clock is set in clk_change_rate, so we'll have
+		 * remuxed back to the original parent before clk_change_rate
+		 * reaches the mux itself.
+		 */
+		if (frac->rate_change_remuxed) {
+			frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx);
+			frac->rate_change_remuxed = 0;
+		}
+	}
+
+	return notifier_from_errno(ret);
+}
+
 static struct clk *rockchip_clk_register_frac_branch(const char *name,
 		const char *const *parent_names, u8 num_parents,
 		void __iomem *base, int muxdiv_offset, u8 div_flags,
 		int gate_offset, u8 gate_shift, u8 gate_flags,
-		unsigned long flags, spinlock_t *lock)
+		unsigned long flags, struct rockchip_clk_branch *child,
+		spinlock_t *lock)
 {
+	struct rockchip_clk_frac *frac;
 	struct clk *clk;
 	struct clk_gate *gate = NULL;
 	struct clk_fractional_divider *div = NULL;
 	const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
 
-	if (gate_offset >= 0) {
-		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
-		if (!gate)
-			return ERR_PTR(-ENOMEM);
+	if (muxdiv_offset < 0)
+		return ERR_PTR(-EINVAL);
 
+	if (child && child->branch_type != branch_mux) {
+		pr_err("%s: fractional child clock for %s can only be a mux\n",
+		       __func__, name);
+		return ERR_PTR(-EINVAL);
+	}
+
+	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
+	if (!frac)
+		return ERR_PTR(-ENOMEM);
+
+	if (gate_offset >= 0) {
+		gate = &frac->gate;
 		gate->flags = gate_flags;
 		gate->reg = base + gate_offset;
 		gate->bit_idx = gate_shift;
@@ -125,13 +185,7 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
 		gate_ops = &clk_gate_ops;
 	}
 
-	if (muxdiv_offset < 0)
-		return ERR_PTR(-EINVAL);
-
-	div = kzalloc(sizeof(*div), GFP_KERNEL);
-	if (!div)
-		return ERR_PTR(-ENOMEM);
-
+	div = &frac->div;
 	div->flags = div_flags;
 	div->reg = base + muxdiv_offset;
 	div->mshift = 16;
@@ -145,7 +199,61 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
 				     NULL, NULL,
 				     &div->hw, div_ops,
 				     gate ? &gate->hw : NULL, gate_ops,
-				     flags);
+				     flags | CLK_SET_RATE_UNGATE);
+	if (IS_ERR(clk)) {
+		kfree(frac);
+		return clk;
+	}
+
+	if (child) {
+		struct clk_mux *frac_mux = &frac->mux;
+		struct clk_init_data init;
+		struct clk *mux_clk;
+		int i, ret;
+
+		frac->mux_frac_idx = -1;
+		for (i = 0; i < child->num_parents; i++) {
+			if (!strcmp(name, child->parent_names[i])) {
+				pr_debug("%s: found fractional parent in mux at pos %d\n",
+					 __func__, i);
+				frac->mux_frac_idx = i;
+				break;
+			}
+		}
+
+		frac->mux_ops = &clk_mux_ops;
+		frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;
+
+		frac_mux->reg = base + child->muxdiv_offset;
+		frac_mux->shift = child->mux_shift;
+		frac_mux->mask = BIT(child->mux_width) - 1;
+		frac_mux->flags = child->mux_flags;
+		frac_mux->lock = lock;
+		frac_mux->hw.init = &init;
+
+		init.name = child->name;
+		init.flags = child->flags | CLK_SET_RATE_PARENT;
+		init.ops = frac->mux_ops;
+		init.parent_names = child->parent_names;
+		init.num_parents = child->num_parents;
+
+		mux_clk = clk_register(NULL, &frac_mux->hw);
+		if (IS_ERR(mux_clk))
+			return clk;
+
+		rockchip_clk_add_lookup(mux_clk, child->id);
+
+		/* notifier on the fraction divider to catch rate changes */
+		if (frac->mux_frac_idx >= 0) {
+			ret = clk_notifier_register(clk, &frac->clk_nb);
+			if (ret)
+				pr_err("%s: failed to register clock notifier for %s\n",
+						__func__, name);
+		} else {
+			pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n",
+				__func__, name, child->name);
+		}
+	}
 
 	return clk;
 }
@@ -249,7 +357,8 @@ void __init rockchip_clk_register_branches(
 				list->parent_names, list->num_parents,
 				reg_base, list->muxdiv_offset, list->div_flags,
 				list->gate_offset, list->gate_shift,
-				list->gate_flags, flags, &clk_lock);
+				list->gate_flags, flags, list->child,
+				&clk_lock);
 			break;
 		case branch_gate:
 			flags |= CLK_SET_RATE_PARENT;
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index dc8ecb2..147db79 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -235,6 +235,7 @@ struct rockchip_clk_branch {
 	int				gate_offset;
 	u8				gate_shift;
 	u8				gate_flags;
+	struct rockchip_clk_branch	*child;
 };
 
 #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
@@ -369,6 +370,24 @@ struct rockchip_clk_branch {
 		.gate_flags	= gf,				\
 	}
 
+#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
+	{							\
+		.id		= _id,				\
+		.branch_type	= branch_fraction_divider,	\
+		.name		= cname,			\
+		.parent_names	= (const char *[]){ pname },	\
+		.num_parents	= 1,				\
+		.flags		= f,				\
+		.muxdiv_offset	= mo,				\
+		.div_shift	= 16,				\
+		.div_width	= 16,				\
+		.div_flags	= df,				\
+		.gate_offset	= go,				\
+		.gate_shift	= gs,				\
+		.gate_flags	= gf,				\
+		.child		= &(struct rockchip_clk_branch)ch, \
+	}
+
 #define MUX(_id, cname, pnames, f, o, s, w, mf)			\
 	{							\
 		.id		= _id,				\
-- 
2.1.4

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

* [PATCH 3/3] clk: rockchip: include downstream muxes into fractional dividers
  2015-08-21 17:46 [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stuebner
  2015-08-21 17:47 ` [PATCH 2/3] clk: rockchip: handle mux dependency of fractional dividers Heiko Stuebner
@ 2015-08-21 17:48 ` Heiko Stuebner
  2015-10-05 19:09   ` Sjoerd Simons
  2015-12-12  3:35   ` Caesar Wang
  2015-10-02 14:12 ` [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stübner
  2015-10-05 19:09 ` Sjoerd Simons
  3 siblings, 2 replies; 12+ messages in thread
From: Heiko Stuebner @ 2015-08-21 17:48 UTC (permalink / raw)
  To: linux-arm-kernel

Use the newly introduced possibility to combine the fractional dividers
with their downstream muxes for all fractional dividers on currently
supported Rockchip SoCs.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/clk/rockchip/clk-rk3188.c | 80 +++++++++++++++++++--------------------
 drivers/clk/rockchip/clk-rk3288.c | 66 ++++++++++++++++----------------
 2 files changed, 74 insertions(+), 72 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
index ed02bbc..faa6695 100644
--- a/drivers/clk/rockchip/clk-rk3188.c
+++ b/drivers/clk/rockchip/clk-rk3188.c
@@ -335,11 +335,11 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
 			RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
 			RK2928_CLKGATE_CON(2), 6, GFLAGS),
-	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
+	COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
 			RK2928_CLKSEL_CON(23), 0,
-			RK2928_CLKGATE_CON(2), 7, GFLAGS),
-	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
-			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
+			RK2928_CLKGATE_CON(2), 7, GFLAGS,
+		MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
+				RK2928_CLKSEL_CON(22), 4, 2, MFLAGS)),
 	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
 			RK2928_CLKSEL_CON(22), 7, IFLAGS),
 
@@ -350,11 +350,11 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 13, GFLAGS),
-	COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pll", CLK_SET_RATE_PARENT,
 			RK2928_CLKSEL_CON(9), 0,
-			RK2928_CLKGATE_CON(0), 14, GFLAGS),
-	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
-			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 14, GFLAGS,
+		MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
+				RK2928_CLKSEL_CON(5), 8, 2, MFLAGS)),
 
 	/*
 	 * Clock-Architecture Diagram 4
@@ -385,35 +385,35 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 8, GFLAGS),
-	COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
 			RK2928_CLKSEL_CON(17), 0,
-			RK2928_CLKGATE_CON(1), 9, GFLAGS),
-	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
-			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 9, GFLAGS,
+		MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
+				RK2928_CLKSEL_CON(13), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 10, GFLAGS),
-	COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
 			RK2928_CLKSEL_CON(18), 0,
-			RK2928_CLKGATE_CON(1), 11, GFLAGS),
-	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
-			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 11, GFLAGS,
+		MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
+				RK2928_CLKSEL_CON(14), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 12, GFLAGS),
-	COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
 			RK2928_CLKSEL_CON(19), 0,
-			RK2928_CLKGATE_CON(1), 13, GFLAGS),
-	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
-			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 13, GFLAGS,
+		MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
+				RK2928_CLKSEL_CON(15), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
 			RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(1), 14, GFLAGS),
-	COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
+	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
 			RK2928_CLKSEL_CON(20), 0,
-			RK2928_CLKGATE_CON(1), 15, GFLAGS),
-	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
-			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(1), 15, GFLAGS,
+		MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
+				RK2928_CLKSEL_CON(16), 8, 2, MFLAGS)),
 
 	GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
 
@@ -584,27 +584,27 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 7, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
 			RK2928_CLKSEL_CON(6), 0,
-			RK2928_CLKGATE_CON(0), 8, GFLAGS),
-	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
-			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 8, GFLAGS,
+		MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+				RK2928_CLKSEL_CON(2), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
 			RK2928_CLKSEL_CON(7), 0,
-			RK2928_CLKGATE_CON(0), 10, GFLAGS),
-	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
-			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 10, GFLAGS,
+		MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
+				RK2928_CLKSEL_CON(3), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 11, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
 			RK2928_CLKSEL_CON(8), 0,
-			RK2928_CLKGATE_CON(0), 12, GFLAGS),
-	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
-			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 12, GFLAGS,
+		MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
+				RK2928_CLKSEL_CON(4), 8, 2, MFLAGS)),
 
 	GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
 	GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
@@ -691,11 +691,11 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
 			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK2928_CLKGATE_CON(0), 9, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
+	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
 			RK2928_CLKSEL_CON(7), 0,
-			RK2928_CLKGATE_CON(0), 10, GFLAGS),
-	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
-			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
+			RK2928_CLKGATE_CON(0), 10, GFLAGS,
+		MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
+				RK2928_CLKSEL_CON(3), 8, 2, MFLAGS)),
 
 	GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
 	GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
index 0df5bae..18fcdb1 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -304,11 +304,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 1, GFLAGS),
-	COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(8), 0,
-			RK3288_CLKGATE_CON(4), 2, GFLAGS),
-	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(4), 2, GFLAGS,
+		MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
+				RK3288_CLKSEL_CON(4), 8, 2, MFLAGS)),
 	COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
 			RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
 			RK3288_CLKGATE_CON(4), 0, GFLAGS),
@@ -320,20 +320,22 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
 			RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 4, GFLAGS),
-	COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
+	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0,
 			RK3288_CLKSEL_CON(9), 0,
-			RK3288_CLKGATE_CON(4), 5, GFLAGS),
-	COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
-			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
+			RK3288_CLKGATE_CON(4), 5, GFLAGS,
+		MUX(0, "spdif_mux", mux_spdif_p, 0,
+				RK3288_CLKSEL_CON(5), 8, 2, MFLAGS)),
+	GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", 0,
 			RK3288_CLKGATE_CON(4), 6, GFLAGS),
 	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
 			RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(4), 7, GFLAGS),
-	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
+	COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
 			RK3288_CLKSEL_CON(41), 0,
-			RK3288_CLKGATE_CON(4), 8, GFLAGS),
-	COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
-			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
+			RK3288_CLKGATE_CON(4), 8, GFLAGS,
+		MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, 0,
+				RK3288_CLKSEL_CON(40), 8, 2, MFLAGS)),
+	GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", 0,
 			RK3288_CLKGATE_CON(4), 9, GFLAGS),
 
 	GATE(0, "sclk_acc_efuse", "xin24m", 0,
@@ -536,45 +538,45 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
 	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0,
 			RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 8, GFLAGS),
-	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(17), 0,
-			RK3288_CLKGATE_CON(1), 9, GFLAGS),
-	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 9, GFLAGS,
+		MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
+				RK3288_CLKSEL_CON(13), 8, 2, MFLAGS)),
 	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
 	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 10, GFLAGS),
-	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(18), 0,
-			RK3288_CLKGATE_CON(1), 11, GFLAGS),
-	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 11, GFLAGS,
+		MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
+				RK3288_CLKSEL_CON(14), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 12, GFLAGS),
-	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(19), 0,
-			RK3288_CLKGATE_CON(1), 13, GFLAGS),
-	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 13, GFLAGS,
+		MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
+				RK3288_CLKSEL_CON(15), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(1), 14, GFLAGS),
-	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(20), 0,
-			RK3288_CLKGATE_CON(1), 15, GFLAGS),
-	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(1), 15, GFLAGS,
+		MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
+				RK3288_CLKSEL_CON(16), 8, 2, MFLAGS)),
 	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
 			RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
 			RK3288_CLKGATE_CON(2), 12, GFLAGS),
-	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
+	COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
 			RK3288_CLKSEL_CON(7), 0,
-			RK3288_CLKGATE_CON(2), 13, GFLAGS),
-	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
-			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
+			RK3288_CLKGATE_CON(2), 13, GFLAGS,
+		MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
+				RK3288_CLKSEL_CON(3), 8, 2, MFLAGS)),
 
 	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
 			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
-- 
2.1.4

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

* [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes
  2015-08-21 17:46 [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stuebner
  2015-08-21 17:47 ` [PATCH 2/3] clk: rockchip: handle mux dependency of fractional dividers Heiko Stuebner
  2015-08-21 17:48 ` [PATCH 3/3] clk: rockchip: include downstream muxes into " Heiko Stuebner
@ 2015-10-02 14:12 ` Heiko Stübner
  2015-10-08 21:58   ` Stephen Boyd
  2015-10-05 19:09 ` Sjoerd Simons
  3 siblings, 1 reply; 12+ messages in thread
From: Heiko Stübner @ 2015-10-02 14:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

any comment on these 3 patches?

Thanks
Heiko

Am Freitag, 21. August 2015, 19:46:31 schrieb Heiko Stuebner:
> Some clocks need to be enabled to accept rate changes. This patch adds a
> new flag CLK_SET_RATE_UNGATE that lets clk_change_rate enable the clock
> before trying to change the rate and disable it again afterwards.
> This of course doesn't effect clocks that are already running at that
> point, as their refcount will only temporarily increase.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>  drivers/clk/clk.c            | 18 ++++++++++++++++++
>  include/linux/clk-provider.h |  1 +
>  2 files changed, 19 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 28cd923..564f11e 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1438,6 +1438,15 @@ static void clk_change_rate(struct clk_core *core)
>  	else if (core->parent)
>  		best_parent_rate = core->parent->rate;
> 
> +	if (core->flags & CLK_SET_RATE_UNGATE) {
> +		unsigned long flags;
> +
> +		clk_core_prepare(core);
> +		flags = clk_enable_lock();
> +		clk_core_enable(core);
> +		clk_enable_unlock(flags);
> +	}
> +
>  	if (core->new_parent && core->new_parent != core->parent) {
>  		old_parent = __clk_set_parent_before(core, core->new_parent);
>  		trace_clk_set_parent(core, core->new_parent);
> @@ -1464,6 +1473,15 @@ static void clk_change_rate(struct clk_core *core)
> 
>  	core->rate = clk_recalc(core, best_parent_rate);
> 
> +	if (core->flags & CLK_SET_RATE_UNGATE) {
> +		unsigned long flags;
> +
> +		flags = clk_enable_lock();
> +		clk_core_disable(core);
> +		clk_enable_unlock(flags);
> +		clk_core_unprepare(core);
> +	}
> +
>  	if (core->notifier_count && old_rate != core->rate)
>  		__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
> 
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 3ecc07d..21e0025 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -31,6 +31,7 @@
>  #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change
> */ #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk
> accuracy */ #define CLK_RECALC_NEW_RATES	BIT(9) /* recalc rates after
> notifications */ +#define CLK_SET_RATE_UNGATE	BIT(10) /* clock needs to run
> to set rate */
> 
>  struct clk;
>  struct clk_hw;

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

* [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes
  2015-08-21 17:46 [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stuebner
                   ` (2 preceding siblings ...)
  2015-10-02 14:12 ` [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stübner
@ 2015-10-05 19:09 ` Sjoerd Simons
  3 siblings, 0 replies; 12+ messages in thread
From: Sjoerd Simons @ 2015-10-05 19:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2015-08-21 at 19:46 +0200, Heiko Stuebner wrote:
> Some clocks need to be enabled to accept rate changes. This patch
> adds a
> new flag CLK_SET_RATE_UNGATE that lets clk_change_rate enable the
> clock
> before trying to change the rate and disable it again afterwards.
> This of course doesn't effect clocks that are already running at that
> point, as their refcount will only temporarily increase.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>

Tested-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>

> ---
>  drivers/clk/clk.c            | 18 ++++++++++++++++++
>  include/linux/clk-provider.h |  1 +
>  2 files changed, 19 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 28cd923..564f11e 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1438,6 +1438,15 @@ static void clk_change_rate(struct clk_core
> *core)
>  	else if (core->parent)
>  		best_parent_rate = core->parent->rate;
>  
> +	if (core->flags & CLK_SET_RATE_UNGATE) {
> +		unsigned long flags;
> +
> +		clk_core_prepare(core);
> +		flags = clk_enable_lock();
> +		clk_core_enable(core);
> +		clk_enable_unlock(flags);
> +	}
> +
>  	if (core->new_parent && core->new_parent != core->parent) {
>  		old_parent = __clk_set_parent_before(core, core
> ->new_parent);
>  		trace_clk_set_parent(core, core->new_parent);
> @@ -1464,6 +1473,15 @@ static void clk_change_rate(struct clk_core
> *core)
>  
>  	core->rate = clk_recalc(core, best_parent_rate);
>  
> +	if (core->flags & CLK_SET_RATE_UNGATE) {
> +		unsigned long flags;
> +
> +		flags = clk_enable_lock();
> +		clk_core_disable(core);
> +		clk_enable_unlock(flags);
> +		clk_core_unprepare(core);
> +	}
> +
>  	if (core->notifier_count && old_rate != core->rate)
>  		__clk_notify(core, POST_RATE_CHANGE, old_rate, core
> ->rate);
>  
> diff --git a/include/linux/clk-provider.h b/include/linux/clk
> -provider.h
> index 3ecc07d..21e0025 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -31,6 +31,7 @@
>  #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate
> change */
>  #define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk
> accuracy */
>  #define CLK_RECALC_NEW_RATES	BIT(9) /* recalc rates after
> notifications */
> +#define CLK_SET_RATE_UNGATE	BIT(10) /* clock needs to run to
> set rate */
>  
>  struct clk;
>  struct clk_hw;

-- 
Sjoerd Simons
Collabora Ltd.

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

* [PATCH 3/3] clk: rockchip: include downstream muxes into fractional dividers
  2015-08-21 17:48 ` [PATCH 3/3] clk: rockchip: include downstream muxes into " Heiko Stuebner
@ 2015-10-05 19:09   ` Sjoerd Simons
  2015-12-12  3:35   ` Caesar Wang
  1 sibling, 0 replies; 12+ messages in thread
From: Sjoerd Simons @ 2015-10-05 19:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2015-08-21 at 19:48 +0200, Heiko Stuebner wrote:
> Use the newly introduced possibility to combine the fractional
> dividers
> with their downstream muxes for all fractional dividers on currently
> supported Rockchip SoCs.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>

Tested-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>


> ---
>  drivers/clk/rockchip/clk-rk3188.c | 80 +++++++++++++++++++----------
> ----------
>  drivers/clk/rockchip/clk-rk3288.c | 66 ++++++++++++++++-------------
> ---
>  2 files changed, 74 insertions(+), 72 deletions(-)
> 
> diff --git a/drivers/clk/rockchip/clk-rk3188.c
> b/drivers/clk/rockchip/clk-rk3188.c
> index ed02bbc..faa6695 100644
> --- a/drivers/clk/rockchip/clk-rk3188.c
> +++ b/drivers/clk/rockchip/clk-rk3188.c
> @@ -335,11 +335,11 @@ static struct rockchip_clk_branch
> common_clk_branches[] __initdata = {
>  	COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
>  			RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8,
> DFLAGS,
>  			RK2928_CLKGATE_CON(2), 6, GFLAGS),
> -	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
> +	COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
>  			RK2928_CLKSEL_CON(23), 0,
> -			RK2928_CLKGATE_CON(2), 7, GFLAGS),
> -	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
> -			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(2), 7, GFLAGS,
> +		MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
> +				RK2928_CLKSEL_CON(22), 4, 2,
> MFLAGS)),
>  	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
>  			RK2928_CLKSEL_CON(22), 7, IFLAGS),
>  
> @@ -350,11 +350,11 @@ static struct rockchip_clk_branch
> common_clk_branches[] __initdata = {
>  	COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
>  			RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(0), 13, GFLAGS),
> -	COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre",
> CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pll",
> CLK_SET_RATE_PARENT,
>  			RK2928_CLKSEL_CON(9), 0,
> -			RK2928_CLKGATE_CON(0), 14, GFLAGS),
> -	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p,
> CLK_SET_RATE_PARENT,
> -			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 14, GFLAGS,
> +		MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p,
> CLK_SET_RATE_PARENT,
> +				RK2928_CLKSEL_CON(5), 8, 2,
> MFLAGS)),
>  
>  	/*
>  	 * Clock-Architecture Diagram 4
> @@ -385,35 +385,35 @@ static struct rockchip_clk_branch
> common_clk_branches[] __initdata = {
>  	COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
>  			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(1), 8, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
>  			RK2928_CLKSEL_CON(17), 0,
> -			RK2928_CLKGATE_CON(1), 9, GFLAGS),
> -	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
> -			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 9, GFLAGS,
> +		MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
> +				RK2928_CLKSEL_CON(13), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
>  			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(1), 10, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
>  			RK2928_CLKSEL_CON(18), 0,
> -			RK2928_CLKGATE_CON(1), 11, GFLAGS),
> -	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
> -			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 11, GFLAGS,
> +		MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
> +				RK2928_CLKSEL_CON(14), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
>  			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(1), 12, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
>  			RK2928_CLKSEL_CON(19), 0,
> -			RK2928_CLKGATE_CON(1), 13, GFLAGS),
> -	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
> -			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 13, GFLAGS,
> +		MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
> +				RK2928_CLKSEL_CON(15), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
>  			RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(1), 14, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
>  			RK2928_CLKSEL_CON(20), 0,
> -			RK2928_CLKGATE_CON(1), 15, GFLAGS),
> -	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
> -			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 15, GFLAGS,
> +		MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
> +				RK2928_CLKSEL_CON(16), 8, 2,
> MFLAGS)),
>  
>  	GATE(SCLK_JTAG, "jtag", "ext_jtag", 0,
> RK2928_CLKGATE_CON(1), 3, GFLAGS),
>  
> @@ -584,27 +584,27 @@ static struct rockchip_clk_branch
> rk3066a_clk_branches[] __initdata = {
>  	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
>  			RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(0), 7, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
>  			RK2928_CLKSEL_CON(6), 0,
> -			RK2928_CLKGATE_CON(0), 8, GFLAGS),
> -	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> -			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 8, GFLAGS,
> +		MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> +				RK2928_CLKSEL_CON(2), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
>  			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(0), 9, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
>  			RK2928_CLKSEL_CON(7), 0,
> -			RK2928_CLKGATE_CON(0), 10, GFLAGS),
> -	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
> -			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 10, GFLAGS,
> +		MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
> +				RK2928_CLKSEL_CON(3), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
>  			RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(0), 11, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
>  			RK2928_CLKSEL_CON(8), 0,
> -			RK2928_CLKGATE_CON(0), 12, GFLAGS),
> -	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
> -			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 12, GFLAGS,
> +		MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
> +				RK2928_CLKSEL_CON(4), 8, 2,
> MFLAGS)),
>  
>  	GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0,
> RK2928_CLKGATE_CON(7), 3, GFLAGS),
>  	GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0,
> RK2928_CLKGATE_CON(7), 4, GFLAGS),
> @@ -691,11 +691,11 @@ static struct rockchip_clk_branch
> rk3188_clk_branches[] __initdata = {
>  	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
>  			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
>  			RK2928_CLKGATE_CON(0), 9, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
>  			RK2928_CLKSEL_CON(7), 0,
> -			RK2928_CLKGATE_CON(0), 10, GFLAGS),
> -	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> -			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 10, GFLAGS,
> +		MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> +				RK2928_CLKSEL_CON(3), 8, 2,
> MFLAGS)),
>  
>  	GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4),
> 14, GFLAGS),
>  	GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4),
> 15, GFLAGS),
> diff --git a/drivers/clk/rockchip/clk-rk3288.c
> b/drivers/clk/rockchip/clk-rk3288.c
> index 0df5bae..18fcdb1 100644
> --- a/drivers/clk/rockchip/clk-rk3288.c
> +++ b/drivers/clk/rockchip/clk-rk3288.c
> @@ -304,11 +304,11 @@ static struct rockchip_clk_branch
> rk3288_clk_branches[] __initdata = {
>  	COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
>  			RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7,
> DFLAGS,
>  			RK3288_CLKGATE_CON(4), 1, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s_frac", "i2s_src",
> CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src",
> CLK_SET_RATE_PARENT,
>  			RK3288_CLKSEL_CON(8), 0,
> -			RK3288_CLKGATE_CON(4), 2, GFLAGS),
> -	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(4), 2, GFLAGS,
> +		MUX(0, "i2s_pre", mux_i2s_pre_p,
> CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(4), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout",
> mux_i2s_clkout_p, 0,
>  			RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
>  			RK3288_CLKGATE_CON(4), 0, GFLAGS),
> @@ -320,20 +320,22 @@ static struct rockchip_clk_branch
> rk3288_clk_branches[] __initdata = {
>  	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
>  			RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
>  			RK3288_CLKGATE_CON(4), 4, GFLAGS),
> -	COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
> +	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0,
>  			RK3288_CLKSEL_CON(9), 0,
> -			RK3288_CLKGATE_CON(4), 5, GFLAGS),
> -	COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
> -			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
> +			RK3288_CLKGATE_CON(4), 5, GFLAGS,
> +		MUX(0, "spdif_mux", mux_spdif_p, 0,
> +				RK3288_CLKSEL_CON(5), 8, 2,
> MFLAGS)),
> +	GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", 0,
>  			RK3288_CLKGATE_CON(4), 6, GFLAGS),
>  	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
>  			RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
>  			RK3288_CLKGATE_CON(4), 7, GFLAGS),
> -	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
> +	COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
>  			RK3288_CLKSEL_CON(41), 0,
> -			RK3288_CLKGATE_CON(4), 8, GFLAGS),
> -	COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch",
> mux_spdif_8ch_p, 0,
> -			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
> +			RK3288_CLKGATE_CON(4), 8, GFLAGS,
> +		MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, 0,
> +				RK3288_CLKSEL_CON(40), 8, 2,
> MFLAGS)),
> +	GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", 0,
>  			RK3288_CLKGATE_CON(4), 9, GFLAGS),
>  
>  	GATE(0, "sclk_acc_efuse", "xin24m", 0,
> @@ -536,45 +538,45 @@ static struct rockchip_clk_branch
> rk3288_clk_branches[] __initdata = {
>  	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p,
> 0,
>  			RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7,
> DFLAGS,
>  			RK3288_CLKGATE_CON(1), 8, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src",
> CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src",
> CLK_SET_RATE_PARENT,
>  			RK3288_CLKSEL_CON(17), 0,
> -			RK3288_CLKGATE_CON(1), 9, GFLAGS),
> -	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p,
> CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 9, GFLAGS,
> +		MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p,
> CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(13), 8, 2,
> MFLAGS)),
>  	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
>  			RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
>  	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
>  			RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
>  			RK3288_CLKGATE_CON(1), 10, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src",
> CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src",
> CLK_SET_RATE_PARENT,
>  			RK3288_CLKSEL_CON(18), 0,
> -			RK3288_CLKGATE_CON(1), 11, GFLAGS),
> -	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p,
> CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 11, GFLAGS,
> +		MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p,
> CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(14), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
>  			RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
>  			RK3288_CLKGATE_CON(1), 12, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src",
> CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src",
> CLK_SET_RATE_PARENT,
>  			RK3288_CLKSEL_CON(19), 0,
> -			RK3288_CLKGATE_CON(1), 13, GFLAGS),
> -	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p,
> CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 13, GFLAGS,
> +		MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p,
> CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(15), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
>  			RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
>  			RK3288_CLKGATE_CON(1), 14, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src",
> CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src",
> CLK_SET_RATE_PARENT,
>  			RK3288_CLKSEL_CON(20), 0,
> -			RK3288_CLKGATE_CON(1), 15, GFLAGS),
> -	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p,
> CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 15, GFLAGS,
> +		MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p,
> CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(16), 8, 2,
> MFLAGS)),
>  	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
>  			RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
>  			RK3288_CLKGATE_CON(2), 12, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src",
> CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src",
> CLK_SET_RATE_PARENT,
>  			RK3288_CLKSEL_CON(7), 0,
> -			RK3288_CLKGATE_CON(2), 13, GFLAGS),
> -	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p,
> CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(2), 13, GFLAGS,
> +		MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p,
> CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(3), 8, 2,
> MFLAGS)),
>  
>  	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
>  			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5,
> DFLAGS,

-- 
Sjoerd Simons
Collabora Ltd.

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

* [PATCH 2/3] clk: rockchip: handle mux dependency of fractional dividers
  2015-08-21 17:47 ` [PATCH 2/3] clk: rockchip: handle mux dependency of fractional dividers Heiko Stuebner
@ 2015-10-05 19:09   ` Sjoerd Simons
  0 siblings, 0 replies; 12+ messages in thread
From: Sjoerd Simons @ 2015-10-05 19:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2015-08-21 at 19:47 +0200, Heiko Stuebner wrote:
> The fractional dividers of Rockchip SoCs contain an "auto-gating
> -feature"
> that requires the downstream mux to actually point to the fractional
> divider and the fractional divider gate to be enabled, for it to
> really
> accept changes to the divider ratio.
> 
> The downstream muxes themselfs are not generic enough to include them
> directly into the fractional divider, as they have varying sources of
> parent clocks including not only clocks related to the fractional
> dividers but other clocks as well.
> 
> To solve this, allow our clock branches to specify direct child clock
> -
> branches in the new child property, let the fractional divider
> register
> its downstream mux through this and add a clock notifier that
> temporarily
> switches the mux setting when it notices rate changes to the
> fractional
> divider.
> 
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>

Tested-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>
Reviewed-by: Sjoerd Simons <sjoerd.simons@collabora.co.uk>


>  drivers/clk/rockchip/clk.c | 137
> ++++++++++++++++++++++++++++++++++++++++-----
>  drivers/clk/rockchip/clk.h |  19 +++++++
>  2 files changed, 142 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
> index 2493881..8c7fd2b 100644
> --- a/drivers/clk/rockchip/clk.c
> +++ b/drivers/clk/rockchip/clk.c
> @@ -102,22 +102,82 @@ static struct clk
> *rockchip_clk_register_branch(const char *name,
>  	return clk;
>  }
>  
> +struct rockchip_clk_frac {
> +	struct notifier_block			clk_nb;
> +	struct clk_fractional_divider		div;
> +	struct clk_gate				gate;
> +
> +	struct clk_mux				mux;
> +	const struct clk_ops			*mux_ops;
> +	int					mux_frac_idx;
> +
> +	bool					rate_change_remu
> xed;
> +	int					rate_change_idx;
> +};
> +
> +#define to_rockchip_clk_frac_nb(nb) \
> +			container_of(nb, struct rockchip_clk_frac,
> clk_nb)
> +
> +static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
> +					 unsigned long event, void
> *data)
> +{
> +	struct clk_notifier_data *ndata = data;
> +	struct rockchip_clk_frac *frac =
> to_rockchip_clk_frac_nb(nb);
> +	struct clk_mux *frac_mux = &frac->mux;
> +	int ret = 0;
> +
> +	pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
> +		 __func__, event, ndata->old_rate, ndata->new_rate);
> +	if (event == PRE_RATE_CHANGE) {
> +		frac->rate_change_idx = frac->mux_ops
> ->get_parent(&frac_mux->hw);
> +		if (frac->rate_change_idx != frac->mux_frac_idx) {
> +			frac->mux_ops->set_parent(&frac_mux->hw,
> frac->mux_frac_idx);
> +			frac->rate_change_remuxed = 1;
> +		}
> +	} else if (event == POST_RATE_CHANGE) {
> +		/*
> +		 * The POST_RATE_CHANGE notifier runs directly after
> the
> +		 * divider clock is set in clk_change_rate, so we'll
> have
> +		 * remuxed back to the original parent before
> clk_change_rate
> +		 * reaches the mux itself.
> +		 */
> +		if (frac->rate_change_remuxed) {
> +			frac->mux_ops->set_parent(&frac_mux->hw,
> frac->rate_change_idx);
> +			frac->rate_change_remuxed = 0;
> +		}
> +	}
> +
> +	return notifier_from_errno(ret);
> +}
> +
>  static struct clk *rockchip_clk_register_frac_branch(const char
> *name,
>  		const char *const *parent_names, u8 num_parents,
>  		void __iomem *base, int muxdiv_offset, u8 div_flags,
>  		int gate_offset, u8 gate_shift, u8 gate_flags,
> -		unsigned long flags, spinlock_t *lock)
> +		unsigned long flags, struct rockchip_clk_branch
> *child,
> +		spinlock_t *lock)
>  {
> +	struct rockchip_clk_frac *frac;
>  	struct clk *clk;
>  	struct clk_gate *gate = NULL;
>  	struct clk_fractional_divider *div = NULL;
>  	const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
>  
> -	if (gate_offset >= 0) {
> -		gate = kzalloc(sizeof(*gate), GFP_KERNEL);
> -		if (!gate)
> -			return ERR_PTR(-ENOMEM);
> +	if (muxdiv_offset < 0)
> +		return ERR_PTR(-EINVAL);
>  
> +	if (child && child->branch_type != branch_mux) {
> +		pr_err("%s: fractional child clock for %s can only
> be a mux\n",
> +		       __func__, name);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
> +	if (!frac)
> +		return ERR_PTR(-ENOMEM);
> +
> +	if (gate_offset >= 0) {
> +		gate = &frac->gate;
>  		gate->flags = gate_flags;
>  		gate->reg = base + gate_offset;
>  		gate->bit_idx = gate_shift;
> @@ -125,13 +185,7 @@ static struct clk
> *rockchip_clk_register_frac_branch(const char *name,
>  		gate_ops = &clk_gate_ops;
>  	}
>  
> -	if (muxdiv_offset < 0)
> -		return ERR_PTR(-EINVAL);
> -
> -	div = kzalloc(sizeof(*div), GFP_KERNEL);
> -	if (!div)
> -		return ERR_PTR(-ENOMEM);
> -
> +	div = &frac->div;
>  	div->flags = div_flags;
>  	div->reg = base + muxdiv_offset;
>  	div->mshift = 16;
> @@ -145,7 +199,61 @@ static struct clk
> *rockchip_clk_register_frac_branch(const char *name,
>  				     NULL, NULL,
>  				     &div->hw, div_ops,
>  				     gate ? &gate->hw : NULL,
> gate_ops,
> -				     flags);
> +				     flags | CLK_SET_RATE_UNGATE);
> +	if (IS_ERR(clk)) {
> +		kfree(frac);
> +		return clk;
> +	}
> +
> +	if (child) {
> +		struct clk_mux *frac_mux = &frac->mux;
> +		struct clk_init_data init;
> +		struct clk *mux_clk;
> +		int i, ret;
> +
> +		frac->mux_frac_idx = -1;
> +		for (i = 0; i < child->num_parents; i++) {
> +			if (!strcmp(name, child->parent_names[i])) {
> +				pr_debug("%s: found fractional
> parent in mux at pos %d\n",
> +					 __func__, i);
> +				frac->mux_frac_idx = i;
> +				break;
> +			}
> +		}
> +
> +		frac->mux_ops = &clk_mux_ops;
> +		frac->clk_nb.notifier_call =
> rockchip_clk_frac_notifier_cb;
> +
> +		frac_mux->reg = base + child->muxdiv_offset;
> +		frac_mux->shift = child->mux_shift;
> +		frac_mux->mask = BIT(child->mux_width) - 1;
> +		frac_mux->flags = child->mux_flags;
> +		frac_mux->lock = lock;
> +		frac_mux->hw.init = &init;
> +
> +		init.name = child->name;
> +		init.flags = child->flags | CLK_SET_RATE_PARENT;
> +		init.ops = frac->mux_ops;
> +		init.parent_names = child->parent_names;
> +		init.num_parents = child->num_parents;
> +
> +		mux_clk = clk_register(NULL, &frac_mux->hw);
> +		if (IS_ERR(mux_clk))
> +			return clk;
> +
> +		rockchip_clk_add_lookup(mux_clk, child->id);
> +
> +		/* notifier on the fraction divider to catch rate
> changes */
> +		if (frac->mux_frac_idx >= 0) {
> +			ret = clk_notifier_register(clk, &frac
> ->clk_nb);
> +			if (ret)
> +				pr_err("%s: failed to register clock
> notifier for %s\n",
> +						__func__, name);
> +		} else {
> +			pr_warn("%s: could not find %s as parent of
> %s, rate changes may not work\n",
> +				__func__, name, child->name);
> +		}
> +	}
>  
>  	return clk;
>  }
> @@ -249,7 +357,8 @@ void __init rockchip_clk_register_branches(
>  				list->parent_names, list
> ->num_parents,
>  				reg_base, list->muxdiv_offset, list
> ->div_flags,
>  				list->gate_offset, list->gate_shift,
> -				list->gate_flags, flags, &clk_lock);
> +				list->gate_flags, flags, list
> ->child,
> +				&clk_lock);
>  			break;
>  		case branch_gate:
>  			flags |= CLK_SET_RATE_PARENT;
> diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
> index dc8ecb2..147db79 100644
> --- a/drivers/clk/rockchip/clk.h
> +++ b/drivers/clk/rockchip/clk.h
> @@ -235,6 +235,7 @@ struct rockchip_clk_branch {
>  	int				gate_offset;
>  	u8				gate_shift;
>  	u8				gate_flags;
> +	struct rockchip_clk_branch	*child;
>  };
>  
>  #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
> @@ -369,6 +370,24 @@ struct rockchip_clk_branch {
>  		.gate_flags	= gf,				
> \
>  	}
>  
> +#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf,
> ch) \
> +	{							\
> +		.id		= _id,				
> \
> +		.branch_type	= branch_fraction_divider,	
> \
> +		.name		= cname,			
> \
> +		.parent_names	= (const char *[]){ pname },	
> \
> +		.num_parents	= 1,				
> \
> +		.flags		= f,				
> \
> +		.muxdiv_offset	= mo,				
> \
> +		.div_shift	= 16,				
> \
> +		.div_width	= 16,				
> \
> +		.div_flags	= df,				
> \
> +		.gate_offset	= go,				
> \
> +		.gate_shift	= gs,				
> \
> +		.gate_flags	= gf,				
> \
> +		.child		= &(struct
> rockchip_clk_branch)ch, \
> +	}
> +
>  #define MUX(_id, cname, pnames, f, o, s, w, mf)			
> \
>  	{							\
>  		.id		= _id,				
> \

-- 
Sjoerd Simons
Collabora Ltd.

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

* [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes
  2015-10-02 14:12 ` [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stübner
@ 2015-10-08 21:58   ` Stephen Boyd
  2015-10-11 10:41     ` Heiko Stübner
  0 siblings, 1 reply; 12+ messages in thread
From: Stephen Boyd @ 2015-10-08 21:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/02, Heiko St?bner wrote:
> Hi,
> 
> any comment on these 3 patches?
> 

Dong has a similar problem, but those patches conflate this with
enabling parent clocks during clk_disable_unused() which makes no
sense to me. So I'm ok with the requirement that we turn clocks
on to change rates, but I wonder if in this case we need to turn
on the clock that's changing rates itself, or if we just need to
turn on the parent and/or future parent of the clock during the
rate switch. Care to elaborate on that?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

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

* [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes
  2015-10-08 21:58   ` Stephen Boyd
@ 2015-10-11 10:41     ` Heiko Stübner
  2015-10-12 16:03       ` Heiko Stübner
  0 siblings, 1 reply; 12+ messages in thread
From: Heiko Stübner @ 2015-10-11 10:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Stephen,

Am Donnerstag, 8. Oktober 2015, 14:58:40 schrieb Stephen Boyd:
> On 10/02, Heiko St?bner wrote:
> > Hi,
> > 
> > any comment on these 3 patches?
> 
> Dong has a similar problem, but those patches conflate this with
> enabling parent clocks during clk_disable_unused() which makes no
> sense to me. So I'm ok with the requirement that we turn clocks
> on to change rates, but I wonder if in this case we need to turn
> on the clock that's changing rates itself, or if we just need to
> turn on the parent and/or future parent of the clock during the
> rate switch. Care to elaborate on that?

As you can see in the follow-up patches, the fractional dividers on Rockchip 
SoCs are quite strange in that they even need to have their _downstream_ mux 
point to them to actually accept rate changes.

The register value always reflects the value set by the system, but hardware 
really only accepts it if the clock is enabled and even the downstream mux 
selects the fractional divider as parent (they call it a auto-gating feature).

So in the worst (and current) case, you end up with the register showing the 
right value, but the hardware can use completely different dividers from the 
previous setting.

That strange behaviour got quite deeply investigated between Rockchip and 
Google engineers who stumbled upon this in the first place, so I'm reasonably 
sure this is the right solution for that clock type :-) .


Heiko

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

* [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes
  2015-10-11 10:41     ` Heiko Stübner
@ 2015-10-12 16:03       ` Heiko Stübner
  2015-10-13  3:34         ` Xing Zheng
  0 siblings, 1 reply; 12+ messages in thread
From: Heiko Stübner @ 2015-10-12 16:03 UTC (permalink / raw)
  To: linux-arm-kernel

Am Sonntag, 11. Oktober 2015, 12:41:09 schrieb Heiko St?bner:
> Hi Stephen,
> 
> Am Donnerstag, 8. Oktober 2015, 14:58:40 schrieb Stephen Boyd:
> > On 10/02, Heiko St?bner wrote:
> > > Hi,
> > > 
> > > any comment on these 3 patches?
> > 
> > Dong has a similar problem, but those patches conflate this with
> > enabling parent clocks during clk_disable_unused() which makes no
> > sense to me. So I'm ok with the requirement that we turn clocks
> > on to change rates, but I wonder if in this case we need to turn
> > on the clock that's changing rates itself, or if we just need to
> > turn on the parent and/or future parent of the clock during the
> > rate switch. Care to elaborate on that?
> 
> As you can see in the follow-up patches, the fractional dividers on Rockchip
> SoCs are quite strange in that they even need to have their _downstream_
> mux point to them to actually accept rate changes.
> 
> The register value always reflects the value set by the system, but hardware
> really only accepts it if the clock is enabled and even the downstream mux
> selects the fractional divider as parent (they call it a auto-gating
> feature).
> 
> So in the worst (and current) case, you end up with the register showing the
> right value, but the hardware can use completely different dividers from
> the previous setting.
> 
> That strange behaviour got quite deeply investigated between Rockchip and
> Google engineers who stumbled upon this in the first place, so I'm
> reasonably sure this is the right solution for that clock type :-) .

Xing Zheng now also independently stumbled upon this issue with his rk3036 
work. And came to the same conclusion that the gate must be enabled as well as 
the downstream mux be set to the fractional divider for it to actually accept 
a new setting.

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

* [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes
  2015-10-12 16:03       ` Heiko Stübner
@ 2015-10-13  3:34         ` Xing Zheng
  0 siblings, 0 replies; 12+ messages in thread
From: Xing Zheng @ 2015-10-13  3:34 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 2015?10?13? 00:03, Heiko St?bner wrote:
> Am Sonntag, 11. Oktober 2015, 12:41:09 schrieb Heiko St?bner:
>> Hi Stephen,
>>
>> Am Donnerstag, 8. Oktober 2015, 14:58:40 schrieb Stephen Boyd:
>>> On 10/02, Heiko St?bner wrote:
>>>> Hi,
>>>>
>>>> any comment on these 3 patches?
>>> Dong has a similar problem, but those patches conflate this with
>>> enabling parent clocks during clk_disable_unused() which makes no
>>> sense to me. So I'm ok with the requirement that we turn clocks
>>> on to change rates, but I wonder if in this case we need to turn
>>> on the clock that's changing rates itself, or if we just need to
>>> turn on the parent and/or future parent of the clock during the
>>> rate switch. Care to elaborate on that?
>> As you can see in the follow-up patches, the fractional dividers on Rockchip
>> SoCs are quite strange in that they even need to have their _downstream_
>> mux point to them to actually accept rate changes.
>>
>> The register value always reflects the value set by the system, but hardware
>> really only accepts it if the clock is enabled and even the downstream mux
>> selects the fractional divider as parent (they call it a auto-gating
>> feature).
>>
>> So in the worst (and current) case, you end up with the register showing the
>> right value, but the hardware can use completely different dividers from
>> the previous setting.
>>
>> That strange behaviour got quite deeply investigated between Rockchip and
>> Google engineers who stumbled upon this in the first place, so I'm
>> reasonably sure this is the right solution for that clock type :-) .
> Xing Zheng now also independently stumbled upon this issue with his rk3036
> work. And came to the same conclusion that the gate must be enabled as well as
> the downstream mux be set to the fractional divider for it to actually accept
> a new setting.
Yes, I discussed such problems with Heiko about the question:
The RK3036 i2s frac(CRU_SEL7_CON) set value is invalid when I playback a 
48KHz music:
/ # io -4 0x20000060
20000060: 01003057
read register is 0x01003057, but the result of frac divider on the basis 
of default 0x0bb8ea60(numerator=3000, denominator=60000, ratio=20), so 
the out of mclk remains 594/20=29.7MHz

I tracked the logs:
[ 49.770322] clk_fd_set_rate: 91, name: i2s_frac, rate = 12288000, 
parent_rate = 594000000
[ 49.778524] clk_fd_set_rate: 107, name: i2s_frac, val = 0x01003057
[ 49.784714] clk_fd_recalc_rate: 29, name: i2s_frac, parent_rate = 594000000
[ 49.791707] clk_fd_recalc_rate: 47, name: i2s_frac, val = 0x01003057, m 
= 256, n = 12375
[ 49.799836] clk_mux_set_parent: 81, name: i2s_pre
It seem like set i2s_frac_div then set mux is i2s_pre. I think we should 
select the correct mux and open clock gate, then set the i2s_frac_div, 
and I tried to do it, setting i2s_frac_div is vaild and mclk is 
12.288MHz. Therefore, I think that select parent mux and enable gate 
should before child node set value.

Thanks. :)

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

* [PATCH 3/3] clk: rockchip: include downstream muxes into fractional dividers
  2015-08-21 17:48 ` [PATCH 3/3] clk: rockchip: include downstream muxes into " Heiko Stuebner
  2015-10-05 19:09   ` Sjoerd Simons
@ 2015-12-12  3:35   ` Caesar Wang
  1 sibling, 0 replies; 12+ messages in thread
From: Caesar Wang @ 2015-12-12  3:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Heiko,

There are any chance to add the RK3036 SoCs for muxes into fractional 
dividers?
As the attachment for my test patchs. (fetch from 
https://github.com/rockchip-linux/kernel -b develop-v4.1)

I have fetch this series pacthes for my Kylin board.

Anyway, I will send the patch for RK3036 if this patch has merged into 
mainline.

? 2015?08?22? 01:48, Heiko Stuebner ??:
> Use the newly introduced possibility to combine the fractional dividers
> with their downstream muxes for all fractional dividers on currently
> supported Rockchip SoCs.
>
> Signed-off-by: Heiko Stuebner <heiko@sntech.de>
> ---
>   drivers/clk/rockchip/clk-rk3188.c | 80 +++++++++++++++++++--------------------
>   drivers/clk/rockchip/clk-rk3288.c | 66 ++++++++++++++++----------------
>   2 files changed, 74 insertions(+), 72 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c
> index ed02bbc..faa6695 100644
> --- a/drivers/clk/rockchip/clk-rk3188.c
> +++ b/drivers/clk/rockchip/clk-rk3188.c
> @@ -335,11 +335,11 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
>   	COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
>   			RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
>   			RK2928_CLKGATE_CON(2), 6, GFLAGS),
> -	COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
> +	COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
>   			RK2928_CLKSEL_CON(23), 0,
> -			RK2928_CLKGATE_CON(2), 7, GFLAGS),
> -	MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
> -			RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(2), 7, GFLAGS,
> +		MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
> +				RK2928_CLKSEL_CON(22), 4, 2, MFLAGS)),
>   	INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
>   			RK2928_CLKSEL_CON(22), 7, IFLAGS),
>   
> @@ -350,11 +350,11 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
>   	COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
>   			RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(0), 13, GFLAGS),
> -	COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pll", CLK_SET_RATE_PARENT,
>   			RK2928_CLKSEL_CON(9), 0,
> -			RK2928_CLKGATE_CON(0), 14, GFLAGS),
> -	MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
> -			RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 14, GFLAGS,
> +		MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
> +				RK2928_CLKSEL_CON(5), 8, 2, MFLAGS)),
>   
>   	/*
>   	 * Clock-Architecture Diagram 4
> @@ -385,35 +385,35 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
>   	COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
>   			RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(1), 8, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
>   			RK2928_CLKSEL_CON(17), 0,
> -			RK2928_CLKGATE_CON(1), 9, GFLAGS),
> -	MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
> -			RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 9, GFLAGS,
> +		MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
> +				RK2928_CLKSEL_CON(13), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
>   			RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(1), 10, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
>   			RK2928_CLKSEL_CON(18), 0,
> -			RK2928_CLKGATE_CON(1), 11, GFLAGS),
> -	MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
> -			RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 11, GFLAGS,
> +		MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
> +				RK2928_CLKSEL_CON(14), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
>   			RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(1), 12, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
>   			RK2928_CLKSEL_CON(19), 0,
> -			RK2928_CLKGATE_CON(1), 13, GFLAGS),
> -	MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
> -			RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 13, GFLAGS,
> +		MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
> +				RK2928_CLKSEL_CON(15), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
>   			RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(1), 14, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
> +	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
>   			RK2928_CLKSEL_CON(20), 0,
> -			RK2928_CLKGATE_CON(1), 15, GFLAGS),
> -	MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
> -			RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(1), 15, GFLAGS,
> +		MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
> +				RK2928_CLKSEL_CON(16), 8, 2, MFLAGS)),
>   
>   	GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
>   
> @@ -584,27 +584,27 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
>   	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
>   			RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(0), 7, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
>   			RK2928_CLKSEL_CON(6), 0,
> -			RK2928_CLKGATE_CON(0), 8, GFLAGS),
> -	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> -			RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 8, GFLAGS,
> +		MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> +				RK2928_CLKSEL_CON(2), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
>   			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(0), 9, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
>   			RK2928_CLKSEL_CON(7), 0,
> -			RK2928_CLKGATE_CON(0), 10, GFLAGS),
> -	MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
> -			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 10, GFLAGS,
> +		MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
> +				RK2928_CLKSEL_CON(3), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
>   			RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(0), 11, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
>   			RK2928_CLKSEL_CON(8), 0,
> -			RK2928_CLKGATE_CON(0), 12, GFLAGS),
> -	MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
> -			RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 12, GFLAGS,
> +		MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
> +				RK2928_CLKSEL_CON(4), 8, 2, MFLAGS)),
>   
>   	GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
>   	GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
> @@ -691,11 +691,11 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
>   	COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
>   			RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
>   			RK2928_CLKGATE_CON(0), 9, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
> +	COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
>   			RK2928_CLKSEL_CON(7), 0,
> -			RK2928_CLKGATE_CON(0), 10, GFLAGS),
> -	MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> -			RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
> +			RK2928_CLKGATE_CON(0), 10, GFLAGS,
> +		MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
> +				RK2928_CLKSEL_CON(3), 8, 2, MFLAGS)),
>   
>   	GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
>   	GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
> diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c
> index 0df5bae..18fcdb1 100644
> --- a/drivers/clk/rockchip/clk-rk3288.c
> +++ b/drivers/clk/rockchip/clk-rk3288.c
> @@ -304,11 +304,11 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
>   	COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
>   			RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(4), 1, GFLAGS),
> -	COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
>   			RK3288_CLKSEL_CON(8), 0,
> -			RK3288_CLKGATE_CON(4), 2, GFLAGS),
> -	MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(4), 2, GFLAGS,
> +		MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(4), 8, 2, MFLAGS)),
>   	COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
>   			RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
>   			RK3288_CLKGATE_CON(4), 0, GFLAGS),
> @@ -320,20 +320,22 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
>   	COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
>   			RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(4), 4, GFLAGS),
> -	COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
> +	COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0,
>   			RK3288_CLKSEL_CON(9), 0,
> -			RK3288_CLKGATE_CON(4), 5, GFLAGS),
> -	COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
> -			RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
> +			RK3288_CLKGATE_CON(4), 5, GFLAGS,
> +		MUX(0, "spdif_mux", mux_spdif_p, 0,
> +				RK3288_CLKSEL_CON(5), 8, 2, MFLAGS)),
> +	GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", 0,
>   			RK3288_CLKGATE_CON(4), 6, GFLAGS),
>   	COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
>   			RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(4), 7, GFLAGS),
> -	COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
> +	COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
>   			RK3288_CLKSEL_CON(41), 0,
> -			RK3288_CLKGATE_CON(4), 8, GFLAGS),
> -	COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
> -			RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
> +			RK3288_CLKGATE_CON(4), 8, GFLAGS,
> +		MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, 0,
> +				RK3288_CLKSEL_CON(40), 8, 2, MFLAGS)),
> +	GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", 0,
>   			RK3288_CLKGATE_CON(4), 9, GFLAGS),
>   
>   	GATE(0, "sclk_acc_efuse", "xin24m", 0,
> @@ -536,45 +538,45 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
>   	COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0,
>   			RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(1), 8, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
>   			RK3288_CLKSEL_CON(17), 0,
> -			RK3288_CLKGATE_CON(1), 9, GFLAGS),
> -	MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 9, GFLAGS,
> +		MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(13), 8, 2, MFLAGS)),
>   	MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
>   			RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
>   	COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
>   			RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(1), 10, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
>   			RK3288_CLKSEL_CON(18), 0,
> -			RK3288_CLKGATE_CON(1), 11, GFLAGS),
> -	MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 11, GFLAGS,
> +		MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(14), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
>   			RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(1), 12, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
>   			RK3288_CLKSEL_CON(19), 0,
> -			RK3288_CLKGATE_CON(1), 13, GFLAGS),
> -	MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 13, GFLAGS,
> +		MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(15), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
>   			RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(1), 14, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
>   			RK3288_CLKSEL_CON(20), 0,
> -			RK3288_CLKGATE_CON(1), 15, GFLAGS),
> -	MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(1), 15, GFLAGS,
> +		MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(16), 8, 2, MFLAGS)),
>   	COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
>   			RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
>   			RK3288_CLKGATE_CON(2), 12, GFLAGS),
> -	COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
> +	COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
>   			RK3288_CLKSEL_CON(7), 0,
> -			RK3288_CLKGATE_CON(2), 13, GFLAGS),
> -	MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
> -			RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
> +			RK3288_CLKGATE_CON(2), 13, GFLAGS,
> +		MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
> +				RK3288_CLKSEL_CON(3), 8, 2, MFLAGS)),
>   
>   	COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
>   			RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,


-- 
caesar wang | software engineer | wxt at rock-chip.com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-clk-rockchip-include-downstream-muxes-into-fractiona.patch
Type: text/x-patch
Size: 9718 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20151212/fb67e321/attachment.bin>

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

end of thread, other threads:[~2015-12-12  3:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-21 17:46 [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stuebner
2015-08-21 17:47 ` [PATCH 2/3] clk: rockchip: handle mux dependency of fractional dividers Heiko Stuebner
2015-10-05 19:09   ` Sjoerd Simons
2015-08-21 17:48 ` [PATCH 3/3] clk: rockchip: include downstream muxes into " Heiko Stuebner
2015-10-05 19:09   ` Sjoerd Simons
2015-12-12  3:35   ` Caesar Wang
2015-10-02 14:12 ` [PATCH 1/3] clk: add flag for clocks that need to be enabled on rate changes Heiko Stübner
2015-10-08 21:58   ` Stephen Boyd
2015-10-11 10:41     ` Heiko Stübner
2015-10-12 16:03       ` Heiko Stübner
2015-10-13  3:34         ` Xing Zheng
2015-10-05 19:09 ` Sjoerd Simons

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