qemu/hw/misc/xilinx-smmu_reg.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the SMMU_REG System Memory Management Unit Configuration
   3 * and event registers
   4 *
   5 * Copyright (c) 2015 Xilinx Inc.
   6 *
   7 * Autogenerated by xregqemu.py 2015-04-05.
   8 *
   9 * Permission is hereby granted, free of charge, to any person obtaining a copy
  10 * of this software and associated documentation files (the "Software"), to deal
  11 * in the Software without restriction, including without limitation the rights
  12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13 * copies of the Software, and to permit persons to whom the Software is
  14 * furnished to do so, subject to the following conditions:
  15 *
  16 * The above copyright notice and this permission notice shall be included in
  17 * all copies or substantial portions of the Software.
  18 *
  19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25 * THE SOFTWARE.
  26 */
  27
  28#include "qemu/osdep.h"
  29#include "hw/sysbus.h"
  30#include "hw/register.h"
  31#include "qemu/bitops.h"
  32#include "qemu/log.h"
  33#include "hw/fdt_generic_util.h"
  34
  35#ifndef XILINX_SMMU_REG_ERR_DEBUG
  36#define XILINX_SMMU_REG_ERR_DEBUG 0
  37#endif
  38
  39#define TYPE_XILINX_SMMU_REG "xlnx.smmu-reg"
  40
  41#define XILINX_SMMU_REG(obj) \
  42     OBJECT_CHECK(SMMU_REG, (obj), TYPE_XILINX_SMMU_REG)
  43
  44REG32(MISC_CTRL, 0x0)
  45    FIELD(MISC_CTRL, SLVERR_ENABLE, 1, 0)
  46REG32(ISR_0, 0x10)
  47    FIELD(ISR_0, ADDR_DECODE_ERR, 1, 31)
  48    FIELD(ISR_0, GBL_FLT_IRPT_NS, 1, 4)
  49    FIELD(ISR_0, GBL_FLT_IRPT_S, 1, 3)
  50    FIELD(ISR_0, COMB_PERF_IRPT_TBU, 1, 2)
  51    FIELD(ISR_0, COMB_IRPT_S, 1, 1)
  52    FIELD(ISR_0, COMB_IRPT_NS, 1, 0)
  53REG32(IMR_0, 0x14)
  54    FIELD(IMR_0, ADDR_DECODE_ERR, 1, 31)
  55    FIELD(IMR_0, GBL_FLT_IRPT_NS, 1, 4)
  56    FIELD(IMR_0, GBL_FLT_IRPT_S, 1, 3)
  57    FIELD(IMR_0, COMB_PERF_IRPT_TBU, 1, 2)
  58    FIELD(IMR_0, COMB_IRPT_S, 1, 1)
  59    FIELD(IMR_0, COMB_IRPT_NS, 1, 0)
  60REG32(IER_0, 0x18)
  61    FIELD(IER_0, ADDR_DECODE_ERR, 1, 31)
  62    FIELD(IER_0, GBL_FLT_IRPT_NS, 1, 4)
  63    FIELD(IER_0, GBL_FLT_IRPT_S, 1, 3)
  64    FIELD(IER_0, COMB_PERF_IRPT_TBU, 1, 2)
  65    FIELD(IER_0, COMB_IRPT_S, 1, 1)
  66    FIELD(IER_0, COMB_IRPT_NS, 1, 0)
  67REG32(IDR_0, 0x1c)
  68    FIELD(IDR_0, ADDR_DECODE_ERR, 1, 31)
  69    FIELD(IDR_0, GBL_FLT_IRPT_NS, 1, 4)
  70    FIELD(IDR_0, GBL_FLT_IRPT_S, 1, 3)
  71    FIELD(IDR_0, COMB_PERF_IRPT_TBU, 1, 2)
  72    FIELD(IDR_0, COMB_IRPT_S, 1, 1)
  73    FIELD(IDR_0, COMB_IRPT_NS, 1, 0)
  74REG32(ITR_0, 0x20)
  75    FIELD(ITR_0, ADDR_DECODE_ERR, 1, 31)
  76    FIELD(ITR_0, GBL_FLT_IRPT_NS, 1, 4)
  77    FIELD(ITR_0, GBL_FLT_IRPT_S, 1, 3)
  78    FIELD(ITR_0, COMB_PERF_IRPT_TBU, 1, 2)
  79    FIELD(ITR_0, COMB_IRPT_S, 1, 1)
  80    FIELD(ITR_0, COMB_IRPT_NS, 1, 0)
  81REG32(QREQN, 0x40)
  82    FIELD(QREQN, TBU_TBU5_5_CG, 1, 14)
  83    FIELD(QREQN, TBU_TBU5_5_PD, 1, 13)
  84    FIELD(QREQN, TBU_TBU4_4_CG, 1, 12)
  85    FIELD(QREQN, TBU_TBU4_4_PD, 1, 11)
  86    FIELD(QREQN, TBU_TBU3_3_CG, 1, 10)
  87    FIELD(QREQN, TBU_TBU3_3_PD, 1, 9)
  88    FIELD(QREQN, PD_MST_BR_TBU2_2, 1, 8)
  89    FIELD(QREQN, PD_SLV_BR_TBU2_2, 1, 7)
  90    FIELD(QREQN, TBU_TBU2_2_CG, 1, 6)
  91    FIELD(QREQN, TBU_TBU2_2_PD, 1, 5)
  92    FIELD(QREQN, TBU_TBU1_1_CG, 1, 4)
  93    FIELD(QREQN, TBU_TBU1_1_PD, 1, 3)
  94    FIELD(QREQN, TBU_TBU0_0_CG, 1, 2)
  95    FIELD(QREQN, TBU_TBU0_0_PD, 1, 1)
  96    FIELD(QREQN, TCU, 1, 0)
  97REG32(MISC, 0x54)
  98    FIELD(MISC, SPNIDEN, 1, 12)
  99    FIELD(MISC, ARQOSARB, 4, 8)
 100    FIELD(MISC, AWAKEUP_PROG, 1, 7)
 101    FIELD(MISC, EMAS, 1, 6)
 102    FIELD(MISC, EMAW, 2, 4)
 103    FIELD(MISC, EMA, 3, 1)
 104REG32(CONFIG_SIGNALS, 0x58)
 105    FIELD(CONFIG_SIGNALS, CFG_NORMALIZE, 1, 1)
 106REG32(ECO_INFO, 0x100)
 107    FIELD(ECO_INFO, ECOREVNUM, 4, 0)
 108REG32(ECO_0, 0x104)
 109REG32(ECO_1, 0x108)
 110
 111#define R_MAX (R_ECO_1 + 1)
 112
 113typedef struct SMMU_REG {
 114    SysBusDevice parent_obj;
 115    MemoryRegion iomem;
 116    qemu_irq irq_imr_0;
 117
 118    uint32_t irq_src;
 119
 120    uint32_t regs[R_MAX];
 121    RegisterInfo regs_info[R_MAX];
 122} SMMU_REG;
 123
 124static void imr_0_update_irq(SMMU_REG *s)
 125{
 126    bool global_irq;
 127    bool ctxt_irq;
 128    bool pending;
 129
 130    global_irq = s->irq_src & 1;
 131    ctxt_irq = s->irq_src & (~1);
 132    s->regs[R_ISR_0] |= ctxt_irq << 0;
 133    s->regs[R_ISR_0] |= ctxt_irq << 1;
 134    s->regs[R_ISR_0] |= global_irq << 3;
 135    s->regs[R_ISR_0] |= global_irq << 4;
 136
 137    pending = s->regs[R_ISR_0] & ~s->regs[R_IMR_0];
 138    qemu_set_irq(s->irq_imr_0, pending);
 139}
 140
 141static void isr_0_postw(RegisterInfo *reg, uint64_t val64)
 142{
 143    SMMU_REG *s = XILINX_SMMU_REG(reg->opaque);
 144    imr_0_update_irq(s);
 145}
 146
 147static uint64_t ier_0_prew(RegisterInfo *reg, uint64_t val64)
 148{
 149    SMMU_REG *s = XILINX_SMMU_REG(reg->opaque);
 150    uint32_t val = val64;
 151
 152    s->regs[R_IMR_0] &= ~val;
 153    imr_0_update_irq(s);
 154    return 0;
 155}
 156
 157static uint64_t idr_0_prew(RegisterInfo *reg, uint64_t val64)
 158{
 159    SMMU_REG *s = XILINX_SMMU_REG(reg->opaque);
 160    uint32_t val = val64;
 161
 162    s->regs[R_IMR_0] |= val;
 163    imr_0_update_irq(s);
 164    return 0;
 165}
 166
 167static uint64_t itr_0_prew(RegisterInfo *reg, uint64_t val64)
 168{
 169    SMMU_REG *s = XILINX_SMMU_REG(reg->opaque);
 170    uint32_t val = val64;
 171
 172    s->regs[R_ISR_0] |= val;
 173    imr_0_update_irq(s);
 174    return 0;
 175}
 176
 177static RegisterAccessInfo smmu_reg_regs_info[] = {
 178    {   .name = "MISC_CTRL",  .decode.addr = A_MISC_CTRL,
 179    },{ .name = "ISR_0",  .decode.addr = A_ISR_0,
 180        .rsvd = 0x7fffffe0,
 181        .ro = 0x7fffffe0,
 182        .w1c = 0x8000001f,
 183        .post_write = isr_0_postw,
 184    },{ .name = "IMR_0",  .decode.addr = A_IMR_0,
 185        .reset = 0x8000001f,
 186        .rsvd = 0x7fffffe0,
 187        .ro = 0x7fffffff,
 188        .w1c = 0x80000000,
 189    },{ .name = "IER_0",  .decode.addr = A_IER_0,
 190        .rsvd = 0x7fffffe0,
 191        .ro = 0x7fffffe0,
 192        .w1c = 0x80000000,
 193        .pre_write = ier_0_prew,
 194    },{ .name = "IDR_0",  .decode.addr = A_IDR_0,
 195        .rsvd = 0x7fffffe0,
 196        .ro = 0x7fffffe0,
 197        .w1c = 0x80000000,
 198        .pre_write = idr_0_prew,
 199    },{ .name = "ITR_0",  .decode.addr = A_ITR_0,
 200        .rsvd = 0x7fffffe0,
 201        .ro = 0x7fffffe0,
 202        .w1c = 0x80000000,
 203        .pre_write = itr_0_prew,
 204    },{ .name = "QREQN",  .decode.addr = A_QREQN,
 205        .reset = 0x7fff,
 206        .rsvd = 0xffff8000,
 207    },{ .name = "MISC",  .decode.addr = A_MISC,
 208        .reset = 0x16,
 209        .rsvd = 0xffffe001,
 210        .ro = 0xf00,
 211    },{ .name = "CONFIG_SIGNALS",  .decode.addr = A_CONFIG_SIGNALS,
 212        .rsvd = 0xfffffffd,
 213    },{ .name = "ECO_INFO",  .decode.addr = A_ECO_INFO,
 214    },{ .name = "ECO_0",  .decode.addr = A_ECO_0,
 215    },{ .name = "ECO_1",  .decode.addr = A_ECO_1,
 216        .reset = 0xffffffff,
 217    }
 218};
 219
 220static void smmu_reg_reset(DeviceState *dev)
 221{
 222    SMMU_REG *s = XILINX_SMMU_REG(dev);
 223    unsigned int i;
 224
 225    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 226        register_reset(&s->regs_info[i]);
 227    }
 228
 229    imr_0_update_irq(s);
 230}
 231
 232static uint64_t smmu_reg_read(void *opaque, hwaddr addr, unsigned size)
 233{
 234    SMMU_REG *s = XILINX_SMMU_REG(opaque);
 235    RegisterInfo *r = &s->regs_info[addr / 4];
 236
 237    if (!r->data) {
 238        qemu_log("%s: Decode error: read from %" HWADDR_PRIx "\n",
 239                 object_get_canonical_path(OBJECT(s)),
 240                 addr);
 241        return 0;
 242    }
 243    return register_read(r);
 244}
 245
 246static void smmu_reg_write(void *opaque, hwaddr addr, uint64_t value,
 247                      unsigned size)
 248{
 249    SMMU_REG *s = XILINX_SMMU_REG(opaque);
 250    RegisterInfo *r = &s->regs_info[addr / 4];
 251
 252    if (!r->data) {
 253        qemu_log("%s: Decode error: write to %" HWADDR_PRIx "=%" PRIx64 "\n",
 254                 object_get_canonical_path(OBJECT(s)),
 255                 addr, value);
 256        return;
 257    }
 258    register_write(r, value, ~0);
 259}
 260
 261static const MemoryRegionOps smmu_reg_ops = {
 262    .read = smmu_reg_read,
 263    .write = smmu_reg_write,
 264    .endianness = DEVICE_LITTLE_ENDIAN,
 265    .valid = {
 266        .min_access_size = 4,
 267        .max_access_size = 4,
 268    },
 269};
 270
 271static void irq_handler(void *opaque, int irq, int level)
 272{
 273    SMMU_REG *s = XILINX_SMMU_REG(opaque);
 274
 275    s->irq_src &= ~(1 << irq);
 276    s->irq_src |= level << irq;
 277    imr_0_update_irq(s);
 278}
 279
 280static void smmu_reg_realize(DeviceState *dev, Error **errp)
 281{
 282    SMMU_REG *s = XILINX_SMMU_REG(dev);
 283    const char *prefix = object_get_canonical_path(OBJECT(dev));
 284    unsigned int i;
 285
 286    for (i = 0; i < ARRAY_SIZE(smmu_reg_regs_info); ++i) {
 287        RegisterInfo *r = &s->regs_info[smmu_reg_regs_info[i].decode.addr/4];
 288
 289        *r = (RegisterInfo) {
 290            .data = (uint8_t *)&s->regs[
 291                    smmu_reg_regs_info[i].decode.addr/4],
 292            .data_size = sizeof(uint32_t),
 293            .access = &smmu_reg_regs_info[i],
 294            .debug = XILINX_SMMU_REG_ERR_DEBUG,
 295            .prefix = prefix,
 296            .opaque = s,
 297        };
 298    }
 299
 300    qdev_init_gpio_in(dev, irq_handler, 17);
 301}
 302
 303static void smmu_reg_init(Object *obj)
 304{
 305    SMMU_REG *s = XILINX_SMMU_REG(obj);
 306    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 307
 308    memory_region_init_io(&s->iomem, obj, &smmu_reg_ops, s,
 309                          TYPE_XILINX_SMMU_REG, R_MAX * 4);
 310    sysbus_init_mmio(sbd, &s->iomem);
 311    sysbus_init_irq(sbd, &s->irq_imr_0);
 312}
 313
 314static int smmu_reg_fdt_get_irq(FDTGenericIntc *obj, qemu_irq *irqs,
 315                                uint32_t *cells, int ncells, int max,
 316                                Error **errp)
 317{
 318    /* FIXME: Add Error checking */
 319    (*irqs) = qdev_get_gpio_in(DEVICE(obj), cells[0]);
 320    return 1;
 321};
 322
 323static const VMStateDescription vmstate_smmu_reg = {
 324    .name = TYPE_XILINX_SMMU_REG,
 325    .version_id = 1,
 326    .minimum_version_id = 1,
 327    .minimum_version_id_old = 1,
 328    .fields = (VMStateField[]) {
 329        VMSTATE_UINT32_ARRAY(regs, SMMU_REG, R_MAX),
 330        VMSTATE_END_OF_LIST(),
 331    }
 332};
 333
 334static void smmu_reg_class_init(ObjectClass *klass, void *data)
 335{
 336    DeviceClass *dc = DEVICE_CLASS(klass);
 337    FDTGenericIntcClass *fgic = FDT_GENERIC_INTC_CLASS(klass);
 338
 339    dc->reset = smmu_reg_reset;
 340    dc->realize = smmu_reg_realize;
 341    dc->vmsd = &vmstate_smmu_reg;
 342    fgic->get_irq = smmu_reg_fdt_get_irq;
 343}
 344
 345static const TypeInfo smmu_reg_info = {
 346    .name          = TYPE_XILINX_SMMU_REG,
 347    .parent        = TYPE_SYS_BUS_DEVICE,
 348    .instance_size = sizeof(SMMU_REG),
 349    .class_init    = smmu_reg_class_init,
 350    .instance_init = smmu_reg_init,
 351    .interfaces = (InterfaceInfo[]) {
 352        { TYPE_FDT_GENERIC_INTC },
 353        { }
 354    },
 355};
 356
 357static void smmu_reg_register_types(void)
 358{
 359    type_register_static(&smmu_reg_info);
 360}
 361
 362type_init(smmu_reg_register_types)
 363