1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "hw/sysbus.h"
27#include "hw/register-dep.h"
28#include "qemu/bitops.h"
29#include "qapi/qmp/qerror.h"
30#include "qemu/log.h"
31
32#ifndef XILINX_LPD_SLCR_SECURE_ERR_DEBUG
33#define XILINX_LPD_SLCR_SECURE_ERR_DEBUG 0
34#endif
35
36#define TYPE_XILINX_LPD_SLCR_SECURE "xlnx.lpd-slcr-secure"
37
38#define XILINX_LPD_SLCR_SECURE(obj) \
39 OBJECT_CHECK(LPDSLCRSecure, (obj), TYPE_XILINX_LPD_SLCR_SECURE)
40
41DEP_REG32(CTRL, 0x4)
42 DEP_FIELD(CTRL, SLVERR_ENABLE, 1, 0)
43DEP_REG32(ISR, 0x8)
44 DEP_FIELD(ISR, ADDR_DECODE_ERR, 1, 0)
45DEP_REG32(IMR, 0xc)
46 DEP_FIELD(IMR, ADDR_DECODE_ERR, 1, 0)
47DEP_REG32(IER, 0x10)
48 DEP_FIELD(IER, ADDR_DECODE_ERR, 1, 0)
49DEP_REG32(IDR, 0x14)
50 DEP_FIELD(IDR, ADDR_DECODE_ERR, 1, 0)
51DEP_REG32(ITR, 0x18)
52 DEP_FIELD(ITR, ADDR_DECODE_ERR, 1, 0)
53DEP_REG32(SLCR_RPU, 0x20)
54 DEP_FIELD(SLCR_RPU, TZ_R5_0, 1, 0)
55 DEP_FIELD(SLCR_RPU, TZ_R5_1, 1, 1)
56DEP_REG32(SLCR_ADMA, 0x24)
57 DEP_FIELD(SLCR_RPU, TZ, 1, 0)
58DEP_REG32(SAFETY_CHK, 0x30)
59DEP_REG32(SLCR_USB, 0x34)
60 DEP_FIELD(SLCR_USB, TZ_USB3_0, 1, 0)
61 DEP_FIELD(SLCR_USB, TZ_USB3_1, 1, 1)
62
63#define R_MAX (R_SLCR_USB + 1)
64
65typedef struct LPDSLCRSecure {
66 SysBusDevice parent_obj;
67 MemoryRegion iomem;
68 qemu_irq irq_isr;
69
70 uint32_t regs[R_MAX];
71 DepRegisterInfo regs_info[R_MAX];
72} LPDSLCRSecure;
73
74static void isr_update_irq(LPDSLCRSecure *s)
75{
76 bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
77 qemu_set_irq(s->irq_isr, pending);
78}
79
80static void isr_postw(DepRegisterInfo *reg, uint64_t val64)
81{
82 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
83 isr_update_irq(s);
84}
85
86static uint64_t ier_prew(DepRegisterInfo *reg, uint64_t val64)
87{
88 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
89 uint32_t val = val64;
90
91 s->regs[R_IMR] &= ~val;
92 isr_update_irq(s);
93 return 0;
94}
95
96static uint64_t idr_prew(DepRegisterInfo *reg, uint64_t val64)
97{
98 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
99 uint32_t val = val64;
100
101 s->regs[R_IMR] |= val;
102 isr_update_irq(s);
103 return 0;
104}
105
106static uint64_t itr_prew(DepRegisterInfo *reg, uint64_t val64)
107{
108 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
109 uint32_t val = val64;
110
111 s->regs[R_ISR] |= val;
112 isr_update_irq(s);
113 return 0;
114}
115
116static DepRegisterAccessInfo lpd_slcr_secure_regs_info[] = {
117 { .name = "CTRL", .decode.addr = A_CTRL,
118 },{ .name = "ISR", .decode.addr = A_ISR,
119 .w1c = 0x1,
120 .post_write = isr_postw,
121 },{ .name = "IMR", .decode.addr = A_IMR,
122 .reset = 0x1,
123 .ro = 0x1,
124 },{ .name = "IER", .decode.addr = A_IER,
125 .pre_write = ier_prew,
126 },{ .name = "IDR", .decode.addr = A_IDR,
127 .pre_write = idr_prew,
128 },{ .name = "ITR", .decode.addr = A_ITR,
129 .pre_write = itr_prew,
130 },{ .name = "SLCR_RPU", .decode.addr = A_SLCR_RPU,
131 },{ .name = "SLCR_ADMA", .decode.addr = A_SLCR_ADMA,
132 },{ .name = "SAFETY_CHK", .decode.addr = A_SAFETY_CHK,
133 },{ .name = "SLCR_USB", .decode.addr = A_SLCR_USB,
134 }
135};
136
137static void lpd_slcr_secure_reset(DeviceState *dev)
138{
139 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(dev);
140 unsigned int i;
141
142 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
143 dep_register_reset(&s->regs_info[i]);
144 }
145
146 isr_update_irq(s);
147}
148
149static uint64_t lpd_slcr_secure_read(void *opaque, hwaddr addr, unsigned size)
150{
151 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(opaque);
152 DepRegisterInfo *r = &s->regs_info[addr / 4];
153
154 if (!r->data) {
155 qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
156 object_get_canonical_path(OBJECT(s)),
157 addr);
158 return 0;
159 }
160 return dep_register_read(r);
161}
162
163static void lpd_slcr_secure_write(void *opaque, hwaddr addr, uint64_t value,
164 unsigned size)
165{
166 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(opaque);
167 DepRegisterInfo *r = &s->regs_info[addr / 4];
168
169 if (!r->data) {
170 qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
171 object_get_canonical_path(OBJECT(s)),
172 addr, value);
173 return;
174 }
175 dep_register_write(r, value, ~0);
176}
177
178static const MemoryRegionOps lpd_slcr_secure_ops = {
179 .read = lpd_slcr_secure_read,
180 .write = lpd_slcr_secure_write,
181 .endianness = DEVICE_LITTLE_ENDIAN,
182 .valid = {
183 .min_access_size = 4,
184 .max_access_size = 4,
185 },
186};
187
188static void lpd_slcr_secure_realize(DeviceState *dev, Error **errp)
189{
190 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(dev);
191 const char *prefix = object_get_canonical_path(OBJECT(dev));
192 unsigned int i;
193
194 for (i = 0; i < ARRAY_SIZE(lpd_slcr_secure_regs_info); ++i) {
195 DepRegisterInfo *r =
196 &s->regs_info[lpd_slcr_secure_regs_info[i].decode.addr / 4];
197
198 *r = (DepRegisterInfo) {
199 .data = (uint8_t *)&s->regs[
200 lpd_slcr_secure_regs_info[i].decode.addr / 4],
201 .data_size = sizeof(uint32_t),
202 .access = &lpd_slcr_secure_regs_info[i],
203 .debug = XILINX_LPD_SLCR_SECURE_ERR_DEBUG,
204 .prefix = prefix,
205 .opaque = s,
206 };
207 }
208}
209
210static void lpd_slcr_secure_init(Object *obj)
211{
212 LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(obj);
213 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
214
215 memory_region_init_io(&s->iomem, obj, &lpd_slcr_secure_ops, s,
216 TYPE_XILINX_LPD_SLCR_SECURE, R_MAX * 4);
217 sysbus_init_mmio(sbd, &s->iomem);
218 sysbus_init_irq(sbd, &s->irq_isr);
219}
220
221static const VMStateDescription vmstate_lpd_slcr_secure = {
222 .name = TYPE_XILINX_LPD_SLCR_SECURE,
223 .version_id = 1,
224 .minimum_version_id = 1,
225 .minimum_version_id_old = 1,
226 .fields = (VMStateField[]) {
227 VMSTATE_UINT32_ARRAY(regs, LPDSLCRSecure, R_MAX),
228 VMSTATE_END_OF_LIST(),
229 }
230};
231
232static void lpd_slcr_secure_class_init(ObjectClass *klass, void *data)
233{
234 DeviceClass *dc = DEVICE_CLASS(klass);
235
236 dc->reset = lpd_slcr_secure_reset;
237 dc->realize = lpd_slcr_secure_realize;
238 dc->vmsd = &vmstate_lpd_slcr_secure;
239}
240
241static const TypeInfo lpd_slcr_secure_info = {
242 .name = TYPE_XILINX_LPD_SLCR_SECURE,
243 .parent = TYPE_SYS_BUS_DEVICE,
244 .instance_size = sizeof(LPDSLCRSecure),
245 .class_init = lpd_slcr_secure_class_init,
246 .instance_init = lpd_slcr_secure_init,
247};
248
249static void lpd_slcr_secure_register_types(void)
250{
251 type_register_static(&lpd_slcr_secure_info);
252}
253
254type_init(lpd_slcr_secure_register_types)
255