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_SECPPCINTSTAT: 140 r = s->secppcintstat; 141 break; 142 case A_SECPPCINTEN: 143 r = s->secppcinten; 144 break; 145 case A_AHBNSPPCEXP0: 146 case A_AHBNSPPCEXP1: 147 case A_AHBNSPPCEXP2: 148 case A_AHBNSPPCEXP3: 149 r = s->ahbexp[offset_to_ppc_idx(offset)].ns; 150 break; 151 case A_APBNSPPC0: 152 case A_APBNSPPC1: 153 r = s->apb[offset_to_ppc_idx(offset)].ns; 154 break; 155 case A_APBNSPPCEXP0: 156 case A_APBNSPPCEXP1: 157 case A_APBNSPPCEXP2: 158 case A_APBNSPPCEXP3: 159 r = s->apbexp[offset_to_ppc_idx(offset)].ns; 160 break; 161 case A_AHBSPPPCEXP0: 162 case A_AHBSPPPCEXP1: 163 case A_AHBSPPPCEXP2: 164 case A_AHBSPPPCEXP3: 165 r = s->apbexp[offset_to_ppc_idx(offset)].sp; 166 break; 167 case A_APBSPPPC0: 168 case A_APBSPPPC1: 169 r = s->apb[offset_to_ppc_idx(offset)].sp; 170 break; 171 case A_APBSPPPCEXP0: 172 case A_APBSPPPCEXP1: 173 case A_APBSPPPCEXP2: 174 case A_APBSPPPCEXP3: 175 r = s->apbexp[offset_to_ppc_idx(offset)].sp; 176 break; 177 case A_NSCCFG: 178 case A_SECMPCINTSTATUS: 179 case A_SECMSCINTSTAT: 180 case A_SECMSCINTEN: 181 case A_BRGINTSTAT: 182 case A_BRGINTEN: 183 case A_NSMSCEXP: 184 qemu_log_mask(LOG_UNIMP, 185 "IoTKit SecCtl S block read: " 186 "unimplemented offset 0x%x\n", offset); 187 r = 0; 188 break; 189 case A_PID4: 190 case A_PID5: 191 case A_PID6: 192 case A_PID7: 193 case A_PID0: 194 case A_PID1: 195 case A_PID2: 196 case A_PID3: 197 case A_CID0: 198 case A_CID1: 199 case A_CID2: 200 case A_CID3: 201 r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4]; 202 break; 203 case A_SECPPCINTCLR: 204 case A_SECMSCINTCLR: 205 case A_BRGINTCLR: 206 qemu_log_mask(LOG_GUEST_ERROR, 207 "IotKit SecCtl S block read: write-only offset 0x%x\n", 208 offset); 209 r = 0; 210 break; 211 default: 212 qemu_log_mask(LOG_GUEST_ERROR, 213 "IotKit SecCtl S block read: bad offset 0x%x\n", offset); 214 r = 0; 215 break; 216 } 217 218 if (size != 4) { 219 /* None of our registers are access-sensitive, so just pull the right 220 * byte out of the word read result. 221 */ 222 r = extract32(r, (addr & 3) * 8, size * 8); 223 } 224 225 trace_iotkit_secctl_s_read(offset, r, size); 226 *pdata = r; 227 return MEMTX_OK; 228 } 229 230 static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc) 231 { 232 int i; 233 234 for (i = 0; i < ppc->numports; i++) { 235 bool v; 236 237 if (extract32(ppc->ns, i, 1)) { 238 v = extract32(ppc->nsp, i, 1); 239 } else { 240 v = extract32(ppc->sp, i, 1); 241 } 242 qemu_set_irq(ppc->ap[i], v); 243 } 244 } 245 246 static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value) 247 { 248 int i; 249 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)); 253 } 254 iotkit_secctl_update_ppc_ap(ppc); 255 } 256 257 static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value) 258 { 259 ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports); 260 iotkit_secctl_update_ppc_ap(ppc); 261 } 262 263 static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value) 264 { 265 ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports); 266 iotkit_secctl_update_ppc_ap(ppc); 267 } 268 269 static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc) 270 { 271 uint32_t value = ppc->parent->secppcintstat; 272 273 qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1)); 274 } 275 276 static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc) 277 { 278 uint32_t value = ppc->parent->secppcinten; 279 280 qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1)); 281 } 282 283 static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr, 284 uint64_t value, 285 unsigned size, MemTxAttrs attrs) 286 { 287 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 288 uint32_t offset = addr; 289 IoTKitSecCtlPPC *ppc; 290 291 trace_iotkit_secctl_s_write(offset, value, size); 292 293 if (size != 4) { 294 /* Byte and halfword writes are ignored */ 295 qemu_log_mask(LOG_GUEST_ERROR, 296 "IotKit SecCtl S block write: bad size, ignored\n"); 297 return MEMTX_OK; 298 } 299 300 switch (offset) { 301 case A_SECRESPCFG: 302 value &= 1; 303 s->secrespcfg = value; 304 qemu_set_irq(s->sec_resp_cfg, s->secrespcfg); 305 break; 306 case A_SECPPCINTCLR: 307 value &= 0x00f000f3; 308 foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear); 309 break; 310 case A_SECPPCINTEN: 311 s->secppcinten = value & 0x00f000f3; 312 foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable); 313 break; 314 case A_AHBNSPPCEXP0: 315 case A_AHBNSPPCEXP1: 316 case A_AHBNSPPCEXP2: 317 case A_AHBNSPPCEXP3: 318 ppc = &s->ahbexp[offset_to_ppc_idx(offset)]; 319 iotkit_secctl_ppc_ns_write(ppc, value); 320 break; 321 case A_APBNSPPC0: 322 case A_APBNSPPC1: 323 ppc = &s->apb[offset_to_ppc_idx(offset)]; 324 iotkit_secctl_ppc_ns_write(ppc, value); 325 break; 326 case A_APBNSPPCEXP0: 327 case A_APBNSPPCEXP1: 328 case A_APBNSPPCEXP2: 329 case A_APBNSPPCEXP3: 330 ppc = &s->apbexp[offset_to_ppc_idx(offset)]; 331 iotkit_secctl_ppc_ns_write(ppc, value); 332 break; 333 case A_AHBSPPPCEXP0: 334 case A_AHBSPPPCEXP1: 335 case A_AHBSPPPCEXP2: 336 case A_AHBSPPPCEXP3: 337 ppc = &s->ahbexp[offset_to_ppc_idx(offset)]; 338 iotkit_secctl_ppc_sp_write(ppc, value); 339 break; 340 case A_APBSPPPC0: 341 case A_APBSPPPC1: 342 ppc = &s->apb[offset_to_ppc_idx(offset)]; 343 iotkit_secctl_ppc_sp_write(ppc, value); 344 break; 345 case A_APBSPPPCEXP0: 346 case A_APBSPPPCEXP1: 347 case A_APBSPPPCEXP2: 348 case A_APBSPPPCEXP3: 349 ppc = &s->apbexp[offset_to_ppc_idx(offset)]; 350 iotkit_secctl_ppc_sp_write(ppc, value); 351 break; 352 case A_NSCCFG: 353 case A_SECMSCINTCLR: 354 case A_SECMSCINTEN: 355 case A_BRGINTCLR: 356 case A_BRGINTEN: 357 qemu_log_mask(LOG_UNIMP, 358 "IoTKit SecCtl S block write: " 359 "unimplemented offset 0x%x\n", offset); 360 break; 361 case A_SECMPCINTSTATUS: 362 case A_SECPPCINTSTAT: 363 case A_SECMSCINTSTAT: 364 case A_BRGINTSTAT: 365 case A_AHBNSPPC0: 366 case A_AHBSPPPC0: 367 case A_NSMSCEXP: 368 case A_PID4: 369 case A_PID5: 370 case A_PID6: 371 case A_PID7: 372 case A_PID0: 373 case A_PID1: 374 case A_PID2: 375 case A_PID3: 376 case A_CID0: 377 case A_CID1: 378 case A_CID2: 379 case A_CID3: 380 qemu_log_mask(LOG_GUEST_ERROR, 381 "IoTKit SecCtl S block write: " 382 "read-only offset 0x%x\n", offset); 383 break; 384 default: 385 qemu_log_mask(LOG_GUEST_ERROR, 386 "IotKit SecCtl S block write: bad offset 0x%x\n", 387 offset); 388 break; 389 } 390 391 return MEMTX_OK; 392 } 393 394 static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr, 395 uint64_t *pdata, 396 unsigned size, MemTxAttrs attrs) 397 { 398 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 399 uint64_t r; 400 uint32_t offset = addr & ~0x3; 401 402 switch (offset) { 403 case A_AHBNSPPPC0: 404 r = 0; 405 break; 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; 411 break; 412 case A_APBNSPPPC0: 413 case A_APBNSPPPC1: 414 r = s->apb[offset_to_ppc_idx(offset)].nsp; 415 break; 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; 421 break; 422 case A_PID4: 423 case A_PID5: 424 case A_PID6: 425 case A_PID7: 426 case A_PID0: 427 case A_PID1: 428 case A_PID2: 429 case A_PID3: 430 case A_CID0: 431 case A_CID1: 432 case A_CID2: 433 case A_CID3: 434 r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4]; 435 break; 436 default: 437 qemu_log_mask(LOG_GUEST_ERROR, 438 "IotKit SecCtl NS block write: bad offset 0x%x\n", 439 offset); 440 r = 0; 441 break; 442 } 443 444 if (size != 4) { 445 /* None of our registers are access-sensitive, so just pull the right 446 * byte out of the word read result. 447 */ 448 r = extract32(r, (addr & 3) * 8, size * 8); 449 } 450 451 trace_iotkit_secctl_ns_read(offset, r, size); 452 *pdata = r; 453 return MEMTX_OK; 454 } 455 456 static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr, 457 uint64_t value, 458 unsigned size, MemTxAttrs attrs) 459 { 460 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque); 461 uint32_t offset = addr; 462 IoTKitSecCtlPPC *ppc; 463 464 trace_iotkit_secctl_ns_write(offset, value, size); 465 466 if (size != 4) { 467 /* Byte and halfword writes are ignored */ 468 qemu_log_mask(LOG_GUEST_ERROR, 469 "IotKit SecCtl NS block write: bad size, ignored\n"); 470 return MEMTX_OK; 471 } 472 473 switch (offset) { 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); 480 break; 481 case A_APBNSPPPC0: 482 case A_APBNSPPPC1: 483 ppc = &s->apb[offset_to_ppc_idx(offset)]; 484 iotkit_secctl_ppc_nsp_write(ppc, value); 485 break; 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); 492 break; 493 case A_AHBNSPPPC0: 494 case A_PID4: 495 case A_PID5: 496 case A_PID6: 497 case A_PID7: 498 case A_PID0: 499 case A_PID1: 500 case A_PID2: 501 case A_PID3: 502 case A_CID0: 503 case A_CID1: 504 case A_CID2: 505 case A_CID3: 506 qemu_log_mask(LOG_GUEST_ERROR, 507 "IoTKit SecCtl NS block write: " 508 "read-only offset 0x%x\n", offset); 509 break; 510 default: 511 qemu_log_mask(LOG_GUEST_ERROR, 512 "IotKit SecCtl NS block write: bad offset 0x%x\n", 513 offset); 514 break; 515 } 516 517 return MEMTX_OK; 518 } 519 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, 528 }; 529 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, 538 }; 539 540 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc) 541 { 542 ppc->ns = 0; 543 ppc->sp = 0; 544 ppc->nsp = 0; 545 } 546 547 static void iotkit_secctl_reset(DeviceState *dev) 548 { 549 IoTKitSecCtl *s = IOTKIT_SECCTL(dev); 550 551 s->secppcintstat = 0; 552 s->secppcinten = 0; 553 s->secrespcfg = 0; 554 555 foreach_ppc(s, iotkit_secctl_reset_ppc); 556 } 557 558 static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level) 559 { 560 IoTKitSecCtlPPC *ppc = opaque; 561 IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent); 562 int irqbit = ppc->irq_bit_offset + n; 563 564 s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level); 565 } 566 567 static void iotkit_secctl_init_ppc(IoTKitSecCtl *s, 568 IoTKitSecCtlPPC *ppc, 569 const char *name, 570 int numports, 571 int irq_bit_offset) 572 { 573 char *gpioname; 574 DeviceState *dev = DEVICE(s); 575 576 ppc->numports = numports; 577 ppc->irq_bit_offset = irq_bit_offset; 578 ppc->parent = s; 579 580 gpioname = g_strdup_printf("%s_nonsec", name); 581 qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports); 582 g_free(gpioname); 583 gpioname = g_strdup_printf("%s_ap", name); 584 qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports); 585 g_free(gpioname); 586 gpioname = g_strdup_printf("%s_irq_enable", name); 587 qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1); 588 g_free(gpioname); 589 gpioname = g_strdup_printf("%s_irq_clear", name); 590 qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1); 591 g_free(gpioname); 592 gpioname = g_strdup_printf("%s_irq_status", name); 593 qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus, 594 ppc, gpioname, 1); 595 g_free(gpioname); 596 } 597 598 static void iotkit_secctl_init(Object *obj) 599 { 600 IoTKitSecCtl *s = IOTKIT_SECCTL(obj); 601 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 602 DeviceState *dev = DEVICE(obj); 603 int i; 604 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); 609 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); 614 g_free(ppcname); 615 } 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); 620 g_free(ppcname); 621 } 622 623 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1); 624 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); 631 } 632 633 static const VMStateDescription iotkit_secctl_ppc_vmstate = { 634 .name = "iotkit-secctl-ppc", 635 .version_id = 1, 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() 642 } 643 }; 644 645 static const VMStateDescription iotkit_secctl_vmstate = { 646 .name = "iotkit-secctl", 647 .version_id = 1, 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() 660 } 661 }; 662 663 static void iotkit_secctl_class_init(ObjectClass *klass, void *data) 664 { 665 DeviceClass *dc = DEVICE_CLASS(klass); 666 667 dc->vmsd = &iotkit_secctl_vmstate; 668 dc->reset = iotkit_secctl_reset; 669 } 670 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, 677 }; 678 679 static void iotkit_secctl_register_types(void) 680 { 681 type_register_static(&iotkit_secctl_info); 682 } 683 684 type_init(iotkit_secctl_register_types); 685