Skip to content

Commit

Permalink
watchdog/aspeed: Introduce an object class per SoC
Browse files Browse the repository at this point in the history
It cleanups the current models for the Aspeed AST2400 and AST2500 SoCs
and prepares ground for future SoCs.

Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Message-id: 20190925143248.10000-11-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 1550d72 commit 6112bd6
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 63 deletions.
9 changes: 5 additions & 4 deletions hw/arm/aspeed_soc.c
Expand Up @@ -214,10 +214,9 @@ static void aspeed_soc_init(Object *obj)
"max-ram-size", &error_abort);

for (i = 0; i < sc->info->wdts_num; i++) {
snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]),
sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
qdev_prop_set_uint32(DEVICE(&s->wdt[i]), "silicon-rev",
sc->info->silicon_rev);
sizeof(s->wdt[i]), typename);
object_property_add_const_link(OBJECT(&s->wdt[i]), "scu",
OBJECT(&s->scu), &error_abort);
}
Expand Down Expand Up @@ -384,13 +383,15 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)

/* Watch dog */
for (i = 0; i < sc->info->wdts_num; i++) {
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);

object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
sc->info->memmap[ASPEED_WDT] + i * 0x20);
sc->info->memmap[ASPEED_WDT] + i * awc->offset);
}

/* Net */
Expand Down
122 changes: 65 additions & 57 deletions hw/watchdog/wdt_aspeed.c
Expand Up @@ -54,21 +54,6 @@ static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
}

static bool is_ast2500(const AspeedWDTState *s)
{
switch (s->silicon_rev) {
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
return true;
case AST2400_A0_SILICON_REV:
case AST2400_A1_SILICON_REV:
default:
break;
}

return false;
}

static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
{
AspeedWDTState *s = ASPEED_WDT(opaque);
Expand Down Expand Up @@ -124,6 +109,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
unsigned size)
{
AspeedWDTState *s = ASPEED_WDT(opaque);
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(s);
bool enable = data & WDT_CTRL_ENABLE;

offset >>= 2;
Expand Down Expand Up @@ -153,24 +139,13 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
}
break;
case WDT_RESET_WIDTH:
{
uint32_t property = data & WDT_POLARITY_MASK;

if (property && is_ast2500(s)) {
if (property == WDT_ACTIVE_HIGH_MAGIC) {
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
} else if (property == WDT_ACTIVE_LOW_MAGIC) {
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
} else if (property == WDT_PUSH_PULL_MAGIC) {
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
} else if (property == WDT_OPEN_DRAIN_MAGIC) {
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
}
if (awc->reset_pulse) {
awc->reset_pulse(s, data & WDT_POLARITY_MASK);
}
s->regs[WDT_RESET_WIDTH] &= ~s->ext_pulse_width_mask;
s->regs[WDT_RESET_WIDTH] |= data & s->ext_pulse_width_mask;
s->regs[WDT_RESET_WIDTH] &= ~awc->ext_pulse_width_mask;
s->regs[WDT_RESET_WIDTH] |= data & awc->ext_pulse_width_mask;
break;
}

case WDT_TIMEOUT_STATUS:
case WDT_TIMEOUT_CLEAR:
qemu_log_mask(LOG_UNIMP,
Expand Down Expand Up @@ -226,9 +201,10 @@ static void aspeed_wdt_reset(DeviceState *dev)
static void aspeed_wdt_timer_expired(void *dev)
{
AspeedWDTState *s = ASPEED_WDT(dev);
uint32_t reset_ctrl_reg = ASPEED_WDT_GET_CLASS(s)->reset_ctrl_reg;

/* Do not reset on SDRAM controller reset */
if (s->scu->regs[SCU_RESET_CONTROL1] & SCU_RESET_SDRAM) {
if (s->scu->regs[reset_ctrl_reg] & SCU_RESET_SDRAM) {
timer_del(s->timer);
s->regs[WDT_CTRL] = 0;
return;
Expand Down Expand Up @@ -256,25 +232,6 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
}
s->scu = ASPEED_SCU(obj);

if (!is_supported_silicon_rev(s->silicon_rev)) {
error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
s->silicon_rev);
return;
}

switch (s->silicon_rev) {
case AST2400_A0_SILICON_REV:
case AST2400_A1_SILICON_REV:
s->ext_pulse_width_mask = 0xff;
break;
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
s->ext_pulse_width_mask = 0xfffff;
break;
default:
g_assert_not_reached();
}

s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev);

/* FIXME: This setting should be derived from the SCU hw strapping
Expand All @@ -287,33 +244,84 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->iomem);
}

static Property aspeed_wdt_properties[] = {
DEFINE_PROP_UINT32("silicon-rev", AspeedWDTState, silicon_rev, 0),
DEFINE_PROP_END_OF_LIST(),
};

static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);

dc->desc = "ASPEED Watchdog Controller";
dc->realize = aspeed_wdt_realize;
dc->reset = aspeed_wdt_reset;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->vmsd = &vmstate_aspeed_wdt;
dc->props = aspeed_wdt_properties;
}

static const TypeInfo aspeed_wdt_info = {
.parent = TYPE_SYS_BUS_DEVICE,
.name = TYPE_ASPEED_WDT,
.instance_size = sizeof(AspeedWDTState),
.class_init = aspeed_wdt_class_init,
.class_size = sizeof(AspeedWDTClass),
.abstract = true,
};

static void aspeed_2400_wdt_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);

dc->desc = "ASPEED 2400 Watchdog Controller";
awc->offset = 0x20;
awc->ext_pulse_width_mask = 0xff;
awc->reset_ctrl_reg = SCU_RESET_CONTROL1;
}

static const TypeInfo aspeed_2400_wdt_info = {
.name = TYPE_ASPEED_2400_WDT,
.parent = TYPE_ASPEED_WDT,
.instance_size = sizeof(AspeedWDTState),
.class_init = aspeed_2400_wdt_class_init,
};

static void aspeed_2500_wdt_reset_pulse(AspeedWDTState *s, uint32_t property)
{
if (property) {
if (property == WDT_ACTIVE_HIGH_MAGIC) {
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
} else if (property == WDT_ACTIVE_LOW_MAGIC) {
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
} else if (property == WDT_PUSH_PULL_MAGIC) {
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
} else if (property == WDT_OPEN_DRAIN_MAGIC) {
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
}
}
}

static void aspeed_2500_wdt_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);

dc->desc = "ASPEED 2500 Watchdog Controller";
awc->offset = 0x20;
awc->ext_pulse_width_mask = 0xfffff;
awc->reset_ctrl_reg = SCU_RESET_CONTROL1;
awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
}

static const TypeInfo aspeed_2500_wdt_info = {
.name = TYPE_ASPEED_2500_WDT,
.parent = TYPE_ASPEED_WDT,
.instance_size = sizeof(AspeedWDTState),
.class_init = aspeed_2500_wdt_class_init,
};

static void wdt_aspeed_register_types(void)
{
watchdog_add_model(&model);
type_register_static(&aspeed_wdt_info);
type_register_static(&aspeed_2400_wdt_info);
type_register_static(&aspeed_2500_wdt_info);
}

type_init(wdt_aspeed_register_types)
18 changes: 16 additions & 2 deletions include/hw/watchdog/wdt_aspeed.h
Expand Up @@ -16,6 +16,8 @@
#define TYPE_ASPEED_WDT "aspeed.wdt"
#define ASPEED_WDT(obj) \
OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
#define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
#define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"

#define ASPEED_WDT_REGS_MAX (0x20 / 4)

Expand All @@ -30,8 +32,20 @@ typedef struct AspeedWDTState {

AspeedSCUState *scu;
uint32_t pclk_freq;
uint32_t silicon_rev;
uint32_t ext_pulse_width_mask;
} AspeedWDTState;

#define ASPEED_WDT_CLASS(klass) \
OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
#define ASPEED_WDT_GET_CLASS(obj) \
OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)

typedef struct AspeedWDTClass {
SysBusDeviceClass parent_class;

uint32_t offset;
uint32_t ext_pulse_width_mask;
uint32_t reset_ctrl_reg;
void (*reset_pulse)(AspeedWDTState *s, uint32_t property);
} AspeedWDTClass;

#endif /* WDT_ASPEED_H */

0 comments on commit 6112bd6

Please sign in to comment.