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 "qapi/error.h" 15 #include "trace.h" 16 #include "hw/sysbus.h" 17 #include "hw/registerfields.h" 18 #include "hw/misc/iotkit-secctl.h" 19 20 /* Registers in the secure privilege control block */ 21 REG32(SECRESPCFG, 0x10) 22 REG32(NSCCFG, 0x14) 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) 32 REG32(BRGINTEN, 0x48) 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) 55 REG32(NSMSCEXP, 0xd0) 56 REG32(PID4, 0xfd0) 57 REG32(PID5, 0xfd4) 58 REG32(PID6, 0xfd8) 59 REG32(PID7, 0xfdc) 60 REG32(PID0, 0xfe0) 61 REG32(PID1, 0xfe4) 62 REG32(PID2, 0xfe8) 63 REG32(PID3, 0xfec) 64 REG32(CID0, 0xff0) 65 REG32(CID1, 0xff4) 66 REG32(CID2, 0xff8) 67 REG32(CID3, 0xffc) 68 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 */ 82 83 static const uint8_t iotkit_secctl_s_idregs[] = { 84 0x04, 0x00, 0x00, 0x00, 85 0x52, 0xb8, 0x0b, 0x00, 86 0x0d, 0xf0, 0x05, 0xb1, 87 }; 88 89 static const uint8_t iotkit_secctl_ns_idregs[] = { 90 0x04, 0x00, 0x00, 0x00, 91 0x53, 0xb8, 0x0b, 0x00, 92 0x0d, 0xf0, 0x05, 0xb1, 93 }; 94 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. 100 */ 101 static inline int offset_to_ppc_idx(uint32_t offset) 102 { 103 return extract32(offset, 2, 2); 104 } 105 106 typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc); 107 108 static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn) 109 { 110 int i; 111 112 for (i = 0; i < IOTS_NUM_APB_PPC; i++) { 113 fn(&s->apb[i]); 114 } 115 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) { 116 fn(&s->apbexp[i]); 117 } 118 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) { 119 fn(&s->ahbexp[i]); 120 } 121 } 122 123 static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr, 124 uint64_t *pdata, 125 unsigned size, MemTxAttrs attrs) 126 { 127 uint64_t r; 128 uint32_t offset = addr & ~0x3; 129 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 130 131 switch (offset) { 132 case A_AHBNSPPC0: 133 case A_AHBSPPPC0: 134 r = 0; 135 break; 136 case A_SECRESPCFG: 137 r = s->secrespcfg; 138 break; 139 case A_NSCCFG: 140 r = s->nsccfg; 141 break; 142 case A_SECMPCINTSTATUS: 143 r = s->mpcintstatus; 144 break; 145 case A_SECPPCINTSTAT: 146 r = s->secppcintstat; 147 break; 148 case A_SECPPCINTEN: 149 r = s->secppcinten; 150 break; 151 case A_BRGINTSTAT: 152 /* QEMU's bus fabric can never report errors as it doesn't buffer 153 * writes, so we never report bridge interrupts. 154 */ 155 r = 0; 156 break; 157 case A_BRGINTEN: 158 r = s->brginten; 159 break; 160 case A_AHBNSPPCEXP0: 161 case A_AHBNSPPCEXP1: 162 case A_AHBNSPPCEXP2: 163 case A_AHBNSPPCEXP3: 164 r = s->ahbexp[offset_to_ppc_idx(offset)].ns; 165 break; 166 case A_APBNSPPC0: 167 case A_APBNSPPC1: 168 r = s->apb[offset_to_ppc_idx(offset)].ns; 169 break; 170 case A_APBNSPPCEXP0: 171 case A_APBNSPPCEXP1: 172 case A_APBNSPPCEXP2: 173 case A_APBNSPPCEXP3: 174 r = s->apbexp[offset_to_ppc_idx(offset)].ns; 175 break; 176 case A_AHBSPPPCEXP0: 177 case A_AHBSPPPCEXP1: 178 case A_AHBSPPPCEXP2: 179 case A_AHBSPPPCEXP3: 180 r = s->apbexp[offset_to_ppc_idx(offset)].sp; 181 break; 182 case A_APBSPPPC0: 183 case A_APBSPPPC1: 184 r = s->apb[offset_to_ppc_idx(offset)].sp; 185 break; 186 case A_APBSPPPCEXP0: 187 case A_APBSPPPCEXP1: 188 case A_APBSPPPCEXP2: 189 case A_APBSPPPCEXP3: 190 r = s->apbexp[offset_to_ppc_idx(offset)].sp; 191 break; 192 case A_SECMSCINTSTAT: 193 case A_SECMSCINTEN: 194 case A_NSMSCEXP: 195 qemu_log_mask(LOG_UNIMP, 196 "IoTKit SecCtl S block read: " 197 "unimplemented offset 0x%x\n", offset); 198 r = 0; 199 break; 200 case A_PID4: 201 case A_PID5: 202 case A_PID6: 203 case A_PID7: 204 case A_PID0: 205 case A_PID1: 206 case A_PID2: 207 case A_PID3: 208 case A_CID0: 209 case A_CID1: 210 case A_CID2: 211 case A_CID3: 212 r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4]; 213 break; 214 case A_SECPPCINTCLR: 215 case A_SECMSCINTCLR: 216 case A_BRGINTCLR: 217 qemu_log_mask(LOG_GUEST_ERROR, 218 "IotKit SecCtl S block read: write-only offset 0x%x\n", 219 offset); 220 r = 0; 221 break; 222 default: 223 qemu_log_mask(LOG_GUEST_ERROR, 224 "IotKit SecCtl S block read: bad offset 0x%x\n", offset); 225 r = 0; 226 break; 227 } 228 229 if (size != 4) { 230 /* None of our registers are access-sensitive, so just pull the right 231 * byte out of the word read result. 232 */ 233 r = extract32(r, (addr & 3) * 8, size * 8); 234 } 235 236 trace_iotkit_secctl_s_read(offset, r, size); 237 *pdata = r; 238 return MEMTX_OK; 239 } 240 241 static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc) 242 { 243 int i; 244 245 for (i = 0; i < ppc->numports; i++) { 246 bool v; 247 248 if (extract32(ppc->ns, i, 1)) { 249 v = extract32(ppc->nsp, i, 1); 250 } else { 251 v = extract32(ppc->sp, i, 1); 252 } 253 qemu_set_irq(ppc->ap[i], v); 254 } 255 } 256 257 static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value) 258 { 259 int i; 260 261 ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports); 262 for (i = 0; i < ppc->numports; i++) { 263 qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1)); 264 } 265 iotkit_secctl_update_ppc_ap(ppc); 266 } 267 268 static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value) 269 { 270 ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports); 271 iotkit_secctl_update_ppc_ap(ppc); 272 } 273 274 static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value) 275 { 276 ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports); 277 iotkit_secctl_update_ppc_ap(ppc); 278 } 279 280 static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc) 281 { 282 uint32_t value = ppc->parent->secppcintstat; 283 284 qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1)); 285 } 286 287 static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc) 288 { 289 uint32_t value = ppc->parent->secppcinten; 290 291 qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1)); 292 } 293 294 static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr, 295 uint64_t value, 296 unsigned size, MemTxAttrs attrs) 297 { 298 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 299 uint32_t offset = addr; 300 IoTKitSecCtlPPC *ppc; 301 302 trace_iotkit_secctl_s_write(offset, value, size); 303 304 if (size != 4) { 305 /* Byte and halfword writes are ignored */ 306 qemu_log_mask(LOG_GUEST_ERROR, 307 "IotKit SecCtl S block write: bad size, ignored\n"); 308 return MEMTX_OK; 309 } 310 311 switch (offset) { 312 case A_NSCCFG: 313 s->nsccfg = value & 3; 314 qemu_set_irq(s->nsc_cfg_irq, s->nsccfg); 315 break; 316 case A_SECRESPCFG: 317 value &= 1; 318 s->secrespcfg = value; 319 qemu_set_irq(s->sec_resp_cfg, s->secrespcfg); 320 break; 321 case A_SECPPCINTCLR: 322 value &= 0x00f000f3; 323 foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear); 324 break; 325 case A_SECPPCINTEN: 326 s->secppcinten = value & 0x00f000f3; 327 foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable); 328 break; 329 case A_BRGINTCLR: 330 break; 331 case A_BRGINTEN: 332 s->brginten = value & 0xffff0000; 333 break; 334 case A_AHBNSPPCEXP0: 335 case A_AHBNSPPCEXP1: 336 case A_AHBNSPPCEXP2: 337 case A_AHBNSPPCEXP3: 338 ppc = &s->ahbexp[offset_to_ppc_idx(offset)]; 339 iotkit_secctl_ppc_ns_write(ppc, value); 340 break; 341 case A_APBNSPPC0: 342 case A_APBNSPPC1: 343 ppc = &s->apb[offset_to_ppc_idx(offset)]; 344 iotkit_secctl_ppc_ns_write(ppc, value); 345 break; 346 case A_APBNSPPCEXP0: 347 case A_APBNSPPCEXP1: 348 case A_APBNSPPCEXP2: 349 case A_APBNSPPCEXP3: 350 ppc = &s->apbexp[offset_to_ppc_idx(offset)]; 351 iotkit_secctl_ppc_ns_write(ppc, value); 352 break; 353 case A_AHBSPPPCEXP0: 354 case A_AHBSPPPCEXP1: 355 case A_AHBSPPPCEXP2: 356 case A_AHBSPPPCEXP3: 357 ppc = &s->ahbexp[offset_to_ppc_idx(offset)]; 358 iotkit_secctl_ppc_sp_write(ppc, value); 359 break; 360 case A_APBSPPPC0: 361 case A_APBSPPPC1: 362 ppc = &s->apb[offset_to_ppc_idx(offset)]; 363 iotkit_secctl_ppc_sp_write(ppc, value); 364 break; 365 case A_APBSPPPCEXP0: 366 case A_APBSPPPCEXP1: 367 case A_APBSPPPCEXP2: 368 case A_APBSPPPCEXP3: 369 ppc = &s->apbexp[offset_to_ppc_idx(offset)]; 370 iotkit_secctl_ppc_sp_write(ppc, value); 371 break; 372 case A_SECMSCINTCLR: 373 case A_SECMSCINTEN: 374 qemu_log_mask(LOG_UNIMP, 375 "IoTKit SecCtl S block write: " 376 "unimplemented offset 0x%x\n", offset); 377 break; 378 case A_SECMPCINTSTATUS: 379 case A_SECPPCINTSTAT: 380 case A_SECMSCINTSTAT: 381 case A_BRGINTSTAT: 382 case A_AHBNSPPC0: 383 case A_AHBSPPPC0: 384 case A_NSMSCEXP: 385 case A_PID4: 386 case A_PID5: 387 case A_PID6: 388 case A_PID7: 389 case A_PID0: 390 case A_PID1: 391 case A_PID2: 392 case A_PID3: 393 case A_CID0: 394 case A_CID1: 395 case A_CID2: 396 case A_CID3: 397 qemu_log_mask(LOG_GUEST_ERROR, 398 "IoTKit SecCtl S block write: " 399 "read-only offset 0x%x\n", offset); 400 break; 401 default: 402 qemu_log_mask(LOG_GUEST_ERROR, 403 "IotKit SecCtl S block write: bad offset 0x%x\n", 404 offset); 405 break; 406 } 407 408 return MEMTX_OK; 409 } 410 411 static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr, 412 uint64_t *pdata, 413 unsigned size, MemTxAttrs attrs) 414 { 415 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 416 uint64_t r; 417 uint32_t offset = addr & ~0x3; 418 419 switch (offset) { 420 case A_AHBNSPPPC0: 421 r = 0; 422 break; 423 case A_AHBNSPPPCEXP0: 424 case A_AHBNSPPPCEXP1: 425 case A_AHBNSPPPCEXP2: 426 case A_AHBNSPPPCEXP3: 427 r = s->ahbexp[offset_to_ppc_idx(offset)].nsp; 428 break; 429 case A_APBNSPPPC0: 430 case A_APBNSPPPC1: 431 r = s->apb[offset_to_ppc_idx(offset)].nsp; 432 break; 433 case A_APBNSPPPCEXP0: 434 case A_APBNSPPPCEXP1: 435 case A_APBNSPPPCEXP2: 436 case A_APBNSPPPCEXP3: 437 r = s->apbexp[offset_to_ppc_idx(offset)].nsp; 438 break; 439 case A_PID4: 440 case A_PID5: 441 case A_PID6: 442 case A_PID7: 443 case A_PID0: 444 case A_PID1: 445 case A_PID2: 446 case A_PID3: 447 case A_CID0: 448 case A_CID1: 449 case A_CID2: 450 case A_CID3: 451 r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4]; 452 break; 453 default: 454 qemu_log_mask(LOG_GUEST_ERROR, 455 "IotKit SecCtl NS block write: bad offset 0x%x\n", 456 offset); 457 r = 0; 458 break; 459 } 460 461 if (size != 4) { 462 /* None of our registers are access-sensitive, so just pull the right 463 * byte out of the word read result. 464 */ 465 r = extract32(r, (addr & 3) * 8, size * 8); 466 } 467 468 trace_iotkit_secctl_ns_read(offset, r, size); 469 *pdata = r; 470 return MEMTX_OK; 471 } 472 473 static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr, 474 uint64_t value, 475 unsigned size, MemTxAttrs attrs) 476 { 477 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 478 uint32_t offset = addr; 479 IoTKitSecCtlPPC *ppc; 480 481 trace_iotkit_secctl_ns_write(offset, value, size); 482 483 if (size != 4) { 484 /* Byte and halfword writes are ignored */ 485 qemu_log_mask(LOG_GUEST_ERROR, 486 "IotKit SecCtl NS block write: bad size, ignored\n"); 487 return MEMTX_OK; 488 } 489 490 switch (offset) { 491 case A_AHBNSPPPCEXP0: 492 case A_AHBNSPPPCEXP1: 493 case A_AHBNSPPPCEXP2: 494 case A_AHBNSPPPCEXP3: 495 ppc = &s->ahbexp[offset_to_ppc_idx(offset)]; 496 iotkit_secctl_ppc_nsp_write(ppc, value); 497 break; 498 case A_APBNSPPPC0: 499 case A_APBNSPPPC1: 500 ppc = &s->apb[offset_to_ppc_idx(offset)]; 501 iotkit_secctl_ppc_nsp_write(ppc, value); 502 break; 503 case A_APBNSPPPCEXP0: 504 case A_APBNSPPPCEXP1: 505 case A_APBNSPPPCEXP2: 506 case A_APBNSPPPCEXP3: 507 ppc = &s->apbexp[offset_to_ppc_idx(offset)]; 508 iotkit_secctl_ppc_nsp_write(ppc, value); 509 break; 510 case A_AHBNSPPPC0: 511 case A_PID4: 512 case A_PID5: 513 case A_PID6: 514 case A_PID7: 515 case A_PID0: 516 case A_PID1: 517 case A_PID2: 518 case A_PID3: 519 case A_CID0: 520 case A_CID1: 521 case A_CID2: 522 case A_CID3: 523 qemu_log_mask(LOG_GUEST_ERROR, 524 "IoTKit SecCtl NS block write: " 525 "read-only offset 0x%x\n", offset); 526 break; 527 default: 528 qemu_log_mask(LOG_GUEST_ERROR, 529 "IotKit SecCtl NS block write: bad offset 0x%x\n", 530 offset); 531 break; 532 } 533 534 return MEMTX_OK; 535 } 536 537 static const MemoryRegionOps iotkit_secctl_s_ops = { 538 .read_with_attrs = iotkit_secctl_s_read, 539 .write_with_attrs = iotkit_secctl_s_write, 540 .endianness = DEVICE_LITTLE_ENDIAN, 541 .valid.min_access_size = 1, 542 .valid.max_access_size = 4, 543 .impl.min_access_size = 1, 544 .impl.max_access_size = 4, 545 }; 546 547 static const MemoryRegionOps iotkit_secctl_ns_ops = { 548 .read_with_attrs = iotkit_secctl_ns_read, 549 .write_with_attrs = iotkit_secctl_ns_write, 550 .endianness = DEVICE_LITTLE_ENDIAN, 551 .valid.min_access_size = 1, 552 .valid.max_access_size = 4, 553 .impl.min_access_size = 1, 554 .impl.max_access_size = 4, 555 }; 556 557 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc) 558 { 559 ppc->ns = 0; 560 ppc->sp = 0; 561 ppc->nsp = 0; 562 } 563 564 static void iotkit_secctl_reset(DeviceState *dev) 565 { 566 IoTKitSecCtl *s = IOTKIT_SECCTL(dev); 567 568 s->secppcintstat = 0; 569 s->secppcinten = 0; 570 s->secrespcfg = 0; 571 s->nsccfg = 0; 572 s->brginten = 0; 573 574 foreach_ppc(s, iotkit_secctl_reset_ppc); 575 } 576 577 static void iotkit_secctl_mpc_status(void *opaque, int n, int level) 578 { 579 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 580 581 s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level); 582 } 583 584 static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level) 585 { 586 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 587 588 s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level); 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", 1); 660 qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status, 661 "mpcexp_status", IOTS_NUM_EXP_MPC); 662 663 memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops, 664 s, "iotkit-secctl-s-regs", 0x1000); 665 memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops, 666 s, "iotkit-secctl-ns-regs", 0x1000); 667 sysbus_init_mmio(sbd, &s->s_regs); 668 sysbus_init_mmio(sbd, &s->ns_regs); 669 } 670 671 static const VMStateDescription iotkit_secctl_ppc_vmstate = { 672 .name = "iotkit-secctl-ppc", 673 .version_id = 1, 674 .minimum_version_id = 1, 675 .fields = (VMStateField[]) { 676 VMSTATE_UINT32(ns, IoTKitSecCtlPPC), 677 VMSTATE_UINT32(sp, IoTKitSecCtlPPC), 678 VMSTATE_UINT32(nsp, IoTKitSecCtlPPC), 679 VMSTATE_END_OF_LIST() 680 } 681 }; 682 683 static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = { 684 .name = "iotkit-secctl-mpcintstatus", 685 .version_id = 1, 686 .minimum_version_id = 1, 687 .fields = (VMStateField[]) { 688 VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl), 689 VMSTATE_END_OF_LIST() 690 } 691 }; 692 693 static const VMStateDescription iotkit_secctl_vmstate = { 694 .name = "iotkit-secctl", 695 .version_id = 1, 696 .minimum_version_id = 1, 697 .fields = (VMStateField[]) { 698 VMSTATE_UINT32(secppcintstat, IoTKitSecCtl), 699 VMSTATE_UINT32(secppcinten, IoTKitSecCtl), 700 VMSTATE_UINT32(secrespcfg, IoTKitSecCtl), 701 VMSTATE_UINT32(nsccfg, IoTKitSecCtl), 702 VMSTATE_UINT32(brginten, IoTKitSecCtl), 703 VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1, 704 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC), 705 VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1, 706 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC), 707 VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1, 708 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC), 709 VMSTATE_END_OF_LIST() 710 }, 711 .subsections = (const VMStateDescription*[]) { 712 &iotkit_secctl_mpcintstatus_vmstate, 713 NULL 714 }, 715 }; 716 717 static void iotkit_secctl_class_init(ObjectClass *klass, void *data) 718 { 719 DeviceClass *dc = DEVICE_CLASS(klass); 720 721 dc->vmsd = &iotkit_secctl_vmstate; 722 dc->reset = iotkit_secctl_reset; 723 } 724 725 static const TypeInfo iotkit_secctl_info = { 726 .name = TYPE_IOTKIT_SECCTL, 727 .parent = TYPE_SYS_BUS_DEVICE, 728 .instance_size = sizeof(IoTKitSecCtl), 729 .instance_init = iotkit_secctl_init, 730 .class_init = iotkit_secctl_class_init, 731 }; 732 733 static void iotkit_secctl_register_types(void) 734 { 735 type_register_static(&iotkit_secctl_info); 736 } 737 738 type_init(iotkit_secctl_register_types); 739