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