]>
Commit | Line | Data |
---|---|---|
067e68e7 AS |
1 | /* |
2 | * Copyright (c) 2018, Impinj, Inc. | |
3 | * | |
4 | * i.MX2 Watchdog IP block | |
5 | * | |
6 | * Author: Andrey Smirnov <[email protected]> | |
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" | |
0b8fa32f | 14 | #include "qemu/module.h" |
067e68e7 AS |
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 && | |
0e7bb14b | 32 | (~value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) { |
067e68e7 AS |
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) |