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
28#include "qemu/osdep.h"
29#include "hw/sysbus.h"
30#include "hw/register.h"
31#include "hw/registerfields.h"
32#include "qemu/bitops.h"
33#include "qemu/log.h"
34#include "qapi/error.h"
35#include "hw/qdev-properties.h"
36#include "migration/vmstate.h"
37#include "hw/irq.h"
38#include "hw/misc/xlnx-cfi-if.h"
39
40#ifndef XILINX_CFRAME_REG_ERR_DEBUG
41#define XILINX_CFRAME_REG_ERR_DEBUG 0
42#endif
43
44#define TYPE_XILINX_CFRAME_REG "xlnx.cframe_reg"
45
46#define XILINX_CFRAME_REG(obj) \
47 OBJECT_CHECK(CFRAME_REG, (obj), TYPE_XILINX_CFRAME_REG)
48
49#define TYPE_XILINX_CFRAME_BCAST_REG "xlnx.cframe-bcast-reg"
50
51#define XILINX_CFRAME_BCAST_REG(obj) \
52 OBJECT_CHECK(CFRAME_BCAST_REG, (obj), TYPE_XILINX_CFRAME_BCAST_REG)
53
54
55
56
57
58
59REG32(CRC0, 0x0)
60 FIELD(CRC, CRC, 0, 32)
61REG32(CRC1, 0x4)
62REG32(CRC2, 0x8)
63REG32(CRC3, 0xc)
64REG32(FAR0, 0x10)
65 FIELD(FAR0, SEGMENT, 23, 2)
66 FIELD(FAR0, BLOCKTYPE, 20, 3)
67 FIELD(FAR0, FRAME_ADDR, 0, 20)
68REG32(FAR1, 0x14)
69REG32(FAR2, 0x18)
70REG32(FAR3, 0x1c)
71REG32(FAR_SFR0, 0x20)
72 FIELD(FAR_SFR0, BLOCKTYPE, 20, 3)
73 FIELD(FAR_SFR0, FRAME_ADDR, 0, 20)
74REG32(FAR_SFR1, 0x24)
75REG32(FAR_SFR2, 0x28)
76REG32(FAR_SFR3, 0x2c)
77REG32(FDRI0, 0x40)
78REG32(FDRI1, 0x44)
79REG32(FDRI2, 0x48)
80REG32(FDRI3, 0x4c)
81REG32(FRCNT0, 0x50)
82 FIELD(FRCNT0, FRCNT, 0, 32)
83REG32(FRCNT1, 0x54)
84REG32(FRCNT2, 0x58)
85REG32(FRCNT3, 0x5c)
86REG32(CMD0, 0x60)
87 FIELD(CMD0, CMD, 0, 5)
88REG32(CMD1, 0x64)
89REG32(CMD2, 0x68)
90REG32(CMD3, 0x6c)
91REG32(CR_MASK0, 0x70)
92REG32(CR_MASK1, 0x74)
93REG32(CR_MASK2, 0x78)
94REG32(CR_MASK3, 0x7c)
95REG32(CTL0, 0x80)
96 FIELD(CTL, PER_FRAME_CRC, 0, 1)
97REG32(CTL1, 0x84)
98REG32(CTL2, 0x88)
99REG32(CTL3, 0x8c)
100REG32(CFRM_ISR0, 0x150)
101 FIELD(CFRM_ISR0, READ_BROADCAST_ERROR, 21, 1)
102 FIELD(CFRM_ISR0, CMD_MISSING_ERROR, 20, 1)
103 FIELD(CFRM_ISR0, RW_ROWOFF_ERROR, 19, 1)
104 FIELD(CFRM_ISR0, READ_REG_ADDR_ERROR, 18, 1)
105 FIELD(CFRM_ISR0, READ_BLK_TYPE_ERROR, 17, 1)
106 FIELD(CFRM_ISR0, READ_FRAME_ADDR_ERROR, 16, 1)
107 FIELD(CFRM_ISR0, WRITE_REG_ADDR_ERROR, 15, 1)
108 FIELD(CFRM_ISR0, WRITE_BLK_TYPE_ERROR, 13, 1)
109 FIELD(CFRM_ISR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
110 FIELD(CFRM_ISR0, MFW_OVERRUN_ERROR, 11, 1)
111 FIELD(CFRM_ISR0, FAR_FIFO_UNDERFLOW, 10, 1)
112 FIELD(CFRM_ISR0, FAR_FIFO_OVERFLOW, 9, 1)
113 FIELD(CFRM_ISR0, PER_FRAME_SEQ_ERROR, 8, 1)
114 FIELD(CFRM_ISR0, CRC_ERROR, 7, 1)
115 FIELD(CFRM_ISR0, WRITE_OVERRUN_ERROR, 6, 1)
116 FIELD(CFRM_ISR0, READ_OVERRUN_ERROR, 5, 1)
117 FIELD(CFRM_ISR0, CMD_INTERRUPT_ERROR, 4, 1)
118 FIELD(CFRM_ISR0, WRITE_INTERRUPT_ERROR, 3, 1)
119 FIELD(CFRM_ISR0, READ_INTERRUPT_ERROR, 2, 1)
120 FIELD(CFRM_ISR0, SEU_CRC_ERROR, 1, 1)
121 FIELD(CFRM_ISR0, SEU_ECC_ERROR, 0, 1)
122REG32(CFRM_ISR1, 0x154)
123REG32(CFRM_ISR2, 0x158)
124REG32(CFRM_ISR3, 0x15c)
125REG32(CFRM_IMR0, 0x160)
126 FIELD(CFRM_IMR0, READ_BROADCAST_ERROR, 21, 1)
127 FIELD(CFRM_IMR0, CMD_MISSING_ERROR, 20, 1)
128 FIELD(CFRM_IMR0, RW_ROWOFF_ERROR, 19, 1)
129 FIELD(CFRM_IMR0, READ_REG_ADDR_ERROR, 18, 1)
130 FIELD(CFRM_IMR0, READ_BLK_TYPE_ERROR, 17, 1)
131 FIELD(CFRM_IMR0, READ_FRAME_ADDR_ERROR, 16, 1)
132 FIELD(CFRM_IMR0, WRITE_REG_ADDR_ERROR, 15, 1)
133 FIELD(CFRM_IMR0, WRITE_BLK_TYPE_ERROR, 13, 1)
134 FIELD(CFRM_IMR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
135 FIELD(CFRM_IMR0, MFW_OVERRUN_ERROR, 11, 1)
136 FIELD(CFRM_IMR0, FAR_FIFO_UNDERFLOW, 10, 1)
137 FIELD(CFRM_IMR0, FAR_FIFO_OVERFLOW, 9, 1)
138 FIELD(CFRM_IMR0, PER_FRAME_SEQ_ERROR, 8, 1)
139 FIELD(CFRM_IMR0, CRC_ERROR, 7, 1)
140 FIELD(CFRM_IMR0, WRITE_OVERRUN_ERROR, 6, 1)
141 FIELD(CFRM_IMR0, READ_OVERRUN_ERROR, 5, 1)
142 FIELD(CFRM_IMR0, CMD_INTERRUPT_ERROR, 4, 1)
143 FIELD(CFRM_IMR0, WRITE_INTERRUPT_ERROR, 3, 1)
144 FIELD(CFRM_IMR0, READ_INTERRUPT_ERROR, 2, 1)
145 FIELD(CFRM_IMR0, SEU_CRC_ERROR, 1, 1)
146 FIELD(CFRM_IMR0, SEU_ECC_ERROR, 0, 1)
147REG32(CFRM_IMR1, 0x164)
148REG32(CFRM_IMR2, 0x168)
149REG32(CFRM_IMR3, 0x16c)
150REG32(CFRM_IER0, 0x170)
151 FIELD(CFRM_IER0, READ_BROADCAST_ERROR, 21, 1)
152 FIELD(CFRM_IER0, CMD_MISSING_ERROR, 20, 1)
153 FIELD(CFRM_IER0, RW_ROWOFF_ERROR, 19, 1)
154 FIELD(CFRM_IER0, READ_REG_ADDR_ERROR, 18, 1)
155 FIELD(CFRM_IER0, READ_BLK_TYPE_ERROR, 17, 1)
156 FIELD(CFRM_IER0, READ_FRAME_ADDR_ERROR, 16, 1)
157 FIELD(CFRM_IER0, WRITE_REG_ADDR_ERROR, 15, 1)
158 FIELD(CFRM_IER0, WRITE_BLK_TYPE_ERROR, 13, 1)
159 FIELD(CFRM_IER0, WRITE_FRAME_ADDR_ERROR, 12, 1)
160 FIELD(CFRM_IER0, MFW_OVERRUN_ERROR, 11, 1)
161 FIELD(CFRM_IER0, FAR_FIFO_UNDERFLOW, 10, 1)
162 FIELD(CFRM_IER0, FAR_FIFO_OVERFLOW, 9, 1)
163 FIELD(CFRM_IER0, PER_FRAME_SEQ_ERROR, 8, 1)
164 FIELD(CFRM_IER0, CRC_ERROR, 7, 1)
165 FIELD(CFRM_IER0, WRITE_OVERRUN_ERROR, 6, 1)
166 FIELD(CFRM_IER0, READ_OVERRUN_ERROR, 5, 1)
167 FIELD(CFRM_IER0, CMD_INTERRUPT_ERROR, 4, 1)
168 FIELD(CFRM_IER0, WRITE_INTERRUPT_ERROR, 3, 1)
169 FIELD(CFRM_IER0, READ_INTERRUPT_ERROR, 2, 1)
170 FIELD(CFRM_IER0, SEU_CRC_ERROR, 1, 1)
171 FIELD(CFRM_IER0, SEU_ECC_ERROR, 0, 1)
172REG32(CFRM_IER1, 0x174)
173REG32(CFRM_IER2, 0x178)
174REG32(CFRM_IER3, 0x17c)
175REG32(CFRM_IDR0, 0x180)
176 FIELD(CFRM_IDR0, READ_BROADCAST_ERROR, 21, 1)
177 FIELD(CFRM_IDR0, CMD_MISSING_ERROR, 20, 1)
178 FIELD(CFRM_IDR0, RW_ROWOFF_ERROR, 19, 1)
179 FIELD(CFRM_IDR0, READ_REG_ADDR_ERROR, 18, 1)
180 FIELD(CFRM_IDR0, READ_BLK_TYPE_ERROR, 17, 1)
181 FIELD(CFRM_IDR0, READ_FRAME_ADDR_ERROR, 16, 1)
182 FIELD(CFRM_IDR0, WRITE_REG_ADDR_ERROR, 15, 1)
183 FIELD(CFRM_IDR0, WRITE_BLK_TYPE_ERROR, 13, 1)
184 FIELD(CFRM_IDR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
185 FIELD(CFRM_IDR0, MFW_OVERRUN_ERROR, 11, 1)
186 FIELD(CFRM_IDR0, FAR_FIFO_UNDERFLOW, 10, 1)
187 FIELD(CFRM_IDR0, FAR_FIFO_OVERFLOW, 9, 1)
188 FIELD(CFRM_IDR0, PER_FRAME_SEQ_ERROR, 8, 1)
189 FIELD(CFRM_IDR0, CRC_ERROR, 7, 1)
190 FIELD(CFRM_IDR0, WRITE_OVERRUN_ERROR, 6, 1)
191 FIELD(CFRM_IDR0, READ_OVERRUN_ERROR, 5, 1)
192 FIELD(CFRM_IDR0, CMD_INTERRUPT_ERROR, 4, 1)
193 FIELD(CFRM_IDR0, WRITE_INTERRUPT_ERROR, 3, 1)
194 FIELD(CFRM_IDR0, READ_INTERRUPT_ERROR, 2, 1)
195 FIELD(CFRM_IDR0, SEU_CRC_ERROR, 1, 1)
196 FIELD(CFRM_IDR0, SEU_ECC_ERROR, 0, 1)
197REG32(CFRM_IDR1, 0x184)
198REG32(CFRM_IDR2, 0x188)
199REG32(CFRM_IDR3, 0x18c)
200REG32(CFRM_ITR0, 0x190)
201 FIELD(CFRM_ITR0, READ_BROADCAST_ERROR, 21, 1)
202 FIELD(CFRM_ITR0, CMD_MISSING_ERROR, 20, 1)
203 FIELD(CFRM_ITR0, RW_ROWOFF_ERROR, 19, 1)
204 FIELD(CFRM_ITR0, READ_REG_ADDR_ERROR, 18, 1)
205 FIELD(CFRM_ITR0, READ_BLK_TYPE_ERROR, 17, 1)
206 FIELD(CFRM_ITR0, READ_FRAME_ADDR_ERROR, 16, 1)
207 FIELD(CFRM_ITR0, WRITE_REG_ADDR_ERROR, 15, 1)
208 FIELD(CFRM_ITR0, WRITE_BLK_TYPE_ERROR, 13, 1)
209 FIELD(CFRM_ITR0, WRITE_FRAME_ADDR_ERROR, 12, 1)
210 FIELD(CFRM_ITR0, MFW_OVERRUN_ERROR, 11, 1)
211 FIELD(CFRM_ITR0, FAR_FIFO_UNDERFLOW, 10, 1)
212 FIELD(CFRM_ITR0, FAR_FIFO_OVERFLOW, 9, 1)
213 FIELD(CFRM_ITR0, PER_FRAME_SEQ_ERROR, 8, 1)
214 FIELD(CFRM_ITR0, CRC_ERROR, 7, 1)
215 FIELD(CFRM_ITR0, WRITE_OVERRUN_ERROR, 6, 1)
216 FIELD(CFRM_ITR0, READ_OVERRUN_ERROR, 5, 1)
217 FIELD(CFRM_ITR0, CMD_INTERRUPT_ERROR, 4, 1)
218 FIELD(CFRM_ITR0, WRITE_INTERRUPT_ERROR, 3, 1)
219 FIELD(CFRM_ITR0, READ_INTERRUPT_ERROR, 2, 1)
220 FIELD(CFRM_ITR0, SEU_CRC_ERROR, 1, 1)
221 FIELD(CFRM_ITR0, SEU_ECC_ERROR, 0, 1)
222REG32(CFRM_ITR1, 0x194)
223REG32(CFRM_ITR2, 0x198)
224REG32(CFRM_ITR3, 0x19c)
225REG32(SEU_SYNDRM00, 0x1a0)
226REG32(SEU_SYNDRM01, 0x1a4)
227REG32(SEU_SYNDRM02, 0x1a8)
228REG32(SEU_SYNDRM03, 0x1ac)
229REG32(SEU_SYNDRM10, 0x1b0)
230REG32(SEU_SYNDRM11, 0x1b4)
231REG32(SEU_SYNDRM12, 0x1b8)
232REG32(SEU_SYNDRM13, 0x1bc)
233REG32(SEU_SYNDRM20, 0x1c0)
234REG32(SEU_SYNDRM21, 0x1c4)
235REG32(SEU_SYNDRM22, 0x1c8)
236REG32(SEU_SYNDRM23, 0x1cc)
237REG32(SEU_SYNDRM30, 0x1d0)
238REG32(SEU_SYNDRM31, 0x1d4)
239REG32(SEU_SYNDRM32, 0x1d8)
240REG32(SEU_SYNDRM33, 0x1dc)
241REG32(SEU_VIRTUAL_SYNDRM0, 0x1e0)
242REG32(SEU_VIRTUAL_SYNDRM1, 0x1e4)
243REG32(SEU_VIRTUAL_SYNDRM2, 0x1e8)
244REG32(SEU_VIRTUAL_SYNDRM3, 0x1ec)
245REG32(SEU_CRC0, 0x1f0)
246REG32(SEU_CRC1, 0x1f4)
247REG32(SEU_CRC2, 0x1f8)
248REG32(SEU_CRC3, 0x1fc)
249REG32(CFRAME_FAR_BOT0, 0x200)
250REG32(CFRAME_FAR_BOT1, 0x204)
251REG32(CFRAME_FAR_BOT2, 0x208)
252REG32(CFRAME_FAR_BOT3, 0x20c)
253REG32(CFRAME_FAR_TOP0, 0x210)
254REG32(CFRAME_FAR_TOP1, 0x214)
255REG32(CFRAME_FAR_TOP2, 0x218)
256REG32(CFRAME_FAR_TOP3, 0x21c)
257REG32(LAST_FRAME_BOT0, 0x220)
258 FIELD(LAST_FRAME_BOT0, BLOCKTYPE1_LAST_FRAME_LSB, 20, 12)
259 FIELD(LAST_FRAME_BOT0, BLOCKTYPE0_LAST_FRAME, 0, 20)
260REG32(LAST_FRAME_BOT1, 0x224)
261 FIELD(LAST_FRAME_BOT1, BLOCKTYPE3_LAST_FRAME_LSB, 28, 4)
262 FIELD(LAST_FRAME_BOT1, BLOCKTYPE2_LAST_FRAME, 8, 20)
263 FIELD(LAST_FRAME_BOT1, BLOCKTYPE1_LAST_FRAME_MSB, 0, 8)
264REG32(LAST_FRAME_BOT2, 0x228)
265 FIELD(LAST_FRAME_BOT2, BLOCKTYPE3_LAST_FRAME_MSB, 0, 16)
266REG32(LAST_FRAME_BOT3, 0x22c)
267REG32(LAST_FRAME_TOP0, 0x230)
268 FIELD(LAST_FRAME_TOP0, BLOCKTYPE5_LAST_FRAME_LSB, 20, 12)
269 FIELD(LAST_FRAME_TOP0, BLOCKTYPE4_LAST_FRAME, 0, 20)
270REG32(LAST_FRAME_TOP1, 0x234)
271 FIELD(LAST_FRAME_TOP1, BLOCKTYPE6_LAST_FRAME, 8, 20)
272 FIELD(LAST_FRAME_TOP1, BLOCKTYPE5_LAST_FRAME_MSB, 0, 8)
273REG32(LAST_FRAME_TOP2, 0x238)
274REG32(LAST_FRAME_TOP3, 0x23c)
275
276#define CFRAME_REG_R_MAX (R_LAST_FRAME_TOP3 + 1)
277
278#define KEYHOLE_STREAM_4K 0x1000
279
280#define FRAME_NUM_QWORDS 25
281#define FRAME_NUM_WORDS (FRAME_NUM_QWORDS * 4)
282
283#define MAX_BLOCKTYPE 6
284#define MAX_BLOCKTYPE_FRAMES 0xFFFFF
285
286typedef enum {
287 CFRAME_CMD_WCFG = 1,
288 CFRAME_CMD_ROWON = 2,
289 CFRAME_CMD_ROWOFF = 3,
290 CFRAME_CMD_RCFG = 4,
291 CFRAME_CMD_DLPARK = 5
292} cframe_cmd;
293
294typedef struct XlnxCFrame {
295 uint32_t addr;
296 uint32_t idx;
297 uint32_t data[FRAME_NUM_WORDS];
298} XlnxCFrame;
299
300typedef struct CFRAME_REG {
301 SysBusDevice parent_obj;
302 MemoryRegion iomem;
303 MemoryRegion iomem_fdri;
304 qemu_irq irq_cfrm_imr;
305
306
307 uint32_t wfifo[4];
308
309 uint32_t regs[CFRAME_REG_R_MAX];
310 RegisterInfo regs_info[CFRAME_REG_R_MAX];
311
312 bool rowon;
313 bool wcfg;
314 bool rcfg;
315
316 GArray *cframes;
317 XlnxCFrame new_f;
318
319 struct {
320 XlnxCfiIf *cfu_fdro;
321 uint32_t blktype_num_frames[7];
322 } cfg;
323 bool row_configured;
324
325} CFRAME_REG;
326
327typedef struct CFRAME_BCAST_REG {
328 SysBusDevice parent_obj;
329 MemoryRegion iomem_reg;
330 MemoryRegion iomem_fdri;
331
332
333 uint32_t wfifo[4];
334
335 struct {
336 XlnxCfiIf *cframe[15];
337 } cfg;
338
339} CFRAME_BCAST_REG;
340
341static void cfrm_imr_update_irq(CFRAME_REG *s)
342{
343 bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0];
344 qemu_set_irq(s->irq_cfrm_imr, pending);
345}
346
347static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64)
348{
349 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
350 cfrm_imr_update_irq(s);
351}
352
353static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64)
354{
355 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
356
357 s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0];
358 s->regs[R_CFRM_IER0] = 0;
359 cfrm_imr_update_irq(s);
360 return 0;
361}
362
363static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64)
364{
365 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
366
367 s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0];
368 s->regs[R_CFRM_IDR0] = 0;
369 cfrm_imr_update_irq(s);
370 return 0;
371}
372
373static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64)
374{
375 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
376
377 s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0];
378 s->regs[R_CFRM_ITR0] = 0;
379 cfrm_imr_update_irq(s);
380 return 0;
381}
382
383static void cframe_incr_far(CFRAME_REG *s)
384{
385 uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR);
386 uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE);
387
388 assert(blktype <= MAX_BLOCKTYPE);
389
390 faddr++;
391 if (faddr > s->cfg.blktype_num_frames[blktype]) {
392
393 faddr = 0;
394 blktype++;
395
396 assert(blktype <= MAX_BLOCKTYPE);
397
398 ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype);
399 }
400
401 ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr);
402}
403
404static XlnxCFrame *cframes_get_frame(CFRAME_REG *s, uint32_t addr)
405{
406 for (int i = 0; i < s->cframes->len; i++) {
407 XlnxCFrame *f = &g_array_index(s->cframes, XlnxCFrame, i);
408
409 if (f->addr == addr) {
410 return f;
411 }
412 }
413 return NULL;
414}
415
416static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val)
417{
418 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
419
420 if (s->row_configured && s->rowon && s->wcfg) {
421 XlnxCFrame *new_f = &s->new_f;
422
423 new_f->data[new_f->idx++] = s->regs[R_FDRI0];
424 new_f->data[new_f->idx++] = s->regs[R_FDRI1];
425 new_f->data[new_f->idx++] = s->regs[R_FDRI2];
426 new_f->data[new_f->idx++] = s->regs[R_FDRI3];
427
428 assert(new_f->idx <= FRAME_NUM_WORDS);
429
430 if (new_f->idx == FRAME_NUM_WORDS) {
431 XlnxCFrame *cur_f;
432
433
434 new_f->addr = extract32(s->regs[R_FAR0], 0, 23);
435
436 cur_f = cframes_get_frame(s, new_f->addr);
437
438 if (cur_f) {
439
440 cur_f[0] = new_f[0];
441 } else {
442 g_array_append_val(s->cframes, new_f[0]);
443 }
444
445 cframe_incr_far(s);
446
447
448 memset(new_f, 0, sizeof(*new_f));
449 }
450 }
451}
452
453static void cfrm_readout_frames(CFRAME_REG *s, uint32_t start_addr,
454 uint32_t end_addr)
455{
456 for (uint32_t addr = start_addr; addr < end_addr; addr++) {
457 XlnxCFrame *f = cframes_get_frame(s, addr);
458
459 for (int i = 0; i < FRAME_NUM_WORDS; i += 4) {
460 XlnxCfiPacket pkt = {};
461
462
463 if (f) {
464 pkt.data[0] = f->data[i];
465 pkt.data[1] = f->data[i + 1];
466 pkt.data[2] = f->data[i + 2];
467 pkt.data[3] = f->data[i + 3];
468 }
469
470 if (s->cfg.cfu_fdro) {
471 xlnx_cfi_transfer_packet(s->cfg.cfu_fdro, &pkt);
472 }
473 }
474 }
475}
476
477static void cfrm_frcnt_post_write(RegisterInfo *reg, uint64_t val)
478{
479 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
480
481 if (s->row_configured && s->rowon && s->rcfg) {
482 uint32_t start_addr = extract32(s->regs[R_FAR0], 0, 23);
483 uint32_t end_addr = start_addr + s->regs[R_FRCNT0] / FRAME_NUM_QWORDS;
484
485 cfrm_readout_frames(s, start_addr, end_addr);
486 }
487}
488
489static void cfrm_cmd_post_write(RegisterInfo *reg, uint64_t val)
490{
491 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
492
493 if (s->row_configured) {
494 uint8_t cmd = ARRAY_FIELD_EX32(s->regs, CMD0, CMD);
495
496 switch (cmd) {
497 case CFRAME_CMD_WCFG:
498 s->wcfg = true;
499 break;
500 case CFRAME_CMD_ROWON:
501 s->rowon = true;
502 break;
503 case CFRAME_CMD_ROWOFF:
504 s->rowon = false;
505 break;
506 case CFRAME_CMD_RCFG:
507 s->rcfg = true;
508 break;
509 case CFRAME_CMD_DLPARK:
510 s->wcfg = false;
511 s->rcfg = false;
512 break;
513 default:
514 break;
515 };
516 }
517}
518
519static uint64_t cfrm_last_frame_bot_post_read(RegisterInfo *reg,
520 uint64_t val64)
521{
522 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
523 uint64_t val = 0;
524
525 switch (reg->access->addr) {
526 case A_LAST_FRAME_BOT0:
527 val = FIELD_DP32(val, LAST_FRAME_BOT0, BLOCKTYPE1_LAST_FRAME_LSB,
528 s->cfg.blktype_num_frames[1]);
529 val = FIELD_DP32(val, LAST_FRAME_BOT0, BLOCKTYPE0_LAST_FRAME,
530 s->cfg.blktype_num_frames[0]);
531 break;
532 case A_LAST_FRAME_BOT1:
533 val = FIELD_DP32(val, LAST_FRAME_BOT1, BLOCKTYPE3_LAST_FRAME_LSB,
534 s->cfg.blktype_num_frames[3]);
535 val = FIELD_DP32(val, LAST_FRAME_BOT1, BLOCKTYPE2_LAST_FRAME,
536 s->cfg.blktype_num_frames[2]);
537 val = FIELD_DP32(val, LAST_FRAME_BOT1, BLOCKTYPE1_LAST_FRAME_MSB,
538 (s->cfg.blktype_num_frames[1] >> 12));
539 break;
540 case A_LAST_FRAME_BOT2:
541 val = FIELD_DP32(val, LAST_FRAME_BOT2, BLOCKTYPE3_LAST_FRAME_MSB,
542 (s->cfg.blktype_num_frames[3] >> 4));
543 break;
544 case A_LAST_FRAME_BOT3:
545 default:
546 break;
547 }
548
549 return val;
550}
551
552static uint64_t cfrm_last_frame_top_post_read(RegisterInfo *reg,
553 uint64_t val64)
554{
555 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
556 uint64_t val = 0;
557
558 switch (reg->access->addr) {
559 case A_LAST_FRAME_TOP0:
560 val = FIELD_DP32(val, LAST_FRAME_TOP0, BLOCKTYPE5_LAST_FRAME_LSB,
561 s->cfg.blktype_num_frames[5]);
562 val = FIELD_DP32(val, LAST_FRAME_TOP0, BLOCKTYPE4_LAST_FRAME,
563 s->cfg.blktype_num_frames[4]);
564 break;
565 case A_LAST_FRAME_TOP1:
566 val = FIELD_DP32(val, LAST_FRAME_TOP1, BLOCKTYPE6_LAST_FRAME,
567 s->cfg.blktype_num_frames[6]);
568 val = FIELD_DP32(val, LAST_FRAME_TOP1, BLOCKTYPE5_LAST_FRAME_MSB,
569 (s->cfg.blktype_num_frames[5] >> 12));
570 break;
571 case A_LAST_FRAME_TOP2:
572 case A_LAST_FRAME_BOT3:
573 default:
574 break;
575 }
576
577 return val;
578}
579
580static void cfrm_far_sfr_post_write(RegisterInfo *reg, uint64_t val)
581{
582 CFRAME_REG *s = XILINX_CFRAME_REG(reg->opaque);
583
584 if (s->row_configured && s->rowon && s->rcfg) {
585 uint32_t start_addr = extract32(s->regs[R_FAR_SFR0], 0, 23);
586
587
588 cfrm_readout_frames(s, start_addr, start_addr + 1);
589 }
590}
591
592static const RegisterAccessInfo cframe_reg_regs_info[] = {
593 { .name = "CRC0", .addr = A_CRC0,
594 .rsvd = 0x00000000,
595 },{ .name = "CRC1", .addr = A_CRC0,
596 .rsvd = 0xffffffff,
597 },{ .name = "CRC2", .addr = A_CRC0,
598 .rsvd = 0xffffffff,
599 },{ .name = "CRC3", .addr = A_CRC0,
600 .rsvd = 0xffffffff,
601 },{ .name = "FAR0", .addr = A_FAR0,
602 .rsvd = 0xfe000000,
603 },{ .name = "FAR1", .addr = A_FAR1,
604 .rsvd = 0xffffffff,
605 },{ .name = "FAR2", .addr = A_FAR2,
606 .rsvd = 0xffffffff,
607 },{ .name = "FAR3", .addr = A_FAR3,
608 .rsvd = 0xffffffff,
609 },{ .name = "FAR_SFR0", .addr = A_FAR_SFR0,
610 .rsvd = 0xff800000,
611 },{ .name = "FAR_SFR1", .addr = A_FAR_SFR1,
612 .rsvd = 0xffffffff,
613 },{ .name = "FAR_SFR2", .addr = A_FAR_SFR2,
614 .rsvd = 0xffffffff,
615 },{ .name = "FAR_SFR3", .addr = A_FAR_SFR3,
616 .rsvd = 0xffffffff,
617 .post_write = cfrm_far_sfr_post_write,
618 },{ .name = "FDRI0", .addr = A_FDRI0,
619 },{ .name = "FDRI1", .addr = A_FDRI1,
620 },{ .name = "FDRI2", .addr = A_FDRI2,
621 },{ .name = "FDRI3", .addr = A_FDRI3,
622 .post_write = cfrm_fdri_post_write,
623 },{ .name = "FRCNT0", .addr = A_FRCNT0,
624 .rsvd = 0x00000000,
625 },{ .name = "FRCNT1", .addr = A_FRCNT1,
626 .rsvd = 0xffffffff,
627 },{ .name = "FRCNT2", .addr = A_FRCNT2,
628 .rsvd = 0xffffffff,
629 },{ .name = "FRCNT3", .addr = A_FRCNT3,
630 .rsvd = 0xffffffff,
631 .post_write = cfrm_frcnt_post_write
632 },{ .name = "CMD0", .addr = A_CMD0,
633 .rsvd = 0xffffffe0,
634 },{ .name = "CMD1", .addr = A_CMD1,
635 .rsvd = 0xffffffff,
636 },{ .name = "CMD2", .addr = A_CMD2,
637 .rsvd = 0xffffffff,
638 },{ .name = "CMD3", .addr = A_CMD3,
639 .rsvd = 0xffffffff,
640 .post_write = cfrm_cmd_post_write
641 },{ .name = "CR_MASK0", .addr = A_CR_MASK0,
642 .rsvd = 0x00000000,
643 },{ .name = "CR_MASK1", .addr = A_CR_MASK1,
644 .rsvd = 0x00000000,
645 },{ .name = "CR_MASK2", .addr = A_CR_MASK2,
646 .rsvd = 0x00000000,
647 },{ .name = "CR_MASK3", .addr = A_CR_MASK3,
648 .rsvd = 0xffffffff,
649 },{ .name = "CTL0", .addr = A_CTL0,
650 .rsvd = 0xfffffff8,
651 },{ .name = "CTL1", .addr = A_CTL1,
652 .rsvd = 0xffffffff,
653 },{ .name = "CTL2", .addr = A_CTL2,
654 .rsvd = 0xffffffff,
655 },{ .name = "CTL3", .addr = A_CTL3,
656 .rsvd = 0xffffffff,
657 },{ .name = "CFRM_ISR0", .addr = A_CFRM_ISR0,
658 .rsvd = 0xffc04000,
659 .w1c = 0x3bfff,
660 },{ .name = "CFRM_ISR1", .addr = A_CFRM_ISR1,
661 .rsvd = 0xffffffff,
662 },{ .name = "CFRM_ISR2", .addr = A_CFRM_ISR2,
663 .rsvd = 0xffffffff,
664 },{ .name = "CFRM_ISR3", .addr = A_CFRM_ISR3,
665 .rsvd = 0xffffffff,
666 .post_write = cfrm_isr_postw,
667 },{ .name = "CFRM_IMR0", .addr = A_CFRM_IMR0,
668 .rsvd = 0xffc04000,
669 .ro = 0xfffff,
670 .reset = 0x3bfff,
671 },{ .name = "CFRM_IMR1", .addr = A_CFRM_IMR1,
672 .rsvd = 0xffffffff,
673 },{ .name = "CFRM_IMR2", .addr = A_CFRM_IMR2,
674 .rsvd = 0xffffffff,
675 },{ .name = "CFRM_IMR3", .addr = A_CFRM_IMR3,
676 .rsvd = 0xffffffff,
677 },{ .name = "CFRM_IER0", .addr = A_CFRM_IER0,
678 .rsvd = 0xffc04000,
679 },{ .name = "CFRM_IER1", .addr = A_CFRM_IER1,
680 .rsvd = 0xffffffff,
681 },{ .name = "CFRM_IER2", .addr = A_CFRM_IER2,
682 .rsvd = 0xffffffff,
683 },{ .name = "CFRM_IER3", .addr = A_CFRM_IER3,
684 .rsvd = 0xffffffff,
685 .pre_write = cfrm_ier_prew,
686 },{ .name = "CFRM_IDR0", .addr = A_CFRM_IDR0,
687 .rsvd = 0xffc04000,
688 },{ .name = "CFRM_IDR1", .addr = A_CFRM_IDR1,
689 .rsvd = 0xffffffff,
690 },{ .name = "CFRM_IDR2", .addr = A_CFRM_IDR2,
691 .rsvd = 0xffffffff,
692 },{ .name = "CFRM_IDR3", .addr = A_CFRM_IDR3,
693 .rsvd = 0xffffffff,
694 .pre_write = cfrm_idr_prew,
695 },{ .name = "CFRM_ITR0", .addr = A_CFRM_ITR0,
696 .rsvd = 0xffc04000,
697 },{ .name = "CFRM_ITR1", .addr = A_CFRM_ITR1,
698 .rsvd = 0xffffffff,
699 },{ .name = "CFRM_ITR2", .addr = A_CFRM_ITR2,
700 .rsvd = 0xffffffff,
701 },{ .name = "CFRM_ITR3", .addr = A_CFRM_ITR3,
702 .rsvd = 0xffffffff,
703 .pre_write = cfrm_itr_prew,
704 },{ .name = "SEU_SYNDRM00", .addr = A_SEU_SYNDRM00,
705 },{ .name = "SEU_SYNDRM01", .addr = A_SEU_SYNDRM01,
706 },{ .name = "SEU_SYNDRM02", .addr = A_SEU_SYNDRM02,
707 },{ .name = "SEU_SYNDRM03", .addr = A_SEU_SYNDRM03,
708 },{ .name = "SEU_SYNDRM10", .addr = A_SEU_SYNDRM10,
709 },{ .name = "SEU_SYNDRM11", .addr = A_SEU_SYNDRM11,
710 },{ .name = "SEU_SYNDRM12", .addr = A_SEU_SYNDRM12,
711 },{ .name = "SEU_SYNDRM13", .addr = A_SEU_SYNDRM13,
712 },{ .name = "SEU_SYNDRM20", .addr = A_SEU_SYNDRM20,
713 },{ .name = "SEU_SYNDRM21", .addr = A_SEU_SYNDRM21,
714 },{ .name = "SEU_SYNDRM22", .addr = A_SEU_SYNDRM22,
715 },{ .name = "SEU_SYNDRM23", .addr = A_SEU_SYNDRM23,
716 },{ .name = "SEU_SYNDRM30", .addr = A_SEU_SYNDRM30,
717 },{ .name = "SEU_SYNDRM31", .addr = A_SEU_SYNDRM31,
718 },{ .name = "SEU_SYNDRM32", .addr = A_SEU_SYNDRM32,
719 },{ .name = "SEU_SYNDRM33", .addr = A_SEU_SYNDRM33,
720 },{ .name = "SEU_VIRTUAL_SYNDRM0", .addr = A_SEU_VIRTUAL_SYNDRM0,
721 },{ .name = "SEU_VIRTUAL_SYNDRM1", .addr = A_SEU_VIRTUAL_SYNDRM1,
722 },{ .name = "SEU_VIRTUAL_SYNDRM2", .addr = A_SEU_VIRTUAL_SYNDRM2,
723 },{ .name = "SEU_VIRTUAL_SYNDRM3", .addr = A_SEU_VIRTUAL_SYNDRM3,
724 },{ .name = "SEU_CRC0", .addr = A_SEU_CRC0,
725 },{ .name = "SEU_CRC1", .addr = A_SEU_CRC1,
726 },{ .name = "SEU_CRC2", .addr = A_SEU_CRC2,
727 },{ .name = "SEU_CRC3", .addr = A_SEU_CRC3,
728 },{ .name = "CFRAME_FAR_BOT0", .addr = A_CFRAME_FAR_BOT0,
729 },{ .name = "CFRAME_FAR_BOT1", .addr = A_CFRAME_FAR_BOT1,
730 },{ .name = "CFRAME_FAR_BOT2", .addr = A_CFRAME_FAR_BOT2,
731 },{ .name = "CFRAME_FAR_BOT3", .addr = A_CFRAME_FAR_BOT3,
732 },{ .name = "CFRAME_FAR_TOP0", .addr = A_CFRAME_FAR_TOP0,
733 },{ .name = "CFRAME_FAR_TOP1", .addr = A_CFRAME_FAR_TOP1,
734 },{ .name = "CFRAME_FAR_TOP2", .addr = A_CFRAME_FAR_TOP2,
735 },{ .name = "CFRAME_FAR_TOP3", .addr = A_CFRAME_FAR_TOP3,
736 },{ .name = "LAST_FRAME_BOT0", .addr = A_LAST_FRAME_BOT0,
737 .ro = 0xffffffff,
738 .post_read = cfrm_last_frame_bot_post_read,
739 },{ .name = "LAST_FRAME_BOT1", .addr = A_LAST_FRAME_BOT1,
740 .ro = 0xffffffff,
741 .post_read = cfrm_last_frame_bot_post_read,
742 },{ .name = "LAST_FRAME_BOT2", .addr = A_LAST_FRAME_BOT2,
743 .ro = 0xffffffff,
744 .post_read = cfrm_last_frame_bot_post_read,
745 },{ .name = "LAST_FRAME_BOT3", .addr = A_LAST_FRAME_BOT3,
746 .ro = 0xffffffff,
747 .post_read = cfrm_last_frame_bot_post_read,
748 },{ .name = "LAST_FRAME_TOP0", .addr = A_LAST_FRAME_TOP0,
749 .ro = 0xffffffff,
750 .post_read = cfrm_last_frame_top_post_read,
751 },{ .name = "LAST_FRAME_TOP1", .addr = A_LAST_FRAME_TOP1,
752 .ro = 0xffffffff,
753 .post_read = cfrm_last_frame_top_post_read,
754 },{ .name = "LAST_FRAME_TOP2", .addr = A_LAST_FRAME_TOP2,
755 .ro = 0xffffffff,
756 .post_read = cfrm_last_frame_top_post_read,
757 },{ .name = "LAST_FRAME_TOP3", .addr = A_LAST_FRAME_TOP3,
758 .ro = 0xffffffff,
759 .post_read = cfrm_last_frame_top_post_read,
760 }
761};
762
763static void cframe_reg_cfi_transfer_packet(XlnxCfiIf *cfi_if,
764 XlnxCfiPacket *pkt)
765{
766 CFRAME_REG *s = XILINX_CFRAME_REG(cfi_if);
767 uint64_t we = MAKE_64BIT_MASK(0, 4 * 8);
768
769 if (!s->row_configured) {
770 return;
771 }
772
773 switch (pkt->reg_addr) {
774 case CFRAME_FAR:
775 s->regs[R_FAR0] = pkt->data[0];
776 break;
777 case CFRAME_SFR:
778 s->regs[R_FAR_SFR0] = pkt->data[0];
779 register_write(&s->regs_info[R_FAR_SFR3], 0,
780 we, object_get_typename(OBJECT(s)),
781 XILINX_CFRAME_REG_ERR_DEBUG);
782 break;
783 case CFRAME_FDRI:
784 {
785 s->regs[R_FDRI0] = pkt->data[0];
786 s->regs[R_FDRI1] = pkt->data[1];
787 s->regs[R_FDRI2] = pkt->data[2];
788 register_write(&s->regs_info[R_FDRI3], pkt->data[3],
789 we, object_get_typename(OBJECT(s)),
790 XILINX_CFRAME_REG_ERR_DEBUG);
791 break;
792 }
793 case CFRAME_CMD:
794 ARRAY_FIELD_DP32(s->regs, CMD0, CMD, pkt->data[0]);
795
796 register_write(&s->regs_info[R_CMD3], 0,
797 we, object_get_typename(OBJECT(s)),
798 XILINX_CFRAME_REG_ERR_DEBUG);
799 break;
800 default:
801 break;
802 }
803}
804
805static uint64_t cframe_reg_fdri_read(void *opaque, hwaddr addr, unsigned size)
806{
807 qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
808 HWADDR_PRIx "\n", __func__, addr);
809 return 0;
810}
811
812static void cframe_reg_fdri_write(void *opaque, hwaddr addr, uint64_t value,
813 unsigned size)
814{
815 CFRAME_REG *s = XILINX_CFRAME_REG(opaque);
816 unsigned int idx;
817
818
819 idx = (addr >> 2) & 3;
820
821 s->wfifo[idx] = value;
822
823
824 if (idx == 3) {
825 uint64_t we = MAKE_64BIT_MASK(0, 4 * 8);
826
827 s->regs[R_FDRI0] = s->wfifo[0];
828 s->regs[R_FDRI1] = s->wfifo[1];
829 s->regs[R_FDRI2] = s->wfifo[2];
830 register_write(&s->regs_info[R_FDRI3], s->wfifo[3],
831 we, object_get_typename(OBJECT(s)),
832 XILINX_CFRAME_REG_ERR_DEBUG);
833
834 memset(s->wfifo, 0, 4 * sizeof(uint32_t));
835 }
836}
837
838static void cframe_reg_reset_enter(Object *obj, ResetType type)
839{
840 CFRAME_REG *s = XILINX_CFRAME_REG(obj);
841 unsigned int i;
842
843 for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
844 register_reset(&s->regs_info[i]);
845 }
846}
847
848static void cframe_reg_reset_hold(Object *obj)
849{
850 CFRAME_REG *s = XILINX_CFRAME_REG(obj);
851
852 cfrm_imr_update_irq(s);
853}
854
855static const MemoryRegionOps cframe_reg_ops = {
856 .read = register_read_memory,
857 .write = register_write_memory,
858 .endianness = DEVICE_LITTLE_ENDIAN,
859 .valid = {
860 .min_access_size = 4,
861 .max_access_size = 4,
862 },
863};
864
865static const MemoryRegionOps cframe_reg_fdri_ops = {
866 .read = cframe_reg_fdri_read,
867 .write = cframe_reg_fdri_write,
868 .endianness = DEVICE_LITTLE_ENDIAN,
869 .valid = {
870 .min_access_size = 4,
871 .max_access_size = 4,
872 },
873};
874
875static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned size)
876{
877 qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
878 HWADDR_PRIx "\n", __func__, addr);
879 return 0;
880}
881
882static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value,
883 unsigned size)
884{
885 CFRAME_BCAST_REG *s = XILINX_CFRAME_BCAST_REG(opaque);
886 unsigned int idx;
887
888
889 idx = (addr >> 2) & 3;
890
891 s->wfifo[idx] = value;
892
893
894 if (idx == 3) {
895 uint32_t reg_addr = extract32(addr, 4, 6);
896 XlnxCfiPacket pkt = {
897 .reg_addr = reg_addr,
898 .data[0] = s->wfifo[0],
899 .data[1] = s->wfifo[1],
900 .data[2] = s->wfifo[2],
901 .data[3] = s->wfifo[3]
902 };
903
904 for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
905 if (s->cfg.cframe[i]) {
906 xlnx_cfi_transfer_packet(s->cfg.cframe[i], &pkt);
907 }
908 }
909
910 memset(s->wfifo, 0, 4 * sizeof(uint32_t));
911 }
912}
913
914static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr,
915 unsigned size)
916{
917 qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%"
918 HWADDR_PRIx "\n", __func__, addr);
919 return 0;
920}
921
922static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value,
923 unsigned size)
924{
925 CFRAME_BCAST_REG *s = XILINX_CFRAME_BCAST_REG(opaque);
926 unsigned int idx;
927
928
929 idx = (addr >> 2) & 3;
930
931 s->wfifo[idx] = value;
932
933
934 if (idx == 3) {
935 XlnxCfiPacket pkt = {
936 .reg_addr = CFRAME_FDRI,
937 .data[0] = s->wfifo[0],
938 .data[1] = s->wfifo[1],
939 .data[2] = s->wfifo[2],
940 .data[3] = s->wfifo[3]
941 };
942
943 for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) {
944 if (s->cfg.cframe[i]) {
945 xlnx_cfi_transfer_packet(s->cfg.cframe[i], &pkt);
946 }
947 }
948
949 memset(s->wfifo, 0, 4 * sizeof(uint32_t));
950 }
951}
952
953static const MemoryRegionOps cframes_bcast_reg_reg_ops = {
954 .read = cframes_bcast_reg_read,
955 .write = cframes_bcast_reg_write,
956 .endianness = DEVICE_LITTLE_ENDIAN,
957 .valid = {
958 .min_access_size = 4,
959 .max_access_size = 4,
960 },
961};
962
963static const MemoryRegionOps cframes_bcast_reg_fdri_ops = {
964 .read = cframes_bcast_fdri_read,
965 .write = cframes_bcast_fdri_write,
966 .endianness = DEVICE_LITTLE_ENDIAN,
967 .valid = {
968 .min_access_size = 4,
969 .max_access_size = 4,
970 },
971};
972
973static void cframe_reg_realize(DeviceState *dev, Error **errp)
974{
975 CFRAME_REG *s = XILINX_CFRAME_REG(dev);
976
977 for (int i = 0; i < ARRAY_SIZE(s->cfg.blktype_num_frames); i++) {
978 if (s->cfg.blktype_num_frames[i] > MAX_BLOCKTYPE_FRAMES) {
979 error_setg(errp,
980 "blktype-frames%d > 0xFFFFF (max frame per block)",
981 i);
982 return;
983 }
984 if (s->cfg.blktype_num_frames[i]) {
985 s->row_configured = true;
986 }
987 }
988}
989
990static void cframe_reg_init(Object *obj)
991{
992 CFRAME_REG *s = XILINX_CFRAME_REG(obj);
993 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
994 RegisterInfoArray *reg_array;
995
996 memory_region_init(&s->iomem, obj, TYPE_XILINX_CFRAME_REG,
997 CFRAME_REG_R_MAX * 4);
998 reg_array =
999 register_init_block32(DEVICE(obj), cframe_reg_regs_info,
1000 ARRAY_SIZE(cframe_reg_regs_info),
1001 s->regs_info, s->regs,
1002 &cframe_reg_ops,
1003 XILINX_CFRAME_REG_ERR_DEBUG,
1004 CFRAME_REG_R_MAX * 4);
1005 memory_region_add_subregion(&s->iomem,
1006 0x0,
1007 ®_array->mem);
1008 sysbus_init_mmio(sbd, &s->iomem);
1009 memory_region_init_io(&s->iomem_fdri, obj, &cframe_reg_fdri_ops, s,
1010 TYPE_XILINX_CFRAME_REG "-fdri", KEYHOLE_STREAM_4K);
1011 sysbus_init_mmio(sbd, &s->iomem_fdri);
1012 sysbus_init_irq(sbd, &s->irq_cfrm_imr);
1013
1014 s->cframes = g_array_new(FALSE, FALSE, sizeof(XlnxCFrame));
1015}
1016
1017static const VMStateDescription vmstate_cframe_reg = {
1018 .name = TYPE_XILINX_CFRAME_REG,
1019 .version_id = 1,
1020 .minimum_version_id = 1,
1021 .fields = (VMStateField[]) {
1022 VMSTATE_UINT32_ARRAY(regs, CFRAME_REG, CFRAME_REG_R_MAX),
1023 VMSTATE_END_OF_LIST(),
1024 }
1025};
1026
1027static Property cframe_regs_props[] = {
1028
1029 DEFINE_PROP_LINK("cfu", CFRAME_REG, cfg.cfu_fdro,
1030 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1031 DEFINE_PROP_LINK("cfu-fdro", CFRAME_REG, cfg.cfu_fdro,
1032 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1033 DEFINE_PROP_UINT32("blktype0-frames", CFRAME_REG,
1034 cfg.blktype_num_frames[0], 0),
1035 DEFINE_PROP_UINT32("blktype1-frames", CFRAME_REG,
1036 cfg.blktype_num_frames[1], 0),
1037 DEFINE_PROP_UINT32("blktype2-frames", CFRAME_REG,
1038 cfg.blktype_num_frames[2], 0),
1039 DEFINE_PROP_UINT32("blktype3-frames", CFRAME_REG,
1040 cfg.blktype_num_frames[3], 0),
1041 DEFINE_PROP_UINT32("blktype4-frames", CFRAME_REG,
1042 cfg.blktype_num_frames[4], 0),
1043 DEFINE_PROP_UINT32("blktype5-frames", CFRAME_REG,
1044 cfg.blktype_num_frames[5], 0),
1045 DEFINE_PROP_UINT32("blktype6-frames", CFRAME_REG,
1046 cfg.blktype_num_frames[6], 0),
1047 DEFINE_PROP_END_OF_LIST(),
1048};
1049
1050static void cframe_bcast_reg_init(Object *obj)
1051{
1052 CFRAME_BCAST_REG *s = XILINX_CFRAME_BCAST_REG(obj);
1053 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1054
1055 memory_region_init_io(&s->iomem_reg, obj, &cframes_bcast_reg_reg_ops, s,
1056 TYPE_XILINX_CFRAME_BCAST_REG, KEYHOLE_STREAM_4K);
1057 memory_region_init_io(&s->iomem_fdri, obj, &cframes_bcast_reg_fdri_ops, s,
1058 TYPE_XILINX_CFRAME_BCAST_REG "-fdri",
1059 KEYHOLE_STREAM_4K);
1060 sysbus_init_mmio(sbd, &s->iomem_reg);
1061 sysbus_init_mmio(sbd, &s->iomem_fdri);
1062}
1063
1064static Property cframe_bcast_regs_props[] = {
1065 DEFINE_PROP_LINK("cframe0", CFRAME_BCAST_REG, cfg.cframe[0],
1066 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1067 DEFINE_PROP_LINK("cframe1", CFRAME_BCAST_REG, cfg.cframe[1],
1068 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1069 DEFINE_PROP_LINK("cframe2", CFRAME_BCAST_REG, cfg.cframe[2],
1070 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1071 DEFINE_PROP_LINK("cframe3", CFRAME_BCAST_REG, cfg.cframe[3],
1072 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1073 DEFINE_PROP_LINK("cframe4", CFRAME_BCAST_REG, cfg.cframe[4],
1074 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1075 DEFINE_PROP_LINK("cframe5", CFRAME_BCAST_REG, cfg.cframe[5],
1076 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1077 DEFINE_PROP_LINK("cframe6", CFRAME_BCAST_REG, cfg.cframe[6],
1078 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1079 DEFINE_PROP_LINK("cframe7", CFRAME_BCAST_REG, cfg.cframe[7],
1080 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1081 DEFINE_PROP_LINK("cframe8", CFRAME_BCAST_REG, cfg.cframe[8],
1082 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1083 DEFINE_PROP_LINK("cframe9", CFRAME_BCAST_REG, cfg.cframe[9],
1084 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1085 DEFINE_PROP_LINK("cframe10", CFRAME_BCAST_REG, cfg.cframe[10],
1086 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1087 DEFINE_PROP_LINK("cframe11", CFRAME_BCAST_REG, cfg.cframe[11],
1088 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1089 DEFINE_PROP_LINK("cframe12", CFRAME_BCAST_REG, cfg.cframe[12],
1090 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1091 DEFINE_PROP_LINK("cframe13", CFRAME_BCAST_REG, cfg.cframe[13],
1092 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1093 DEFINE_PROP_LINK("cframe14", CFRAME_BCAST_REG, cfg.cframe[14],
1094 TYPE_XLNX_CFI_IF, XlnxCfiIf *),
1095 DEFINE_PROP_END_OF_LIST(),
1096};
1097
1098static void cframe_reg_class_init(ObjectClass *klass, void *data)
1099{
1100 ResettableClass *rc = RESETTABLE_CLASS(klass);
1101 DeviceClass *dc = DEVICE_CLASS(klass);
1102 XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass);
1103
1104 dc->vmsd = &vmstate_cframe_reg;
1105 dc->realize = cframe_reg_realize;
1106 rc->phases.enter = cframe_reg_reset_enter;
1107 rc->phases.hold = cframe_reg_reset_hold;
1108 device_class_set_props(dc, cframe_regs_props);
1109 xcic->cfi_transfer_packet = cframe_reg_cfi_transfer_packet;
1110}
1111
1112static void cframe_bcast_reg_class_init(ObjectClass *klass, void *data)
1113{
1114 DeviceClass *dc = DEVICE_CLASS(klass);
1115
1116 device_class_set_props(dc, cframe_bcast_regs_props);
1117}
1118
1119static const TypeInfo cframe_reg_info = {
1120 .name = TYPE_XILINX_CFRAME_REG,
1121 .parent = TYPE_SYS_BUS_DEVICE,
1122 .instance_size = sizeof(CFRAME_REG),
1123 .class_init = cframe_reg_class_init,
1124 .instance_init = cframe_reg_init,
1125 .interfaces = (InterfaceInfo[]) {
1126 { TYPE_XLNX_CFI_IF },
1127 { }
1128 }
1129};
1130
1131static const TypeInfo cframe_bcast_reg_info = {
1132 .name = TYPE_XILINX_CFRAME_BCAST_REG,
1133 .parent = TYPE_SYS_BUS_DEVICE,
1134 .instance_size = sizeof(CFRAME_BCAST_REG),
1135 .class_init = cframe_bcast_reg_class_init,
1136 .instance_init = cframe_bcast_reg_init,
1137};
1138
1139static void cframe_reg_register_types(void)
1140{
1141 type_register_static(&cframe_reg_info);
1142 type_register_static(&cframe_bcast_reg_info);
1143}
1144
1145type_init(cframe_reg_register_types)
1146