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        r = s->secmscintstat;
 194        break;
 195    case A_SECMSCINTEN:
 196        r = s->secmscinten;
 197        break;
 198    case A_NSMSCEXP:
 199        r = s->nsmscexp;
 200        break;
 201    case A_PID4:
 202    case A_PID5:
 203    case A_PID6:
 204    case A_PID7:
 205    case A_PID0:
 206    case A_PID1:
 207    case A_PID2:
 208    case A_PID3:
 209    case A_CID0:
 210    case A_CID1:
 211    case A_CID2:
 212    case A_CID3:
 213        r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
 214        break;
 215    case A_SECPPCINTCLR:
 216    case A_SECMSCINTCLR:
 217    case A_BRGINTCLR:
 218        qemu_log_mask(LOG_GUEST_ERROR,
 219                      "IotKit SecCtl S block read: write-only offset 0x%x\n",
 220                      offset);
 221        r = 0;
 222        break;
 223    default:
 224        qemu_log_mask(LOG_GUEST_ERROR,
 225                      "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
 226        r = 0;
 227        break;
 228    }
 229
 230    if (size != 4) {
 231        /* None of our registers are access-sensitive, so just pull the right
 232         * byte out of the word read result.
 233         */
 234        r = extract32(r, (addr & 3) * 8, size * 8);
 235    }
 236
 237    trace_iotkit_secctl_s_read(offset, r, size);
 238    *pdata = r;
 239    return MEMTX_OK;
 240}
 241
 242static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
 243{
 244    int i;
 245
 246    for (i = 0; i < ppc->numports; i++) {
 247        bool v;
 248
 249        if (extract32(ppc->ns, i, 1)) {
 250            v = extract32(ppc->nsp, i, 1);
 251        } else {
 252            v = extract32(ppc->sp, i, 1);
 253        }
 254        qemu_set_irq(ppc->ap[i], v);
 255    }
 256}
 257
 258static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
 259{
 260    int i;
 261
 262    ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
 263    for (i = 0; i < ppc->numports; i++) {
 264        qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
 265    }
 266    iotkit_secctl_update_ppc_ap(ppc);
 267}
 268
 269static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
 270{
 271    ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
 272    iotkit_secctl_update_ppc_ap(ppc);
 273}
 274
 275static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
 276{
 277    ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
 278    iotkit_secctl_update_ppc_ap(ppc);
 279}
 280
 281static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
 282{
 283    uint32_t value = ppc->parent->secppcintstat;
 284
 285    qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
 286}
 287
 288static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
 289{
 290    uint32_t value = ppc->parent->secppcinten;
 291
 292    qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
 293}
 294
 295static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
 296{
 297    int i;
 298
 299    for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
 300        qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
 301    }
 302}
 303
 304static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
 305{
 306    /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
 307    bool level = s->secmscintstat & s->secmscinten;
 308
 309    qemu_set_irq(s->msc_irq, level);
 310}
 311
 312static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
 313                                         uint64_t value,
 314                                         unsigned size, MemTxAttrs attrs)
 315{
 316    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
 317    uint32_t offset = addr;
 318    IoTKitSecCtlPPC *ppc;
 319
 320    trace_iotkit_secctl_s_write(offset, value, size);
 321
 322    if (size != 4) {
 323        /* Byte and halfword writes are ignored */
 324        qemu_log_mask(LOG_GUEST_ERROR,
 325                      "IotKit SecCtl S block write: bad size, ignored\n");
 326        return MEMTX_OK;
 327    }
 328
 329    switch (offset) {
 330    case A_NSCCFG:
 331        s->nsccfg = value & 3;
 332        qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
 333        break;
 334    case A_SECRESPCFG:
 335        value &= 1;
 336        s->secrespcfg = value;
 337        qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
 338        break;
 339    case A_SECPPCINTCLR:
 340        value &= 0x00f000f3;
 341        foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
 342        break;
 343    case A_SECPPCINTEN:
 344        s->secppcinten = value & 0x00f000f3;
 345        foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
 346        break;
 347    case A_BRGINTCLR:
 348        break;
 349    case A_BRGINTEN:
 350        s->brginten = value & 0xffff0000;
 351        break;
 352    case A_AHBNSPPCEXP0:
 353    case A_AHBNSPPCEXP1:
 354    case A_AHBNSPPCEXP2:
 355    case A_AHBNSPPCEXP3:
 356        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
 357        iotkit_secctl_ppc_ns_write(ppc, value);
 358        break;
 359    case A_APBNSPPC0:
 360    case A_APBNSPPC1:
 361        ppc = &s->apb[offset_to_ppc_idx(offset)];
 362        iotkit_secctl_ppc_ns_write(ppc, value);
 363        break;
 364    case A_APBNSPPCEXP0:
 365    case A_APBNSPPCEXP1:
 366    case A_APBNSPPCEXP2:
 367    case A_APBNSPPCEXP3:
 368        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
 369        iotkit_secctl_ppc_ns_write(ppc, value);
 370        break;
 371    case A_AHBSPPPCEXP0:
 372    case A_AHBSPPPCEXP1:
 373    case A_AHBSPPPCEXP2:
 374    case A_AHBSPPPCEXP3:
 375        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
 376        iotkit_secctl_ppc_sp_write(ppc, value);
 377        break;
 378    case A_APBSPPPC0:
 379    case A_APBSPPPC1:
 380        ppc = &s->apb[offset_to_ppc_idx(offset)];
 381        iotkit_secctl_ppc_sp_write(ppc, value);
 382        break;
 383    case A_APBSPPPCEXP0:
 384    case A_APBSPPPCEXP1:
 385    case A_APBSPPPCEXP2:
 386    case A_APBSPPPCEXP3:
 387        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
 388        iotkit_secctl_ppc_sp_write(ppc, value);
 389        break;
 390    case A_SECMSCINTCLR:
 391        iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
 392        break;
 393    case A_SECMSCINTEN:
 394        s->secmscinten = value;
 395        iotkit_secctl_update_msc_irq(s);
 396        break;
 397    case A_NSMSCEXP:
 398        s->nsmscexp = value;
 399        iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
 400        break;
 401    case A_SECMPCINTSTATUS:
 402    case A_SECPPCINTSTAT:
 403    case A_SECMSCINTSTAT:
 404    case A_BRGINTSTAT:
 405    case A_AHBNSPPC0:
 406    case A_AHBSPPPC0:
 407    case A_PID4:
 408    case A_PID5:
 409    case A_PID6:
 410    case A_PID7:
 411    case A_PID0:
 412    case A_PID1:
 413    case A_PID2:
 414    case A_PID3:
 415    case A_CID0:
 416    case A_CID1:
 417    case A_CID2:
 418    case A_CID3:
 419        qemu_log_mask(LOG_GUEST_ERROR,
 420                      "IoTKit SecCtl S block write: "
 421                      "read-only offset 0x%x\n", offset);
 422        break;
 423    default:
 424        qemu_log_mask(LOG_GUEST_ERROR,
 425                      "IotKit SecCtl S block write: bad offset 0x%x\n",
 426                      offset);
 427        break;
 428    }
 429
 430    return MEMTX_OK;
 431}
 432
 433static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
 434                                         uint64_t *pdata,
 435                                         unsigned size, MemTxAttrs attrs)
 436{
 437    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
 438    uint64_t r;
 439    uint32_t offset = addr & ~0x3;
 440
 441    switch (offset) {
 442    case A_AHBNSPPPC0:
 443        r = 0;
 444        break;
 445    case A_AHBNSPPPCEXP0:
 446    case A_AHBNSPPPCEXP1:
 447    case A_AHBNSPPPCEXP2:
 448    case A_AHBNSPPPCEXP3:
 449        r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
 450        break;
 451    case A_APBNSPPPC0:
 452    case A_APBNSPPPC1:
 453        r = s->apb[offset_to_ppc_idx(offset)].nsp;
 454        break;
 455    case A_APBNSPPPCEXP0:
 456    case A_APBNSPPPCEXP1:
 457    case A_APBNSPPPCEXP2:
 458    case A_APBNSPPPCEXP3:
 459        r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
 460        break;
 461    case A_PID4:
 462    case A_PID5:
 463    case A_PID6:
 464    case A_PID7:
 465    case A_PID0:
 466    case A_PID1:
 467    case A_PID2:
 468    case A_PID3:
 469    case A_CID0:
 470    case A_CID1:
 471    case A_CID2:
 472    case A_CID3:
 473        r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
 474        break;
 475    default:
 476        qemu_log_mask(LOG_GUEST_ERROR,
 477                      "IotKit SecCtl NS block write: bad offset 0x%x\n",
 478                      offset);
 479        r = 0;
 480        break;
 481    }
 482
 483    if (size != 4) {
 484        /* None of our registers are access-sensitive, so just pull the right
 485         * byte out of the word read result.
 486         */
 487        r = extract32(r, (addr & 3) * 8, size * 8);
 488    }
 489
 490    trace_iotkit_secctl_ns_read(offset, r, size);
 491    *pdata = r;
 492    return MEMTX_OK;
 493}
 494
 495static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
 496                                          uint64_t value,
 497                                          unsigned size, MemTxAttrs attrs)
 498{
 499    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
 500    uint32_t offset = addr;
 501    IoTKitSecCtlPPC *ppc;
 502
 503    trace_iotkit_secctl_ns_write(offset, value, size);
 504
 505    if (size != 4) {
 506        /* Byte and halfword writes are ignored */
 507        qemu_log_mask(LOG_GUEST_ERROR,
 508                      "IotKit SecCtl NS block write: bad size, ignored\n");
 509        return MEMTX_OK;
 510    }
 511
 512    switch (offset) {
 513    case A_AHBNSPPPCEXP0:
 514    case A_AHBNSPPPCEXP1:
 515    case A_AHBNSPPPCEXP2:
 516    case A_AHBNSPPPCEXP3:
 517        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
 518        iotkit_secctl_ppc_nsp_write(ppc, value);
 519        break;
 520    case A_APBNSPPPC0:
 521    case A_APBNSPPPC1:
 522        ppc = &s->apb[offset_to_ppc_idx(offset)];
 523        iotkit_secctl_ppc_nsp_write(ppc, value);
 524        break;
 525    case A_APBNSPPPCEXP0:
 526    case A_APBNSPPPCEXP1:
 527    case A_APBNSPPPCEXP2:
 528    case A_APBNSPPPCEXP3:
 529        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
 530        iotkit_secctl_ppc_nsp_write(ppc, value);
 531        break;
 532    case A_AHBNSPPPC0:
 533    case A_PID4:
 534    case A_PID5:
 535    case A_PID6:
 536    case A_PID7:
 537    case A_PID0:
 538    case A_PID1:
 539    case A_PID2:
 540    case A_PID3:
 541    case A_CID0:
 542    case A_CID1:
 543    case A_CID2:
 544    case A_CID3:
 545        qemu_log_mask(LOG_GUEST_ERROR,
 546                      "IoTKit SecCtl NS block write: "
 547                      "read-only offset 0x%x\n", offset);
 548        break;
 549    default:
 550        qemu_log_mask(LOG_GUEST_ERROR,
 551                      "IotKit SecCtl NS block write: bad offset 0x%x\n",
 552                      offset);
 553        break;
 554    }
 555
 556    return MEMTX_OK;
 557}
 558
 559static const MemoryRegionOps iotkit_secctl_s_ops = {
 560    .read_with_attrs = iotkit_secctl_s_read,
 561    .write_with_attrs = iotkit_secctl_s_write,
 562    .endianness = DEVICE_LITTLE_ENDIAN,
 563    .valid.min_access_size = 1,
 564    .valid.max_access_size = 4,
 565    .impl.min_access_size = 1,
 566    .impl.max_access_size = 4,
 567};
 568
 569static const MemoryRegionOps iotkit_secctl_ns_ops = {
 570    .read_with_attrs = iotkit_secctl_ns_read,
 571    .write_with_attrs = iotkit_secctl_ns_write,
 572    .endianness = DEVICE_LITTLE_ENDIAN,
 573    .valid.min_access_size = 1,
 574    .valid.max_access_size = 4,
 575    .impl.min_access_size = 1,
 576    .impl.max_access_size = 4,
 577};
 578
 579static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
 580{
 581    ppc->ns = 0;
 582    ppc->sp = 0;
 583    ppc->nsp = 0;
 584}
 585
 586static void iotkit_secctl_reset(DeviceState *dev)
 587{
 588    IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
 589
 590    s->secppcintstat = 0;
 591    s->secppcinten = 0;
 592    s->secrespcfg = 0;
 593    s->nsccfg = 0;
 594    s->brginten = 0;
 595
 596    foreach_ppc(s, iotkit_secctl_reset_ppc);
 597}
 598
 599static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
 600{
 601    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
 602
 603    s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
 604}
 605
 606static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
 607{
 608    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
 609
 610    s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
 611}
 612
 613static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
 614{
 615    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
 616
 617    s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
 618    iotkit_secctl_update_msc_irq(s);
 619}
 620
 621static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
 622{
 623    IoTKitSecCtlPPC *ppc = opaque;
 624    IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
 625    int irqbit = ppc->irq_bit_offset + n;
 626
 627    s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
 628}
 629
 630static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
 631                                   IoTKitSecCtlPPC *ppc,
 632                                   const char *name,
 633                                   int numports,
 634                                   int irq_bit_offset)
 635{
 636    char *gpioname;
 637    DeviceState *dev = DEVICE(s);
 638
 639    ppc->numports = numports;
 640    ppc->irq_bit_offset = irq_bit_offset;
 641    ppc->parent = s;
 642
 643    gpioname = g_strdup_printf("%s_nonsec", name);
 644    qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
 645    g_free(gpioname);
 646    gpioname = g_strdup_printf("%s_ap", name);
 647    qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
 648    g_free(gpioname);
 649    gpioname = g_strdup_printf("%s_irq_enable", name);
 650    qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
 651    g_free(gpioname);
 652    gpioname = g_strdup_printf("%s_irq_clear", name);
 653    qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
 654    g_free(gpioname);
 655    gpioname = g_strdup_printf("%s_irq_status", name);
 656    qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
 657                                        ppc, gpioname, 1);
 658    g_free(gpioname);
 659}
 660
 661static void iotkit_secctl_init(Object *obj)
 662{
 663    IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
 664    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 665    DeviceState *dev = DEVICE(obj);
 666    int i;
 667
 668    iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
 669                           IOTS_APB_PPC0_NUM_PORTS, 0);
 670    iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
 671                           IOTS_APB_PPC1_NUM_PORTS, 1);
 672
 673    for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
 674        IoTKitSecCtlPPC *ppc = &s->apbexp[i];
 675        char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
 676        iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
 677        g_free(ppcname);
 678    }
 679    for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
 680        IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
 681        char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
 682        iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
 683        g_free(ppcname);
 684    }
 685
 686    qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
 687    qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
 688
 689    qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
 690                            IOTS_NUM_MPC);
 691    qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
 692                            "mpcexp_status", IOTS_NUM_EXP_MPC);
 693
 694    qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
 695                            "mscexp_status", IOTS_NUM_EXP_MSC);
 696    qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
 697                             IOTS_NUM_EXP_MSC);
 698    qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
 699                             IOTS_NUM_EXP_MSC);
 700    qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
 701
 702    memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
 703                          s, "iotkit-secctl-s-regs", 0x1000);
 704    memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
 705                          s, "iotkit-secctl-ns-regs", 0x1000);
 706    sysbus_init_mmio(sbd, &s->s_regs);
 707    sysbus_init_mmio(sbd, &s->ns_regs);
 708}
 709
 710static const VMStateDescription iotkit_secctl_ppc_vmstate = {
 711    .name = "iotkit-secctl-ppc",
 712    .version_id = 1,
 713    .minimum_version_id = 1,
 714    .fields = (VMStateField[]) {
 715        VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
 716        VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
 717        VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
 718        VMSTATE_END_OF_LIST()
 719    }
 720};
 721
 722static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
 723    .name = "iotkit-secctl-mpcintstatus",
 724    .version_id = 1,
 725    .minimum_version_id = 1,
 726    .fields = (VMStateField[]) {
 727        VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
 728        VMSTATE_END_OF_LIST()
 729    }
 730};
 731
 732static bool needed_always(void *opaque)
 733{
 734    return true;
 735}
 736
 737static const VMStateDescription iotkit_secctl_msc_vmstate = {
 738    .name = "iotkit-secctl/msc",
 739    .version_id = 1,
 740    .minimum_version_id = 1,
 741    .needed = needed_always,
 742    .fields = (VMStateField[]) {
 743        VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
 744        VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
 745        VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
 746        VMSTATE_END_OF_LIST()
 747    }
 748};
 749
 750static const VMStateDescription iotkit_secctl_vmstate = {
 751    .name = "iotkit-secctl",
 752    .version_id = 1,
 753    .minimum_version_id = 1,
 754    .fields = (VMStateField[]) {
 755        VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
 756        VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
 757        VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
 758        VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
 759        VMSTATE_UINT32(brginten, IoTKitSecCtl),
 760        VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
 761                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
 762        VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
 763                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
 764        VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
 765                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
 766        VMSTATE_END_OF_LIST()
 767    },
 768    .subsections = (const VMStateDescription*[]) {
 769        &iotkit_secctl_mpcintstatus_vmstate,
 770        &iotkit_secctl_msc_vmstate,
 771        NULL
 772    },
 773};
 774
 775static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
 776{
 777    DeviceClass *dc = DEVICE_CLASS(klass);
 778
 779    dc->vmsd = &iotkit_secctl_vmstate;
 780    dc->reset = iotkit_secctl_reset;
 781}
 782
 783static const TypeInfo iotkit_secctl_info = {
 784    .name = TYPE_IOTKIT_SECCTL,
 785    .parent = TYPE_SYS_BUS_DEVICE,
 786    .instance_size = sizeof(IoTKitSecCtl),
 787    .instance_init = iotkit_secctl_init,
 788    .class_init = iotkit_secctl_class_init,
 789};
 790
 791static void iotkit_secctl_register_types(void)
 792{
 793    type_register_static(&iotkit_secctl_info);
 794}
 795
 796type_init(iotkit_secctl_register_types);
 797