1 /*
2  * Copyright 2022-2024 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 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
27 #define RX_MBIDX_TO_ALLOC_IDX(x)	(x)
28 #define ALLOC_IDX_TO_RXMB_IDX(x)	(x)
29 #else
30 #define RX_MBIDX_TO_ALLOC_IDX(x)	(x - CONFIG_CAN_NXP_S32_MAX_TX)
31 #define ALLOC_IDX_TO_RXMB_IDX(x)	(x + CONFIG_CAN_NXP_S32_MAX_TX)
32 #endif
33 
34 
35 /*
36  * Convert from TX message buffer index to allocated TX ID and vice
37  * versa.
38  */
39 #define TX_MBIDX_TO_ALLOC_IDX(x) (x)
40 #define ALLOC_IDX_TO_TXMB_IDX(x) (x)
41 
42 #define CAN_NXP_S32_TIMEOUT_MS  1
43 #define CAN_NXP_S32_MAX_BITRATE	8000000
44 #define CAN_NXP_S32_DATA_LENGTH 64
45 
46 #define CAN_NXP_S32_TDCO_MAX FIELD_GET(CANXL_SIC_BTDCC_FTDCOFF_MASK, CANXL_SIC_BTDCC_FTDCOFF_MASK)
47 
48 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
49 /* RX FIFO depth is fixed to the maximum value */
50 #define CAN_NXP_S32_RX_FIFO_DEPTH 32
51 /* RX FIFO water mark equal 1 that allows the interrupt is generated after 1 message received */
52 #define CAN_NXP_S32_RX_FIFO_WATERMARK 1
53 #endif
54 
55 #if defined(CONFIG_CAN_FD_MODE) && defined(CONFIG_CAN_NXP_S32_RX_FIFO)
56 #define CAN_NXP_S32_FD_MODE 1
57 #endif
58 
59 #define BCANXL_ST_STFERR_MASK   BIT(4)
60 #define BCANXL_ST_FRMERR_MASK   BIT(5)
61 #define BCANXL_ST_CRCERR_MASK   BIT(6)
62 #define BCANXL_ST_ACKERR_MASK   BIT(7)
63 #define BCANXL_ST_BIT0ERR_MASK  BIT(8)
64 #define BCANXL_ST_BIT1ERR_MASK  BIT(9)
65 #define BCANXL_ST_OVRERR_MASK   BIT(15)
66 #define BCANXL_ST_FLTCONF(x) (uint8_t)((x << BCANXL_ST_FLTCONF_SHIFT) & BCANXL_ST_FLTCONF_MASK)
67 
68 #define CANXL_CLEAR_ALL_ERRORS  0x7FFF0F00U
69 
70 LOG_MODULE_REGISTER(nxp_s32_canxl, CONFIG_CAN_LOG_LEVEL);
71 
72 struct can_nxp_s32_config {
73 	const struct can_driver_config common;
74 	CANXL_SIC_Type *base_sic;
75 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
76 	CANXL_RXFIFO_Type * base_rx_fifo;
77 	CANXL_RXFIFO_CONTROL_Type *base_rx_fifo_ctrl;
78 #endif
79 	CANXL_MRU_Type * base_mru;
80 	uint8 instance;
81 	const struct device *clock_dev;
82 	clock_control_subsys_t clock_subsys;
83 	const struct pinctrl_dev_config *pin_cfg;
84 	Canexcel_Ip_ConfigType *can_cfg;
85 	void (*irq_config_func)(void);
86 };
87 
88 struct can_nxp_s32_tx_callback {
89 	Canexcel_Ip_DataInfoType tx_info;
90 	can_tx_callback_t function;
91 	void *arg;
92 };
93 
94 struct can_nxp_s32_rx_callback {
95 	struct can_filter filter;
96 #ifndef CONFIG_CAN_NXP_S32_RX_FIFO
97 	Canexcel_Ip_DataInfoType rx_info;
98 #endif
99 	can_rx_callback_t function;
100 	void *arg;
101 };
102 
103 struct can_nxp_s32_data {
104 	struct can_driver_data common;
105 	Canexcel_Ip_StateType *can_state;
106 
107 	ATOMIC_DEFINE(rx_allocs, CONFIG_CAN_NXP_S32_MAX_RX);
108 	struct k_mutex rx_mutex;
109 	struct can_nxp_s32_rx_callback rx_cbs[CONFIG_CAN_NXP_S32_MAX_RX];
110 #ifndef CONFIG_CAN_NXP_S32_RX_FIFO
111 	Canexcel_RxFdMsg *rx_msg;
112 #endif
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 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
121 	Canexcel_Ip_RxFifoFilterID_ADDR * rx_fifo_filter;
122 	Canexcel_RxFdMsg *rx_fifo;
123 #endif
124 
125 	struct can_timing timing;
126 #ifdef CAN_NXP_S32_FD_MODE
127 	struct can_timing timing_data;
128 #endif
129 	enum can_state state;
130 };
131 
can_nxp_s32_get_capabilities(const struct device * dev,can_mode_t * cap)132 static int can_nxp_s32_get_capabilities(const struct device *dev, can_mode_t *cap)
133 {
134 	ARG_UNUSED(dev);
135 
136 	*cap = CAN_MODE_NORMAL | CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
137 
138 	if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
139 		*cap |= CAN_MODE_MANUAL_RECOVERY;
140 	}
141 
142 	if (IS_ENABLED(CAN_NXP_S32_FD_MODE)) {
143 		*cap |= CAN_MODE_FD;
144 	}
145 
146 	return 0;
147 }
148 
149 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
can_nxp_s32_config_rx_fifo_filter(const struct device * dev,int filter_id)150 static void can_nxp_s32_config_rx_fifo_filter(const struct device *dev, int filter_id)
151 {
152 	const struct can_nxp_s32_config *config = dev->config;
153 	struct can_nxp_s32_data *data = dev->data;
154 
155 	/* Lock the RxFIFO by System by reading register */
156 	(void)config->base_rx_fifo_ctrl->RXFSYSLOCK;
157 
158 	CanXL_ConfigIDFilter(config->base_rx_fifo,
159 				&data->rx_fifo_filter[filter_id], filter_id);
160 
161 	if ((config->base_rx_fifo_ctrl->RXFCSTA & CANXL_RXFIFO_CONTROL_RXFCSTA_SYSLOCK_MASK)
162 						== CANXL_RXFIFO_CONTROL_RXFCSTA_SYSLOCK_MASK) {
163 		/* Clear the sys lock to enable transfers */
164 		config->base_rx_fifo_ctrl->RXFSYSLOCK =
165 						CANXL_RXFIFO_CONTROL_RXFSYSLOCK_SYSLOCK_MASK;
166 	}
167 }
168 
169 /* Get the RxFiFO filter matched with the received RxFIFO message queue */
can_nxp_s32_get_rx_fifo_filter(struct can_nxp_s32_data * data,uint8_t queue_idx)170 static inline int can_nxp_s32_get_rx_fifo_filter(struct can_nxp_s32_data *data, uint8_t queue_idx)
171 {
172 	int alloc = -ENOSPC;
173 	uint32_t mask;
174 
175 	for (int filter_id = 0; filter_id < CONFIG_CAN_NXP_S32_MAX_RX; filter_id++) {
176 		mask = data->rx_fifo_filter[filter_id].idAddrFilterL;
177 
178 		if (mask == 0) {
179 			continue;
180 		}
181 
182 		if ((data->rx_fifo[queue_idx].Header.Id & mask) ==
183 		    (data->rx_fifo_filter[filter_id].idAddrFilterH & mask)) {
184 			alloc = filter_id;
185 			break;
186 		}
187 	}
188 
189 	return alloc;
190 }
191 #endif
192 
can_nxp_s32_start(const struct device * dev)193 static int can_nxp_s32_start(const struct device *dev)
194 {
195 	const struct can_nxp_s32_config *config = dev->config;
196 	struct can_nxp_s32_data *data = dev->data;
197 	int err;
198 
199 	if (data->common.started) {
200 		return -EALREADY;
201 	}
202 
203 	if (config->common.phy != NULL) {
204 		err = can_transceiver_enable(config->common.phy, data->common.mode);
205 		if (err != 0) {
206 			LOG_ERR("failed to enable CAN transceiver (err %d)", err);
207 			return err;
208 		}
209 	}
210 
211 	/* Reset statistics and clear all errors */
212 	CAN_STATS_RESET(dev);
213 	Canexcel_Ip_ClearErrorStatus(config->instance, CANXL_CLEAR_ALL_ERRORS);
214 
215 	data->common.started = true;
216 
217 	return 0;
218 }
219 
can_nxp_s32_stop(const struct device * dev)220 static int can_nxp_s32_stop(const struct device *dev)
221 {
222 	const struct can_nxp_s32_config *config = dev->config;
223 	struct can_nxp_s32_data *data = dev->data;
224 	can_tx_callback_t function;
225 	void *arg;
226 	int alloc;
227 	int err;
228 
229 	if (!data->common.started) {
230 		return -EALREADY;
231 	}
232 
233 	data->common.started = false;
234 
235 	/* Abort any pending TX frames before entering freeze mode */
236 	for (alloc = 0; alloc < CONFIG_CAN_NXP_S32_MAX_TX; alloc++) {
237 		function = data->tx_cbs[alloc].function;
238 		arg = data->tx_cbs[alloc].arg;
239 
240 		if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
241 			if (Canexcel_Ip_DeactivateMD(config->instance,
242 					ALLOC_IDX_TO_TXMB_IDX(alloc))) {
243 				LOG_ERR("Can't abort message !");
244 			};
245 
246 			function(dev, -ENETDOWN, arg);
247 			k_sem_give(&data->tx_allocs_sem);
248 		}
249 	}
250 
251 	if (config->common.phy != NULL) {
252 		err = can_transceiver_disable(config->common.phy);
253 		if (err != 0) {
254 			LOG_ERR("failed to disable CAN transceiver (err %d)", err);
255 			return err;
256 		}
257 	}
258 
259 	return 0;
260 }
261 
can_nxp_s32_set_fd_mode(CANXL_SIC_Type * base,boolean enable_fd,boolean enable_brs)262 static void can_nxp_s32_set_fd_mode(CANXL_SIC_Type *base,
263 					boolean enable_fd,
264 					boolean enable_brs)
265 {
266 	base->BCFG2 = (base->BCFG2 & ~CANXL_SIC_BCFG2_FDEN_MASK) |
267 			CANXL_SIC_BCFG2_FDEN(enable_fd ? 1UL : 0UL);
268 	base->BCFG1 = (base->BCFG1 & ~CANXL_SIC_BCFG1_FDRSDIS_MASK) |
269 			CANXL_SIC_BCFG1_FDRSDIS(enable_brs ? 0UL : 1UL);
270 	base->BTDCC &= ~(CANXL_SIC_BTDCC_FTDCEN_MASK |
271 			CANXL_SIC_BTDCC_FTDCOFF_MASK);
272 }
273 
can_nxp_s32_set_mode(const struct device * dev,can_mode_t mode)274 static int can_nxp_s32_set_mode(const struct device *dev, can_mode_t mode)
275 {
276 	can_mode_t supported = CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY;
277 	const struct can_nxp_s32_config *config = dev->config;
278 	struct can_nxp_s32_data *data = dev->data;
279 	Canexcel_Ip_ModesType can_nxp_s32_mode = CAN_MODE_NORMAL;
280 	bool canfd = false;
281 	bool brs = false;
282 
283 	if (data->common.started) {
284 		return -EBUSY;
285 	}
286 
287 	if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
288 		supported |= CAN_MODE_MANUAL_RECOVERY;
289 	}
290 
291 	if (IS_ENABLED(CAN_NXP_S32_FD_MODE)) {
292 		supported |= CAN_MODE_FD;
293 	}
294 
295 	if ((mode & ~(supported)) != 0) {
296 		LOG_ERR("unsupported mode: 0x%08x", mode);
297 		return -ENOTSUP;
298 	}
299 
300 	if ((mode & (CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY))
301 				== (CAN_MODE_LOOPBACK | CAN_MODE_LISTENONLY)) {
302 		LOG_ERR("unsupported mode loopback and "
303 			"mode listen-only at the same time: 0x%08x", mode);
304 		return -ENOTSUP;
305 	}
306 
307 	canfd = !!(mode & CAN_MODE_FD);
308 	brs = canfd;
309 
310 	if (mode & CAN_MODE_LISTENONLY) {
311 		can_nxp_s32_mode = CANEXCEL_LISTEN_ONLY_MODE;
312 	} else if (mode & CAN_MODE_LOOPBACK) {
313 		can_nxp_s32_mode = CANEXCEL_LOOPBACK_MODE;
314 	}
315 
316 	Canexcel_Ip_EnterFreezeMode(config->instance);
317 
318 	can_nxp_s32_set_fd_mode(config->base_sic, canfd, brs);
319 
320 	if (IS_ENABLED(CONFIG_CAN_MANUAL_RECOVERY_MODE)) {
321 		Canexcel_Ip_StatusType status;
322 		uint32_t options = 0U;
323 
324 		if ((mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
325 			options = CANXL_IP_BUSOFF_RECOVERY_U32;
326 		}
327 
328 		status = CanXL_ConfigCtrlOptions(config->base_sic, options);
329 		if (status != CANEXCEL_STATUS_SUCCESS) {
330 			return -EIO;
331 		}
332 	}
333 
334 	CanXL_SetOperationMode(config->base_sic, can_nxp_s32_mode);
335 
336 	Canexcel_Ip_ExitFreezeMode(config->instance);
337 
338 	data->common.mode = mode;
339 
340 	return 0;
341 }
342 
can_nxp_s32_get_core_clock(const struct device * dev,uint32_t * rate)343 static int can_nxp_s32_get_core_clock(const struct device *dev, uint32_t *rate)
344 {
345 	const struct can_nxp_s32_config *config = dev->config;
346 
347 	__ASSERT_NO_MSG(rate != NULL);
348 
349 	return clock_control_get_rate(config->clock_dev, config->clock_subsys, rate);
350 }
351 
can_nxp_s32_get_max_filters(const struct device * dev,bool ide)352 static int can_nxp_s32_get_max_filters(const struct device *dev, bool ide)
353 {
354 	ARG_UNUSED(ide);
355 
356 	return CONFIG_CAN_NXP_S32_MAX_RX;
357 }
358 
can_nxp_s32_get_state(const struct device * dev,enum can_state * state,struct can_bus_err_cnt * err_cnt)359 static int can_nxp_s32_get_state(const struct device *dev, enum can_state *state,
360 						struct can_bus_err_cnt *err_cnt)
361 {
362 	const struct can_nxp_s32_config *config = dev->config;
363 	struct can_nxp_s32_data *data = dev->data;
364 	uint8_t bcanxl_status;
365 
366 	if (state) {
367 		if (!data->common.started) {
368 			*state = CAN_STATE_STOPPED;
369 		} else {
370 			Canexcel_Ip_GetControllerStatus(config->instance, &bcanxl_status);
371 			if (bcanxl_status & BCANXL_ST_FLTCONF(2)) {
372 				*state = CAN_STATE_BUS_OFF;
373 			} else if (bcanxl_status & BCANXL_ST_FLTCONF(1)) {
374 				*state = CAN_STATE_ERROR_PASSIVE;
375 			} else if (config->base_sic->SYSS &
376 				(CANXL_SIC_SYSS_CRXWRN_MASK | CANXL_SIC_SYSS_CTXWRN_MASK)) {
377 				*state = CAN_STATE_ERROR_WARNING;
378 			} else {
379 				*state = CAN_STATE_ERROR_ACTIVE;
380 			}
381 		}
382 	}
383 
384 	if (err_cnt) {
385 		Canexcel_Ip_GetControllerTxErrorCounter(config->instance, &err_cnt->tx_err_cnt);
386 		Canexcel_Ip_GetControllerRxErrorCounter(config->instance, &err_cnt->rx_err_cnt);
387 	}
388 
389 	return 0;
390 }
391 
can_nxp_s32_set_state_change_callback(const struct device * dev,can_state_change_callback_t callback,void * user_data)392 static void can_nxp_s32_set_state_change_callback(const struct device *dev,
393 							can_state_change_callback_t callback,
394 							void *user_data)
395 {
396 	struct can_nxp_s32_data *data = dev->data;
397 
398 	data->common.state_change_cb = callback;
399 	data->common.state_change_cb_user_data = user_data;
400 }
401 
402 #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
can_nxp_s32_recover(const struct device * dev,k_timeout_t timeout)403 static int can_nxp_s32_recover(const struct device *dev, k_timeout_t timeout)
404 {
405 	const struct can_nxp_s32_config *config = dev->config;
406 	struct can_nxp_s32_data *data = dev->data;
407 	enum can_state state;
408 	uint64_t start_time;
409 	int ret = 0;
410 
411 	if (!data->common.started) {
412 		return -ENETDOWN;
413 	}
414 
415 	if ((data->common.mode & CAN_MODE_MANUAL_RECOVERY) == 0U) {
416 		return -ENOTSUP;
417 	}
418 
419 	can_nxp_s32_get_state(dev, &state, NULL);
420 	if (state != CAN_STATE_BUS_OFF) {
421 		return 0;
422 	}
423 
424 	start_time = k_uptime_ticks();
425 	config->base_sic->BCFG1 &= (~CANXL_SIC_BCFG1_ABRDIS_MASK);
426 
427 	if (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
428 		can_nxp_s32_get_state(dev, &state, NULL);
429 
430 		while (state == CAN_STATE_BUS_OFF) {
431 			if (!K_TIMEOUT_EQ(timeout, K_FOREVER) &&
432 				k_uptime_ticks() - start_time >= timeout.ticks) {
433 				ret = -EAGAIN;
434 			}
435 
436 			can_nxp_s32_get_state(dev, &state, NULL);
437 		}
438 	}
439 
440 	config->base_sic->BCFG1 |= CANXL_SIC_BCFG1_ABRDIS_MASK;
441 
442 	return ret;
443 }
444 #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
445 
can_nxp_s32_remove_rx_filter(const struct device * dev,int filter_id)446 static void can_nxp_s32_remove_rx_filter(const struct device *dev, int filter_id)
447 {
448 	const struct can_nxp_s32_config *config = dev->config;
449 	struct can_nxp_s32_data *data = dev->data;
450 	int mb_indx = ALLOC_IDX_TO_RXMB_IDX(filter_id);
451 
452 	if (filter_id < 0 || filter_id >= CONFIG_CAN_NXP_S32_MAX_RX) {
453 		LOG_ERR("filter ID %d out of bounds", filter_id);
454 		return;
455 	}
456 
457 	k_mutex_lock(&data->rx_mutex, K_FOREVER);
458 
459 	if (atomic_test_and_clear_bit(data->rx_allocs, filter_id)) {
460 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
461 		data->rx_fifo_filter[mb_indx].idAddrFilterL = 0;
462 		data->rx_fifo_filter[mb_indx].idAddrFilterH = 0;
463 
464 		Canexcel_Ip_EnterFreezeMode(config->instance);
465 
466 		can_nxp_s32_config_rx_fifo_filter(dev, mb_indx);
467 
468 		Canexcel_Ip_ExitFreezeMode(config->instance);
469 #else
470 		if (Canexcel_Ip_DeactivateMD(config->instance, mb_indx)) {
471 			LOG_ERR("Can't abort message !");
472 		};
473 #endif
474 
475 		data->rx_cbs[filter_id].function = NULL;
476 		data->rx_cbs[filter_id].arg = NULL;
477 		data->rx_cbs[filter_id].filter = (struct can_filter){0};
478 	} else {
479 		LOG_WRN("Filter ID %d already detached", filter_id);
480 	}
481 
482 	k_mutex_unlock(&data->rx_mutex);
483 }
484 
can_nxp_s32_add_rx_filter(const struct device * dev,can_rx_callback_t callback,void * user_data,const struct can_filter * filter)485 static int can_nxp_s32_add_rx_filter(const struct device *dev,
486 				can_rx_callback_t callback,
487 				void *user_data,
488 				const struct can_filter *filter)
489 {
490 	const struct can_nxp_s32_config *config = dev->config;
491 	struct can_nxp_s32_data *data = dev->data;
492 	int alloc = -ENOSPC;
493 	int mb_indx;
494 	uint32_t mask;
495 
496 	if ((filter->flags & ~(CAN_FILTER_IDE)) != 0) {
497 		LOG_ERR("unsupported CAN filter flags 0x%02x", filter->flags);
498 		return -ENOTSUP;
499 	}
500 
501 	k_mutex_lock(&data->rx_mutex, K_FOREVER);
502 
503 	/* Find and allocate RX message buffer */
504 	for (int i = 0; i < CONFIG_CAN_NXP_S32_MAX_RX; i++) {
505 		if (!atomic_test_and_set_bit(data->rx_allocs, i)) {
506 			alloc = i;
507 			break;
508 		}
509 	}
510 
511 	if (alloc == -ENOSPC) {
512 		LOG_ERR("No free filter bank found");
513 		goto unlock;
514 	}
515 
516 	data->rx_cbs[alloc].function = callback;
517 	data->rx_cbs[alloc].arg = user_data;
518 	data->rx_cbs[alloc].filter = *filter;
519 
520 	/* Set Rx Mb individual mask for */
521 	mb_indx = ALLOC_IDX_TO_RXMB_IDX(alloc);
522 	if (!!(filter->flags & CAN_FILTER_IDE)) {
523 		mask = filter->mask & CANXL_IP_ID_EXT_MASK;
524 	} else {
525 		mask = (filter->mask << CANXL_IP_ID_STD_SHIFT) & CANXL_IP_ID_STD_MASK;
526 	}
527 
528 #ifndef CONFIG_CAN_ACCEPT_RTR
529 	mask |= CANXL_MSG_DESCRIPTORS_MDFLT1FD_RTRMSK_MASK;
530 #endif /* !CONFIG_CAN_ACCEPT_RTR */
531 
532 	Canexcel_Ip_EnterFreezeMode(config->instance);
533 
534 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
535 	uint32_t filter_id;
536 
537 	if (!!(filter->flags & CAN_FILTER_IDE)) {
538 		filter_id = filter->id & CANXL_IP_ID_EXT_MASK;
539 	} else {
540 		filter_id = (filter->id << CANXL_IP_ID_STD_SHIFT) & CANXL_IP_ID_STD_MASK;
541 	}
542 
543 	data->rx_fifo_filter[mb_indx].filterType = CANEXCEL_IP_RX_FIFO_MASK_FILTER;
544 	data->rx_fifo_filter[mb_indx].idAddrFilterL = mask;
545 	data->rx_fifo_filter[mb_indx].idAddrFilterH = filter_id;
546 
547 	can_nxp_s32_config_rx_fifo_filter(dev, mb_indx);
548 #else
549 	data->rx_cbs[alloc].rx_info = (Canexcel_Ip_DataInfoType) {
550 		.frame = CANEXCEL_CLASIC_FRAME,
551 		.idType = !!(filter->flags & CAN_FILTER_IDE) ?
552 				CANEXCEL_MSG_ID_EXT : CANEXCEL_MSG_ID_STD,
553 		.dataLength = CAN_NXP_S32_DATA_LENGTH,
554 	};
555 
556 	Canexcel_Ip_SetRxIndividualMask(config->instance, mb_indx,
557 						data->rx_cbs[alloc].rx_info.frame, mask);
558 
559 	Canexcel_Ip_ConfigRx(config->instance, mb_indx, filter->id,
560 					&data->rx_cbs[alloc].rx_info);
561 
562 	Canexcel_Ip_ReceiveFD(config->instance, mb_indx, &data->rx_msg[alloc], FALSE);
563 #endif
564 
565 	Canexcel_Ip_ExitFreezeMode(config->instance);
566 
567 unlock:
568 	k_mutex_unlock(&data->rx_mutex);
569 
570 	return alloc;
571 }
572 
can_nxp_s32_send(const struct device * dev,const struct can_frame * frame,k_timeout_t timeout,can_tx_callback_t callback,void * user_data)573 static int can_nxp_s32_send(const struct device *dev,
574 				const struct can_frame *frame,
575 				k_timeout_t timeout,
576 				can_tx_callback_t callback, void *user_data)
577 {
578 	const struct can_nxp_s32_config *config = dev->config;
579 	uint8_t data_length = can_dlc_to_bytes(frame->dlc);
580 	struct can_nxp_s32_data *data = dev->data;
581 	Canexcel_Ip_StatusType status;
582 	enum can_state state;
583 	int alloc, mb_indx;
584 
585 #ifdef CAN_NXP_S32_FD_MODE
586 	if ((frame->flags & ~(CAN_FRAME_IDE | CAN_FRAME_FDF | CAN_FRAME_BRS)) != 0) {
587 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
588 		return -ENOTSUP;
589 	}
590 
591 	if ((frame->flags & CAN_FRAME_FDF) != 0 &&
592 			(config->base_sic->BCFG2 & CANXL_SIC_BCFG2_FDEN_MASK) == 0) {
593 		LOG_ERR("CAN FD format not supported in non-FD mode");
594 		return -ENOTSUP;
595 	}
596 
597 	if ((frame->flags & CAN_FRAME_BRS) != 0 &&
598 			~(config->base_sic->BCFG1 & CANXL_SIC_BCFG1_FDRSDIS_MASK) == 0) {
599 		LOG_ERR("CAN FD BRS not supported in non-FD mode");
600 		return -ENOTSUP;
601 	}
602 #else
603 	if ((frame->flags & ~CAN_FRAME_IDE) != 0) {
604 		LOG_ERR("unsupported CAN frame flags 0x%02x", frame->flags);
605 		return -ENOTSUP;
606 	}
607 #endif
608 
609 	if (data_length > sizeof(frame->data)) {
610 		LOG_ERR("data length (%d) > max frame data length (%d)",
611 			data_length, sizeof(frame->data));
612 		return -EINVAL;
613 	}
614 
615 	if ((frame->flags & CAN_FRAME_FDF) == 0) {
616 		if (frame->dlc > CAN_MAX_DLC) {
617 			LOG_ERR("DLC of %d for non-FD format frame", frame->dlc);
618 			return -EINVAL;
619 		}
620 #ifdef CAN_NXP_S32_FD_MODE
621 	} else {
622 		if (frame->dlc > CANFD_MAX_DLC) {
623 			LOG_ERR("DLC of %d for CAN FD format frame", frame->dlc);
624 			return -EINVAL;
625 		}
626 #endif
627 	}
628 
629 	if (!data->common.started) {
630 		return -ENETDOWN;
631 	}
632 
633 	can_nxp_s32_get_state(dev, &state, NULL);
634 	if (state == CAN_STATE_BUS_OFF) {
635 		LOG_ERR("Transmit failed, bus-off");
636 		return -ENETUNREACH;
637 	}
638 
639 	if (k_sem_take(&data->tx_allocs_sem, timeout) != 0) {
640 		return -EAGAIN;
641 	}
642 
643 	for (alloc = 0; alloc < CONFIG_CAN_NXP_S32_MAX_TX; alloc++) {
644 		if (!atomic_test_and_set_bit(data->tx_allocs, alloc)) {
645 			break;
646 		}
647 	}
648 
649 	data->tx_cbs[alloc].function = callback;
650 	data->tx_cbs[alloc].arg = user_data;
651 	mb_indx = ALLOC_IDX_TO_TXMB_IDX(alloc);
652 	data->tx_cbs[alloc].tx_info = (Canexcel_Ip_DataInfoType) {
653 		.frame = !!(frame->flags & CAN_FRAME_FDF) ?
654 				CANEXCEL_FD_FRAME : CANEXCEL_CLASIC_FRAME,
655 		.enable_brs = !!(frame->flags & CAN_FRAME_BRS) ? TRUE : FALSE,
656 		.idType = !!(frame->flags & CAN_FRAME_IDE) ?
657 				CANEXCEL_MSG_ID_EXT : CANEXCEL_MSG_ID_STD,
658 		.priority = 0,
659 		.fd_padding = 0,
660 		.dataLength = data_length,
661 		.is_polling = FALSE
662 	};
663 
664 	LOG_DBG("%s: Sending %d bytes Tx Mb %d, "
665 		"Tx Id: 0x%x, "
666 		"Id type: %s %s %s %s",
667 		dev->name, data_length,
668 		mb_indx, frame->id,
669 		!!(frame->flags & CAN_FRAME_IDE) ?
670 				"extended" : "standard",
671 		!!(frame->flags & CAN_FRAME_RTR) ? "RTR" : "",
672 		!!(frame->flags & CAN_FRAME_FDF) ? "FD frame" : "",
673 		!!(frame->flags & CAN_FRAME_BRS) ? "BRS" : "");
674 
675 	k_mutex_lock(&data->tx_mutex, K_FOREVER);
676 	/* Send MB Interrupt */
677 	status = Canexcel_Ip_SendFDMsg(config->instance, mb_indx, &data->tx_cbs[alloc].tx_info,
678 				frame->id, (uint8_t *)&frame->data, &data->tx_msg[alloc]);
679 	k_mutex_unlock(&data->tx_mutex);
680 
681 	if (status != CANEXCEL_STATUS_SUCCESS) {
682 		return -EIO;
683 	}
684 
685 	return 0;
686 }
687 
nxp_s32_zcan_timing_to_canxl_timing(const struct can_timing * timing,Canexcel_Ip_TimeSegmentType * canxl_timing)688 static void nxp_s32_zcan_timing_to_canxl_timing(const struct can_timing *timing,
689 							Canexcel_Ip_TimeSegmentType *canxl_timing)
690 {
691 	LOG_DBG("propSeg: %d, phase_seg1: %d, phase_seg2: %d, prescaler: %d, sjw: %d",
692 		timing->prop_seg, timing->phase_seg1, timing->phase_seg2,
693 		timing->prescaler, timing->sjw);
694 
695 	canxl_timing->propSeg = timing->prop_seg - 1U;
696 	canxl_timing->phaseSeg1 = timing->phase_seg1 - 1U;
697 	canxl_timing->phaseSeg2 = timing->phase_seg2 - 1U;
698 	canxl_timing->preDivider = timing->prescaler - 1U;
699 	canxl_timing->rJumpwidth = timing->sjw - 1U;
700 }
701 
can_nxp_s32_set_timing(const struct device * dev,const struct can_timing * timing)702 static int can_nxp_s32_set_timing(const struct device *dev,
703 			const struct can_timing *timing)
704 {
705 	const struct can_nxp_s32_config *config = dev->config;
706 	struct can_nxp_s32_data *data = dev->data;
707 	Canexcel_Ip_TimeSegmentType can_time_segment = {0};
708 
709 	if (data->common.started) {
710 		return -EBUSY;
711 	}
712 
713 	nxp_s32_zcan_timing_to_canxl_timing(timing, &can_time_segment);
714 
715 	/* Set timing for CAN instance*/
716 	CanXL_SetBaudRate(config->base_sic, &can_time_segment);
717 
718 	return 0;
719 }
720 
721 #ifdef CAN_NXP_S32_FD_MODE
can_nxp_s32_set_timing_data(const struct device * dev,const struct can_timing * timing_data)722 static int can_nxp_s32_set_timing_data(const struct device *dev,
723 			const struct can_timing *timing_data)
724 {
725 	const struct can_nxp_s32_config *config = dev->config;
726 	struct can_nxp_s32_data *data = dev->data;
727 	Canexcel_Ip_TimeSegmentType can_fd_time_segment = {0};
728 
729 	if (data->common.started) {
730 		return -EBUSY;
731 	}
732 
733 	nxp_s32_zcan_timing_to_canxl_timing(timing_data, &can_fd_time_segment);
734 
735 	/* Set timing for CAN FD instance*/
736 	CanXL_SetFDBaudRate(config->base_sic, &can_fd_time_segment);
737 
738 	Canexcel_Ip_SetTDCOffsetFD(config->instance, true, false,
739 				CAN_CALC_TDCO((timing_data), 0U, CAN_NXP_S32_TDCO_MAX));
740 
741 	return 0;
742 }
743 #endif
744 
can_nxp_s32_err_callback(const struct device * dev,Canexcel_Ip_EventType eventType,uint32_t u32SysStatus,const Canexcel_Ip_StateType * canexcelState)745 static void can_nxp_s32_err_callback(const struct device *dev,
746 					Canexcel_Ip_EventType eventType,
747 					uint32_t u32SysStatus,
748 					const Canexcel_Ip_StateType *canexcelState)
749 {
750 	const struct can_nxp_s32_config *config = dev->config;
751 	struct can_nxp_s32_data *data = dev->data;
752 	enum can_state state;
753 	struct can_bus_err_cnt err_cnt;
754 	void *cb_data = data->common.state_change_cb_user_data;
755 	can_tx_callback_t function;
756 	int alloc;
757 	void *arg;
758 
759 	switch (eventType) {
760 	case CANEXCEL_EVENT_TX_WARNING:
761 		LOG_DBG("Tx Warning (error 0x%x)", u32SysStatus);
762 		break;
763 	case CANEXCEL_EVENT_RX_WARNING:
764 		LOG_DBG("Rx Warning (error 0x%x)", u32SysStatus);
765 		break;
766 	case CANEXCEL_EVENT_BUSOFF:
767 		LOG_DBG("Bus Off (error 0x%x)", u32SysStatus);
768 		break;
769 	case CANEXCEL_EVENT_ERROR:
770 		LOG_DBG("Error Format Frames (error 0x%x)", u32SysStatus);
771 		break;
772 	case CANEXCEL_EVENT_ERROR_FD:
773 		LOG_DBG("Error Data Phase (error 0x%x)", u32SysStatus);
774 		break;
775 	case CANEXCEL_EVENT_PASSIVE:
776 		LOG_DBG("Error Passive (error 0x%x)", u32SysStatus);
777 		break;
778 	default:
779 		break;
780 	}
781 
782 	if (u32SysStatus & BCANXL_ST_BIT0ERR_MASK) {
783 		CAN_STATS_BIT0_ERROR_INC(dev);
784 	}
785 	if (u32SysStatus & BCANXL_ST_BIT1ERR_MASK) {
786 		CAN_STATS_BIT1_ERROR_INC(dev);
787 	}
788 	if (u32SysStatus & BCANXL_ST_ACKERR_MASK) {
789 		CAN_STATS_ACK_ERROR_INC(dev);
790 	}
791 	if (u32SysStatus & BCANXL_ST_STFERR_MASK) {
792 		CAN_STATS_STUFF_ERROR_INC(dev);
793 	}
794 	if (u32SysStatus & BCANXL_ST_FRMERR_MASK) {
795 		CAN_STATS_FORM_ERROR_INC(dev);
796 	}
797 	if (u32SysStatus & BCANXL_ST_CRCERR_MASK) {
798 		CAN_STATS_CRC_ERROR_INC(dev);
799 	}
800 	if (u32SysStatus & BCANXL_ST_OVRERR_MASK) {
801 		CAN_STATS_RX_OVERRUN_INC(dev);
802 	}
803 
804 	can_nxp_s32_get_state(dev, &state, &err_cnt);
805 	if (data->state != state) {
806 		data->state = state;
807 		if (data->common.state_change_cb) {
808 			data->common.state_change_cb(dev, state, err_cnt, cb_data);
809 		}
810 	}
811 
812 	if (state == CAN_STATE_BUS_OFF) {
813 		/* Abort any pending TX frames in case of bus-off */
814 		for (alloc = 0; alloc < CONFIG_CAN_NXP_S32_MAX_TX; alloc++) {
815 			/* Copy callback function and argument before clearing bit */
816 			function = data->tx_cbs[alloc].function;
817 			arg = data->tx_cbs[alloc].arg;
818 
819 			if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
820 				if (Canexcel_Ip_DeactivateMD(config->instance,
821 						ALLOC_IDX_TO_TXMB_IDX(alloc))) {
822 					LOG_ERR("Can't abort message !");
823 				};
824 
825 				function(dev, -ENETUNREACH, arg);
826 				k_sem_give(&data->tx_allocs_sem);
827 			}
828 		}
829 	}
830 }
831 
nxp_s32_msg_data_to_zcan_frame(Canexcel_RxFdMsg msg_data,struct can_frame * frame)832 static void nxp_s32_msg_data_to_zcan_frame(Canexcel_RxFdMsg msg_data,
833 							struct can_frame *frame)
834 {
835 	memset(frame, 0, sizeof(*frame));
836 
837 	if (!!(msg_data.Header.Id & CANXL_TX_HEADER_IDE_MASK)) {
838 		frame->flags |= CAN_FRAME_IDE;
839 	}
840 
841 	if (!!(frame->flags & CAN_FRAME_IDE)) {
842 		frame->id = (msg_data.Header.Id & CANXL_IP_ID_EXT_MASK);
843 	} else {
844 		frame->id = ((msg_data.Header.Id & CANXL_IP_ID_STD_MASK)
845 						>> CANXL_IP_ID_STD_SHIFT);
846 	}
847 
848 	frame->dlc = (msg_data.Header.Control & CANXL_TX_HEADER_DLC_MASK)
849 						>> CANXL_TX_HEADER_DLC_SHIFT;
850 
851 	if (!!(msg_data.Header.Control & CANXL_TX_HEADER_FDF_MASK)) {
852 		frame->flags |= CAN_FRAME_FDF;
853 	}
854 
855 	if (!!(msg_data.Header.Control & CANXL_TX_HEADER_BRS_MASK)) {
856 		frame->flags |= CAN_FRAME_BRS;
857 	}
858 
859 	if (!!(msg_data.Header.Id & CANXL_TX_HEADER_RTR_MASK)) {
860 		frame->flags |= CAN_FRAME_RTR;
861 	} else {
862 		memcpy(frame->data, msg_data.data, can_dlc_to_bytes(frame->dlc));
863 	}
864 
865 #ifdef CONFIG_CAN_RX_TIMESTAMP
866 	frame->timestamp = msg_data.timeStampL;
867 #endif /* CAN_RX_TIMESTAMP */
868 }
869 
can_nxp_s32_ctrl_callback(const struct device * dev,Canexcel_Ip_EventType eventType,uint32_t buffidx,const Canexcel_Ip_StateType * canexcelState)870 static void can_nxp_s32_ctrl_callback(const struct device *dev,
871 					Canexcel_Ip_EventType eventType, uint32_t buffidx,
872 					const Canexcel_Ip_StateType *canexcelState)
873 {
874 	const struct can_nxp_s32_config *config = dev->config;
875 	struct can_nxp_s32_data *data = dev->data;
876 	struct can_frame frame = {0};
877 	can_tx_callback_t tx_func;
878 	can_rx_callback_t rx_func;
879 	int alloc;
880 
881 	if (eventType == CANEXCEL_EVENT_TX_COMPLETE) {
882 		alloc = TX_MBIDX_TO_ALLOC_IDX(buffidx);
883 		tx_func = data->tx_cbs[alloc].function;
884 		LOG_DBG("%s: Sent Tx Mb %d", dev->name, buffidx);
885 		if (atomic_test_and_clear_bit(data->tx_allocs, alloc)) {
886 			tx_func(dev, 0, data->tx_cbs[alloc].arg);
887 			k_sem_give(&data->tx_allocs_sem);
888 		}
889 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
890 	} else if (eventType == CANEXCEL_EVENT_RXFIFO_COMPLETE) {
891 		uint8_t queue_idx = ((config->base_rx_fifo_ctrl->RXFCSTA &
892 				      CANXL_RXFIFO_CONTROL_RXFCSTA_HWPOINTER_MASK) >>
893 				     CANXL_RXFIFO_CONTROL_RXFCSTA_HWPOINTER_SHIFT) -
894 				    1;
895 
896 		alloc = can_nxp_s32_get_rx_fifo_filter(data, queue_idx);
897 
898 		if (alloc != -ENOSPC) {
899 			rx_func = data->rx_cbs[alloc].function;
900 			if (atomic_test_bit(data->rx_allocs, alloc)) {
901 				nxp_s32_msg_data_to_zcan_frame(data->rx_fifo[queue_idx], &frame);
902 
903 				LOG_DBG("%s: Received %d bytes Rx FiFo %d, "
904 					"Rx Id: 0x%x, "
905 					"Id type: %s %s %s %s",
906 					dev->name, can_dlc_to_bytes(frame.dlc),
907 					alloc, frame.id,
908 					!!(frame.flags & CAN_FRAME_IDE) ?
909 							"extended" : "standard",
910 					!!(frame.flags & CAN_FRAME_RTR) ? "RTR" : "",
911 					!!(frame.flags & CAN_FRAME_FDF) ? "FD frame" : "",
912 					!!(frame.flags & CAN_FRAME_BRS) ? "BRS" : "");
913 
914 				rx_func(dev, &frame, data->rx_cbs[alloc].arg);
915 			}
916 		}
917 
918 		/* Pop 1 (= RXFSYSPOP + 1) received RxFIFO message queue */
919 		config->base_rx_fifo_ctrl->RXFSYSPOP = 0;
920 #else
921 	} else if (eventType == CANEXCEL_EVENT_RX_COMPLETE) {
922 		alloc = RX_MBIDX_TO_ALLOC_IDX(buffidx);
923 		rx_func = data->rx_cbs[alloc].function;
924 		if (atomic_test_bit(data->rx_allocs, alloc)) {
925 			nxp_s32_msg_data_to_zcan_frame(data->rx_msg[alloc], &frame);
926 
927 			LOG_DBG("%s: Received %d bytes Rx Mb %d, "
928 				"Rx Id: 0x%x, "
929 				"Id type: %s %s %s %s",
930 				dev->name, can_dlc_to_bytes(frame.dlc),
931 				buffidx, frame.id,
932 				!!(frame.flags & CAN_FRAME_IDE) ?
933 						"extended" : "standard",
934 				!!(frame.flags & CAN_FRAME_RTR) ? "RTR" : "",
935 				!!(frame.flags & CAN_FRAME_FDF) ? "FD frame" : "",
936 				!!(frame.flags & CAN_FRAME_BRS) ? "BRS" : "");
937 
938 			rx_func(dev, &frame, data->rx_cbs[alloc].arg);
939 
940 			if (Canexcel_Ip_ReceiveFD(config->instance, buffidx,
941 				&data->rx_msg[alloc], FALSE) != CANEXCEL_STATUS_SUCCESS) {
942 				LOG_ERR("MB %d is not ready for receiving next message", buffidx);
943 			}
944 		}
945 #endif
946 	}
947 }
948 
can_nxp_s32_init(const struct device * dev)949 static int can_nxp_s32_init(const struct device *dev)
950 {
951 	const struct can_nxp_s32_config *config = dev->config;
952 	struct can_nxp_s32_data *data = dev->data;
953 	int err;
954 #ifdef CONFIG_CAN_RX_TIMESTAMP
955 	Canexcel_Ip_TimeStampConf_Type time_stamp = {
956 		.ts64bit = FALSE, /* Time stamp size is 32 bits */
957 		.capture = CANEXCEL_TIMESTAMPCAPTURE_END,
958 		.src = CANTBS_TIMESURCE_BUS1
959 	};
960 #endif
961 
962 	if (config->common.phy != NULL) {
963 		if (!device_is_ready(config->common.phy)) {
964 			LOG_ERR("CAN transceiver not ready");
965 			return -ENODEV;
966 		}
967 	}
968 
969 	if (!device_is_ready(config->clock_dev)) {
970 		LOG_ERR("Clock control device not ready");
971 		return -ENODEV;
972 	}
973 
974 	err = clock_control_on(config->clock_dev, config->clock_subsys);
975 	if (err) {
976 		LOG_ERR("Failed to enable clock");
977 		return err;
978 	}
979 
980 	k_mutex_init(&data->rx_mutex);
981 	k_mutex_init(&data->tx_mutex);
982 	k_sem_init(&data->tx_allocs_sem, CONFIG_CAN_NXP_S32_MAX_TX, CONFIG_CAN_NXP_S32_MAX_TX);
983 
984 	err = pinctrl_apply_state(config->pin_cfg, PINCTRL_STATE_DEFAULT);
985 	if (err < 0) {
986 		return err;
987 	}
988 
989 	/* Enable CANXL HW */
990 	IP_MC_RGM->PRST_0[0].PRST_0 &=
991 		~(MC_RGM_PRST_0_PERIPH_16_RST_MASK | MC_RGM_PRST_0_PERIPH_24_RST_MASK);
992 
993 	err = can_calc_timing(dev, &data->timing, config->common.bitrate,
994 			      config->common.sample_point);
995 	if (err == -EINVAL) {
996 		LOG_ERR("Can't find timing for given param");
997 		return -EIO;
998 	}
999 
1000 	if (err > 0) {
1001 		LOG_WRN("Sample-point error : %d", err);
1002 	}
1003 
1004 	LOG_DBG("Setting CAN bitrate %d:", config->common.bitrate);
1005 	nxp_s32_zcan_timing_to_canxl_timing(&data->timing, &config->can_cfg->bitrate);
1006 
1007 #ifdef CAN_NXP_S32_FD_MODE
1008 	err = can_calc_timing_data(dev, &data->timing_data, config->common.bitrate_data,
1009 				   config->common.sample_point_data);
1010 	if (err == -EINVAL) {
1011 		LOG_ERR("Can't find timing data for given param");
1012 		return -EIO;
1013 	}
1014 
1015 	if (err > 0) {
1016 		LOG_WRN("Sample-point-data err : %d", err);
1017 	}
1018 
1019 	LOG_DBG("Setting CAN FD bitrate %d:", config->common.bitrate_data);
1020 	nxp_s32_zcan_timing_to_canxl_timing(&data->timing_data, &config->can_cfg->Fd_bitrate);
1021 #endif
1022 
1023 	/* Initialize CAN structure */
1024 	Canexcel_Ip_Init(config->instance, config->can_cfg, data->can_state);
1025 
1026 #ifdef CAN_NXP_S32_FD_MODE
1027 	Canexcel_Ip_SetTDCOffsetFD(config->instance, true, false,
1028 				CAN_CALC_TDCO((&data->timing_data), 0U, CAN_NXP_S32_TDCO_MAX));
1029 #endif
1030 
1031 	/* Configure time stamp */
1032 #ifdef CONFIG_CAN_RX_TIMESTAMP
1033 	Canexcel_Ip_ConfigTimeStamp(config->instance, &time_stamp);
1034 #endif
1035 
1036 	/* Enable Interrupt */
1037 	Canexcel_Ip_EnableInterrupts(config->instance);
1038 
1039 	/* Enable Error Interrupt */
1040 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_RX_WARNING, TRUE);
1041 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_TX_WARNING, TRUE);
1042 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_ERR, TRUE);
1043 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_BUSOFF, TRUE);
1044 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_PASIVE_ERR, TRUE);
1045 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_RXSMB_OVER, TRUE);
1046 #ifdef CAN_NXP_S32_FD_MODE
1047 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_ERR_FAST, TRUE);
1048 #endif
1049 #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
1050 	CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_RXFIFO_OVER, TRUE);
1051 
1052 	/* Configure number of ID acceptance filters*/
1053 	config->base_rx_fifo->AFCFG =
1054 				CANXL_RXFIFO_AFCFG_ACPTID(CONFIG_CAN_NXP_S32_MAX_RX - 1);
1055 #endif
1056 
1057 	config->irq_config_func();
1058 
1059 	can_nxp_s32_get_state(dev, &data->state, NULL);
1060 
1061 	return 0;
1062 }
1063 
can_nxp_s32_isr_rx_tx_mru(const struct device * dev)1064 static void can_nxp_s32_isr_rx_tx_mru(const struct device *dev)
1065 {
1066 	const struct can_nxp_s32_config *config = dev->config;
1067 
1068 	Canexcel_Ip_RxTxIRQHandler(config->instance);
1069 
1070 	if ((config->base_mru->CHXCONFIG[0u].CH_CFG0 & CANXL_MRU_CH_CFG0_CHE_MASK)
1071 					== CANXL_MRU_CH_CFG0_CHE_MASK) {
1072 		Canexcel_Ip_MruIRQHandler(config->instance);
1073 	}
1074 }
1075 
can_nxp_s32_isr_error(const struct device * dev)1076 static void can_nxp_s32_isr_error(const struct device *dev)
1077 {
1078 	const struct can_nxp_s32_config *config = dev->config;
1079 
1080 	Canexcel_Ip_ErrIRQHandler(config->instance);
1081 }
1082 
1083 static DEVICE_API(can, can_nxp_s32_driver_api) = {
1084 	.get_capabilities = can_nxp_s32_get_capabilities,
1085 	.start = can_nxp_s32_start,
1086 	.stop = can_nxp_s32_stop,
1087 	.set_mode = can_nxp_s32_set_mode,
1088 	.set_timing = can_nxp_s32_set_timing,
1089 	.send = can_nxp_s32_send,
1090 	.add_rx_filter = can_nxp_s32_add_rx_filter,
1091 	.remove_rx_filter = can_nxp_s32_remove_rx_filter,
1092 	.get_state = can_nxp_s32_get_state,
1093 #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE
1094 	.recover = can_nxp_s32_recover,
1095 #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */
1096 	.set_state_change_callback = can_nxp_s32_set_state_change_callback,
1097 	.get_core_clock = can_nxp_s32_get_core_clock,
1098 	.get_max_filters = can_nxp_s32_get_max_filters,
1099 	.timing_min = {
1100 		.sjw = 0x01,
1101 		.prop_seg = 0x01,
1102 		.phase_seg1 = 0x01,
1103 		.phase_seg2 = 0x02,
1104 		.prescaler = 0x01
1105 	},
1106 	.timing_max = {
1107 		.sjw = 0x04,
1108 		.prop_seg = 0x08,
1109 		.phase_seg1 = 0x08,
1110 		.phase_seg2 = 0x08,
1111 		.prescaler = 0x100
1112 	},
1113 #ifdef CAN_NXP_S32_FD_MODE
1114 	.set_timing_data = can_nxp_s32_set_timing_data,
1115 	.timing_data_min = {
1116 		.sjw = 0x01,
1117 		.prop_seg = 0x01,
1118 		.phase_seg1 = 0x01,
1119 		.phase_seg2 = 0x02,
1120 		.prescaler = 0x01
1121 	},
1122 	.timing_data_max = {
1123 		.sjw = 0x04,
1124 		.prop_seg = 0x08,
1125 		.phase_seg1 = 0x08,
1126 		.phase_seg2 = 0x08,
1127 		.prescaler = 0x100
1128 	}
1129 #endif
1130 };
1131 
1132 #define _CAN_NXP_S32_IRQ_CONFIG(node_id, prop, idx)					\
1133 	do {										\
1134 		IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq),				\
1135 				DT_IRQ_BY_IDX(node_id, idx, priority),			\
1136 				UTIL_CAT(can_nxp_s32_isr_,				\
1137 					DT_STRING_TOKEN_BY_IDX(node_id, prop, idx)),	\
1138 				DEVICE_DT_GET(node_id),					\
1139 				DT_IRQ_BY_IDX(node_id, idx, flags));			\
1140 		irq_enable(DT_IRQ_BY_IDX(node_id, idx, irq));				\
1141 	} while (false);
1142 
1143 #define CAN_NXP_S32_IRQ_CONFIG(n)							\
1144 	static void can_irq_config_##n(void)						\
1145 	{										\
1146 		DT_INST_FOREACH_PROP_ELEM(n, interrupt_names, _CAN_NXP_S32_IRQ_CONFIG);	\
1147 	}
1148 
1149 #define CAN_NXP_S32_ERR_CALLBACK(n)							\
1150 	void nxp_s32_can_##n##_err_callback(uint8 instance, Canexcel_Ip_EventType eventType,\
1151 		uint32 u32SysStatus, const Canexcel_Ip_StateType *canexcelState)	\
1152 	{										\
1153 		const struct device *dev = DEVICE_DT_INST_GET(n);			\
1154 		can_nxp_s32_err_callback(dev, eventType, u32SysStatus, canexcelState);	\
1155 	}
1156 
1157 #define CAN_NXP_S32_CTRL_CALLBACK(n)							\
1158 	void nxp_s32_can_##n##_ctrl_callback(uint8 instance, Canexcel_Ip_EventType eventType,\
1159 			uint32 buffIdx, const Canexcel_Ip_StateType *canexcelState)	\
1160 	{										\
1161 		const struct device *dev = DEVICE_DT_INST_GET(n);			\
1162 		can_nxp_s32_ctrl_callback(dev, eventType, buffIdx, canexcelState);	\
1163 	}
1164 
1165 #if defined(CAN_NXP_S32_FD_MODE)
1166 #define CAN_NXP_S32_BRS		1
1167 #else
1168 #define CAN_NXP_S32_BRS		0
1169 #endif
1170 
1171 #define CAN_NXP_S32_HW_INSTANCE_CHECK(i, n) \
1172 	((DT_INST_REG_ADDR(n) == IP_CANXL_##i##__SIC_BASE) ? i : 0)
1173 
1174 #define CAN_NXP_S32_HW_INSTANCE(n) \
1175 	LISTIFY(__DEBRACKET CANXL_SIC_INSTANCE_COUNT, CAN_NXP_S32_HW_INSTANCE_CHECK, (|), n)
1176 
1177 #define CAN_NXP_S32_INIT_DEVICE(n)							\
1178 	CAN_NXP_S32_CTRL_CALLBACK(n)							\
1179 	CAN_NXP_S32_ERR_CALLBACK(n)							\
1180 	CAN_NXP_S32_IRQ_CONFIG(n)							\
1181 	PINCTRL_DT_INST_DEFINE(n);							\
1182 											\
1183 	__nocache Canexcel_Ip_StateType can_nxp_s32_state##n;				\
1184 	__nocache Canexcel_TxFdMsgType tx_msg##n[CONFIG_CAN_NXP_S32_MAX_TX];		\
1185 	IF_DISABLED(CONFIG_CAN_NXP_S32_RX_FIFO,						\
1186 		(__nocache Canexcel_RxFdMsg rx_msg_##n[CONFIG_CAN_NXP_S32_MAX_RX];))	\
1187 	IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO,						\
1188 		(__nocache Canexcel_RxFdMsg rx_fifo_##n[CAN_NXP_S32_RX_FIFO_DEPTH];	\
1189 		static Canexcel_Ip_RxFifoFilterID_ADDR					\
1190 			rx_fifo_filter##n[CONFIG_CAN_NXP_S32_MAX_RX];))			\
1191 	Canexcel_Ip_ConfigType can_nxp_s32_default_config##n = {			\
1192 		.rx_mbdesc = (uint8)IS_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO) ?		\
1193 							0 : CONFIG_CAN_NXP_S32_MAX_RX,	\
1194 		.tx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_TX,				\
1195 		.CanxlMode = CANEXCEL_LISTEN_ONLY_MODE,					\
1196 		.fd_enable = (boolean)IS_ENABLED(CAN_NXP_S32_FD_MODE),			\
1197 		.bitRateSwitch = (boolean)CAN_NXP_S32_BRS,				\
1198 		.ctrlOptions = CANXL_IP_BUSOFF_RECOVERY_U32,				\
1199 		.Callback = nxp_s32_can_##n##_ctrl_callback,				\
1200 		.ErrorCallback = nxp_s32_can_##n##_err_callback,			\
1201 		IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO,					\
1202 			(.is_rx_fifo_needed = (boolean)TRUE,				\
1203 			.pRxFifoConfig = {						\
1204 				.Rx_Fifo_Depth = CAN_NXP_S32_RX_FIFO_DEPTH,		\
1205 				.Rx_Fifo_Watermark = CAN_NXP_S32_RX_FIFO_WATERMARK,	\
1206 				.Rx_Fifo_Msg_Size = CAN_NXP_S32_DATA_LENGTH,		\
1207 				.Rx_Fifo_KeepLast = (boolean)FALSE,			\
1208 				.isPolling = (boolean)FALSE,				\
1209 				.MsgBuffersPtr = (uint32 *)rx_fifo_##n,			\
1210 			},))								\
1211 	};										\
1212 	static struct can_nxp_s32_data can_nxp_s32_data_##n = {				\
1213 		.can_state = (Canexcel_Ip_StateType *)&can_nxp_s32_state##n,		\
1214 		.tx_msg = tx_msg##n,							\
1215 		IF_DISABLED(CONFIG_CAN_NXP_S32_RX_FIFO,					\
1216 			(.rx_msg = rx_msg_##n,))					\
1217 		IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO,					\
1218 			(.rx_fifo = rx_fifo_##n,					\
1219 			.rx_fifo_filter =						\
1220 				(Canexcel_Ip_RxFifoFilterID_ADDR *)&rx_fifo_filter##n,))\
1221 	};										\
1222 	static struct can_nxp_s32_config can_nxp_s32_config_##n = {			\
1223 		.common = CAN_DT_DRIVER_CONFIG_INST_GET(n, 0, CAN_NXP_S32_MAX_BITRATE),	\
1224 		.base_sic = (CANXL_SIC_Type *)DT_INST_REG_ADDR_BY_NAME(n, sic),		\
1225 		IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO,					\
1226 			(.base_rx_fifo = (CANXL_RXFIFO_Type *)				\
1227 				DT_INST_REG_ADDR_BY_NAME(n, rx_fifo),			\
1228 			.base_rx_fifo_ctrl = (CANXL_RXFIFO_CONTROL_Type *)		\
1229 				DT_INST_REG_ADDR_BY_NAME(n, rx_fifo_ctrl),))		\
1230 		.base_mru = (CANXL_MRU_Type *)DT_INST_REG_ADDR_BY_NAME(n, mru),		\
1231 		.instance = CAN_NXP_S32_HW_INSTANCE(n),					\
1232 		.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),			\
1233 		.clock_subsys = (clock_control_subsys_t)				\
1234 				DT_INST_CLOCKS_CELL(n, name),				\
1235 		.pin_cfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),				\
1236 		.can_cfg = (Canexcel_Ip_ConfigType *)&can_nxp_s32_default_config##n,	\
1237 		.irq_config_func = can_irq_config_##n					\
1238 	};										\
1239 	static int can_nxp_s32_##n##_init(const struct device *dev)			\
1240 	{										\
1241 		return can_nxp_s32_init(dev);						\
1242 	}										\
1243 	CAN_DEVICE_DT_INST_DEFINE(n,							\
1244 				  can_nxp_s32_##n##_init,				\
1245 				  NULL,							\
1246 				  &can_nxp_s32_data_##n,				\
1247 				  &can_nxp_s32_config_##n,				\
1248 				  POST_KERNEL,						\
1249 				  CONFIG_CAN_INIT_PRIORITY,				\
1250 				  &can_nxp_s32_driver_api);
1251 
1252 DT_INST_FOREACH_STATUS_OKAY(CAN_NXP_S32_INIT_DEVICE)
1253