[PATCH V3] arm: imx: correct the hardware clock gate setting for shared nodes

Stefan Agner stefan at agner.ch
Wed Dec 10 13:33:22 PST 2014


On 2014-12-10 22:24, Stefan Agner wrote:
> On 2014-12-10 10:51, Anson Huang wrote:
>> 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.
> 
> Wow, this is one long sentence! :-) Could you split that up and simplify
> it a bit? Especially the "hold share count" part confused me at first, I
> thought you mean *share_count > 0, but you actually ment share_count !=
> NULL (maybe "clk gates which have share count allocated").
> 
>>
>> 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 at freescale.com>
>> ---
>> changes from V2:
>> 	1. uboot -> U-Boot;
>> 	2. add .is_enabled change into commit log;
>> 	3. improve the condition check code.
>>  arch/arm/mach-imx/clk-gate2.c |   23 +++++++++++++++++++----
>>  1 file changed, 19 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
>> index 5a75cdc..8935bff 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)
>>  {
>>  	struct clk_gate2 *gate = to_clk_gate2(hw);
>>
>> -	if (gate->share_count)
>> -		return !!__clk_get_enable_count(hw->clk);
>> -	else
>> -		return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
>> +	return clk_gate2_reg_is_enabled(gate->reg, gate->bit_idx);
>> +}
>> +
>> +static void clk_gate2_disable_unused(struct clk_hw *hw)
>> +{
>> +	struct clk_gate2 *gate = to_clk_gate2(hw);
>> +	unsigned long flags = 0;
>> +	u32 reg;
>> +
>> +	spin_lock_irqsave(gate->lock, flags);
>> +
>> +	if (!gate->share_count || *gate->share_count == 0) {
> 
> By introducing the .disable_unused callback the framework won't call the
> .disable callback anymore, even if enable_count is 0 and the clock is
> enabled according to .is_enabled. Wouldn't this interfere the disabling
> of normal, non-shared clock gates?
> 

Ok, see it now, we disable the clock in this if statement in the
share_count == NULL case... Sorry about that.

--
Stefan

>> +		reg = readl(gate->reg);
>> +		reg &= ~(3 << gate->bit_idx);
>> +		writel(reg, gate->reg);
>> +	}
>> +
>> +	spin_unlock_irqrestore(gate->lock, flags);
>>  }
>>
>>  static struct clk_ops clk_gate2_ops = {
>>  	.enable = clk_gate2_enable,
>>  	.disable = clk_gate2_disable,
>> +	.disable_unused = clk_gate2_disable_unused,
>>  	.is_enabled = clk_gate2_is_enabled,
>>  };
> 
> --
> Stefan




More information about the linux-arm-kernel mailing list