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