Message ID | 20220308072005.307955-34-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | target/nios2: Shadow register set, EIC and VIC | expand |
On 08/03/2022 07:20, Richard Henderson wrote: > From: Amir Gonnen <amir.gonnen@neuroblade.ai> > > Demonstrate how to use nios2 VIC on a machine. > Introduce a new machine property to attach a VIC. > > When VIC is present, let the CPU know that it should use the > External Interrupt Interface instead of the Internal Interrupt Interface. > The devices on the machine are attached to the VIC and not directly to cpu. > To allow VIC update EIC fields, we set the "cpu" property of the VIC > with a reference to the nios2 cpu. > > Signed-off-by: Amir Gonnen <amir.gonnen@neuroblade.ai> > Message-Id: <20220303153906.2024748-6-amir.gonnen@neuroblade.ai> > [rth: Put a property on the 10m50-ghrd machine, rather than > create a new machine class.] > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > hw/nios2/10m50_devboard.c | 61 +++++++++++++++++++++++++++++++++------ > hw/nios2/Kconfig | 1 + > 2 files changed, 53 insertions(+), 9 deletions(-) > > diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c > index f4931b8a67..bdbc6539c9 100644 > --- a/hw/nios2/10m50_devboard.c > +++ b/hw/nios2/10m50_devboard.c > @@ -43,6 +43,8 @@ struct Nios2MachineState { > MemoryRegion phys_tcm_alias; > MemoryRegion phys_ram; > MemoryRegion phys_ram_alias; > + > + bool vic; > }; > > #define TYPE_NIOS2_MACHINE MACHINE_TYPE_NAME("10m50-ghrd") > @@ -81,10 +83,40 @@ static void nios2_10m50_ghrd_init(MachineState *machine) > memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base, > &nms->phys_ram_alias); > > - /* Create CPU -- FIXME */ > - cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU)); > - for (i = 0; i < 32; i++) { > - irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i); > + /* Create CPU. We need to set eic_present between init and realize. */ > + cpu = NIOS2_CPU(object_new(TYPE_NIOS2_CPU)); > + > + /* Enable the External Interrupt Controller within the CPU. */ > + cpu->eic_present = nms->vic; > + > + /* Configure new exception vectors. */ > + cpu->reset_addr = 0xd4000000; > + cpu->exception_addr = 0xc8000120; > + cpu->fast_tlb_miss_addr = 0xc0000100; > + > + qdev_realize(DEVICE(cpu), NULL, &error_fatal); > + object_unref(CPU(cpu)); I believe this can be replaced with qdev_realize_and_unref()? > + if (nms->vic) { > + DeviceState *dev = qdev_new("nios2-vic"); And with a separate header for nios2_vic.h you can include that and use TYPE_NIOS2_VIC here instead of hard-coding the type name. > + MemoryRegion *dev_mr; > + qemu_irq cpu_irq; > + > + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_fatal); > + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); > + > + cpu_irq = qdev_get_gpio_in_named(DEVICE(cpu), "EIC", 0); > + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq); > + for (int i = 0; i < 32; i++) { > + irq[i] = qdev_get_gpio_in(dev, i); > + } > + > + dev_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); > + memory_region_add_subregion(address_space_mem, 0x18002000, dev_mr); > + } else { > + for (i = 0; i < 32; i++) { > + irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i); > + } > } > > /* Register: Altera 16550 UART */ > @@ -105,15 +137,22 @@ static void nios2_10m50_ghrd_init(MachineState *machine) > sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880); > sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]); > > - /* Configure new exception vectors and reset CPU for it to take effect. */ > - cpu->reset_addr = 0xd4000000; > - cpu->exception_addr = 0xc8000120; > - cpu->fast_tlb_miss_addr = 0xc0000100; > - > nios2_load_kernel(cpu, ram_base, ram_size, nms->parent_obj.initrd_filename, > BINARY_DEVICE_TREE_FILE, NULL); > } > > +static bool get_vic(Object *obj, Error **errp) > +{ > + Nios2MachineState *nms = NIOS2_MACHINE(obj); > + return nms->vic; > +} > + > +static void set_vic(Object *obj, bool value, Error **errp) > +{ > + Nios2MachineState *nms = NIOS2_MACHINE(obj); > + nms->vic = value; > +} > + > static void nios2_10m50_ghrd_class_init(ObjectClass *oc, void *data) > { > MachineClass *mc = MACHINE_CLASS(oc); > @@ -121,6 +160,10 @@ static void nios2_10m50_ghrd_class_init(ObjectClass *oc, void *data) > mc->desc = "Altera 10M50 GHRD Nios II design"; > mc->init = nios2_10m50_ghrd_init; > mc->is_default = true; > + > + object_class_property_add_bool(oc, "vic", get_vic, set_vic); > + object_class_property_set_description(oc, "vic", > + "Set on/off to enable/disable the Vectored Interrupt Controller"); > } > > static const TypeInfo nios2_10m50_ghrd_type_info = { > diff --git a/hw/nios2/Kconfig b/hw/nios2/Kconfig > index b10ea640da..4748ae27b6 100644 > --- a/hw/nios2/Kconfig > +++ b/hw/nios2/Kconfig > @@ -3,6 +3,7 @@ config NIOS2_10M50 > select NIOS2 > select SERIAL > select ALTERA_TIMER > + select NIOS2_VIC > > config NIOS2_GENERIC_NOMMU > bool ATB, Mark.
On 3/7/22 22:43, Mark Cave-Ayland wrote: >> + qdev_realize(DEVICE(cpu), NULL, &error_fatal); >> + object_unref(CPU(cpu)); > > I believe this can be replaced with qdev_realize_and_unref()? Oh, nice. I copied this from hw/arm/virt, which has code between these two points. >> + if (nms->vic) { >> + DeviceState *dev = qdev_new("nios2-vic"); > > And with a separate header for nios2_vic.h you can include that and use TYPE_NIOS2_VIC > here instead of hard-coding the type name. Ok. r~
diff --git a/hw/nios2/10m50_devboard.c b/hw/nios2/10m50_devboard.c index f4931b8a67..bdbc6539c9 100644 --- a/hw/nios2/10m50_devboard.c +++ b/hw/nios2/10m50_devboard.c @@ -43,6 +43,8 @@ struct Nios2MachineState { MemoryRegion phys_tcm_alias; MemoryRegion phys_ram; MemoryRegion phys_ram_alias; + + bool vic; }; #define TYPE_NIOS2_MACHINE MACHINE_TYPE_NAME("10m50-ghrd") @@ -81,10 +83,40 @@ static void nios2_10m50_ghrd_init(MachineState *machine) memory_region_add_subregion(address_space_mem, 0xc0000000 + ram_base, &nms->phys_ram_alias); - /* Create CPU -- FIXME */ - cpu = NIOS2_CPU(cpu_create(TYPE_NIOS2_CPU)); - for (i = 0; i < 32; i++) { - irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i); + /* Create CPU. We need to set eic_present between init and realize. */ + cpu = NIOS2_CPU(object_new(TYPE_NIOS2_CPU)); + + /* Enable the External Interrupt Controller within the CPU. */ + cpu->eic_present = nms->vic; + + /* Configure new exception vectors. */ + cpu->reset_addr = 0xd4000000; + cpu->exception_addr = 0xc8000120; + cpu->fast_tlb_miss_addr = 0xc0000100; + + qdev_realize(DEVICE(cpu), NULL, &error_fatal); + object_unref(CPU(cpu)); + + if (nms->vic) { + DeviceState *dev = qdev_new("nios2-vic"); + MemoryRegion *dev_mr; + qemu_irq cpu_irq; + + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_fatal); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + cpu_irq = qdev_get_gpio_in_named(DEVICE(cpu), "EIC", 0); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, cpu_irq); + for (int i = 0; i < 32; i++) { + irq[i] = qdev_get_gpio_in(dev, i); + } + + dev_mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_add_subregion(address_space_mem, 0x18002000, dev_mr); + } else { + for (i = 0; i < 32; i++) { + irq[i] = qdev_get_gpio_in_named(DEVICE(cpu), "IRQ", i); + } } /* Register: Altera 16550 UART */ @@ -105,15 +137,22 @@ static void nios2_10m50_ghrd_init(MachineState *machine) sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xe0000880); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq[5]); - /* Configure new exception vectors and reset CPU for it to take effect. */ - cpu->reset_addr = 0xd4000000; - cpu->exception_addr = 0xc8000120; - cpu->fast_tlb_miss_addr = 0xc0000100; - nios2_load_kernel(cpu, ram_base, ram_size, nms->parent_obj.initrd_filename, BINARY_DEVICE_TREE_FILE, NULL); } +static bool get_vic(Object *obj, Error **errp) +{ + Nios2MachineState *nms = NIOS2_MACHINE(obj); + return nms->vic; +} + +static void set_vic(Object *obj, bool value, Error **errp) +{ + Nios2MachineState *nms = NIOS2_MACHINE(obj); + nms->vic = value; +} + static void nios2_10m50_ghrd_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -121,6 +160,10 @@ static void nios2_10m50_ghrd_class_init(ObjectClass *oc, void *data) mc->desc = "Altera 10M50 GHRD Nios II design"; mc->init = nios2_10m50_ghrd_init; mc->is_default = true; + + object_class_property_add_bool(oc, "vic", get_vic, set_vic); + object_class_property_set_description(oc, "vic", + "Set on/off to enable/disable the Vectored Interrupt Controller"); } static const TypeInfo nios2_10m50_ghrd_type_info = { diff --git a/hw/nios2/Kconfig b/hw/nios2/Kconfig index b10ea640da..4748ae27b6 100644 --- a/hw/nios2/Kconfig +++ b/hw/nios2/Kconfig @@ -3,6 +3,7 @@ config NIOS2_10M50 select NIOS2 select SERIAL select ALTERA_TIMER + select NIOS2_VIC config NIOS2_GENERIC_NOMMU bool