aspeed/timer: Introduce an object class per SoC
The most important changes will be on the register range 0x34 - 0x3C memops. Introduce class read/write operations to handle the differences between SoCs. Signed-off-by: Cédric Le Goater <clg@kaod.org> Reviewed-by: Joel Stanley <joel@jms.id.au> Message-id: 20190925143248.10000-5-clg@kaod.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
e09cf36321
commit
72d96f8e22
@ -182,8 +182,9 @@ static void aspeed_soc_init(Object *obj)
|
||||
sysbus_init_child_obj(obj, "rtc", OBJECT(&s->rtc), sizeof(s->rtc),
|
||||
TYPE_ASPEED_RTC);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
|
||||
sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl),
|
||||
sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
|
||||
sizeof(s->timerctrl), typename);
|
||||
object_property_add_const_link(OBJECT(&s->timerctrl), "scu",
|
||||
OBJECT(&s->scu), &error_abort);
|
||||
|
||||
|
@ -253,13 +253,8 @@ static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
|
||||
case 0x40 ... 0x8c: /* Timers 5 - 8 */
|
||||
value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
|
||||
break;
|
||||
/* Illegal */
|
||||
case 0x38:
|
||||
case 0x3C:
|
||||
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;
|
||||
}
|
||||
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:
|
||||
aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
|
||||
break;
|
||||
/* Illegal */
|
||||
case 0x38:
|
||||
case 0x3C:
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -472,6 +463,64 @@ static const MemoryRegionOps aspeed_timer_ops = {
|
||||
.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)
|
||||
{
|
||||
AspeedTimer *t = &s->timers[id];
|
||||
@ -570,11 +619,47 @@ static const TypeInfo aspeed_timer_info = {
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedTimerCtrlState),
|
||||
.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)
|
||||
{
|
||||
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)
|
||||
|
@ -28,6 +28,9 @@
|
||||
#define ASPEED_TIMER(obj) \
|
||||
OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER);
|
||||
#define TYPE_ASPEED_TIMER "aspeed.timer"
|
||||
#define TYPE_ASPEED_2400_TIMER TYPE_ASPEED_TIMER "-ast2400"
|
||||
#define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500"
|
||||
|
||||
#define ASPEED_TIMER_NR_TIMERS 8
|
||||
|
||||
typedef struct AspeedTimer {
|
||||
@ -60,4 +63,16 @@ typedef struct AspeedTimerCtrlState {
|
||||
AspeedSCUState *scu;
|
||||
} AspeedTimerCtrlState;
|
||||
|
||||
#define ASPEED_TIMER_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AspeedTimerClass, (klass), TYPE_ASPEED_TIMER)
|
||||
#define ASPEED_TIMER_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AspeedTimerClass, (obj), TYPE_ASPEED_TIMER)
|
||||
|
||||
typedef struct AspeedTimerClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint64_t (*read)(AspeedTimerCtrlState *s, hwaddr offset);
|
||||
void (*write)(AspeedTimerCtrlState *s, hwaddr offset, uint64_t value);
|
||||
} AspeedTimerClass;
|
||||
|
||||
#endif /* ASPEED_TIMER_H */
|
||||
|
Loading…
Reference in New Issue
Block a user