diff --git a/hw/pxa.h b/hw/pxa.h
index c2dede2..142f094 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -66,10 +66,6 @@
 DeviceState *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env,
         qemu_irq *arm_pic);
 
-/* 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,
                 qemu_irq wake_irq, DeviceState *pic, int lines);
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index bc9542e..a2604f1 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2104,7 +2104,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, arm_pic[ARM_PIC_CPU_WAKE],
             s->pic, 121);
@@ -2239,7 +2245,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, arm_pic[ARM_PIC_CPU_WAKE],
             s->pic, 85);
diff --git a/hw/pxa2xx_timer.c b/hw/pxa2xx_timer.c
index 08141a2..d30c45c 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 bool 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)
 {
@@ -101,7 +115,7 @@ static void pxa2xx_timer_update(void *opaque, uint64_t now_qemu)
     now_vm = s->clock +
             muldiv64(now_qemu - s->lastload, s->freq, get_ticks_per_sec());
 
-    for (i = 0; i < 4; i ++) {
+    for (i = 0; i < 4; i++) {
         new_qemu = now_qemu + muldiv64((uint32_t) (s->timer[i].value - now_vm),
                         get_ticks_per_sec(), s->freq);
         qemu_mod_timer(s->timer[i].qtimer, new_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))) {
@@ -184,7 +198,8 @@ static uint32_t pxa2xx_timer_read(void *opaque, target_phys_addr_t offset)
         if (!s->tm4[tm].freq)
             return s->tm4[tm].clock;
         return s->tm4[tm].clock + muldiv64(qemu_get_clock(vm_clock) -
-                        s->tm4[tm].lastload, s->tm4[tm].freq, get_ticks_per_sec());
+                        s->tm4[tm].lastload, s->tm4[tm].freq,
+                        get_ticks_per_sec());
     case OIER:
         return s->irq_enabled;
     case OSSR:	/* Status register */
@@ -199,7 +214,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:
@@ -217,7 +232,6 @@ static void pxa2xx_timer_write(void *opaque, target_phys_addr_t offset,
 {
     int i, tm = 0;
     PXA2xxTimerInfo *s = (PXA2xxTimerInfo *) opaque;
-
     switch (offset) {
     case OSMR3:  tm ++;
     case OSMR2:  tm ++;
@@ -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,130 +375,152 @@ 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;
     s->lastload = qemu_get_clock(vm_clock);
     s->reset3 = 0;
 
-    for (i = 0; i < 4; i ++) {
+    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);
-
-    register_savevm(NULL, "pxa2xx_timer", 0, 0,
-                    pxa2xx_timer_save, pxa2xx_timer_load, s);
+    sysbus_init_mmio(dev, 0x00001000, iomemtype);
 
-    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);
