aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2008-02-04 11:26:55 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-02-04 12:52:17 -0500
commitae30ceac3c6bbacdb227816abe6f0c7ea867ac7c (patch)
treeaeb0d30de00a6ef48224845f2e9cb21ddb57e9f5 /arch
parent85802afeb010502471f64dccf9839f60995c8579 (diff)
[ARM] 4812/1: RealView: clockevents support for the RealView platforms
The patch updates the RealView code to the clockevents infrastructure. The SMP support is implemented in subsequent patches. Based on the Versatile implementation by Kevin Hilman. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-realview/core.c78
2 files changed, 67 insertions, 12 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a2b7e4a52f73..b82828e768ad 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -169,6 +169,7 @@ config ARCH_REALVIEW
169 select ARM_AMBA 169 select ARM_AMBA
170 select ICST307 170 select ICST307
171 select GENERIC_TIME 171 select GENERIC_TIME
172 select GENERIC_CLOCKEVENTS
172 help 173 help
173 This enables support for ARM Ltd RealView boards. 174 This enables support for ARM Ltd RealView boards.
174 175
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index f805840f6f44..6c68deed84dc 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -26,6 +26,7 @@
26#include <linux/amba/bus.h> 26#include <linux/amba/bus.h>
27#include <linux/amba/clcd.h> 27#include <linux/amba/clcd.h>
28#include <linux/clocksource.h> 28#include <linux/clocksource.h>
29#include <linux/clockchips.h>
29 30
30#include <asm/system.h> 31#include <asm/system.h>
31#include <asm/hardware.h> 32#include <asm/hardware.h>
@@ -485,20 +486,77 @@ void realview_leds_event(led_event_t ledevt)
485#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) 486#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
486#endif 487#endif
487 488
489static void timer_set_mode(enum clock_event_mode mode,
490 struct clock_event_device *clk)
491{
492 unsigned long ctrl;
493
494 switch(mode) {
495 case CLOCK_EVT_MODE_PERIODIC:
496 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
497
498 ctrl = TIMER_CTRL_PERIODIC;
499 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
500 break;
501 case CLOCK_EVT_MODE_ONESHOT:
502 /* period set, and timer enabled in 'next_event' hook */
503 ctrl = TIMER_CTRL_ONESHOT;
504 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
505 break;
506 case CLOCK_EVT_MODE_UNUSED:
507 case CLOCK_EVT_MODE_SHUTDOWN:
508 default:
509 ctrl = 0;
510 }
511
512 writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
513}
514
515static int timer_set_next_event(unsigned long evt,
516 struct clock_event_device *unused)
517{
518 unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
519
520 writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
521 writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
522
523 return 0;
524}
525
526static struct clock_event_device timer0_clockevent = {
527 .name = "timer0",
528 .shift = 32,
529 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
530 .set_mode = timer_set_mode,
531 .set_next_event = timer_set_next_event,
532 .rating = 300,
533 .irq = IRQ_TIMERINT0_1,
534 .cpumask = CPU_MASK_ALL,
535};
536
537static void __init realview_clockevents_init(void)
538{
539 timer0_clockevent.mult =
540 div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
541 timer0_clockevent.max_delta_ns =
542 clockevent_delta2ns(0xffffffff, &timer0_clockevent);
543 timer0_clockevent.min_delta_ns =
544 clockevent_delta2ns(0xf, &timer0_clockevent);
545
546 clockevents_register_device(&timer0_clockevent);
547}
548
488/* 549/*
489 * IRQ handler for the timer 550 * IRQ handler for the timer
490 */ 551 */
491static irqreturn_t realview_timer_interrupt(int irq, void *dev_id) 552static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
492{ 553{
493 // ...clear the interrupt 554 struct clock_event_device *evt = &timer0_clockevent;
494 writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
495 555
496 timer_tick(); 556 /* clear the interrupt */
557 writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
497 558
498#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS) 559 evt->event_handler(evt);
499 smp_send_timer();
500 update_process_times(user_mode(get_irq_regs()));
501#endif
502 560
503 return IRQ_HANDLED; 561 return IRQ_HANDLED;
504} 562}
@@ -564,17 +622,13 @@ static void __init realview_timer_init(void)
564 writel(0, TIMER2_VA_BASE + TIMER_CTRL); 622 writel(0, TIMER2_VA_BASE + TIMER_CTRL);
565 writel(0, TIMER3_VA_BASE + TIMER_CTRL); 623 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
566 624
567 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
568 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
569 writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
570 TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
571
572 /* 625 /*
573 * Make irqs happen for the system timer 626 * Make irqs happen for the system timer
574 */ 627 */
575 setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq); 628 setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
576 629
577 realview_clocksource_init(); 630 realview_clocksource_init();
631 realview_clockevents_init();
578} 632}
579 633
580struct sys_timer realview_timer = { 634struct sys_timer realview_timer = {