diff mbox

[1/2] clk: introduce optional disable_unused callback

Message ID CACRpkdbRK6qpO74pU=fKL8Jz0_ENV_SJjvyFXEYKEpx802rnog@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Linus Walleij Dec. 6, 2012, 7:07 p.m. UTC
On Tue, Dec 4, 2012 at 10:00 PM, Mike Turquette <mturquette@linaro.org> wrote:

> Some gate clocks have special needs which must be handled during the
> disable-unused clocks sequence.  These needs might be driven by software
> due to the fact that we're disabling a clock outside of the normal
> clk_disable path and a clk's enable_count will not be accurate.  On the
> other hand a specific hardware programming sequence might need to be
> followed for this corner case.
>
> This change is needed for the upcoming OMAP port to the common clock
> framework.  Specifically, it is undesirable to treat the disable-unused
> path identically to the normal clk_disable path since other software
> layers are involved.  In this case OMAP's clockdomain code throws WARNs
> and bails early due to the clock's enable_count being set to zero.  A
> custom callback mitigates this problem nicely.
>
> Cc: Paul Walmsley <paul@pwsan.com>
> Signed-off-by: Mike Turquette <mturquette@linaro.org>

This semantic change:

> -       if (__clk_is_enabled(clk) && clk->ops->disable)
> -               clk->ops->disable(clk->hw);
> +       /*
> +        * some gate clocks have special needs during the disable-unused
> +        * sequence.  call .disable_unused if available, otherwise fall
> +        * back to .disable
> +        */
> +       if (__clk_is_enabled(clk)) {
> +               if (clk->ops->disable_unused)
> +                       clk->ops->disable_unused(clk->hw);
> +               else if (clk->ops->disable)
> +                       clk->ops->disable(clk->hw);
> +       }

Means that you should probably go into all drivers and set their
.disable_unused to point to the clk_disable() implentation. Something
like the below (untested, Signed-off-by: Linus Walleij
<linus.walleij@linaro.org>



Yours,
Linus Walleij

Comments

Ulf Hansson Dec. 6, 2012, 9:58 p.m. UTC | #1
On 6 December 2012 20:07, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Tue, Dec 4, 2012 at 10:00 PM, Mike Turquette <mturquette@linaro.org> wrote:
>
>> Some gate clocks have special needs which must be handled during the
>> disable-unused clocks sequence.  These needs might be driven by software
>> due to the fact that we're disabling a clock outside of the normal
>> clk_disable path and a clk's enable_count will not be accurate.  On the
>> other hand a specific hardware programming sequence might need to be
>> followed for this corner case.
>>
>> This change is needed for the upcoming OMAP port to the common clock
>> framework.  Specifically, it is undesirable to treat the disable-unused
>> path identically to the normal clk_disable path since other software
>> layers are involved.  In this case OMAP's clockdomain code throws WARNs
>> and bails early due to the clock's enable_count being set to zero.  A
>> custom callback mitigates this problem nicely.
>>
>> Cc: Paul Walmsley <paul@pwsan.com>
>> Signed-off-by: Mike Turquette <mturquette@linaro.org>
>
> This semantic change:
>
>> -       if (__clk_is_enabled(clk) && clk->ops->disable)
>> -               clk->ops->disable(clk->hw);
>> +       /*
>> +        * some gate clocks have special needs during the disable-unused
>> +        * sequence.  call .disable_unused if available, otherwise fall
>> +        * back to .disable
>> +        */
>> +       if (__clk_is_enabled(clk)) {
>> +               if (clk->ops->disable_unused)
>> +                       clk->ops->disable_unused(clk->hw);
>> +               else if (clk->ops->disable)
>> +                       clk->ops->disable(clk->hw);
>> +       }
>
> Means that you should probably go into all drivers and set their
> .disable_unused to point to the clk_disable() implentation. Something
> like the below (untested, Signed-off-by: Linus Walleij
> <linus.walleij@linaro.org>
>
> diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
> index a15f792..504abde 100644
> --- a/drivers/clk/clk-u300.c
> +++ b/drivers/clk/clk-u300.c
> @@ -340,6 +340,7 @@ static const struct clk_ops syscon_clk_ops = {
>         .unprepare = syscon_clk_unprepare,
>         .enable = syscon_clk_enable,
>         .disable = syscon_clk_disable,
> +       .disable_unused = syscon_clk_disable,
>         .is_enabled = syscon_clk_is_enabled,
>         .recalc_rate = syscon_clk_recalc_rate,
>         .round_rate = syscon_clk_round_rate,
> diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c
> index 7eee7f7..1d3ff60 100644
> --- a/drivers/clk/ux500/clk-prcc.c
> +++ b/drivers/clk/ux500/clk-prcc.c
> @@ -84,12 +84,14 @@ static int clk_prcc_is_enabled(struct clk_hw *hw)
>  static struct clk_ops clk_prcc_pclk_ops = {
>         .enable = clk_prcc_pclk_enable,
>         .disable = clk_prcc_pclk_disable,
> +       .disable_unused = clk_prcc_pclk_disable,
>         .is_enabled = clk_prcc_is_enabled,
>  };
>
>  static struct clk_ops clk_prcc_kclk_ops = {
>         .enable = clk_prcc_kclk_enable,
>         .disable = clk_prcc_kclk_disable,
> +       .disable_unused = clk_prcc_kclk_disable,
>         .is_enabled = clk_prcc_is_enabled,
>  };
>
> diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
> index 74faa7e..00498f2 100644
> --- a/drivers/clk/ux500/clk-prcmu.c
> +++ b/drivers/clk/ux500/clk-prcmu.c
> @@ -172,6 +172,7 @@ static struct clk_ops clk_prcmu_scalable_ops = {
>         .unprepare = clk_prcmu_unprepare,
>         .enable = clk_prcmu_enable,
>         .disable = clk_prcmu_disable,
> +       .disable_unused = clk_prcmu_disable,
>         .is_enabled = clk_prcmu_is_enabled,
>         .recalc_rate = clk_prcmu_recalc_rate,
>         .round_rate = clk_prcmu_round_rate,
> @@ -183,6 +184,7 @@ static struct clk_ops clk_prcmu_gate_ops = {
>         .unprepare = clk_prcmu_unprepare,
>         .enable = clk_prcmu_enable,
>         .disable = clk_prcmu_disable,
> +       .disable_unused = clk_prcmu_disable,
>         .is_enabled = clk_prcmu_is_enabled,
>         .recalc_rate = clk_prcmu_recalc_rate,
>  };
> @@ -204,6 +206,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
>         .unprepare = clk_prcmu_opp_unprepare,
>         .enable = clk_prcmu_enable,
>         .disable = clk_prcmu_disable,
> +       .disable_unused = clk_prcmu_disable,
>         .is_enabled = clk_prcmu_is_enabled,
>         .recalc_rate = clk_prcmu_recalc_rate,
>  };
> @@ -213,6 +216,7 @@ static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
>         .unprepare = clk_prcmu_opp_volt_unprepare,
>         .enable = clk_prcmu_enable,
>         .disable = clk_prcmu_disable,
> +       .disable_unused = clk_prcmu_disable,
>         .is_enabled = clk_prcmu_is_enabled,
>         .recalc_rate = clk_prcmu_recalc_rate,
>         .round_rate = clk_prcmu_round_rate,
>
>
> Yours,
> Linus Walleij
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

I am not sure such change is needed. It kind of depends on what Mike
decides to put in the clk documentation. :-)

According to commit msg, it seems like the .disable_unused function
will be optional and must only be implemented for those clks that has
has special issues to consider.

Kind regards
Ulf Hansson
Mike Turquette Dec. 6, 2012, 10:05 p.m. UTC | #2
On Thu, Dec 6, 2012 at 1:58 PM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
> On 6 December 2012 20:07, Linus Walleij <linus.walleij@linaro.org> wrote:
>> On Tue, Dec 4, 2012 at 10:00 PM, Mike Turquette <mturquette@linaro.org> wrote:
>>
>>> Some gate clocks have special needs which must be handled during the
>>> disable-unused clocks sequence.  These needs might be driven by software
>>> due to the fact that we're disabling a clock outside of the normal
>>> clk_disable path and a clk's enable_count will not be accurate.  On the
>>> other hand a specific hardware programming sequence might need to be
>>> followed for this corner case.
>>>
>>> This change is needed for the upcoming OMAP port to the common clock
>>> framework.  Specifically, it is undesirable to treat the disable-unused
>>> path identically to the normal clk_disable path since other software
>>> layers are involved.  In this case OMAP's clockdomain code throws WARNs
>>> and bails early due to the clock's enable_count being set to zero.  A
>>> custom callback mitigates this problem nicely.
>>>
>>> Cc: Paul Walmsley <paul@pwsan.com>
>>> Signed-off-by: Mike Turquette <mturquette@linaro.org>
>>
>> This semantic change:
>>
>>> -       if (__clk_is_enabled(clk) && clk->ops->disable)
>>> -               clk->ops->disable(clk->hw);
>>> +       /*
>>> +        * some gate clocks have special needs during the disable-unused
>>> +        * sequence.  call .disable_unused if available, otherwise fall
>>> +        * back to .disable
>>> +        */
>>> +       if (__clk_is_enabled(clk)) {
>>> +               if (clk->ops->disable_unused)
>>> +                       clk->ops->disable_unused(clk->hw);
>>> +               else if (clk->ops->disable)
>>> +                       clk->ops->disable(clk->hw);
>>> +       }
>>
>> Means that you should probably go into all drivers and set their
>> .disable_unused to point to the clk_disable() implentation. Something
>> like the below (untested, Signed-off-by: Linus Walleij
>> <linus.walleij@linaro.org>
>>
>> diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
>> index a15f792..504abde 100644
>> --- a/drivers/clk/clk-u300.c
>> +++ b/drivers/clk/clk-u300.c
>> @@ -340,6 +340,7 @@ static const struct clk_ops syscon_clk_ops = {
>>         .unprepare = syscon_clk_unprepare,
>>         .enable = syscon_clk_enable,
>>         .disable = syscon_clk_disable,
>> +       .disable_unused = syscon_clk_disable,
>>         .is_enabled = syscon_clk_is_enabled,
>>         .recalc_rate = syscon_clk_recalc_rate,
>>         .round_rate = syscon_clk_round_rate,
>> diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c
>> index 7eee7f7..1d3ff60 100644
>> --- a/drivers/clk/ux500/clk-prcc.c
>> +++ b/drivers/clk/ux500/clk-prcc.c
>> @@ -84,12 +84,14 @@ static int clk_prcc_is_enabled(struct clk_hw *hw)
>>  static struct clk_ops clk_prcc_pclk_ops = {
>>         .enable = clk_prcc_pclk_enable,
>>         .disable = clk_prcc_pclk_disable,
>> +       .disable_unused = clk_prcc_pclk_disable,
>>         .is_enabled = clk_prcc_is_enabled,
>>  };
>>
>>  static struct clk_ops clk_prcc_kclk_ops = {
>>         .enable = clk_prcc_kclk_enable,
>>         .disable = clk_prcc_kclk_disable,
>> +       .disable_unused = clk_prcc_kclk_disable,
>>         .is_enabled = clk_prcc_is_enabled,
>>  };
>>
>> diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
>> index 74faa7e..00498f2 100644
>> --- a/drivers/clk/ux500/clk-prcmu.c
>> +++ b/drivers/clk/ux500/clk-prcmu.c
>> @@ -172,6 +172,7 @@ static struct clk_ops clk_prcmu_scalable_ops = {
>>         .unprepare = clk_prcmu_unprepare,
>>         .enable = clk_prcmu_enable,
>>         .disable = clk_prcmu_disable,
>> +       .disable_unused = clk_prcmu_disable,
>>         .is_enabled = clk_prcmu_is_enabled,
>>         .recalc_rate = clk_prcmu_recalc_rate,
>>         .round_rate = clk_prcmu_round_rate,
>> @@ -183,6 +184,7 @@ static struct clk_ops clk_prcmu_gate_ops = {
>>         .unprepare = clk_prcmu_unprepare,
>>         .enable = clk_prcmu_enable,
>>         .disable = clk_prcmu_disable,
>> +       .disable_unused = clk_prcmu_disable,
>>         .is_enabled = clk_prcmu_is_enabled,
>>         .recalc_rate = clk_prcmu_recalc_rate,
>>  };
>> @@ -204,6 +206,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
>>         .unprepare = clk_prcmu_opp_unprepare,
>>         .enable = clk_prcmu_enable,
>>         .disable = clk_prcmu_disable,
>> +       .disable_unused = clk_prcmu_disable,
>>         .is_enabled = clk_prcmu_is_enabled,
>>         .recalc_rate = clk_prcmu_recalc_rate,
>>  };
>> @@ -213,6 +216,7 @@ static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
>>         .unprepare = clk_prcmu_opp_volt_unprepare,
>>         .enable = clk_prcmu_enable,
>>         .disable = clk_prcmu_disable,
>> +       .disable_unused = clk_prcmu_disable,
>>         .is_enabled = clk_prcmu_is_enabled,
>>         .recalc_rate = clk_prcmu_recalc_rate,
>>         .round_rate = clk_prcmu_round_rate,
>>
>>
>> Yours,
>> Linus Walleij
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> I am not sure such change is needed. It kind of depends on what Mike
> decides to put in the clk documentation. :-)
>
> According to commit msg, it seems like the .disable_unused function
> will be optional and must only be implemented for those clks that has
> has special issues to consider.
>

That is correct.  I don't want people to read the above code while
porting their platform and perceive that .disable_unused is mandatory
in any way.  Using the same function in both pointers defeats the
purpose of the new optional callback.

Regards,
Mike

> Kind regards
> Ulf Hansson
Linus Walleij Dec. 7, 2012, 8:11 a.m. UTC | #3
On Thu, Dec 6, 2012 at 11:05 PM, Mike Turquette <mturquette@linaro.org> wrote:
> On Thu, Dec 6, 2012 at 1:58 PM, Ulf Hansson <ulf.hansson@linaro.org> wrote:

>> According to commit msg, it seems like the .disable_unused function
>> will be optional and must only be implemented for those clks that has
>> has special issues to consider.
>>
>
> That is correct.  I don't want people to read the above code while
> porting their platform and perceive that .disable_unused is mandatory
> in any way.  Using the same function in both pointers defeats the
> purpose of the new optional callback.

Aha I get it...
Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij
diff mbox

Patch

diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c
index a15f792..504abde 100644
--- a/drivers/clk/clk-u300.c
+++ b/drivers/clk/clk-u300.c
@@ -340,6 +340,7 @@  static const struct clk_ops syscon_clk_ops = {
 	.unprepare = syscon_clk_unprepare,
 	.enable = syscon_clk_enable,
 	.disable = syscon_clk_disable,
+	.disable_unused = syscon_clk_disable,
 	.is_enabled = syscon_clk_is_enabled,
 	.recalc_rate = syscon_clk_recalc_rate,
 	.round_rate = syscon_clk_round_rate,
diff --git a/drivers/clk/ux500/clk-prcc.c b/drivers/clk/ux500/clk-prcc.c
index 7eee7f7..1d3ff60 100644
--- a/drivers/clk/ux500/clk-prcc.c
+++ b/drivers/clk/ux500/clk-prcc.c
@@ -84,12 +84,14 @@  static int clk_prcc_is_enabled(struct clk_hw *hw)
 static struct clk_ops clk_prcc_pclk_ops = {
 	.enable = clk_prcc_pclk_enable,
 	.disable = clk_prcc_pclk_disable,
+	.disable_unused = clk_prcc_pclk_disable,
 	.is_enabled = clk_prcc_is_enabled,
 };

 static struct clk_ops clk_prcc_kclk_ops = {
 	.enable = clk_prcc_kclk_enable,
 	.disable = clk_prcc_kclk_disable,
+	.disable_unused = clk_prcc_kclk_disable,
 	.is_enabled = clk_prcc_is_enabled,
 };

diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c
index 74faa7e..00498f2 100644
--- a/drivers/clk/ux500/clk-prcmu.c
+++ b/drivers/clk/ux500/clk-prcmu.c
@@ -172,6 +172,7 @@  static struct clk_ops clk_prcmu_scalable_ops = {
 	.unprepare = clk_prcmu_unprepare,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
+	.disable_unused = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
 	.recalc_rate = clk_prcmu_recalc_rate,
 	.round_rate = clk_prcmu_round_rate,
@@ -183,6 +184,7 @@  static struct clk_ops clk_prcmu_gate_ops = {
 	.unprepare = clk_prcmu_unprepare,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
+	.disable_unused = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
 	.recalc_rate = clk_prcmu_recalc_rate,
 };
@@ -204,6 +206,7 @@  static struct clk_ops clk_prcmu_opp_gate_ops = {
 	.unprepare = clk_prcmu_opp_unprepare,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
+	.disable_unused = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
 	.recalc_rate = clk_prcmu_recalc_rate,
 };
@@ -213,6 +216,7 @@  static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
 	.unprepare = clk_prcmu_opp_volt_unprepare,
 	.enable = clk_prcmu_enable,
 	.disable = clk_prcmu_disable,
+	.disable_unused = clk_prcmu_disable,
 	.is_enabled = clk_prcmu_is_enabled,
 	.recalc_rate = clk_prcmu_recalc_rate,
 	.round_rate = clk_prcmu_round_rate,