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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).