Statistics
| Branch: | Revision:

root / hw / arm_timer.c @ 1de7afc9

History | View | Annotate | Download (10.6 kB)

1 5fafdf24 ths
/*
2 cdbdb648 pbrook
 * ARM PrimeCell Timer modules.
3 cdbdb648 pbrook
 *
4 cdbdb648 pbrook
 * Copyright (c) 2005-2006 CodeSourcery.
5 cdbdb648 pbrook
 * Written by Paul Brook
6 cdbdb648 pbrook
 *
7 8e31bf38 Matthew Fernandez
 * This code is licensed under the GPL.
8 cdbdb648 pbrook
 */
9 cdbdb648 pbrook
10 6a824ec3 Paul Brook
#include "sysbus.h"
11 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
12 104a26a2 Mark Langsdorf
#include "qemu-common.h"
13 104a26a2 Mark Langsdorf
#include "qdev.h"
14 49d4d9b6 Paolo Bonzini
#include "ptimer.h"
15 cdbdb648 pbrook
16 cdbdb648 pbrook
/* Common timer implementation.  */
17 cdbdb648 pbrook
18 cdbdb648 pbrook
#define TIMER_CTRL_ONESHOT      (1 << 0)
19 cdbdb648 pbrook
#define TIMER_CTRL_32BIT        (1 << 1)
20 cdbdb648 pbrook
#define TIMER_CTRL_DIV1         (0 << 2)
21 cdbdb648 pbrook
#define TIMER_CTRL_DIV16        (1 << 2)
22 cdbdb648 pbrook
#define TIMER_CTRL_DIV256       (2 << 2)
23 cdbdb648 pbrook
#define TIMER_CTRL_IE           (1 << 5)
24 cdbdb648 pbrook
#define TIMER_CTRL_PERIODIC     (1 << 6)
25 cdbdb648 pbrook
#define TIMER_CTRL_ENABLE       (1 << 7)
26 cdbdb648 pbrook
27 cdbdb648 pbrook
typedef struct {
28 423f0742 pbrook
    ptimer_state *timer;
29 cdbdb648 pbrook
    uint32_t control;
30 cdbdb648 pbrook
    uint32_t limit;
31 cdbdb648 pbrook
    int freq;
32 cdbdb648 pbrook
    int int_level;
33 d537cf6c pbrook
    qemu_irq irq;
34 cdbdb648 pbrook
} arm_timer_state;
35 cdbdb648 pbrook
36 cdbdb648 pbrook
/* Check all active timers, and schedule the next timer interrupt.  */
37 cdbdb648 pbrook
38 423f0742 pbrook
static void arm_timer_update(arm_timer_state *s)
39 cdbdb648 pbrook
{
40 cdbdb648 pbrook
    /* Update interrupts.  */
41 cdbdb648 pbrook
    if (s->int_level && (s->control & TIMER_CTRL_IE)) {
42 d537cf6c pbrook
        qemu_irq_raise(s->irq);
43 cdbdb648 pbrook
    } else {
44 d537cf6c pbrook
        qemu_irq_lower(s->irq);
45 cdbdb648 pbrook
    }
46 cdbdb648 pbrook
}
47 cdbdb648 pbrook
48 a8170e5e Avi Kivity
static uint32_t arm_timer_read(void *opaque, hwaddr offset)
49 cdbdb648 pbrook
{
50 cdbdb648 pbrook
    arm_timer_state *s = (arm_timer_state *)opaque;
51 cdbdb648 pbrook
52 cdbdb648 pbrook
    switch (offset >> 2) {
53 cdbdb648 pbrook
    case 0: /* TimerLoad */
54 cdbdb648 pbrook
    case 6: /* TimerBGLoad */
55 cdbdb648 pbrook
        return s->limit;
56 cdbdb648 pbrook
    case 1: /* TimerValue */
57 423f0742 pbrook
        return ptimer_get_count(s->timer);
58 cdbdb648 pbrook
    case 2: /* TimerControl */
59 cdbdb648 pbrook
        return s->control;
60 cdbdb648 pbrook
    case 4: /* TimerRIS */
61 cdbdb648 pbrook
        return s->int_level;
62 cdbdb648 pbrook
    case 5: /* TimerMIS */
63 cdbdb648 pbrook
        if ((s->control & TIMER_CTRL_IE) == 0)
64 cdbdb648 pbrook
            return 0;
65 cdbdb648 pbrook
        return s->int_level;
66 cdbdb648 pbrook
    default:
67 edb94a41 Peter Maydell
        qemu_log_mask(LOG_GUEST_ERROR,
68 edb94a41 Peter Maydell
                      "%s: Bad offset %x\n", __func__, (int)offset);
69 cdbdb648 pbrook
        return 0;
70 cdbdb648 pbrook
    }
71 cdbdb648 pbrook
}
72 cdbdb648 pbrook
73 423f0742 pbrook
/* Reset the timer limit after settings have changed.  */
74 423f0742 pbrook
static void arm_timer_recalibrate(arm_timer_state *s, int reload)
75 423f0742 pbrook
{
76 423f0742 pbrook
    uint32_t limit;
77 423f0742 pbrook
78 a9cf98d9 Rabin Vincent
    if ((s->control & (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) {
79 423f0742 pbrook
        /* Free running.  */
80 423f0742 pbrook
        if (s->control & TIMER_CTRL_32BIT)
81 423f0742 pbrook
            limit = 0xffffffff;
82 423f0742 pbrook
        else
83 423f0742 pbrook
            limit = 0xffff;
84 423f0742 pbrook
    } else {
85 423f0742 pbrook
          /* Periodic.  */
86 423f0742 pbrook
          limit = s->limit;
87 423f0742 pbrook
    }
88 423f0742 pbrook
    ptimer_set_limit(s->timer, limit, reload);
89 423f0742 pbrook
}
90 423f0742 pbrook
91 a8170e5e Avi Kivity
static void arm_timer_write(void *opaque, hwaddr offset,
92 cdbdb648 pbrook
                            uint32_t value)
93 cdbdb648 pbrook
{
94 cdbdb648 pbrook
    arm_timer_state *s = (arm_timer_state *)opaque;
95 423f0742 pbrook
    int freq;
96 cdbdb648 pbrook
97 cdbdb648 pbrook
    switch (offset >> 2) {
98 cdbdb648 pbrook
    case 0: /* TimerLoad */
99 cdbdb648 pbrook
        s->limit = value;
100 423f0742 pbrook
        arm_timer_recalibrate(s, 1);
101 cdbdb648 pbrook
        break;
102 cdbdb648 pbrook
    case 1: /* TimerValue */
103 cdbdb648 pbrook
        /* ??? Linux seems to want to write to this readonly register.
104 cdbdb648 pbrook
           Ignore it.  */
105 cdbdb648 pbrook
        break;
106 cdbdb648 pbrook
    case 2: /* TimerControl */
107 cdbdb648 pbrook
        if (s->control & TIMER_CTRL_ENABLE) {
108 cdbdb648 pbrook
            /* Pause the timer if it is running.  This may cause some
109 cdbdb648 pbrook
               inaccuracy dure to rounding, but avoids a whole lot of other
110 cdbdb648 pbrook
               messyness.  */
111 423f0742 pbrook
            ptimer_stop(s->timer);
112 cdbdb648 pbrook
        }
113 cdbdb648 pbrook
        s->control = value;
114 423f0742 pbrook
        freq = s->freq;
115 cdbdb648 pbrook
        /* ??? Need to recalculate expiry time after changing divisor.  */
116 cdbdb648 pbrook
        switch ((value >> 2) & 3) {
117 423f0742 pbrook
        case 1: freq >>= 4; break;
118 423f0742 pbrook
        case 2: freq >>= 8; break;
119 cdbdb648 pbrook
        }
120 d6759902 Rabin Vincent
        arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE);
121 423f0742 pbrook
        ptimer_set_freq(s->timer, freq);
122 cdbdb648 pbrook
        if (s->control & TIMER_CTRL_ENABLE) {
123 cdbdb648 pbrook
            /* Restart the timer if still enabled.  */
124 423f0742 pbrook
            ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
125 cdbdb648 pbrook
        }
126 cdbdb648 pbrook
        break;
127 cdbdb648 pbrook
    case 3: /* TimerIntClr */
128 cdbdb648 pbrook
        s->int_level = 0;
129 cdbdb648 pbrook
        break;
130 cdbdb648 pbrook
    case 6: /* TimerBGLoad */
131 cdbdb648 pbrook
        s->limit = value;
132 423f0742 pbrook
        arm_timer_recalibrate(s, 0);
133 cdbdb648 pbrook
        break;
134 cdbdb648 pbrook
    default:
135 edb94a41 Peter Maydell
        qemu_log_mask(LOG_GUEST_ERROR,
136 edb94a41 Peter Maydell
                      "%s: Bad offset %x\n", __func__, (int)offset);
137 cdbdb648 pbrook
    }
138 423f0742 pbrook
    arm_timer_update(s);
139 cdbdb648 pbrook
}
140 cdbdb648 pbrook
141 cdbdb648 pbrook
static void arm_timer_tick(void *opaque)
142 cdbdb648 pbrook
{
143 423f0742 pbrook
    arm_timer_state *s = (arm_timer_state *)opaque;
144 423f0742 pbrook
    s->int_level = 1;
145 423f0742 pbrook
    arm_timer_update(s);
146 cdbdb648 pbrook
}
147 cdbdb648 pbrook
148 eecd33a5 Juan Quintela
static const VMStateDescription vmstate_arm_timer = {
149 eecd33a5 Juan Quintela
    .name = "arm_timer",
150 eecd33a5 Juan Quintela
    .version_id = 1,
151 eecd33a5 Juan Quintela
    .minimum_version_id = 1,
152 eecd33a5 Juan Quintela
    .minimum_version_id_old = 1,
153 eecd33a5 Juan Quintela
    .fields      = (VMStateField[]) {
154 eecd33a5 Juan Quintela
        VMSTATE_UINT32(control, arm_timer_state),
155 eecd33a5 Juan Quintela
        VMSTATE_UINT32(limit, arm_timer_state),
156 eecd33a5 Juan Quintela
        VMSTATE_INT32(int_level, arm_timer_state),
157 eecd33a5 Juan Quintela
        VMSTATE_PTIMER(timer, arm_timer_state),
158 eecd33a5 Juan Quintela
        VMSTATE_END_OF_LIST()
159 eecd33a5 Juan Quintela
    }
160 eecd33a5 Juan Quintela
};
161 23e39294 pbrook
162 6a824ec3 Paul Brook
static arm_timer_state *arm_timer_init(uint32_t freq)
163 cdbdb648 pbrook
{
164 cdbdb648 pbrook
    arm_timer_state *s;
165 423f0742 pbrook
    QEMUBH *bh;
166 cdbdb648 pbrook
167 7267c094 Anthony Liguori
    s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
168 423f0742 pbrook
    s->freq = freq;
169 cdbdb648 pbrook
    s->control = TIMER_CTRL_IE;
170 cdbdb648 pbrook
171 423f0742 pbrook
    bh = qemu_bh_new(arm_timer_tick, s);
172 423f0742 pbrook
    s->timer = ptimer_init(bh);
173 eecd33a5 Juan Quintela
    vmstate_register(NULL, -1, &vmstate_arm_timer, s);
174 cdbdb648 pbrook
    return s;
175 cdbdb648 pbrook
}
176 cdbdb648 pbrook
177 cdbdb648 pbrook
/* ARM PrimeCell SP804 dual timer module.
178 7b4252e8 Peter Chubb
 * Docs at
179 7b4252e8 Peter Chubb
 * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0271d/index.html
180 7b4252e8 Peter Chubb
*/
181 cdbdb648 pbrook
182 cdbdb648 pbrook
typedef struct {
183 6a824ec3 Paul Brook
    SysBusDevice busdev;
184 e219dea2 Avi Kivity
    MemoryRegion iomem;
185 6a824ec3 Paul Brook
    arm_timer_state *timer[2];
186 104a26a2 Mark Langsdorf
    uint32_t freq0, freq1;
187 cdbdb648 pbrook
    int level[2];
188 d537cf6c pbrook
    qemu_irq irq;
189 cdbdb648 pbrook
} sp804_state;
190 cdbdb648 pbrook
191 7b4252e8 Peter Chubb
static const uint8_t sp804_ids[] = {
192 7b4252e8 Peter Chubb
    /* Timer ID */
193 7b4252e8 Peter Chubb
    0x04, 0x18, 0x14, 0,
194 7b4252e8 Peter Chubb
    /* PrimeCell ID */
195 7b4252e8 Peter Chubb
    0xd, 0xf0, 0x05, 0xb1
196 7b4252e8 Peter Chubb
};
197 7b4252e8 Peter Chubb
198 d537cf6c pbrook
/* Merge the IRQs from the two component devices.  */
199 cdbdb648 pbrook
static void sp804_set_irq(void *opaque, int irq, int level)
200 cdbdb648 pbrook
{
201 cdbdb648 pbrook
    sp804_state *s = (sp804_state *)opaque;
202 cdbdb648 pbrook
203 cdbdb648 pbrook
    s->level[irq] = level;
204 d537cf6c pbrook
    qemu_set_irq(s->irq, s->level[0] || s->level[1]);
205 cdbdb648 pbrook
}
206 cdbdb648 pbrook
207 a8170e5e Avi Kivity
static uint64_t sp804_read(void *opaque, hwaddr offset,
208 e219dea2 Avi Kivity
                           unsigned size)
209 cdbdb648 pbrook
{
210 cdbdb648 pbrook
    sp804_state *s = (sp804_state *)opaque;
211 cdbdb648 pbrook
212 cdbdb648 pbrook
    if (offset < 0x20) {
213 cdbdb648 pbrook
        return arm_timer_read(s->timer[0], offset);
214 7b4252e8 Peter Chubb
    }
215 7b4252e8 Peter Chubb
    if (offset < 0x40) {
216 cdbdb648 pbrook
        return arm_timer_read(s->timer[1], offset - 0x20);
217 cdbdb648 pbrook
    }
218 7b4252e8 Peter Chubb
219 7b4252e8 Peter Chubb
    /* TimerPeriphID */
220 7b4252e8 Peter Chubb
    if (offset >= 0xfe0 && offset <= 0xffc) {
221 7b4252e8 Peter Chubb
        return sp804_ids[(offset - 0xfe0) >> 2];
222 7b4252e8 Peter Chubb
    }
223 7b4252e8 Peter Chubb
224 7b4252e8 Peter Chubb
    switch (offset) {
225 7b4252e8 Peter Chubb
    /* Integration Test control registers, which we won't support */
226 7b4252e8 Peter Chubb
    case 0xf00: /* TimerITCR */
227 7b4252e8 Peter Chubb
    case 0xf04: /* TimerITOP (strictly write only but..) */
228 edb94a41 Peter Maydell
        qemu_log_mask(LOG_UNIMP,
229 edb94a41 Peter Maydell
                      "%s: integration test registers unimplemented\n",
230 edb94a41 Peter Maydell
                      __func__);
231 7b4252e8 Peter Chubb
        return 0;
232 7b4252e8 Peter Chubb
    }
233 7b4252e8 Peter Chubb
234 edb94a41 Peter Maydell
    qemu_log_mask(LOG_GUEST_ERROR,
235 edb94a41 Peter Maydell
                  "%s: Bad offset %x\n", __func__, (int)offset);
236 7b4252e8 Peter Chubb
    return 0;
237 cdbdb648 pbrook
}
238 cdbdb648 pbrook
239 a8170e5e Avi Kivity
static void sp804_write(void *opaque, hwaddr offset,
240 e219dea2 Avi Kivity
                        uint64_t value, unsigned size)
241 cdbdb648 pbrook
{
242 cdbdb648 pbrook
    sp804_state *s = (sp804_state *)opaque;
243 cdbdb648 pbrook
244 cdbdb648 pbrook
    if (offset < 0x20) {
245 cdbdb648 pbrook
        arm_timer_write(s->timer[0], offset, value);
246 7b4252e8 Peter Chubb
        return;
247 7b4252e8 Peter Chubb
    }
248 7b4252e8 Peter Chubb
249 7b4252e8 Peter Chubb
    if (offset < 0x40) {
250 cdbdb648 pbrook
        arm_timer_write(s->timer[1], offset - 0x20, value);
251 7b4252e8 Peter Chubb
        return;
252 cdbdb648 pbrook
    }
253 7b4252e8 Peter Chubb
254 7b4252e8 Peter Chubb
    /* Technically we could be writing to the Test Registers, but not likely */
255 edb94a41 Peter Maydell
    qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n",
256 edb94a41 Peter Maydell
                  __func__, (int)offset);
257 cdbdb648 pbrook
}
258 cdbdb648 pbrook
259 e219dea2 Avi Kivity
static const MemoryRegionOps sp804_ops = {
260 e219dea2 Avi Kivity
    .read = sp804_read,
261 e219dea2 Avi Kivity
    .write = sp804_write,
262 e219dea2 Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
263 cdbdb648 pbrook
};
264 cdbdb648 pbrook
265 81986ac4 Juan Quintela
static const VMStateDescription vmstate_sp804 = {
266 81986ac4 Juan Quintela
    .name = "sp804",
267 81986ac4 Juan Quintela
    .version_id = 1,
268 81986ac4 Juan Quintela
    .minimum_version_id = 1,
269 81986ac4 Juan Quintela
    .minimum_version_id_old = 1,
270 81986ac4 Juan Quintela
    .fields      = (VMStateField[]) {
271 81986ac4 Juan Quintela
        VMSTATE_INT32_ARRAY(level, sp804_state, 2),
272 81986ac4 Juan Quintela
        VMSTATE_END_OF_LIST()
273 81986ac4 Juan Quintela
    }
274 81986ac4 Juan Quintela
};
275 23e39294 pbrook
276 81a322d4 Gerd Hoffmann
static int sp804_init(SysBusDevice *dev)
277 cdbdb648 pbrook
{
278 6a824ec3 Paul Brook
    sp804_state *s = FROM_SYSBUS(sp804_state, dev);
279 d537cf6c pbrook
    qemu_irq *qi;
280 cdbdb648 pbrook
281 d537cf6c pbrook
    qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
282 6a824ec3 Paul Brook
    sysbus_init_irq(dev, &s->irq);
283 104a26a2 Mark Langsdorf
    s->timer[0] = arm_timer_init(s->freq0);
284 104a26a2 Mark Langsdorf
    s->timer[1] = arm_timer_init(s->freq1);
285 6a824ec3 Paul Brook
    s->timer[0]->irq = qi[0];
286 6a824ec3 Paul Brook
    s->timer[1]->irq = qi[1];
287 e219dea2 Avi Kivity
    memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
288 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->iomem);
289 81986ac4 Juan Quintela
    vmstate_register(&dev->qdev, -1, &vmstate_sp804, s);
290 81a322d4 Gerd Hoffmann
    return 0;
291 cdbdb648 pbrook
}
292 cdbdb648 pbrook
293 cdbdb648 pbrook
/* Integrator/CP timer module.  */
294 cdbdb648 pbrook
295 cdbdb648 pbrook
typedef struct {
296 6a824ec3 Paul Brook
    SysBusDevice busdev;
297 e219dea2 Avi Kivity
    MemoryRegion iomem;
298 6a824ec3 Paul Brook
    arm_timer_state *timer[3];
299 cdbdb648 pbrook
} icp_pit_state;
300 cdbdb648 pbrook
301 a8170e5e Avi Kivity
static uint64_t icp_pit_read(void *opaque, hwaddr offset,
302 e219dea2 Avi Kivity
                             unsigned size)
303 cdbdb648 pbrook
{
304 cdbdb648 pbrook
    icp_pit_state *s = (icp_pit_state *)opaque;
305 cdbdb648 pbrook
    int n;
306 cdbdb648 pbrook
307 cdbdb648 pbrook
    /* ??? Don't know the PrimeCell ID for this device.  */
308 cdbdb648 pbrook
    n = offset >> 8;
309 ee71c984 Peter Maydell
    if (n > 2) {
310 edb94a41 Peter Maydell
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
311 2ac71179 Paul Brook
    }
312 cdbdb648 pbrook
313 cdbdb648 pbrook
    return arm_timer_read(s->timer[n], offset & 0xff);
314 cdbdb648 pbrook
}
315 cdbdb648 pbrook
316 a8170e5e Avi Kivity
static void icp_pit_write(void *opaque, hwaddr offset,
317 e219dea2 Avi Kivity
                          uint64_t value, unsigned size)
318 cdbdb648 pbrook
{
319 cdbdb648 pbrook
    icp_pit_state *s = (icp_pit_state *)opaque;
320 cdbdb648 pbrook
    int n;
321 cdbdb648 pbrook
322 cdbdb648 pbrook
    n = offset >> 8;
323 ee71c984 Peter Maydell
    if (n > 2) {
324 edb94a41 Peter Maydell
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
325 2ac71179 Paul Brook
    }
326 cdbdb648 pbrook
327 cdbdb648 pbrook
    arm_timer_write(s->timer[n], offset & 0xff, value);
328 cdbdb648 pbrook
}
329 cdbdb648 pbrook
330 e219dea2 Avi Kivity
static const MemoryRegionOps icp_pit_ops = {
331 e219dea2 Avi Kivity
    .read = icp_pit_read,
332 e219dea2 Avi Kivity
    .write = icp_pit_write,
333 e219dea2 Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
334 cdbdb648 pbrook
};
335 cdbdb648 pbrook
336 81a322d4 Gerd Hoffmann
static int icp_pit_init(SysBusDevice *dev)
337 cdbdb648 pbrook
{
338 6a824ec3 Paul Brook
    icp_pit_state *s = FROM_SYSBUS(icp_pit_state, dev);
339 cdbdb648 pbrook
340 cdbdb648 pbrook
    /* Timer 0 runs at the system clock speed (40MHz).  */
341 6a824ec3 Paul Brook
    s->timer[0] = arm_timer_init(40000000);
342 cdbdb648 pbrook
    /* The other two timers run at 1MHz.  */
343 6a824ec3 Paul Brook
    s->timer[1] = arm_timer_init(1000000);
344 6a824ec3 Paul Brook
    s->timer[2] = arm_timer_init(1000000);
345 6a824ec3 Paul Brook
346 6a824ec3 Paul Brook
    sysbus_init_irq(dev, &s->timer[0]->irq);
347 6a824ec3 Paul Brook
    sysbus_init_irq(dev, &s->timer[1]->irq);
348 6a824ec3 Paul Brook
    sysbus_init_irq(dev, &s->timer[2]->irq);
349 cdbdb648 pbrook
350 e219dea2 Avi Kivity
    memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000);
351 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->iomem);
352 23e39294 pbrook
    /* This device has no state to save/restore.  The component timers will
353 23e39294 pbrook
       save themselves.  */
354 81a322d4 Gerd Hoffmann
    return 0;
355 cdbdb648 pbrook
}
356 6a824ec3 Paul Brook
357 999e12bb Anthony Liguori
static void icp_pit_class_init(ObjectClass *klass, void *data)
358 999e12bb Anthony Liguori
{
359 999e12bb Anthony Liguori
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
360 999e12bb Anthony Liguori
361 999e12bb Anthony Liguori
    sdc->init = icp_pit_init;
362 999e12bb Anthony Liguori
}
363 999e12bb Anthony Liguori
364 39bffca2 Anthony Liguori
static TypeInfo icp_pit_info = {
365 39bffca2 Anthony Liguori
    .name          = "integrator_pit",
366 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
367 39bffca2 Anthony Liguori
    .instance_size = sizeof(icp_pit_state),
368 39bffca2 Anthony Liguori
    .class_init    = icp_pit_class_init,
369 39bffca2 Anthony Liguori
};
370 39bffca2 Anthony Liguori
371 39bffca2 Anthony Liguori
static Property sp804_properties[] = {
372 39bffca2 Anthony Liguori
    DEFINE_PROP_UINT32("freq0", sp804_state, freq0, 1000000),
373 39bffca2 Anthony Liguori
    DEFINE_PROP_UINT32("freq1", sp804_state, freq1, 1000000),
374 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
375 999e12bb Anthony Liguori
};
376 999e12bb Anthony Liguori
377 999e12bb Anthony Liguori
static void sp804_class_init(ObjectClass *klass, void *data)
378 999e12bb Anthony Liguori
{
379 999e12bb Anthony Liguori
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
380 39bffca2 Anthony Liguori
    DeviceClass *k = DEVICE_CLASS(klass);
381 999e12bb Anthony Liguori
382 999e12bb Anthony Liguori
    sdc->init = sp804_init;
383 39bffca2 Anthony Liguori
    k->props = sp804_properties;
384 999e12bb Anthony Liguori
}
385 999e12bb Anthony Liguori
386 39bffca2 Anthony Liguori
static TypeInfo sp804_info = {
387 39bffca2 Anthony Liguori
    .name          = "sp804",
388 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
389 39bffca2 Anthony Liguori
    .instance_size = sizeof(sp804_state),
390 39bffca2 Anthony Liguori
    .class_init    = sp804_class_init,
391 999e12bb Anthony Liguori
};
392 999e12bb Anthony Liguori
393 83f7d43a Andreas Färber
static void arm_timer_register_types(void)
394 6a824ec3 Paul Brook
{
395 39bffca2 Anthony Liguori
    type_register_static(&icp_pit_info);
396 39bffca2 Anthony Liguori
    type_register_static(&sp804_info);
397 6a824ec3 Paul Brook
}
398 6a824ec3 Paul Brook
399 83f7d43a Andreas Färber
type_init(arm_timer_register_types)