aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-versatile
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-01-14 08:30:16 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-05-02 04:35:34 -0400
commite388771458b4ff3ad81ab70e390b24d069647da4 (patch)
tree43f130464e60cabf5a1357355277f3d959cd1789 /arch/arm/mach-versatile
parentf4b8b319bf21bf3576014ce7336763cd3e1684ef (diff)
ARM: Realview/Versatile: separate out common SP804 timer code
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.c135
1 files changed, 3 insertions, 132 deletions
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index e9d255f33674..b68ddd349f12 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -28,8 +28,6 @@
28#include <linux/amba/clcd.h> 28#include <linux/amba/clcd.h>
29#include <linux/amba/pl061.h> 29#include <linux/amba/pl061.h>
30#include <linux/amba/mmci.h> 30#include <linux/amba/mmci.h>
31#include <linux/clocksource.h>
32#include <linux/clockchips.h>
33#include <linux/cnt32_to_63.h> 31#include <linux/cnt32_to_63.h>
34#include <linux/io.h> 32#include <linux/io.h>
35 33
@@ -50,6 +48,7 @@
50#include <mach/clkdev.h> 48#include <mach/clkdev.h>
51#include <mach/hardware.h> 49#include <mach/hardware.h>
52#include <mach/platform.h> 50#include <mach/platform.h>
51#include <plat/timer-sp.h>
53 52
54#include "core.h" 53#include "core.h"
55 54
@@ -877,120 +876,6 @@ void __init versatile_init(void)
877#define TIMER1_VA_BASE (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20) 876#define TIMER1_VA_BASE (__io_address(VERSATILE_TIMER0_1_BASE) + 0x20)
878#define TIMER2_VA_BASE __io_address(VERSATILE_TIMER2_3_BASE) 877#define TIMER2_VA_BASE __io_address(VERSATILE_TIMER2_3_BASE)
879#define TIMER3_VA_BASE (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20) 878#define TIMER3_VA_BASE (__io_address(VERSATILE_TIMER2_3_BASE) + 0x20)
880#define VA_IC_BASE __io_address(VERSATILE_VIC_BASE)
881
882/*
883 * How long is the timer interval?
884 */
885#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
886#if TIMER_INTERVAL >= 0x100000
887#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
888#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
889#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
890#elif TIMER_INTERVAL >= 0x10000
891#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */
892#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
893#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
894#else
895#define TIMER_RELOAD (TIMER_INTERVAL)
896#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
897#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
898#endif
899
900static void timer_set_mode(enum clock_event_mode mode,
901 struct clock_event_device *clk)
902{
903 unsigned long ctrl;
904
905 switch(mode) {
906 case CLOCK_EVT_MODE_PERIODIC:
907 writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
908
909 ctrl = TIMER_CTRL_PERIODIC;
910 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
911 break;
912 case CLOCK_EVT_MODE_ONESHOT:
913 /* period set, and timer enabled in 'next_event' hook */
914 ctrl = TIMER_CTRL_ONESHOT;
915 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
916 break;
917 case CLOCK_EVT_MODE_UNUSED:
918 case CLOCK_EVT_MODE_SHUTDOWN:
919 default:
920 ctrl = 0;
921 }
922
923 writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
924}
925
926static int timer_set_next_event(unsigned long evt,
927 struct clock_event_device *unused)
928{
929 unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
930
931 writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
932 writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
933
934 return 0;
935}
936
937static struct clock_event_device timer0_clockevent = {
938 .name = "timer0",
939 .shift = 32,
940 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
941 .set_mode = timer_set_mode,
942 .set_next_event = timer_set_next_event,
943};
944
945/*
946 * IRQ handler for the timer
947 */
948static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id)
949{
950 struct clock_event_device *evt = &timer0_clockevent;
951
952 writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
953
954 evt->event_handler(evt);
955
956 return IRQ_HANDLED;
957}
958
959static struct irqaction versatile_timer_irq = {
960 .name = "Versatile Timer Tick",
961 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
962 .handler = versatile_timer_interrupt,
963};
964
965static cycle_t versatile_get_cycles(struct clocksource *cs)
966{
967 return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
968}
969
970static struct clocksource clocksource_versatile = {
971 .name = "timer3",
972 .rating = 200,
973 .read = versatile_get_cycles,
974 .mask = CLOCKSOURCE_MASK(32),
975 .shift = 20,
976 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
977};
978
979static int __init versatile_clocksource_init(void)
980{
981 /* setup timer3 as free-running clocksource */
982 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
983 writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
984 writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
985 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
986 TIMER3_VA_BASE + TIMER_CTRL);
987
988 clocksource_versatile.mult =
989 clocksource_khz2mult(1000, clocksource_versatile.shift);
990 clocksource_register(&clocksource_versatile);
991
992 return 0;
993}
994 879
995/* 880/*
996 * Set up timer interrupt, and return the current time in seconds. 881 * Set up timer interrupt, and return the current time in seconds.
@@ -1019,22 +904,8 @@ static void __init versatile_timer_init(void)
1019 writel(0, TIMER2_VA_BASE + TIMER_CTRL); 904 writel(0, TIMER2_VA_BASE + TIMER_CTRL);
1020 writel(0, TIMER3_VA_BASE + TIMER_CTRL); 905 writel(0, TIMER3_VA_BASE + TIMER_CTRL);
1021 906
1022 /* 907 sp804_clocksource_init(TIMER3_VA_BASE);
1023 * Make irqs happen for the system timer 908 sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1);
1024 */
1025 setup_irq(IRQ_TIMERINT0_1, &versatile_timer_irq);
1026
1027 versatile_clocksource_init();
1028
1029 timer0_clockevent.mult =
1030 div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
1031 timer0_clockevent.max_delta_ns =
1032 clockevent_delta2ns(0xffffffff, &timer0_clockevent);
1033 timer0_clockevent.min_delta_ns =
1034 clockevent_delta2ns(0xf, &timer0_clockevent);
1035
1036 timer0_clockevent.cpumask = cpumask_of(0);
1037 clockevents_register_device(&timer0_clockevent);
1038} 909}
1039 910
1040struct sys_timer versatile_timer = { 911struct sys_timer versatile_timer = {