aboutsummaryrefslogtreecommitdiff
path: root/hw/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'hw/watchdog')
-rw-r--r--hw/watchdog/allwinner-wdt.c10
-rw-r--r--hw/watchdog/cmsdk-apb-watchdog.c44
-rw-r--r--hw/watchdog/sbsa_gwdt.c12
-rw-r--r--hw/watchdog/spapr_watchdog.c2
-rw-r--r--hw/watchdog/watchdog.c6
-rw-r--r--hw/watchdog/wdt_aspeed.c39
-rw-r--r--hw/watchdog/wdt_diag288.c8
-rw-r--r--hw/watchdog/wdt_i6300esb.c8
-rw-r--r--hw/watchdog/wdt_ib700.c6
-rw-r--r--hw/watchdog/wdt_imx2.c10
10 files changed, 87 insertions, 58 deletions
diff --git a/hw/watchdog/allwinner-wdt.c b/hw/watchdog/allwinner-wdt.c
index d35711c..8fcd776 100644
--- a/hw/watchdog/allwinner-wdt.c
+++ b/hw/watchdog/allwinner-wdt.c
@@ -28,7 +28,7 @@
#include "hw/sysbus.h"
#include "hw/registerfields.h"
#include "hw/watchdog/allwinner-wdt.h"
-#include "sysemu/watchdog.h"
+#include "system/watchdog.h"
#include "migration/vmstate.h"
/* WDT registers */
@@ -275,7 +275,7 @@ static void allwinner_wdt_write(void *opaque, hwaddr offset,
static const MemoryRegionOps allwinner_wdt_ops = {
.read = allwinner_wdt_read,
.write = allwinner_wdt_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
@@ -348,7 +348,7 @@ static void allwinner_wdt_realize(DeviceState *dev, Error **errp)
ptimer_transaction_commit(s->timer);
}
-static void allwinner_wdt_class_init(ObjectClass *klass, void *data)
+static void allwinner_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ResettableClass *rc = RESETTABLE_CLASS(klass);
@@ -358,7 +358,7 @@ static void allwinner_wdt_class_init(ObjectClass *klass, void *data)
dc->vmsd = &allwinner_wdt_vmstate;
}
-static void allwinner_wdt_sun4i_class_init(ObjectClass *klass, void *data)
+static void allwinner_wdt_sun4i_class_init(ObjectClass *klass, const void *data)
{
AwWdtClass *awc = AW_WDT_CLASS(klass);
@@ -371,7 +371,7 @@ static void allwinner_wdt_sun4i_class_init(ObjectClass *klass, void *data)
awc->get_intv_value = allwinner_wdt_sun4i_get_intv_value;
}
-static void allwinner_wdt_sun6i_class_init(ObjectClass *klass, void *data)
+static void allwinner_wdt_sun6i_class_init(ObjectClass *klass, const void *data)
{
AwWdtClass *awc = AW_WDT_CLASS(klass);
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
index 3091e5c..6a8d07c 100644
--- a/hw/watchdog/cmsdk-apb-watchdog.c
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
@@ -12,8 +12,8 @@
/*
* This is a model of the "APB watchdog" which is part of the Cortex-M
* System Design Kit (CMSDK) and documented in the Cortex-M System
- * Design Kit Technical Reference Manual (ARM DDI0479C):
- * https://developer.arm.com/products/system-design/system-design-kits/cortex-m-system-design-kit
+ * Design Kit Technical Reference Manual (ARM DDI0479):
+ * https://developer.arm.com/documentation/ddi0479/
*
* We also support the variant of this device found in the TI
* Stellaris/Luminary boards and documented in:
@@ -25,7 +25,7 @@
#include "trace.h"
#include "qapi/error.h"
#include "qemu/module.h"
-#include "sysemu/watchdog.h"
+#include "system/watchdog.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
@@ -196,16 +196,13 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
switch (offset) {
case A_WDOGLOAD:
- /*
- * Reset the load value and the current count, and make sure
- * we're counting.
- */
+ /* Reset the load value and the current count. */
ptimer_transaction_begin(s->timer);
ptimer_set_limit(s->timer, value, 1);
- ptimer_run(s->timer, 0);
ptimer_transaction_commit(s->timer);
break;
- case A_WDOGCONTROL:
+ case A_WDOGCONTROL: {
+ uint32_t prev_control = s->control;
if (s->is_luminary && 0 != (R_WDOGCONTROL_INTEN_MASK & s->control)) {
/*
* The Luminary version of this device ignores writes to
@@ -215,8 +212,25 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
break;
}
s->control = value & R_WDOGCONTROL_VALID_MASK;
+ if (R_WDOGCONTROL_INTEN_MASK & (s->control ^ prev_control)) {
+ ptimer_transaction_begin(s->timer);
+ if (R_WDOGCONTROL_INTEN_MASK & s->control) {
+ /*
+ * Set HIGH to enable the counter and the interrupt. Reloads
+ * the counter from the value in WDOGLOAD when the interrupt
+ * is enabled, after previously being disabled.
+ */
+ ptimer_set_count(s->timer, ptimer_get_limit(s->timer));
+ ptimer_run(s->timer, 0);
+ } else {
+ /* Or LOW to disable the counter and interrupt. */
+ ptimer_stop(s->timer);
+ }
+ ptimer_transaction_commit(s->timer);
+ }
cmsdk_apb_watchdog_update(s);
break;
+ }
case A_WDOGINTCLR:
s->intstatus = 0;
ptimer_transaction_begin(s->timer);
@@ -305,8 +319,14 @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
s->resetstatus = 0;
/* Set the limit and the count */
ptimer_transaction_begin(s->timer);
+ /*
+ * We need to stop the ptimer before setting its limit reset value. If the
+ * order is the opposite when the code executes the stop after setting a new
+ * limit it may want to recalculate the count based on the current time (if
+ * the timer was currently running) and it won't get the proper reset value.
+ */
+ ptimer_stop(s->timer);
ptimer_set_limit(s->timer, 0xffffffff, 1);
- ptimer_run(s->timer, 0);
ptimer_transaction_commit(s->timer);
}
@@ -374,13 +394,13 @@ static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
}
};
-static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, void *data)
+static void cmsdk_apb_watchdog_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = cmsdk_apb_watchdog_realize;
dc->vmsd = &cmsdk_apb_watchdog_vmstate;
- dc->reset = cmsdk_apb_watchdog_reset;
+ device_class_set_legacy_reset(dc, cmsdk_apb_watchdog_reset);
}
static const TypeInfo cmsdk_apb_watchdog_info = {
diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c
index d437535..ce84849 100644
--- a/hw/watchdog/sbsa_gwdt.c
+++ b/hw/watchdog/sbsa_gwdt.c
@@ -16,8 +16,8 @@
*/
#include "qemu/osdep.h"
-#include "sysemu/reset.h"
-#include "sysemu/watchdog.h"
+#include "system/reset.h"
+#include "system/watchdog.h"
#include "hw/qdev-properties.h"
#include "hw/watchdog/sbsa_gwdt.h"
#include "qemu/timer.h"
@@ -174,7 +174,6 @@ static void sbsa_gwdt_write(void *opaque, hwaddr offset, uint64_t data,
qemu_log_mask(LOG_GUEST_ERROR, "bad address in control frame write :"
" 0x%x\n", (int)offset);
}
- return;
}
static void wdt_sbsa_gwdt_reset(DeviceState *dev)
@@ -262,7 +261,7 @@ static void wdt_sbsa_gwdt_realize(DeviceState *dev, Error **errp)
dev);
}
-static Property wdt_sbsa_gwdt_props[] = {
+static const Property wdt_sbsa_gwdt_props[] = {
/*
* Timer frequency in Hz. This must match the frequency used by
* the CPU's generic timer. Default 62.5Hz matches QEMU's legacy
@@ -270,15 +269,14 @@ static Property wdt_sbsa_gwdt_props[] = {
*/
DEFINE_PROP_UINT64("clock-frequency", struct SBSA_GWDTState, freq,
62500000),
- DEFINE_PROP_END_OF_LIST(),
};
-static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, void *data)
+static void wdt_sbsa_gwdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = wdt_sbsa_gwdt_realize;
- dc->reset = wdt_sbsa_gwdt_reset;
+ device_class_set_legacy_reset(dc, wdt_sbsa_gwdt_reset);
dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->vmsd = &vmstate_sbsa_gwdt;
diff --git a/hw/watchdog/spapr_watchdog.c b/hw/watchdog/spapr_watchdog.c
index 2bb1d3c..5b3f50d 100644
--- a/hw/watchdog/spapr_watchdog.c
+++ b/hw/watchdog/spapr_watchdog.c
@@ -249,7 +249,7 @@ static void spapr_wdt_realize(DeviceState *dev, Error **errp)
&w->leave_others, OBJ_PROP_FLAG_READ);
}
-static void spapr_wdt_class_init(ObjectClass *oc, void *data)
+static void spapr_wdt_class_init(ObjectClass *oc, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 9550461..0721373 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -26,8 +26,8 @@
#include "qapi/error.h"
#include "qapi/qapi-commands-run-state.h"
#include "qapi/qapi-events-run-state.h"
-#include "sysemu/runstate.h"
-#include "sysemu/watchdog.h"
+#include "system/runstate.h"
+#include "system/watchdog.h"
#include "hw/nmi.h"
#include "qemu/help_option.h"
#include "trace.h"
@@ -85,7 +85,7 @@ void watchdog_perform_action(void)
break;
default:
- assert(0);
+ g_assert_not_reached();
}
}
diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
index 75685c5..3022643 100644
--- a/hw/watchdog/wdt_aspeed.c
+++ b/hw/watchdog/wdt_aspeed.c
@@ -13,7 +13,7 @@
#include "qemu/log.h"
#include "qemu/module.h"
#include "qemu/timer.h"
-#include "sysemu/watchdog.h"
+#include "system/watchdog.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "hw/watchdog/wdt_aspeed.h"
@@ -51,11 +51,20 @@
#define WDT_TIMEOUT_CLEAR (0x14 / 4)
#define WDT_RESTART_MAGIC 0x4755
+#define WDT_SW_RESET_ENABLE 0xAEEDF123
#define AST2600_SCU_RESET_CONTROL1 (0x40 / 4)
#define SCU_RESET_CONTROL1 (0x04 / 4)
#define SCU_RESET_SDRAM BIT(0)
+static bool aspeed_wdt_is_soc_reset_mode(const AspeedWDTState *s)
+{
+ uint32_t mode;
+
+ mode = extract32(s->regs[WDT_CTRL], 5, 2);
+ return (mode == WDT_CTRL_RESET_MODE_SOC);
+}
+
static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
{
return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
@@ -199,19 +208,23 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
case WDT_TIMEOUT_STATUS:
case WDT_TIMEOUT_CLEAR:
case WDT_RESET_MASK2:
- case WDT_SW_RESET_CTRL:
case WDT_SW_RESET_MASK1:
case WDT_SW_RESET_MASK2:
qemu_log_mask(LOG_UNIMP,
"%s: uninmplemented write at offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
break;
+ case WDT_SW_RESET_CTRL:
+ if (aspeed_wdt_is_soc_reset_mode(s) &&
+ (data == WDT_SW_RESET_ENABLE)) {
+ watchdog_perform_action();
+ }
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
__func__, offset);
}
- return;
}
static const VMStateDescription vmstate_aspeed_wdt = {
@@ -278,7 +291,8 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev);
- /* FIXME: This setting should be derived from the SCU hw strapping
+ /*
+ * FIXME: This setting should be derived from the SCU hw strapping
* register SCU70
*/
s->pclk_freq = PCLK_HZ;
@@ -288,19 +302,18 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->iomem);
}
-static Property aspeed_wdt_properties[] = {
+static const Property aspeed_wdt_properties[] = {
DEFINE_PROP_LINK("scu", AspeedWDTState, scu, TYPE_ASPEED_SCU,
AspeedSCUState *),
- DEFINE_PROP_END_OF_LIST(),
};
-static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
+static void aspeed_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->desc = "ASPEED Watchdog Controller";
dc->realize = aspeed_wdt_realize;
- dc->reset = aspeed_wdt_reset;
+ device_class_set_legacy_reset(dc, aspeed_wdt_reset);
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->vmsd = &vmstate_aspeed_wdt;
device_class_set_props(dc, aspeed_wdt_properties);
@@ -316,7 +329,7 @@ static const TypeInfo aspeed_wdt_info = {
.abstract = true,
};
-static void aspeed_2400_wdt_class_init(ObjectClass *klass, void *data)
+static void aspeed_2400_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
@@ -353,7 +366,7 @@ static void aspeed_2500_wdt_reset_pulse(AspeedWDTState *s, uint32_t property)
}
}
-static void aspeed_2500_wdt_class_init(ObjectClass *klass, void *data)
+static void aspeed_2500_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
@@ -376,7 +389,7 @@ static const TypeInfo aspeed_2500_wdt_info = {
.class_init = aspeed_2500_wdt_class_init,
};
-static void aspeed_2600_wdt_class_init(ObjectClass *klass, void *data)
+static void aspeed_2600_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
@@ -399,7 +412,7 @@ static const TypeInfo aspeed_2600_wdt_info = {
.class_init = aspeed_2600_wdt_class_init,
};
-static void aspeed_1030_wdt_class_init(ObjectClass *klass, void *data)
+static void aspeed_1030_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
@@ -422,7 +435,7 @@ static const TypeInfo aspeed_1030_wdt_info = {
.class_init = aspeed_1030_wdt_class_init,
};
-static void aspeed_2700_wdt_class_init(ObjectClass *klass, void *data)
+static void aspeed_2700_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
index 1b73b16..1275353 100644
--- a/hw/watchdog/wdt_diag288.c
+++ b/hw/watchdog/wdt_diag288.c
@@ -12,8 +12,8 @@
*/
#include "qemu/osdep.h"
-#include "sysemu/reset.h"
-#include "sysemu/watchdog.h"
+#include "system/reset.h"
+#include "system/watchdog.h"
#include "qemu/timer.h"
#include "hw/watchdog/wdt_diag288.h"
#include "migration/vmstate.h"
@@ -108,14 +108,14 @@ static void wdt_diag288_unrealize(DeviceState *dev)
timer_free(diag288->timer);
}
-static void wdt_diag288_class_init(ObjectClass *klass, void *data)
+static void wdt_diag288_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
DIAG288Class *diag288 = DIAG288_CLASS(klass);
dc->realize = wdt_diag288_realize;
dc->unrealize = wdt_diag288_unrealize;
- dc->reset = wdt_diag288_reset;
+ device_class_set_legacy_reset(dc, wdt_diag288_reset);
dc->hotpluggable = false;
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->vmsd = &vmstate_diag288;
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
index 8bce050..bb8a276 100644
--- a/hw/watchdog/wdt_i6300esb.c
+++ b/hw/watchdog/wdt_i6300esb.c
@@ -23,7 +23,7 @@
#include "qemu/module.h"
#include "qemu/timer.h"
-#include "sysemu/watchdog.h"
+#include "system/watchdog.h"
#include "hw/pci/pci_device.h"
#include "migration/vmstate.h"
#include "qom/object.h"
@@ -457,7 +457,7 @@ static void i6300esb_exit(PCIDevice *dev)
timer_free(d->timer);
}
-static void i6300esb_class_init(ObjectClass *klass, void *data)
+static void i6300esb_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
@@ -469,7 +469,7 @@ static void i6300esb_class_init(ObjectClass *klass, void *data)
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_ESB_9;
k->class_id = PCI_CLASS_SYSTEM_OTHER;
- dc->reset = i6300esb_reset;
+ device_class_set_legacy_reset(dc, i6300esb_reset);
dc->vmsd = &vmstate_i6300esb;
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->desc = "Intel 6300ESB";
@@ -480,7 +480,7 @@ static const TypeInfo i6300esb_info = {
.parent = TYPE_PCI_DEVICE,
.instance_size = sizeof(I6300State),
.class_init = i6300esb_class_init,
- .interfaces = (InterfaceInfo[]) {
+ .interfaces = (const InterfaceInfo[]) {
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
{ },
},
diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c
index eea8da6..51a26a4 100644
--- a/hw/watchdog/wdt_ib700.c
+++ b/hw/watchdog/wdt_ib700.c
@@ -22,7 +22,7 @@
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu/timer.h"
-#include "sysemu/watchdog.h"
+#include "system/watchdog.h"
#include "hw/isa/isa.h"
#include "migration/vmstate.h"
#include "qom/object.h"
@@ -128,12 +128,12 @@ static void wdt_ib700_reset(DeviceState *dev)
timer_del(s->timer);
}
-static void wdt_ib700_class_init(ObjectClass *klass, void *data)
+static void wdt_ib700_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = wdt_ib700_realize;
- dc->reset = wdt_ib700_reset;
+ device_class_set_legacy_reset(dc, wdt_ib700_reset);
dc->vmsd = &vmstate_ib700;
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);
dc->desc = "iBASE 700";
diff --git a/hw/watchdog/wdt_imx2.c b/hw/watchdog/wdt_imx2.c
index 6452fc4..10151a1 100644
--- a/hw/watchdog/wdt_imx2.c
+++ b/hw/watchdog/wdt_imx2.c
@@ -12,7 +12,7 @@
#include "qemu/osdep.h"
#include "qemu/bitops.h"
#include "qemu/module.h"
-#include "sysemu/watchdog.h"
+#include "system/watchdog.h"
#include "migration/vmstate.h"
#include "hw/qdev-properties.h"
@@ -39,7 +39,6 @@ static void imx2_wdt_expired(void *opaque)
/* Perform watchdog action if watchdog is enabled */
if (s->wcr & IMX2_WDT_WCR_WDE) {
- s->wrsr = IMX2_WDT_WRSR_TOUT;
watchdog_perform_action();
}
}
@@ -282,19 +281,18 @@ static void imx2_wdt_realize(DeviceState *dev, Error **errp)
}
}
-static Property imx2_wdt_properties[] = {
+static const Property imx2_wdt_properties[] = {
DEFINE_PROP_BOOL("pretimeout-support", IMX2WdtState, pretimeout_support,
false),
- DEFINE_PROP_END_OF_LIST()
};
-static void imx2_wdt_class_init(ObjectClass *klass, void *data)
+static void imx2_wdt_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
device_class_set_props(dc, imx2_wdt_properties);
dc->realize = imx2_wdt_realize;
- dc->reset = imx2_wdt_reset;
+ device_class_set_legacy_reset(dc, imx2_wdt_reset);
dc->vmsd = &vmstate_imx2_wdt;
dc->desc = "i.MX2 watchdog timer";
set_bit(DEVICE_CATEGORY_WATCHDOG, dc->categories);