summary refs log tree commit diff stats
path: root/hw/timer/aspeed_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/timer/aspeed_timer.c')
-rw-r--r--hw/timer/aspeed_timer.c36
1 files changed, 28 insertions, 8 deletions
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
index 7f73d0c753..bcce2192a9 100644
--- a/hw/timer/aspeed_timer.c
+++ b/hw/timer/aspeed_timer.c
@@ -160,7 +160,9 @@ static uint64_t calculate_next(struct AspeedTimer *t)
     timer_del(&t->timer);
 
     if (timer_overflow_interrupt(t)) {
+        AspeedTimerCtrlState *s = timer_to_ctrl(t);
         t->level = !t->level;
+        s->irq_sts |= BIT(t->id);
         qemu_set_irq(t->irq, t->level);
     }
 
@@ -199,7 +201,9 @@ static void aspeed_timer_expire(void *opaque)
     }
 
     if (interrupt) {
+        AspeedTimerCtrlState *s = timer_to_ctrl(t);
         t->level = !t->level;
+        s->irq_sts |= BIT(t->id);
         qemu_set_irq(t->irq, t->level);
     }
 
@@ -244,9 +248,6 @@ static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
     case 0x30: /* Control Register */
         value = s->ctrl;
         break;
-    case 0x34: /* Control Register 2 */
-        value = s->ctrl2;
-        break;
     case 0x00 ... 0x2c: /* Timers 1 - 4 */
         value = aspeed_timer_get_value(&s->timers[(offset >> 4)], reg);
         break;
@@ -438,9 +439,6 @@ static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
     case 0x30:
         aspeed_timer_set_ctrl(s, tv);
         break;
-    case 0x34:
-        aspeed_timer_set_ctrl2(s, tv);
-        break;
     /* Timer Registers */
     case 0x00 ... 0x2c:
         aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS), reg, tv);
@@ -468,6 +466,9 @@ static uint64_t aspeed_2400_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
     uint64_t value;
 
     switch (offset) {
+    case 0x34:
+        value = s->ctrl2;
+        break;
     case 0x38:
     case 0x3C:
     default:
@@ -482,7 +483,12 @@ static uint64_t aspeed_2400_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
 static void aspeed_2400_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
                                     uint64_t value)
 {
+    const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
+
     switch (offset) {
+    case 0x34:
+        aspeed_timer_set_ctrl2(s, tv);
+        break;
     case 0x38:
     case 0x3C:
     default:
@@ -497,6 +503,9 @@ static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
     uint64_t value;
 
     switch (offset) {
+    case 0x34:
+        value = s->ctrl2;
+        break;
     case 0x38:
         value = s->ctrl3 & BIT(0);
         break;
@@ -517,6 +526,9 @@ static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
     uint8_t command;
 
     switch (offset) {
+    case 0x34:
+        aspeed_timer_set_ctrl2(s, tv);
+        break;
     case 0x38:
         command = (value >> 1) & 0xFF;
         if (command == 0xAE) {
@@ -543,6 +555,9 @@ static uint64_t aspeed_2600_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
     uint64_t value;
 
     switch (offset) {
+    case 0x34:
+        value = s->irq_sts;
+        break;
     case 0x38:
     case 0x3C:
     default:
@@ -560,6 +575,9 @@ static void aspeed_2600_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
     const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
 
     switch (offset) {
+    case 0x34:
+        s->irq_sts &= tv;
+        break;
     case 0x3C:
         aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
         break;
@@ -626,6 +644,7 @@ static void aspeed_timer_reset(DeviceState *dev)
     s->ctrl = 0;
     s->ctrl2 = 0;
     s->ctrl3 = 0;
+    s->irq_sts = 0;
 }
 
 static const VMStateDescription vmstate_aspeed_timer = {
@@ -644,12 +663,13 @@ static const VMStateDescription vmstate_aspeed_timer = {
 
 static const VMStateDescription vmstate_aspeed_timer_state = {
     .name = "aspeed.timerctrl",
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields = (VMStateField[]) {
         VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
         VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
         VMSTATE_UINT32(ctrl3, AspeedTimerCtrlState),
+        VMSTATE_UINT32(irq_sts, AspeedTimerCtrlState),
         VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
                              ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
                              AspeedTimer),