]>
Commit | Line | Data |
---|---|---|
0a7bc1c0 AS |
1 | /* |
2 | * IMX7 Secure Non-Volatile Storage | |
3 | * | |
4 | * Copyright (c) 2018, Impinj, Inc. | |
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 | * Bare minimum emulation code needed to support being able to shut | |
12 | * down linux guest gracefully. | |
13 | */ | |
14 | ||
15 | #include "qemu/osdep.h" | |
16 | #include "hw/misc/imx7_snvs.h" | |
17 | #include "qemu/log.h" | |
0b8fa32f | 18 | #include "qemu/module.h" |
54d31236 | 19 | #include "sysemu/runstate.h" |
0a7bc1c0 AS |
20 | |
21 | static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size) | |
22 | { | |
23 | return 0; | |
24 | } | |
25 | ||
26 | static void imx7_snvs_write(void *opaque, hwaddr offset, | |
27 | uint64_t v, unsigned size) | |
28 | { | |
29 | const uint32_t value = v; | |
30 | const uint32_t mask = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN; | |
31 | ||
32 | if (offset == SNVS_LPCR && ((value & mask) == mask)) { | |
33 | qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); | |
34 | } | |
35 | } | |
36 | ||
37 | static const struct MemoryRegionOps imx7_snvs_ops = { | |
38 | .read = imx7_snvs_read, | |
39 | .write = imx7_snvs_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 real | |
45 | * device but in practice there is no reason for a guest to access | |
46 | * this device unaligned. | |
47 | */ | |
48 | .min_access_size = 4, | |
49 | .max_access_size = 4, | |
50 | .unaligned = false, | |
51 | }, | |
52 | }; | |
53 | ||
54 | static void imx7_snvs_init(Object *obj) | |
55 | { | |
56 | SysBusDevice *sd = SYS_BUS_DEVICE(obj); | |
57 | IMX7SNVSState *s = IMX7_SNVS(obj); | |
58 | ||
59 | memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s, | |
60 | TYPE_IMX7_SNVS, 0x1000); | |
61 | ||
62 | sysbus_init_mmio(sd, &s->mmio); | |
63 | } | |
64 | ||
65 | static void imx7_snvs_class_init(ObjectClass *klass, void *data) | |
66 | { | |
67 | DeviceClass *dc = DEVICE_CLASS(klass); | |
68 | ||
69 | dc->desc = "i.MX7 Secure Non-Volatile Storage Module"; | |
70 | } | |
71 | ||
72 | static const TypeInfo imx7_snvs_info = { | |
73 | .name = TYPE_IMX7_SNVS, | |
74 | .parent = TYPE_SYS_BUS_DEVICE, | |
75 | .instance_size = sizeof(IMX7SNVSState), | |
76 | .instance_init = imx7_snvs_init, | |
77 | .class_init = imx7_snvs_class_init, | |
78 | }; | |
79 | ||
80 | static void imx7_snvs_register_type(void) | |
81 | { | |
82 | type_register_static(&imx7_snvs_info); | |
83 | } | |
84 | type_init(imx7_snvs_register_type) |