Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / hw / net / can / ctucan_core.c
blob812b83e93e1ab908ac5646c50fcae1f720afa9b6
1 /*
2 * CTU CAN FD PCI device emulation
3 * http://canbus.pages.fel.cvut.cz/
5 * Copyright (c) 2019 Jan Charvat (jancharvat.charvat@gmail.com)
7 * Based on Kvaser PCI CAN device (SJA1000 based) emulation implemented by
8 * Jin Yang and Pavel Pisa
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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
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.
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"
36 #include "ctucan_core.h"
38 #ifndef DEBUG_CAN
39 #define DEBUG_CAN 0
40 #endif /*DEBUG_CAN*/
42 #define DPRINTF(fmt, ...) \
43 do { \
44 if (DEBUG_CAN) { \
45 qemu_log("[ctucan]: " fmt , ## __VA_ARGS__); \
46 } \
47 } while (0)
49 static void ctucan_buff2frame(const uint8_t *buff, qemu_can_frame *frame)
51 frame->can_id = 0;
52 frame->can_dlc = 0;
53 frame->flags = 0;
55 if (buff == NULL) {
56 return;
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;
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);
68 w = le32_to_cpu(*(uint32_t *)(buff + 4));
69 identifier_w = (union ctu_can_fd_identifier_w)w;
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;
80 if (frame_form_w.s.esi_rsv) {
81 frame->flags |= QEMU_CAN_FRMF_ESI;
84 if (frame_form_w.s.rtr) {
85 frame->can_id |= QEMU_CAN_RTR_FLAG;
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;
96 memcpy(frame->data, buff + 0x10, 0x40);
100 static int ctucan_frame2buff(const qemu_can_frame *frame, uint8_t *buff)
102 unsigned int bytes_cnt = -1;
103 memset(buff, 0, CTUCAN_MSG_MAX_LEN * sizeof(*buff));
105 if (frame == NULL) {
106 return bytes_cnt;
109 union ctu_can_fd_frame_form_w frame_form_w;
110 union ctu_can_fd_identifier_w identifier_w;
112 frame_form_w.u32 = 0;
113 identifier_w.u32 = 0;
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;
120 frame_form_w.s.dlc = can_len2dlc(frame->can_dlc);
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;
131 if (frame->flags & QEMU_CAN_FRMF_ESI) {
132 frame_form_w.s.esi_rsv = 1;
135 if (frame->can_id & QEMU_CAN_RTR_FLAG) {
136 frame_form_w.s.rtr = 1;
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;
145 *(uint32_t *)buff = cpu_to_le32(frame_form_w.u32);
146 *(uint32_t *)(buff + 4) = cpu_to_le32(identifier_w.u32);
149 memcpy(buff + 0x10, frame->data, 0x40);
151 return bytes_cnt;
154 static void ctucan_update_irq(CtuCanCoreState *s)
156 union ctu_can_fd_int_stat int_rq;
158 int_rq.u32 = 0;
160 if (s->rx_status_rx_settings.s.rxfrc) {
161 int_rq.s.rbnei = 1;
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);
173 static void ctucan_update_txnf(CtuCanCoreState *s)
175 int i;
176 int txnf;
177 unsigned int buff_st;
179 txnf = 0;
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;
187 s->status.s.txnf = txnf;
190 void ctucan_hardware_reset(CtuCanCoreState *s)
192 DPRINTF("Hardware reset in progress!!!\n");
193 int i;
194 unsigned int buff_st;
195 uint32_t buff_st_mask;
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));
204 s->status.s.idle = 1;
206 ctucan_update_txnf(s);
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;
213 /* Flush RX buffer */
214 s->rx_tail_pos = 0;
215 s->rx_cnt = 0;
216 s->rx_frame_rem = 0;
218 /* Set on progdokum reset value */
219 s->mode_settings.u32 = 0;
220 s->mode_settings.s.fde = 1;
222 s->int_stat.u32 = 0;
223 s->int_ena.u32 = 0;
224 s->int_mask.u32 = 0;
226 s->rx_status_rx_settings.u32 = 0;
227 s->rx_status_rx_settings.s.rxe = 0;
229 s->rx_fr_ctr.u32 = 0;
230 s->tx_fr_ctr.u32 = 0;
232 s->yolo_reg.s.yolo_val = 3735928559;
234 qemu_irq_lower(s->irq);
237 static void ctucan_send_ready_buffers(CtuCanCoreState *s)
239 qemu_can_frame frame;
240 uint8_t *pf;
241 int buff2tx_idx;
242 uint32_t tx_prio_max;
244 if (!s->mode_settings.s.ena) {
245 return;
248 do {
249 union ctu_can_fd_int_stat int_stat;
250 int i;
251 buff2tx_idx = -1;
252 tx_prio_max = 0;
254 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) {
255 uint32_t prio;
257 if (extract32(s->tx_status.u32, i * 4, 4) != TXT_RDY) {
258 continue;
260 prio = (s->tx_priority.u32 >> (i * 4)) & 0x7;
261 if (tx_prio_max < prio) {
262 tx_prio_max = prio;
263 buff2tx_idx = i;
266 if (buff2tx_idx == -1) {
267 break;
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);
286 #define CTUCAN_CORE_TXBUFF_SPAN \
287 (CTU_CAN_FD_TXTB2_DATA_1 - CTU_CAN_FD_TXTB1_DATA_1)
289 void ctucan_mem_write(CtuCanCoreState *s, hwaddr addr, uint64_t val,
290 unsigned size)
292 int i;
294 DPRINTF("write 0x%02llx addr 0x%02x\n",
295 (unsigned long long)val, (unsigned int)addr);
297 if (addr >= CTUCAN_CORE_MEM_SIZE) {
298 return;
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);
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;
318 break;
319 case CTU_CAN_FD_COMMAND:
321 union ctu_can_fd_command command;
322 command.u32 = (uint32_t)val;
323 if (command.s.cdo) {
324 s->status.s.dor = 0;
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;
332 if (command.s.txfcrst) {
333 s->tx_fr_ctr.s.tx_fr_ctr_val = 0;
335 if (command.s.rxfcrst) {
336 s->rx_fr_ctr.s.rx_fr_ctr_val = 0;
338 break;
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;
362 tx_command.u32 = (uint32_t)val;
363 mask.u32 = 0;
364 mask.s.txb1 = 1;
366 for (i = 0; i < CTUCAN_CORE_TXBUF_NUM; i++) {
367 if (!(tx_command.u32 & (mask.u32 << i))) {
368 continue;
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;
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;
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;
387 s->tx_status.u32 = (s->tx_status.u32 & ~buff_st_mask) |
388 (buff_st << (i * 4));
391 ctucan_send_ready_buffers(s);
392 ctucan_update_txnf(s);
394 break;
395 case CTU_CAN_FD_TX_PRIORITY:
396 s->tx_priority.u32 = (uint32_t)val;
397 break;
400 ctucan_update_irq(s);
403 return;
406 uint64_t ctucan_mem_read(CtuCanCoreState *s, hwaddr addr, unsigned size)
408 uint32_t val = 0;
410 DPRINTF("read addr 0x%02x ...\n", (unsigned int)addr);
412 if (addr > CTUCAN_CORE_MEM_SIZE) {
413 return 0;
416 switch (addr & ~3) {
417 case CTU_CAN_FD_DEVICE_ID:
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;
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:
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;
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;
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;
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;
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;
493 s->rx_tail_pos = (s->rx_tail_pos + 4) % CTUCAN_RCV_BUF_LEN;
494 } else {
495 val = 0;
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;
515 val >>= ((addr & 3) << 3);
516 if (size < 8) {
517 val &= ((uint64_t)1 << (size << 3)) - 1;
520 return val;
523 bool ctucan_can_receive(CanBusClientState *client)
525 CtuCanCoreState *s = container_of(client, CtuCanCoreState, bus_client);
527 if (!s->mode_settings.s.ena) {
528 return false;
531 return true; /* always return true, when operation mode */
534 ssize_t ctucan_receive(CanBusClientState *client, const qemu_can_frame *frames,
535 size_t frames_cnt)
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;
545 if (frames_cnt <= 0) {
546 return 0;
549 ret = ctucan_frame2buff(frame, rcv);
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;
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;
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++;
572 s->status.s.rxne = 1;
574 ctucan_update_irq(s);
576 return 1;
579 static CanBusClientInfo ctucan_bus_client_info = {
580 .can_receive = ctucan_can_receive,
581 .receive = ctucan_receive,
585 int ctucan_connect_to_bus(CtuCanCoreState *s, CanBusState *bus)
587 s->bus_client.info = &ctucan_bus_client_info;
589 if (!bus) {
590 return -EINVAL;
593 if (can_bus_insert_client(bus, &s->bus_client) < 0) {
594 return -1;
597 return 0;
600 void ctucan_disconnect(CtuCanCoreState *s)
602 can_bus_remove_client(&s->bus_client);
605 int ctucan_init(CtuCanCoreState *s, qemu_irq irq)
607 s->irq = irq;
609 qemu_irq_lower(s->irq);
611 ctucan_hardware_reset(s);
613 return 0;
616 const VMStateDescription vmstate_qemu_ctucan_tx_buffer = {
617 .name = "qemu_ctucan_tx_buffer",
618 .version_id = 1,
619 .minimum_version_id = 1,
620 .fields = (const VMStateField[]) {
621 VMSTATE_UINT8_ARRAY(data, CtuCanCoreMsgBuffer, CTUCAN_CORE_MSG_MAX_LEN),
622 VMSTATE_END_OF_LIST()
626 static int ctucan_post_load(void *opaque, int version_id)
628 CtuCanCoreState *s = opaque;
629 ctucan_update_irq(s);
630 return 0;
633 /* VMState is needed for live migration of QEMU images */
634 const VMStateDescription vmstate_ctucan = {
635 .name = "ctucan",
636 .version_id = 1,
637 .minimum_version_id = 1,
638 .post_load = ctucan_post_load,
639 .fields = (const VMStateField[]) {
640 VMSTATE_UINT32(mode_settings.u32, CtuCanCoreState),
641 VMSTATE_UINT32(status.u32, CtuCanCoreState),
642 VMSTATE_UINT32(int_stat.u32, CtuCanCoreState),
643 VMSTATE_UINT32(int_ena.u32, CtuCanCoreState),
644 VMSTATE_UINT32(int_mask.u32, CtuCanCoreState),
645 VMSTATE_UINT32(brt.u32, CtuCanCoreState),
646 VMSTATE_UINT32(brt_fd.u32, CtuCanCoreState),
647 VMSTATE_UINT32(ewl_erp_fault_state.u32, CtuCanCoreState),
648 VMSTATE_UINT32(rec_tec.u32, CtuCanCoreState),
649 VMSTATE_UINT32(err_norm_err_fd.u32, CtuCanCoreState),
650 VMSTATE_UINT32(ctr_pres.u32, CtuCanCoreState),
651 VMSTATE_UINT32(filter_a_mask.u32, CtuCanCoreState),
652 VMSTATE_UINT32(filter_a_val.u32, CtuCanCoreState),
653 VMSTATE_UINT32(filter_b_mask.u32, CtuCanCoreState),
654 VMSTATE_UINT32(filter_b_val.u32, CtuCanCoreState),
655 VMSTATE_UINT32(filter_c_mask.u32, CtuCanCoreState),
656 VMSTATE_UINT32(filter_c_val.u32, CtuCanCoreState),
657 VMSTATE_UINT32(filter_ran_low.u32, CtuCanCoreState),
658 VMSTATE_UINT32(filter_ran_high.u32, CtuCanCoreState),
659 VMSTATE_UINT32(filter_control_filter_status.u32, CtuCanCoreState),
660 VMSTATE_UINT32(rx_mem_info.u32, CtuCanCoreState),
661 VMSTATE_UINT32(rx_pointers.u32, CtuCanCoreState),
662 VMSTATE_UINT32(rx_status_rx_settings.u32, CtuCanCoreState),
663 VMSTATE_UINT32(tx_status.u32, CtuCanCoreState),
664 VMSTATE_UINT32(tx_priority.u32, CtuCanCoreState),
665 VMSTATE_UINT32(err_capt_alc.u32, CtuCanCoreState),
666 VMSTATE_UINT32(trv_delay_ssp_cfg.u32, CtuCanCoreState),
667 VMSTATE_UINT32(rx_fr_ctr.u32, CtuCanCoreState),
668 VMSTATE_UINT32(tx_fr_ctr.u32, CtuCanCoreState),
669 VMSTATE_UINT32(debug_register.u32, CtuCanCoreState),
670 VMSTATE_UINT32(yolo_reg.u32, CtuCanCoreState),
671 VMSTATE_UINT32(timestamp_low.u32, CtuCanCoreState),
672 VMSTATE_UINT32(timestamp_high.u32, CtuCanCoreState),
674 VMSTATE_STRUCT_ARRAY(tx_buffer, CtuCanCoreState,
675 CTUCAN_CORE_TXBUF_NUM, 0, vmstate_qemu_ctucan_tx_buffer,
676 CtuCanCoreMsgBuffer),
678 VMSTATE_BUFFER(rx_buff, CtuCanCoreState),
679 VMSTATE_UINT32(rx_tail_pos, CtuCanCoreState),
680 VMSTATE_UINT32(rx_cnt, CtuCanCoreState),
681 VMSTATE_UINT32(rx_frame_rem, CtuCanCoreState),
683 VMSTATE_END_OF_LIST()