All of lore.kernel.org
 help / color / mirror / Atom feed
From: crwulff@gmail.com
To: qemu-devel@nongnu.org
Cc: Chris Wulff <crwulff@gmail.com>
Subject: [Qemu-devel] [PATCH 3/9] Altera: Add support for Altera devices required to boot linux on NiosII.
Date: Sun,  9 Sep 2012 20:20:01 -0400	[thread overview]
Message-ID: <1347236407-10465-4-git-send-email-crwulff@gmail.com> (raw)
In-Reply-To: <1347236407-10465-1-git-send-email-crwulff@gmail.com>

From: Chris Wulff <crwulff@gmail.com>

Signed-off-by: Chris Wulff <crwulff@gmail.com>
---
 hw/Makefile.objs   |    5 ++
 hw/altera.h        |   34 ++++++++
 hw/altera_timer.c  |  198 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/altera_uart.c   |  218 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/altera_vic.c    |  195 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/nios2.h         |   46 +++++++++++
 hw/nios2_pic_cpu.c |   48 ++++++++++++
 7 files changed, 744 insertions(+)
 create mode 100644 hw/altera.h
 create mode 100644 hw/altera_timer.c
 create mode 100644 hw/altera_uart.c
 create mode 100644 hw/altera_vic.c
 create mode 100644 hw/nios2.h
 create mode 100644 hw/nios2_pic_cpu.c

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 6dfebd2..59dd2d5 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -67,6 +67,11 @@ hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axidma.o
 hw-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
 hw-obj-$(CONFIG_XILINX_AXI) += stream.o
 
+# Altera devices
+hw-obj-$(CONFIG_ALTERA) += altera_vic.o
+hw-obj-$(CONFIG_ALTERA) += altera_uart.o
+hw-obj-$(CONFIG_ALTERA) += altera_timer.o
+
 # PKUnity SoC devices
 hw-obj-$(CONFIG_PUV3) += puv3_intc.o
 hw-obj-$(CONFIG_PUV3) += puv3_ost.o
diff --git a/hw/altera.h b/hw/altera.h
new file mode 100644
index 0000000..b25366e
--- /dev/null
+++ b/hw/altera.h
@@ -0,0 +1,34 @@
+/*
+ * Altera Nios II device instantiation header.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+/* timer */
+static inline DeviceState *altera_timer_create(target_phys_addr_t base,
+                                               qemu_irq irq, int freq)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "altera,timer");
+    qdev_prop_set_uint32(dev, "frequency", freq);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    return dev;
+}
+
diff --git a/hw/altera_timer.c b/hw/altera_timer.c
new file mode 100644
index 0000000..e490da5
--- /dev/null
+++ b/hw/altera_timer.c
@@ -0,0 +1,198 @@
+/*
+ * QEMU model of the Altera timer.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "sysbus.h"
+#include "sysemu.h"
+#include "ptimer.h"
+
+#define R_STATUS     0
+#define R_CONTROL    1
+#define R_PERIODL    2
+#define R_PERIODH    3
+#define R_SNAPL      4
+#define R_SNAPH      5
+#define R_MAX        6
+
+#define STATUS_TO  0x0001
+#define STATUS_RUN 0x0002
+
+#define CONTROL_ITO   0x0001
+#define CONTROL_CONT  0x0002
+#define CONTROL_START 0x0004
+#define CONTROL_STOP  0x0008
+
+struct altera_timer {
+    SysBusDevice  busdev;
+    MemoryRegion  mmio;
+    qemu_irq      irq;
+    uint32_t      freq_hz;
+    QEMUBH       *bh;
+    ptimer_state *ptimer;
+    uint32_t      regs[R_MAX];
+};
+
+static uint64_t timer_read(void *opaque, target_phys_addr_t addr,
+                           unsigned int size)
+{
+    struct altera_timer *t = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    addr &= 0x7;
+    switch (addr) {
+    case R_STATUS:
+        r = t->regs[R_STATUS];
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(t->regs)) {
+            r = t->regs[addr];
+        }
+        break;
+    }
+
+    qemu_set_irq(t->irq, t->regs[R_STATUS] & t->regs[R_CONTROL] & CONTROL_ITO);
+
+    return r;
+}
+
+static void timer_start(struct altera_timer *t)
+{
+    ptimer_stop(t->ptimer);
+    ptimer_set_count(t->ptimer, (t->regs[R_PERIODH]<<16) | t->regs[R_PERIODL]);
+    ptimer_run(t->ptimer, 1);
+}
+
+static void timer_write(void *opaque, target_phys_addr_t addr,
+                        uint64_t val64, unsigned int size)
+{
+    struct altera_timer *t = opaque;
+    uint32_t value = val64;
+    uint32_t count = 0;
+
+    addr >>= 2;
+    addr &= 0x7;
+    switch (addr) {
+    case R_STATUS:
+        /* Writing zero clears the timeout */
+        t->regs[R_STATUS] &= ~STATUS_TO;
+        break;
+
+    case R_CONTROL:
+        t->regs[R_CONTROL] = value & (CONTROL_ITO | CONTROL_CONT);
+        if ((value & CONTROL_START) &&
+            ((t->regs[R_STATUS] & STATUS_RUN) == 0)) {
+            timer_start(t);
+        }
+        if ((value & CONTROL_STOP) && (t->regs[R_STATUS] & STATUS_RUN)) {
+            ptimer_stop(t->ptimer);
+        }
+        break;
+
+    case R_PERIODL:
+    case R_PERIODH:
+        t->regs[addr] = value & 0xFFFF;
+        if (t->regs[R_STATUS] & STATUS_RUN) {
+            timer_start(t);
+        }
+        break;
+
+    case R_SNAPL:
+    case R_SNAPH:
+        count = ptimer_get_count(t->ptimer);
+        t->regs[R_SNAPL] = count & 0xFFFF;
+        t->regs[R_SNAPH] = (count>>16) & 0xFFFF;
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(t->regs)) {
+            t->regs[addr] = value;
+        }
+        break;
+    }
+
+    qemu_set_irq(t->irq, t->regs[R_STATUS] & t->regs[R_CONTROL] & CONTROL_ITO);
+}
+
+static const MemoryRegionOps timer_ops = {
+    .read = timer_read,
+    .write = timer_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4
+    }
+};
+
+static void timer_hit(void *opaque)
+{
+    struct altera_timer *t = opaque;
+    t->regs[R_STATUS] |= STATUS_TO;
+
+    if (t->regs[R_CONTROL] & CONTROL_CONT) {
+        timer_start(t);
+    }
+    qemu_set_irq(t->irq, t->regs[R_STATUS] & t->regs[R_CONTROL] & CONTROL_ITO);
+}
+
+static int altera_timer_init(SysBusDevice *dev)
+{
+    struct altera_timer *t = FROM_SYSBUS(typeof(*t), dev);
+
+    sysbus_init_irq(dev, &t->irq);
+
+    t->bh = qemu_bh_new(timer_hit, t);
+    t->ptimer = ptimer_init(t->bh);
+    ptimer_set_freq(t->ptimer, t->freq_hz);
+
+    memory_region_init_io(&t->mmio, &timer_ops, t, "altera,timer",
+                          R_MAX * sizeof(uint32_t));
+    sysbus_init_mmio(dev, &t->mmio);
+    return 0;
+}
+
+static Property altera_timer_properties[] = {
+    DEFINE_PROP_UINT32("frequency", struct altera_timer, freq_hz, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_timer_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = altera_timer_init;
+    dc->props = altera_timer_properties;
+}
+
+static TypeInfo altera_timer_info = {
+    .name          = "altera,timer",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(struct altera_timer),
+    .class_init    = altera_timer_class_init,
+};
+
+static void altera_timer_register(void)
+{
+    type_register_static(&altera_timer_info);
+}
+
+type_init(altera_timer_register)
+
diff --git a/hw/altera_uart.c b/hw/altera_uart.c
new file mode 100644
index 0000000..e32651e
--- /dev/null
+++ b/hw/altera_uart.c
@@ -0,0 +1,218 @@
+/*
+ * QEMU model of the Altera uart.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+
+#define R_RXDATA        0
+#define R_TXDATA        1
+#define R_STATUS        2
+#define R_CONTROL       3
+#define R_DIVISOR       4
+#define R_ENDOFPACKET   5
+#define R_MAX           6
+
+#define STATUS_PE        0x0001
+#define STATUS_FE        0x0002
+#define STATUS_BRK       0x0004
+#define STATUS_ROE       0x0008
+#define STATUS_TOE       0x0010
+#define STATUS_TMT       0x0020
+#define STATUS_TRDY      0x0040
+#define STATUS_RRDY      0x0080
+#define STATUS_E         0x0100
+#define STATUS_DTCS      0x0400
+#define STATUS_CTS       0x0800
+#define STATUS_EOP       0x1000
+
+#define CONTROL_IPE      0x0001
+#define CONTROL_IFE      0x0002
+#define CONTROL_IBRK     0x0004
+#define CONTROL_IROE     0x0008
+#define CONTROL_ITOE     0x0010
+#define CONTROL_ITMT     0x0020
+#define CONTROL_ITRDY    0x0040
+#define CONTROL_IRRDY    0x0080
+#define CONTROL_IE       0x0100
+#define CONTROL_TBRK     0x0200
+#define CONTROL_IDTCS    0x0400
+#define CONTROL_RTS      0x0800
+#define CONTROL_IEOP     0x1000
+
+struct altera_uart {
+    SysBusDevice busdev;
+    MemoryRegion mmio;
+    CharDriverState *chr;
+    qemu_irq irq;
+
+    uint32_t regs[R_MAX];
+};
+
+static void uart_update_irq(struct altera_uart *s)
+{
+    unsigned int irq;
+
+    irq = (s->regs[R_STATUS] & s->regs[R_CONTROL] &
+          (STATUS_PE | STATUS_FE | STATUS_BRK | STATUS_ROE | STATUS_TOE |
+           STATUS_TMT | STATUS_TRDY | STATUS_RRDY | STATUS_E | STATUS_DTCS));
+    irq = (irq == 0) ? 0 : 1;
+    qemu_set_irq(s->irq, irq);
+}
+
+static uint64_t uart_read(void *opaque, target_phys_addr_t addr,
+                          unsigned int size)
+{
+    struct altera_uart *s = opaque;
+    uint32_t r = 0;
+    addr >>= 2;
+    addr &= 0x7;
+    switch (addr) {
+    case R_RXDATA:
+        r = s->regs[R_RXDATA];
+        s->regs[R_STATUS] &= ~STATUS_RRDY;
+        uart_update_irq(s);
+        break;
+
+    case R_STATUS:
+        r = s->regs[R_STATUS];
+        s->regs[R_STATUS] &= ~(STATUS_PE | STATUS_FE | STATUS_BRK |
+                               STATUS_ROE | STATUS_TOE | STATUS_E |
+                               STATUS_DTCS);
+        uart_update_irq(s);
+        break;
+
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+
+    return r;
+}
+
+static void uart_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t val64, unsigned int size)
+{
+    struct altera_uart *s = opaque;
+    uint32_t value = val64;
+    unsigned char ch = value;
+
+    addr >>= 2;
+    addr &= 0x7;
+
+    switch (addr) {
+    case R_TXDATA:
+        if (s->chr) {
+            qemu_chr_fe_write(s->chr, &ch, 1);
+        }
+
+        s->regs[addr] = value;
+        break;
+
+    case R_RXDATA:
+    case R_STATUS:
+        /* No writeable bits */
+        break;
+
+    default:
+        s->regs[addr] = value;
+        break;
+    }
+    uart_update_irq(s);
+}
+
+static void uart_rx(void *opaque, const uint8_t *buf, int size)
+{
+    struct altera_uart *s = opaque;
+
+    s->regs[R_RXDATA] = *buf;
+    s->regs[R_STATUS] |= STATUS_RRDY;
+
+    uart_update_irq(s);
+}
+
+static int uart_can_rx(void *opaque)
+{
+    struct altera_uart *s = opaque;
+    return ((s->regs[R_STATUS] & STATUS_RRDY) == 0);
+}
+
+static void uart_event(void *opaque, int event)
+{
+}
+
+static const MemoryRegionOps uart_ops = {
+    .read = uart_read,
+    .write = uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4
+    }
+};
+
+static int altera_uart_init(SysBusDevice *dev)
+{
+    struct altera_uart *s = FROM_SYSBUS(typeof(*s), dev);
+
+    s->regs[R_STATUS] = STATUS_TMT | STATUS_TRDY; /* Always ready to tx */
+
+    sysbus_init_irq(dev, &s->irq);
+
+    memory_region_init_io(&s->mmio, &uart_ops, s,
+                          "altera,uart", R_MAX * sizeof(uint32_t));
+    sysbus_init_mmio(dev, &s->mmio);
+
+    s->chr = qemu_char_get_next_serial();
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
+    }
+
+    return 0;
+}
+
+static Property altera_uart_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_uart_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = altera_uart_init;
+    dc->props = altera_uart_properties;
+}
+
+static TypeInfo altera_uart_info = {
+    .name          = "altera,uart",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(struct altera_uart),
+    .class_init    = altera_uart_class_init,
+};
+
+static void altera_uart_register(void)
+{
+    type_register_static(&altera_uart_info);
+}
+
+type_init(altera_uart_register)
+
diff --git a/hw/altera_vic.c b/hw/altera_vic.c
new file mode 100644
index 0000000..43a2b68
--- /dev/null
+++ b/hw/altera_vic.c
@@ -0,0 +1,195 @@
+/*
+ * QEMU Altera Vectored Interrupt Controller.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "sysbus.h"
+#include "hw.h"
+
+#define R_INT_CONFIG_0      0
+#define R_INT_ENABLE       32
+#define R_INT_ENABLE_SET   33
+#define R_INT_ENABLE_CLR   34
+#define R_INT_PENDING      35
+#define R_INT_RAW_STATUS   36
+#define R_SW_INTERRUPT     37
+#define R_SW_INTERRUPT_SET 38
+#define R_SW_INTERRUPT_CLR 39
+#define R_VIC_CONFIG       40
+#define R_VIC_STATUS       41
+#define R_VEC_TBL_BASE     42
+#define R_VEC_TBL_ADDR     43
+#define R_MAX              44
+
+struct altera_vic {
+    SysBusDevice busdev;
+    MemoryRegion mmio;
+    qemu_irq parent_irq;
+
+    /* Runtime control registers.  */
+    uint32_t regs[R_MAX];
+};
+
+static void update_irq(struct altera_vic *pv)
+{
+    uint32_t i;
+    pv->regs[R_INT_PENDING] = (pv->regs[R_INT_RAW_STATUS] |
+                               pv->regs[R_SW_INTERRUPT]) &
+                              pv->regs[R_INT_ENABLE];
+
+    for (i = 0; i < 32; i++) {
+        if (pv->regs[R_INT_PENDING] & (1 << i)) {
+            break;
+        }
+    }
+    if (i == 32) {
+        pv->regs[R_VEC_TBL_ADDR] = 0;
+        pv->regs[R_VIC_STATUS] = 0;
+        qemu_irq_lower(pv->parent_irq);
+    } else {
+        pv->regs[R_VEC_TBL_ADDR] = pv->regs[R_VEC_TBL_BASE] +
+                                   i*(4 << (pv->regs[R_VIC_CONFIG] & 7));
+        pv->regs[R_VIC_STATUS] = 0x80000000 | i;
+        qemu_irq_raise(pv->parent_irq);
+    }
+}
+
+static uint64_t pic_read(void *opaque, target_phys_addr_t addr,
+                         unsigned int size)
+{
+    struct altera_vic *pv = opaque;
+    uint32_t r = 0;
+
+    addr >>= 2;
+    if (addr < R_MAX) {
+        r = pv->regs[addr];
+    }
+
+    return r;
+}
+
+static void pic_write(void *opaque, target_phys_addr_t addr,
+                      uint64_t val64, unsigned int size)
+{
+    struct altera_vic *pv = opaque;
+    uint32_t value = val64;
+
+    addr >>= 2;
+    if (addr < R_INT_ENABLE) {
+        /* R_INT_CONFIG_XX */
+        pv->regs[addr] = value & 0x00001FFF;
+    } else {
+        switch (addr) {
+        case R_INT_PENDING:
+        case R_INT_RAW_STATUS:
+        case R_VIC_STATUS:
+        case R_VEC_TBL_ADDR:
+            /* read only */
+            break;
+
+        case R_INT_ENABLE_SET:
+            pv->regs[R_INT_ENABLE] |= value;
+            break;
+
+        case R_SW_INTERRUPT_SET:
+            pv->regs[R_SW_INTERRUPT] |= value;
+            break;
+
+        case R_INT_ENABLE_CLR:
+            pv->regs[R_INT_ENABLE] &= ~value;
+            break;
+
+        case R_SW_INTERRUPT_CLR:
+            pv->regs[R_SW_INTERRUPT] &= ~value;
+            break;
+
+        case R_VIC_CONFIG:
+            pv->regs[addr] = value & 0x0000000F;
+            break;
+
+        default:
+            if (addr < ARRAY_SIZE(pv->regs)) {
+                pv->regs[addr] = value;
+            }
+            break;
+        }
+    }
+    update_irq(pv);
+}
+
+static const MemoryRegionOps pic_ops = {
+    .read = pic_read,
+    .write = pic_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void irq_handler(void *opaque, int irq, int level)
+{
+    struct altera_vic *pv = opaque;
+
+    pv->regs[R_INT_RAW_STATUS] &= ~(1 << irq);
+    pv->regs[R_INT_RAW_STATUS] |= level << irq;
+
+    update_irq(pv);
+}
+
+static int altera_vic_init(SysBusDevice *dev)
+{
+    struct altera_vic *pv = FROM_SYSBUS(typeof(*pv), dev);
+
+    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
+    sysbus_init_irq(dev, &pv->parent_irq);
+
+    memset(pv->regs, 0, sizeof(uint32_t) * R_MAX);
+    memory_region_init_io(&pv->mmio, &pic_ops, pv,
+                          "altera,vic", R_MAX * sizeof(uint32_t));
+    sysbus_init_mmio(dev, &pv->mmio);
+    return 0;
+}
+
+static Property altera_vic_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void altera_vic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = altera_vic_init;
+    dc->props = altera_vic_properties;
+}
+
+static TypeInfo altera_vic_info = {
+    .name          = "altera,vic",
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(struct altera_vic),
+    .class_init    = altera_vic_class_init,
+};
+
+static void altera_vic_register(void)
+{
+    type_register_static(&altera_vic_info);
+}
+
+type_init(altera_vic_register)
+
diff --git a/hw/nios2.h b/hw/nios2.h
new file mode 100644
index 0000000..a4af154
--- /dev/null
+++ b/hw/nios2.h
@@ -0,0 +1,46 @@
+/*
+ * Altera Nios II CPU interrupt controllers
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "sysbus.h"
+
+qemu_irq *nios2_pic_init_cpu(CPUNios2State *env);
+
+static inline DeviceState *
+altera_vic_create(target_phys_addr_t base, qemu_irq irq, int kind_of_intr)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "altera,vic");
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    return dev;
+}
+
+static inline DeviceState *
+altera_iic_create(qemu_irq irq, int kind_of_intr)
+{
+    DeviceState *dev;
+
+    dev = qdev_create(NULL, "altera,iic");
+    qdev_init_nofail(dev);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, irq);
+    return dev;
+}
diff --git a/hw/nios2_pic_cpu.c b/hw/nios2_pic_cpu.c
new file mode 100644
index 0000000..c89b4ae
--- /dev/null
+++ b/hw/nios2_pic_cpu.c
@@ -0,0 +1,48 @@
+/*
+ * QEMU Altera Nios II CPU interrupt wrapper logic.
+ *
+ * Copyright (c) 2012 Chris Wulff <crwulff@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+
+#include "hw.h"
+#include "pc.h"
+#include "nios2.h"
+
+void pic_info(Monitor *mon)
+{
+}
+
+void irq_info(Monitor *mon)
+{
+}
+
+static void nios2_pic_cpu_handler(void *opaque, int irq, int level)
+{
+    CPUNios2State *env = (CPUNios2State *)opaque;
+    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;
+
+    if (level) {
+        cpu_interrupt(env, type);
+    } else {
+        cpu_reset_interrupt(env, type);
+    }
+}
+
+qemu_irq *nios2_pic_init_cpu(CPUNios2State *env)
+{
+    return qemu_allocate_irqs(nios2_pic_cpu_handler, env, 2);
+}
-- 
1.7.9.5

  parent reply	other threads:[~2012-09-10  0:19 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <Nios2-Resend2>
2012-09-10  0:19 ` [Qemu-devel] [PATCH 0/9] Altera NiosII support crwulff
2012-09-10  0:19   ` [Qemu-devel] [PATCH 1/9] NiosII: Add support for the Altera NiosII soft-core CPU crwulff
2012-09-11 20:19     ` Blue Swirl
2012-09-14  3:30       ` Chris Wulff
2012-09-11 21:34     ` Aurelien Jarno
2012-09-11 22:30       ` Richard Henderson
2012-09-11 23:18       ` Richard Henderson
2012-09-14  3:42       ` Chris Wulff
2012-09-15 15:33       ` Chris Wulff
2012-09-15 14:55     ` Andreas Färber
2012-09-10  0:20   ` [Qemu-devel] [PATCH 2/9] NiosII: Disassembly of NiosII instructions ported from GDB crwulff
2012-09-11 19:58     ` Blue Swirl
2012-09-10  0:20   ` crwulff [this message]
2012-09-11 19:53     ` [Qemu-devel] [PATCH 3/9] Altera: Add support for Altera devices required to boot linux on NiosII Blue Swirl
2012-09-15 15:06       ` Andreas Färber
2012-09-10  0:20   ` [Qemu-devel] [PATCH 4/9] LabX: Support for some Lab X FPGA devices crwulff
2012-09-11 20:22     ` Blue Swirl
2012-09-10  0:20   ` [Qemu-devel] [PATCH 5/9] FDT: Add additional access methods for array types and walking children crwulff
2012-09-12  0:12     ` Peter Crosthwaite
2012-09-10  0:20   ` [Qemu-devel] [PATCH 6/9] NiosII: Build system and documentation integration crwulff
2012-09-10  0:20   ` [Qemu-devel] [PATCH 7/9] NiosII: Add a config that is dynamically set up by a device tree file crwulff
2012-09-11 19:40     ` Blue Swirl
2012-09-10  0:20   ` [Qemu-devel] [PATCH 8/9] MicroBlaze: " crwulff
2012-09-11 19:27     ` Blue Swirl
2012-09-12  0:17       ` Peter Crosthwaite
2012-09-14 19:13         ` Blue Swirl
2012-09-11 23:59     ` Peter Crosthwaite
2012-09-14  4:01       ` Chris Wulff
2012-09-10  0:20   ` [Qemu-devel] [PATCH 9/9] xilinx_timer: Fix a compile error if debug messages are enabled crwulff
2012-09-12  0:25     ` Peter Crosthwaite
2012-09-11 23:40   ` [Qemu-devel] [PATCH 0/9] Altera NiosII support Peter Crosthwaite

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=1347236407-10465-4-git-send-email-crwulff@gmail.com \
    --to=crwulff@gmail.com \
    --cc=qemu-devel@nongnu.org \
    /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.