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