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