1 | /* |
2 | * IMX7 Secure Non-Volatile Storage |
3 | * |
4 | * Copyright (c) 2018, Impinj, Inc. |
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 | * 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" |
18 | #include "qemu/module.h" |
19 | #include "sysemu/runstate.h" |
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) |
85 | |