diff options
-rw-r--r-- | arch/arm/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-versatile/core.c | 75 |
2 files changed, 35 insertions, 41 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2aadd0e1e586..cddd054676c0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -166,6 +166,7 @@ config ARCH_VERSATILE | |||
166 | select ARM_AMBA | 166 | select ARM_AMBA |
167 | select ARM_VIC | 167 | select ARM_VIC |
168 | select ICST307 | 168 | select ICST307 |
169 | select GENERIC_TIME | ||
169 | help | 170 | help |
170 | This enables support for ARM Ltd Versatile board. | 171 | This enables support for ARM Ltd Versatile board. |
171 | 172 | ||
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 | */ | ||
835 | static 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 | */ |
874 | static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id) | 835 | static 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 | ||
855 | static cycle_t versatile_get_cycles(void) | ||
856 | { | ||
857 | return ~readl(TIMER3_VA_BASE + TIMER_VALUE); | ||
858 | } | ||
859 | |||
860 | static 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 | |||
869 | static 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 | ||
932 | struct sys_timer versatile_timer = { | 925 | struct sys_timer versatile_timer = { |
933 | .init = versatile_timer_init, | 926 | .init = versatile_timer_init, |
934 | .offset = versatile_gettimeoffset, | ||
935 | }; | 927 | }; |
928 | |||