diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 12:03:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 12:03:55 -0400 |
commit | a7726350e06401929eac0aa0677a5467106565fc (patch) | |
tree | e189513e5014bdfccd73a3af731a6b57733743fa /drivers/clocksource | |
parent | 4d26aa305414dbb33b3c32fb205b68004cda8ffc (diff) | |
parent | afcf7924ecab726dab0227188783c4a40d9f0eec (diff) |
Merge tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC cleanup from Olof Johansson:
"Here is a collection of cleanup patches. Among the pieces that stand
out are:
- The deletion of h720x platforms
- Split of at91 non-dt platforms to their own Kconfig file to keep
them separate
- General cleanups and refactoring of i.MX and MXS platforms
- Some restructuring of clock tables for OMAP
- Convertion of PMC driver for Tegra to dt-only
- Some renames of sunxi -> sun4i (Allwinner A10)
- ... plus a bunch of other stuff that I haven't mentioned"
* tag 'cleanup-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (119 commits)
ARM: i.MX: remove unused ARCH_* configs
ARM i.MX53: remove platform ahci support
ARM: sunxi: Rework the restart code
irqchip: sunxi: Rename sunxi to sun4i
irqchip: sunxi: Make use of the IRQCHIP_DECLARE macro
clocksource: sunxi: Rename sunxi to sun4i
clocksource: sunxi: make use of CLKSRC_OF
clocksource: sunxi: Cleanup the timer code
ARM: at91: remove trailing semicolon from macros
ARM: at91/setup: fix trivial typos
ARM: EXYNOS: remove "config EXYNOS_DEV_DRM"
ARM: EXYNOS: change the name of USB ohci header
ARM: SAMSUNG: Remove unnecessary code for dma
ARM: S3C24XX: Remove unused GPIO drive strength register definitions
ARM: OMAP4+: PM: Restore CPU power state to ON with clockdomain force wakeup method
ARM: S3C24XX: Removed unneeded dependency on CPU_S3C2412
ARM: S3C24XX: Removed unneeded dependency on CPU_S3C2410
ARM: S3C24XX: Removed unneeded dependency on ARCH_S3C24XX for boards
ARM: SAMSUNG: Fix typo "CONFIG_SAMSUNG_DEV_RTC"
ARM: S5P64X0: Fix typo "CONFIG_S5P64X0_SETUP_SDHCI"
...
Diffstat (limited to 'drivers/clocksource')
-rw-r--r-- | drivers/clocksource/Kconfig | 2 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 3 | ||||
-rw-r--r-- | drivers/clocksource/bcm2835_timer.c | 12 | ||||
-rw-r--r-- | drivers/clocksource/clksrc-of.c | 5 | ||||
-rw-r--r-- | drivers/clocksource/mxs_timer.c | 304 | ||||
-rw-r--r-- | drivers/clocksource/sun4i_timer.c (renamed from drivers/clocksource/sunxi_timer.c) | 94 | ||||
-rw-r--r-- | drivers/clocksource/tegra20_timer.c | 75 | ||||
-rw-r--r-- | drivers/clocksource/vt8500_timer.c | 16 |
8 files changed, 382 insertions, 129 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e507ab7df60b..9002185a0a1a 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -25,7 +25,7 @@ config DW_APB_TIMER_OF | |||
25 | config ARMADA_370_XP_TIMER | 25 | config ARMADA_370_XP_TIMER |
26 | bool | 26 | bool |
27 | 27 | ||
28 | config SUNXI_TIMER | 28 | config SUN4I_TIMER |
29 | bool | 29 | bool |
30 | 30 | ||
31 | config VT8500_TIMER | 31 | config VT8500_TIMER |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 96e25319659b..4897f243a000 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -16,7 +16,8 @@ obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o | |||
16 | obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o | 16 | obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o |
17 | obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o | 17 | obj-$(CONFIG_ARMADA_370_XP_TIMER) += time-armada-370-xp.o |
18 | obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o | 18 | obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o |
19 | obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o | 19 | obj-$(CONFIG_ARCH_MXS) += mxs_timer.o |
20 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | ||
20 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o | 21 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o |
21 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o | 22 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o |
22 | obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o | 23 | obj-$(CONFIG_ARCH_BCM) += bcm_kona_timer.o |
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index 50c68fef944b..766611d29945 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c | |||
@@ -95,23 +95,13 @@ static irqreturn_t bcm2835_time_interrupt(int irq, void *dev_id) | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | static struct of_device_id bcm2835_time_match[] __initconst = { | 98 | static void __init bcm2835_timer_init(struct device_node *node) |
99 | { .compatible = "brcm,bcm2835-system-timer" }, | ||
100 | {} | ||
101 | }; | ||
102 | |||
103 | static void __init bcm2835_timer_init(void) | ||
104 | { | 99 | { |
105 | struct device_node *node; | ||
106 | void __iomem *base; | 100 | void __iomem *base; |
107 | u32 freq; | 101 | u32 freq; |
108 | int irq; | 102 | int irq; |
109 | struct bcm2835_timer *timer; | 103 | struct bcm2835_timer *timer; |
110 | 104 | ||
111 | node = of_find_matching_node(NULL, bcm2835_time_match); | ||
112 | if (!node) | ||
113 | panic("No bcm2835 timer node"); | ||
114 | |||
115 | base = of_iomap(node, 0); | 105 | base = of_iomap(node, 0); |
116 | if (!base) | 106 | if (!base) |
117 | panic("Can't remap registers"); | 107 | panic("Can't remap registers"); |
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c index bdabdaa8d00f..37f5325bec95 100644 --- a/drivers/clocksource/clksrc-of.c +++ b/drivers/clocksource/clksrc-of.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
19 | #include <linux/clocksource.h> | ||
19 | 20 | ||
20 | extern struct of_device_id __clksrc_of_table[]; | 21 | extern struct of_device_id __clksrc_of_table[]; |
21 | 22 | ||
@@ -26,10 +27,10 @@ void __init clocksource_of_init(void) | |||
26 | { | 27 | { |
27 | struct device_node *np; | 28 | struct device_node *np; |
28 | const struct of_device_id *match; | 29 | const struct of_device_id *match; |
29 | void (*init_func)(void); | 30 | clocksource_of_init_fn init_func; |
30 | 31 | ||
31 | for_each_matching_node_and_match(np, __clksrc_of_table, &match) { | 32 | for_each_matching_node_and_match(np, __clksrc_of_table, &match) { |
32 | init_func = match->data; | 33 | init_func = match->data; |
33 | init_func(); | 34 | init_func(np); |
34 | } | 35 | } |
35 | } | 36 | } |
diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c new file mode 100644 index 000000000000..02af4204af86 --- /dev/null +++ b/drivers/clocksource/mxs_timer.c | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2000-2001 Deep Blue Solutions | ||
3 | * Copyright (C) 2002 Shane Nay (shane@minirl.com) | ||
4 | * Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com) | ||
5 | * Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) | ||
6 | * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version 2 | ||
11 | * of the License, or (at your option) any later version. | ||
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., 51 Franklin Street, Fifth Floor, Boston, | ||
20 | * MA 02110-1301, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/err.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/clockchips.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_address.h> | ||
30 | #include <linux/of_irq.h> | ||
31 | #include <linux/stmp_device.h> | ||
32 | |||
33 | #include <asm/mach/time.h> | ||
34 | #include <asm/sched_clock.h> | ||
35 | |||
36 | /* | ||
37 | * There are 2 versions of the timrot on Freescale MXS-based SoCs. | ||
38 | * The v1 on MX23 only gets 16 bits counter, while v2 on MX28 | ||
39 | * extends the counter to 32 bits. | ||
40 | * | ||
41 | * The implementation uses two timers, one for clock_event and | ||
42 | * another for clocksource. MX28 uses timrot 0 and 1, while MX23 | ||
43 | * uses 0 and 2. | ||
44 | */ | ||
45 | |||
46 | #define MX23_TIMROT_VERSION_OFFSET 0x0a0 | ||
47 | #define MX28_TIMROT_VERSION_OFFSET 0x120 | ||
48 | #define BP_TIMROT_MAJOR_VERSION 24 | ||
49 | #define BV_TIMROT_VERSION_1 0x01 | ||
50 | #define BV_TIMROT_VERSION_2 0x02 | ||
51 | #define timrot_is_v1() (timrot_major_version == BV_TIMROT_VERSION_1) | ||
52 | |||
53 | /* | ||
54 | * There are 4 registers for each timrotv2 instance, and 2 registers | ||
55 | * for each timrotv1. So address step 0x40 in macros below strides | ||
56 | * one instance of timrotv2 while two instances of timrotv1. | ||
57 | * | ||
58 | * As the result, HW_TIMROT_XXXn(1) defines the address of timrot1 | ||
59 | * on MX28 while timrot2 on MX23. | ||
60 | */ | ||
61 | /* common between v1 and v2 */ | ||
62 | #define HW_TIMROT_ROTCTRL 0x00 | ||
63 | #define HW_TIMROT_TIMCTRLn(n) (0x20 + (n) * 0x40) | ||
64 | /* v1 only */ | ||
65 | #define HW_TIMROT_TIMCOUNTn(n) (0x30 + (n) * 0x40) | ||
66 | /* v2 only */ | ||
67 | #define HW_TIMROT_RUNNING_COUNTn(n) (0x30 + (n) * 0x40) | ||
68 | #define HW_TIMROT_FIXED_COUNTn(n) (0x40 + (n) * 0x40) | ||
69 | |||
70 | #define BM_TIMROT_TIMCTRLn_RELOAD (1 << 6) | ||
71 | #define BM_TIMROT_TIMCTRLn_UPDATE (1 << 7) | ||
72 | #define BM_TIMROT_TIMCTRLn_IRQ_EN (1 << 14) | ||
73 | #define BM_TIMROT_TIMCTRLn_IRQ (1 << 15) | ||
74 | #define BP_TIMROT_TIMCTRLn_SELECT 0 | ||
75 | #define BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL 0x8 | ||
76 | #define BV_TIMROTv2_TIMCTRLn_SELECT__32KHZ_XTAL 0xb | ||
77 | #define BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS 0xf | ||
78 | |||
79 | static struct clock_event_device mxs_clockevent_device; | ||
80 | static enum clock_event_mode mxs_clockevent_mode = CLOCK_EVT_MODE_UNUSED; | ||
81 | |||
82 | static void __iomem *mxs_timrot_base; | ||
83 | static u32 timrot_major_version; | ||
84 | |||
85 | static inline void timrot_irq_disable(void) | ||
86 | { | ||
87 | __raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base + | ||
88 | HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR); | ||
89 | } | ||
90 | |||
91 | static inline void timrot_irq_enable(void) | ||
92 | { | ||
93 | __raw_writel(BM_TIMROT_TIMCTRLn_IRQ_EN, mxs_timrot_base + | ||
94 | HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_SET); | ||
95 | } | ||
96 | |||
97 | static void timrot_irq_acknowledge(void) | ||
98 | { | ||
99 | __raw_writel(BM_TIMROT_TIMCTRLn_IRQ, mxs_timrot_base + | ||
100 | HW_TIMROT_TIMCTRLn(0) + STMP_OFFSET_REG_CLR); | ||
101 | } | ||
102 | |||
103 | static cycle_t timrotv1_get_cycles(struct clocksource *cs) | ||
104 | { | ||
105 | return ~((__raw_readl(mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1)) | ||
106 | & 0xffff0000) >> 16); | ||
107 | } | ||
108 | |||
109 | static int timrotv1_set_next_event(unsigned long evt, | ||
110 | struct clock_event_device *dev) | ||
111 | { | ||
112 | /* timrot decrements the count */ | ||
113 | __raw_writel(evt, mxs_timrot_base + HW_TIMROT_TIMCOUNTn(0)); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int timrotv2_set_next_event(unsigned long evt, | ||
119 | struct clock_event_device *dev) | ||
120 | { | ||
121 | /* timrot decrements the count */ | ||
122 | __raw_writel(evt, mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(0)); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static irqreturn_t mxs_timer_interrupt(int irq, void *dev_id) | ||
128 | { | ||
129 | struct clock_event_device *evt = dev_id; | ||
130 | |||
131 | timrot_irq_acknowledge(); | ||
132 | evt->event_handler(evt); | ||
133 | |||
134 | return IRQ_HANDLED; | ||
135 | } | ||
136 | |||
137 | static struct irqaction mxs_timer_irq = { | ||
138 | .name = "MXS Timer Tick", | ||
139 | .dev_id = &mxs_clockevent_device, | ||
140 | .flags = IRQF_TIMER | IRQF_IRQPOLL, | ||
141 | .handler = mxs_timer_interrupt, | ||
142 | }; | ||
143 | |||
144 | #ifdef DEBUG | ||
145 | static const char *clock_event_mode_label[] const = { | ||
146 | [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC", | ||
147 | [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT", | ||
148 | [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN", | ||
149 | [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED" | ||
150 | }; | ||
151 | #endif /* DEBUG */ | ||
152 | |||
153 | static void mxs_set_mode(enum clock_event_mode mode, | ||
154 | struct clock_event_device *evt) | ||
155 | { | ||
156 | /* Disable interrupt in timer module */ | ||
157 | timrot_irq_disable(); | ||
158 | |||
159 | if (mode != mxs_clockevent_mode) { | ||
160 | /* Set event time into the furthest future */ | ||
161 | if (timrot_is_v1()) | ||
162 | __raw_writel(0xffff, | ||
163 | mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1)); | ||
164 | else | ||
165 | __raw_writel(0xffffffff, | ||
166 | mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1)); | ||
167 | |||
168 | /* Clear pending interrupt */ | ||
169 | timrot_irq_acknowledge(); | ||
170 | } | ||
171 | |||
172 | #ifdef DEBUG | ||
173 | pr_info("%s: changing mode from %s to %s\n", __func__, | ||
174 | clock_event_mode_label[mxs_clockevent_mode], | ||
175 | clock_event_mode_label[mode]); | ||
176 | #endif /* DEBUG */ | ||
177 | |||
178 | /* Remember timer mode */ | ||
179 | mxs_clockevent_mode = mode; | ||
180 | |||
181 | switch (mode) { | ||
182 | case CLOCK_EVT_MODE_PERIODIC: | ||
183 | pr_err("%s: Periodic mode is not implemented\n", __func__); | ||
184 | break; | ||
185 | case CLOCK_EVT_MODE_ONESHOT: | ||
186 | timrot_irq_enable(); | ||
187 | break; | ||
188 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
189 | case CLOCK_EVT_MODE_UNUSED: | ||
190 | case CLOCK_EVT_MODE_RESUME: | ||
191 | /* Left event sources disabled, no more interrupts appear */ | ||
192 | break; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static struct clock_event_device mxs_clockevent_device = { | ||
197 | .name = "mxs_timrot", | ||
198 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
199 | .set_mode = mxs_set_mode, | ||
200 | .set_next_event = timrotv2_set_next_event, | ||
201 | .rating = 200, | ||
202 | }; | ||
203 | |||
204 | static int __init mxs_clockevent_init(struct clk *timer_clk) | ||
205 | { | ||
206 | if (timrot_is_v1()) | ||
207 | mxs_clockevent_device.set_next_event = timrotv1_set_next_event; | ||
208 | mxs_clockevent_device.cpumask = cpumask_of(0); | ||
209 | clockevents_config_and_register(&mxs_clockevent_device, | ||
210 | clk_get_rate(timer_clk), | ||
211 | timrot_is_v1() ? 0xf : 0x2, | ||
212 | timrot_is_v1() ? 0xfffe : 0xfffffffe); | ||
213 | |||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static struct clocksource clocksource_mxs = { | ||
218 | .name = "mxs_timer", | ||
219 | .rating = 200, | ||
220 | .read = timrotv1_get_cycles, | ||
221 | .mask = CLOCKSOURCE_MASK(16), | ||
222 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
223 | }; | ||
224 | |||
225 | static u32 notrace mxs_read_sched_clock_v2(void) | ||
226 | { | ||
227 | return ~readl_relaxed(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1)); | ||
228 | } | ||
229 | |||
230 | static int __init mxs_clocksource_init(struct clk *timer_clk) | ||
231 | { | ||
232 | unsigned int c = clk_get_rate(timer_clk); | ||
233 | |||
234 | if (timrot_is_v1()) | ||
235 | clocksource_register_hz(&clocksource_mxs, c); | ||
236 | else { | ||
237 | clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1), | ||
238 | "mxs_timer", c, 200, 32, clocksource_mmio_readl_down); | ||
239 | setup_sched_clock(mxs_read_sched_clock_v2, 32, c); | ||
240 | } | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static void __init mxs_timer_init(struct device_node *np) | ||
246 | { | ||
247 | struct clk *timer_clk; | ||
248 | int irq; | ||
249 | |||
250 | mxs_timrot_base = of_iomap(np, 0); | ||
251 | WARN_ON(!mxs_timrot_base); | ||
252 | |||
253 | timer_clk = of_clk_get(np, 0); | ||
254 | if (IS_ERR(timer_clk)) { | ||
255 | pr_err("%s: failed to get clk\n", __func__); | ||
256 | return; | ||
257 | } | ||
258 | |||
259 | clk_prepare_enable(timer_clk); | ||
260 | |||
261 | /* | ||
262 | * Initialize timers to a known state | ||
263 | */ | ||
264 | stmp_reset_block(mxs_timrot_base + HW_TIMROT_ROTCTRL); | ||
265 | |||
266 | /* get timrot version */ | ||
267 | timrot_major_version = __raw_readl(mxs_timrot_base + | ||
268 | (of_device_is_compatible(np, "fsl,imx23-timrot") ? | ||
269 | MX23_TIMROT_VERSION_OFFSET : | ||
270 | MX28_TIMROT_VERSION_OFFSET)); | ||
271 | timrot_major_version >>= BP_TIMROT_MAJOR_VERSION; | ||
272 | |||
273 | /* one for clock_event */ | ||
274 | __raw_writel((timrot_is_v1() ? | ||
275 | BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL : | ||
276 | BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) | | ||
277 | BM_TIMROT_TIMCTRLn_UPDATE | | ||
278 | BM_TIMROT_TIMCTRLn_IRQ_EN, | ||
279 | mxs_timrot_base + HW_TIMROT_TIMCTRLn(0)); | ||
280 | |||
281 | /* another for clocksource */ | ||
282 | __raw_writel((timrot_is_v1() ? | ||
283 | BV_TIMROTv1_TIMCTRLn_SELECT__32KHZ_XTAL : | ||
284 | BV_TIMROTv2_TIMCTRLn_SELECT__TICK_ALWAYS) | | ||
285 | BM_TIMROT_TIMCTRLn_RELOAD, | ||
286 | mxs_timrot_base + HW_TIMROT_TIMCTRLn(1)); | ||
287 | |||
288 | /* set clocksource timer fixed count to the maximum */ | ||
289 | if (timrot_is_v1()) | ||
290 | __raw_writel(0xffff, | ||
291 | mxs_timrot_base + HW_TIMROT_TIMCOUNTn(1)); | ||
292 | else | ||
293 | __raw_writel(0xffffffff, | ||
294 | mxs_timrot_base + HW_TIMROT_FIXED_COUNTn(1)); | ||
295 | |||
296 | /* init and register the timer to the framework */ | ||
297 | mxs_clocksource_init(timer_clk); | ||
298 | mxs_clockevent_init(timer_clk); | ||
299 | |||
300 | /* Make irqs happen */ | ||
301 | irq = irq_of_parse_and_map(np, 0); | ||
302 | setup_irq(irq, &mxs_timer_irq); | ||
303 | } | ||
304 | CLOCKSOURCE_OF_DECLARE(mxs, "fsl,timrot", mxs_timer_init); | ||
diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sun4i_timer.c index 0ce85e29769b..d4674e78ef35 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sun4i_timer.c | |||
@@ -22,66 +22,64 @@ | |||
22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
24 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
25 | #include <linux/sunxi_timer.h> | ||
26 | #include <linux/clk/sunxi.h> | ||
27 | 25 | ||
28 | #define TIMER_CTL_REG 0x00 | 26 | #define TIMER_IRQ_EN_REG 0x00 |
29 | #define TIMER_CTL_ENABLE (1 << 0) | 27 | #define TIMER_IRQ_EN(val) (1 << val) |
30 | #define TIMER_IRQ_ST_REG 0x04 | 28 | #define TIMER_IRQ_ST_REG 0x04 |
31 | #define TIMER0_CTL_REG 0x10 | 29 | #define TIMER_CTL_REG(val) (0x10 * val + 0x10) |
32 | #define TIMER0_CTL_ENABLE (1 << 0) | 30 | #define TIMER_CTL_ENABLE (1 << 0) |
33 | #define TIMER0_CTL_AUTORELOAD (1 << 1) | 31 | #define TIMER_CTL_AUTORELOAD (1 << 1) |
34 | #define TIMER0_CTL_ONESHOT (1 << 7) | 32 | #define TIMER_CTL_ONESHOT (1 << 7) |
35 | #define TIMER0_INTVAL_REG 0x14 | 33 | #define TIMER_INTVAL_REG(val) (0x10 * val + 0x14) |
36 | #define TIMER0_CNTVAL_REG 0x18 | 34 | #define TIMER_CNTVAL_REG(val) (0x10 * val + 0x18) |
37 | 35 | ||
38 | #define TIMER_SCAL 16 | 36 | #define TIMER_SCAL 16 |
39 | 37 | ||
40 | static void __iomem *timer_base; | 38 | static void __iomem *timer_base; |
41 | 39 | ||
42 | static void sunxi_clkevt_mode(enum clock_event_mode mode, | 40 | static void sun4i_clkevt_mode(enum clock_event_mode mode, |
43 | struct clock_event_device *clk) | 41 | struct clock_event_device *clk) |
44 | { | 42 | { |
45 | u32 u = readl(timer_base + TIMER0_CTL_REG); | 43 | u32 u = readl(timer_base + TIMER_CTL_REG(0)); |
46 | 44 | ||
47 | switch (mode) { | 45 | switch (mode) { |
48 | case CLOCK_EVT_MODE_PERIODIC: | 46 | case CLOCK_EVT_MODE_PERIODIC: |
49 | u &= ~(TIMER0_CTL_ONESHOT); | 47 | u &= ~(TIMER_CTL_ONESHOT); |
50 | writel(u | TIMER0_CTL_ENABLE, timer_base + TIMER0_CTL_REG); | 48 | writel(u | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG(0)); |
51 | break; | 49 | break; |
52 | 50 | ||
53 | case CLOCK_EVT_MODE_ONESHOT: | 51 | case CLOCK_EVT_MODE_ONESHOT: |
54 | writel(u | TIMER0_CTL_ONESHOT, timer_base + TIMER0_CTL_REG); | 52 | writel(u | TIMER_CTL_ONESHOT, timer_base + TIMER_CTL_REG(0)); |
55 | break; | 53 | break; |
56 | case CLOCK_EVT_MODE_UNUSED: | 54 | case CLOCK_EVT_MODE_UNUSED: |
57 | case CLOCK_EVT_MODE_SHUTDOWN: | 55 | case CLOCK_EVT_MODE_SHUTDOWN: |
58 | default: | 56 | default: |
59 | writel(u & ~(TIMER0_CTL_ENABLE), timer_base + TIMER0_CTL_REG); | 57 | writel(u & ~(TIMER_CTL_ENABLE), timer_base + TIMER_CTL_REG(0)); |
60 | break; | 58 | break; |
61 | } | 59 | } |
62 | } | 60 | } |
63 | 61 | ||
64 | static int sunxi_clkevt_next_event(unsigned long evt, | 62 | static int sun4i_clkevt_next_event(unsigned long evt, |
65 | struct clock_event_device *unused) | 63 | struct clock_event_device *unused) |
66 | { | 64 | { |
67 | u32 u = readl(timer_base + TIMER0_CTL_REG); | 65 | u32 u = readl(timer_base + TIMER_CTL_REG(0)); |
68 | writel(evt, timer_base + TIMER0_CNTVAL_REG); | 66 | writel(evt, timer_base + TIMER_CNTVAL_REG(0)); |
69 | writel(u | TIMER0_CTL_ENABLE | TIMER0_CTL_AUTORELOAD, | 67 | writel(u | TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD, |
70 | timer_base + TIMER0_CTL_REG); | 68 | timer_base + TIMER_CTL_REG(0)); |
71 | 69 | ||
72 | return 0; | 70 | return 0; |
73 | } | 71 | } |
74 | 72 | ||
75 | static struct clock_event_device sunxi_clockevent = { | 73 | static struct clock_event_device sun4i_clockevent = { |
76 | .name = "sunxi_tick", | 74 | .name = "sun4i_tick", |
77 | .rating = 300, | 75 | .rating = 300, |
78 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 76 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, |
79 | .set_mode = sunxi_clkevt_mode, | 77 | .set_mode = sun4i_clkevt_mode, |
80 | .set_next_event = sunxi_clkevt_next_event, | 78 | .set_next_event = sun4i_clkevt_next_event, |
81 | }; | 79 | }; |
82 | 80 | ||
83 | 81 | ||
84 | static irqreturn_t sunxi_timer_interrupt(int irq, void *dev_id) | 82 | static irqreturn_t sun4i_timer_interrupt(int irq, void *dev_id) |
85 | { | 83 | { |
86 | struct clock_event_device *evt = (struct clock_event_device *)dev_id; | 84 | struct clock_event_device *evt = (struct clock_event_device *)dev_id; |
87 | 85 | ||
@@ -91,30 +89,20 @@ static irqreturn_t sunxi_timer_interrupt(int irq, void *dev_id) | |||
91 | return IRQ_HANDLED; | 89 | return IRQ_HANDLED; |
92 | } | 90 | } |
93 | 91 | ||
94 | static struct irqaction sunxi_timer_irq = { | 92 | static struct irqaction sun4i_timer_irq = { |
95 | .name = "sunxi_timer0", | 93 | .name = "sun4i_timer0", |
96 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 94 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, |
97 | .handler = sunxi_timer_interrupt, | 95 | .handler = sun4i_timer_interrupt, |
98 | .dev_id = &sunxi_clockevent, | 96 | .dev_id = &sun4i_clockevent, |
99 | }; | ||
100 | |||
101 | static struct of_device_id sunxi_timer_dt_ids[] = { | ||
102 | { .compatible = "allwinner,sunxi-timer" }, | ||
103 | { } | ||
104 | }; | 97 | }; |
105 | 98 | ||
106 | void __init sunxi_timer_init(void) | 99 | static void __init sun4i_timer_init(struct device_node *node) |
107 | { | 100 | { |
108 | struct device_node *node; | ||
109 | unsigned long rate = 0; | 101 | unsigned long rate = 0; |
110 | struct clk *clk; | 102 | struct clk *clk; |
111 | int ret, irq; | 103 | int ret, irq; |
112 | u32 val; | 104 | u32 val; |
113 | 105 | ||
114 | node = of_find_matching_node(NULL, sunxi_timer_dt_ids); | ||
115 | if (!node) | ||
116 | panic("No sunxi timer node"); | ||
117 | |||
118 | timer_base = of_iomap(node, 0); | 106 | timer_base = of_iomap(node, 0); |
119 | if (!timer_base) | 107 | if (!timer_base) |
120 | panic("Can't map registers"); | 108 | panic("Can't map registers"); |
@@ -123,8 +111,6 @@ void __init sunxi_timer_init(void) | |||
123 | if (irq <= 0) | 111 | if (irq <= 0) |
124 | panic("Can't parse IRQ"); | 112 | panic("Can't parse IRQ"); |
125 | 113 | ||
126 | sunxi_init_clocks(); | ||
127 | |||
128 | clk = of_clk_get(node, 0); | 114 | clk = of_clk_get(node, 0); |
129 | if (IS_ERR(clk)) | 115 | if (IS_ERR(clk)) |
130 | panic("Can't get timer clock"); | 116 | panic("Can't get timer clock"); |
@@ -132,29 +118,31 @@ void __init sunxi_timer_init(void) | |||
132 | rate = clk_get_rate(clk); | 118 | rate = clk_get_rate(clk); |
133 | 119 | ||
134 | writel(rate / (TIMER_SCAL * HZ), | 120 | writel(rate / (TIMER_SCAL * HZ), |
135 | timer_base + TIMER0_INTVAL_REG); | 121 | timer_base + TIMER_INTVAL_REG(0)); |
136 | 122 | ||
137 | /* set clock source to HOSC, 16 pre-division */ | 123 | /* set clock source to HOSC, 16 pre-division */ |
138 | val = readl(timer_base + TIMER0_CTL_REG); | 124 | val = readl(timer_base + TIMER_CTL_REG(0)); |
139 | val &= ~(0x07 << 4); | 125 | val &= ~(0x07 << 4); |
140 | val &= ~(0x03 << 2); | 126 | val &= ~(0x03 << 2); |
141 | val |= (4 << 4) | (1 << 2); | 127 | val |= (4 << 4) | (1 << 2); |
142 | writel(val, timer_base + TIMER0_CTL_REG); | 128 | writel(val, timer_base + TIMER_CTL_REG(0)); |
143 | 129 | ||
144 | /* set mode to auto reload */ | 130 | /* set mode to auto reload */ |
145 | val = readl(timer_base + TIMER0_CTL_REG); | 131 | val = readl(timer_base + TIMER_CTL_REG(0)); |
146 | writel(val | TIMER0_CTL_AUTORELOAD, timer_base + TIMER0_CTL_REG); | 132 | writel(val | TIMER_CTL_AUTORELOAD, timer_base + TIMER_CTL_REG(0)); |
147 | 133 | ||
148 | ret = setup_irq(irq, &sunxi_timer_irq); | 134 | ret = setup_irq(irq, &sun4i_timer_irq); |
149 | if (ret) | 135 | if (ret) |
150 | pr_warn("failed to setup irq %d\n", irq); | 136 | pr_warn("failed to setup irq %d\n", irq); |
151 | 137 | ||
152 | /* Enable timer0 interrupt */ | 138 | /* Enable timer0 interrupt */ |
153 | val = readl(timer_base + TIMER_CTL_REG); | 139 | val = readl(timer_base + TIMER_IRQ_EN_REG); |
154 | writel(val | TIMER_CTL_ENABLE, timer_base + TIMER_CTL_REG); | 140 | writel(val | TIMER_IRQ_EN(0), timer_base + TIMER_IRQ_EN_REG); |
155 | 141 | ||
156 | sunxi_clockevent.cpumask = cpumask_of(0); | 142 | sun4i_clockevent.cpumask = cpumask_of(0); |
157 | 143 | ||
158 | clockevents_config_and_register(&sunxi_clockevent, rate / TIMER_SCAL, | 144 | clockevents_config_and_register(&sun4i_clockevent, rate / TIMER_SCAL, |
159 | 0x1, 0xff); | 145 | 0x1, 0xff); |
160 | } | 146 | } |
147 | CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer", | ||
148 | sun4i_timer_init); | ||
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 0bde03feb095..ae877b021b54 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c | |||
@@ -154,29 +154,12 @@ static struct irqaction tegra_timer_irq = { | |||
154 | .dev_id = &tegra_clockevent, | 154 | .dev_id = &tegra_clockevent, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static const struct of_device_id timer_match[] __initconst = { | 157 | static void __init tegra20_init_timer(struct device_node *np) |
158 | { .compatible = "nvidia,tegra20-timer" }, | ||
159 | {} | ||
160 | }; | ||
161 | |||
162 | static const struct of_device_id rtc_match[] __initconst = { | ||
163 | { .compatible = "nvidia,tegra20-rtc" }, | ||
164 | {} | ||
165 | }; | ||
166 | |||
167 | static void __init tegra20_init_timer(void) | ||
168 | { | 158 | { |
169 | struct device_node *np; | ||
170 | struct clk *clk; | 159 | struct clk *clk; |
171 | unsigned long rate; | 160 | unsigned long rate; |
172 | int ret; | 161 | int ret; |
173 | 162 | ||
174 | np = of_find_matching_node(NULL, timer_match); | ||
175 | if (!np) { | ||
176 | pr_err("Failed to find timer DT node\n"); | ||
177 | BUG(); | ||
178 | } | ||
179 | |||
180 | timer_reg_base = of_iomap(np, 0); | 163 | timer_reg_base = of_iomap(np, 0); |
181 | if (!timer_reg_base) { | 164 | if (!timer_reg_base) { |
182 | pr_err("Can't map timer registers\n"); | 165 | pr_err("Can't map timer registers\n"); |
@@ -189,7 +172,7 @@ static void __init tegra20_init_timer(void) | |||
189 | BUG(); | 172 | BUG(); |
190 | } | 173 | } |
191 | 174 | ||
192 | clk = clk_get_sys("timer", NULL); | 175 | clk = of_clk_get(np, 0); |
193 | if (IS_ERR(clk)) { | 176 | if (IS_ERR(clk)) { |
194 | pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); | 177 | pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); |
195 | rate = 12000000; | 178 | rate = 12000000; |
@@ -200,30 +183,6 @@ static void __init tegra20_init_timer(void) | |||
200 | 183 | ||
201 | of_node_put(np); | 184 | of_node_put(np); |
202 | 185 | ||
203 | np = of_find_matching_node(NULL, rtc_match); | ||
204 | if (!np) { | ||
205 | pr_err("Failed to find RTC DT node\n"); | ||
206 | BUG(); | ||
207 | } | ||
208 | |||
209 | rtc_base = of_iomap(np, 0); | ||
210 | if (!rtc_base) { | ||
211 | pr_err("Can't map RTC registers"); | ||
212 | BUG(); | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * rtc registers are used by read_persistent_clock, keep the rtc clock | ||
217 | * enabled | ||
218 | */ | ||
219 | clk = clk_get_sys("rtc-tegra", NULL); | ||
220 | if (IS_ERR(clk)) | ||
221 | pr_warn("Unable to get rtc-tegra clock\n"); | ||
222 | else | ||
223 | clk_prepare_enable(clk); | ||
224 | |||
225 | of_node_put(np); | ||
226 | |||
227 | switch (rate) { | 186 | switch (rate) { |
228 | case 12000000: | 187 | case 12000000: |
229 | timer_writel(0x000b, TIMERUS_USEC_CFG); | 188 | timer_writel(0x000b, TIMERUS_USEC_CFG); |
@@ -259,12 +218,34 @@ static void __init tegra20_init_timer(void) | |||
259 | tegra_clockevent.irq = tegra_timer_irq.irq; | 218 | tegra_clockevent.irq = tegra_timer_irq.irq; |
260 | clockevents_config_and_register(&tegra_clockevent, 1000000, | 219 | clockevents_config_and_register(&tegra_clockevent, 1000000, |
261 | 0x1, 0x1fffffff); | 220 | 0x1, 0x1fffffff); |
262 | #ifdef CONFIG_HAVE_ARM_TWD | 221 | } |
263 | twd_local_timer_of_register(); | 222 | CLOCKSOURCE_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); |
264 | #endif | 223 | |
224 | static void __init tegra20_init_rtc(struct device_node *np) | ||
225 | { | ||
226 | struct clk *clk; | ||
227 | |||
228 | rtc_base = of_iomap(np, 0); | ||
229 | if (!rtc_base) { | ||
230 | pr_err("Can't map RTC registers"); | ||
231 | BUG(); | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * rtc registers are used by read_persistent_clock, keep the rtc clock | ||
236 | * enabled | ||
237 | */ | ||
238 | clk = of_clk_get(np, 0); | ||
239 | if (IS_ERR(clk)) | ||
240 | pr_warn("Unable to get rtc-tegra clock\n"); | ||
241 | else | ||
242 | clk_prepare_enable(clk); | ||
243 | |||
244 | of_node_put(np); | ||
245 | |||
265 | register_persistent_clock(NULL, tegra_read_persistent_clock); | 246 | register_persistent_clock(NULL, tegra_read_persistent_clock); |
266 | } | 247 | } |
267 | CLOCKSOURCE_OF_DECLARE(tegra20, "nvidia,tegra20-timer", tegra20_init_timer); | 248 | CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); |
268 | 249 | ||
269 | #ifdef CONFIG_PM | 250 | #ifdef CONFIG_PM |
270 | static u32 usec_config; | 251 | static u32 usec_config; |
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index 8efc86b5b5dd..64f553f04fa4 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c | |||
@@ -129,22 +129,10 @@ static struct irqaction irq = { | |||
129 | .dev_id = &clockevent, | 129 | .dev_id = &clockevent, |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static struct of_device_id vt8500_timer_ids[] = { | 132 | static void __init vt8500_timer_init(struct device_node *np) |
133 | { .compatible = "via,vt8500-timer" }, | ||
134 | { } | ||
135 | }; | ||
136 | |||
137 | static void __init vt8500_timer_init(void) | ||
138 | { | 133 | { |
139 | struct device_node *np; | ||
140 | int timer_irq; | 134 | int timer_irq; |
141 | 135 | ||
142 | np = of_find_matching_node(NULL, vt8500_timer_ids); | ||
143 | if (!np) { | ||
144 | pr_err("%s: Timer description missing from Device Tree\n", | ||
145 | __func__); | ||
146 | return; | ||
147 | } | ||
148 | regbase = of_iomap(np, 0); | 136 | regbase = of_iomap(np, 0); |
149 | if (!regbase) { | 137 | if (!regbase) { |
150 | pr_err("%s: Missing iobase description in Device Tree\n", | 138 | pr_err("%s: Missing iobase description in Device Tree\n", |
@@ -177,4 +165,4 @@ static void __init vt8500_timer_init(void) | |||
177 | 4, 0xf0000000); | 165 | 4, 0xf0000000); |
178 | } | 166 | } |
179 | 167 | ||
180 | CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init) | 168 | CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); |