diff options
Diffstat (limited to 'drivers/clocksource/cadence_ttc_timer.c')
-rw-r--r-- | drivers/clocksource/cadence_ttc_timer.c | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c new file mode 100644 index 000000000000..685bc60e210a --- /dev/null +++ b/drivers/clocksource/cadence_ttc_timer.c | |||
@@ -0,0 +1,436 @@ | |||
1 | /* | ||
2 | * This file contains driver for the Cadence Triple Timer Counter Rev 06 | ||
3 | * | ||
4 | * Copyright (C) 2011-2013 Xilinx | ||
5 | * | ||
6 | * based on arch/mips/kernel/time.c timer driver | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
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 | |||
18 | #include <linux/clk.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/clockchips.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/of_irq.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/clk-provider.h> | ||
25 | |||
26 | /* | ||
27 | * This driver configures the 2 16-bit count-up timers as follows: | ||
28 | * | ||
29 | * T1: Timer 1, clocksource for generic timekeeping | ||
30 | * T2: Timer 2, clockevent source for hrtimers | ||
31 | * T3: Timer 3, <unused> | ||
32 | * | ||
33 | * The input frequency to the timer module for emulation is 2.5MHz which is | ||
34 | * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32, | ||
35 | * the timers are clocked at 78.125KHz (12.8 us resolution). | ||
36 | |||
37 | * The input frequency to the timer module in silicon is configurable and | ||
38 | * obtained from device tree. The pre-scaler of 32 is used. | ||
39 | */ | ||
40 | |||
41 | /* | ||
42 | * Timer Register Offset Definitions of Timer 1, Increment base address by 4 | ||
43 | * and use same offsets for Timer 2 | ||
44 | */ | ||
45 | #define TTC_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ | ||
46 | #define TTC_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ | ||
47 | #define TTC_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ | ||
48 | #define TTC_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ | ||
49 | #define TTC_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ | ||
50 | #define TTC_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ | ||
51 | |||
52 | #define TTC_CNT_CNTRL_DISABLE_MASK 0x1 | ||
53 | |||
54 | /* | ||
55 | * Setup the timers to use pre-scaling, using a fixed value for now that will | ||
56 | * work across most input frequency, but it may need to be more dynamic | ||
57 | */ | ||
58 | #define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ | ||
59 | #define PRESCALE 2048 /* The exponent must match this */ | ||
60 | #define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) | ||
61 | #define CLK_CNTRL_PRESCALE_EN 1 | ||
62 | #define CNT_CNTRL_RESET (1 << 4) | ||
63 | |||
64 | /** | ||
65 | * struct ttc_timer - This definition defines local timer structure | ||
66 | * | ||
67 | * @base_addr: Base address of timer | ||
68 | * @clk: Associated clock source | ||
69 | * @clk_rate_change_nb Notifier block for clock rate changes | ||
70 | */ | ||
71 | struct ttc_timer { | ||
72 | void __iomem *base_addr; | ||
73 | struct clk *clk; | ||
74 | struct notifier_block clk_rate_change_nb; | ||
75 | }; | ||
76 | |||
77 | #define to_ttc_timer(x) \ | ||
78 | container_of(x, struct ttc_timer, clk_rate_change_nb) | ||
79 | |||
80 | struct ttc_timer_clocksource { | ||
81 | struct ttc_timer ttc; | ||
82 | struct clocksource cs; | ||
83 | }; | ||
84 | |||
85 | #define to_ttc_timer_clksrc(x) \ | ||
86 | container_of(x, struct ttc_timer_clocksource, cs) | ||
87 | |||
88 | struct ttc_timer_clockevent { | ||
89 | struct ttc_timer ttc; | ||
90 | struct clock_event_device ce; | ||
91 | }; | ||
92 | |||
93 | #define to_ttc_timer_clkevent(x) \ | ||
94 | container_of(x, struct ttc_timer_clockevent, ce) | ||
95 | |||
96 | /** | ||
97 | * ttc_set_interval - Set the timer interval value | ||
98 | * | ||
99 | * @timer: Pointer to the timer instance | ||
100 | * @cycles: Timer interval ticks | ||
101 | **/ | ||
102 | static void ttc_set_interval(struct ttc_timer *timer, | ||
103 | unsigned long cycles) | ||
104 | { | ||
105 | u32 ctrl_reg; | ||
106 | |||
107 | /* Disable the counter, set the counter value and re-enable counter */ | ||
108 | ctrl_reg = __raw_readl(timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
109 | ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; | ||
110 | __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
111 | |||
112 | __raw_writel(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); | ||
113 | |||
114 | /* | ||
115 | * Reset the counter (0x10) so that it starts from 0, one-shot | ||
116 | * mode makes this needed for timing to be right. | ||
117 | */ | ||
118 | ctrl_reg |= CNT_CNTRL_RESET; | ||
119 | ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; | ||
120 | __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * ttc_clock_event_interrupt - Clock event timer interrupt handler | ||
125 | * | ||
126 | * @irq: IRQ number of the Timer | ||
127 | * @dev_id: void pointer to the ttc_timer instance | ||
128 | * | ||
129 | * returns: Always IRQ_HANDLED - success | ||
130 | **/ | ||
131 | static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id) | ||
132 | { | ||
133 | struct ttc_timer_clockevent *ttce = dev_id; | ||
134 | struct ttc_timer *timer = &ttce->ttc; | ||
135 | |||
136 | /* Acknowledge the interrupt and call event handler */ | ||
137 | __raw_readl(timer->base_addr + TTC_ISR_OFFSET); | ||
138 | |||
139 | ttce->ce.event_handler(&ttce->ce); | ||
140 | |||
141 | return IRQ_HANDLED; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * __ttc_clocksource_read - Reads the timer counter register | ||
146 | * | ||
147 | * returns: Current timer counter register value | ||
148 | **/ | ||
149 | static cycle_t __ttc_clocksource_read(struct clocksource *cs) | ||
150 | { | ||
151 | struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; | ||
152 | |||
153 | return (cycle_t)__raw_readl(timer->base_addr + | ||
154 | TTC_COUNT_VAL_OFFSET); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * ttc_set_next_event - Sets the time interval for next event | ||
159 | * | ||
160 | * @cycles: Timer interval ticks | ||
161 | * @evt: Address of clock event instance | ||
162 | * | ||
163 | * returns: Always 0 - success | ||
164 | **/ | ||
165 | static int ttc_set_next_event(unsigned long cycles, | ||
166 | struct clock_event_device *evt) | ||
167 | { | ||
168 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); | ||
169 | struct ttc_timer *timer = &ttce->ttc; | ||
170 | |||
171 | ttc_set_interval(timer, cycles); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * ttc_set_mode - Sets the mode of timer | ||
177 | * | ||
178 | * @mode: Mode to be set | ||
179 | * @evt: Address of clock event instance | ||
180 | **/ | ||
181 | static void ttc_set_mode(enum clock_event_mode mode, | ||
182 | struct clock_event_device *evt) | ||
183 | { | ||
184 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); | ||
185 | struct ttc_timer *timer = &ttce->ttc; | ||
186 | u32 ctrl_reg; | ||
187 | |||
188 | switch (mode) { | ||
189 | case CLOCK_EVT_MODE_PERIODIC: | ||
190 | ttc_set_interval(timer, | ||
191 | DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk), | ||
192 | PRESCALE * HZ)); | ||
193 | break; | ||
194 | case CLOCK_EVT_MODE_ONESHOT: | ||
195 | case CLOCK_EVT_MODE_UNUSED: | ||
196 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
197 | ctrl_reg = __raw_readl(timer->base_addr + | ||
198 | TTC_CNT_CNTRL_OFFSET); | ||
199 | ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; | ||
200 | __raw_writel(ctrl_reg, | ||
201 | timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
202 | break; | ||
203 | case CLOCK_EVT_MODE_RESUME: | ||
204 | ctrl_reg = __raw_readl(timer->base_addr + | ||
205 | TTC_CNT_CNTRL_OFFSET); | ||
206 | ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; | ||
207 | __raw_writel(ctrl_reg, | ||
208 | timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, | ||
214 | unsigned long event, void *data) | ||
215 | { | ||
216 | struct clk_notifier_data *ndata = data; | ||
217 | struct ttc_timer *ttc = to_ttc_timer(nb); | ||
218 | struct ttc_timer_clocksource *ttccs = container_of(ttc, | ||
219 | struct ttc_timer_clocksource, ttc); | ||
220 | |||
221 | switch (event) { | ||
222 | case POST_RATE_CHANGE: | ||
223 | /* | ||
224 | * Do whatever is necessary to maintain a proper time base | ||
225 | * | ||
226 | * I cannot find a way to adjust the currently used clocksource | ||
227 | * to the new frequency. __clocksource_updatefreq_hz() sounds | ||
228 | * good, but does not work. Not sure what's that missing. | ||
229 | * | ||
230 | * This approach works, but triggers two clocksource switches. | ||
231 | * The first after unregister to clocksource jiffies. And | ||
232 | * another one after the register to the newly registered timer. | ||
233 | * | ||
234 | * Alternatively we could 'waste' another HW timer to ping pong | ||
235 | * between clock sources. That would also use one register and | ||
236 | * one unregister call, but only trigger one clocksource switch | ||
237 | * for the cost of another HW timer used by the OS. | ||
238 | */ | ||
239 | clocksource_unregister(&ttccs->cs); | ||
240 | clocksource_register_hz(&ttccs->cs, | ||
241 | ndata->new_rate / PRESCALE); | ||
242 | /* fall through */ | ||
243 | case PRE_RATE_CHANGE: | ||
244 | case ABORT_RATE_CHANGE: | ||
245 | default: | ||
246 | return NOTIFY_DONE; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) | ||
251 | { | ||
252 | struct ttc_timer_clocksource *ttccs; | ||
253 | int err; | ||
254 | |||
255 | ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); | ||
256 | if (WARN_ON(!ttccs)) | ||
257 | return; | ||
258 | |||
259 | ttccs->ttc.clk = clk; | ||
260 | |||
261 | err = clk_prepare_enable(ttccs->ttc.clk); | ||
262 | if (WARN_ON(err)) { | ||
263 | kfree(ttccs); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | ttccs->ttc.clk_rate_change_nb.notifier_call = | ||
268 | ttc_rate_change_clocksource_cb; | ||
269 | ttccs->ttc.clk_rate_change_nb.next = NULL; | ||
270 | if (clk_notifier_register(ttccs->ttc.clk, | ||
271 | &ttccs->ttc.clk_rate_change_nb)) | ||
272 | pr_warn("Unable to register clock notifier.\n"); | ||
273 | |||
274 | ttccs->ttc.base_addr = base; | ||
275 | ttccs->cs.name = "ttc_clocksource"; | ||
276 | ttccs->cs.rating = 200; | ||
277 | ttccs->cs.read = __ttc_clocksource_read; | ||
278 | ttccs->cs.mask = CLOCKSOURCE_MASK(16); | ||
279 | ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
280 | |||
281 | /* | ||
282 | * Setup the clock source counter to be an incrementing counter | ||
283 | * with no interrupt and it rolls over at 0xFFFF. Pre-scale | ||
284 | * it by 32 also. Let it start running now. | ||
285 | */ | ||
286 | __raw_writel(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); | ||
287 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | ||
288 | ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); | ||
289 | __raw_writel(CNT_CNTRL_RESET, | ||
290 | ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); | ||
291 | |||
292 | err = clocksource_register_hz(&ttccs->cs, | ||
293 | clk_get_rate(ttccs->ttc.clk) / PRESCALE); | ||
294 | if (WARN_ON(err)) { | ||
295 | kfree(ttccs); | ||
296 | return; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, | ||
301 | unsigned long event, void *data) | ||
302 | { | ||
303 | struct clk_notifier_data *ndata = data; | ||
304 | struct ttc_timer *ttc = to_ttc_timer(nb); | ||
305 | struct ttc_timer_clockevent *ttcce = container_of(ttc, | ||
306 | struct ttc_timer_clockevent, ttc); | ||
307 | |||
308 | switch (event) { | ||
309 | case POST_RATE_CHANGE: | ||
310 | { | ||
311 | unsigned long flags; | ||
312 | |||
313 | /* | ||
314 | * clockevents_update_freq should be called with IRQ disabled on | ||
315 | * the CPU the timer provides events for. The timer we use is | ||
316 | * common to both CPUs, not sure if we need to run on both | ||
317 | * cores. | ||
318 | */ | ||
319 | local_irq_save(flags); | ||
320 | clockevents_update_freq(&ttcce->ce, | ||
321 | ndata->new_rate / PRESCALE); | ||
322 | local_irq_restore(flags); | ||
323 | |||
324 | /* fall through */ | ||
325 | } | ||
326 | case PRE_RATE_CHANGE: | ||
327 | case ABORT_RATE_CHANGE: | ||
328 | default: | ||
329 | return NOTIFY_DONE; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static void __init ttc_setup_clockevent(struct clk *clk, | ||
334 | void __iomem *base, u32 irq) | ||
335 | { | ||
336 | struct ttc_timer_clockevent *ttcce; | ||
337 | int err; | ||
338 | |||
339 | ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); | ||
340 | if (WARN_ON(!ttcce)) | ||
341 | return; | ||
342 | |||
343 | ttcce->ttc.clk = clk; | ||
344 | |||
345 | err = clk_prepare_enable(ttcce->ttc.clk); | ||
346 | if (WARN_ON(err)) { | ||
347 | kfree(ttcce); | ||
348 | return; | ||
349 | } | ||
350 | |||
351 | ttcce->ttc.clk_rate_change_nb.notifier_call = | ||
352 | ttc_rate_change_clockevent_cb; | ||
353 | ttcce->ttc.clk_rate_change_nb.next = NULL; | ||
354 | if (clk_notifier_register(ttcce->ttc.clk, | ||
355 | &ttcce->ttc.clk_rate_change_nb)) | ||
356 | pr_warn("Unable to register clock notifier.\n"); | ||
357 | |||
358 | ttcce->ttc.base_addr = base; | ||
359 | ttcce->ce.name = "ttc_clockevent"; | ||
360 | ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | ||
361 | ttcce->ce.set_next_event = ttc_set_next_event; | ||
362 | ttcce->ce.set_mode = ttc_set_mode; | ||
363 | ttcce->ce.rating = 200; | ||
364 | ttcce->ce.irq = irq; | ||
365 | ttcce->ce.cpumask = cpu_possible_mask; | ||
366 | |||
367 | /* | ||
368 | * Setup the clock event timer to be an interval timer which | ||
369 | * is prescaled by 32 using the interval interrupt. Leave it | ||
370 | * disabled for now. | ||
371 | */ | ||
372 | __raw_writel(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); | ||
373 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | ||
374 | ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); | ||
375 | __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); | ||
376 | |||
377 | err = request_irq(irq, ttc_clock_event_interrupt, | ||
378 | IRQF_DISABLED | IRQF_TIMER, | ||
379 | ttcce->ce.name, ttcce); | ||
380 | if (WARN_ON(err)) { | ||
381 | kfree(ttcce); | ||
382 | return; | ||
383 | } | ||
384 | |||
385 | clockevents_config_and_register(&ttcce->ce, | ||
386 | clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe); | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * ttc_timer_init - Initialize the timer | ||
391 | * | ||
392 | * Initializes the timer hardware and register the clock source and clock event | ||
393 | * timers with Linux kernal timer framework | ||
394 | */ | ||
395 | static void __init ttc_timer_init(struct device_node *timer) | ||
396 | { | ||
397 | unsigned int irq; | ||
398 | void __iomem *timer_baseaddr; | ||
399 | struct clk *clk; | ||
400 | static int initialized; | ||
401 | |||
402 | if (initialized) | ||
403 | return; | ||
404 | |||
405 | initialized = 1; | ||
406 | |||
407 | /* | ||
408 | * Get the 1st Triple Timer Counter (TTC) block from the device tree | ||
409 | * and use it. Note that the event timer uses the interrupt and it's the | ||
410 | * 2nd TTC hence the irq_of_parse_and_map(,1) | ||
411 | */ | ||
412 | timer_baseaddr = of_iomap(timer, 0); | ||
413 | if (!timer_baseaddr) { | ||
414 | pr_err("ERROR: invalid timer base address\n"); | ||
415 | BUG(); | ||
416 | } | ||
417 | |||
418 | irq = irq_of_parse_and_map(timer, 1); | ||
419 | if (irq <= 0) { | ||
420 | pr_err("ERROR: invalid interrupt number\n"); | ||
421 | BUG(); | ||
422 | } | ||
423 | |||
424 | clk = of_clk_get_by_name(timer, "cpu_1x"); | ||
425 | if (IS_ERR(clk)) { | ||
426 | pr_err("ERROR: timer input clock not found\n"); | ||
427 | BUG(); | ||
428 | } | ||
429 | |||
430 | ttc_setup_clocksource(clk, timer_baseaddr); | ||
431 | ttc_setup_clockevent(clk, timer_baseaddr + 4, irq); | ||
432 | |||
433 | pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); | ||
434 | } | ||
435 | |||
436 | CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init); | ||