From: Axel Heider <axel.hei...@hensoldt.net> Add 2x sp804 timer devices.
Co-Authored-by: Florian Hauschild <florian.hausch...@hensoldt.net> Signed-off-by: Axel Heider <axel.hei...@hensoldt.net> --- docs/system/arm/virt.rst | 1 + hw/arm/Kconfig | 1 + hw/arm/virt.c | 47 ++++++++++++++++++++++++++++++++++++++++ include/hw/arm/virt.h | 2 ++ 4 files changed, 51 insertions(+) diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index 20442ea2c1..9ad5a3e048 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -28,6 +28,7 @@ The virt board supports: - Flash memory - One PL011 UART - An RTC +- Two SP804 Dual-Timers - The fw_cfg device that allows a guest to obtain data from QEMU - A PL061 GPIO controller - An optional SMMUv3 IOMMU diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig index 17fcde8e1c..9be8ebcc5b 100644 --- a/hw/arm/Kconfig +++ b/hw/arm/Kconfig @@ -18,6 +18,7 @@ config ARM_VIRT select PL011 # UART select PL031 # RTC select PL061 # GPIO + select ARM_TIMER # sp804 select GPIO_PWR select PLATFORM_BUS select SMBIOS diff --git a/hw/arm/virt.c b/hw/arm/virt.c index b871350856..ae043ce04e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -154,6 +154,8 @@ static const MemMapEntry base_memmap[] = { [VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN}, [VIRT_PVTIME] = { 0x090a0000, 0x00010000 }, [VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 }, + [VIRT_TIMER0] = { 0x090c0000, 0x00001000 }, + [VIRT_TIMER1] = { 0x090d0000, 0x00001000 }, [VIRT_MMIO] = { 0x0a000000, 0x00000200 }, /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */ [VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 }, @@ -190,6 +192,8 @@ static const int a15irqmap[] = { [VIRT_GPIO] = 7, [VIRT_SECURE_UART] = 8, [VIRT_ACPI_GED] = 9, + [VIRT_TIMER0] = 10, + [VIRT_TIMER1] = 11, [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ [VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */ [VIRT_SMMU] = 74, /* ...to 74 + NUM_SMMU_IRQS - 1 */ @@ -236,6 +240,46 @@ static void create_randomness(MachineState *ms, const char *node) qemu_fdt_setprop(ms->fdt, node, "rng-seed", seed.rng, sizeof(seed.rng)); } +static void create_timer(const VirtMachineState *vms, int timer_id) +{ + switch (timer_id) { + case VIRT_TIMER0: + case VIRT_TIMER1: + break; + default: + error_report("timer ID %d unsupported", timer_id); + exit(1); + } + + MemMapEntry *entry = &(vms->memmap[timer_id]); + int irq = vms->irqmap[timer_id]; + MachineState *ms = MACHINE(vms); + + sysbus_create_simple("sp804", entry->base, qdev_get_gpio_in(vms->gic, irq)); + + char *nodename = g_strdup_printf("/sp804@%" PRIx64, entry->base); + qemu_fdt_add_subnode(ms->fdt, nodename); + + const char compat[] = "arm,sp804\0arm,primecell"; + qemu_fdt_setprop(ms->fdt, nodename, "compatible", compat, sizeof(compat)); + + const char clocknames[] = "timerclk0\0timerclk1\0apb_pclk"; + qemu_fdt_setprop(ms->fdt, nodename, "clock-names", + clocknames, sizeof(clocknames)); + + qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, entry->base, + 2, entry->size); + + qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", + GIC_FDT_IRQ_TYPE_SPI, irq, + GIC_FDT_IRQ_FLAGS_LEVEL_HI); + + qemu_fdt_setprop_cells(ms->fdt, nodename, "clocks", + vms->clock_phandle, vms->clock_phandle); + + g_free(nodename); +} + static void create_fdt(VirtMachineState *vms) { MachineState *ms = MACHINE(vms); @@ -2238,6 +2282,9 @@ static void machvirt_init(MachineState *machine) create_rtc(vms); + create_timer(vms, VIRT_TIMER0); + create_timer(vms, VIRT_TIMER1); + create_pcie(vms); if (has_ged && aarch64 && firmware_loaded && virt_is_acpi_enabled(vms)) { diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 6ec479ca2b..90fdf0b05a 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -86,6 +86,8 @@ enum { VIRT_ACPI_GED, VIRT_NVDIMM_ACPI, VIRT_PVTIME, + VIRT_TIMER0, + VIRT_TIMER1, VIRT_LOWMEMMAP_LAST, }; -- 2.34.5