diff options
author | Michal Simek <monstr@monstr.eu> | 2010-10-07 03:39:21 -0400 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-10-21 01:52:00 -0400 |
commit | ccea0e6e49e4db8ee7968c183ecddb3e399c5f54 (patch) | |
tree | 387e07bf5e4eed3628c7361cdd7129cc0a31f250 /arch/microblaze | |
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>
Diffstat (limited to 'arch/microblaze')
-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 7fab800496ae..cd257537ae54 100644 --- a/arch/microblaze/include/asm/cpuinfo.h +++ b/arch/microblaze/include/asm/cpuinfo.h | |||
@@ -77,7 +77,6 @@ struct cpuinfo { | |||
77 | u32 num_rd_brk; | 77 | u32 num_rd_brk; |
78 | u32 num_wr_brk; | 78 | u32 num_wr_brk; |
79 | u32 cpu_clock_freq; /* store real freq of cpu */ | 79 | u32 cpu_clock_freq; /* store real freq of cpu */ |
80 | u32 freq_div_hz; /* store freq/HZ */ | ||
81 | 80 | ||
82 | /* FPGA family */ | 81 | /* FPGA family */ |
83 | u32 fpga_family_code; | 82 | u32 fpga_family_code; |
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index fcb97e86003d..a5aa33db1df3 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c | |||
@@ -38,6 +38,9 @@ static unsigned int timer_baseaddr; | |||
38 | #define TIMER_BASE timer_baseaddr | 38 | #define TIMER_BASE timer_baseaddr |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | unsigned int freq_div_hz; | ||
42 | unsigned int timer_clock_freq; | ||
43 | |||
41 | #define TCSR0 (0x00) | 44 | #define TCSR0 (0x00) |
42 | #define TLR0 (0x04) | 45 | #define TLR0 (0x04) |
43 | #define TCR0 (0x08) | 46 | #define TCR0 (0x08) |
@@ -115,7 +118,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode, | |||
115 | switch (mode) { | 118 | switch (mode) { |
116 | case CLOCK_EVT_MODE_PERIODIC: | 119 | case CLOCK_EVT_MODE_PERIODIC: |
117 | printk(KERN_INFO "%s: periodic\n", __func__); | 120 | printk(KERN_INFO "%s: periodic\n", __func__); |
118 | microblaze_timer0_start_periodic(cpuinfo.freq_div_hz); | 121 | microblaze_timer0_start_periodic(freq_div_hz); |
119 | break; | 122 | break; |
120 | case CLOCK_EVT_MODE_ONESHOT: | 123 | case CLOCK_EVT_MODE_ONESHOT: |
121 | printk(KERN_INFO "%s: oneshot\n", __func__); | 124 | printk(KERN_INFO "%s: oneshot\n", __func__); |
@@ -168,7 +171,7 @@ static struct irqaction timer_irqaction = { | |||
168 | static __init void microblaze_clockevent_init(void) | 171 | static __init void microblaze_clockevent_init(void) |
169 | { | 172 | { |
170 | clockevent_microblaze_timer.mult = | 173 | clockevent_microblaze_timer.mult = |
171 | div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, | 174 | div_sc(timer_clock_freq, NSEC_PER_SEC, |
172 | clockevent_microblaze_timer.shift); | 175 | clockevent_microblaze_timer.shift); |
173 | clockevent_microblaze_timer.max_delta_ns = | 176 | clockevent_microblaze_timer.max_delta_ns = |
174 | clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer); | 177 | clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer); |
@@ -201,7 +204,7 @@ static struct cyclecounter microblaze_cc = { | |||
201 | 204 | ||
202 | int __init init_microblaze_timecounter(void) | 205 | int __init init_microblaze_timecounter(void) |
203 | { | 206 | { |
204 | microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC, | 207 | microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC, |
205 | microblaze_cc.shift); | 208 | microblaze_cc.shift); |
206 | 209 | ||
207 | timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); | 210 | timecounter_init(µblaze_tc, µblaze_cc, sched_clock()); |
@@ -221,7 +224,7 @@ static struct clocksource clocksource_microblaze = { | |||
221 | static int __init microblaze_clocksource_init(void) | 224 | static int __init microblaze_clocksource_init(void) |
222 | { | 225 | { |
223 | clocksource_microblaze.mult = | 226 | clocksource_microblaze.mult = |
224 | clocksource_hz2mult(cpuinfo.cpu_clock_freq, | 227 | clocksource_hz2mult(timer_clock_freq, |
225 | clocksource_microblaze.shift); | 228 | clocksource_microblaze.shift); |
226 | if (clocksource_register(&clocksource_microblaze)) | 229 | if (clocksource_register(&clocksource_microblaze)) |
227 | panic("failed to register clocksource"); | 230 | panic("failed to register clocksource"); |
@@ -247,6 +250,7 @@ void __init time_init(void) | |||
247 | u32 irq, i = 0; | 250 | u32 irq, i = 0; |
248 | u32 timer_num = 1; | 251 | u32 timer_num = 1; |
249 | struct device_node *timer = NULL; | 252 | struct device_node *timer = NULL; |
253 | const void *prop; | ||
250 | #ifdef CONFIG_SELFMOD_TIMER | 254 | #ifdef CONFIG_SELFMOD_TIMER |
251 | unsigned int timer_baseaddr = 0; | 255 | unsigned int timer_baseaddr = 0; |
252 | int arr_func[] = { | 256 | int arr_func[] = { |
@@ -286,7 +290,14 @@ void __init time_init(void) | |||
286 | printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n", | 290 | printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n", |
287 | timer_list[i], timer_baseaddr, irq); | 291 | timer_list[i], timer_baseaddr, irq); |
288 | 292 | ||
289 | cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ; | 293 | /* If there is clock-frequency property than use it */ |
294 | prop = of_get_property(timer, "clock-frequency", NULL); | ||
295 | if (prop) | ||
296 | timer_clock_freq = be32_to_cpup(prop); | ||
297 | else | ||
298 | timer_clock_freq = cpuinfo.cpu_clock_freq; | ||
299 | |||
300 | freq_div_hz = timer_clock_freq / HZ; | ||
290 | 301 | ||
291 | setup_irq(irq, &timer_irqaction); | 302 | setup_irq(irq, &timer_irqaction); |
292 | #ifdef CONFIG_HEART_BEAT | 303 | #ifdef CONFIG_HEART_BEAT |