aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-12-10 04:51:42 -0500
committerShawn Guo <shawn.guo@linaro.org>2015-01-05 07:53:05 -0500
commit3d27bc5c313ef9f953d1a8eb6927307cdda3aa52 (patch)
treee9dc9793730643de99f306b70a47c40a3cca3589 /arch/arm/mach-imx
parent60ad8467c1bf0cae19ccc9d142914a2288ac85e7 (diff)
ARM: imx: correct the hardware clock gate setting for shared nodes
For those clk gates which hold share count, since its is_enabled callback is only checking the share count rather than reading the hardware register setting, in the late phase of kernel bootup, the clk_disable_unused action will NOT handle the scenario of share_count is 0 but the hardware setting is enabled, actually, U-Boot normally enables all clk gates, then those shared clk gates will be always enabled until they are used by some modules. So the problem would be: when kernel boot up, the usecount cat from clk tree is 0, but the clk gates actually is enabled in hardware register, it will confuse user and bring unnecessary power consumption. This patch adds .disable_unused callback and using hardware register check for .is_enabled callback of shared nodes to handle such scenario in late phase of kernel boot up, then the hardware status will match the clk tree info. Signed-off-by: Anson Huang <b20788@freescale.com> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/clk-gate2.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
index 5a75cdc81891..8935bff99fe7 100644
--- a/arch/arm/mach-imx/clk-gate2.c
+++ b/arch/arm/mach-imx/clk-gate2.c
@@ -96,15 +96,30 @@ static int clk_gate2_is_enabled(struct clk_hw *hw)
96{ 96{
97 struct clk_gate2 *gate = to_clk_gate2(hw); 97 struct clk_gate2 *gate = to_clk_gate2(hw);
98 98
99 if (gate->share_count) 99 return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
100 return !!__clk_get_enable_count(hw->clk); 100}
101 else 101
102 return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx); 102static void clk_gate2_disable_unused(struct clk_hw *hw)
103{
104 struct clk_gate2 *gate = to_clk_gate2(hw);
105 unsigned long flags = 0;
106 u32 reg;
107
108 spin_lock_irqsave(gate->lock, flags);
109
110 if (!gate->share_count || *gate->share_count == 0) {
111 reg = readl(gate->reg);
112 reg &= ~(3 << gate->bit_idx);
113 writel(reg, gate->reg);
114 }
115
116 spin_unlock_irqrestore(gate->lock, flags);
103} 117}
104 118
105static struct clk_ops clk_gate2_ops = { 119static struct clk_ops clk_gate2_ops = {
106 .enable = clk_gate2_enable, 120 .enable = clk_gate2_enable,
107 .disable = clk_gate2_disable, 121 .disable = clk_gate2_disable,
122 .disable_unused = clk_gate2_disable_unused,
108 .is_enabled = clk_gate2_is_enabled, 123 .is_enabled = clk_gate2_is_enabled,
109}; 124};
110 125