فهرست منبع

allwinner-a10-pit: avoid generation of spurious interrupts

The model was generating interrupts for all enabled timers after the
expiration of one of them. Avoid this by passing explicitly the timer
index to the callback function.

Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
Reviewed-by: Li Guang <lig.fnst@cn.fujitsu.com>
Reviewed-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Message-id: 1395771730-16882-4-git-send-email-b.galvani@gmail.com
[PMM: avoid duplicate typedef of AwA10PITState]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Beniamino Galvani 11 سال پیش
والد
کامیت
323a8771cf
2فایلهای تغییر یافته به همراه24 افزوده شده و 13 حذف شده
  1. 14 11
      hw/timer/allwinner-a10-pit.c
  2. 10 2
      include/hw/timer/allwinner-a10-pit.h

+ 14 - 11
hw/timer/allwinner-a10-pit.c

@@ -193,18 +193,17 @@ static void a10_pit_reset(DeviceState *dev)
 
 static void a10_pit_timer_cb(void *opaque)
 {
-    AwA10PITState *s = AW_A10_PIT(opaque);
-    uint8_t i;
+    AwA10TimerContext *tc = opaque;
+    AwA10PITState *s = tc->container;
+    uint8_t i = tc->index;
 
-    for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
-        if (s->control[i] & AW_A10_PIT_TIMER_EN) {
-            s->irq_status |= 1 << i;
-            if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
-                ptimer_stop(s->timer[i]);
-                s->control[i] &= ~AW_A10_PIT_TIMER_EN;
-            }
-            qemu_irq_pulse(s->irq[i]);
+    if (s->control[i] & AW_A10_PIT_TIMER_EN) {
+        s->irq_status |= 1 << i;
+        if (s->control[i] & AW_A10_PIT_TIMER_MODE) {
+            ptimer_stop(s->timer[i]);
+            s->control[i] &= ~AW_A10_PIT_TIMER_EN;
         }
+        qemu_irq_pulse(s->irq[i]);
     }
 }
 
@@ -223,7 +222,11 @@ static void a10_pit_init(Object *obj)
     sysbus_init_mmio(sbd, &s->iomem);
 
     for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
-        bh[i] = qemu_bh_new(a10_pit_timer_cb, s);
+        AwA10TimerContext *tc = &s->timer_context[i];
+
+        tc->container = s;
+        tc->index = i;
+        bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
         s->timer[i] = ptimer_init(bh[i]);
         ptimer_set_freq(s->timer[i], 240000);
     }

+ 10 - 2
include/hw/timer/allwinner-a10-pit.h

@@ -35,12 +35,20 @@
 
 #define AW_A10_PIT_DEFAULT_CLOCK   0x4
 
-typedef struct AwA10PITState {
+typedef struct AwA10PITState AwA10PITState;
+
+typedef struct AwA10TimerContext {
+    AwA10PITState *container;
+    int index;
+} AwA10TimerContext;
+
+struct AwA10PITState {
     /*< private >*/
     SysBusDevice parent_obj;
     /*< public >*/
     qemu_irq irq[AW_A10_PIT_TIMER_NR];
     ptimer_state * timer[AW_A10_PIT_TIMER_NR];
+    AwA10TimerContext timer_context[AW_A10_PIT_TIMER_NR];
     MemoryRegion iomem;
 
     uint32_t irq_enable;
@@ -53,6 +61,6 @@ typedef struct AwA10PITState {
     uint32_t count_lo;
     uint32_t count_hi;
     uint32_t count_ctl;
-} AwA10PITState;
+};
 
 #endif