All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
@ 2015-12-24  0:25 Andrew Baumann
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes Andrew Baumann
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

This patch series adds initial support for Raspberry Pi 2
(bcm2836). It is heavily based on the original (out of tree) work of
Gregory Estrade, Stefan Weil and others to support Raspberry Pi 1.

At the end of this series, it is possible to boot a recent raspbian
kernel to a serial console using an invocation such as:

  qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd
  2015-09-24-raspbian-jessie.vhd -append "rw earlyprintk loglevel=8
  console=ttyAMA0 root=/dev/mmcblk0p2" -serial stdio

(where raspbian-boot is the boot partition from the matching image,
and after commenting-out or removing /etc/ld.so.preload to avoid an
unimplemented setend instruction).

I plan to add DMA, USB, framebuffer, timers, and other system devices
(vchiq, power, mphi, aux/uart1) in future patches. In the meantime,
the complete code is available at: https://github.com/0xabu/qemu

Although this series includes many of the peripherals common to Pi1
(aka bcm2835 aka Pi0), it's not yet possible to boot a Pi1, because it
requires additional peripherals, so I'll also add that SoC and machine
in a later patch.

v2 changes:
 * cleanup based on reviews of mbox and ic devices by Peter Crosthwaite
   (see specific notes on each patch)
 * removed custom SD controller in favour of sdhci

Cheers,
Andrew

Andrew Baumann (7):
  bcm2835_mbox: add BCM2835 mailboxes
  bcm2835_property: add bcm2835 property channel
  bcm2835_ic: add bcm2835 interrupt controller
  bcm2835_peripherals: add rollup device for bcm2835 peripherals
  bcm2836_control: add bcm2836 ARM control logic
  bcm2836: add bcm2836 soc device
  raspi: add raspberry pi 2 machine

 default-configs/arm-softmmu.mak      |   1 +
 hw/arm/Makefile.objs                 |   1 +
 hw/arm/bcm2835_peripherals.c         | 198 ++++++++++++++++++++
 hw/arm/bcm2836.c                     | 135 ++++++++++++++
 hw/arm/raspi.c                       | 179 +++++++++++++++++++
 hw/intc/Makefile.objs                |   1 +
 hw/intc/bcm2835_ic.c                 | 233 ++++++++++++++++++++++++
 hw/intc/bcm2836_control.c            | 338 +++++++++++++++++++++++++++++++++++
 hw/misc/Makefile.objs                |   2 +
 hw/misc/bcm2835_mbox.c               | 323 +++++++++++++++++++++++++++++++++
 hw/misc/bcm2835_property.c           | 277 ++++++++++++++++++++++++++++
 include/hw/arm/bcm2835_peripherals.h |  42 +++++
 include/hw/arm/bcm2836.h             |  33 ++++
 include/hw/arm/raspi_platform.h      | 161 +++++++++++++++++
 include/hw/intc/bcm2835_ic.h         |  33 ++++
 include/hw/intc/bcm2836_control.h    |  51 ++++++
 include/hw/misc/bcm2835_mbox.h       |  37 ++++
 include/hw/misc/bcm2835_mbox_defs.h  |  26 +++
 include/hw/misc/bcm2835_property.h   |  29 +++
 19 files changed, 2100 insertions(+)
 create mode 100644 hw/arm/bcm2835_peripherals.c
 create mode 100644 hw/arm/bcm2836.c
 create mode 100644 hw/arm/raspi.c
 create mode 100644 hw/intc/bcm2835_ic.c
 create mode 100644 hw/intc/bcm2836_control.c
 create mode 100644 hw/misc/bcm2835_mbox.c
 create mode 100644 hw/misc/bcm2835_property.c
 create mode 100644 include/hw/arm/bcm2835_peripherals.h
 create mode 100644 include/hw/arm/bcm2836.h
 create mode 100644 include/hw/arm/raspi_platform.h
 create mode 100644 include/hw/intc/bcm2835_ic.h
 create mode 100644 include/hw/intc/bcm2836_control.h
 create mode 100644 include/hw/misc/bcm2835_mbox.h
 create mode 100644 include/hw/misc/bcm2835_mbox_defs.h
 create mode 100644 include/hw/misc/bcm2835_property.h

-- 
2.5.3

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
@ 2015-12-24  0:25 ` Andrew Baumann
  2015-12-31  0:12   ` Peter Crosthwaite
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 2/7] bcm2835_property: add bcm2835 property channel Andrew Baumann
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

This adds the system mailboxes which are used to communicate with a
number of GPU peripherals on Pi/Pi2.

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---

Notes:
    v2:
     * renamed bcm2835_sbm to bcm2835_mbox
     * dropped bcm2835_arm_control.h (needed defs moved to bcm2835_mbox.c)
     * documented use of private address space through defines in bcm2835_mbox_defs.h
     * remove unused fields from BCM2835Mbox
     * s/int/bool/ where appropriate
     * cleaned up logic in _update and _mbox_update_status for clarity/simplicity
     * added vmstate
     * misc cleanup

 default-configs/arm-softmmu.mak     |   1 +
 hw/misc/Makefile.objs               |   1 +
 hw/misc/bcm2835_mbox.c              | 323 ++++++++++++++++++++++++++++++++++++
 include/hw/misc/bcm2835_mbox.h      |  37 +++++
 include/hw/misc/bcm2835_mbox_defs.h |  26 +++
 5 files changed, 388 insertions(+)
 create mode 100644 hw/misc/bcm2835_mbox.c
 create mode 100644 include/hw/misc/bcm2835_mbox.h
 create mode 100644 include/hw/misc/bcm2835_mbox_defs.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index d9b90a5..a9f82a1 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -79,6 +79,7 @@ CONFIG_TUSB6010=y
 CONFIG_IMX=y
 CONFIG_MAINSTONE=y
 CONFIG_NSERIES=y
+CONFIG_RASPI=y
 CONFIG_REALVIEW=y
 CONFIG_ZAURUS=y
 CONFIG_ZYNQ=y
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index aeb6b7d..e36f2ee 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -34,6 +34,7 @@ obj-$(CONFIG_OMAP) += omap_gpmc.o
 obj-$(CONFIG_OMAP) += omap_l4.o
 obj-$(CONFIG_OMAP) += omap_sdrc.o
 obj-$(CONFIG_OMAP) += omap_tap.o
+obj-$(CONFIG_RASPI) += bcm2835_mbox.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
diff --git a/hw/misc/bcm2835_mbox.c b/hw/misc/bcm2835_mbox.c
new file mode 100644
index 0000000..69b8e2a
--- /dev/null
+++ b/hw/misc/bcm2835_mbox.c
@@ -0,0 +1,323 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ *
+ * This file models the system mailboxes, which are used for
+ * communication with low-bandwidth GPU peripherals. Refs:
+ *   https://github.com/raspberrypi/firmware/wiki/Mailboxes
+ *   https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes
+ */
+
+#include "hw/misc/bcm2835_mbox.h"
+
+/* Mailbox status register (...0x98) */
+#define ARM_MS_FULL       0x80000000
+#define ARM_MS_EMPTY      0x40000000
+#define ARM_MS_LEVEL      0x400000FF /* Max. value depends on mailbox depth */
+
+/* MAILBOX config/status register (...0x9C) */
+/* ANY write to this register clears the error bits! */
+#define ARM_MC_IHAVEDATAIRQEN    0x00000001 /* mbox irq enable:  has data */
+#define ARM_MC_IHAVESPACEIRQEN   0x00000002 /* mbox irq enable:  has space */
+#define ARM_MC_OPPISEMPTYIRQEN   0x00000004 /* mbox irq enable: Opp is empty */
+#define ARM_MC_MAIL_CLEAR        0x00000008 /* mbox clear write 1, then  0 */
+#define ARM_MC_IHAVEDATAIRQPEND  0x00000010 /* mbox irq pending:  has space */
+#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mbox irq pending: Opp is empty */
+#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mbox irq pending */
+/* Bit 7 is unused */
+#define ARM_MC_ERRNOOWN   0x00000100 /* error : none owner read from mailbox */
+#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */
+#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */
+
+static void mbox_update_status(BCM2835Mbox *mb)
+{
+    mb->status &= ~(ARM_MS_EMPTY | ARM_MS_FULL);
+    if (mb->count == 0) {
+        mb->status |= ARM_MS_EMPTY;
+    } else if (mb->count == MBOX_SIZE) {
+        mb->status |= ARM_MS_FULL;
+    }
+}
+
+static void mbox_init(BCM2835Mbox *mb)
+{
+    int n;
+
+    mb->count = 0;
+    mb->config = 0;
+    for (n = 0; n < MBOX_SIZE; n++) {
+        mb->reg[n] = MBOX_INVALID_DATA;
+    }
+    mbox_update_status(mb);
+}
+
+static uint32_t mbox_pull(BCM2835Mbox *mb, int index)
+{
+    int n;
+    uint32_t val;
+
+    assert(mb->count > 0);
+    assert(index < mb->count);
+
+    val = mb->reg[index];
+    for (n = index + 1; n < mb->count; n++) {
+        mb->reg[n - 1] = mb->reg[n];
+    }
+    mb->count--;
+    mb->reg[mb->count] = MBOX_INVALID_DATA;
+
+    mbox_update_status(mb);
+
+    return val;
+}
+
+static void mbox_push(BCM2835Mbox *mb, uint32_t val)
+{
+    assert(mb->count < MBOX_SIZE);
+    mb->reg[mb->count++] = val;
+    mbox_update_status(mb);
+}
+
+static void bcm2835_mbox_update(BCM2835MboxState *s)
+{
+    uint32_t value;
+    bool set;
+    int n;
+
+    /* Avoid unwanted recursive calls */
+    s->mbox_irq_disabled = true;
+
+    /* Get pending responses and put them in the vc->arm mbox,
+     * as long as it's not full */
+    for (n = 0; n < MBOX_CHAN_COUNT; n++) {
+        while (s->available[n] && !(s->mbox[0].status & ARM_MS_FULL)) {
+            value = ldl_phys(&s->mbox_as, n << MBOX_AS_CHAN_SHIFT);
+            if (value == MBOX_INVALID_DATA) {
+                /* Interrupt pending, but there's no data. Hmmm... */
+                hw_error("%s: spurious interrupt on channel %d", __func__, n);
+            }
+            mbox_push(&s->mbox[0], value);
+        }
+    }
+
+    /* Try to push pending requests from the arm->vc mbox */
+    /* TODO (?) */
+
+    /* Re-enable calls from the IRQ routine */
+    s->mbox_irq_disabled = false;
+
+    /* Update ARM IRQ status */
+    set = false;
+    s->mbox[0].config &= ~ARM_MC_IHAVEDATAIRQPEND;
+    if (!(s->mbox[0].status & ARM_MS_EMPTY)) {
+        s->mbox[0].config |= ARM_MC_IHAVEDATAIRQPEND;
+        if (s->mbox[0].config & ARM_MC_IHAVEDATAIRQEN) {
+            set = true;
+        }
+    }
+    qemu_set_irq(s->arm_irq, set);
+}
+
+static void bcm2835_mbox_set_irq(void *opaque, int irq, int level)
+{
+    BCM2835MboxState *s = opaque;
+
+    s->available[irq] = level;
+
+    /* avoid recursively calling bcm2835_mbox_update when the interrupt
+     * status changes due to the ldl_phys call within that function */
+    if (!s->mbox_irq_disabled) {
+        bcm2835_mbox_update(s);
+    }
+}
+
+static uint64_t bcm2835_mbox_read(void *opaque, hwaddr offset, unsigned size)
+{
+    BCM2835MboxState *s = opaque;
+    uint32_t res = 0;
+
+    offset &= 0xff;
+
+    switch (offset) {
+    case 0x80 ... 0x8c:  /* MAIL0_READ */
+        if (s->mbox[0].status & ARM_MS_EMPTY) {
+            res = MBOX_INVALID_DATA;
+        } else {
+            res = mbox_pull(&s->mbox[0], 0);
+        }
+        break;
+    case 0x90:  /* MAIL0_PEEK */
+        res = s->mbox[0].reg[0];
+        break;
+    case 0x94:  /* MAIL0_SENDER */
+        break;
+    case 0x98:  /* MAIL0_STATUS */
+        res = s->mbox[0].status;
+        break;
+    case 0x9c:  /* MAIL0_CONFIG */
+        res = s->mbox[0].config;
+        break;
+    case 0xb8:  /* MAIL1_STATUS */
+        res = s->mbox[1].status;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return 0;
+    }
+
+    bcm2835_mbox_update(s);
+
+    return res;
+}
+
+static void bcm2835_mbox_write(void *opaque, hwaddr offset,
+                               uint64_t value, unsigned size)
+{
+    BCM2835MboxState *s = opaque;
+    hwaddr childaddr;
+    uint8_t ch;
+
+    offset &= 0xff;
+
+    switch (offset) {
+    case 0x94:  /* MAIL0_SENDER */
+        break;
+
+    case 0x9c:  /* MAIL0_CONFIG */
+        s->mbox[0].config &= ~ARM_MC_IHAVEDATAIRQEN;
+        s->mbox[0].config |= value & ARM_MC_IHAVEDATAIRQEN;
+        break;
+
+    case 0xa0 ... 0xac:
+        if (s->mbox[1].status & ARM_MS_FULL) {
+            /* Mailbox full */
+            qemu_log_mask(LOG_GUEST_ERROR, "%s: mailbox full\n", __func__);
+        } else {
+            ch = value & 0xf;
+            if (ch < MBOX_CHAN_COUNT) {
+                childaddr = ch << MBOX_AS_CHAN_SHIFT;
+                if (ldl_phys(&s->mbox_as, childaddr + MBOX_AS_PENDING)) {
+                    /* Child busy, push delayed. Push it in the arm->vc mbox */
+                    mbox_push(&s->mbox[1], value);
+                } else {
+                    /* Push it directly to the child device */
+                    stl_phys(&s->mbox_as, childaddr, value);
+                }
+            } else {
+                /* Invalid channel number */
+                qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid channel %u\n",
+                              __func__, ch);
+            }
+        }
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return;
+    }
+
+    bcm2835_mbox_update(s);
+}
+
+static const MemoryRegionOps bcm2835_mbox_ops = {
+    .read = bcm2835_mbox_read,
+    .write = bcm2835_mbox_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+/* vmstate of a single mailbox */
+static const VMStateDescription vmstate_bcm2835_mbox_box = {
+    .name = TYPE_BCM2835_MBOX "_box",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(reg, BCM2835Mbox, MBOX_SIZE),
+        VMSTATE_UINT32(count, BCM2835Mbox),
+        VMSTATE_UINT32(status, BCM2835Mbox),
+        VMSTATE_UINT32(config, BCM2835Mbox),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+/* vmstate of the entire device */
+static const VMStateDescription vmstate_bcm2835_mbox = {
+    .name = TYPE_BCM2835_MBOX,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_BOOL_ARRAY(available, BCM2835MboxState, MBOX_CHAN_COUNT),
+        VMSTATE_STRUCT_ARRAY(mbox, BCM2835MboxState, 2, 1,
+                             vmstate_bcm2835_mbox_box, BCM2835Mbox),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void bcm2835_mbox_init(Object *obj)
+{
+    BCM2835MboxState *s = BCM2835_MBOX(obj);
+    memory_region_init_io(&s->iomem, obj, &bcm2835_mbox_ops, s,
+                          TYPE_BCM2835_MBOX, 0x400);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->arm_irq);
+    qdev_init_gpio_in(DEVICE(s), bcm2835_mbox_set_irq, MBOX_CHAN_COUNT);
+}
+
+static void bcm2835_mbox_reset(DeviceState *dev)
+{
+    BCM2835MboxState *s = BCM2835_MBOX(dev);
+    int n;
+
+    mbox_init(&s->mbox[0]);
+    mbox_init(&s->mbox[1]);
+    s->mbox_irq_disabled = false;
+    for (n = 0; n < MBOX_CHAN_COUNT; n++) {
+        s->available[n] = false;
+    }
+}
+
+static void bcm2835_mbox_realize(DeviceState *dev, Error **errp)
+{
+    BCM2835MboxState *s = BCM2835_MBOX(dev);
+    Object *obj;
+    Error *err = NULL;
+
+    obj = object_property_get_link(OBJECT(dev), "mbox_mr", &err);
+    if (obj == NULL) {
+        error_setg(errp, "%s: required mbox_mr link not found: %s",
+                   __func__, error_get_pretty(err));
+        return;
+    }
+
+    s->mbox_mr = MEMORY_REGION(obj);
+    address_space_init(&s->mbox_as, s->mbox_mr, NULL);
+    bcm2835_mbox_reset(dev);
+}
+
+static void bcm2835_mbox_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = bcm2835_mbox_realize;
+    dc->reset = bcm2835_mbox_reset;
+    dc->vmsd = &vmstate_bcm2835_mbox;
+}
+
+static TypeInfo bcm2835_mbox_info = {
+    .name          = TYPE_BCM2835_MBOX,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BCM2835MboxState),
+    .class_init    = bcm2835_mbox_class_init,
+    .instance_init = bcm2835_mbox_init,
+};
+
+static void bcm2835_mbox_register_types(void)
+{
+    type_register_static(&bcm2835_mbox_info);
+}
+
+type_init(bcm2835_mbox_register_types)
diff --git a/include/hw/misc/bcm2835_mbox.h b/include/hw/misc/bcm2835_mbox.h
new file mode 100644
index 0000000..f24560c
--- /dev/null
+++ b/include/hw/misc/bcm2835_mbox.h
@@ -0,0 +1,37 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_MBOX_H
+#define BCM2835_MBOX_H
+
+#include "bcm2835_mbox_defs.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+#define TYPE_BCM2835_MBOX "bcm2835_mbox"
+#define BCM2835_MBOX(obj) \
+        OBJECT_CHECK(BCM2835MboxState, (obj), TYPE_BCM2835_MBOX)
+
+typedef struct {
+    uint32_t reg[MBOX_SIZE];
+    uint32_t count;
+    uint32_t status;
+    uint32_t config;
+} BCM2835Mbox;
+
+typedef struct {
+    /*< private >*/
+    SysBusDevice busdev;
+    /*< public >*/
+    MemoryRegion *mbox_mr;
+    AddressSpace mbox_as;
+    MemoryRegion iomem;
+    bool mbox_irq_disabled;
+    qemu_irq arm_irq;
+    bool available[MBOX_CHAN_COUNT];
+    BCM2835Mbox mbox[2];
+} BCM2835MboxState;
+
+#endif
diff --git a/include/hw/misc/bcm2835_mbox_defs.h b/include/hw/misc/bcm2835_mbox_defs.h
new file mode 100644
index 0000000..48d8ee4
--- /dev/null
+++ b/include/hw/misc/bcm2835_mbox_defs.h
@@ -0,0 +1,26 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_MBOX_DEFS_H
+#define BCM2835_MBOX_DEFS_H
+
+/* Constants shared with the ARM identifying separate mailbox channels */
+#define MBOX_CHAN_POWER    0 /* for use by the power management interface */
+#define MBOX_CHAN_FB       1 /* for use by the frame buffer */
+#define MBOX_CHAN_VCHIQ    3 /* for use by the VCHIQ interface */
+#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */
+#define MBOX_CHAN_COUNT    9
+
+#define MBOX_SIZE          32
+#define MBOX_INVALID_DATA  0x0f
+
+/* Layout of the private address space used for communication between
+ * the mbox device emulation, and child devices: each channel occupies
+ * 16 bytes of address space, but only two registers are presently defined. */
+#define MBOX_AS_CHAN_SHIFT 4
+#define MBOX_AS_DATA       0 /* request / response data (RW at offset 0) */
+#define MBOX_AS_PENDING    4 /* pending response status (RO at offset 4) */
+
+#endif /* BCM2835_MBOX_DEFS_H */
-- 
2.5.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v2 2/7] bcm2835_property: add bcm2835 property channel
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes Andrew Baumann
@ 2015-12-24  0:25 ` Andrew Baumann
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller Andrew Baumann
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

This sits behind the mailbox interface, and implements
request/response queries for system properties. The
framebuffer-related properties will be added in a later patch.

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---
 hw/misc/Makefile.objs              |   1 +
 hw/misc/bcm2835_property.c         | 277 +++++++++++++++++++++++++++++++++++++
 include/hw/misc/bcm2835_property.h |  29 ++++
 3 files changed, 307 insertions(+)
 create mode 100644 hw/misc/bcm2835_property.c
 create mode 100644 include/hw/misc/bcm2835_property.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index e36f2ee..b9d94de 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -35,6 +35,7 @@ obj-$(CONFIG_OMAP) += omap_l4.o
 obj-$(CONFIG_OMAP) += omap_sdrc.o
 obj-$(CONFIG_OMAP) += omap_tap.o
 obj-$(CONFIG_RASPI) += bcm2835_mbox.o
+obj-$(CONFIG_RASPI) += bcm2835_property.o
 obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
new file mode 100644
index 0000000..8a6eb0e
--- /dev/null
+++ b/hw/misc/bcm2835_property.c
@@ -0,0 +1,277 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "hw/misc/bcm2835_property.h"
+#include "hw/misc/bcm2835_mbox_defs.h"
+
+/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
+
+static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
+{
+    uint32_t tag;
+    uint32_t bufsize;
+    uint32_t tot_len;
+    size_t resplen;
+    uint32_t tmp;
+
+    value &= ~0xf;
+
+    s->addr = value;
+
+    tot_len = ldl_phys(&s->dma_as, value);
+
+    /* @(addr + 4) : Buffer response code */
+    value = s->addr + 8;
+    while (value + 8 <= s->addr + tot_len) {
+        tag = ldl_phys(&s->dma_as, value);
+        bufsize = ldl_phys(&s->dma_as, value + 4);
+        /* @(value + 8) : Request/response indicator */
+        resplen = 0;
+        switch (tag) {
+        case 0x00000000: /* End tag */
+            break;
+        case 0x00000001: /* Get firmware revision */
+            stl_phys(&s->dma_as, value + 12, 346337);
+            resplen = 4;
+            break;
+
+        case 0x00010001: /* Get board model */
+            resplen = 4;
+            break;
+        case 0x00010002: /* Get board revision */
+            resplen = 4;
+            break;
+        case 0x00010003: /* Get board MAC address */
+            /* write the first four bytes of the 6-byte MAC */
+            stl_phys(&s->dma_as, value + 12, 0xB827EBD0);
+            /* write the last two bytes, avoid any write past the buffer end */
+            stb_phys(&s->dma_as, value + 16, 0xEE);
+            stb_phys(&s->dma_as, value + 17, 0xDF);
+            resplen = 6;
+            break;
+        case 0x00010004: /* Get board serial */
+            resplen = 8;
+            break;
+        case 0x00010005: /* Get ARM memory */
+            /* base */
+            stl_phys(&s->dma_as, value + 12, 0);
+            /* size */
+            stl_phys(&s->dma_as, value + 16, s->ram_size);
+            resplen = 8;
+            break;
+        case 0x00028001: /* Set power state */
+            /* Assume that whatever device they asked for exists,
+             * and we'll just claim we set it to the desired state */
+            tmp = ldl_phys(&s->dma_as, value + 16);
+            stl_phys(&s->dma_as, value + 16, (tmp & 1));
+            resplen = 8;
+            break;
+
+        /* Clocks */
+
+        case 0x00030001: /* Get clock state */
+            stl_phys(&s->dma_as, value + 16, 0x1);
+            resplen = 8;
+            break;
+
+        case 0x00038001: /* Set clock state */
+            resplen = 8;
+            break;
+
+        case 0x00030002: /* Get clock rate */
+        case 0x00030004: /* Get max clock rate */
+        case 0x00030007: /* Get min clock rate */
+            switch (ldl_phys(&s->dma_as, value + 12)) {
+            case 1: /* EMMC */
+                stl_phys(&s->dma_as, value + 16, 50000000);
+                break;
+            case 2: /* UART */
+                stl_phys(&s->dma_as, value + 16, 3000000);
+                break;
+            default:
+                stl_phys(&s->dma_as, value + 16, 700000000);
+                break;
+            }
+            resplen = 8;
+            break;
+
+        case 0x00038002: /* Set clock rate */
+        case 0x00038004: /* Set max clock rate */
+        case 0x00038007: /* Set min clock rate */
+            resplen = 8;
+            break;
+
+        /* Temperature */
+
+        case 0x00030006: /* Get temperature */
+            stl_phys(&s->dma_as, value + 16, 25000);
+            resplen = 8;
+            break;
+
+        case 0x0003000A: /* Get max temperature */
+            stl_phys(&s->dma_as, value + 16, 99000);
+            resplen = 8;
+            break;
+
+
+        case 0x00060001: /* Get DMA channels */
+            /* channels 2-5 */
+            stl_phys(&s->dma_as, value + 12, 0x003C);
+            resplen = 4;
+            break;
+
+        case 0x00050001: /* Get command line */
+            resplen = 0;
+            break;
+
+        default:
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "bcm2835_property: unhandled tag %08x\n", tag);
+            break;
+        }
+
+        if (tag == 0) {
+            break;
+        }
+
+        stl_phys(&s->dma_as, value + 8, (1 << 31) | resplen);
+        value += bufsize + 12;
+    }
+
+    /* Buffer response code */
+    stl_phys(&s->dma_as, s->addr + 4, (1 << 31));
+}
+
+static uint64_t bcm2835_property_read(void *opaque, hwaddr offset,
+                                      unsigned size)
+{
+    BCM2835PropertyState *s = opaque;
+    uint32_t res = 0;
+
+    switch (offset) {
+    case MBOX_AS_DATA:
+        res = MBOX_CHAN_PROPERTY | s->addr;
+        s->pending = false;
+        qemu_set_irq(s->mbox_irq, 0);
+        break;
+
+    case MBOX_AS_PENDING:
+        res = s->pending;
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return 0;
+    }
+
+    return res;
+}
+
+static void bcm2835_property_write(void *opaque, hwaddr offset,
+                                   uint64_t value, unsigned size)
+{
+    BCM2835PropertyState *s = opaque;
+
+    switch (offset) {
+    case MBOX_AS_DATA:
+        if (!s->pending) {
+            s->pending = true;
+            bcm2835_property_mbox_push(s, value);
+            qemu_set_irq(s->mbox_irq, 1);
+        }
+        break;
+
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return;
+    }
+
+}
+
+static const MemoryRegionOps bcm2835_property_ops = {
+    .read = bcm2835_property_read,
+    .write = bcm2835_property_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+static const VMStateDescription vmstate_bcm2835_property = {
+    .name = TYPE_BCM2835_PROPERTY,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(addr, BCM2835PropertyState),
+        VMSTATE_BOOL(pending, BCM2835PropertyState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void bcm2835_property_init(Object *obj)
+{
+    BCM2835PropertyState *s = BCM2835_PROPERTY(obj);
+    memory_region_init_io(&s->iomem, OBJECT(s), &bcm2835_property_ops, s,
+                          TYPE_BCM2835_PROPERTY, 0x10);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->mbox_irq);
+}
+
+static void bcm2835_property_reset(DeviceState *dev)
+{
+    BCM2835PropertyState *s = BCM2835_PROPERTY(dev);
+
+    s->pending = false;
+}
+
+static void bcm2835_property_realize(DeviceState *dev, Error **errp)
+{
+    BCM2835PropertyState *s = BCM2835_PROPERTY(dev);
+    Object *obj;
+    Error *err = NULL;
+
+    obj = object_property_get_link(OBJECT(dev), "dma_mr", &err);
+    if (obj == NULL) {
+        error_setg(errp, "%s: required dma_mr link not found: %s",
+                   __func__, error_get_pretty(err));
+        return;
+    }
+
+    s->dma_mr = MEMORY_REGION(obj);
+    address_space_init(&s->dma_as, s->dma_mr, NULL);
+
+    bcm2835_property_reset(dev);
+}
+
+static Property bcm2835_property_props[] = {
+    DEFINE_PROP_UINT32("ram-size", BCM2835PropertyState, ram_size, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void bcm2835_property_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->props = bcm2835_property_props;
+    dc->realize = bcm2835_property_realize;
+    dc->vmsd = &vmstate_bcm2835_property;
+}
+
+static TypeInfo bcm2835_property_info = {
+    .name          = TYPE_BCM2835_PROPERTY,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BCM2835PropertyState),
+    .class_init    = bcm2835_property_class_init,
+    .instance_init = bcm2835_property_init,
+};
+
+static void bcm2835_property_register_types(void)
+{
+    type_register_static(&bcm2835_property_info);
+}
+
+type_init(bcm2835_property_register_types)
diff --git a/include/hw/misc/bcm2835_property.h b/include/hw/misc/bcm2835_property.h
new file mode 100644
index 0000000..f71bf8c
--- /dev/null
+++ b/include/hw/misc/bcm2835_property.h
@@ -0,0 +1,29 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_PROPERTY_H
+#define BCM2835_PROPERTY_H
+
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+#define TYPE_BCM2835_PROPERTY "bcm2835_property"
+#define BCM2835_PROPERTY(obj) \
+        OBJECT_CHECK(BCM2835PropertyState, (obj), TYPE_BCM2835_PROPERTY)
+
+typedef struct {
+    /*< private >*/
+    SysBusDevice busdev;
+    /*< public >*/
+    MemoryRegion *dma_mr;
+    AddressSpace dma_as;
+    MemoryRegion iomem;
+    uint32_t addr;
+    bool pending;
+    qemu_irq mbox_irq;
+    uint32_t ram_size;
+} BCM2835PropertyState;
+
+#endif
-- 
2.5.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes Andrew Baumann
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 2/7] bcm2835_property: add bcm2835 property channel Andrew Baumann
@ 2015-12-24  0:25 ` Andrew Baumann
  2015-12-31  0:33   ` Peter Crosthwaite
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals Andrew Baumann
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---

Notes:
    v2 changes:
     * split inputs to named gpu_irq and arm_irq gpio inputs
     * use 64-bit gpu_irq and 8-bit arm_irq status rather than 3*32-bit bitfields
     * added defined names for register offsets
     * deleted nop realize method
     * other misc cleanup suggested in review

 hw/intc/Makefile.objs        |   1 +
 hw/intc/bcm2835_ic.c         | 233 +++++++++++++++++++++++++++++++++++++++++++
 include/hw/intc/bcm2835_ic.h |  33 ++++++
 3 files changed, 267 insertions(+)
 create mode 100644 hw/intc/bcm2835_ic.c
 create mode 100644 include/hw/intc/bcm2835_ic.h

diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 004b0c2..2ad1204 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -24,6 +24,7 @@ obj-$(CONFIG_GRLIB) += grlib_irqmp.o
 obj-$(CONFIG_IOAPIC) += ioapic.o
 obj-$(CONFIG_OMAP) += omap_intc.o
 obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
+obj-$(CONFIG_RASPI) += bcm2835_ic.o
 obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
new file mode 100644
index 0000000..9624e8b
--- /dev/null
+++ b/hw/intc/bcm2835_ic.c
@@ -0,0 +1,233 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ * Heavily based on pl190.c, copyright terms below:
+ *
+ * Arm PrimeCell PL190 Vector Interrupt Controller
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/intc/bcm2835_ic.h"
+
+#define GPU_IRQS 64
+#define ARM_IRQS 8
+
+#define IRQ_PENDING_BASIC       0x00 /* IRQ basic pending */
+#define IRQ_PENDING_1           0x04 /* IRQ pending 1 */
+#define IRQ_PENDING_2           0x08 /* IRQ pending 2 */
+#define FIQ_CONTROL             0x0C /* FIQ register */
+#define IRQ_ENABLE_1            0x10 /* Interrupt enable register 1 */
+#define IRQ_ENABLE_2            0x14 /* Interrupt enable register 2 */
+#define IRQ_ENABLE_BASIC        0x18 /* Base interrupt enable register */
+#define IRQ_DISABLE_1           0x1C /* Interrupt disable register 1 */
+#define IRQ_DISABLE_2           0x20 /* Interrupt disable register 2 */
+#define IRQ_DISABLE_BASIC       0x24 /* Base interrupt disable register */
+
+/* Update interrupts.  */
+static void bcm2835_ic_update(BCM2835ICState *s)
+{
+    bool set = false;
+
+    if (s->fiq_enable) {
+        if (s->fiq_select >= GPU_IRQS) {
+            /* ARM IRQ */
+            set = extract32(s->arm_irq_level, s->fiq_select - GPU_IRQS, 1);
+        } else {
+            set = extract64(s->gpu_irq_level, s->fiq_select, 1);
+        }
+    }
+    qemu_set_irq(s->fiq, set);
+
+    set = (s->gpu_irq_level & s->gpu_irq_enable)
+        || (s->arm_irq_level & s->arm_irq_enable);
+    qemu_set_irq(s->irq, set);
+
+}
+
+static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
+{
+    BCM2835ICState *s = opaque;
+    assert(irq >= 0 && irq < 64);
+    s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
+    bcm2835_ic_update(s);
+}
+
+static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
+{
+    BCM2835ICState *s = opaque;
+    assert(irq >= 0 && irq < 8);
+    s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
+    bcm2835_ic_update(s);
+}
+
+static const int irq_dups[] = { 7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62 };
+
+static uint64_t bcm2835_ic_read(void *opaque, hwaddr offset, unsigned size)
+{
+    BCM2835ICState *s = opaque;
+    uint32_t res = 0;
+    uint64_t gpu_pending = s->gpu_irq_level & s->gpu_irq_enable;
+    int i;
+
+    switch (offset) {
+    case IRQ_PENDING_BASIC:
+        /* bits 0-7: ARM irqs */
+        res = s->arm_irq_level & s->arm_irq_enable;
+
+        /* bits 8 & 9: pending registers 1 & 2 */
+        res |= (((uint32_t)gpu_pending) != 0) << 8;
+        res |= ((gpu_pending >> 32) != 0) << 9;
+
+        /* bits 10-20: selected GPU IRQs */
+        for (i = 0; i < ARRAY_SIZE(irq_dups); i++) {
+            res |= extract64(gpu_pending, irq_dups[i], 1) << (i + 10);
+        }
+        break;
+    case IRQ_PENDING_1:  /* IRQ pending 1 */
+        res = gpu_pending;
+        break;
+    case IRQ_PENDING_2:  /* IRQ pending 2 */
+        res = gpu_pending >> 32;
+        break;
+    case FIQ_CONTROL:  /* FIQ register */
+        res = (s->fiq_enable << 7) | s->fiq_select;
+        break;
+    case IRQ_ENABLE_1:  /* Interrupt enable register 1 */
+        res = s->gpu_irq_enable;
+        break;
+    case IRQ_ENABLE_2:  /* Interrupt enable register 2 */
+        res = s->gpu_irq_enable >> 32;
+        break;
+    case IRQ_ENABLE_BASIC:  /* Base interrupt enable register */
+        res = s->arm_irq_enable;
+        break;
+    case IRQ_DISABLE_1:  /* Interrupt disable register 1 */
+        res = ~s->gpu_irq_enable;
+        break;
+    case IRQ_DISABLE_2:  /* Interrupt disable register 2 */
+        res = ~s->gpu_irq_enable >> 32;
+        break;
+    case IRQ_DISABLE_BASIC:  /* Base interrupt disable register */
+        res = ~s->arm_irq_enable;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return 0;
+    }
+
+    return res;
+}
+
+static void bcm2835_ic_write(void *opaque, hwaddr offset, uint64_t val,
+                             unsigned size)
+{
+    BCM2835ICState *s = opaque;
+
+    switch (offset) {
+    case FIQ_CONTROL:
+        s->fiq_select = (val & 0x7f);
+        s->fiq_enable = (val >> 7) & 0x1;
+        break;
+    case IRQ_ENABLE_1:
+        s->gpu_irq_enable |= val;
+        break;
+    case IRQ_ENABLE_2:
+        s->gpu_irq_enable |= val << 32;
+        break;
+    case IRQ_ENABLE_BASIC:
+        s->arm_irq_enable |= val & 0xff;
+        break;
+    case IRQ_DISABLE_1:
+        s->gpu_irq_enable &= ~val;
+        break;
+    case IRQ_DISABLE_2:
+        s->gpu_irq_enable &= ~(val << 32);
+        break;
+    case IRQ_DISABLE_BASIC:
+        s->arm_irq_enable &= ~val & 0xff;
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return;
+    }
+    bcm2835_ic_update(s);
+}
+
+static const MemoryRegionOps bcm2835_ic_ops = {
+    .read = bcm2835_ic_read,
+    .write = bcm2835_ic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+};
+
+static void bcm2835_ic_reset(DeviceState *d)
+{
+    BCM2835ICState *s = BCM2835_IC(d);
+
+    s->gpu_irq_enable = 0;
+    s->arm_irq_enable = 0;
+    s->fiq_enable = false;
+    s->fiq_select = 0;
+}
+
+static void bcm2835_ic_init(Object *obj)
+{
+    BCM2835ICState *s = BCM2835_IC(obj);
+
+    memory_region_init_io(&s->iomem, obj, &bcm2835_ic_ops, s, TYPE_BCM2835_IC,
+                          0x200);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+
+    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_gpu_irq,
+                            BCM2835_IC_GPU_IRQ, GPU_IRQS);
+    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_arm_irq,
+                            BCM2835_IC_ARM_IRQ, ARM_IRQS);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->fiq);
+}
+
+static const VMStateDescription vmstate_bcm2835_ic = {
+    .name = TYPE_BCM2835_IC,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT64(gpu_irq_level, BCM2835ICState),
+        VMSTATE_UINT64(gpu_irq_enable, BCM2835ICState),
+        VMSTATE_UINT8(arm_irq_level, BCM2835ICState),
+        VMSTATE_UINT8(arm_irq_enable, BCM2835ICState),
+        VMSTATE_BOOL(fiq_enable, BCM2835ICState),
+        VMSTATE_UINT8(fiq_select, BCM2835ICState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void bcm2835_ic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = bcm2835_ic_reset;
+    dc->vmsd = &vmstate_bcm2835_ic;
+}
+
+static TypeInfo bcm2835_ic_info = {
+    .name          = TYPE_BCM2835_IC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BCM2835ICState),
+    .class_init    = bcm2835_ic_class_init,
+    .instance_init = bcm2835_ic_init,
+};
+
+static void bcm2835_ic_register_types(void)
+{
+    type_register_static(&bcm2835_ic_info);
+}
+
+type_init(bcm2835_ic_register_types)
diff --git a/include/hw/intc/bcm2835_ic.h b/include/hw/intc/bcm2835_ic.h
new file mode 100644
index 0000000..d897f44
--- /dev/null
+++ b/include/hw/intc/bcm2835_ic.h
@@ -0,0 +1,33 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_IC_H
+#define BCM2835_IC_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_BCM2835_IC "bcm2835_ic"
+#define BCM2835_IC(obj) OBJECT_CHECK(BCM2835ICState, (obj), TYPE_BCM2835_IC)
+
+#define BCM2835_IC_GPU_IRQ "gpu-irq"
+#define BCM2835_IC_ARM_IRQ "arm-irq"
+
+typedef struct BCM2835ICState {
+    /*< private >*/
+    SysBusDevice busdev;
+    /*< public >*/
+
+    MemoryRegion iomem;
+
+    /* 64 GPU IRQs + 8 ARM IRQs = 72 total (GPU first) */
+    uint64_t gpu_irq_level, gpu_irq_enable;
+    uint8_t arm_irq_level, arm_irq_enable;
+    bool fiq_enable;
+    uint8_t fiq_select;
+    qemu_irq irq;
+    qemu_irq fiq;
+} BCM2835ICState;
+
+#endif
-- 
2.5.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
                   ` (2 preceding siblings ...)
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller Andrew Baumann
@ 2015-12-24  0:25 ` Andrew Baumann
  2015-12-31  2:53   ` Peter Crosthwaite
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic Andrew Baumann
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

This device maintains all the non-CPU peripherals on bcm2835 (Pi1)
which are also present on bcm2836 (Pi2). It also implements the
private address space used for DMA.

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---

Notes:
    v2 changes:
     * adapted to use common SDHCI emulation

 hw/arm/Makefile.objs                 |   1 +
 hw/arm/bcm2835_peripherals.c         | 198 +++++++++++++++++++++++++++++++++++
 include/hw/arm/bcm2835_peripherals.h |  42 ++++++++
 include/hw/arm/raspi_platform.h      | 161 ++++++++++++++++++++++++++++
 4 files changed, 402 insertions(+)
 create mode 100644 hw/arm/bcm2835_peripherals.c
 create mode 100644 include/hw/arm/bcm2835_peripherals.h
 create mode 100644 include/hw/arm/raspi_platform.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 2195b60..82cc142 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -11,6 +11,7 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-$(CONFIG_DIGIC) += digic.o
 obj-y += omap1.o omap2.o strongarm.o
 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
+obj-$(CONFIG_RASPI) += bcm2835_peripherals.o
 obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
 obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
 obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
new file mode 100644
index 0000000..deb6336
--- /dev/null
+++ b/hw/arm/bcm2835_peripherals.c
@@ -0,0 +1,198 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "hw/arm/bcm2835_peripherals.h"
+#include "hw/misc/bcm2835_mbox_defs.h"
+#include "hw/arm/raspi_platform.h"
+
+/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
+#define BCM2835_SDHC_CAPAREG 0x52034b4
+
+static void bcm2835_peripherals_init(Object *obj)
+{
+    BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
+
+    /* Memory region for peripheral devices, which we export to our parent */
+    memory_region_init_io(&s->peri_mr, OBJECT(s), NULL, s,
+                          "bcm2835_peripherals", 0x1000000);
+    object_property_add_child(obj, "peripheral_io", OBJECT(&s->peri_mr), NULL);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
+
+    /* Internal memory region for peripheral bus addresses (not exported) */
+    memory_region_init_io(&s->gpu_bus_mr, OBJECT(s), NULL, s, "bcm2835_gpu_bus",
+                          (uint64_t)1 << 32);
+    object_property_add_child(obj, "gpu_bus", OBJECT(&s->gpu_bus_mr), NULL);
+
+    /* Internal memory region for communication of mailbox channel data */
+    memory_region_init_io(&s->mbox_mr, OBJECT(s), NULL, s, "bcm2835_mbox",
+                          MBOX_CHAN_COUNT << 4);
+
+    /* Interrupt Controller */
+    object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
+    object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL);
+    qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default());
+
+    /* UART0 */
+    s->uart0 = SYS_BUS_DEVICE(object_new("pl011"));
+    object_property_add_child(obj, "uart0", OBJECT(s->uart0), NULL);
+    qdev_set_parent_bus(DEVICE(s->uart0), sysbus_get_default());
+
+    /* Mailboxes */
+    object_initialize(&s->mboxes, sizeof(s->mboxes), TYPE_BCM2835_MBOX);
+    object_property_add_child(obj, "mbox", OBJECT(&s->mboxes), NULL);
+    qdev_set_parent_bus(DEVICE(&s->mboxes), sysbus_get_default());
+
+    object_property_add_const_link(OBJECT(&s->mboxes), "mbox_mr",
+                                   OBJECT(&s->mbox_mr), &error_abort);
+
+    /* Property channel */
+    object_initialize(&s->property, sizeof(s->property), TYPE_BCM2835_PROPERTY);
+    object_property_add_child(obj, "property", OBJECT(&s->property), NULL);
+    qdev_set_parent_bus(DEVICE(&s->property), sysbus_get_default());
+
+    object_property_add_const_link(OBJECT(&s->property), "dma_mr",
+                                   OBJECT(&s->gpu_bus_mr), &error_abort);
+
+    /* Extended Mass Media Controller */
+    object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
+    object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
+    qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
+}
+
+static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
+{
+    BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
+    MemoryRegion *ram;
+    Error *err = NULL;
+    uint32_t ram_size;
+    int n;
+
+    /* Map peripherals and RAM into the GPU address space. */
+    memory_region_init_alias(&s->peri_mr_alias, OBJECT(s),
+                             "bcm2835_peripherals", &s->peri_mr, 0,
+                             memory_region_size(&s->peri_mr));
+
+    memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE,
+                                        &s->peri_mr_alias, 1);
+
+    /* XXX: assume that RAM is contiguous and mapped at system address zero */
+    ram = memory_region_find(get_system_memory(), 0, 1).mr;
+    assert(ram != NULL && memory_region_size(ram) >= 128 * 1024 * 1024);
+    ram_size = memory_region_size(ram);
+
+    /* RAM is aliased four times (different cache configurations) on the GPU */
+    for (n = 0; n < 4; n++) {
+        memory_region_init_alias(&s->ram_alias[n], OBJECT(s),
+                                 "bcm2835_gpu_ram_alias[*]", ram, 0, ram_size);
+        memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30,
+                                            &s->ram_alias[n], 0);
+    }
+
+    /* Interrupt Controller */
+    object_property_set_bool(OBJECT(&s->ic), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
+                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
+    sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
+
+    /* UART0 */
+    object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    memory_region_add_subregion(&s->peri_mr, UART0_OFFSET,
+                                sysbus_mmio_get_region(s->uart0, 0));
+    sysbus_connect_irq(s->uart0, 0,
+        qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
+                               INTERRUPT_VC_UART));
+
+    /* Mailboxes */
+    object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET,
+                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0,
+        qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
+                               INTERRUPT_ARM_MAILBOX - ARM_IRQ0_BASE));
+
+    /* Mailbox-addressable peripherals use the private mbox_mr address space
+     * and pseudo-irqs to dispatch requests and responses. */
+
+    /* Property channel */
+    object_property_set_int(OBJECT(&s->property), ram_size, "ram-size", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    object_property_set_bool(OBJECT(&s->property), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    memory_region_add_subregion(&s->mbox_mr,
+                MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT,
+                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
+                      qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
+
+    /* Extended Mass Media Controller */
+    object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
+                            &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET,
+                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
+        qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
+                               INTERRUPT_VC_ARASANSDIO));
+}
+
+static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = bcm2835_peripherals_realize;
+}
+
+static const TypeInfo bcm2835_peripherals_type_info = {
+    .name = TYPE_BCM2835_PERIPHERALS,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BCM2835PeripheralState),
+    .instance_init = bcm2835_peripherals_init,
+    .class_init = bcm2835_peripherals_class_init,
+};
+
+static void bcm2835_peripherals_register_types(void)
+{
+    type_register_static(&bcm2835_peripherals_type_info);
+}
+
+type_init(bcm2835_peripherals_register_types)
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
new file mode 100644
index 0000000..b3ba574
--- /dev/null
+++ b/include/hw/arm/bcm2835_peripherals.h
@@ -0,0 +1,42 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2835_PERIPHERALS_H
+#define BCM2835_PERIPHERALS_H
+
+#include "qemu-common.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "hw/intc/bcm2835_ic.h"
+#include "hw/misc/bcm2835_property.h"
+#include "hw/misc/bcm2835_mbox.h"
+#include "hw/sd/sdhci.h"
+
+#define TYPE_BCM2835_PERIPHERALS "bcm2835_peripherals"
+#define BCM2835_PERIPHERALS(obj) \
+    OBJECT_CHECK(BCM2835PeripheralState, (obj), TYPE_BCM2835_PERIPHERALS)
+
+typedef struct BCM2835PeripheralState {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    MemoryRegion peri_mr, peri_mr_alias, gpu_bus_mr, mbox_mr;
+    MemoryRegion ram_alias[4];
+    qemu_irq irq, fiq;
+
+    SysBusDevice *uart0;
+    BCM2835ICState ic;
+    BCM2835PropertyState property;
+    BCM2835MboxState mboxes;
+    SDHCIState sdhci;
+} BCM2835PeripheralState;
+
+#endif /* BCM2835_PERIPHERALS_H */
diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
new file mode 100644
index 0000000..8386949
--- /dev/null
+++ b/include/hw/arm/raspi_platform.h
@@ -0,0 +1,161 @@
+/*
+ * bcm2708 aka bcm2835/2836 aka Raspberry Pi/Pi2 SoC platform defines
+ *
+ * These definitions are derived from those in Linux at
+ * arch/arm/mach-{bcm2708,bcm2709}/include/mach/platform.h
+ * where they carry the following notice:
+ */
+
+/*
+ * arch/arm/mach-bcm2708/include/mach/platform.h
+ *
+ * Copyright (C) 2010 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* Peripheral base address on the VC (GPU) system bus */
+#define BCM2835_VC_PERI_BASE 0x7e000000
+
+/* Peripheral base addresses seen by the CPU: Pi1 and Pi2 differ */
+#define BCM2835_PERI_BASE       0x20000000
+#define BCM2836_PERI_BASE       0x3F000000
+
+/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
+#define BCM2836_CONTROL_BASE    0x40000000
+
+#define MCORE_OFFSET            0x0000   /* Fake frame buffer device
+                                          * (the multicore sync block) */
+#define IC0_OFFSET              0x2000
+#define ST_OFFSET               0x3000   /* System Timer */
+#define MPHI_OFFSET             0x6000   /* Message-based Parallel Host Intf. */
+#define DMA_OFFSET              0x7000   /* DMA controller, channels 0-14 */
+#define ARM_OFFSET              0xB000   /* BCM2708 ARM control block */
+#define ARMCTRL_OFFSET          (ARM_OFFSET + 0x000)
+#define ARMCTRL_IC_OFFSET       (ARM_OFFSET + 0x200) /* Interrupt controller */
+#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 */
+#define ARMCTRL_0_SBM_OFFSET    (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
+                                                      * Doorbells & Mailboxes */
+#define PM_OFFSET               0x100000 /* Power Management, Reset controller
+                                          * and Watchdog registers */
+#define PCM_CLOCK_OFFSET        0x101098 /* PCM Clock */
+#define RNG_OFFSET              0x104000 /* Hardware RNG */
+#define GPIO_OFFSET             0x200000 /* GPIO */
+#define UART0_OFFSET            0x201000 /* Uart 0 */
+#define MMCI0_OFFSET            0x202000 /* MMC interface */
+#define I2S_OFFSET              0x203000 /* I2S */
+#define SPI0_OFFSET             0x204000 /* SPI0 */
+#define BSC0_OFFSET             0x205000 /* BSC0 I2C/TWI */
+#define UART1_OFFSET            0x215000 /* Uart 1 */
+#define EMMC_OFFSET             0x300000 /* eMMC interface */
+#define SMI_OFFSET              0x600000 /* SMI */
+#define BSC1_OFFSET             0x804000 /* BSC1 I2C/TWI */
+#define USB_OFFSET              0x980000 /* DTC_OTG USB controller */
+#define DMA15_OFFSET            0xE05000 /* DMA controller, channel 15 */
+
+/*
+ * Interrupt assignments
+ */
+
+#define ARM_IRQ1_BASE                  0
+#define INTERRUPT_TIMER0               (ARM_IRQ1_BASE + 0)
+#define INTERRUPT_TIMER1               (ARM_IRQ1_BASE + 1)
+#define INTERRUPT_TIMER2               (ARM_IRQ1_BASE + 2)
+#define INTERRUPT_TIMER3               (ARM_IRQ1_BASE + 3)
+#define INTERRUPT_CODEC0               (ARM_IRQ1_BASE + 4)
+#define INTERRUPT_CODEC1               (ARM_IRQ1_BASE + 5)
+#define INTERRUPT_CODEC2               (ARM_IRQ1_BASE + 6)
+#define INTERRUPT_VC_JPEG              (ARM_IRQ1_BASE + 7)
+#define INTERRUPT_ISP                  (ARM_IRQ1_BASE + 8)
+#define INTERRUPT_VC_USB               (ARM_IRQ1_BASE + 9)
+#define INTERRUPT_VC_3D                (ARM_IRQ1_BASE + 10)
+#define INTERRUPT_TRANSPOSER           (ARM_IRQ1_BASE + 11)
+#define INTERRUPT_MULTICORESYNC0       (ARM_IRQ1_BASE + 12)
+#define INTERRUPT_MULTICORESYNC1       (ARM_IRQ1_BASE + 13)
+#define INTERRUPT_MULTICORESYNC2       (ARM_IRQ1_BASE + 14)
+#define INTERRUPT_MULTICORESYNC3       (ARM_IRQ1_BASE + 15)
+#define INTERRUPT_DMA0                 (ARM_IRQ1_BASE + 16)
+#define INTERRUPT_DMA1                 (ARM_IRQ1_BASE + 17)
+#define INTERRUPT_VC_DMA2              (ARM_IRQ1_BASE + 18)
+#define INTERRUPT_VC_DMA3              (ARM_IRQ1_BASE + 19)
+#define INTERRUPT_DMA4                 (ARM_IRQ1_BASE + 20)
+#define INTERRUPT_DMA5                 (ARM_IRQ1_BASE + 21)
+#define INTERRUPT_DMA6                 (ARM_IRQ1_BASE + 22)
+#define INTERRUPT_DMA7                 (ARM_IRQ1_BASE + 23)
+#define INTERRUPT_DMA8                 (ARM_IRQ1_BASE + 24)
+#define INTERRUPT_DMA9                 (ARM_IRQ1_BASE + 25)
+#define INTERRUPT_DMA10                (ARM_IRQ1_BASE + 26)
+#define INTERRUPT_DMA11                (ARM_IRQ1_BASE + 27)
+#define INTERRUPT_DMA12                (ARM_IRQ1_BASE + 28)
+#define INTERRUPT_AUX                  (ARM_IRQ1_BASE + 29)
+#define INTERRUPT_ARM                  (ARM_IRQ1_BASE + 30)
+#define INTERRUPT_VPUDMA               (ARM_IRQ1_BASE + 31)
+
+#define ARM_IRQ2_BASE                  32
+#define INTERRUPT_HOSTPORT             (ARM_IRQ2_BASE + 0)
+#define INTERRUPT_VIDEOSCALER          (ARM_IRQ2_BASE + 1)
+#define INTERRUPT_CCP2TX               (ARM_IRQ2_BASE + 2)
+#define INTERRUPT_SDC                  (ARM_IRQ2_BASE + 3)
+#define INTERRUPT_DSI0                 (ARM_IRQ2_BASE + 4)
+#define INTERRUPT_AVE                  (ARM_IRQ2_BASE + 5)
+#define INTERRUPT_CAM0                 (ARM_IRQ2_BASE + 6)
+#define INTERRUPT_CAM1                 (ARM_IRQ2_BASE + 7)
+#define INTERRUPT_HDMI0                (ARM_IRQ2_BASE + 8)
+#define INTERRUPT_HDMI1                (ARM_IRQ2_BASE + 9)
+#define INTERRUPT_PIXELVALVE1          (ARM_IRQ2_BASE + 10)
+#define INTERRUPT_I2CSPISLV            (ARM_IRQ2_BASE + 11)
+#define INTERRUPT_DSI1                 (ARM_IRQ2_BASE + 12)
+#define INTERRUPT_PWA0                 (ARM_IRQ2_BASE + 13)
+#define INTERRUPT_PWA1                 (ARM_IRQ2_BASE + 14)
+#define INTERRUPT_CPR                  (ARM_IRQ2_BASE + 15)
+#define INTERRUPT_SMI                  (ARM_IRQ2_BASE + 16)
+#define INTERRUPT_GPIO0                (ARM_IRQ2_BASE + 17)
+#define INTERRUPT_GPIO1                (ARM_IRQ2_BASE + 18)
+#define INTERRUPT_GPIO2                (ARM_IRQ2_BASE + 19)
+#define INTERRUPT_GPIO3                (ARM_IRQ2_BASE + 20)
+#define INTERRUPT_VC_I2C               (ARM_IRQ2_BASE + 21)
+#define INTERRUPT_VC_SPI               (ARM_IRQ2_BASE + 22)
+#define INTERRUPT_VC_I2SPCM            (ARM_IRQ2_BASE + 23)
+#define INTERRUPT_VC_SDIO              (ARM_IRQ2_BASE + 24)
+#define INTERRUPT_VC_UART              (ARM_IRQ2_BASE + 25)
+#define INTERRUPT_SLIMBUS              (ARM_IRQ2_BASE + 26)
+#define INTERRUPT_VEC                  (ARM_IRQ2_BASE + 27)
+#define INTERRUPT_CPG                  (ARM_IRQ2_BASE + 28)
+#define INTERRUPT_RNG                  (ARM_IRQ2_BASE + 29)
+#define INTERRUPT_VC_ARASANSDIO        (ARM_IRQ2_BASE + 30)
+#define INTERRUPT_AVSPMON              (ARM_IRQ2_BASE + 31)
+
+#define ARM_IRQ0_BASE                  64
+#define INTERRUPT_ARM_TIMER            (ARM_IRQ0_BASE + 0)
+#define INTERRUPT_ARM_MAILBOX          (ARM_IRQ0_BASE + 1)
+#define INTERRUPT_ARM_DOORBELL_0       (ARM_IRQ0_BASE + 2)
+#define INTERRUPT_ARM_DOORBELL_1       (ARM_IRQ0_BASE + 3)
+#define INTERRUPT_VPU0_HALTED          (ARM_IRQ0_BASE + 4)
+#define INTERRUPT_VPU1_HALTED          (ARM_IRQ0_BASE + 5)
+#define INTERRUPT_ILLEGAL_TYPE0        (ARM_IRQ0_BASE + 6)
+#define INTERRUPT_ILLEGAL_TYPE1        (ARM_IRQ0_BASE + 7)
+#define INTERRUPT_PENDING1             (ARM_IRQ0_BASE + 8)
+#define INTERRUPT_PENDING2             (ARM_IRQ0_BASE + 9)
+#define INTERRUPT_JPEG                 (ARM_IRQ0_BASE + 10)
+#define INTERRUPT_USB                  (ARM_IRQ0_BASE + 11)
+#define INTERRUPT_3D                   (ARM_IRQ0_BASE + 12)
+#define INTERRUPT_DMA2                 (ARM_IRQ0_BASE + 13)
+#define INTERRUPT_DMA3                 (ARM_IRQ0_BASE + 14)
+#define INTERRUPT_I2C                  (ARM_IRQ0_BASE + 15)
+#define INTERRUPT_SPI                  (ARM_IRQ0_BASE + 16)
+#define INTERRUPT_I2SPCM               (ARM_IRQ0_BASE + 17)
+#define INTERRUPT_SDIO                 (ARM_IRQ0_BASE + 18)
+#define INTERRUPT_UART                 (ARM_IRQ0_BASE + 19)
+#define INTERRUPT_ARASANSDIO           (ARM_IRQ0_BASE + 20)
-- 
2.5.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
                   ` (3 preceding siblings ...)
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals Andrew Baumann
@ 2015-12-24  0:25 ` Andrew Baumann
  2015-12-31  3:20   ` Peter Crosthwaite
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 6/7] bcm2836: add bcm2836 soc device Andrew Baumann
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

This module is specific to the bcm2836 (Pi2). It implements the top
level interrupt controller, and mailboxes used for inter-processor
synchronisation.

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---
 hw/intc/Makefile.objs             |   2 +-
 hw/intc/bcm2836_control.c         | 338 ++++++++++++++++++++++++++++++++++++++
 include/hw/intc/bcm2836_control.h |  51 ++++++
 3 files changed, 390 insertions(+), 1 deletion(-)
 create mode 100644 hw/intc/bcm2836_control.c
 create mode 100644 include/hw/intc/bcm2836_control.h

diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 2ad1204..6a13a39 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -24,7 +24,7 @@ obj-$(CONFIG_GRLIB) += grlib_irqmp.o
 obj-$(CONFIG_IOAPIC) += ioapic.o
 obj-$(CONFIG_OMAP) += omap_intc.o
 obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
-obj-$(CONFIG_RASPI) += bcm2835_ic.o
+obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
 obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
new file mode 100644
index 0000000..d68b4d9
--- /dev/null
+++ b/hw/intc/bcm2836_control.c
@@ -0,0 +1,338 @@
+/*
+ * Rasperry Pi 2 emulation ARM control logic module.
+ * Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * At present, only implements interrupt routing, and mailboxes (i.e.,
+ * not local timer, PMU interrupt, or AXI counters).
+ *
+ * Ref:
+ * https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf
+ *
+ * Based on bcm2835_ic.c, terms below...
+ */
+
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+/* Heavily based on pl190.c, copyright terms below. */
+
+/*
+ * Arm PrimeCell PL190 Vector Interrupt Controller
+ *
+ * Copyright (c) 2006 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/intc/bcm2836_control.h"
+
+#define ROUTE_CORE(x) ((x) & 0x3)
+#define ROUTE_FIQ(x)  (((x) & 0x4) != 0)
+
+#define IRQ_BIT(cntrl, num) (((cntrl) & (1 << (num))) != 0)
+#define FIQ_BIT(cntrl, num) (((cntrl) & (1 << ((num) + 4))) != 0)
+
+#define IRQ_CNTPSIRQ    0
+#define IRQ_CNTPNSIRQ   1
+#define IRQ_CNTHPIRQ    2
+#define IRQ_CNTVIRQ     3
+#define IRQ_MAILBOX0    4
+#define IRQ_MAILBOX1    5
+#define IRQ_MAILBOX2    6
+#define IRQ_MAILBOX3    7
+#define IRQ_GPU         8
+#define IRQ_PMU         9
+#define IRQ_AXI         10
+#define IRQ_TIMER       11
+#define IRQ_MAX         IRQ_TIMER
+
+/* Update interrupts.  */
+static void bcm2836_control_update(BCM2836ControlState *s)
+{
+    int i, j;
+
+    /*
+     * reset pending IRQs/FIQs
+     */
+
+    for (i = 0; i < BCM2836_NCORES; i++) {
+        s->irqsrc[i] = s->fiqsrc[i] = 0;
+    }
+
+    /*
+     * apply routing logic, update status regs
+     */
+
+    if (s->gpu_irq) {
+        assert(s->route_gpu_irq < BCM2836_NCORES);
+        s->irqsrc[s->route_gpu_irq] |= (uint32_t)1 << IRQ_GPU;
+    }
+
+    if (s->gpu_fiq) {
+        assert(s->route_gpu_fiq < BCM2836_NCORES);
+        s->fiqsrc[s->route_gpu_fiq] |= (uint32_t)1 << IRQ_GPU;
+    }
+
+    for (i = 0; i < BCM2836_NCORES; i++) {
+        /* handle local interrupts for this core */
+        if (s->localirqs[i]) {
+            assert(s->localirqs[i] < (1 << IRQ_MAILBOX0));
+            for (j = 0; j < IRQ_MAILBOX0; j++) {
+                if ((s->localirqs[i] & (1 << j)) != 0) {
+                    /* local interrupt j is set */
+                    if (FIQ_BIT(s->timercontrol[i], j)) {
+                        /* deliver a FIQ */
+                        s->fiqsrc[i] |= (uint32_t)1 << j;
+                    } else if (IRQ_BIT(s->timercontrol[i], j)) {
+                        /* deliver an IRQ */
+                        s->irqsrc[i] |= (uint32_t)1 << j;
+                    } else {
+                        /* the interrupt is masked */
+                    }
+                }
+            }
+        }
+
+        /* handle mailboxes for this core */
+        for (j = 0; j < BCM2836_MBPERCORE; j++) {
+            if (s->mailboxes[i * BCM2836_MBPERCORE + j] != 0) {
+                /* mailbox j is set */
+                if (FIQ_BIT(s->mailboxcontrol[i], j)) {
+                    /* deliver a FIQ */
+                    s->fiqsrc[i] |= (uint32_t)1 << (j + IRQ_MAILBOX0);
+                } else if (IRQ_BIT(s->mailboxcontrol[i], j)) {
+                    /* deliver an IRQ */
+                    s->irqsrc[i] |= (uint32_t)1 << (j + IRQ_MAILBOX0);
+                } else {
+                    /* the interrupt is masked */
+                }
+            }
+        }
+    }
+
+    /*
+     * call set_irq appropriately for each output
+     */
+
+    for (i = 0; i < BCM2836_NCORES; i++) {
+        qemu_set_irq(s->irq[i], s->irqsrc[i] != 0);
+        qemu_set_irq(s->fiq[i], s->fiqsrc[i] != 0);
+    }
+}
+
+static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
+                                          int level)
+{
+    BCM2836ControlState *s = opaque;
+
+    assert(core >= 0 && core < BCM2836_NCORES);
+    assert(local_irq >= 0 && local_irq <= IRQ_CNTVIRQ);
+
+    if (level) {
+        s->localirqs[core] |= 1 << local_irq;
+    } else {
+        s->localirqs[core] &= ~((uint32_t)1 << local_irq);
+    }
+
+    bcm2836_control_update(s);
+}
+
+/* XXX: the following wrapper functions are a kludgy workaround,
+ * needed because I can't seem to pass useful information in the "irq"
+ * parameter when using named interrupts. Feel free to clean this up!
+ */
+
+static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
+{
+    bcm2836_control_set_local_irq(opaque, core, 0, level);
+}
+
+static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
+{
+    bcm2836_control_set_local_irq(opaque, core, 1, level);
+}
+
+static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
+{
+    bcm2836_control_set_local_irq(opaque, core, 2, level);
+}
+
+static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
+{
+    bcm2836_control_set_local_irq(opaque, core, 3, level);
+}
+
+static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
+{
+    BCM2836ControlState *s = opaque;
+
+    s->gpu_irq = level;
+
+    bcm2836_control_update(s);
+}
+
+static void bcm2836_control_set_gpu_fiq(void *opaque, int irq, int level)
+{
+    BCM2836ControlState *s = opaque;
+
+    s->gpu_fiq = level;
+
+    bcm2836_control_update(s);
+}
+
+static uint64_t bcm2836_control_read(void *opaque, hwaddr offset, unsigned size)
+{
+    BCM2836ControlState *s = opaque;
+
+    if (offset == 0xc) {
+        /* GPU interrupt routing */
+        assert(s->route_gpu_fiq < BCM2836_NCORES
+               && s->route_gpu_irq < BCM2836_NCORES);
+        return ((uint32_t)s->route_gpu_fiq << 2) | s->route_gpu_irq;
+    } else if (offset >= 0x40 && offset < 0x50) {
+        /* Timer interrupt control registers */
+        return s->timercontrol[(offset - 0x40) >> 2];
+    } else if (offset >= 0x50 && offset < 0x60) {
+        /* Mailbox interrupt control registers */
+        return s->mailboxcontrol[(offset - 0x50) >> 2];
+    } else if (offset >= 0x60 && offset < 0x70) {
+        /* IRQ source registers */
+        return s->irqsrc[(offset - 0x60) >> 2];
+    } else if (offset >= 0x70 && offset < 0x80) {
+        /* FIQ source registers */
+        return s->fiqsrc[(offset - 0x70) >> 2];
+    } else if (offset >= 0xc0 && offset < 0x100) {
+        /* Mailboxes */
+        return s->mailboxes[(offset - 0xc0) >> 2];
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return 0;
+    }
+}
+
+static void bcm2836_control_write(void *opaque, hwaddr offset,
+                                  uint64_t val, unsigned size)
+{
+    BCM2836ControlState *s = opaque;
+
+    if (offset == 0xc) {
+        /* GPU interrupt routing */
+        s->route_gpu_irq = val & 0x3;
+        s->route_gpu_fiq = (val >> 2) & 0x3;
+    } else if (offset >= 0x40 && offset < 0x50) {
+        /* Timer interrupt control registers */
+        s->timercontrol[(offset - 0x40) >> 2] = val & 0xff;
+    } else if (offset >= 0x50 && offset < 0x60) {
+        /* Mailbox interrupt control registers */
+        s->mailboxcontrol[(offset - 0x50) >> 2] = val & 0xff;
+    } else if (offset >= 0x80 && offset < 0xc0) {
+        /* Mailbox set registers */
+        s->mailboxes[(offset - 0x80) >> 2] |= val;
+    } else if (offset >= 0xc0 && offset < 0x100) {
+        /* Mailbox clear registers */
+        s->mailboxes[(offset - 0xc0) >> 2] &= ~val;
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
+                      __func__, offset);
+        return;
+    }
+
+    bcm2836_control_update(s);
+}
+
+static const MemoryRegionOps bcm2836_control_ops = {
+    .read = bcm2836_control_read,
+    .write = bcm2836_control_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void bcm2836_control_reset(DeviceState *d)
+{
+    BCM2836ControlState *s = BCM2836_CONTROL(d);
+    int i;
+
+    s->route_gpu_irq = s->route_gpu_fiq = 0;
+
+    for (i = 0; i < BCM2836_NCORES; i++) {
+        s->timercontrol[i] = 0;
+        s->mailboxcontrol[i] = 0;
+    }
+
+    for (i = 0; i < BCM2836_NCORES * BCM2836_MBPERCORE; i++) {
+        s->mailboxes[i] = 0;
+    }
+}
+
+static void bcm2836_control_init(Object *obj)
+{
+    BCM2836ControlState *s = BCM2836_CONTROL(obj);
+    DeviceState *dev = DEVICE(obj);
+
+    memory_region_init_io(&s->iomem, obj, &bcm2836_control_ops, s,
+                          TYPE_BCM2836_CONTROL, 0x100);
+    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
+
+    /* inputs from each CPU core */
+    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq0, "cntpsirq",
+                            BCM2836_NCORES);
+    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq1, "cntpnsirq",
+                            BCM2836_NCORES);
+    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq2, "cnthpirq",
+                            BCM2836_NCORES);
+    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq3, "cntvirq",
+                            BCM2836_NCORES);
+    /* qdev_init_gpio_in_named(dev, bcm2836_control_set_pmu_irq, "pmuirq",
+                            BCM2836_NCORES); */
+
+    /* IRQ and FIQ inputs from upstream bcm2835 controller */
+    qdev_init_gpio_in_named(dev, bcm2836_control_set_gpu_irq, "gpu_irq", 1);
+    qdev_init_gpio_in_named(dev, bcm2836_control_set_gpu_fiq, "gpu_fiq", 1);
+
+    /* outputs to CPU cores */
+    qdev_init_gpio_out_named(dev, s->irq, "irq", BCM2836_NCORES);
+    qdev_init_gpio_out_named(dev, s->fiq, "fiq", BCM2836_NCORES);
+}
+
+static const VMStateDescription vmstate_bcm2836_control = {
+    .name = TYPE_BCM2836_CONTROL,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(mailboxes, BCM2836ControlState,
+                             BCM2836_NCORES * BCM2836_MBPERCORE),
+        VMSTATE_UINT8(route_gpu_irq, BCM2836ControlState),
+        VMSTATE_UINT8(route_gpu_fiq, BCM2836ControlState),
+        VMSTATE_UINT32_ARRAY(timercontrol, BCM2836ControlState, BCM2836_NCORES),
+        VMSTATE_UINT32_ARRAY(mailboxcontrol, BCM2836ControlState,
+                             BCM2836_NCORES),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void bcm2836_control_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = bcm2836_control_reset;
+    dc->vmsd = &vmstate_bcm2836_control;
+}
+
+static TypeInfo bcm2836_control_info = {
+    .name          = TYPE_BCM2836_CONTROL,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BCM2836ControlState),
+    .class_init    = bcm2836_control_class_init,
+    .instance_init = bcm2836_control_init,
+};
+
+static void bcm2836_control_register_types(void)
+{
+    type_register_static(&bcm2836_control_info);
+}
+
+type_init(bcm2836_control_register_types)
diff --git a/include/hw/intc/bcm2836_control.h b/include/hw/intc/bcm2836_control.h
new file mode 100644
index 0000000..8a9a2f2
--- /dev/null
+++ b/include/hw/intc/bcm2836_control.h
@@ -0,0 +1,51 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2836_CONTROL_H
+#define BCM2836_CONTROL_H
+
+#include "hw/sysbus.h"
+
+/* 4 mailboxes per core, for 16 total */
+#define BCM2836_NCORES 4
+#define BCM2836_MBPERCORE 4
+
+#define TYPE_BCM2836_CONTROL "bcm2836_control"
+#define BCM2836_CONTROL(obj) \
+    OBJECT_CHECK(BCM2836ControlState, (obj), TYPE_BCM2836_CONTROL)
+
+typedef struct BCM2836ControlState {
+    /*< private >*/
+    SysBusDevice busdev;
+    /*< public >*/
+    MemoryRegion iomem;
+
+    /* interrupt status registers (not directly visible to user) */
+    bool gpu_irq, gpu_fiq;
+    uint32_t localirqs[BCM2836_NCORES];
+
+    /* mailboxes */
+    uint32_t mailboxes[BCM2836_NCORES * BCM2836_MBPERCORE];
+
+    /* interrupt routing/control registers */
+    uint8_t route_gpu_irq, route_gpu_fiq;
+    uint32_t timercontrol[BCM2836_NCORES];
+    uint32_t mailboxcontrol[BCM2836_NCORES];
+
+    /* interrupt source registers, post-routing (visible) */
+    uint32_t irqsrc[BCM2836_NCORES];
+    uint32_t fiqsrc[BCM2836_NCORES];
+
+    /* outputs to CPU cores */
+    qemu_irq irq[BCM2836_NCORES];
+    qemu_irq fiq[BCM2836_NCORES];
+} BCM2836ControlState;
+
+#endif
-- 
2.5.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v2 6/7] bcm2836: add bcm2836 soc device
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
                   ` (4 preceding siblings ...)
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic Andrew Baumann
@ 2015-12-24  0:25 ` Andrew Baumann
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 7/7] raspi: add raspberry pi 2 machine Andrew Baumann
  2015-12-31  1:13 ` [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Piotr Król
  7 siblings, 0 replies; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

This is the SoC for Raspberry Pi 2.

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---
 hw/arm/Makefile.objs     |   2 +-
 hw/arm/bcm2836.c         | 135 +++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/arm/bcm2836.h |  33 ++++++++++++
 3 files changed, 169 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/bcm2836.c
 create mode 100644 include/hw/arm/bcm2836.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 82cc142..f55f8d2 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -11,7 +11,7 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-$(CONFIG_DIGIC) += digic.o
 obj-y += omap1.o omap2.o strongarm.o
 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
-obj-$(CONFIG_RASPI) += bcm2835_peripherals.o
+obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o
 obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
 obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
 obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
new file mode 100644
index 0000000..4b0544e
--- /dev/null
+++ b/hw/arm/bcm2836.c
@@ -0,0 +1,135 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#include "hw/arm/bcm2836.h"
+#include "hw/arm/raspi_platform.h"
+#include "hw/sysbus.h"
+#include "sysemu/sysemu.h" /* for smp_cpus */
+#include "exec/address-spaces.h"
+
+static void bcm2836_init(Object *obj)
+{
+    BCM2836State *s = BCM2836(obj);
+    int n;
+
+    /* TODO: probably shouldn't be using smp_cpus here */
+    assert(smp_cpus <= BCM2836_NCPUS);
+    for (n = 0; n < smp_cpus; n++) {
+        object_initialize(&s->cpus[n], sizeof(s->cpus[n]),
+                          "cortex-a15-" TYPE_ARM_CPU);
+        object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]),
+                                  &error_abort);
+    }
+
+    object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2836_CONTROL);
+    object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL);
+    qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default());
+
+    object_initialize(&s->peripherals, sizeof(s->peripherals),
+                      TYPE_BCM2835_PERIPHERALS);
+    object_property_add_child(obj, "peripherals", OBJECT(&s->peripherals),
+                              &error_abort);
+    qdev_set_parent_bus(DEVICE(&s->peripherals), sysbus_get_default());
+}
+
+static void bcm2836_realize(DeviceState *dev, Error **errp)
+{
+    BCM2836State *s = BCM2836(dev);
+    Error *err = NULL;
+    int n;
+
+    /* common peripherals from bcm2835 */
+    object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
+                            BCM2836_PERI_BASE, 1);
+
+    /* bcm2836 interrupt controller (and mailboxes, etc.) */
+    object_property_set_bool(OBJECT(&s->ic), true, "realized", &err);
+    if (err) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(&s->ic), 0, BCM2836_CONTROL_BASE);
+
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
+                       qdev_get_gpio_in_named(DEVICE(&s->ic), "gpu_irq", 0));
+    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
+                       qdev_get_gpio_in_named(DEVICE(&s->ic), "gpu_fiq", 0));
+
+    /* TODO: probably shouldn't be using smp_cpus here */
+    assert(smp_cpus <= BCM2836_NCPUS);
+    for (n = 0; n < smp_cpus; n++) {
+        /* Mirror bcm2836, which has clusterid set to 0xf */
+        s->cpus[n].mp_affinity = 0xF00 | n;
+
+        /* set periphbase/CBAR value for CPU-local registers */
+        object_property_set_int(OBJECT(&s->cpus[n]),
+                                BCM2836_PERI_BASE + MCORE_OFFSET,
+                                "reset-cbar", &err);
+        if (err) {
+            error_report_err(err);
+            exit(1);
+        }
+
+        object_property_set_bool(OBJECT(&s->cpus[n]), true, "realized", &err);
+        if (err) {
+            error_report_err(err);
+            exit(1);
+        }
+
+        /* Connect irq/fiq outputs from the interrupt controller. */
+        qdev_connect_gpio_out_named(DEVICE(&s->ic), "irq", n,
+                                    qdev_get_gpio_in(DEVICE(&s->cpus[n]),
+                                                     ARM_CPU_IRQ));
+        qdev_connect_gpio_out_named(DEVICE(&s->ic), "fiq", n,
+                                    qdev_get_gpio_in(DEVICE(&s->cpus[n]),
+                                                     ARM_CPU_FIQ));
+
+        /* Connect timers from the CPU to the interrupt controller */
+        s->cpus[n].gt_timer_outputs[GTIMER_PHYS]
+            = qdev_get_gpio_in_named(DEVICE(&s->ic), "cntpsirq", 0);
+        s->cpus[n].gt_timer_outputs[GTIMER_VIRT]
+            = qdev_get_gpio_in_named(DEVICE(&s->ic), "cntvirq", 0);
+    }
+}
+
+static void bcm2836_class_init(ObjectClass *oc, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(oc);
+
+    dc->realize = bcm2836_realize;
+
+    /*
+     * Reason: creates an ARM CPU, thus use after free(), see
+     * arm_cpu_class_init()
+     */
+    dc->cannot_destroy_with_object_finalize_yet = true;
+}
+
+static const TypeInfo bcm2836_type_info = {
+    .name = TYPE_BCM2836,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(BCM2836State),
+    .instance_init = bcm2836_init,
+    .class_init = bcm2836_class_init,
+};
+
+static void bcm2836_register_types(void)
+{
+    type_register_static(&bcm2836_type_info);
+}
+
+type_init(bcm2836_register_types)
diff --git a/include/hw/arm/bcm2836.h b/include/hw/arm/bcm2836.h
new file mode 100644
index 0000000..a78e919
--- /dev/null
+++ b/include/hw/arm/bcm2836.h
@@ -0,0 +1,33 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+#ifndef BCM2836_H
+#define BCM2836_H
+
+#include "hw/arm/arm.h"
+#include "hw/arm/bcm2835_peripherals.h"
+#include "hw/intc/bcm2836_control.h"
+
+#define TYPE_BCM2836 "bcm2836"
+#define BCM2836(obj) OBJECT_CHECK(BCM2836State, (obj), TYPE_BCM2836)
+
+#define BCM2836_NCPUS 4
+
+typedef struct BCM2836State {
+    /*< private >*/
+    DeviceState parent_obj;
+    /*< public >*/
+
+    ARMCPU cpus[BCM2836_NCPUS];
+    BCM2836ControlState ic;
+    BCM2835PeripheralState peripherals;
+} BCM2836State;
+
+#endif /* BCM2836_H */
-- 
2.5.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Qemu-devel] [PATCH v2 7/7] raspi: add raspberry pi 2 machine
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
                   ` (5 preceding siblings ...)
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 6/7] bcm2836: add bcm2836 soc device Andrew Baumann
@ 2015-12-24  0:25 ` Andrew Baumann
  2015-12-31  1:13 ` [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Piotr Król
  7 siblings, 0 replies; 22+ messages in thread
From: Andrew Baumann @ 2015-12-24  0:25 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, Andrew Baumann, qemu-arm, Paolo Bonzini

bcm2835/Pi1 requires more peripherals, and will be added in a later
patch series.

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---
 hw/arm/Makefile.objs |   2 +-
 hw/arm/raspi.c       | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 180 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/raspi.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index f55f8d2..a711e4d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -11,7 +11,7 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
 obj-$(CONFIG_DIGIC) += digic.o
 obj-y += omap1.o omap2.o strongarm.o
 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
-obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o
+obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
 obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
 obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
 obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
new file mode 100644
index 0000000..cc80c56
--- /dev/null
+++ b/hw/arm/raspi.c
@@ -0,0 +1,179 @@
+/*
+ * Raspberry Pi emulation (c) 2012 Gregory Estrade
+ * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
+ *
+ * Rasperry Pi 2 emulation Copyright (c) 2015, Microsoft
+ * Written by Andrew Baumann
+ *
+ * This code is licensed under the GNU GPLv2 and later.
+ */
+
+/* Based on versatilepb.c, copyright terms below. */
+
+/*
+ * ARM Versatile Platform/Application Baseboard System emulation.
+ *
+ * Copyright (c) 2005-2007 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licensed under the GPL.
+ */
+
+#include "hw/arm/bcm2836.h"
+#include "qemu/error-report.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/arm/arm.h"
+#include "sysemu/sysemu.h"
+#include "hw/arm/raspi_platform.h"
+
+#define SMPBOOT_ADDR    0x300 /* this should leave enough space for ATAGS */
+#define MVBAR_ADDR      0x400 /* secure vectors */
+#define BOARDSETUP_ADDR (MVBAR_ADDR + 0x20) /* board setup code */
+#define FIRMWARE_ADDR   0x8000 /* Pi loads kernel.img here by default */
+
+/* Table of Linux board IDs for different Pi versions */
+static const int raspi_boardid[] = {[1] = 0xc42, [2] = 0xc43};
+
+typedef struct RaspiMachineState {
+    union {
+        Object obj;
+        BCM2836State pi2;
+    } soc;
+    MemoryRegion ram;
+} RaspiMachineState;
+
+static void write_smpboot(ARMCPU *cpu, const struct arm_boot_info *info)
+{
+    static const uint32_t smpboot[] = {
+        0xE1A0E00F, /*    mov     lr, pc */
+        0xE3A0FE42, /*    mov     pc, #0x420           ;call BOARDSETUP_ADDR */
+        0xEE100FB0, /*    mrc     p15, 0, r0, c0, c0, 5;get core ID */
+        0xE7E10050, /*    ubfx    r0, r0, #0, #2       ;extract LSB */
+        0xE59F5014, /*    ldr     r5, =0x400000CC      ;load mbox base */
+        0xE320F001, /* 1: yield */
+        0xE7953200, /*    ldr     r3, [r5, r0, lsl #4] ;read mbox for our core*/
+        0xE3530000, /*    cmp     r3, #0               ;spin while zero */
+        0x0AFFFFFB, /*    beq     1b */
+        0xE7853200, /*    str     r3, [r5, r0, lsl #4] ;clear mbox */
+        0xE12FFF13, /*    bx      r3                   ;jump to target */
+        0x400000CC, /* (constant: mailbox 3 read/clear base) */
+    };
+
+    assert(SMPBOOT_ADDR + sizeof(smpboot) <= MVBAR_ADDR);
+    rom_add_blob_fixed("raspi_smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
+static void write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info)
+{
+    static const uint32_t board_setup[] = {
+        /* MVBAR_ADDR: secure monitor vectors */
+        0xEAFFFFFE, /* (spin) */
+        0xEAFFFFFE, /* (spin) */
+        0xE1B0F00E, /* movs pc, lr ;SMC exception return */
+        0xEAFFFFFE, /* (spin) */
+        0xEAFFFFFE, /* (spin) */
+        0xEAFFFFFE, /* (spin) */
+        0xEAFFFFFE, /* (spin) */
+        0xEAFFFFFE, /* (spin) */
+        /* BOARDSETUP_ADDR */
+        0xE3A00B01, /* mov     r0, #0x400             ;MVBAR_ADDR */
+        0xEE0C0F30, /* mcr     p15, 0, r0, c12, c0, 1 ;set MVBAR */
+        0xE3000131, /* movw    r0, #0x131             ;enable HVC, AW, FW, NS */
+        0xEE010F11, /* mcr     p15, 0, r0, c1, c1, 0  ;write SCR */
+        0xE1A0100E, /* mov     r1, lr                 ;save LR across SMC */
+        0xE1600070, /* smc     #0                     ;monitor call */
+        0xE1A0F001, /* mov     pc, r1                 ;return */
+    };
+
+    rom_add_blob_fixed("raspi_boardsetup", board_setup, sizeof(board_setup),
+                       MVBAR_ADDR);
+}
+
+static void reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
+{
+    CPUState *cs = CPU(cpu);
+    cpu_set_pc(cs, info->smp_loader_start);
+}
+
+static void setup_boot(MachineState *machine, int version, size_t ram_size)
+{
+    static struct arm_boot_info binfo;
+    int r;
+
+    binfo.board_id = raspi_boardid[version];
+    binfo.ram_size = ram_size;
+    binfo.nb_cpus = smp_cpus;
+
+    /* Pi2 supports security extensions, which require special setup code */
+    if (version == 2) {
+        binfo.smp_loader_start = SMPBOOT_ADDR,
+        binfo.write_secondary_boot = write_smpboot,
+        binfo.secondary_cpu_reset_hook = reset_secondary,
+        binfo.board_setup_addr = BOARDSETUP_ADDR;
+        binfo.write_board_setup = write_board_setup;
+        binfo.secure_board_setup = true;
+        binfo.secure_boot = true;
+    }
+
+    /* If the user specified a "firmware" image (e.g. UEFI), we bypass
+       the normal Linux boot process */
+    if (machine->firmware) {
+        /* load the firmware image (typically kernel.img) */
+        r = load_image_targphys(machine->firmware, FIRMWARE_ADDR,
+                                ram_size - FIRMWARE_ADDR);
+        if (r < 0) {
+            error_report("Failed to load firmware from %s", machine->firmware);
+            exit(1);
+        }
+
+        /* set variables so arm_load_kernel does the right thing */
+        binfo.entry = FIRMWARE_ADDR;
+        binfo.firmware_loaded = true;
+    } else {
+        /* Just let arm_load_kernel do everything for us... */
+        binfo.kernel_filename = machine->kernel_filename;
+        binfo.kernel_cmdline = machine->kernel_cmdline;
+        binfo.initrd_filename = machine->initrd_filename;
+    }
+
+    arm_load_kernel(ARM_CPU(first_cpu), &binfo);
+}
+
+static void raspi2_init(MachineState *machine)
+{
+    RaspiMachineState *s = g_new0(RaspiMachineState, 1);
+
+    /* Initialise the SOC */
+    object_initialize(&s->soc.pi2, sizeof(s->soc.pi2), TYPE_BCM2836);
+    object_property_add_child(OBJECT(machine), "soc", &s->soc.obj,
+                              &error_abort);
+
+    /* Allocate and map RAM */
+    memory_region_allocate_system_memory(&s->ram, OBJECT(machine), "ram",
+                                         machine->ram_size);
+    memory_region_add_subregion_overlap(get_system_memory(), 0, &s->ram, 0);
+
+    /* Setup the SOC */
+    object_property_set_bool(&s->soc.obj, true, "realized", &error_abort);
+
+    /* Boot! */
+    setup_boot(machine, 2, machine->ram_size);
+}
+
+static void raspi2_machine_init(MachineClass *mc)
+{
+    mc->desc = "Raspberry Pi 2";
+    mc->init = raspi2_init;
+    mc->block_default_type = IF_SD;
+    mc->no_parallel = 1;
+    mc->no_floppy = 1;
+    mc->no_cdrom = 1;
+    mc->max_cpus = BCM2836_NCPUS;
+    /* XXX: Temporary restriction in RAM size from the full 1GB. Since
+     * we do not yet support the framebuffer / GPU, we need to limit
+     * RAM usable by the OS to sit below the peripherals. */
+    mc->default_ram_size = BCM2836_PERI_BASE;
+};
+DEFINE_MACHINE("raspi2", raspi2_machine_init)
-- 
2.5.3

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes Andrew Baumann
@ 2015-12-31  0:12   ` Peter Crosthwaite
  2015-12-31 18:06     ` Andrew Baumann
  0 siblings, 1 reply; 22+ messages in thread
From: Peter Crosthwaite @ 2015-12-31  0:12 UTC (permalink / raw)
  To: Andrew Baumann
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, qemu-devel@nongnu.org Developers, qemu-arm,
	Paolo Bonzini

On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
<Andrew.Baumann@microsoft.com> wrote:
> This adds the system mailboxes which are used to communicate with a
> number of GPU peripherals on Pi/Pi2.
>
> Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> ---
>
> Notes:
>     v2:
>      * renamed bcm2835_sbm to bcm2835_mbox
>      * dropped bcm2835_arm_control.h (needed defs moved to bcm2835_mbox.c)
>      * documented use of private address space through defines in bcm2835_mbox_defs.h
>      * remove unused fields from BCM2835Mbox
>      * s/int/bool/ where appropriate
>      * cleaned up logic in _update and _mbox_update_status for clarity/simplicity
>      * added vmstate
>      * misc cleanup
>
>  default-configs/arm-softmmu.mak     |   1 +
>  hw/misc/Makefile.objs               |   1 +
>  hw/misc/bcm2835_mbox.c              | 323 ++++++++++++++++++++++++++++++++++++
>  include/hw/misc/bcm2835_mbox.h      |  37 +++++
>  include/hw/misc/bcm2835_mbox_defs.h |  26 +++
>  5 files changed, 388 insertions(+)
>  create mode 100644 hw/misc/bcm2835_mbox.c
>  create mode 100644 include/hw/misc/bcm2835_mbox.h
>  create mode 100644 include/hw/misc/bcm2835_mbox_defs.h
>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index d9b90a5..a9f82a1 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -79,6 +79,7 @@ CONFIG_TUSB6010=y
>  CONFIG_IMX=y
>  CONFIG_MAINSTONE=y
>  CONFIG_NSERIES=y
> +CONFIG_RASPI=y
>  CONFIG_REALVIEW=y
>  CONFIG_ZAURUS=y
>  CONFIG_ZYNQ=y
> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
> index aeb6b7d..e36f2ee 100644
> --- a/hw/misc/Makefile.objs
> +++ b/hw/misc/Makefile.objs
> @@ -34,6 +34,7 @@ obj-$(CONFIG_OMAP) += omap_gpmc.o
>  obj-$(CONFIG_OMAP) += omap_l4.o
>  obj-$(CONFIG_OMAP) += omap_sdrc.o
>  obj-$(CONFIG_OMAP) += omap_tap.o
> +obj-$(CONFIG_RASPI) += bcm2835_mbox.o
>  obj-$(CONFIG_SLAVIO) += slavio_misc.o
>  obj-$(CONFIG_ZYNQ) += zynq_slcr.o
>  obj-$(CONFIG_ZYNQ) += zynq-xadc.o
> diff --git a/hw/misc/bcm2835_mbox.c b/hw/misc/bcm2835_mbox.c
> new file mode 100644
> index 0000000..69b8e2a
> --- /dev/null
> +++ b/hw/misc/bcm2835_mbox.c
> @@ -0,0 +1,323 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade

Should we change this to "Broadcom SoC emulation"?

> + * This code is licensed under the GNU GPLv2 and later.
> + *
> + * This file models the system mailboxes, which are used for
> + * communication with low-bandwidth GPU peripherals. Refs:
> + *   https://github.com/raspberrypi/firmware/wiki/Mailboxes
> + *   https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes
> + */
> +
> +#include "hw/misc/bcm2835_mbox.h"
> +
> +/* Mailbox status register (...0x98) */

So the reg offsets could be MACRO defined here to avoid having to to
comment 0x98 (and 0x9c) is two places.

> +#define ARM_MS_FULL       0x80000000
> +#define ARM_MS_EMPTY      0x40000000
> +#define ARM_MS_LEVEL      0x400000FF /* Max. value depends on mailbox depth */
> +
> +/* MAILBOX config/status register (...0x9C) */
> +/* ANY write to this register clears the error bits! */
> +#define ARM_MC_IHAVEDATAIRQEN    0x00000001 /* mbox irq enable:  has data */
> +#define ARM_MC_IHAVESPACEIRQEN   0x00000002 /* mbox irq enable:  has space */
> +#define ARM_MC_OPPISEMPTYIRQEN   0x00000004 /* mbox irq enable: Opp is empty */
> +#define ARM_MC_MAIL_CLEAR        0x00000008 /* mbox clear write 1, then  0 */
> +#define ARM_MC_IHAVEDATAIRQPEND  0x00000010 /* mbox irq pending:  has space */
> +#define ARM_MC_IHAVESPACEIRQPEND 0x00000020 /* mbox irq pending: Opp is empty */
> +#define ARM_MC_OPPISEMPTYIRQPEND 0x00000040 /* mbox irq pending */
> +/* Bit 7 is unused */
> +#define ARM_MC_ERRNOOWN   0x00000100 /* error : none owner read from mailbox */
> +#define ARM_MC_ERROVERFLW 0x00000200 /* error : write to fill mailbox */
> +#define ARM_MC_ERRUNDRFLW 0x00000400 /* error : read from empty mailbox */
> +
> +static void mbox_update_status(BCM2835Mbox *mb)
> +{
> +    mb->status &= ~(ARM_MS_EMPTY | ARM_MS_FULL);
> +    if (mb->count == 0) {
> +        mb->status |= ARM_MS_EMPTY;
> +    } else if (mb->count == MBOX_SIZE) {
> +        mb->status |= ARM_MS_FULL;
> +    }
> +}
> +
> +static void mbox_init(BCM2835Mbox *mb)

mbox_reset

> +{
> +    int n;
> +
> +    mb->count = 0;
> +    mb->config = 0;
> +    for (n = 0; n < MBOX_SIZE; n++) {
> +        mb->reg[n] = MBOX_INVALID_DATA;
> +    }
> +    mbox_update_status(mb);
> +}
> +
> +static uint32_t mbox_pull(BCM2835Mbox *mb, int index)
> +{
> +    int n;
> +    uint32_t val;
> +
> +    assert(mb->count > 0);
> +    assert(index < mb->count);
> +
> +    val = mb->reg[index];
> +    for (n = index + 1; n < mb->count; n++) {
> +        mb->reg[n - 1] = mb->reg[n];
> +    }
> +    mb->count--;
> +    mb->reg[mb->count] = MBOX_INVALID_DATA;
> +
> +    mbox_update_status(mb);
> +
> +    return val;
> +}
> +
> +static void mbox_push(BCM2835Mbox *mb, uint32_t val)
> +{
> +    assert(mb->count < MBOX_SIZE);

mbox_update can call mbox_push with val == a DMA value, which usually
suggests that this may be a guest controllable (and a guest error
rather than an assert). Is the mbox AS guest accessible? (I had a look
at the later patches, and the MBox AS seems private but can values be
set via the guest indirectly?).

> +    mb->reg[mb->count++] = val;
> +    mbox_update_status(mb);
> +}
> +
> +static void bcm2835_mbox_update(BCM2835MboxState *s)
> +{
> +    uint32_t value;
> +    bool set;
> +    int n;
> +
> +    /* Avoid unwanted recursive calls */

You should really only need to comment this idea the once. The one
below is more informative so you can drop this.

> +    s->mbox_irq_disabled = true;
> +
> +    /* Get pending responses and put them in the vc->arm mbox,
> +     * as long as it's not full */
> +    for (n = 0; n < MBOX_CHAN_COUNT; n++) {
> +        while (s->available[n] && !(s->mbox[0].status & ARM_MS_FULL)) {
> +            value = ldl_phys(&s->mbox_as, n << MBOX_AS_CHAN_SHIFT);
> +            if (value == MBOX_INVALID_DATA) {
> +                /* Interrupt pending, but there's no data. Hmmm... */
> +                hw_error("%s: spurious interrupt on channel %d", __func__, n);

hw_error should be avoided, it should be an assert for something if
this is a QEMU code error, or LOG_GUEST_ERROR or LOG_UNIMP.

> +            }
> +            mbox_push(&s->mbox[0], value);
> +        }
> +    }
> +
> +    /* Try to push pending requests from the arm->vc mbox */
> +    /* TODO (?) */
> +
> +    /* Re-enable calls from the IRQ routine */
> +    s->mbox_irq_disabled = false;
> +
> +    /* Update ARM IRQ status */
> +    set = false;
> +    s->mbox[0].config &= ~ARM_MC_IHAVEDATAIRQPEND;
> +    if (!(s->mbox[0].status & ARM_MS_EMPTY)) {
> +        s->mbox[0].config |= ARM_MC_IHAVEDATAIRQPEND;
> +        if (s->mbox[0].config & ARM_MC_IHAVEDATAIRQEN) {
> +            set = true;
> +        }
> +    }
> +    qemu_set_irq(s->arm_irq, set);
> +}
> +
> +static void bcm2835_mbox_set_irq(void *opaque, int irq, int level)
> +{
> +    BCM2835MboxState *s = opaque;
> +
> +    s->available[irq] = level;
> +
> +    /* avoid recursively calling bcm2835_mbox_update when the interrupt
> +     * status changes due to the ldl_phys call within that function */

Space before */

> +    if (!s->mbox_irq_disabled) {
> +        bcm2835_mbox_update(s);
> +    }
> +}
> +
> +static uint64_t bcm2835_mbox_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    BCM2835MboxState *s = opaque;
> +    uint32_t res = 0;
> +
> +    offset &= 0xff;
> +
> +    switch (offset) {
> +    case 0x80 ... 0x8c:  /* MAIL0_READ */
> +        if (s->mbox[0].status & ARM_MS_EMPTY) {
> +            res = MBOX_INVALID_DATA;
> +        } else {
> +            res = mbox_pull(&s->mbox[0], 0);
> +        }
> +        break;
> +    case 0x90:  /* MAIL0_PEEK */
> +        res = s->mbox[0].reg[0];
> +        break;
> +    case 0x94:  /* MAIL0_SENDER */
> +        break;
> +    case 0x98:  /* MAIL0_STATUS */
> +        res = s->mbox[0].status;
> +        break;
> +    case 0x9c:  /* MAIL0_CONFIG */
> +        res = s->mbox[0].config;
> +        break;

Blank line here (you seem to logically break the switches below in the
write handler).

> +    case 0xb8:  /* MAIL1_STATUS */
> +        res = s->mbox[1].status;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return 0;
> +    }
> +
> +    bcm2835_mbox_update(s);
> +
> +    return res;
> +}
> +
> +static void bcm2835_mbox_write(void *opaque, hwaddr offset,
> +                               uint64_t value, unsigned size)
> +{
> +    BCM2835MboxState *s = opaque;
> +    hwaddr childaddr;
> +    uint8_t ch;
> +
> +    offset &= 0xff;
> +
> +    switch (offset) {
> +    case 0x94:  /* MAIL0_SENDER */
> +        break;
> +
> +    case 0x9c:  /* MAIL0_CONFIG */
> +        s->mbox[0].config &= ~ARM_MC_IHAVEDATAIRQEN;
> +        s->mbox[0].config |= value & ARM_MC_IHAVEDATAIRQEN;
> +        break;
> +
> +    case 0xa0 ... 0xac:
> +        if (s->mbox[1].status & ARM_MS_FULL) {
> +            /* Mailbox full */
> +            qemu_log_mask(LOG_GUEST_ERROR, "%s: mailbox full\n", __func__);
> +        } else {
> +            ch = value & 0xf;
> +            if (ch < MBOX_CHAN_COUNT) {
> +                childaddr = ch << MBOX_AS_CHAN_SHIFT;
> +                if (ldl_phys(&s->mbox_as, childaddr + MBOX_AS_PENDING)) {
> +                    /* Child busy, push delayed. Push it in the arm->vc mbox */
> +                    mbox_push(&s->mbox[1], value);
> +                } else {
> +                    /* Push it directly to the child device */
> +                    stl_phys(&s->mbox_as, childaddr, value);
> +                }
> +            } else {
> +                /* Invalid channel number */
> +                qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid channel %u\n",
> +                              __func__, ch);
> +            }
> +        }
> +        break;
> +
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return;
> +    }
> +
> +    bcm2835_mbox_update(s);
> +}
> +
> +static const MemoryRegionOps bcm2835_mbox_ops = {
> +    .read = bcm2835_mbox_read,
> +    .write = bcm2835_mbox_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .valid.min_access_size = 4,
> +    .valid.max_access_size = 4,
> +};
> +
> +/* vmstate of a single mailbox */
> +static const VMStateDescription vmstate_bcm2835_mbox_box = {
> +    .name = TYPE_BCM2835_MBOX "_box",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32_ARRAY(reg, BCM2835Mbox, MBOX_SIZE),
> +        VMSTATE_UINT32(count, BCM2835Mbox),
> +        VMSTATE_UINT32(status, BCM2835Mbox),
> +        VMSTATE_UINT32(config, BCM2835Mbox),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +/* vmstate of the entire device */
> +static const VMStateDescription vmstate_bcm2835_mbox = {
> +    .name = TYPE_BCM2835_MBOX,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_BOOL_ARRAY(available, BCM2835MboxState, MBOX_CHAN_COUNT),
> +        VMSTATE_STRUCT_ARRAY(mbox, BCM2835MboxState, 2, 1,
> +                             vmstate_bcm2835_mbox_box, BCM2835Mbox),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void bcm2835_mbox_init(Object *obj)
> +{
> +    BCM2835MboxState *s = BCM2835_MBOX(obj);

Blank line here.

> +    memory_region_init_io(&s->iomem, obj, &bcm2835_mbox_ops, s,
> +                          TYPE_BCM2835_MBOX, 0x400);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->arm_irq);
> +    qdev_init_gpio_in(DEVICE(s), bcm2835_mbox_set_irq, MBOX_CHAN_COUNT);
> +}
> +
> +static void bcm2835_mbox_reset(DeviceState *dev)
> +{
> +    BCM2835MboxState *s = BCM2835_MBOX(dev);
> +    int n;
> +
> +    mbox_init(&s->mbox[0]);
> +    mbox_init(&s->mbox[1]);
> +    s->mbox_irq_disabled = false;
> +    for (n = 0; n < MBOX_CHAN_COUNT; n++) {
> +        s->available[n] = false;
> +    }
> +}
> +
> +static void bcm2835_mbox_realize(DeviceState *dev, Error **errp)
> +{
> +    BCM2835MboxState *s = BCM2835_MBOX(dev);
> +    Object *obj;
> +    Error *err = NULL;
> +
> +    obj = object_property_get_link(OBJECT(dev), "mbox_mr", &err);

Link property should be - rather than _.

> +    if (obj == NULL) {
> +        error_setg(errp, "%s: required mbox_mr link not found: %s",
> +                   __func__, error_get_pretty(err));
> +        return;
> +    }
> +
> +    s->mbox_mr = MEMORY_REGION(obj);
> +    address_space_init(&s->mbox_as, s->mbox_mr, NULL);
> +    bcm2835_mbox_reset(dev);
> +}
> +
> +static void bcm2835_mbox_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = bcm2835_mbox_realize;
> +    dc->reset = bcm2835_mbox_reset;
> +    dc->vmsd = &vmstate_bcm2835_mbox;
> +}
> +
> +static TypeInfo bcm2835_mbox_info = {
> +    .name          = TYPE_BCM2835_MBOX,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(BCM2835MboxState),
> +    .class_init    = bcm2835_mbox_class_init,
> +    .instance_init = bcm2835_mbox_init,
> +};
> +
> +static void bcm2835_mbox_register_types(void)
> +{
> +    type_register_static(&bcm2835_mbox_info);
> +}
> +
> +type_init(bcm2835_mbox_register_types)
> diff --git a/include/hw/misc/bcm2835_mbox.h b/include/hw/misc/bcm2835_mbox.h
> new file mode 100644
> index 0000000..f24560c
> --- /dev/null
> +++ b/include/hw/misc/bcm2835_mbox.h
> @@ -0,0 +1,37 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2835_MBOX_H
> +#define BCM2835_MBOX_H
> +
> +#include "bcm2835_mbox_defs.h"
> +#include "hw/sysbus.h"
> +#include "exec/address-spaces.h"
> +
> +#define TYPE_BCM2835_MBOX "bcm2835_mbox"

Type name should be - separated not _. With machine configs and device
hotplug, typenames and properties have backwards compatibility issues
so we want to get them straight from the start.

> +#define BCM2835_MBOX(obj) \
> +        OBJECT_CHECK(BCM2835MboxState, (obj), TYPE_BCM2835_MBOX)
> +
> +typedef struct {
> +    uint32_t reg[MBOX_SIZE];
> +    uint32_t count;
> +    uint32_t status;
> +    uint32_t config;
> +} BCM2835Mbox;
> +
> +typedef struct {
> +    /*< private >*/
> +    SysBusDevice busdev;
> +    /*< public >*/
> +    MemoryRegion *mbox_mr;
> +    AddressSpace mbox_as;
> +    MemoryRegion iomem;
> +    bool mbox_irq_disabled;
> +    qemu_irq arm_irq;

I would move this one-up to before irq_disabled to avoid mixing io and
internal state defs.

> +    bool available[MBOX_CHAN_COUNT];
> +    BCM2835Mbox mbox[2];
> +} BCM2835MboxState;
> +
> +#endif
> diff --git a/include/hw/misc/bcm2835_mbox_defs.h b/include/hw/misc/bcm2835_mbox_defs.h
> new file mode 100644
> index 0000000..48d8ee4
> --- /dev/null
> +++ b/include/hw/misc/bcm2835_mbox_defs.h
> @@ -0,0 +1,26 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2835_MBOX_DEFS_H
> +#define BCM2835_MBOX_DEFS_H
> +
> +/* Constants shared with the ARM identifying separate mailbox channels */
> +#define MBOX_CHAN_POWER    0 /* for use by the power management interface */
> +#define MBOX_CHAN_FB       1 /* for use by the frame buffer */
> +#define MBOX_CHAN_VCHIQ    3 /* for use by the VCHIQ interface */
> +#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */
> +#define MBOX_CHAN_COUNT    9
> +
> +#define MBOX_SIZE          32
> +#define MBOX_INVALID_DATA  0x0f
> +
> +/* Layout of the private address space used for communication between
> + * the mbox device emulation, and child devices: each channel occupies
> + * 16 bytes of address space, but only two registers are presently defined. */

Space before */

Regards,
Peter

> +#define MBOX_AS_CHAN_SHIFT 4
> +#define MBOX_AS_DATA       0 /* request / response data (RW at offset 0) */
> +#define MBOX_AS_PENDING    4 /* pending response status (RO at offset 4) */
> +
> +#endif /* BCM2835_MBOX_DEFS_H */
> --
> 2.5.3
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller Andrew Baumann
@ 2015-12-31  0:33   ` Peter Crosthwaite
  0 siblings, 0 replies; 22+ messages in thread
From: Peter Crosthwaite @ 2015-12-31  0:33 UTC (permalink / raw)
  To: Andrew Baumann
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, qemu-devel@nongnu.org Developers, qemu-arm,
	Paolo Bonzini

On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
<Andrew.Baumann@microsoft.com> wrote:
> Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> ---
>
> Notes:
>     v2 changes:
>      * split inputs to named gpu_irq and arm_irq gpio inputs
>      * use 64-bit gpu_irq and 8-bit arm_irq status rather than 3*32-bit bitfields
>      * added defined names for register offsets
>      * deleted nop realize method
>      * other misc cleanup suggested in review
>
>  hw/intc/Makefile.objs        |   1 +
>  hw/intc/bcm2835_ic.c         | 233 +++++++++++++++++++++++++++++++++++++++++++
>  include/hw/intc/bcm2835_ic.h |  33 ++++++
>  3 files changed, 267 insertions(+)
>  create mode 100644 hw/intc/bcm2835_ic.c
>  create mode 100644 include/hw/intc/bcm2835_ic.h
>
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 004b0c2..2ad1204 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -24,6 +24,7 @@ obj-$(CONFIG_GRLIB) += grlib_irqmp.o
>  obj-$(CONFIG_IOAPIC) += ioapic.o
>  obj-$(CONFIG_OMAP) += omap_intc.o
>  obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
> +obj-$(CONFIG_RASPI) += bcm2835_ic.o
>  obj-$(CONFIG_SH4) += sh_intc.o
>  obj-$(CONFIG_XICS) += xics.o
>  obj-$(CONFIG_XICS_KVM) += xics_kvm.o
> diff --git a/hw/intc/bcm2835_ic.c b/hw/intc/bcm2835_ic.c
> new file mode 100644
> index 0000000..9624e8b
> --- /dev/null
> +++ b/hw/intc/bcm2835_ic.c
> @@ -0,0 +1,233 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + * Heavily based on pl190.c, copyright terms below:
> + *
> + * Arm PrimeCell PL190 Vector Interrupt Controller
> + *
> + * Copyright (c) 2006 CodeSourcery.
> + * Written by Paul Brook
> + *

So your own modifications are now heavy enough for you and/or an
affiliation to claim at least co-authorship.

> + * This code is licensed under the GPL.
> + */
> +
> +#include "hw/intc/bcm2835_ic.h"
> +
> +#define GPU_IRQS 64
> +#define ARM_IRQS 8
> +
> +#define IRQ_PENDING_BASIC       0x00 /* IRQ basic pending */
> +#define IRQ_PENDING_1           0x04 /* IRQ pending 1 */
> +#define IRQ_PENDING_2           0x08 /* IRQ pending 2 */
> +#define FIQ_CONTROL             0x0C /* FIQ register */
> +#define IRQ_ENABLE_1            0x10 /* Interrupt enable register 1 */
> +#define IRQ_ENABLE_2            0x14 /* Interrupt enable register 2 */
> +#define IRQ_ENABLE_BASIC        0x18 /* Base interrupt enable register */
> +#define IRQ_DISABLE_1           0x1C /* Interrupt disable register 1 */
> +#define IRQ_DISABLE_2           0x20 /* Interrupt disable register 2 */
> +#define IRQ_DISABLE_BASIC       0x24 /* Base interrupt disable register */
> +
> +/* Update interrupts.  */
> +static void bcm2835_ic_update(BCM2835ICState *s)
> +{
> +    bool set = false;
> +
> +    if (s->fiq_enable) {
> +        if (s->fiq_select >= GPU_IRQS) {
> +            /* ARM IRQ */
> +            set = extract32(s->arm_irq_level, s->fiq_select - GPU_IRQS, 1);
> +        } else {
> +            set = extract64(s->gpu_irq_level, s->fiq_select, 1);
> +        }
> +    }
> +    qemu_set_irq(s->fiq, set);
> +
> +    set = (s->gpu_irq_level & s->gpu_irq_enable)
> +        || (s->arm_irq_level & s->arm_irq_enable);
> +    qemu_set_irq(s->irq, set);
> +
> +}
> +
> +static void bcm2835_ic_set_gpu_irq(void *opaque, int irq, int level)
> +{
> +    BCM2835ICState *s = opaque;

Blank line here.

> +    assert(irq >= 0 && irq < 64);
> +    s->gpu_irq_level = deposit64(s->gpu_irq_level, irq, 1, level != 0);
> +    bcm2835_ic_update(s);
> +}
> +
> +static void bcm2835_ic_set_arm_irq(void *opaque, int irq, int level)
> +{
> +    BCM2835ICState *s = opaque;

Blank line here.

> +    assert(irq >= 0 && irq < 8);
> +    s->arm_irq_level = deposit32(s->arm_irq_level, irq, 1, level != 0);
> +    bcm2835_ic_update(s);
> +}
> +
> +static const int irq_dups[] = { 7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62 };
> +
> +static uint64_t bcm2835_ic_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    BCM2835ICState *s = opaque;
> +    uint32_t res = 0;
> +    uint64_t gpu_pending = s->gpu_irq_level & s->gpu_irq_enable;
> +    int i;
> +
> +    switch (offset) {
> +    case IRQ_PENDING_BASIC:
> +        /* bits 0-7: ARM irqs */
> +        res = s->arm_irq_level & s->arm_irq_enable;
> +
> +        /* bits 8 & 9: pending registers 1 & 2 */
> +        res |= (((uint32_t)gpu_pending) != 0) << 8;
> +        res |= ((gpu_pending >> 32) != 0) << 9;
> +
> +        /* bits 10-20: selected GPU IRQs */
> +        for (i = 0; i < ARRAY_SIZE(irq_dups); i++) {
> +            res |= extract64(gpu_pending, irq_dups[i], 1) << (i + 10);
> +        }
> +        break;
> +    case IRQ_PENDING_1:  /* IRQ pending 1 */

Drop trailing comment here and all below.

> +        res = gpu_pending;
> +        break;
> +    case IRQ_PENDING_2:  /* IRQ pending 2 */
> +        res = gpu_pending >> 32;
> +        break;
> +    case FIQ_CONTROL:  /* FIQ register */
> +        res = (s->fiq_enable << 7) | s->fiq_select;
> +        break;
> +    case IRQ_ENABLE_1:  /* Interrupt enable register 1 */
> +        res = s->gpu_irq_enable;
> +        break;
> +    case IRQ_ENABLE_2:  /* Interrupt enable register 2 */
> +        res = s->gpu_irq_enable >> 32;
> +        break;
> +    case IRQ_ENABLE_BASIC:  /* Base interrupt enable register */
> +        res = s->arm_irq_enable;
> +        break;
> +    case IRQ_DISABLE_1:  /* Interrupt disable register 1 */
> +        res = ~s->gpu_irq_enable;
> +        break;
> +    case IRQ_DISABLE_2:  /* Interrupt disable register 2 */
> +        res = ~s->gpu_irq_enable >> 32;
> +        break;
> +    case IRQ_DISABLE_BASIC:  /* Base interrupt disable register */
> +        res = ~s->arm_irq_enable;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return 0;
> +    }
> +
> +    return res;
> +}
> +
> +static void bcm2835_ic_write(void *opaque, hwaddr offset, uint64_t val,
> +                             unsigned size)
> +{
> +    BCM2835ICState *s = opaque;
> +
> +    switch (offset) {
> +    case FIQ_CONTROL:
> +        s->fiq_select = (val & 0x7f);
> +        s->fiq_enable = (val >> 7) & 0x1;

extract32 for both (my criteria is if there is both a shift and mask
it should extract instead of be manual).

> +        break;
> +    case IRQ_ENABLE_1:
> +        s->gpu_irq_enable |= val;
> +        break;
> +    case IRQ_ENABLE_2:
> +        s->gpu_irq_enable |= val << 32;
> +        break;
> +    case IRQ_ENABLE_BASIC:
> +        s->arm_irq_enable |= val & 0xff;
> +        break;
> +    case IRQ_DISABLE_1:
> +        s->gpu_irq_enable &= ~val;
> +        break;
> +    case IRQ_DISABLE_2:
> +        s->gpu_irq_enable &= ~(val << 32);
> +        break;
> +    case IRQ_DISABLE_BASIC:
> +        s->arm_irq_enable &= ~val & 0xff;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return;
> +    }
> +    bcm2835_ic_update(s);
> +}
> +
> +static const MemoryRegionOps bcm2835_ic_ops = {
> +    .read = bcm2835_ic_read,
> +    .write = bcm2835_ic_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +    .valid.min_access_size = 4,
> +    .valid.max_access_size = 4,
> +};
> +
> +static void bcm2835_ic_reset(DeviceState *d)
> +{
> +    BCM2835ICState *s = BCM2835_IC(d);
> +
> +    s->gpu_irq_enable = 0;
> +    s->arm_irq_enable = 0;
> +    s->fiq_enable = false;
> +    s->fiq_select = 0;
> +}
> +
> +static void bcm2835_ic_init(Object *obj)
> +{
> +    BCM2835ICState *s = BCM2835_IC(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &bcm2835_ic_ops, s, TYPE_BCM2835_IC,
> +                          0x200);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> +
> +    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_gpu_irq,
> +                            BCM2835_IC_GPU_IRQ, GPU_IRQS);
> +    qdev_init_gpio_in_named(DEVICE(s), bcm2835_ic_set_arm_irq,
> +                            BCM2835_IC_ARM_IRQ, ARM_IRQS);
> +
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
> +    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->fiq);
> +}
> +
> +static const VMStateDescription vmstate_bcm2835_ic = {
> +    .name = TYPE_BCM2835_IC,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT64(gpu_irq_level, BCM2835ICState),
> +        VMSTATE_UINT64(gpu_irq_enable, BCM2835ICState),
> +        VMSTATE_UINT8(arm_irq_level, BCM2835ICState),
> +        VMSTATE_UINT8(arm_irq_enable, BCM2835ICState),
> +        VMSTATE_BOOL(fiq_enable, BCM2835ICState),
> +        VMSTATE_UINT8(fiq_select, BCM2835ICState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void bcm2835_ic_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = bcm2835_ic_reset;
> +    dc->vmsd = &vmstate_bcm2835_ic;
> +}
> +
> +static TypeInfo bcm2835_ic_info = {
> +    .name          = TYPE_BCM2835_IC,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(BCM2835ICState),
> +    .class_init    = bcm2835_ic_class_init,
> +    .instance_init = bcm2835_ic_init,
> +};
> +
> +static void bcm2835_ic_register_types(void)
> +{
> +    type_register_static(&bcm2835_ic_info);
> +}
> +
> +type_init(bcm2835_ic_register_types)
> diff --git a/include/hw/intc/bcm2835_ic.h b/include/hw/intc/bcm2835_ic.h
> new file mode 100644
> index 0000000..d897f44
> --- /dev/null
> +++ b/include/hw/intc/bcm2835_ic.h
> @@ -0,0 +1,33 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2835_IC_H
> +#define BCM2835_IC_H
> +
> +#include "hw/sysbus.h"
> +
> +#define TYPE_BCM2835_IC "bcm2835_ic"

s/_/-

> +#define BCM2835_IC(obj) OBJECT_CHECK(BCM2835ICState, (obj), TYPE_BCM2835_IC)
> +
> +#define BCM2835_IC_GPU_IRQ "gpu-irq"
> +#define BCM2835_IC_ARM_IRQ "arm-irq"
> +
> +typedef struct BCM2835ICState {
> +    /*< private >*/
> +    SysBusDevice busdev;
> +    /*< public >*/
> +
> +    MemoryRegion iomem;
> +
> +    /* 64 GPU IRQs + 8 ARM IRQs = 72 total (GPU first) */
> +    uint64_t gpu_irq_level, gpu_irq_enable;
> +    uint8_t arm_irq_level, arm_irq_enable;
> +    bool fiq_enable;
> +    uint8_t fiq_select;

> +    qemu_irq irq;
> +    qemu_irq fiq;

Move these two up to below iomem to separate IO from internal state.

Otherwise,

Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>

Regards,
Peter

> +} BCM2835ICState;
> +
> +#endif
> --
> 2.5.3
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
  2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
                   ` (6 preceding siblings ...)
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 7/7] raspi: add raspberry pi 2 machine Andrew Baumann
@ 2015-12-31  1:13 ` Piotr Król
  2016-01-06 18:27   ` Andrew Baumann
  7 siblings, 1 reply; 22+ messages in thread
From: Piotr Król @ 2015-12-31  1:13 UTC (permalink / raw)
  To: qemu-devel

On Wed, Dec 23, 2015 at 04:25:24PM -0800, Andrew Baumann wrote:
> This patch series adds initial support for Raspberry Pi 2
> (bcm2836). It is heavily based on the original (out of tree) work of
> Gregory Estrade, Stefan Weil and others to support Raspberry Pi 1.
> 
> At the end of this series, it is possible to boot a recent raspbian
> kernel to a serial console using an invocation such as:
> 
>   qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd
>   2015-09-24-raspbian-jessie.vhd -append "rw earlyprintk loglevel=8
>   console=ttyAMA0 root=/dev/mmcblk0p2" -serial stdio
> 
> (where raspbian-boot is the boot partition from the matching image,
> and after commenting-out or removing /etc/ld.so.preload to avoid an
> unimplemented setend instruction).
> 
> I plan to add DMA, USB, framebuffer, timers, and other system devices
> (vchiq, power, mphi, aux/uart1) in future patches. In the meantime,
> the complete code is available at: https://github.com/0xabu/qemu

Hi Andrew,
many thanks for this patch series. I'm very interested in this effort from
Linux perspective. And would like to help with testing and maybe some
development.

First, I tried your code from raspi branch (ar7-raspi doesn't compile [1]).
Using recent Raspbian 2015-11-21-raspbian-jessie (same results I saw for
2015-09-24). I'm getting kernel panic:

[    6.892677] random: systemd urandom read with 7 bits of entropy available
[    6.908292] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
[    6.908292] 
[    6.909692] CPU: 0 PID: 1 Comm: systemd Not tainted 4.1.13-v7+ #826
[    6.910106] Hardware name: BCM2709
[    6.911818] [<80018444>] (unwind_backtrace) from [<80013e08>] (show_stack+0x20/0x24)
[    6.912539] [<80013e08>] (show_stack) from [<8055a188>] (dump_stack+0x98/0xe0)
[    6.913074] [<8055a188>] (dump_stack) from [<80556340>] (panic+0xa4/0x204)
[    6.913721] [<80556340>] (panic) from [<800293c8>] (do_exit+0xa0c/0xa64)
[    6.914181] [<800293c8>] (do_exit) from [<800294b8>] (do_group_exit+0x4c/0xcc)
[    6.914770] [<800294b8>] (do_group_exit) from [<80033f1c>] (get_signal+0x2b0/0x6e0)
[    6.915311] [<80033f1c>] (get_signal) from [<80013190>] (do_signal+0x98/0x3ac)
[    6.915825] [<80013190>] (do_signal) from [<8001368c>] (do_work_pending+0xb8/0xc8)
[    6.916352] [<8001368c>] (do_work_pending) from [<8000f9e4>] (work_pending+0xc/0x20)
[    6.917774] ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
[    6.917774] 

Full log [3].

Third test I tried is to apply patches from this series on top of master
(38a762fec63f), what cause hang on:

[   15.094558 ] mmc0: Timeout waiting for hardware interrupt

Full log [2].

I do not follow this mailing list, so maybe I missing some pieces.
If I need some other patches to test this series please let me know.

My questions:

Does 2015-09-24-raspbian-jessie.vhd extracted Linux partition from raspbian
image or simply img converted to vhd format ? Is there any problem with using img ?

Would you mind to issue tracking on GitHub and pull requests or you want whole
communication and possible fixes go through QEMU mailing list ? I think that it
maybe useful for code that is not ready for upstreaming. I saw you have issue
tracking disabled.

Any other pointers how to fix those issues are appreciated.

[1] https://gist.github.com/pietrushnic/d2b7714524f0a2db3530
[2] https://gist.github.com/pietrushnic/cfe3d8d70d883a683250
[3] https://gist.github.com/pietrushnic/7daff0f1227de79d1af3

> 
> Although this series includes many of the peripherals common to Pi1
> (aka bcm2835 aka Pi0), it's not yet possible to boot a Pi1, because it
> requires additional peripherals, so I'll also add that SoC and machine
> in a later patch.
> 
> v2 changes:
>  * cleanup based on reviews of mbox and ic devices by Peter Crosthwaite
>    (see specific notes on each patch)
>  * removed custom SD controller in favour of sdhci
> 
> Cheers,
> Andrew
> 
> Andrew Baumann (7):
>   bcm2835_mbox: add BCM2835 mailboxes
>   bcm2835_property: add bcm2835 property channel
>   bcm2835_ic: add bcm2835 interrupt controller
>   bcm2835_peripherals: add rollup device for bcm2835 peripherals
>   bcm2836_control: add bcm2836 ARM control logic
>   bcm2836: add bcm2836 soc device
>   raspi: add raspberry pi 2 machine
> 
>  default-configs/arm-softmmu.mak      |   1 +
>  hw/arm/Makefile.objs                 |   1 +
>  hw/arm/bcm2835_peripherals.c         | 198 ++++++++++++++++++++
>  hw/arm/bcm2836.c                     | 135 ++++++++++++++
>  hw/arm/raspi.c                       | 179 +++++++++++++++++++
>  hw/intc/Makefile.objs                |   1 +
>  hw/intc/bcm2835_ic.c                 | 233 ++++++++++++++++++++++++
>  hw/intc/bcm2836_control.c            | 338 +++++++++++++++++++++++++++++++++++
>  hw/misc/Makefile.objs                |   2 +
>  hw/misc/bcm2835_mbox.c               | 323 +++++++++++++++++++++++++++++++++
>  hw/misc/bcm2835_property.c           | 277 ++++++++++++++++++++++++++++
>  include/hw/arm/bcm2835_peripherals.h |  42 +++++
>  include/hw/arm/bcm2836.h             |  33 ++++
>  include/hw/arm/raspi_platform.h      | 161 +++++++++++++++++
>  include/hw/intc/bcm2835_ic.h         |  33 ++++
>  include/hw/intc/bcm2836_control.h    |  51 ++++++
>  include/hw/misc/bcm2835_mbox.h       |  37 ++++
>  include/hw/misc/bcm2835_mbox_defs.h  |  26 +++
>  include/hw/misc/bcm2835_property.h   |  29 +++
>  19 files changed, 2100 insertions(+)
>  create mode 100644 hw/arm/bcm2835_peripherals.c
>  create mode 100644 hw/arm/bcm2836.c
>  create mode 100644 hw/arm/raspi.c
>  create mode 100644 hw/intc/bcm2835_ic.c
>  create mode 100644 hw/intc/bcm2836_control.c
>  create mode 100644 hw/misc/bcm2835_mbox.c
>  create mode 100644 hw/misc/bcm2835_property.c
>  create mode 100644 include/hw/arm/bcm2835_peripherals.h
>  create mode 100644 include/hw/arm/bcm2836.h
>  create mode 100644 include/hw/arm/raspi_platform.h
>  create mode 100644 include/hw/intc/bcm2835_ic.h
>  create mode 100644 include/hw/intc/bcm2836_control.h
>  create mode 100644 include/hw/misc/bcm2835_mbox.h
>  create mode 100644 include/hw/misc/bcm2835_mbox_defs.h
>  create mode 100644 include/hw/misc/bcm2835_property.h
> 
> -- 
> 2.5.3
> 
> 

Best Regards,
-- 
Piotr Król
Embedded Systems Consultant
http://3mdeb.com | @3mdeb_com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals Andrew Baumann
@ 2015-12-31  2:53   ` Peter Crosthwaite
  2015-12-31 18:23     ` Andrew Baumann
  0 siblings, 1 reply; 22+ messages in thread
From: Peter Crosthwaite @ 2015-12-31  2:53 UTC (permalink / raw)
  To: Andrew Baumann, Alistair Francis
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, qemu-devel@nongnu.org Developers, qemu-arm,
	Paolo Bonzini

On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
<Andrew.Baumann@microsoft.com> wrote:
> This device maintains all the non-CPU peripherals on bcm2835 (Pi1)
> which are also present on bcm2836 (Pi2). It also implements the
> private address space used for DMA.
>
> Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> ---
>
> Notes:
>     v2 changes:
>      * adapted to use common SDHCI emulation
>
>  hw/arm/Makefile.objs                 |   1 +
>  hw/arm/bcm2835_peripherals.c         | 198 +++++++++++++++++++++++++++++++++++
>  include/hw/arm/bcm2835_peripherals.h |  42 ++++++++
>  include/hw/arm/raspi_platform.h      | 161 ++++++++++++++++++++++++++++
>  4 files changed, 402 insertions(+)
>  create mode 100644 hw/arm/bcm2835_peripherals.c
>  create mode 100644 include/hw/arm/bcm2835_peripherals.h
>  create mode 100644 include/hw/arm/raspi_platform.h
>
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index 2195b60..82cc142 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -11,6 +11,7 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o
>  obj-$(CONFIG_DIGIC) += digic.o
>  obj-y += omap1.o omap2.o strongarm.o
>  obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
> +obj-$(CONFIG_RASPI) += bcm2835_peripherals.o
>  obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
>  obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
>  obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
> new file mode 100644
> index 0000000..deb6336
> --- /dev/null
> +++ b/hw/arm/bcm2835_peripherals.c
> @@ -0,0 +1,198 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
> + *
> + * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
> + * Written by Andrew Baumann
> + *
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#include "hw/arm/bcm2835_peripherals.h"
> +#include "hw/misc/bcm2835_mbox_defs.h"
> +#include "hw/arm/raspi_platform.h"
> +
> +/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
> +#define BCM2835_SDHC_CAPAREG 0x52034b4
> +
> +static void bcm2835_peripherals_init(Object *obj)
> +{
> +    BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
> +
> +    /* Memory region for peripheral devices, which we export to our parent */
> +    memory_region_init_io(&s->peri_mr, OBJECT(s), NULL, s,
> +                          "bcm2835_peripherals", 0x1000000);
> +    object_property_add_child(obj, "peripheral_io", OBJECT(&s->peri_mr), NULL);

s/_/-, here and below. The names of child devices are user-exposed via
QOM canonical paths.

> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
> +
> +    /* Internal memory region for peripheral bus addresses (not exported) */
> +    memory_region_init_io(&s->gpu_bus_mr, OBJECT(s), NULL, s, "bcm2835_gpu_bus",
> +                          (uint64_t)1 << 32);

You already have obj for the OBJECT casted version of s.

Why do you us memory_region_init_io though instead of
memory_region_init? This looks like a container MR which is what
unqualified memory_region_init provides.

> +    object_property_add_child(obj, "gpu_bus", OBJECT(&s->gpu_bus_mr), NULL);
> +
> +    /* Internal memory region for communication of mailbox channel data */
> +    memory_region_init_io(&s->mbox_mr, OBJECT(s), NULL, s, "bcm2835_mbox",
> +                          MBOX_CHAN_COUNT << 4);
> +

Same here. Although this container seems to have only one subregion at
offset 0 (the property device). Long term, will this MR have more
stuff in it or will always be just the property?

> +    /* Interrupt Controller */
> +    object_initialize(&s->ic, sizeof(s->ic), TYPE_BCM2835_IC);
> +    object_property_add_child(obj, "ic", OBJECT(&s->ic), NULL);
> +    qdev_set_parent_bus(DEVICE(&s->ic), sysbus_get_default());
> +
> +    /* UART0 */
> +    s->uart0 = SYS_BUS_DEVICE(object_new("pl011"));
> +    object_property_add_child(obj, "uart0", OBJECT(s->uart0), NULL);
> +    qdev_set_parent_bus(DEVICE(s->uart0), sysbus_get_default());
> +
> +    /* Mailboxes */
> +    object_initialize(&s->mboxes, sizeof(s->mboxes), TYPE_BCM2835_MBOX);
> +    object_property_add_child(obj, "mbox", OBJECT(&s->mboxes), NULL);
> +    qdev_set_parent_bus(DEVICE(&s->mboxes), sysbus_get_default());
> +
> +    object_property_add_const_link(OBJECT(&s->mboxes), "mbox_mr",
> +                                   OBJECT(&s->mbox_mr), &error_abort);
> +
> +    /* Property channel */
> +    object_initialize(&s->property, sizeof(s->property), TYPE_BCM2835_PROPERTY);
> +    object_property_add_child(obj, "property", OBJECT(&s->property), NULL);
> +    qdev_set_parent_bus(DEVICE(&s->property), sysbus_get_default());
> +
> +    object_property_add_const_link(OBJECT(&s->property), "dma_mr",
> +                                   OBJECT(&s->gpu_bus_mr), &error_abort);
> +
> +    /* Extended Mass Media Controller */
> +    object_initialize(&s->sdhci, sizeof(s->sdhci), TYPE_SYSBUS_SDHCI);
> +    object_property_add_child(obj, "sdhci", OBJECT(&s->sdhci), NULL);
> +    qdev_set_parent_bus(DEVICE(&s->sdhci), sysbus_get_default());
> +}
> +
> +static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
> +{
> +    BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev);
> +    MemoryRegion *ram;
> +    Error *err = NULL;
> +    uint32_t ram_size;
> +    int n;
> +
> +    /* Map peripherals and RAM into the GPU address space. */
> +    memory_region_init_alias(&s->peri_mr_alias, OBJECT(s),
> +                             "bcm2835_peripherals", &s->peri_mr, 0,
> +                             memory_region_size(&s->peri_mr));
> +
> +    memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE,
> +                                        &s->peri_mr_alias, 1);
> +
> +    /* XXX: assume that RAM is contiguous and mapped at system address zero */
> +    ram = memory_region_find(get_system_memory(), 0, 1).mr;

Not sure about this. Alistair (from Xilinx) has a similar problem
where the SoC needed to do a complex split of the single DDR into
multiple system address regions. I cc'd you on a patch. Following
Alistair's patch in the Xiinx ep108/zynqmp work, the system_memory
region is now fully owned by the SoC level and disused by the
machine/board level. I would suggest something similar here. The board
is responsible for creating (and mainly sizing) the RAM, and links (or
const-link's) the RAM to the SoC where it can be subregioned as-is
without this search. As you already have SoC level memory regions for
your multiple address spaces, you may actually end up with
system_memory being completely unused (and that is OK).

> +    assert(ram != NULL && memory_region_size(ram) >= 128 * 1024 * 1024);

What is is the significance of the 128MB lower clamp? This should
probably be a weaker error than assert. Depending on the reason for
the error, it could be located in a number of different places. If the
SoC cannot function without 128MB for some reason this is the right
place.

If it is for forcing the user to not pass something to -m because that
is simply not what is on the board, then it should be done on the
board level. I'm thinking it would be reasonable to defeature -m for
these fixed boards as it does make less and less sense.

> +    ram_size = memory_region_size(ram);
> +
> +    /* RAM is aliased four times (different cache configurations) on the GPU */
> +    for (n = 0; n < 4; n++) {
> +        memory_region_init_alias(&s->ram_alias[n], OBJECT(s),
> +                                 "bcm2835_gpu_ram_alias[*]", ram, 0, ram_size);
> +        memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30,
> +                                            &s->ram_alias[n], 0);
> +    }
> +
> +    /* Interrupt Controller */
> +    object_property_set_bool(OBJECT(&s->ic), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET,
> +                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0));
> +    sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
> +
> +    /* UART0 */
> +    object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    memory_region_add_subregion(&s->peri_mr, UART0_OFFSET,
> +                                sysbus_mmio_get_region(s->uart0, 0));
> +    sysbus_connect_irq(s->uart0, 0,
> +        qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
> +                               INTERRUPT_VC_UART));
> +
> +    /* Mailboxes */
> +    object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET,
> +                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0));
> +    sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0,
> +        qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ,
> +                               INTERRUPT_ARM_MAILBOX - ARM_IRQ0_BASE));
> +
> +    /* Mailbox-addressable peripherals use the private mbox_mr address space
> +     * and pseudo-irqs to dispatch requests and responses. */

This comment location seems odd. Should it just go with the definition
of mbox_mr? It could possibly be a top level comment too.

Space before  */

> +
> +    /* Property channel */

These are all self-documented by the already-well-named s-> fields, so
you can drop these comments indicating what you are realizing.

> +    object_property_set_int(OBJECT(&s->property), ram_size, "ram-size", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    object_property_set_bool(OBJECT(&s->property), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    memory_region_add_subregion(&s->mbox_mr,
> +                MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT,
> +                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0));
> +    sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0,
> +                      qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY));
> +
> +    /* Extended Mass Media Controller */
> +    object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg",
> +                            &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err);
> +    if (err) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET,
> +                sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0));
> +    sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
> +        qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
> +                               INTERRUPT_VC_ARASANSDIO));
> +}
> +
> +static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +
> +    dc->realize = bcm2835_peripherals_realize;
> +}
> +
> +static const TypeInfo bcm2835_peripherals_type_info = {
> +    .name = TYPE_BCM2835_PERIPHERALS,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(BCM2835PeripheralState),
> +    .instance_init = bcm2835_peripherals_init,
> +    .class_init = bcm2835_peripherals_class_init,
> +};
> +
> +static void bcm2835_peripherals_register_types(void)
> +{
> +    type_register_static(&bcm2835_peripherals_type_info);
> +}
> +
> +type_init(bcm2835_peripherals_register_types)
> diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
> new file mode 100644
> index 0000000..b3ba574
> --- /dev/null
> +++ b/include/hw/arm/bcm2835_peripherals.h
> @@ -0,0 +1,42 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
> + *
> + * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
> + * Written by Andrew Baumann
> + *
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2835_PERIPHERALS_H
> +#define BCM2835_PERIPHERALS_H
> +
> +#include "qemu-common.h"
> +#include "exec/address-spaces.h"
> +#include "hw/sysbus.h"
> +#include "hw/intc/bcm2835_ic.h"
> +#include "hw/misc/bcm2835_property.h"
> +#include "hw/misc/bcm2835_mbox.h"
> +#include "hw/sd/sdhci.h"
> +
> +#define TYPE_BCM2835_PERIPHERALS "bcm2835_peripherals"
> +#define BCM2835_PERIPHERALS(obj) \
> +    OBJECT_CHECK(BCM2835PeripheralState, (obj), TYPE_BCM2835_PERIPHERALS)
> +
> +typedef struct BCM2835PeripheralState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    MemoryRegion peri_mr, peri_mr_alias, gpu_bus_mr, mbox_mr;
> +    MemoryRegion ram_alias[4];
> +    qemu_irq irq, fiq;
> +
> +    SysBusDevice *uart0;
> +    BCM2835ICState ic;
> +    BCM2835PropertyState property;
> +    BCM2835MboxState mboxes;
> +    SDHCIState sdhci;
> +} BCM2835PeripheralState;
> +
> +#endif /* BCM2835_PERIPHERALS_H */
> diff --git a/include/hw/arm/raspi_platform.h b/include/hw/arm/raspi_platform.h
> new file mode 100644
> index 0000000..8386949
> --- /dev/null
> +++ b/include/hw/arm/raspi_platform.h
> @@ -0,0 +1,161 @@
> +/*
> + * bcm2708 aka bcm2835/2836 aka Raspberry Pi/Pi2 SoC platform defines
> + *
> + * These definitions are derived from those in Linux at
> + * arch/arm/mach-{bcm2708,bcm2709}/include/mach/platform.h

I think this is in the same basket as the header from P1. We should
cherry pick out the defs that we care about (or are likely to care
about in near term follow up). I'm guessing this is sourced from the
same Linux fork as before?

> + * where they carry the following notice:
> + */
> +
> +/*
> + * arch/arm/mach-bcm2708/include/mach/platform.h
> + *
> + * Copyright (C) 2010 Broadcom
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
> + */
> +
> +/* Peripheral base address on the VC (GPU) system bus */
> +#define BCM2835_VC_PERI_BASE 0x7e000000
> +
> +/* Peripheral base addresses seen by the CPU: Pi1 and Pi2 differ */
> +#define BCM2835_PERI_BASE       0x20000000
> +#define BCM2836_PERI_BASE       0x3F000000
> +

These two should be defined by their resp. socs.

> +/* "QA7" (Pi2) interrupt controller and mailboxes etc. */
> +#define BCM2836_CONTROL_BASE    0x40000000
> +
> +#define MCORE_OFFSET            0x0000   /* Fake frame buffer device
> +                                          * (the multicore sync block) */
> +#define IC0_OFFSET              0x2000
> +#define ST_OFFSET               0x3000   /* System Timer */
> +#define MPHI_OFFSET             0x6000   /* Message-based Parallel Host Intf. */
> +#define DMA_OFFSET              0x7000   /* DMA controller, channels 0-14 */
> +#define ARM_OFFSET              0xB000   /* BCM2708 ARM control block */
> +#define ARMCTRL_OFFSET          (ARM_OFFSET + 0x000)
> +#define ARMCTRL_IC_OFFSET       (ARM_OFFSET + 0x200) /* Interrupt controller */
> +#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 */
> +#define ARMCTRL_0_SBM_OFFSET    (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
> +                                                      * Doorbells & Mailboxes */
> +#define PM_OFFSET               0x100000 /* Power Management, Reset controller
> +                                          * and Watchdog registers */
> +#define PCM_CLOCK_OFFSET        0x101098 /* PCM Clock */
> +#define RNG_OFFSET              0x104000 /* Hardware RNG */
> +#define GPIO_OFFSET             0x200000 /* GPIO */
> +#define UART0_OFFSET            0x201000 /* Uart 0 */

Trailing comments that don't add anything should be dropped.

> +#define MMCI0_OFFSET            0x202000 /* MMC interface */
> +#define I2S_OFFSET              0x203000 /* I2S */
> +#define SPI0_OFFSET             0x204000 /* SPI0 */
> +#define BSC0_OFFSET             0x205000 /* BSC0 I2C/TWI */
> +#define UART1_OFFSET            0x215000 /* Uart 1 */
> +#define EMMC_OFFSET             0x300000 /* eMMC interface */
> +#define SMI_OFFSET              0x600000 /* SMI */
> +#define BSC1_OFFSET             0x804000 /* BSC1 I2C/TWI */
> +#define USB_OFFSET              0x980000 /* DTC_OTG USB controller */
> +#define DMA15_OFFSET            0xE05000 /* DMA controller, channel 15 */
> +
> +/*
> + * Interrupt assignments
> + */
> +
> +#define ARM_IRQ1_BASE                  0
> +#define INTERRUPT_TIMER0               (ARM_IRQ1_BASE + 0)
> +#define INTERRUPT_TIMER1               (ARM_IRQ1_BASE + 1)
> +#define INTERRUPT_TIMER2               (ARM_IRQ1_BASE + 2)
> +#define INTERRUPT_TIMER3               (ARM_IRQ1_BASE + 3)
> +#define INTERRUPT_CODEC0               (ARM_IRQ1_BASE + 4)
> +#define INTERRUPT_CODEC1               (ARM_IRQ1_BASE + 5)
> +#define INTERRUPT_CODEC2               (ARM_IRQ1_BASE + 6)
> +#define INTERRUPT_VC_JPEG              (ARM_IRQ1_BASE + 7)
> +#define INTERRUPT_ISP                  (ARM_IRQ1_BASE + 8)
> +#define INTERRUPT_VC_USB               (ARM_IRQ1_BASE + 9)
> +#define INTERRUPT_VC_3D                (ARM_IRQ1_BASE + 10)
> +#define INTERRUPT_TRANSPOSER           (ARM_IRQ1_BASE + 11)
> +#define INTERRUPT_MULTICORESYNC0       (ARM_IRQ1_BASE + 12)
> +#define INTERRUPT_MULTICORESYNC1       (ARM_IRQ1_BASE + 13)
> +#define INTERRUPT_MULTICORESYNC2       (ARM_IRQ1_BASE + 14)
> +#define INTERRUPT_MULTICORESYNC3       (ARM_IRQ1_BASE + 15)
> +#define INTERRUPT_DMA0                 (ARM_IRQ1_BASE + 16)
> +#define INTERRUPT_DMA1                 (ARM_IRQ1_BASE + 17)
> +#define INTERRUPT_VC_DMA2              (ARM_IRQ1_BASE + 18)
> +#define INTERRUPT_VC_DMA3              (ARM_IRQ1_BASE + 19)
> +#define INTERRUPT_DMA4                 (ARM_IRQ1_BASE + 20)
> +#define INTERRUPT_DMA5                 (ARM_IRQ1_BASE + 21)
> +#define INTERRUPT_DMA6                 (ARM_IRQ1_BASE + 22)
> +#define INTERRUPT_DMA7                 (ARM_IRQ1_BASE + 23)
> +#define INTERRUPT_DMA8                 (ARM_IRQ1_BASE + 24)
> +#define INTERRUPT_DMA9                 (ARM_IRQ1_BASE + 25)
> +#define INTERRUPT_DMA10                (ARM_IRQ1_BASE + 26)
> +#define INTERRUPT_DMA11                (ARM_IRQ1_BASE + 27)
> +#define INTERRUPT_DMA12                (ARM_IRQ1_BASE + 28)
> +#define INTERRUPT_AUX                  (ARM_IRQ1_BASE + 29)
> +#define INTERRUPT_ARM                  (ARM_IRQ1_BASE + 30)
> +#define INTERRUPT_VPUDMA               (ARM_IRQ1_BASE + 31)
> +
> +#define ARM_IRQ2_BASE                  32

Can you just keep it as one big 64-long list? I don't think we need
the _BASE defs at all anymore.

> +#define INTERRUPT_HOSTPORT             (ARM_IRQ2_BASE + 0)
> +#define INTERRUPT_VIDEOSCALER          (ARM_IRQ2_BASE + 1)
> +#define INTERRUPT_CCP2TX               (ARM_IRQ2_BASE + 2)
> +#define INTERRUPT_SDC                  (ARM_IRQ2_BASE + 3)
> +#define INTERRUPT_DSI0                 (ARM_IRQ2_BASE + 4)
> +#define INTERRUPT_AVE                  (ARM_IRQ2_BASE + 5)
> +#define INTERRUPT_CAM0                 (ARM_IRQ2_BASE + 6)
> +#define INTERRUPT_CAM1                 (ARM_IRQ2_BASE + 7)
> +#define INTERRUPT_HDMI0                (ARM_IRQ2_BASE + 8)
> +#define INTERRUPT_HDMI1                (ARM_IRQ2_BASE + 9)
> +#define INTERRUPT_PIXELVALVE1          (ARM_IRQ2_BASE + 10)
> +#define INTERRUPT_I2CSPISLV            (ARM_IRQ2_BASE + 11)
> +#define INTERRUPT_DSI1                 (ARM_IRQ2_BASE + 12)
> +#define INTERRUPT_PWA0                 (ARM_IRQ2_BASE + 13)
> +#define INTERRUPT_PWA1                 (ARM_IRQ2_BASE + 14)
> +#define INTERRUPT_CPR                  (ARM_IRQ2_BASE + 15)
> +#define INTERRUPT_SMI                  (ARM_IRQ2_BASE + 16)
> +#define INTERRUPT_GPIO0                (ARM_IRQ2_BASE + 17)
> +#define INTERRUPT_GPIO1                (ARM_IRQ2_BASE + 18)
> +#define INTERRUPT_GPIO2                (ARM_IRQ2_BASE + 19)
> +#define INTERRUPT_GPIO3                (ARM_IRQ2_BASE + 20)
> +#define INTERRUPT_VC_I2C               (ARM_IRQ2_BASE + 21)
> +#define INTERRUPT_VC_SPI               (ARM_IRQ2_BASE + 22)
> +#define INTERRUPT_VC_I2SPCM            (ARM_IRQ2_BASE + 23)
> +#define INTERRUPT_VC_SDIO              (ARM_IRQ2_BASE + 24)
> +#define INTERRUPT_VC_UART              (ARM_IRQ2_BASE + 25)
> +#define INTERRUPT_SLIMBUS              (ARM_IRQ2_BASE + 26)
> +#define INTERRUPT_VEC                  (ARM_IRQ2_BASE + 27)
> +#define INTERRUPT_CPG                  (ARM_IRQ2_BASE + 28)
> +#define INTERRUPT_RNG                  (ARM_IRQ2_BASE + 29)
> +#define INTERRUPT_VC_ARASANSDIO        (ARM_IRQ2_BASE + 30)
> +#define INTERRUPT_AVSPMON              (ARM_IRQ2_BASE + 31)
> +
> +#define ARM_IRQ0_BASE                  64

This 64 shouldn't be needed anymore with the arm_irqs now in their own
enumeration space. It should just count from 0 again (and I think the
only usages you have of these subtract off ARM_IRQ0_BASE).

> +#define INTERRUPT_ARM_TIMER            (ARM_IRQ0_BASE + 0)
> +#define INTERRUPT_ARM_MAILBOX          (ARM_IRQ0_BASE + 1)
> +#define INTERRUPT_ARM_DOORBELL_0       (ARM_IRQ0_BASE + 2)
> +#define INTERRUPT_ARM_DOORBELL_1       (ARM_IRQ0_BASE + 3)
> +#define INTERRUPT_VPU0_HALTED          (ARM_IRQ0_BASE + 4)
> +#define INTERRUPT_VPU1_HALTED          (ARM_IRQ0_BASE + 5)
> +#define INTERRUPT_ILLEGAL_TYPE0        (ARM_IRQ0_BASE + 6)
> +#define INTERRUPT_ILLEGAL_TYPE1        (ARM_IRQ0_BASE + 7)

The defs after here are confusing. Are they for a different SoC? I
thought the SoC was limited to 8 ARM_ irqs?

Regards,
Peter

> +#define INTERRUPT_PENDING1             (ARM_IRQ0_BASE + 8)
> +#define INTERRUPT_PENDING2             (ARM_IRQ0_BASE + 9)
> +#define INTERRUPT_JPEG                 (ARM_IRQ0_BASE + 10)
> +#define INTERRUPT_USB                  (ARM_IRQ0_BASE + 11)
> +#define INTERRUPT_3D                   (ARM_IRQ0_BASE + 12)
> +#define INTERRUPT_DMA2                 (ARM_IRQ0_BASE + 13)
> +#define INTERRUPT_DMA3                 (ARM_IRQ0_BASE + 14)
> +#define INTERRUPT_I2C                  (ARM_IRQ0_BASE + 15)
> +#define INTERRUPT_SPI                  (ARM_IRQ0_BASE + 16)
> +#define INTERRUPT_I2SPCM               (ARM_IRQ0_BASE + 17)
> +#define INTERRUPT_SDIO                 (ARM_IRQ0_BASE + 18)
> +#define INTERRUPT_UART                 (ARM_IRQ0_BASE + 19)
> +#define INTERRUPT_ARASANSDIO           (ARM_IRQ0_BASE + 20)
> --
> 2.5.3
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic
  2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic Andrew Baumann
@ 2015-12-31  3:20   ` Peter Crosthwaite
  2015-12-31 18:43     ` Andrew Baumann
  0 siblings, 1 reply; 22+ messages in thread
From: Peter Crosthwaite @ 2015-12-31  3:20 UTC (permalink / raw)
  To: Andrew Baumann
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, qemu-devel@nongnu.org Developers, qemu-arm,
	Paolo Bonzini

On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
<Andrew.Baumann@microsoft.com> wrote:
> This module is specific to the bcm2836 (Pi2). It implements the top
> level interrupt controller, and mailboxes used for inter-processor
> synchronisation.
>
> Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
> ---
>  hw/intc/Makefile.objs             |   2 +-
>  hw/intc/bcm2836_control.c         | 338 ++++++++++++++++++++++++++++++++++++++
>  include/hw/intc/bcm2836_control.h |  51 ++++++
>  3 files changed, 390 insertions(+), 1 deletion(-)
>  create mode 100644 hw/intc/bcm2836_control.c
>  create mode 100644 include/hw/intc/bcm2836_control.h
>
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index 2ad1204..6a13a39 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -24,7 +24,7 @@ obj-$(CONFIG_GRLIB) += grlib_irqmp.o
>  obj-$(CONFIG_IOAPIC) += ioapic.o
>  obj-$(CONFIG_OMAP) += omap_intc.o
>  obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
> -obj-$(CONFIG_RASPI) += bcm2835_ic.o
> +obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
>  obj-$(CONFIG_SH4) += sh_intc.o
>  obj-$(CONFIG_XICS) += xics.o
>  obj-$(CONFIG_XICS_KVM) += xics_kvm.o
> diff --git a/hw/intc/bcm2836_control.c b/hw/intc/bcm2836_control.c
> new file mode 100644
> index 0000000..d68b4d9
> --- /dev/null
> +++ b/hw/intc/bcm2836_control.c
> @@ -0,0 +1,338 @@
> +/*
> + * Rasperry Pi 2 emulation ARM control logic module.
> + * Copyright (c) 2015, Microsoft
> + * Written by Andrew Baumann
> + *
> + * At present, only implements interrupt routing, and mailboxes (i.e.,
> + * not local timer, PMU interrupt, or AXI counters).
> + *
> + * Ref:
> + * https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2836/QA7_rev3.4.pdf

This looks like an mpcore. Check hw/cpu/a9mpcore and friends to see
how those are implemented. I think this is architecturally OK for the
moment, although if you intend to expand this with Timers etc. it
should be in hw/cpu/ and containerised. I think the containerisation
can happen later but should be put it in hw/cpu/ straight up?

> + *
> + * Based on bcm2835_ic.c, terms below...
> + */
> +
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +/* Heavily based on pl190.c, copyright terms below. */
> +

I don't think we need to recursively explode all the copyrights
everytime a sysbus device is used as a template. I think it is
reasonable to call this new code.

> +/*
> + * Arm PrimeCell PL190 Vector Interrupt Controller
> + *
> + * Copyright (c) 2006 CodeSourcery.
> + * Written by Paul Brook
> + *
> + * This code is licensed under the GPL.
> + */
> +
> +#include "hw/intc/bcm2836_control.h"
> +
> +#define ROUTE_CORE(x) ((x) & 0x3)
> +#define ROUTE_FIQ(x)  (((x) & 0x4) != 0)
> +
> +#define IRQ_BIT(cntrl, num) (((cntrl) & (1 << (num))) != 0)
> +#define FIQ_BIT(cntrl, num) (((cntrl) & (1 << ((num) + 4))) != 0)
> +
> +#define IRQ_CNTPSIRQ    0
> +#define IRQ_CNTPNSIRQ   1
> +#define IRQ_CNTHPIRQ    2
> +#define IRQ_CNTVIRQ     3
> +#define IRQ_MAILBOX0    4
> +#define IRQ_MAILBOX1    5
> +#define IRQ_MAILBOX2    6
> +#define IRQ_MAILBOX3    7
> +#define IRQ_GPU         8
> +#define IRQ_PMU         9
> +#define IRQ_AXI         10
> +#define IRQ_TIMER       11
> +#define IRQ_MAX         IRQ_TIMER
> +
> +/* Update interrupts.  */
> +static void bcm2836_control_update(BCM2836ControlState *s)
> +{
> +    int i, j;
> +
> +    /*
> +     * reset pending IRQs/FIQs
> +     */

Collapse to single line comment, here and below.

> +
> +    for (i = 0; i < BCM2836_NCORES; i++) {
> +        s->irqsrc[i] = s->fiqsrc[i] = 0;
> +    }
> +
> +    /*
> +     * apply routing logic, update status regs
> +     */
> +
> +    if (s->gpu_irq) {
> +        assert(s->route_gpu_irq < BCM2836_NCORES);
> +        s->irqsrc[s->route_gpu_irq] |= (uint32_t)1 << IRQ_GPU;
> +    }
> +
> +    if (s->gpu_fiq) {
> +        assert(s->route_gpu_fiq < BCM2836_NCORES);
> +        s->fiqsrc[s->route_gpu_fiq] |= (uint32_t)1 << IRQ_GPU;
> +    }
> +
> +    for (i = 0; i < BCM2836_NCORES; i++) {
> +        /* handle local interrupts for this core */
> +        if (s->localirqs[i]) {
> +            assert(s->localirqs[i] < (1 << IRQ_MAILBOX0));

Curious, what is the source of this limitation?

> +            for (j = 0; j < IRQ_MAILBOX0; j++) {
> +                if ((s->localirqs[i] & (1 << j)) != 0) {
> +                    /* local interrupt j is set */
> +                    if (FIQ_BIT(s->timercontrol[i], j)) {
> +                        /* deliver a FIQ */
> +                        s->fiqsrc[i] |= (uint32_t)1 << j;
> +                    } else if (IRQ_BIT(s->timercontrol[i], j)) {
> +                        /* deliver an IRQ */

Overcommented.

> +                        s->irqsrc[i] |= (uint32_t)1 << j;
> +                    } else {
> +                        /* the interrupt is masked */
> +                    }
> +                }
> +            }
> +        }
> +
> +        /* handle mailboxes for this core */
> +        for (j = 0; j < BCM2836_MBPERCORE; j++) {
> +            if (s->mailboxes[i * BCM2836_MBPERCORE + j] != 0) {
> +                /* mailbox j is set */
> +                if (FIQ_BIT(s->mailboxcontrol[i], j)) {
> +                    /* deliver a FIQ */
> +                    s->fiqsrc[i] |= (uint32_t)1 << (j + IRQ_MAILBOX0);
> +                } else if (IRQ_BIT(s->mailboxcontrol[i], j)) {
> +                    /* deliver an IRQ */
> +                    s->irqsrc[i] |= (uint32_t)1 << (j + IRQ_MAILBOX0);
> +                } else {
> +                    /* the interrupt is masked */
> +                }
> +            }
> +        }
> +    }
> +
> +    /*
> +     * call set_irq appropriately for each output
> +     */
> +
> +    for (i = 0; i < BCM2836_NCORES; i++) {
> +        qemu_set_irq(s->irq[i], s->irqsrc[i] != 0);
> +        qemu_set_irq(s->fiq[i], s->fiqsrc[i] != 0);
> +    }
> +}
> +
> +static void bcm2836_control_set_local_irq(void *opaque, int core, int local_irq,
> +                                          int level)
> +{
> +    BCM2836ControlState *s = opaque;
> +
> +    assert(core >= 0 && core < BCM2836_NCORES);
> +    assert(local_irq >= 0 && local_irq <= IRQ_CNTVIRQ);
> +
> +    if (level) {
> +        s->localirqs[core] |= 1 << local_irq;
> +    } else {
> +        s->localirqs[core] &= ~((uint32_t)1 << local_irq);
> +    }
> +
> +    bcm2836_control_update(s);
> +}
> +
> +/* XXX: the following wrapper functions are a kludgy workaround,
> + * needed because I can't seem to pass useful information in the "irq"
> + * parameter when using named interrupts. Feel free to clean this up!
> + */

Yep. Known issue. The lack of opaque data other than the device itself
to qemu_irq definitions. Fine as-is until that core code is fixed, or
you could resort to some ## magic.

> +
> +static void bcm2836_control_set_local_irq0(void *opaque, int core, int level)
> +{
> +    bcm2836_control_set_local_irq(opaque, core, 0, level);
> +}
> +
> +static void bcm2836_control_set_local_irq1(void *opaque, int core, int level)
> +{
> +    bcm2836_control_set_local_irq(opaque, core, 1, level);
> +}
> +
> +static void bcm2836_control_set_local_irq2(void *opaque, int core, int level)
> +{
> +    bcm2836_control_set_local_irq(opaque, core, 2, level);
> +}
> +
> +static void bcm2836_control_set_local_irq3(void *opaque, int core, int level)
> +{
> +    bcm2836_control_set_local_irq(opaque, core, 3, level);
> +}
> +
> +static void bcm2836_control_set_gpu_irq(void *opaque, int irq, int level)
> +{
> +    BCM2836ControlState *s = opaque;
> +
> +    s->gpu_irq = level;
> +
> +    bcm2836_control_update(s);
> +}
> +
> +static void bcm2836_control_set_gpu_fiq(void *opaque, int irq, int level)
> +{
> +    BCM2836ControlState *s = opaque;
> +
> +    s->gpu_fiq = level;
> +
> +    bcm2836_control_update(s);
> +}
> +
> +static uint64_t bcm2836_control_read(void *opaque, hwaddr offset, unsigned size)
> +{
> +    BCM2836ControlState *s = opaque;
> +
> +    if (offset == 0xc) {
> +        /* GPU interrupt routing */
> +        assert(s->route_gpu_fiq < BCM2836_NCORES
> +               && s->route_gpu_irq < BCM2836_NCORES);
> +        return ((uint32_t)s->route_gpu_fiq << 2) | s->route_gpu_irq;
> +    } else if (offset >= 0x40 && offset < 0x50) {
> +        /* Timer interrupt control registers */
> +        return s->timercontrol[(offset - 0x40) >> 2];
> +    } else if (offset >= 0x50 && offset < 0x60) {
> +        /* Mailbox interrupt control registers */
> +        return s->mailboxcontrol[(offset - 0x50) >> 2];
> +    } else if (offset >= 0x60 && offset < 0x70) {
> +        /* IRQ source registers */
> +        return s->irqsrc[(offset - 0x60) >> 2];
> +    } else if (offset >= 0x70 && offset < 0x80) {
> +        /* FIQ source registers */
> +        return s->fiqsrc[(offset - 0x70) >> 2];
> +    } else if (offset >= 0xc0 && offset < 0x100) {
> +        /* Mailboxes */
> +        return s->mailboxes[(offset - 0xc0) >> 2];
> +    } else {
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return 0;
> +    }
> +}
> +
> +static void bcm2836_control_write(void *opaque, hwaddr offset,
> +                                  uint64_t val, unsigned size)
> +{
> +    BCM2836ControlState *s = opaque;
> +
> +    if (offset == 0xc) {
> +        /* GPU interrupt routing */
> +        s->route_gpu_irq = val & 0x3;
> +        s->route_gpu_fiq = (val >> 2) & 0x3;
> +    } else if (offset >= 0x40 && offset < 0x50) {
> +        /* Timer interrupt control registers */
> +        s->timercontrol[(offset - 0x40) >> 2] = val & 0xff;
> +    } else if (offset >= 0x50 && offset < 0x60) {
> +        /* Mailbox interrupt control registers */
> +        s->mailboxcontrol[(offset - 0x50) >> 2] = val & 0xff;
> +    } else if (offset >= 0x80 && offset < 0xc0) {
> +        /* Mailbox set registers */
> +        s->mailboxes[(offset - 0x80) >> 2] |= val;
> +    } else if (offset >= 0xc0 && offset < 0x100) {
> +        /* Mailbox clear registers */
> +        s->mailboxes[(offset - 0xc0) >> 2] &= ~val;
> +    } else {
> +        qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
> +                      __func__, offset);
> +        return;
> +    }
> +
> +    bcm2836_control_update(s);
> +}
> +
> +static const MemoryRegionOps bcm2836_control_ops = {
> +    .read = bcm2836_control_read,
> +    .write = bcm2836_control_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void bcm2836_control_reset(DeviceState *d)
> +{
> +    BCM2836ControlState *s = BCM2836_CONTROL(d);
> +    int i;
> +
> +    s->route_gpu_irq = s->route_gpu_fiq = 0;
> +
> +    for (i = 0; i < BCM2836_NCORES; i++) {
> +        s->timercontrol[i] = 0;
> +        s->mailboxcontrol[i] = 0;
> +    }
> +
> +    for (i = 0; i < BCM2836_NCORES * BCM2836_MBPERCORE; i++) {
> +        s->mailboxes[i] = 0;
> +    }
> +}
> +
> +static void bcm2836_control_init(Object *obj)
> +{
> +    BCM2836ControlState *s = BCM2836_CONTROL(obj);
> +    DeviceState *dev = DEVICE(obj);
> +
> +    memory_region_init_io(&s->iomem, obj, &bcm2836_control_ops, s,
> +                          TYPE_BCM2836_CONTROL, 0x100);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem);
> +
> +    /* inputs from each CPU core */
> +    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq0, "cntpsirq",
> +                            BCM2836_NCORES);
> +    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq1, "cntpnsirq",
> +                            BCM2836_NCORES);
> +    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq2, "cnthpirq",
> +                            BCM2836_NCORES);
> +    qdev_init_gpio_in_named(dev, bcm2836_control_set_local_irq3, "cntvirq",
> +                            BCM2836_NCORES);
> +    /* qdev_init_gpio_in_named(dev, bcm2836_control_set_pmu_irq, "pmuirq",
> +                            BCM2836_NCORES); */
> +
> +    /* IRQ and FIQ inputs from upstream bcm2835 controller */
> +    qdev_init_gpio_in_named(dev, bcm2836_control_set_gpu_irq, "gpu_irq", 1);
> +    qdev_init_gpio_in_named(dev, bcm2836_control_set_gpu_fiq, "gpu_fiq", 1);
> +
> +    /* outputs to CPU cores */
> +    qdev_init_gpio_out_named(dev, s->irq, "irq", BCM2836_NCORES);
> +    qdev_init_gpio_out_named(dev, s->fiq, "fiq", BCM2836_NCORES);
> +}
> +
> +static const VMStateDescription vmstate_bcm2836_control = {
> +    .name = TYPE_BCM2836_CONTROL,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32_ARRAY(mailboxes, BCM2836ControlState,
> +                             BCM2836_NCORES * BCM2836_MBPERCORE),
> +        VMSTATE_UINT8(route_gpu_irq, BCM2836ControlState),
> +        VMSTATE_UINT8(route_gpu_fiq, BCM2836ControlState),
> +        VMSTATE_UINT32_ARRAY(timercontrol, BCM2836ControlState, BCM2836_NCORES),
> +        VMSTATE_UINT32_ARRAY(mailboxcontrol, BCM2836ControlState,
> +                             BCM2836_NCORES),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void bcm2836_control_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = bcm2836_control_reset;
> +    dc->vmsd = &vmstate_bcm2836_control;
> +}
> +
> +static TypeInfo bcm2836_control_info = {
> +    .name          = TYPE_BCM2836_CONTROL,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(BCM2836ControlState),
> +    .class_init    = bcm2836_control_class_init,
> +    .instance_init = bcm2836_control_init,
> +};
> +
> +static void bcm2836_control_register_types(void)
> +{
> +    type_register_static(&bcm2836_control_info);
> +}
> +
> +type_init(bcm2836_control_register_types)
> diff --git a/include/hw/intc/bcm2836_control.h b/include/hw/intc/bcm2836_control.h
> new file mode 100644
> index 0000000..8a9a2f2
> --- /dev/null
> +++ b/include/hw/intc/bcm2836_control.h
> @@ -0,0 +1,51 @@
> +/*
> + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> + * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
> + *
> + * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
> + * Written by Andrew Baumann
> + *
> + * This code is licensed under the GNU GPLv2 and later.
> + */
> +
> +#ifndef BCM2836_CONTROL_H
> +#define BCM2836_CONTROL_H
> +
> +#include "hw/sysbus.h"
> +
> +/* 4 mailboxes per core, for 16 total */
> +#define BCM2836_NCORES 4
> +#define BCM2836_MBPERCORE 4
> +
> +#define TYPE_BCM2836_CONTROL "bcm2836_control"
> +#define BCM2836_CONTROL(obj) \
> +    OBJECT_CHECK(BCM2836ControlState, (obj), TYPE_BCM2836_CONTROL)
> +
> +typedef struct BCM2836ControlState {
> +    /*< private >*/
> +    SysBusDevice busdev;
> +    /*< public >*/
> +    MemoryRegion iomem;
> +
> +    /* interrupt status registers (not directly visible to user) */
> +    bool gpu_irq, gpu_fiq;
> +    uint32_t localirqs[BCM2836_NCORES];
> +
> +    /* mailboxes */
> +    uint32_t mailboxes[BCM2836_NCORES * BCM2836_MBPERCORE];
> +
> +    /* interrupt routing/control registers */
> +    uint8_t route_gpu_irq, route_gpu_fiq;
> +    uint32_t timercontrol[BCM2836_NCORES];
> +    uint32_t mailboxcontrol[BCM2836_NCORES];
> +
> +    /* interrupt source registers, post-routing (visible) */
> +    uint32_t irqsrc[BCM2836_NCORES];
> +    uint32_t fiqsrc[BCM2836_NCORES];
> +
> +    /* outputs to CPU cores */
> +    qemu_irq irq[BCM2836_NCORES];
> +    qemu_irq fiq[BCM2836_NCORES];
> +} BCM2836ControlState;
> +
> +#endif
> --
> 2.5.3
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes
  2015-12-31  0:12   ` Peter Crosthwaite
@ 2015-12-31 18:06     ` Andrew Baumann
  0 siblings, 0 replies; 22+ messages in thread
From: Andrew Baumann @ 2015-12-31 18:06 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, qemu-devel@nongnu.org Developers, qemu-arm,
	Paolo Bonzini

Hi Peter,

> From: Peter Crosthwaite [mailto:crosthwaitepeter@gmail.com]
> Sent: Wednesday, 30 December 2015 16:13
> On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
> <Andrew.Baumann@microsoft.com> wrote:
> > This adds the system mailboxes which are used to communicate with a
> > number of GPU peripherals on Pi/Pi2.
[...]
> > --- /dev/null
> > +++ b/hw/misc/bcm2835_mbox.c
> > @@ -0,0 +1,323 @@
> > +/*
> > + * Raspberry Pi emulation (c) 2012 Gregory Estrade
> 
> Should we change this to "Broadcom SoC emulation"?

Until we support more than one Broadcom SoC, probably not -- this is all based on the Pi documentation, and I have no idea how much commonality there is to other parts.

[...]
> > +static void mbox_push(BCM2835Mbox *mb, uint32_t val)
> > +{
> > +    assert(mb->count < MBOX_SIZE);
> 
> mbox_update can call mbox_push with val == a DMA value, which usually
> suggests that this may be a guest controllable (and a guest error
> rather than an assert). Is the mbox AS guest accessible? (I had a look
> at the later patches, and the MBox AS seems private but can values be
> set via the guest indirectly?).

These come from child devices (bcm2835_property in the present series). The other case where this arises is a push in mbox 1, but that is already checked in bcm2835_mbox_write, so I think an assert is appropriate.

[...]
> > +static void bcm2835_mbox_set_irq(void *opaque, int irq, int level)
> > +{
> > +    BCM2835MboxState *s = opaque;
> > +
> > +    s->available[irq] = level;
> > +
> > +    /* avoid recursively calling bcm2835_mbox_update when the interrupt
> > +     * status changes due to the ldl_phys call within that function */
> 
> Space before */

Huh? You mean newline? (There's already a space.)

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals
  2015-12-31  2:53   ` Peter Crosthwaite
@ 2015-12-31 18:23     ` Andrew Baumann
  0 siblings, 0 replies; 22+ messages in thread
From: Andrew Baumann @ 2015-12-31 18:23 UTC (permalink / raw)
  To: Peter Crosthwaite, Alistair Francis
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, qemu-devel@nongnu.org Developers, qemu-arm,
	Paolo Bonzini

> From: Peter Crosthwaite [mailto:crosthwaitepeter@gmail.com]
> Sent: Wednesday, 30 December 2015 18:54
> On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
> <Andrew.Baumann@microsoft.com> wrote:
> > This device maintains all the non-CPU peripherals on bcm2835 (Pi1)
> > which are also present on bcm2836 (Pi2). It also implements the
> > private address space used for DMA.
[...]
> > +    sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->peri_mr);
> > +
> > +    /* Internal memory region for peripheral bus addresses (not exported)
> */
> > +    memory_region_init_io(&s->gpu_bus_mr, OBJECT(s), NULL, s,
> "bcm2835_gpu_bus",
> > +                          (uint64_t)1 << 32);
> 
> You already have obj for the OBJECT casted version of s.
> 
> Why do you us memory_region_init_io though instead of
> memory_region_init? This looks like a container MR which is what
> unqualified memory_region_init provides.

Hmm, probably just copy-and-paste. If memory_region_init works, I'll use that.

> > +    object_property_add_child(obj, "gpu_bus", OBJECT(&s->gpu_bus_mr),
> NULL);
> > +
> > +    /* Internal memory region for communication of mailbox channel data
> */
> > +    memory_region_init_io(&s->mbox_mr, OBJECT(s), NULL, s,
> "bcm2835_mbox",
> > +                          MBOX_CHAN_COUNT << 4);
> > +
> 
> Same here. Although this container seems to have only one subregion at
> offset 0 (the property device). Long term, will this MR have more
> stuff in it or will always be just the property?

Yes, there are a couple more such devices to come. See:
https://github.com/0xabu/qemu/blob/raspi/hw/arm/bcm2835_peripherals.c#L263

[...]
> > +    /* XXX: assume that RAM is contiguous and mapped at system address
> zero */
> > +    ram = memory_region_find(get_system_memory(), 0, 1).mr;
> 
> Not sure about this. Alistair (from Xilinx) has a similar problem
> where the SoC needed to do a complex split of the single DDR into
> multiple system address regions. I cc'd you on a patch. Following
> Alistair's patch in the Xiinx ep108/zynqmp work, the system_memory
> region is now fully owned by the SoC level and disused by the
> machine/board level. I would suggest something similar here. The board
> is responsible for creating (and mainly sizing) the RAM, and links (or
> const-link's) the RAM to the SoC where it can be subregioned as-is
> without this search. As you already have SoC level memory regions for
> your multiple address spaces, you may actually end up with
> system_memory being completely unused (and that is OK).

Ok. There are different Pi boards with different ram sizes, so it seems the right thing to do is allocate the ram as I already do at the board level, but then pass it via a link property to the SoC (as Alistair does) and not bother with system_memory.

> > +    assert(ram != NULL && memory_region_size(ram) >= 128 * 1024 *
> 1024);
> 
> What is is the significance of the 128MB lower clamp? This should
> probably be a weaker error than assert. Depending on the reason for
> the error, it could be located in a number of different places. If the
> SoC cannot function without 128MB for some reason this is the right
> place.

This was just a paranoid check to make sure that my fragile search for the system memory found the right thing -- 128MB was just a lower bound on a sane memory size. It can go away.

[...]
> > +    /* Property channel */
> 
> These are all self-documented by the already-well-named s-> fields, so
> you can drop these comments indicating what you are realizing.

*shrug* I find them quite helpful when navigating the code. Plus I never really see the point of deleting (accurate, non-distracting) comments.

[...]
> > --- /dev/null
> > +++ b/include/hw/arm/raspi_platform.h
> > @@ -0,0 +1,161 @@
> > +/*
> > + * bcm2708 aka bcm2835/2836 aka Raspberry Pi/Pi2 SoC platform defines
> > + *
> > + * These definitions are derived from those in Linux at
> > + * arch/arm/mach-{bcm2708,bcm2709}/include/mach/platform.h
> 
> I think this is in the same basket as the header from P1. We should
> cherry pick out the defs that we care about (or are likely to care
> about in near term follow up). I'm guessing this is sourced from the
> same Linux fork as before?

Yes. I can drop some of the defs (e.g. redundant interrupts); however, assuming that we'll eventually have a full-fledged emulation, most of them will end up being needed, so I'd prefer not to have to throw them all away and then re-add them in later patches.

[...]
> > +#define ARM_IRQ2_BASE                  32
> 
> Can you just keep it as one big 64-long list? I don't think we need
> the _BASE defs at all anymore.

Yes, we could, but this helps diff-ability against the original file, and I really don't think it's that hard to parse.

[...]
> > +#define ARM_IRQ0_BASE                  64
> 
> This 64 shouldn't be needed anymore with the arm_irqs now in their own
> enumeration space. It should just count from 0 again (and I think the
> only usages you have of these subtract off ARM_IRQ0_BASE).

Agreed. I was planning to address this by setting ARM_IRQ0_BASE to 0 (again to keep the diff easily readable).

> > +#define INTERRUPT_ARM_TIMER            (ARM_IRQ0_BASE + 0)
> > +#define INTERRUPT_ARM_MAILBOX          (ARM_IRQ0_BASE + 1)
> > +#define INTERRUPT_ARM_DOORBELL_0       (ARM_IRQ0_BASE + 2)
> > +#define INTERRUPT_ARM_DOORBELL_1       (ARM_IRQ0_BASE + 3)
> > +#define INTERRUPT_VPU0_HALTED          (ARM_IRQ0_BASE + 4)
> > +#define INTERRUPT_VPU1_HALTED          (ARM_IRQ0_BASE + 5)
> > +#define INTERRUPT_ILLEGAL_TYPE0        (ARM_IRQ0_BASE + 6)
> > +#define INTERRUPT_ILLEGAL_TYPE1        (ARM_IRQ0_BASE + 7)
> 
> The defs after here are confusing. Are they for a different SoC? I
> thought the SoC was limited to 8 ARM_ irqs?

This seems to be an artifact of the way Linux manages the interrupt controller. Some of the GPU IRQs on the interrupt controller are aliased into another set of status bits where they can be checked in the same read as the ARM IRQs. It looks like Linux treats those as totally different interrupts. I'll just delete them from this file.

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic
  2015-12-31  3:20   ` Peter Crosthwaite
@ 2015-12-31 18:43     ` Andrew Baumann
  0 siblings, 0 replies; 22+ messages in thread
From: Andrew Baumann @ 2015-12-31 18:43 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, Grégory ESTRADE, Stefan Weil,
	Peter Crosthwaite, qemu-devel@nongnu.org Developers, qemu-arm,
	Paolo Bonzini

> From: Peter Crosthwaite [mailto:crosthwaitepeter@gmail.com]
> Sent: Wednesday, 30 December 2015 19:21
> On Wed, Dec 23, 2015 at 4:25 PM, Andrew Baumann
> <Andrew.Baumann@microsoft.com> wrote:
> > This module is specific to the bcm2836 (Pi2). It implements the top
> > level interrupt controller, and mailboxes used for inter-processor
> > synchronisation.
[...]
> > --- /dev/null
> > +++ b/hw/intc/bcm2836_control.c
> > @@ -0,0 +1,338 @@
> > +/*
> > + * Rasperry Pi 2 emulation ARM control logic module.
> > + * Copyright (c) 2015, Microsoft
> > + * Written by Andrew Baumann
> > + *
> > + * At present, only implements interrupt routing, and mailboxes (i.e.,
> > + * not local timer, PMU interrupt, or AXI counters).
> > + *
> > + * Ref:
> > + *
> https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm28
> 36/QA7_rev3.4.pdf
> 
> This looks like an mpcore. Check hw/cpu/a9mpcore and friends to see
> how those are implemented. I think this is architecturally OK for the
> moment, although if you intend to expand this with Timers etc. it
> should be in hw/cpu/ and containerised. I think the containerisation
> can happen later but should be put it in hw/cpu/ straight up?

If only! I (and probably everyone that has ported an OS to it) wish it was an mpcore and not another custom Pi-specific thing :)

You might have an argument for moving the whole file from hw/intc to hw/cpu, but I don't think splitting these functions up (even if we implemented them all in the future, which I don't plan to do unless some guest OS turns out to use them) makes much sense. The spec is written as if it was one device, and the registers are all interleaved (e.g. the interrupt routing config registers are sandwiched in between the timer control/prescaler and status registers).

I really don't care which directory it lives in, however -- you can tell me what's best. As presently implemented (and as it is used by Linux and Windows), this thing is closest to an interrupt controller.

[...]
> > +    for (i = 0; i < BCM2836_NCORES; i++) {
> > +        /* handle local interrupts for this core */
> > +        if (s->localirqs[i]) {
> > +            assert(s->localirqs[i] < (1 << IRQ_MAILBOX0));
> 
> Curious, what is the source of this limitation?

That's just sanity-checking an invariant of my implementation. The local interrupts for each core are the four timers, the PMU interrupt (NYI), and the four mailboxes. However, the mailboxes use a separate set of registers (and are handled in logic below this), so it's an internal error if we ever see those bits set. This could be better commented, and the uint32_t for localirqs could be a uint8.

> > +            for (j = 0; j < IRQ_MAILBOX0; j++) {
> > +                if ((s->localirqs[i] & (1 << j)) != 0) {
> > +                    /* local interrupt j is set */
> > +                    if (FIQ_BIT(s->timercontrol[i], j)) {
> > +                        /* deliver a FIQ */
> > +                        s->fiqsrc[i] |= (uint32_t)1 << j;
> > +                    } else if (IRQ_BIT(s->timercontrol[i], j)) {
> > +                        /* deliver an IRQ */
> 
> Overcommented.

Maybe I'm more defensive because this is my code, but I'm respectfully going to disagree and ignore you on this one, at least until the next patch series :) I'm not a fan of deleting comments that are accurate, concise, and (IMHO) help the reader of the code immediately understand its logic. We can discuss it again in v3 if you feel strongly about it.

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
  2015-12-31  1:13 ` [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Piotr Król
@ 2016-01-06 18:27   ` Andrew Baumann
  2016-01-07  0:09     ` Piotr Król
  0 siblings, 1 reply; 22+ messages in thread
From: Andrew Baumann @ 2016-01-06 18:27 UTC (permalink / raw)
  To: Piotr Król, qemu-devel

Hi Piotr,

Sorry, I just noticed this email. Please keep me in the To or CC, as I am not good at keeping up with all the traffic on qemu-devel.

> From: qemu-devel-bounces+andrew.baumann=microsoft.com@nongnu.org
> [mailto:qemu-devel-
> bounces+andrew.baumann=microsoft.com@nongnu.org] On Behalf Of Piotr
> Król
> Sent: Wednesday, 30 December 2015 17:14

> First, I tried your code from raspi branch (ar7-raspi doesn't compile [1]).
> Using recent Raspbian 2015-11-21-raspbian-jessie (same results I saw for
> 2015-09-24). I'm getting kernel panic:
> 
> [    6.892677] random: systemd urandom read with 7 bits of entropy available
> [    6.908292] Kernel panic - not syncing: Attempted to kill init!
> exitcode=0x00000004

This is most likely an unimplemented setend instruction in the userspace memcmp. You need to mount the image, and comment out the contents of (or just remove) /etc/ld.so.preload, then it should boot further.

BTW, I mentioned this briefly in the notes on Linux at the end of this page:
https://github.com/0xabu/qemu/wiki

> Third test I tried is to apply patches from this series on top of master
> (38a762fec63f), what cause hang on:
> 
> [   15.094558 ] mmc0: Timeout waiting for hardware interrupt

Hmm, I have seen this error on the raspi machine, but I don't think I saw it on raspi2 before. Does it also occur on the older (09-24) image? I've seen this on raspi, but it only occurs when using the DMA controller, and in the patch series presently on list, there is no DMA controller included, so it can't be that.

> I do not follow this mailing list, so maybe I missing some pieces.
> If I need some other patches to test this series please let me know.

There are other patches (on the list) with changes to sd and sdhci emulation needed to boot Windows, but for Linux I believe this is all you need.

> My questions:
> 
> Does 2015-09-24-raspbian-jessie.vhd extracted Linux partition from raspbian
> image or simply img converted to vhd format ? Is there any problem with
> using img ?

No, img is fine. I converted it to a VHD container, because it's easier to work with on Windows (and avoids qemu's warning about raw images).

> Would you mind to issue tracking on GitHub and pull requests or you want
> whole
> communication and possible fixes go through QEMU mailing list ? I think that
> it
> maybe useful for code that is not ready for upstreaming. I saw you have
> issue
> tracking disabled.

I'm in a bind here. My original goal was simply to contribute the raspi2 + Windows guest support. Then I discovered that the raspi work itself was not yet in mainline qemu, and so I've been working to clean that up and get it merged along with the raspi2 work. However, I don't have the time/resources to be a long-term maintainer of everything Pi-related. I'm happy to enable issue tracking on github, but don't want to give a false impression as to the level of support it's likely to receive :) On pull requests: my goal is to get everything in my raspi branch merged upstream (which is why I recently dropped some stub device emulations that weren't needed); assuming that happens I'd prefer if subsequent changes went through the qemu patch process, since ultimately that's how they'll get into mainline and be maintained in the longer term. (I'm happy to be CCed on patches and provide feedback.)

BTW, the biggest roadblock in my plan above is the USB host controller emulation (by Gregory), which is obviously incomplete/hacky, but still works well enough for Linux keyboard/mouse that it's useful to people. If someone wants to pick that up, I would be very happy :)

Cheers,
Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
  2016-01-06 18:27   ` Andrew Baumann
@ 2016-01-07  0:09     ` Piotr Król
  2016-01-07  0:14       ` Andrew Baumann
  2016-01-07  2:46       ` Peter Crosthwaite
  0 siblings, 2 replies; 22+ messages in thread
From: Piotr Król @ 2016-01-07  0:09 UTC (permalink / raw)
  To: Andrew Baumann; +Cc: qemu-devel

On Wed, Jan 06, 2016 at 06:27:54PM +0000, Andrew Baumann wrote:
> Hi Piotr,
> 
> Sorry, I just noticed this email. Please keep me in the To or CC, as I am not good at keeping up with all the traffic on qemu-devel.

Hi Andrew,
this was my fault instead reply-to-all I send reply to mailing list. I
realized after sending.

> 
> > From: qemu-devel-bounces+andrew.baumann=microsoft.com@nongnu.org
> > [mailto:qemu-devel-
> > bounces+andrew.baumann=microsoft.com@nongnu.org] On Behalf Of Piotr
> > Król
> > Sent: Wednesday, 30 December 2015 17:14
> 
> > First, I tried your code from raspi branch (ar7-raspi doesn't compile [1]).
> > Using recent Raspbian 2015-11-21-raspbian-jessie (same results I saw for
> > 2015-09-24). I'm getting kernel panic:
> > 
> > [    6.892677] random: systemd urandom read with 7 bits of entropy available
> > [    6.908292] Kernel panic - not syncing: Attempted to kill init!
> > exitcode=0x00000004
> 
> This is most likely an unimplemented setend instruction in the
> userspace memcmp. You need to mount the image, and comment out the
> contents of (or just remove) /etc/ld.so.preload, then it should boot
> further.

Yes, I figured this out.

> 
> BTW, I mentioned this briefly in the notes on Linux at the end of this page:
> https://github.com/0xabu/qemu/wiki
> 
> > Third test I tried is to apply patches from this series on top of master
> > (38a762fec63f), what cause hang on:
> > 
> > [   15.094558 ] mmc0: Timeout waiting for hardware interrupt
> 
> Hmm, I have seen this error on the raspi machine, but I don't think I
> saw it on raspi2 before. Does it also occur on the older (09-24)
> image? I've seen this on raspi, but it only occurs when using the DMA
> controller, and in the patch series presently on list, there is no DMA
> controller included, so it can't be that.
> 

I tried v2 with qemu 38a762fec63f using:

$ qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd 2015-11-21-raspbian-jessie.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2" -dtb raspbian-boot/bcm2709-rpi-2-b.dtb -usbdevice mouse -usbdevice keyboard -serial stdio

WARNING: Image format was not specified for '2015-11-21-raspbian-jessie.img' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
         Specify the 'raw' format explicitly to remove the restrictions.
qemu-system-arm: -usbdevice mouse: Error: no usb bus to attach usbdevice mouse, please try -machine usb=on and check that the machine model supports USB
qemu-system-arm: -usbdevice mouse: could not add USB device 'mouse'
 
Removing USB:
qemu-system-arm -M raspi2 -kernel 2015-11-21-raspbian-boot/kernel7.img -sd 2015-11-21-raspbian-jessie.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2" -dtb 2015-11-21-raspbian-boot/bcm2709-rpi-2-b.dtb -serial stdio

[    5.071960] uart-pl011 3f201000.uart: no DMA platform data
[   15.083445] mmc0: Timeout waiting for hardware interrupt.
<hang>

Same stuff with 2015-09-24.

Trying your GitHub raspi branch everything works fine after commenting in
/etc/ld.so.preload.

> > I do not follow this mailing list, so maybe I missing some pieces.
> > If I need some other patches to test this series please let me know.
> 

> There are other patches (on the list) with changes to sd and sdhci
> emulation needed to boot Windows, but for Linux I believe this is all
> you need.
> 
> > My questions:
> > 
> > Does 2015-09-24-raspbian-jessie.vhd extracted Linux partition from raspbian
> > image or simply img converted to vhd format ? Is there any problem with
> > using img ?
> 
> No, img is fine. I converted it to a VHD container, because it's
> easier to work with on Windows (and avoids qemu's warning about raw
> images).
> 
> > Would you mind to issue tracking on GitHub and pull requests or you want
> > whole
> > communication and possible fixes go through QEMU mailing list ? I think that
> > it
> > maybe useful for code that is not ready for upstreaming. I saw you have
> > issue
> > tracking disabled.
> 
> I'm in a bind here. My original goal was simply to contribute the
> raspi2 + Windows guest support. Then I discovered that the raspi work
> itself was not yet in mainline qemu, and so I've been working to clean
> that up and get it merged along with the raspi2 work. However, I don't
> have the time/resources to be a long-term maintainer of everything
> Pi-related. I'm happy to enable issue tracking on github, but don't
> want to give a false impression as to the level of support it's likely
> to receive :) On pull requests: my goal is to get everything in my
> raspi branch merged upstream (which is why I recently dropped some
> stub device emulations that weren't needed); assuming that happens I'd
> prefer if subsequent changes went through the qemu patch process,
> since ultimately that's how they'll get into mainline and be
> maintained in the longer term. (I'm happy to be CCed on patches and
> provide feedback.)

Understood. Will use mailing list and probably fork of your GitHub
repository.

> 
> BTW, the biggest roadblock in my plan above is the USB host controller
> emulation (by Gregory), which is obviously incomplete/hacky, but still
> works well enough for Linux keyboard/mouse that it's useful to people.
> If someone wants to pick that up, I would be very happy :)

What you mean by 'pick that up' ? Is Gregory's USB code available
somewhere and have to be cleaned and upstreamed ? Please point me to
this pice and I would check what I can do.

> 
> Cheers,
> Andrew

Best Regards,
-- 
Piotr Król
Embedded Systems Consultant
http://3mdeb.com | @3mdeb_com

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
  2016-01-07  0:09     ` Piotr Król
@ 2016-01-07  0:14       ` Andrew Baumann
  2016-01-07  2:46       ` Peter Crosthwaite
  1 sibling, 0 replies; 22+ messages in thread
From: Andrew Baumann @ 2016-01-07  0:14 UTC (permalink / raw)
  To: Piotr Król; +Cc: qemu-devel

> From: Piotr Król [mailto:piotr.krol@3mdeb.com]
> Sent: Wednesday, 6 January 2016 16:10
[...]
> I tried v2 with qemu 38a762fec63f using:
> 
> $ qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd 2015-
> 11-21-raspbian-jessie.img -append "rw earlyprintk loglevel=8
> console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2" -
> dtb raspbian-boot/bcm2709-rpi-2-b.dtb -usbdevice mouse -usbdevice
> keyboard -serial stdio

Try dropping the -dtb parameter. I think the DTB file tells Linux to use the non-existent DMA controller. If that doesn't work, check the command I included in the initial email of the patch series ("patch" 0/7) -- I tested that at least once :)

> > BTW, the biggest roadblock in my plan above is the USB host controller
> > emulation (by Gregory), which is obviously incomplete/hacky, but still
> > works well enough for Linux keyboard/mouse that it's useful to people.
> > If someone wants to pick that up, I would be very happy :)
> 
> What you mean by 'pick that up' ? Is Gregory's USB code available
> somewhere and have to be cleaned and upstreamed ? Please point me to
> this pice and I would check what I can do.

It's here:
https://github.com/0xabu/qemu/blob/raspi/hw/usb/bcm2835_usb.c

I have not attempted to understand the code, or the controller it emulates but the first comment says a lot:
	/* This is wrong at so many levels, but well, I'm releasing it anyway */

Cheers,
Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
  2016-01-07  0:09     ` Piotr Król
  2016-01-07  0:14       ` Andrew Baumann
@ 2016-01-07  2:46       ` Peter Crosthwaite
  2016-01-07  4:47         ` Andrew Baumann
  1 sibling, 1 reply; 22+ messages in thread
From: Peter Crosthwaite @ 2016-01-07  2:46 UTC (permalink / raw)
  To: Piotr Król, Andrew Baumann, qemu-devel

On Wed, Jan 6, 2016 at 4:09 PM, Piotr Król <piotr.krol@3mdeb.com> wrote:
> On Wed, Jan 06, 2016 at 06:27:54PM +0000, Andrew Baumann wrote:
>> Hi Piotr,
>>
>> Sorry, I just noticed this email. Please keep me in the To or CC, as I am not good at keeping up with all the traffic on qemu-devel.
>
> Hi Andrew,
> this was my fault instead reply-to-all I send reply to mailing list. I
> realized after sending.
>
>>
>> > From: qemu-devel-bounces+andrew.baumann=microsoft.com@nongnu.org
>> > [mailto:qemu-devel-
>> > bounces+andrew.baumann=microsoft.com@nongnu.org] On Behalf Of Piotr
>> > Król
>> > Sent: Wednesday, 30 December 2015 17:14
>>
>> > First, I tried your code from raspi branch (ar7-raspi doesn't compile [1]).
>> > Using recent Raspbian 2015-11-21-raspbian-jessie (same results I saw for
>> > 2015-09-24). I'm getting kernel panic:
>> >
>> > [    6.892677] random: systemd urandom read with 7 bits of entropy available
>> > [    6.908292] Kernel panic - not syncing: Attempted to kill init!
>> > exitcode=0x00000004
>>
>> This is most likely an unimplemented setend instruction in the
>> userspace memcmp. You need to mount the image, and comment out the
>> contents of (or just remove) /etc/ld.so.preload, then it should boot
>> further.
>
> Yes, I figured this out.
>

Do you need BE8 or BE32?

Some BE8 support can be found here:

https://github.com/Xilinx/qemu/commits/mainline/big_endian

Paolo did have BE32 in the original work but I simplified it out of my
own BE work, as I didn't have any tests for it.
 (I was focussed on AArch64 BE at the time).

Watch out for this bug:

https://lists.gnu.org/archive/html/qemu-devel/2015-10/msg05762.html

Which is probably still at large in that Xilinx branch.

Regards,
Peter

>>
>> BTW, I mentioned this briefly in the notes on Linux at the end of this page:
>> https://github.com/0xabu/qemu/wiki
>>
>> > Third test I tried is to apply patches from this series on top of master
>> > (38a762fec63f), what cause hang on:
>> >
>> > [   15.094558 ] mmc0: Timeout waiting for hardware interrupt
>>
>> Hmm, I have seen this error on the raspi machine, but I don't think I
>> saw it on raspi2 before. Does it also occur on the older (09-24)
>> image? I've seen this on raspi, but it only occurs when using the DMA
>> controller, and in the patch series presently on list, there is no DMA
>> controller included, so it can't be that.
>>
>
> I tried v2 with qemu 38a762fec63f using:
>
> $ qemu-system-arm -M raspi2 -kernel raspbian-boot/kernel7.img -sd 2015-11-21-raspbian-jessie.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2" -dtb raspbian-boot/bcm2709-rpi-2-b.dtb -usbdevice mouse -usbdevice keyboard -serial stdio
>
> WARNING: Image format was not specified for '2015-11-21-raspbian-jessie.img' and probing guessed raw.
>          Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
>          Specify the 'raw' format explicitly to remove the restrictions.
> qemu-system-arm: -usbdevice mouse: Error: no usb bus to attach usbdevice mouse, please try -machine usb=on and check that the machine model supports USB
> qemu-system-arm: -usbdevice mouse: could not add USB device 'mouse'
>
> Removing USB:
> qemu-system-arm -M raspi2 -kernel 2015-11-21-raspbian-boot/kernel7.img -sd 2015-11-21-raspbian-jessie.img -append "rw earlyprintk loglevel=8 console=ttyAMA0,115200 dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2" -dtb 2015-11-21-raspbian-boot/bcm2709-rpi-2-b.dtb -serial stdio
>
> [    5.071960] uart-pl011 3f201000.uart: no DMA platform data
> [   15.083445] mmc0: Timeout waiting for hardware interrupt.
> <hang>
>
> Same stuff with 2015-09-24.
>
> Trying your GitHub raspi branch everything works fine after commenting in
> /etc/ld.so.preload.
>
>> > I do not follow this mailing list, so maybe I missing some pieces.
>> > If I need some other patches to test this series please let me know.
>>
>
>> There are other patches (on the list) with changes to sd and sdhci
>> emulation needed to boot Windows, but for Linux I believe this is all
>> you need.
>>
>> > My questions:
>> >
>> > Does 2015-09-24-raspbian-jessie.vhd extracted Linux partition from raspbian
>> > image or simply img converted to vhd format ? Is there any problem with
>> > using img ?
>>
>> No, img is fine. I converted it to a VHD container, because it's
>> easier to work with on Windows (and avoids qemu's warning about raw
>> images).
>>
>> > Would you mind to issue tracking on GitHub and pull requests or you want
>> > whole
>> > communication and possible fixes go through QEMU mailing list ? I think that
>> > it
>> > maybe useful for code that is not ready for upstreaming. I saw you have
>> > issue
>> > tracking disabled.
>>
>> I'm in a bind here. My original goal was simply to contribute the
>> raspi2 + Windows guest support. Then I discovered that the raspi work
>> itself was not yet in mainline qemu, and so I've been working to clean
>> that up and get it merged along with the raspi2 work. However, I don't
>> have the time/resources to be a long-term maintainer of everything
>> Pi-related. I'm happy to enable issue tracking on github, but don't
>> want to give a false impression as to the level of support it's likely
>> to receive :) On pull requests: my goal is to get everything in my
>> raspi branch merged upstream (which is why I recently dropped some
>> stub device emulations that weren't needed); assuming that happens I'd
>> prefer if subsequent changes went through the qemu patch process,
>> since ultimately that's how they'll get into mainline and be
>> maintained in the longer term. (I'm happy to be CCed on patches and
>> provide feedback.)
>
> Understood. Will use mailing list and probably fork of your GitHub
> repository.
>
>>
>> BTW, the biggest roadblock in my plan above is the USB host controller
>> emulation (by Gregory), which is obviously incomplete/hacky, but still
>> works well enough for Linux keyboard/mouse that it's useful to people.
>> If someone wants to pick that up, I would be very happy :)
>
> What you mean by 'pick that up' ? Is Gregory's USB code available
> somewhere and have to be cleaned and upstreamed ? Please point me to
> this pice and I would check what I can do.
>
>>
>> Cheers,
>> Andrew
>
> Best Regards,
> --
> Piotr Król
> Embedded Systems Consultant
> http://3mdeb.com | @3mdeb_com
>

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
  2016-01-07  2:46       ` Peter Crosthwaite
@ 2016-01-07  4:47         ` Andrew Baumann
  2016-01-07 10:16           ` Peter Maydell
  0 siblings, 1 reply; 22+ messages in thread
From: Andrew Baumann @ 2016-01-07  4:47 UTC (permalink / raw)
  To: Peter Crosthwaite, Piotr Król, qemu-devel

> From: Peter Crosthwaite [mailto:crosthwaitepeter@gmail.com]
> Sent: Wednesday, 6 January 2016 18:47
> On Wed, Jan 6, 2016 at 4:09 PM, Piotr Król <piotr.krol@3mdeb.com> wrote:
> > On Wed, Jan 06, 2016 at 06:27:54PM +0000, Andrew Baumann wrote:
> >> This is most likely an unimplemented setend instruction in the
> >> userspace memcmp. You need to mount the image, and comment out
> the
> >> contents of (or just remove) /etc/ld.so.preload, then it should boot
> >> further.
> >
> > Yes, I figured this out.
> >
> 
> Do you need BE8 or BE32?

After quickly reading up on this, I'm pretty sure we only care about BE8. This is for the setend instructions in memcmp, e.g.:
https://github.com/raspberrypi/linux/commit/5cbcb76ee23807632fcd5db19ebcc2d913011f17

> Some BE8 support can be found here:
> 
> https://github.com/Xilinx/qemu/commits/mainline/big_endian

Thanks for the pointer. It would be nice to get this in for Pi (particularly for newer pi1 kernels, as they have started using the optimised memcmp in the kernel) but it's not on my critical path. Would a Tested-By help?

Andrew

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support
  2016-01-07  4:47         ` Andrew Baumann
@ 2016-01-07 10:16           ` Peter Maydell
  0 siblings, 0 replies; 22+ messages in thread
From: Peter Maydell @ 2016-01-07 10:16 UTC (permalink / raw)
  To: Andrew Baumann; +Cc: Peter Crosthwaite, qemu-devel, Piotr Król

On 7 January 2016 at 04:47, Andrew Baumann <Andrew.Baumann@microsoft.com> wrote:
> Thanks for the pointer. It would be nice to get this in for Pi
> (particularly for newer pi1 kernels, as they have started using
> the optimised memcmp in the kernel) but it's not on my critical path.
> Would a Tested-By help?

Somebody needs to actually send the patches to the mailing list...

(Personally I would prefer the BE32 support as per Paolo's original
patch, since for review you end up needing to think about all the
combinations, but we'll see.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2016-01-07 10:16 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-24  0:25 [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 1/7] bcm2835_mbox: add BCM2835 mailboxes Andrew Baumann
2015-12-31  0:12   ` Peter Crosthwaite
2015-12-31 18:06     ` Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 2/7] bcm2835_property: add bcm2835 property channel Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 3/7] bcm2835_ic: add bcm2835 interrupt controller Andrew Baumann
2015-12-31  0:33   ` Peter Crosthwaite
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 4/7] bcm2835_peripherals: add rollup device for bcm2835 peripherals Andrew Baumann
2015-12-31  2:53   ` Peter Crosthwaite
2015-12-31 18:23     ` Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 5/7] bcm2836_control: add bcm2836 ARM control logic Andrew Baumann
2015-12-31  3:20   ` Peter Crosthwaite
2015-12-31 18:43     ` Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 6/7] bcm2836: add bcm2836 soc device Andrew Baumann
2015-12-24  0:25 ` [Qemu-devel] [PATCH v2 7/7] raspi: add raspberry pi 2 machine Andrew Baumann
2015-12-31  1:13 ` [Qemu-devel] [PATCH v2 0/7] Raspberry Pi 2 support Piotr Król
2016-01-06 18:27   ` Andrew Baumann
2016-01-07  0:09     ` Piotr Król
2016-01-07  0:14       ` Andrew Baumann
2016-01-07  2:46       ` Peter Crosthwaite
2016-01-07  4:47         ` Andrew Baumann
2016-01-07 10:16           ` Peter Maydell

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.