1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#include "qemu/osdep.h"
28#include "hw/sysbus.h"
29#include "hw/register.h"
30#include "qemu/bitops.h"
31#include "qemu/log.h"
32#include "migration/vmstate.h"
33#include "hw/qdev-properties.h"
34
35#ifndef XILINX_XPIO_DCI_COMPONENT_ERR_DEBUG
36#define XILINX_XPIO_DCI_COMPONENT_ERR_DEBUG 0
37#endif
38
39#define TYPE_XILINX_XPIO_DCI_COMPONENT "xlnx.versal-xpio-dci"
40
41#define XILINX_XPIO_DCI_COMPONENT(obj) \
42 OBJECT_CHECK(XPIO_DCI_COMPONENT, (obj), TYPE_XILINX_XPIO_DCI_COMPONENT)
43
44REG32(REG_PCSR_MASK, 0x0)
45 FIELD(REG_PCSR_MASK, DCI_OFC_RST, 21, 1)
46 FIELD(REG_PCSR_MASK, TEST_SAFE, 20, 1)
47 FIELD(REG_PCSR_MASK, SLVERREN, 19, 1)
48 FIELD(REG_PCSR_MASK, MEM_CLEAR_TRIGGER, 18, 1)
49 FIELD(REG_PCSR_MASK, SYS_RST_MASK, 15, 3)
50 FIELD(REG_PCSR_MASK, PWRDN, 14, 1)
51 FIELD(REG_PCSR_MASK, DISNPICLK, 13, 1)
52 FIELD(REG_PCSR_MASK, APBEN, 12, 1)
53 FIELD(REG_PCSR_MASK, SCAN_CLEAR_TRIGGER, 11, 1)
54 FIELD(REG_PCSR_MASK, STARTCAL, 10, 1)
55 FIELD(REG_PCSR_MASK, FABRICEN, 9, 1)
56 FIELD(REG_PCSR_MASK, TRISTATE, 8, 1)
57 FIELD(REG_PCSR_MASK, HOLDSTATE, 7, 1)
58 FIELD(REG_PCSR_MASK, INITSTATE, 6, 1)
59 FIELD(REG_PCSR_MASK, ODISABLE, 2, 4)
60 FIELD(REG_PCSR_MASK, GATEREG, 1, 1)
61 FIELD(REG_PCSR_MASK, PCOMPLETE, 0, 1)
62REG32(REG_PCSR_CONTROL, 0x4)
63 FIELD(REG_PCSR_CONTROL, DCI_OFC_RST, 21, 1)
64 FIELD(REG_PCSR_CONTROL, TEST_SAFE, 20, 1)
65 FIELD(REG_PCSR_CONTROL, SLVERREN, 19, 1)
66 FIELD(REG_PCSR_CONTROL, MEM_CLEAR_TRIGGER, 18, 1)
67 FIELD(REG_PCSR_CONTROL, SYS_RST_MASK, 15, 3)
68 FIELD(REG_PCSR_CONTROL, PWRDN, 14, 1)
69 FIELD(REG_PCSR_CONTROL, DISNPICLK, 13, 1)
70 FIELD(REG_PCSR_CONTROL, APBEN, 12, 1)
71 FIELD(REG_PCSR_CONTROL, SCAN_CLEAR_TRIGGER, 11, 1)
72 FIELD(REG_PCSR_CONTROL, STARTCAL, 10, 1)
73 FIELD(REG_PCSR_CONTROL, FABRICEN, 9, 1)
74 FIELD(REG_PCSR_CONTROL, TRISTATE, 8, 1)
75 FIELD(REG_PCSR_CONTROL, HOLDSTATE, 7, 1)
76 FIELD(REG_PCSR_CONTROL, INITSTATE, 6, 1)
77 FIELD(REG_PCSR_CONTROL, ODISABLE, 2, 4)
78 FIELD(REG_PCSR_CONTROL, GATEREG, 1, 1)
79 FIELD(REG_PCSR_CONTROL, PCOMPLETE, 0, 1)
80REG32(REG_PCSR_STATUS, 0x8)
81 FIELD(REG_PCSR_STATUS, HARD_FAIL_OR, 11, 3)
82 FIELD(REG_PCSR_STATUS, HARD_FAIL_AND, 8, 3)
83 FIELD(REG_PCSR_STATUS, MEM_CLEAR_PASS, 7, 1)
84 FIELD(REG_PCSR_STATUS, MEM_CLEAR_DONE, 6, 1)
85 FIELD(REG_PCSR_STATUS, CALERROR, 5, 1)
86 FIELD(REG_PCSR_STATUS, CALDONE, 4, 1)
87 FIELD(REG_PCSR_STATUS, INCAL, 3, 1)
88 FIELD(REG_PCSR_STATUS, SCAN_CLEAR_PASS, 2, 1)
89 FIELD(REG_PCSR_STATUS, SCAN_CLEAR_DONE, 1, 1)
90 FIELD(REG_PCSR_STATUS, PCSRLOCK, 0, 1)
91REG32(REG_PCSR_LOCK, 0xc)
92 FIELD(REG_PCSR_LOCK, STATE, 0, 1)
93REG32(DCI_CFG_0, 0x24)
94 FIELD(DCI_CFG_0, XMC_DCI_DEBUG_SEL_1, 12, 16)
95 FIELD(DCI_CFG_0, XMC_UPDATE_CONTROL, 10, 2)
96 FIELD(DCI_CFG_0, XMC_DCI_CASCADE_SEL, 8, 2)
97 FIELD(DCI_CFG_0, XMC_DCI_FLTR_CTRL, 4, 4)
98 FIELD(DCI_CFG_0, XMC_EN_OUT_FLTR, 3, 1)
99 FIELD(DCI_CFG_0, XMC_WAIT_BYPASS, 2, 1)
100 FIELD(DCI_CFG_0, XMC_TST_EN, 1, 1)
101 FIELD(DCI_CFG_0, XMC_EN_DCI, 0, 1)
102REG32(DCI_CFG_1, 0x28)
103 FIELD(DCI_CFG_1, XMC_DCI_DEBUG_SEL_3, 16, 8)
104 FIELD(DCI_CFG_1, XMC_DCI_DEBUG_SEL_2, 0, 16)
105REG32(DCI_CFG_2, 0x2c)
106 FIELD(DCI_CFG_2, XMC_CSSD_CTRL_2, 16, 16)
107 FIELD(DCI_CFG_2, XMC_CSSD_CTRL_1, 0, 16)
108REG32(DCI_CFG_3, 0x30)
109 FIELD(DCI_CFG_3, XMC_DCI_REF_OPT, 0, 13)
110REG32(DCI_CFG_4, 0x34)
111 FIELD(DCI_CFG_4, XMC_DCI_SCL_CTRL_2, 16, 16)
112 FIELD(DCI_CFG_4, XMC_DCI_SCL_CTRL_1, 0, 16)
113REG32(DCI_CFG_5, 0x38)
114 FIELD(DCI_CFG_5, XMC_DCI_SCL_CTRL_4, 16, 16)
115 FIELD(DCI_CFG_5, XMC_DCI_SCL_CTRL_3, 0, 16)
116REG32(DCI_CFG_6, 0x3c)
117 FIELD(DCI_CFG_6, XMC_CSSD_CTRL_3, 0, 4)
118REG32(DCI_CFG_7, 0x40)
119 FIELD(DCI_CFG_7, XMC_DCI_SCL_CTRL_5, 0, 16)
120REG32(DCI_CFG_8, 0x44)
121 FIELD(DCI_CFG_8, XMC_DCI_SCL_CTRL_7, 16, 16)
122 FIELD(DCI_CFG_8, XMC_DCI_SCL_CTRL_6, 0, 16)
123REG32(DCI_CFG_9, 0x48)
124 FIELD(DCI_CFG_9, MC_CSSD_TRIG_N, 31, 1)
125 FIELD(DCI_CFG_9, MCI_DCI_LOCK_DIR_UPXDWN, 30, 1)
126 FIELD(DCI_CFG_9, XMC_DCI_SCL_CTRL_8, 0, 30)
127REG32(DCI_CFG_10, 0x4c)
128REG32(DCI_CFG_11, 0x50)
129REG32(DCI_CFG_12, 0x54)
130 FIELD(DCI_CFG_12, EN_DCI, 17, 1)
131 FIELD(DCI_CFG_12, XMC_DCI_SCL_CTRL_11, 1, 16)
132 FIELD(DCI_CFG_12, BROADCAST_DISABLE, 0, 1)
133REG32(DCI_CFG_13, 0x58)
134 FIELD(DCI_CFG_13, CUR_ST_RD, 4, 7)
135 FIELD(DCI_CFG_13, DCI_LOCK_DONE_DOWN, 2, 1)
136 FIELD(DCI_CFG_13, DCI_LOCK_DONE_UP, 1, 1)
137 FIELD(DCI_CFG_13, DCI_LOCK, 0, 1)
138REG32(DCI_CFG_14, 0x5c)
139 FIELD(DCI_CFG_14, DCI_ZBUS, 0, 18)
140REG32(DCI_CFG_15, 0x60)
141 FIELD(DCI_CFG_15, MC_RTRIM_BUS, 0, 31)
142REG32(OFC_CFG_0, 0x64)
143REG32(OFC_CFG_1, 0x68)
144REG32(OFC_CFG_2, 0x6c)
145REG32(OFC_CFG_3, 0x70)
146 FIELD(OFC_CFG_3, OFC_REG_BUS_3, 0, 12)
147REG32(OFC_CFG_4, 0x74)
148REG32(OFC_CFG_5, 0x78)
149REG32(OFC_CFG_6, 0x7c)
150 FIELD(OFC_CFG_6, MC_VRDMY_CODE, 0, 21)
151
152#define XPIO_DCI_COMPONENT_R_MAX (R_OFC_CFG_6 + 1)
153
154typedef struct XPIO_DCI_COMPONENT {
155 SysBusDevice parent_obj;
156 MemoryRegion iomem;
157
158 uint32_t regs[XPIO_DCI_COMPONENT_R_MAX];
159 RegisterInfo regs_info[XPIO_DCI_COMPONENT_R_MAX];
160} XPIO_DCI_COMPONENT;
161
162#define LOCK_VAL 0xF9E8D7C6
163
164static void xpio_dci_lock_postw(RegisterInfo *reg, uint64_t val64)
165{
166 XPIO_DCI_COMPONENT *s = XILINX_XPIO_DCI_COMPONENT(reg->opaque);
167 bool locked = val64 != LOCK_VAL;
168
169 ARRAY_FIELD_DP32(s->regs, REG_PCSR_STATUS, PCSRLOCK, locked);
170 ARRAY_FIELD_DP32(s->regs, REG_PCSR_LOCK, STATE, locked);
171}
172
173static const RegisterAccessInfo xpio_dci_component_regs_info[] = {
174 { .name = "REG_PCSR_MASK", .addr = A_REG_PCSR_MASK,
175 .reset = 0x200000,
176 .rsvd = 0xffc00000,
177 },{ .name = "REG_PCSR_CONTROL", .addr = A_REG_PCSR_CONTROL,
178 .reset = 0x2001fe,
179 .rsvd = 0xffc00000,
180 },{ .name = "REG_PCSR_STATUS", .addr = A_REG_PCSR_STATUS,
181 .reset = R_REG_PCSR_STATUS_PCSRLOCK_MASK \
182 | R_REG_PCSR_STATUS_MEM_CLEAR_PASS_MASK \
183 | R_REG_PCSR_STATUS_MEM_CLEAR_DONE_MASK \
184 | R_REG_PCSR_STATUS_CALDONE_MASK \
185 | R_REG_PCSR_STATUS_SCAN_CLEAR_PASS_MASK \
186 | R_REG_PCSR_STATUS_SCAN_CLEAR_DONE_MASK,
187 .rsvd = 0xffffc000,
188 .ro = 0x3fff,
189 },{ .name = "REG_PCSR_LOCK", .addr = A_REG_PCSR_LOCK,
190 .reset = 0x1,
191 .post_write = xpio_dci_lock_postw
192 },{ .name = "DCI_CFG_0", .addr = A_DCI_CFG_0,
193 .rsvd = 0xf0000000,
194 },{ .name = "DCI_CFG_1", .addr = A_DCI_CFG_1,
195 .rsvd = 0xff000000,
196 },{ .name = "DCI_CFG_2", .addr = A_DCI_CFG_2,
197 },{ .name = "DCI_CFG_3", .addr = A_DCI_CFG_3,
198 .rsvd = 0xffffe000,
199 },{ .name = "DCI_CFG_4", .addr = A_DCI_CFG_4,
200 },{ .name = "DCI_CFG_5", .addr = A_DCI_CFG_5,
201 },{ .name = "DCI_CFG_6", .addr = A_DCI_CFG_6,
202 .rsvd = 0xfffffff0,
203 },{ .name = "DCI_CFG_7", .addr = A_DCI_CFG_7,
204 .rsvd = 0xffff0000,
205 },{ .name = "DCI_CFG_8", .addr = A_DCI_CFG_8,
206 },{ .name = "DCI_CFG_9", .addr = A_DCI_CFG_9,
207 },{ .name = "DCI_CFG_10", .addr = A_DCI_CFG_10,
208 },{ .name = "DCI_CFG_11", .addr = A_DCI_CFG_11,
209 },{ .name = "DCI_CFG_12", .addr = A_DCI_CFG_12,
210 .rsvd = 0xfffc0000,
211 },{ .name = "DCI_CFG_13", .addr = A_DCI_CFG_13,
212 .reset = 0x6,
213 .rsvd = 0xfffff800,
214 .ro = 0x7f7,
215 },{ .name = "DCI_CFG_14", .addr = A_DCI_CFG_14,
216 .rsvd = 0xfffc0000,
217 .ro = 0x3ffff,
218 },{ .name = "DCI_CFG_15", .addr = A_DCI_CFG_15,
219 .rsvd = 0x80000000,
220 },{ .name = "OFC_CFG_0", .addr = A_OFC_CFG_0,
221 },{ .name = "OFC_CFG_1", .addr = A_OFC_CFG_1,
222 },{ .name = "OFC_CFG_2", .addr = A_OFC_CFG_2,
223 },{ .name = "OFC_CFG_3", .addr = A_OFC_CFG_3,
224 .rsvd = 0xfffff000,
225 },{ .name = "OFC_CFG_4", .addr = A_OFC_CFG_4,
226 },{ .name = "OFC_CFG_5", .addr = A_OFC_CFG_5,
227 },{ .name = "OFC_CFG_6", .addr = A_OFC_CFG_6,
228 .rsvd = 0xffe00000,
229 }
230};
231
232static void xpio_dci_component_reset(DeviceState *dev)
233{
234 XPIO_DCI_COMPONENT *s = XILINX_XPIO_DCI_COMPONENT(dev);
235 unsigned int i;
236
237 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
238 register_reset(&s->regs_info[i]);
239 }
240}
241
242static MemTxResult reg_write(void *opaque, hwaddr addr,
243 uint64_t data, unsigned size, MemTxAttrs attrs)
244{
245 RegisterInfoArray *reg_array = opaque;
246 XPIO_DCI_COMPONENT *s = XILINX_XPIO_DCI_COMPONENT(reg_array->r[0]->opaque);
247
248
249 if (ARRAY_FIELD_EX32(s->regs, REG_PCSR_LOCK, STATE)
250 && addr != A_REG_PCSR_LOCK) {
251 return MEMTX_ERROR;
252 }
253
254 register_write_memory(opaque, addr, data, size);
255 return MEMTX_OK;
256}
257
258static const MemoryRegionOps xpio_dci_component_ops = {
259 .read = register_read_memory,
260 .write_with_attrs = reg_write,
261 .endianness = DEVICE_LITTLE_ENDIAN,
262 .valid = {
263 .min_access_size = 4,
264 .max_access_size = 4,
265 },
266};
267
268static void xpio_dci_component_realize(DeviceState *dev, Error **errp)
269{
270
271}
272
273static void xpio_dci_component_init(Object *obj)
274{
275 XPIO_DCI_COMPONENT *s = XILINX_XPIO_DCI_COMPONENT(obj);
276 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
277 RegisterInfoArray *reg_array;
278
279 memory_region_init(&s->iomem, obj, TYPE_XILINX_XPIO_DCI_COMPONENT,
280 XPIO_DCI_COMPONENT_R_MAX * 4);
281 reg_array =
282 register_init_block32(DEVICE(obj), xpio_dci_component_regs_info,
283 ARRAY_SIZE(xpio_dci_component_regs_info),
284 s->regs_info, s->regs,
285 &xpio_dci_component_ops,
286 XILINX_XPIO_DCI_COMPONENT_ERR_DEBUG,
287 XPIO_DCI_COMPONENT_R_MAX * 4);
288 memory_region_add_subregion(&s->iomem,
289 0x0,
290 ®_array->mem);
291 sysbus_init_mmio(sbd, &s->iomem);
292}
293
294static const VMStateDescription vmstate_xpio_dci_component = {
295 .name = TYPE_XILINX_XPIO_DCI_COMPONENT,
296 .version_id = 1,
297 .minimum_version_id = 1,
298 .fields = (VMStateField[]) {
299 VMSTATE_UINT32_ARRAY(regs, XPIO_DCI_COMPONENT,
300 XPIO_DCI_COMPONENT_R_MAX),
301 VMSTATE_END_OF_LIST(),
302 }
303};
304
305static void xpio_dci_component_class_init(ObjectClass *klass, void *data)
306{
307 DeviceClass *dc = DEVICE_CLASS(klass);
308
309 dc->reset = xpio_dci_component_reset;
310 dc->realize = xpio_dci_component_realize;
311 dc->vmsd = &vmstate_xpio_dci_component;
312}
313
314static const TypeInfo xpio_dci_component_info = {
315 .name = TYPE_XILINX_XPIO_DCI_COMPONENT,
316 .parent = TYPE_SYS_BUS_DEVICE,
317 .instance_size = sizeof(XPIO_DCI_COMPONENT),
318 .class_init = xpio_dci_component_class_init,
319 .instance_init = xpio_dci_component_init,
320};
321
322static void xpio_dci_component_register_types(void)
323{
324 type_register_static(&xpio_dci_component_info);
325}
326
327type_init(xpio_dci_component_register_types)
328