2 * Generic watchdog device model for SBSA
4 * The watchdog device has been implemented as revision 1 variant of
5 * the ARM SBSA specification v6.0
6 * (https://developer.arm.com/documentation/den0029/d?lang=en)
8 * Copyright Linaro.org 2020
11 * Shashi Mallela <shashi.mallela@linaro.org>
13 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
14 * option) any later version. See the COPYING file in the top-level directory.
18 #include "qemu/osdep.h"
19 #include "sysemu/reset.h"
20 #include "sysemu/watchdog.h"
21 #include "hw/watchdog/sbsa_gwdt.h"
22 #include "qemu/timer.h"
23 #include "migration/vmstate.h"
25 #include "qemu/module.h"
27 static const VMStateDescription vmstate_sbsa_gwdt
= {
30 .minimum_version_id
= 1,
31 .fields
= (const VMStateField
[]) {
32 VMSTATE_TIMER_PTR(timer
, SBSA_GWDTState
),
33 VMSTATE_UINT32(wcs
, SBSA_GWDTState
),
34 VMSTATE_UINT32(worl
, SBSA_GWDTState
),
35 VMSTATE_UINT32(woru
, SBSA_GWDTState
),
36 VMSTATE_UINT32(wcvl
, SBSA_GWDTState
),
37 VMSTATE_UINT32(wcvu
, SBSA_GWDTState
),
42 typedef enum WdtRefreshType
{
47 static uint64_t sbsa_gwdt_rread(void *opaque
, hwaddr addr
, unsigned int size
)
49 SBSA_GWDTState
*s
= SBSA_GWDT(opaque
);
54 /* watch refresh read has no effect and returns 0 */
57 case SBSA_GWDT_W_IIDR
:
61 qemu_log_mask(LOG_GUEST_ERROR
, "bad address in refresh frame read :"
62 " 0x%x\n", (int)addr
);
67 static uint64_t sbsa_gwdt_read(void *opaque
, hwaddr addr
, unsigned int size
)
69 SBSA_GWDTState
*s
= SBSA_GWDT(opaque
);
88 case SBSA_GWDT_W_IIDR
:
92 qemu_log_mask(LOG_GUEST_ERROR
, "bad address in control frame read :"
93 " 0x%x\n", (int)addr
);
98 static void sbsa_gwdt_update_timer(SBSA_GWDTState
*s
, WdtRefreshType rtype
)
100 uint64_t timeout
= 0;
104 if (s
->wcs
& SBSA_GWDT_WCS_EN
) {
106 * Extract the upper 16 bits from woru & 32 bits from worl
107 * registers to construct the 48 bit offset value
112 timeout
= muldiv64(timeout
, NANOSECONDS_PER_SECOND
, SBSA_TIMER_FREQ
);
113 timeout
+= qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
);
115 if ((rtype
== EXPLICIT_REFRESH
) || ((rtype
== TIMEOUT_REFRESH
) &&
116 (!(s
->wcs
& SBSA_GWDT_WCS_WS0
)))) {
117 /* store the current timeout value into compare registers */
118 s
->wcvu
= timeout
>> 32;
121 timer_mod(s
->timer
, timeout
);
125 static void sbsa_gwdt_rwrite(void *opaque
, hwaddr offset
, uint64_t data
,
127 SBSA_GWDTState
*s
= SBSA_GWDT(opaque
);
129 if (offset
== SBSA_GWDT_WRR
) {
130 s
->wcs
&= ~(SBSA_GWDT_WCS_WS0
| SBSA_GWDT_WCS_WS1
);
132 sbsa_gwdt_update_timer(s
, EXPLICIT_REFRESH
);
134 qemu_log_mask(LOG_GUEST_ERROR
, "bad address in refresh frame write :"
135 " 0x%x\n", (int)offset
);
139 static void sbsa_gwdt_write(void *opaque
, hwaddr offset
, uint64_t data
,
141 SBSA_GWDTState
*s
= SBSA_GWDT(opaque
);
145 s
->wcs
= data
& SBSA_GWDT_WCS_EN
;
146 qemu_set_irq(s
->irq
, 0);
147 sbsa_gwdt_update_timer(s
, EXPLICIT_REFRESH
);
152 s
->wcs
&= ~(SBSA_GWDT_WCS_WS0
| SBSA_GWDT_WCS_WS1
);
153 qemu_set_irq(s
->irq
, 0);
154 sbsa_gwdt_update_timer(s
, EXPLICIT_REFRESH
);
158 s
->woru
= data
& SBSA_GWDT_WOR_MASK
;
159 s
->wcs
&= ~(SBSA_GWDT_WCS_WS0
| SBSA_GWDT_WCS_WS1
);
160 qemu_set_irq(s
->irq
, 0);
161 sbsa_gwdt_update_timer(s
, EXPLICIT_REFRESH
);
173 qemu_log_mask(LOG_GUEST_ERROR
, "bad address in control frame write :"
174 " 0x%x\n", (int)offset
);
179 static void wdt_sbsa_gwdt_reset(DeviceState
*dev
)
181 SBSA_GWDTState
*s
= SBSA_GWDT(dev
);
190 s
->id
= SBSA_GWDT_ID
;
193 static void sbsa_gwdt_timer_sysinterrupt(void *opaque
)
195 SBSA_GWDTState
*s
= SBSA_GWDT(opaque
);
197 if (!(s
->wcs
& SBSA_GWDT_WCS_WS0
)) {
198 s
->wcs
|= SBSA_GWDT_WCS_WS0
;
199 sbsa_gwdt_update_timer(s
, TIMEOUT_REFRESH
);
200 qemu_set_irq(s
->irq
, 1);
202 s
->wcs
|= SBSA_GWDT_WCS_WS1
;
203 qemu_log_mask(CPU_LOG_RESET
, "Watchdog timer expired.\n");
205 * Reset the watchdog only if the guest gets notified about
206 * expiry. watchdog_perform_action() may temporarily relinquish
207 * the BQL; reset before triggering the action to avoid races with
208 * sbsa_gwdt instructions.
210 switch (get_watchdog_action()) {
211 case WATCHDOG_ACTION_DEBUG
:
212 case WATCHDOG_ACTION_NONE
:
213 case WATCHDOG_ACTION_PAUSE
:
216 wdt_sbsa_gwdt_reset(DEVICE(s
));
218 watchdog_perform_action();
222 static const MemoryRegionOps sbsa_gwdt_rops
= {
223 .read
= sbsa_gwdt_rread
,
224 .write
= sbsa_gwdt_rwrite
,
225 .endianness
= DEVICE_LITTLE_ENDIAN
,
226 .valid
.min_access_size
= 4,
227 .valid
.max_access_size
= 4,
228 .valid
.unaligned
= false,
231 static const MemoryRegionOps sbsa_gwdt_ops
= {
232 .read
= sbsa_gwdt_read
,
233 .write
= sbsa_gwdt_write
,
234 .endianness
= DEVICE_LITTLE_ENDIAN
,
235 .valid
.min_access_size
= 4,
236 .valid
.max_access_size
= 4,
237 .valid
.unaligned
= false,
240 static void wdt_sbsa_gwdt_realize(DeviceState
*dev
, Error
**errp
)
242 SBSA_GWDTState
*s
= SBSA_GWDT(dev
);
243 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
245 memory_region_init_io(&s
->rmmio
, OBJECT(dev
),
248 SBSA_GWDT_RMMIO_SIZE
);
250 memory_region_init_io(&s
->cmmio
, OBJECT(dev
),
253 SBSA_GWDT_CMMIO_SIZE
);
255 sysbus_init_mmio(sbd
, &s
->rmmio
);
256 sysbus_init_mmio(sbd
, &s
->cmmio
);
258 sysbus_init_irq(sbd
, &s
->irq
);
260 s
->timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
, sbsa_gwdt_timer_sysinterrupt
,
264 static void wdt_sbsa_gwdt_class_init(ObjectClass
*klass
, void *data
)
266 DeviceClass
*dc
= DEVICE_CLASS(klass
);
268 dc
->realize
= wdt_sbsa_gwdt_realize
;
269 dc
->reset
= wdt_sbsa_gwdt_reset
;
270 dc
->hotpluggable
= false;
271 set_bit(DEVICE_CATEGORY_WATCHDOG
, dc
->categories
);
272 dc
->vmsd
= &vmstate_sbsa_gwdt
;
273 dc
->desc
= "SBSA-compliant generic watchdog device";
276 static const TypeInfo wdt_sbsa_gwdt_info
= {
277 .class_init
= wdt_sbsa_gwdt_class_init
,
278 .parent
= TYPE_SYS_BUS_DEVICE
,
279 .name
= TYPE_WDT_SBSA
,
280 .instance_size
= sizeof(SBSA_GWDTState
),
283 static void wdt_sbsa_gwdt_register_types(void)
285 type_register_static(&wdt_sbsa_gwdt_info
);
288 type_init(wdt_sbsa_gwdt_register_types
)