[PATCHv2,4/6] clk: ti: clkctrl: add API to notify reset status
diff mbox series

Message ID 20190828065929.32150-5-t-kristo@ti.com
State New
Headers show
Series
  • clk: ti: reset handling support fixes
Related show

Commit Message

Tero Kristo Aug. 28, 2019, 6:59 a.m. UTC
When an IP has both a clkctrl clock being fed into it and has hardware
reset lines, the control for these must be synced against each other.
While disabling a clock, all the hardware reset lines must be asserted
at the same time, and while enabling, resets must be deasserted.
Otherwise, the IP module fails to transition from to idle/active. To
handle this situation properly, a callback is added for clkctrl clocks
which is used by the PRM reset driver to tell the status of the reset
lines. This info is then used to sync state.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 drivers/clk/ti/clkctrl.c | 44 ++++++++++++++++++++++++++++++++++++++++
 include/linux/clk/ti.h   |  1 +
 2 files changed, 45 insertions(+)

Comments

Stephen Boyd Aug. 29, 2019, 8:05 p.m. UTC | #1
Quoting Tero Kristo (2019-08-27 23:59:27)
> diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
> index e3e0a66a6ce2..47a0d1398c6f 100644
> --- a/drivers/clk/ti/clkctrl.c
> +++ b/drivers/clk/ti/clkctrl.c
> @@ -680,3 +689,38 @@ u32 ti_clk_is_in_standby(struct clk *clk)
>         return false;
>  }
>  EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
> +
> +/**
> + * ti_clk_notify_resets - Notify the clock driver associated reset status

This is completely unused in this patch series. What's going on?

> + * @clk: clock to notify reset status for
> + * @asserted: true if all HW reset lines are asserted
> + *
> + * Some clkctrl clocks have associated resets for them which effectively
> + * prevent the clock to transition from/to idle if the reset state is not
> + * in sync. For the clock to transition to idle properly, all associated
> + * resets must be asserted, and to leave idle, vice versa. To provide the
> + * current reset status, the reset driver should issue this callback.
> + */
Tero Kristo Aug. 30, 2019, 6:06 a.m. UTC | #2
On 29/08/2019 23:05, Stephen Boyd wrote:
> Quoting Tero Kristo (2019-08-27 23:59:27)
>> diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
>> index e3e0a66a6ce2..47a0d1398c6f 100644
>> --- a/drivers/clk/ti/clkctrl.c
>> +++ b/drivers/clk/ti/clkctrl.c
>> @@ -680,3 +689,38 @@ u32 ti_clk_is_in_standby(struct clk *clk)
>>          return false;
>>   }
>>   EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
>> +
>> +/**
>> + * ti_clk_notify_resets - Notify the clock driver associated reset status
> 
> This is completely unused in this patch series. What's going on?

This is needed by the OMAP reset driver. See:

https://lwn.net/Articles/797597/

-Tero

>> + * @clk: clock to notify reset status for
>> + * @asserted: true if all HW reset lines are asserted
>> + *
>> + * Some clkctrl clocks have associated resets for them which effectively
>> + * prevent the clock to transition from/to idle if the reset state is not
>> + * in sync. For the clock to transition to idle properly, all associated
>> + * resets must be asserted, and to leave idle, vice versa. To provide the
>> + * current reset status, the reset driver should issue this callback.
>> + */

--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
Stephen Boyd Sept. 6, 2019, 4:15 p.m. UTC | #3
Quoting Tero Kristo (2019-08-29 23:06:41)
> On 29/08/2019 23:05, Stephen Boyd wrote:
> > Quoting Tero Kristo (2019-08-27 23:59:27)
> >> diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
> >> index e3e0a66a6ce2..47a0d1398c6f 100644
> >> --- a/drivers/clk/ti/clkctrl.c
> >> +++ b/drivers/clk/ti/clkctrl.c
> >> @@ -680,3 +689,38 @@ u32 ti_clk_is_in_standby(struct clk *clk)
> >>          return false;
> >>   }
> >>   EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
> >> +
> >> +/**
> >> + * ti_clk_notify_resets - Notify the clock driver associated reset status
> > 
> > This is completely unused in this patch series. What's going on?
> 
> This is needed by the OMAP reset driver. See:
> 
> https://lwn.net/Articles/797597/
> 

Ok. I decided to punt this topic forward to next release at the least.
To clarify, TI is not special with regards to coordinating resets and
clk enable/disable state. Every other silicon vendor has the same
requirements and nobody is doing a good job at it.

Please devise a way that avoids making a tight coupling between the clk
driver and the reset driver in this way. Are the two in the same
register space? Perhaps we need to combine the two drivers then. Or can
this be implemented as a genpd that coordinates the resets and clk
controls for various devices?
Tero Kristo Sept. 6, 2019, 7:57 p.m. UTC | #4
On 06/09/2019 19:15, Stephen Boyd wrote:
> Quoting Tero Kristo (2019-08-29 23:06:41)
>> On 29/08/2019 23:05, Stephen Boyd wrote:
>>> Quoting Tero Kristo (2019-08-27 23:59:27)
>>>> diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
>>>> index e3e0a66a6ce2..47a0d1398c6f 100644
>>>> --- a/drivers/clk/ti/clkctrl.c
>>>> +++ b/drivers/clk/ti/clkctrl.c
>>>> @@ -680,3 +689,38 @@ u32 ti_clk_is_in_standby(struct clk *clk)
>>>>           return false;
>>>>    }
>>>>    EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
>>>> +
>>>> +/**
>>>> + * ti_clk_notify_resets - Notify the clock driver associated reset status
>>>
>>> This is completely unused in this patch series. What's going on?
>>
>> This is needed by the OMAP reset driver. See:
>>
>> https://lwn.net/Articles/797597/
>>
> 
> Ok. I decided to punt this topic forward to next release at the least.
> To clarify, TI is not special with regards to coordinating resets and
> clk enable/disable state. Every other silicon vendor has the same
> requirements and nobody is doing a good job at it.
> 
> Please devise a way that avoids making a tight coupling between the clk
> driver and the reset driver in this way. Are the two in the same
> register space?

No, they do not share register space. One is under a PRM node, one is 
under CM node, and there are multiple instances of each following each 
other:

prm-1
prm-2
prm-3

...

cm-1
cm-2
cm-3

And the gap between PRM + CM nodes is multiple megabytes in register 
space. To make things worse, there are some mutant CM nodes in the 
middle of the PRM nodes on certain SoCs.

  Perhaps we need to combine the two drivers then. Or can
> this be implemented as a genpd that coordinates the resets and clk
> controls for various devices?

Generally, ti-sysc bus driver is the one doing the trick combining reset 
+ clock handling. However, this is linked at the pm-runtime on device 
level so it imposes certain sequencing due to way kernel PM is 
implemented. Basically we can't enable the clocks + deassert reset for 
remoteproc before the driver is able to load up the firmware for it. 
Maybe if I add a custom genpd or just custom PM runtime for the 
remoteprocs that would handle both clk + reset...

Another potential change I can think of here is that I would add resets 
property under the clkctrl nodes, and link them via DT handles. The 
clock driver would get a handle to the reset controller, and query its 
state via generic API instead of adding this custom one. I would still 
need to add a separate custom API for telling the clocks that reset 
controller is in place though... And this would still be a hard link 
between reset + clocks.

Do you think fully custom PM implementation would be better here which 
would just control reset + clock signals directly?

-Tero
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
Stephen Boyd Sept. 6, 2019, 8:37 p.m. UTC | #5
Quoting Tero Kristo (2019-09-06 12:57:06)
> On 06/09/2019 19:15, Stephen Boyd wrote:
> > Quoting Tero Kristo (2019-08-29 23:06:41)
> >> On 29/08/2019 23:05, Stephen Boyd wrote:
> >>> Quoting Tero Kristo (2019-08-27 23:59:27)
> >>>> diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
> >>>> index e3e0a66a6ce2..47a0d1398c6f 100644
> >>>> --- a/drivers/clk/ti/clkctrl.c
> >>>> +++ b/drivers/clk/ti/clkctrl.c
> >>>> @@ -680,3 +689,38 @@ u32 ti_clk_is_in_standby(struct clk *clk)
> >>>>           return false;
> >>>>    }
> >>>>    EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
> >>>> +
> >>>> +/**
> >>>> + * ti_clk_notify_resets - Notify the clock driver associated reset status
> >>>
> >>> This is completely unused in this patch series. What's going on?
> >>
> >> This is needed by the OMAP reset driver. See:
> >>
> >> https://lwn.net/Articles/797597/
> >>
> > 
> > Ok. I decided to punt this topic forward to next release at the least.
> > To clarify, TI is not special with regards to coordinating resets and
> > clk enable/disable state. Every other silicon vendor has the same
> > requirements and nobody is doing a good job at it.
> > 
> > Please devise a way that avoids making a tight coupling between the clk
> > driver and the reset driver in this way. Are the two in the same
> > register space?
> 
> No, they do not share register space. One is under a PRM node, one is 
> under CM node, and there are multiple instances of each following each 
> other:
> 
> prm-1
> prm-2
> prm-3

So PRM is reset?

> 
> ...
> 
> cm-1
> cm-2
> cm-3

And CM is clk?

> 
> And the gap between PRM + CM nodes is multiple megabytes in register 
> space. To make things worse, there are some mutant CM nodes in the 
> middle of the PRM nodes on certain SoCs.

Ok, sounds fair!

> 
>   Perhaps we need to combine the two drivers then. Or can
> > this be implemented as a genpd that coordinates the resets and clk
> > controls for various devices?
> 
> Generally, ti-sysc bus driver is the one doing the trick combining reset 
> + clock handling. However, this is linked at the pm-runtime on device 
> level so it imposes certain sequencing due to way kernel PM is 
> implemented. Basically we can't enable the clocks + deassert reset for 
> remoteproc before the driver is able to load up the firmware for it. 
> Maybe if I add a custom genpd or just custom PM runtime for the 
> remoteprocs that would handle both clk + reset...
> 
> Another potential change I can think of here is that I would add resets 
> property under the clkctrl nodes, and link them via DT handles. The 
> clock driver would get a handle to the reset controller, and query its 
> state via generic API instead of adding this custom one. I would still 
> need to add a separate custom API for telling the clocks that reset 
> controller is in place though... And this would still be a hard link 
> between reset + clocks.
> 
> Do you think fully custom PM implementation would be better here which 
> would just control reset + clock signals directly?
> 

From what you're saying it sounds like a job for genpds. Maybe genpds
aren't up to the task yet, but we want devices that have resets and clks
going to them to manage the order of operations somehow without having
to "lie" and say that the resets go to the clk controller when they
don't (or vice versa).
Tero Kristo Sept. 6, 2019, 8:53 p.m. UTC | #6
On 06/09/2019 23:37, Stephen Boyd wrote:
> Quoting Tero Kristo (2019-09-06 12:57:06)
>> On 06/09/2019 19:15, Stephen Boyd wrote:
>>> Quoting Tero Kristo (2019-08-29 23:06:41)
>>>> On 29/08/2019 23:05, Stephen Boyd wrote:
>>>>> Quoting Tero Kristo (2019-08-27 23:59:27)
>>>>>> diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
>>>>>> index e3e0a66a6ce2..47a0d1398c6f 100644
>>>>>> --- a/drivers/clk/ti/clkctrl.c
>>>>>> +++ b/drivers/clk/ti/clkctrl.c
>>>>>> @@ -680,3 +689,38 @@ u32 ti_clk_is_in_standby(struct clk *clk)
>>>>>>            return false;
>>>>>>     }
>>>>>>     EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
>>>>>> +
>>>>>> +/**
>>>>>> + * ti_clk_notify_resets - Notify the clock driver associated reset status
>>>>>
>>>>> This is completely unused in this patch series. What's going on?
>>>>
>>>> This is needed by the OMAP reset driver. See:
>>>>
>>>> https://lwn.net/Articles/797597/
>>>>
>>>
>>> Ok. I decided to punt this topic forward to next release at the least.
>>> To clarify, TI is not special with regards to coordinating resets and
>>> clk enable/disable state. Every other silicon vendor has the same
>>> requirements and nobody is doing a good job at it.
>>>
>>> Please devise a way that avoids making a tight coupling between the clk
>>> driver and the reset driver in this way. Are the two in the same
>>> register space?
>>
>> No, they do not share register space. One is under a PRM node, one is
>> under CM node, and there are multiple instances of each following each
>> other:
>>
>> prm-1
>> prm-2
>> prm-3
> 
> So PRM is reset?

PRM is for Power and Reset Manager.

> 
>>
>> ...
>>
>> cm-1
>> cm-2
>> cm-3
> 
> And CM is clk?

CM is for Clock Manager.

So basically for both answer is yes.

> 
>>
>> And the gap between PRM + CM nodes is multiple megabytes in register
>> space. To make things worse, there are some mutant CM nodes in the
>> middle of the PRM nodes on certain SoCs.
> 
> Ok, sounds fair!
> 
>>
>>    Perhaps we need to combine the two drivers then. Or can
>>> this be implemented as a genpd that coordinates the resets and clk
>>> controls for various devices?
>>
>> Generally, ti-sysc bus driver is the one doing the trick combining reset
>> + clock handling. However, this is linked at the pm-runtime on device
>> level so it imposes certain sequencing due to way kernel PM is
>> implemented. Basically we can't enable the clocks + deassert reset for
>> remoteproc before the driver is able to load up the firmware for it.
>> Maybe if I add a custom genpd or just custom PM runtime for the
>> remoteprocs that would handle both clk + reset...
>>
>> Another potential change I can think of here is that I would add resets
>> property under the clkctrl nodes, and link them via DT handles. The
>> clock driver would get a handle to the reset controller, and query its
>> state via generic API instead of adding this custom one. I would still
>> need to add a separate custom API for telling the clocks that reset
>> controller is in place though... And this would still be a hard link
>> between reset + clocks.
>>
>> Do you think fully custom PM implementation would be better here which
>> would just control reset + clock signals directly?
>>
> 
>  From what you're saying it sounds like a job for genpds. Maybe genpds
> aren't up to the task yet, but we want devices that have resets and clks
> going to them to manage the order of operations somehow without having
> to "lie" and say that the resets go to the clk controller when they
> don't (or vice versa).

Yeah I am not too sure if genpd would suit this purpose as it has no 
support for reset control so far I believe. However I think the custom 
PM implementation might. I will give it a shot next week and see how it 
fares. Basically the main issue I am trying to tackle is not to 
introduce any timeouts anywhere due to the hardware level dependencies 
of these two guys.

-Tero
--
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki

Patch
diff mbox series

diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
index e3e0a66a6ce2..47a0d1398c6f 100644
--- a/drivers/clk/ti/clkctrl.c
+++ b/drivers/clk/ti/clkctrl.c
@@ -25,6 +25,8 @@ 
 #include "clock.h"
 
 #define NO_IDLEST			0
+#define HAS_RESET			1
+#define RESET_ASSERTED			2
 
 #define OMAP4_MODULEMODE_MASK		0x3
 
@@ -164,6 +166,9 @@  static int _omap4_clkctrl_clk_enable(struct clk_hw *hw)
 	if (test_bit(NO_IDLEST, &clk->flags))
 		return 0;
 
+	if (test_bit(RESET_ASSERTED, &clk->flags))
+		return 0;
+
 	/* Wait until module is enabled */
 	while (!_omap4_is_ready(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
 		if (_omap4_is_timeout(&timeout, OMAP4_MAX_MODULE_READY_TIME)) {
@@ -193,6 +198,10 @@  static void _omap4_clkctrl_clk_disable(struct clk_hw *hw)
 	if (test_bit(NO_IDLEST, &clk->flags))
 		goto exit;
 
+	if (test_bit(HAS_RESET, &clk->flags) &&
+	    !test_bit(RESET_ASSERTED, &clk->flags))
+		goto exit;
+
 	/* Wait until module is disabled */
 	while (!_omap4_is_idle(ti_clk_ll_ops->clk_readl(&clk->enable_reg))) {
 		if (_omap4_is_timeout(&timeout,
@@ -680,3 +689,38 @@  u32 ti_clk_is_in_standby(struct clk *clk)
 	return false;
 }
 EXPORT_SYMBOL_GPL(ti_clk_is_in_standby);
+
+/**
+ * ti_clk_notify_resets - Notify the clock driver associated reset status
+ * @clk: clock to notify reset status for
+ * @asserted: true if all HW reset lines are asserted
+ *
+ * Some clkctrl clocks have associated resets for them which effectively
+ * prevent the clock to transition from/to idle if the reset state is not
+ * in sync. For the clock to transition to idle properly, all associated
+ * resets must be asserted, and to leave idle, vice versa. To provide the
+ * current reset status, the reset driver should issue this callback.
+ */
+void ti_clk_notify_resets(struct clk *clk, bool asserted)
+{
+	struct clk_hw *hw;
+	struct clk_hw_omap *hwclk;
+
+	if (!clk)
+		return;
+
+	hw = __clk_get_hw(clk);
+
+	if (!omap2_clk_is_hw_omap(hw))
+		return;
+
+	hwclk = to_clk_hw_omap(hw);
+
+	set_bit(HAS_RESET, &hwclk->flags);
+
+	if (asserted)
+		set_bit(RESET_ASSERTED, &hwclk->flags);
+	else
+		clear_bit(RESET_ASSERTED, &hwclk->flags);
+}
+EXPORT_SYMBOL_GPL(ti_clk_notify_resets);
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 3fb777f7103a..ae34e3f5cf7a 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -299,6 +299,7 @@  struct ti_clk_features {
 void ti_clk_setup_features(struct ti_clk_features *features);
 const struct ti_clk_features *ti_clk_get_features(void);
 u32 ti_clk_is_in_standby(struct clk *clk);
+void ti_clk_notify_resets(struct clk *clk, bool asserted);
 int omap3_noncore_dpll_save_context(struct clk_hw *hw);
 void omap3_noncore_dpll_restore_context(struct clk_hw *hw);