xref: /openbmc/qemu/hw/net/can/ctucan_core.c (revision ad6f932f)
1 /*
2  * CTU CAN FD PCI device emulation
3  * http://canbus.pages.fel.cvut.cz/
4  *
5  * Copyright (c) 2019 Jan Charvat (jancharvat.charvat@gmail.com)
6  *
7  * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by
8  * Jin Yang and Pavel Pisa
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a copy
11  * of this software and associated documentation files (the "Software"), to deal
12  * in the Software without restriction, including without limitation the rights
13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14  * copies of the Software, and to permit persons to whom the Software is
15  * furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included in
18  * all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26  * THE SOFTWARE.
27  */
28 
29 #include "qemu/osdep.h"
30 #include "qemu/log.h"
31 #include "chardev/char.h"
32 #include "hw/irq.h"
33 #include "migration/vmstate.h"
34 #include "net/can_emu.h"
35 
36 #include "ctucan_core.h"
37 
38 #ifndef DEBUG_CAN
39 #define DEBUG_CAN 0
40 #endif /*DEBUG_CAN*/
41 
42 #define DPRINTF(fmt, ...) \
43     do { \
44         if (DEBUG_CAN) { \
45             qemu_log("[ctucan]: " fmt , ## __VA_ARGS__); \
46         } \
47     } while (0)
48 
49 static void ctucan_buff2frame(const uint8_t *buff, qemu_can_frame *frame)
50 {
51     frame->can_id = 0;
52     frame->can_dlc = 0;
53     frame->flags = 0;
54 
55     if (buff == NULL) {
56         return;
57     }
58     {
59         union ctu_can_fd_frame_form_w frame_form_w;
60         union ctu_can_fd_identifier_w identifier_w;
61         unsigned int ide;
62         uint32_t w;
63 
64         w = le32_to_cpu(*(uint32_t *)buff);
65         frame_form_w = (union ctu_can_fd_frame_form_w)w;
66         frame->can_dlc = can_dlc2len(frame_form_w.s.dlc);
67 
68         w = le32_to_cpu(*(uint32_t *)(buff + 4));
69         identifier_w = (union ctu_can_fd_identifier_w)w;
70 
71         ide = frame_form_w.s.ide;
72         if (ide) {
73             frame->can_id = (identifier_w.s.identifier_base << 18) |
74                             identifier_w.s.identifier_ext;
75             frame->can_id |= QEMU_CAN_EFF_FLAG;
76         } else {
77             frame->can_id = identifier_w.s.identifier_base;
78         }
79 
80         if (frame_form_w.s.esi_rsv) {
81             frame->flags |= QEMU_CAN_FRMF_ESI;
82         }
83 
84         if (frame_form_w.s.rtr) {
85             frame->can_id |= QEMU_CAN_RTR_FLAG;
86         }
87 
88         if (frame_form_w.s.fdf) {   /*CAN FD*/
89             frame->flags |= QEMU_CAN_FRMF_TYPE_FD;
90             if (frame_form_w.s.brs) {
91                 frame->flags |= QEMU_CAN_FRMF_BRS;
92             }
93         }
94     }
95 
96     memcpy(frame->data, buff + 0x10, 0x40);
97 }
98 
99 
100 static int ctucan_frame2buff(const qemu_can_frame *frame, uint8_t *buff)
101 {
102     unsigned int bytes_cnt = -1;
103     memset(buff, 0, CTUCAN_MSG_MAX_LEN * sizeof(*buff));
104 
105     if (frame == NULL) {
106         return bytes_cnt;
107     }
108     {
109         union ctu_can_fd_frame_form_w frame_form_w;
110         union ctu_can_fd_identifier_w identifier_w;
111 
112         frame_form_w.u32 = 0;
113         identifier_w.u32 = 0;
114 
115         bytes_cnt = frame->can_dlc;
116         bytes_cnt = (bytes_cnt + 3) & ~3;
117         bytes_cnt += 16;
118         frame_form_w.s.rwcnt = (bytes_cnt >> 2) - 1;
119 
120         frame_form_w.s.dlc = can_len2dlc(frame->can_dlc);
121 
122         if (frame->can_id & QEMU_CAN_EFF_FLAG) {
123             frame_form_w.s.ide = 1;
124             identifier_w.s.identifier_base =
125                                     (frame->can_id & 0x1FFC0000) >> 18;
126             identifier_w.s.identifier_ext = frame->can_id & 0x3FFFF;
127         } else {
128             identifier_w.s.identifier_base = frame->can_id & 0x7FF;
129         }
130 
131         if (frame->flags & QEMU_CAN_FRMF_ESI) {
132             frame_form_w.s.esi_rsv = 1;
133         }
134 
135         if (frame->can_id & QEMU_CAN_RTR_FLAG) {
136             frame_form_w.s.rtr = 1;
137         }
138 
139         if (frame->flags & QEMU_CAN_FRMF_TYPE_FD) {  /*CAN FD*/
140            frame_form_w.s.fdf = 1;
141             if (frame->flags & QEMU_CAN_FRMF_BRS) {
142                 frame_form_w.s.brs = 1;
143             }
144         }
145         *(uint32_t *)buff = cpu_to_le32(frame_form_w.u32);
146         *(uint32_t *)(buff + 4) = cpu_to_le32(identifier_w.u32);
147     }
148 
149     memcpy(buff + 0x10, frame->data, 0x40);
150 
151     return bytes_cnt;
152 }
153 
154 static void ctucan_update_irq(CtuCanCoreState *s)
155 {
156     union ctu_can_fd_int_stat int_rq;
157 
158     int_rq.u32 = 0;
159 
160     if (s->rx_status_rx_settings.s.rxfrc) {
161         int_rq.s.rbnei = 1;
162     }
163 
164     int_rq.u32 &= ~s->int_mask.u32;
165     s->int_stat.u32 |= int_rq.u32;
166     if (s->int_stat.u32 & s->int_ena.u32) {
167         qemu_irq_raise(s->irq);
168     } else {
169         qemu_irq_lower(s->irq);
170     }
171 }
172 
173 static void ctucan_update_txnf(CtuCanCoreState *s)
174 {
175     int i;
176     int txnf;
177     unsigned int buff_st;
178 
179     txnf = 0;
180 
181     for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) {
182         buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf;
183         if (buff_st == TXT_ETY) {
184             txnf = 1;
185         }
186     }
187     s->status.s.txnf = txnf;
188 }
189 
190 void ctucan_hardware_reset(CtuCanCoreState *s)
191 {
192     DPRINTF("Hardware reset in progress!!!\n");
193     int i;
194     unsigned int buff_st;
195     uint32_t buff_st_mask;
196 
197     s->tx_status.u32 = 0;
198     for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) {
199         buff_st_mask = 0xf << (i * 4);
200         buff_st = TXT_ETY;
201         s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) |
202             (buff_st << (i * 4));
203     }
204     s->status.s.idle = 1;
205 
206     ctucan_update_txnf(s);
207 
208     s->rx_status_rx_settings.u32 = 0;
209     s->rx_tail_pos = 0;
210     s->rx_cnt = 0;
211     s->rx_frame_rem = 0;
212 
213     /* Flush RX buffer */
214     s->rx_tail_pos = 0;
215     s->rx_cnt = 0;
216     s->rx_frame_rem = 0;
217 
218     /* Set on progdokum reset value */
219     s->mode_settings.u32 = 0;
220     s->mode_settings.s.fde = 1;
221 
222     s->int_stat.u32 = 0;
223     s->int_ena.u32 = 0;
224     s->int_mask.u32 = 0;
225 
226     s->rx_status_rx_settings.u32 = 0;
227     s->rx_status_rx_settings.s.rxe = 0;
228 
229     s->rx_fr_ctr.u32 = 0;
230     s->tx_fr_ctr.u32 = 0;
231 
232     s->yolo_reg.s.yolo_val = 3735928559;
233 
234     qemu_irq_lower(s->irq);
235 }
236 
237 static void ctucan_send_ready_buffers(CtuCanCoreState *s)
238 {
239     qemu_can_frame frame;
240     uint8_t *pf;
241     int buff2tx_idx;
242     uint32_t tx_prio_max;
243 
244     if (!s->mode_settings.s.ena) {
245         return;
246     }
247 
248     do {
249         union ctu_can_fd_int_stat int_stat;
250         int i;
251         buff2tx_idx = -1;
252         tx_prio_max = 0;
253 
254         for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) {
255             uint32_t prio;
256 
257             if (extract32(s->tx_status.u32, i * 4, 4) != TXT_RDY) {
258                 continue;
259             }
260             prio = (s->tx_priority.u32 >> (i * 4)) & 0x7;
261             if (tx_prio_max < prio) {
262                 tx_prio_max = prio;
263                 buff2tx_idx = i;
264             }
265         }
266         if (buff2tx_idx == -1) {
267             break;
268         }
269         int_stat.u32 = 0;
270         pf = s->tx_buffer[buff2tx_idx].data;
271         ctucan_buff2frame(pf, &frame);
272         s->status.s.idle = 0;
273         s->status.s.txs = 1;
274         can_bus_client_send(&s->bus_client, &frame, 1);
275         s->status.s.idle = 1;
276         s->status.s.txs = 0;
277         s->tx_fr_ctr.s.tx_fr_ctr_val++;
278         int_stat.s.txi = 1;
279         int_stat.s.txbhci = 1;
280         s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32;
281         s->tx_status.u32 = deposit32(s->tx_status.u32,
282                                      buff2tx_idx * 4, 4, TXT_TOK);
283     } while (1);
284 }
285 
286 #define CTUCAN_CORE_TXBUFF_SPAN \
287             (CTU_CAN_FD_TXTB2_DATA_1 - CTU_CAN_FD_TXTB1_DATA_1)
288 
289 void ctucan_mem_write(CtuCanCoreState *s, hwaddr addr, uint64_t val,
290                        unsigned size)
291 {
292     int              i;
293 
294     DPRINTF("write 0x%02llx addr 0x%02x\n",
295             (unsigned long long)val, (unsigned int)addr);
296 
297     if (addr >= CTUCAN_CORE_MEM_SIZE) {
298         return;
299     }
300 
301     if (addr >= CTU_CAN_FD_TXTB1_DATA_1) {
302         int buff_num;
303         addr -= CTU_CAN_FD_TXTB1_DATA_1;
304         buff_num = addr / CTUCAN_CORE_TXBUFF_SPAN;
305         addr %= CTUCAN_CORE_TXBUFF_SPAN;
306         if ((buff_num < CTUCAN_CORE_TXBUF_NUM) &&
307             ((addr + size) <= sizeof(s->tx_buffer[buff_num].data))) {
308             stn_le_p(s->tx_buffer[buff_num].data + addr, size, val);
309         }
310     } else {
311         switch (addr & ~3) {
312         case CTU_CAN_FD_MODE:
313             s->mode_settings.u32 = (uint32_t)val;
314             if (s->mode_settings.s.rst) {
315                 ctucan_hardware_reset(s);
316                 s->mode_settings.s.rst = 0;
317             }
318             break;
319         case CTU_CAN_FD_COMMAND:
320         {
321             union ctu_can_fd_command command;
322             command.u32 = (uint32_t)val;
323             if (command.s.cdo) {
324                 s->status.s.dor = 0;
325             }
326             if (command.s.rrb) {
327                 s->rx_tail_pos = 0;
328                 s->rx_cnt = 0;
329                 s->rx_frame_rem = 0;
330                 s->rx_status_rx_settings.s.rxfrc = 0;
331             }
332             if (command.s.txfcrst) {
333                 s->tx_fr_ctr.s.tx_fr_ctr_val = 0;
334             }
335             if (command.s.rxfcrst) {
336                 s->rx_fr_ctr.s.rx_fr_ctr_val = 0;
337             }
338             break;
339         }
340         case CTU_CAN_FD_INT_STAT:
341             s->int_stat.u32 &= ~(uint32_t)val;
342             break;
343         case CTU_CAN_FD_INT_ENA_SET:
344             s->int_ena.u32 |= (uint32_t)val;
345             break;
346         case CTU_CAN_FD_INT_ENA_CLR:
347             s->int_ena.u32 &= ~(uint32_t)val;
348             break;
349         case CTU_CAN_FD_INT_MASK_SET:
350             s->int_mask.u32 |= (uint32_t)val;
351             break;
352         case CTU_CAN_FD_INT_MASK_CLR:
353             s->int_mask.u32 &= ~(uint32_t)val;
354             break;
355         case CTU_CAN_FD_TX_COMMAND:
356             if (s->mode_settings.s.ena) {
357                 union ctu_can_fd_tx_command tx_command;
358                 union ctu_can_fd_tx_command mask;
359                 unsigned int buff_st;
360                 uint32_t buff_st_mask;
361 
362                 tx_command.u32 = (uint32_t)val;
363                 mask.u32 = 0;
364                 mask.s.txb1 = 1;
365 
366                 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) {
367                     if (!(tx_command.u32 & (mask.u32 << i))) {
368                         continue;
369                     }
370                     buff_st_mask = 0xf << (i * 4);
371                     buff_st = (s->tx_status.u32 >> (i * 4)) & 0xf;
372                     if (tx_command.s.txca) {
373                         if (buff_st == TXT_RDY) {
374                             buff_st = TXT_ABT;
375                         }
376                     }
377                     if (tx_command.s.txcr) {
378                         if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) ||
379                             (buff_st == TXT_ABT) || (buff_st == TXT_ETY))
380                             buff_st = TXT_RDY;
381                     }
382                     if (tx_command.s.txce) {
383                         if ((buff_st == TXT_TOK) || (buff_st == TXT_ERR) ||
384                             (buff_st == TXT_ABT))
385                             buff_st = TXT_ETY;
386                     }
387                     s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) |
388                                         (buff_st << (i * 4));
389                 }
390 
391                 ctucan_send_ready_buffers(s);
392                 ctucan_update_txnf(s);
393             }
394             break;
395         case CTU_CAN_FD_TX_PRIORITY:
396             s->tx_priority.u32 = (uint32_t)val;
397             break;
398         }
399 
400         ctucan_update_irq(s);
401     }
402 
403     return;
404 }
405 
406 uint64_t ctucan_mem_read(CtuCanCoreState *s, hwaddr addr, unsigned size)
407 {
408     uint32_t val = 0;
409 
410     DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr);
411 
412     if (addr > CTUCAN_CORE_MEM_SIZE) {
413         return 0;
414     }
415 
416     switch (addr & ~3) {
417     case CTU_CAN_FD_DEVICE_ID:
418         {
419             union ctu_can_fd_device_id_version idver;
420             idver.u32 = 0;
421             idver.s.device_id = CTU_CAN_FD_ID;
422             idver.s.ver_major = 2;
423             idver.s.ver_minor = 2;
424             val = idver.u32;
425         }
426         break;
427     case CTU_CAN_FD_MODE:
428         val = s->mode_settings.u32;
429         break;
430     case CTU_CAN_FD_STATUS:
431         val = s->status.u32;
432         break;
433     case CTU_CAN_FD_INT_STAT:
434         val = s->int_stat.u32;
435         break;
436     case CTU_CAN_FD_INT_ENA_SET:
437     case CTU_CAN_FD_INT_ENA_CLR:
438         val = s->int_ena.u32;
439         break;
440     case CTU_CAN_FD_INT_MASK_SET:
441     case CTU_CAN_FD_INT_MASK_CLR:
442         val = s->int_mask.u32;
443         break;
444     case CTU_CAN_FD_RX_MEM_INFO:
445         s->rx_mem_info.u32 = 0;
446         s->rx_mem_info.s.rx_buff_size = CTUCAN_RCV_BUF_LEN >> 2;
447         s->rx_mem_info.s.rx_mem_free = (CTUCAN_RCV_BUF_LEN -
448                                         s->rx_cnt) >> 2;
449         val = s->rx_mem_info.u32;
450         break;
451     case CTU_CAN_FD_RX_POINTERS:
452     {
453         uint32_t rx_head_pos = s->rx_tail_pos + s->rx_cnt;
454         rx_head_pos %= CTUCAN_RCV_BUF_LEN;
455         s->rx_pointers.s.rx_wpp = rx_head_pos;
456         s->rx_pointers.s.rx_rpp = s->rx_tail_pos;
457         val = s->rx_pointers.u32;
458         break;
459     }
460     case CTU_CAN_FD_RX_STATUS:
461     case CTU_CAN_FD_RX_SETTINGS:
462         if (!s->rx_status_rx_settings.s.rxfrc) {
463             s->rx_status_rx_settings.s.rxe = 1;
464         } else {
465             s->rx_status_rx_settings.s.rxe = 0;
466         }
467         if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) {
468             s->rx_status_rx_settings.s.rxf = 1;
469         } else {
470             s->rx_status_rx_settings.s.rxf = 0;
471         }
472         val = s->rx_status_rx_settings.u32;
473         break;
474     case CTU_CAN_FD_RX_DATA:
475         if (s->rx_cnt) {
476             memcpy(&val, s->rx_buff + s->rx_tail_pos, 4);
477             val = le32_to_cpu(val);
478             if (!s->rx_frame_rem) {
479                 union ctu_can_fd_frame_form_w frame_form_w;
480                 frame_form_w.u32 = val;
481                 s->rx_frame_rem = frame_form_w.s.rwcnt * 4 + 4;
482             }
483             s->rx_cnt -= 4;
484             s->rx_frame_rem -= 4;
485             if (!s->rx_frame_rem) {
486                 s->rx_status_rx_settings.s.rxfrc--;
487                 if (!s->rx_status_rx_settings.s.rxfrc) {
488                     s->status.s.rxne = 0;
489                     s->status.s.idle = 1;
490                     s->status.s.rxs = 0;
491                 }
492             }
493             s->rx_tail_pos = (s->rx_tail_pos + 4) % CTUCAN_RCV_BUF_LEN;
494         } else {
495             val = 0;
496         }
497         break;
498     case CTU_CAN_FD_TX_STATUS:
499         val = s->tx_status.u32;
500         break;
501     case CTU_CAN_FD_TX_PRIORITY:
502         val = s->tx_priority.u32;
503         break;
504     case CTU_CAN_FD_RX_FR_CTR:
505         val = s->rx_fr_ctr.s.rx_fr_ctr_val;
506         break;
507     case CTU_CAN_FD_TX_FR_CTR:
508         val = s->tx_fr_ctr.s.tx_fr_ctr_val;
509         break;
510     case CTU_CAN_FD_YOLO_REG:
511         val = s->yolo_reg.s.yolo_val;
512         break;
513     }
514 
515     val >>= ((addr & 3) << 3);
516     if (size < 8) {
517         val &= ((uint64_t)1 << (size << 3)) - 1;
518     }
519 
520     return val;
521 }
522 
523 bool ctucan_can_receive(CanBusClientState *client)
524 {
525     CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client);
526 
527     if (!s->mode_settings.s.ena) {
528         return false;
529     }
530 
531     return true; /* always return true, when operation mode */
532 }
533 
534 ssize_t ctucan_receive(CanBusClientState *client, const qemu_can_frame *frames,
535                         size_t frames_cnt)
536 {
537     CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client);
538     static uint8_t rcv[CTUCAN_MSG_MAX_LEN];
539     int i;
540     int ret = -1;
541     const qemu_can_frame *frame = frames;
542     union ctu_can_fd_int_stat int_stat;
543     int_stat.u32 = 0;
544 
545     if (frames_cnt <= 0) {
546         return 0;
547     }
548 
549     ret = ctucan_frame2buff(frame, rcv);
550 
551     if (s->rx_cnt + ret > CTUCAN_RCV_BUF_LEN) { /* Data overrun. */
552         s->status.s.dor = 1;
553         int_stat.s.doi = 1;
554         s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32;
555         ctucan_update_irq(s);
556         DPRINTF("Receive FIFO overrun\n");
557         return ret;
558     }
559     s->status.s.idle = 0;
560     s->status.s.rxs = 1;
561     int_stat.s.rxi = 1;
562     if (((s->rx_cnt + 3) & ~3) == CTUCAN_RCV_BUF_LEN) {
563         int_stat.s.rxfi = 1;
564     }
565     s->int_stat.u32 |= int_stat.u32 & ~s->int_mask.u32;
566     s->rx_fr_ctr.s.rx_fr_ctr_val++;
567     s->rx_status_rx_settings.s.rxfrc++;
568     for (i = 0; i < ret; i++) {
569         s->rx_buff[(s->rx_tail_pos + s->rx_cnt) % CTUCAN_RCV_BUF_LEN] = rcv[i];
570         s->rx_cnt++;
571     }
572     s->status.s.rxne = 1;
573 
574     ctucan_update_irq(s);
575 
576     return 1;
577 }
578 
579 static CanBusClientInfo ctucan_bus_client_info = {
580     .can_receive = ctucan_can_receive,
581     .receive = ctucan_receive,
582 };
583 
584 
585 int ctucan_connect_to_bus(CtuCanCoreState *s, CanBusState *bus)
586 {
587     s->bus_client.info = &ctucan_bus_client_info;
588 
589     if (!bus) {
590         return -EINVAL;
591     }
592 
593     if (can_bus_insert_client(bus, &s->bus_client) < 0) {
594         return -1;
595     }
596 
597     return 0;
598 }
599 
600 void ctucan_disconnect(CtuCanCoreState *s)
601 {
602     can_bus_remove_client(&s->bus_client);
603 }
604 
605 int ctucan_init(CtuCanCoreState *s, qemu_irq irq)
606 {
607     s->irq = irq;
608 
609     qemu_irq_lower(s->irq);
610 
611     ctucan_hardware_reset(s);
612 
613     return 0;
614 }
615 
616 const VMStateDescription vmstate_qemu_ctucan_tx_buffer = {
617     .name = "qemu_ctucan_tx_buffer",
618     .version_id = 1,
619     .minimum_version_id = 1,
620     .minimum_version_id_old = 1,
621     .fields = (VMStateField[]) {
622         VMSTATE_UINT8_ARRAY(data, CtuCanCoreMsgBuffer, CTUCAN_CORE_MSG_MAX_LEN),
623         VMSTATE_END_OF_LIST()
624     }
625 };
626 
627 static int ctucan_post_load(void *opaque, int version_id)
628 {
629     CtuCanCoreState *s = opaque;
630     ctucan_update_irq(s);
631     return 0;
632 }
633 
634 /* VMState is needed for live migration of QEMU images */
635 const VMStateDescription vmstate_ctucan = {
636     .name = "ctucan",
637     .version_id = 1,
638     .minimum_version_id = 1,
639     .minimum_version_id_old = 1,
640     .post_load = ctucan_post_load,
641     .fields = (VMStateField[]) {
642         VMSTATE_UINT32(mode_settings.u32, CtuCanCoreState),
643         VMSTATE_UINT32(status.u32, CtuCanCoreState),
644         VMSTATE_UINT32(int_stat.u32, CtuCanCoreState),
645         VMSTATE_UINT32(int_ena.u32, CtuCanCoreState),
646         VMSTATE_UINT32(int_mask.u32, CtuCanCoreState),
647         VMSTATE_UINT32(brt.u32, CtuCanCoreState),
648         VMSTATE_UINT32(brt_fd.u32, CtuCanCoreState),
649         VMSTATE_UINT32(ewl_erp_fault_state.u32, CtuCanCoreState),
650         VMSTATE_UINT32(rec_tec.u32, CtuCanCoreState),
651         VMSTATE_UINT32(err_norm_err_fd.u32, CtuCanCoreState),
652         VMSTATE_UINT32(ctr_pres.u32, CtuCanCoreState),
653         VMSTATE_UINT32(filter_a_mask.u32, CtuCanCoreState),
654         VMSTATE_UINT32(filter_a_val.u32, CtuCanCoreState),
655         VMSTATE_UINT32(filter_b_mask.u32, CtuCanCoreState),
656         VMSTATE_UINT32(filter_b_val.u32, CtuCanCoreState),
657         VMSTATE_UINT32(filter_c_mask.u32, CtuCanCoreState),
658         VMSTATE_UINT32(filter_c_val.u32, CtuCanCoreState),
659         VMSTATE_UINT32(filter_ran_low.u32, CtuCanCoreState),
660         VMSTATE_UINT32(filter_ran_high.u32, CtuCanCoreState),
661         VMSTATE_UINT32(filter_control_filter_status.u32, CtuCanCoreState),
662         VMSTATE_UINT32(rx_mem_info.u32, CtuCanCoreState),
663         VMSTATE_UINT32(rx_pointers.u32, CtuCanCoreState),
664         VMSTATE_UINT32(rx_status_rx_settings.u32, CtuCanCoreState),
665         VMSTATE_UINT32(tx_status.u32, CtuCanCoreState),
666         VMSTATE_UINT32(tx_priority.u32, CtuCanCoreState),
667         VMSTATE_UINT32(err_capt_alc.u32, CtuCanCoreState),
668         VMSTATE_UINT32(trv_delay_ssp_cfg.u32, CtuCanCoreState),
669         VMSTATE_UINT32(rx_fr_ctr.u32, CtuCanCoreState),
670         VMSTATE_UINT32(tx_fr_ctr.u32, CtuCanCoreState),
671         VMSTATE_UINT32(debug_register.u32, CtuCanCoreState),
672         VMSTATE_UINT32(yolo_reg.u32, CtuCanCoreState),
673         VMSTATE_UINT32(timestamp_low.u32, CtuCanCoreState),
674         VMSTATE_UINT32(timestamp_high.u32, CtuCanCoreState),
675 
676         VMSTATE_STRUCT_ARRAY(tx_buffer, CtuCanCoreState,
677                 CTUCAN_CORE_TXBUF_NUM, 0, vmstate_qemu_ctucan_tx_buffer,
678                 CtuCanCoreMsgBuffer),
679 
680         VMSTATE_BUFFER(rx_buff, CtuCanCoreState),
681         VMSTATE_UINT32(rx_tail_pos, CtuCanCoreState),
682         VMSTATE_UINT32(rx_cnt, CtuCanCoreState),
683         VMSTATE_UINT32(rx_frame_rem, CtuCanCoreState),
684 
685         VMSTATE_END_OF_LIST()
686     }
687 };
688