qemu/hw/misc/iotkit-sysctl.c
<<
>>
Prefs
   1/*
   2 * ARM IoTKit system control element
   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/*
  13 * This is a model of the "system control element" which is part of the
  14 * Arm IoTKit and documented in
  15 * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
  16 * Specifically, it implements the "system control register" blocks.
  17 */
  18
  19#include "qemu/osdep.h"
  20#include "qemu/bitops.h"
  21#include "qemu/log.h"
  22#include "trace.h"
  23#include "qapi/error.h"
  24#include "sysemu/sysemu.h"
  25#include "hw/sysbus.h"
  26#include "hw/registerfields.h"
  27#include "hw/misc/iotkit-sysctl.h"
  28#include "target/arm/arm-powerctl.h"
  29#include "target/arm/cpu.h"
  30
  31REG32(SECDBGSTAT, 0x0)
  32REG32(SECDBGSET, 0x4)
  33REG32(SECDBGCLR, 0x8)
  34REG32(SCSECCTRL, 0xc)
  35REG32(FCLK_DIV, 0x10)
  36REG32(SYSCLK_DIV, 0x14)
  37REG32(CLOCK_FORCE, 0x18)
  38REG32(RESET_SYNDROME, 0x100)
  39REG32(RESET_MASK, 0x104)
  40REG32(SWRESET, 0x108)
  41    FIELD(SWRESET, SWRESETREQ, 9, 1)
  42REG32(GRETREG, 0x10c)
  43REG32(INITSVTOR0, 0x110)
  44REG32(INITSVTOR1, 0x114)
  45REG32(CPUWAIT, 0x118)
  46REG32(NMI_ENABLE, 0x11c) /* BUSWAIT in IoTKit */
  47REG32(WICCTRL, 0x120)
  48REG32(EWCTRL, 0x124)
  49REG32(PDCM_PD_SYS_SENSE, 0x200)
  50REG32(PDCM_PD_SRAM0_SENSE, 0x20c)
  51REG32(PDCM_PD_SRAM1_SENSE, 0x210)
  52REG32(PDCM_PD_SRAM2_SENSE, 0x214)
  53REG32(PDCM_PD_SRAM3_SENSE, 0x218)
  54REG32(PID4, 0xfd0)
  55REG32(PID5, 0xfd4)
  56REG32(PID6, 0xfd8)
  57REG32(PID7, 0xfdc)
  58REG32(PID0, 0xfe0)
  59REG32(PID1, 0xfe4)
  60REG32(PID2, 0xfe8)
  61REG32(PID3, 0xfec)
  62REG32(CID0, 0xff0)
  63REG32(CID1, 0xff4)
  64REG32(CID2, 0xff8)
  65REG32(CID3, 0xffc)
  66
  67/* PID/CID values */
  68static const int sysctl_id[] = {
  69    0x04, 0x00, 0x00, 0x00, /* PID4..PID7 */
  70    0x54, 0xb8, 0x0b, 0x00, /* PID0..PID3 */
  71    0x0d, 0xf0, 0x05, 0xb1, /* CID0..CID3 */
  72};
  73
  74/*
  75 * Set the initial secure vector table offset address for the core.
  76 * This will take effect when the CPU next resets.
  77 */
  78static void set_init_vtor(uint64_t cpuid, uint32_t vtor)
  79{
  80    Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid));
  81
  82    if (cpuobj) {
  83        if (object_property_find(cpuobj, "init-svtor", NULL)) {
  84            object_property_set_uint(cpuobj, vtor, "init-svtor", &error_abort);
  85        }
  86    }
  87}
  88
  89static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset,
  90                                    unsigned size)
  91{
  92    IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
  93    uint64_t r;
  94
  95    switch (offset) {
  96    case A_SECDBGSTAT:
  97        r = s->secure_debug;
  98        break;
  99    case A_SCSECCTRL:
 100        if (!s->is_sse200) {
 101            goto bad_offset;
 102        }
 103        r = s->scsecctrl;
 104        break;
 105    case A_FCLK_DIV:
 106        if (!s->is_sse200) {
 107            goto bad_offset;
 108        }
 109        r = s->fclk_div;
 110        break;
 111    case A_SYSCLK_DIV:
 112        if (!s->is_sse200) {
 113            goto bad_offset;
 114        }
 115        r = s->sysclk_div;
 116        break;
 117    case A_CLOCK_FORCE:
 118        if (!s->is_sse200) {
 119            goto bad_offset;
 120        }
 121        r = s->clock_force;
 122        break;
 123    case A_RESET_SYNDROME:
 124        r = s->reset_syndrome;
 125        break;
 126    case A_RESET_MASK:
 127        r = s->reset_mask;
 128        break;
 129    case A_GRETREG:
 130        r = s->gretreg;
 131        break;
 132    case A_INITSVTOR0:
 133        r = s->initsvtor0;
 134        break;
 135    case A_INITSVTOR1:
 136        if (!s->is_sse200) {
 137            goto bad_offset;
 138        }
 139        r = s->initsvtor1;
 140        break;
 141    case A_CPUWAIT:
 142        r = s->cpuwait;
 143        break;
 144    case A_NMI_ENABLE:
 145        /* In IoTKit this is named BUSWAIT but is marked reserved, R/O, zero */
 146        if (!s->is_sse200) {
 147            r = 0;
 148            break;
 149        }
 150        r = s->nmi_enable;
 151        break;
 152    case A_WICCTRL:
 153        r = s->wicctrl;
 154        break;
 155    case A_EWCTRL:
 156        if (!s->is_sse200) {
 157            goto bad_offset;
 158        }
 159        r = s->ewctrl;
 160        break;
 161    case A_PDCM_PD_SYS_SENSE:
 162        if (!s->is_sse200) {
 163            goto bad_offset;
 164        }
 165        r = s->pdcm_pd_sys_sense;
 166        break;
 167    case A_PDCM_PD_SRAM0_SENSE:
 168        if (!s->is_sse200) {
 169            goto bad_offset;
 170        }
 171        r = s->pdcm_pd_sram0_sense;
 172        break;
 173    case A_PDCM_PD_SRAM1_SENSE:
 174        if (!s->is_sse200) {
 175            goto bad_offset;
 176        }
 177        r = s->pdcm_pd_sram1_sense;
 178        break;
 179    case A_PDCM_PD_SRAM2_SENSE:
 180        if (!s->is_sse200) {
 181            goto bad_offset;
 182        }
 183        r = s->pdcm_pd_sram2_sense;
 184        break;
 185    case A_PDCM_PD_SRAM3_SENSE:
 186        if (!s->is_sse200) {
 187            goto bad_offset;
 188        }
 189        r = s->pdcm_pd_sram3_sense;
 190        break;
 191    case A_PID4 ... A_CID3:
 192        r = sysctl_id[(offset - A_PID4) / 4];
 193        break;
 194    case A_SECDBGSET:
 195    case A_SECDBGCLR:
 196    case A_SWRESET:
 197        qemu_log_mask(LOG_GUEST_ERROR,
 198                      "IoTKit SysCtl read: read of WO offset %x\n",
 199                      (int)offset);
 200        r = 0;
 201        break;
 202    default:
 203    bad_offset:
 204        qemu_log_mask(LOG_GUEST_ERROR,
 205                      "IoTKit SysCtl read: bad offset %x\n", (int)offset);
 206        r = 0;
 207        break;
 208    }
 209    trace_iotkit_sysctl_read(offset, r, size);
 210    return r;
 211}
 212
 213static void iotkit_sysctl_write(void *opaque, hwaddr offset,
 214                                 uint64_t value, unsigned size)
 215{
 216    IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
 217
 218    trace_iotkit_sysctl_write(offset, value, size);
 219
 220    /*
 221     * Most of the state here has to do with control of reset and
 222     * similar kinds of power up -- for instance the guest can ask
 223     * what the reason for the last reset was, or forbid reset for
 224     * some causes (like the non-secure watchdog). Most of this is
 225     * not relevant to QEMU, which doesn't really model anything other
 226     * than a full power-on reset.
 227     * We just model the registers as reads-as-written.
 228     */
 229
 230    switch (offset) {
 231    case A_RESET_SYNDROME:
 232        qemu_log_mask(LOG_UNIMP,
 233                      "IoTKit SysCtl RESET_SYNDROME unimplemented\n");
 234        s->reset_syndrome = value;
 235        break;
 236    case A_RESET_MASK:
 237        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl RESET_MASK unimplemented\n");
 238        s->reset_mask = value;
 239        break;
 240    case A_GRETREG:
 241        /*
 242         * General retention register, which is only reset by a power-on
 243         * reset. Technically this implementation is complete, since
 244         * QEMU only supports power-on resets...
 245         */
 246        s->gretreg = value;
 247        break;
 248    case A_INITSVTOR0:
 249        s->initsvtor0 = value;
 250        set_init_vtor(0, s->initsvtor0);
 251        break;
 252    case A_CPUWAIT:
 253        if ((s->cpuwait & 1) && !(value & 1)) {
 254            /* Powering up CPU 0 */
 255            arm_set_cpu_on_and_reset(0);
 256        }
 257        if ((s->cpuwait & 2) && !(value & 2)) {
 258            /* Powering up CPU 1 */
 259            arm_set_cpu_on_and_reset(1);
 260        }
 261        s->cpuwait = value;
 262        break;
 263    case A_WICCTRL:
 264        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl WICCTRL unimplemented\n");
 265        s->wicctrl = value;
 266        break;
 267    case A_SECDBGSET:
 268        /* write-1-to-set */
 269        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SECDBGSET unimplemented\n");
 270        s->secure_debug |= value;
 271        break;
 272    case A_SECDBGCLR:
 273        /* write-1-to-clear */
 274        s->secure_debug &= ~value;
 275        break;
 276    case A_SWRESET:
 277        /* One w/o bit to request a reset; all other bits reserved */
 278        if (value & R_SWRESET_SWRESETREQ_MASK) {
 279            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 280        }
 281        break;
 282    case A_SCSECCTRL:
 283        if (!s->is_sse200) {
 284            goto bad_offset;
 285        }
 286        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SCSECCTRL unimplemented\n");
 287        s->scsecctrl = value;
 288        break;
 289    case A_FCLK_DIV:
 290        if (!s->is_sse200) {
 291            goto bad_offset;
 292        }
 293        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl FCLK_DIV unimplemented\n");
 294        s->fclk_div = value;
 295        break;
 296    case A_SYSCLK_DIV:
 297        if (!s->is_sse200) {
 298            goto bad_offset;
 299        }
 300        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl SYSCLK_DIV unimplemented\n");
 301        s->sysclk_div = value;
 302        break;
 303    case A_CLOCK_FORCE:
 304        if (!s->is_sse200) {
 305            goto bad_offset;
 306        }
 307        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl CLOCK_FORCE unimplemented\n");
 308        s->clock_force = value;
 309        break;
 310    case A_INITSVTOR1:
 311        if (!s->is_sse200) {
 312            goto bad_offset;
 313        }
 314        s->initsvtor1 = value;
 315        set_init_vtor(1, s->initsvtor1);
 316        break;
 317    case A_EWCTRL:
 318        if (!s->is_sse200) {
 319            goto bad_offset;
 320        }
 321        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl EWCTRL unimplemented\n");
 322        s->ewctrl = value;
 323        break;
 324    case A_PDCM_PD_SYS_SENSE:
 325        if (!s->is_sse200) {
 326            goto bad_offset;
 327        }
 328        qemu_log_mask(LOG_UNIMP,
 329                      "IoTKit SysCtl PDCM_PD_SYS_SENSE unimplemented\n");
 330        s->pdcm_pd_sys_sense = value;
 331        break;
 332    case A_PDCM_PD_SRAM0_SENSE:
 333        if (!s->is_sse200) {
 334            goto bad_offset;
 335        }
 336        qemu_log_mask(LOG_UNIMP,
 337                      "IoTKit SysCtl PDCM_PD_SRAM0_SENSE unimplemented\n");
 338        s->pdcm_pd_sram0_sense = value;
 339        break;
 340    case A_PDCM_PD_SRAM1_SENSE:
 341        if (!s->is_sse200) {
 342            goto bad_offset;
 343        }
 344        qemu_log_mask(LOG_UNIMP,
 345                      "IoTKit SysCtl PDCM_PD_SRAM1_SENSE unimplemented\n");
 346        s->pdcm_pd_sram1_sense = value;
 347        break;
 348    case A_PDCM_PD_SRAM2_SENSE:
 349        if (!s->is_sse200) {
 350            goto bad_offset;
 351        }
 352        qemu_log_mask(LOG_UNIMP,
 353                      "IoTKit SysCtl PDCM_PD_SRAM2_SENSE unimplemented\n");
 354        s->pdcm_pd_sram2_sense = value;
 355        break;
 356    case A_PDCM_PD_SRAM3_SENSE:
 357        if (!s->is_sse200) {
 358            goto bad_offset;
 359        }
 360        qemu_log_mask(LOG_UNIMP,
 361                      "IoTKit SysCtl PDCM_PD_SRAM3_SENSE unimplemented\n");
 362        s->pdcm_pd_sram3_sense = value;
 363        break;
 364    case A_NMI_ENABLE:
 365        /* In IoTKit this is BUSWAIT: reserved, R/O, zero */
 366        if (!s->is_sse200) {
 367            goto ro_offset;
 368        }
 369        qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n");
 370        s->nmi_enable = value;
 371        break;
 372    case A_SECDBGSTAT:
 373    case A_PID4 ... A_CID3:
 374    ro_offset:
 375        qemu_log_mask(LOG_GUEST_ERROR,
 376                      "IoTKit SysCtl write: write of RO offset %x\n",
 377                      (int)offset);
 378        break;
 379    default:
 380    bad_offset:
 381        qemu_log_mask(LOG_GUEST_ERROR,
 382                      "IoTKit SysCtl write: bad offset %x\n", (int)offset);
 383        break;
 384    }
 385}
 386
 387static const MemoryRegionOps iotkit_sysctl_ops = {
 388    .read = iotkit_sysctl_read,
 389    .write = iotkit_sysctl_write,
 390    .endianness = DEVICE_LITTLE_ENDIAN,
 391    /* byte/halfword accesses are just zero-padded on reads and writes */
 392    .impl.min_access_size = 4,
 393    .impl.max_access_size = 4,
 394    .valid.min_access_size = 1,
 395    .valid.max_access_size = 4,
 396};
 397
 398static void iotkit_sysctl_reset(DeviceState *dev)
 399{
 400    IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
 401
 402    trace_iotkit_sysctl_reset();
 403    s->secure_debug = 0;
 404    s->reset_syndrome = 1;
 405    s->reset_mask = 0;
 406    s->gretreg = 0;
 407    s->initsvtor0 = s->initsvtor0_rst;
 408    s->initsvtor1 = s->initsvtor1_rst;
 409    s->cpuwait = s->cpuwait_rst;
 410    s->wicctrl = 0;
 411    s->scsecctrl = 0;
 412    s->fclk_div = 0;
 413    s->sysclk_div = 0;
 414    s->clock_force = 0;
 415    s->nmi_enable = 0;
 416    s->ewctrl = 0;
 417    s->pdcm_pd_sys_sense = 0x7f;
 418    s->pdcm_pd_sram0_sense = 0;
 419    s->pdcm_pd_sram1_sense = 0;
 420    s->pdcm_pd_sram2_sense = 0;
 421    s->pdcm_pd_sram3_sense = 0;
 422}
 423
 424static void iotkit_sysctl_init(Object *obj)
 425{
 426    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 427    IoTKitSysCtl *s = IOTKIT_SYSCTL(obj);
 428
 429    memory_region_init_io(&s->iomem, obj, &iotkit_sysctl_ops,
 430                          s, "iotkit-sysctl", 0x1000);
 431    sysbus_init_mmio(sbd, &s->iomem);
 432}
 433
 434static void iotkit_sysctl_realize(DeviceState *dev, Error **errp)
 435{
 436    IoTKitSysCtl *s = IOTKIT_SYSCTL(dev);
 437
 438    /* The top 4 bits of the SYS_VERSION register tell us if we're an SSE-200 */
 439    if (extract32(s->sys_version, 28, 4) == 2) {
 440        s->is_sse200 = true;
 441    }
 442}
 443
 444static bool sse200_needed(void *opaque)
 445{
 446    IoTKitSysCtl *s = IOTKIT_SYSCTL(opaque);
 447
 448    return s->is_sse200;
 449}
 450
 451static const VMStateDescription iotkit_sysctl_sse200_vmstate = {
 452    .name = "iotkit-sysctl/sse-200",
 453    .version_id = 1,
 454    .minimum_version_id = 1,
 455    .needed = sse200_needed,
 456    .fields = (VMStateField[]) {
 457        VMSTATE_UINT32(scsecctrl, IoTKitSysCtl),
 458        VMSTATE_UINT32(fclk_div, IoTKitSysCtl),
 459        VMSTATE_UINT32(sysclk_div, IoTKitSysCtl),
 460        VMSTATE_UINT32(clock_force, IoTKitSysCtl),
 461        VMSTATE_UINT32(initsvtor1, IoTKitSysCtl),
 462        VMSTATE_UINT32(nmi_enable, IoTKitSysCtl),
 463        VMSTATE_UINT32(pdcm_pd_sys_sense, IoTKitSysCtl),
 464        VMSTATE_UINT32(pdcm_pd_sram0_sense, IoTKitSysCtl),
 465        VMSTATE_UINT32(pdcm_pd_sram1_sense, IoTKitSysCtl),
 466        VMSTATE_UINT32(pdcm_pd_sram2_sense, IoTKitSysCtl),
 467        VMSTATE_UINT32(pdcm_pd_sram3_sense, IoTKitSysCtl),
 468        VMSTATE_END_OF_LIST()
 469    }
 470};
 471
 472static const VMStateDescription iotkit_sysctl_vmstate = {
 473    .name = "iotkit-sysctl",
 474    .version_id = 1,
 475    .minimum_version_id = 1,
 476    .fields = (VMStateField[]) {
 477        VMSTATE_UINT32(secure_debug, IoTKitSysCtl),
 478        VMSTATE_UINT32(reset_syndrome, IoTKitSysCtl),
 479        VMSTATE_UINT32(reset_mask, IoTKitSysCtl),
 480        VMSTATE_UINT32(gretreg, IoTKitSysCtl),
 481        VMSTATE_UINT32(initsvtor0, IoTKitSysCtl),
 482        VMSTATE_UINT32(cpuwait, IoTKitSysCtl),
 483        VMSTATE_UINT32(wicctrl, IoTKitSysCtl),
 484        VMSTATE_END_OF_LIST()
 485    },
 486    .subsections = (const VMStateDescription*[]) {
 487        &iotkit_sysctl_sse200_vmstate,
 488        NULL
 489    }
 490};
 491
 492static Property iotkit_sysctl_props[] = {
 493    DEFINE_PROP_UINT32("SYS_VERSION", IoTKitSysCtl, sys_version, 0),
 494    DEFINE_PROP_UINT32("CPUWAIT_RST", IoTKitSysCtl, cpuwait_rst, 0),
 495    DEFINE_PROP_UINT32("INITSVTOR0_RST", IoTKitSysCtl, initsvtor0_rst,
 496                       0x10000000),
 497    DEFINE_PROP_UINT32("INITSVTOR1_RST", IoTKitSysCtl, initsvtor1_rst,
 498                       0x10000000),
 499    DEFINE_PROP_END_OF_LIST()
 500};
 501
 502static void iotkit_sysctl_class_init(ObjectClass *klass, void *data)
 503{
 504    DeviceClass *dc = DEVICE_CLASS(klass);
 505
 506    dc->vmsd = &iotkit_sysctl_vmstate;
 507    dc->reset = iotkit_sysctl_reset;
 508    dc->props = iotkit_sysctl_props;
 509    dc->realize = iotkit_sysctl_realize;
 510}
 511
 512static const TypeInfo iotkit_sysctl_info = {
 513    .name = TYPE_IOTKIT_SYSCTL,
 514    .parent = TYPE_SYS_BUS_DEVICE,
 515    .instance_size = sizeof(IoTKitSysCtl),
 516    .instance_init = iotkit_sysctl_init,
 517    .class_init = iotkit_sysctl_class_init,
 518};
 519
 520static void iotkit_sysctl_register_types(void)
 521{
 522    type_register_static(&iotkit_sysctl_info);
 523}
 524
 525type_init(iotkit_sysctl_register_types);
 526