master
c 1,461 lines 44.4 KB
Raw
1 /*
2 * QEMU model of the NXP FLEXCAN device.
3 *
4 * This implementation is based on the following reference manual:
5 * i.MX 6Dual/6Quad Applications Processor Reference Manual
6 * Document Number: IMX6DQRM, Rev. 6, 05/2020
7 *
8 * Copyright (c) 2025 Matyas Bobek <matyas.bobek@gmail.com>
9 *
10 * Based on CTU CAN FD emulation implemented by Jan Charvat.
11 *
12 * SPDX-License-Identifier: GPL-2.0-or-later
13 */
14
15 #include "qemu/osdep.h"
16 #include "qemu/log.h"
17 #include "hw/core/sysbus.h"
18 #include "qapi/error.h"
19 #include "hw/core/irq.h"
20 #include "migration/vmstate.h"
21 #include "net/can_emu.h"
22 #include "hw/core/qdev-properties.h"
23 #include "trace.h"
24
25 #include "hw/net/flexcan.h"
26 #include "flexcan_regs.h"
27 #include "qemu/timer.h"
28
29 /*
30 * Indicates MB w/ received frame has not been serviced yet
31 * This is an emulator-only flag in position of unused (reserved) bit
32 * of message buffer control register
33 */
34 #define FLEXCAN_MB_CNT_NOT_SRV BIT(23)
35 /**
36 * if no MB is locked, FlexcanState.locked_mb
37 * is set to FLEXCAN_NO_MB_LOCKED
38 */
39 #define FLEXCAN_NO_MB_LOCKED -1
40 /**
41 * if no frame is waiting in the SMB, FlexcanState.smb_target_mbid
42 * is set to FLEXCAN_SMB_EMPTY
43 */
44 #define FLEXCAN_SMB_EMPTY -1
45 /**
46 * When the module is disabled or in freeze mode,
47 * the timer is not running. That is indicated by setting
48 * FlexcanState.timer_start to FLEXCAN_TIMER_STOPPED.
49 */
50 #define FLEXCAN_TIMER_STOPPED -1
51
52 /* These constants are returned by flexcan_fifo_rx() and flexcan_mb_rx(), */
53 enum FlexcanRx {
54 /* Retry the other receiving mechanism (ie. message bufer or mailbox). */
55 FLEXCAN_RX_SEARCH_RETRY,
56 /* The frame was received and stored. */
57 FLEXCAN_RX_SEARCH_ACCEPT,
58 /* The frame was filtered out and dropped. */
59 FLEXCAN_RX_SEARCH_DROPPED,
60 };
61
62 /*
63 * These constants are returned by flexcan_mb_rx_check_mb().
64 * See flexcan_mb_rx_check_mb() kerneldoc for details.
65 */
66 enum FlexcanCheck {
67 FLEXCAN_CHECK_MB_NIL = 0,
68 FLEXCAN_CHECK_MB_MATCH = 3,
69 FLEXCAN_CHECK_MB_MATCH_NON_FREE = 1,
70 FLEXCAN_CHECK_MB_MATCH_LOCKED = 5,
71 };
72
73 static const FlexcanRegs flexcan_regs_write_mask = {
74 .mcr = 0xF6EB337F,
75 .ctrl = 0xFFFFFFFF,
76 .timer = 0xFFFFFFFF,
77 .tcr = 0xFFFFFFFF,
78 .rxmgmask = 0xFFFFFFFF,
79 .rx14mask = 0xFFFFFFFF,
80 .rx15mask = 0xFFFFFFFF,
81 .ecr = 0xFFFFFFFF,
82 .esr = 0xFFFFFFFF,
83 .imask2 = 0xFFFFFFFF,
84 .imask1 = 0xFFFFFFFF,
85 .iflag2 = 0,
86 .iflag1 = 0,
87 .ctrl2 = 0xFFFFFFFF,
88 .esr2 = 0,
89 .imeur = 0,
90 .lrfr = 0,
91 .crcr = 0,
92 .rxfgmask = 0xFFFFFFFF,
93 .rxfir = 0,
94 .cbt = 0,
95 ._reserved2 = 0,
96 .dbg1 = 0,
97 .dbg2 = 0,
98 .mbs = { [0 ... 63] = {
99 .can_ctrl = 0xFFFFFFFF & ~FLEXCAN_MB_CNT_NOT_SRV,
100 .can_id = 0xFFFFFFFF,
101 .data = { 0xFFFFFFFF, 0xFFFFFFFF },
102 } },
103 ._reserved4 = {0},
104 .rximr = { [0 ... 63] = 0xFFFFFFFF },
105 ._reserved5 = {0},
106 .gfwr_mx6 = 0xFFFFFFFF,
107 ._reserved6 = {0},
108 ._reserved8 = {0},
109 .rx_smb0 = {
110 .can_ctrl = 0,
111 .can_id = 0,
112 .data = { 0, 0 },
113 },
114 .rx_smb1 = {0, 0, 0, 0},
115 };
116 static const FlexcanRegs flexcan_regs_reset_mask = {
117 .mcr = 0x80000000,
118 .ctrl = 0xFFFFFFFF,
119 .timer = 0,
120 .tcr = 0,
121 .rxmgmask = 0xFFFFFFFF,
122 .rx14mask = 0xFFFFFFFF,
123 .rx15mask = 0xFFFFFFFF,
124 .ecr = 0,
125 .esr = 0,
126 .imask2 = 0,
127 .imask1 = 0,
128 .iflag2 = 0,
129 .iflag1 = 0,
130 .ctrl2 = 0xFFFFFFFF,
131 .esr2 = 0,
132 .imeur = 0,
133 .lrfr = 0,
134 .crcr = 0,
135 .rxfgmask = 0xFFFFFFFF,
136 .rxfir = 0xFFFFFFFF,
137 .cbt = 0,
138 ._reserved2 = 0,
139 .dbg1 = 0,
140 .dbg2 = 0,
141 .mbs = { [0 ... FLEXCAN_MAILBOX_COUNT - 1] = {
142 .can_ctrl = 0xFFFFFFFF,
143 .can_id = 0xFFFFFFFF,
144 .data = { 0xFFFFFFFF, 0xFFFFFFFF },
145 } },
146 ._reserved4 = {0},
147 .rximr = { [0 ... 63] = 0xFFFFFFFF },
148 ._reserved5 = {0},
149 .gfwr_mx6 = 0,
150 ._reserved6 = {0},
151 ._reserved8 = {0},
152 .rx_smb0 = {
153 .can_ctrl = 0,
154 .can_id = 0,
155 .data = { 0, 0 },
156 },
157 .rx_smb1 = {0, 0, 0, 0},
158 };
159
160 /* length of buffer used to format register names in trace output */
161 #define FLEXCAN_DBG_BUF_LEN 16
162
163 /**
164 * flexcan_dbg_mb_code_strs - Readable names for CODE field codes
165 *
166 * Readable names for possible values of CODE field in message buffer
167 * control word.
168 */
169 static const char *flexcan_dbg_mb_code_strs[16] = {
170 "INACTIVE_RX",
171 "FULL",
172 "EMPTY",
173 "OVERRUN",
174 "INACTIVE_TX",
175 "RANSWER",
176 "DATA",
177 "TANSWER"
178 };
179
180 /**
181 * flexcan_dbg_mb_code() - Get the string representation of a mailbox code
182 * @mb_ctrl: The mailbox control register value
183 * @buf: The buffer to store the string representation
184 *
185 * Return: Either constant string or string formatted into @buf
186 */
187 static const char *flexcan_dbg_mb_code(uint32_t mb_ctrl, char *buf)
188 {
189 uint32_t code = mb_ctrl & FLEXCAN_MB_CODE_MASK;
190 uint32_t code_idx = code >> 24;
191 if (code == FLEXCAN_MB_CODE_TX_ABORT) {
192 return "ABORT";
193 } else {
194 const char *code_str = flexcan_dbg_mb_code_strs[code_idx >> 1];
195 if (code_idx & 1) {
196 g_snprintf(buf, FLEXCAN_DBG_BUF_LEN, "%s+BUSY", code_str);
197 return buf;
198 }
199
200 return code_str;
201 }
202 }
203
204 static const char *flexcan_dbg_reg_name_fixed(hwaddr addr)
205 {
206 switch (addr) {
207 case offsetof(FlexcanRegs, mcr):
208 return "MCR";
209 case offsetof(FlexcanRegs, ctrl):
210 return "CTRL";
211 case offsetof(FlexcanRegs, timer):
212 return "TIMER";
213 case offsetof(FlexcanRegs, esr):
214 return "ESR";
215 case offsetof(FlexcanRegs, rxmgmask):
216 return "RXMGMASK";
217 case offsetof(FlexcanRegs, rx14mask):
218 return "RX14MASK";
219 case offsetof(FlexcanRegs, rx15mask):
220 return "RX15MASK";
221 case offsetof(FlexcanRegs, rxfgmask):
222 return "RXFGMASK";
223 case offsetof(FlexcanRegs, ecr):
224 return "ECR";
225 case offsetof(FlexcanRegs, ctrl2):
226 return "CTRL2";
227 case offsetof(FlexcanRegs, imask2):
228 return "IMASK2";
229 case offsetof(FlexcanRegs, imask1):
230 return "IMASK1";
231 case offsetof(FlexcanRegs, iflag2):
232 return "IFLAG2";
233 case offsetof(FlexcanRegs, iflag1):
234 return "IFLAG1";
235 }
236 return NULL;
237 }
238
239 static inline void flexcan_trace_mem_op(FlexcanState *s, hwaddr addr,
240 uint32_t value, int size, bool is_wr)
241 {
242 if (trace_event_get_state_backends(TRACE_FLEXCAN_MEM_OP)) {
243 const char *reg_name = "unknown";
244 char reg_name_buf[FLEXCAN_DBG_BUF_LEN] = { 0 };
245 const char *reg_name_fixed = flexcan_dbg_reg_name_fixed(addr);
246 const char *op_string = is_wr ? "write" : "read";
247
248 if (reg_name_fixed) {
249 reg_name = reg_name_fixed;
250 } else if (addr >= 0x80 && addr < 0x480) {
251 int mbidx = (addr - 0x80) / 16;
252 g_snprintf(reg_name_buf, sizeof(reg_name_buf), "MB%i", mbidx);
253 reg_name = reg_name_buf;
254 } else if (addr >= 0x880 && addr < 0x9e0) {
255 int id = (addr - 0x880) / 4;
256 g_snprintf(reg_name_buf, sizeof(reg_name_buf), "RXIMR%i", id);
257 reg_name = reg_name_buf;
258 }
259
260 trace_flexcan_mem_op(DEVICE(s)->canonical_path, op_string, value, addr,
261 reg_name, size);
262 }
263 }
264
265 static enum FlexcanRx flexcan_mb_rx(FlexcanState *s,
266 const qemu_can_frame *frame);
267 static void flexcan_mb_unlock(FlexcanState *s);
268
269 /* ========== Mailbox Utils ========== */
270
271 /**
272 * flexcan_mailbox_count() - Get number of enabled mailboxes
273 * @s: FlexCAN device pointer
274 *
275 * Count is based on MCR[MAXMB] field. Note that some of those mailboxes
276 * might be part of queue or queue ID filters or ordinary message buffers.
277 */
278 static inline int flexcan_enabled_mailbox_count(const FlexcanState *s)
279 {
280 return MIN((s->regs.mcr & FLEXCAN_MCR_MAXMB(UINT32_MAX)) + 1,
281 FLEXCAN_MAILBOX_COUNT);
282 }
283
284 /**
285 * flexcan_get_first_message_buffer() - Get pointer to first message buffer
286 * @s: FlexCAN device pointer
287 *
288 * In context of this function, message buffer means a mailbox which is not
289 * a queue element nor a queue filter. Note this function does not take
290 * MCR[MAXMB] into account, meaning that the returned mailbox
291 * might be disabled.
292 */
293 static FlexcanRegsMessageBuffer *flexcan_get_first_message_buffer(
294 FlexcanState *s)
295 {
296 if (s->regs.mcr & FLEXCAN_MCR_FEN) {
297 int rffn = (s->regs.ctrl2 & FLEXCAN_CTRL2_RFFN(UINT32_MAX)) >> 24;
298 return s->regs.mbs + 8 + 2 * rffn;
299 }
300
301 return s->regs.mbs;
302 }
303
304 /**
305 * flexcan_get_last_enabled_mailbox() - Get pointer to last enabled mailbox.
306 * @s: FlexCAN device pointer
307 *
308 * When used with flexcan_get_first_message_buffer(), all mailboxes *ptr in
309 * range `first_message_buffer() <= ptr <= last_enabled_mailbox` are valid
310 * message buffer mailboxes.
311 *
312 * Return: Last enabled mailbox in MCR[MAXMB] sense. The mailbox might be
313 * of any type.
314 */
315 static inline FlexcanRegsMessageBuffer *flexcan_get_last_enabled_mailbox(
316 FlexcanState *s)
317 {
318 return s->regs.mbs + flexcan_enabled_mailbox_count(s);
319 }
320
321 /* ========== Free-running Timer ========== */
322 static inline int64_t flexcan_get_time(void)
323 {
324 return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
325 }
326
327 /**
328 * flexcan_get_bitrate() - Calculate CAN bitrate (in Hz)
329 * @s: FlexCAN device pointer
330 *
331 * The bitrate is determined by FlexCAN configuration in CTRL1 register,
332 * and CCM co
333 */
334 static uint32_t flexcan_get_bitrate(FlexcanState *s)
335 {
336 uint32_t conf_presdiv = (s->regs.ctrl & FLEXCAN_CTRL_PRESDIV_MASK) >> 24;
337 uint32_t conf_pseg1 = (s->regs.ctrl & FLEXCAN_CTRL_PSEG1_MASK) >> 19;
338 uint32_t conf_pseg2 = (s->regs.ctrl & FLEXCAN_CTRL_PSEG2_MASK) >> 16;
339 uint32_t conf_propseg = s->regs.ctrl & FLEXCAN_CTRL_PROPSEG_MASK;
340
341 /* N of time quanta for segments */
342 uint32_t tseg1 = 2 + conf_pseg1 + conf_propseg;
343 uint32_t tseg2 = 1 + conf_pseg2;
344 uint32_t total_qpb = 1 + tseg1 + tseg2;
345
346 uint32_t pe_freq, s_freq, bitrate;
347
348 /* s_freq: CAN clock from CCM divided by the prescaler */
349 pe_freq = imx_ccm_get_clock_frequency(s->ccm, CLK_CAN);
350 s_freq = pe_freq / (1 + conf_presdiv);
351 bitrate = s_freq / total_qpb;
352
353 trace_flexcan_get_bitrate(DEVICE(s)->canonical_path, pe_freq,
354 1 + conf_presdiv, s_freq, tseg1, tseg2, total_qpb,
355 bitrate);
356 return bitrate;
357 }
358
359 /**
360 * int128_mul_6464() - Multiply two 64-bit integers into a 128-bit one
361 */
362 static Int128 int128_muls_6464(int64_t ai, int64_t bi)
363 {
364 uint64_t l, h;
365
366 muls64(&l, &h, ai, bi);
367 return int128_make128(l, h);
368 }
369
370 /**
371 * flexcan_get_timestamp() - Get current value of the 16-bit free-running timer
372 * @s: FlexCAN device pointer
373 * @mk_unique: if true, make the timestamp unique by incrementing it if needed
374 */
375 static uint32_t flexcan_get_timestamp(FlexcanState *s, bool mk_unique)
376 {
377 const Int128 nanoseconds_in_second = int128_makes64((int64_t)1e9);
378 Int128 ncycles, cycles128;
379 int64_t current_time, elapsed_time_ns;
380 uint64_t cycles;
381 uint32_t rv, shift = 0;
382
383 if (s->timer_start == FLEXCAN_TIMER_STOPPED) {
384 /* timer is not running, return last value */
385 trace_flexcan_get_timestamp(DEVICE(s)->canonical_path, -1, 0, 0, 0,
386 s->regs.timer);
387 return s->regs.timer;
388 }
389
390 current_time = flexcan_get_time();
391 elapsed_time_ns = current_time - s->timer_start;
392 if (elapsed_time_ns < 0) {
393 trace_flexcan_timer_overflow(DEVICE(s)->canonical_path, current_time,
394 s->timer_start, elapsed_time_ns);
395 return 0xFFFF;
396 }
397
398 ncycles = int128_muls_6464(s->timer_freq, elapsed_time_ns);
399 cycles128 = int128_divs(ncycles, nanoseconds_in_second);
400 /* 64 bits hold for over 50k years at 10MHz */
401 cycles = int128_getlo(cycles128);
402
403 if (mk_unique && cycles <= s->last_rx_timer_cycles) {
404 shift = 1;
405 cycles = s->last_rx_timer_cycles + shift;
406 }
407
408 s->last_rx_timer_cycles = cycles;
409 rv = (uint32_t)cycles & 0xFFFF;
410
411 trace_flexcan_get_timestamp(DEVICE(s)->canonical_path,
412 elapsed_time_ns / (uint32_t)1e6,
413 s->timer_freq, cycles, shift, rv);
414 return rv;
415 }
416
417 /**
418 * flexcan_timer_start() - Start the free-running timer
419 * @s: FlexCAN device pointer
420 *
421 * This should be called when the module leaves freeze mode.
422 */
423 static void flexcan_timer_start(FlexcanState *s)
424 {
425 s->timer_freq = flexcan_get_bitrate(s);
426 s->timer_start = flexcan_get_time();
427 s->last_rx_timer_cycles = 0;
428
429 trace_flexcan_timer_start(DEVICE(s)->canonical_path, s->timer_freq,
430 s->regs.timer);
431 }
432
433 /**
434 * flexcan_timer_stop() - Stop the free-running timer
435 * @s: FlexCAN device pointer
436 *
437 * This should be called when the module enters freeze mode.
438 * Stores the current timestamp in the TIMER register.
439 */
440 static void flexcan_timer_stop(FlexcanState *s)
441 {
442 s->regs.timer = flexcan_get_timestamp(s, false);
443 s->timer_start = FLEXCAN_TIMER_STOPPED;
444
445 trace_flexcan_timer_stop(DEVICE(s)->canonical_path, s->timer_freq,
446 s->regs.timer);
447 }
448
449 /* ========== IRQ handling ========== */
450 /**
451 * flexcan_irq_update() - Update qemu_irq line based on interrupt registers
452 * @s: FlexCAN device pointer
453 */
454 static void flexcan_irq_update(FlexcanState *s)
455 {
456 uint32_t mb_irqs[2];
457 int irq_pending;
458 /* these are all interrupt sources from FlexCAN */
459 /* mailbox interrupt sources */
460 mb_irqs[0] = s->regs.iflag1 & s->regs.imask1;
461 mb_irqs[1] = s->regs.iflag2 & s->regs.imask2;
462
463 /**
464 * these interrupts aren't currently used and they can never be raised
465 *
466 * bool irq_wake_up = (s->regs.mcr & FLEXCAN_MCR_WAK_MSK) &&
467 * (s->regs.ecr & FLEXCAN_ESR_WAK_INT);
468 * bool irq_bus_off = (s->regs.ctrl & FLEXCAN_CTRL_BOFF_MSK) &&
469 * (s->regs.ecr & FLEXCAN_ESR_BOFF_INT);
470 * bool irq_error = (s->regs.ctrl & FLEXCAN_CTRL_ERR_MSK) &&
471 * (s->regs.ecr & FLEXCAN_ESR_ERR_INT);
472 * bool irq_tx_warn = (s->regs.ctrl & FLEXCAN_CTRL_TWRN_MSK) &&
473 * (s->regs.ecr & FLEXCAN_ESR_TWRN_INT);
474 * bool irq_rx_warn = (s->regs.ctrl & FLEXCAN_CTRL_RWRN_MSK) &&
475 * (s->regs.ecr & FLEXCAN_ESR_RWRN_INT);
476 */
477
478 irq_pending = (mb_irqs[0] || mb_irqs[1]) ? 1 : 0;
479 trace_flexcan_irq_update(DEVICE(s)->canonical_path, mb_irqs[0], mb_irqs[1],
480 irq_pending);
481
482 qemu_set_irq(s->irq, irq_pending);
483 }
484
485 /**
486 * flexcan_irq_iflag_set() - Set IFLAG bit corresponding to MB mbidx
487 * @s: FlexCAN device pointer
488 * @mbidx: mailbox index
489 */
490 static void flexcan_irq_iflag_set(FlexcanState *s, int mbidx)
491 {
492 if (mbidx < 32) {
493 s->regs.iflag1 |= BIT(mbidx);
494 } else {
495 s->regs.iflag2 |= BIT(mbidx - 32);
496 }
497 }
498
499 /**
500 * flexcan_irq_iflag_clear() - Clear IFLAG bit corresponding to MB mbidx
501 * @s: FlexCAN device pointer
502 * @mbidx: mailbox index
503 */
504 static void flexcan_irq_iflag_clear(FlexcanState *s, int mbidx)
505 {
506 if (mbidx < 32) {
507 s->regs.iflag1 &= ~BIT(mbidx);
508 } else {
509 s->regs.iflag2 &= ~BIT(mbidx - 32);
510 }
511 }
512
513 /* ========== RESET ========== */
514 static void flexcan_reset_local_state(FlexcanState *s)
515 {
516 uint32_t *reset_mask = (uint32_t *)&flexcan_regs_reset_mask;
517 for (int i = 0; i < (sizeof(FlexcanRegs) / 4); i++) {
518 s->regs_raw[i] &= reset_mask[i];
519 }
520
521 s->regs.mcr |= 0x5980000F;
522 s->locked_mbidx = FLEXCAN_NO_MB_LOCKED;
523 s->smb_target_mbidx = FLEXCAN_SMB_EMPTY;
524 s->timer_start = FLEXCAN_TIMER_STOPPED;
525
526 trace_flexcan_reset(DEVICE(s)->canonical_path);
527 }
528
529 static void flexcan_reset_enter(Object *obj, ResetType type)
530 {
531 FlexcanState *s = CAN_FLEXCAN(obj);
532
533 memset(&s->regs, 0, sizeof(s->regs));
534 flexcan_reset_local_state(s);
535 }
536
537 static void flexcan_reset_hold(Object *obj, ResetType type)
538 {
539 FlexcanState *s = CAN_FLEXCAN(obj);
540
541 flexcan_irq_update(s);
542 }
543
544
545 /* ========== Operation mode control ========== */
546 /**
547 * flexcan_update_esr() - Update ESR based on mode and CAN bus connection state
548 * @s: FlexCAN device pointer
549 */
550 static void flexcan_update_esr(FlexcanState *s)
551 {
552 bool is_running = (s->regs.mcr & FLEXCAN_MCR_NOT_RDY) == 0;
553 /* potentially, there could be other influences on ESR[SYNCH] */
554
555 if (is_running && s->canbus) {
556 s->regs.esr |= FLEXCAN_ESR_SYNCH | FLEXCAN_ESR_IDLE;
557 } else {
558 s->regs.esr &= ~(FLEXCAN_ESR_SYNCH | FLEXCAN_ESR_IDLE);
559 }
560 }
561
562 /**
563 * flexcan_update_esr() - Process MCR write
564 * @s: FlexCAN device pointer
565 * @pv: previously set MCR value
566 *
567 * This function expects the new MCR value to be already written in s->regs.mcr.
568 */
569 static void flexcan_set_mcr(FlexcanState *s, const uint32_t pv)
570 {
571 uint32_t cv = s->regs.mcr;
572
573 /* -- module disable mode -- */
574 if (!(pv & FLEXCAN_MCR_MDIS) && (cv & FLEXCAN_MCR_MDIS)) {
575 /* transition to Module Disable mode */
576 cv |= FLEXCAN_MCR_LPM_ACK;
577 } else if ((pv & FLEXCAN_MCR_MDIS) && !(cv & FLEXCAN_MCR_MDIS)) {
578 /* transition from Module Disable mode */
579 cv &= ~FLEXCAN_MCR_LPM_ACK;
580 }
581
582 /* -- soft reset -- */
583 if (!(cv & FLEXCAN_MCR_LPM_ACK) && (cv & FLEXCAN_MCR_SOFTRST)) {
584 if (s->regs.mcr & FLEXCAN_MCR_LPM_ACK) {
585 qemu_log_mask(LOG_GUEST_ERROR,
586 "%s: invalid soft reset request in low-power mode",
587 DEVICE(s)->canonical_path);
588 }
589
590 flexcan_reset_local_state(s);
591 cv = s->regs.mcr;
592 }
593
594 /* -- freeze mode -- */
595 if (!(cv & FLEXCAN_MCR_LPM_ACK) &&
596 (cv & FLEXCAN_MCR_FRZ) &&
597 (cv & FLEXCAN_MCR_HALT)) {
598 cv |= FLEXCAN_MCR_FRZ_ACK;
599 } else {
600 cv &= ~FLEXCAN_MCR_FRZ_ACK;
601 }
602
603 /* -- fifo mode -- */
604 if (
605 ((pv & FLEXCAN_MCR_FEN) && !(cv & FLEXCAN_MCR_FEN)) ||
606 (!(pv & FLEXCAN_MCR_FEN) && (cv & FLEXCAN_MCR_FEN))
607 ) {
608 /* clear iflags used by fifo */
609 s->regs.iflag1 &= ~(
610 FLEXCAN_IFLAG_RX_FIFO_AVAILABLE |
611 FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
612 FLEXCAN_IFLAG_RX_FIFO_WARN
613 );
614 }
615 if (!(pv & FLEXCAN_MCR_FEN) && (cv & FLEXCAN_MCR_FEN)) {
616 /* zero out fifo region, we rely on zeroed can_ctrl for empty slots */
617 memset(s->regs.mbs, 0,
618 FLEXCAN_FIFO_DEPTH * sizeof(FlexcanRegsMessageBuffer));
619 }
620
621 /*
622 * assert NOT_RDY bit if in disable,
623 * stop (not implemented) or freeze mode
624 */
625 if ((cv & FLEXCAN_MCR_LPM_ACK) || (cv & FLEXCAN_MCR_FRZ_ACK)) {
626 cv |= FLEXCAN_MCR_NOT_RDY;
627 } else {
628 cv &= ~FLEXCAN_MCR_NOT_RDY;
629 }
630
631 if ((pv & FLEXCAN_MCR_NOT_RDY) && !(cv & FLEXCAN_MCR_NOT_RDY)) {
632 /* module went up, start the timer */
633 flexcan_timer_start(s);
634 } else if (!(pv & FLEXCAN_MCR_NOT_RDY) && (cv & FLEXCAN_MCR_NOT_RDY)) {
635 /* module went down, store the current timer value */
636 flexcan_timer_stop(s);
637 }
638
639 s->regs.mcr = cv;
640 flexcan_update_esr(s);
641 trace_flexcan_set_mcr(
642 DEVICE(s)->canonical_path,
643 cv & FLEXCAN_MCR_LPM_ACK ? "DISABLED" : "ENABLED",
644 (cv & FLEXCAN_MCR_FRZ_ACK || cv & FLEXCAN_MCR_LPM_ACK) ?
645 "FROZEN" : "RUNNING",
646 cv & FLEXCAN_MCR_FEN ? "FIFO" : "MAILBOX",
647 cv & FLEXCAN_MCR_NOT_RDY ? "NOT_RDY" : "RDY",
648 s->regs.esr & FLEXCAN_ESR_SYNCH ? "SYNC" : "NOSYNC"
649 );
650 }
651
652 /* ========== TX ========== */
653 static void flexcan_transmit(FlexcanState *s, int mbidx)
654 {
655 FlexcanRegsMessageBuffer *mb = &s->regs.mbs[mbidx];
656 qemu_can_frame frame = {
657 .flags = 0,
658 };
659 uint32_t *frame_data = (uint32_t *)&frame.data;
660 uint32_t timestamp = flexcan_get_timestamp(s, true);
661
662 if ((s->regs.ctrl & FLEXCAN_CTRL_LOM) ||
663 (s->regs.mcr & FLEXCAN_MCR_NOT_RDY)) {
664 /* no transmiting in listen-only, freeze or low-power mode */
665 return;
666 }
667
668 if (mb->can_ctrl & FLEXCAN_MB_CNT_IDE) {
669 /* 29b ID stored in bits [0, 29) */
670 uint32_t id = mb->can_id & 0x1FFFFFFF;
671 frame.can_id = id | QEMU_CAN_EFF_FLAG;
672 } else {
673 /* 11b ID stored in bits [18, 29) */
674 uint32_t id = (mb->can_id & (0x7FF << 18)) >> 18;
675 frame.can_id = id;
676 }
677
678 frame.can_dlc = (mb->can_ctrl & (0xF << 16)) >> 16;
679
680 for (int i = 0; i < 2; i++) {
681 stl_be_p(&frame_data[i], mb->data[i]);
682 }
683
684 if (!(s->regs.mcr & FLEXCAN_MCR_SRX_DIS)) {
685 /* self-reception */
686 flexcan_mb_rx(s, &frame);
687 }
688 if (!(s->regs.ctrl & FLEXCAN_CTRL_LPB)) {
689 /* send to bus if not in loopback mode */
690 if (s->canbus) {
691 can_bus_client_send(&s->bus_client, &frame, 1);
692 } else {
693 /* todo: raise error (no ack) */
694 }
695 }
696
697 mb->can_ctrl &= ~(FLEXCAN_MB_CODE_MASK | FLEXCAN_MB_CNT_TIMESTAMP_MASK);
698 mb->can_ctrl |= FLEXCAN_MB_CODE_TX_INACTIVE |
699 FLEXCAN_MB_CNT_TIMESTAMP(timestamp);
700
701 /* todo: compute the CRC */
702 s->regs.crcr = FLEXCAN_CRCR_TXCRC(0) | FLEXCAN_CRCR_MBCRC(mbidx);
703
704 flexcan_irq_iflag_set(s, mbidx);
705 }
706
707 static void flexcan_mb_write(FlexcanState *s, int mbid)
708 {
709 FlexcanRegsMessageBuffer *mb = &s->regs.mbs[mbid];
710
711 bool is_mailbox = (mb <= flexcan_get_last_enabled_mailbox(s)) &&
712 (mb >= flexcan_get_first_message_buffer(s));
713
714 if (trace_event_get_state_backends(TRACE_FLEXCAN_MB_WRITE)) {
715 char code_str_buf[FLEXCAN_DBG_BUF_LEN] = { 0 };
716 const char *code_str = flexcan_dbg_mb_code(mb->can_ctrl, code_str_buf);
717 trace_flexcan_mb_write(DEVICE(s)->canonical_path, mbid, code_str,
718 is_mailbox, mb->can_ctrl, mb->can_id);
719 }
720
721 if (!is_mailbox) {
722 /**
723 * Disabled mailbox or mailbox in region of queue filters
724 * was updated. Either way there is nothing to do.
725 */
726 return;
727 }
728
729 /* any write to message buffer clears the not_serviced flag */
730 mb->can_ctrl &= ~FLEXCAN_MB_CNT_NOT_SRV;
731
732 /**
733 * todo: search for active tx mbs on transition from freeze/disable mode
734 */
735 switch (mb->can_ctrl & FLEXCAN_MB_CODE_MASK) {
736 case FLEXCAN_MB_CODE_TX_INACTIVE:
737 QEMU_FALLTHROUGH;
738 case FLEXCAN_MB_CODE_RX_INACTIVE:
739 QEMU_FALLTHROUGH;
740 case FLEXCAN_MB_CODE_RX_EMPTY:
741 QEMU_FALLTHROUGH;
742 case FLEXCAN_MB_CODE_RX_FULL:
743 QEMU_FALLTHROUGH;
744 case FLEXCAN_MB_CODE_RX_RANSWER:
745 break;
746
747 case FLEXCAN_MB_CODE_TX_DATA:
748 flexcan_transmit(s, mbid);
749 break;
750 case FLEXCAN_MB_CODE_TX_ABORT:
751 /*
752 * as transmission is instant, it can never be aborted
753 * we need to set CODE in C/S back to the previous code
754 */
755 mb->can_ctrl &= ~FLEXCAN_MB_CODE(1);
756 break;
757 case FLEXCAN_MB_CODE_TX_TANSWER:
758 break;
759 default:
760 /* prevent setting the busy bit */
761 mb->can_ctrl &= ~FLEXCAN_MB_CODE_RX_BUSY_BIT;
762 break;
763 }
764
765 }
766
767 /* ========== RX ========== */
768 static void flexcan_mb_move_in(FlexcanState *s, const qemu_can_frame *frame,
769 FlexcanRegsMessageBuffer *target_mb)
770 {
771 uint32_t frame_len = frame->can_dlc;
772 uint32_t *frame_data = (uint32_t *)&frame->data;
773 int timestamp = flexcan_get_timestamp(s, true);
774 uint32_t new_code = 0;
775
776 memset(target_mb, 0, sizeof(FlexcanRegsMessageBuffer));
777
778 if (frame_len > 8) {
779 frame_len = 8;
780 }
781 for (int i = 0; i < 2; i++) {
782 target_mb->data[i] = ldl_be_p(&frame_data[i]);
783 }
784
785 switch (target_mb->can_ctrl & FLEXCAN_MB_CODE_MASK) {
786 case FLEXCAN_MB_CODE_RX_FULL:
787 case FLEXCAN_MB_CODE_RX_OVERRUN:
788 if (target_mb->can_ctrl & FLEXCAN_MB_CNT_NOT_SRV) {
789 new_code = FLEXCAN_MB_CODE_RX_OVERRUN;
790 } else {
791 new_code = FLEXCAN_MB_CODE_RX_FULL;
792 }
793 break;
794 case FLEXCAN_MB_CODE_RX_RANSWER:
795 assert(s->regs.ctrl2 & FLEXCAN_CTRL2_RRS);
796 new_code = FLEXCAN_MB_CODE_TX_TANSWER;
797 break;
798 default:
799 new_code = FLEXCAN_MB_CODE_RX_FULL;
800 }
801
802 target_mb->can_ctrl = new_code
803 | FLEXCAN_MB_CNT_TIMESTAMP(timestamp)
804 | FLEXCAN_MB_CNT_LENGTH(frame_len)
805 | FLEXCAN_MB_CNT_NOT_SRV
806 | FLEXCAN_MB_CNT_SRR; /* always set for received frames */
807 if (frame->can_id & QEMU_CAN_RTR_FLAG) {
808 target_mb->can_ctrl |= FLEXCAN_MB_CNT_RTR;
809 }
810
811 if (frame->can_id & QEMU_CAN_EFF_FLAG) {
812 target_mb->can_ctrl |= FLEXCAN_MB_CNT_IDE;
813 target_mb->can_id |= frame->can_id & QEMU_CAN_EFF_MASK;
814 } else {
815 target_mb->can_id |= (frame->can_id & QEMU_CAN_SFF_MASK) << 18;
816 }
817 }
818 static void flexcan_mb_lock(FlexcanState *s, int mbidx)
819 {
820 FlexcanRegsMessageBuffer *mb = &s->regs.mbs[mbidx];
821 if ((mb > flexcan_get_last_enabled_mailbox(s)) ||
822 (mb < flexcan_get_first_message_buffer(s))) {
823 return;
824 }
825 switch (mb->can_ctrl & FLEXCAN_MB_CODE_MASK) {
826 case FLEXCAN_MB_CODE_RX_FULL:
827 QEMU_FALLTHROUGH;
828 case FLEXCAN_MB_CODE_RX_OVERRUN:
829 QEMU_FALLTHROUGH;
830 case FLEXCAN_MB_CODE_RX_RANSWER:
831 /* continue */
832 trace_flexcan_mb_lock(DEVICE(s)->canonical_path, mbidx, 1);
833 break;
834 default:
835 trace_flexcan_mb_lock(DEVICE(s)->canonical_path, mbidx, 0);
836 return;
837 }
838
839 s->locked_mbidx = mbidx;
840 }
841
842 static void flexcan_mb_unlock(FlexcanState *s)
843 {
844 int locked_mbidx = s->locked_mbidx;
845 bool has_pending_frame = locked_mbidx == s->smb_target_mbidx;
846
847 if (s->locked_mbidx == FLEXCAN_NO_MB_LOCKED) {
848 return;
849 }
850
851 assert(locked_mbidx >= 0 && locked_mbidx < FLEXCAN_MAILBOX_COUNT);
852 FlexcanRegsMessageBuffer *locked_mb = &s->regs.mbs[locked_mbidx];
853 s->locked_mbidx = FLEXCAN_NO_MB_LOCKED;
854
855 if (locked_mb >= flexcan_get_first_message_buffer(s) &&
856 locked_mb <= flexcan_get_last_enabled_mailbox(s)
857 ) {
858 /* mark the message buffer as serviced */
859 locked_mb->can_ctrl &= ~FLEXCAN_MB_CNT_NOT_SRV;
860 }
861
862 /* try move in from SMB */
863 trace_flexcan_mb_unlock(DEVICE(s)->canonical_path, locked_mbidx,
864 has_pending_frame ? " PENDING FRAME IN SMB" : "");
865
866 /* todo: in low-power modes, this should be postponed until exit */
867 if (has_pending_frame) {
868 FlexcanRegsMessageBuffer *target_mb = &s->regs.mbs[locked_mbidx];
869 memcpy(target_mb, &s->regs.rx_smb0, sizeof(FlexcanRegsMessageBuffer));
870
871 memset(&s->regs.rx_smb0, 0, sizeof(FlexcanRegsMessageBuffer));
872 s->locked_mbidx = FLEXCAN_SMB_EMPTY;
873
874 flexcan_irq_iflag_set(s, locked_mbidx);
875 }
876 }
877
878 static bool flexcan_can_receive(CanBusClientState *client)
879 {
880 FlexcanState *s = container_of(client, FlexcanState, bus_client);
881 return !(s->regs.mcr & FLEXCAN_MCR_NOT_RDY);
882 }
883
884 /* --------- RX FIFO ---------- */
885
886 /**
887 * flexcan_fifo_pop() - Pop message from FIFO and update IRQs
888 * @s: FlexCAN device pointer
889 *
890 * Does not require the queue to be non-empty.
891 */
892 static void flexcan_fifo_pop(FlexcanState *s)
893 {
894 if (s->regs.mbs[0].can_ctrl != 0) {
895 /* move queue elements forward */
896 memmove(&s->regs.mbs[0], &s->regs.mbs[1],
897 sizeof(s->regs.mbs[0]) * (FLEXCAN_FIFO_DEPTH - 1));
898
899 /* clear the first-in slot */
900 memset(&s->regs.mbs[FLEXCAN_FIFO_DEPTH - 1], 0,
901 sizeof(FlexcanRegsMessageBuffer));
902
903 trace_flexcan_fifo_pop(DEVICE(s)->canonical_path, 1,
904 s->regs.mbs[0].can_ctrl != 0);
905 } else {
906 trace_flexcan_fifo_pop(DEVICE(s)->canonical_path, 0, 0);
907 }
908
909 if (s->regs.mbs[0].can_ctrl != 0) {
910 flexcan_irq_iflag_set(s, I_FIFO_AVAILABLE);
911 } else {
912 flexcan_irq_iflag_clear(s, I_FIFO_AVAILABLE);
913 }
914 }
915
916 /**
917 * flexcan_fifo_find_free_slot() - Find the first free slot in the FIFO
918 * @s: FlexCAN device pointer
919 *
920 * Return: Pointer to the first free slot in the FIFO,
921 * or NULL if the queue is full.
922 */
923 static FlexcanRegsMessageBuffer *flexcan_fifo_find_free_slot(FlexcanState *s)
924 {
925 for (int i = 0; i < FLEXCAN_FIFO_DEPTH; i++) {
926 FlexcanRegsMessageBuffer *mb = &s->regs.mbs[i];
927 if (mb->can_ctrl == 0) {
928 return mb;
929 }
930 }
931 return NULL;
932 }
933
934 /**
935 * flexcan_fifo_push() - Update FIFO IRQs after frame move-in
936 * @s: FlexCAN device pointer
937 * @slot: Target FIFO slot
938 *
939 * The usage is as follows:
940 * 1. Get free slot pointer using flexcan_fifo_find_free_slot()
941 * 2. Move the frame in if not NULL
942 * 3. Call flexcan_fifo_push() regardless of the NULL pointer
943 */
944 static void flexcan_fifo_push(FlexcanState *s, FlexcanRegsMessageBuffer *slot)
945 {
946 if (slot) {
947 int n_occupied = slot - s->regs.mbs;
948 if (n_occupied == 4) { /* 4 means the 5th slot was filled in */
949 /*
950 * fifo occupancy increased from 4 to 5,
951 * raising FIFO_WARN interrupt
952 */
953 flexcan_irq_iflag_set(s, I_FIFO_WARN);
954 }
955 flexcan_irq_iflag_set(s, I_FIFO_AVAILABLE);
956
957 trace_flexcan_fifo_push(DEVICE(s)->canonical_path, n_occupied);
958 } else {
959 flexcan_irq_iflag_set(s, I_FIFO_OVERFLOW);
960
961 trace_flexcan_fifo_push(DEVICE(s)->canonical_path, -1);
962 }
963 }
964
965 static enum FlexcanRx flexcan_fifo_rx(FlexcanState *s,
966 const qemu_can_frame *buf)
967 {
968 /* todo: filtering. return FLEXCAN_FIFO_RX_RETRY if filtered out */
969 if ((s->regs.mcr & FLEXCAN_MCR_IDAM_MASK) == FLEXCAN_MCR_IDAM_D) {
970 /* all frames rejected */
971 return FLEXCAN_RX_SEARCH_RETRY;
972 } else {
973 /* push message to queue if not full */
974 FlexcanRegsMessageBuffer *slot = flexcan_fifo_find_free_slot(s);
975 if (slot) {
976 flexcan_mb_move_in(s, buf, slot);
977 }
978 flexcan_fifo_push(s, slot);
979
980 return slot ? FLEXCAN_RX_SEARCH_ACCEPT : FLEXCAN_RX_SEARCH_DROPPED;
981 }
982 }
983
984 /* --------- RX message buffer ---------- */
985
986 /**
987 * flexcan_mb_rx_check_mb() - Check if a mb matches a received frame
988 * @s: FlexCAN device pointer
989 * @buf: Frame to be received from CAN subsystem
990 * @mbid: Target mailbox index. The mailbox must be a valid message buffer.
991 *
992 * Return: FLEXCAN_CHECK_MB_NIL if the message buffer does not match.
993 * FLEXCAN_CHECK_MB_MATCH if the message buffer matches the received
994 * frame and is free-to-receive,
995 * FLEXCAN_CHECK_MB_MATCH_LOCKED if the message buffer matches,
996 * but is locked,
997 * FLEXCAN_CHECK_MB_MATCH_NON_FREE if the message buffer matches,
998 * but is not free-to-receive
999 * for some other reason.
1000 */
1001 static enum FlexcanCheck flexcan_mb_rx_check_mb(FlexcanState *s,
1002 const qemu_can_frame *buf,
1003 int mbid)
1004 {
1005 FlexcanRegsMessageBuffer *mb = &s->regs.mbs[mbid];
1006 const bool is_rtr = !!(buf->can_id & QEMU_CAN_RTR_FLAG);
1007 const bool is_serviced = !(mb->can_ctrl & FLEXCAN_MB_CNT_NOT_SRV);
1008 const bool is_locked = s->locked_mbidx == mbid;
1009
1010 bool is_free_to_receive = false;
1011 bool is_matched = false;
1012
1013 switch (mb->can_ctrl & FLEXCAN_MB_CODE_MASK) {
1014 case FLEXCAN_MB_CODE_RX_RANSWER:
1015 if (is_rtr && !(s->regs.ctrl2 & FLEXCAN_CTRL2_RRS)) {
1016 /* todo: do the actual matching/filtering and RTR answer */
1017 is_matched = true;
1018 }
1019 break;
1020 case FLEXCAN_MB_CODE_RX_FULL:
1021 QEMU_FALLTHROUGH;
1022 case FLEXCAN_MB_CODE_RX_OVERRUN:
1023 is_free_to_receive = is_serviced;
1024 /* todo: do the actual matching/filtering */
1025 is_matched = true;
1026 break;
1027 case FLEXCAN_MB_CODE_RX_EMPTY:
1028 is_free_to_receive = true;
1029 /* todo: do the actual matching/filtering */
1030 is_matched = true;
1031 break;
1032 default:
1033 break;
1034 }
1035
1036 if (trace_event_get_state_backends(TRACE_FLEXCAN_MB_RX_CHECK_MB)) {
1037 char code_str_buf[FLEXCAN_DBG_BUF_LEN] = { 0 };
1038 const char *code_str = flexcan_dbg_mb_code(mb->can_ctrl, code_str_buf);
1039 trace_flexcan_mb_rx_check_mb(DEVICE(s)->canonical_path, mbid, code_str,
1040 is_matched, is_free_to_receive,
1041 is_serviced, is_locked);
1042 }
1043
1044 if (!is_matched) {
1045 return FLEXCAN_CHECK_MB_NIL;
1046 }
1047
1048 if (is_locked) {
1049 return FLEXCAN_CHECK_MB_MATCH_LOCKED;
1050 }
1051
1052 if (is_free_to_receive) {
1053 return FLEXCAN_CHECK_MB_MATCH;
1054 }
1055
1056 return FLEXCAN_CHECK_MB_MATCH_NON_FREE;
1057 }
1058
1059 static enum FlexcanRx flexcan_mb_rx(FlexcanState *s, const qemu_can_frame *buf)
1060 {
1061 int last_not_free_to_receive_mbid = -1;
1062 bool last_not_free_to_receive_locked = false;
1063
1064 FlexcanRegsMessageBuffer *first_mb = flexcan_get_first_message_buffer(s);
1065 FlexcanRegsMessageBuffer *last_mb = flexcan_get_last_enabled_mailbox(s);
1066
1067 for (FlexcanRegsMessageBuffer *mb = first_mb;
1068 mb <= last_mb; mb++) {
1069 int mbid = mb - s->regs.mbs;
1070 enum FlexcanCheck r = flexcan_mb_rx_check_mb(s, buf, mbid);
1071 if (r == FLEXCAN_CHECK_MB_MATCH) {
1072 flexcan_mb_move_in(s, buf, mb);
1073 flexcan_irq_iflag_set(s, mbid);
1074 return FLEXCAN_RX_SEARCH_ACCEPT;
1075 }
1076
1077 if (r == FLEXCAN_CHECK_MB_MATCH_NON_FREE) {
1078 last_not_free_to_receive_mbid = mbid;
1079 last_not_free_to_receive_locked = false;
1080 } else if (r == FLEXCAN_CHECK_MB_MATCH_LOCKED) {
1081 /*
1082 * message buffer is locked,
1083 * we can move in the message after it's unlocked
1084 */
1085 last_not_free_to_receive_mbid = mbid;
1086 last_not_free_to_receive_locked = true;
1087 }
1088 }
1089
1090 if (last_not_free_to_receive_mbid >= 0) {
1091 if (last_not_free_to_receive_locked) {
1092 /*
1093 * copy to temporary mailbox (SMB)
1094 * it will be moved in when the mailbox is unlocked
1095 */
1096 s->regs.rx_smb0.can_ctrl =
1097 s->regs.mbs[last_not_free_to_receive_mbid].can_id;
1098 flexcan_mb_move_in(s, buf, &s->regs.rx_smb0);
1099 s->smb_target_mbidx = last_not_free_to_receive_mbid;
1100 return FLEXCAN_RX_SEARCH_ACCEPT;
1101 }
1102
1103 if (s->regs.mcr & FLEXCAN_MCR_IRMQ) {
1104 flexcan_mb_move_in(s, buf,
1105 &s->regs.mbs[last_not_free_to_receive_mbid]);
1106 flexcan_irq_iflag_set(s, last_not_free_to_receive_mbid);
1107 return FLEXCAN_RX_SEARCH_ACCEPT;
1108 }
1109 }
1110
1111 return FLEXCAN_RX_SEARCH_RETRY;
1112 }
1113
1114 static ssize_t flexcan_receive(CanBusClientState *client,
1115 const qemu_can_frame *frames, size_t frames_cnt)
1116 {
1117 FlexcanState *s = container_of(client, FlexcanState, bus_client);
1118 trace_flexcan_receive(DEVICE(s)->canonical_path, frames_cnt);
1119
1120 if (frames_cnt == 0) {
1121 return 0;
1122 }
1123
1124 /* clear the SMB, as it would be overriden in hardware */
1125 memset(&s->regs.rx_smb0, 0, sizeof(FlexcanRegsMessageBuffer));
1126 s->smb_target_mbidx = FLEXCAN_SMB_EMPTY;
1127
1128 for (size_t i = 0; i < frames_cnt; i++) {
1129 int r;
1130 const qemu_can_frame *frame = &frames[i];
1131 if (frame->can_id & QEMU_CAN_ERR_FLAG) {
1132 /* todo: error frame handling */
1133 continue;
1134 }
1135 if (frame->flags & QEMU_CAN_FRMF_TYPE_FD) {
1136 /* CAN FD supported only in later FlexCAN version */
1137 continue;
1138 }
1139
1140 /* todo: this order logic is not complete and needs further work */
1141 if (s->regs.mcr & FLEXCAN_MCR_FEN &&
1142 s->regs.ctrl2 & FLEXCAN_CTRL2_MRP) {
1143 r = flexcan_mb_rx(s, frame);
1144 if (r == FLEXCAN_RX_SEARCH_RETRY) {
1145 flexcan_fifo_rx(s, frame);
1146 }
1147 } else if (s->regs.mcr & FLEXCAN_MCR_FEN) {
1148 r = flexcan_fifo_rx(s, frame);
1149 if (r == FLEXCAN_RX_SEARCH_RETRY) {
1150 flexcan_mb_rx(s, frame);
1151 }
1152 } else {
1153 flexcan_mb_rx(s, frame);
1154 }
1155 }
1156
1157 flexcan_irq_update(s);
1158 return 1;
1159 }
1160
1161 /* ========== I/O handling ========== */
1162 static void flexcan_mem_write(void *opaque, hwaddr addr, uint64_t val,
1163 unsigned size)
1164 {
1165 FlexcanState *s = opaque;
1166 const int mbid = (addr - offsetof(FlexcanRegs, mbs)) /
1167 sizeof(s->regs.mbs[0]);
1168 uint32_t write_mask = ((const uint32_t *)
1169 &flexcan_regs_write_mask)[addr / 4];
1170 uint32_t old_value = s->regs_raw[addr / 4];
1171
1172 /*
1173 * 0 for bits that can "only be written in Freeze mode as it is blocked
1174 * by hardware in other modes"
1175 */
1176 const uint32_t freeze_mask_mcr = 0xDF54CC80;
1177 const uint32_t freeze_mask_ctrl1 = 0x0000E740;
1178
1179 flexcan_trace_mem_op(s, addr, val, size, true);
1180 switch (addr) {
1181 case offsetof(FlexcanRegs, mcr):
1182 if (!(s->regs.mcr & FLEXCAN_MCR_FRZ_ACK)) {
1183 write_mask &= freeze_mask_mcr;
1184 }
1185 s->regs.mcr = (val & write_mask) | (old_value & ~write_mask);
1186 flexcan_set_mcr(s, old_value);
1187 break;
1188 case offsetof(FlexcanRegs, ctrl):
1189 if (!(s->regs.mcr & FLEXCAN_MCR_FRZ_ACK)) {
1190 write_mask &= freeze_mask_ctrl1;
1191 }
1192 s->regs.ctrl = (val & write_mask) | (old_value & ~write_mask);
1193 break;
1194 case offsetof(FlexcanRegs, iflag1):
1195 s->regs.iflag1 &= ~val;
1196 if ((s->regs.mcr & FLEXCAN_MCR_FEN) &&
1197 (val & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE)) {
1198 flexcan_fifo_pop(s);
1199 }
1200 break;
1201 case offsetof(FlexcanRegs, iflag2):
1202 s->regs.iflag2 &= ~val;
1203 break;
1204 case offsetof(FlexcanRegs, ctrl2):
1205 QEMU_FALLTHROUGH;
1206 case offsetof(FlexcanRegs, ecr):
1207 QEMU_FALLTHROUGH;
1208 case offsetof(FlexcanRegs, rxmgmask):
1209 QEMU_FALLTHROUGH;
1210 case offsetof(FlexcanRegs, rx14mask):
1211 QEMU_FALLTHROUGH;
1212 case offsetof(FlexcanRegs, rx15mask):
1213 QEMU_FALLTHROUGH;
1214 case offsetof(FlexcanRegs, rxfgmask):
1215 QEMU_FALLTHROUGH;
1216 case offsetof(FlexcanRegs, rximr[0]) ... offsetof(FlexcanRegs, rximr[63]):
1217 /* these registers can only be written in freeze mode */
1218 if (!(s->regs.mcr & FLEXCAN_MCR_FRZ_ACK)) {
1219 break;
1220 }
1221 QEMU_FALLTHROUGH;
1222 default:
1223 s->regs_raw[addr / 4] = (val & write_mask) | (old_value & ~write_mask);
1224
1225 if (0 <= mbid && mbid < ARRAY_SIZE(s->regs.mbs)) {
1226 /* access to mailbox */
1227
1228 if (s->locked_mbidx == mbid) {
1229 flexcan_mb_unlock(s);
1230 }
1231
1232 /* check for invalid writes into FIFO region */
1233 if (s->regs.mcr & FLEXCAN_MCR_FEN && mbid < FLEXCAN_FIFO_DEPTH) {
1234 qemu_log_mask(LOG_GUEST_ERROR,
1235 "%s: Invalid write to Rx-FIFO structure",
1236 DEVICE(s)->canonical_path);
1237 return;
1238 }
1239
1240 /* run mailbox processing function on write to control word */
1241 if ((addr & 0xF) == 0) {
1242 flexcan_mb_write(s, mbid);
1243 }
1244 }
1245 break;
1246 }
1247
1248 flexcan_irq_update(s);
1249 }
1250
1251 static uint64_t flexcan_mem_read(void *opqaue, hwaddr addr, unsigned size)
1252 {
1253 FlexcanState *s = opqaue;
1254 const int mbid = (addr - offsetof(FlexcanRegs, mbs)) /
1255 sizeof(s->regs.mbs[0]);
1256 uint32_t rv = s->regs_raw[addr >> 2];
1257
1258 if (0 <= mbid && mbid < ARRAY_SIZE(s->regs.mbs)) {
1259 /* reading from mailbox */
1260 if (addr % 16 == 0 && s->locked_mbidx != mbid) {
1261 /* reading control word locks the mailbox */
1262 flexcan_mb_unlock(s);
1263 flexcan_mb_lock(s, mbid);
1264 flexcan_irq_update(s);
1265 rv = s->regs.mbs[mbid].can_ctrl & ~FLEXCAN_MB_CNT_NOT_SRV;
1266 }
1267 } else if (addr == offsetof(FlexcanRegs, timer)) {
1268 flexcan_mb_unlock(s);
1269 flexcan_irq_update(s);
1270 rv = flexcan_get_timestamp(s, false);
1271 }
1272
1273 flexcan_trace_mem_op(s, addr, rv, size, false);
1274 return rv;
1275 }
1276
1277 static bool flexcan_mem_accepts(void *opaque, hwaddr addr,
1278 unsigned size, bool is_write,
1279 MemTxAttrs attrs)
1280 {
1281 FlexcanState *s = opaque;
1282
1283 if ((s->regs.ctrl2 & FLEXCAN_CTRL2_WRMFRZ) &&
1284 (s->regs.mcr & FLEXCAN_MCR_FRZ_ACK)) {
1285 /* unrestricted access to FlexCAN memory in freeze mode */
1286 return true;
1287 } else if (attrs.user && (s->regs.mcr & FLEXCAN_MCR_SUPV)) {
1288 qemu_log_mask(LOG_GUEST_ERROR,
1289 "%s: Invalid user-mode access to restricted register",
1290 DEVICE(s)->canonical_path);
1291 return false;
1292 } else if (attrs.user && is_write && addr < 4) {
1293 qemu_log_mask(LOG_GUEST_ERROR,
1294 "%s: Invalid user-mode access to MCR",
1295 DEVICE(s)->canonical_path);
1296 return false;
1297 }
1298
1299 return true;
1300 }
1301
1302 static const struct MemoryRegionOps flexcan2_ops = {
1303 .read = flexcan_mem_read,
1304 .write = flexcan_mem_write,
1305 .endianness = DEVICE_LITTLE_ENDIAN,
1306 .valid = {
1307 .min_access_size = 1,
1308 .max_access_size = 4,
1309 .unaligned = true,
1310 .accepts = flexcan_mem_accepts
1311 },
1312 .impl = {
1313 .min_access_size = 4,
1314 .max_access_size = 4,
1315 .unaligned = false
1316 },
1317 };
1318
1319 static const struct MemoryRegionOps flexcan3_ops = {
1320 .read = flexcan_mem_read,
1321 .write = flexcan_mem_write,
1322 .endianness = DEVICE_LITTLE_ENDIAN,
1323 .valid = {
1324 .min_access_size = 1,
1325 .max_access_size = 8,
1326 .unaligned = true,
1327 .accepts = flexcan_mem_accepts
1328 },
1329 .impl = {
1330 .min_access_size = 4,
1331 .max_access_size = 4,
1332 .unaligned = false
1333 },
1334 };
1335
1336 static CanBusClientInfo flexcan_bus_client_info = {
1337 .can_receive = flexcan_can_receive,
1338 .receive = flexcan_receive,
1339 };
1340
1341 static int flexcan_connect_to_bus(FlexcanState *s, CanBusState *bus)
1342 {
1343 s->bus_client.info = &flexcan_bus_client_info;
1344
1345 if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1346 return -1;
1347 }
1348 return 0;
1349 }
1350
1351 static void flexcan2_init(Object *obj)
1352 {
1353 FlexcanState *s = CAN_FLEXCAN(obj);
1354
1355 memory_region_init_io(
1356 &s->iomem, obj, &flexcan2_ops, s, TYPE_CAN_FLEXCAN2,
1357 offsetof(FlexcanRegs, _reserved6)
1358 );
1359 }
1360
1361 static void flexcan3_init(Object *obj)
1362 {
1363 FlexcanState *s = CAN_FLEXCAN(obj);
1364
1365 memory_region_init_io(
1366 &s->iomem, obj, &flexcan3_ops, s, TYPE_CAN_FLEXCAN3,
1367 sizeof(FlexcanRegs)
1368 );
1369 }
1370
1371 static void flexcan_realize(DeviceState *dev, Error **errp)
1372 {
1373 FlexcanState *s = CAN_FLEXCAN(dev);
1374
1375 if (s->canbus) {
1376 if (flexcan_connect_to_bus(s, s->canbus) < 0) {
1377 error_setg(errp, "%s: flexcan_connect_to_bus failed",
1378 dev->canonical_path);
1379 return;
1380 }
1381 }
1382
1383 if (!s->ccm) {
1384 error_setg(errp, "%s 'clock-control-module' link property not set",
1385 dev->canonical_path);
1386 return;
1387 }
1388
1389 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
1390 sysbus_init_irq(SYS_BUS_DEVICE(SYS_BUS_DEVICE(dev)), &s->irq);
1391 }
1392
1393 static const VMStateDescription vmstate_can = {
1394 .name = TYPE_CAN_FLEXCAN,
1395 .version_id = 1,
1396 .minimum_version_id = 1,
1397 .fields = (const VMStateField[]) {
1398 VMSTATE_INT64(timer_start, FlexcanState),
1399 VMSTATE_UINT32_ARRAY(regs_raw, FlexcanState, sizeof(FlexcanRegs) / 4),
1400 VMSTATE_INT32(locked_mbidx, FlexcanState),
1401 VMSTATE_INT32(smb_target_mbidx, FlexcanState),
1402 VMSTATE_END_OF_LIST(),
1403 },
1404 };
1405
1406 static const Property flexcan_properties[] = {
1407 DEFINE_PROP_LINK("canbus", FlexcanState, canbus, TYPE_CAN_BUS,
1408 CanBusState *),
1409 DEFINE_PROP_LINK("clock-control-module", FlexcanState, ccm, TYPE_IMX_CCM,
1410 IMXCCMState *),
1411 };
1412
1413 static void flexcan_class_init(ObjectClass *klass, const void *data)
1414 {
1415 DeviceClass *dc = DEVICE_CLASS(klass);
1416 ResettableClass *rc = RESETTABLE_CLASS(klass);
1417
1418 rc->phases.enter = flexcan_reset_enter;
1419 rc->phases.hold = flexcan_reset_hold;
1420 dc->realize = flexcan_realize;
1421 device_class_set_props(dc, flexcan_properties);
1422 dc->vmsd = &vmstate_can;
1423 }
1424
1425 static void flexcan2_class_init(ObjectClass *klass, const void *data)
1426 {
1427 DeviceClass *dc = DEVICE_CLASS(klass);
1428
1429 dc->desc = "i.MX FlexCAN 2 Controller";
1430 }
1431
1432 static void flexcan3_class_init(ObjectClass *klass, const void *data)
1433 {
1434 DeviceClass *dc = DEVICE_CLASS(klass);
1435
1436 dc->desc = "i.MX FlexCAN 3 Controller";
1437 }
1438
1439 static const TypeInfo flexcan_types[] = {
1440 {
1441 .name = TYPE_CAN_FLEXCAN,
1442 .parent = TYPE_SYS_BUS_DEVICE,
1443 .instance_size = sizeof(FlexcanState),
1444 .class_init = flexcan_class_init,
1445 .abstract = true,
1446 },
1447 {
1448 .name = TYPE_CAN_FLEXCAN2,
1449 .parent = TYPE_CAN_FLEXCAN,
1450 .class_init = flexcan2_class_init,
1451 .instance_init = flexcan2_init,
1452 },
1453 {
1454 .name = TYPE_CAN_FLEXCAN3,
1455 .parent = TYPE_CAN_FLEXCAN,
1456 .class_init = flexcan3_class_init,
1457 .instance_init = flexcan3_init,
1458 },
1459 };
1460
1461 DEFINE_TYPES(flexcan_types)