From: François LEGAL <de...@thom.fr.eu.org> Add the global timer to A9 MPCore.
Signed-off-by: François LEGAL <de...@thom.fr.eu.org> [PC Changes: * new commit message * split off original version as a separate patch ] Signed-off-by: Peter Crosthwaite <peter.crosthwa...@xilinx.com> --- This will likely conflict with Andreas' MPCore work. Changed from v1: Set authorship to Francois and added SOB. hw/cpu/a9mpcore.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index 6c00a59..56d101e 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -15,6 +15,7 @@ typedef struct A9MPPrivState { uint32_t num_cpu; MemoryRegion container; DeviceState *mptimer; + DeviceState *mpgtimer; DeviceState *wdt; DeviceState *gic; DeviceState *scu; @@ -31,6 +32,7 @@ static int a9mp_priv_init(SysBusDevice *dev) { A9MPPrivState *s = FROM_SYSBUS(A9MPPrivState, dev); SysBusDevice *timerbusdev, *wdtbusdev, *gicbusdev, *scubusdev; + SysBusDevice *gtimerbusdev; int i; s->gic = qdev_create(NULL, "arm_gic"); @@ -50,6 +52,11 @@ static int a9mp_priv_init(SysBusDevice *dev) qdev_init_nofail(s->scu); scubusdev = SYS_BUS_DEVICE(s->scu); + s->mpgtimer = qdev_create(NULL, "a9_globaltimer"); + qdev_prop_set_uint32(s->mpgtimer, "num-cpu", s->num_cpu); + qdev_init_nofail(s->mpgtimer); + gtimerbusdev = SYS_BUS_DEVICE(s->mpgtimer); + s->mptimer = qdev_create(NULL, "arm_mptimer"); qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu); qdev_init_nofail(s->mptimer); @@ -68,8 +75,6 @@ static int a9mp_priv_init(SysBusDevice *dev) * 0x0600-0x06ff -- private timers and watchdogs * 0x0700-0x0fff -- nothing * 0x1000-0x1fff -- GIC Distributor - * - * We should implement the global timer but don't currently do so. */ memory_region_init(&s->container, OBJECT(s), "a9mp-priv-container", 0x2000); memory_region_add_subregion(&s->container, 0, @@ -80,6 +85,8 @@ static int a9mp_priv_init(SysBusDevice *dev) /* Note that the A9 exposes only the "timer/watchdog for this core" * memory region, not the "timer/watchdog for core X" ones 11MPcore has. */ + memory_region_add_subregion(&s->container, 0x200, + sysbus_mmio_get_region(gtimerbusdev, 0)); memory_region_add_subregion(&s->container, 0x600, sysbus_mmio_get_region(timerbusdev, 0)); memory_region_add_subregion(&s->container, 0x620, @@ -90,10 +97,13 @@ static int a9mp_priv_init(SysBusDevice *dev) sysbus_init_mmio(dev, &s->container); /* Wire up the interrupt from each watchdog and timer. - * For each core the timer is PPI 29 and the watchdog PPI 30. + * For each core the global timer is PPI 27, the private + * timer is PPI 29 and the watchdog PPI 30. */ for (i = 0; i < s->num_cpu; i++) { int ppibase = (s->num_irq - 32) + i * 32; + sysbus_connect_irq(gtimerbusdev, i, + qdev_get_gpio_in(s->gic, ppibase + 27)); sysbus_connect_irq(timerbusdev, i, qdev_get_gpio_in(s->gic, ppibase + 29)); sysbus_connect_irq(wdtbusdev, i, -- 1.8.3.rc1.44.gb387c77.dirty