aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/timer/aspeed_timer.c36
-rw-r--r--include/hw/timer/aspeed_timer.h1
2 files changed, 29 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),
diff --git a/include/hw/timer/aspeed_timer.h b/include/hw/timer/aspeed_timer.h
index 69b1377af0..948329893c 100644
--- a/include/hw/timer/aspeed_timer.h
+++ b/include/hw/timer/aspeed_timer.h
@@ -60,6 +60,7 @@ typedef struct AspeedTimerCtrlState {
uint32_t ctrl;
uint32_t ctrl2;
uint32_t ctrl3;
+ uint32_t irq_sts;
AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
AspeedSCUState *scu;