[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH arm-devs v2 2/2] cpu/a9mpcore: Add Global Timer
From: |
peter . crosthwaite |
Subject: |
[Qemu-devel] [PATCH arm-devs v2 2/2] cpu/a9mpcore: Add Global Timer |
Date: |
Mon, 15 Jul 2013 15:19:48 +1000 |
From: François LEGAL <address@hidden>
Add the global timer to A9 MPCore.
Signed-off-by: François LEGAL <address@hidden>
[PC Changes:
* new commit message
* split off original version as a separate patch
]
Signed-off-by: Peter Crosthwaite <address@hidden>
---
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