aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2019-09-25 16:32:30 +0200
committerPeter Maydell <peter.maydell@linaro.org>2019-10-15 18:09:04 +0100
commitd85c87c1d1bf4353a4cb2c19988f81b9c667f7c6 (patch)
treeffdc43a7753c3b77b0098c960f96395a39836976
parent72d96f8e2288e4bc7b31011c0c3f00448e2cef19 (diff)
downloadqemu-d85c87c1d1bf4353a4cb2c19988f81b9c667f7c6.zip
qemu-d85c87c1d1bf4353a4cb2c19988f81b9c667f7c6.tar.gz
qemu-d85c87c1d1bf4353a4cb2c19988f81b9c667f7c6.tar.bz2
aspeed/timer: Add support for control register 3
The AST2500 timer has a third control register that is used to implement a set-to-clear feature for the main control register. This models the behaviour expected by the AST2500 while maintaining the same behaviour for the AST2400. The vmstate version is not increased yet because the structure is modified again in the following patches. 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-6-clg@kaod.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/timer/aspeed_timer.c19
-rw-r--r--include/hw/timer/aspeed_timer.h1
2 files changed, 20 insertions, 0 deletions
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
index c78bc1b..d70e78a 100644
--- a/hw/timer/aspeed_timer.c
+++ b/hw/timer/aspeed_timer.c
@@ -498,6 +498,8 @@ static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
switch (offset) {
case 0x38:
+ value = s->ctrl3 & BIT(0);
+ break;
case 0x3C:
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
@@ -511,9 +513,24 @@ static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
uint64_t value)
{
+ const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
+ uint8_t command;
+
switch (offset) {
case 0x38:
+ command = (value >> 1) & 0xFF;
+ if (command == 0xAE) {
+ s->ctrl3 = 0x1;
+ } else if (command == 0xEA) {
+ s->ctrl3 = 0x0;
+ }
+ break;
case 0x3C:
+ if (s->ctrl3 & BIT(0)) {
+ aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
+ }
+ break;
+
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
@@ -574,6 +591,7 @@ static void aspeed_timer_reset(DeviceState *dev)
}
s->ctrl = 0;
s->ctrl2 = 0;
+ s->ctrl3 = 0;
}
static const VMStateDescription vmstate_aspeed_timer = {
@@ -597,6 +615,7 @@ static const VMStateDescription vmstate_aspeed_timer_state = {
.fields = (VMStateField[]) {
VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
+ VMSTATE_UINT32(ctrl3, 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 a791fee..1e0288e 100644
--- a/include/hw/timer/aspeed_timer.h
+++ b/include/hw/timer/aspeed_timer.h
@@ -58,6 +58,7 @@ typedef struct AspeedTimerCtrlState {
uint32_t ctrl;
uint32_t ctrl2;
+ uint32_t ctrl3;
AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
AspeedSCUState *scu;