Statistics
| Branch: | Revision:

root / hw / arm_timer.c @ 1d6198c3

History | View | Annotate | Download (8.9 kB)

1
/*
2
 * ARM PrimeCell Timer modules.
3
 *
4
 * Copyright (c) 2005-2006 CodeSourcery.
5
 * Written by Paul Brook
6
 *
7
 * This code is licenced under the GPL.
8
 */
9

    
10
#include "hw.h"
11
#include "qemu-timer.h"
12
#include "primecell.h"
13

    
14
/* Common timer implementation.  */
15

    
16
#define TIMER_CTRL_ONESHOT      (1 << 0)
17
#define TIMER_CTRL_32BIT        (1 << 1)
18
#define TIMER_CTRL_DIV1         (0 << 2)
19
#define TIMER_CTRL_DIV16        (1 << 2)
20
#define TIMER_CTRL_DIV256       (2 << 2)
21
#define TIMER_CTRL_IE           (1 << 5)
22
#define TIMER_CTRL_PERIODIC     (1 << 6)
23
#define TIMER_CTRL_ENABLE       (1 << 7)
24

    
25
typedef struct {
26
    ptimer_state *timer;
27
    uint32_t control;
28
    uint32_t limit;
29
    int freq;
30
    int int_level;
31
    qemu_irq irq;
32
} arm_timer_state;
33

    
34
/* Check all active timers, and schedule the next timer interrupt.  */
35

    
36
static void arm_timer_update(arm_timer_state *s)
37
{
38
    /* Update interrupts.  */
39
    if (s->int_level && (s->control & TIMER_CTRL_IE)) {
40
        qemu_irq_raise(s->irq);
41
    } else {
42
        qemu_irq_lower(s->irq);
43
    }
44
}
45

    
46
static uint32_t arm_timer_read(void *opaque, target_phys_addr_t offset)
47
{
48
    arm_timer_state *s = (arm_timer_state *)opaque;
49

    
50
    switch (offset >> 2) {
51
    case 0: /* TimerLoad */
52
    case 6: /* TimerBGLoad */
53
        return s->limit;
54
    case 1: /* TimerValue */
55
        return ptimer_get_count(s->timer);
56
    case 2: /* TimerControl */
57
        return s->control;
58
    case 4: /* TimerRIS */
59
        return s->int_level;
60
    case 5: /* TimerMIS */
61
        if ((s->control & TIMER_CTRL_IE) == 0)
62
            return 0;
63
        return s->int_level;
64
    default:
65
        cpu_abort (cpu_single_env, "arm_timer_read: Bad offset %x\n",
66
                   (int)offset);
67
        return 0;
68
    }
69
}
70

    
71
/* Reset the timer limit after settings have changed.  */
72
static void arm_timer_recalibrate(arm_timer_state *s, int reload)
73
{
74
    uint32_t limit;
75

    
76
    if ((s->control & TIMER_CTRL_PERIODIC) == 0) {
77
        /* Free running.  */
78
        if (s->control & TIMER_CTRL_32BIT)
79
            limit = 0xffffffff;
80
        else
81
            limit = 0xffff;
82
    } else {
83
          /* Periodic.  */
84
          limit = s->limit;
85
    }
86
    ptimer_set_limit(s->timer, limit, reload);
87
}
88

    
89
static void arm_timer_write(void *opaque, target_phys_addr_t offset,
90
                            uint32_t value)
91
{
92
    arm_timer_state *s = (arm_timer_state *)opaque;
93
    int freq;
94

    
95
    switch (offset >> 2) {
96
    case 0: /* TimerLoad */
97
        s->limit = value;
98
        arm_timer_recalibrate(s, 1);
99
        break;
100
    case 1: /* TimerValue */
101
        /* ??? Linux seems to want to write to this readonly register.
102
           Ignore it.  */
103
        break;
104
    case 2: /* TimerControl */
105
        if (s->control & TIMER_CTRL_ENABLE) {
106
            /* Pause the timer if it is running.  This may cause some
107
               inaccuracy dure to rounding, but avoids a whole lot of other
108
               messyness.  */
109
            ptimer_stop(s->timer);
110
        }
111
        s->control = value;
112
        freq = s->freq;
113
        /* ??? Need to recalculate expiry time after changing divisor.  */
114
        switch ((value >> 2) & 3) {
115
        case 1: freq >>= 4; break;
116
        case 2: freq >>= 8; break;
117
        }
118
        arm_timer_recalibrate(s, 0);
119
        ptimer_set_freq(s->timer, freq);
120
        if (s->control & TIMER_CTRL_ENABLE) {
121
            /* Restart the timer if still enabled.  */
122
            ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
123
        }
124
        break;
125
    case 3: /* TimerIntClr */
126
        s->int_level = 0;
127
        break;
128
    case 6: /* TimerBGLoad */
129
        s->limit = value;
130
        arm_timer_recalibrate(s, 0);
131
        break;
132
    default:
133
        cpu_abort (cpu_single_env, "arm_timer_write: Bad offset %x\n",
134
                   (int)offset);
135
    }
136
    arm_timer_update(s);
137
}
138

    
139
static void arm_timer_tick(void *opaque)
140
{
141
    arm_timer_state *s = (arm_timer_state *)opaque;
142
    s->int_level = 1;
143
    arm_timer_update(s);
144
}
145

    
146
static void arm_timer_save(QEMUFile *f, void *opaque)
147
{
148
    arm_timer_state *s = (arm_timer_state *)opaque;
149
    qemu_put_be32(f, s->control);
150
    qemu_put_be32(f, s->limit);
151
    qemu_put_be32(f, s->int_level);
152
    qemu_put_ptimer(f, s->timer);
153
}
154

    
155
static int arm_timer_load(QEMUFile *f, void *opaque, int version_id)
156
{
157
    arm_timer_state *s = (arm_timer_state *)opaque;
158

    
159
    if (version_id != 1)
160
        return -EINVAL;
161

    
162
    s->control = qemu_get_be32(f);
163
    s->limit = qemu_get_be32(f);
164
    s->int_level = qemu_get_be32(f);
165
    qemu_get_ptimer(f, s->timer);
166
    return 0;
167
}
168

    
169
static void *arm_timer_init(uint32_t freq, qemu_irq irq)
170
{
171
    arm_timer_state *s;
172
    QEMUBH *bh;
173

    
174
    s = (arm_timer_state *)qemu_mallocz(sizeof(arm_timer_state));
175
    s->irq = irq;
176
    s->freq = freq;
177
    s->control = TIMER_CTRL_IE;
178

    
179
    bh = qemu_bh_new(arm_timer_tick, s);
180
    s->timer = ptimer_init(bh);
181
    register_savevm("arm_timer", -1, 1, arm_timer_save, arm_timer_load, s);
182
    return s;
183
}
184

    
185
/* ARM PrimeCell SP804 dual timer module.
186
   Docs for this device don't seem to be publicly available.  This
187
   implementation is based on guesswork, the linux kernel sources and the
188
   Integrator/CP timer modules.  */
189

    
190
typedef struct {
191
    void *timer[2];
192
    int level[2];
193
    qemu_irq irq;
194
} sp804_state;
195

    
196
/* Merge the IRQs from the two component devices.  */
197
static void sp804_set_irq(void *opaque, int irq, int level)
198
{
199
    sp804_state *s = (sp804_state *)opaque;
200

    
201
    s->level[irq] = level;
202
    qemu_set_irq(s->irq, s->level[0] || s->level[1]);
203
}
204

    
205
static uint32_t sp804_read(void *opaque, target_phys_addr_t offset)
206
{
207
    sp804_state *s = (sp804_state *)opaque;
208

    
209
    /* ??? Don't know the PrimeCell ID for this device.  */
210
    if (offset < 0x20) {
211
        return arm_timer_read(s->timer[0], offset);
212
    } else {
213
        return arm_timer_read(s->timer[1], offset - 0x20);
214
    }
215
}
216

    
217
static void sp804_write(void *opaque, target_phys_addr_t offset,
218
                        uint32_t value)
219
{
220
    sp804_state *s = (sp804_state *)opaque;
221

    
222
    if (offset < 0x20) {
223
        arm_timer_write(s->timer[0], offset, value);
224
    } else {
225
        arm_timer_write(s->timer[1], offset - 0x20, value);
226
    }
227
}
228

    
229
static CPUReadMemoryFunc *sp804_readfn[] = {
230
   sp804_read,
231
   sp804_read,
232
   sp804_read
233
};
234

    
235
static CPUWriteMemoryFunc *sp804_writefn[] = {
236
   sp804_write,
237
   sp804_write,
238
   sp804_write
239
};
240

    
241
static void sp804_save(QEMUFile *f, void *opaque)
242
{
243
    sp804_state *s = (sp804_state *)opaque;
244
    qemu_put_be32(f, s->level[0]);
245
    qemu_put_be32(f, s->level[1]);
246
}
247

    
248
static int sp804_load(QEMUFile *f, void *opaque, int version_id)
249
{
250
    sp804_state *s = (sp804_state *)opaque;
251

    
252
    if (version_id != 1)
253
        return -EINVAL;
254

    
255
    s->level[0] = qemu_get_be32(f);
256
    s->level[1] = qemu_get_be32(f);
257
    return 0;
258
}
259

    
260
void sp804_init(uint32_t base, qemu_irq irq)
261
{
262
    int iomemtype;
263
    sp804_state *s;
264
    qemu_irq *qi;
265

    
266
    s = (sp804_state *)qemu_mallocz(sizeof(sp804_state));
267
    qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
268
    s->irq = irq;
269
    /* ??? The timers are actually configurable between 32kHz and 1MHz, but
270
       we don't implement that.  */
271
    s->timer[0] = arm_timer_init(1000000, qi[0]);
272
    s->timer[1] = arm_timer_init(1000000, qi[1]);
273
    iomemtype = cpu_register_io_memory(0, sp804_readfn,
274
                                       sp804_writefn, s);
275
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
276
    register_savevm("sp804", -1, 1, sp804_save, sp804_load, s);
277
}
278

    
279

    
280
/* Integrator/CP timer module.  */
281

    
282
typedef struct {
283
    void *timer[3];
284
} icp_pit_state;
285

    
286
static uint32_t icp_pit_read(void *opaque, target_phys_addr_t offset)
287
{
288
    icp_pit_state *s = (icp_pit_state *)opaque;
289
    int n;
290

    
291
    /* ??? Don't know the PrimeCell ID for this device.  */
292
    n = offset >> 8;
293
    if (n > 3)
294
        cpu_abort(cpu_single_env, "sp804_read: Bad timer %d\n", n);
295

    
296
    return arm_timer_read(s->timer[n], offset & 0xff);
297
}
298

    
299
static void icp_pit_write(void *opaque, target_phys_addr_t offset,
300
                          uint32_t value)
301
{
302
    icp_pit_state *s = (icp_pit_state *)opaque;
303
    int n;
304

    
305
    n = offset >> 8;
306
    if (n > 3)
307
        cpu_abort(cpu_single_env, "sp804_write: Bad timer %d\n", n);
308

    
309
    arm_timer_write(s->timer[n], offset & 0xff, value);
310
}
311

    
312

    
313
static CPUReadMemoryFunc *icp_pit_readfn[] = {
314
   icp_pit_read,
315
   icp_pit_read,
316
   icp_pit_read
317
};
318

    
319
static CPUWriteMemoryFunc *icp_pit_writefn[] = {
320
   icp_pit_write,
321
   icp_pit_write,
322
   icp_pit_write
323
};
324

    
325
void icp_pit_init(uint32_t base, qemu_irq *pic, int irq)
326
{
327
    int iomemtype;
328
    icp_pit_state *s;
329

    
330
    s = (icp_pit_state *)qemu_mallocz(sizeof(icp_pit_state));
331
    /* Timer 0 runs at the system clock speed (40MHz).  */
332
    s->timer[0] = arm_timer_init(40000000, pic[irq]);
333
    /* The other two timers run at 1MHz.  */
334
    s->timer[1] = arm_timer_init(1000000, pic[irq + 1]);
335
    s->timer[2] = arm_timer_init(1000000, pic[irq + 2]);
336

    
337
    iomemtype = cpu_register_io_memory(0, icp_pit_readfn,
338
                                       icp_pit_writefn, s);
339
    cpu_register_physical_memory(base, 0x00001000, iomemtype);
340
    /* This device has no state to save/restore.  The component timers will
341
       save themselves.  */
342
}