master
c 782 lines 22.8 KB
Raw
1 /*
2 * Arm IoT Kit security controller
3 *
4 * Copyright (c) 2018 Linaro Limited
5 * Written by Peter Maydell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 or
9 * (at your option) any later version.
10 */
11
12 #include "qemu/osdep.h"
13 #include "qemu/log.h"
14 #include "qemu/module.h"
15 #include "qapi/error.h"
16 #include "trace.h"
17 #include "hw/core/sysbus.h"
18 #include "migration/vmstate.h"
19 #include "hw/core/registerfields.h"
20 #include "hw/core/irq.h"
21 #include "hw/misc/iotkit-secctl.h"
22 #include "hw/arm/armsse-version.h"
23 #include "hw/core/qdev-properties.h"
24
25 /* Registers in the secure privilege control block */
26 REG32(SECRESPCFG, 0x10)
27 REG32(NSCCFG, 0x14)
28 REG32(SECMPCINTSTATUS, 0x1c)
29 REG32(SECPPCINTSTAT, 0x20)
30 REG32(SECPPCINTCLR, 0x24)
31 REG32(SECPPCINTEN, 0x28)
32 REG32(SECMSCINTSTAT, 0x30)
33 REG32(SECMSCINTCLR, 0x34)
34 REG32(SECMSCINTEN, 0x38)
35 REG32(BRGINTSTAT, 0x40)
36 REG32(BRGINTCLR, 0x44)
37 REG32(BRGINTEN, 0x48)
38 REG32(AHBNSPPC0, 0x50)
39 REG32(AHBNSPPCEXP0, 0x60)
40 REG32(AHBNSPPCEXP1, 0x64)
41 REG32(AHBNSPPCEXP2, 0x68)
42 REG32(AHBNSPPCEXP3, 0x6c)
43 REG32(APBNSPPC0, 0x70)
44 REG32(APBNSPPC1, 0x74)
45 REG32(APBNSPPCEXP0, 0x80)
46 REG32(APBNSPPCEXP1, 0x84)
47 REG32(APBNSPPCEXP2, 0x88)
48 REG32(APBNSPPCEXP3, 0x8c)
49 REG32(AHBSPPPC0, 0x90)
50 REG32(AHBSPPPCEXP0, 0xa0)
51 REG32(AHBSPPPCEXP1, 0xa4)
52 REG32(AHBSPPPCEXP2, 0xa8)
53 REG32(AHBSPPPCEXP3, 0xac)
54 REG32(APBSPPPC0, 0xb0)
55 REG32(APBSPPPC1, 0xb4)
56 REG32(APBSPPPCEXP0, 0xc0)
57 REG32(APBSPPPCEXP1, 0xc4)
58 REG32(APBSPPPCEXP2, 0xc8)
59 REG32(APBSPPPCEXP3, 0xcc)
60 REG32(NSMSCEXP, 0xd0)
61 REG32(PID4, 0xfd0)
62 REG32(PID5, 0xfd4)
63 REG32(PID6, 0xfd8)
64 REG32(PID7, 0xfdc)
65 REG32(PID0, 0xfe0)
66 REG32(PID1, 0xfe4)
67 REG32(PID2, 0xfe8)
68 REG32(PID3, 0xfec)
69 REG32(CID0, 0xff0)
70 REG32(CID1, 0xff4)
71 REG32(CID2, 0xff8)
72 REG32(CID3, 0xffc)
73
74 /* Registers in the non-secure privilege control block */
75 REG32(AHBNSPPPC0, 0x90)
76 REG32(AHBNSPPPCEXP0, 0xa0)
77 REG32(AHBNSPPPCEXP1, 0xa4)
78 REG32(AHBNSPPPCEXP2, 0xa8)
79 REG32(AHBNSPPPCEXP3, 0xac)
80 REG32(APBNSPPPC0, 0xb0)
81 REG32(APBNSPPPC1, 0xb4)
82 REG32(APBNSPPPCEXP0, 0xc0)
83 REG32(APBNSPPPCEXP1, 0xc4)
84 REG32(APBNSPPPCEXP2, 0xc8)
85 REG32(APBNSPPPCEXP3, 0xcc)
86 /* PID and CID registers are also present in the NS block */
87
88 static const uint8_t iotkit_secctl_s_idregs[] = {
89 0x04, 0x00, 0x00, 0x00,
90 0x52, 0xb8, 0x0b, 0x00,
91 0x0d, 0xf0, 0x05, 0xb1,
92 };
93
94 static const uint8_t iotkit_secctl_ns_idregs[] = {
95 0x04, 0x00, 0x00, 0x00,
96 0x53, 0xb8, 0x0b, 0x00,
97 0x0d, 0xf0, 0x05, 0xb1,
98 };
99
100 static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
101 0x04, 0x00, 0x00, 0x00,
102 0x52, 0xb8, 0x2b, 0x00,
103 0x0d, 0xf0, 0x05, 0xb1,
104 };
105
106 static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
107 0x04, 0x00, 0x00, 0x00,
108 0x53, 0xb8, 0x2b, 0x00,
109 0x0d, 0xf0, 0x05, 0xb1,
110 };
111
112 static const uint8_t iotkit_secctl_s_sse310_idregs[] = {
113 0x04, 0x00, 0x00, 0x00,
114 0x52, 0xb8, 0x3b, 0x00,
115 0x0d, 0xf0, 0x05, 0xb1,
116 };
117
118 static const uint8_t iotkit_secctl_ns_sse310_idregs[] = {
119 0x04, 0x00, 0x00, 0x00,
120 0x53, 0xb8, 0x3b, 0x00,
121 0x0d, 0xf0, 0x05, 0xb1,
122 };
123
124
125 /* The register sets for the various PPCs (AHB internal, APB internal,
126 * AHB expansion, APB expansion) are all set up so that they are
127 * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
128 * 0, 1, 2, 3 of that type, so we can convert a register address offset
129 * into an index into a PPC array easily.
130 */
131 static inline int offset_to_ppc_idx(uint32_t offset)
132 {
133 return extract32(offset, 2, 2);
134 }
135
136 typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
137
138 static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
139 {
140 int i;
141
142 for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
143 fn(&s->apb[i]);
144 }
145 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
146 fn(&s->apbexp[i]);
147 }
148 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
149 fn(&s->ahbexp[i]);
150 }
151 }
152
153 static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
154 uint64_t *pdata,
155 unsigned size, MemTxAttrs attrs)
156 {
157 uint64_t r;
158 uint32_t offset = addr & ~0x3;
159 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
160
161 switch (offset) {
162 case A_AHBNSPPC0:
163 case A_AHBSPPPC0:
164 r = 0;
165 break;
166 case A_SECRESPCFG:
167 r = s->secrespcfg;
168 break;
169 case A_NSCCFG:
170 r = s->nsccfg;
171 break;
172 case A_SECMPCINTSTATUS:
173 r = s->mpcintstatus;
174 break;
175 case A_SECPPCINTSTAT:
176 r = s->secppcintstat;
177 break;
178 case A_SECPPCINTEN:
179 r = s->secppcinten;
180 break;
181 case A_BRGINTSTAT:
182 /* QEMU's bus fabric can never report errors as it doesn't buffer
183 * writes, so we never report bridge interrupts.
184 */
185 r = 0;
186 break;
187 case A_BRGINTEN:
188 r = s->brginten;
189 break;
190 case A_AHBNSPPCEXP0 ... A_AHBNSPPCEXP3:
191 r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
192 break;
193 case A_APBNSPPC0:
194 case A_APBNSPPC1:
195 r = s->apb[offset_to_ppc_idx(offset)].ns;
196 break;
197 case A_APBNSPPCEXP0 ... A_APBNSPPCEXP3:
198 r = s->apbexp[offset_to_ppc_idx(offset)].ns;
199 break;
200 case A_AHBSPPPCEXP0 ... A_AHBSPPPCEXP3:
201 r = s->ahbexp[offset_to_ppc_idx(offset)].sp;
202 break;
203 case A_APBSPPPC0:
204 case A_APBSPPPC1:
205 r = s->apb[offset_to_ppc_idx(offset)].sp;
206 break;
207 case A_APBSPPPCEXP0 ... A_APBSPPPCEXP3:
208 r = s->apbexp[offset_to_ppc_idx(offset)].sp;
209 break;
210 case A_SECMSCINTSTAT:
211 r = s->secmscintstat;
212 break;
213 case A_SECMSCINTEN:
214 r = s->secmscinten;
215 break;
216 case A_NSMSCEXP:
217 r = s->nsmscexp;
218 break;
219 case A_PID4 ... A_CID3:
220 switch (s->sse_version) {
221 case ARMSSE_SSE300:
222 r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
223 break;
224 case ARMSSE_SSE310:
225 r = iotkit_secctl_s_sse310_idregs[(offset - A_PID4) / 4];
226 break;
227 default:
228 r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
229 break;
230 }
231 break;
232 case A_SECPPCINTCLR:
233 case A_SECMSCINTCLR:
234 case A_BRGINTCLR:
235 qemu_log_mask(LOG_GUEST_ERROR,
236 "IotKit SecCtl S block read: write-only offset 0x%x\n",
237 offset);
238 r = 0;
239 break;
240 default:
241 qemu_log_mask(LOG_GUEST_ERROR,
242 "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
243 r = 0;
244 break;
245 }
246
247 if (size != 4) {
248 /* None of our registers are access-sensitive, so just pull the right
249 * byte out of the word read result.
250 */
251 r = extract32(r, (addr & 3) * 8, size * 8);
252 }
253
254 trace_iotkit_secctl_s_read(offset, r, size);
255 *pdata = r;
256 return MEMTX_OK;
257 }
258
259 static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
260 {
261 int i;
262
263 for (i = 0; i < ppc->numports; i++) {
264 bool v;
265
266 if (extract32(ppc->ns, i, 1)) {
267 v = extract32(ppc->nsp, i, 1);
268 } else {
269 v = extract32(ppc->sp, i, 1);
270 }
271 qemu_set_irq(ppc->ap[i], v);
272 }
273 }
274
275 static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
276 {
277 int i;
278
279 ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
280 for (i = 0; i < ppc->numports; i++) {
281 qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
282 }
283 iotkit_secctl_update_ppc_ap(ppc);
284 }
285
286 static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
287 {
288 ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
289 iotkit_secctl_update_ppc_ap(ppc);
290 }
291
292 static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
293 {
294 ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
295 iotkit_secctl_update_ppc_ap(ppc);
296 }
297
298 static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
299 {
300 uint32_t value = ppc->parent->secppcintstat;
301
302 qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
303 }
304
305 static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
306 {
307 uint32_t value = ppc->parent->secppcinten;
308
309 qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
310 }
311
312 static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
313 {
314 int i;
315
316 for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
317 qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
318 }
319 }
320
321 static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
322 {
323 /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
324 bool level = s->secmscintstat & s->secmscinten;
325
326 qemu_set_irq(s->msc_irq, level);
327 }
328
329 static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
330 uint64_t value,
331 unsigned size, MemTxAttrs attrs)
332 {
333 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
334 uint32_t offset = addr;
335 IoTKitSecCtlPPC *ppc;
336
337 trace_iotkit_secctl_s_write(offset, value, size);
338
339 if (size != 4) {
340 /* Byte and halfword writes are ignored */
341 qemu_log_mask(LOG_GUEST_ERROR,
342 "IotKit SecCtl S block write: bad size, ignored\n");
343 return MEMTX_OK;
344 }
345
346 switch (offset) {
347 case A_NSCCFG:
348 s->nsccfg = value & 3;
349 qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
350 break;
351 case A_SECRESPCFG:
352 value &= 1;
353 s->secrespcfg = value;
354 qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
355 break;
356 case A_SECPPCINTCLR:
357 s->secppcintstat &= ~(value & 0x00f000f3);
358 foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
359 break;
360 case A_SECPPCINTEN:
361 s->secppcinten = value & 0x00f000f3;
362 foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
363 break;
364 case A_BRGINTCLR:
365 break;
366 case A_BRGINTEN:
367 s->brginten = value & 0xffff0000;
368 break;
369 case A_AHBNSPPCEXP0 ... A_AHBNSPPCEXP3:
370 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
371 iotkit_secctl_ppc_ns_write(ppc, value);
372 break;
373 case A_APBNSPPC0:
374 case A_APBNSPPC1:
375 ppc = &s->apb[offset_to_ppc_idx(offset)];
376 iotkit_secctl_ppc_ns_write(ppc, value);
377 break;
378 case A_APBNSPPCEXP0 ... A_APBNSPPCEXP3:
379 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
380 iotkit_secctl_ppc_ns_write(ppc, value);
381 break;
382 case A_AHBSPPPCEXP0 ... A_AHBSPPPCEXP3:
383 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
384 iotkit_secctl_ppc_sp_write(ppc, value);
385 break;
386 case A_APBSPPPC0:
387 case A_APBSPPPC1:
388 ppc = &s->apb[offset_to_ppc_idx(offset)];
389 iotkit_secctl_ppc_sp_write(ppc, value);
390 break;
391 case A_APBSPPPCEXP0 ... A_APBSPPPCEXP3:
392 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
393 iotkit_secctl_ppc_sp_write(ppc, value);
394 break;
395 case A_SECMSCINTCLR:
396 iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
397 break;
398 case A_SECMSCINTEN:
399 s->secmscinten = value;
400 iotkit_secctl_update_msc_irq(s);
401 break;
402 case A_NSMSCEXP:
403 s->nsmscexp = value;
404 iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
405 break;
406 case A_SECMPCINTSTATUS:
407 case A_SECPPCINTSTAT:
408 case A_SECMSCINTSTAT:
409 case A_BRGINTSTAT:
410 case A_AHBNSPPC0:
411 case A_AHBSPPPC0:
412 case A_PID4 ... A_CID3:
413 qemu_log_mask(LOG_GUEST_ERROR,
414 "IoTKit SecCtl S block write: "
415 "read-only offset 0x%x\n", offset);
416 break;
417 default:
418 qemu_log_mask(LOG_GUEST_ERROR,
419 "IotKit SecCtl S block write: bad offset 0x%x\n",
420 offset);
421 break;
422 }
423
424 return MEMTX_OK;
425 }
426
427 static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
428 uint64_t *pdata,
429 unsigned size, MemTxAttrs attrs)
430 {
431 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
432 uint64_t r;
433 uint32_t offset = addr & ~0x3;
434
435 switch (offset) {
436 case A_AHBNSPPPC0:
437 r = 0;
438 break;
439 case A_AHBNSPPPCEXP0 ... A_AHBNSPPPCEXP3:
440 r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
441 break;
442 case A_APBNSPPPC0:
443 case A_APBNSPPPC1:
444 r = s->apb[offset_to_ppc_idx(offset)].nsp;
445 break;
446 case A_APBNSPPPCEXP0 ... A_APBNSPPPCEXP3:
447 r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
448 break;
449 case A_PID4 ... A_CID3:
450 switch (s->sse_version) {
451 case ARMSSE_SSE300:
452 r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
453 break;
454 case ARMSSE_SSE310:
455 r = iotkit_secctl_ns_sse310_idregs[(offset - A_PID4) / 4];
456 break;
457 default:
458 r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
459 break;
460 }
461 break;
462 default:
463 qemu_log_mask(LOG_GUEST_ERROR,
464 "IotKit SecCtl NS block write: bad offset 0x%x\n",
465 offset);
466 r = 0;
467 break;
468 }
469
470 if (size != 4) {
471 /* None of our registers are access-sensitive, so just pull the right
472 * byte out of the word read result.
473 */
474 r = extract32(r, (addr & 3) * 8, size * 8);
475 }
476
477 trace_iotkit_secctl_ns_read(offset, r, size);
478 *pdata = r;
479 return MEMTX_OK;
480 }
481
482 static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
483 uint64_t value,
484 unsigned size, MemTxAttrs attrs)
485 {
486 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
487 uint32_t offset = addr;
488 IoTKitSecCtlPPC *ppc;
489
490 trace_iotkit_secctl_ns_write(offset, value, size);
491
492 if (size != 4) {
493 /* Byte and halfword writes are ignored */
494 qemu_log_mask(LOG_GUEST_ERROR,
495 "IotKit SecCtl NS block write: bad size, ignored\n");
496 return MEMTX_OK;
497 }
498
499 switch (offset) {
500 case A_AHBNSPPPCEXP0 ... A_AHBNSPPPCEXP3:
501 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
502 iotkit_secctl_ppc_nsp_write(ppc, value);
503 break;
504 case A_APBNSPPPC0:
505 case A_APBNSPPPC1:
506 ppc = &s->apb[offset_to_ppc_idx(offset)];
507 iotkit_secctl_ppc_nsp_write(ppc, value);
508 break;
509 case A_APBNSPPPCEXP0 ... A_APBNSPPPCEXP3:
510 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
511 iotkit_secctl_ppc_nsp_write(ppc, value);
512 break;
513 case A_AHBNSPPPC0:
514 case A_PID4 ... A_CID3:
515 qemu_log_mask(LOG_GUEST_ERROR,
516 "IoTKit SecCtl NS block write: "
517 "read-only offset 0x%x\n", offset);
518 break;
519 default:
520 qemu_log_mask(LOG_GUEST_ERROR,
521 "IotKit SecCtl NS block write: bad offset 0x%x\n",
522 offset);
523 break;
524 }
525
526 return MEMTX_OK;
527 }
528
529 static const MemoryRegionOps iotkit_secctl_s_ops = {
530 .read_with_attrs = iotkit_secctl_s_read,
531 .write_with_attrs = iotkit_secctl_s_write,
532 .endianness = DEVICE_LITTLE_ENDIAN,
533 .valid.min_access_size = 1,
534 .valid.max_access_size = 4,
535 .impl.min_access_size = 1,
536 .impl.max_access_size = 4,
537 };
538
539 static const MemoryRegionOps iotkit_secctl_ns_ops = {
540 .read_with_attrs = iotkit_secctl_ns_read,
541 .write_with_attrs = iotkit_secctl_ns_write,
542 .endianness = DEVICE_LITTLE_ENDIAN,
543 .valid.min_access_size = 1,
544 .valid.max_access_size = 4,
545 .impl.min_access_size = 1,
546 .impl.max_access_size = 4,
547 };
548
549 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
550 {
551 ppc->ns = 0;
552 ppc->sp = 0;
553 ppc->nsp = 0;
554 }
555
556 static void iotkit_secctl_reset(DeviceState *dev)
557 {
558 IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
559
560 s->secppcintstat = 0;
561 s->secppcinten = 0;
562 s->secrespcfg = 0;
563 s->nsccfg = 0;
564 s->brginten = 0;
565
566 foreach_ppc(s, iotkit_secctl_reset_ppc);
567 }
568
569 static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
570 {
571 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
572
573 s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
574 }
575
576 static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
577 {
578 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
579
580 s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
581 }
582
583 static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
584 {
585 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
586
587 s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
588 iotkit_secctl_update_msc_irq(s);
589 }
590
591 static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
592 {
593 IoTKitSecCtlPPC *ppc = opaque;
594 IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
595 int irqbit = ppc->irq_bit_offset + n;
596
597 s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
598 }
599
600 static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
601 IoTKitSecCtlPPC *ppc,
602 const char *name,
603 int numports,
604 int irq_bit_offset)
605 {
606 char *gpioname;
607 DeviceState *dev = DEVICE(s);
608
609 ppc->numports = numports;
610 ppc->irq_bit_offset = irq_bit_offset;
611 ppc->parent = s;
612
613 gpioname = g_strdup_printf("%s_nonsec", name);
614 qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
615 g_free(gpioname);
616 gpioname = g_strdup_printf("%s_ap", name);
617 qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
618 g_free(gpioname);
619 gpioname = g_strdup_printf("%s_irq_enable", name);
620 qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
621 g_free(gpioname);
622 gpioname = g_strdup_printf("%s_irq_clear", name);
623 qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
624 g_free(gpioname);
625 gpioname = g_strdup_printf("%s_irq_status", name);
626 qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
627 ppc, gpioname, 1);
628 g_free(gpioname);
629 }
630
631 static void iotkit_secctl_init(Object *obj)
632 {
633 IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
634 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
635 DeviceState *dev = DEVICE(obj);
636 int i;
637
638 iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
639 IOTS_APB_PPC0_NUM_PORTS, 0);
640 iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
641 IOTS_APB_PPC1_NUM_PORTS, 1);
642
643 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
644 IoTKitSecCtlPPC *ppc = &s->apbexp[i];
645 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
646 iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
647 g_free(ppcname);
648 }
649 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
650 IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
651 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
652 iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
653 g_free(ppcname);
654 }
655
656 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
657 qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
658
659 qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
660 IOTS_NUM_MPC);
661 qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
662 "mpcexp_status", IOTS_NUM_EXP_MPC);
663
664 qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
665 "mscexp_status", IOTS_NUM_EXP_MSC);
666 qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
667 IOTS_NUM_EXP_MSC);
668 qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
669 IOTS_NUM_EXP_MSC);
670 qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
671
672 memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
673 s, "iotkit-secctl-s-regs", 0x1000);
674 memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
675 s, "iotkit-secctl-ns-regs", 0x1000);
676 sysbus_init_mmio(sbd, &s->s_regs);
677 sysbus_init_mmio(sbd, &s->ns_regs);
678 }
679
680 static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
681 {
682 IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
683
684 if (!armsse_version_valid(s->sse_version)) {
685 error_setg(errp, "invalid sse-version value %d", s->sse_version);
686 return;
687 }
688 }
689
690 static const VMStateDescription iotkit_secctl_ppc_vmstate = {
691 .name = "iotkit-secctl-ppc",
692 .version_id = 1,
693 .minimum_version_id = 1,
694 .fields = (const VMStateField[]) {
695 VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
696 VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
697 VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
698 VMSTATE_END_OF_LIST()
699 }
700 };
701
702 static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
703 .name = "iotkit-secctl-mpcintstatus",
704 .version_id = 1,
705 .minimum_version_id = 1,
706 .fields = (const VMStateField[]) {
707 VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
708 VMSTATE_END_OF_LIST()
709 }
710 };
711
712 static bool needed_always(void *opaque)
713 {
714 return true;
715 }
716
717 static const VMStateDescription iotkit_secctl_msc_vmstate = {
718 .name = "iotkit-secctl/msc",
719 .version_id = 1,
720 .minimum_version_id = 1,
721 .needed = needed_always,
722 .fields = (const VMStateField[]) {
723 VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
724 VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
725 VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
726 VMSTATE_END_OF_LIST()
727 }
728 };
729
730 static const VMStateDescription iotkit_secctl_vmstate = {
731 .name = "iotkit-secctl",
732 .version_id = 1,
733 .minimum_version_id = 1,
734 .fields = (const VMStateField[]) {
735 VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
736 VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
737 VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
738 VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
739 VMSTATE_UINT32(brginten, IoTKitSecCtl),
740 VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
741 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
742 VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
743 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
744 VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
745 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
746 VMSTATE_END_OF_LIST()
747 },
748 .subsections = (const VMStateDescription * const []) {
749 &iotkit_secctl_mpcintstatus_vmstate,
750 &iotkit_secctl_msc_vmstate,
751 NULL
752 },
753 };
754
755 static const Property iotkit_secctl_props[] = {
756 DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
757 };
758
759 static void iotkit_secctl_class_init(ObjectClass *klass, const void *data)
760 {
761 DeviceClass *dc = DEVICE_CLASS(klass);
762
763 dc->vmsd = &iotkit_secctl_vmstate;
764 device_class_set_legacy_reset(dc, iotkit_secctl_reset);
765 dc->realize = iotkit_secctl_realize;
766 device_class_set_props(dc, iotkit_secctl_props);
767 }
768
769 static const TypeInfo iotkit_secctl_info = {
770 .name = TYPE_IOTKIT_SECCTL,
771 .parent = TYPE_SYS_BUS_DEVICE,
772 .instance_size = sizeof(IoTKitSecCtl),
773 .instance_init = iotkit_secctl_init,
774 .class_init = iotkit_secctl_class_init,
775 };
776
777 static void iotkit_secctl_register_types(void)
778 {
779 type_register_static(&iotkit_secctl_info);
780 }
781
782 type_init(iotkit_secctl_register_types);