aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-zynq/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-zynq/timer.c')
-rw-r--r--arch/arm/mach-zynq/timer.c261
1 files changed, 188 insertions, 73 deletions
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
index f9fbc9c1e7a6..82357d94a0e0 100644
--- a/arch/arm/mach-zynq/timer.c
+++ b/arch/arm/mach-zynq/timer.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * This file contains driver for the Xilinx PS Timer Counter IP. 2 * This file contains driver for the Xilinx PS Timer Counter IP.
3 * 3 *
4 * Copyright (C) 2011 Xilinx 4 * Copyright (C) 2011-2013 Xilinx
5 * 5 *
6 * based on arch/mips/kernel/time.c timer driver 6 * based on arch/mips/kernel/time.c timer driver
7 * 7 *
@@ -15,6 +15,7 @@
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 */ 16 */
17 17
18#include <linux/clk.h>
18#include <linux/interrupt.h> 19#include <linux/interrupt.h>
19#include <linux/clockchips.h> 20#include <linux/clockchips.h>
20#include <linux/of_address.h> 21#include <linux/of_address.h>
@@ -24,6 +25,21 @@
24#include "common.h" 25#include "common.h"
25 26
26/* 27/*
28 * This driver configures the 2 16-bit count-up timers as follows:
29 *
30 * T1: Timer 1, clocksource for generic timekeeping
31 * T2: Timer 2, clockevent source for hrtimers
32 * T3: Timer 3, <unused>
33 *
34 * The input frequency to the timer module for emulation is 2.5MHz which is
35 * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
36 * the timers are clocked at 78.125KHz (12.8 us resolution).
37
38 * The input frequency to the timer module in silicon is configurable and
39 * obtained from device tree. The pre-scaler of 32 is used.
40 */
41
42/*
27 * Timer Register Offset Definitions of Timer 1, Increment base address by 4 43 * Timer Register Offset Definitions of Timer 1, Increment base address by 4
28 * and use same offsets for Timer 2 44 * and use same offsets for Timer 2
29 */ 45 */
@@ -44,17 +60,24 @@
44#define PRESCALE 2048 /* The exponent must match this */ 60#define PRESCALE 2048 /* The exponent must match this */
45#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) 61#define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1)
46#define CLK_CNTRL_PRESCALE_EN 1 62#define CLK_CNTRL_PRESCALE_EN 1
47#define CNT_CNTRL_RESET (1<<4) 63#define CNT_CNTRL_RESET (1 << 4)
48 64
49/** 65/**
50 * struct xttcps_timer - This definition defines local timer structure 66 * struct xttcps_timer - This definition defines local timer structure
51 * 67 *
52 * @base_addr: Base address of timer 68 * @base_addr: Base address of timer
53 **/ 69 * @clk: Associated clock source
70 * @clk_rate_change_nb Notifier block for clock rate changes
71 */
54struct xttcps_timer { 72struct xttcps_timer {
55 void __iomem *base_addr; 73 void __iomem *base_addr;
74 struct clk *clk;
75 struct notifier_block clk_rate_change_nb;
56}; 76};
57 77
78#define to_xttcps_timer(x) \
79 container_of(x, struct xttcps_timer, clk_rate_change_nb)
80
58struct xttcps_timer_clocksource { 81struct xttcps_timer_clocksource {
59 struct xttcps_timer xttc; 82 struct xttcps_timer xttc;
60 struct clocksource cs; 83 struct clocksource cs;
@@ -66,7 +89,6 @@ struct xttcps_timer_clocksource {
66struct xttcps_timer_clockevent { 89struct xttcps_timer_clockevent {
67 struct xttcps_timer xttc; 90 struct xttcps_timer xttc;
68 struct clock_event_device ce; 91 struct clock_event_device ce;
69 struct clk *clk;
70}; 92};
71 93
72#define to_xttcps_timer_clkevent(x) \ 94#define to_xttcps_timer_clkevent(x) \
@@ -167,8 +189,8 @@ static void xttcps_set_mode(enum clock_event_mode mode,
167 switch (mode) { 189 switch (mode) {
168 case CLOCK_EVT_MODE_PERIODIC: 190 case CLOCK_EVT_MODE_PERIODIC:
169 xttcps_set_interval(timer, 191 xttcps_set_interval(timer,
170 DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk), 192 DIV_ROUND_CLOSEST(clk_get_rate(xttce->xttc.clk),
171 PRESCALE * HZ)); 193 PRESCALE * HZ));
172 break; 194 break;
173 case CLOCK_EVT_MODE_ONESHOT: 195 case CLOCK_EVT_MODE_ONESHOT:
174 case CLOCK_EVT_MODE_UNUSED: 196 case CLOCK_EVT_MODE_UNUSED:
@@ -189,79 +211,148 @@ static void xttcps_set_mode(enum clock_event_mode mode,
189 } 211 }
190} 212}
191 213
192static void __init zynq_ttc_setup_clocksource(struct device_node *np, 214static int xttcps_rate_change_clocksource_cb(struct notifier_block *nb,
193 void __iomem *base) 215 unsigned long event, void *data)
216{
217 struct clk_notifier_data *ndata = data;
218 struct xttcps_timer *xttcps = to_xttcps_timer(nb);
219 struct xttcps_timer_clocksource *xttccs = container_of(xttcps,
220 struct xttcps_timer_clocksource, xttc);
221
222 switch (event) {
223 case POST_RATE_CHANGE:
224 /*
225 * Do whatever is necessary to maintain a proper time base
226 *
227 * I cannot find a way to adjust the currently used clocksource
228 * to the new frequency. __clocksource_updatefreq_hz() sounds
229 * good, but does not work. Not sure what's that missing.
230 *
231 * This approach works, but triggers two clocksource switches.
232 * The first after unregister to clocksource jiffies. And
233 * another one after the register to the newly registered timer.
234 *
235 * Alternatively we could 'waste' another HW timer to ping pong
236 * between clock sources. That would also use one register and
237 * one unregister call, but only trigger one clocksource switch
238 * for the cost of another HW timer used by the OS.
239 */
240 clocksource_unregister(&xttccs->cs);
241 clocksource_register_hz(&xttccs->cs,
242 ndata->new_rate / PRESCALE);
243 /* fall through */
244 case PRE_RATE_CHANGE:
245 case ABORT_RATE_CHANGE:
246 default:
247 return NOTIFY_DONE;
248 }
249}
250
251static void __init xttc_setup_clocksource(struct clk *clk, void __iomem *base)
194{ 252{
195 struct xttcps_timer_clocksource *ttccs; 253 struct xttcps_timer_clocksource *ttccs;
196 struct clk *clk;
197 int err; 254 int err;
198 u32 reg;
199 255
200 ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); 256 ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
201 if (WARN_ON(!ttccs)) 257 if (WARN_ON(!ttccs))
202 return; 258 return;
203 259
204 err = of_property_read_u32(np, "reg", &reg); 260 ttccs->xttc.clk = clk;
205 if (WARN_ON(err))
206 return;
207 261
208 clk = of_clk_get_by_name(np, "cpu_1x"); 262 err = clk_prepare_enable(ttccs->xttc.clk);
209 if (WARN_ON(IS_ERR(clk)))
210 return;
211
212 err = clk_prepare_enable(clk);
213 if (WARN_ON(err)) 263 if (WARN_ON(err))
214 return; 264 return;
215 265
216 ttccs->xttc.base_addr = base + reg * 4; 266 ttccs->xttc.clk_rate_change_nb.notifier_call =
267 xttcps_rate_change_clocksource_cb;
268 ttccs->xttc.clk_rate_change_nb.next = NULL;
269 if (clk_notifier_register(ttccs->xttc.clk,
270 &ttccs->xttc.clk_rate_change_nb))
271 pr_warn("Unable to register clock notifier.\n");
217 272
218 ttccs->cs.name = np->name; 273 ttccs->xttc.base_addr = base;
274 ttccs->cs.name = "xttcps_clocksource";
219 ttccs->cs.rating = 200; 275 ttccs->cs.rating = 200;
220 ttccs->cs.read = __xttc_clocksource_read; 276 ttccs->cs.read = __xttc_clocksource_read;
221 ttccs->cs.mask = CLOCKSOURCE_MASK(16); 277 ttccs->cs.mask = CLOCKSOURCE_MASK(16);
222 ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; 278 ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
223 279
280 /*
281 * Setup the clock source counter to be an incrementing counter
282 * with no interrupt and it rolls over at 0xFFFF. Pre-scale
283 * it by 32 also. Let it start running now.
284 */
224 __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPS_IER_OFFSET); 285 __raw_writel(0x0, ttccs->xttc.base_addr + XTTCPS_IER_OFFSET);
225 __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, 286 __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
226 ttccs->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); 287 ttccs->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET);
227 __raw_writel(CNT_CNTRL_RESET, 288 __raw_writel(CNT_CNTRL_RESET,
228 ttccs->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); 289 ttccs->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET);
229 290
230 err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE); 291 err = clocksource_register_hz(&ttccs->cs,
292 clk_get_rate(ttccs->xttc.clk) / PRESCALE);
231 if (WARN_ON(err)) 293 if (WARN_ON(err))
232 return; 294 return;
295
233} 296}
234 297
235static void __init zynq_ttc_setup_clockevent(struct device_node *np, 298static int xttcps_rate_change_clockevent_cb(struct notifier_block *nb,
236 void __iomem *base) 299 unsigned long event, void *data)
300{
301 struct clk_notifier_data *ndata = data;
302 struct xttcps_timer *xttcps = to_xttcps_timer(nb);
303 struct xttcps_timer_clockevent *xttcce = container_of(xttcps,
304 struct xttcps_timer_clockevent, xttc);
305
306 switch (event) {
307 case POST_RATE_CHANGE:
308 {
309 unsigned long flags;
310
311 /*
312 * clockevents_update_freq should be called with IRQ disabled on
313 * the CPU the timer provides events for. The timer we use is
314 * common to both CPUs, not sure if we need to run on both
315 * cores.
316 */
317 local_irq_save(flags);
318 clockevents_update_freq(&xttcce->ce,
319 ndata->new_rate / PRESCALE);
320 local_irq_restore(flags);
321
322 /* fall through */
323 }
324 case PRE_RATE_CHANGE:
325 case ABORT_RATE_CHANGE:
326 default:
327 return NOTIFY_DONE;
328 }
329}
330
331static void __init xttc_setup_clockevent(struct clk *clk,
332 void __iomem *base, u32 irq)
237{ 333{
238 struct xttcps_timer_clockevent *ttcce; 334 struct xttcps_timer_clockevent *ttcce;
239 int err, irq; 335 int err;
240 u32 reg;
241 336
242 ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); 337 ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
243 if (WARN_ON(!ttcce)) 338 if (WARN_ON(!ttcce))
244 return; 339 return;
245 340
246 err = of_property_read_u32(np, "reg", &reg); 341 ttcce->xttc.clk = clk;
247 if (WARN_ON(err))
248 return;
249 342
250 ttcce->xttc.base_addr = base + reg * 4; 343 err = clk_prepare_enable(ttcce->xttc.clk);
251
252 ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
253 if (WARN_ON(IS_ERR(ttcce->clk)))
254 return;
255
256 err = clk_prepare_enable(ttcce->clk);
257 if (WARN_ON(err)) 344 if (WARN_ON(err))
258 return; 345 return;
259 346
260 irq = irq_of_parse_and_map(np, 0); 347 ttcce->xttc.clk_rate_change_nb.notifier_call =
261 if (WARN_ON(!irq)) 348 xttcps_rate_change_clockevent_cb;
262 return; 349 ttcce->xttc.clk_rate_change_nb.next = NULL;
350 if (clk_notifier_register(ttcce->xttc.clk,
351 &ttcce->xttc.clk_rate_change_nb))
352 pr_warn("Unable to register clock notifier.\n");
263 353
264 ttcce->ce.name = np->name; 354 ttcce->xttc.base_addr = base;
355 ttcce->ce.name = "xttcps_clockevent";
265 ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; 356 ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
266 ttcce->ce.set_next_event = xttcps_set_next_event; 357 ttcce->ce.set_next_event = xttcps_set_next_event;
267 ttcce->ce.set_mode = xttcps_set_mode; 358 ttcce->ce.set_mode = xttcps_set_mode;
@@ -269,56 +360,80 @@ static void __init zynq_ttc_setup_clockevent(struct device_node *np,
269 ttcce->ce.irq = irq; 360 ttcce->ce.irq = irq;
270 ttcce->ce.cpumask = cpu_possible_mask; 361 ttcce->ce.cpumask = cpu_possible_mask;
271 362
363 /*
364 * Setup the clock event timer to be an interval timer which
365 * is prescaled by 32 using the interval interrupt. Leave it
366 * disabled for now.
367 */
272 __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET); 368 __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET);
273 __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, 369 __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
274 ttcce->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET); 370 ttcce->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET);
275 __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPS_IER_OFFSET); 371 __raw_writel(0x1, ttcce->xttc.base_addr + XTTCPS_IER_OFFSET);
276 372
277 err = request_irq(irq, xttcps_clock_event_interrupt, IRQF_TIMER, 373 err = request_irq(irq, xttcps_clock_event_interrupt,
278 np->name, ttcce); 374 IRQF_DISABLED | IRQF_TIMER,
375 ttcce->ce.name, ttcce);
279 if (WARN_ON(err)) 376 if (WARN_ON(err))
280 return; 377 return;
281 378
282 clockevents_config_and_register(&ttcce->ce, 379 clockevents_config_and_register(&ttcce->ce,
283 clk_get_rate(ttcce->clk) / PRESCALE, 380 clk_get_rate(ttcce->xttc.clk) / PRESCALE, 1, 0xfffe);
284 1, 0xfffe);
285} 381}
286 382
287static const __initconst struct of_device_id zynq_ttc_match[] = {
288 { .compatible = "xlnx,ttc-counter-clocksource",
289 .data = zynq_ttc_setup_clocksource, },
290 { .compatible = "xlnx,ttc-counter-clockevent",
291 .data = zynq_ttc_setup_clockevent, },
292 {}
293};
294
295/** 383/**
296 * xttcps_timer_init - Initialize the timer 384 * xttcps_timer_init - Initialize the timer
297 * 385 *
298 * Initializes the timer hardware and register the clock source and clock event 386 * Initializes the timer hardware and register the clock source and clock event
299 * timers with Linux kernal timer framework 387 * timers with Linux kernal timer framework
300 **/ 388 */
389static void __init xttcps_timer_init_of(struct device_node *timer)
390{
391 unsigned int irq;
392 void __iomem *timer_baseaddr;
393 struct clk *clk;
394
395 /*
396 * Get the 1st Triple Timer Counter (TTC) block from the device tree
397 * and use it. Note that the event timer uses the interrupt and it's the
398 * 2nd TTC hence the irq_of_parse_and_map(,1)
399 */
400 timer_baseaddr = of_iomap(timer, 0);
401 if (!timer_baseaddr) {
402 pr_err("ERROR: invalid timer base address\n");
403 BUG();
404 }
405
406 irq = irq_of_parse_and_map(timer, 1);
407 if (irq <= 0) {
408 pr_err("ERROR: invalid interrupt number\n");
409 BUG();
410 }
411
412 clk = of_clk_get_by_name(timer, "cpu_1x");
413 if (IS_ERR(clk)) {
414 pr_err("ERROR: timer input clock not found\n");
415 BUG();
416 }
417
418 xttc_setup_clocksource(clk, timer_baseaddr);
419 xttc_setup_clockevent(clk, timer_baseaddr + 4, irq);
420
421 pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq);
422}
423
301void __init xttcps_timer_init(void) 424void __init xttcps_timer_init(void)
302{ 425{
303 struct device_node *np; 426 const char * const timer_list[] = {
304 427 "cdns,ttc",
305 for_each_compatible_node(np, NULL, "xlnx,ttc") { 428 NULL
306 struct device_node *np_chld; 429 };
307 void __iomem *base; 430 struct device_node *timer;
308 431
309 base = of_iomap(np, 0); 432 timer = of_find_compatible_node(NULL, NULL, timer_list[0]);
310 if (WARN_ON(!base)) 433 if (!timer) {
311 return; 434 pr_err("ERROR: no compatible timer found\n");
312 435 BUG();
313 for_each_available_child_of_node(np, np_chld) {
314 int (*cb)(struct device_node *np, void __iomem *base);
315 const struct of_device_id *match;
316
317 match = of_match_node(zynq_ttc_match, np_chld);
318 if (match) {
319 cb = match->data;
320 cb(np_chld, base);
321 }
322 }
323 } 436 }
437
438 xttcps_timer_init_of(timer);
324} 439}