Skip to content

Commit

Permalink
aspeed/timer: Add support for IRQ status register on the AST2600
Browse files Browse the repository at this point in the history
The AST2600 timer replaces control register 2 with a interrupt status
register. It is set by hardware when an IRQ occurs and cleared by
software.

Modify the vmstate version to take into account the new fields.

Based on previous work from Joel Stanley.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Message-id: 20190925143248.10000-8-clg@kaod.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
legoater authored and pm215 committed Oct 15, 2019
1 parent c20375d commit fadefad
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
36 changes: 28 additions & 8 deletions hw/timer/aspeed_timer.c
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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;
Expand All @@ -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) {
Expand All @@ -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:
Expand All @@ -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;
Expand Down Expand Up @@ -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 = {
Expand All @@ -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),
Expand Down
1 change: 1 addition & 0 deletions include/hw/timer/aspeed_timer.h
Expand Up @@ -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;
Expand Down

0 comments on commit fadefad

Please sign in to comment.