branch Attitude Adjustment
[12.09/openwrt.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 struct cpumask *cpumask)
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, cpumask);
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);
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_all_mask);
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_all_mask);
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_all_mask);
300         }
301 }