qemu/hw/misc/xlnx-lpd-slcr-secure.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the LPDSLCRSecure
   3 *
   4 * Copyright (c) 2016 Greensocs.
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25#include "qemu/osdep.h"
  26#include "hw/sysbus.h"
  27#include "hw/register.h"
  28#include "qemu/bitops.h"
  29#include "qapi/qmp/qerror.h"
  30#include "qemu/log.h"
  31
  32#ifndef XILINX_LPD_SLCR_SECURE_ERR_DEBUG
  33#define XILINX_LPD_SLCR_SECURE_ERR_DEBUG 0
  34#endif
  35
  36#define TYPE_XILINX_LPD_SLCR_SECURE "xlnx.lpd-slcr-secure"
  37
  38#define XILINX_LPD_SLCR_SECURE(obj) \
  39     OBJECT_CHECK(LPDSLCRSecure, (obj), TYPE_XILINX_LPD_SLCR_SECURE)
  40
  41REG32(CTRL, 0x4)
  42    FIELD(CTRL, SLVERR_ENABLE, 1, 0)
  43REG32(ISR, 0x8)
  44    FIELD(ISR, ADDR_DECODE_ERR, 1, 0)
  45REG32(IMR, 0xc)
  46    FIELD(IMR, ADDR_DECODE_ERR, 1, 0)
  47REG32(IER, 0x10)
  48    FIELD(IER, ADDR_DECODE_ERR, 1, 0)
  49REG32(IDR, 0x14)
  50    FIELD(IDR, ADDR_DECODE_ERR, 1, 0)
  51REG32(ITR, 0x18)
  52    FIELD(ITR, ADDR_DECODE_ERR, 1, 0)
  53REG32(SLCR_RPU, 0x20)
  54    FIELD(SLCR_RPU, TZ_R5_0, 1, 0)
  55    FIELD(SLCR_RPU, TZ_R5_1, 1, 1)
  56REG32(SLCR_ADMA, 0x24)
  57    FIELD(SLCR_RPU, TZ, 1, 0)
  58REG32(SAFETY_CHK, 0x30)
  59REG32(SLCR_USB, 0x34)
  60    FIELD(SLCR_USB, TZ_USB3_0, 1, 0)
  61    FIELD(SLCR_USB, TZ_USB3_1, 1, 1)
  62
  63#define R_MAX (R_SLCR_USB + 1)
  64
  65typedef struct LPDSLCRSecure {
  66    SysBusDevice parent_obj;
  67    MemoryRegion iomem;
  68    qemu_irq irq_isr;
  69
  70    uint32_t regs[R_MAX];
  71    RegisterInfo regs_info[R_MAX];
  72} LPDSLCRSecure;
  73
  74static void isr_update_irq(LPDSLCRSecure *s)
  75{
  76    bool pending = s->regs[R_ISR] & ~s->regs[R_IMR];
  77    qemu_set_irq(s->irq_isr, pending);
  78}
  79
  80static void isr_postw(RegisterInfo *reg, uint64_t val64)
  81{
  82    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
  83    isr_update_irq(s);
  84}
  85
  86static uint64_t ier_prew(RegisterInfo *reg, uint64_t val64)
  87{
  88    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
  89    uint32_t val = val64;
  90
  91    s->regs[R_IMR] &= ~val;
  92    isr_update_irq(s);
  93    return 0;
  94}
  95
  96static uint64_t idr_prew(RegisterInfo *reg, uint64_t val64)
  97{
  98    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
  99    uint32_t val = val64;
 100
 101    s->regs[R_IMR] |= val;
 102    isr_update_irq(s);
 103    return 0;
 104}
 105
 106static uint64_t itr_prew(RegisterInfo *reg, uint64_t val64)
 107{
 108    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(reg->opaque);
 109    uint32_t val = val64;
 110
 111    s->regs[R_ISR] |= val;
 112    isr_update_irq(s);
 113    return 0;
 114}
 115
 116static RegisterAccessInfo lpd_slcr_secure_regs_info[] = {
 117    { .name = "CTRL",  .decode.addr = A_CTRL,
 118    },{ .name = "ISR",  .decode.addr = A_ISR,
 119        .w1c = 0x1,
 120        .post_write = isr_postw,
 121    },{ .name = "IMR",  .decode.addr = A_IMR,
 122        .reset = 0x1,
 123        .ro = 0x1,
 124    },{ .name = "IER",  .decode.addr = A_IER,
 125        .pre_write = ier_prew,
 126    },{ .name = "IDR",  .decode.addr = A_IDR,
 127        .pre_write = idr_prew,
 128    },{ .name = "ITR",  .decode.addr = A_ITR,
 129        .pre_write = itr_prew,
 130    },{ .name = "SLCR_RPU",   .decode.addr = A_SLCR_RPU,
 131    },{ .name = "SLCR_ADMA",  .decode.addr = A_SLCR_ADMA,
 132    },{ .name = "SAFETY_CHK", .decode.addr = A_SAFETY_CHK,
 133    },{ .name = "SLCR_USB",   .decode.addr = A_SLCR_USB,
 134    }
 135};
 136
 137static void lpd_slcr_secure_reset(DeviceState *dev)
 138{
 139    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(dev);
 140    unsigned int i;
 141
 142    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 143        register_reset(&s->regs_info[i]);
 144    }
 145
 146    isr_update_irq(s);
 147}
 148
 149static uint64_t lpd_slcr_secure_read(void *opaque, hwaddr addr, unsigned size)
 150{
 151    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(opaque);
 152    RegisterInfo *r = &s->regs_info[addr / 4];
 153
 154    if (!r->data) {
 155        qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
 156                 object_get_canonical_path(OBJECT(s)),
 157                 addr);
 158        return 0;
 159    }
 160    return register_read(r);
 161}
 162
 163static void lpd_slcr_secure_write(void *opaque, hwaddr addr, uint64_t value,
 164                                  unsigned size)
 165{
 166    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(opaque);
 167    RegisterInfo *r = &s->regs_info[addr / 4];
 168
 169    if (!r->data) {
 170        qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
 171                 object_get_canonical_path(OBJECT(s)),
 172                 addr, value);
 173        return;
 174    }
 175    register_write(r, value, ~0);
 176}
 177
 178static const MemoryRegionOps lpd_slcr_secure_ops = {
 179    .read = lpd_slcr_secure_read,
 180    .write = lpd_slcr_secure_write,
 181    .endianness = DEVICE_LITTLE_ENDIAN,
 182    .valid = {
 183        .min_access_size = 4,
 184        .max_access_size = 4,
 185    },
 186};
 187
 188static void lpd_slcr_secure_realize(DeviceState *dev, Error **errp)
 189{
 190    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(dev);
 191    const char *prefix = object_get_canonical_path(OBJECT(dev));
 192    unsigned int i;
 193
 194    for (i = 0; i < ARRAY_SIZE(lpd_slcr_secure_regs_info); ++i) {
 195        RegisterInfo *r =
 196                &s->regs_info[lpd_slcr_secure_regs_info[i].decode.addr / 4];
 197
 198        *r = (RegisterInfo) {
 199            .data = (uint8_t *)&s->regs[
 200                    lpd_slcr_secure_regs_info[i].decode.addr / 4],
 201            .data_size = sizeof(uint32_t),
 202            .access = &lpd_slcr_secure_regs_info[i],
 203            .debug = XILINX_LPD_SLCR_SECURE_ERR_DEBUG,
 204            .prefix = prefix,
 205            .opaque = s,
 206        };
 207    }
 208}
 209
 210static void lpd_slcr_secure_init(Object *obj)
 211{
 212    LPDSLCRSecure *s = XILINX_LPD_SLCR_SECURE(obj);
 213    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 214
 215    memory_region_init_io(&s->iomem, obj, &lpd_slcr_secure_ops, s,
 216                          TYPE_XILINX_LPD_SLCR_SECURE, R_MAX * 4);
 217    sysbus_init_mmio(sbd, &s->iomem);
 218    sysbus_init_irq(sbd, &s->irq_isr);
 219}
 220
 221static const VMStateDescription vmstate_lpd_slcr_secure = {
 222    .name = TYPE_XILINX_LPD_SLCR_SECURE,
 223    .version_id = 1,
 224    .minimum_version_id = 1,
 225    .minimum_version_id_old = 1,
 226    .fields = (VMStateField[]) {
 227        VMSTATE_UINT32_ARRAY(regs, LPDSLCRSecure, R_MAX),
 228        VMSTATE_END_OF_LIST(),
 229    }
 230};
 231
 232static void lpd_slcr_secure_class_init(ObjectClass *klass, void *data)
 233{
 234    DeviceClass *dc = DEVICE_CLASS(klass);
 235
 236    dc->reset = lpd_slcr_secure_reset;
 237    dc->realize = lpd_slcr_secure_realize;
 238    dc->vmsd = &vmstate_lpd_slcr_secure;
 239}
 240
 241static const TypeInfo lpd_slcr_secure_info = {
 242    .name          = TYPE_XILINX_LPD_SLCR_SECURE,
 243    .parent        = TYPE_SYS_BUS_DEVICE,
 244    .instance_size = sizeof(LPDSLCRSecure),
 245    .class_init    = lpd_slcr_secure_class_init,
 246    .instance_init = lpd_slcr_secure_init,
 247};
 248
 249static void lpd_slcr_secure_register_types(void)
 250{
 251    type_register_static(&lpd_slcr_secure_info);
 252}
 253
 254type_init(lpd_slcr_secure_register_types)
 255