]> Pileus Git - ~andy/linux/blob - arch/arm/mach-prima2/timer-marco.c
Merge tag 'tegra-for-3.10-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git...
[~andy/linux] / arch / arm / mach-prima2 / timer-marco.c
1 /*
2  * System timer for CSR SiRFprimaII
3  *
4  * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
5  *
6  * Licensed under GPLv2 or later.
7  */
8
9 #include <linux/kernel.h>
10 #include <linux/interrupt.h>
11 #include <linux/clockchips.h>
12 #include <linux/clocksource.h>
13 #include <linux/bitops.h>
14 #include <linux/irq.h>
15 #include <linux/clk.h>
16 #include <linux/slab.h>
17 #include <linux/of.h>
18 #include <linux/of_irq.h>
19 #include <linux/of_address.h>
20 #include <asm/sched_clock.h>
21 #include <asm/localtimer.h>
22 #include <asm/mach/time.h>
23
24 #include "common.h"
25
26 #define SIRFSOC_TIMER_32COUNTER_0_CTRL                  0x0000
27 #define SIRFSOC_TIMER_32COUNTER_1_CTRL                  0x0004
28 #define SIRFSOC_TIMER_MATCH_0                           0x0018
29 #define SIRFSOC_TIMER_MATCH_1                           0x001c
30 #define SIRFSOC_TIMER_COUNTER_0                         0x0048
31 #define SIRFSOC_TIMER_COUNTER_1                         0x004c
32 #define SIRFSOC_TIMER_INTR_STATUS                       0x0060
33 #define SIRFSOC_TIMER_WATCHDOG_EN                       0x0064
34 #define SIRFSOC_TIMER_64COUNTER_CTRL                    0x0068
35 #define SIRFSOC_TIMER_64COUNTER_LO                      0x006c
36 #define SIRFSOC_TIMER_64COUNTER_HI                      0x0070
37 #define SIRFSOC_TIMER_64COUNTER_LOAD_LO                 0x0074
38 #define SIRFSOC_TIMER_64COUNTER_LOAD_HI                 0x0078
39 #define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO             0x007c
40 #define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI             0x0080
41
42 #define SIRFSOC_TIMER_REG_CNT 6
43
44 static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
45         SIRFSOC_TIMER_WATCHDOG_EN,
46         SIRFSOC_TIMER_32COUNTER_0_CTRL,
47         SIRFSOC_TIMER_32COUNTER_1_CTRL,
48         SIRFSOC_TIMER_64COUNTER_CTRL,
49         SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
50         SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
51 };
52
53 static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
54
55 static void __iomem *sirfsoc_timer_base;
56 static void __init sirfsoc_of_timer_map(void);
57
58 /* disable count and interrupt */
59 static inline void sirfsoc_timer_count_disable(int idx)
60 {
61         writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
62                 sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
63 }
64
65 /* enable count and interrupt */
66 static inline void sirfsoc_timer_count_enable(int idx)
67 {
68         writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
69                 sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
70 }
71
72 /* timer interrupt handler */
73 static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
74 {
75         struct clock_event_device *ce = dev_id;
76         int cpu = smp_processor_id();
77
78         /* clear timer interrupt */
79         writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
80
81         if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
82                 sirfsoc_timer_count_disable(cpu);
83
84         ce->event_handler(ce);
85
86         return IRQ_HANDLED;
87 }
88
89 /* read 64-bit timer counter */
90 static cycle_t sirfsoc_timer_read(struct clocksource *cs)
91 {
92         u64 cycles;
93
94         writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
95                         BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
96
97         cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
98         cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
99
100         return cycles;
101 }
102
103 static int sirfsoc_timer_set_next_event(unsigned long delta,
104         struct clock_event_device *ce)
105 {
106         int cpu = smp_processor_id();
107
108         writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
109                 4 * cpu);
110         writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
111                 4 * cpu);
112
113         /* enable the tick */
114         sirfsoc_timer_count_enable(cpu);
115
116         return 0;
117 }
118
119 static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
120         struct clock_event_device *ce)
121 {
122         switch (mode) {
123         case CLOCK_EVT_MODE_ONESHOT:
124                 /* enable in set_next_event */
125                 break;
126         default:
127                 break;
128         }
129
130         sirfsoc_timer_count_disable(smp_processor_id());
131 }
132
133 static void sirfsoc_clocksource_suspend(struct clocksource *cs)
134 {
135         int i;
136
137         for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
138                 sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
139 }
140
141 static void sirfsoc_clocksource_resume(struct clocksource *cs)
142 {
143         int i;
144
145         for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
146                 writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
147
148         writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
149                 sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
150         writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
151                 sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
152
153         writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
154                 BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
155 }
156
157 static struct clock_event_device sirfsoc_clockevent = {
158         .name = "sirfsoc_clockevent",
159         .rating = 200,
160         .features = CLOCK_EVT_FEAT_ONESHOT,
161         .set_mode = sirfsoc_timer_set_mode,
162         .set_next_event = sirfsoc_timer_set_next_event,
163 };
164
165 static struct clocksource sirfsoc_clocksource = {
166         .name = "sirfsoc_clocksource",
167         .rating = 200,
168         .mask = CLOCKSOURCE_MASK(64),
169         .flags = CLOCK_SOURCE_IS_CONTINUOUS,
170         .read = sirfsoc_timer_read,
171         .suspend = sirfsoc_clocksource_suspend,
172         .resume = sirfsoc_clocksource_resume,
173 };
174
175 static struct irqaction sirfsoc_timer_irq = {
176         .name = "sirfsoc_timer0",
177         .flags = IRQF_TIMER | IRQF_NOBALANCING,
178         .handler = sirfsoc_timer_interrupt,
179         .dev_id = &sirfsoc_clockevent,
180 };
181
182 #ifdef CONFIG_LOCAL_TIMERS
183
184 static struct irqaction sirfsoc_timer1_irq = {
185         .name = "sirfsoc_timer1",
186         .flags = IRQF_TIMER | IRQF_NOBALANCING,
187         .handler = sirfsoc_timer_interrupt,
188 };
189
190 static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
191 {
192         /* Use existing clock_event for cpu 0 */
193         if (!smp_processor_id())
194                 return 0;
195
196         ce->irq = sirfsoc_timer1_irq.irq;
197         ce->name = "local_timer";
198         ce->features = sirfsoc_clockevent.features;
199         ce->rating = sirfsoc_clockevent.rating;
200         ce->set_mode = sirfsoc_timer_set_mode;
201         ce->set_next_event = sirfsoc_timer_set_next_event;
202         ce->shift = sirfsoc_clockevent.shift;
203         ce->mult = sirfsoc_clockevent.mult;
204         ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
205         ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
206
207         sirfsoc_timer1_irq.dev_id = ce;
208         BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
209         irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
210
211         clockevents_register_device(ce);
212         return 0;
213 }
214
215 static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
216 {
217         sirfsoc_timer_count_disable(1);
218
219         remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
220 }
221
222 static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
223         .setup  = sirfsoc_local_timer_setup,
224         .stop   = sirfsoc_local_timer_stop,
225 };
226 #endif /* CONFIG_LOCAL_TIMERS */
227
228 static void __init sirfsoc_clockevent_init(void)
229 {
230         clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
231
232         sirfsoc_clockevent.max_delta_ns =
233                 clockevent_delta2ns(-2, &sirfsoc_clockevent);
234         sirfsoc_clockevent.min_delta_ns =
235                 clockevent_delta2ns(2, &sirfsoc_clockevent);
236
237         sirfsoc_clockevent.cpumask = cpumask_of(0);
238         clockevents_register_device(&sirfsoc_clockevent);
239 #ifdef CONFIG_LOCAL_TIMERS
240         local_timer_register(&sirfsoc_local_timer_ops);
241 #endif
242 }
243
244 /* initialize the kernel jiffy timer source */
245 void __init sirfsoc_marco_timer_init(void)
246 {
247         unsigned long rate;
248         u32 timer_div;
249         struct clk *clk;
250
251         /* initialize clocking early, we want to set the OS timer */
252         sirfsoc_of_clk_init();
253
254         /* timer's input clock is io clock */
255         clk = clk_get_sys("io", NULL);
256
257         BUG_ON(IS_ERR(clk));
258         rate = clk_get_rate(clk);
259
260         BUG_ON(rate < CLOCK_TICK_RATE);
261         BUG_ON(rate % CLOCK_TICK_RATE);
262
263         sirfsoc_of_timer_map();
264
265         /* Initialize the timer dividers */
266         timer_div = rate / CLOCK_TICK_RATE - 1;
267         writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
268         writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
269         writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
270
271         /* Initialize timer counters to 0 */
272         writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
273         writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
274         writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
275                 BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
276         writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
277         writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
278
279         /* Clear all interrupts */
280         writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
281
282         BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
283
284         BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
285
286         sirfsoc_clockevent_init();
287 }
288
289 static struct of_device_id timer_ids[] = {
290         { .compatible = "sirf,marco-tick" },
291         {},
292 };
293
294 static void __init sirfsoc_of_timer_map(void)
295 {
296         struct device_node *np;
297
298         np = of_find_matching_node(NULL, timer_ids);
299         if (!np)
300                 return;
301         sirfsoc_timer_base = of_iomap(np, 0);
302         if (!sirfsoc_timer_base)
303                 panic("unable to map timer cpu registers\n");
304
305         sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
306         if (!sirfsoc_timer_irq.irq)
307                 panic("No irq passed for timer0 via DT\n");
308
309 #ifdef CONFIG_LOCAL_TIMERS
310         sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
311         if (!sirfsoc_timer1_irq.irq)
312                 panic("No irq passed for timer1 via DT\n");
313 #endif
314
315         of_node_put(np);
316 }