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 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 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 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 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 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 140ad80e367SPeter 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 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 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 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 22130029973SRichard Henderson static const Property xram_ctrl_properties[] = { 2229f617635SEdgar E. Iglesias DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB), 2239f617635SEdgar E. Iglesias }; 2249f617635SEdgar E. Iglesias 225*12d1a768SPhilippe Mathieu-Daudé static void xram_ctrl_class_init(ObjectClass *klass, const void *data) 2269f617635SEdgar E. Iglesias { 2279f617635SEdgar E. Iglesias ResettableClass *rc = RESETTABLE_CLASS(klass); 2289f617635SEdgar E. Iglesias DeviceClass *dc = DEVICE_CLASS(klass); 2299f617635SEdgar E. Iglesias 2309f617635SEdgar E. Iglesias dc->realize = xram_ctrl_realize; 2319f617635SEdgar E. Iglesias dc->vmsd = &vmstate_xram_ctrl; 2329f617635SEdgar E. Iglesias device_class_set_props(dc, xram_ctrl_properties); 2339f617635SEdgar E. Iglesias 2349f617635SEdgar E. Iglesias rc->phases.enter = xram_ctrl_reset_enter; 2359f617635SEdgar E. Iglesias rc->phases.hold = xram_ctrl_reset_hold; 2369f617635SEdgar E. Iglesias } 2379f617635SEdgar E. Iglesias 2389f617635SEdgar E. Iglesias static const TypeInfo xram_ctrl_info = { 2399f617635SEdgar E. Iglesias .name = TYPE_XLNX_XRAM_CTRL, 2409f617635SEdgar E. Iglesias .parent = TYPE_SYS_BUS_DEVICE, 2419f617635SEdgar E. Iglesias .instance_size = sizeof(XlnxXramCtrl), 2429f617635SEdgar E. Iglesias .class_init = xram_ctrl_class_init, 2439f617635SEdgar E. Iglesias .instance_init = xram_ctrl_init, 2449f617635SEdgar E. Iglesias .instance_finalize = xram_ctrl_finalize, 2459f617635SEdgar E. Iglesias }; 2469f617635SEdgar E. Iglesias 2479f617635SEdgar E. Iglesias static void xram_ctrl_register_types(void) 2489f617635SEdgar E. Iglesias { 2499f617635SEdgar E. Iglesias type_register_static(&xram_ctrl_info); 2509f617635SEdgar E. Iglesias } 2519f617635SEdgar E. Iglesias 2529f617635SEdgar E. Iglesias type_init(xram_ctrl_register_types) 253