diff options
author | Michal Simek <monstr@monstr.eu> | 2010-10-07 17:39:21 +1000 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-10-21 15:52:00 +1000 |
commit | ccea0e6e49e4db8ee7968c183ecddb3e399c5f54 (patch) | |
tree | 387e07bf5e4eed3628c7361cdd7129cc0a31f250 | |
parent | 02b08045a0306c38131c6d7155c4034a775d40b1 (diff) |
microblaze: Support timer on AXI lite
New microblaze systems uses two buses. One for memories
and flashes and the second for low-speed peripherals
which can run on different CLK. This is the reason
why the kernel is trying to read clock-frequency
directly from node. If there is then the kernel will
work with it. If not then cpu CLK is used.
Signed-off-by: Michal Simek <monstr@monstr.eu>
-rw-r--r-- | arch/microblaze/include/asm/cpuinfo.h | 1 | ||||
-rw-r--r-- | arch/microblaze/kernel/timer.c | 21 |
2 files changed, 16 insertions, 6 deletions
diff --git a/arch/microblaze/include/asm/cpuinfo.h b/arch/microblaze/include/asm/cpuinfo.h index 7fab800496a..cd257537ae5 100644 --- a/arch/microblaze/include/asm/cpuinfo.h +++ b/arch/microblaze/include/asm/cpuinfo.h @@ -77,7 +77,6 @@ struct cpuinfo { u32 num_rd_brk; u32 num_wr_brk; u32 cpu_clock_freq; /* store real freq of cpu */ - u32 freq_div_hz; /* store freq/HZ */ /* FPGA family */ u32 fpga_family_code; diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index fcb97e86003..a5aa33db1df 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c @@ -38,6 +38,9 @@ static unsigned int timer_baseaddr; #define TIMER_BASE timer_baseaddr #endif +unsigned int freq_div_hz; +unsigned int timer_clock_freq; + #define TCSR0 (0x00) #define TLR0 (0x04) #define TCR0 (0x08) @@ -115,7 +118,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode, switch (mode) { case CLOCK_EVT_MODE_PERIODIC: printk(KERN_INFO "%s: periodic\n", __func__); - microblaze_timer0_start_periodic(cpuinfo.freq_div_hz); + microblaze_timer0_start_periodic(freq_div_hz); break; case CLOCK_EVT_MODE_ONESHOT: printk(KERN_INFO "%s: oneshot\n", __func__); @@ -168,7 +171,7 @@ static struct irqaction timer_irqaction = { static __init void microblaze_clockevent_init(void) { clockevent_microblaze_timer.mult = - div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, + div_sc(timer_clock_freq, NSEC_PER_SEC, clockevent_microblaze_timer.shift); clockevent_microblaze_timer.max_delta_ns = clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer); @@ -201,7 +204,7 @@ static struct cyclecounter microblaze_cc = { int __init init_microblaze_timecounter(void) { - microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, + microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, microblaze_cc.shift); timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); @@ -221,7 +224,7 @@ static struct clocksource clocksource_microblaze = { static int __init microblaze_clocksource_init(void) { clocksource_microblaze.mult = - clocksource_hz2mult(cpuinfo.cpu_clock_freq, + clocksource_hz2mult(timer_clock_freq, clocksource_microblaze.shift); if (clocksource_register(&clocksource_microblaze)) panic("failed to register clocksource"); @@ -247,6 +250,7 @@ void __init time_init(void) u32 irq, i = 0; u32 timer_num = 1; struct device_node *timer = NULL; + const void *prop; #ifdef CONFIG_SELFMOD_TIMER unsigned int timer_baseaddr = 0; int arr_func[] = { @@ -286,7 +290,14 @@ void __init time_init(void) printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n", timer_list[i], timer_baseaddr, irq); - cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ; + /* If there is clock-frequency property than use it */ + prop = of_get_property(timer, "clock-frequency", NULL); + if (prop) + timer_clock_freq = be32_to_cpup(prop); + else + timer_clock_freq = cpuinfo.cpu_clock_freq; + + freq_div_hz = timer_clock_freq / HZ; setup_irq(irq, &timer_irqaction); #ifdef CONFIG_HEART_BEAT |