1 /*
2 * Copyright (c) 2019 Vestas Wind Systems A/S
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /* Base driver compatible */
8 #define DT_DRV_COMPAT nxp_flexcan
9
10 /* CAN FD extension compatible */
11 #define FLEXCAN_FD_DRV_COMPAT nxp_flexcan_fd
12
13 #include <zephyr/kernel.h>
14 #include <zephyr/sys/atomic.h>
15 #include <zephyr/drivers/can.h>
16 #include <zephyr/drivers/can/transceiver.h>
17 #include <zephyr/drivers/clock_control.h>
18 #include <zephyr/device.h>
19 #include <zephyr/sys/byteorder.h>
20 #include <fsl_flexcan.h>
21 #include <zephyr/logging/log.h>
22 #include <zephyr/irq.h>
23 #include <zephyr/drivers/pinctrl.h>
24
25 LOG_MODULE_REGISTER(can_mcux_flexcan, CONFIG_CAN_LOG_LEVEL);
26
27 #if ((defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5641) || \
28 (defined(FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829) && FSL_FEATURE_FLEXCAN_HAS_ERRATA_5829))
29 /* the first valid MB should be occupied by ERRATA 5461 or 5829. */
30 #define RX_START_IDX 1
31 #else
32 #define RX_START_IDX 0
33 #endif
34
35 /* The maximum number of message buffers for concurrent active instances */
36 #ifdef CONFIG_CAN_MAX_MB
37 #define MCUX_FLEXCAN_MAX_MB CONFIG_CAN_MAX_MB
38 #else
39 #define MCUX_FLEXCAN_MAX_MB FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(0)
40 #endif
41
42 /*
43 * RX message buffers (filters) will take up the first N message
44 * buffers. The rest are available for TX use.
45 */
46 #define MCUX_FLEXCAN_MAX_RX (CONFIG_CAN_MAX_FILTER + RX_START_IDX)
47 #define MCUX_FLEXCAN_MAX_TX (MCUX_FLEXCAN_MAX_MB - MCUX_FLEXCAN_MAX_RX)
48
49 /*
50 * Convert from RX message buffer index to allocated filter ID and
51 * vice versa.
52 */
53 #define RX_MBIDX_TO_ALLOC_IDX(x) (x)
54 #define ALLOC_IDX_TO_RXMB_IDX(x) (x)
55
56 /*
57 * Convert from TX message buffer index to allocated TX ID and vice
58 * versa.
59 */
60 #define TX_MBIDX_TO_ALLOC_IDX(x) (x - MCUX_FLEXCAN_MAX_RX)
61 #define ALLOC_IDX_TO_TXMB_IDX(x) (x + MCUX_FLEXCAN_MAX_RX)
62
63 /* Convert from back from FLEXCAN IDs to Zephyr CAN IDs. */
64 #define FLEXCAN_ID_TO_CAN_ID_STD(id) \
65 ((uint32_t)((((uint32_t)(id)) & CAN_ID_STD_MASK) >> CAN_ID_STD_SHIFT))
66 #define FLEXCAN_ID_TO_CAN_ID_EXT(id) \
67 ((uint32_t)((((uint32_t)(id)) & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK)) \
68 >> CAN_ID_EXT_SHIFT))
69
70 struct mcux_flexcan_config {
71 const struct can_driver_config common;
72 CAN_Type *base;
73 const struct device *clock_dev;
74 clock_control_subsys_t clock_subsys;
75 int clk_source;
76 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
77 bool flexcan_fd;
78 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
79 void (*irq_config_func)(const struct device *dev);
80 void (*irq_enable_func)(void);
81 void (*irq_disable_func)(void);
82 const struct pinctrl_dev_config *pincfg;
83 };
84
85 struct mcux_flexcan_rx_callback {
86 flexcan_rx_mb_config_t mb_config;
87 union {
88 flexcan_frame_t classic;
89 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
90 flexcan_fd_frame_t fd;
91 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
92 } frame;
93 can_rx_callback_t function;
94 void *arg;
95 };
96
97 struct mcux_flexcan_tx_callback {
98 can_tx_callback_t function;
99 void *arg;
100 };
101
102 struct mcux_flexcan_data {
103 struct can_driver_data common;
104 const struct device *dev;
105 flexcan_handle_t handle;
106
107 ATOMIC_DEFINE(rx_allocs, MCUX_FLEXCAN_MAX_RX);
108 struct k_mutex rx_mutex;
109 struct mcux_flexcan_rx_callback rx_cbs[MCUX_FLEXCAN_MAX_RX];
110
111 ATOMIC_DEFINE(tx_allocs, MCUX_FLEXCAN_MAX_TX);
112 struct k_sem tx_allocs_sem;
113 struct k_mutex tx_mutex;
114 struct mcux_flexcan_tx_callback tx_cbs[MCUX_FLEXCAN_MAX_TX];
115 enum can_state state;
116 struct can_timing timing;
117 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
118 struct can_timing timing_data;
119 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
120 };
121
mcux_flexcan_get_core_clock(const struct device * dev,uint32_t * rate)122 static int mcux_flexcan_get_core_clock(const struct device *dev, uint32_t *rate)
123 {
124 const struct mcux_flexcan_config *config = dev->config;
125
126 return clock_control_get_rate(config->clock_dev, config->clock_subsys, rate);
127 }
128
mcux_flexcan_get_max_filters(const struct device * dev,bool ide)129 static int mcux_flexcan_get_max_filters(const struct device *dev, bool ide)
130 {
131 ARG_UNUSED(ide);
132
133 return CONFIG_CAN_MAX_FILTER;
134 }
135
mcux_flexcan_set_timing(const struct device * dev,const struct can_timing * timing)136 static int mcux_flexcan_set_timing(const struct device *dev,
137 const struct can_timing *timing)
138 {
139 struct mcux_flexcan_data *data = dev->data;
140
141 if (!timing) {
142 return -EINVAL;
143 }
144
145 if (data->common.started) {
146 return -EBUSY;
147 }
148
149 data->timing = *timing;
150
151 return 0;
152 }
153
154 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
mcux_flexcan_set_timing_data(const struct device * dev,const struct can_timing * timing_data)155 static int mcux_flexcan_set_timing_data(const struct device *dev,
156 const struct can_timing *timing_data)
157 {
158 struct mcux_flexcan_data *data = dev->data;
159
160 if (!timing_data) {
161 return -EINVAL;
162 }
163
164 if (data->common.started) {
165 return -EBUSY;
166 }
167
168 data->timing_data = *timing_data;
169
170 return 0;
171 }
172 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
173
mcux_flexcan_get_capabilities(const struct device * dev,can_mode_t * cap)174 static int mcux_flexcan_get_capabilities(const struct device *dev, can_mode_t *cap)
175 {
176 __maybe_unused const struct mcux_flexcan_config *config = dev->config;
177
178 *cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_3_SAMPLES;
179
180 if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
181 *cap |= CAN_MODE_MANUAL_RECOVERY;
182 }
183
184 if (UTIL_AND(IS_ENABLED(CONFIG_CAN_MCUX_FLEXCAN_FD), config->flexcan_fd)) {
185 *cap |= CAN_MODE_FD;
186 }
187
188 return 0;
189 }
190
mcux_flexcan_mb_start(const struct device * dev,int alloc)191 static status_t mcux_flexcan_mb_start(const struct device *dev, int alloc)
192 {
193 const struct mcux_flexcan_config *config = dev->config;
194 struct mcux_flexcan_data *data = dev->data;
195 flexcan_mb_transfer_t xfer;
196 status_t status;
197
198 __ASSERT_NO_MSG(alloc >= 0 && alloc < ARRAY_SIZE(data->rx_cbs));
199
200 xfer.mbIdx = ALLOC_IDX_TO_RXMB_IDX(alloc);
201
202 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
203 if ((data->common.mode & CAN_MODE_FD) != 0U) {
204 xfer.framefd = &data->rx_cbs[alloc].frame.fd;
205 FLEXCAN_SetFDRxMbConfig(config->base, ALLOC_IDX_TO_RXMB_IDX(alloc),
206 &data->rx_cbs[alloc].mb_config, true);
207 status = FLEXCAN_TransferFDReceiveNonBlocking(config->base, &data->handle, &xfer);
208 } else {
209 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
210 xfer.frame = &data->rx_cbs[alloc].frame.classic;
211 FLEXCAN_SetRxMbConfig(config->base, ALLOC_IDX_TO_RXMB_IDX(alloc),
212 &data->rx_cbs[alloc].mb_config, true);
213 status = FLEXCAN_TransferReceiveNonBlocking(config->base, &data->handle, &xfer);
214 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
215 }
216 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
217
218 return status;
219 }
220
mcux_flexcan_mb_stop(const struct device * dev,int alloc)221 static void mcux_flexcan_mb_stop(const struct device *dev, int alloc)
222 {
223 const struct mcux_flexcan_config *config = dev->config;
224 struct mcux_flexcan_data *data = dev->data;
225
226 __ASSERT_NO_MSG(alloc >= 0 && alloc < ARRAY_SIZE(data->rx_cbs));
227
228 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
229 if ((data->common.mode & CAN_MODE_FD) != 0U) {
230 FLEXCAN_TransferFDAbortReceive(config->base, &data->handle,
231 ALLOC_IDX_TO_RXMB_IDX(alloc));
232 FLEXCAN_SetFDRxMbConfig(config->base, ALLOC_IDX_TO_RXMB_IDX(alloc),
233 NULL, false);
234 } else {
235 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
236 FLEXCAN_TransferAbortReceive(config->base, &data->handle,
237 ALLOC_IDX_TO_RXMB_IDX(alloc));
238 FLEXCAN_SetRxMbConfig(config->base, ALLOC_IDX_TO_RXMB_IDX(alloc),
239 NULL, false);
240 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
241 }
242 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
243 }
244
mcux_flexcan_start(const struct device * dev)245 static int mcux_flexcan_start(const struct device *dev)
246 {
247 const struct mcux_flexcan_config *config = dev->config;
248 struct mcux_flexcan_data *data = dev->data;
249 flexcan_timing_config_t timing;
250 int err;
251
252 if (data->common.started) {
253 return -EALREADY;
254 }
255
256 if (config->common.phy != NULL) {
257 err = can_transceiver_enable(config->common.phy, data->common.mode);
258 if (err != 0) {
259 LOG_ERR("failed to enable CAN transceiver (err %d)", err);
260 return err;
261 }
262 }
263
264 /* Reset statistics and clear error counters */
265 CAN_STATS_RESET(dev);
266 config->base->ECR &= ~(CAN_ECR_TXERRCNT_MASK | CAN_ECR_RXERRCNT_MASK);
267
268 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
269 status_t status;
270 int alloc;
271
272 if (config->flexcan_fd) {
273 /* Re-add all RX filters using current mode */
274 k_mutex_lock(&data->rx_mutex, K_FOREVER);
275
276 for (alloc = RX_START_IDX; alloc < MCUX_FLEXCAN_MAX_RX; alloc++) {
277 if (atomic_test_bit(data->rx_allocs, alloc)) {
278 status = mcux_flexcan_mb_start(dev, alloc);
279 if (status != kStatus_Success) {
280 LOG_ERR("Failed to re-add rx filter id %d (err = %d)",
281 alloc, status);
282 k_mutex_unlock(&data->rx_mutex);
283 return -EIO;
284 }
285 }
286 }
287
288 k_mutex_unlock(&data->rx_mutex);
289 }
290 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
291
292 /* Delay this until start since setting the timing automatically exits freeze mode */
293 timing.preDivider = data->timing.prescaler - 1U;
294 timing.rJumpwidth = data->timing.sjw - 1U;
295 timing.phaseSeg1 = data->timing.phase_seg1 - 1U;
296 timing.phaseSeg2 = data->timing.phase_seg2 - 1U;
297 timing.propSeg = data->timing.prop_seg - 1U;
298 FLEXCAN_SetTimingConfig(config->base, &timing);
299
300 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
301 if (config->flexcan_fd) {
302 timing.fpreDivider = data->timing_data.prescaler - 1U;
303 timing.frJumpwidth = data->timing_data.sjw - 1U;
304 timing.fphaseSeg1 = data->timing_data.phase_seg1 - 1U;
305 timing.fphaseSeg2 = data->timing_data.phase_seg2 - 1U;
306 timing.fpropSeg = data->timing_data.prop_seg;
307 FLEXCAN_SetFDTimingConfig(config->base, &timing);
308
309 FLEXCAN_EnterFreezeMode(config->base);
310 config->base->FDCTRL &= ~(CAN_FDCTRL_TDCOFF_MASK);
311 config->base->FDCTRL |= FIELD_PREP(CAN_FDCTRL_TDCOFF_MASK,
312 CAN_CALC_TDCO((&data->timing_data), 1U, 31U));
313 FLEXCAN_ExitFreezeMode(config->base);
314 }
315 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
316
317 data->common.started = true;
318
319 return 0;
320 }
321
mcux_flexcan_stop(const struct device * dev)322 static int mcux_flexcan_stop(const struct device *dev)
323 {
324 const struct mcux_flexcan_config *config = dev->config;
325 struct mcux_flexcan_data *data = dev->data;
326 can_tx_callback_t function;
327 void *arg;
328 int alloc;
329 int err;
330
331 if (!data->common.started) {
332 return -EALREADY;
333 }
334
335 data->common.started = false;
336
337 /* Abort any pending TX frames before entering freeze mode */
338 for (alloc = 0; alloc < MCUX_FLEXCAN_MAX_TX; alloc++) {
339 function = data->tx_cbs[alloc].function;
340 arg = data->tx_cbs[alloc].arg;
341
342 if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
343 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
344 if ((data->common.mode & CAN_MODE_FD) != 0U) {
345 FLEXCAN_TransferFDAbortSend(config->base, &data->handle,
346 ALLOC_IDX_TO_TXMB_IDX(alloc));
347 } else {
348 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
349 FLEXCAN_TransferAbortSend(config->base, &data->handle,
350 ALLOC_IDX_TO_TXMB_IDX(alloc));
351 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
352 }
353 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
354
355 function(dev, -ENETDOWN, arg);
356 k_sem_give(&data->tx_allocs_sem);
357 }
358 }
359
360 FLEXCAN_EnterFreezeMode(config->base);
361
362 if (UTIL_AND(IS_ENABLED(CONFIG_CAN_MCUX_FLEXCAN_FD), config->flexcan_fd)) {
363 /*
364 * Remove all RX filters and re-add them in start() since the mode may change
365 * between stop()/start().
366 */
367 k_mutex_lock(&data->rx_mutex, K_FOREVER);
368
369 for (alloc = RX_START_IDX; alloc < MCUX_FLEXCAN_MAX_RX; alloc++) {
370 if (atomic_test_bit(data->rx_allocs, alloc)) {
371 mcux_flexcan_mb_stop(dev, alloc);
372 }
373 }
374
375 k_mutex_unlock(&data->rx_mutex);
376 }
377
378 if (config->common.phy != NULL) {
379 err = can_transceiver_disable(config->common.phy);
380 if (err != 0) {
381 LOG_ERR("failed to disable CAN transceiver (err %d)", err);
382 return err;
383 }
384 }
385
386 return 0;
387 }
388
mcux_flexcan_set_mode(const struct device * dev,can_mode_t mode)389 static int mcux_flexcan_set_mode(const struct device *dev, can_mode_t mode)
390 {
391 can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_3_SAMPLES;
392 const struct mcux_flexcan_config *config = dev->config;
393 struct mcux_flexcan_data *data = dev->data;
394 uint32_t ctrl1;
395 uint32_t mcr;
396
397 if (data->common.started) {
398 return -EBUSY;
399 }
400
401 if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
402 supported |= CAN_MODE_MANUAL_RECOVERY;
403 }
404
405 if (UTIL_AND(IS_ENABLED(CONFIG_CAN_MCUX_FLEXCAN_FD), config->flexcan_fd)) {
406 supported |= CAN_MODE_FD;
407 }
408
409 if ((mode & ~(supported)) != 0) {
410 LOG_ERR("unsupported mode: 0x%08x", mode);
411 return -ENOTSUP;
412 }
413
414 if ((mode & CAN_MODE_FD) != 0 && (mode & CAN_MODE_3_SAMPLES) != 0) {
415 LOG_ERR("triple samling is not supported in CAN FD mode");
416 return -ENOTSUP;
417 }
418
419 ctrl1 = config->base->CTRL1;
420 mcr = config->base->MCR;
421
422 if ((mode & CAN_MODE_LOOPBACK) != 0) {
423 /* Enable loopback and self-reception */
424 ctrl1 |= CAN_CTRL1_LPB_MASK;
425 mcr &= ~(CAN_MCR_SRXDIS_MASK);
426 } else {
427 /* Disable loopback and self-reception */
428 ctrl1 &= ~(CAN_CTRL1_LPB_MASK);
429 mcr |= CAN_MCR_SRXDIS_MASK;
430 }
431
432 if ((mode & CAN_MODE_LISTENONLY) != 0) {
433 /* Enable listen-only mode */
434 ctrl1 |= CAN_CTRL1_LOM_MASK;
435 } else {
436 /* Disable listen-only mode */
437 ctrl1 &= ~(CAN_CTRL1_LOM_MASK);
438 }
439
440 if ((mode & CAN_MODE_3_SAMPLES) != 0) {
441 /* Enable triple sampling mode */
442 ctrl1 |= CAN_CTRL1_SMP_MASK;
443 } else {
444 /* Disable triple sampling mode */
445 ctrl1 &= ~(CAN_CTRL1_SMP_MASK);
446 }
447
448 if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
449 if ((mode & CAN_MODE_MANUAL_RECOVERY) != 0) {
450 /* Disable auto-recovery from bus-off */
451 ctrl1 |= CAN_CTRL1_BOFFREC_MASK;
452 } else {
453 /* Enable auto-recovery from bus-off */
454 ctrl1 &= ~(CAN_CTRL1_BOFFREC_MASK);
455 }
456 }
457
458 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
459 if (config->flexcan_fd) {
460 if ((mode & CAN_MODE_FD) != 0) {
461 /* Enable CAN FD mode */
462 mcr |= CAN_MCR_FDEN_MASK;
463
464 /* Transceiver Delay Compensation must be disabled in loopback mode */
465 if ((mode & CAN_MODE_LOOPBACK) != 0) {
466 config->base->FDCTRL &= ~(CAN_FDCTRL_TDCEN_MASK);
467 } else {
468 config->base->FDCTRL |= CAN_FDCTRL_TDCEN_MASK;
469 }
470 } else {
471 /* Disable CAN FD mode */
472 mcr &= ~(CAN_MCR_FDEN_MASK);
473 }
474 }
475 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
476
477 config->base->CTRL1 = ctrl1;
478 config->base->MCR = mcr;
479
480 data->common.mode = mode;
481
482 return 0;
483 }
484
mcux_flexcan_from_can_frame(const struct can_frame * src,flexcan_frame_t * dest)485 static void mcux_flexcan_from_can_frame(const struct can_frame *src,
486 flexcan_frame_t *dest)
487 {
488 memset(dest, 0, sizeof(*dest));
489
490 if ((src->flags & CAN_FRAME_IDE) != 0) {
491 dest->format = kFLEXCAN_FrameFormatExtend;
492 dest->id = FLEXCAN_ID_EXT(src->id);
493 } else {
494 dest->format = kFLEXCAN_FrameFormatStandard;
495 dest->id = FLEXCAN_ID_STD(src->id);
496 }
497
498 if ((src->flags & CAN_FRAME_RTR) != 0) {
499 dest->type = kFLEXCAN_FrameTypeRemote;
500 } else {
501 dest->type = kFLEXCAN_FrameTypeData;
502 dest->dataWord0 = sys_cpu_to_be32(src->data_32[0]);
503 dest->dataWord1 = sys_cpu_to_be32(src->data_32[1]);
504 }
505
506 dest->length = src->dlc;
507 }
508
mcux_flexcan_to_can_frame(const flexcan_frame_t * src,struct can_frame * dest)509 static void mcux_flexcan_to_can_frame(const flexcan_frame_t *src,
510 struct can_frame *dest)
511 {
512 memset(dest, 0, sizeof(*dest));
513
514 if (src->format == kFLEXCAN_FrameFormatStandard) {
515 dest->id = FLEXCAN_ID_TO_CAN_ID_STD(src->id);
516 } else {
517 dest->flags |= CAN_FRAME_IDE;
518 dest->id = FLEXCAN_ID_TO_CAN_ID_EXT(src->id);
519 }
520
521 if (src->type == kFLEXCAN_FrameTypeRemote) {
522 dest->flags |= CAN_FRAME_RTR;
523 } else {
524 dest->data_32[0] = sys_be32_to_cpu(src->dataWord0);
525 dest->data_32[1] = sys_be32_to_cpu(src->dataWord1);
526 }
527
528 dest->dlc = src->length;
529 #ifdef CONFIG_CAN_RX_TIMESTAMP
530 dest->timestamp = src->timestamp;
531 #endif /* CAN_RX_TIMESTAMP */
532 }
533
534 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
mcux_flexcan_fd_from_can_frame(const struct can_frame * src,flexcan_fd_frame_t * dest)535 static void mcux_flexcan_fd_from_can_frame(const struct can_frame *src,
536 flexcan_fd_frame_t *dest)
537 {
538 int i;
539
540 memset(dest, 0, sizeof(*dest));
541
542 if ((src->flags & CAN_FRAME_IDE) != 0) {
543 dest->format = kFLEXCAN_FrameFormatExtend;
544 dest->id = FLEXCAN_ID_EXT(src->id);
545 } else {
546 dest->format = kFLEXCAN_FrameFormatStandard;
547 dest->id = FLEXCAN_ID_STD(src->id);
548 }
549
550 if ((src->flags & CAN_FRAME_RTR) != 0) {
551 dest->type = kFLEXCAN_FrameTypeRemote;
552 } else {
553 dest->type = kFLEXCAN_FrameTypeData;
554
555 for (i = 0; i < ARRAY_SIZE(dest->dataWord); i++) {
556 dest->dataWord[i] = sys_cpu_to_be32(src->data_32[i]);
557 }
558 }
559
560 if ((src->flags & CAN_FRAME_FDF) != 0) {
561 dest->edl = 1;
562 }
563
564 if ((src->flags & CAN_FRAME_BRS) != 0) {
565 dest->brs = 1;
566 }
567
568 dest->length = src->dlc;
569 }
570
mcux_flexcan_fd_to_can_frame(const flexcan_fd_frame_t * src,struct can_frame * dest)571 static void mcux_flexcan_fd_to_can_frame(const flexcan_fd_frame_t *src,
572 struct can_frame *dest)
573 {
574 int i;
575
576 memset(dest, 0, sizeof(*dest));
577
578 if (src->format == kFLEXCAN_FrameFormatStandard) {
579 dest->id = FLEXCAN_ID_TO_CAN_ID_STD(src->id);
580 } else {
581 dest->flags |= CAN_FRAME_IDE;
582 dest->id = FLEXCAN_ID_TO_CAN_ID_EXT(src->id);
583 }
584
585 if (src->type == kFLEXCAN_FrameTypeRemote) {
586 dest->flags |= CAN_FRAME_RTR;
587 } else {
588 for (i = 0; i < ARRAY_SIZE(dest->data_32); i++) {
589 dest->data_32[i] = sys_be32_to_cpu(src->dataWord[i]);
590 }
591 }
592
593 if (src->edl != 0) {
594 dest->flags |= CAN_FRAME_FDF;
595 }
596
597 if (src->brs != 0) {
598 dest->flags |= CAN_FRAME_BRS;
599 }
600
601 if (src->esi != 0) {
602 dest->flags |= CAN_FRAME_ESI;
603 }
604
605 dest->dlc = src->length;
606
607 #ifdef CONFIG_CAN_RX_TIMESTAMP
608 dest->timestamp = src->timestamp;
609 #endif /* CAN_RX_TIMESTAMP */
610 }
611 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
612
mcux_flexcan_can_filter_to_mbconfig(const struct can_filter * src,flexcan_rx_mb_config_t * dest,uint32_t * mask)613 static void mcux_flexcan_can_filter_to_mbconfig(const struct can_filter *src,
614 flexcan_rx_mb_config_t *dest,
615 uint32_t *mask)
616 {
617 static const uint32_t ide_mask = 1U;
618 static const uint32_t rtr_mask = !IS_ENABLED(CONFIG_CAN_ACCEPT_RTR);
619
620 if ((src->flags & CAN_FILTER_IDE) != 0) {
621 dest->format = kFLEXCAN_FrameFormatExtend;
622 dest->id = FLEXCAN_ID_EXT(src->id);
623 *mask = FLEXCAN_RX_MB_EXT_MASK(src->mask, rtr_mask, ide_mask);
624 } else {
625 dest->format = kFLEXCAN_FrameFormatStandard;
626 dest->id = FLEXCAN_ID_STD(src->id);
627 *mask = FLEXCAN_RX_MB_STD_MASK(src->mask, rtr_mask, ide_mask);
628 }
629
630 dest->type = kFLEXCAN_FrameTypeData;
631 }
632
mcux_flexcan_get_state(const struct device * dev,enum can_state * state,struct can_bus_err_cnt * err_cnt)633 static int mcux_flexcan_get_state(const struct device *dev, enum can_state *state,
634 struct can_bus_err_cnt *err_cnt)
635 {
636 const struct mcux_flexcan_config *config = dev->config;
637 struct mcux_flexcan_data *data = dev->data;
638 uint64_t status_flags;
639
640 if (state != NULL) {
641 if (!data->common.started) {
642 *state = CAN_STATE_STOPPED;
643 } else {
644 status_flags = FLEXCAN_GetStatusFlags(config->base);
645
646 if ((status_flags & CAN_ESR1_FLTCONF(2)) != 0U) {
647 *state = CAN_STATE_BUS_OFF;
648 } else if ((status_flags & CAN_ESR1_FLTCONF(1)) != 0U) {
649 *state = CAN_STATE_ERROR_PASSIVE;
650 } else if ((status_flags &
651 (kFLEXCAN_TxErrorWarningFlag | kFLEXCAN_RxErrorWarningFlag)) != 0) {
652 *state = CAN_STATE_ERROR_WARNING;
653 } else {
654 *state = CAN_STATE_ERROR_ACTIVE;
655 }
656 }
657 }
658
659 if (err_cnt != NULL) {
660 FLEXCAN_GetBusErrCount(config->base, &err_cnt->tx_err_cnt,
661 &err_cnt->rx_err_cnt);
662 }
663
664 return 0;
665 }
666
mcux_flexcan_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)667 static int mcux_flexcan_send(const struct device *dev,
668 const struct can_frame *frame,
669 k_timeout_t timeout,
670 can_tx_callback_t callback, void *user_data)
671 {
672 const struct mcux_flexcan_config *config = dev->config;
673 struct mcux_flexcan_data *data = dev->data;
674 flexcan_mb_transfer_t xfer;
675 enum can_state state;
676 status_t status = kStatus_Fail;
677 uint8_t max_dlc = CAN_MAX_DLC;
678 int alloc;
679
680 if (UTIL_AND(IS_ENABLED(CONFIG_CAN_MCUX_FLEXCAN_FD),
681 ((data->common.mode & CAN_MODE_FD) != 0U))) {
682 if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR |
683 CAN_FRAME_FDF | CAN_FRAME_BRS)) != 0) {
684 LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
685 return -ENOTSUP;
686 }
687
688 if ((frame->flags & CAN_FRAME_FDF) != 0) {
689 max_dlc = CANFD_MAX_DLC;
690 }
691 } else {
692 if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_RTR)) != 0) {
693 LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
694 return -ENOTSUP;
695 }
696 }
697
698 if (frame->dlc > max_dlc) {
699 LOG_ERR("DLC of %d exceeds maximum (%d)", frame->dlc, max_dlc);
700 return -EINVAL;
701 }
702
703 if (!data->common.started) {
704 return -ENETDOWN;
705 }
706
707 (void)mcux_flexcan_get_state(dev, &state, NULL);
708 if (state == CAN_STATE_BUS_OFF) {
709 LOG_DBG("Transmit failed, bus-off");
710 return -ENETUNREACH;
711 }
712
713 if (k_sem_take(&data->tx_allocs_sem, timeout) != 0) {
714 return -EAGAIN;
715 }
716
717 for (alloc = 0; alloc < MCUX_FLEXCAN_MAX_TX; alloc++) {
718 if (!atomic_test_and_set_bit(data->tx_allocs, alloc)) {
719 break;
720 }
721 }
722
723 data->tx_cbs[alloc].function = callback;
724 data->tx_cbs[alloc].arg = user_data;
725 xfer.mbIdx = ALLOC_IDX_TO_TXMB_IDX(alloc);
726
727 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
728 if ((data->common.mode & CAN_MODE_FD) != 0U) {
729 FLEXCAN_SetFDTxMbConfig(config->base, xfer.mbIdx, true);
730 } else {
731 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
732 FLEXCAN_SetTxMbConfig(config->base, xfer.mbIdx, true);
733 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
734 }
735 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
736
737 k_mutex_lock(&data->tx_mutex, K_FOREVER);
738 config->irq_disable_func();
739
740 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
741 if ((data->common.mode & CAN_MODE_FD) != 0U) {
742 flexcan_fd_frame_t flexcan_frame;
743
744 mcux_flexcan_fd_from_can_frame(frame, &flexcan_frame);
745 xfer.framefd = &flexcan_frame;
746 status = FLEXCAN_TransferFDSendNonBlocking(config->base, &data->handle, &xfer);
747 } else {
748 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
749 flexcan_frame_t flexcan_frame;
750
751 mcux_flexcan_from_can_frame(frame, &flexcan_frame);
752 xfer.frame = &flexcan_frame;
753 status = FLEXCAN_TransferSendNonBlocking(config->base, &data->handle, &xfer);
754 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
755 }
756 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
757
758 config->irq_enable_func();
759 k_mutex_unlock(&data->tx_mutex);
760 if (status != kStatus_Success) {
761 return -EIO;
762 }
763
764 return 0;
765 }
766
mcux_flexcan_add_rx_filter(const struct device * dev,can_rx_callback_t callback,void * user_data,const struct can_filter * filter)767 static int mcux_flexcan_add_rx_filter(const struct device *dev,
768 can_rx_callback_t callback,
769 void *user_data,
770 const struct can_filter *filter)
771 {
772 const struct mcux_flexcan_config *config = dev->config;
773 struct mcux_flexcan_data *data = dev->data;
774 status_t status;
775 uint32_t mask;
776 int alloc = -ENOSPC;
777 int i;
778
779 if ((filter->flags & ~(CAN_FILTER_IDE)) != 0) {
780 LOG_ERR("unsupported CAN filter flags 0x%02x", filter->flags);
781 return -ENOTSUP;
782 }
783
784 k_mutex_lock(&data->rx_mutex, K_FOREVER);
785
786 /* Find and allocate RX message buffer */
787 for (i = RX_START_IDX; i < MCUX_FLEXCAN_MAX_RX; i++) {
788 if (!atomic_test_and_set_bit(data->rx_allocs, i)) {
789 alloc = i;
790 break;
791 }
792 }
793
794 if (alloc == -ENOSPC) {
795 goto unlock;
796 }
797
798 mcux_flexcan_can_filter_to_mbconfig(filter, &data->rx_cbs[alloc].mb_config,
799 &mask);
800
801 data->rx_cbs[alloc].arg = user_data;
802 data->rx_cbs[alloc].function = callback;
803
804 /* The indidual RX mask registers can only be written in freeze mode */
805 FLEXCAN_EnterFreezeMode(config->base);
806 config->base->RXIMR[ALLOC_IDX_TO_RXMB_IDX(alloc)] = mask;
807
808 if (data->common.started) {
809 FLEXCAN_ExitFreezeMode(config->base);
810 }
811
812 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
813 /* Defer starting FlexCAN FD MBs unless started */
814 if (!config->flexcan_fd || data->common.started) {
815 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
816 status = mcux_flexcan_mb_start(dev, alloc);
817 if (status != kStatus_Success) {
818 LOG_ERR("Failed to start rx for filter id %d (err = %d)",
819 alloc, status);
820 alloc = -ENOSPC;
821 }
822 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
823 }
824 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
825
826 unlock:
827 k_mutex_unlock(&data->rx_mutex);
828
829 return alloc;
830 }
831
mcux_flexcan_set_state_change_callback(const struct device * dev,can_state_change_callback_t callback,void * user_data)832 static void mcux_flexcan_set_state_change_callback(const struct device *dev,
833 can_state_change_callback_t callback,
834 void *user_data)
835 {
836 struct mcux_flexcan_data *data = dev->data;
837
838 data->common.state_change_cb = callback;
839 data->common.state_change_cb_user_data = user_data;
840 }
841
842 #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
mcux_flexcan_recover(const struct device * dev,k_timeout_t timeout)843 static int mcux_flexcan_recover(const struct device *dev, k_timeout_t timeout)
844 {
845 const struct mcux_flexcan_config *config = dev->config;
846 struct mcux_flexcan_data *data = dev->data;
847 enum can_state state;
848 uint64_t start_time;
849 int ret = 0;
850
851 if (!data->common.started) {
852 return -ENETDOWN;
853 }
854
855 if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
856 return -ENOTSUP;
857 }
858
859 (void)mcux_flexcan_get_state(dev, &state, NULL);
860 if (state != CAN_STATE_BUS_OFF) {
861 return 0;
862 }
863
864 start_time = k_uptime_ticks();
865 config->base->CTRL1 &= ~CAN_CTRL1_BOFFREC_MASK;
866
867 if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
868 (void)mcux_flexcan_get_state(dev, &state, NULL);
869
870 while (state == CAN_STATE_BUS_OFF) {
871 if (!K_TIMEOUT_EQ(timeout, K_FOREVER) &&
872 k_uptime_ticks() - start_time >= timeout.ticks) {
873 ret = -EAGAIN;
874 }
875
876 (void)mcux_flexcan_get_state(dev, &state, NULL);
877 }
878 }
879
880 config->base->CTRL1 |= CAN_CTRL1_BOFFREC_MASK;
881
882 return ret;
883 }
884 #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
885
mcux_flexcan_remove_rx_filter(const struct device * dev,int filter_id)886 static void mcux_flexcan_remove_rx_filter(const struct device *dev, int filter_id)
887 {
888 struct mcux_flexcan_data *data = dev->data;
889
890 if (filter_id < 0 || filter_id >= MCUX_FLEXCAN_MAX_RX) {
891 LOG_ERR("filter ID %d out of bounds", filter_id);
892 return;
893 }
894
895 k_mutex_lock(&data->rx_mutex, K_FOREVER);
896
897 if (atomic_test_and_clear_bit(data->rx_allocs, filter_id)) {
898 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
899 const struct mcux_flexcan_config *config = dev->config;
900
901 /* Stop FlexCAN FD MBs unless already in stopped mode */
902 if (!config->flexcan_fd || data->common.started) {
903 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
904 mcux_flexcan_mb_stop(dev, filter_id);
905 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
906 }
907 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
908
909 data->rx_cbs[filter_id].function = NULL;
910 data->rx_cbs[filter_id].arg = NULL;
911 } else {
912 LOG_WRN("Filter ID %d already detached", filter_id);
913 }
914
915 k_mutex_unlock(&data->rx_mutex);
916 }
917
mcux_flexcan_transfer_error_status(const struct device * dev,uint64_t error)918 static inline void mcux_flexcan_transfer_error_status(const struct device *dev,
919 uint64_t error)
920 {
921 const struct mcux_flexcan_config *config = dev->config;
922 struct mcux_flexcan_data *data = dev->data;
923 const can_state_change_callback_t cb = data->common.state_change_cb;
924 void *cb_data = data->common.state_change_cb_user_data;
925 can_tx_callback_t function;
926 void *arg;
927 int alloc;
928 enum can_state state;
929 struct can_bus_err_cnt err_cnt;
930
931 if ((error & kFLEXCAN_Bit0Error) != 0U) {
932 CAN_STATS_BIT0_ERROR_INC(dev);
933 }
934
935 if ((error & kFLEXCAN_Bit1Error) != 0U) {
936 CAN_STATS_BIT1_ERROR_INC(dev);
937 }
938
939 if ((error & kFLEXCAN_AckError) != 0U) {
940 CAN_STATS_ACK_ERROR_INC(dev);
941 }
942
943 if ((error & kFLEXCAN_StuffingError) != 0U) {
944 CAN_STATS_STUFF_ERROR_INC(dev);
945 }
946
947 if ((error & kFLEXCAN_FormError) != 0U) {
948 CAN_STATS_FORM_ERROR_INC(dev);
949 }
950
951 if ((error & kFLEXCAN_CrcError) != 0U) {
952 CAN_STATS_CRC_ERROR_INC(dev);
953 }
954
955 (void)mcux_flexcan_get_state(dev, &state, &err_cnt);
956 if (data->state != state) {
957 data->state = state;
958
959 if (cb != NULL) {
960 cb(dev, state, err_cnt, cb_data);
961 }
962 }
963
964 if (state == CAN_STATE_BUS_OFF) {
965 /* Abort any pending TX frames in case of bus-off */
966 for (alloc = 0; alloc < MCUX_FLEXCAN_MAX_TX; alloc++) {
967 /* Copy callback function and argument before clearing bit */
968 function = data->tx_cbs[alloc].function;
969 arg = data->tx_cbs[alloc].arg;
970
971 if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
972 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
973 if ((data->common.mode & CAN_MODE_FD) != 0U) {
974 FLEXCAN_TransferFDAbortSend(config->base, &data->handle,
975 ALLOC_IDX_TO_TXMB_IDX(alloc));
976 } else {
977 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
978 FLEXCAN_TransferAbortSend(config->base, &data->handle,
979 ALLOC_IDX_TO_TXMB_IDX(alloc));
980 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
981 }
982 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
983
984 function(dev, -ENETUNREACH, arg);
985 k_sem_give(&data->tx_allocs_sem);
986 }
987 }
988 }
989 }
990
mcux_flexcan_transfer_tx_idle(const struct device * dev,uint32_t mb)991 static inline void mcux_flexcan_transfer_tx_idle(const struct device *dev,
992 uint32_t mb)
993 {
994 struct mcux_flexcan_data *data = dev->data;
995 can_tx_callback_t function;
996 void *arg;
997 int alloc;
998
999 alloc = TX_MBIDX_TO_ALLOC_IDX(mb);
1000
1001 /* Copy callback function and argument before clearing bit */
1002 function = data->tx_cbs[alloc].function;
1003 arg = data->tx_cbs[alloc].arg;
1004
1005 if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
1006 function(dev, 0, arg);
1007 k_sem_give(&data->tx_allocs_sem);
1008 }
1009 }
1010
mcux_flexcan_transfer_rx_idle(const struct device * dev,uint32_t mb)1011 static inline void mcux_flexcan_transfer_rx_idle(const struct device *dev,
1012 uint32_t mb)
1013 {
1014 const struct mcux_flexcan_config *config = dev->config;
1015 struct mcux_flexcan_data *data = dev->data;
1016 can_rx_callback_t function;
1017 flexcan_mb_transfer_t xfer;
1018 struct can_frame frame;
1019 status_t status = kStatus_Fail;
1020 void *arg;
1021 int alloc;
1022
1023 alloc = RX_MBIDX_TO_ALLOC_IDX(mb);
1024 function = data->rx_cbs[alloc].function;
1025 arg = data->rx_cbs[alloc].arg;
1026
1027 if (atomic_test_bit(data->rx_allocs, alloc)) {
1028 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1029 if ((data->common.mode & CAN_MODE_FD) != 0U) {
1030 mcux_flexcan_fd_to_can_frame(&data->rx_cbs[alloc].frame.fd, &frame);
1031 } else {
1032 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1033 mcux_flexcan_to_can_frame(&data->rx_cbs[alloc].frame.classic, &frame);
1034 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1035 }
1036 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1037 function(dev, &frame, arg);
1038
1039 /* Setup RX message buffer to receive next message */
1040 xfer.mbIdx = mb;
1041 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1042 if ((data->common.mode & CAN_MODE_FD) != 0U) {
1043 xfer.framefd = &data->rx_cbs[alloc].frame.fd;
1044 status = FLEXCAN_TransferFDReceiveNonBlocking(config->base,
1045 &data->handle,
1046 &xfer);
1047 } else {
1048 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1049 xfer.frame = &data->rx_cbs[alloc].frame.classic;
1050 status = FLEXCAN_TransferReceiveNonBlocking(config->base,
1051 &data->handle,
1052 &xfer);
1053 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1054 }
1055 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1056
1057 if (status != kStatus_Success) {
1058 LOG_ERR("Failed to restart rx for filter id %d "
1059 "(err = %d)", alloc, status);
1060 }
1061 }
1062 }
1063
FLEXCAN_CALLBACK(mcux_flexcan_transfer_callback)1064 static FLEXCAN_CALLBACK(mcux_flexcan_transfer_callback)
1065 {
1066 struct mcux_flexcan_data *data = (struct mcux_flexcan_data *)userData;
1067 const struct mcux_flexcan_config *config = data->dev->config;
1068 /*
1069 * The result field can either be a MB index (which is limited to 32 bit
1070 * value) or a status flags value, which is 32 bit on some platforms but
1071 * 64 on others. To decouple the remaining functions from this, the
1072 * result field is always promoted to uint64_t.
1073 */
1074 uint32_t mb = (uint32_t)result;
1075 uint64_t status_flags = result;
1076
1077 ARG_UNUSED(base);
1078
1079 switch (status) {
1080 case kStatus_FLEXCAN_UnHandled:
1081 /* Not all fault confinement state changes are handled by the HAL */
1082 __fallthrough;
1083 case kStatus_FLEXCAN_ErrorStatus:
1084 mcux_flexcan_transfer_error_status(data->dev, status_flags);
1085 break;
1086 case kStatus_FLEXCAN_TxSwitchToRx:
1087 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1088 if ((data->common.mode & CAN_MODE_FD) != 0U) {
1089 FLEXCAN_TransferFDAbortReceive(config->base, &data->handle, mb);
1090 } else {
1091 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1092 FLEXCAN_TransferAbortReceive(config->base, &data->handle, mb);
1093 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1094 }
1095 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1096 __fallthrough;
1097 case kStatus_FLEXCAN_TxIdle:
1098 mcux_flexcan_transfer_tx_idle(data->dev, mb);
1099 break;
1100 case kStatus_FLEXCAN_RxOverflow:
1101 CAN_STATS_RX_OVERRUN_INC(data->dev);
1102 __fallthrough;
1103 case kStatus_Fail:
1104 /* If reading an RX MB failed mark it as idle to be reprocessed. */
1105 __fallthrough;
1106 case kStatus_FLEXCAN_RxIdle:
1107 mcux_flexcan_transfer_rx_idle(data->dev, mb);
1108 break;
1109 default:
1110 LOG_WRN("Unhandled status 0x%08x (result = 0x%016llx)",
1111 status, status_flags);
1112 }
1113 }
1114
mcux_flexcan_isr(const struct device * dev)1115 static void mcux_flexcan_isr(const struct device *dev)
1116 {
1117 const struct mcux_flexcan_config *config = dev->config;
1118 struct mcux_flexcan_data *data = dev->data;
1119
1120 FLEXCAN_TransferHandleIRQ(config->base, &data->handle);
1121 }
1122
mcux_flexcan_init(const struct device * dev)1123 static int mcux_flexcan_init(const struct device *dev)
1124 {
1125 const struct mcux_flexcan_config *config = dev->config;
1126 struct mcux_flexcan_data *data = dev->data;
1127 flexcan_config_t flexcan_config;
1128 uint32_t clock_freq;
1129 int err;
1130
1131 if (config->common.phy != NULL) {
1132 if (!device_is_ready(config->common.phy)) {
1133 LOG_ERR("CAN transceiver not ready");
1134 return -ENODEV;
1135 }
1136 }
1137
1138 if (!device_is_ready(config->clock_dev)) {
1139 LOG_ERR("clock device not ready");
1140 return -ENODEV;
1141 }
1142
1143 k_mutex_init(&data->rx_mutex);
1144 k_mutex_init(&data->tx_mutex);
1145 k_sem_init(&data->tx_allocs_sem, MCUX_FLEXCAN_MAX_TX,
1146 MCUX_FLEXCAN_MAX_TX);
1147
1148 err = can_calc_timing(dev, &data->timing, config->common.bitrate,
1149 config->common.sample_point);
1150 if (err == -EINVAL) {
1151 LOG_ERR("Can't find timing for given param");
1152 return -EIO;
1153 }
1154 LOG_DBG("Presc: %d, Seg1S1: %d, Seg2: %d",
1155 data->timing.prescaler, data->timing.phase_seg1,
1156 data->timing.phase_seg2);
1157 LOG_DBG("Sample-point err : %d", err);
1158
1159 /* Validate initial timing parameters */
1160 err = can_set_timing(dev, &data->timing);
1161 if (err != 0) {
1162 LOG_ERR("failed to set timing (err %d)", err);
1163 return -ENODEV;
1164 }
1165
1166 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1167 if (config->flexcan_fd) {
1168 err = can_calc_timing_data(dev, &data->timing_data,
1169 config->common.bitrate_data,
1170 config->common.sample_point_data);
1171 if (err == -EINVAL) {
1172 LOG_ERR("Can't find timing for given param");
1173 return -EIO;
1174 }
1175 LOG_DBG("Presc: %d, Seg1S1: %d, Seg2: %d",
1176 data->timing_data.prescaler, data->timing_data.phase_seg1,
1177 data->timing_data.phase_seg2);
1178 LOG_DBG("Sample-point err : %d", err);
1179
1180 /* Validate initial data phase timing parameters */
1181 err = can_set_timing_data(dev, &data->timing_data);
1182 if (err != 0) {
1183 LOG_ERR("failed to set data phase timing (err %d)", err);
1184 return -ENODEV;
1185 }
1186 }
1187 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1188
1189 err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
1190 if (err != 0) {
1191 return err;
1192 }
1193
1194 err = mcux_flexcan_get_core_clock(dev, &clock_freq);
1195 if (err != 0) {
1196 return -EIO;
1197 }
1198
1199 data->dev = dev;
1200
1201 FLEXCAN_GetDefaultConfig(&flexcan_config);
1202 flexcan_config.maxMbNum = MCUX_FLEXCAN_MAX_MB;
1203 flexcan_config.clkSrc = config->clk_source;
1204 flexcan_config.baudRate = clock_freq /
1205 (1U + data->timing.prop_seg + data->timing.phase_seg1 +
1206 data->timing.phase_seg2) / data->timing.prescaler;
1207
1208 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1209 if (config->flexcan_fd) {
1210 flexcan_config.baudRateFD = clock_freq /
1211 (1U + data->timing_data.prop_seg + data->timing_data.phase_seg1 +
1212 data->timing_data.phase_seg2) / data->timing_data.prescaler;
1213 }
1214 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1215
1216 flexcan_config.enableIndividMask = true;
1217 flexcan_config.enableLoopBack = false;
1218 flexcan_config.disableSelfReception = true;
1219 /* Initialize in listen-only mode since FLEXCAN_{FD}Init() exits freeze mode */
1220 flexcan_config.enableListenOnlyMode = true;
1221
1222 flexcan_config.timingConfig.rJumpwidth = data->timing.sjw - 1U;
1223 flexcan_config.timingConfig.propSeg = data->timing.prop_seg - 1U;
1224 flexcan_config.timingConfig.phaseSeg1 = data->timing.phase_seg1 - 1U;
1225 flexcan_config.timingConfig.phaseSeg2 = data->timing.phase_seg2 - 1U;
1226
1227 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1228 if (config->flexcan_fd) {
1229 flexcan_config.timingConfig.frJumpwidth = data->timing_data.sjw - 1U;
1230 flexcan_config.timingConfig.fpropSeg = data->timing_data.prop_seg;
1231 flexcan_config.timingConfig.fphaseSeg1 = data->timing_data.phase_seg1 - 1U;
1232 flexcan_config.timingConfig.fphaseSeg2 = data->timing_data.phase_seg2 - 1U;
1233
1234 FLEXCAN_FDInit(config->base, &flexcan_config, clock_freq, kFLEXCAN_64BperMB, true);
1235 } else {
1236 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1237 FLEXCAN_Init(config->base, &flexcan_config, clock_freq);
1238 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1239 }
1240 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1241
1242 FLEXCAN_TransferCreateHandle(config->base, &data->handle,
1243 mcux_flexcan_transfer_callback, data);
1244
1245 /* Manually enter freeze mode, set normal mode, and clear error counters */
1246 FLEXCAN_EnterFreezeMode(config->base);
1247 (void)mcux_flexcan_set_mode(dev, CAN_MODE_NORMAL);
1248 config->base->ECR &= ~(CAN_ECR_TXERRCNT_MASK | CAN_ECR_RXERRCNT_MASK);
1249
1250 config->irq_config_func(dev);
1251
1252 /* Enable auto-recovery from bus-off */
1253 config->base->CTRL1 &= ~(CAN_CTRL1_BOFFREC_MASK);
1254
1255 (void)mcux_flexcan_get_state(dev, &data->state, NULL);
1256
1257 return 0;
1258 }
1259
1260 static DEVICE_API(can, mcux_flexcan_driver_api) __maybe_unused = {
1261 .get_capabilities = mcux_flexcan_get_capabilities,
1262 .start = mcux_flexcan_start,
1263 .stop = mcux_flexcan_stop,
1264 .set_mode = mcux_flexcan_set_mode,
1265 .set_timing = mcux_flexcan_set_timing,
1266 .send = mcux_flexcan_send,
1267 .add_rx_filter = mcux_flexcan_add_rx_filter,
1268 .remove_rx_filter = mcux_flexcan_remove_rx_filter,
1269 .get_state = mcux_flexcan_get_state,
1270 #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
1271 .recover = mcux_flexcan_recover,
1272 #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
1273 .set_state_change_callback = mcux_flexcan_set_state_change_callback,
1274 .get_core_clock = mcux_flexcan_get_core_clock,
1275 .get_max_filters = mcux_flexcan_get_max_filters,
1276 /*
1277 * FlexCAN timing limits are specified in the "FLEXCANx_CTRL1 field
1278 * descriptions" table in the SoC reference manual.
1279 *
1280 * Note that the values here are the "physical" timing limits, whereas
1281 * the register field limits are physical values minus 1 (which is
1282 * handled by the flexcan_timing_config_t field assignments elsewhere
1283 * in this driver).
1284 */
1285 .timing_min = {
1286 .sjw = 0x01,
1287 .prop_seg = 0x01,
1288 .phase_seg1 = 0x01,
1289 .phase_seg2 = 0x02,
1290 .prescaler = 0x01
1291 },
1292 .timing_max = {
1293 .sjw = 0x04,
1294 .prop_seg = 0x08,
1295 .phase_seg1 = 0x08,
1296 .phase_seg2 = 0x08,
1297 .prescaler = 0x100
1298 }
1299 };
1300
1301 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1302 static DEVICE_API(can, mcux_flexcan_fd_driver_api) = {
1303 .get_capabilities = mcux_flexcan_get_capabilities,
1304 .start = mcux_flexcan_start,
1305 .stop = mcux_flexcan_stop,
1306 .set_mode = mcux_flexcan_set_mode,
1307 .set_timing = mcux_flexcan_set_timing,
1308 .set_timing_data = mcux_flexcan_set_timing_data,
1309 .send = mcux_flexcan_send,
1310 .add_rx_filter = mcux_flexcan_add_rx_filter,
1311 .remove_rx_filter = mcux_flexcan_remove_rx_filter,
1312 .get_state = mcux_flexcan_get_state,
1313 #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
1314 .recover = mcux_flexcan_recover,
1315 #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
1316 .set_state_change_callback = mcux_flexcan_set_state_change_callback,
1317 .get_core_clock = mcux_flexcan_get_core_clock,
1318 .get_max_filters = mcux_flexcan_get_max_filters,
1319 /*
1320 * FlexCAN FD timing limits are specified in the "CAN Bit Timing
1321 * Register (CBT)" and "CAN FD Bit Timing Register" field description
1322 * tables in the SoC reference manual.
1323 *
1324 * Note that the values here are the "physical" timing limits, whereas
1325 * the register field limits are physical values minus 1 (which is
1326 * handled by the flexcan_timing_config_t field assignments elsewhere
1327 * in this driver). The exception to this are the prop_seg values for
1328 * the data phase, which correspond to the allowed register values.
1329 */
1330 .timing_min = {
1331 .sjw = 0x01,
1332 .prop_seg = 0x01,
1333 .phase_seg1 = 0x01,
1334 .phase_seg2 = 0x02,
1335 .prescaler = 0x01
1336 },
1337 .timing_max = {
1338 .sjw = 0x20,
1339 .prop_seg = 0x40,
1340 .phase_seg1 = 0x20,
1341 .phase_seg2 = 0x20,
1342 .prescaler = 0x400
1343 },
1344 .timing_data_min = {
1345 .sjw = 0x01,
1346 .prop_seg = 0x01,
1347 .phase_seg1 = 0x01,
1348 .phase_seg2 = 0x02,
1349 .prescaler = 0x01
1350 },
1351 .timing_data_max = {
1352 .sjw = 0x08,
1353 .prop_seg = 0x1f,
1354 .phase_seg1 = 0x08,
1355 .phase_seg2 = 0x08,
1356 .prescaler = 0x400
1357 },
1358 };
1359 #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1360
1361 #define FLEXCAN_IRQ_BY_IDX(node_id, prop, idx, cell) \
1362 DT_IRQ_BY_NAME(node_id, \
1363 DT_STRING_TOKEN_BY_IDX(node_id, prop, idx), cell)
1364
1365 #define FLEXCAN_IRQ_ENABLE_CODE(node_id, prop, idx) \
1366 irq_enable(FLEXCAN_IRQ_BY_IDX(node_id, prop, idx, irq));
1367
1368 #define FLEXCAN_IRQ_DISABLE_CODE(node_id, prop, idx) \
1369 irq_disable(FLEXCAN_IRQ_BY_IDX(node_id, prop, idx, irq));
1370
1371 #define FLEXCAN_IRQ_CONFIG_CODE(node_id, prop, idx) \
1372 do { \
1373 IRQ_CONNECT(FLEXCAN_IRQ_BY_IDX(node_id, prop, idx, irq), \
1374 FLEXCAN_IRQ_BY_IDX(node_id, prop, idx, priority), \
1375 mcux_flexcan_isr, \
1376 DEVICE_DT_GET(node_id), 0); \
1377 FLEXCAN_IRQ_ENABLE_CODE(node_id, prop, idx); \
1378 } while (false);
1379
1380 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1381 #define FLEXCAN_MAX_BITRATE(id) \
1382 COND_CODE_1(DT_INST_NODE_HAS_COMPAT(id, FLEXCAN_FD_DRV_COMPAT), \
1383 (8000000), (1000000))
1384 #else /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1385 #define FLEXCAN_MAX_BITRATE(id) 1000000
1386 #endif /* !CONFIG_CAN_MCUX_FLEXCAN_FD */
1387
1388 #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD
1389 #define FLEXCAN_DRIVER_API(id) \
1390 COND_CODE_1(DT_INST_NODE_HAS_COMPAT(id, FLEXCAN_FD_DRV_COMPAT), \
1391 (mcux_flexcan_fd_driver_api), \
1392 (mcux_flexcan_driver_api))
1393 #else /* CONFIG_CAN_MCUX_FLEXCAN_FD */
1394 #define FLEXCAN_DRIVER_API(id) mcux_flexcan_driver_api
1395 #endif /* !CONFIG_CAN_MCUX_FLEXCAN_FD */
1396
1397 #define FLEXCAN_DEVICE_INIT_MCUX(id) \
1398 PINCTRL_DT_INST_DEFINE(id); \
1399 \
1400 static void mcux_flexcan_irq_config_##id(const struct device *dev); \
1401 static void mcux_flexcan_irq_enable_##id(void); \
1402 static void mcux_flexcan_irq_disable_##id(void); \
1403 \
1404 static const struct mcux_flexcan_config mcux_flexcan_config_##id = { \
1405 .common = CAN_DT_DRIVER_CONFIG_INST_GET(id, 0, FLEXCAN_MAX_BITRATE(id)), \
1406 .base = (CAN_Type *)DT_INST_REG_ADDR(id), \
1407 .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(id)), \
1408 .clock_subsys = (clock_control_subsys_t) \
1409 DT_INST_CLOCKS_CELL(id, name), \
1410 .clk_source = DT_INST_PROP(id, clk_source), \
1411 IF_ENABLED(CONFIG_CAN_MCUX_FLEXCAN_FD, ( \
1412 .flexcan_fd = DT_INST_NODE_HAS_COMPAT(id, FLEXCAN_FD_DRV_COMPAT), \
1413 )) \
1414 .irq_config_func = mcux_flexcan_irq_config_##id, \
1415 .irq_enable_func = mcux_flexcan_irq_enable_##id, \
1416 .irq_disable_func = mcux_flexcan_irq_disable_##id, \
1417 .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \
1418 }; \
1419 \
1420 static struct mcux_flexcan_data mcux_flexcan_data_##id; \
1421 \
1422 CAN_DEVICE_DT_INST_DEFINE(id, mcux_flexcan_init, \
1423 NULL, &mcux_flexcan_data_##id, \
1424 &mcux_flexcan_config_##id, \
1425 POST_KERNEL, CONFIG_CAN_INIT_PRIORITY,\
1426 &FLEXCAN_DRIVER_API(id)); \
1427 \
1428 static void mcux_flexcan_irq_config_##id(const struct device *dev) \
1429 { \
1430 DT_INST_FOREACH_PROP_ELEM(id, interrupt_names, FLEXCAN_IRQ_CONFIG_CODE); \
1431 } \
1432 \
1433 static void mcux_flexcan_irq_enable_##id(void) \
1434 { \
1435 DT_INST_FOREACH_PROP_ELEM(id, interrupt_names, FLEXCAN_IRQ_ENABLE_CODE); \
1436 } \
1437 \
1438 static void mcux_flexcan_irq_disable_##id(void) \
1439 { \
1440 DT_INST_FOREACH_PROP_ELEM(id, interrupt_names, FLEXCAN_IRQ_DISABLE_CODE); \
1441 }
1442
1443 DT_INST_FOREACH_STATUS_OKAY(FLEXCAN_DEVICE_INIT_MCUX)
1444