summary refs log tree commit diff stats
path: root/hw/watchdog/wdt_aspeed.c
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2019-09-25 16:32:35 +0200
committerPeter Maydell <peter.maydell@linaro.org>2019-10-15 18:09:04 +0100
commit6112bd6d9b8e03c1c454c4785a56402573ccb16e (patch)
treeb42744f1bf5f5260363ef0e52510d34aa56280e2 /hw/watchdog/wdt_aspeed.c
parent1550d7267984b19796089f767832c30da80494ec (diff)
downloadfocaccia-qemu-6112bd6d9b8e03c1c454c4785a56402573ccb16e.tar.gz
focaccia-qemu-6112bd6d9b8e03c1c454c4785a56402573ccb16e.zip
watchdog/aspeed: Introduce an object class per SoC
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>
Diffstat (limited to 'hw/watchdog/wdt_aspeed.c')
-rw-r--r--hw/watchdog/wdt_aspeed.c122
1 files changed, 65 insertions, 57 deletions
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index f710036535..fc0e6c486a 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -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);
@@ -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;
@@ -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,
@@ -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;
@@ -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
@@ -287,20 +244,15 @@ 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 = {
@@ -308,12 +260,68 @@ static const TypeInfo aspeed_wdt_info = {
     .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)