Statistics
| Branch: | Revision:

root / hw / timer / arm_timer.c @ 25fce9ad

History | View | Annotate | Download (10.9 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 83c9f4ca Paolo Bonzini
#include "hw/sysbus.h"
11 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
12 104a26a2 Mark Langsdorf
#include "qemu-common.h"
13 83c9f4ca Paolo Bonzini
#include "hw/qdev.h"
14 83c9f4ca Paolo Bonzini
#include "hw/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 0c88dea5 Andreas Färber
#define TYPE_SP804 "sp804"
183 0c88dea5 Andreas Färber
#define SP804(obj) OBJECT_CHECK(SP804State, (obj), TYPE_SP804)
184 0c88dea5 Andreas Färber
185 1024d7f0 Andreas Färber
typedef struct SP804State {
186 0c88dea5 Andreas Färber
    SysBusDevice parent_obj;
187 0c88dea5 Andreas Färber
188 e219dea2 Avi Kivity
    MemoryRegion iomem;
189 6a824ec3 Paul Brook
    arm_timer_state *timer[2];
190 104a26a2 Mark Langsdorf
    uint32_t freq0, freq1;
191 cdbdb648 pbrook
    int level[2];
192 d537cf6c pbrook
    qemu_irq irq;
193 1024d7f0 Andreas Färber
} SP804State;
194 cdbdb648 pbrook
195 7b4252e8 Peter Chubb
static const uint8_t sp804_ids[] = {
196 7b4252e8 Peter Chubb
    /* Timer ID */
197 7b4252e8 Peter Chubb
    0x04, 0x18, 0x14, 0,
198 7b4252e8 Peter Chubb
    /* PrimeCell ID */
199 7b4252e8 Peter Chubb
    0xd, 0xf0, 0x05, 0xb1
200 7b4252e8 Peter Chubb
};
201 7b4252e8 Peter Chubb
202 d537cf6c pbrook
/* Merge the IRQs from the two component devices.  */
203 cdbdb648 pbrook
static void sp804_set_irq(void *opaque, int irq, int level)
204 cdbdb648 pbrook
{
205 1024d7f0 Andreas Färber
    SP804State *s = (SP804State *)opaque;
206 cdbdb648 pbrook
207 cdbdb648 pbrook
    s->level[irq] = level;
208 d537cf6c pbrook
    qemu_set_irq(s->irq, s->level[0] || s->level[1]);
209 cdbdb648 pbrook
}
210 cdbdb648 pbrook
211 a8170e5e Avi Kivity
static uint64_t sp804_read(void *opaque, hwaddr offset,
212 e219dea2 Avi Kivity
                           unsigned size)
213 cdbdb648 pbrook
{
214 1024d7f0 Andreas Färber
    SP804State *s = (SP804State *)opaque;
215 cdbdb648 pbrook
216 cdbdb648 pbrook
    if (offset < 0x20) {
217 cdbdb648 pbrook
        return arm_timer_read(s->timer[0], offset);
218 7b4252e8 Peter Chubb
    }
219 7b4252e8 Peter Chubb
    if (offset < 0x40) {
220 cdbdb648 pbrook
        return arm_timer_read(s->timer[1], offset - 0x20);
221 cdbdb648 pbrook
    }
222 7b4252e8 Peter Chubb
223 7b4252e8 Peter Chubb
    /* TimerPeriphID */
224 7b4252e8 Peter Chubb
    if (offset >= 0xfe0 && offset <= 0xffc) {
225 7b4252e8 Peter Chubb
        return sp804_ids[(offset - 0xfe0) >> 2];
226 7b4252e8 Peter Chubb
    }
227 7b4252e8 Peter Chubb
228 7b4252e8 Peter Chubb
    switch (offset) {
229 7b4252e8 Peter Chubb
    /* Integration Test control registers, which we won't support */
230 7b4252e8 Peter Chubb
    case 0xf00: /* TimerITCR */
231 7b4252e8 Peter Chubb
    case 0xf04: /* TimerITOP (strictly write only but..) */
232 edb94a41 Peter Maydell
        qemu_log_mask(LOG_UNIMP,
233 edb94a41 Peter Maydell
                      "%s: integration test registers unimplemented\n",
234 edb94a41 Peter Maydell
                      __func__);
235 7b4252e8 Peter Chubb
        return 0;
236 7b4252e8 Peter Chubb
    }
237 7b4252e8 Peter Chubb
238 edb94a41 Peter Maydell
    qemu_log_mask(LOG_GUEST_ERROR,
239 edb94a41 Peter Maydell
                  "%s: Bad offset %x\n", __func__, (int)offset);
240 7b4252e8 Peter Chubb
    return 0;
241 cdbdb648 pbrook
}
242 cdbdb648 pbrook
243 a8170e5e Avi Kivity
static void sp804_write(void *opaque, hwaddr offset,
244 e219dea2 Avi Kivity
                        uint64_t value, unsigned size)
245 cdbdb648 pbrook
{
246 1024d7f0 Andreas Färber
    SP804State *s = (SP804State *)opaque;
247 cdbdb648 pbrook
248 cdbdb648 pbrook
    if (offset < 0x20) {
249 cdbdb648 pbrook
        arm_timer_write(s->timer[0], offset, value);
250 7b4252e8 Peter Chubb
        return;
251 7b4252e8 Peter Chubb
    }
252 7b4252e8 Peter Chubb
253 7b4252e8 Peter Chubb
    if (offset < 0x40) {
254 cdbdb648 pbrook
        arm_timer_write(s->timer[1], offset - 0x20, value);
255 7b4252e8 Peter Chubb
        return;
256 cdbdb648 pbrook
    }
257 7b4252e8 Peter Chubb
258 7b4252e8 Peter Chubb
    /* Technically we could be writing to the Test Registers, but not likely */
259 edb94a41 Peter Maydell
    qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %x\n",
260 edb94a41 Peter Maydell
                  __func__, (int)offset);
261 cdbdb648 pbrook
}
262 cdbdb648 pbrook
263 e219dea2 Avi Kivity
static const MemoryRegionOps sp804_ops = {
264 e219dea2 Avi Kivity
    .read = sp804_read,
265 e219dea2 Avi Kivity
    .write = sp804_write,
266 e219dea2 Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
267 cdbdb648 pbrook
};
268 cdbdb648 pbrook
269 81986ac4 Juan Quintela
static const VMStateDescription vmstate_sp804 = {
270 81986ac4 Juan Quintela
    .name = "sp804",
271 81986ac4 Juan Quintela
    .version_id = 1,
272 81986ac4 Juan Quintela
    .minimum_version_id = 1,
273 81986ac4 Juan Quintela
    .minimum_version_id_old = 1,
274 81986ac4 Juan Quintela
    .fields      = (VMStateField[]) {
275 1024d7f0 Andreas Färber
        VMSTATE_INT32_ARRAY(level, SP804State, 2),
276 81986ac4 Juan Quintela
        VMSTATE_END_OF_LIST()
277 81986ac4 Juan Quintela
    }
278 81986ac4 Juan Quintela
};
279 23e39294 pbrook
280 0c88dea5 Andreas Färber
static int sp804_init(SysBusDevice *sbd)
281 cdbdb648 pbrook
{
282 0c88dea5 Andreas Färber
    DeviceState *dev = DEVICE(sbd);
283 0c88dea5 Andreas Färber
    SP804State *s = SP804(dev);
284 d537cf6c pbrook
    qemu_irq *qi;
285 cdbdb648 pbrook
286 d537cf6c pbrook
    qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
287 0c88dea5 Andreas Färber
    sysbus_init_irq(sbd, &s->irq);
288 104a26a2 Mark Langsdorf
    s->timer[0] = arm_timer_init(s->freq0);
289 104a26a2 Mark Langsdorf
    s->timer[1] = arm_timer_init(s->freq1);
290 6a824ec3 Paul Brook
    s->timer[0]->irq = qi[0];
291 6a824ec3 Paul Brook
    s->timer[1]->irq = qi[1];
292 853dca12 Paolo Bonzini
    memory_region_init_io(&s->iomem, OBJECT(s), &sp804_ops, s,
293 853dca12 Paolo Bonzini
                          "sp804", 0x1000);
294 0c88dea5 Andreas Färber
    sysbus_init_mmio(sbd, &s->iomem);
295 0c88dea5 Andreas Färber
    vmstate_register(dev, -1, &vmstate_sp804, s);
296 81a322d4 Gerd Hoffmann
    return 0;
297 cdbdb648 pbrook
}
298 cdbdb648 pbrook
299 cdbdb648 pbrook
/* Integrator/CP timer module.  */
300 cdbdb648 pbrook
301 e2051b42 Andreas Färber
#define TYPE_INTEGRATOR_PIT "integrator_pit"
302 e2051b42 Andreas Färber
#define INTEGRATOR_PIT(obj) \
303 e2051b42 Andreas Färber
    OBJECT_CHECK(icp_pit_state, (obj), TYPE_INTEGRATOR_PIT)
304 e2051b42 Andreas Färber
305 cdbdb648 pbrook
typedef struct {
306 e2051b42 Andreas Färber
    SysBusDevice parent_obj;
307 e2051b42 Andreas Färber
308 e219dea2 Avi Kivity
    MemoryRegion iomem;
309 6a824ec3 Paul Brook
    arm_timer_state *timer[3];
310 cdbdb648 pbrook
} icp_pit_state;
311 cdbdb648 pbrook
312 a8170e5e Avi Kivity
static uint64_t icp_pit_read(void *opaque, hwaddr offset,
313 e219dea2 Avi Kivity
                             unsigned size)
314 cdbdb648 pbrook
{
315 cdbdb648 pbrook
    icp_pit_state *s = (icp_pit_state *)opaque;
316 cdbdb648 pbrook
    int n;
317 cdbdb648 pbrook
318 cdbdb648 pbrook
    /* ??? Don't know the PrimeCell ID for this device.  */
319 cdbdb648 pbrook
    n = offset >> 8;
320 ee71c984 Peter Maydell
    if (n > 2) {
321 edb94a41 Peter Maydell
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
322 2ac71179 Paul Brook
    }
323 cdbdb648 pbrook
324 cdbdb648 pbrook
    return arm_timer_read(s->timer[n], offset & 0xff);
325 cdbdb648 pbrook
}
326 cdbdb648 pbrook
327 a8170e5e Avi Kivity
static void icp_pit_write(void *opaque, hwaddr offset,
328 e219dea2 Avi Kivity
                          uint64_t value, unsigned size)
329 cdbdb648 pbrook
{
330 cdbdb648 pbrook
    icp_pit_state *s = (icp_pit_state *)opaque;
331 cdbdb648 pbrook
    int n;
332 cdbdb648 pbrook
333 cdbdb648 pbrook
    n = offset >> 8;
334 ee71c984 Peter Maydell
    if (n > 2) {
335 edb94a41 Peter Maydell
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad timer %d\n", __func__, n);
336 2ac71179 Paul Brook
    }
337 cdbdb648 pbrook
338 cdbdb648 pbrook
    arm_timer_write(s->timer[n], offset & 0xff, value);
339 cdbdb648 pbrook
}
340 cdbdb648 pbrook
341 e219dea2 Avi Kivity
static const MemoryRegionOps icp_pit_ops = {
342 e219dea2 Avi Kivity
    .read = icp_pit_read,
343 e219dea2 Avi Kivity
    .write = icp_pit_write,
344 e219dea2 Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
345 cdbdb648 pbrook
};
346 cdbdb648 pbrook
347 81a322d4 Gerd Hoffmann
static int icp_pit_init(SysBusDevice *dev)
348 cdbdb648 pbrook
{
349 e2051b42 Andreas Färber
    icp_pit_state *s = INTEGRATOR_PIT(dev);
350 cdbdb648 pbrook
351 cdbdb648 pbrook
    /* Timer 0 runs at the system clock speed (40MHz).  */
352 6a824ec3 Paul Brook
    s->timer[0] = arm_timer_init(40000000);
353 cdbdb648 pbrook
    /* The other two timers run at 1MHz.  */
354 6a824ec3 Paul Brook
    s->timer[1] = arm_timer_init(1000000);
355 6a824ec3 Paul Brook
    s->timer[2] = arm_timer_init(1000000);
356 6a824ec3 Paul Brook
357 6a824ec3 Paul Brook
    sysbus_init_irq(dev, &s->timer[0]->irq);
358 6a824ec3 Paul Brook
    sysbus_init_irq(dev, &s->timer[1]->irq);
359 6a824ec3 Paul Brook
    sysbus_init_irq(dev, &s->timer[2]->irq);
360 cdbdb648 pbrook
361 853dca12 Paolo Bonzini
    memory_region_init_io(&s->iomem, OBJECT(s), &icp_pit_ops, s,
362 853dca12 Paolo Bonzini
                          "icp_pit", 0x1000);
363 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->iomem);
364 23e39294 pbrook
    /* This device has no state to save/restore.  The component timers will
365 23e39294 pbrook
       save themselves.  */
366 81a322d4 Gerd Hoffmann
    return 0;
367 cdbdb648 pbrook
}
368 6a824ec3 Paul Brook
369 999e12bb Anthony Liguori
static void icp_pit_class_init(ObjectClass *klass, void *data)
370 999e12bb Anthony Liguori
{
371 999e12bb Anthony Liguori
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
372 999e12bb Anthony Liguori
373 999e12bb Anthony Liguori
    sdc->init = icp_pit_init;
374 999e12bb Anthony Liguori
}
375 999e12bb Anthony Liguori
376 8c43a6f0 Andreas Färber
static const TypeInfo icp_pit_info = {
377 e2051b42 Andreas Färber
    .name          = TYPE_INTEGRATOR_PIT,
378 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
379 39bffca2 Anthony Liguori
    .instance_size = sizeof(icp_pit_state),
380 39bffca2 Anthony Liguori
    .class_init    = icp_pit_class_init,
381 39bffca2 Anthony Liguori
};
382 39bffca2 Anthony Liguori
383 39bffca2 Anthony Liguori
static Property sp804_properties[] = {
384 1024d7f0 Andreas Färber
    DEFINE_PROP_UINT32("freq0", SP804State, freq0, 1000000),
385 1024d7f0 Andreas Färber
    DEFINE_PROP_UINT32("freq1", SP804State, freq1, 1000000),
386 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
387 999e12bb Anthony Liguori
};
388 999e12bb Anthony Liguori
389 999e12bb Anthony Liguori
static void sp804_class_init(ObjectClass *klass, void *data)
390 999e12bb Anthony Liguori
{
391 999e12bb Anthony Liguori
    SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
392 39bffca2 Anthony Liguori
    DeviceClass *k = DEVICE_CLASS(klass);
393 999e12bb Anthony Liguori
394 999e12bb Anthony Liguori
    sdc->init = sp804_init;
395 39bffca2 Anthony Liguori
    k->props = sp804_properties;
396 999e12bb Anthony Liguori
}
397 999e12bb Anthony Liguori
398 8c43a6f0 Andreas Färber
static const TypeInfo sp804_info = {
399 0c88dea5 Andreas Färber
    .name          = TYPE_SP804,
400 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
401 1024d7f0 Andreas Färber
    .instance_size = sizeof(SP804State),
402 39bffca2 Anthony Liguori
    .class_init    = sp804_class_init,
403 999e12bb Anthony Liguori
};
404 999e12bb Anthony Liguori
405 83f7d43a Andreas Färber
static void arm_timer_register_types(void)
406 6a824ec3 Paul Brook
{
407 39bffca2 Anthony Liguori
    type_register_static(&icp_pit_info);
408 39bffca2 Anthony Liguori
    type_register_static(&sp804_info);
409 6a824ec3 Paul Brook
}
410 6a824ec3 Paul Brook
411 83f7d43a Andreas Färber
type_init(arm_timer_register_types)