Skip to content

Commit 9eb0a55

Browse files
congnguyenhuunashif
authored andcommitted
drivers: nxp_s32_canxl: add support RX FIFO
Driver supports both CAN classic and CAN FD frames when using RX FIFO mode Signed-off-by: Cong Nguyen Huu <[email protected]>
1 parent c78f583 commit 9eb0a55

File tree

3 files changed

+201
-34
lines changed

3 files changed

+201
-34
lines changed

drivers/can/Kconfig.nxp_s32

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2022-2023 NXP
1+
# Copyright 2022-2024 NXP
22
# SPDX-License-Identifier: Apache-2.0
33

44
config CAN_NXP_S32_CANXL
@@ -10,17 +10,23 @@ config CAN_NXP_S32_CANXL
1010
Enable support for NXP S32 CANXL driver.
1111

1212
if CAN_NXP_S32_CANXL
13+
config CAN_NXP_S32_RX_FIFO
14+
bool "NXP S32 CANXL uses RX FIFO"
15+
default y
16+
help
17+
If this is enabled, NXP S32 CANXL uses RX FIFO.
18+
Otherwise NXP S32 CANXL uses RX Message Descriptor.
19+
1320
config CAN_NXP_S32_MAX_RX
1421
int "Maximum number of RX descriptors"
15-
depends on CAN_NXP_S32_CANXL
1622
default 16
17-
range 1 128
23+
range 1 32 if CAN_NXP_S32_RX_FIFO
24+
range 1 128 if !CAN_NXP_S32_RX_FIFO
1825
help
1926
Maximum number of RX descriptors.
2027

2128
config CAN_NXP_S32_MAX_TX
2229
int "Maximum number of TX descriptors"
23-
depends on CAN_NXP_S32_CANXL
2430
default 16
2531
range 1 128
2632
help

drivers/can/can_nxp_s32_canxl.c

Lines changed: 178 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022-2023 NXP
2+
* Copyright 2022-2024 NXP
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -23,8 +23,14 @@
2323
* Convert from RX message buffer index to allocated filter ID and
2424
* vice versa.
2525
*/
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
2630
#define RX_MBIDX_TO_ALLOC_IDX(x) (x - CONFIG_CAN_NXP_S32_MAX_TX)
2731
#define ALLOC_IDX_TO_RXMB_IDX(x) (x + CONFIG_CAN_NXP_S32_MAX_TX)
32+
#endif
33+
2834

2935
/*
3036
* Convert from TX message buffer index to allocated TX ID and vice
@@ -37,6 +43,13 @@
3743
#define CAN_NXP_S32_MAX_BITRATE 8000000
3844
#define CAN_NXP_S32_DATA_LENGTH 64
3945

46+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
47+
/* RX FIFO depth is fixed to the maximum value */
48+
#define CAN_NXP_S32_RX_FIFO_DEPTH 32
49+
/* RX FIFO water mark equal 1 that allows the interrupt is generated after 1 message received */
50+
#define CAN_NXP_S32_RX_FIFO_WATERMARK 1
51+
#endif
52+
4053
LOG_MODULE_REGISTER(nxp_s32_canxl, CONFIG_CAN_LOG_LEVEL);
4154

4255
#define SP_AND_TIMING_NOT_SET(inst) \
@@ -66,6 +79,10 @@ struct can_nxp_s32_config {
6679
CANXL_SIC_Type *base_sic;
6780
CANXL_GRP_CONTROL_Type *base_grp_ctrl;
6881
CANXL_DSC_CONTROL_Type *base_dsc_ctrl;
82+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
83+
CANXL_RXFIFO_Type * base_rx_fifo;
84+
CANXL_RXFIFO_CONTROL_Type *base_rx_fifo_ctrl;
85+
#endif
6986
uint8 instance;
7087
const struct device *clock_dev;
7188
clock_control_subsys_t clock_subsys;
@@ -98,7 +115,9 @@ struct can_nxp_s32_tx_callback {
98115

99116
struct can_nxp_s32_rx_callback {
100117
struct can_filter filter;
118+
#ifndef CONFIG_CAN_NXP_S32_RX_FIFO
101119
Canexcel_Ip_DataInfoType rx_info;
120+
#endif
102121
can_rx_callback_t function;
103122
void *arg;
104123
};
@@ -109,14 +128,21 @@ struct can_nxp_s32_data {
109128
ATOMIC_DEFINE(rx_allocs, CONFIG_CAN_NXP_S32_MAX_RX);
110129
struct k_mutex rx_mutex;
111130
struct can_nxp_s32_rx_callback rx_cbs[CONFIG_CAN_NXP_S32_MAX_RX];
131+
#ifndef CONFIG_CAN_NXP_S32_RX_FIFO
112132
Canexcel_RxFdMsg *rx_msg;
133+
#endif
113134

114135
ATOMIC_DEFINE(tx_allocs, CONFIG_CAN_NXP_S32_MAX_TX);
115136
struct k_sem tx_allocs_sem;
116137
struct k_mutex tx_mutex;
117138
struct can_nxp_s32_tx_callback tx_cbs[CONFIG_CAN_NXP_S32_MAX_TX];
118139
Canexcel_TxFdMsgType *tx_msg;
119140

141+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
142+
Canexcel_Ip_RxFifoFilterID_ADDR * rx_fifo_filter;
143+
Canexcel_RxFdMsg *rx_fifo;
144+
#endif
145+
120146
struct can_timing timing;
121147
#ifdef CONFIG_CAN_FD_MODE
122148
struct can_timing timing_data;
@@ -140,6 +166,50 @@ static int can_nxp_s32_get_capabilities(const struct device *dev, can_mode_t *ca
140166
return 0;
141167
}
142168

169+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
170+
static void can_nxp_s32_config_rx_fifo_filter(const struct device *dev, int filter_id)
171+
{
172+
const struct can_nxp_s32_config *config = dev->config;
173+
struct can_nxp_s32_data *data = dev->data;
174+
175+
/* Lock the RxFIFO by System by reading register */
176+
(void)config->base_rx_fifo_ctrl->RXFSYSLOCK;
177+
178+
CanXL_ConfigIDFilter(config->base_rx_fifo,
179+
&data->rx_fifo_filter[filter_id], filter_id);
180+
181+
if ((config->base_rx_fifo_ctrl->RXFCSTA & CANXL_RXFIFO_CONTROL_RXFCSTA_SYSLOCK_MASK)
182+
== CANXL_RXFIFO_CONTROL_RXFCSTA_SYSLOCK_MASK) {
183+
/* Clear the sys lock to enable transfers */
184+
config->base_rx_fifo_ctrl->RXFSYSLOCK =
185+
CANXL_RXFIFO_CONTROL_RXFSYSLOCK_SYSLOCK_MASK;
186+
}
187+
}
188+
189+
/* Get the RxFiFO filter matched with the received RxFIFO message queue */
190+
static inline int can_nxp_s32_get_rx_fifo_filter(struct can_nxp_s32_data *data)
191+
{
192+
int alloc = -ENOSPC;
193+
uint32_t mask;
194+
195+
for (int filter_id = 0; filter_id < CONFIG_CAN_NXP_S32_MAX_RX; filter_id++) {
196+
mask = data->rx_fifo_filter[filter_id].idAddrFilterL;
197+
198+
if (mask == 0) {
199+
continue;
200+
}
201+
202+
if ((data->rx_fifo[0].Header.Id & mask) ==
203+
(data->rx_fifo_filter[filter_id].idAddrFilterH & mask)) {
204+
alloc = filter_id;
205+
break;
206+
}
207+
}
208+
209+
return alloc;
210+
}
211+
#endif
212+
143213
static int can_nxp_s32_start(const struct device *dev)
144214
{
145215
const struct can_nxp_s32_config *config = dev->config;
@@ -404,9 +474,20 @@ static void can_nxp_s32_remove_rx_filter(const struct device *dev, int filter_id
404474
k_mutex_lock(&data->rx_mutex, K_FOREVER);
405475

406476
if (atomic_test_and_clear_bit(data->rx_allocs, filter_id)) {
477+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
478+
data->rx_fifo_filter[mb_indx].idAddrFilterL = 0;
479+
data->rx_fifo_filter[mb_indx].idAddrFilterH = 0;
480+
481+
Canexcel_Ip_EnterFreezeMode(config->instance);
482+
483+
can_nxp_s32_config_rx_fifo_filter(dev, mb_indx);
484+
485+
Canexcel_Ip_ExitFreezeMode(config->instance);
486+
#else
407487
if (can_nxp_s32_abort_msg(config, mb_indx)) {
408488
LOG_ERR("Can't abort message !");
409489
};
490+
#endif
410491

411492
data->rx_cbs[filter_id].function = NULL;
412493
data->rx_cbs[filter_id].arg = NULL;
@@ -458,31 +539,47 @@ static int can_nxp_s32_add_rx_filter(const struct device *dev,
458539
data->rx_cbs[alloc].arg = user_data;
459540
data->rx_cbs[alloc].filter = *filter;
460541

461-
data->rx_cbs[alloc].rx_info = (Canexcel_Ip_DataInfoType) {
462-
.frame = !!(filter->flags & CAN_FILTER_FDF) ?
463-
CANEXCEL_FD_FRAME : CANEXCEL_CLASIC_FRAME,
464-
.idType = !!(filter->flags & CAN_FILTER_IDE) ?
465-
CANEXCEL_MSG_ID_EXT : CANEXCEL_MSG_ID_STD,
466-
.dataLength = CAN_NXP_S32_DATA_LENGTH,
467-
};
468-
469542
/* Set Rx Mb individual mask for */
470543
mb_indx = ALLOC_IDX_TO_RXMB_IDX(alloc);
471544
if (!!(filter->flags & CAN_FILTER_IDE)) {
472-
mask = (filter->mask & CANXL_IP_ID_EXT_MASK);
545+
mask = filter->mask & CANXL_IP_ID_EXT_MASK;
473546
} else {
474-
mask = ((filter->mask << CANXL_IP_ID_STD_SHIFT) & CANXL_IP_ID_STD_MASK);
547+
mask = (filter->mask << CANXL_IP_ID_STD_SHIFT) & CANXL_IP_ID_STD_MASK;
475548
}
476549

477550
Canexcel_Ip_EnterFreezeMode(config->instance);
478551

552+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
553+
uint32_t filter_id;
554+
555+
if (!!(filter->flags & CAN_FILTER_IDE)) {
556+
filter_id = filter->id & CANXL_IP_ID_EXT_MASK;
557+
} else {
558+
filter_id = (filter->id << CANXL_IP_ID_STD_SHIFT) & CANXL_IP_ID_STD_MASK;
559+
}
560+
561+
data->rx_fifo_filter[mb_indx].filterType = CANEXCEL_IP_RX_FIFO_MASK_FILTER;
562+
data->rx_fifo_filter[mb_indx].idAddrFilterL = mask;
563+
data->rx_fifo_filter[mb_indx].idAddrFilterH = filter_id;
564+
565+
can_nxp_s32_config_rx_fifo_filter(dev, mb_indx);
566+
#else
567+
data->rx_cbs[alloc].rx_info = (Canexcel_Ip_DataInfoType) {
568+
.frame = !!(filter->flags & CAN_FILTER_FDF) ?
569+
CANEXCEL_FD_FRAME : CANEXCEL_CLASIC_FRAME,
570+
.idType = !!(filter->flags & CAN_FILTER_IDE) ?
571+
CANEXCEL_MSG_ID_EXT : CANEXCEL_MSG_ID_STD,
572+
.dataLength = CAN_NXP_S32_DATA_LENGTH,
573+
};
574+
479575
Canexcel_Ip_SetRxIndividualMask(config->instance, mb_indx,
480576
data->rx_cbs[alloc].rx_info.frame, mask);
481577

482578
Canexcel_Ip_ConfigRx(config->instance, mb_indx, filter->id,
483579
&data->rx_cbs[alloc].rx_info);
484580

485581
Canexcel_Ip_ReceiveFD(config->instance, mb_indx, &data->rx_msg[alloc], FALSE);
582+
#endif
486583

487584
Canexcel_Ip_ExitFreezeMode(config->instance);
488585

@@ -775,7 +872,6 @@ static void can_nxp_s32_ctrl_callback(const struct device *dev,
775872
struct can_frame frame = {0};
776873
can_tx_callback_t tx_func;
777874
can_rx_callback_t rx_func;
778-
Canexcel_Ip_StatusType status;
779875
int alloc;
780876

781877
if (eventType == CANEXCEL_EVENT_TX_COMPLETE) {
@@ -786,6 +882,33 @@ static void can_nxp_s32_ctrl_callback(const struct device *dev,
786882
tx_func(dev, 0, data->tx_cbs[alloc].arg);
787883
k_sem_give(&data->tx_allocs_sem);
788884
}
885+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
886+
} else if (eventType == CANEXCEL_EVENT_RXFIFO_COMPLETE) {
887+
alloc = can_nxp_s32_get_rx_fifo_filter(data);
888+
889+
if (alloc != -ENOSPC) {
890+
rx_func = data->rx_cbs[alloc].function;
891+
if (atomic_test_bit(data->rx_allocs, alloc)) {
892+
nxp_s32_msg_data_to_zcan_frame(data->rx_fifo[0], &frame);
893+
894+
LOG_DBG("%s: Received %d bytes Rx FiFo %d, "
895+
"Rx Id: 0x%x, "
896+
"Id type: %s %s %s %s",
897+
dev->name, can_dlc_to_bytes(frame.dlc),
898+
alloc, frame.id,
899+
!!(frame.flags & CAN_FRAME_IDE) ?
900+
"extended" : "standard",
901+
!!(frame.flags & CAN_FRAME_RTR) ? "RTR" : "",
902+
!!(frame.flags & CAN_FRAME_FDF) ? "FD frame" : "",
903+
!!(frame.flags & CAN_FRAME_BRS) ? "BRS" : "");
904+
905+
rx_func(dev, &frame, data->rx_cbs[alloc].arg);
906+
}
907+
}
908+
909+
/* Pop 1 (= RXFSYSPOP + 1) received RxFIFO message queue */
910+
config->base_rx_fifo_ctrl->RXFSYSPOP = 0;
911+
#else
789912
} else if (eventType == CANEXCEL_EVENT_RX_COMPLETE) {
790913
alloc = RX_MBIDX_TO_ALLOC_IDX(buffidx);
791914
rx_func = data->rx_cbs[alloc].function;
@@ -805,12 +928,12 @@ static void can_nxp_s32_ctrl_callback(const struct device *dev,
805928

806929
rx_func(dev, &frame, data->rx_cbs[alloc].arg);
807930

808-
status = Canexcel_Ip_ReceiveFD(config->instance, buffidx,
809-
&data->rx_msg[alloc], FALSE);
810-
if (status != CANEXCEL_STATUS_SUCCESS) {
931+
if (Canexcel_Ip_ReceiveFD(config->instance, buffidx,
932+
&data->rx_msg[alloc], FALSE) != CANEXCEL_STATUS_SUCCESS) {
811933
LOG_ERR("MB %d is not ready for receiving next message", buffidx);
812934
}
813935
}
936+
#endif
814937
}
815938
}
816939

@@ -925,6 +1048,13 @@ static int can_nxp_s32_init(const struct device *dev)
9251048
CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_ERR, TRUE);
9261049
CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_BUSOFF, TRUE);
9271050
CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_PASIVE_ERR, TRUE);
1051+
#ifdef CONFIG_CAN_NXP_S32_RX_FIFO
1052+
CanXL_SetErrIntCmd(config->base_sic, CANXL_INT_RXFIFO_OVER, TRUE);
1053+
1054+
/* Configure number of ID acceptance filters*/
1055+
config->base_rx_fifo->AFCFG =
1056+
CANXL_RXFIFO_AFCFG_ACPTID(CONFIG_CAN_NXP_S32_MAX_RX - 1);
1057+
#endif
9281058

9291059
config->irq_config_func();
9301060

@@ -1063,30 +1193,57 @@ static const struct can_driver_api can_nxp_s32_driver_api = {
10631193
CAN_NXP_S32_ERR_CALLBACK(n) \
10641194
CAN_NXP_S32_IRQ_CONFIG(n) \
10651195
PINCTRL_DT_INST_DEFINE(n); \
1196+
\
1197+
__nocache Canexcel_Ip_StateType can_nxp_s32_state##n; \
1198+
__nocache Canexcel_TxFdMsgType tx_msg##n[CONFIG_CAN_NXP_S32_MAX_TX]; \
1199+
IF_DISABLED(CONFIG_CAN_NXP_S32_RX_FIFO, \
1200+
(__nocache Canexcel_RxFdMsg rx_msg_##n[CONFIG_CAN_NXP_S32_MAX_RX];)) \
1201+
IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO, \
1202+
(__nocache Canexcel_RxFdMsg rx_fifo_##n[CAN_NXP_S32_RX_FIFO_DEPTH]; \
1203+
static Canexcel_Ip_RxFifoFilterID_ADDR \
1204+
rx_fifo_filter##n[CONFIG_CAN_NXP_S32_MAX_RX];)) \
10661205
Canexcel_Ip_ConfigType can_nxp_s32_default_config##n = { \
1067-
.rx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_RX, \
1206+
.rx_mbdesc = (uint8)IS_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO) ? \
1207+
0 : CONFIG_CAN_NXP_S32_MAX_RX, \
10681208
.tx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_TX, \
10691209
.CanxlMode = CANEXCEL_LISTEN_ONLY_MODE, \
10701210
.fd_enable = (boolean)CAN_NXP_S32_FD_MODE, \
10711211
.bitRateSwitch = (boolean)CAN_NXP_S32_BRS, \
10721212
.ctrlOptions = (uint32)CAN_NXP_S32_CTRL_OPTIONS, \
10731213
.Callback = nxp_s32_can_##n##_ctrl_callback, \
1074-
.ErrorCallback = nxp_s32_can_##n##_err_callback \
1214+
.ErrorCallback = nxp_s32_can_##n##_err_callback, \
1215+
IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO, \
1216+
(.is_rx_fifo_needed = (boolean)TRUE, \
1217+
.pRxFifoConfig = { \
1218+
.Rx_Fifo_Depth = CAN_NXP_S32_RX_FIFO_DEPTH, \
1219+
.Rx_Fifo_Watermark = CAN_NXP_S32_RX_FIFO_WATERMARK, \
1220+
.Rx_Fifo_Msg_Size = CAN_NXP_S32_DATA_LENGTH, \
1221+
.Rx_Fifo_KeepLast = (boolean)FALSE, \
1222+
.isPolling = (boolean)FALSE, \
1223+
.MsgBuffersPtr = (uint32 *)rx_fifo_##n, \
1224+
},)) \
10751225
}; \
1076-
__nocache Canexcel_Ip_StateType can_nxp_s32_state##n; \
1077-
__nocache Canexcel_TxFdMsgType tx_msg##n[CONFIG_CAN_NXP_S32_MAX_TX]; \
1078-
__nocache Canexcel_RxFdMsg rx_msg_##n[CONFIG_CAN_NXP_S32_MAX_RX]; \
10791226
static struct can_nxp_s32_data can_nxp_s32_data_##n = { \
10801227
.can_state = (Canexcel_Ip_StateType *)&can_nxp_s32_state##n, \
10811228
.tx_msg = tx_msg##n, \
1082-
.rx_msg = rx_msg_##n, \
1229+
IF_DISABLED(CONFIG_CAN_NXP_S32_RX_FIFO, \
1230+
(.rx_msg = rx_msg_##n,)) \
1231+
IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO, \
1232+
(.rx_fifo = rx_fifo_##n, \
1233+
.rx_fifo_filter = \
1234+
(Canexcel_Ip_RxFifoFilterID_ADDR *)&rx_fifo_filter##n,))\
10831235
}; \
10841236
static struct can_nxp_s32_config can_nxp_s32_config_##n = { \
10851237
.base_sic = (CANXL_SIC_Type *)DT_INST_REG_ADDR_BY_NAME(n, sic), \
10861238
.base_grp_ctrl = (CANXL_GRP_CONTROL_Type *) \
10871239
DT_INST_REG_ADDR_BY_NAME(n, grp_ctrl), \
10881240
.base_dsc_ctrl = (CANXL_DSC_CONTROL_Type *) \
10891241
DT_INST_REG_ADDR_BY_NAME(n, dsc_ctrl), \
1242+
IF_ENABLED(CONFIG_CAN_NXP_S32_RX_FIFO, \
1243+
(.base_rx_fifo = (CANXL_RXFIFO_Type *) \
1244+
DT_INST_REG_ADDR_BY_NAME(n, rx_fifo), \
1245+
.base_rx_fifo_ctrl = (CANXL_RXFIFO_CONTROL_Type *) \
1246+
DT_INST_REG_ADDR_BY_NAME(n, rx_fifo_ctrl),)) \
10901247
.instance = CAN_NXP_S32_HW_INSTANCE(n), \
10911248
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
10921249
.clock_subsys = (clock_control_subsys_t) \

0 commit comments

Comments
 (0)