Root/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
49static unsigned int frequency;
50static struct clock_event_device timer_device_devs[MAX_TIMERS];
51static struct irqaction timer_device_irqs[MAX_TIMERS];
52static int timer_device_next_timer = 0;
53
54DEFINE_SPINLOCK(timer_device_lock);
55
56/*
57 * timer_device_set_next_event()
58 * Cause the timer to go off "cycles" from now.
59 */
60static 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 */
70static 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 */
115static 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 */
146static 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 */
158static 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 */
172static 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 */
247int __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 */
257void 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}
302

Archive Download this file



interactive