aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-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 = {