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

Reply via email to