[v8,10/21] clk: tegra: clk-super: Add restore-context support
diff mbox series

Message ID 1565308020-31952-11-git-send-email-skomatineni@nvidia.com
State New
Headers show
Series
  • SC7 entry and exit support for Tegra210
Related show

Commit Message

Sowjanya Komatineni Aug. 8, 2019, 11:46 p.m. UTC
This patch implements restore_context for clk_super_mux and clk_super.

During system supend, core power goes off the and context of Tegra
CAR registers is lost.

So on system resume, context of super clock registers are restored
to have them in same state as before suspend.

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/clk/tegra/clk-super.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Comments

Dmitry Osipenko Aug. 9, 2019, 12:17 p.m. UTC | #1
09.08.2019 2:46, Sowjanya Komatineni пишет:
> This patch implements restore_context for clk_super_mux and clk_super.
> 
> During system supend, core power goes off the and context of Tegra
> CAR registers is lost.
> 
> So on system resume, context of super clock registers are restored
> to have them in same state as before suspend.
> 
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
> ---
>  drivers/clk/tegra/clk-super.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
> index e2a1e95a8db7..74c9e913e41c 100644
> --- a/drivers/clk/tegra/clk-super.c
> +++ b/drivers/clk/tegra/clk-super.c
> @@ -124,9 +124,18 @@ static int clk_super_set_parent(struct clk_hw *hw, u8 index)
>  	return err;
>  }
>  
> +static void clk_super_mux_restore_context(struct clk_hw *hw)
> +{
> +	struct clk_hw *parent = clk_hw_get_parent(hw);
> +	int parent_id = clk_hw_get_parent_index(hw, parent);
> +
> +	clk_super_set_parent(hw, parent_id);

All Super clocks have a divider, including the "MUX". Thus I'm wondering
if there is a chance that divider's configuration may differ on resume
from what it was on suspend.

> +}
> +
>  static const struct clk_ops tegra_clk_super_mux_ops = {
>  	.get_parent = clk_super_get_parent,
>  	.set_parent = clk_super_set_parent,
> +	.restore_context = clk_super_mux_restore_context,
>  };
>  
>  static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
> @@ -162,12 +171,24 @@ static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate,
>  	return super->div_ops->set_rate(div_hw, rate, parent_rate);
>  }
>  
> +static void clk_super_restore_context(struct clk_hw *hw)
> +{
> +	struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
> +	struct clk_hw *div_hw = &super->frac_div.hw;
> +	struct clk_hw *parent = clk_hw_get_parent(hw);
> +	int parent_id = clk_hw_get_parent_index(hw, parent);
> +
> +	super->div_ops->restore_context(div_hw);
> +	clk_super_set_parent(hw, parent_id);
> +}
> +
>  const struct clk_ops tegra_clk_super_ops = {
>  	.get_parent = clk_super_get_parent,
>  	.set_parent = clk_super_set_parent,
>  	.set_rate = clk_super_set_rate,
>  	.round_rate = clk_super_round_rate,
>  	.recalc_rate = clk_super_recalc_rate,
> +	.restore_context = clk_super_restore_context,
>  };
>  
>  struct clk *tegra_clk_register_super_mux(const char *name,
>
Sowjanya Komatineni Aug. 9, 2019, 5:08 p.m. UTC | #2
On 8/9/19 5:17 AM, Dmitry Osipenko wrote:
> 09.08.2019 2:46, Sowjanya Komatineni пишет:
>> This patch implements restore_context for clk_super_mux and clk_super.
>>
>> During system supend, core power goes off the and context of Tegra
>> CAR registers is lost.
>>
>> So on system resume, context of super clock registers are restored
>> to have them in same state as before suspend.
>>
>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>> ---
>>   drivers/clk/tegra/clk-super.c | 21 +++++++++++++++++++++
>>   1 file changed, 21 insertions(+)
>>
>> diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
>> index e2a1e95a8db7..74c9e913e41c 100644
>> --- a/drivers/clk/tegra/clk-super.c
>> +++ b/drivers/clk/tegra/clk-super.c
>> @@ -124,9 +124,18 @@ static int clk_super_set_parent(struct clk_hw *hw, u8 index)
>>   	return err;
>>   }
>>   
>> +static void clk_super_mux_restore_context(struct clk_hw *hw)
>> +{
>> +	struct clk_hw *parent = clk_hw_get_parent(hw);
>> +	int parent_id = clk_hw_get_parent_index(hw, parent);
>> +
>> +	clk_super_set_parent(hw, parent_id);
> All Super clocks have a divider, including the "MUX". Thus I'm wondering
> if there is a chance that divider's configuration may differ on resume
> from what it was on suspend.

tegra_clk_register_super_mux which uses tegra_clk_super_mux_ops doesn't 
do divider rate programming.

I believe you are referring to sclk_divider, cclklp_divider, 
cclkg_divider...

these are registered as clk_divider and are restored during clk_divider 
resume.

>> +}
>> +
>>   static const struct clk_ops tegra_clk_super_mux_ops = {
>>   	.get_parent = clk_super_get_parent,
>>   	.set_parent = clk_super_set_parent,
>> +	.restore_context = clk_super_mux_restore_context,
>>   };
>>   
>>   static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
>> @@ -162,12 +171,24 @@ static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate,
>>   	return super->div_ops->set_rate(div_hw, rate, parent_rate);
>>   }
>>   
>> +static void clk_super_restore_context(struct clk_hw *hw)
>> +{
>> +	struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
>> +	struct clk_hw *div_hw = &super->frac_div.hw;
>> +	struct clk_hw *parent = clk_hw_get_parent(hw);
>> +	int parent_id = clk_hw_get_parent_index(hw, parent);
>> +
>> +	super->div_ops->restore_context(div_hw);
>> +	clk_super_set_parent(hw, parent_id);
>> +}
>> +
>>   const struct clk_ops tegra_clk_super_ops = {
>>   	.get_parent = clk_super_get_parent,
>>   	.set_parent = clk_super_set_parent,
>>   	.set_rate = clk_super_set_rate,
>>   	.round_rate = clk_super_round_rate,
>>   	.recalc_rate = clk_super_recalc_rate,
>> +	.restore_context = clk_super_restore_context,
>>   };
>>   
>>   struct clk *tegra_clk_register_super_mux(const char *name,
>>
Dmitry Osipenko Aug. 11, 2019, 5:29 p.m. UTC | #3
09.08.2019 20:08, Sowjanya Komatineni пишет:
> 
> On 8/9/19 5:17 AM, Dmitry Osipenko wrote:
>> 09.08.2019 2:46, Sowjanya Komatineni пишет:
>>> This patch implements restore_context for clk_super_mux and clk_super.
>>>
>>> During system supend, core power goes off the and context of Tegra
>>> CAR registers is lost.
>>>
>>> So on system resume, context of super clock registers are restored
>>> to have them in same state as before suspend.
>>>
>>> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
>>> ---
>>>   drivers/clk/tegra/clk-super.c | 21 +++++++++++++++++++++
>>>   1 file changed, 21 insertions(+)
>>>
>>> diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
>>> index e2a1e95a8db7..74c9e913e41c 100644
>>> --- a/drivers/clk/tegra/clk-super.c
>>> +++ b/drivers/clk/tegra/clk-super.c
>>> @@ -124,9 +124,18 @@ static int clk_super_set_parent(struct clk_hw *hw, u8 index)
>>>       return err;
>>>   }
>>>   +static void clk_super_mux_restore_context(struct clk_hw *hw)
>>> +{
>>> +    struct clk_hw *parent = clk_hw_get_parent(hw);
>>> +    int parent_id = clk_hw_get_parent_index(hw, parent);
>>> +
>>> +    clk_super_set_parent(hw, parent_id);
>> All Super clocks have a divider, including the "MUX". Thus I'm wondering
>> if there is a chance that divider's configuration may differ on resume
>> from what it was on suspend.
> 
> tegra_clk_register_super_mux which uses tegra_clk_super_mux_ops doesn't do divider rate
> programming.
> 
> I believe you are referring to sclk_divider, cclklp_divider, cclkg_divider...
> 
> these are registered as clk_divider and are restored during clk_divider resume.

Indeed, thanks for the clarification.
Thierry Reding Aug. 12, 2019, 9:55 a.m. UTC | #4
On Thu, Aug 08, 2019 at 04:46:49PM -0700, Sowjanya Komatineni wrote:
> This patch implements restore_context for clk_super_mux and clk_super.
> 
> During system supend, core power goes off the and context of Tegra
> CAR registers is lost.
> 
> So on system resume, context of super clock registers are restored
> to have them in same state as before suspend.
> 
> Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
> ---
>  drivers/clk/tegra/clk-super.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)

Acked-by: Thierry Reding <treding@nvidia.com>

Patch
diff mbox series

diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
index e2a1e95a8db7..74c9e913e41c 100644
--- a/drivers/clk/tegra/clk-super.c
+++ b/drivers/clk/tegra/clk-super.c
@@ -124,9 +124,18 @@  static int clk_super_set_parent(struct clk_hw *hw, u8 index)
 	return err;
 }
 
+static void clk_super_mux_restore_context(struct clk_hw *hw)
+{
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	clk_super_set_parent(hw, parent_id);
+}
+
 static const struct clk_ops tegra_clk_super_mux_ops = {
 	.get_parent = clk_super_get_parent,
 	.set_parent = clk_super_set_parent,
+	.restore_context = clk_super_mux_restore_context,
 };
 
 static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -162,12 +171,24 @@  static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate,
 	return super->div_ops->set_rate(div_hw, rate, parent_rate);
 }
 
+static void clk_super_restore_context(struct clk_hw *hw)
+{
+	struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
+	struct clk_hw *div_hw = &super->frac_div.hw;
+	struct clk_hw *parent = clk_hw_get_parent(hw);
+	int parent_id = clk_hw_get_parent_index(hw, parent);
+
+	super->div_ops->restore_context(div_hw);
+	clk_super_set_parent(hw, parent_id);
+}
+
 const struct clk_ops tegra_clk_super_ops = {
 	.get_parent = clk_super_get_parent,
 	.set_parent = clk_super_set_parent,
 	.set_rate = clk_super_set_rate,
 	.round_rate = clk_super_round_rate,
 	.recalc_rate = clk_super_recalc_rate,
+	.restore_context = clk_super_restore_context,
 };
 
 struct clk *tegra_clk_register_super_mux(const char *name,