diff options
Diffstat (limited to 'hw/watchdog')
-rw-r--r-- | hw/watchdog/allwinner-wdt.c | 10 | ||||
-rw-r--r-- | hw/watchdog/cmsdk-apb-watchdog.c | 44 | ||||
-rw-r--r-- | hw/watchdog/sbsa_gwdt.c | 12 | ||||
-rw-r--r-- | hw/watchdog/spapr_watchdog.c | 2 | ||||
-rw-r--r-- | hw/watchdog/watchdog.c | 6 | ||||
-rw-r--r-- | hw/watchdog/wdt_aspeed.c | 39 | ||||
-rw-r--r-- | hw/watchdog/wdt_diag288.c | 8 | ||||
-rw-r--r-- | hw/watchdog/wdt_i6300esb.c | 8 | ||||
-rw-r--r-- | hw/watchdog/wdt_ib700.c | 6 | ||||
-rw-r--r-- | hw/watchdog/wdt_imx2.c | 10 |
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); |