From: dkl Date: Thu, 24 Apr 2014 01:30:12 +0000 (+0800) Subject: clk: rockchip: add CLK_SET_RATE_PARENT_IN_ORDER X-Git-Tag: firefly_0821_release~5414 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ad11a1286b9b5ac52cb83b7b4db8c7d27db9f182;p=firefly-linux-kernel-4.4.55.git 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. --- 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 = ; + rockchip,flags = ; }; /* 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;