1 /* 2 * Copyright (c) 2018, Impinj, Inc. 3 * 4 * i.MX2 Watchdog IP block 5 * 6 * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 7 * 8 * This work is licensed under the terms of the GNU GPL, version 2 or later. 9 * See the COPYING file in the top-level directory. 10 */ 11 12 #include "qemu/osdep.h" 13 #include "qemu/bitops.h" 14 #include "qemu/module.h" 15 #include "sysemu/watchdog.h" 16 17 #include "hw/misc/imx2_wdt.h" 18 19 #define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */ 20 #define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */ 21 22 static uint64_t imx2_wdt_read(void *opaque, hwaddr addr, 23 unsigned int size) 24 { 25 return 0; 26 } 27 28 static void imx2_wdt_write(void *opaque, hwaddr addr, 29 uint64_t value, unsigned int size) 30 { 31 if (addr == IMX2_WDT_WCR && 32 (~value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) { 33 watchdog_perform_action(); 34 } 35 } 36 37 static const MemoryRegionOps imx2_wdt_ops = { 38 .read = imx2_wdt_read, 39 .write = imx2_wdt_write, 40 .endianness = DEVICE_NATIVE_ENDIAN, 41 .impl = { 42 /* 43 * Our device would not work correctly if the guest was doing 44 * unaligned access. This might not be a limitation on the 45 * real device but in practice there is no reason for a guest 46 * to access this device unaligned. 47 */ 48 .min_access_size = 4, 49 .max_access_size = 4, 50 .unaligned = false, 51 }, 52 }; 53 54 static void imx2_wdt_realize(DeviceState *dev, Error **errp) 55 { 56 IMX2WdtState *s = IMX2_WDT(dev); 57 58 memory_region_init_io(&s->mmio, OBJECT(dev), 59 &imx2_wdt_ops, s, 60 TYPE_IMX2_WDT".mmio", 61 IMX2_WDT_REG_NUM * sizeof(uint16_t)); 62 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); 63 } 64 65 static void imx2_wdt_class_init(ObjectClass *klass, void *data) 66 { 67 DeviceClass *dc = DEVICE_CLASS(klass); 68 69 dc->realize = imx2_wdt_realize; 70 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 71 } 72 73 static const TypeInfo imx2_wdt_info = { 74 .name = TYPE_IMX2_WDT, 75 .parent = TYPE_SYS_BUS_DEVICE, 76 .instance_size = sizeof(IMX2WdtState), 77 .class_init = imx2_wdt_class_init, 78 }; 79 80 static WatchdogTimerModel model = { 81 .wdt_name = "imx2-watchdog", 82 .wdt_description = "i.MX2 Watchdog", 83 }; 84 85 static void imx2_wdt_register_type(void) 86 { 87 watchdog_add_model(&model); 88 type_register_static(&imx2_wdt_info); 89 } 90 type_init(imx2_wdt_register_type) 91