]> git.proxmox.com Git - mirror_qemu.git/blame - hw/timer/pxa2xx_timer.c
hw/timer: QOM'ify pl031
[mirror_qemu.git] / hw / timer / pxa2xx_timer.c
CommitLineData
a171fe39
AZ
1/*
2 * Intel XScale PXA255/270 OS Timers.
3 *
4 * Copyright (c) 2006 Openedhand Ltd.
5 * Copyright (c) 2006 Thorsten Zitterell
6 *
8e31bf38 7 * This code is licensed under the GPL.
a171fe39
AZ
8 */
9
8ef94f0b 10#include "qemu/osdep.h"
83c9f4ca 11#include "hw/hw.h"
1de7afc9 12#include "qemu/timer.h"
9c17d615 13#include "sysemu/sysemu.h"
0d09e41a 14#include "hw/arm/pxa.h"
83c9f4ca 15#include "hw/sysbus.h"
a171fe39
AZ
16
17#define OSMR0 0x00
18#define OSMR1 0x04
19#define OSMR2 0x08
20#define OSMR3 0x0c
21#define OSMR4 0x80
22#define OSMR5 0x84
23#define OSMR6 0x88
24#define OSMR7 0x8c
25#define OSMR8 0x90
26#define OSMR9 0x94
27#define OSMR10 0x98
28#define OSMR11 0x9c
29#define OSCR 0x10 /* OS Timer Count */
30#define OSCR4 0x40
31#define OSCR5 0x44
32#define OSCR6 0x48
33#define OSCR7 0x4c
34#define OSCR8 0x50
35#define OSCR9 0x54
36#define OSCR10 0x58
37#define OSCR11 0x5c
38#define OSSR 0x14 /* Timer status register */
39#define OWER 0x18
40#define OIER 0x1c /* Interrupt enable register 3-0 to E3-E0 */
41#define OMCR4 0xc0 /* OS Match Control registers */
42#define OMCR5 0xc4
43#define OMCR6 0xc8
44#define OMCR7 0xcc
45#define OMCR8 0xd0
46#define OMCR9 0xd4
47#define OMCR10 0xd8
48#define OMCR11 0xdc
49#define OSNR 0x20
50
51#define PXA25X_FREQ 3686400 /* 3.6864 MHz */
52#define PXA27X_FREQ 3250000 /* 3.25 MHz */
53
54static int pxa2xx_timer4_freq[8] = {
55 [0] = 0,
56 [1] = 32768,
57 [2] = 1000,
58 [3] = 1,
59 [4] = 1000000,
60 /* [5] is the "Externally supplied clock". Assign if necessary. */
61 [5 ... 7] = 0,
62};
63
feea4361
AF
64#define TYPE_PXA2XX_TIMER "pxa2xx-timer"
65#define PXA2XX_TIMER(obj) \
66 OBJECT_CHECK(PXA2xxTimerInfo, (obj), TYPE_PXA2XX_TIMER)
67
797e9542
DES
68typedef struct PXA2xxTimerInfo PXA2xxTimerInfo;
69
bc24a225 70typedef struct {
a171fe39 71 uint32_t value;
5251d196 72 qemu_irq irq;
a171fe39
AZ
73 QEMUTimer *qtimer;
74 int num;
797e9542 75 PXA2xxTimerInfo *info;
bc24a225 76} PXA2xxTimer0;
a171fe39 77
bc24a225
PB
78typedef struct {
79 PXA2xxTimer0 tm;
a171fe39
AZ
80 int32_t oldclock;
81 int32_t clock;
82 uint64_t lastload;
83 uint32_t freq;
84 uint32_t control;
bc24a225 85} PXA2xxTimer4;
a171fe39 86
797e9542 87struct PXA2xxTimerInfo {
feea4361
AF
88 SysBusDevice parent_obj;
89
b755bde3 90 MemoryRegion iomem;
797e9542
DES
91 uint32_t flags;
92
a171fe39
AZ
93 int32_t clock;
94 int32_t oldclock;
95 uint64_t lastload;
96 uint32_t freq;
bc24a225 97 PXA2xxTimer0 timer[4];
a171fe39
AZ
98 uint32_t events;
99 uint32_t irq_enabled;
100 uint32_t reset3;
a171fe39 101 uint32_t snapshot;
797e9542 102
4ff927cc 103 qemu_irq irq4;
797e9542 104 PXA2xxTimer4 tm4[8];
797e9542
DES
105};
106
107#define PXA2XX_TIMER_HAVE_TM4 0
108
109static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s)
110{
111 return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4);
112}
a171fe39
AZ
113
114static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
115{
d353eb43 116 PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
a171fe39
AZ
117 int i;
118 uint32_t now_vm;
119 uint64_t new_qemu;
120
121 now_vm = s->clock +
6ee093c9 122 muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
a171fe39
AZ
123
124 for (i = 0; i < 4; i ++) {
125 new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
6ee093c9 126 get_ticks_per_sec(), s->freq);
bc72ad67 127 timer_mod(s->timer[i].qtimer, new_qemu);
a171fe39
AZ
128 }
129}
130
131static void pxa2xx_timer_update4(void *opaque, uint64_t now_qemu, int n)
132{
d353eb43 133 PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
a171fe39
AZ
134 uint32_t now_vm;
135 uint64_t new_qemu;
136 static const int counters[8] = { 0, 0, 0, 0, 4, 4, 6, 6 };
137 int counter;
138
139 if (s->tm4[n].control & (1 << 7))
140 counter = n;
141 else
142 counter = counters[n];
143
144 if (!s->tm4[counter].freq) {
bc72ad67 145 timer_del(s->tm4[n].tm.qtimer);
a171fe39
AZ
146 return;
147 }
148
149 now_vm = s->tm4[counter].clock + muldiv64(now_qemu -
150 s->tm4[counter].lastload,
6ee093c9 151 s->tm4[counter].freq, get_ticks_per_sec());
a171fe39 152
3bdd58a4 153 new_qemu = now_qemu + muldiv64((uint32_t) (s->tm4[n].tm.value - now_vm),
6ee093c9 154 get_ticks_per_sec(), s->tm4[counter].freq);
bc72ad67 155 timer_mod(s->tm4[n].tm.qtimer, new_qemu);
a171fe39
AZ
156}
157
a8170e5e 158static uint64_t pxa2xx_timer_read(void *opaque, hwaddr offset,
b755bde3 159 unsigned size)
a171fe39 160{
d353eb43 161 PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
a171fe39
AZ
162 int tm = 0;
163
a171fe39
AZ
164 switch (offset) {
165 case OSMR3: tm ++;
de16017d 166 /* fall through */
a171fe39 167 case OSMR2: tm ++;
de16017d 168 /* fall through */
a171fe39 169 case OSMR1: tm ++;
de16017d 170 /* fall through */
a171fe39
AZ
171 case OSMR0:
172 return s->timer[tm].value;
173 case OSMR11: tm ++;
de16017d 174 /* fall through */
a171fe39 175 case OSMR10: tm ++;
de16017d 176 /* fall through */
a171fe39 177 case OSMR9: tm ++;
de16017d 178 /* fall through */
a171fe39 179 case OSMR8: tm ++;
de16017d 180 /* fall through */
a171fe39 181 case OSMR7: tm ++;
de16017d 182 /* fall through */
a171fe39 183 case OSMR6: tm ++;
de16017d 184 /* fall through */
a171fe39 185 case OSMR5: tm ++;
de16017d 186 /* fall through */
a171fe39 187 case OSMR4:
797e9542 188 if (!pxa2xx_timer_has_tm4(s))
a171fe39 189 goto badreg;
3bdd58a4 190 return s->tm4[tm].tm.value;
a171fe39 191 case OSCR:
bc72ad67 192 return s->clock + muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
6ee093c9 193 s->lastload, s->freq, get_ticks_per_sec());
a171fe39 194 case OSCR11: tm ++;
de16017d 195 /* fall through */
a171fe39 196 case OSCR10: tm ++;
de16017d 197 /* fall through */
a171fe39 198 case OSCR9: tm ++;
de16017d 199 /* fall through */
a171fe39 200 case OSCR8: tm ++;
de16017d 201 /* fall through */
a171fe39 202 case OSCR7: tm ++;
de16017d 203 /* fall through */
a171fe39 204 case OSCR6: tm ++;
de16017d 205 /* fall through */
a171fe39 206 case OSCR5: tm ++;
de16017d 207 /* fall through */
a171fe39 208 case OSCR4:
797e9542 209 if (!pxa2xx_timer_has_tm4(s))
a171fe39
AZ
210 goto badreg;
211
212 if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) {
213 if (s->tm4[tm - 1].freq)
214 s->snapshot = s->tm4[tm - 1].clock + muldiv64(
bc72ad67 215 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
a171fe39 216 s->tm4[tm - 1].lastload,
6ee093c9 217 s->tm4[tm - 1].freq, get_ticks_per_sec());
a171fe39
AZ
218 else
219 s->snapshot = s->tm4[tm - 1].clock;
220 }
221
222 if (!s->tm4[tm].freq)
223 return s->tm4[tm].clock;
bc72ad67 224 return s->tm4[tm].clock + muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
6ee093c9 225 s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
a171fe39
AZ
226 case OIER:
227 return s->irq_enabled;
228 case OSSR: /* Status register */
229 return s->events;
230 case OWER:
231 return s->reset3;
232 case OMCR11: tm ++;
de16017d 233 /* fall through */
a171fe39 234 case OMCR10: tm ++;
de16017d 235 /* fall through */
a171fe39 236 case OMCR9: tm ++;
de16017d 237 /* fall through */
a171fe39 238 case OMCR8: tm ++;
de16017d 239 /* fall through */
a171fe39 240 case OMCR7: tm ++;
de16017d 241 /* fall through */
a171fe39 242 case OMCR6: tm ++;
de16017d 243 /* fall through */
a171fe39 244 case OMCR5: tm ++;
de16017d 245 /* fall through */
a171fe39 246 case OMCR4:
797e9542 247 if (!pxa2xx_timer_has_tm4(s))
a171fe39
AZ
248 goto badreg;
249 return s->tm4[tm].control;
250 case OSNR:
251 return s->snapshot;
252 default:
253 badreg:
2ac71179 254 hw_error("pxa2xx_timer_read: Bad offset " REG_FMT "\n", offset);
a171fe39
AZ
255 }
256
257 return 0;
258}
259
a8170e5e 260static void pxa2xx_timer_write(void *opaque, hwaddr offset,
b755bde3 261 uint64_t value, unsigned size)
a171fe39
AZ
262{
263 int i, tm = 0;
d353eb43 264 PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
a171fe39 265
a171fe39
AZ
266 switch (offset) {
267 case OSMR3: tm ++;
de16017d 268 /* fall through */
a171fe39 269 case OSMR2: tm ++;
de16017d 270 /* fall through */
a171fe39 271 case OSMR1: tm ++;
de16017d 272 /* fall through */
a171fe39
AZ
273 case OSMR0:
274 s->timer[tm].value = value;
bc72ad67 275 pxa2xx_timer_update(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
a171fe39
AZ
276 break;
277 case OSMR11: tm ++;
de16017d 278 /* fall through */
a171fe39 279 case OSMR10: tm ++;
de16017d 280 /* fall through */
a171fe39 281 case OSMR9: tm ++;
de16017d 282 /* fall through */
a171fe39 283 case OSMR8: tm ++;
de16017d 284 /* fall through */
a171fe39 285 case OSMR7: tm ++;
de16017d 286 /* fall through */
a171fe39 287 case OSMR6: tm ++;
de16017d 288 /* fall through */
a171fe39 289 case OSMR5: tm ++;
de16017d 290 /* fall through */
a171fe39 291 case OSMR4:
797e9542 292 if (!pxa2xx_timer_has_tm4(s))
a171fe39 293 goto badreg;
3bdd58a4 294 s->tm4[tm].tm.value = value;
bc72ad67 295 pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
a171fe39
AZ
296 break;
297 case OSCR:
298 s->oldclock = s->clock;
bc72ad67 299 s->lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
a171fe39
AZ
300 s->clock = value;
301 pxa2xx_timer_update(s, s->lastload);
302 break;
303 case OSCR11: tm ++;
de16017d 304 /* fall through */
a171fe39 305 case OSCR10: tm ++;
de16017d 306 /* fall through */
a171fe39 307 case OSCR9: tm ++;
de16017d 308 /* fall through */
a171fe39 309 case OSCR8: tm ++;
de16017d 310 /* fall through */
a171fe39 311 case OSCR7: tm ++;
de16017d 312 /* fall through */
a171fe39 313 case OSCR6: tm ++;
de16017d 314 /* fall through */
a171fe39 315 case OSCR5: tm ++;
de16017d 316 /* fall through */
a171fe39 317 case OSCR4:
797e9542 318 if (!pxa2xx_timer_has_tm4(s))
a171fe39
AZ
319 goto badreg;
320 s->tm4[tm].oldclock = s->tm4[tm].clock;
bc72ad67 321 s->tm4[tm].lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
a171fe39
AZ
322 s->tm4[tm].clock = value;
323 pxa2xx_timer_update4(s, s->tm4[tm].lastload, tm);
324 break;
325 case OIER:
326 s->irq_enabled = value & 0xfff;
327 break;
328 case OSSR: /* Status register */
8034ce7d 329 value &= s->events;
a171fe39 330 s->events &= ~value;
8034ce7d
AZ
331 for (i = 0; i < 4; i ++, value >>= 1)
332 if (value & 1)
5251d196 333 qemu_irq_lower(s->timer[i].irq);
8034ce7d
AZ
334 if (pxa2xx_timer_has_tm4(s) && !(s->events & 0xff0) && value)
335 qemu_irq_lower(s->irq4);
a171fe39
AZ
336 break;
337 case OWER: /* XXX: Reset on OSMR3 match? */
338 s->reset3 = value;
339 break;
340 case OMCR7: tm ++;
de16017d 341 /* fall through */
a171fe39 342 case OMCR6: tm ++;
de16017d 343 /* fall through */
a171fe39 344 case OMCR5: tm ++;
de16017d 345 /* fall through */
a171fe39 346 case OMCR4:
797e9542 347 if (!pxa2xx_timer_has_tm4(s))
a171fe39
AZ
348 goto badreg;
349 s->tm4[tm].control = value & 0x0ff;
350 /* XXX Stop if running (shouldn't happen) */
351 if ((value & (1 << 7)) || tm == 0)
352 s->tm4[tm].freq = pxa2xx_timer4_freq[value & 7];
353 else {
354 s->tm4[tm].freq = 0;
bc72ad67 355 pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
a171fe39
AZ
356 }
357 break;
358 case OMCR11: tm ++;
de16017d 359 /* fall through */
a171fe39 360 case OMCR10: tm ++;
de16017d 361 /* fall through */
a171fe39 362 case OMCR9: tm ++;
de16017d 363 /* fall through */
a171fe39 364 case OMCR8: tm += 4;
797e9542 365 if (!pxa2xx_timer_has_tm4(s))
a171fe39
AZ
366 goto badreg;
367 s->tm4[tm].control = value & 0x3ff;
368 /* XXX Stop if running (shouldn't happen) */
369 if ((value & (1 << 7)) || !(tm & 1))
370 s->tm4[tm].freq =
371 pxa2xx_timer4_freq[(value & (1 << 8)) ? 0 : (value & 7)];
372 else {
373 s->tm4[tm].freq = 0;
bc72ad67 374 pxa2xx_timer_update4(s, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), tm);
a171fe39
AZ
375 }
376 break;
377 default:
378 badreg:
2ac71179 379 hw_error("pxa2xx_timer_write: Bad offset " REG_FMT "\n", offset);
a171fe39
AZ
380 }
381}
382
b755bde3
BC
383static const MemoryRegionOps pxa2xx_timer_ops = {
384 .read = pxa2xx_timer_read,
385 .write = pxa2xx_timer_write,
386 .endianness = DEVICE_NATIVE_ENDIAN,
a171fe39
AZ
387};
388
389static void pxa2xx_timer_tick(void *opaque)
390{
bc24a225 391 PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque;
797e9542 392 PXA2xxTimerInfo *i = t->info;
a171fe39
AZ
393
394 if (i->irq_enabled & (1 << t->num)) {
a171fe39 395 i->events |= 1 << t->num;
5251d196 396 qemu_irq_raise(t->irq);
a171fe39
AZ
397 }
398
399 if (t->num == 3)
400 if (i->reset3 & 1) {
401 i->reset3 = 0;
3f582262 402 qemu_system_reset_request();
a171fe39
AZ
403 }
404}
405
406static void pxa2xx_timer_tick4(void *opaque)
407{
bc24a225 408 PXA2xxTimer4 *t = (PXA2xxTimer4 *) opaque;
d353eb43 409 PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->tm.info;
a171fe39 410
3bdd58a4 411 pxa2xx_timer_tick(&t->tm);
a171fe39
AZ
412 if (t->control & (1 << 3))
413 t->clock = 0;
414 if (t->control & (1 << 6))
bc72ad67 415 pxa2xx_timer_update4(i, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), t->tm.num - 4);
4ff927cc
DES
416 if (i->events & 0xff0)
417 qemu_irq_raise(i->irq4);
a171fe39
AZ
418}
419
797e9542 420static int pxa25x_timer_post_load(void *opaque, int version_id)
aa941b94 421{
d353eb43 422 PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
aa941b94
AZ
423 int64_t now;
424 int i;
425
bc72ad67 426 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
aa941b94
AZ
427 pxa2xx_timer_update(s, now);
428
797e9542
DES
429 if (pxa2xx_timer_has_tm4(s))
430 for (i = 0; i < 8; i ++)
aa941b94 431 pxa2xx_timer_update4(s, now, i);
aa941b94
AZ
432
433 return 0;
434}
435
797e9542 436static int pxa2xx_timer_init(SysBusDevice *dev)
a171fe39 437{
feea4361 438 PXA2xxTimerInfo *s = PXA2XX_TIMER(dev);
a171fe39 439 int i;
a171fe39 440
a171fe39
AZ
441 s->irq_enabled = 0;
442 s->oldclock = 0;
443 s->clock = 0;
bc72ad67 444 s->lastload = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
a171fe39 445 s->reset3 = 0;
a171fe39
AZ
446
447 for (i = 0; i < 4; i ++) {
448 s->timer[i].value = 0;
5251d196 449 sysbus_init_irq(dev, &s->timer[i].irq);
a171fe39
AZ
450 s->timer[i].info = s;
451 s->timer[i].num = i;
bc72ad67 452 s->timer[i].qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
a171fe39
AZ
453 pxa2xx_timer_tick, &s->timer[i]);
454 }
797e9542 455 if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) {
4ff927cc 456 sysbus_init_irq(dev, &s->irq4);
797e9542
DES
457
458 for (i = 0; i < 8; i ++) {
459 s->tm4[i].tm.value = 0;
460 s->tm4[i].tm.info = s;
461 s->tm4[i].tm.num = i + 4;
797e9542
DES
462 s->tm4[i].freq = 0;
463 s->tm4[i].control = 0x0;
bc72ad67 464 s->tm4[i].tm.qtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
797e9542
DES
465 pxa2xx_timer_tick4, &s->tm4[i]);
466 }
467 }
a171fe39 468
853dca12 469 memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_timer_ops, s,
b755bde3 470 "pxa2xx-timer", 0x00001000);
750ecd44 471 sysbus_init_mmio(dev, &s->iomem);
aa941b94 472
797e9542 473 return 0;
a171fe39
AZ
474}
475
797e9542
DES
476static const VMStateDescription vmstate_pxa2xx_timer0_regs = {
477 .name = "pxa2xx_timer0",
8034ce7d
AZ
478 .version_id = 2,
479 .minimum_version_id = 2,
797e9542
DES
480 .fields = (VMStateField[]) {
481 VMSTATE_UINT32(value, PXA2xxTimer0),
797e9542
DES
482 VMSTATE_END_OF_LIST(),
483 },
484};
485
486static const VMStateDescription vmstate_pxa2xx_timer4_regs = {
487 .name = "pxa2xx_timer4",
488 .version_id = 1,
489 .minimum_version_id = 1,
797e9542
DES
490 .fields = (VMStateField[]) {
491 VMSTATE_STRUCT(tm, PXA2xxTimer4, 1,
492 vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
493 VMSTATE_INT32(oldclock, PXA2xxTimer4),
494 VMSTATE_INT32(clock, PXA2xxTimer4),
495 VMSTATE_UINT64(lastload, PXA2xxTimer4),
496 VMSTATE_UINT32(freq, PXA2xxTimer4),
497 VMSTATE_UINT32(control, PXA2xxTimer4),
498 VMSTATE_END_OF_LIST(),
499 },
500};
501
502static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id)
a171fe39 503{
797e9542 504 return pxa2xx_timer_has_tm4(opaque);
a171fe39
AZ
505}
506
797e9542
DES
507static const VMStateDescription vmstate_pxa2xx_timer_regs = {
508 .name = "pxa2xx_timer",
509 .version_id = 1,
510 .minimum_version_id = 1,
797e9542
DES
511 .post_load = pxa25x_timer_post_load,
512 .fields = (VMStateField[]) {
513 VMSTATE_INT32(clock, PXA2xxTimerInfo),
514 VMSTATE_INT32(oldclock, PXA2xxTimerInfo),
515 VMSTATE_UINT64(lastload, PXA2xxTimerInfo),
516 VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1,
517 vmstate_pxa2xx_timer0_regs, PXA2xxTimer0),
518 VMSTATE_UINT32(events, PXA2xxTimerInfo),
519 VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo),
520 VMSTATE_UINT32(reset3, PXA2xxTimerInfo),
521 VMSTATE_UINT32(snapshot, PXA2xxTimerInfo),
522 VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8,
523 pxa2xx_timer_has_tm4_test, 0,
524 vmstate_pxa2xx_timer4_regs, PXA2xxTimer4),
525 VMSTATE_END_OF_LIST(),
a171fe39 526 }
797e9542
DES
527};
528
999e12bb
AL
529static Property pxa25x_timer_dev_properties[] = {
530 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ),
531 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
feea4361 532 PXA2XX_TIMER_HAVE_TM4, false),
999e12bb 533 DEFINE_PROP_END_OF_LIST(),
797e9542
DES
534};
535
999e12bb
AL
536static void pxa25x_timer_dev_class_init(ObjectClass *klass, void *data)
537{
39bffca2 538 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 539
39bffca2 540 dc->desc = "PXA25x timer";
39bffca2 541 dc->props = pxa25x_timer_dev_properties;
999e12bb
AL
542}
543
8c43a6f0 544static const TypeInfo pxa25x_timer_dev_info = {
39bffca2 545 .name = "pxa25x-timer",
feea4361 546 .parent = TYPE_PXA2XX_TIMER,
39bffca2
AL
547 .instance_size = sizeof(PXA2xxTimerInfo),
548 .class_init = pxa25x_timer_dev_class_init,
999e12bb
AL
549};
550
551static Property pxa27x_timer_dev_properties[] = {
552 DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ),
553 DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags,
feea4361 554 PXA2XX_TIMER_HAVE_TM4, true),
999e12bb
AL
555 DEFINE_PROP_END_OF_LIST(),
556};
557
558static void pxa27x_timer_dev_class_init(ObjectClass *klass, void *data)
559{
39bffca2 560 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 561
39bffca2 562 dc->desc = "PXA27x timer";
39bffca2 563 dc->props = pxa27x_timer_dev_properties;
999e12bb
AL
564}
565
8c43a6f0 566static const TypeInfo pxa27x_timer_dev_info = {
39bffca2 567 .name = "pxa27x-timer",
feea4361 568 .parent = TYPE_PXA2XX_TIMER,
39bffca2
AL
569 .instance_size = sizeof(PXA2xxTimerInfo),
570 .class_init = pxa27x_timer_dev_class_init,
797e9542
DES
571};
572
feea4361
AF
573static void pxa2xx_timer_class_init(ObjectClass *oc, void *data)
574{
575 DeviceClass *dc = DEVICE_CLASS(oc);
576 SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(oc);
577
578 sdc->init = pxa2xx_timer_init;
579 dc->vmsd = &vmstate_pxa2xx_timer_regs;
580}
581
582static const TypeInfo pxa2xx_timer_type_info = {
583 .name = TYPE_PXA2XX_TIMER,
584 .parent = TYPE_SYS_BUS_DEVICE,
585 .instance_size = sizeof(PXA2xxTimerInfo),
586 .abstract = true,
587 .class_init = pxa2xx_timer_class_init,
588};
589
83f7d43a 590static void pxa2xx_timer_register_types(void)
797e9542 591{
feea4361 592 type_register_static(&pxa2xx_timer_type_info);
39bffca2
AL
593 type_register_static(&pxa25x_timer_dev_info);
594 type_register_static(&pxa27x_timer_dev_info);
83f7d43a
AF
595}
596
597type_init(pxa2xx_timer_register_types)