aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-versatile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-versatile')
-rw-r--r--arch/arm/mach-versatile/core.c68
1 files changed, 58 insertions, 10 deletions
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 08a9fe6eeadb..1275aa7d2eb1 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -27,6 +27,7 @@
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#include <linux/clocksource.h>
30#include <linux/clockchips.h>
30 31
31#include <asm/cnt32_to_63.h> 32#include <asm/cnt32_to_63.h>
32#include <asm/system.h> 33#include <asm/system.h>
@@ -829,19 +830,61 @@ void __init versatile_init(void)
829#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC) 830#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
830#endif 831#endif
831 832
833static void timer_set_mode(enum clock_event_mode mode,
834 struct clock_event_device *clk)
835{
836 unsigned long ctrl;
837
838 switch(mode) {
839 case CLOCK_EVT_MODE_PERIODIC:
840 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
841
842 ctrl = TIMER_CTRL_PERIODIC;
843 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
844 break;
845 case CLOCK_EVT_MODE_ONESHOT:
846 /* period set, and timer enabled in 'next_event' hook */
847 ctrl = TIMER_CTRL_ONESHOT;
848 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
849 break;
850 case CLOCK_EVT_MODE_UNUSED:
851 case CLOCK_EVT_MODE_SHUTDOWN:
852 default:
853 ctrl = 0;
854 }
855
856 writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
857}
858
859static int timer_set_next_event(unsigned long evt,
860 struct clock_event_device *unused)
861{
862 unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
863
864 writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
865 writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
866
867 return 0;
868}
869
870static struct clock_event_device timer0_clockevent = {
871 .name = "timer0",
872 .shift = 32,
873 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
874 .set_mode = timer_set_mode,
875 .set_next_event = timer_set_next_event,
876};
877
832/* 878/*
833 * IRQ handler for the timer 879 * IRQ handler for the timer
834 */ 880 */
835static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id) 881static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
836{ 882{
837 write_seqlock(&xtime_lock); 883 struct clock_event_device *evt = &timer0_clockevent;
838 884
839 // ...clear the interrupt
840 writel(1, TIMER0_VA_BASE + TIMER_INTCLR); 885 writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
841 886
842 timer_tick(); 887 evt->event_handler(evt);
843
844 write_sequnlock(&xtime_lock);
845 888
846 return IRQ_HANDLED; 889 return IRQ_HANDLED;
847} 890}
@@ -909,17 +952,22 @@ static void __init versatile_timer_init(void)
909 writel(0, TIMER2_VA_BASE + TIMER_CTRL); 952 writel(0, TIMER2_VA_BASE + TIMER_CTRL);
910 writel(0, TIMER3_VA_BASE + TIMER_CTRL); 953 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
911 954
912 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
913 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
914 writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
915 TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
916
917 /* 955 /*
918 * Make irqs happen for the system timer 956 * Make irqs happen for the system timer
919 */ 957 */
920 setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq); 958 setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
921 959
922 versatile_clocksource_init(); 960 versatile_clocksource_init();
961
962 timer0_clockevent.mult =
963 div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
964 timer0_clockevent.max_delta_ns =
965 clockevent_delta2ns(0xffffffff, &timer0_clockevent);
966 timer0_clockevent.min_delta_ns =
967 clockevent_delta2ns(0xf, &timer0_clockevent);
968
969 timer0_clockevent.cpumask = cpumask_of_cpu(0);
970 clockevents_register_device(&timer0_clockevent);
923} 971}
924 972
925struct sys_timer versatile_timer = { 973struct sys_timer versatile_timer = {