OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [arm/] [mach-davinci/] [time.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * DaVinci timer subsystem
3
 *
4
 * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
5
 *
6
 * 2007 (c) MontaVista Software, Inc. This file is licensed under
7
 * the terms of the GNU General Public License version 2. This program
8
 * is licensed "as is" without any warranty of any kind, whether express
9
 * or implied.
10
 */
11
#include <linux/kernel.h>
12
#include <linux/init.h>
13
#include <linux/types.h>
14
#include <linux/interrupt.h>
15
#include <linux/clocksource.h>
16
#include <linux/clockchips.h>
17
#include <linux/spinlock.h>
18
 
19
#include <asm/io.h>
20
#include <asm/hardware.h>
21
#include <asm/system.h>
22
#include <asm/irq.h>
23
#include <asm/mach/irq.h>
24
#include <asm/mach/time.h>
25
#include <asm/errno.h>
26
#include <asm/arch/io.h>
27
 
28
static struct clock_event_device clockevent_davinci;
29
 
30
#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
31
#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
32
#define DAVINCI_WDOG_BASE   (IO_PHYS + 0x21C00)
33
 
34
enum {
35
        T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS,
36
};
37
 
38
#define IS_TIMER1(id)    (id & 0x2)
39
#define IS_TIMER0(id)    (!IS_TIMER1(id))
40
#define IS_TIMER_TOP(id) ((id & 0x1))
41
#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id))
42
 
43
static int timer_irqs[NUM_TIMERS] = {
44
        IRQ_TINT0_TINT12,
45
        IRQ_TINT0_TINT34,
46
        IRQ_TINT1_TINT12,
47
        IRQ_TINT1_TINT34,
48
};
49
 
50
/*
51
 * This driver configures the 2 64-bit count-up timers as 4 independent
52
 * 32-bit count-up timers used as follows:
53
 *
54
 * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
55
 * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
56
 * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
57
 * T1_TOP: Timer 1, top   :  <unused>
58
 */
59
#define TID_CLOCKEVENT  T0_BOT
60
#define TID_CLOCKSOURCE T0_TOP
61
 
62
/* Timer register offsets */
63
#define PID12                        0x0
64
#define TIM12                        0x10
65
#define TIM34                        0x14
66
#define PRD12                        0x18
67
#define PRD34                        0x1c
68
#define TCR                          0x20
69
#define TGCR                         0x24
70
#define WDTCR                        0x28
71
 
72
/* Timer register bitfields */
73
#define TCR_ENAMODE_DISABLE          0x0
74
#define TCR_ENAMODE_ONESHOT          0x1
75
#define TCR_ENAMODE_PERIODIC         0x2
76
#define TCR_ENAMODE_MASK             0x3
77
 
78
#define TGCR_TIMMODE_SHIFT           2
79
#define TGCR_TIMMODE_64BIT_GP        0x0
80
#define TGCR_TIMMODE_32BIT_UNCHAINED 0x1
81
#define TGCR_TIMMODE_64BIT_WDOG      0x2
82
#define TGCR_TIMMODE_32BIT_CHAINED   0x3
83
 
84
#define TGCR_TIM12RS_SHIFT           0
85
#define TGCR_TIM34RS_SHIFT           1
86
#define TGCR_RESET                   0x0
87
#define TGCR_UNRESET                 0x1
88
#define TGCR_RESET_MASK              0x3
89
 
90
#define WDTCR_WDEN_SHIFT             14
91
#define WDTCR_WDEN_DISABLE           0x0
92
#define WDTCR_WDEN_ENABLE            0x1
93
#define WDTCR_WDKEY_SHIFT            16
94
#define WDTCR_WDKEY_SEQ0             0xa5c6
95
#define WDTCR_WDKEY_SEQ1             0xda7e
96
 
97
struct timer_s {
98
        char *name;
99
        unsigned int id;
100
        unsigned long period;
101
        unsigned long opts;
102
        unsigned long reg_base;
103
        unsigned long tim_reg;
104
        unsigned long prd_reg;
105
        unsigned long enamode_shift;
106
        struct irqaction irqaction;
107
};
108
static struct timer_s timers[];
109
 
110
/* values for 'opts' field of struct timer_s */
111
#define TIMER_OPTS_DISABLED   0x00
112
#define TIMER_OPTS_ONESHOT    0x01
113
#define TIMER_OPTS_PERIODIC   0x02
114
 
115
static int timer32_config(struct timer_s *t)
116
{
117
        u32 tcr = davinci_readl(t->reg_base + TCR);
118
 
119
        /* disable timer */
120
        tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
121
        davinci_writel(tcr, t->reg_base + TCR);
122
 
123
        /* reset counter to zero, set new period */
124
        davinci_writel(0, t->tim_reg);
125
        davinci_writel(t->period, t->prd_reg);
126
 
127
        /* Set enable mode */
128
        if (t->opts & TIMER_OPTS_ONESHOT) {
129
                tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift;
130
        } else if (t->opts & TIMER_OPTS_PERIODIC) {
131
                tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
132
        }
133
 
134
        davinci_writel(tcr, t->reg_base + TCR);
135
        return 0;
136
}
137
 
138
static inline u32 timer32_read(struct timer_s *t)
139
{
140
        return davinci_readl(t->tim_reg);
141
}
142
 
143
static irqreturn_t timer_interrupt(int irq, void *dev_id)
144
{
145
        struct clock_event_device *evt = &clockevent_davinci;
146
 
147
        evt->event_handler(evt);
148
        return IRQ_HANDLED;
149
}
150
 
151
/* called when 32-bit counter wraps */
152
static irqreturn_t freerun_interrupt(int irq, void *dev_id)
153
{
154
        return IRQ_HANDLED;
155
}
156
 
157
static struct timer_s timers[] = {
158
        [TID_CLOCKEVENT] = {
159
                .name      = "clockevent",
160
                .opts      = TIMER_OPTS_DISABLED,
161
                .irqaction = {
162
                        .flags   = IRQF_DISABLED | IRQF_TIMER,
163
                        .handler = timer_interrupt,
164
                }
165
        },
166
        [TID_CLOCKSOURCE] = {
167
                .name       = "free-run counter",
168
                .period     = ~0,
169
                .opts       = TIMER_OPTS_PERIODIC,
170
                .irqaction = {
171
                        .flags   = IRQF_DISABLED | IRQF_TIMER,
172
                        .handler = freerun_interrupt,
173
                }
174
        },
175
};
176
 
177
static void __init timer_init(void)
178
{
179
        u32 bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
180
        int i;
181
 
182
        /* Global init of each 64-bit timer as a whole */
183
        for(i=0; i<2; i++) {
184
                u32 tgcr, base = bases[i];
185
 
186
                /* Disabled, Internal clock source */
187
                davinci_writel(0, base + TCR);
188
 
189
                /* reset both timers, no pre-scaler for timer34 */
190
                tgcr = 0;
191
                davinci_writel(tgcr, base + TGCR);
192
 
193
                /* Set both timers to unchained 32-bit */
194
                tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT;
195
                davinci_writel(tgcr, base + TGCR);
196
 
197
                /* Unreset timers */
198
                tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
199
                        (TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
200
                davinci_writel(tgcr, base + TGCR);
201
 
202
                /* Init both counters to zero */
203
                davinci_writel(0, base + TIM12);
204
                davinci_writel(0, base + TIM34);
205
        }
206
 
207
        /* Init of each timer as a 32-bit timer */
208
        for (i=0; i< ARRAY_SIZE(timers); i++) {
209
                struct timer_s *t = &timers[i];
210
 
211
                if (t->name) {
212
                        t->id = i;
213
                        t->reg_base = (IS_TIMER1(t->id) ?
214
                               DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE);
215
 
216
                        if (IS_TIMER_BOT(t->id)) {
217
                                t->enamode_shift = 6;
218
                                t->tim_reg = t->reg_base + TIM12;
219
                                t->prd_reg = t->reg_base + PRD12;
220
                        } else {
221
                                t->enamode_shift = 22;
222
                                t->tim_reg = t->reg_base + TIM34;
223
                                t->prd_reg = t->reg_base + PRD34;
224
                        }
225
 
226
                        /* Register interrupt */
227
                        t->irqaction.name = t->name;
228
                        t->irqaction.dev_id = (void *)t;
229
                        if (t->irqaction.handler != NULL) {
230
                                setup_irq(timer_irqs[t->id], &t->irqaction);
231
                        }
232
 
233
                        timer32_config(&timers[i]);
234
                }
235
        }
236
}
237
 
238
/*
239
 * clocksource
240
 */
241
static cycle_t read_cycles(void)
242
{
243
        struct timer_s *t = &timers[TID_CLOCKSOURCE];
244
 
245
        return (cycles_t)timer32_read(t);
246
}
247
 
248
static struct clocksource clocksource_davinci = {
249
        .name           = "timer0_1",
250
        .rating         = 300,
251
        .read           = read_cycles,
252
        .mask           = CLOCKSOURCE_MASK(32),
253
        .shift          = 24,
254
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
255
};
256
 
257
/*
258
 * clockevent
259
 */
260
static int davinci_set_next_event(unsigned long cycles,
261
                                  struct clock_event_device *evt)
262
{
263
        struct timer_s *t = &timers[TID_CLOCKEVENT];
264
 
265
        t->period = cycles;
266
        timer32_config(t);
267
        return 0;
268
}
269
 
270
static void davinci_set_mode(enum clock_event_mode mode,
271
                             struct clock_event_device *evt)
272
{
273
        struct timer_s *t = &timers[TID_CLOCKEVENT];
274
 
275
        switch (mode) {
276
        case CLOCK_EVT_MODE_PERIODIC:
277
                t->period = CLOCK_TICK_RATE / (HZ);
278
                t->opts = TIMER_OPTS_PERIODIC;
279
                timer32_config(t);
280
                break;
281
        case CLOCK_EVT_MODE_ONESHOT:
282
                t->opts = TIMER_OPTS_ONESHOT;
283
                break;
284
        case CLOCK_EVT_MODE_UNUSED:
285
        case CLOCK_EVT_MODE_SHUTDOWN:
286
                t->opts = TIMER_OPTS_DISABLED;
287
                break;
288
        case CLOCK_EVT_MODE_RESUME:
289
                break;
290
        }
291
}
292
 
293
static struct clock_event_device clockevent_davinci = {
294
        .name           = "timer0_0",
295
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
296
        .shift          = 32,
297
        .set_next_event = davinci_set_next_event,
298
        .set_mode       = davinci_set_mode,
299
};
300
 
301
 
302
static void __init davinci_timer_init(void)
303
{
304
        static char err[] __initdata = KERN_ERR
305
                "%s: can't register clocksource!\n";
306
 
307
        /* init timer hw */
308
        timer_init();
309
 
310
        /* setup clocksource */
311
        clocksource_davinci.mult =
312
                clocksource_khz2mult(CLOCK_TICK_RATE/1000,
313
                                     clocksource_davinci.shift);
314
        if (clocksource_register(&clocksource_davinci))
315
                printk(err, clocksource_davinci.name);
316
 
317
        /* setup clockevent */
318
        clockevent_davinci.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
319
                                         clockevent_davinci.shift);
320
        clockevent_davinci.max_delta_ns =
321
                clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
322
        clockevent_davinci.min_delta_ns =
323
                clockevent_delta2ns(1, &clockevent_davinci);
324
 
325
        clockevent_davinci.cpumask = cpumask_of_cpu(0);
326
        clockevents_register_device(&clockevent_davinci);
327
}
328
 
329
struct sys_timer davinci_timer = {
330
        .init   = davinci_timer_init,
331
};
332
 
333
 
334
/* reset board using watchdog timer */
335
void davinci_watchdog_reset(void) {
336
        u32 tgcr, wdtcr, base = DAVINCI_WDOG_BASE;
337
 
338
        /* disable, internal clock source */
339
        davinci_writel(0, base + TCR);
340
 
341
        /* reset timer, set mode to 64-bit watchdog, and unreset */
342
        tgcr = 0;
343
        davinci_writel(tgcr, base + TCR);
344
        tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
345
        tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
346
                (TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
347
        davinci_writel(tgcr, base + TCR);
348
 
349
        /* clear counter and period regs */
350
        davinci_writel(0, base + TIM12);
351
        davinci_writel(0, base + TIM34);
352
        davinci_writel(0, base + PRD12);
353
        davinci_writel(0, base + PRD34);
354
 
355
        /* enable */
356
        wdtcr = davinci_readl(base + WDTCR);
357
        wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT;
358
        davinci_writel(wdtcr, base + WDTCR);
359
 
360
        /* put watchdog in pre-active state */
361
        wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
362
                (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
363
        davinci_writel(wdtcr, base + WDTCR);
364
 
365
        /* put watchdog in active state */
366
        wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
367
                (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
368
        davinci_writel(wdtcr, base + WDTCR);
369
 
370
        /* write an invalid value to the WDKEY field to trigger
371
         * a watchdog reset */
372
        wdtcr = 0x00004000;
373
        davinci_writel(wdtcr, base + WDTCR);
374
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.