hw/arm_gic: Make gic_reset a sysbus reset function
authorPeter Maydell <peter.maydell@linaro.org>
Fri, 13 Apr 2012 11:39:09 +0000 (11:39 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Fri, 13 Apr 2012 12:29:04 +0000 (12:29 +0000)
Make gic_reset a sysbus reset function, so we actually
reset the GIC on system reset rather than only at init.
For the NVIC this requires us also to implement reset
of the SysTick.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
hw/arm_gic.c
hw/armv7m_nvic.c

index b54357033b6f2f63fefdf64f4499d76cfe8aa89e..81858c3971f502ff46d544568591c5518e8971f6 100644 (file)
@@ -741,8 +741,9 @@ static const MemoryRegionOps gic_cpu_ops = {
 };
 #endif
 
-static void gic_reset(gic_state *s)
+static void gic_reset(DeviceState *dev)
 {
+    gic_state *s = FROM_SYSBUS(gic_state, sysbus_from_qdev(dev));
     int i;
     memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
@@ -905,7 +906,6 @@ static void gic_init(gic_state *s, int num_irq)
     }
 #endif
 
-    gic_reset(s);
     register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
 }
 
@@ -938,6 +938,7 @@ static void arm_gic_class_init(ObjectClass *klass, void *data)
     SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
     sbc->init = arm_gic_init;
     dc->props = arm_gic_properties;
+    dc->reset = gic_reset;
     dc->no_user = 1;
 }
 
index 79cf44867806f20b6c4b4cac7d6d1701d144d0d7..5cfa971cab12e7453094f3acadaf5c0541900cc7 100644 (file)
@@ -76,6 +76,14 @@ static void systick_timer_tick(void * opaque)
     }
 }
 
+static void systick_reset(nvic_state *s)
+{
+    s->systick.control = 0;
+    s->systick.reload = 0;
+    s->systick.tick = 0;
+    qemu_del_timer(s->systick.timer);
+}
+
 /* The external routines use the hardware vector numbering, ie. the first
    IRQ is #16.  The internal GIC routines use #32 as the first IRQ.  */
 void armv7m_nvic_set_pending(void *opaque, int irq)
@@ -371,6 +379,13 @@ static const VMStateDescription vmstate_nvic = {
     }
 };
 
+static void armv7m_nvic_reset(DeviceState *dev)
+{
+    nvic_state *s = FROM_SYSBUSGIC(nvic_state, sysbus_from_qdev(dev));
+    gic_reset(&s->gic.busdev.qdev);
+    systick_reset(s);
+}
+
 static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
@@ -400,6 +415,7 @@ static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
 
     sdc->init = armv7m_nvic_init;
     dc->vmsd  = &vmstate_nvic;
+    dc->reset = armv7m_nvic_reset;
     dc->props = armv7m_nvic_properties;
 }