]> git.proxmox.com Git - mirror_qemu.git/blobdiff - hw/omap2.c
hpet: Save/restore cached RTC IRQ level
[mirror_qemu.git] / hw / omap2.c
index 0e78fc506245219da00b3f826a03469bcbdba2dd..a6851b0fb08b234e80a950a5376adfb8013386cf 100644 (file)
 #include "qemu-char.h"
 #include "flash.h"
 #include "soc_dma.h"
+#include "sysbus.h"
 #include "audio/audio.h"
 
-/* Multichannel SPI */
-struct omap_mcspi_s {
-    qemu_irq irq;
-    int chnum;
-
-    uint32_t sysconfig;
-    uint32_t systest;
-    uint32_t irqst;
-    uint32_t irqen;
-    uint32_t wken;
-    uint32_t control;
-
-    struct omap_mcspi_ch_s {
-        qemu_irq txdrq;
-        qemu_irq rxdrq;
-        uint32_t (*txrx)(void *opaque, uint32_t, int);
-        void *opaque;
-
-        uint32_t tx;
-        uint32_t rx;
-
-        uint32_t config;
-        uint32_t status;
-        uint32_t control;
-    } ch[4];
-};
-
-static inline void omap_mcspi_interrupt_update(struct omap_mcspi_s *s)
-{
-    qemu_set_irq(s->irq, s->irqst & s->irqen);
-}
-
-static inline void omap_mcspi_dmarequest_update(struct omap_mcspi_ch_s *ch)
-{
-    qemu_set_irq(ch->txdrq,
-                    (ch->control & 1) &&               /* EN */
-                    (ch->config & (1 << 14)) &&                /* DMAW */
-                    (ch->status & (1 << 1)) &&         /* TXS */
-                    ((ch->config >> 12) & 3) != 1);    /* TRM */
-    qemu_set_irq(ch->rxdrq,
-                    (ch->control & 1) &&               /* EN */
-                    (ch->config & (1 << 15)) &&                /* DMAW */
-                    (ch->status & (1 << 0)) &&         /* RXS */
-                    ((ch->config >> 12) & 3) != 2);    /* TRM */
-}
-
-static void omap_mcspi_transfer_run(struct omap_mcspi_s *s, int chnum)
-{
-    struct omap_mcspi_ch_s *ch = s->ch + chnum;
-
-    if (!(ch->control & 1))                            /* EN */
-        return;
-    if ((ch->status & (1 << 0)) &&                     /* RXS */
-                    ((ch->config >> 12) & 3) != 2 &&   /* TRM */
-                    !(ch->config & (1 << 19)))         /* TURBO */
-        goto intr_update;
-    if ((ch->status & (1 << 1)) &&                     /* TXS */
-                    ((ch->config >> 12) & 3) != 1)     /* TRM */
-        goto intr_update;
-
-    if (!(s->control & 1) ||                           /* SINGLE */
-                    (ch->config & (1 << 20))) {                /* FORCE */
-        if (ch->txrx)
-            ch->rx = ch->txrx(ch->opaque, ch->tx,      /* WL */
-                            1 + (0x1f & (ch->config >> 7)));
-    }
-
-    ch->tx = 0;
-    ch->status |= 1 << 2;                              /* EOT */
-    ch->status |= 1 << 1;                              /* TXS */
-    if (((ch->config >> 12) & 3) != 2)                 /* TRM */
-        ch->status |= 1 << 0;                          /* RXS */
-
-intr_update:
-    if ((ch->status & (1 << 0)) &&                     /* RXS */
-                    ((ch->config >> 12) & 3) != 2 &&   /* TRM */
-                    !(ch->config & (1 << 19)))         /* TURBO */
-        s->irqst |= 1 << (2 + 4 * chnum);              /* RX_FULL */
-    if ((ch->status & (1 << 1)) &&                     /* TXS */
-                    ((ch->config >> 12) & 3) != 1)     /* TRM */
-        s->irqst |= 1 << (0 + 4 * chnum);              /* TX_EMPTY */
-    omap_mcspi_interrupt_update(s);
-    omap_mcspi_dmarequest_update(ch);
-}
-
-static void omap_mcspi_reset(struct omap_mcspi_s *s)
-{
-    int ch;
-
-    s->sysconfig = 0;
-    s->systest = 0;
-    s->irqst = 0;
-    s->irqen = 0;
-    s->wken = 0;
-    s->control = 4;
-
-    for (ch = 0; ch < 4; ch ++) {
-        s->ch[ch].config = 0x060000;
-        s->ch[ch].status = 2;                          /* TXS */
-        s->ch[ch].control = 0;
-
-        omap_mcspi_dmarequest_update(s->ch + ch);
-    }
-
-    omap_mcspi_interrupt_update(s);
-}
-
-static uint32_t omap_mcspi_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
-    int ch = 0;
-    uint32_t ret;
-
-    switch (addr) {
-    case 0x00: /* MCSPI_REVISION */
-        return 0x91;
-
-    case 0x10: /* MCSPI_SYSCONFIG */
-        return s->sysconfig;
-
-    case 0x14: /* MCSPI_SYSSTATUS */
-        return 1;                                      /* RESETDONE */
-
-    case 0x18: /* MCSPI_IRQSTATUS */
-        return s->irqst;
-
-    case 0x1c: /* MCSPI_IRQENABLE */
-        return s->irqen;
-
-    case 0x20: /* MCSPI_WAKEUPENABLE */
-        return s->wken;
-
-    case 0x24: /* MCSPI_SYST */
-        return s->systest;
-
-    case 0x28: /* MCSPI_MODULCTRL */
-        return s->control;
-
-    case 0x68: ch ++;
-    case 0x54: ch ++;
-    case 0x40: ch ++;
-    case 0x2c: /* MCSPI_CHCONF */
-        return s->ch[ch].config;
-
-    case 0x6c: ch ++;
-    case 0x58: ch ++;
-    case 0x44: ch ++;
-    case 0x30: /* MCSPI_CHSTAT */
-        return s->ch[ch].status;
-
-    case 0x70: ch ++;
-    case 0x5c: ch ++;
-    case 0x48: ch ++;
-    case 0x34: /* MCSPI_CHCTRL */
-        return s->ch[ch].control;
-
-    case 0x74: ch ++;
-    case 0x60: ch ++;
-    case 0x4c: ch ++;
-    case 0x38: /* MCSPI_TX */
-        return s->ch[ch].tx;
-
-    case 0x78: ch ++;
-    case 0x64: ch ++;
-    case 0x50: ch ++;
-    case 0x3c: /* MCSPI_RX */
-        s->ch[ch].status &= ~(1 << 0);                 /* RXS */
-        ret = s->ch[ch].rx;
-        omap_mcspi_transfer_run(s, ch);
-        return ret;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_mcspi_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
-    int ch = 0;
-
-    switch (addr) {
-    case 0x00: /* MCSPI_REVISION */
-    case 0x14: /* MCSPI_SYSSTATUS */
-    case 0x30: /* MCSPI_CHSTAT0 */
-    case 0x3c: /* MCSPI_RX0 */
-    case 0x44: /* MCSPI_CHSTAT1 */
-    case 0x50: /* MCSPI_RX1 */
-    case 0x58: /* MCSPI_CHSTAT2 */
-    case 0x64: /* MCSPI_RX2 */
-    case 0x6c: /* MCSPI_CHSTAT3 */
-    case 0x78: /* MCSPI_RX3 */
-        OMAP_RO_REG(addr);
-        return;
-
-    case 0x10: /* MCSPI_SYSCONFIG */
-        if (value & (1 << 1))                          /* SOFTRESET */
-            omap_mcspi_reset(s);
-        s->sysconfig = value & 0x31d;
-        break;
-
-    case 0x18: /* MCSPI_IRQSTATUS */
-        if (!((s->control & (1 << 3)) && (s->systest & (1 << 11)))) {
-            s->irqst &= ~value;
-            omap_mcspi_interrupt_update(s);
-        }
-        break;
-
-    case 0x1c: /* MCSPI_IRQENABLE */
-        s->irqen = value & 0x1777f;
-        omap_mcspi_interrupt_update(s);
-        break;
-
-    case 0x20: /* MCSPI_WAKEUPENABLE */
-        s->wken = value & 1;
-        break;
-
-    case 0x24: /* MCSPI_SYST */
-        if (s->control & (1 << 3))                     /* SYSTEM_TEST */
-            if (value & (1 << 11)) {                   /* SSB */
-                s->irqst |= 0x1777f;
-                omap_mcspi_interrupt_update(s);
-            }
-        s->systest = value & 0xfff;
-        break;
-
-    case 0x28: /* MCSPI_MODULCTRL */
-        if (value & (1 << 3))                          /* SYSTEM_TEST */
-            if (s->systest & (1 << 11)) {              /* SSB */
-                s->irqst |= 0x1777f;
-                omap_mcspi_interrupt_update(s);
-            }
-        s->control = value & 0xf;
-        break;
-
-    case 0x68: ch ++;
-    case 0x54: ch ++;
-    case 0x40: ch ++;
-    case 0x2c: /* MCSPI_CHCONF */
-        if ((value ^ s->ch[ch].config) & (3 << 14))    /* DMAR | DMAW */
-            omap_mcspi_dmarequest_update(s->ch + ch);
-        if (((value >> 12) & 3) == 3)                  /* TRM */
-            fprintf(stderr, "%s: invalid TRM value (3)\n", __FUNCTION__);
-        if (((value >> 7) & 0x1f) < 3)                 /* WL */
-            fprintf(stderr, "%s: invalid WL value (%i)\n",
-                            __FUNCTION__, (value >> 7) & 0x1f);
-        s->ch[ch].config = value & 0x7fffff;
-        break;
-
-    case 0x70: ch ++;
-    case 0x5c: ch ++;
-    case 0x48: ch ++;
-    case 0x34: /* MCSPI_CHCTRL */
-        if (value & ~s->ch[ch].control & 1) {          /* EN */
-            s->ch[ch].control |= 1;
-            omap_mcspi_transfer_run(s, ch);
-        } else
-            s->ch[ch].control = value & 1;
-        break;
-
-    case 0x74: ch ++;
-    case 0x60: ch ++;
-    case 0x4c: ch ++;
-    case 0x38: /* MCSPI_TX */
-        s->ch[ch].tx = value;
-        s->ch[ch].status &= ~(1 << 1);                 /* TXS */
-        omap_mcspi_transfer_run(s, ch);
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-        return;
-    }
-}
-
-static CPUReadMemoryFunc * const omap_mcspi_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_mcspi_read,
-};
-
-static CPUWriteMemoryFunc * const omap_mcspi_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_mcspi_write,
-};
-
-struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum,
-                qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
-{
-    int iomemtype;
-    struct omap_mcspi_s *s = (struct omap_mcspi_s *)
-            qemu_mallocz(sizeof(struct omap_mcspi_s));
-    struct omap_mcspi_ch_s *ch = s->ch;
-
-    s->irq = irq;
-    s->chnum = chnum;
-    while (chnum --) {
-        ch->txdrq = *drq ++;
-        ch->rxdrq = *drq ++;
-        ch ++;
-    }
-    omap_mcspi_reset(s);
-
-    iomemtype = l4_register_io_memory(omap_mcspi_readfn,
-                    omap_mcspi_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
-
-    return s;
-}
-
-void omap_mcspi_attach(struct omap_mcspi_s *s,
-                uint32_t (*txrx)(void *opaque, uint32_t, int), void *opaque,
-                int chipselect)
-{
-    if (chipselect < 0 || chipselect >= s->chnum)
-        hw_error("%s: Bad chipselect %i\n", __FUNCTION__, chipselect);
-
-    s->ch[chipselect].txrx = txrx;
-    s->ch[chipselect].opaque = opaque;
-}
-
 /* Enhanced Audio Controller (CODEC only) */
 struct omap_eac_s {
     qemu_irq irq;
+    MemoryRegion iomem;
 
     uint16_t sysconfig;
     uint8_t config[4];
@@ -645,11 +324,16 @@ static void omap_eac_reset(struct omap_eac_s *s)
     omap_eac_interrupt_update(s);
 }
 
-static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_eac_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
     uint32_t ret;
 
+    if (size != 2) {
+        return omap_badwidth_read16(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:        /* CPCFR1 */
         return s->config[0];
@@ -757,10 +441,14 @@ static uint32_t omap_eac_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_eac_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_eac_s *s = (struct omap_eac_s *) opaque;
 
+    if (size != 2) {
+        return omap_badwidth_write16(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x098:        /* APD1LCR */
     case 0x09c:        /* APD1RCR */
@@ -896,24 +584,17 @@ static void omap_eac_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_eac_readfn[] = {
-    omap_badwidth_read16,
-    omap_eac_read,
-    omap_badwidth_read16,
+static const MemoryRegionOps omap_eac_ops = {
+    .read = omap_eac_read,
+    .write = omap_eac_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static CPUWriteMemoryFunc * const omap_eac_writefn[] = {
-    omap_badwidth_write16,
-    omap_eac_write,
-    omap_badwidth_write16,
-};
-
-struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
+static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
                 qemu_irq irq, qemu_irq *drq, omap_clk fclk, omap_clk iclk)
 {
-    int iomemtype;
     struct omap_eac_s *s = (struct omap_eac_s *)
-            qemu_mallocz(sizeof(struct omap_eac_s));
+            g_malloc0(sizeof(struct omap_eac_s));
 
     s->irq = irq;
     s->codec.rxdrq = *drq ++;
@@ -922,9 +603,9 @@ struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 
     AUD_register_card("OMAP EAC", &s->codec.card);
 
-    iomemtype = cpu_register_io_memory(omap_eac_readfn,
-                    omap_eac_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
@@ -932,6 +613,8 @@ struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
 /* STI/XTI (emulation interface) console - reverse engineered only */
 struct omap_sti_s {
     qemu_irq irq;
+    MemoryRegion iomem;
+    MemoryRegion iomem_fifo;
     CharDriverState *chr;
 
     uint32_t sysconfig;
@@ -961,10 +644,15 @@ static void omap_sti_reset(struct omap_sti_s *s)
     omap_sti_interrupt_update(s);
 }
 
-static uint32_t omap_sti_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sti_read(void *opaque, target_phys_addr_t addr,
+                              unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x00: /* STI_REVISION */
         return 0x10;
@@ -998,10 +686,14 @@ static uint32_t omap_sti_read(void *opaque, target_phys_addr_t addr)
 }
 
 static void omap_sti_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                           uint64_t value, unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x00: /* STI_REVISION */
     case 0x14: /* STI_SYSSTATUS / STI_RX_STATUS / XTI_SYSSTATUS */
@@ -1043,270 +735,78 @@ static void omap_sti_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sti_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_sti_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sti_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_sti_write,
+static const MemoryRegionOps omap_sti_ops = {
+    .read = omap_sti_read,
+    .write = omap_sti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static uint32_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_sti_fifo_read(void *opaque, target_phys_addr_t addr,
+                                   unsigned size)
 {
     OMAP_BAD_REG(addr);
     return 0;
 }
 
 static void omap_sti_fifo_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                                uint64_t value, unsigned size)
 {
     struct omap_sti_s *s = (struct omap_sti_s *) opaque;
     int ch = addr >> 6;
     uint8_t byte = value;
 
+    if (size != 1) {
+        return omap_badwidth_write8(opaque, addr, size);
+    }
+
     if (ch == STI_TRACE_CONTROL_CHANNEL) {
         /* Flush channel <i>value</i>.  */
-        qemu_chr_write(s->chr, (const uint8_t *) "\r", 1);
+        qemu_chr_fe_write(s->chr, (const uint8_t *) "\r", 1);
     } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
         if (value == 0xc0 || value == 0xc3) {
             /* Open channel <i>ch</i>.  */
         } else if (value == 0x00)
-            qemu_chr_write(s->chr, (const uint8_t *) "\n", 1);
+            qemu_chr_fe_write(s->chr, (const uint8_t *) "\n", 1);
         else
-            qemu_chr_write(s->chr, &byte, 1);
+            qemu_chr_fe_write(s->chr, &byte, 1);
     }
 }
 
-static CPUReadMemoryFunc * const omap_sti_fifo_readfn[] = {
-    omap_sti_fifo_read,
-    omap_badwidth_read8,
-    omap_badwidth_read8,
-};
-
-static CPUWriteMemoryFunc * const omap_sti_fifo_writefn[] = {
-    omap_sti_fifo_write,
-    omap_badwidth_write8,
-    omap_badwidth_write8,
+static const MemoryRegionOps omap_sti_fifo_ops = {
+    .read = omap_sti_fifo_read,
+    .write = omap_sti_fifo_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
+                MemoryRegion *sysmem,
                 target_phys_addr_t channel_base, qemu_irq irq, omap_clk clk,
                 CharDriverState *chr)
 {
-    int iomemtype;
     struct omap_sti_s *s = (struct omap_sti_s *)
-            qemu_mallocz(sizeof(struct omap_sti_s));
+            g_malloc0(sizeof(struct omap_sti_s));
 
     s->irq = irq;
     omap_sti_reset(s);
 
-    s->chr = chr ?: qemu_chr_open("null", "null", NULL);
+    s->chr = chr ?: qemu_chr_new("null", "null", NULL);
 
-    iomemtype = l4_register_io_memory(omap_sti_readfn,
-                    omap_sti_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
-    iomemtype = cpu_register_io_memory(omap_sti_fifo_readfn,
-                    omap_sti_fifo_writefn, s);
-    cpu_register_physical_memory(channel_base, 0x10000, iomemtype);
+    memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s,
+                          "omap.sti.fifo", 0x10000);
+    memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo);
 
     return s;
 }
 
 /* L4 Interconnect */
-struct omap_target_agent_s {
-    struct omap_l4_s *bus;
-    int regions;
-    struct omap_l4_region_s *start;
-    target_phys_addr_t base;
-    uint32_t component;
-    uint32_t control;
-    uint32_t status;
-};
-
-struct omap_l4_s {
-    target_phys_addr_t base;
-    int ta_num;
-    struct omap_target_agent_s ta[0];
-};
-
-#ifdef L4_MUX_HACK
-static int omap_l4_io_entries;
-static int omap_cpu_io_entry;
-static struct omap_l4_entry {
-        CPUReadMemoryFunc * const *mem_read;
-        CPUWriteMemoryFunc * const *mem_write;
-        void *opaque;
-} *omap_l4_io_entry;
-static CPUReadMemoryFunc * const *omap_l4_io_readb_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readh_fn;
-static CPUReadMemoryFunc * const *omap_l4_io_readw_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeb_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writeh_fn;
-static CPUWriteMemoryFunc * const *omap_l4_io_writew_fn;
-static void **omap_l4_io_opaque;
-
-int l4_register_io_memory(CPUReadMemoryFunc * const *mem_read,
-                CPUWriteMemoryFunc * const *mem_write, void *opaque)
-{
-    omap_l4_io_entry[omap_l4_io_entries].mem_read = mem_read;
-    omap_l4_io_entry[omap_l4_io_entries].mem_write = mem_write;
-    omap_l4_io_entry[omap_l4_io_entries].opaque = opaque;
-
-    return omap_l4_io_entries ++;
-}
-
-static uint32_t omap_l4_io_readb(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readb_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readh(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readh_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static uint32_t omap_l4_io_readw(void *opaque, target_phys_addr_t addr)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_readw_fn[i](omap_l4_io_opaque[i], addr);
-}
-
-static void omap_l4_io_writeb(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeb_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writeh(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writeh_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static void omap_l4_io_writew(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    unsigned int i = (addr - OMAP2_L4_BASE) >> TARGET_PAGE_BITS;
-
-    return omap_l4_io_writew_fn[i](omap_l4_io_opaque[i], addr, value);
-}
-
-static CPUReadMemoryFunc * const omap_l4_io_readfn[] = {
-    omap_l4_io_readb,
-    omap_l4_io_readh,
-    omap_l4_io_readw,
-};
-
-static CPUWriteMemoryFunc * const omap_l4_io_writefn[] = {
-    omap_l4_io_writeb,
-    omap_l4_io_writeh,
-    omap_l4_io_writew,
-};
-#endif
-
-struct omap_l4_s *omap_l4_init(target_phys_addr_t base, int ta_num)
-{
-    struct omap_l4_s *bus = qemu_mallocz(
-                    sizeof(*bus) + ta_num * sizeof(*bus->ta));
-
-    bus->ta_num = ta_num;
-    bus->base = base;
-
-#ifdef L4_MUX_HACK
-    omap_l4_io_entries = 1;
-    omap_l4_io_entry = qemu_mallocz(125 * sizeof(*omap_l4_io_entry));
-
-    omap_cpu_io_entry =
-            cpu_register_io_memory(omap_l4_io_readfn,
-                            omap_l4_io_writefn, bus);
-# define L4_PAGES      (0xb4000 / TARGET_PAGE_SIZE)
-    omap_l4_io_readb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_readw_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeb_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writeh_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_writew_fn = qemu_mallocz(sizeof(void *) * L4_PAGES);
-    omap_l4_io_opaque = qemu_mallocz(sizeof(void *) * L4_PAGES);
-#endif
-
-    return bus;
-}
-
-static uint32_t omap_l4ta_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-
-    switch (addr) {
-    case 0x00: /* COMPONENT */
-        return s->component;
-
-    case 0x20: /* AGENT_CONTROL */
-        return s->control;
-
-    case 0x28: /* AGENT_STATUS */
-        return s->status;
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_l4ta_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
-
-    switch (addr) {
-    case 0x00: /* COMPONENT */
-    case 0x28: /* AGENT_STATUS */
-        OMAP_RO_REG(addr);
-        break;
-
-    case 0x20: /* AGENT_CONTROL */
-        s->control = value & 0x01000700;
-        if (value & 1)                                 /* OCP_RESET */
-            s->status &= ~1;                           /* REQ_TIMEOUT */
-        break;
-
-    default:
-        OMAP_BAD_REG(addr);
-    }
-}
-
-static CPUReadMemoryFunc * const omap_l4ta_readfn[] = {
-    omap_badwidth_read16,
-    omap_l4ta_read,
-    omap_badwidth_read16,
-};
-
-static CPUWriteMemoryFunc * const omap_l4ta_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_l4ta_write,
-};
-
 #define L4TA(n)                (n)
 #define L4TAO(n)       ((n) + 39)
 
-static struct omap_l4_region_s {
-    target_phys_addr_t offset;
-    size_t size;
-    int access;
-} omap_l4_region[125] = {
+static const struct omap_l4_region_s omap_l4_region[125] = {
     [  1] = { 0x40800,  0x800, 32          }, /* Initiator agent */
     [  2] = { 0x41000, 0x1000, 32          }, /* Link agent */
     [  0] = { 0x40000,  0x800, 32          }, /* Address and protection */
@@ -1434,12 +934,7 @@ static struct omap_l4_region_s {
     [124] = { 0xb3000, 0x1000, 32 | 16 | 8 }, /* L4TA39 */
 };
 
-static struct omap_l4_agent_info_s {
-    int ta;
-    int region;
-    int regions;
-    int ta_region;
-} omap_l4_agent_info[54] = {
+static const struct omap_l4_agent_info_s omap_l4_agent_info[54] = {
     { 0,           0, 3, 2 }, /* L4IA initiatior agent */
     { L4TAO(1),    3, 2, 1 }, /* Control and pinout module */
     { L4TAO(2),    5, 2, 1 }, /* 32K timer */
@@ -1496,172 +991,17 @@ static struct omap_l4_agent_info_s {
     { L4TA(39),  123, 2, 1 }, /* HDQ/1-Wire */
 };
 
-#define omap_l4ta(bus, cs)     omap_l4ta_get(bus, L4TA(cs))
-#define omap_l4tao(bus, cs)    omap_l4ta_get(bus, L4TAO(cs))
-
-struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, int cs)
-{
-    int i, iomemtype;
-    struct omap_target_agent_s *ta = NULL;
-    struct omap_l4_agent_info_s *info = NULL;
-
-    for (i = 0; i < bus->ta_num; i ++)
-        if (omap_l4_agent_info[i].ta == cs) {
-            ta = &bus->ta[i];
-            info = &omap_l4_agent_info[i];
-            break;
-        }
-    if (!ta) {
-        fprintf(stderr, "%s: bad target agent (%i)\n", __FUNCTION__, cs);
-        exit(-1);
-    }
-
-    ta->bus = bus;
-    ta->start = &omap_l4_region[info->region];
-    ta->regions = info->regions;
-
-    ta->component = ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    ta->status = 0x00000000;
-    ta->control = 0x00000200;  /* XXX 01000200 for L4TAO */
-
-    iomemtype = l4_register_io_memory(omap_l4ta_readfn,
-                    omap_l4ta_writefn, ta);
-    ta->base = omap_l4_attach(ta, info->ta_region, iomemtype);
-
-    return ta;
-}
-
-target_phys_addr_t omap_l4_attach(struct omap_target_agent_s *ta, int region,
-                int iotype)
-{
-    target_phys_addr_t base;
-    ssize_t size;
-#ifdef L4_MUX_HACK
-    int i;
-#endif
-
-    if (region < 0 || region >= ta->regions) {
-        fprintf(stderr, "%s: bad io region (%i)\n", __FUNCTION__, region);
-        exit(-1);
-    }
-
-    base = ta->bus->base + ta->start[region].offset;
-    size = ta->start[region].size;
-    if (iotype) {
-#ifndef L4_MUX_HACK
-        cpu_register_physical_memory(base, size, iotype);
-#else
-        cpu_register_physical_memory(base, size, omap_cpu_io_entry);
-        i = (base - ta->bus->base) / TARGET_PAGE_SIZE;
-        for (; size > 0; size -= TARGET_PAGE_SIZE, i ++) {
-            omap_l4_io_readb_fn[i] = omap_l4_io_entry[iotype].mem_read[0];
-            omap_l4_io_readh_fn[i] = omap_l4_io_entry[iotype].mem_read[1];
-            omap_l4_io_readw_fn[i] = omap_l4_io_entry[iotype].mem_read[2];
-            omap_l4_io_writeb_fn[i] = omap_l4_io_entry[iotype].mem_write[0];
-            omap_l4_io_writeh_fn[i] = omap_l4_io_entry[iotype].mem_write[1];
-            omap_l4_io_writew_fn[i] = omap_l4_io_entry[iotype].mem_write[2];
-            omap_l4_io_opaque[i] = omap_l4_io_entry[iotype].opaque;
-        }
-#endif
-    }
-
-    return base;
-}
-
-/* TEST-Chip-level TAP */
-static uint32_t omap_tap_read(void *opaque, target_phys_addr_t addr)
-{
-    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
-
-    switch (addr) {
-    case 0x204:        /* IDCODE_reg */
-        switch (s->mpu_model) {
-        case omap2420:
-        case omap2422:
-        case omap2423:
-            return 0x5b5d902f; /* ES 2.2 */
-        case omap2430:
-            return 0x5b68a02f; /* ES 2.2 */
-        case omap3430:
-            return 0x1b7ae02f; /* ES 2 */
-        default:
-            hw_error("%s: Bad mpu model\n", __FUNCTION__);
-        }
-
-    case 0x208:        /* PRODUCTION_ID_reg for OMAP2 */
-    case 0x210:        /* PRODUCTION_ID_reg for OMAP3 */
-        switch (s->mpu_model) {
-        case omap2420:
-            return 0x000254f0; /* POP ESHS2.1.1 in N91/93/95, ES2 in N800 */
-        case omap2422:
-            return 0x000400f0;
-        case omap2423:
-            return 0x000800f0;
-        case omap2430:
-            return 0x000000f0;
-        case omap3430:
-            return 0x000000f0;
-        default:
-            hw_error("%s: Bad mpu model\n", __FUNCTION__);
-        }
-
-    case 0x20c:
-        switch (s->mpu_model) {
-        case omap2420:
-        case omap2422:
-        case omap2423:
-            return 0xcafeb5d9; /* ES 2.2 */
-        case omap2430:
-            return 0xcafeb68a; /* ES 2.2 */
-        case omap3430:
-            return 0xcafeb7ae; /* ES 2 */
-        default:
-            hw_error("%s: Bad mpu model\n", __FUNCTION__);
-        }
-
-    case 0x218:        /* DIE_ID_reg */
-        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    case 0x21c:        /* DIE_ID_reg */
-        return 0x54 << 24;
-    case 0x220:        /* DIE_ID_reg */
-        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    case 0x224:        /* DIE_ID_reg */
-        return ('Q' << 24) | ('E' << 16) | ('M' << 8) | ('U' << 0);
-    }
-
-    OMAP_BAD_REG(addr);
-    return 0;
-}
-
-static void omap_tap_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
-{
-    OMAP_BAD_REG(addr);
-}
-
-static CPUReadMemoryFunc * const omap_tap_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_tap_read,
-};
-
-static CPUWriteMemoryFunc * const omap_tap_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_tap_write,
-};
-
-void omap_tap_init(struct omap_target_agent_s *ta,
-                struct omap_mpu_state_s *mpu)
-{
-    omap_l4_attach(ta, 0, l4_register_io_memory(
-                            omap_tap_readfn, omap_tap_writefn, mpu));
-}
+#define omap_l4ta(bus, cs)     \
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TA(cs))
+#define omap_l4tao(bus, cs)    \
+    omap_l4ta_get(bus, omap_l4_region, omap_l4_agent_info, L4TAO(cs))
 
 /* Power, Reset, and Clock Management */
 struct omap_prcm_s {
     qemu_irq irq[3];
     struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem0;
+    MemoryRegion iomem1;
 
     uint32_t irqst[3];
     uint32_t irqen[3];
@@ -1700,11 +1040,16 @@ static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
     /* XXX or is the mask applied before PRCM_IRQSTATUS_* ? */
 }
 
-static uint32_t omap_prcm_read(void *opaque, target_phys_addr_t addr)
+static uint64_t omap_prcm_read(void *opaque, target_phys_addr_t addr,
+                               unsigned size)
 {
     struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
     uint32_t ret;
 
+    if (size != 4) {
+        return omap_badwidth_read32(opaque, addr);
+    }
+
     switch (addr) {
     case 0x000:        /* PRCM_REVISION */
         return 0x10;
@@ -2008,10 +1353,14 @@ static void omap_prcm_dpll_update(struct omap_prcm_s *s)
 }
 
 static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
-                uint32_t value)
+                            uint64_t value, unsigned size)
 {
     struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
 
+    if (size != 4) {
+        return omap_badwidth_write32(opaque, addr, value);
+    }
+
     switch (addr) {
     case 0x000:        /* PRCM_REVISION */
     case 0x054:        /* PRCM_VOLTST */
@@ -2267,7 +1616,7 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     case 0x500:        /* CM_CLKEN_PLL */
         if (value & 0xffffff30)
             fprintf(stderr, "%s: write 0s in CM_CLKEN_PLL for "
-                            "future compatiblity\n", __FUNCTION__);
+                            "future compatibility\n", __FUNCTION__);
         if ((s->clken[9] ^ value) & 0xcc) {
             s->clken[9] &= ~0xcc;
             s->clken[9] |= value & 0xcc;
@@ -2286,7 +1635,7 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     case 0x540:        /* CM_CLKSEL1_PLL */
         if (value & 0xfc4000d7)
             fprintf(stderr, "%s: write 0s in CM_CLKSEL1_PLL for "
-                            "future compatiblity\n", __FUNCTION__);
+                            "future compatibility\n", __FUNCTION__);
         if ((s->clksel[5] ^ value) & 0x003fff00) {
             s->clksel[5] = value & 0x03bfff28;
             omap_prcm_dpll_update(s);
@@ -2298,7 +1647,7 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     case 0x544:        /* CM_CLKSEL2_PLL */
         if (value & ~3)
             fprintf(stderr, "%s: write 0s in CM_CLKSEL2_PLL[31:2] for "
-                            "future compatiblity\n", __FUNCTION__);
+                            "future compatibility\n", __FUNCTION__);
         if (s->clksel[6] != (value & 3)) {
             s->clksel[6] = value & 3;
             omap_prcm_dpll_update(s);
@@ -2361,16 +1710,10 @@ static void omap_prcm_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_prcm_readfn[] = {
-    omap_badwidth_read32,
-    omap_badwidth_read32,
-    omap_prcm_read,
-};
-
-static CPUWriteMemoryFunc * const omap_prcm_writefn[] = {
-    omap_badwidth_write32,
-    omap_badwidth_write32,
-    omap_prcm_write,
+static const MemoryRegionOps omap_prcm_ops = {
+    .read = omap_prcm_read,
+    .write = omap_prcm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_prcm_reset(struct omap_prcm_s *s)
@@ -2453,13 +1796,12 @@ static void omap_prcm_coldreset(struct omap_prcm_s *s)
     omap_prcm_reset(s);
 }
 
-struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
+static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
                 qemu_irq mpu_int, qemu_irq dsp_int, qemu_irq iva_int,
                 struct omap_mpu_state_s *mpu)
 {
-    int iomemtype;
     struct omap_prcm_s *s = (struct omap_prcm_s *)
-            qemu_mallocz(sizeof(struct omap_prcm_s));
+            g_malloc0(sizeof(struct omap_prcm_s));
 
     s->irq[0] = mpu_int;
     s->irq[1] = dsp_int;
@@ -2467,10 +1809,12 @@ struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
     s->mpu = mpu;
     omap_prcm_coldreset(s);
 
-    iomemtype = l4_register_io_memory(omap_prcm_readfn,
-                    omap_prcm_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
-    omap_l4_attach(ta, 1, iomemtype);
+    memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0",
+                          omap_l4_region_size(ta, 0));
+    memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1",
+                          omap_l4_region_size(ta, 1));
+    omap_l4_attach(ta, 0, &s->iomem0);
+    omap_l4_attach(ta, 1, &s->iomem1);
 
     return s;
 }
@@ -2478,6 +1822,7 @@ struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta,
 /* System and Pinout control */
 struct omap_sysctl_s {
     struct omap_mpu_state_s *mpu;
+    MemoryRegion iomem;
 
     uint32_t sysconfig;
     uint32_t devconfig;
@@ -2731,16 +2076,20 @@ static void omap_sysctl_write(void *opaque, target_phys_addr_t addr,
     }
 }
 
-static CPUReadMemoryFunc * const omap_sysctl_readfn[] = {
-    omap_sysctl_read8,
-    omap_badwidth_read32,      /* TODO */
-    omap_sysctl_read,
-};
-
-static CPUWriteMemoryFunc * const omap_sysctl_writefn[] = {
-    omap_sysctl_write8,
-    omap_badwidth_write32,     /* TODO */
-    omap_sysctl_write,
+static const MemoryRegionOps omap_sysctl_ops = {
+    .old_mmio = {
+        .read = {
+            omap_sysctl_read8,
+            omap_badwidth_read32,      /* TODO */
+            omap_sysctl_read,
+        },
+        .write = {
+            omap_sysctl_write8,
+            omap_badwidth_write32,     /* TODO */
+            omap_sysctl_write,
+        },
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
 static void omap_sysctl_reset(struct omap_sysctl_s *s)
@@ -2827,19 +2176,18 @@ static void omap_sysctl_reset(struct omap_sysctl_s *s)
     s->padconf[0x44] = 0x00000800;
 }
 
-struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
+static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
                 omap_clk iclk, struct omap_mpu_state_s *mpu)
 {
-    int iomemtype;
     struct omap_sysctl_s *s = (struct omap_sysctl_s *)
-            qemu_mallocz(sizeof(struct omap_sysctl_s));
+            g_malloc0(sizeof(struct omap_sysctl_s));
 
     s->mpu = mpu;
     omap_sysctl_reset(s);
 
-    iomemtype = l4_register_io_memory(omap_sysctl_readfn,
-                    omap_sysctl_writefn, s);
-    omap_l4_attach(ta, 0, iomemtype);
+    memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl",
+                          omap_l4_region_size(ta, 0));
+    omap_l4_attach(ta, 0, &s->iomem);
 
     return s;
 }
@@ -2849,7 +2197,6 @@ static void omap2_mpu_reset(void *opaque)
 {
     struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
 
-    omap_inth_reset(mpu->ih[0]);
     omap_dma_reset(mpu->dma);
     omap_prcm_reset(mpu->prcm);
     omap_sysctl_reset(mpu->sysc);
@@ -2873,7 +2220,6 @@ static void omap2_mpu_reset(void *opaque)
     omap_uart_reset(mpu->uart[1]);
     omap_uart_reset(mpu->uart[2]);
     omap_mmc_reset(mpu->mmc);
-    omap_gpif_reset(mpu->gpif);
     omap_mcspi_reset(mpu->mcspi[0]);
     omap_mcspi_reset(mpu->mcspi[1]);
     omap_i2c_reset(mpu->i2c[0]);
@@ -2894,17 +2240,18 @@ static const struct dma_irq_map omap2_dma_irq_map[] = {
     { 0, OMAP_INT_24XX_SDMA_IRQ3 },
 };
 
-struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
+struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem,
+                unsigned long sdram_size,
                 const char *core)
 {
     struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
-            qemu_mallocz(sizeof(struct omap_mpu_state_s));
-    ram_addr_t sram_base, q2_base;
+            g_malloc0(sizeof(struct omap_mpu_state_s));
     qemu_irq *cpu_irq;
     qemu_irq dma_irqs[4];
-    omap_clk gpio_clks[4];
     DriveInfo *dinfo;
     int i;
+    SysBusDevice *busdev;
+    struct omap_target_agent_s *ta;
 
     /* Core */
     s->mpu_model = omap2420;
@@ -2922,105 +2269,123 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
     omap_clk_init(s);
 
     /* Memory-mapped stuff */
-    cpu_register_physical_memory(OMAP2_Q2_BASE, s->sdram_size,
-                    (q2_base = qemu_ram_alloc(s->sdram_size)) | IO_MEM_RAM);
-    cpu_register_physical_memory(OMAP2_SRAM_BASE, s->sram_size,
-                    (sram_base = qemu_ram_alloc(s->sram_size)) | IO_MEM_RAM);
+    memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size);
+    vmstate_register_ram_global(&s->sdram);
+    memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram);
+    memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size);
+    vmstate_register_ram_global(&s->sram);
+    memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram);
 
-    s->l4 = omap_l4_init(OMAP2_L4_BASE, 54);
+    s->l4 = omap_l4_init(sysmem, OMAP2_L4_BASE, 54);
 
     /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */
     cpu_irq = arm_pic_init_cpu(s->env);
-    s->ih[0] = omap2_inth_init(0x480fe000, 0x1000, 3, &s->irq[0],
-                    cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ],
-                    omap_findclk(s, "mpu_intc_fclk"),
-                    omap_findclk(s, "mpu_intc_iclk"));
-
+    s->ih[0] = qdev_create(NULL, "omap2-intc");
+    qdev_prop_set_uint8(s->ih[0], "revision", 0x21);
+    qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk"));
+    qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk"));
+    qdev_init_nofail(s->ih[0]);
+    busdev = sysbus_from_qdev(s->ih[0]);
+    sysbus_connect_irq(busdev, 0, cpu_irq[ARM_PIC_CPU_IRQ]);
+    sysbus_connect_irq(busdev, 1, cpu_irq[ARM_PIC_CPU_FIQ]);
+    sysbus_mmio_map(busdev, 0, 0x480fe000);
     s->prcm = omap_prcm_init(omap_l4tao(s->l4, 3),
-                    s->irq[0][OMAP_INT_24XX_PRCM_MPU_IRQ], NULL, NULL, s);
+                             qdev_get_gpio_in(s->ih[0],
+                                              OMAP_INT_24XX_PRCM_MPU_IRQ),
+                             NULL, NULL, s);
 
     s->sysc = omap_sysctl_init(omap_l4tao(s->l4, 1),
                     omap_findclk(s, "omapctrl_iclk"), s);
 
-    for (i = 0; i < 4; i ++)
-        dma_irqs[i] =
-                s->irq[omap2_dma_irq_map[i].ih][omap2_dma_irq_map[i].intr];
-    s->dma = omap_dma4_init(0x48056000, dma_irqs, s, 256, 32,
+    for (i = 0; i < 4; i++) {
+        dma_irqs[i] = qdev_get_gpio_in(s->ih[omap2_dma_irq_map[i].ih],
+                                       omap2_dma_irq_map[i].intr);
+    }
+    s->dma = omap_dma4_init(0x48056000, dma_irqs, sysmem, s, 256, 32,
                     omap_findclk(s, "sdma_iclk"),
                     omap_findclk(s, "sdma_fclk"));
     s->port->addr_valid = omap2_validate_addr;
 
     /* Register SDRAM and SRAM ports for fast DMA transfers.  */
-    soc_dma_port_add_mem_ram(s->dma, q2_base, OMAP2_Q2_BASE, s->sdram_size);
-    soc_dma_port_add_mem_ram(s->dma, sram_base, OMAP2_SRAM_BASE, s->sram_size);
-
-    s->uart[0] = omap2_uart_init(omap_l4ta(s->l4, 19),
-                    s->irq[0][OMAP_INT_24XX_UART1_IRQ],
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sdram),
+                         OMAP2_Q2_BASE, s->sdram_size);
+    soc_dma_port_add_mem(s->dma, memory_region_get_ram_ptr(&s->sram),
+                         OMAP2_SRAM_BASE, s->sram_size);
+
+    s->uart[0] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 19),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART1_IRQ),
                     omap_findclk(s, "uart1_fclk"),
                     omap_findclk(s, "uart1_iclk"),
                     s->drq[OMAP24XX_DMA_UART1_TX],
-                    s->drq[OMAP24XX_DMA_UART1_RX], serial_hds[0]);
-    s->uart[1] = omap2_uart_init(omap_l4ta(s->l4, 20),
-                    s->irq[0][OMAP_INT_24XX_UART2_IRQ],
+                    s->drq[OMAP24XX_DMA_UART1_RX],
+                    "uart1",
+                    serial_hds[0]);
+    s->uart[1] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 20),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART2_IRQ),
                     omap_findclk(s, "uart2_fclk"),
                     omap_findclk(s, "uart2_iclk"),
                     s->drq[OMAP24XX_DMA_UART2_TX],
                     s->drq[OMAP24XX_DMA_UART2_RX],
+                    "uart2",
                     serial_hds[0] ? serial_hds[1] : NULL);
-    s->uart[2] = omap2_uart_init(omap_l4ta(s->l4, 21),
-                    s->irq[0][OMAP_INT_24XX_UART3_IRQ],
+    s->uart[2] = omap2_uart_init(sysmem, omap_l4ta(s->l4, 21),
+                                 qdev_get_gpio_in(s->ih[0],
+                                                  OMAP_INT_24XX_UART3_IRQ),
                     omap_findclk(s, "uart3_fclk"),
                     omap_findclk(s, "uart3_iclk"),
                     s->drq[OMAP24XX_DMA_UART3_TX],
                     s->drq[OMAP24XX_DMA_UART3_RX],
+                    "uart3",
                     serial_hds[0] && serial_hds[1] ? serial_hds[2] : NULL);
 
     s->gptimer[0] = omap_gp_timer_init(omap_l4ta(s->l4, 7),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER1],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER1),
                     omap_findclk(s, "wu_gpt1_clk"),
                     omap_findclk(s, "wu_l4_iclk"));
     s->gptimer[1] = omap_gp_timer_init(omap_l4ta(s->l4, 8),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER2],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER2),
                     omap_findclk(s, "core_gpt2_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[2] = omap_gp_timer_init(omap_l4ta(s->l4, 22),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER3],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER3),
                     omap_findclk(s, "core_gpt3_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[3] = omap_gp_timer_init(omap_l4ta(s->l4, 23),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER4],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER4),
                     omap_findclk(s, "core_gpt4_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[4] = omap_gp_timer_init(omap_l4ta(s->l4, 24),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER5],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER5),
                     omap_findclk(s, "core_gpt5_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[5] = omap_gp_timer_init(omap_l4ta(s->l4, 25),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER6],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER6),
                     omap_findclk(s, "core_gpt6_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[6] = omap_gp_timer_init(omap_l4ta(s->l4, 26),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER7],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER7),
                     omap_findclk(s, "core_gpt7_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[7] = omap_gp_timer_init(omap_l4ta(s->l4, 27),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER8],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER8),
                     omap_findclk(s, "core_gpt8_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[8] = omap_gp_timer_init(omap_l4ta(s->l4, 28),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER9],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER9),
                     omap_findclk(s, "core_gpt9_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[9] = omap_gp_timer_init(omap_l4ta(s->l4, 29),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER10],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER10),
                     omap_findclk(s, "core_gpt10_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[10] = omap_gp_timer_init(omap_l4ta(s->l4, 30),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER11],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER11),
                     omap_findclk(s, "core_gpt11_clk"),
                     omap_findclk(s, "core_l4_iclk"));
     s->gptimer[11] = omap_gp_timer_init(omap_l4ta(s->l4, 31),
-                    s->irq[0][OMAP_INT_24XX_GPTIMER12],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPTIMER12),
                     omap_findclk(s, "core_gpt12_clk"),
                     omap_findclk(s, "core_l4_iclk"));
 
@@ -3031,26 +2396,52 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
                     omap_findclk(s, "core_l4_iclk"));
 
     s->i2c[0] = omap2_i2c_init(omap_l4tao(s->l4, 5),
-                    s->irq[0][OMAP_INT_24XX_I2C1_IRQ],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C1_IRQ),
                     &s->drq[OMAP24XX_DMA_I2C1_TX],
                     omap_findclk(s, "i2c1.fclk"),
                     omap_findclk(s, "i2c1.iclk"));
     s->i2c[1] = omap2_i2c_init(omap_l4tao(s->l4, 6),
-                    s->irq[0][OMAP_INT_24XX_I2C2_IRQ],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_I2C2_IRQ),
                     &s->drq[OMAP24XX_DMA_I2C2_TX],
                     omap_findclk(s, "i2c2.fclk"),
                     omap_findclk(s, "i2c2.iclk"));
 
-    gpio_clks[0] = omap_findclk(s, "gpio1_dbclk");
-    gpio_clks[1] = omap_findclk(s, "gpio2_dbclk");
-    gpio_clks[2] = omap_findclk(s, "gpio3_dbclk");
-    gpio_clks[3] = omap_findclk(s, "gpio4_dbclk");
-    s->gpif = omap2_gpio_init(omap_l4ta(s->l4, 3),
-                    &s->irq[0][OMAP_INT_24XX_GPIO_BANK1],
-                    gpio_clks, omap_findclk(s, "gpio_iclk"), 4);
-
-    s->sdrc = omap_sdrc_init(0x68009000);
-    s->gpmc = omap_gpmc_init(0x6800a000, s->irq[0][OMAP_INT_24XX_GPMC_IRQ]);
+    s->gpio = qdev_create(NULL, "omap2-gpio");
+    qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model);
+    qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk"));
+    qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk"));
+    if (s->mpu_model == omap2430) {
+        qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk"));
+    }
+    qdev_init_nofail(s->gpio);
+    busdev = sysbus_from_qdev(s->gpio);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK1));
+    sysbus_connect_irq(busdev, 3,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK2));
+    sysbus_connect_irq(busdev, 6,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK3));
+    sysbus_connect_irq(busdev, 9,
+                       qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPIO_BANK4));
+    if (s->mpu_model == omap2430) {
+        sysbus_connect_irq(busdev, 12,
+                           qdev_get_gpio_in(s->ih[0],
+                                            OMAP_INT_243X_GPIO_BANK5));
+    }
+    ta = omap_l4ta(s->l4, 3);
+    sysbus_mmio_map(busdev, 0, omap_l4_region_base(ta, 1));
+    sysbus_mmio_map(busdev, 1, omap_l4_region_base(ta, 0));
+    sysbus_mmio_map(busdev, 2, omap_l4_region_base(ta, 2));
+    sysbus_mmio_map(busdev, 3, omap_l4_region_base(ta, 4));
+    sysbus_mmio_map(busdev, 4, omap_l4_region_base(ta, 5));
+
+    s->sdrc = omap_sdrc_init(sysmem, 0x68009000);
+    s->gpmc = omap_gpmc_init(s, 0x6800a000,
+                             qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_GPMC_IRQ),
+                             s->drq[OMAP24XX_DMA_GPMC]);
 
     dinfo = drive_get(IF_SD, 0, 0);
     if (!dinfo) {
@@ -3058,36 +2449,38 @@ struct omap_mpu_state_s *omap2420_mpu_init(unsigned long sdram_size,
         exit(1);
     }
     s->mmc = omap2_mmc_init(omap_l4tao(s->l4, 9), dinfo->bdrv,
-                    s->irq[0][OMAP_INT_24XX_MMC_IRQ],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MMC_IRQ),
                     &s->drq[OMAP24XX_DMA_MMC1_TX],
                     omap_findclk(s, "mmc_fclk"), omap_findclk(s, "mmc_iclk"));
 
     s->mcspi[0] = omap_mcspi_init(omap_l4ta(s->l4, 35), 4,
-                    s->irq[0][OMAP_INT_24XX_MCSPI1_IRQ],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI1_IRQ),
                     &s->drq[OMAP24XX_DMA_SPI1_TX0],
                     omap_findclk(s, "spi1_fclk"),
                     omap_findclk(s, "spi1_iclk"));
     s->mcspi[1] = omap_mcspi_init(omap_l4ta(s->l4, 36), 2,
-                    s->irq[0][OMAP_INT_24XX_MCSPI2_IRQ],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_MCSPI2_IRQ),
                     &s->drq[OMAP24XX_DMA_SPI2_TX0],
                     omap_findclk(s, "spi2_fclk"),
                     omap_findclk(s, "spi2_iclk"));
 
-    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), 0x68000800,
+    s->dss = omap_dss_init(omap_l4ta(s->l4, 10), sysmem, 0x68000800,
                     /* XXX wire M_IRQ_25, D_L2_IRQ_30 and I_IRQ_13 together */
-                    s->irq[0][OMAP_INT_24XX_DSS_IRQ], s->drq[OMAP24XX_DMA_DSS],
+                    qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_DSS_IRQ),
+                           s->drq[OMAP24XX_DMA_DSS],
                     omap_findclk(s, "dss_clk1"), omap_findclk(s, "dss_clk2"),
                     omap_findclk(s, "dss_54m_clk"),
                     omap_findclk(s, "dss_l3_iclk"),
                     omap_findclk(s, "dss_l4_iclk"));
 
-    omap_sti_init(omap_l4ta(s->l4, 18), 0x54000000,
-                    s->irq[0][OMAP_INT_24XX_STI], omap_findclk(s, "emul_ck"),
+    omap_sti_init(omap_l4ta(s->l4, 18), sysmem, 0x54000000,
+                  qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_STI),
+                  omap_findclk(s, "emul_ck"),
                     serial_hds[0] && serial_hds[1] && serial_hds[2] ?
                     serial_hds[3] : NULL);
 
     s->eac = omap_eac_init(omap_l4ta(s->l4, 32),
-                    s->irq[0][OMAP_INT_24XX_EAC_IRQ],
+                           qdev_get_gpio_in(s->ih[0], OMAP_INT_24XX_EAC_IRQ),
                     /* Ten consecutive lines */
                     &s->drq[OMAP24XX_DMA_EAC_AC_RD],
                     omap_findclk(s, "func_96m_clk"),