mlock: replace stale comments in munlock_vma_page()
[linux-2.6.git] / arch / arm / plat-nomadik / timer.c
blob62f18ad43a282b9019e97b5b2a974d5ef8a9802d
1 /*
2 * linux/arch/arm/mach-nomadik/timer.c
4 * Copyright (C) 2008 STMicroelectronics
5 * Copyright (C) 2009 Alessandro Rubini, somewhat based on at91sam926x
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2, as
9 * published by the Free Software Foundation.
11 #include <linux/init.h>
12 #include <linux/interrupt.h>
13 #include <linux/irq.h>
14 #include <linux/io.h>
15 #include <linux/clockchips.h>
16 #include <linux/jiffies.h>
17 #include <asm/mach/time.h>
19 #include <plat/mtu.h>
21 static u32 nmdk_count; /* accumulated count */
22 static u32 nmdk_cycle; /* write-once */
24 /* setup by the platform code */
25 void __iomem *mtu_base;
28 * clocksource: the MTU device is a decrementing counters, so we negate
29 * the value being read.
31 static cycle_t nmdk_read_timer(struct clocksource *cs)
33 u32 count = readl(mtu_base + MTU_VAL(0));
34 return nmdk_count + nmdk_cycle - count;
38 static struct clocksource nmdk_clksrc = {
39 .name = "mtu_0",
40 .rating = 120,
41 .read = nmdk_read_timer,
42 .shift = 20,
43 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
47 * Clockevent device: currently only periodic mode is supported
49 static void nmdk_clkevt_mode(enum clock_event_mode mode,
50 struct clock_event_device *dev)
52 unsigned long flags;
54 switch (mode) {
55 case CLOCK_EVT_MODE_PERIODIC:
56 /* enable interrupts -- and count current value? */
57 raw_local_irq_save(flags);
58 writel(readl(mtu_base + MTU_IMSC) | 1, mtu_base + MTU_IMSC);
59 raw_local_irq_restore(flags);
60 break;
61 case CLOCK_EVT_MODE_ONESHOT:
62 BUG(); /* Not supported, yet */
63 /* FALLTHROUGH */
64 case CLOCK_EVT_MODE_SHUTDOWN:
65 case CLOCK_EVT_MODE_UNUSED:
66 /* disable irq */
67 raw_local_irq_save(flags);
68 writel(readl(mtu_base + MTU_IMSC) & ~1, mtu_base + MTU_IMSC);
69 raw_local_irq_restore(flags);
70 break;
71 case CLOCK_EVT_MODE_RESUME:
72 break;
76 static struct clock_event_device nmdk_clkevt = {
77 .name = "mtu_0",
78 .features = CLOCK_EVT_FEAT_PERIODIC,
79 .shift = 32,
80 .rating = 100,
81 .set_mode = nmdk_clkevt_mode,
85 * IRQ Handler for the timer 0 of the MTU block. The irq is not shared
86 * as we are the only users of mtu0 by now.
88 static irqreturn_t nmdk_timer_interrupt(int irq, void *dev_id)
90 /* ack: "interrupt clear register" */
91 writel(1 << 0, mtu_base + MTU_ICR);
93 /* we can't count lost ticks, unfortunately */
94 nmdk_count += nmdk_cycle;
95 nmdk_clkevt.event_handler(&nmdk_clkevt);
97 return IRQ_HANDLED;
101 * Set up timer interrupt, and return the current time in seconds.
103 static struct irqaction nmdk_timer_irq = {
104 .name = "Nomadik Timer Tick",
105 .flags = IRQF_DISABLED | IRQF_TIMER,
106 .handler = nmdk_timer_interrupt,
109 static void nmdk_timer_reset(void)
111 u32 cr;
113 writel(0, mtu_base + MTU_CR(0)); /* off */
115 /* configure load and background-load, and fire it up */
116 writel(nmdk_cycle, mtu_base + MTU_LR(0));
117 writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
118 cr = MTU_CRn_PERIODIC | MTU_CRn_PRESCALE_1 | MTU_CRn_32BITS;
119 writel(cr, mtu_base + MTU_CR(0));
120 writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
123 void __init nmdk_timer_init(void)
125 unsigned long rate;
126 int bits;
128 rate = CLOCK_TICK_RATE; /* 2.4MHz */
129 nmdk_cycle = (rate + HZ/2) / HZ;
131 /* Init the timer and register clocksource */
132 nmdk_timer_reset();
134 nmdk_clksrc.mult = clocksource_hz2mult(rate, nmdk_clksrc.shift);
135 bits = 8*sizeof(nmdk_count);
136 nmdk_clksrc.mask = CLOCKSOURCE_MASK(bits);
138 if (clocksource_register(&nmdk_clksrc))
139 printk(KERN_ERR "timer: failed to initialize clock "
140 "source %s\n", nmdk_clksrc.name);
142 /* Register irq and clockevents */
143 setup_irq(IRQ_MTU0, &nmdk_timer_irq);
144 nmdk_clkevt.mult = div_sc(rate, NSEC_PER_SEC, nmdk_clkevt.shift);
145 nmdk_clkevt.cpumask = cpumask_of(0);
146 clockevents_register_device(&nmdk_clkevt);