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"
14 #include "qapi/error.h"
16 #include "hw/sysbus.h"
17 #include "hw/registerfields.h"
18 #include "hw/misc/iotkit-secctl.h"
20 /* Registers in the secure privilege control block */
21 REG32(SECRESPCFG
, 0x10)
23 REG32(SECMPCINTSTATUS
, 0x1c)
24 REG32(SECPPCINTSTAT
, 0x20)
25 REG32(SECPPCINTCLR
, 0x24)
26 REG32(SECPPCINTEN
, 0x28)
27 REG32(SECMSCINTSTAT
, 0x30)
28 REG32(SECMSCINTCLR
, 0x34)
29 REG32(SECMSCINTEN
, 0x38)
30 REG32(BRGINTSTAT
, 0x40)
31 REG32(BRGINTCLR
, 0x44)
33 REG32(AHBNSPPC0
, 0x50)
34 REG32(AHBNSPPCEXP0
, 0x60)
35 REG32(AHBNSPPCEXP1
, 0x64)
36 REG32(AHBNSPPCEXP2
, 0x68)
37 REG32(AHBNSPPCEXP3
, 0x6c)
38 REG32(APBNSPPC0
, 0x70)
39 REG32(APBNSPPC1
, 0x74)
40 REG32(APBNSPPCEXP0
, 0x80)
41 REG32(APBNSPPCEXP1
, 0x84)
42 REG32(APBNSPPCEXP2
, 0x88)
43 REG32(APBNSPPCEXP3
, 0x8c)
44 REG32(AHBSPPPC0
, 0x90)
45 REG32(AHBSPPPCEXP0
, 0xa0)
46 REG32(AHBSPPPCEXP1
, 0xa4)
47 REG32(AHBSPPPCEXP2
, 0xa8)
48 REG32(AHBSPPPCEXP3
, 0xac)
49 REG32(APBSPPPC0
, 0xb0)
50 REG32(APBSPPPC1
, 0xb4)
51 REG32(APBSPPPCEXP0
, 0xc0)
52 REG32(APBSPPPCEXP1
, 0xc4)
53 REG32(APBSPPPCEXP2
, 0xc8)
54 REG32(APBSPPPCEXP3
, 0xcc)
69 /* Registers in the non-secure privilege control block */
70 REG32(AHBNSPPPC0
, 0x90)
71 REG32(AHBNSPPPCEXP0
, 0xa0)
72 REG32(AHBNSPPPCEXP1
, 0xa4)
73 REG32(AHBNSPPPCEXP2
, 0xa8)
74 REG32(AHBNSPPPCEXP3
, 0xac)
75 REG32(APBNSPPPC0
, 0xb0)
76 REG32(APBNSPPPC1
, 0xb4)
77 REG32(APBNSPPPCEXP0
, 0xc0)
78 REG32(APBNSPPPCEXP1
, 0xc4)
79 REG32(APBNSPPPCEXP2
, 0xc8)
80 REG32(APBNSPPPCEXP3
, 0xcc)
81 /* PID and CID registers are also present in the NS block */
83 static const uint8_t iotkit_secctl_s_idregs
[] = {
84 0x04, 0x00, 0x00, 0x00,
85 0x52, 0xb8, 0x0b, 0x00,
86 0x0d, 0xf0, 0x05, 0xb1,
89 static const uint8_t iotkit_secctl_ns_idregs
[] = {
90 0x04, 0x00, 0x00, 0x00,
91 0x53, 0xb8, 0x0b, 0x00,
92 0x0d, 0xf0, 0x05, 0xb1,
95 /* The register sets for the various PPCs (AHB internal, APB internal,
96 * AHB expansion, APB expansion) are all set up so that they are
97 * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
98 * 0, 1, 2, 3 of that type, so we can convert a register address offset
99 * into an an index into a PPC array easily.
101 static inline int offset_to_ppc_idx(uint32_t offset
)
103 return extract32(offset
, 2, 2);
106 typedef void PerPPCFunction(IoTKitSecCtlPPC
*ppc
);
108 static void foreach_ppc(IoTKitSecCtl
*s
, PerPPCFunction
*fn
)
112 for (i
= 0; i
< IOTS_NUM_APB_PPC
; i
++) {
115 for (i
= 0; i
< IOTS_NUM_APB_EXP_PPC
; i
++) {
118 for (i
= 0; i
< IOTS_NUM_AHB_EXP_PPC
; i
++) {
123 static MemTxResult
iotkit_secctl_s_read(void *opaque
, hwaddr addr
,
125 unsigned size
, MemTxAttrs attrs
)
128 uint32_t offset
= addr
& ~0x3;
129 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
139 case A_SECPPCINTSTAT
:
140 r
= s
->secppcintstat
;
149 r
= s
->ahbexp
[offset_to_ppc_idx(offset
)].ns
;
153 r
= s
->apb
[offset_to_ppc_idx(offset
)].ns
;
159 r
= s
->apbexp
[offset_to_ppc_idx(offset
)].ns
;
165 r
= s
->apbexp
[offset_to_ppc_idx(offset
)].sp
;
169 r
= s
->apb
[offset_to_ppc_idx(offset
)].sp
;
175 r
= s
->apbexp
[offset_to_ppc_idx(offset
)].sp
;
178 case A_SECMPCINTSTATUS
:
179 case A_SECMSCINTSTAT
:
184 qemu_log_mask(LOG_UNIMP
,
185 "IoTKit SecCtl S block read: "
186 "unimplemented offset 0x%x\n", offset
);
201 r
= iotkit_secctl_s_idregs
[(offset
- A_PID4
) / 4];
206 qemu_log_mask(LOG_GUEST_ERROR
,
207 "IotKit SecCtl S block read: write-only offset 0x%x\n",
212 qemu_log_mask(LOG_GUEST_ERROR
,
213 "IotKit SecCtl S block read: bad offset 0x%x\n", offset
);
219 /* None of our registers are access-sensitive, so just pull the right
220 * byte out of the word read result.
222 r
= extract32(r
, (addr
& 3) * 8, size
* 8);
225 trace_iotkit_secctl_s_read(offset
, r
, size
);
230 static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC
*ppc
)
234 for (i
= 0; i
< ppc
->numports
; i
++) {
237 if (extract32(ppc
->ns
, i
, 1)) {
238 v
= extract32(ppc
->nsp
, i
, 1);
240 v
= extract32(ppc
->sp
, i
, 1);
242 qemu_set_irq(ppc
->ap
[i
], v
);
246 static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC
*ppc
, uint32_t value
)
250 ppc
->ns
= value
& MAKE_64BIT_MASK(0, ppc
->numports
);
251 for (i
= 0; i
< ppc
->numports
; i
++) {
252 qemu_set_irq(ppc
->nonsec
[i
], extract32(ppc
->ns
, i
, 1));
254 iotkit_secctl_update_ppc_ap(ppc
);
257 static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC
*ppc
, uint32_t value
)
259 ppc
->sp
= value
& MAKE_64BIT_MASK(0, ppc
->numports
);
260 iotkit_secctl_update_ppc_ap(ppc
);
263 static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC
*ppc
, uint32_t value
)
265 ppc
->nsp
= value
& MAKE_64BIT_MASK(0, ppc
->numports
);
266 iotkit_secctl_update_ppc_ap(ppc
);
269 static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC
*ppc
)
271 uint32_t value
= ppc
->parent
->secppcintstat
;
273 qemu_set_irq(ppc
->irq_clear
, extract32(value
, ppc
->irq_bit_offset
, 1));
276 static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC
*ppc
)
278 uint32_t value
= ppc
->parent
->secppcinten
;
280 qemu_set_irq(ppc
->irq_enable
, extract32(value
, ppc
->irq_bit_offset
, 1));
283 static MemTxResult
iotkit_secctl_s_write(void *opaque
, hwaddr addr
,
285 unsigned size
, MemTxAttrs attrs
)
287 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
288 uint32_t offset
= addr
;
289 IoTKitSecCtlPPC
*ppc
;
291 trace_iotkit_secctl_s_write(offset
, value
, size
);
294 /* Byte and halfword writes are ignored */
295 qemu_log_mask(LOG_GUEST_ERROR
,
296 "IotKit SecCtl S block write: bad size, ignored\n");
303 s
->secrespcfg
= value
;
304 qemu_set_irq(s
->sec_resp_cfg
, s
->secrespcfg
);
308 foreach_ppc(s
, iotkit_secctl_ppc_update_irq_clear
);
311 s
->secppcinten
= value
& 0x00f000f3;
312 foreach_ppc(s
, iotkit_secctl_ppc_update_irq_enable
);
318 ppc
= &s
->ahbexp
[offset_to_ppc_idx(offset
)];
319 iotkit_secctl_ppc_ns_write(ppc
, value
);
323 ppc
= &s
->apb
[offset_to_ppc_idx(offset
)];
324 iotkit_secctl_ppc_ns_write(ppc
, value
);
330 ppc
= &s
->apbexp
[offset_to_ppc_idx(offset
)];
331 iotkit_secctl_ppc_ns_write(ppc
, value
);
337 ppc
= &s
->ahbexp
[offset_to_ppc_idx(offset
)];
338 iotkit_secctl_ppc_sp_write(ppc
, value
);
342 ppc
= &s
->apb
[offset_to_ppc_idx(offset
)];
343 iotkit_secctl_ppc_sp_write(ppc
, value
);
349 ppc
= &s
->apbexp
[offset_to_ppc_idx(offset
)];
350 iotkit_secctl_ppc_sp_write(ppc
, value
);
357 qemu_log_mask(LOG_UNIMP
,
358 "IoTKit SecCtl S block write: "
359 "unimplemented offset 0x%x\n", offset
);
361 case A_SECMPCINTSTATUS
:
362 case A_SECPPCINTSTAT
:
363 case A_SECMSCINTSTAT
:
380 qemu_log_mask(LOG_GUEST_ERROR
,
381 "IoTKit SecCtl S block write: "
382 "read-only offset 0x%x\n", offset
);
385 qemu_log_mask(LOG_GUEST_ERROR
,
386 "IotKit SecCtl S block write: bad offset 0x%x\n",
394 static MemTxResult
iotkit_secctl_ns_read(void *opaque
, hwaddr addr
,
396 unsigned size
, MemTxAttrs attrs
)
398 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
400 uint32_t offset
= addr
& ~0x3;
406 case A_AHBNSPPPCEXP0
:
407 case A_AHBNSPPPCEXP1
:
408 case A_AHBNSPPPCEXP2
:
409 case A_AHBNSPPPCEXP3
:
410 r
= s
->ahbexp
[offset_to_ppc_idx(offset
)].nsp
;
414 r
= s
->apb
[offset_to_ppc_idx(offset
)].nsp
;
416 case A_APBNSPPPCEXP0
:
417 case A_APBNSPPPCEXP1
:
418 case A_APBNSPPPCEXP2
:
419 case A_APBNSPPPCEXP3
:
420 r
= s
->apbexp
[offset_to_ppc_idx(offset
)].nsp
;
434 r
= iotkit_secctl_ns_idregs
[(offset
- A_PID4
) / 4];
437 qemu_log_mask(LOG_GUEST_ERROR
,
438 "IotKit SecCtl NS block write: bad offset 0x%x\n",
445 /* None of our registers are access-sensitive, so just pull the right
446 * byte out of the word read result.
448 r
= extract32(r
, (addr
& 3) * 8, size
* 8);
451 trace_iotkit_secctl_ns_read(offset
, r
, size
);
456 static MemTxResult
iotkit_secctl_ns_write(void *opaque
, hwaddr addr
,
458 unsigned size
, MemTxAttrs attrs
)
460 IoTKitSecCtl
*s
= IOTKIT_SECCTL(opaque
);
461 uint32_t offset
= addr
;
462 IoTKitSecCtlPPC
*ppc
;
464 trace_iotkit_secctl_ns_write(offset
, value
, size
);
467 /* Byte and halfword writes are ignored */
468 qemu_log_mask(LOG_GUEST_ERROR
,
469 "IotKit SecCtl NS block write: bad size, ignored\n");
474 case A_AHBNSPPPCEXP0
:
475 case A_AHBNSPPPCEXP1
:
476 case A_AHBNSPPPCEXP2
:
477 case A_AHBNSPPPCEXP3
:
478 ppc
= &s
->ahbexp
[offset_to_ppc_idx(offset
)];
479 iotkit_secctl_ppc_nsp_write(ppc
, value
);
483 ppc
= &s
->apb
[offset_to_ppc_idx(offset
)];
484 iotkit_secctl_ppc_nsp_write(ppc
, value
);
486 case A_APBNSPPPCEXP0
:
487 case A_APBNSPPPCEXP1
:
488 case A_APBNSPPPCEXP2
:
489 case A_APBNSPPPCEXP3
:
490 ppc
= &s
->apbexp
[offset_to_ppc_idx(offset
)];
491 iotkit_secctl_ppc_nsp_write(ppc
, value
);
506 qemu_log_mask(LOG_GUEST_ERROR
,
507 "IoTKit SecCtl NS block write: "
508 "read-only offset 0x%x\n", offset
);
511 qemu_log_mask(LOG_GUEST_ERROR
,
512 "IotKit SecCtl NS block write: bad offset 0x%x\n",
520 static const MemoryRegionOps iotkit_secctl_s_ops
= {
521 .read_with_attrs
= iotkit_secctl_s_read
,
522 .write_with_attrs
= iotkit_secctl_s_write
,
523 .endianness
= DEVICE_LITTLE_ENDIAN
,
524 .valid
.min_access_size
= 1,
525 .valid
.max_access_size
= 4,
526 .impl
.min_access_size
= 1,
527 .impl
.max_access_size
= 4,
530 static const MemoryRegionOps iotkit_secctl_ns_ops
= {
531 .read_with_attrs
= iotkit_secctl_ns_read
,
532 .write_with_attrs
= iotkit_secctl_ns_write
,
533 .endianness
= DEVICE_LITTLE_ENDIAN
,
534 .valid
.min_access_size
= 1,
535 .valid
.max_access_size
= 4,
536 .impl
.min_access_size
= 1,
537 .impl
.max_access_size
= 4,
540 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC
*ppc
)
547 static void iotkit_secctl_reset(DeviceState
*dev
)
549 IoTKitSecCtl
*s
= IOTKIT_SECCTL(dev
);
551 s
->secppcintstat
= 0;
555 foreach_ppc(s
, iotkit_secctl_reset_ppc
);
558 static void iotkit_secctl_ppc_irqstatus(void *opaque
, int n
, int level
)
560 IoTKitSecCtlPPC
*ppc
= opaque
;
561 IoTKitSecCtl
*s
= IOTKIT_SECCTL(ppc
->parent
);
562 int irqbit
= ppc
->irq_bit_offset
+ n
;
564 s
->secppcintstat
= deposit32(s
->secppcintstat
, irqbit
, 1, level
);
567 static void iotkit_secctl_init_ppc(IoTKitSecCtl
*s
,
568 IoTKitSecCtlPPC
*ppc
,
574 DeviceState
*dev
= DEVICE(s
);
576 ppc
->numports
= numports
;
577 ppc
->irq_bit_offset
= irq_bit_offset
;
580 gpioname
= g_strdup_printf("%s_nonsec", name
);
581 qdev_init_gpio_out_named(dev
, ppc
->nonsec
, gpioname
, numports
);
583 gpioname
= g_strdup_printf("%s_ap", name
);
584 qdev_init_gpio_out_named(dev
, ppc
->ap
, gpioname
, numports
);
586 gpioname
= g_strdup_printf("%s_irq_enable", name
);
587 qdev_init_gpio_out_named(dev
, &ppc
->irq_enable
, gpioname
, 1);
589 gpioname
= g_strdup_printf("%s_irq_clear", name
);
590 qdev_init_gpio_out_named(dev
, &ppc
->irq_clear
, gpioname
, 1);
592 gpioname
= g_strdup_printf("%s_irq_status", name
);
593 qdev_init_gpio_in_named_with_opaque(dev
, iotkit_secctl_ppc_irqstatus
,
598 static void iotkit_secctl_init(Object
*obj
)
600 IoTKitSecCtl
*s
= IOTKIT_SECCTL(obj
);
601 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
602 DeviceState
*dev
= DEVICE(obj
);
605 iotkit_secctl_init_ppc(s
, &s
->apb
[0], "apb_ppc0",
606 IOTS_APB_PPC0_NUM_PORTS
, 0);
607 iotkit_secctl_init_ppc(s
, &s
->apb
[1], "apb_ppc1",
608 IOTS_APB_PPC1_NUM_PORTS
, 1);
610 for (i
= 0; i
< IOTS_NUM_APB_EXP_PPC
; i
++) {
611 IoTKitSecCtlPPC
*ppc
= &s
->apbexp
[i
];
612 char *ppcname
= g_strdup_printf("apb_ppcexp%d", i
);
613 iotkit_secctl_init_ppc(s
, ppc
, ppcname
, IOTS_PPC_NUM_PORTS
, 4 + i
);
616 for (i
= 0; i
< IOTS_NUM_AHB_EXP_PPC
; i
++) {
617 IoTKitSecCtlPPC
*ppc
= &s
->ahbexp
[i
];
618 char *ppcname
= g_strdup_printf("ahb_ppcexp%d", i
);
619 iotkit_secctl_init_ppc(s
, ppc
, ppcname
, IOTS_PPC_NUM_PORTS
, 20 + i
);
623 qdev_init_gpio_out_named(dev
, &s
->sec_resp_cfg
, "sec_resp_cfg", 1);
625 memory_region_init_io(&s
->s_regs
, obj
, &iotkit_secctl_s_ops
,
626 s
, "iotkit-secctl-s-regs", 0x1000);
627 memory_region_init_io(&s
->ns_regs
, obj
, &iotkit_secctl_ns_ops
,
628 s
, "iotkit-secctl-ns-regs", 0x1000);
629 sysbus_init_mmio(sbd
, &s
->s_regs
);
630 sysbus_init_mmio(sbd
, &s
->ns_regs
);
633 static const VMStateDescription iotkit_secctl_ppc_vmstate
= {
634 .name
= "iotkit-secctl-ppc",
636 .minimum_version_id
= 1,
637 .fields
= (VMStateField
[]) {
638 VMSTATE_UINT32(ns
, IoTKitSecCtlPPC
),
639 VMSTATE_UINT32(sp
, IoTKitSecCtlPPC
),
640 VMSTATE_UINT32(nsp
, IoTKitSecCtlPPC
),
641 VMSTATE_END_OF_LIST()
645 static const VMStateDescription iotkit_secctl_vmstate
= {
646 .name
= "iotkit-secctl",
648 .minimum_version_id
= 1,
649 .fields
= (VMStateField
[]) {
650 VMSTATE_UINT32(secppcintstat
, IoTKitSecCtl
),
651 VMSTATE_UINT32(secppcinten
, IoTKitSecCtl
),
652 VMSTATE_UINT32(secrespcfg
, IoTKitSecCtl
),
653 VMSTATE_STRUCT_ARRAY(apb
, IoTKitSecCtl
, IOTS_NUM_APB_PPC
, 1,
654 iotkit_secctl_ppc_vmstate
, IoTKitSecCtlPPC
),
655 VMSTATE_STRUCT_ARRAY(apbexp
, IoTKitSecCtl
, IOTS_NUM_APB_EXP_PPC
, 1,
656 iotkit_secctl_ppc_vmstate
, IoTKitSecCtlPPC
),
657 VMSTATE_STRUCT_ARRAY(ahbexp
, IoTKitSecCtl
, IOTS_NUM_AHB_EXP_PPC
, 1,
658 iotkit_secctl_ppc_vmstate
, IoTKitSecCtlPPC
),
659 VMSTATE_END_OF_LIST()
663 static void iotkit_secctl_class_init(ObjectClass
*klass
, void *data
)
665 DeviceClass
*dc
= DEVICE_CLASS(klass
);
667 dc
->vmsd
= &iotkit_secctl_vmstate
;
668 dc
->reset
= iotkit_secctl_reset
;
671 static const TypeInfo iotkit_secctl_info
= {
672 .name
= TYPE_IOTKIT_SECCTL
,
673 .parent
= TYPE_SYS_BUS_DEVICE
,
674 .instance_size
= sizeof(IoTKitSecCtl
),
675 .instance_init
= iotkit_secctl_init
,
676 .class_init
= iotkit_secctl_class_init
,
679 static void iotkit_secctl_register_types(void)
681 type_register_static(&iotkit_secctl_info
);
684 type_init(iotkit_secctl_register_types
);