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