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#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);
 846