Skip to content

Commit

Permalink
powerpc: Fix decrementer setup on 1GHz boards
Browse files Browse the repository at this point in the history
We noticed that recent kernels didn't boot on our 1GHz Canyonlands 460EX
boards anymore. As it seems, patch 8d165db [powerpc: Improve
decrementer accuracy] introduced this problem. The routine div_sc()
overflows with shift = 32 resulting in this incorrect setup:

time_init: decrementer frequency = 1000.000012 MHz
time_init: processor frequency   = 1000.000012 MHz
clocksource: timebase mult[400000] shift[22] registered
clockevent: decrementer mult[33] shift[32] cpu[0]

This patch now introduces a local div_dc64() version of this function
so that this overflow doesn't happen anymore.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Detlev Zundel <dzu@denx.de>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Stefan Roese authored and Benjamin Herrenschmidt committed Jan 15, 2010
1 parent b0ff153 commit 3e7b484
Showing 1 changed file with 10 additions and 1 deletion.
11 changes: 10 additions & 1 deletion arch/powerpc/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,12 +903,21 @@ static void decrementer_set_mode(enum clock_event_mode mode,
decrementer_set_next_event(DECREMENTER_MAX, dev);
}

static inline uint64_t div_sc64(unsigned long ticks, unsigned long nsec,
int shift)
{
uint64_t tmp = ((uint64_t)ticks) << shift;

do_div(tmp, nsec);
return tmp;
}

static void __init setup_clockevent_multiplier(unsigned long hz)
{
u64 mult, shift = 32;

while (1) {
mult = div_sc(hz, NSEC_PER_SEC, shift);
mult = div_sc64(hz, NSEC_PER_SEC, shift);
if (mult && (mult >> 32UL) == 0UL)
break;

Expand Down

0 comments on commit 3e7b484

Please sign in to comment.