diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-01-14 08:30:16 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-05-02 04:35:34 -0400 |
commit | e388771458b4ff3ad81ab70e390b24d069647da4 (patch) | |
tree | 43f130464e60cabf5a1357355277f3d959cd1789 /arch/arm/mach-versatile | |
parent | f4b8b319bf21bf3576014ce7336763cd3e1684ef (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.c | 135 |
1 files changed, 3 insertions, 132 deletions
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index e9d255f3367..b68ddd349f1 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 | |||
900 | static 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 | |||
926 | static 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 | |||
937 | static 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 | */ | ||
948 | static 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 | |||
959 | static 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 | |||
965 | static cycle_t versatile_get_cycles(struct clocksource *cs) | ||
966 | { | ||
967 | return ~readl(TIMER3_VA_BASE + TIMER_VALUE); | ||
968 | } | ||
969 | |||
970 | static 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 | |||
979 | static 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 | ||
1040 | struct sys_timer versatile_timer = { | 911 | struct sys_timer versatile_timer = { |