diff mbox

[RFC,v2,12/18] ARM: OMAP2+: timer: Add suspend-resume callbacks for clockevent device

Message ID 1356959231-17335-13-git-send-email-vaibhav.bedia@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Vaibhav Bedia Dec. 31, 2012, 1:07 p.m. UTC
The current OMAP timer code registers two timers -
one as clocksource and one as clockevent.
AM33XX has only one usable timer in the WKUP domain
so one of the timers needs suspend-resume support
to restore the configuration to pre-suspend state.

commit adc78e6 (timekeeping: Add suspend and resume
of clock event devices) introduced .suspend and .resume
callbacks for clock event devices. Leverages these
callbacks to have AM33XX clockevent timer which is
in not in WKUP domain to behave properly across system
suspend.

Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Benoit Cousson <b-cousson@ti.com>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Kevin Hilman <khilman@deeprootsystems.com>
Cc: Vaibhav Hiremath <hvaibhav@ti.com>
Cc: Jon Hunter <jon-hunter@ti.com>
---
v1->v2:
	Get rid of harcoded timer id.
	Note: since a platform device is not created for these timer
	instances and because there's very minimal change needed for
	restarting the timer a full blown context save and restore
	has been skipped.

 arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
 1 files changed, 33 insertions(+), 0 deletions(-)

Comments

Santosh Shilimkar Jan. 8, 2013, 3:15 p.m. UTC | #1
On Monday 31 December 2012 06:37 PM, Vaibhav Bedia wrote:
> The current OMAP timer code registers two timers -
> one as clocksource and one as clockevent.
> AM33XX has only one usable timer in the WKUP domain
> so one of the timers needs suspend-resume support
> to restore the configuration to pre-suspend state.
>
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
>
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
> Cc: Jon Hunter <jon-hunter@ti.com>
> ---
> v1->v2:
> 	Get rid of harcoded timer id.
> 	Note: since a platform device is not created for these timer
> 	instances and because there's very minimal change needed for
> 	restarting the timer a full blown context save and restore
> 	has been skipped.
>
>   arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
>   1 files changed, 33 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index 691aa67..38f9cbc 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>   	}
>   }
>
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
> +	omap_hwmod_idle(oh);
> +}
> +
> +static void omap_clkevt_resume(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	omap_hwmod_enable(oh);
> +	__omap_dm_timer_load_start(&clkev,
> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> +}
> +
Am still bit uncomfortable with direct hwmod usage in the suspend/resmue
hooks.

Jon, Any alternatives you can think of ?

Regards,
Santosh
Vaibhav Bedia Jan. 11, 2013, 4:37 a.m. UTC | #2
On Tue, Jan 08, 2013 at 20:45:10, Shilimkar, Santosh wrote:
> On Monday 31 December 2012 06:37 PM, Vaibhav Bedia wrote:
> > The current OMAP timer code registers two timers -
> > one as clocksource and one as clockevent.
> > AM33XX has only one usable timer in the WKUP domain
> > so one of the timers needs suspend-resume support
> > to restore the configuration to pre-suspend state.
> >
> > commit adc78e6 (timekeeping: Add suspend and resume
> > of clock event devices) introduced .suspend and .resume
> > callbacks for clock event devices. Leverages these
> > callbacks to have AM33XX clockevent timer which is
> > in not in WKUP domain to behave properly across system
> > suspend.
> >
> > Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Paul Walmsley <paul@pwsan.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Vaibhav Hiremath <hvaibhav@ti.com>
> > Cc: Jon Hunter <jon-hunter@ti.com>
> > ---
> > v1->v2:
> > 	Get rid of harcoded timer id.
> > 	Note: since a platform device is not created for these timer
> > 	instances and because there's very minimal change needed for
> > 	restarting the timer a full blown context save and restore
> > 	has been skipped.
> >
> >   arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
> >   1 files changed, 33 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> > index 691aa67..38f9cbc 100644
> > --- a/arch/arm/mach-omap2/timer.c
> > +++ b/arch/arm/mach-omap2/timer.c
> > @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
> >   	}
> >   }
> >
> > +static void omap_clkevt_suspend(struct clock_event_device *unused)
> > +{
> > +	char name[10];
> > +	struct omap_hwmod *oh;
> > +
> > +	sprintf(name, "timer%d", clkev.id);
> > +	oh = omap_hwmod_lookup(name);
> > +	if (!oh)
> > +		return;
> > +
> > +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
> > +	omap_hwmod_idle(oh);
> > +}
> > +
> > +static void omap_clkevt_resume(struct clock_event_device *unused)
> > +{
> > +	char name[10];
> > +	struct omap_hwmod *oh;
> > +
> > +	sprintf(name, "timer%d", clkev.id);
> > +	oh = omap_hwmod_lookup(name);
> > +	if (!oh)
> > +		return;
> > +
> > +	omap_hwmod_enable(oh);
> > +	__omap_dm_timer_load_start(&clkev,
> > +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> > +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> > +}
> > +
> Am still bit uncomfortable with direct hwmod usage in the suspend/resmue
> hooks.
> 
> Jon, Any alternatives you can think of ?
> 

Jon,

Any suggestions here?

Regards,
Vaibhav
Hunter, Jon Jan. 17, 2013, 6:40 p.m. UTC | #3
On 12/31/2012 07:07 AM, Vaibhav Bedia wrote:
> The current OMAP timer code registers two timers -
> one as clocksource and one as clockevent.
> AM33XX has only one usable timer in the WKUP domain
> so one of the timers needs suspend-resume support
> to restore the configuration to pre-suspend state.
> 
> commit adc78e6 (timekeeping: Add suspend and resume
> of clock event devices) introduced .suspend and .resume
> callbacks for clock event devices. Leverages these
> callbacks to have AM33XX clockevent timer which is
> in not in WKUP domain to behave properly across system
> suspend.
> 
> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> Cc: Benoit Cousson <b-cousson@ti.com>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
> Cc: Jon Hunter <jon-hunter@ti.com>
> ---
> v1->v2:
> 	Get rid of harcoded timer id.
> 	Note: since a platform device is not created for these timer
> 	instances and because there's very minimal change needed for
> 	restarting the timer a full blown context save and restore
> 	has been skipped.
> 
>  arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
>  1 files changed, 33 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index 691aa67..38f9cbc 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>  	}
>  }
>  
> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);

I am not sure you need to call __omap_dm_timer_stop() here. This should
have already been called as timekeeping_suspend() will call
omap2_gp_timer_set_mode() to shutdown the timer.

> +	omap_hwmod_idle(oh);
> +}
> +
> +static void omap_clkevt_resume(struct clock_event_device *unused)
> +{
> +	char name[10];
> +	struct omap_hwmod *oh;
> +
> +	sprintf(name, "timer%d", clkev.id);
> +	oh = omap_hwmod_lookup(name);
> +	if (!oh)
> +		return;
> +
> +	omap_hwmod_enable(oh);
> +	__omap_dm_timer_load_start(&clkev,
> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);

Similarly here, I am not sure these __omap_dm_timer_xxxx calls are needed.

> +}
> +
>  static struct clock_event_device clockevent_gpt = {
>  	.name		= "gp_timer",
>  	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
> @@ -135,6 +165,8 @@ static struct clock_event_device clockevent_gpt = {
>  	.rating		= 300,
>  	.set_next_event	= omap2_gp_timer_set_next_event,
>  	.set_mode	= omap2_gp_timer_set_mode,
> +	.suspend	= omap_clkevt_suspend,
> +	.resume		= omap_clkevt_resume,

AFAIK, this is only applicable for AM335x devices and so should not be
added for all.

>  };
>  
>  static struct property device_disabled = {
> @@ -323,6 +355,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
>  	int res;
>  
>  	clkev.errata = omap_dm_timer_get_errata();
> +	clkev.id = gptimer_id;

We should not use gptimer_id anymore. This will go away once the
migration to dev-tree is completed. You may be better off storing the
oh_name in the clock_event_device name field and passing to the
suspend/resume handlers.

Cheers
Jon
Hunter, Jon Jan. 17, 2013, 6:45 p.m. UTC | #4
On 01/10/2013 10:37 PM, Bedia, Vaibhav wrote:
> On Tue, Jan 08, 2013 at 20:45:10, Shilimkar, Santosh wrote:
>> On Monday 31 December 2012 06:37 PM, Vaibhav Bedia wrote:
>>> The current OMAP timer code registers two timers -
>>> one as clocksource and one as clockevent.
>>> AM33XX has only one usable timer in the WKUP domain
>>> so one of the timers needs suspend-resume support
>>> to restore the configuration to pre-suspend state.
>>>
>>> commit adc78e6 (timekeeping: Add suspend and resume
>>> of clock event devices) introduced .suspend and .resume
>>> callbacks for clock event devices. Leverages these
>>> callbacks to have AM33XX clockevent timer which is
>>> in not in WKUP domain to behave properly across system
>>> suspend.
>>>
>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>> Cc: Benoit Cousson <b-cousson@ti.com>
>>> Cc: Paul Walmsley <paul@pwsan.com>
>>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>>> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
>>> Cc: Jon Hunter <jon-hunter@ti.com>
>>> ---
>>> v1->v2:
>>> 	Get rid of harcoded timer id.
>>> 	Note: since a platform device is not created for these timer
>>> 	instances and because there's very minimal change needed for
>>> 	restarting the timer a full blown context save and restore
>>> 	has been skipped.
>>>
>>>   arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
>>>   1 files changed, 33 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>>> index 691aa67..38f9cbc 100644
>>> --- a/arch/arm/mach-omap2/timer.c
>>> +++ b/arch/arm/mach-omap2/timer.c
>>> @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>>>   	}
>>>   }
>>>
>>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
>>> +{
>>> +	char name[10];
>>> +	struct omap_hwmod *oh;
>>> +
>>> +	sprintf(name, "timer%d", clkev.id);
>>> +	oh = omap_hwmod_lookup(name);
>>> +	if (!oh)
>>> +		return;
>>> +
>>> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
>>> +	omap_hwmod_idle(oh);
>>> +}
>>> +
>>> +static void omap_clkevt_resume(struct clock_event_device *unused)
>>> +{
>>> +	char name[10];
>>> +	struct omap_hwmod *oh;
>>> +
>>> +	sprintf(name, "timer%d", clkev.id);
>>> +	oh = omap_hwmod_lookup(name);
>>> +	if (!oh)
>>> +		return;
>>> +
>>> +	omap_hwmod_enable(oh);
>>> +	__omap_dm_timer_load_start(&clkev,
>>> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
>>> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
>>> +}
>>> +
>> Am still bit uncomfortable with direct hwmod usage in the suspend/resmue
>> hooks.
>>
>> Jon, Any alternatives you can think of ?
>>
> 
> Jon,
> 
> Any suggestions here?

Sorry completed this missed this!

Unfortunately, I don't have any good suggestions here. However, I am
wondering if the suspend/resume handlers can just be calls to
omap_hwmod_idle/enable and we can remove these __omap_dm_timer_xxxx
calls (I don't think they are needed). Furthermore, my understanding is
this is only needed for AM335x (per the changelog), and so we should not
add suspend/resume handlers for all OMAP2+ based devices.

Cheers
Jon
Santosh Shilimkar Jan. 18, 2013, 5:25 a.m. UTC | #5
On Friday 18 January 2013 12:15 AM, Jon Hunter wrote:
>
> On 01/10/2013 10:37 PM, Bedia, Vaibhav wrote:
>> On Tue, Jan 08, 2013 at 20:45:10, Shilimkar, Santosh wrote:
>>> On Monday 31 December 2012 06:37 PM, Vaibhav Bedia wrote:
>>>> The current OMAP timer code registers two timers -
>>>> one as clocksource and one as clockevent.
>>>> AM33XX has only one usable timer in the WKUP domain
>>>> so one of the timers needs suspend-resume support
>>>> to restore the configuration to pre-suspend state.
>>>>
>>>> commit adc78e6 (timekeeping: Add suspend and resume
>>>> of clock event devices) introduced .suspend and .resume
>>>> callbacks for clock event devices. Leverages these
>>>> callbacks to have AM33XX clockevent timer which is
>>>> in not in WKUP domain to behave properly across system
>>>> suspend.
>>>>
>>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>> Cc: Benoit Cousson <b-cousson@ti.com>
>>>> Cc: Paul Walmsley <paul@pwsan.com>
>>>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>>>> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
>>>> Cc: Jon Hunter <jon-hunter@ti.com>
>>>> ---
>>>> v1->v2:
>>>> 	Get rid of harcoded timer id.
>>>> 	Note: since a platform device is not created for these timer
>>>> 	instances and because there's very minimal change needed for
>>>> 	restarting the timer a full blown context save and restore
>>>> 	has been skipped.
>>>>
>>>>    arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
>>>>    1 files changed, 33 insertions(+), 0 deletions(-)
>>>>
>>>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>>>> index 691aa67..38f9cbc 100644
>>>> --- a/arch/arm/mach-omap2/timer.c
>>>> +++ b/arch/arm/mach-omap2/timer.c
>>>> @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>>>>    	}
>>>>    }
>>>>
>>>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
>>>> +{
>>>> +	char name[10];
>>>> +	struct omap_hwmod *oh;
>>>> +
>>>> +	sprintf(name, "timer%d", clkev.id);
>>>> +	oh = omap_hwmod_lookup(name);
>>>> +	if (!oh)
>>>> +		return;
>>>> +
>>>> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
>>>> +	omap_hwmod_idle(oh);
>>>> +}
>>>> +
>>>> +static void omap_clkevt_resume(struct clock_event_device *unused)
>>>> +{
>>>> +	char name[10];
>>>> +	struct omap_hwmod *oh;
>>>> +
>>>> +	sprintf(name, "timer%d", clkev.id);
>>>> +	oh = omap_hwmod_lookup(name);
>>>> +	if (!oh)
>>>> +		return;
>>>> +
>>>> +	omap_hwmod_enable(oh);
>>>> +	__omap_dm_timer_load_start(&clkev,
>>>> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
>>>> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
>>>> +}
>>>> +
>>> Am still bit uncomfortable with direct hwmod usage in the suspend/resmue
>>> hooks.
>>>
>>> Jon, Any alternatives you can think of ?
>>>
>>
>> Jon,
>>
>> Any suggestions here?
>
> Sorry completed this missed this!
>
> Unfortunately, I don't have any good suggestions here. However, I am
> wondering if the suspend/resume handlers can just be calls to
> omap_hwmod_idle/enable and we can remove these __omap_dm_timer_xxxx
> calls (I don't think they are needed). Furthermore, my understanding is
> this is only needed for AM335x (per the changelog), and so we should not
> add suspend/resume handlers for all OMAP2+ based devices.
>
I agree with the direction.

Regards,
Santosh
Vaibhav Bedia Jan. 21, 2013, 7:22 a.m. UTC | #6
Hi Jon,

On Fri, Jan 18, 2013 at 00:10:40, Hunter, Jon wrote:
> 
> On 12/31/2012 07:07 AM, Vaibhav Bedia wrote:
> > The current OMAP timer code registers two timers -
> > one as clocksource and one as clockevent.
> > AM33XX has only one usable timer in the WKUP domain
> > so one of the timers needs suspend-resume support
> > to restore the configuration to pre-suspend state.
> > 
> > commit adc78e6 (timekeeping: Add suspend and resume
> > of clock event devices) introduced .suspend and .resume
> > callbacks for clock event devices. Leverages these
> > callbacks to have AM33XX clockevent timer which is
> > in not in WKUP domain to behave properly across system
> > suspend.
> > 
> > Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> > Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> > Cc: Benoit Cousson <b-cousson@ti.com>
> > Cc: Paul Walmsley <paul@pwsan.com>
> > Cc: Kevin Hilman <khilman@deeprootsystems.com>
> > Cc: Vaibhav Hiremath <hvaibhav@ti.com>
> > Cc: Jon Hunter <jon-hunter@ti.com>
> > ---
> > v1->v2:
> > 	Get rid of harcoded timer id.
> > 	Note: since a platform device is not created for these timer
> > 	instances and because there's very minimal change needed for
> > 	restarting the timer a full blown context save and restore
> > 	has been skipped.
> > 
> >  arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
> >  1 files changed, 33 insertions(+), 0 deletions(-)
> > 
> > diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> > index 691aa67..38f9cbc 100644
> > --- a/arch/arm/mach-omap2/timer.c
> > +++ b/arch/arm/mach-omap2/timer.c
> > @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
> >  	}
> >  }
> >  
> > +static void omap_clkevt_suspend(struct clock_event_device *unused)
> > +{
> > +	char name[10];
> > +	struct omap_hwmod *oh;
> > +
> > +	sprintf(name, "timer%d", clkev.id);
> > +	oh = omap_hwmod_lookup(name);
> > +	if (!oh)
> > +		return;
> > +
> > +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
> 
> I am not sure you need to call __omap_dm_timer_stop() here. This should
> have already been called as timekeeping_suspend() will call
> omap2_gp_timer_set_mode() to shutdown the timer.

You are right, i can drop the call to __omap_dm_timer_stop().

> 
> > +	omap_hwmod_idle(oh);
> > +}
> > +
> > +static void omap_clkevt_resume(struct clock_event_device *unused)
> > +{
> > +	char name[10];
> > +	struct omap_hwmod *oh;
> > +
> > +	sprintf(name, "timer%d", clkev.id);
> > +	oh = omap_hwmod_lookup(name);
> > +	if (!oh)
> > +		return;
> > +
> > +	omap_hwmod_enable(oh);
> > +	__omap_dm_timer_load_start(&clkev,
> > +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> > +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> 
> Similarly here, I am not sure these __omap_dm_timer_xxxx calls are needed.

I went through the code again. __omap_dm_timer_load_start() is invoked
from omap2_gp_timer_set_mode() with the auto-reload flag when setting the
mode to CLOCK_EVT_MODE_PERIODIC and without the auto-reload flag in
omap2_gp_timer_set_next_event(). So looks like this call can be dropped.
But I do need the call to __omap_dm_timer_int_enable() to re-enable the
interrupts from the timer.

> 
> > +}
> > +
> >  static struct clock_event_device clockevent_gpt = {
> >  	.name		= "gp_timer",
> >  	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
> > @@ -135,6 +165,8 @@ static struct clock_event_device clockevent_gpt = {
> >  	.rating		= 300,
> >  	.set_next_event	= omap2_gp_timer_set_next_event,
> >  	.set_mode	= omap2_gp_timer_set_mode,
> > +	.suspend	= omap_clkevt_suspend,
> > +	.resume		= omap_clkevt_resume,
> 
> AFAIK, this is only applicable for AM335x devices and so should not be
> added for all.
> 

Agreed. Will address this in the next version.

> >  };
> >  
> >  static struct property device_disabled = {
> > @@ -323,6 +355,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
> >  	int res;
> >  
> >  	clkev.errata = omap_dm_timer_get_errata();
> > +	clkev.id = gptimer_id;
> 
> We should not use gptimer_id anymore. This will go away once the
> migration to dev-tree is completed. You may be better off storing the
> oh_name in the clock_event_device name field and passing to the
> suspend/resume handlers.
> 

Currently the name field in clock_event_device is set to "gp_timer". Should I set
the name in omap2_gp_clockevent_init() based on the gptimer_id?

Regards,
Vaibhav
Vaibhav Bedia Jan. 21, 2013, 7:22 a.m. UTC | #7
On Fri, Jan 18, 2013 at 10:55:43, Shilimkar, Santosh wrote:
> On Friday 18 January 2013 12:15 AM, Jon Hunter wrote:
> >
> > On 01/10/2013 10:37 PM, Bedia, Vaibhav wrote:
> >> On Tue, Jan 08, 2013 at 20:45:10, Shilimkar, Santosh wrote:
> >>> On Monday 31 December 2012 06:37 PM, Vaibhav Bedia wrote:
> >>>> The current OMAP timer code registers two timers -
> >>>> one as clocksource and one as clockevent.
> >>>> AM33XX has only one usable timer in the WKUP domain
> >>>> so one of the timers needs suspend-resume support
> >>>> to restore the configuration to pre-suspend state.
> >>>>
> >>>> commit adc78e6 (timekeeping: Add suspend and resume
> >>>> of clock event devices) introduced .suspend and .resume
> >>>> callbacks for clock event devices. Leverages these
> >>>> callbacks to have AM33XX clockevent timer which is
> >>>> in not in WKUP domain to behave properly across system
> >>>> suspend.
> >>>>
> >>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
> >>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
> >>>> Cc: Benoit Cousson <b-cousson@ti.com>
> >>>> Cc: Paul Walmsley <paul@pwsan.com>
> >>>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
> >>>> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
> >>>> Cc: Jon Hunter <jon-hunter@ti.com>
> >>>> ---
> >>>> v1->v2:
> >>>> 	Get rid of harcoded timer id.
> >>>> 	Note: since a platform device is not created for these timer
> >>>> 	instances and because there's very minimal change needed for
> >>>> 	restarting the timer a full blown context save and restore
> >>>> 	has been skipped.
> >>>>
> >>>>    arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
> >>>>    1 files changed, 33 insertions(+), 0 deletions(-)
> >>>>
> >>>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> >>>> index 691aa67..38f9cbc 100644
> >>>> --- a/arch/arm/mach-omap2/timer.c
> >>>> +++ b/arch/arm/mach-omap2/timer.c
> >>>> @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
> >>>>    	}
> >>>>    }
> >>>>
> >>>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
> >>>> +{
> >>>> +	char name[10];
> >>>> +	struct omap_hwmod *oh;
> >>>> +
> >>>> +	sprintf(name, "timer%d", clkev.id);
> >>>> +	oh = omap_hwmod_lookup(name);
> >>>> +	if (!oh)
> >>>> +		return;
> >>>> +
> >>>> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
> >>>> +	omap_hwmod_idle(oh);
> >>>> +}
> >>>> +
> >>>> +static void omap_clkevt_resume(struct clock_event_device *unused)
> >>>> +{
> >>>> +	char name[10];
> >>>> +	struct omap_hwmod *oh;
> >>>> +
> >>>> +	sprintf(name, "timer%d", clkev.id);
> >>>> +	oh = omap_hwmod_lookup(name);
> >>>> +	if (!oh)
> >>>> +		return;
> >>>> +
> >>>> +	omap_hwmod_enable(oh);
> >>>> +	__omap_dm_timer_load_start(&clkev,
> >>>> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
> >>>> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
> >>>> +}
> >>>> +
> >>> Am still bit uncomfortable with direct hwmod usage in the suspend/resmue
> >>> hooks.
> >>>
> >>> Jon, Any alternatives you can think of ?
> >>>
> >>
> >> Jon,
> >>
> >> Any suggestions here?
> >
> > Sorry completed this missed this!
> >
> > Unfortunately, I don't have any good suggestions here. However, I am
> > wondering if the suspend/resume handlers can just be calls to
> > omap_hwmod_idle/enable and we can remove these __omap_dm_timer_xxxx
> > calls (I don't think they are needed). Furthermore, my understanding is
> > this is only needed for AM335x (per the changelog), and so we should not
> > add suspend/resume handlers for all OMAP2+ based devices.
> >
> I agree with the direction.
> 

I need to retain the call to enable the interrupt but the others can be dropped.
Will take care of this and the comment on invoking the suspend/resume handlers
only for AM335x in the next version.

Regards,
Vaibhav
Hunter, Jon Jan. 30, 2013, 5:46 p.m. UTC | #8
On 01/21/2013 01:22 AM, Bedia, Vaibhav wrote:
> On Fri, Jan 18, 2013 at 10:55:43, Shilimkar, Santosh wrote:
>> On Friday 18 January 2013 12:15 AM, Jon Hunter wrote:
>>>
>>> On 01/10/2013 10:37 PM, Bedia, Vaibhav wrote:
>>>> On Tue, Jan 08, 2013 at 20:45:10, Shilimkar, Santosh wrote:
>>>>> On Monday 31 December 2012 06:37 PM, Vaibhav Bedia wrote:
>>>>>> The current OMAP timer code registers two timers -
>>>>>> one as clocksource and one as clockevent.
>>>>>> AM33XX has only one usable timer in the WKUP domain
>>>>>> so one of the timers needs suspend-resume support
>>>>>> to restore the configuration to pre-suspend state.
>>>>>>
>>>>>> commit adc78e6 (timekeeping: Add suspend and resume
>>>>>> of clock event devices) introduced .suspend and .resume
>>>>>> callbacks for clock event devices. Leverages these
>>>>>> callbacks to have AM33XX clockevent timer which is
>>>>>> in not in WKUP domain to behave properly across system
>>>>>> suspend.
>>>>>>
>>>>>> Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
>>>>>> Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
>>>>>> Cc: Benoit Cousson <b-cousson@ti.com>
>>>>>> Cc: Paul Walmsley <paul@pwsan.com>
>>>>>> Cc: Kevin Hilman <khilman@deeprootsystems.com>
>>>>>> Cc: Vaibhav Hiremath <hvaibhav@ti.com>
>>>>>> Cc: Jon Hunter <jon-hunter@ti.com>
>>>>>> ---
>>>>>> v1->v2:
>>>>>> 	Get rid of harcoded timer id.
>>>>>> 	Note: since a platform device is not created for these timer
>>>>>> 	instances and because there's very minimal change needed for
>>>>>> 	restarting the timer a full blown context save and restore
>>>>>> 	has been skipped.
>>>>>>
>>>>>>    arch/arm/mach-omap2/timer.c |   33 +++++++++++++++++++++++++++++++++
>>>>>>    1 files changed, 33 insertions(+), 0 deletions(-)
>>>>>>
>>>>>> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
>>>>>> index 691aa67..38f9cbc 100644
>>>>>> --- a/arch/arm/mach-omap2/timer.c
>>>>>> +++ b/arch/arm/mach-omap2/timer.c
>>>>>> @@ -128,6 +128,36 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
>>>>>>    	}
>>>>>>    }
>>>>>>
>>>>>> +static void omap_clkevt_suspend(struct clock_event_device *unused)
>>>>>> +{
>>>>>> +	char name[10];
>>>>>> +	struct omap_hwmod *oh;
>>>>>> +
>>>>>> +	sprintf(name, "timer%d", clkev.id);
>>>>>> +	oh = omap_hwmod_lookup(name);
>>>>>> +	if (!oh)
>>>>>> +		return;
>>>>>> +
>>>>>> +	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
>>>>>> +	omap_hwmod_idle(oh);
>>>>>> +}
>>>>>> +
>>>>>> +static void omap_clkevt_resume(struct clock_event_device *unused)
>>>>>> +{
>>>>>> +	char name[10];
>>>>>> +	struct omap_hwmod *oh;
>>>>>> +
>>>>>> +	sprintf(name, "timer%d", clkev.id);
>>>>>> +	oh = omap_hwmod_lookup(name);
>>>>>> +	if (!oh)
>>>>>> +		return;
>>>>>> +
>>>>>> +	omap_hwmod_enable(oh);
>>>>>> +	__omap_dm_timer_load_start(&clkev,
>>>>>> +			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
>>>>>> +	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
>>>>>> +}
>>>>>> +
>>>>> Am still bit uncomfortable with direct hwmod usage in the suspend/resmue
>>>>> hooks.
>>>>>
>>>>> Jon, Any alternatives you can think of ?
>>>>>
>>>>
>>>> Jon,
>>>>
>>>> Any suggestions here?
>>>
>>> Sorry completed this missed this!
>>>
>>> Unfortunately, I don't have any good suggestions here. However, I am
>>> wondering if the suspend/resume handlers can just be calls to
>>> omap_hwmod_idle/enable and we can remove these __omap_dm_timer_xxxx
>>> calls (I don't think they are needed). Furthermore, my understanding is
>>> this is only needed for AM335x (per the changelog), and so we should not
>>> add suspend/resume handlers for all OMAP2+ based devices.
>>>
>> I agree with the direction.
>>
> 
> I need to retain the call to enable the interrupt but the others can be dropped.
> Will take care of this and the comment on invoking the suspend/resume handlers
> only for AM335x in the next version.

Ok fair enough. By the way, I posted a patch today [1] that will use the
hwmod name as the clockevent timer name. Care to try on top of that
patch and then we can eliminate the sprintf.

Cheers
Jon

[1] http://www.spinics.net/lists/arm-kernel/msg221262.html
Vaibhav Bedia Jan. 31, 2013, 11:17 a.m. UTC | #9
On Wed, Jan 30, 2013 at 23:16:34, Hunter, Jon wrote:
> 
> Ok fair enough. By the way, I posted a patch today [1] that will use the
> hwmod name as the clockevent timer name. Care to try on top of that
> patch and then we can eliminate the sprintf.
> 

Thanks. Will try it out later today.

Regards,
Vaibhav
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 691aa67..38f9cbc 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -128,6 +128,36 @@  static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 	}
 }
 
+static void omap_clkevt_suspend(struct clock_event_device *unused)
+{
+	char name[10];
+	struct omap_hwmod *oh;
+
+	sprintf(name, "timer%d", clkev.id);
+	oh = omap_hwmod_lookup(name);
+	if (!oh)
+		return;
+
+	__omap_dm_timer_stop(&clkev, 1, clkev.rate);
+	omap_hwmod_idle(oh);
+}
+
+static void omap_clkevt_resume(struct clock_event_device *unused)
+{
+	char name[10];
+	struct omap_hwmod *oh;
+
+	sprintf(name, "timer%d", clkev.id);
+	oh = omap_hwmod_lookup(name);
+	if (!oh)
+		return;
+
+	omap_hwmod_enable(oh);
+	__omap_dm_timer_load_start(&clkev,
+			OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR, 0, 1);
+	__omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
+}
+
 static struct clock_event_device clockevent_gpt = {
 	.name		= "gp_timer",
 	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
@@ -135,6 +165,8 @@  static struct clock_event_device clockevent_gpt = {
 	.rating		= 300,
 	.set_next_event	= omap2_gp_timer_set_next_event,
 	.set_mode	= omap2_gp_timer_set_mode,
+	.suspend	= omap_clkevt_suspend,
+	.resume		= omap_clkevt_resume,
 };
 
 static struct property device_disabled = {
@@ -323,6 +355,7 @@  static void __init omap2_gp_clockevent_init(int gptimer_id,
 	int res;
 
 	clkev.errata = omap_dm_timer_get_errata();
+	clkev.id = gptimer_id;
 
 	/*
 	 * For clock-event timers we never read the timer counter and