[PATCH v2 05/14] ARM: integrator: use clocksource_of_init for sp804

Russell King - ARM Linux linux at arm.linux.org.uk
Fri Mar 15 08:15:54 EDT 2013


On Wed, Mar 13, 2013 at 10:00:14AM +0100, Linus Walleij wrote:
> Then the Integrator/AP timer has this code in the
> integrator_clockevent_init() function:
> 
> 	clkevt_base = base;
> 	/* Calculate and program a divisor */
> 	if (rate > 0x100000 * HZ) {
> 		rate /= 256;
> 		ctrl |= TIMER_CTRL_DIV256;
> 	} else if (rate > 0x10000 * HZ) {
> 		rate /= 16;
> 		ctrl |= TIMER_CTRL_DIV16;
> 	}
> 
> It appears the SP804 has no code to handle this
> divisor/prescaler at all. Which means that you regress
> the Integrator/AP again.
> 
> It appears (from arm_timer.h) that the SP804 actually
> has this prescaler, but then first make a separate patch
> to make the SP804 driver use that divisor (like above) so
> you don't degrade the quality of the AP timer. The prescaler
> make it possible to let the system sleep for longer times
> when using NO_HZ so it's *pretty* important (and it will
> increas the quality of all SP804-based machines as well).
> 
> As you surely understand, since the counter on the
> Integrator/AP is only 16 bit this is very important, since
> we don't want it to wake up too often.
> 
> Then the clocksource init function has this:
> 
> 	if (rate >= 1500000) {
> 		rate /= 16;
> 		ctrl |= TIMER_CTRL_DIV16;
> 	}
> 
> Here I'm more uncertain. As I know from extensive
> discussions with John and Thomas, there are many many
> factors to decide the clocksource. Basically the above lines
> limits the precision of the clocksource in exchange for a
> longer time until wrap-around. Again, the 16bit nature of the
> Integrator/AP timer is a factor here.

Integrator/AP selects the prescaler based on the fact that it is only a
16-bit counter, which has to be clocked at a rate which gives us our
desired periodic tick interval.

SP804 does not do this because, being a 32-bit counter, it is completely
unnecessary to use the prescaler - and using the prescaler will result
in loss of fine-grained timing accuracy.  Making use of the prescaler
there is absurd - the timer will run to 4000 odd seconds before wrapping
with a prescaler of 1.

You end up needing 64-bit arithmetic if you try to apply the Integrator/AP
logic to SP804 - it becomes this:

 	if (rate > 0x1000000000 * HZ) {
 		rate /= 256;
 		ctrl |= TIMER_CTRL_DIV256;
 	} else if (rate > 0x100000000 * HZ) {
 		rate /= 16;
 		ctrl |= TIMER_CTRL_DIV16;
 	}

or more precisely:
	if (rate > HZ * 0x100 * ((unsigned long long)wrap + 1)) {
...
 	} else if (rate > HZ * 0x10 * ((unsigned long long)wrap + 1)) {
...

You need that wrap value anyway for clockevents_config_and_register.



More information about the linux-arm-kernel mailing list