aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-integrator/integrator_ap.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2014-10-15 09:30:25 -0400
committerLinus Walleij <linus.walleij@linaro.org>2014-10-28 10:42:34 -0400
commitbeb5818bd012953c79de38f9726f327d8e311569 (patch)
treeeea623f0319fe7aa988fb96cc97ef17cea62852d /arch/arm/mach-integrator/integrator_ap.c
parent9713497b6c64c67c8763f8f07fad325b193764b6 (diff)
ARM: integrator: move AP timer to clocksource
This moves the timer/clocksource implementation for the Integrator/AP down to drivers/clocksource and augments the driver a little to use CLOCKSOURCE_OF_DECLARE(). Remove the static mapping of the timer blocks while we're at it. Tested on the Integrator/AP. Acked-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/mach-integrator/integrator_ap.c')
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c190
1 files changed, 0 insertions, 190 deletions
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 8ca290b479b1..8a879b654fde 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -27,13 +27,9 @@
27#include <linux/syscore_ops.h> 27#include <linux/syscore_ops.h>
28#include <linux/amba/bus.h> 28#include <linux/amba/bus.h>
29#include <linux/amba/kmi.h> 29#include <linux/amba/kmi.h>
30#include <linux/clocksource.h>
31#include <linux/clockchips.h>
32#include <linux/interrupt.h>
33#include <linux/io.h> 30#include <linux/io.h>
34#include <linux/irqchip.h> 31#include <linux/irqchip.h>
35#include <linux/mtd/physmap.h> 32#include <linux/mtd/physmap.h>
36#include <linux/clk.h>
37#include <linux/platform_data/clk-integrator.h> 33#include <linux/platform_data/clk-integrator.h>
38#include <linux/of_irq.h> 34#include <linux/of_irq.h>
39#include <linux/of_address.h> 35#include <linux/of_address.h>
@@ -41,8 +37,6 @@
41#include <linux/stat.h> 37#include <linux/stat.h>
42#include <linux/sys_soc.h> 38#include <linux/sys_soc.h>
43#include <linux/termios.h> 39#include <linux/termios.h>
44#include <linux/sched_clock.h>
45#include <linux/clk-provider.h>
46 40
47#include <asm/hardware/arm_timer.h> 41#include <asm/hardware/arm_timer.h>
48#include <asm/setup.h> 42#include <asm/setup.h>
@@ -89,11 +83,6 @@ static void __iomem *ebi_base;
89 83
90static struct map_desc ap_io_desc[] __initdata __maybe_unused = { 84static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
91 { 85 {
92 .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),
93 .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),
94 .length = SZ_4K,
95 .type = MT_DEVICE
96 }, {
97 .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE), 86 .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
98 .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE), 87 .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
99 .length = SZ_4K, 88 .length = SZ_4K,
@@ -257,188 +246,10 @@ struct amba_pl010_data ap_uart_data = {
257 .set_mctrl = integrator_uart_set_mctrl, 246 .set_mctrl = integrator_uart_set_mctrl,
258}; 247};
259 248
260/*
261 * Where is the timer (VA)?
262 */
263#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
264#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
265#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
266
267static unsigned long timer_reload;
268
269static u64 notrace integrator_read_sched_clock(void)
270{
271 return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
272}
273
274static void integrator_clocksource_init(unsigned long inrate,
275 void __iomem *base)
276{
277 u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
278 unsigned long rate = inrate;
279
280 if (rate >= 1500000) {
281 rate /= 16;
282 ctrl |= TIMER_CTRL_DIV16;
283 }
284
285 writel(0xffff, base + TIMER_LOAD);
286 writel(ctrl, base + TIMER_CTRL);
287
288 clocksource_mmio_init(base + TIMER_VALUE, "timer2",
289 rate, 200, 16, clocksource_mmio_readl_down);
290 sched_clock_register(integrator_read_sched_clock, 16, rate);
291}
292
293static void __iomem * clkevt_base;
294
295/*
296 * IRQ handler for the timer
297 */
298static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
299{
300 struct clock_event_device *evt = dev_id;
301
302 /* clear the interrupt */
303 writel(1, clkevt_base + TIMER_INTCLR);
304
305 evt->event_handler(evt);
306
307 return IRQ_HANDLED;
308}
309
310static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
311{
312 u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
313
314 /* Disable timer */
315 writel(ctrl, clkevt_base + TIMER_CTRL);
316
317 switch (mode) {
318 case CLOCK_EVT_MODE_PERIODIC:
319 /* Enable the timer and start the periodic tick */
320 writel(timer_reload, clkevt_base + TIMER_LOAD);
321 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
322 writel(ctrl, clkevt_base + TIMER_CTRL);
323 break;
324 case CLOCK_EVT_MODE_ONESHOT:
325 /* Leave the timer disabled, .set_next_event will enable it */
326 ctrl &= ~TIMER_CTRL_PERIODIC;
327 writel(ctrl, clkevt_base + TIMER_CTRL);
328 break;
329 case CLOCK_EVT_MODE_UNUSED:
330 case CLOCK_EVT_MODE_SHUTDOWN:
331 case CLOCK_EVT_MODE_RESUME:
332 default:
333 /* Just leave in disabled state */
334 break;
335 }
336
337}
338
339static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
340{
341 unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
342
343 writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
344 writel(next, clkevt_base + TIMER_LOAD);
345 writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
346
347 return 0;
348}
349
350static struct clock_event_device integrator_clockevent = {
351 .name = "timer1",
352 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
353 .set_mode = clkevt_set_mode,
354 .set_next_event = clkevt_set_next_event,
355 .rating = 300,
356};
357
358static struct irqaction integrator_timer_irq = {
359 .name = "timer",
360 .flags = IRQF_TIMER | IRQF_IRQPOLL,
361 .handler = integrator_timer_interrupt,
362 .dev_id = &integrator_clockevent,
363};
364
365static void integrator_clockevent_init(unsigned long inrate,
366 void __iomem *base, int irq)
367{
368 unsigned long rate = inrate;
369 unsigned int ctrl = 0;
370
371 clkevt_base = base;
372 /* Calculate and program a divisor */
373 if (rate > 0x100000 * HZ) {
374 rate /= 256;
375 ctrl |= TIMER_CTRL_DIV256;
376 } else if (rate > 0x10000 * HZ) {
377 rate /= 16;
378 ctrl |= TIMER_CTRL_DIV16;
379 }
380 timer_reload = rate / HZ;
381 writel(ctrl, clkevt_base + TIMER_CTRL);
382
383 setup_irq(irq, &integrator_timer_irq);
384 clockevents_config_and_register(&integrator_clockevent,
385 rate,
386 1,
387 0xffffU);
388}
389
390void __init ap_init_early(void) 249void __init ap_init_early(void)
391{ 250{
392} 251}
393 252
394static void __init ap_of_timer_init(void)
395{
396 struct device_node *node;
397 const char *path;
398 void __iomem *base;
399 int err;
400 int irq;
401 struct clk *clk;
402 unsigned long rate;
403
404 of_clk_init(NULL);
405
406 err = of_property_read_string(of_aliases,
407 "arm,timer-primary", &path);
408 if (WARN_ON(err))
409 return;
410 node = of_find_node_by_path(path);
411 base = of_iomap(node, 0);
412 if (WARN_ON(!base))
413 return;
414
415 clk = of_clk_get(node, 0);
416 BUG_ON(IS_ERR(clk));
417 clk_prepare_enable(clk);
418 rate = clk_get_rate(clk);
419
420 writel(0, base + TIMER_CTRL);
421 integrator_clocksource_init(rate, base);
422
423 err = of_property_read_string(of_aliases,
424 "arm,timer-secondary", &path);
425 if (WARN_ON(err))
426 return;
427 node = of_find_node_by_path(path);
428 base = of_iomap(node, 0);
429 if (WARN_ON(!base))
430 return;
431 irq = irq_of_parse_and_map(node, 0);
432
433 clk = of_clk_get(node, 0);
434 BUG_ON(IS_ERR(clk));
435 clk_prepare_enable(clk);
436 rate = clk_get_rate(clk);
437
438 writel(0, base + TIMER_CTRL);
439 integrator_clockevent_init(rate, base, irq);
440}
441
442static void __init ap_init_irq_of(void) 253static void __init ap_init_irq_of(void)
443{ 254{
444 cm_init(); 255 cm_init();
@@ -553,7 +364,6 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
553 .map_io = ap_map_io, 364 .map_io = ap_map_io,
554 .init_early = ap_init_early, 365 .init_early = ap_init_early,
555 .init_irq = ap_init_irq_of, 366 .init_irq = ap_init_irq_of,
556 .init_time = ap_of_timer_init,
557 .init_machine = ap_init_of, 367 .init_machine = ap_init_of,
558 .restart = integrator_restart, 368 .restart = integrator_restart,
559 .dt_compat = ap_dt_board_compat, 369 .dt_compat = ap_dt_board_compat,