d2d094d37aaa895eae15ff86fbf2a96aa64e8f28
[openwrt/svn-archive/archive.git] / target / linux / ubicom32 / files / arch / ubicom32 / kernel / timer_device.c
1 /*
2 * arch/ubicom32/kernel/timer_device.c
3 * Implements a Ubicom32 clock device and event devices.
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 */
28 #include <linux/types.h>
29 #include <linux/clockchips.h>
30 #include <linux/clocksource.h>
31 #include <linux/spinlock.h>
32 #include <asm/ip5000.h>
33 #include <asm/machdep.h>
34
35 #if defined(CONFIG_SMP)
36 #include <asm/smp.h>
37 #endif
38
39 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
40 #define MAX_TIMERS (2 + CONFIG_TIMER_EXTRA_ALLOC)
41 #else
42 #define MAX_TIMERS (NR_CPUS + CONFIG_TIMER_EXTRA_ALLOC)
43 #endif
44
45 #if (MAX_TIMERS > 10)
46 #error "Ubicom32 only has 10 timers"
47 #endif
48
49 static unsigned int frequency;
50 static struct clock_event_device timer_device_devs[MAX_TIMERS];
51 static struct irqaction timer_device_irqs[MAX_TIMERS];
52 static int timer_device_next_timer = 0;
53
54 DEFINE_SPINLOCK(timer_device_lock);
55
56 /*
57 * timer_device_set_next_event()
58 * Cause the timer to go off "cycles" from now.
59 */
60 static int timer_device_set_next_event(unsigned long cycles, struct clock_event_device *dev)
61 {
62 timer_set(dev->irq, cycles);
63 return 0;
64 }
65
66 /*
67 * timer_device_set_mode()
68 * Handle the mode switch for a clock event device.
69 */
70 static void timer_device_set_mode(enum clock_event_mode mode, struct clock_event_device *dev)
71 {
72 switch (mode) {
73 case CLOCK_EVT_MODE_SHUTDOWN:
74 /*
75 * Make sure the vector is disabled
76 * until the next event is set.
77 */
78 printk(KERN_NOTICE "timer[%d]: shutdown\n", dev->irq);
79 ldsr_disable_vector(dev->irq);
80 break;
81
82 case CLOCK_EVT_MODE_ONESHOT:
83 /*
84 * Make sure the vector is disabled
85 * until the next event is set.
86 */
87 printk(KERN_NOTICE "timer[%d]: oneshot\n", dev->irq);
88 ldsr_disable_vector(dev->irq);
89 break;
90
91 case CLOCK_EVT_MODE_PERIODIC:
92 /*
93 * The periodic request is 1 per jiffies
94 */
95 printk(KERN_NOTICE "timer[%d]: periodic: %d cycles\n",
96 dev->irq, frequency / CONFIG_HZ);
97 timer_set(dev->irq, frequency / CONFIG_HZ);
98 break;
99
100 case CLOCK_EVT_MODE_UNUSED:
101 case CLOCK_EVT_MODE_RESUME:
102 printk(KERN_WARNING "timer[%d]: unimplemented mode: %d\n",
103 dev->irq, mode);
104 break;
105 };
106 }
107
108 /*
109 * timer_device_event()
110 * Call the device's event handler.
111 *
112 * The pointer is initialized by the generic Linux code
113 * to the function to be called.
114 */
115 static irqreturn_t timer_device_event(int irq, void *dev_id)
116 {
117 struct clock_event_device *dev = (struct clock_event_device *)dev_id;
118
119 if (dev->mode == CLOCK_EVT_MODE_PERIODIC) {
120 /*
121 * The periodic request is 1 per jiffies
122 */
123 timer_reset(dev->irq, frequency / CONFIG_HZ);
124 } else {
125 /*
126 * The timer will go off again at the rollover
127 * point. We must disable the IRQ to prevent
128 * getting a spurious interrupt.
129 */
130 ldsr_disable_vector(dev->irq);
131 }
132
133 if (!dev->event_handler) {
134 printk(KERN_CRIT "no registered event handler\n");
135 return IRQ_HANDLED;
136 }
137
138 dev->event_handler(dev);
139 return IRQ_HANDLED;
140 }
141
142 /*
143 * timer_device_clockbase_read()
144 * Provide a primary clocksource around the sysval timer.
145 */
146 static cycle_t timer_device_clockbase_read(void)
147 {
148 return (cycle_t)UBICOM32_IO_TIMER->sysval;
149 }
150
151 /*
152 * Primary Clock Source Description
153 *
154 * We use 24 for the shift factor because we want
155 * to ensure there are less than 2^24 clocks
156 * in a jiffie of 10 ms.
157 */
158 static struct clocksource timer_device_clockbase = {
159 .name = "sysval",
160 .rating = 400,
161 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
162 .mask = CLOCKSOURCE_MASK(32),
163 .shift = 24,
164 .mult = 0,
165 .read = timer_device_clockbase_read,
166 };
167
168 /*
169 * timer_device_alloc_event()
170 * Allocate a timer device event.
171 */
172 static int timer_device_alloc_event(const char *name, int cpuid, const cpumask_t *mask)
173 {
174 struct clock_event_device *dev;
175 struct irqaction *action;
176
177 /*
178 * Are we out of configured timers?
179 */
180 spin_lock(&timer_device_lock);
181 if (timer_device_next_timer >= MAX_TIMERS) {
182 spin_unlock(&timer_device_lock);
183 printk(KERN_WARNING "out of timer event entries\n");
184 return -1;
185 }
186 dev = &timer_device_devs[timer_device_next_timer];
187 action = &timer_device_irqs[timer_device_next_timer];
188 timer_device_next_timer++;
189 spin_unlock(&timer_device_lock);
190
191 /*
192 * Now allocate a timer to ourselves.
193 */
194 dev->irq = timer_alloc();
195 if (dev->irq == -1) {
196 spin_lock(&timer_device_lock);
197 timer_device_next_timer--;
198 spin_unlock(&timer_device_lock);
199 printk(KERN_WARNING "out of hardware timers\n");
200 return -1;
201 }
202
203 /*
204 * Init the IRQ action structure. Make sure
205 * this in place before you register the clock
206 * event device.
207 */
208 action->name = name;
209 action->flags = IRQF_DISABLED | IRQF_TIMER;
210 action->handler = timer_device_event;
211 cpumask_copy(&action->mask, mask);
212 action->dev_id = dev;
213 setup_irq(dev->irq, action);
214 irq_set_affinity(dev->irq, mask);
215 ldsr_disable_vector(dev->irq);
216
217 /*
218 * init clock dev structure.
219 *
220 * The min_delta_ns is chosen to ensure that setting next
221 * event will never be requested with too small of value.
222 */
223 dev->name = name;
224 dev->rating = timer_device_clockbase.rating;
225 dev->shift = timer_device_clockbase.shift;
226 dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
227 dev->set_mode = timer_device_set_mode;
228 dev->set_next_event = timer_device_set_next_event;
229 dev->mult = div_sc(frequency, NSEC_PER_SEC, dev->shift);
230 dev->max_delta_ns = clockevent_delta2ns(0xffffffff, dev);
231 dev->min_delta_ns = clockevent_delta2ns(100, dev);
232 dev->cpumask = mask;
233 printk(KERN_NOTICE "timer[%d]: %s - created\n", dev->irq, dev->name);
234
235 /*
236 * Now register the device.
237 */
238 clockevents_register_device(dev);
239 return dev->irq;
240 }
241
242 #if defined(CONFIG_LOCAL_TIMERS)
243 /*
244 * local_timer_setup()
245 * Allocation function for creating a per cpu local timer.
246 */
247 int __cpuinit local_timer_setup(unsigned int cpu)
248 {
249 return timer_device_alloc_event("timer-cpu", cpu, cpumask_of(cpu));
250 }
251 #endif
252
253 /*
254 * timer_device_init()
255 * Create and init a generic clock driver for Ubicom32.
256 */
257 void timer_device_init(void)
258 {
259 int i;
260
261 /*
262 * Get the frequency from the processor device tree node or use
263 * the default if not available. We will store this as the frequency
264 * of the timer to avoid future calculations.
265 */
266 frequency = processor_frequency();
267 if (frequency == 0) {
268 frequency = CLOCK_TICK_RATE;
269 }
270
271 /*
272 * Setup the primary clock source around sysval. Linux does not
273 * supply a Mhz multiplier so convert down to khz.
274 */
275 timer_device_clockbase.mult =
276 clocksource_khz2mult(frequency / 1000,
277 timer_device_clockbase.shift);
278 if (clocksource_register(&timer_device_clockbase)) {
279 printk(KERN_ERR "timer: clocksource failed to register\n");
280 return;
281 }
282
283 /*
284 * Always allocate a primary timer.
285 */
286 timer_device_alloc_event("timer-primary", -1, CPU_MASK_ALL_PTR);
287
288 #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
289 /*
290 * If BROADCAST is selected we need to add a broadcast timer.
291 */
292 timer_device_alloc_event("timer-broadcast", -1, CPU_MASK_ALL_PTR);
293 #endif
294
295 /*
296 * Allocate extra timers that are requested.
297 */
298 for (i = 0; i < CONFIG_TIMER_EXTRA_ALLOC; i++) {
299 timer_device_alloc_event("timer-extra", -1, CPU_MASK_ALL_PTR);
300 }
301 }