aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
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
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')
-rw-r--r--arch/arm/Kconfig5
-rw-r--r--arch/arm/mach-realview/core.c139
-rw-r--r--arch/arm/mach-versatile/core.c135
-rw-r--r--arch/arm/plat-versatile/Makefile1
-rw-r--r--arch/arm/plat-versatile/include/plat/timer-sp.h2
-rw-r--r--arch/arm/plat-versatile/timer-sp.c168
6 files changed, 182 insertions, 268 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e8265f257674..553487052772 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -257,6 +257,7 @@ config ARCH_REALVIEW
257 select GENERIC_CLOCKEVENTS 257 select GENERIC_CLOCKEVENTS
258 select ARCH_WANT_OPTIONAL_GPIOLIB 258 select ARCH_WANT_OPTIONAL_GPIOLIB
259 select PLAT_VERSATILE 259 select PLAT_VERSATILE
260 select ARM_TIMER_SP804
260 help 261 help
261 This enables support for ARM Ltd RealView boards. 262 This enables support for ARM Ltd RealView boards.
262 263
@@ -271,6 +272,7 @@ config ARCH_VERSATILE
271 select GENERIC_CLOCKEVENTS 272 select GENERIC_CLOCKEVENTS
272 select ARCH_WANT_OPTIONAL_GPIOLIB 273 select ARCH_WANT_OPTIONAL_GPIOLIB
273 select PLAT_VERSATILE 274 select PLAT_VERSATILE
275 select ARM_TIMER_SP804
274 help 276 help
275 This enables support for ARM Ltd Versatile board. 277 This enables support for ARM Ltd Versatile board.
276 278
@@ -944,6 +946,9 @@ config PLAT_PXA
944config PLAT_VERSATILE 946config PLAT_VERSATILE
945 bool 947 bool
946 948
949config ARM_TIMER_SP804
950 bool
951
947source arch/arm/mm/Kconfig 952source arch/arm/mm/Kconfig
948 953
949config IWMMXT 954config IWMMXT
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 17eb7eb780d8..80b8142463c1 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -25,8 +25,6 @@
25#include <linux/interrupt.h> 25#include <linux/interrupt.h>
26#include <linux/amba/bus.h> 26#include <linux/amba/bus.h>
27#include <linux/amba/clcd.h> 27#include <linux/amba/clcd.h>
28#include <linux/clocksource.h>
29#include <linux/clockchips.h>
30#include <linux/io.h> 28#include <linux/io.h>
31#include <linux/smsc911x.h> 29#include <linux/smsc911x.h>
32#include <linux/ata_platform.h> 30#include <linux/ata_platform.h>
@@ -51,6 +49,7 @@
51#include <mach/clkdev.h> 49#include <mach/clkdev.h>
52#include <mach/platform.h> 50#include <mach/platform.h>
53#include <mach/irqs.h> 51#include <mach/irqs.h>
52#include <plat/timer-sp.h>
54 53
55#include "core.h" 54#include "core.h"
56 55
@@ -646,133 +645,6 @@ void __iomem *timer2_va_base;
646void __iomem *timer3_va_base; 645void __iomem *timer3_va_base;
647 646
648/* 647/*
649 * How long is the timer interval?
650 */
651#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
652#if TIMER_INTERVAL >= 0x100000
653#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
654#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
655#define TICKS2USECS(x) (256 * (x) / TICKS_PER_uSEC)
656#elif TIMER_INTERVAL >= 0x10000
657#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */
658#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
659#define TICKS2USECS(x) (16 * (x) / TICKS_PER_uSEC)
660#else
661#define TIMER_RELOAD (TIMER_INTERVAL)
662#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
663#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
664#endif
665
666static void timer_set_mode(enum clock_event_mode mode,
667 struct clock_event_device *clk)
668{
669 unsigned long ctrl;
670
671 switch(mode) {
672 case CLOCK_EVT_MODE_PERIODIC:
673 writel(TIMER_RELOAD, timer0_va_base + TIMER_LOAD);
674
675 ctrl = TIMER_CTRL_PERIODIC;
676 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
677 break;
678 case CLOCK_EVT_MODE_ONESHOT:
679 /* period set, and timer enabled in 'next_event' hook */
680 ctrl = TIMER_CTRL_ONESHOT;
681 ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
682 break;
683 case CLOCK_EVT_MODE_UNUSED:
684 case CLOCK_EVT_MODE_SHUTDOWN:
685 default:
686 ctrl = 0;
687 }
688
689 writel(ctrl, timer0_va_base + TIMER_CTRL);
690}
691
692static int timer_set_next_event(unsigned long evt,
693 struct clock_event_device *unused)
694{
695 unsigned long ctrl = readl(timer0_va_base + TIMER_CTRL);
696
697 writel(evt, timer0_va_base + TIMER_LOAD);
698 writel(ctrl | TIMER_CTRL_ENABLE, timer0_va_base + TIMER_CTRL);
699
700 return 0;
701}
702
703static struct clock_event_device timer0_clockevent = {
704 .name = "timer0",
705 .shift = 32,
706 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
707 .set_mode = timer_set_mode,
708 .set_next_event = timer_set_next_event,
709 .rating = 300,
710 .cpumask = cpu_all_mask,
711};
712
713static void __init realview_clockevents_init(unsigned int timer_irq)
714{
715 timer0_clockevent.irq = timer_irq;
716 timer0_clockevent.mult =
717 div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
718 timer0_clockevent.max_delta_ns =
719 clockevent_delta2ns(0xffffffff, &timer0_clockevent);
720 timer0_clockevent.min_delta_ns =
721 clockevent_delta2ns(0xf, &timer0_clockevent);
722
723 clockevents_register_device(&timer0_clockevent);
724}
725
726/*
727 * IRQ handler for the timer
728 */
729static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
730{
731 struct clock_event_device *evt = &timer0_clockevent;
732
733 /* clear the interrupt */
734 writel(1, timer0_va_base + TIMER_INTCLR);
735
736 evt->event_handler(evt);
737
738 return IRQ_HANDLED;
739}
740
741static struct irqaction realview_timer_irq = {
742 .name = "RealView Timer Tick",
743 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
744 .handler = realview_timer_interrupt,
745};
746
747static cycle_t realview_get_cycles(struct clocksource *cs)
748{
749 return ~readl(timer3_va_base + TIMER_VALUE);
750}
751
752static struct clocksource clocksource_realview = {
753 .name = "timer3",
754 .rating = 200,
755 .read = realview_get_cycles,
756 .mask = CLOCKSOURCE_MASK(32),
757 .shift = 20,
758 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
759};
760
761static void __init realview_clocksource_init(void)
762{
763 /* setup timer 0 as free-running clocksource */
764 writel(0, timer3_va_base + TIMER_CTRL);
765 writel(0xffffffff, timer3_va_base + TIMER_LOAD);
766 writel(0xffffffff, timer3_va_base + TIMER_VALUE);
767 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
768 timer3_va_base + TIMER_CTRL);
769
770 clocksource_realview.mult =
771 clocksource_khz2mult(1000, clocksource_realview.shift);
772 clocksource_register(&clocksource_realview);
773}
774
775/*
776 * Set up the clock source and clock events devices 648 * Set up the clock source and clock events devices
777 */ 649 */
778void __init realview_timer_init(unsigned int timer_irq) 650void __init realview_timer_init(unsigned int timer_irq)
@@ -799,13 +671,8 @@ void __init realview_timer_init(unsigned int timer_irq)
799 writel(0, timer2_va_base + TIMER_CTRL); 671 writel(0, timer2_va_base + TIMER_CTRL);
800 writel(0, timer3_va_base + TIMER_CTRL); 672 writel(0, timer3_va_base + TIMER_CTRL);
801 673
802 /* 674 sp804_clocksource_init(timer3_va_base);
803 * Make irqs happen for the system timer 675 sp804_clockevents_init(timer0_va_base, timer_irq);
804 */
805 setup_irq(timer_irq, &realview_timer_irq);
806
807 realview_clocksource_init();
808 realview_clockevents_init(timer_irq);
809} 676}
810 677
811/* 678/*
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 = {
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index 2228fd1725ac..334d2f14232c 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -1 +1,2 @@
1obj-y := clock.o 1obj-y := clock.o
2obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
diff --git a/arch/arm/plat-versatile/include/plat/timer-sp.h b/arch/arm/plat-versatile/include/plat/timer-sp.h
new file mode 100644
index 000000000000..21e75e30d497
--- /dev/null
+++ b/arch/arm/plat-versatile/include/plat/timer-sp.h
@@ -0,0 +1,2 @@
1void sp804_clocksource_init(void __iomem *);
2void sp804_clockevents_init(void __iomem *, unsigned int);
diff --git a/arch/arm/plat-versatile/timer-sp.c b/arch/arm/plat-versatile/timer-sp.c
new file mode 100644
index 000000000000..98722f44640c
--- /dev/null
+++ b/arch/arm/plat-versatile/timer-sp.c
@@ -0,0 +1,168 @@
1/*
2 * linux/arch/arm/plat-versatile/timer-sp.c
3 *
4 * Copyright (C) 1999 - 2003 ARM Limited
5 * Copyright (C) 2000 Deep Blue Solutions Ltd
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21#include <linux/clocksource.h>
22#include <linux/clockchips.h>
23#include <linux/interrupt.h>
24#include <linux/irq.h>
25#include <linux/io.h>
26
27#include <asm/hardware/arm_timer.h>
28
29#include <mach/platform.h>
30
31#include <plat/timer-sp.h>
32
33/*
34 * How long is the timer interval?
35 */
36#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
37#if TIMER_INTERVAL >= 0x100000
38#define TIMER_RELOAD (TIMER_INTERVAL >> 8)
39#define TIMER_DIVISOR (TIMER_CTRL_DIV256)
40#elif TIMER_INTERVAL >= 0x10000
41#define TIMER_RELOAD (TIMER_INTERVAL >> 4) /* Divide by 16 */
42#define TIMER_DIVISOR (TIMER_CTRL_DIV16)
43#else
44#define TIMER_RELOAD (TIMER_INTERVAL)
45#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
46#endif
47
48
49static void __iomem *clksrc_base;
50
51static cycle_t sp804_read(struct clocksource *cs)
52{
53 return ~readl(clksrc_base + TIMER_VALUE);
54}
55
56static struct clocksource clocksource_sp804 = {
57 .name = "timer3",
58 .rating = 200,
59 .read = sp804_read,
60 .mask = CLOCKSOURCE_MASK(32),
61 .shift = 20,
62 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
63};
64
65void __init sp804_clocksource_init(void __iomem *base)
66{
67 struct clocksource *cs = &clocksource_sp804;
68
69 clksrc_base = base;
70
71 /* setup timer 0 as free-running clocksource */
72 writel(0, clksrc_base + TIMER_CTRL);
73 writel(0xffffffff, clksrc_base + TIMER_LOAD);
74 writel(0xffffffff, clksrc_base + TIMER_VALUE);
75 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
76 clksrc_base + TIMER_CTRL);
77
78 cs->mult = clocksource_khz2mult(1000, cs->shift);
79 clocksource_register(cs);
80}
81
82
83static void __iomem *clkevt_base;
84
85/*
86 * IRQ handler for the timer
87 */
88static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
89{
90 struct clock_event_device *evt = dev_id;
91
92 /* clear the interrupt */
93 writel(1, clkevt_base + TIMER_INTCLR);
94
95 evt->event_handler(evt);
96
97 return IRQ_HANDLED;
98}
99
100static void sp804_set_mode(enum clock_event_mode mode,
101 struct clock_event_device *evt)
102{
103 unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE;
104
105 writel(ctrl, clkevt_base + TIMER_CTRL);
106
107 switch (mode) {
108 case CLOCK_EVT_MODE_PERIODIC:
109 writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD);
110 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
111 break;
112
113 case CLOCK_EVT_MODE_ONESHOT:
114 /* period set, and timer enabled in 'next_event' hook */
115 ctrl |= TIMER_CTRL_ONESHOT;
116 break;
117
118 case CLOCK_EVT_MODE_UNUSED:
119 case CLOCK_EVT_MODE_SHUTDOWN:
120 default:
121 break;
122 }
123
124 writel(ctrl, clkevt_base + TIMER_CTRL);
125}
126
127static int sp804_set_next_event(unsigned long next,
128 struct clock_event_device *evt)
129{
130 unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
131
132 writel(next, clkevt_base + TIMER_LOAD);
133 writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
134
135 return 0;
136}
137
138static struct clock_event_device sp804_clockevent = {
139 .name = "timer0",
140 .shift = 32,
141 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
142 .set_mode = sp804_set_mode,
143 .set_next_event = sp804_set_next_event,
144 .rating = 300,
145 .cpumask = cpu_all_mask,
146};
147
148static struct irqaction sp804_timer_irq = {
149 .name = "timer",
150 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
151 .handler = sp804_timer_interrupt,
152 .dev_id = &sp804_clockevent,
153};
154
155void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq)
156{
157 struct clock_event_device *evt = &sp804_clockevent;
158
159 clkevt_base = base;
160
161 evt->irq = timer_irq;
162 evt->mult = div_sc(1000000, NSEC_PER_SEC, evt->shift);
163 evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt);
164 evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
165
166 setup_irq(timer_irq, &sp804_timer_irq);
167 clockevents_register_device(evt);
168}