qemu/hw/misc/xlnx-versal-xramc.c
<<
>>
Prefs
   1/*
   2 * QEMU model of the Xilinx XRAM Controller.
   3 *
   4 * Copyright (c) 2021 Xilinx Inc.
   5 * SPDX-License-Identifier: GPL-2.0-or-later
   6 * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
   7 */
   8
   9#include "qemu/osdep.h"
  10#include "qemu/units.h"
  11#include "qapi/error.h"
  12#include "migration/vmstate.h"
  13#include "hw/sysbus.h"
  14#include "hw/register.h"
  15#include "hw/qdev-properties.h"
  16#include "hw/irq.h"
  17#include "hw/misc/xlnx-versal-xramc.h"
  18
  19#ifndef XLNX_XRAM_CTRL_ERR_DEBUG
  20#define XLNX_XRAM_CTRL_ERR_DEBUG 0
  21#endif
  22
  23static void xram_update_irq(XlnxXramCtrl *s)
  24{
  25    bool pending = s->regs[R_XRAM_ISR] & ~s->regs[R_XRAM_IMR];
  26    qemu_set_irq(s->irq, pending);
  27}
  28
  29static void xram_isr_postw(RegisterInfo *reg, uint64_t val64)
  30{
  31    XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
  32    xram_update_irq(s);
  33}
  34
  35static uint64_t xram_ien_prew(RegisterInfo *reg, uint64_t val64)
  36{
  37    XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
  38    uint32_t val = val64;
  39
  40    s->regs[R_XRAM_IMR] &= ~val;
  41    xram_update_irq(s);
  42    return 0;
  43}
  44
  45static uint64_t xram_ids_prew(RegisterInfo *reg, uint64_t val64)
  46{
  47    XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
  48    uint32_t val = val64;
  49
  50    s->regs[R_XRAM_IMR] |= val;
  51    xram_update_irq(s);
  52    return 0;
  53}
  54
  55static const RegisterAccessInfo xram_ctrl_regs_info[] = {
  56    {   .name = "XRAM_ERR_CTRL",  .addr = A_XRAM_ERR_CTRL,
  57        .reset = 0xf,
  58        .rsvd = 0xfffffff0,
  59    },{ .name = "XRAM_ISR",  .addr = A_XRAM_ISR,
  60        .rsvd = 0xfffff800,
  61        .w1c = 0x7ff,
  62        .post_write = xram_isr_postw,
  63    },{ .name = "XRAM_IMR",  .addr = A_XRAM_IMR,
  64        .reset = 0x7ff,
  65        .rsvd = 0xfffff800,
  66        .ro = 0x7ff,
  67    },{ .name = "XRAM_IEN",  .addr = A_XRAM_IEN,
  68        .rsvd = 0xfffff800,
  69        .pre_write = xram_ien_prew,
  70    },{ .name = "XRAM_IDS",  .addr = A_XRAM_IDS,
  71        .rsvd = 0xfffff800,
  72        .pre_write = xram_ids_prew,
  73    },{ .name = "XRAM_ECC_CNTL",  .addr = A_XRAM_ECC_CNTL,
  74        .rsvd = 0xfffffff8,
  75    },{ .name = "XRAM_CLR_EXE",  .addr = A_XRAM_CLR_EXE,
  76        .rsvd = 0xffffff00,
  77    },{ .name = "XRAM_CE_FFA",  .addr = A_XRAM_CE_FFA,
  78        .rsvd = 0xfff00000,
  79        .ro = 0xfffff,
  80    },{ .name = "XRAM_CE_FFD0",  .addr = A_XRAM_CE_FFD0,
  81        .ro = 0xffffffff,
  82    },{ .name = "XRAM_CE_FFD1",  .addr = A_XRAM_CE_FFD1,
  83        .ro = 0xffffffff,
  84    },{ .name = "XRAM_CE_FFD2",  .addr = A_XRAM_CE_FFD2,
  85        .ro = 0xffffffff,
  86    },{ .name = "XRAM_CE_FFD3",  .addr = A_XRAM_CE_FFD3,
  87        .ro = 0xffffffff,
  88    },{ .name = "XRAM_CE_FFE",  .addr = A_XRAM_CE_FFE,
  89        .rsvd = 0xffff0000,
  90        .ro = 0xffff,
  91    },{ .name = "XRAM_UE_FFA",  .addr = A_XRAM_UE_FFA,
  92        .rsvd = 0xfff00000,
  93        .ro = 0xfffff,
  94    },{ .name = "XRAM_UE_FFD0",  .addr = A_XRAM_UE_FFD0,
  95        .ro = 0xffffffff,
  96    },{ .name = "XRAM_UE_FFD1",  .addr = A_XRAM_UE_FFD1,
  97        .ro = 0xffffffff,
  98    },{ .name = "XRAM_UE_FFD2",  .addr = A_XRAM_UE_FFD2,
  99        .ro = 0xffffffff,
 100    },{ .name = "XRAM_UE_FFD3",  .addr = A_XRAM_UE_FFD3,
 101        .ro = 0xffffffff,
 102    },{ .name = "XRAM_UE_FFE",  .addr = A_XRAM_UE_FFE,
 103        .rsvd = 0xffff0000,
 104        .ro = 0xffff,
 105    },{ .name = "XRAM_FI_D0",  .addr = A_XRAM_FI_D0,
 106    },{ .name = "XRAM_FI_D1",  .addr = A_XRAM_FI_D1,
 107    },{ .name = "XRAM_FI_D2",  .addr = A_XRAM_FI_D2,
 108    },{ .name = "XRAM_FI_D3",  .addr = A_XRAM_FI_D3,
 109    },{ .name = "XRAM_FI_SY",  .addr = A_XRAM_FI_SY,
 110        .rsvd = 0xffff0000,
 111    },{ .name = "XRAM_RMW_UE_FFA",  .addr = A_XRAM_RMW_UE_FFA,
 112        .rsvd = 0xfff00000,
 113        .ro = 0xfffff,
 114    },{ .name = "XRAM_FI_CNTR",  .addr = A_XRAM_FI_CNTR,
 115        .rsvd = 0xff000000,
 116    },{ .name = "XRAM_IMP",  .addr = A_XRAM_IMP,
 117        .reset = 0x4,
 118        .rsvd = 0xfffffff0,
 119        .ro = 0xf,
 120    },{ .name = "XRAM_PRDY_DBG",  .addr = A_XRAM_PRDY_DBG,
 121        .reset = 0xffff,
 122        .rsvd = 0xffff0000,
 123        .ro = 0xffff,
 124    },{ .name = "XRAM_SAFETY_CHK",  .addr = A_XRAM_SAFETY_CHK,
 125    }
 126};
 127
 128static void xram_ctrl_reset_enter(Object *obj, ResetType type)
 129{
 130    XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 131    unsigned int i;
 132
 133    for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
 134        register_reset(&s->regs_info[i]);
 135    }
 136
 137    ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
 138}
 139
 140static void xram_ctrl_reset_hold(Object *obj)
 141{
 142    XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 143
 144    xram_update_irq(s);
 145}
 146
 147static const MemoryRegionOps xram_ctrl_ops = {
 148    .read = register_read_memory,
 149    .write = register_write_memory,
 150    .endianness = DEVICE_LITTLE_ENDIAN,
 151    .valid = {
 152        .min_access_size = 4,
 153        .max_access_size = 4,
 154    },
 155};
 156
 157static void xram_ctrl_realize(DeviceState *dev, Error **errp)
 158{
 159    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 160    XlnxXramCtrl *s = XLNX_XRAM_CTRL(dev);
 161
 162    switch (s->cfg.size) {
 163    case 64 * KiB:
 164        s->cfg.encoded_size = 0;
 165        break;
 166    case 128 * KiB:
 167        s->cfg.encoded_size = 1;
 168        break;
 169    case 256 * KiB:
 170        s->cfg.encoded_size = 2;
 171        break;
 172    case 512 * KiB:
 173        s->cfg.encoded_size = 3;
 174        break;
 175    case 1 * MiB:
 176        s->cfg.encoded_size = 4;
 177        break;
 178    default:
 179        error_setg(errp, "Unsupported XRAM size %" PRId64, s->cfg.size);
 180        return;
 181    }
 182
 183    memory_region_init_ram(&s->ram, OBJECT(s),
 184                           object_get_canonical_path_component(OBJECT(s)),
 185                           s->cfg.size, &error_fatal);
 186    sysbus_init_mmio(sbd, &s->ram);
 187}
 188
 189static void xram_ctrl_init(Object *obj)
 190{
 191    XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 192    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 193
 194    s->reg_array =
 195        register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
 196                              ARRAY_SIZE(xram_ctrl_regs_info),
 197                              s->regs_info, s->regs,
 198                              &xram_ctrl_ops,
 199                              XLNX_XRAM_CTRL_ERR_DEBUG,
 200                              XRAM_CTRL_R_MAX * 4);
 201    sysbus_init_mmio(sbd, &s->reg_array->mem);
 202    sysbus_init_irq(sbd, &s->irq);
 203}
 204
 205static void xram_ctrl_finalize(Object *obj)
 206{
 207    XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
 208    register_finalize_block(s->reg_array);
 209}
 210
 211static const VMStateDescription vmstate_xram_ctrl = {
 212    .name = TYPE_XLNX_XRAM_CTRL,
 213    .version_id = 1,
 214    .minimum_version_id = 1,
 215    .fields = (VMStateField[]) {
 216        VMSTATE_UINT32_ARRAY(regs, XlnxXramCtrl, XRAM_CTRL_R_MAX),
 217        VMSTATE_END_OF_LIST(),
 218    }
 219};
 220
 221static Property xram_ctrl_properties[] = {
 222    DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
 223    DEFINE_PROP_END_OF_LIST(),
 224};
 225
 226static void xram_ctrl_class_init(ObjectClass *klass, void *data)
 227{
 228    ResettableClass *rc = RESETTABLE_CLASS(klass);
 229    DeviceClass *dc = DEVICE_CLASS(klass);
 230
 231    dc->realize = xram_ctrl_realize;
 232    dc->vmsd = &vmstate_xram_ctrl;
 233    device_class_set_props(dc, xram_ctrl_properties);
 234
 235    rc->phases.enter = xram_ctrl_reset_enter;
 236    rc->phases.hold = xram_ctrl_reset_hold;
 237}
 238
 239static const TypeInfo xram_ctrl_info = {
 240    .name              = TYPE_XLNX_XRAM_CTRL,
 241    .parent            = TYPE_SYS_BUS_DEVICE,
 242    .instance_size     = sizeof(XlnxXramCtrl),
 243    .class_init        = xram_ctrl_class_init,
 244    .instance_init     = xram_ctrl_init,
 245    .instance_finalize = xram_ctrl_finalize,
 246};
 247
 248static void xram_ctrl_register_types(void)
 249{
 250    type_register_static(&xram_ctrl_info);
 251}
 252
 253type_init(xram_ctrl_register_types)
 254