aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-versatile
diff options
context:
space:
mode:
authorKevin Hilman <khilman@mvista.com>2007-03-08 14:25:13 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2007-04-21 16:02:39 -0400
commitb49c87c2a5059af14b68ee5f596ac0e9c93678bb (patch)
tree6c2645fe9d60a3a1f5f7ff277c68bf41e038d69f /arch/arm/mach-versatile
parente32f1502be3fa459723b1e4105e014f0828f7513 (diff)
[ARM] 4260/1: clocksource support for Versatile platform
Update Versatile to use new clocksource infrastructure for basic timekeeping. Signed-off-by: Kevin Hilman <khilman@mvista.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-versatile')
-rw-r--r--arch/arm/mach-versatile/core.c75
1 files changed, 34 insertions, 41 deletions
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index bf71507c76fd..08a9fe6eeadb 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -26,6 +26,7 @@
26#include <linux/interrupt.h> 26#include <linux/interrupt.h>
27#include <linux/amba/bus.h> 27#include <linux/amba/bus.h>
28#include <linux/amba/clcd.h> 28#include <linux/amba/clcd.h>
29#include <linux/clocksource.h>
29 30
30#include <asm/cnt32_to_63.h> 31#include <asm/cnt32_to_63.h>
31#include <asm/system.h> 32#include <asm/system.h>
@@ -829,46 +830,6 @@ void __init versatile_init(void)
829#endif 830#endif
830 831
831/* 832/*
832 * Returns number of ms since last clock interrupt. Note that interrupts
833 * will have been disabled by do_gettimeoffset()
834 */
835static unsigned long versatile_gettimeoffset(void)
836{
837 unsigned long ticks1, ticks2, status;
838
839 /*
840 * Get the current number of ticks. Note that there is a race
841 * condition between us reading the timer and checking for
842 * an interrupt. We get around this by ensuring that the
843 * counter has not reloaded between our two reads.
844 */
845 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
846 do {
847 ticks1 = ticks2;
848 status = __raw_readl(VA_IC_BASE + VIC_RAW_STATUS);
849 ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
850 } while (ticks2 > ticks1);
851
852 /*
853 * Number of ticks since last interrupt.
854 */
855 ticks1 = TIMER_RELOAD - ticks2;
856
857 /*
858 * Interrupt pending? If so, we've reloaded once already.
859 *
860 * FIXME: Need to check this is effectively timer 0 that expires
861 */
862 if (status & IRQMASK_TIMERINT0_1)
863 ticks1 += TIMER_RELOAD;
864
865 /*
866 * Convert the ticks to usecs
867 */
868 return TICKS2USECS(ticks1);
869}
870
871/*
872 * IRQ handler for the timer 833 * IRQ handler for the timer
873 */ 834 */
874static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id) 835static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
@@ -891,6 +852,36 @@ static struct irqaction versatile_timer_irq = {
891 .handler = versatile_timer_interrupt, 852 .handler = versatile_timer_interrupt,
892}; 853};
893 854
855static cycle_t versatile_get_cycles(void)
856{
857 return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
858}
859
860static struct clocksource clocksource_versatile = {
861 .name = "timer3",
862 .rating = 200,
863 .read = versatile_get_cycles,
864 .mask = CLOCKSOURCE_MASK(32),
865 .shift = 20,
866 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
867};
868
869static int __init versatile_clocksource_init(void)
870{
871 /* setup timer3 as free-running clocksource */
872 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
873 writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
874 writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
875 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
876 TIMER3_VA_BASE + TIMER_CTRL);
877
878 clocksource_versatile.mult =
879 clocksource_khz2mult(1000, clocksource_versatile.shift);
880 clocksource_register(&clocksource_versatile);
881
882 return 0;
883}
884
894/* 885/*
895 * Set up timer interrupt, and return the current time in seconds. 886 * Set up timer interrupt, and return the current time in seconds.
896 */ 887 */
@@ -927,9 +918,11 @@ static void __init versatile_timer_init(void)
927 * Make irqs happen for the system timer 918 * Make irqs happen for the system timer
928 */ 919 */
929 setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); 920 setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
921
922 versatile_clocksource_init();
930} 923}
931 924
932struct sys_timer versatile_timer = { 925struct sys_timer versatile_timer = {
933 .init = versatile_timer_init, 926 .init = versatile_timer_init,
934 .offset = versatile_gettimeoffset,
935}; 927};
928