All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Baumann <Andrew.Baumann@microsoft.com>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Grégory ESTRADE" <gregory.estrade@gmail.com>,
	"Stefan Weil" <sw@weilnetz.de>,
	"Peter Crosthwaite" <crosthwaite.peter@gmail.com>,
	"Andrew Baumann" <Andrew.Baumann@microsoft.com>,
	qemu-arm@nongnu.org, "Paolo Bonzini" <pbonzini@redhat.com>
Subject: [Qemu-devel] [PATCH 3/8] bcm2835_ic: add bcm2835 interrupt controller
Date: Thu, 3 Dec 2015 22:01:22 -0800	[thread overview]
Message-ID: <1449208887-9564-3-git-send-email-Andrew.Baumann@microsoft.com> (raw)
In-Reply-To: <1449208887-9564-1-git-send-email-Andrew.Baumann@microsoft.com>

Signed-off-by: Andrew Baumann <Andrew.Baumann@microsoft.com>
---
 hw/intc/Makefile.objs        |   1 +
 hw/intc/bcm2835_ic.c         | 234 +++++++++++++++++++++++++++++++++++++++++++
 include/hw/intc/bcm2835_ic.h |  26 +++++
 3 files changed, 261 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..2419575
--- /dev/null
+++ b/hw/intc/bcm2835_ic.c
@@ -0,0 +1,234 @@
+/*
+ * 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 IR_B 2
+#define IR_1 0
+#define IR_2 1
+
+/* Update interrupts.  */
+static void bcm2835_ic_update(BCM2835IcState *s)
+{
+    int set;
+    int i;
+
+    set = 0;
+    if (s->fiq_enable) {
+        set = s->level[s->fiq_select >> 5] & (1u << (s->fiq_select & 0x1f));
+    }
+    qemu_set_irq(s->fiq, set);
+
+    set = 0;
+    for (i = 0; i < 3; i++) {
+        set |= (s->level[i] & s->irq_enable[i]);
+    }
+    qemu_set_irq(s->irq, set);
+
+}
+
+static void bcm2835_ic_set_irq(void *opaque, int irq, int level)
+{
+    BCM2835IcState *s = (BCM2835IcState *)opaque;
+
+    if (irq >= 0 && irq <= 71) {
+        if (level) {
+                s->level[irq >> 5] |= 1u << (irq & 0x1f);
+        } else {
+                s->level[irq >> 5] &= ~(1u << (irq & 0x1f));
+        }
+    } else {
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "bcm2835_ic_set_irq: Bad irq %d\n", irq);
+    }
+
+    bcm2835_ic_update(s);
+}
+
+static const int irq_dups[] = { 7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62, -1 };
+
+static uint64_t bcm2835_ic_read(void *opaque, hwaddr offset,
+    unsigned size)
+{
+    BCM2835IcState *s = (BCM2835IcState *)opaque;
+    int i;
+    int p = 0;
+    uint32_t res = 0;
+
+    switch (offset) {
+    case 0x00:  /* IRQ basic pending */
+        /* bits 0-7 - ARM irqs */
+        res = (s->level[IR_B] & s->irq_enable[IR_B]) & 0xff;
+        for (i = 0; i < 64; i++) {
+            if (i == irq_dups[p]) {
+                /* bits 10-20 - selected GPU irqs */
+                if (s->level[i >> 5] & s->irq_enable[i >> 5]
+                    & (1u << (i & 0x1f))) {
+                    res |= (1u << (10 + p));
+                }
+                p++;
+            } else {
+                /* bits 8-9 - one or more bits set in pending registers 1-2 */
+                if (s->level[i >> 5] & s->irq_enable[i >> 5]
+                    & (1u << (i & 0x1f))) {
+                    res |= (1u << (8 + (i >> 5)));
+                }
+            }
+        }
+        break;
+    case 0x04:  /* IRQ pending 1 */
+        res = s->level[IR_1] & s->irq_enable[IR_1];
+        break;
+    case 0x08:  /* IRQ pending 2 */
+        res = s->level[IR_2] & s->irq_enable[IR_2];
+        break;
+    case 0x0C:  /* FIQ register */
+        res = (s->fiq_enable << 7) | s->fiq_select;
+        break;
+    case 0x10:  /* Interrupt enable register 1 */
+        res = s->irq_enable[IR_1];
+        break;
+    case 0x14:  /* Interrupt enable register 2 */
+        res = s->irq_enable[IR_2];
+        break;
+    case 0x18:  /* Base interrupt enable register */
+        res = s->irq_enable[IR_B];
+        break;
+    case 0x1C:  /* Interrupt disable register 1 */
+        res = ~s->irq_enable[IR_1];
+        break;
+    case 0x20:  /* Interrupt disable register 2 */
+        res = ~s->irq_enable[IR_2];
+        break;
+    case 0x24:  /* Base interrupt disable register */
+        res = ~s->irq_enable[IR_B];
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "bcm2835_ic_read: Bad offset %x\n", (int)offset);
+        return 0;
+    }
+
+    return res;
+}
+
+static void bcm2835_ic_write(void *opaque, hwaddr offset,
+    uint64_t val, unsigned size)
+{
+    BCM2835IcState *s = (BCM2835IcState *)opaque;
+
+    switch (offset) {
+    case 0x0C:  /* FIQ register */
+        s->fiq_select = (val & 0x7f);
+        s->fiq_enable = (val >> 7) & 0x1;
+        break;
+    case 0x10:  /* Interrupt enable register 1 */
+        s->irq_enable[IR_1] |= val;
+        break;
+    case 0x14:  /* Interrupt enable register 2 */
+        s->irq_enable[IR_2] |= val;
+        break;
+    case 0x18:  /* Base interrupt enable register */
+        s->irq_enable[IR_B] |= (val & 0xff);
+        break;
+    case 0x1C:  /* Interrupt disable register 1 */
+        s->irq_enable[IR_1] &= ~val;
+        break;
+    case 0x20:  /* Interrupt disable register 2 */
+        s->irq_enable[IR_2] &= ~val;
+        break;
+    case 0x24:  /* Base interrupt disable register */
+        s->irq_enable[IR_B] &= (~val & 0xff);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "bcm2835_ic_write: Bad offset %x\n", (int)offset);
+        return;
+    }
+    bcm2835_ic_update(s);
+}
+
+static const MemoryRegionOps bcm2835_ic_ops = {
+    .read = bcm2835_ic_read,
+    .write = bcm2835_ic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void bcm2835_ic_reset(DeviceState *d)
+{
+    BCM2835IcState *s = BCM2835_IC(d);
+    int i;
+
+    for (i = 0; i < 3; i++) {
+        s->irq_enable[i] = 0;
+    }
+    s->fiq_enable = 0;
+    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(DEVICE(s), bcm2835_ic_set_irq, 72);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq);
+    sysbus_init_irq(SYS_BUS_DEVICE(s), &s->fiq);
+}
+
+static void bcm2835_ic_realize(DeviceState *dev, Error **errp)
+{
+}
+
+static const VMStateDescription vmstate_bcm2835_ic = {
+    .name = TYPE_BCM2835_IC,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(level, BCM2835IcState, 3),
+        VMSTATE_UINT32_ARRAY(irq_enable, BCM2835IcState, 3),
+        VMSTATE_INT32(fiq_enable, BCM2835IcState),
+        VMSTATE_INT32(fiq_select, BCM2835IcState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void bcm2835_ic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = bcm2835_ic_realize;
+    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..428139d
--- /dev/null
+++ b/include/hw/intc/bcm2835_ic.h
@@ -0,0 +1,26 @@
+/*
+ * 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)
+
+typedef struct BCM2835IcState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+
+    uint32_t level[3];
+    uint32_t irq_enable[3];
+    int fiq_enable;
+    int fiq_select;
+    qemu_irq irq;
+    qemu_irq fiq;
+} BCM2835IcState;
+
+#endif
-- 
2.5.3

  parent reply	other threads:[~2015-12-04  6:03 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-04  0:00 [Qemu-devel] [PATCH 0/8] Raspberry Pi 2 support Andrew Baumann
2015-12-04  0:29 ` Andrew Baumann
2015-12-04  6:01 ` [Qemu-devel] [PATCH 1/8] bcm2835_sbm: add BCM2835 mailboxes Andrew Baumann
2015-12-04  6:01   ` [Qemu-devel] [PATCH 2/8] bcm2835_property: add bcm2835 property channel Andrew Baumann
2015-12-04  6:01   ` Andrew Baumann [this message]
2015-12-06  5:19     ` [Qemu-devel] [PATCH 3/8] bcm2835_ic: add bcm2835 interrupt controller Peter Crosthwaite
2015-12-09  6:25       ` Andrew Baumann
2015-12-04  6:01   ` [Qemu-devel] [PATCH 4/8] bcm2835_emmc: add bcm2835 MMC/SD controller Andrew Baumann
2015-12-06  5:25     ` Peter Crosthwaite
2015-12-09  6:19       ` Andrew Baumann
2015-12-09  7:40         ` Peter Crosthwaite
2015-12-09 18:17           ` Andrew Baumann
2015-12-09 18:54             ` Peter Crosthwaite
2015-12-09 19:01               ` Andrew Baumann
2015-12-09 21:01               ` Peter Maydell
2015-12-09 21:37                 ` Andrew Baumann
2015-12-09 21:38                 ` Peter Crosthwaite
2015-12-09 23:09               ` Kevin O'Connor
2015-12-04  6:01   ` [Qemu-devel] [PATCH 5/8] bcm2835_peripherals: add rollup device for bcm2835 peripherals Andrew Baumann
2015-12-04  6:01   ` [Qemu-devel] [PATCH 6/8] bcm2836_control: add bcm2836 ARM control logic Andrew Baumann
2015-12-04  6:01   ` [Qemu-devel] [PATCH 7/8] bcm2836: add bcm2836 soc device Andrew Baumann
2015-12-04  6:01   ` [Qemu-devel] [PATCH 8/8] raspi: add raspberry pi 2 machine Andrew Baumann
2015-12-07  6:36   ` [Qemu-devel] [PATCH 1/8] bcm2835_sbm: add BCM2835 mailboxes Peter Crosthwaite
2015-12-07 17:24     ` Andrew Baumann
2015-12-21 22:49   ` Peter Crosthwaite
2015-12-21 23:15     ` Andrew Baumann
2015-12-21 23:33       ` Peter Crosthwaite
2015-12-21 23:36         ` Grégory ESTRADE
2015-12-21 23:59         ` Andrew Baumann
2015-12-23 20:32         ` Paolo Bonzini
2015-12-23 23:59           ` Peter Crosthwaite
2015-12-24  0:13             ` Andrew Baumann
2015-12-21 23:34       ` Grégory ESTRADE

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1449208887-9564-3-git-send-email-Andrew.Baumann@microsoft.com \
    --to=andrew.baumann@microsoft.com \
    --cc=crosthwaite.peter@gmail.com \
    --cc=gregory.estrade@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=sw@weilnetz.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.