[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