xref: /qemu/hw/misc/xlnx-versal-xramc.c (revision b355f08a)
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 
23 static 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 
29 static 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 
35 static 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 
45 static 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 
55 static 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 
128 static 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 
140 static void xram_ctrl_reset_hold(Object *obj)
141 {
142     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
143 
144     xram_update_irq(s);
145 }
146 
147 static 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 
157 static 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 
189 static 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 
205 static void xram_ctrl_finalize(Object *obj)
206 {
207     XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
208     register_finalize_block(s->reg_array);
209 }
210 
211 static 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 
221 static Property xram_ctrl_properties[] = {
222     DEFINE_PROP_UINT64("size", XlnxXramCtrl, cfg.size, 1 * MiB),
223     DEFINE_PROP_END_OF_LIST(),
224 };
225 
226 static 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 
239 static 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 
248 static void xram_ctrl_register_types(void)
249 {
250     type_register_static(&xram_ctrl_info);
251 }
252 
253 type_init(xram_ctrl_register_types)
254