1 /*
2  * Copyright 2022-2023 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/atomic.h>
9 #include <zephyr/drivers/can.h>
10 #include <zephyr/drivers/can/transceiver.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/pinctrl.h>
14 #include <zephyr/logging/log.h>
15 #include <zephyr/irq.h>
16 
17 #include <CanEXCEL_Ip_HwAccess.h>
18 #include <CanEXCEL_Ip_Irq.h>
19 
20 #define DT_DRV_COMPAT nxp_s32_canxl
21 
22 /*
23  * Convert from RX message buffer index to allocated filter ID and
24  * vice versa.
25  */
26 #define RX_MBIDX_TO_ALLOC_IDX(x)	(x - CONFIG_CAN_NXP_S32_MAX_TX)
27 #define ALLOC_IDX_TO_RXMB_IDX(x)	(x + CONFIG_CAN_NXP_S32_MAX_TX)
28 
29 /*
30  * Convert from TX message buffer index to allocated TX ID and vice
31  * versa.
32  */
33 #define TX_MBIDX_TO_ALLOC_IDX(x) (x)
34 #define ALLOC_IDX_TO_TXMB_IDX(x) (x)
35 
36 #define CAN_NXP_S32_TIMEOUT_MS  1
37 #define CAN_NXP_S32_MAX_BITRATE	8000000
38 #define CAN_NXP_S32_DATA_LENGTH 64
39 
40 LOG_MODULE_REGISTER(nxp_s32_canxl, CONFIG_CAN_LOG_LEVEL);
41 
42 #define SP_AND_TIMING_NOT_SET(inst)				\
43 	(!DT_INST_NODE_HAS_PROP(inst, sample_point) &&		\
44 	!(DT_INST_NODE_HAS_PROP(inst, prop_seg) &&		\
45 	DT_INST_NODE_HAS_PROP(inst, phase_seg1) &&		\
46 	DT_INST_NODE_HAS_PROP(inst, phase_seg2))) ||
47 
48 #if DT_INST_FOREACH_STATUS_OKAY(SP_AND_TIMING_NOT_SET) 0
49 #error You must either set a sampling-point or timings (phase-seg* and prop-seg)
50 #endif
51 
52 #ifdef CONFIG_CAN_FD_MODE
53 
54 #define SP_AND_TIMING_DATA_NOT_SET(inst)			\
55 	(!DT_INST_NODE_HAS_PROP(inst, sample_point_data) &&	\
56 	!(DT_INST_NODE_HAS_PROP(inst, prop_seg_data) &&		\
57 	DT_INST_NODE_HAS_PROP(inst, phase_seg1_data) &&		\
58 	DT_INST_NODE_HAS_PROP(inst, phase_seg2_data))) ||
59 
60 #if DT_INST_FOREACH_STATUS_OKAY(SP_AND_TIMING_DATA_NOT_SET) 0
61 #error You must either set a sampling-point-data or timings (phase-seg-data* and prop-seg-data)
62 #endif
63 #endif
64 
65 struct can_nxp_s32_config {
66 	CANXL_SIC_Type *base_sic;
67 	CANXL_GRP_CONTROL_Type *base_grp_ctrl;
68 	CANXL_DSC_CONTROL_Type *base_dsc_ctrl;
69 	uint8 instance;
70 	const struct device *clock_dev;
71 	clock_control_subsys_t clock_subsys;
72 	uint32_t bitrate;
73 	uint32_t sample_point;
74 	uint32_t sjw;
75 	uint32_t prop_seg;
76 	uint32_t phase_seg1;
77 	uint32_t phase_seg2;
78 #ifdef CONFIG_CAN_FD_MODE
79 	uint32_t bitrate_data;
80 	uint32_t sample_point_data;
81 	uint32_t sjw_data;
82 	uint32_t prop_seg_data;
83 	uint32_t phase_seg1_data;
84 	uint32_t phase_seg2_data;
85 #endif
86 	uint32_t max_bitrate;
87 	const struct device *phy;
88 	const struct pinctrl_dev_config *pin_cfg;
89 	Canexcel_Ip_ConfigType *can_cfg;
90 	void (*irq_config_func)(void);
91 };
92 
93 struct can_nxp_s32_tx_callback {
94 	Canexcel_Ip_DataInfoType tx_info;
95 	can_tx_callback_t function;
96 	void *arg;
97 };
98 
99 struct can_nxp_s32_rx_callback {
100 	struct can_filter filter;
101 	Canexcel_Ip_DataInfoType rx_info;
102 	can_rx_callback_t function;
103 	void *arg;
104 };
105 
106 struct can_nxp_s32_data {
107 	Canexcel_Ip_StateType *can_state;
108 
109 	ATOMIC_DEFINE(rx_allocs, CONFIG_CAN_NXP_S32_MAX_RX);
110 	struct k_mutex rx_mutex;
111 	struct can_nxp_s32_rx_callback rx_cbs[CONFIG_CAN_NXP_S32_MAX_RX];
112 	Canexcel_RxFdMsg *rx_msg;
113 
114 	ATOMIC_DEFINE(tx_allocs, CONFIG_CAN_NXP_S32_MAX_TX);
115 	struct k_sem tx_allocs_sem;
116 	struct k_mutex tx_mutex;
117 	struct can_nxp_s32_tx_callback tx_cbs[CONFIG_CAN_NXP_S32_MAX_TX];
118 	Canexcel_TxFdMsgType *tx_msg;
119 
120 	struct can_timing timing;
121 #ifdef CONFIG_CAN_FD_MODE
122 	struct can_timing timing_data;
123 #endif
124 	enum can_state state;
125 	can_state_change_callback_t state_change_cb;
126 	void *state_change_cb_data;
127 	bool started;
128 };
129 
can_nxp_s32_get_capabilities(const struct device * dev,can_mode_t * cap)130 static int can_nxp_s32_get_capabilities(const struct device *dev, can_mode_t *cap)
131 {
132 	ARG_UNUSED(dev);
133 
134 	*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
135 
136 #if CONFIG_CAN_FD_MODE
137 	*cap |= CAN_MODE_FD;
138 #endif
139 
140 	return 0;
141 }
142 
can_nxp_s32_start(const struct device * dev)143 static int can_nxp_s32_start(const struct device *dev)
144 {
145 	const struct can_nxp_s32_config *config = dev->config;
146 	struct can_nxp_s32_data *data = dev->data;
147 	int err;
148 
149 	if (data->started) {
150 		return -EALREADY;
151 	}
152 
153 	if (config->phy != NULL) {
154 		err = can_transceiver_enable(config->phy);
155 		if (err != 0) {
156 			LOG_ERR("failed to enable CAN transceiver (err %d)", err);
157 			return err;
158 		}
159 	}
160 
161 	data->started = true;
162 
163 	return 0;
164 }
165 
can_nxp_s32_abort_msg(const struct can_nxp_s32_config * config,int mb_idx)166 static int can_nxp_s32_abort_msg(const struct can_nxp_s32_config *config, int mb_idx)
167 {
168 	uint32_t time_start = 0;
169 	int ret = 0;
170 
171 	Canexcel_Ip_EnterFreezeMode(config->instance);
172 
173 	CanXL_ClearMsgBuffIntCmd(config->base_grp_ctrl, mb_idx);
174 	CanXL_ClearMsgDescIntStatusFlag(config->base_grp_ctrl, mb_idx);
175 
176 	time_start = k_uptime_get();
177 	/* Set system lock Status */
178 	(void)config->base_dsc_ctrl->DSCMBCTRLAR[mb_idx].SYSLOCK.DCSYSLOCK;
179 	while (CanXL_GetDescControlStatus(config->base_dsc_ctrl, mb_idx)
180 			== CANEXCEL_DESCNTSTATUS_LOCKED_HW) {
181 		if (k_uptime_get() - time_start >= CAN_NXP_S32_TIMEOUT_MS) {
182 			ret = CANEXCEL_STATUS_TIMEOUT;
183 			break;
184 		}
185 	}
186 
187 	/* Inactive descriptor */
188 	config->base_dsc_ctrl->DSCMBCTRLAR[mb_idx].ACT.DCACT = 0;
189 
190 	Canexcel_Ip_ExitFreezeMode(config->instance);
191 
192 	return ret;
193 }
194 
can_nxp_s32_stop(const struct device * dev)195 static int can_nxp_s32_stop(const struct device *dev)
196 {
197 	const struct can_nxp_s32_config *config = dev->config;
198 	struct can_nxp_s32_data *data = dev->data;
199 	can_tx_callback_t function;
200 	void *arg;
201 	int alloc;
202 	int err;
203 
204 	if (!data->started) {
205 		return -EALREADY;
206 	}
207 
208 	data->started = false;
209 
210 	/* Abort any pending TX frames before entering freeze mode */
211 	for (alloc = 0; alloc < CONFIG_CAN_NXP_S32_MAX_TX; alloc++) {
212 		function = data->tx_cbs[alloc].function;
213 		arg = data->tx_cbs[alloc].arg;
214 
215 		if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
216 			if (can_nxp_s32_abort_msg(config,
217 					ALLOC_IDX_TO_TXMB_IDX(alloc))) {
218 				LOG_ERR("Can't abort message !");
219 			};
220 
221 			function(dev, -ENETDOWN, arg);
222 			k_sem_give(&data->tx_allocs_sem);
223 		}
224 	}
225 
226 	if (config->phy != NULL) {
227 		err = can_transceiver_disable(config->phy);
228 		if (err != 0) {
229 			LOG_ERR("failed to disable CAN transceiver (err %d)", err);
230 			return err;
231 		}
232 	}
233 
234 	return 0;
235 }
236 
237 
can_nxp_s32_set_mode(const struct device * dev,can_mode_t mode)238 static int can_nxp_s32_set_mode(const struct device *dev, can_mode_t mode)
239 {
240 	const struct can_nxp_s32_config *config = dev->config;
241 	struct can_nxp_s32_data *data = dev->data;
242 	Canexcel_Ip_ModesType can_nxp_s32_mode = CAN_MODE_NORMAL;
243 	bool canfd = false;
244 	bool brs = false;
245 
246 	if (data->started) {
247 		return -EBUSY;
248 	}
249 #ifdef CONFIG_CAN_FD_MODE
250 	if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY | CAN_MODE_FD)) != 0) {
251 #else
252 	if ((mode & ~(CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) != 0) {
253 #endif
254 		LOG_ERR("unsupported mode: 0x%08x", mode);
255 		return -ENOTSUP;
256 	}
257 
258 	if ((mode & (CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY))
259 				== (CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) {
260 		LOG_ERR("unsupported mode loopback and "
261 			"mode listen-only at the same time: 0x%08x", mode);
262 		return -ENOTSUP;
263 	}
264 
265 	canfd = !!(mode & CAN_MODE_FD);
266 	brs = canfd;
267 
268 	if (mode & CAN_MODE_LISTENONLY) {
269 		can_nxp_s32_mode = CANEXCEL_LISTEN_ONLY_MODE;
270 	} else if (mode & CAN_MODE_LOOPBACK) {
271 		can_nxp_s32_mode = CANEXCEL_LOOPBACK_MODE;
272 	}
273 
274 	Canexcel_Ip_EnterFreezeMode(config->instance);
275 
276 	CanXL_SetFDEnabled(config->base_sic, canfd, brs);
277 
278 	CanXL_SetOperationMode(config->base_sic, can_nxp_s32_mode);
279 
280 	Canexcel_Ip_ExitFreezeMode(config->instance);
281 
282 	return 0;
283 }
284 
285 static int can_nxp_s32_get_core_clock(const struct device *dev, uint32_t *rate)
286 {
287 	const struct can_nxp_s32_config *config = dev->config;
288 
289 	__ASSERT_NO_MSG(rate != NULL);
290 
291 	return clock_control_get_rate(config->clock_dev, config->clock_subsys, rate);
292 }
293 
294 static int can_nxp_s32_get_max_filters(const struct device *dev, bool ide)
295 {
296 	ARG_UNUSED(ide);
297 
298 	return CONFIG_CAN_NXP_S32_MAX_RX;
299 }
300 
301 static int can_nxp_s32_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate)
302 {
303 	const struct can_nxp_s32_config *config = dev->config;
304 
305 	*max_bitrate = config->max_bitrate;
306 
307 	return 0;
308 }
309 
310 static int can_nxp_s32_get_state(const struct device *dev, enum can_state *state,
311 						struct can_bus_err_cnt *err_cnt)
312 {
313 	const struct can_nxp_s32_config *config = dev->config;
314 	struct can_nxp_s32_data *data = dev->data;
315 	uint32_t sys_status = config->base_sic->SYSS;
316 
317 	if (state) {
318 		if (!data->started) {
319 			*state = CAN_STATE_STOPPED;
320 		} else {
321 			if (sys_status & CANXL_SIC_SYSS_CBOFF_MASK) {
322 				*state = CAN_STATE_BUS_OFF;
323 			} else if (sys_status & CANXL_SIC_SYSS_CPASERR_MASK) {
324 				*state = CAN_STATE_ERROR_PASSIVE;
325 			} else if (sys_status & (CANXL_SIC_SYSS_CRXWRN_MASK
326 						| CANXL_SIC_SYSS_CTXWRN_MASK)) {
327 				*state = CAN_STATE_ERROR_WARNING;
328 			} else {
329 				*state = CAN_STATE_ERROR_ACTIVE;
330 			}
331 		}
332 	}
333 
334 	if (err_cnt) {
335 		/* NXP S32 CANXL HAL is not supported error counter */
336 		err_cnt->tx_err_cnt = 0;
337 		err_cnt->rx_err_cnt = 0;
338 	}
339 
340 	return 0;
341 }
342 
343 static void can_nxp_s32_set_state_change_callback(const struct device *dev,
344 							can_state_change_callback_t callback,
345 							void *user_data)
346 {
347 	struct can_nxp_s32_data *data = dev->data;
348 
349 	data->state_change_cb = callback;
350 	data->state_change_cb_data = user_data;
351 }
352 
353 #ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
354 static int can_nxp_s32_recover(const struct device *dev, k_timeout_t timeout)
355 {
356 	const struct can_nxp_s32_config *config = dev->config;
357 	struct can_nxp_s32_data *data = dev->data;
358 	enum can_state state;
359 	uint64_t start_time;
360 	int ret = 0;
361 
362 	if (!data->started) {
363 		return -ENETDOWN;
364 	}
365 
366 	can_nxp_s32_get_state(dev, &state, NULL);
367 	if (state != CAN_STATE_BUS_OFF) {
368 		return 0;
369 	}
370 
371 	start_time = k_uptime_ticks();
372 	config->base_sic->BCFG1 &= (~CANXL_SIC_BCFG1_ABRDIS_MASK);
373 
374 	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
375 		can_nxp_s32_get_state(dev, &state, NULL);
376 
377 		while (state == CAN_STATE_BUS_OFF) {
378 			if (!K_TIMEOUT_EQ(timeout, K_FOREVER) &&
379 				k_uptime_ticks() - start_time >= timeout.ticks) {
380 				ret = -EAGAIN;
381 			}
382 
383 			can_nxp_s32_get_state(dev, &state, NULL);
384 		}
385 	}
386 
387 	config->base_sic->BCFG1 |= CANXL_SIC_BCFG1_ABRDIS_MASK;
388 
389 	return ret;
390 }
391 #endif
392 
393 static void can_nxp_s32_remove_rx_filter(const struct device *dev, int filter_id)
394 {
395 	const struct can_nxp_s32_config *config = dev->config;
396 	struct can_nxp_s32_data *data = dev->data;
397 	int mb_indx = ALLOC_IDX_TO_RXMB_IDX(filter_id);
398 
399 	__ASSERT_NO_MSG(filter_id >= 0 && filter_id < CONFIG_CAN_NXP_S32_MAX_RX);
400 
401 	k_mutex_lock(&data->rx_mutex, K_FOREVER);
402 
403 	if (atomic_test_and_clear_bit(data->rx_allocs, filter_id)) {
404 		if (can_nxp_s32_abort_msg(config, mb_indx)) {
405 			LOG_ERR("Can't abort message !");
406 		};
407 
408 		data->rx_cbs[filter_id].function = NULL;
409 		data->rx_cbs[filter_id].arg = NULL;
410 		data->rx_cbs[filter_id].filter = (struct can_filter){0};
411 	} else {
412 		LOG_WRN("Filter ID %d already detached", filter_id);
413 	}
414 
415 	k_mutex_unlock(&data->rx_mutex);
416 }
417 
418 static int can_nxp_s32_add_rx_filter(const struct device *dev,
419 				can_rx_callback_t callback,
420 				void *user_data,
421 				const struct can_filter *filter)
422 {
423 	const struct can_nxp_s32_config *config = dev->config;
424 	struct can_nxp_s32_data *data = dev->data;
425 	int alloc = -ENOSPC;
426 	int mb_indx;
427 	uint32_t mask;
428 
429 	__ASSERT_NO_MSG(callback != NULL);
430 #if defined(CONFIG_CAN_FD_MODE)
431 	if ((filter->flags & ~(CAN_FILTER_IDE | CAN_FILTER_DATA | CAN_FILTER_FDF)) != 0) {
432 #else
433 	if ((filter->flags & ~(CAN_FILTER_IDE | CAN_FILTER_DATA)) != 0) {
434 #endif
435 		LOG_ERR("unsupported CAN filter flags 0x%02x", filter->flags);
436 		return -ENOTSUP;
437 	}
438 
439 	k_mutex_lock(&data->rx_mutex, K_FOREVER);
440 
441 	/* Find and allocate RX message buffer */
442 	for (int i = 0; i < CONFIG_CAN_NXP_S32_MAX_RX; i++) {
443 		if (!atomic_test_and_set_bit(data->rx_allocs, i)) {
444 			alloc = i;
445 			break;
446 		}
447 	}
448 
449 	if (alloc == -ENOSPC) {
450 		LOG_ERR("No free filter bank found");
451 		goto unlock;
452 	}
453 
454 	data->rx_cbs[alloc].function = callback;
455 	data->rx_cbs[alloc].arg = user_data;
456 	data->rx_cbs[alloc].filter = *filter;
457 
458 	data->rx_cbs[alloc].rx_info = (Canexcel_Ip_DataInfoType) {
459 		.frame = !!(filter->flags & CAN_FILTER_FDF) ?
460 				CANEXCEL_FD_FRAME : CANEXCEL_CLASIC_FRAME,
461 		.idType = !!(filter->flags & CAN_FILTER_IDE) ?
462 				CANEXCEL_MSG_ID_EXT : CANEXCEL_MSG_ID_STD,
463 		.dataLength = CAN_NXP_S32_DATA_LENGTH,
464 	};
465 
466 	/* Set Rx Mb individual mask for */
467 	mb_indx = ALLOC_IDX_TO_RXMB_IDX(alloc);
468 	if (!!(filter->flags & CAN_FILTER_IDE)) {
469 		mask = (filter->mask & CANXL_IP_ID_EXT_MASK);
470 	} else {
471 		mask = ((filter->mask << CANXL_IP_ID_STD_SHIFT) & CANXL_IP_ID_STD_MASK);
472 	}
473 
474 	Canexcel_Ip_EnterFreezeMode(config->instance);
475 
476 	Canexcel_Ip_SetRxIndividualMask(config->instance, mb_indx,
477 						data->rx_cbs[alloc].rx_info.frame, mask);
478 
479 	Canexcel_Ip_ConfigRx(config->instance, mb_indx, filter->id,
480 					&data->rx_cbs[alloc].rx_info);
481 
482 	Canexcel_Ip_ReceiveFD(config->instance, mb_indx, &data->rx_msg[alloc], FALSE);
483 
484 	Canexcel_Ip_ExitFreezeMode(config->instance);
485 
486 unlock:
487 	k_mutex_unlock(&data->rx_mutex);
488 
489 	return alloc;
490 }
491 
492 static int can_nxp_s32_send(const struct device *dev,
493 				const struct can_frame *frame,
494 				k_timeout_t timeout,
495 				can_tx_callback_t callback, void *user_data)
496 {
497 	const struct can_nxp_s32_config *config = dev->config;
498 	uint8_t data_length = can_dlc_to_bytes(frame->dlc);
499 	struct can_nxp_s32_data *data = dev->data;
500 	Canexcel_Ip_StatusType status;
501 	enum can_state state;
502 	int alloc, mb_indx;
503 
504 	__ASSERT_NO_MSG(callback != NULL);
505 
506 #ifdef CONFIG_CAN_FD_MODE
507 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_FDF | CAN_FRAME_BRS)) != 0) {
508 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
509 		return -ENOTSUP;
510 	}
511 
512 	if ((frame->flags & CAN_FRAME_FDF) != 0 &&
513 			(config->base_sic->BCFG2 & CANXL_SIC_BCFG2_FDEN_MASK) == 0) {
514 		LOG_ERR("CAN-FD format not supported in non-FD mode");
515 		return -ENOTSUP;
516 	}
517 
518 	if ((frame->flags & CAN_FRAME_BRS) != 0 &&
519 			~(config->base_sic->BCFG1 & CANXL_SIC_BCFG1_FDRSDIS_MASK) == 0) {
520 		LOG_ERR("CAN-FD BRS not supported in non-FD mode");
521 		return -ENOTSUP;
522 	}
523 #else
524 	if ((frame->flags & ~CAN_FRAME_IDE) != 0) {
525 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
526 		return -ENOTSUP;
527 	}
528 #endif
529 
530 	if (data_length > sizeof(frame->data)) {
531 		LOG_ERR("data length (%d) > max frame data length (%d)",
532 			data_length, sizeof(frame->data));
533 		return -EINVAL;
534 	}
535 
536 	if ((frame->flags & CAN_FRAME_FDF) == 0) {
537 		if (frame->dlc > CAN_MAX_DLC) {
538 			LOG_ERR("DLC of %d for non-FD format frame", frame->dlc);
539 			return -EINVAL;
540 		}
541 #ifdef CONFIG_CAN_FD_MODE
542 	} else {
543 		if (frame->dlc > CANFD_MAX_DLC) {
544 			LOG_ERR("DLC of %d for CAN-FD format frame", frame->dlc);
545 			return -EINVAL;
546 		}
547 #endif
548 	}
549 
550 	if (!data->started) {
551 		return -ENETDOWN;
552 	}
553 
554 	can_nxp_s32_get_state(dev, &state, NULL);
555 	if (state == CAN_STATE_BUS_OFF) {
556 		LOG_ERR("Transmit failed, bus-off");
557 		return -ENETUNREACH;
558 	}
559 
560 	if (k_sem_take(&data->tx_allocs_sem, timeout) != 0) {
561 		return -EAGAIN;
562 	}
563 
564 	for (alloc = 0; alloc < CONFIG_CAN_NXP_S32_MAX_TX; alloc++) {
565 		if (!atomic_test_and_set_bit(data->tx_allocs, alloc)) {
566 			break;
567 		}
568 	}
569 
570 	data->tx_cbs[alloc].function = callback;
571 	data->tx_cbs[alloc].arg = user_data;
572 	mb_indx = ALLOC_IDX_TO_TXMB_IDX(alloc);
573 	data->tx_cbs[alloc].tx_info = (Canexcel_Ip_DataInfoType) {
574 		.frame = !!(frame->flags & CAN_FRAME_FDF) ?
575 				CANEXCEL_FD_FRAME : CANEXCEL_CLASIC_FRAME,
576 		.enable_brs = !!(frame->flags & CAN_FRAME_BRS) ? TRUE : FALSE,
577 		.idType = !!(frame->flags & CAN_FRAME_IDE) ?
578 				CANEXCEL_MSG_ID_EXT : CANEXCEL_MSG_ID_STD,
579 		.priority = 0,
580 		.fd_padding = 0,
581 		.dataLength = data_length,
582 		.is_polling = FALSE
583 	};
584 
585 	LOG_DBG("%s: Sending %d bytes Tx Mb %d, "
586 		"Tx Id: 0x%x, "
587 		"Id type: %s %s %s %s",
588 		dev->name, data_length,
589 		mb_indx, frame->id,
590 		!!(frame->flags & CAN_FRAME_IDE) ?
591 				"extended" : "standard",
592 		!!(frame->flags & CAN_FRAME_RTR) ? "RTR" : "",
593 		!!(frame->flags & CAN_FRAME_FDF) ? "FD frame" : "",
594 		!!(frame->flags & CAN_FRAME_BRS) ? "BRS" : "");
595 
596 	k_mutex_lock(&data->tx_mutex, K_FOREVER);
597 	/* Send MB Interrupt */
598 	status = Canexcel_Ip_SendFDMsg(config->instance, mb_indx, &data->tx_cbs[alloc].tx_info,
599 				frame->id, (uint8_t *)&frame->data, &data->tx_msg[alloc]);
600 	k_mutex_unlock(&data->tx_mutex);
601 
602 	if (status != CANEXCEL_STATUS_SUCCESS) {
603 		return -EIO;
604 	}
605 
606 	return 0;
607 }
608 
609 static void nxp_s32_zcan_timing_to_canxl_timing(const struct can_timing *timing,
610 							Canexcel_Ip_TimeSegmentType *canxl_timing)
611 {
612 	LOG_DBG("propSeg: %d, phase_seg1: %d, phase_seg2: %d, prescaler: %d, sjw: %d",
613 		timing->prop_seg, timing->phase_seg1, timing->phase_seg2,
614 		timing->prescaler, timing->sjw);
615 
616 	canxl_timing->propSeg = timing->prop_seg - 1U;
617 	canxl_timing->phaseSeg1 = timing->phase_seg1 - 1U;
618 	canxl_timing->phaseSeg2 = timing->phase_seg2 - 1U;
619 	canxl_timing->preDivider = timing->prescaler - 1U;
620 	canxl_timing->rJumpwidth = timing->sjw - 1U;
621 }
622 
623 static int can_nxp_s32_set_timing(const struct device *dev,
624 			const struct can_timing *timing)
625 {
626 	const struct can_nxp_s32_config *config = dev->config;
627 	struct can_nxp_s32_data *data = dev->data;
628 	Canexcel_Ip_TimeSegmentType can_time_segment = {0};
629 
630 	if (data->started) {
631 		return -EBUSY;
632 	}
633 
634 	nxp_s32_zcan_timing_to_canxl_timing(timing, &can_time_segment);
635 
636 	/* Set timing for CAN instance*/
637 	CanXL_SetBaudRate(config->base_sic, &can_time_segment);
638 
639 	return 0;
640 }
641 
642 #ifdef CONFIG_CAN_FD_MODE
643 static int can_nxp_s32_set_timing_data(const struct device *dev,
644 			const struct can_timing *timing_data)
645 {
646 	const struct can_nxp_s32_config *config = dev->config;
647 	struct can_nxp_s32_data *data = dev->data;
648 	Canexcel_Ip_TimeSegmentType can_fd_time_segment = {0};
649 
650 	if (data->started) {
651 		return -EBUSY;
652 	}
653 
654 	nxp_s32_zcan_timing_to_canxl_timing(timing_data, &can_fd_time_segment);
655 
656 	/* Set timing for CAN FD instance*/
657 	CanXL_SetFDBaudRate(config->base_sic, &can_fd_time_segment);
658 
659 	return 0;
660 }
661 #endif
662 
663 static void can_nxp_s32_err_callback(const struct device *dev,
664 					Canexcel_Ip_EventType eventType,
665 					uint32 u32SysStatus,
666 					const Canexcel_Ip_StateType *canexcelState)
667 {
668 	const struct can_nxp_s32_config *config = dev->config;
669 	struct can_nxp_s32_data *data = dev->data;
670 	enum can_state state;
671 	struct can_bus_err_cnt err_cnt;
672 	void *cb_data = data->state_change_cb_data;
673 	can_tx_callback_t function;
674 	int alloc;
675 	void *arg;
676 
677 	switch (eventType) {
678 	case CANEXCEL_EVENT_TX_WARNING:
679 		LOG_DBG("Tx Warning (error 0x%x)", u32SysStatus);
680 		break;
681 	case CANEXCEL_EVENT_RX_WARNING:
682 		LOG_DBG("Rx Warning (error 0x%x)", u32SysStatus);
683 		break;
684 	case CANEXCEL_EVENT_BUSOFF:
685 		LOG_DBG("Bus Off (error 0x%x)", u32SysStatus);
686 		break;
687 	case CANEXCEL_EVENT_ERROR:
688 		LOG_DBG("Error Format Frames (error 0x%x)", u32SysStatus);
689 		break;
690 	case CANEXCEL_EVENT_ERROR_FD:
691 		LOG_DBG("Error Data Phase (error 0x%x)", u32SysStatus);
692 		break;
693 	case CANEXCEL_EVENT_PASSIVE:
694 		LOG_DBG("Error Passive (error 0x%x)", u32SysStatus);
695 		break;
696 	default:
697 		break;
698 	}
699 
700 	can_nxp_s32_get_state(dev, &state, &err_cnt);
701 	if (data->state != state) {
702 		data->state = state;
703 		if (data->state_change_cb) {
704 			data->state_change_cb(dev, state, err_cnt, cb_data);
705 		}
706 	}
707 
708 	if (state == CAN_STATE_BUS_OFF) {
709 		/* Abort any pending TX frames in case of bus-off */
710 		for (alloc = 0; alloc < CONFIG_CAN_NXP_S32_MAX_TX; alloc++) {
711 			/* Copy callback function and argument before clearing bit */
712 			function = data->tx_cbs[alloc].function;
713 			arg = data->tx_cbs[alloc].arg;
714 
715 			if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
716 				if (can_nxp_s32_abort_msg(config,
717 						ALLOC_IDX_TO_TXMB_IDX(alloc))) {
718 					LOG_ERR("Can't abort message !");
719 				};
720 
721 				function(dev, -ENETUNREACH, arg);
722 				k_sem_give(&data->tx_allocs_sem);
723 			}
724 		}
725 	}
726 }
727 
728 static void nxp_s32_msg_data_to_zcan_frame(Canexcel_RxFdMsg msg_data,
729 							struct can_frame *frame)
730 {
731 	memset(frame, 0, sizeof(*frame));
732 
733 	if (!!(msg_data.Header.Id & CANXL_TX_HEADER_IDE_MASK)) {
734 		frame->flags |= CAN_FRAME_IDE;
735 	}
736 
737 	if (!!(frame->flags & CAN_FRAME_IDE)) {
738 		frame->id = (msg_data.Header.Id & CANXL_IP_ID_EXT_MASK);
739 	} else {
740 		frame->id = ((msg_data.Header.Id & CANXL_IP_ID_STD_MASK)
741 						>> CANXL_IP_ID_STD_SHIFT);
742 	}
743 
744 	frame->dlc = (msg_data.Header.Control & CANXL_TX_HEADER_DLC_MASK)
745 						>> CANXL_TX_HEADER_DLC_SHIFT;
746 
747 	if (!!(msg_data.Header.Control & CANXL_TX_HEADER_FDF_MASK)) {
748 		frame->flags |= CAN_FRAME_FDF;
749 	}
750 
751 	if (!!(msg_data.Header.Control & CANXL_TX_HEADER_BRS_MASK)) {
752 		frame->flags |= CAN_FRAME_BRS;
753 	}
754 
755 	if (!!(msg_data.Header.Id & CANXL_TX_HEADER_RTR_MASK)) {
756 		frame->flags |= CAN_FRAME_RTR;
757 	} else {
758 		memcpy(frame->data, msg_data.data, can_dlc_to_bytes(frame->dlc));
759 	}
760 
761 #ifdef CONFIG_CAN_RX_TIMESTAMP
762 	frame->timestamp = msg_data.timeStampL;
763 #endif /* CAN_RX_TIMESTAMP */
764 }
765 
766 static void can_nxp_s32_ctrl_callback(const struct device *dev,
767 					Canexcel_Ip_EventType eventType, uint32 buffidx,
768 					const Canexcel_Ip_StateType *canexcelState)
769 {
770 	const struct can_nxp_s32_config *config = dev->config;
771 	struct can_nxp_s32_data *data = dev->data;
772 	struct can_frame frame = {0};
773 	can_tx_callback_t tx_func;
774 	can_rx_callback_t rx_func;
775 	Canexcel_Ip_StatusType status;
776 	int alloc;
777 
778 	if (eventType == CANEXCEL_EVENT_TX_COMPLETE) {
779 		alloc = TX_MBIDX_TO_ALLOC_IDX(buffidx);
780 		tx_func = data->tx_cbs[alloc].function;
781 		LOG_DBG("%s: Sent Tx Mb %d", dev->name, buffidx);
782 		if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
783 			tx_func(dev, 0, data->tx_cbs[alloc].arg);
784 			k_sem_give(&data->tx_allocs_sem);
785 		}
786 	} else if (eventType == CANEXCEL_EVENT_RX_COMPLETE) {
787 		alloc = RX_MBIDX_TO_ALLOC_IDX(buffidx);
788 		rx_func = data->rx_cbs[alloc].function;
789 		if (atomic_test_bit(data->rx_allocs, alloc)) {
790 			nxp_s32_msg_data_to_zcan_frame(data->rx_msg[alloc], &frame);
791 
792 			LOG_DBG("%s: Received %d bytes Rx Mb %d, "
793 				"Rx Id: 0x%x, "
794 				"Id type: %s %s %s %s",
795 				dev->name, can_dlc_to_bytes(frame.dlc),
796 				buffidx, frame.id,
797 				!!(frame.flags & CAN_FRAME_IDE) ?
798 						"extended" : "standard",
799 				!!(frame.flags & CAN_FRAME_RTR) ? "RTR" : "",
800 				!!(frame.flags & CAN_FRAME_FDF) ? "FD frame" : "",
801 				!!(frame.flags & CAN_FRAME_BRS) ? "BRS" : "");
802 
803 			rx_func(dev, &frame, data->rx_cbs[alloc].arg);
804 
805 			status = Canexcel_Ip_ReceiveFD(config->instance, buffidx,
806 							&data->rx_msg[alloc], FALSE);
807 			if (status != CANEXCEL_STATUS_SUCCESS) {
808 				LOG_ERR("MB %d is not ready for receiving next message", buffidx);
809 			}
810 		}
811 	}
812 }
813 
814 static int can_nxp_s32_init(const struct device *dev)
815 {
816 	const struct can_nxp_s32_config *config = dev->config;
817 	struct can_nxp_s32_data *data = dev->data;
818 	int err;
819 #ifdef CONFIG_CAN_RX_TIMESTAMP
820 	Canexcel_Ip_TimeStampConf_Type time_stamp = {
821 		.ts64bit = FALSE, /* Time stamp size is 32 bits */
822 		.capture = CANEXCEL_TIMESTAMPCAPTURE_END,
823 		.src = CANTBS_TIMESURCE_BUS1
824 	};
825 #endif
826 
827 	if (config->phy != NULL) {
828 		if (!device_is_ready(config->phy)) {
829 			LOG_ERR("CAN transceiver not ready");
830 			return -ENODEV;
831 		}
832 	}
833 
834 	if (!device_is_ready(config->clock_dev)) {
835 		LOG_ERR("Clock control device not ready");
836 		return -ENODEV;
837 	}
838 
839 	err = clock_control_on(config->clock_dev, config->clock_subsys);
840 	if (err) {
841 		LOG_ERR("Failed to enable clock");
842 		return err;
843 	}
844 
845 	k_mutex_init(&data->rx_mutex);
846 	k_mutex_init(&data->tx_mutex);
847 	k_sem_init(&data->tx_allocs_sem, CONFIG_CAN_NXP_S32_MAX_TX, CONFIG_CAN_NXP_S32_MAX_TX);
848 
849 	err = pinctrl_apply_state(config->pin_cfg, PINCTRL_STATE_DEFAULT);
850 	if (err < 0) {
851 		return err;
852 	}
853 
854 	/* Enable CANXL HW */
855 	IP_MC_RGM->PRST_0[0].PRST_0 &=
856 		~(MC_RGM_PRST_0_PERIPH_16_RST_MASK | MC_RGM_PRST_0_PERIPH_24_RST_MASK);
857 
858 	data->timing.sjw = config->sjw;
859 	if (config->sample_point) {
860 		err = can_calc_timing(dev, &data->timing, config->bitrate,
861 						config->sample_point);
862 		if (err == -EINVAL) {
863 			LOG_ERR("Can't find timing for given param");
864 			return -EIO;
865 		}
866 		if (err > 0) {
867 			LOG_WRN("Sample-point error : %d", err);
868 		}
869 	} else {
870 		data->timing.prop_seg = config->prop_seg;
871 		data->timing.phase_seg1 = config->phase_seg1;
872 		data->timing.phase_seg2 = config->phase_seg2;
873 		err = can_calc_prescaler(dev, &data->timing, config->bitrate);
874 		if (err) {
875 			LOG_WRN("Bitrate error: %d", err);
876 		}
877 	}
878 
879 	LOG_DBG("Setting CAN bitrate %d:", config->bitrate);
880 	nxp_s32_zcan_timing_to_canxl_timing(&data->timing, &config->can_cfg->bitrate);
881 
882 #ifdef CONFIG_CAN_FD_MODE
883 	data->timing_data.sjw = config->sjw_data;
884 	if (config->sample_point_data) {
885 		err = can_calc_timing_data(dev, &data->timing_data, config->bitrate_data,
886 						config->sample_point_data);
887 		if (err == -EINVAL) {
888 			LOG_ERR("Can't find timing data for given param");
889 			return -EIO;
890 		}
891 		if (err > 0) {
892 			LOG_WRN("Sample-point-data err : %d", err);
893 		}
894 	} else {
895 		data->timing_data.prop_seg = config->prop_seg_data;
896 		data->timing_data.phase_seg1 = config->phase_seg1_data;
897 		data->timing_data.phase_seg2 = config->phase_seg2_data;
898 		err = can_calc_prescaler(dev, &data->timing_data, config->bitrate_data);
899 		if (err) {
900 			LOG_WRN("Bitrate data error: %d", err);
901 		}
902 	}
903 
904 	LOG_DBG("Setting CAN-FD bitrate %d:", config->bitrate_data);
905 	nxp_s32_zcan_timing_to_canxl_timing(&data->timing_data, &config->can_cfg->Fd_bitrate);
906 #endif
907 
908 	/* Initialize CAN structure */
909 	Canexcel_Ip_Init(config->instance, config->can_cfg, data->can_state);
910 
911 	/* Configure time stamp */
912 #ifdef CONFIG_CAN_RX_TIMESTAMP
913 	Canexcel_Ip_ConfigTimeStamp(config->instance, &time_stamp);
914 #endif
915 
916 	/* Enable Interrupt */
917 	Canexcel_Ip_EnableInterrupts(config->instance);
918 
919 	/* Enable Error Interrupt */
920 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_RX_WARNING, TRUE);
921 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_TX_WARNING, TRUE);
922 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_ERR, TRUE);
923 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_BUSOFF, TRUE);
924 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_PASIVE_ERR, TRUE);
925 
926 	config->irq_config_func();
927 
928 	can_nxp_s32_get_state(dev, &data->state, NULL);
929 
930 	return 0;
931 }
932 
933 static const struct can_driver_api can_nxp_s32_driver_api = {
934 	.get_capabilities = can_nxp_s32_get_capabilities,
935 	.start = can_nxp_s32_start,
936 	.stop = can_nxp_s32_stop,
937 	.set_mode = can_nxp_s32_set_mode,
938 	.set_timing = can_nxp_s32_set_timing,
939 	.send = can_nxp_s32_send,
940 	.add_rx_filter = can_nxp_s32_add_rx_filter,
941 	.remove_rx_filter = can_nxp_s32_remove_rx_filter,
942 	.get_state = can_nxp_s32_get_state,
943 #ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
944 	.recover = can_nxp_s32_recover,
945 #endif
946 	.set_state_change_callback = can_nxp_s32_set_state_change_callback,
947 	.get_core_clock = can_nxp_s32_get_core_clock,
948 	.get_max_filters = can_nxp_s32_get_max_filters,
949 	.get_max_bitrate = can_nxp_s32_get_max_bitrate,
950 	.timing_min = {
951 		.sjw = 0x01,
952 		.prop_seg = 0x01,
953 		.phase_seg1 = 0x01,
954 		.phase_seg2 = 0x02,
955 		.prescaler = 0x01
956 	},
957 	.timing_max = {
958 		.sjw = 0x04,
959 		.prop_seg = 0x08,
960 		.phase_seg1 = 0x08,
961 		.phase_seg2 = 0x08,
962 		.prescaler = 0x100
963 	},
964 #ifdef CONFIG_CAN_FD_MODE
965 	.set_timing_data = can_nxp_s32_set_timing_data,
966 	.timing_data_min = {
967 		.sjw = 0x01,
968 		.prop_seg = 0x01,
969 		.phase_seg1 = 0x01,
970 		.phase_seg2 = 0x02,
971 		.prescaler = 0x01
972 	},
973 	.timing_data_max = {
974 		.sjw = 0x04,
975 		.prop_seg = 0x08,
976 		.phase_seg1 = 0x08,
977 		.phase_seg2 = 0x08,
978 		.prescaler = 0x100
979 	}
980 #endif
981 };
982 
983 #define CAN_NXP_S32_NODE(n)			DT_NODELABEL(can##n)
984 
985 #define CAN_NXP_S32_IRQ_HANDLER(n, irq_name)	DT_CAT5(CANXL, n, _, irq_name, Handler)
986 
987 #define _CAN_NXP_S32_IRQ_CONFIG(node_id, prop, idx, n)					\
988 	do {										\
989 		extern void (CAN_NXP_S32_IRQ_HANDLER(n,					\
990 				DT_STRING_TOKEN_BY_IDX(node_id, prop, idx)))(void);	\
991 		IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq),				\
992 				DT_IRQ_BY_IDX(node_id, idx, priority),			\
993 				CAN_NXP_S32_IRQ_HANDLER(n,				\
994 					DT_STRING_TOKEN_BY_IDX(node_id, prop, idx)),	\
995 				NULL,							\
996 				DT_IRQ_BY_IDX(node_id, idx, flags));			\
997 		irq_enable(DT_IRQ_BY_IDX(node_id, idx, irq));				\
998 	} while (false);
999 
1000 #define CAN_NXP_S32_IRQ_CONFIG(n)							\
1001 	static void can_irq_config_##n(void)						\
1002 	{										\
1003 		DT_FOREACH_PROP_ELEM_VARGS(CAN_NXP_S32_NODE(n), interrupt_names,	\
1004 							_CAN_NXP_S32_IRQ_CONFIG, n);	\
1005 	}
1006 
1007 #define CAN_NXP_S32_ERR_CALLBACK(n)							\
1008 	void nxp_s32_can_##n##_err_callback(uint8 instance, Canexcel_Ip_EventType eventType,\
1009 		uint32 u32SysStatus, const Canexcel_Ip_StateType *canexcelState)	\
1010 	{										\
1011 		const struct device *dev = DEVICE_DT_GET(CAN_NXP_S32_NODE(n));		\
1012 		can_nxp_s32_err_callback(dev, eventType, u32SysStatus, canexcelState);	\
1013 	}
1014 
1015 #define CAN_NXP_S32_CTRL_CALLBACK(n)							\
1016 	void nxp_s32_can_##n##_ctrl_callback(uint8 instance, Canexcel_Ip_EventType eventType,\
1017 			uint32 buffIdx, const Canexcel_Ip_StateType *canexcelState)	\
1018 	{										\
1019 		const struct device *dev = DEVICE_DT_GET(CAN_NXP_S32_NODE(n));		\
1020 		can_nxp_s32_ctrl_callback(dev, eventType, buffIdx, canexcelState);	\
1021 	}
1022 
1023 #if defined(CONFIG_CAN_FD_MODE)
1024 #define CAN_NXP_S32_TIMING_DATA_CONFIG(n)						\
1025 		.bitrate_data = DT_PROP(CAN_NXP_S32_NODE(n), bus_speed_data),		\
1026 		.sjw_data = DT_PROP(CAN_NXP_S32_NODE(n), sjw_data),			\
1027 		.prop_seg_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), prop_seg_data, 0),	\
1028 		.phase_seg1_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg1_data, 0),	\
1029 		.phase_seg2_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg2_data, 0),	\
1030 		.sample_point_data = DT_PROP_OR(CAN_NXP_S32_NODE(n), sample_point_data, 0),
1031 #define CAN_NXP_S32_FD_MODE	1
1032 #define CAN_NXP_S32_BRS		1
1033 #else
1034 #define CAN_NXP_S32_TIMING_DATA_CONFIG(n)
1035 #define CAN_NXP_S32_FD_MODE	0
1036 #define CAN_NXP_S32_BRS		0
1037 #endif
1038 
1039 #ifdef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
1040 #define CAN_NXP_S32_CTRL_OPTIONS CANXL_IP_BUSOFF_RECOVERY_U32
1041 #else
1042 #define CAN_NXP_S32_CTRL_OPTIONS 0
1043 #endif
1044 
1045 #define CAN_NXP_S32_INIT_DEVICE(n)							\
1046 	CAN_NXP_S32_CTRL_CALLBACK(n)							\
1047 	CAN_NXP_S32_ERR_CALLBACK(n)							\
1048 	CAN_NXP_S32_IRQ_CONFIG(n)							\
1049 	PINCTRL_DT_DEFINE(CAN_NXP_S32_NODE(n));						\
1050 	Canexcel_Ip_ConfigType can_nxp_s32_default_config##n = {			\
1051 		.rx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_RX,				\
1052 		.tx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_TX,				\
1053 		.CanxlMode = CANEXCEL_LISTEN_ONLY_MODE,					\
1054 		.fd_enable = (boolean)CAN_NXP_S32_FD_MODE,				\
1055 		.bitRateSwitch = (boolean)CAN_NXP_S32_BRS,				\
1056 		.ctrlOptions = (uint32)CAN_NXP_S32_CTRL_OPTIONS,			\
1057 		.Callback = nxp_s32_can_##n##_ctrl_callback,				\
1058 		.ErrorCallback = nxp_s32_can_##n##_err_callback				\
1059 	};										\
1060 	__nocache Canexcel_Ip_StateType can_nxp_s32_state##n;				\
1061 	__nocache Canexcel_TxFdMsgType tx_msg##n[CONFIG_CAN_NXP_S32_MAX_TX];		\
1062 	__nocache Canexcel_RxFdMsg rx_msg_##n[CONFIG_CAN_NXP_S32_MAX_RX];		\
1063 	static struct can_nxp_s32_data can_nxp_s32_data_##n = {				\
1064 		.can_state = (Canexcel_Ip_StateType *)&can_nxp_s32_state##n,		\
1065 		.tx_msg = tx_msg##n,							\
1066 		.rx_msg = rx_msg_##n,							\
1067 	};										\
1068 	static struct can_nxp_s32_config can_nxp_s32_config_##n = {			\
1069 		.base_sic = (CANXL_SIC_Type *)						\
1070 				DT_REG_ADDR_BY_NAME(CAN_NXP_S32_NODE(n), sic),		\
1071 		.base_grp_ctrl = (CANXL_GRP_CONTROL_Type *)				\
1072 				DT_REG_ADDR_BY_NAME(CAN_NXP_S32_NODE(n), grp_ctrl),	\
1073 		.base_dsc_ctrl = (CANXL_DSC_CONTROL_Type *)				\
1074 				DT_REG_ADDR_BY_NAME(CAN_NXP_S32_NODE(n), dsc_ctrl),	\
1075 		.instance = n,								\
1076 		.clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(CAN_NXP_S32_NODE(n))),	\
1077 		.clock_subsys = (clock_control_subsys_t)				\
1078 				DT_CLOCKS_CELL(CAN_NXP_S32_NODE(n), name),		\
1079 		.bitrate = DT_PROP(CAN_NXP_S32_NODE(n), bus_speed),			\
1080 		.sjw = DT_PROP(CAN_NXP_S32_NODE(n), sjw),				\
1081 		.prop_seg = DT_PROP_OR(CAN_NXP_S32_NODE(n), prop_seg, 0),		\
1082 		.phase_seg1 = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg1, 0),		\
1083 		.phase_seg2 = DT_PROP_OR(CAN_NXP_S32_NODE(n), phase_seg2, 0),		\
1084 		.sample_point = DT_PROP_OR(CAN_NXP_S32_NODE(n), sample_point, 0),	\
1085 		CAN_NXP_S32_TIMING_DATA_CONFIG(n)					\
1086 		.max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(CAN_NXP_S32_NODE(n),	\
1087 							CAN_NXP_S32_MAX_BITRATE),	\
1088 		.phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(CAN_NXP_S32_NODE(n), phys)),	\
1089 		.pin_cfg = PINCTRL_DT_DEV_CONFIG_GET(CAN_NXP_S32_NODE(n)),		\
1090 		.can_cfg = (Canexcel_Ip_ConfigType *)&can_nxp_s32_default_config##n,	\
1091 		.irq_config_func = can_irq_config_##n					\
1092 	};										\
1093 	static int can_nxp_s32_##n##_init(const struct device *dev)			\
1094 	{										\
1095 		return can_nxp_s32_init(dev);						\
1096 	}										\
1097 	CAN_DEVICE_DT_DEFINE(CAN_NXP_S32_NODE(n),					\
1098 			     can_nxp_s32_##n##_init,					\
1099 			     NULL,							\
1100 			     &can_nxp_s32_data_##n,					\
1101 			     &can_nxp_s32_config_##n,					\
1102 			     POST_KERNEL,						\
1103 			     CONFIG_CAN_INIT_PRIORITY,					\
1104 			     &can_nxp_s32_driver_api);
1105 
1106 #if DT_NODE_HAS_STATUS(CAN_NXP_S32_NODE(0), okay)
1107 CAN_NXP_S32_INIT_DEVICE(0)
1108 #endif
1109 
1110 #if DT_NODE_HAS_STATUS(CAN_NXP_S32_NODE(1), okay)
1111 CAN_NXP_S32_INIT_DEVICE(1)
1112 #endif
1113