diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2011-03-03 14:14:44 +0100 |
---|---|---|
committer | Andrzej Zaborowski <balrog@zabor.org> | 2011-03-03 14:14:44 +0100 |
commit | 797e9542f56b37632fddbfeb810d4a9ed1fc55ab (patch) | |
tree | b37785b65b32315b155e15917a9c4c7a0999dc3f /hw/pxa2xx_timer.c | |
parent | d353eb43cffc4e8f44f3acba0d04743ba3f4aca1 (diff) | |
download | qemu-797e9542f56b37632fddbfeb810d4a9ed1fc55ab.zip qemu-797e9542f56b37632fddbfeb810d4a9ed1fc55ab.tar.gz qemu-797e9542f56b37632fddbfeb810d4a9ed1fc55ab.tar.bz2 |
pxa2xx_timer: switch to using qdev/vmstate
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>
Diffstat (limited to 'hw/pxa2xx_timer.c')
-rw-r--r-- | hw/pxa2xx_timer.c | 244 |
1 files changed, 141 insertions, 103 deletions
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c index 08141a2..3a50138 100644 --- a/hw/pxa2xx_timer.c +++ b/hw/pxa2xx_timer.c @@ -10,8 +10,8 @@ #include "hw.h" #include "qemu-timer.h" #include "sysemu.h" -#include "qdev.h" #include "pxa.h" +#include "sysbus.h" #define OSMR0 0x00 #define OSMR1 0x04 @@ -60,13 +60,14 @@ static int pxa2xx_timer4_freq[8] = { [5 ... 7] = 0, }; +typedef struct PXA2xxTimerInfo PXA2xxTimerInfo; + typedef struct { uint32_t value; int level; - qemu_irq irq; QEMUTimer *qtimer; int num; - void *info; + PXA2xxTimerInfo *info; } PXA2xxTimer0; typedef struct { @@ -78,18 +79,31 @@ typedef struct { uint32_t control; } PXA2xxTimer4; -typedef struct { +struct PXA2xxTimerInfo { + SysBusDevice busdev; + uint32_t flags; + int32_t clock; int32_t oldclock; uint64_t lastload; uint32_t freq; PXA2xxTimer0 timer[4]; - PXA2xxTimer4 *tm4; + qemu_irq irqs[5]; uint32_t events; uint32_t irq_enabled; uint32_t reset3; uint32_t snapshot; -} PXA2xxTimerInfo; + + PXA2xxTimer4 tm4[8]; + qemu_irq irq4; +}; + +#define PXA2XX_TIMER_HAVE_TM4 0 + +static inline int pxa2xx_timer_has_tm4(PXA2xxTimerInfo *s) +{ + return s->flags & (1 << PXA2XX_TIMER_HAVE_TM4); +} static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu) { @@ -154,7 +168,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset) case OSMR6: tm ++; case OSMR5: tm ++; case OSMR4: - if (!s->tm4) + if (!pxa2xx_timer_has_tm4(s)) goto badreg; return s->tm4[tm].tm.value; case OSCR: @@ -168,7 +182,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset) case OSCR6: tm ++; case OSCR5: tm ++; case OSCR4: - if (!s->tm4) + if (!pxa2xx_timer_has_tm4(s)) goto badreg; if ((tm == 9 - 4 || tm == 11 - 4) && (s->tm4[tm].control & (1 << 9))) { @@ -199,7 +213,7 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset) case OMCR6: tm ++; case OMCR5: tm ++; case OMCR4: - if (!s->tm4) + if (!pxa2xx_timer_has_tm4(s)) goto badreg; return s->tm4[tm].control; case OSNR: @@ -234,7 +248,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, case OSMR6: tm ++; case OSMR5: tm ++; case OSMR4: - if (!s->tm4) + if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].tm.value = value; pxa2xx_timer_update4(s, qemu_get_clock(vm_clock), tm); @@ -253,7 +267,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, case OSCR6: tm ++; case OSCR5: tm ++; case OSCR4: - if (!s->tm4) + if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].oldclock = s->tm4[tm].clock; s->tm4[tm].lastload = qemu_get_clock(vm_clock); @@ -268,15 +282,15 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, for (i = 0; i < 4; i ++, value >>= 1) { if (s->timer[i].level && (value & 1)) { s->timer[i].level = 0; - qemu_irq_lower(s->timer[i].irq); + qemu_irq_lower(s->irqs[i]); } } - if (s->tm4) { + if (pxa2xx_timer_has_tm4(s)) { for (i = 0; i < 8; i ++, value >>= 1) if (s->tm4[i].tm.level && (value & 1)) s->tm4[i].tm.level = 0; if (!(s->events & 0xff0)) - qemu_irq_lower(s->tm4->tm.irq); + qemu_irq_lower(s->irq4); } break; case OWER: /* XXX: Reset on OSMR3 match? */ @@ -286,7 +300,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, case OMCR6: tm ++; case OMCR5: tm ++; case OMCR4: - if (!s->tm4) + if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].control = value & 0x0ff; /* XXX Stop if running (shouldn't happen) */ @@ -301,7 +315,7 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset, case OMCR10: tm ++; case OMCR9: tm ++; case OMCR8: tm += 4; - if (!s->tm4) + if (!pxa2xx_timer_has_tm4(s)) goto badreg; s->tm4[tm].control = value & 0x3ff; /* XXX Stop if running (shouldn't happen) */ @@ -334,12 +348,12 @@ static CPUWriteMemoryFunc * const pxa2xx_timer_writefn[] = { static void pxa2xx_timer_tick(void *opaque) { PXA2xxTimer0 *t = (PXA2xxTimer0 *) opaque; - PXA2xxTimerInfo *i = (PXA2xxTimerInfo *) t->info; + PXA2xxTimerInfo *i = t->info; if (i->irq_enabled & (1 << t->num)) { t->level = 1; i->events |= 1 << t->num; - qemu_irq_raise(t->irq); + qemu_irq_raise(t->num < 4 ? i->irqs[t->num] : i->irq4); } if (t->num == 3) @@ -361,81 +375,29 @@ static void pxa2xx_timer_tick4(void *opaque) pxa2xx_timer_update4(i, qemu_get_clock(vm_clock), t->tm.num - 4); } -static void pxa2xx_timer_save(QEMUFile *f, void *opaque) -{ - PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; - int i; - - qemu_put_be32s(f, (uint32_t *) &s->clock); - qemu_put_be32s(f, (uint32_t *) &s->oldclock); - qemu_put_be64s(f, &s->lastload); - - for (i = 0; i < 4; i ++) { - qemu_put_be32s(f, &s->timer[i].value); - qemu_put_be32(f, s->timer[i].level); - } - if (s->tm4) - for (i = 0; i < 8; i ++) { - qemu_put_be32s(f, &s->tm4[i].tm.value); - qemu_put_be32(f, s->tm4[i].tm.level); - qemu_put_sbe32s(f, &s->tm4[i].oldclock); - qemu_put_sbe32s(f, &s->tm4[i].clock); - qemu_put_be64s(f, &s->tm4[i].lastload); - qemu_put_be32s(f, &s->tm4[i].freq); - qemu_put_be32s(f, &s->tm4[i].control); - } - - qemu_put_be32s(f, &s->events); - qemu_put_be32s(f, &s->irq_enabled); - qemu_put_be32s(f, &s->reset3); - qemu_put_be32s(f, &s->snapshot); -} - -static int pxa2xx_timer_load(QEMUFile *f, void *opaque, int version_id) +static int pxa25x_timer_post_load(void *opaque, int version_id) { PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque; int64_t now; int i; - qemu_get_be32s(f, (uint32_t *) &s->clock); - qemu_get_be32s(f, (uint32_t *) &s->oldclock); - qemu_get_be64s(f, &s->lastload); - now = qemu_get_clock(vm_clock); - for (i = 0; i < 4; i ++) { - qemu_get_be32s(f, &s->timer[i].value); - s->timer[i].level = qemu_get_be32(f); - } pxa2xx_timer_update(s, now); - if (s->tm4) - for (i = 0; i < 8; i ++) { - qemu_get_be32s(f, &s->tm4[i].tm.value); - s->tm4[i].tm.level = qemu_get_be32(f); - qemu_get_sbe32s(f, &s->tm4[i].oldclock); - qemu_get_sbe32s(f, &s->tm4[i].clock); - qemu_get_be64s(f, &s->tm4[i].lastload); - qemu_get_be32s(f, &s->tm4[i].freq); - qemu_get_be32s(f, &s->tm4[i].control); + if (pxa2xx_timer_has_tm4(s)) + for (i = 0; i < 8; i ++) pxa2xx_timer_update4(s, now, i); - } - - qemu_get_be32s(f, &s->events); - qemu_get_be32s(f, &s->irq_enabled); - qemu_get_be32s(f, &s->reset3); - qemu_get_be32s(f, &s->snapshot); return 0; } -static PXA2xxTimerInfo *pxa2xx_timer_init(target_phys_addr_t base, - DeviceState *pic) +static int pxa2xx_timer_init(SysBusDevice *dev) { int i; int iomemtype; PXA2xxTimerInfo *s; - s = (PXA2xxTimerInfo *) qemu_mallocz(sizeof(PXA2xxTimerInfo)); + s = FROM_SYSBUS(PXA2xxTimerInfo, dev); s->irq_enabled = 0; s->oldclock = 0; s->clock = 0; @@ -444,47 +406,123 @@ static PXA2xxTimerInfo *pxa2xx_timer_init(target_phys_addr_t base, for (i = 0; i < 4; i ++) { s->timer[i].value = 0; - s->timer[i].irq = qdev_get_gpio_in(pic, PXA2XX_PIC_OST_0 + i); + sysbus_init_irq(dev, &s->irqs[i]); s->timer[i].info = s; s->timer[i].num = i; s->timer[i].level = 0; s->timer[i].qtimer = qemu_new_timer(vm_clock, pxa2xx_timer_tick, &s->timer[i]); } + if (s->flags & (1 << PXA2XX_TIMER_HAVE_TM4)) { + sysbus_init_irq(dev, &s->irq4); + + for (i = 0; i < 8; i ++) { + s->tm4[i].tm.value = 0; + s->tm4[i].tm.info = s; + s->tm4[i].tm.num = i + 4; + s->tm4[i].tm.level = 0; + s->tm4[i].freq = 0; + s->tm4[i].control = 0x0; + s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock, + pxa2xx_timer_tick4, &s->tm4[i]); + } + } iomemtype = cpu_register_io_memory(pxa2xx_timer_readfn, pxa2xx_timer_writefn, s, DEVICE_NATIVE_ENDIAN); - cpu_register_physical_memory(base, 0x00001000, iomemtype); + sysbus_init_mmio(dev, 0x00001000, iomemtype); - register_savevm(NULL, "pxa2xx_timer", 0, 0, - pxa2xx_timer_save, pxa2xx_timer_load, s); - - return s; + return 0; } -void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic) +static const VMStateDescription vmstate_pxa2xx_timer0_regs = { + .name = "pxa2xx_timer0", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(value, PXA2xxTimer0), + VMSTATE_INT32(level, PXA2xxTimer0), + VMSTATE_END_OF_LIST(), + }, +}; + +static const VMStateDescription vmstate_pxa2xx_timer4_regs = { + .name = "pxa2xx_timer4", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField[]) { + VMSTATE_STRUCT(tm, PXA2xxTimer4, 1, + vmstate_pxa2xx_timer0_regs, PXA2xxTimer0), + VMSTATE_INT32(oldclock, PXA2xxTimer4), + VMSTATE_INT32(clock, PXA2xxTimer4), + VMSTATE_UINT64(lastload, PXA2xxTimer4), + VMSTATE_UINT32(freq, PXA2xxTimer4), + VMSTATE_UINT32(control, PXA2xxTimer4), + VMSTATE_END_OF_LIST(), + }, +}; + +static bool pxa2xx_timer_has_tm4_test(void *opaque, int version_id) { - PXA2xxTimerInfo *s = pxa2xx_timer_init(base, pic); - s->freq = PXA25X_FREQ; - s->tm4 = NULL; + return pxa2xx_timer_has_tm4(opaque); } -void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic) -{ - PXA2xxTimerInfo *s = pxa2xx_timer_init(base, pic); - int i; - s->freq = PXA27X_FREQ; - s->tm4 = (PXA2xxTimer4 *) qemu_mallocz(8 * - sizeof(PXA2xxTimer4)); - for (i = 0; i < 8; i ++) { - s->tm4[i].tm.value = 0; - s->tm4[i].tm.irq = qdev_get_gpio_in(pic, PXA27X_PIC_OST_4_11); - s->tm4[i].tm.info = s; - s->tm4[i].tm.num = i + 4; - s->tm4[i].tm.level = 0; - s->tm4[i].freq = 0; - s->tm4[i].control = 0x0; - s->tm4[i].tm.qtimer = qemu_new_timer(vm_clock, - pxa2xx_timer_tick4, &s->tm4[i]); +static const VMStateDescription vmstate_pxa2xx_timer_regs = { + .name = "pxa2xx_timer", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = pxa25x_timer_post_load, + .fields = (VMStateField[]) { + VMSTATE_INT32(clock, PXA2xxTimerInfo), + VMSTATE_INT32(oldclock, PXA2xxTimerInfo), + VMSTATE_UINT64(lastload, PXA2xxTimerInfo), + VMSTATE_STRUCT_ARRAY(timer, PXA2xxTimerInfo, 4, 1, + vmstate_pxa2xx_timer0_regs, PXA2xxTimer0), + VMSTATE_UINT32(events, PXA2xxTimerInfo), + VMSTATE_UINT32(irq_enabled, PXA2xxTimerInfo), + VMSTATE_UINT32(reset3, PXA2xxTimerInfo), + VMSTATE_UINT32(snapshot, PXA2xxTimerInfo), + VMSTATE_STRUCT_ARRAY_TEST(tm4, PXA2xxTimerInfo, 8, + pxa2xx_timer_has_tm4_test, 0, + vmstate_pxa2xx_timer4_regs, PXA2xxTimer4), + VMSTATE_END_OF_LIST(), } -} +}; + +static SysBusDeviceInfo pxa25x_timer_dev_info = { + .init = pxa2xx_timer_init, + .qdev.name = "pxa25x-timer", + .qdev.desc = "PXA25x timer", + .qdev.size = sizeof(PXA2xxTimerInfo), + .qdev.vmsd = &vmstate_pxa2xx_timer_regs, + .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA25X_FREQ), + DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags, + PXA2XX_TIMER_HAVE_TM4, false), + DEFINE_PROP_END_OF_LIST(), + }, +}; + +static SysBusDeviceInfo pxa27x_timer_dev_info = { + .init = pxa2xx_timer_init, + .qdev.name = "pxa27x-timer", + .qdev.desc = "PXA27x timer", + .qdev.size = sizeof(PXA2xxTimerInfo), + .qdev.vmsd = &vmstate_pxa2xx_timer_regs, + .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("freq", PXA2xxTimerInfo, freq, PXA27X_FREQ), + DEFINE_PROP_BIT("tm4", PXA2xxTimerInfo, flags, + PXA2XX_TIMER_HAVE_TM4, true), + DEFINE_PROP_END_OF_LIST(), + }, +}; + +static void pxa2xx_timer_register(void) +{ + sysbus_register_withprop(&pxa25x_timer_dev_info); + sysbus_register_withprop(&pxa27x_timer_dev_info); +}; +device_init(pxa2xx_timer_register); |