diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2013-05-13 13:07:32 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-06-11 18:47:35 -0400 |
commit | c99f72addbf5c0ad37d5a9b26f99208464d35f5c (patch) | |
tree | f86803ce60ba8969740b51e71aa26d8685d5468a /arch/arm/mach-clps711x | |
parent | d0ad52a6fa9018d18076a887898f7912ae91f246 (diff) |
ARM: clps711x: Add clocksource framework
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch/arm/mach-clps711x')
-rw-r--r-- | arch/arm/mach-clps711x/common.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c index 768d41c68cea..bd658398a819 100644 --- a/arch/arm/mach-clps711x/common.c +++ b/arch/arm/mach-clps711x/common.c | |||
@@ -27,12 +27,14 @@ | |||
27 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
28 | #include <linux/clkdev.h> | 28 | #include <linux/clkdev.h> |
29 | #include <linux/clockchips.h> | 29 | #include <linux/clockchips.h> |
30 | #include <linux/clocksource.h> | ||
30 | #include <linux/clk-provider.h> | 31 | #include <linux/clk-provider.h> |
31 | 32 | ||
32 | #include <asm/exception.h> | 33 | #include <asm/exception.h> |
33 | #include <asm/mach/irq.h> | 34 | #include <asm/mach/irq.h> |
34 | #include <asm/mach/map.h> | 35 | #include <asm/mach/map.h> |
35 | #include <asm/mach/time.h> | 36 | #include <asm/mach/time.h> |
37 | #include <asm/sched_clock.h> | ||
36 | #include <asm/system_misc.h> | 38 | #include <asm/system_misc.h> |
37 | 39 | ||
38 | #include <mach/hardware.h> | 40 | #include <mach/hardware.h> |
@@ -251,13 +253,32 @@ asmlinkage void __exception_irq_entry clps711x_handle_irq(struct pt_regs *regs) | |||
251 | handle_IRQ(fls16(irqstat) + 16, regs); | 253 | handle_IRQ(fls16(irqstat) + 16, regs); |
252 | } | 254 | } |
253 | 255 | ||
256 | static u32 notrace clps711x_sched_clock_read(void) | ||
257 | { | ||
258 | return ~readw_relaxed(CLPS711X_VIRT_BASE + TC1D); | ||
259 | } | ||
260 | |||
254 | static void clps711x_clockevent_set_mode(enum clock_event_mode mode, | 261 | static void clps711x_clockevent_set_mode(enum clock_event_mode mode, |
255 | struct clock_event_device *evt) | 262 | struct clock_event_device *evt) |
256 | { | 263 | { |
264 | disable_irq(IRQ_TC2OI); | ||
265 | |||
266 | switch (mode) { | ||
267 | case CLOCK_EVT_MODE_PERIODIC: | ||
268 | enable_irq(IRQ_TC2OI); | ||
269 | break; | ||
270 | case CLOCK_EVT_MODE_ONESHOT: | ||
271 | /* Not supported */ | ||
272 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
273 | case CLOCK_EVT_MODE_UNUSED: | ||
274 | case CLOCK_EVT_MODE_RESUME: | ||
275 | /* Left event sources disabled, no more interrupts appear */ | ||
276 | break; | ||
277 | } | ||
257 | } | 278 | } |
258 | 279 | ||
259 | static struct clock_event_device clockevent_clps711x = { | 280 | static struct clock_event_device clockevent_clps711x = { |
260 | .name = "CLPS711x Clockevents", | 281 | .name = "clps711x-clockevent", |
261 | .rating = 300, | 282 | .rating = 300, |
262 | .features = CLOCK_EVT_FEAT_PERIODIC, | 283 | .features = CLOCK_EVT_FEAT_PERIODIC, |
263 | .set_mode = clps711x_clockevent_set_mode, | 284 | .set_mode = clps711x_clockevent_set_mode, |
@@ -271,8 +292,8 @@ static irqreturn_t clps711x_timer_interrupt(int irq, void *dev_id) | |||
271 | } | 292 | } |
272 | 293 | ||
273 | static struct irqaction clps711x_timer_irq = { | 294 | static struct irqaction clps711x_timer_irq = { |
274 | .name = "CLPS711x Timer Tick", | 295 | .name = "clps711x-timer", |
275 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 296 | .flags = IRQF_TIMER | IRQF_IRQPOLL, |
276 | .handler = clps711x_timer_interrupt, | 297 | .handler = clps711x_timer_interrupt, |
277 | }; | 298 | }; |
278 | 299 | ||
@@ -320,9 +341,9 @@ void __init clps711x_timer_init(void) | |||
320 | else | 341 | else |
321 | timh = 541440; | 342 | timh = 541440; |
322 | } else | 343 | } else |
323 | timh = cpu / 144; | 344 | timh = DIV_ROUND_CLOSEST(cpu, 144); |
324 | 345 | ||
325 | timl = timh / 256; | 346 | timl = DIV_ROUND_CLOSEST(timh, 256); |
326 | 347 | ||
327 | /* All clocks are fixed */ | 348 | /* All clocks are fixed */ |
328 | add_fixed_clk(clk_pll, "pll", pll); | 349 | add_fixed_clk(clk_pll, "pll", pll); |
@@ -335,13 +356,24 @@ void __init clps711x_timer_init(void) | |||
335 | 356 | ||
336 | pr_info("CPU frequency set at %i Hz.\n", cpu); | 357 | pr_info("CPU frequency set at %i Hz.\n", cpu); |
337 | 358 | ||
359 | /* Start Timer1 in free running mode (Low frequency) */ | ||
360 | tmp = clps_readl(SYSCON1) & ~(SYSCON1_TC1S | SYSCON1_TC1M); | ||
361 | clps_writel(tmp, SYSCON1); | ||
362 | |||
363 | setup_sched_clock(clps711x_sched_clock_read, 16, timl); | ||
364 | |||
365 | clocksource_mmio_init(CLPS711X_VIRT_BASE + TC1D, | ||
366 | "clps711x_clocksource", timl, 300, 16, | ||
367 | clocksource_mmio_readw_down); | ||
368 | |||
369 | /* Set Timer2 prescaler */ | ||
338 | clps_writew(DIV_ROUND_CLOSEST(timh, HZ), TC2D); | 370 | clps_writew(DIV_ROUND_CLOSEST(timh, HZ), TC2D); |
339 | 371 | ||
340 | tmp = clps_readl(SYSCON1); | 372 | /* Start Timer2 in prescale mode (High frequency)*/ |
341 | tmp |= SYSCON1_TC2S | SYSCON1_TC2M; | 373 | tmp = clps_readl(SYSCON1) | SYSCON1_TC2M | SYSCON1_TC2S; |
342 | clps_writel(tmp, SYSCON1); | 374 | clps_writel(tmp, SYSCON1); |
343 | 375 | ||
344 | clockevents_config_and_register(&clockevent_clps711x, timh, 1, 0xffff); | 376 | clockevents_config_and_register(&clockevent_clps711x, timh, 0, 0); |
345 | 377 | ||
346 | setup_irq(IRQ_TC2OI, &clps711x_timer_irq); | 378 | setup_irq(IRQ_TC2OI, &clps711x_timer_irq); |
347 | } | 379 | } |