Statistics
| Branch: | Revision:

root / hw / arm_timer.c @ be62a2eb

History | View | Annotate | Download (9.8 kB)

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

    
10
#include "sysbus.h"
11
#include "qemu-timer.h"
12
#include "qemu-common.h"
13
#include "qdev.h"
14

    
15
/* Common timer implementation.  */
16

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

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

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

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

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

    
51
    switch (offset >> 2) {
52
    case 0: /* TimerLoad */
53
    case 6: /* TimerBGLoad */
54
        return s->limit;
55
    case 1: /* TimerValue */
56
        return ptimer_get_count(s->timer);
57
    case 2: /* TimerControl */
58
        return s->control;
59
    case 4: /* TimerRIS */
60
        return s->int_level;
61
    case 5: /* TimerMIS */
62
        if ((s->control & TIMER_CTRL_IE) == 0)
63
            return 0;
64
        return s->int_level;
65
    default:
66
        hw_error("%s: Bad offset %x\n", __func__, (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 | TIMER_CTRL_ONESHOT)) == 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, s->control & TIMER_CTRL_ENABLE);
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
        hw_error("%s: Bad offset %x\n", __func__, (int)offset);
134
    }
135
    arm_timer_update(s);
136
}
137

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

    
145
static const VMStateDescription vmstate_arm_timer = {
146
    .name = "arm_timer",
147
    .version_id = 1,
148
    .minimum_version_id = 1,
149
    .minimum_version_id_old = 1,
150
    .fields      = (VMStateField[]) {
151
        VMSTATE_UINT32(control, arm_timer_state),
152
        VMSTATE_UINT32(limit, arm_timer_state),
153
        VMSTATE_INT32(int_level, arm_timer_state),
154
        VMSTATE_PTIMER(timer, arm_timer_state),
155
        VMSTATE_END_OF_LIST()
156
    }
157
};
158

    
159
static arm_timer_state *arm_timer_init(uint32_t freq)
160
{
161
    arm_timer_state *s;
162
    QEMUBH *bh;
163

    
164
    s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
165
    s->freq = freq;
166
    s->control = TIMER_CTRL_IE;
167

    
168
    bh = qemu_bh_new(arm_timer_tick, s);
169
    s->timer = ptimer_init(bh);
170
    vmstate_register(NULL, -1, &vmstate_arm_timer, s);
171
    return s;
172
}
173

    
174
/* ARM PrimeCell SP804 dual timer module.
175
 * Docs at
176
 * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
177
*/
178

    
179
typedef struct {
180
    SysBusDevice busdev;
181
    MemoryRegion iomem;
182
    arm_timer_state *timer[2];
183
    uint32_t freq0, freq1;
184
    int level[2];
185
    qemu_irq irq;
186
} sp804_state;
187

    
188
static const uint8_t sp804_ids[] = {
189
    /* Timer ID */
190
    0x04, 0x18, 0x14, 0,
191
    /* PrimeCell ID */
192
    0xd, 0xf0, 0x05, 0xb1
193
};
194

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

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

    
204
static uint64_t sp804_read(void *opaque, target_phys_addr_t offset,
205
                           unsigned size)
206
{
207
    sp804_state *s = (sp804_state *)opaque;
208

    
209
    if (offset < 0x20) {
210
        return arm_timer_read(s->timer[0], offset);
211
    }
212
    if (offset < 0x40) {
213
        return arm_timer_read(s->timer[1], offset - 0x20);
214
    }
215

    
216
    /* TimerPeriphID */
217
    if (offset >= 0xfe0 && offset <= 0xffc) {
218
        return sp804_ids[(offset - 0xfe0) >> 2];
219
    }
220

    
221
    switch (offset) {
222
    /* Integration Test control registers, which we won't support */
223
    case 0xf00: /* TimerITCR */
224
    case 0xf04: /* TimerITOP (strictly write only but..) */
225
        return 0;
226
    }
227

    
228
    hw_error("%s: Bad offset %x\n", __func__, (int)offset);
229
    return 0;
230
}
231

    
232
static void sp804_write(void *opaque, target_phys_addr_t offset,
233
                        uint64_t value, unsigned size)
234
{
235
    sp804_state *s = (sp804_state *)opaque;
236

    
237
    if (offset < 0x20) {
238
        arm_timer_write(s->timer[0], offset, value);
239
        return;
240
    }
241

    
242
    if (offset < 0x40) {
243
        arm_timer_write(s->timer[1], offset - 0x20, value);
244
        return;
245
    }
246

    
247
    /* Technically we could be writing to the Test Registers, but not likely */
248
    hw_error("%s: Bad offset %x\n", __func__, (int)offset);
249
}
250

    
251
static const MemoryRegionOps sp804_ops = {
252
    .read = sp804_read,
253
    .write = sp804_write,
254
    .endianness = DEVICE_NATIVE_ENDIAN,
255
};
256

    
257
static const VMStateDescription vmstate_sp804 = {
258
    .name = "sp804",
259
    .version_id = 1,
260
    .minimum_version_id = 1,
261
    .minimum_version_id_old = 1,
262
    .fields      = (VMStateField[]) {
263
        VMSTATE_INT32_ARRAY(level, sp804_state, 2),
264
        VMSTATE_END_OF_LIST()
265
    }
266
};
267

    
268
static int sp804_init(SysBusDevice *dev)
269
{
270
    sp804_state *s = FROM_SYSBUS(sp804_state, dev);
271
    qemu_irq *qi;
272

    
273
    qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
274
    sysbus_init_irq(dev, &s->irq);
275
    /* The timers are configurable between 32kHz and 1MHz
276
     * defaulting to 1MHz but overrideable as individual properties */
277
    s->timer[0] = arm_timer_init(s->freq0);
278
    s->timer[1] = arm_timer_init(s->freq1);
279

    
280
    s->timer[0]->irq = qi[0];
281
    s->timer[1]->irq = qi[1];
282
    memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
283
    sysbus_init_mmio(dev, &s->iomem);
284
    vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
285
    return 0;
286
}
287

    
288
static SysBusDeviceInfo sp804_info = {
289
    .init = sp804_init,
290
    .qdev.name = "sp804",
291
    .qdev.size = sizeof(sp804_state),
292
    .qdev.props = (Property[]) {
293
        DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
294
        DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
295
        DEFINE_PROP_END_OF_LIST(),
296
    }
297
};
298

    
299
/* Integrator/CP timer module.  */
300

    
301
typedef struct {
302
    SysBusDevice busdev;
303
    MemoryRegion iomem;
304
    arm_timer_state *timer[3];
305
} icp_pit_state;
306

    
307
static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset,
308
                             unsigned size)
309
{
310
    icp_pit_state *s = (icp_pit_state *)opaque;
311
    int n;
312

    
313
    /* ??? Don't know the PrimeCell ID for this device.  */
314
    n = offset >> 8;
315
    if (n > 2) {
316
        hw_error("%s: Bad timer %d\n", __func__, n);
317
    }
318

    
319
    return arm_timer_read(s->timer[n], offset & 0xff);
320
}
321

    
322
static void icp_pit_write(void *opaque, target_phys_addr_t offset,
323
                          uint64_t value, unsigned size)
324
{
325
    icp_pit_state *s = (icp_pit_state *)opaque;
326
    int n;
327

    
328
    n = offset >> 8;
329
    if (n > 2) {
330
        hw_error("%s: Bad timer %d\n", __func__, n);
331
    }
332

    
333
    arm_timer_write(s->timer[n], offset & 0xff, value);
334
}
335

    
336
static const MemoryRegionOps icp_pit_ops = {
337
    .read = icp_pit_read,
338
    .write = icp_pit_write,
339
    .endianness = DEVICE_NATIVE_ENDIAN,
340
};
341

    
342
static int icp_pit_init(SysBusDevice *dev)
343
{
344
    icp_pit_state *s = FROM_SYSBUS(icp_pit_state, dev);
345

    
346
    /* Timer 0 runs at the system clock speed (40MHz).  */
347
    s->timer[0] = arm_timer_init(40000000);
348
    /* The other two timers run at 1MHz.  */
349
    s->timer[1] = arm_timer_init(1000000);
350
    s->timer[2] = arm_timer_init(1000000);
351

    
352
    sysbus_init_irq(dev, &s->timer[0]->irq);
353
    sysbus_init_irq(dev, &s->timer[1]->irq);
354
    sysbus_init_irq(dev, &s->timer[2]->irq);
355

    
356
    memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
357
    sysbus_init_mmio(dev, &s->iomem);
358
    /* This device has no state to save/restore.  The component timers will
359
       save themselves.  */
360
    return 0;
361
}
362

    
363
static void arm_timer_register_devices(void)
364
{
365
    sysbus_register_dev("integrator_pit", sizeof(icp_pit_state), icp_pit_init);
366
    sysbus_register_withprop(&sp804_info);
367
}
368

    
369
device_init(arm_timer_register_devices)