Patchwork [arm-devs,v2,2/2] cpu/a9mpcore: Add Global Timer

login
register
mail settings
Submitter Peter Crosthwaite
Date July 15, 2013, 5:19 a.m.
Message ID <43e3685aa2479bc9a640fe23e7e41545c3c62539.1373862169.git.peter.crosthwaite@xilinx.com>
Download mbox | patch
Permalink /patch/258957/
State New
Headers show

Comments

Peter Crosthwaite - July 15, 2013, 5:19 a.m.
From: François LEGAL <devel@thom.fr.eu.org>

Add the global timer to A9 MPCore.

Signed-off-by: François LEGAL <devel@thom.fr.eu.org>
[PC Changes:
 * new commit message
 * split off original version as a separate patch
]
Signed-off-by: Peter Crosthwaite <peter.crosthwaite@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(-)
Peter Maydell - July 15, 2013, 1:21 p.m.
On 15 July 2013 06:19,  <peter.crosthwaite@xilinx.com> wrote:
> From: François LEGAL <devel@thom.fr.eu.org>
>
> Add the global timer to A9 MPCore.
>
> Signed-off-by: François LEGAL <devel@thom.fr.eu.org>
> [PC Changes:
>  * new commit message
>  * split off original version as a separate patch
> ]
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

assuming you sort out the confusion I mentioned in my review
of patch 1 over what the device is actually called.

thanks
-- PMM

Patch

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,