diff --git a/MAINTAINERS b/MAINTAINERS index 062074e47c..99293a5e02 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -259,7 +259,6 @@ M: Marek Vasut S: Maintained F: target/nios2/ F: hw/nios2/ -F: hw/intc/nios2_iic.c F: disas/nios2.c F: default-configs/nios2-softmmu.mak diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 3f82cc230a..7c3e9daf58 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -37,7 +37,6 @@ specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_plic.c')) specific_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c')) specific_ss.add(when: 'CONFIG_LOONGSON_LIOINTC', if_true: files('loongson_liointc.c')) specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gic.c')) -specific_ss.add(when: 'CONFIG_NIOS2', if_true: files('nios2_iic.c')) specific_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_intc.c')) specific_ss.add(when: 'CONFIG_OMPIC', if_true: files('ompic.c')) specific_ss.add(when: 'CONFIG_OPENPIC_KVM', if_true: files('openpic_kvm.c')) diff --git a/hw/intc/nios2_iic.c b/hw/intc/nios2_iic.c deleted file mode 100644 index 216db67059..0000000000 --- a/hw/intc/nios2_iic.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * QEMU Altera Internal Interrupt Controller. - * - * Copyright (c) 2012 Chris Wulff - * - * 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 - * - */ - -#include "qemu/osdep.h" -#include "qemu/module.h" -#include "qapi/error.h" - -#include "hw/irq.h" -#include "hw/sysbus.h" -#include "cpu.h" -#include "qom/object.h" - -#define TYPE_ALTERA_IIC "altera,iic" -OBJECT_DECLARE_SIMPLE_TYPE(AlteraIIC, ALTERA_IIC) - -struct AlteraIIC { - SysBusDevice parent_obj; - void *cpu; - qemu_irq parent_irq; -}; - -static void update_irq(AlteraIIC *pv) -{ - CPUNios2State *env = &((Nios2CPU *)(pv->cpu))->env; - - qemu_set_irq(pv->parent_irq, - env->regs[CR_IPENDING] & env->regs[CR_IENABLE]); -} - -static void irq_handler(void *opaque, int irq, int level) -{ - AlteraIIC *pv = opaque; - CPUNios2State *env = &((Nios2CPU *)(pv->cpu))->env; - - env->regs[CR_IPENDING] &= ~(1 << irq); - env->regs[CR_IPENDING] |= !!level << irq; - - update_irq(pv); -} - -static void altera_iic_init(Object *obj) -{ - AlteraIIC *pv = ALTERA_IIC(obj); - - qdev_init_gpio_in(DEVICE(pv), irq_handler, 32); - sysbus_init_irq(SYS_BUS_DEVICE(obj), &pv->parent_irq); -} - -static void altera_iic_realize(DeviceState *dev, Error **errp) -{ - struct AlteraIIC *pv = ALTERA_IIC(dev); - - pv->cpu = object_property_get_link(OBJECT(dev), "cpu", &error_abort); -} - -static void altera_iic_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - /* Reason: needs to be wired up, e.g. by nios2_10m50_ghrd_init() */ - dc->user_creatable = false; - dc->realize = altera_iic_realize; -} - -static TypeInfo altera_iic_info = { - .name = TYPE_ALTERA_IIC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(AlteraIIC), - .instance_init = altera_iic_init, - .class_init = altera_iic_class_init, -}; - -static void altera_iic_register(void) -{ - type_register_static(&altera_iic_info); -} - -type_init(altera_iic_register) diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c index 5c13b74306..a14fc31e86 100644 --- a/hw/nios2/10m50_devboard.c +++ b/hw/nios2/10m50_devboard.c @@ -52,7 +52,7 @@ static void nios2_10m50_ghrd_init(MachineState *machine) ram_addr_t tcm_size = 0x1000; /* 1 kiB, but QEMU limit is 4 kiB */ ram_addr_t ram_base = 0x08000000; ram_addr_t ram_size = 0x08000000; - qemu_irq *cpu_irq, irq[32]; + qemu_irq irq[32]; int i; /* Physical TCM (tb_ram_1k) with alias at 0xc0000000 */ @@ -75,17 +75,8 @@ static void nios2_10m50_ghrd_init(MachineState *machine) /* Create CPU -- FIXME */ cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU)); - - /* Register: CPU interrupt controller (PIC) */ - cpu_irq = nios2_cpu_pic_init(cpu); - - /* Register: Internal Interrupt Controller (IIC) */ - dev = qdev_new("altera,iic"); - object_property_add_const_link(OBJECT(dev), "cpu", OBJECT(cpu)); - sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); - sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq[0]); for (i = 0; i < 32; i++) { - irq[i] = qdev_get_gpio_in(dev, i); + irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i); } /* Register: Altera 16550 UART */ diff --git a/hw/nios2/cpu_pic.c b/hw/nios2/cpu_pic.c index 5ea7e52ab8..3fb621c5c8 100644 --- a/hw/nios2/cpu_pic.c +++ b/hw/nios2/cpu_pic.c @@ -26,32 +26,6 @@ #include "boot.h" -static void nios2_pic_cpu_handler(void *opaque, int irq, int level) -{ - Nios2CPU *cpu = opaque; - CPUNios2State *env = &cpu->env; - CPUState *cs = CPU(cpu); - int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD; - - if (type == CPU_INTERRUPT_HARD) { - env->irq_pending = level; - - if (level && (env->regs[CR_STATUS] & CR_STATUS_PIE)) { - env->irq_pending = 0; - cpu_interrupt(cs, type); - } else if (!level) { - env->irq_pending = 0; - cpu_reset_interrupt(cs, type); - } - } else { - if (level) { - cpu_interrupt(cs, type); - } else { - cpu_reset_interrupt(cs, type); - } - } -} - void nios2_check_interrupts(CPUNios2State *env) { if (env->irq_pending && @@ -60,8 +34,3 @@ void nios2_check_interrupts(CPUNios2State *env) cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HARD); } } - -qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu) -{ - return qemu_allocate_irqs(nios2_pic_cpu_handler, cpu, 2); -} diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c index 8f7011fcb9..52ebda89ca 100644 --- a/target/nios2/cpu.c +++ b/target/nios2/cpu.c @@ -64,6 +64,27 @@ static void nios2_cpu_reset(DeviceState *dev) #endif } +#ifndef CONFIG_USER_ONLY +static void nios2_cpu_set_irq(void *opaque, int irq, int level) +{ + Nios2CPU *cpu = opaque; + CPUNios2State *env = &cpu->env; + CPUState *cs = CPU(cpu); + + env->regs[CR_IPENDING] &= ~(1 << irq); + env->regs[CR_IPENDING] |= !!level << irq; + + env->irq_pending = env->regs[CR_IPENDING] & env->regs[CR_IENABLE]; + + if (env->irq_pending && (env->regs[CR_STATUS] & CR_STATUS_PIE)) { + env->irq_pending = 0; + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else if (!env->irq_pending) { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } +} +#endif + static void nios2_cpu_initfn(Object *obj) { Nios2CPU *cpu = NIOS2_CPU(obj); @@ -72,6 +93,15 @@ static void nios2_cpu_initfn(Object *obj) #if !defined(CONFIG_USER_ONLY) mmu_init(&cpu->env); + + /* + * These interrupt lines model the IIC (internal interrupt + * controller). QEMU does not currently support the EIC + * (external interrupt controller) -- if we did it would be + * a separate device in hw/intc with a custom interface to + * the CPU, and boards using it would not wire up these IRQ lines. + */ + qdev_init_gpio_in_named(DEVICE(cpu), nios2_cpu_set_irq, "IRQ", 32); #endif } diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index 86bbe1d867..b7efb54ba7 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -201,7 +201,6 @@ void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); -qemu_irq *nios2_cpu_pic_init(Nios2CPU *cpu); void nios2_check_interrupts(CPUNios2State *env); void do_nios2_semihosting(CPUNios2State *env);