From 57e72f2a1977448959fe4a492bc48cd2988c1f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20LEGAL?= Date: Sun, 1 Dec 2013 23:37:11 -0800 Subject: [PATCH] cpu/a9mpcore: Add Global Timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the global timer to A9 MPCore. Signed-off-by: François LEGAL Reviewed-by: Peter Maydell Message-id: ff92f35f438ac671b57d99d823723dd3e62d2c49.1385969450.git.peter.crosthwaite@xilinx.com [PC Changes: * new commit message * split off original version as a separate patch * Rebased against new mpcore implementation (with struct embedding) ] Signed-off-by: Peter Crosthwaite Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/cpu/a9mpcore.c | 26 +++++++++++++++++++++----- include/hw/cpu/a9mpcore.h | 2 ++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index a38464badf..c09358c6e7 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -30,6 +30,9 @@ static void a9mp_priv_initfn(Object *obj) object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC); qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); + object_initialize(&s->gtimer, sizeof(s->gtimer), TYPE_A9_GTIMER); + qdev_set_parent_bus(DEVICE(&s->gtimer), sysbus_get_default()); + object_initialize(&s->mptimer, sizeof(s->mptimer), TYPE_ARM_MPTIMER); qdev_set_parent_bus(DEVICE(&s->mptimer), sysbus_get_default()); @@ -41,8 +44,9 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp) { SysBusDevice *sbd = SYS_BUS_DEVICE(dev); A9MPPrivState *s = A9MPCORE_PRIV(dev); - DeviceState *scudev, *gicdev, *mptimerdev, *wdtdev; - SysBusDevice *scubusdev, *gicbusdev, *mptimerbusdev, *wdtbusdev; + DeviceState *scudev, *gicdev, *gtimerdev, *mptimerdev, *wdtdev; + SysBusDevice *scubusdev, *gicbusdev, *gtimerbusdev, *mptimerbusdev, + *wdtbusdev; Error *err = NULL; int i; @@ -71,6 +75,15 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp) /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(dev, a9mp_priv_set_irq, s->num_irq - 32); + gtimerdev = DEVICE(&s->gtimer); + qdev_prop_set_uint32(gtimerdev, "num-cpu", s->num_cpu); + object_property_set_bool(OBJECT(&s->gtimer), true, "realized", &err); + if (err != NULL) { + error_propagate(errp, err); + return; + } + gtimerbusdev = SYS_BUS_DEVICE(&s->gtimer); + mptimerdev = DEVICE(&s->mptimer); qdev_prop_set_uint32(mptimerdev, "num-cpu", s->num_cpu); object_property_set_bool(OBJECT(&s->mptimer), true, "realized", &err); @@ -97,14 +110,14 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp) * 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_add_subregion(&s->container, 0, sysbus_mmio_get_region(scubusdev, 0)); /* GIC CPU interface */ memory_region_add_subregion(&s->container, 0x100, sysbus_mmio_get_region(gicbusdev, 1)); + memory_region_add_subregion(&s->container, 0x200, + sysbus_mmio_get_region(gtimerbusdev, 0)); /* Note that the A9 exposes only the "timer/watchdog for this core" * memory region, not the "timer/watchdog for core X" ones 11MPcore has. */ @@ -116,10 +129,13 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp) sysbus_mmio_get_region(gicbusdev, 0)); /* 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(gicdev, ppibase + 27)); sysbus_connect_irq(mptimerbusdev, i, qdev_get_gpio_in(gicdev, ppibase + 29)); sysbus_connect_irq(wdtbusdev, i, diff --git a/include/hw/cpu/a9mpcore.h b/include/hw/cpu/a9mpcore.h index 8eece07123..5d67ca22c4 100644 --- a/include/hw/cpu/a9mpcore.h +++ b/include/hw/cpu/a9mpcore.h @@ -14,6 +14,7 @@ #include "hw/intc/arm_gic.h" #include "hw/misc/a9scu.h" #include "hw/timer/arm_mptimer.h" +#include "hw/timer/a9gtimer.h" #define TYPE_A9MPCORE_PRIV "a9mpcore_priv" #define A9MPCORE_PRIV(obj) \ @@ -30,6 +31,7 @@ typedef struct A9MPPrivState { A9SCUState scu; GICState gic; + A9GTimerState gtimer; ARMMPTimerState mptimer; ARMMPTimerState wdt; } A9MPPrivState;