xref: /openbmc/qemu/hw/misc/xlnx-versal-xramc.c (revision 83baec642a13a69398a2643a1f905606c13cd363)
19f617635SEdgar E. Iglesias /*
29f617635SEdgar E. Iglesias  * QEMU model of the Xilinx XRAM Controller.
39f617635SEdgar E. Iglesias  *
49f617635SEdgar E. Iglesias  * Copyright (c) 2021 Xilinx Inc.
59f617635SEdgar E. Iglesias  * SPDX-License-Identifier: GPL-2.0-or-later
69f617635SEdgar E. Iglesias  * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
79f617635SEdgar E. Iglesias  */
89f617635SEdgar E. Iglesias 
99f617635SEdgar E. Iglesias #include "qemu/osdep.h"
109f617635SEdgar E. Iglesias #include "qemu/units.h"
119f617635SEdgar E. Iglesias #include "qapi/error.h"
129f617635SEdgar E. Iglesias #include "migration/vmstate.h"
139f617635SEdgar E. Iglesias #include "hw/sysbus.h"
149f617635SEdgar E. Iglesias #include "hw/register.h"
159f617635SEdgar E. Iglesias #include "hw/qdev-properties.h"
169f617635SEdgar E. Iglesias #include "hw/irq.h"
179f617635SEdgar E. Iglesias #include "hw/misc/xlnx-versal-xramc.h"
189f617635SEdgar E. Iglesias 
199f617635SEdgar E. Iglesias #ifndef XLNX_XRAM_CTRL_ERR_DEBUG
209f617635SEdgar E. Iglesias #define XLNX_XRAM_CTRL_ERR_DEBUG 0
219f617635SEdgar E. Iglesias #endif
229f617635SEdgar E. Iglesias 
xram_update_irq(XlnxXramCtrl * s)239f617635SEdgar E. Iglesias static void xram_update_irq(XlnxXramCtrl *s)
249f617635SEdgar E. Iglesias {
259f617635SEdgar E. Iglesias     bool pending = s->regs[R_XRAM_ISR] & ~s->regs[R_XRAM_IMR];
269f617635SEdgar E. Iglesias     qemu_set_irq(s->irq, pending);
279f617635SEdgar E. Iglesias }
289f617635SEdgar E. Iglesias 
xram_isr_postw(RegisterInfo * reg,uint64_t val64)299f617635SEdgar E. Iglesias static void xram_isr_postw(RegisterInfo *reg, uint64_t val64)
309f617635SEdgar E. Iglesias {
319f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
329f617635SEdgar E. Iglesias     xram_update_irq(s);
339f617635SEdgar E. Iglesias }
349f617635SEdgar E. Iglesias 
xram_ien_prew(RegisterInfo * reg,uint64_t val64)359f617635SEdgar E. Iglesias static uint64_t xram_ien_prew(RegisterInfo *reg, uint64_t val64)
369f617635SEdgar E. Iglesias {
379f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
389f617635SEdgar E. Iglesias     uint32_t val = val64;
399f617635SEdgar E. Iglesias 
409f617635SEdgar E. Iglesias     s->regs[R_XRAM_IMR] &= ~val;
419f617635SEdgar E. Iglesias     xram_update_irq(s);
429f617635SEdgar E. Iglesias     return 0;
439f617635SEdgar E. Iglesias }
449f617635SEdgar E. Iglesias 
xram_ids_prew(RegisterInfo * reg,uint64_t val64)459f617635SEdgar E. Iglesias static uint64_t xram_ids_prew(RegisterInfo *reg, uint64_t val64)
469f617635SEdgar E. Iglesias {
479f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(reg->opaque);
489f617635SEdgar E. Iglesias     uint32_t val = val64;
499f617635SEdgar E. Iglesias 
509f617635SEdgar E. Iglesias     s->regs[R_XRAM_IMR] |= val;
519f617635SEdgar E. Iglesias     xram_update_irq(s);
529f617635SEdgar E. Iglesias     return 0;
539f617635SEdgar E. Iglesias }
549f617635SEdgar E. Iglesias 
559f617635SEdgar E. Iglesias static const RegisterAccessInfo xram_ctrl_regs_info[] = {
569f617635SEdgar E. Iglesias     {   .name = "XRAM_ERR_CTRL",  .addr = A_XRAM_ERR_CTRL,
579f617635SEdgar E. Iglesias         .reset = 0xf,
589f617635SEdgar E. Iglesias         .rsvd = 0xfffffff0,
599f617635SEdgar E. Iglesias     },{ .name = "XRAM_ISR",  .addr = A_XRAM_ISR,
609f617635SEdgar E. Iglesias         .rsvd = 0xfffff800,
619f617635SEdgar E. Iglesias         .w1c = 0x7ff,
629f617635SEdgar E. Iglesias         .post_write = xram_isr_postw,
639f617635SEdgar E. Iglesias     },{ .name = "XRAM_IMR",  .addr = A_XRAM_IMR,
649f617635SEdgar E. Iglesias         .reset = 0x7ff,
659f617635SEdgar E. Iglesias         .rsvd = 0xfffff800,
669f617635SEdgar E. Iglesias         .ro = 0x7ff,
679f617635SEdgar E. Iglesias     },{ .name = "XRAM_IEN",  .addr = A_XRAM_IEN,
689f617635SEdgar E. Iglesias         .rsvd = 0xfffff800,
699f617635SEdgar E. Iglesias         .pre_write = xram_ien_prew,
709f617635SEdgar E. Iglesias     },{ .name = "XRAM_IDS",  .addr = A_XRAM_IDS,
719f617635SEdgar E. Iglesias         .rsvd = 0xfffff800,
729f617635SEdgar E. Iglesias         .pre_write = xram_ids_prew,
739f617635SEdgar E. Iglesias     },{ .name = "XRAM_ECC_CNTL",  .addr = A_XRAM_ECC_CNTL,
749f617635SEdgar E. Iglesias         .rsvd = 0xfffffff8,
759f617635SEdgar E. Iglesias     },{ .name = "XRAM_CLR_EXE",  .addr = A_XRAM_CLR_EXE,
769f617635SEdgar E. Iglesias         .rsvd = 0xffffff00,
779f617635SEdgar E. Iglesias     },{ .name = "XRAM_CE_FFA",  .addr = A_XRAM_CE_FFA,
789f617635SEdgar E. Iglesias         .rsvd = 0xfff00000,
799f617635SEdgar E. Iglesias         .ro = 0xfffff,
809f617635SEdgar E. Iglesias     },{ .name = "XRAM_CE_FFD0",  .addr = A_XRAM_CE_FFD0,
819f617635SEdgar E. Iglesias         .ro = 0xffffffff,
829f617635SEdgar E. Iglesias     },{ .name = "XRAM_CE_FFD1",  .addr = A_XRAM_CE_FFD1,
839f617635SEdgar E. Iglesias         .ro = 0xffffffff,
849f617635SEdgar E. Iglesias     },{ .name = "XRAM_CE_FFD2",  .addr = A_XRAM_CE_FFD2,
859f617635SEdgar E. Iglesias         .ro = 0xffffffff,
869f617635SEdgar E. Iglesias     },{ .name = "XRAM_CE_FFD3",  .addr = A_XRAM_CE_FFD3,
879f617635SEdgar E. Iglesias         .ro = 0xffffffff,
889f617635SEdgar E. Iglesias     },{ .name = "XRAM_CE_FFE",  .addr = A_XRAM_CE_FFE,
899f617635SEdgar E. Iglesias         .rsvd = 0xffff0000,
909f617635SEdgar E. Iglesias         .ro = 0xffff,
919f617635SEdgar E. Iglesias     },{ .name = "XRAM_UE_FFA",  .addr = A_XRAM_UE_FFA,
929f617635SEdgar E. Iglesias         .rsvd = 0xfff00000,
939f617635SEdgar E. Iglesias         .ro = 0xfffff,
949f617635SEdgar E. Iglesias     },{ .name = "XRAM_UE_FFD0",  .addr = A_XRAM_UE_FFD0,
959f617635SEdgar E. Iglesias         .ro = 0xffffffff,
969f617635SEdgar E. Iglesias     },{ .name = "XRAM_UE_FFD1",  .addr = A_XRAM_UE_FFD1,
979f617635SEdgar E. Iglesias         .ro = 0xffffffff,
989f617635SEdgar E. Iglesias     },{ .name = "XRAM_UE_FFD2",  .addr = A_XRAM_UE_FFD2,
999f617635SEdgar E. Iglesias         .ro = 0xffffffff,
1009f617635SEdgar E. Iglesias     },{ .name = "XRAM_UE_FFD3",  .addr = A_XRAM_UE_FFD3,
1019f617635SEdgar E. Iglesias         .ro = 0xffffffff,
1029f617635SEdgar E. Iglesias     },{ .name = "XRAM_UE_FFE",  .addr = A_XRAM_UE_FFE,
1039f617635SEdgar E. Iglesias         .rsvd = 0xffff0000,
1049f617635SEdgar E. Iglesias         .ro = 0xffff,
1059f617635SEdgar E. Iglesias     },{ .name = "XRAM_FI_D0",  .addr = A_XRAM_FI_D0,
1069f617635SEdgar E. Iglesias     },{ .name = "XRAM_FI_D1",  .addr = A_XRAM_FI_D1,
1079f617635SEdgar E. Iglesias     },{ .name = "XRAM_FI_D2",  .addr = A_XRAM_FI_D2,
1089f617635SEdgar E. Iglesias     },{ .name = "XRAM_FI_D3",  .addr = A_XRAM_FI_D3,
1099f617635SEdgar E. Iglesias     },{ .name = "XRAM_FI_SY",  .addr = A_XRAM_FI_SY,
1109f617635SEdgar E. Iglesias         .rsvd = 0xffff0000,
1119f617635SEdgar E. Iglesias     },{ .name = "XRAM_RMW_UE_FFA",  .addr = A_XRAM_RMW_UE_FFA,
1129f617635SEdgar E. Iglesias         .rsvd = 0xfff00000,
1139f617635SEdgar E. Iglesias         .ro = 0xfffff,
1149f617635SEdgar E. Iglesias     },{ .name = "XRAM_FI_CNTR",  .addr = A_XRAM_FI_CNTR,
1159f617635SEdgar E. Iglesias         .rsvd = 0xff000000,
1169f617635SEdgar E. Iglesias     },{ .name = "XRAM_IMP",  .addr = A_XRAM_IMP,
1179f617635SEdgar E. Iglesias         .reset = 0x4,
1189f617635SEdgar E. Iglesias         .rsvd = 0xfffffff0,
1199f617635SEdgar E. Iglesias         .ro = 0xf,
1209f617635SEdgar E. Iglesias     },{ .name = "XRAM_PRDY_DBG",  .addr = A_XRAM_PRDY_DBG,
1219f617635SEdgar E. Iglesias         .reset = 0xffff,
1229f617635SEdgar E. Iglesias         .rsvd = 0xffff0000,
1239f617635SEdgar E. Iglesias         .ro = 0xffff,
1249f617635SEdgar E. Iglesias     },{ .name = "XRAM_SAFETY_CHK",  .addr = A_XRAM_SAFETY_CHK,
1259f617635SEdgar E. Iglesias     }
1269f617635SEdgar E. Iglesias };
1279f617635SEdgar E. Iglesias 
xram_ctrl_reset_enter(Object * obj,ResetType type)1289f617635SEdgar E. Iglesias static void xram_ctrl_reset_enter(Object *obj, ResetType type)
1299f617635SEdgar E. Iglesias {
1309f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
1319f617635SEdgar E. Iglesias     unsigned int i;
1329f617635SEdgar E. Iglesias 
1339f617635SEdgar E. Iglesias     for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
1349f617635SEdgar E. Iglesias         register_reset(&s->regs_info[i]);
1359f617635SEdgar E. Iglesias     }
1369f617635SEdgar E. Iglesias 
1379f617635SEdgar E. Iglesias     ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
1389f617635SEdgar E. Iglesias }
1399f617635SEdgar E. Iglesias 
xram_ctrl_reset_hold(Object * obj,ResetType type)140*ad80e367SPeter Maydell static void xram_ctrl_reset_hold(Object *obj, ResetType type)
1419f617635SEdgar E. Iglesias {
1429f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
1439f617635SEdgar E. Iglesias 
1449f617635SEdgar E. Iglesias     xram_update_irq(s);
1459f617635SEdgar E. Iglesias }
1469f617635SEdgar E. Iglesias 
1479f617635SEdgar E. Iglesias static const MemoryRegionOps xram_ctrl_ops = {
1489f617635SEdgar E. Iglesias     .read = register_read_memory,
1499f617635SEdgar E. Iglesias     .write = register_write_memory,
1509f617635SEdgar E. Iglesias     .endianness = DEVICE_LITTLE_ENDIAN,
1519f617635SEdgar E. Iglesias     .valid = {
1529f617635SEdgar E. Iglesias         .min_access_size = 4,
1539f617635SEdgar E. Iglesias         .max_access_size = 4,
1549f617635SEdgar E. Iglesias     },
1559f617635SEdgar E. Iglesias };
1569f617635SEdgar E. Iglesias 
xram_ctrl_realize(DeviceState * dev,Error ** errp)1579f617635SEdgar E. Iglesias static void xram_ctrl_realize(DeviceState *dev, Error **errp)
1589f617635SEdgar E. Iglesias {
1599f617635SEdgar E. Iglesias     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1609f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(dev);
1619f617635SEdgar E. Iglesias 
1629f617635SEdgar E. Iglesias     switch (s->cfg.size) {
1639f617635SEdgar E. Iglesias     case 64 * KiB:
1649f617635SEdgar E. Iglesias         s->cfg.encoded_size = 0;
1659f617635SEdgar E. Iglesias         break;
1669f617635SEdgar E. Iglesias     case 128 * KiB:
1679f617635SEdgar E. Iglesias         s->cfg.encoded_size = 1;
1689f617635SEdgar E. Iglesias         break;
1699f617635SEdgar E. Iglesias     case 256 * KiB:
1709f617635SEdgar E. Iglesias         s->cfg.encoded_size = 2;
1719f617635SEdgar E. Iglesias         break;
1729f617635SEdgar E. Iglesias     case 512 * KiB:
1739f617635SEdgar E. Iglesias         s->cfg.encoded_size = 3;
1749f617635SEdgar E. Iglesias         break;
1759f617635SEdgar E. Iglesias     case 1 * MiB:
1769f617635SEdgar E. Iglesias         s->cfg.encoded_size = 4;
1779f617635SEdgar E. Iglesias         break;
1789f617635SEdgar E. Iglesias     default:
1799f617635SEdgar E. Iglesias         error_setg(errp, "Unsupported XRAM size %" PRId64, s->cfg.size);
1809f617635SEdgar E. Iglesias         return;
1819f617635SEdgar E. Iglesias     }
1829f617635SEdgar E. Iglesias 
1839f617635SEdgar E. Iglesias     memory_region_init_ram(&s->ram, OBJECT(s),
1849f617635SEdgar E. Iglesias                            object_get_canonical_path_component(OBJECT(s)),
1859f617635SEdgar E. Iglesias                            s->cfg.size, &error_fatal);
1869f617635SEdgar E. Iglesias     sysbus_init_mmio(sbd, &s->ram);
1879f617635SEdgar E. Iglesias }
1889f617635SEdgar E. Iglesias 
xram_ctrl_init(Object * obj)1899f617635SEdgar E. Iglesias static void xram_ctrl_init(Object *obj)
1909f617635SEdgar E. Iglesias {
1919f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
1929f617635SEdgar E. Iglesias     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1939f617635SEdgar E. Iglesias 
1949f617635SEdgar E. Iglesias     s->reg_array =
1959f617635SEdgar E. Iglesias         register_init_block32(DEVICE(obj), xram_ctrl_regs_info,
1969f617635SEdgar E. Iglesias                               ARRAY_SIZE(xram_ctrl_regs_info),
1979f617635SEdgar E. Iglesias                               s->regs_info, s->regs,
1989f617635SEdgar E. Iglesias                               &xram_ctrl_ops,
1999f617635SEdgar E. Iglesias                               XLNX_XRAM_CTRL_ERR_DEBUG,
2009f617635SEdgar E. Iglesias                               XRAM_CTRL_R_MAX * 4);
2019f617635SEdgar E. Iglesias     sysbus_init_mmio(sbd, &s->reg_array->mem);
2029f617635SEdgar E. Iglesias     sysbus_init_irq(sbd, &s->irq);
2039f617635SEdgar E. Iglesias }
2049f617635SEdgar E. Iglesias 
xram_ctrl_finalize(Object * obj)2059f617635SEdgar E. Iglesias static void xram_ctrl_finalize(Object *obj)
2069f617635SEdgar E. Iglesias {
2079f617635SEdgar E. Iglesias     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
2089f617635SEdgar E. Iglesias     register_finalize_block(s->reg_array);
2099f617635SEdgar E. Iglesias }
2109f617635SEdgar E. Iglesias 
2119f617635SEdgar E. Iglesias static const VMStateDescription vmstate_xram_ctrl = {
2129f617635SEdgar E. Iglesias     .name = TYPE_XLNX_XRAM_CTRL,
2139f617635SEdgar E. Iglesias     .version_id = 1,
2149f617635SEdgar E. Iglesias     .minimum_version_id = 1,
215e4ea952fSRichard Henderson     .fields = (const VMStateField[]) {
2169f617635SEdgar E. Iglesias         VMSTATE_UINT32_ARRAY(regs, XlnxXramCtrl, XRAM_CTRL_R_MAX),
2179f617635SEdgar E. Iglesias         VMSTATE_END_OF_LIST(),
2189f617635SEdgar E. Iglesias     }
2199f617635SEdgar E. Iglesias };
2209f617635SEdgar E. Iglesias 
2219f617635SEdgar E. Iglesias static Property xram_ctrl_properties[] = {
2229f617635SEdgar E. Iglesias     DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
2239f617635SEdgar E. Iglesias     DEFINE_PROP_END_OF_LIST(),
2249f617635SEdgar E. Iglesias };
2259f617635SEdgar E. Iglesias 
xram_ctrl_class_init(ObjectClass * klass,void * data)2269f617635SEdgar E. Iglesias static void xram_ctrl_class_init(ObjectClass *klass, void *data)
2279f617635SEdgar E. Iglesias {
2289f617635SEdgar E. Iglesias     ResettableClass *rc = RESETTABLE_CLASS(klass);
2299f617635SEdgar E. Iglesias     DeviceClass *dc = DEVICE_CLASS(klass);
2309f617635SEdgar E. Iglesias 
2319f617635SEdgar E. Iglesias     dc->realize = xram_ctrl_realize;
2329f617635SEdgar E. Iglesias     dc->vmsd = &vmstate_xram_ctrl;
2339f617635SEdgar E. Iglesias     device_class_set_props(dc, xram_ctrl_properties);
2349f617635SEdgar E. Iglesias 
2359f617635SEdgar E. Iglesias     rc->phases.enter = xram_ctrl_reset_enter;
2369f617635SEdgar E. Iglesias     rc->phases.hold = xram_ctrl_reset_hold;
2379f617635SEdgar E. Iglesias }
2389f617635SEdgar E. Iglesias 
2399f617635SEdgar E. Iglesias static const TypeInfo xram_ctrl_info = {
2409f617635SEdgar E. Iglesias     .name              = TYPE_XLNX_XRAM_CTRL,
2419f617635SEdgar E. Iglesias     .parent            = TYPE_SYS_BUS_DEVICE,
2429f617635SEdgar E. Iglesias     .instance_size     = sizeof(XlnxXramCtrl),
2439f617635SEdgar E. Iglesias     .class_init        = xram_ctrl_class_init,
2449f617635SEdgar E. Iglesias     .instance_init     = xram_ctrl_init,
2459f617635SEdgar E. Iglesias     .instance_finalize = xram_ctrl_finalize,
2469f617635SEdgar E. Iglesias };
2479f617635SEdgar E. Iglesias 
xram_ctrl_register_types(void)2489f617635SEdgar E. Iglesias static void xram_ctrl_register_types(void)
2499f617635SEdgar E. Iglesias {
2509f617635SEdgar E. Iglesias     type_register_static(&xram_ctrl_info);
2519f617635SEdgar E. Iglesias }
2529f617635SEdgar E. Iglesias 
2539f617635SEdgar E. Iglesias type_init(xram_ctrl_register_types)
254