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