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