Signed-off-by: Alistair Francis <alistair.fran...@xilinx.com> --- hw/microblaze/xlnx-zynqmp-pmu.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/hw/microblaze/xlnx-zynqmp-pmu.c b/hw/microblaze/xlnx-zynqmp-pmu.c index 999a5657cf..f466c56e45 100644 --- a/hw/microblaze/xlnx-zynqmp-pmu.c +++ b/hw/microblaze/xlnx-zynqmp-pmu.c @@ -26,6 +26,7 @@ #include "hw/intc/xlnx-zynqmp-ipi.h" #include "hw/intc/xlnx-pmu-iomod-intc.h" +#include "hw/timer/xlnx-pmu-iomod-pit.h" /* Define the PMU device */ @@ -40,6 +41,7 @@ #define XLNX_ZYNQMP_PMU_INTC_ADDR 0xFFD40000 #define XLNX_ZYNQMP_PMU_NUM_IPIS 4 +#define XLNX_ZYNQMP_PMU_NUM_PITS 4 static const uint64_t ipi_addr[XLNX_ZYNQMP_PMU_NUM_IPIS] = { 0xFF340000, 0xFF350000, 0xFF360000, 0xFF370000, @@ -48,6 +50,13 @@ static const uint64_t ipi_irq[XLNX_ZYNQMP_PMU_NUM_IPIS] = { 19, 20, 21, 22, }; +static const uint64_t pit_addr[XLNX_ZYNQMP_PMU_NUM_PITS] = { + 0xFFD40040, 0xFFD40050, 0xFFD40060, 0xFFD40070, +}; +static const uint64_t pit_irq[XLNX_ZYNQMP_PMU_NUM_PITS] = { + 3, 4, 5, 6, +}; + typedef struct XlnxZynqMPPMUSoCState { /*< private >*/ DeviceState parent_obj; @@ -147,7 +156,9 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine) MemoryRegion *pmu_rom = g_new(MemoryRegion, 1); MemoryRegion *pmu_ram = g_new(MemoryRegion, 1); XlnxZynqMPIPI *ipi[XLNX_ZYNQMP_PMU_NUM_IPIS]; + XlnxPMUPIT *pit[XLNX_ZYNQMP_PMU_NUM_PITS]; qemu_irq irq[32]; + qemu_irq hit_in; int i; /* Create the ROM */ @@ -186,6 +197,30 @@ static void xlnx_zynqmp_pmu_init(MachineState *machine) sysbus_connect_irq(SYS_BUS_DEVICE(ipi[i]), 0, irq[ipi_irq[i]]); } + /* Create and connect the IOMOD PIT devices */ + for (i = 0; i < XLNX_ZYNQMP_PMU_NUM_PITS; i++) { + pit[i] = g_new0(XlnxPMUPIT, 1); + object_initialize(pit[i], sizeof(XlnxPMUPIT), TYPE_XLNX_ZYNQMP_IOMODULE_PIT); + qdev_set_parent_bus(DEVICE(pit[i]), sysbus_get_default()); + } + + for (i = 0; i < XLNX_ZYNQMP_PMU_NUM_PITS; i++) { + object_property_set_bool(OBJECT(pit[i]), true, "realized", + &error_abort); + sysbus_mmio_map(SYS_BUS_DEVICE(pit[i]), 0, pit_addr[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(pit[i]), 0, irq[pit_irq[i]]); + } + + /* PIT1 hits into PIT0 */ + hit_in = qdev_get_gpio_in_named(DEVICE(pit[0]), "ps_hit_in", 0); + qdev_connect_gpio_out_named(DEVICE(pit[1]), "ps_hit_out", 0, hit_in); + + /* PIT3 hits into PIT2 */ + hit_in = qdev_get_gpio_in_named(DEVICE(pit[2]), "ps_hit_in", 0); + qdev_connect_gpio_out_named(DEVICE(pit[3]), "ps_hit_out", 0, hit_in); + + /* TODO: PIT0 and PIT2 "ps_config" GPIO goes to The GPO1 device. */ + /* Load the kernel */ microblaze_load_kernel(&pmu->cpu, XLNX_ZYNQMP_PMU_RAM_ADDR, machine->ram_size, -- 2.14.1