pxa2xx_timer: switch to using qdev/vmstate
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Thu, 3 Mar 2011 13:14:44 +0000 (14:14 +0100)
committerAndrzej Zaborowski <balrog@zabor.org>
Thu, 3 Mar 2011 13:14:44 +0000 (14:14 +0100)
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>
hw/pxa.h
hw/pxa2xx.c
hw/pxa2xx_timer.c

index 5874116..7d7f49e 100644 (file)
--- a/hw/pxa.h
+++ b/hw/pxa.h
 /* pxa2xx_pic.c */
 DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env);
 
-/* pxa2xx_timer.c */
-void pxa25x_timer_init(target_phys_addr_t base, DeviceState *pic);
-void pxa27x_timer_init(target_phys_addr_t base, DeviceState *pic);
-
 /* pxa2xx_gpio.c */
 DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
                 CPUState *env, DeviceState *pic, int lines);
index 6ff8131..7c31fab 100644 (file)
@@ -2100,7 +2100,13 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
     s->dma = pxa27x_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
 
-    pxa27x_timer_init(0x40a00000, s->pic);
+    sysbus_create_varargs("pxa27x-timer", 0x40a00000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
+                    qdev_get_gpio_in(s->pic, PXA27X_PIC_OST_4_11),
+                    NULL);
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 121);
 
@@ -2229,7 +2235,12 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
     s->dma = pxa255_dma_init(0x40000000,
                     qdev_get_gpio_in(s->pic, PXA2XX_PIC_DMA));
 
-    pxa25x_timer_init(0x40a00000, s->pic);
+    sysbus_create_varargs("pxa25x-timer", 0x40a00000,
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 0),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 1),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 2),
+                    qdev_get_gpio_in(s->pic, PXA2XX_PIC_OST_0 + 3),
+                    NULL);
 
     s->gpio = pxa2xx_gpio_init(0x40e00000, s->env, s->pic, 85);
 
index 08141a2..3a50138 100644 (file)
@@ -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);