aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2008-02-04 11:24:54 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-02-04 12:52:16 -0500
commit85802afeb010502471f64dccf9839f60995c8579 (patch)
treecfeb1aa57a7c0f1691301ccd14fc4da044aa5157
parentae9458d6a0956aa21cb49e1251e35a8d4dacbe6e (diff)
[ARM] 4811/1: RealView: clocksource support for the RealView platforms
The patch updates the RealView platform code to use the generic clocksource infrastructure for basic time keeping. 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>
-rw-r--r--arch/arm/Kconfig1
-rw-r--r--arch/arm/mach-realview/core.c73
2 files changed, 32 insertions, 42 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4b1a8e3d292c..a2b7e4a52f73 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -168,6 +168,7 @@ config ARCH_REALVIEW
168 bool "ARM Ltd. RealView family" 168 bool "ARM Ltd. RealView family"
169 select ARM_AMBA 169 select ARM_AMBA
170 select ICST307 170 select ICST307
171 select GENERIC_TIME
171 help 172 help
172 This enables support for ARM Ltd RealView boards. 173 This enables support for ARM Ltd RealView boards.
173 174
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 61d70218f1e8..f805840f6f44 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -25,6 +25,7 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
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 29
29#include <asm/system.h> 30#include <asm/system.h>
30#include <asm/hardware.h> 31#include <asm/hardware.h>
@@ -485,47 +486,6 @@ void realview_leds_event(led_event_t ledevt)
485#endif 486#endif
486 487
487/* 488/*
488 * Returns number of ms since last clock interrupt. Note that interrupts
489 * will have been disabled by do_gettimeoffset()
490 */
491static unsigned long realview_gettimeoffset(void)
492{
493 unsigned long ticks1, ticks2, status;
494
495 /*
496 * Get the current number of ticks. Note that there is a race
497 * condition between us reading the timer and checking for
498 * an interrupt. We get around this by ensuring that the
499 * counter has not reloaded between our two reads.
500 */
501 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
502 do {
503 ticks1 = ticks2;
504 status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
505 + ((IRQ_TIMERINT0_1 >> 5) << 2));
506 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
507 } while (ticks2 > ticks1);
508
509 /*
510 * Number of ticks since last interrupt.
511 */
512 ticks1 = TIMER_RELOAD - ticks2;
513
514 /*
515 * Interrupt pending? If so, we've reloaded once already.
516 *
517 * FIXME: Need to check this is effectively timer 0 that expires
518 */
519 if (status & IRQMASK_TIMERINT0_1)
520 ticks1 += TIMER_RELOAD;
521
522 /*
523 * Convert the ticks to usecs
524 */
525 return TICKS2USECS(ticks1);
526}
527
528/*
529 * IRQ handler for the timer 489 * IRQ handler for the timer
530 */ 490 */
531static irqreturn_t realview_timer_interrupt(int irq, void *dev_id) 491static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
@@ -549,6 +509,34 @@ static struct irqaction realview_timer_irq = {
549 .handler = realview_timer_interrupt, 509 .handler = realview_timer_interrupt,
550}; 510};
551 511
512static cycle_t realview_get_cycles(void)
513{
514 return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
515}
516
517static struct clocksource clocksource_realview = {
518 .name = "timer3",
519 .rating = 200,
520 .read = realview_get_cycles,
521 .mask = CLOCKSOURCE_MASK(32),
522 .shift = 20,
523 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
524};
525
526static void __init realview_clocksource_init(void)
527{
528 /* setup timer 0 as free-running clocksource */
529 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
530 writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
531 writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
532 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
533 TIMER3_VA_BASE + TIMER_CTRL);
534
535 clocksource_realview.mult =
536 clocksource_khz2mult(1000, clocksource_realview.shift);
537 clocksource_register(&clocksource_realview);
538}
539
552/* 540/*
553 * Set up timer interrupt, and return the current time in seconds. 541 * Set up timer interrupt, and return the current time in seconds.
554 */ 542 */
@@ -585,9 +573,10 @@ static void __init realview_timer_init(void)
585 * Make irqs happen for the system timer 573 * Make irqs happen for the system timer
586 */ 574 */
587 setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq); 575 setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
576
577 realview_clocksource_init();
588} 578}
589 579
590struct sys_timer realview_timer = { 580struct sys_timer realview_timer = {
591 .init = realview_timer_init, 581 .init = realview_timer_init,
592 .offset = realview_gettimeoffset,
593}; 582};