[PATCH-V3 3/3] ARM: OMAP: Make OMAP clocksource source selection using kernel param

Hiremath, Vaibhav hvaibhav at ti.com
Mon Apr 23 13:35:19 EDT 2012


On Fri, Apr 20, 2012 at 06:04:20, Hilman, Kevin wrote:
> Vaibhav Hiremath <hvaibhav at ti.com> writes:
> 

Thanks Kevin for the review comments and sorry for delayed response... 
Please find my response in-lined below -


> > Current OMAP code supports couple of clocksource options based
> > on compilation flag (CONFIG_OMAP_32K_TIMER). The 32KHz sync-timer
> > and a gptimer which can run on 32KHz or system clock (e.g 38.4 MHz).
> > So there can be 3 options -
> >
> > 1. 32KHz sync-timer
> > 2. Sys_clock based (e.g 13/19.2/26/38.4 MHz) gptimer
> > 3. 32KHz based gptimer.
> >
> > The optional gptimer based clocksource was added so that it can
> > give the high precision than sync-timer, so expected usage was 2
> > and not 3.
> > Unfortunately option 2, clocksource doesn't meet the requirement of
> > free-running clock as per clocksource need. It stops in low power states
> > when sys_clock is cut. That makes gptimer based clocksource option
> > useless for OMAP2/3/4 devices with sys_clock as a clock input.
> > Option 3 will still work but it is no better than 32K sync-timer
> > based clocksource.
> >
> > So ideally we can kill the gptimer based clocksource option but there
> > are some OMAP based derivative SoCs like AM33XX which doesn't have
> > 32K sync-timer hardware IP and need to fallback on 32KHz based gptimer
> > clocksource.
> > Considering above, make sync-timer and gptimer clocksource runtime
> > selectable so that both OMAP and AMXXXX continue to use the same code.
> >
> > Also, in order to precisely configure/setup sched_clock for given
> > clocksource, decision has to be made early enough in boot sequence.
> >
> > So, the solution is,
> >
> > Use kernel parameter ("clocksource=") to override
> > default 32k_sync-timer, in addition to this, we also use hwmod database
> > lookup mechanism, through which at run-time we can identify availability
> > of 32k-sync timer on the device, else fall back to gptimer.
> >
> > Signed-off-by: Vaibhav Hiremath <hvaibhav at ti.com>
> > Signed-off-by: Felipe Balbi <balbi at ti.com>
> > CC: Santosh Shilimkar <santosh.shilimkar at ti.com>
> > Cc: Benoit Cousson <b-cousson at ti.com>
> > Cc: Tony Lindgren <tony at atomide.com>
> > Cc: Paul Walmsley <paul at pwsan.com>
> > Cc: Tarun Kanti DebBarma <tarun.kanti at ti.com>
> > Cc: Ming Lei <tom.leiming at gmail.com>
> 
> [...]
> 
> > @@ -285,7 +273,32 @@ static u32 notrace dmtimer_read_sched_clock(void)
> >  }
> >
> >  /* Setup free-running counter for clocksource */
> > -static void __init omap2_gp_clocksource_init(int gptimer_id,
> > +static int __init omap2_sync32k_clocksource_init(void)
> > +{
> > +	int res;
> > +	u32 pbase, size;
> > +	struct omap_hwmod *oh;
> > +	struct resource mem_rsrc;
> 
> minor nit: personaly, I find 'rsrc' hard on the eyes.  I suggest just
> using 'res' for this variable name.
> 

Ok, I will change it accordingly.


> > +	const char *oh_name = "counter_32k";
> > +	oh = omap_hwmod_lookup(oh_name);
> > +	if (!oh || oh->slaves_cnt == 0)
> > +		return -ENODEV;
> > +
> > +	res = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM,
> > +				NULL, &mem_rsrc);
> > +	if (!res) {
> > +		pbase = mem_rsrc.start + OMAP2_32KSYNCNT_CR_OFF;
> > +		size = mem_rsrc.end - mem_rsrc.start;
> 
> This should be (end - start + 1), but instead, use the resource_size()
> helper should be used for this.
> 

Good point. I will change this for resource_size().


> Also note that because you're adding an offset of 0x10 to the start, the
> ioremap later is actually mapping 0x10 past the end.  More on the base
> address later...
> 

Comment on top of this code will enough, isn't it?


> > +
> > +		res = omap_init_clocksource_32k(pbase, size);
> > +	}
> > +
> > +	WARN_ON(res);
> 
> Just use pr_warn() here instead of WARN_ON() which will dump a full
> backtrace, and isn't necessary.
> 

Ok, will change it.

> [...]
> 
> > @@ -510,3 +541,28 @@ static int __init omap2_dm_timer_init(void)
> >  	return 0;
> >  }
> >  arch_initcall(omap2_dm_timer_init);
> > +
> > +/**
> > + * omap2_override_clocksource - clocksource override with user configuration
> > + *
> > + * Allows user to override default clocksource, using kernel parameter
> > + *   clocksource="gp timer"
> > + *
> > + * Note that, here we are using same standard kernel parameter "clocksource=",
> > + * and not introducing any OMAP specific interface.
> > + */
> 
> Are you sure the clocksource= setup function is getting called in
> kernel/time/clocksource.c as well?  IOW, do both the generic one and
> this one get called?
> 

Yes, 100%.

> To be honest, I still don't like this.  The clocksource core will
> already sets the right clocksource, and this is duplicating that.
> 
> I do see why you're doing this though because both clocksource init
> functions call setup_sched_clock().
> 
> Ideally, we would just wait to call setup_sched_clock() until later
> (possibly in a late_initcall) after the clocksource selection is
> decided.   I'm not sure we have the right hooks to do that though.
> 
> Possibly by setting a flag in the ->enable method of each clocksource,
> and checking that in a late_initcall before calling setup_sched_clock.
> That would be easy for the GP timer, but the 32k timer is setting up an
> mmio clocksource, so we don't have an ->enable method.
> 
> Any other ideas?
> 

Based on all the discussion we had on this, I believe we do not have any 
other option here; this is the only solution we could come up with.


> [...]
> 
> > diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
> > index 5068fe5..bd4a3fd 100644
> > --- a/arch/arm/plat-omap/counter_32k.c
> > +++ b/arch/arm/plat-omap/counter_32k.c
> > @@ -35,8 +35,6 @@
> >   */
> >  static void __iomem *timer_32k_base;
> >
> > -#define OMAP16XX_TIMER_32K_SYNCHRONIZED		0xfffbc410
> > -
> >  static u32 notrace omap_32k_read_sched_clock(void)
> >  {
> >  	return timer_32k_base ? __raw_readl(timer_32k_base) : 0;
> > @@ -68,54 +66,43 @@ void read_persistent_clock(struct timespec *ts)
> >  	*ts = *tsp;
> >  }
> >
> > -int __init omap_init_clocksource_32k(void)
> > +int __init omap_init_clocksource_32k(u32 pbase, unsigned long size)
> 
> Now that this takes some arguments, this function wants some kerneldoc.
> 

Should I create new documentation inside Documentation/arm/OMAP/
with name "counter_32k"?

> In particular, you should document that 'pbase' is the address of the
> counter register, not the base of the IP.
> 
> That being said, I think the pbase passed in should probably be the base
> of the IP register, not the address of the counter register. It seems to
> me that it's at offset 0x10 on all SoCs anyways.
> 
> Doing that will also ensure that the ioremap'd range covers the whole
> IP, and not from the counter register to 0x10 past the end.
> 

Yeah, you are right, I can get rid of this offset and move it to 
counter_32k.c file.

Thanks,
Vaibhav

> Kevin
> 




More information about the linux-arm-kernel mailing list