summaryrefslogtreecommitdiff
path: root/hw/timer
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2019-09-25 16:32:31 +0200
committerPeter Maydell <peter.maydell@linaro.org>2019-10-15 18:09:04 +0100
commitc20375dd8678eae2462a986938e6d119cb5abefa (patch)
tree1f7622b8bbe5e525cc00386d6cae57835ffd8ab5 /hw/timer
parentd85c87c1d1bf4353a4cb2c19988f81b9c667f7c6 (diff)
downloadqemu-c20375dd8678eae2462a986938e6d119cb5abefa.zip
aspeed/timer: Add AST2600 support
The AST2600 timer has a third control register that is used to implement a set-to-clear feature for the main control register. On the AST2600, it is not configurable via 0x38 (control register 3) as it is on the AST2500. 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-7-clg@kaod.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/timer')
-rw-r--r--hw/timer/aspeed_timer.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
index d70e78a029..7f73d0c753 100644
--- a/hw/timer/aspeed_timer.c
+++ b/hw/timer/aspeed_timer.c
@@ -538,6 +538,40 @@ static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
}
}
+static uint64_t aspeed_2600_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
+{
+ uint64_t value;
+
+ switch (offset) {
+ case 0x38:
+ case 0x3C:
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ value = 0;
+ break;
+ }
+ return value;
+}
+
+static void aspeed_2600_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
+ uint64_t value)
+{
+ const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
+
+ switch (offset) {
+ case 0x3C:
+ aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
+ break;
+
+ case 0x38:
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
+ __func__, offset);
+ break;
+ }
+}
+
static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
{
AspeedTimer *t = &s->timers[id];
@@ -674,11 +708,28 @@ static const TypeInfo aspeed_2500_timer_info = {
.class_init = aspeed_2500_timer_class_init,
};
+static void aspeed_2600_timer_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
+
+ dc->desc = "ASPEED 2600 Timer";
+ awc->read = aspeed_2600_timer_read;
+ awc->write = aspeed_2600_timer_write;
+}
+
+static const TypeInfo aspeed_2600_timer_info = {
+ .name = TYPE_ASPEED_2600_TIMER,
+ .parent = TYPE_ASPEED_TIMER,
+ .class_init = aspeed_2600_timer_class_init,
+};
+
static void aspeed_timer_register_types(void)
{
type_register_static(&aspeed_timer_info);
type_register_static(&aspeed_2400_timer_info);
type_register_static(&aspeed_2500_timer_info);
+ type_register_static(&aspeed_2600_timer_info);
}
type_init(aspeed_timer_register_types)