Merge commit 'gnu/master' into test
[qemu] / hw / mpcore.c
index 1d5fcc7..a5eddd9 100644 (file)
@@ -7,9 +7,8 @@
  * This code is licenced under the GPL.
  */
 
-#include "hw.h"
+#include "sysbus.h"
 #include "qemu-timer.h"
-#include "primecell.h"
 
 #define MPCORE_PRIV_BASE  0x10100000
 #define NCPU 4
@@ -41,8 +40,9 @@ typedef struct {
 } mpcore_timer_state;
 
 typedef struct mpcore_priv_state {
-    gic_state *gic;
+    gic_state gic;
     uint32_t scu_control;
+    int iomemtype;
     mpcore_timer_state timer[8];
 } mpcore_priv_state;
 
@@ -51,7 +51,7 @@ typedef struct mpcore_priv_state {
 static inline void mpcore_timer_update_irq(mpcore_timer_state *s)
 {
     if (s->status & ~s->old_status) {
-        gic_set_pending_private(s->mpcore->gic, s->id >> 1, 29 + (s->id & 1));
+        gic_set_pending_private(&s->mpcore->gic, s->id >> 1, 29 + (s->id & 1));
     }
     s->old_status = s->status;
 }
@@ -181,7 +181,7 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
         } else {
             id = (offset - 0x200) >> 8;
         }
-        return gic_cpu_read(s->gic, id, offset & 0xff);
+        return gic_cpu_read(&s->gic, id, offset & 0xff);
     } else if (offset < 0xb00) {
         /* Timers.  */
         if (offset < 0x700) {
@@ -195,8 +195,7 @@ static uint32_t mpcore_priv_read(void *opaque, target_phys_addr_t offset)
         return mpcore_timer_read(&s->timer[id], offset & 0xf);
     }
 bad_reg:
-    cpu_abort(cpu_single_env, "mpcore_priv_read: Bad offset %x\n",
-              (int)offset);
+    hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
     return 0;
 }
 
@@ -225,7 +224,7 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
         } else {
             id = (offset - 0x200) >> 8;
         }
-        gic_cpu_write(s->gic, id, offset & 0xff, value);
+        gic_cpu_write(&s->gic, id, offset & 0xff, value);
     } else if (offset < 0xb00) {
         /* Timers.  */
         if (offset < 0x700) {
@@ -241,8 +240,7 @@ static void mpcore_priv_write(void *opaque, target_phys_addr_t offset,
     }
     return;
 bad_reg:
-    cpu_abort(cpu_single_env, "mpcore_priv_read: Bad offset %x\n",
-              (int)offset);
+    hw_error("mpcore_priv_read: Bad offset %x\n", (int)offset);
 }
 
 static CPUReadMemoryFunc *mpcore_priv_readfn[] = {
@@ -257,32 +255,34 @@ static CPUWriteMemoryFunc *mpcore_priv_writefn[] = {
    mpcore_priv_write
 };
 
+static void mpcore_priv_map(SysBusDevice *dev, target_phys_addr_t base)
+{
+    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
+    cpu_register_physical_memory(base, 0x1000, s->iomemtype);
+    cpu_register_physical_memory(base + 0x1000, 0x1000, s->gic.iomemtype);
+}
 
-static qemu_irq *mpcore_priv_init(uint32_t base, qemu_irq *pic_irq)
+static void mpcore_priv_init(SysBusDevice *dev)
 {
-    mpcore_priv_state *s;
-    int iomemtype;
+    mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
     int i;
 
-    s = (mpcore_priv_state *)qemu_mallocz(sizeof(mpcore_priv_state));
-    s->gic = gic_init(base + 0x1000, pic_irq);
-    if (!s->gic)
-        return NULL;
-    iomemtype = cpu_register_io_memory(0, mpcore_priv_readfn,
-                                       mpcore_priv_writefn, s);
-    cpu_register_physical_memory(base, 0x00001000, iomemtype);
+    gic_init(&s->gic);
+    s->iomemtype = cpu_register_io_memory(0, mpcore_priv_readfn,
+                                          mpcore_priv_writefn, s);
+    sysbus_init_mmio_cb(dev, 0x2000, mpcore_priv_map);
     for (i = 0; i < 8; i++) {
         mpcore_timer_init(s, &s->timer[i], i);
     }
-    return s->gic->in;
 }
 
 /* Dummy PIC to route IRQ lines.  The baseboard has 4 independent IRQ
    controllers.  The output of these, plus some of the raw input lines
    are fed into a single SMP-aware interrupt controller on the CPU.  */
 typedef struct {
-    qemu_irq *cpuic;
-    qemu_irq *rvic[4];
+    SysBusDevice busdev;
+    qemu_irq cpuic[32];
+    qemu_irq rvic[4][64];
 } mpcore_rirq_state;
 
 /* Map baseboard IRQs onto CPU IRQ lines.  */
@@ -309,17 +309,36 @@ static void mpcore_rirq_set_irq(void *opaque, int irq, int level)
     }
 }
 
-qemu_irq *mpcore_irq_init(qemu_irq *cpu_irq)
+static void realview_mpcore_init(SysBusDevice *dev)
 {
-    mpcore_rirq_state *s;
+    mpcore_rirq_state *s = FROM_SYSBUS(mpcore_rirq_state, dev);
+    DeviceState *gic;
+    DeviceState *priv;
     int n;
+    int i;
 
+    priv = sysbus_create_simple("arm11mpcore_priv", MPCORE_PRIV_BASE, NULL);
+    sysbus_pass_irq(dev, sysbus_from_qdev(priv));
+    for (i = 0; i < 32; i++) {
+        s->cpuic[i] = qdev_get_gpio_in(priv, i);
+    }
     /* ??? IRQ routing is hardcoded to "normal" mode.  */
-    s = qemu_mallocz(sizeof(mpcore_rirq_state));
-    s->cpuic = mpcore_priv_init(MPCORE_PRIV_BASE, cpu_irq);
     for (n = 0; n < 4; n++) {
-        s->rvic[n] = realview_gic_init(0x10040000 + n * 0x10000,
-                                       s->cpuic[10 + n]);
+        gic = sysbus_create_simple("realview_gic", 0x10040000 + n * 0x10000,
+                                   s->cpuic[10 + n]);
+        for (i = 0; i < 64; i++) {
+            s->rvic[n][i] = qdev_get_gpio_in(gic, i);
+        }
     }
-    return qemu_allocate_irqs(mpcore_rirq_set_irq, s, 64);
+    qdev_init_gpio_in(&dev->qdev, mpcore_rirq_set_irq, 64);
 }
+
+static void mpcore_register_devices(void)
+{
+    sysbus_register_dev("realview_mpcore", sizeof(mpcore_rirq_state),
+                        realview_mpcore_init);
+    sysbus_register_dev("arm11mpcore_priv", sizeof(mpcore_priv_state),
+                        mpcore_priv_init);
+}
+
+device_init(mpcore_register_devices)