[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 3/9] Altera: Add support for Altera devices requ
From: |
Blue Swirl |
Subject: |
Re: [Qemu-devel] [PATCH 3/9] Altera: Add support for Altera devices required to boot linux on NiosII. |
Date: |
Tue, 11 Sep 2012 19:53:49 +0000 |
On Mon, Sep 10, 2012 at 12:20 AM, <address@hidden> wrote:
> From: Chris Wulff <address@hidden>
>
> Signed-off-by: Chris Wulff <address@hidden>
> ---
> 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 <address@hidden>
> + *
> + * 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 <address@hidden>
> + *
> + * 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 {
CamelCase
> + 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;
uint32_t does not match uint64_t for function return value.
> +
> + 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);
It would be better to set the IRQ only if the state has changed.
> +
> + 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,
Native endian cases should be rare, you should fix it to LE or BE.
> + .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 = {
const
> + .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)
> +
newline
> 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 <address@hidden>
> + *
> + * 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 <address@hidden>
> + *
> + * 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));
Spaces around '*'.
> + 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 <address@hidden>
> + *
> + * 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>
> + */
> +
Missing duplicate include protection #ifdeffery.
> +#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 <address@hidden>
> + *
> + * 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;
Useless cast in C.
> + 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
>
>
- [Qemu-devel] [PATCH 0/9] Altera NiosII support, crwulff, 2012/09/09
- [Qemu-devel] [PATCH 3/9] Altera: Add support for Altera devices required to boot linux on NiosII., crwulff, 2012/09/09
- Re: [Qemu-devel] [PATCH 3/9] Altera: Add support for Altera devices required to boot linux on NiosII.,
Blue Swirl <=
- [Qemu-devel] [PATCH 5/9] FDT: Add additional access methods for array types and walking children., crwulff, 2012/09/09
- [Qemu-devel] [PATCH 7/9] NiosII: Add a config that is dynamically set up by a device tree file., crwulff, 2012/09/09
- [Qemu-devel] [PATCH 6/9] NiosII: Build system and documentation integration., crwulff, 2012/09/09
- [Qemu-devel] [PATCH 1/9] NiosII: Add support for the Altera NiosII soft-core CPU., crwulff, 2012/09/09