From ad11a1286b9b5ac52cb83b7b4db8c7d27db9f182 Mon Sep 17 00:00:00 2001 From: dkl <dkl@rock-chips.com> Date: Thu, 24 Apr 2014 09:30:12 +0800 Subject: [PATCH] clk: rockchip: add CLK_SET_RATE_PARENT_IN_ORDER If the flag CLK_SET_RATE_PARENT_IN_ORDER is set, consider the order of .set_parent and .set_rate, to prevent a too large temporary rate on rate change. This will fix the bug of clk_gpu in rk3288. --- arch/arm/boot/dts/rk3288-clocks.dtsi | 1 + drivers/clk/clk.c | 13 +++++++++++-- include/dt-bindings/clock/rockchip.h | 4 ++++ include/linux/clk-provider.h | 3 +++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-clocks.dtsi b/arch/arm/boot/dts/rk3288-clocks.dtsi index f3e007fe34d3..1649d729f81f 100755 --- a/arch/arm/boot/dts/rk3288-clocks.dtsi +++ b/arch/arm/boot/dts/rk3288-clocks.dtsi @@ -1732,6 +1732,7 @@ #clock-cells = <0>; rockchip,clkops-idx = <CLKOPS_RATE_MUX_DIV>; + rockchip,flags = <CLK_SET_RATE_PARENT_IN_ORDER>; }; /* reg[5]: reserved */ diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2cf2ea6b77a1..251c10b63c41 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1374,14 +1374,23 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even static void clk_change_rate(struct clk *clk) { struct clk *child; - unsigned long old_rate; + unsigned long old_rate, tmp_rate; unsigned long best_parent_rate = 0; old_rate = clk->rate; /* set parent */ - if (clk->new_parent && clk->new_parent != clk->parent) + if (clk->new_parent && clk->new_parent != clk->parent) { + if (clk->flags & CLK_SET_RATE_PARENT_IN_ORDER) { + tmp_rate = clk->ops->recalc_rate(clk->hw, clk->new_parent->rate); + if ((tmp_rate > clk->rate) && (tmp_rate > clk->new_rate)) { + if (clk->ops->set_rate) + clk->ops->set_rate(clk->hw, clk->new_rate, clk->new_parent->rate); + } + } + __clk_set_parent(clk, clk->new_parent, clk->new_parent_index); + } if (clk->parent) best_parent_rate = clk->parent->rate; diff --git a/include/dt-bindings/clock/rockchip.h b/include/dt-bindings/clock/rockchip.h index c216a0e9c109..ffd38921c4b0 100644 --- a/include/dt-bindings/clock/rockchip.h +++ b/include/dt-bindings/clock/rockchip.h @@ -28,6 +28,10 @@ #define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ +#define CLK_SET_RATE_PARENT_IN_ORDER BIT(8) /* consider the order of re-parent + and set_div on rate change */ + + /* Rockchip pll flags */ #define CLK_PLL_3188 BIT(0) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index dce14cd2a410..6ee9fbf109ef 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -28,6 +28,9 @@ #define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ #define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ #define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ +#define CLK_SET_RATE_PARENT_IN_ORDER BIT(8) /* consider the order of re-parent + and set_div on rate change */ + struct clk_hw; -- 2.34.1