qemu/hw/misc/iotkit-secctl.c
<<
>>
Prefs
   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 */
  21REG32(SECRESPCFG, 0x10)
  22REG32(NSCCFG, 0x14)
  23REG32(SECMPCINTSTATUS, 0x1c)
  24REG32(SECPPCINTSTAT, 0x20)
  25REG32(SECPPCINTCLR, 0x24)
  26REG32(SECPPCINTEN, 0x28)
  27REG32(SECMSCINTSTAT, 0x30)
  28REG32(SECMSCINTCLR, 0x34)
  29REG32(SECMSCINTEN, 0x38)
  30REG32(BRGINTSTAT, 0x40)
  31REG32(BRGINTCLR, 0x44)
  32REG32(BRGINTEN, 0x48)
  33REG32(AHBNSPPC0, 0x50)
  34REG32(AHBNSPPCEXP0, 0x60)
  35REG32(AHBNSPPCEXP1, 0x64)
  36REG32(AHBNSPPCEXP2, 0x68)
  37REG32(AHBNSPPCEXP3, 0x6c)
  38REG32(APBNSPPC0, 0x70)
  39REG32(APBNSPPC1, 0x74)
  40REG32(APBNSPPCEXP0, 0x80)
  41REG32(APBNSPPCEXP1, 0x84)
  42REG32(APBNSPPCEXP2, 0x88)
  43REG32(APBNSPPCEXP3, 0x8c)
  44REG32(AHBSPPPC0, 0x90)
  45REG32(AHBSPPPCEXP0, 0xa0)
  46REG32(AHBSPPPCEXP1, 0xa4)
  47REG32(AHBSPPPCEXP2, 0xa8)
  48REG32(AHBSPPPCEXP3, 0xac)
  49REG32(APBSPPPC0, 0xb0)
  50REG32(APBSPPPC1, 0xb4)
  51REG32(APBSPPPCEXP0, 0xc0)
  52REG32(APBSPPPCEXP1, 0xc4)
  53REG32(APBSPPPCEXP2, 0xc8)
  54REG32(APBSPPPCEXP3, 0xcc)
  55REG32(NSMSCEXP, 0xd0)
  56REG32(PID4, 0xfd0)
  57REG32(PID5, 0xfd4)
  58REG32(PID6, 0xfd8)
  59REG32(PID7, 0xfdc)
  60REG32(PID0, 0xfe0)
  61REG32(PID1, 0xfe4)
  62REG32(PID2, 0xfe8)
  63REG32(PID3, 0xfec)
  64REG32(CID0, 0xff0)
  65REG32(CID1, 0xff4)
  66REG32(CID2, 0xff8)
  67REG32(CID3, 0xffc)
  68
  69/* Registers in the non-secure privilege control block */
  70REG32(AHBNSPPPC0, 0x90)
  71REG32(AHBNSPPPCEXP0, 0xa0)
  72REG32(AHBNSPPPCEXP1, 0xa4)
  73REG32(AHBNSPPPCEXP2, 0xa8)
  74REG32(AHBNSPPPCEXP3, 0xac)
  75REG32(APBNSPPPC0, 0xb0)
  76REG32(APBNSPPPC1, 0xb4)
  77REG32(APBNSPPPCEXP0, 0xc0)
  78REG32(APBNSPPPCEXP1, 0xc4)
  79REG32(APBNSPPPCEXP2, 0xc8)
  80REG32(APBNSPPPCEXP3, 0xcc)
  81/* PID and CID registers are also present in the NS block */
  82
  83static const uint8_t iotkit_secctl_s_idregs[] = {
  84    0x04, 0x00, 0x00, 0x00,
  85    0x52, 0xb8, 0x0b, 0x00,
  86    0x0d, 0xf0, 0x05, 0xb1,
  87};
  88
  89static 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 */
 101static inline int offset_to_ppc_idx(uint32_t offset)
 102{
 103    return extract32(offset, 2, 2);
 104}
 105
 106typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
 107
 108static 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
 123static 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
 241static 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
 257static 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
 268static 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
 274static 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
 280static 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
 287static 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
 294static 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
 411static 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
 473static 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
 537static 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
 547static 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
 557static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
 558{
 559    ppc->ns = 0;
 560    ppc->sp = 0;
 561    ppc->nsp = 0;
 562}
 563
 564static 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
 577static 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
 584static 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
 591static 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
 600static 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
 631static 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
 671static 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
 683static 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
 693static 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
 717static 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
 725static 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
 733static void iotkit_secctl_register_types(void)
 734{
 735    type_register_static(&iotkit_secctl_info);
 736}
 737
 738type_init(iotkit_secctl_register_types);
 739