|
@@ -253,13 +253,8 @@ static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
|
|
case 0x40 ... 0x8c: /* Timers 5 - 8 */
|
|
case 0x40 ... 0x8c: /* Timers 5 - 8 */
|
|
value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
|
|
value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
|
|
break;
|
|
break;
|
|
- /* Illegal */
|
|
|
|
- case 0x38:
|
|
|
|
- case 0x3C:
|
|
|
|
default:
|
|
default:
|
|
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
|
|
|
- __func__, offset);
|
|
|
|
- value = 0;
|
|
|
|
|
|
+ value = ASPEED_TIMER_GET_CLASS(s)->read(s, offset);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
trace_aspeed_timer_read(offset, size, value);
|
|
trace_aspeed_timer_read(offset, size, value);
|
|
@@ -453,12 +448,8 @@ static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
|
|
case 0x40 ... 0x8c:
|
|
case 0x40 ... 0x8c:
|
|
aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
|
|
aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
|
|
break;
|
|
break;
|
|
- /* Illegal */
|
|
|
|
- case 0x38:
|
|
|
|
- case 0x3C:
|
|
|
|
default:
|
|
default:
|
|
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
|
|
|
- __func__, offset);
|
|
|
|
|
|
+ ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -472,6 +463,64 @@ static const MemoryRegionOps aspeed_timer_ops = {
|
|
.valid.unaligned = false,
|
|
.valid.unaligned = false,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static uint64_t aspeed_2400_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_2400_timer_write(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);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static uint64_t aspeed_2500_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_2500_timer_write(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);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
|
|
static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
|
|
{
|
|
{
|
|
AspeedTimer *t = &s->timers[id];
|
|
AspeedTimer *t = &s->timers[id];
|
|
@@ -570,11 +619,47 @@ static const TypeInfo aspeed_timer_info = {
|
|
.parent = TYPE_SYS_BUS_DEVICE,
|
|
.parent = TYPE_SYS_BUS_DEVICE,
|
|
.instance_size = sizeof(AspeedTimerCtrlState),
|
|
.instance_size = sizeof(AspeedTimerCtrlState),
|
|
.class_init = timer_class_init,
|
|
.class_init = timer_class_init,
|
|
|
|
+ .class_size = sizeof(AspeedTimerClass),
|
|
|
|
+ .abstract = true,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static void aspeed_2400_timer_class_init(ObjectClass *klass, void *data)
|
|
|
|
+{
|
|
|
|
+ DeviceClass *dc = DEVICE_CLASS(klass);
|
|
|
|
+ AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
|
|
|
|
+
|
|
|
|
+ dc->desc = "ASPEED 2400 Timer";
|
|
|
|
+ awc->read = aspeed_2400_timer_read;
|
|
|
|
+ awc->write = aspeed_2400_timer_write;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const TypeInfo aspeed_2400_timer_info = {
|
|
|
|
+ .name = TYPE_ASPEED_2400_TIMER,
|
|
|
|
+ .parent = TYPE_ASPEED_TIMER,
|
|
|
|
+ .class_init = aspeed_2400_timer_class_init,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static void aspeed_2500_timer_class_init(ObjectClass *klass, void *data)
|
|
|
|
+{
|
|
|
|
+ DeviceClass *dc = DEVICE_CLASS(klass);
|
|
|
|
+ AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
|
|
|
|
+
|
|
|
|
+ dc->desc = "ASPEED 2500 Timer";
|
|
|
|
+ awc->read = aspeed_2500_timer_read;
|
|
|
|
+ awc->write = aspeed_2500_timer_write;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const TypeInfo aspeed_2500_timer_info = {
|
|
|
|
+ .name = TYPE_ASPEED_2500_TIMER,
|
|
|
|
+ .parent = TYPE_ASPEED_TIMER,
|
|
|
|
+ .class_init = aspeed_2500_timer_class_init,
|
|
};
|
|
};
|
|
|
|
|
|
static void aspeed_timer_register_types(void)
|
|
static void aspeed_timer_register_types(void)
|
|
{
|
|
{
|
|
type_register_static(&aspeed_timer_info);
|
|
type_register_static(&aspeed_timer_info);
|
|
|
|
+ type_register_static(&aspeed_2400_timer_info);
|
|
|
|
+ type_register_static(&aspeed_2500_timer_info);
|
|
}
|
|
}
|
|
|
|
|
|
type_init(aspeed_timer_register_types)
|
|
type_init(aspeed_timer_register_types)
|