1
1
/*
2
- * Copyright 2022-2023 NXP
2
+ * Copyright 2022-2024 NXP
3
3
*
4
4
* SPDX-License-Identifier: Apache-2.0
5
5
*/
23
23
* Convert from RX message buffer index to allocated filter ID and
24
24
* vice versa.
25
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
26
30
#define RX_MBIDX_TO_ALLOC_IDX (x ) (x - CONFIG_CAN_NXP_S32_MAX_TX)
27
31
#define ALLOC_IDX_TO_RXMB_IDX (x ) (x + CONFIG_CAN_NXP_S32_MAX_TX)
32
+ #endif
33
+
28
34
29
35
/*
30
36
* Convert from TX message buffer index to allocated TX ID and vice
37
43
#define CAN_NXP_S32_MAX_BITRATE 8000000
38
44
#define CAN_NXP_S32_DATA_LENGTH 64
39
45
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
+
40
53
LOG_MODULE_REGISTER (nxp_s32_canxl , CONFIG_CAN_LOG_LEVEL );
41
54
42
55
#define SP_AND_TIMING_NOT_SET (inst ) \
@@ -66,6 +79,10 @@ struct can_nxp_s32_config {
66
79
CANXL_SIC_Type * base_sic ;
67
80
CANXL_GRP_CONTROL_Type * base_grp_ctrl ;
68
81
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
69
86
uint8 instance ;
70
87
const struct device * clock_dev ;
71
88
clock_control_subsys_t clock_subsys ;
@@ -98,7 +115,9 @@ struct can_nxp_s32_tx_callback {
98
115
99
116
struct can_nxp_s32_rx_callback {
100
117
struct can_filter filter ;
118
+ #ifndef CONFIG_CAN_NXP_S32_RX_FIFO
101
119
Canexcel_Ip_DataInfoType rx_info ;
120
+ #endif
102
121
can_rx_callback_t function ;
103
122
void * arg ;
104
123
};
@@ -109,14 +128,21 @@ struct can_nxp_s32_data {
109
128
ATOMIC_DEFINE (rx_allocs , CONFIG_CAN_NXP_S32_MAX_RX );
110
129
struct k_mutex rx_mutex ;
111
130
struct can_nxp_s32_rx_callback rx_cbs [CONFIG_CAN_NXP_S32_MAX_RX ];
131
+ #ifndef CONFIG_CAN_NXP_S32_RX_FIFO
112
132
Canexcel_RxFdMsg * rx_msg ;
133
+ #endif
113
134
114
135
ATOMIC_DEFINE (tx_allocs , CONFIG_CAN_NXP_S32_MAX_TX );
115
136
struct k_sem tx_allocs_sem ;
116
137
struct k_mutex tx_mutex ;
117
138
struct can_nxp_s32_tx_callback tx_cbs [CONFIG_CAN_NXP_S32_MAX_TX ];
118
139
Canexcel_TxFdMsgType * tx_msg ;
119
140
141
+ #ifdef CONFIG_CAN_NXP_S32_RX_FIFO
142
+ Canexcel_Ip_RxFifoFilterID_ADDR * rx_fifo_filter ;
143
+ Canexcel_RxFdMsg * rx_fifo ;
144
+ #endif
145
+
120
146
struct can_timing timing ;
121
147
#ifdef CONFIG_CAN_FD_MODE
122
148
struct can_timing timing_data ;
@@ -140,6 +166,50 @@ static int can_nxp_s32_get_capabilities(const struct device *dev, can_mode_t *ca
140
166
return 0 ;
141
167
}
142
168
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
+
143
213
static int can_nxp_s32_start (const struct device * dev )
144
214
{
145
215
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
404
474
k_mutex_lock (& data -> rx_mutex , K_FOREVER );
405
475
406
476
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
407
487
if (can_nxp_s32_abort_msg (config , mb_indx )) {
408
488
LOG_ERR ("Can't abort message !" );
409
489
};
490
+ #endif
410
491
411
492
data -> rx_cbs [filter_id ].function = NULL ;
412
493
data -> rx_cbs [filter_id ].arg = NULL ;
@@ -458,31 +539,47 @@ static int can_nxp_s32_add_rx_filter(const struct device *dev,
458
539
data -> rx_cbs [alloc ].arg = user_data ;
459
540
data -> rx_cbs [alloc ].filter = * filter ;
460
541
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
-
469
542
/* Set Rx Mb individual mask for */
470
543
mb_indx = ALLOC_IDX_TO_RXMB_IDX (alloc );
471
544
if (!!(filter -> flags & CAN_FILTER_IDE )) {
472
- mask = ( filter -> mask & CANXL_IP_ID_EXT_MASK ) ;
545
+ mask = filter -> mask & CANXL_IP_ID_EXT_MASK ;
473
546
} 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 ;
475
548
}
476
549
477
550
Canexcel_Ip_EnterFreezeMode (config -> instance );
478
551
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
+
479
575
Canexcel_Ip_SetRxIndividualMask (config -> instance , mb_indx ,
480
576
data -> rx_cbs [alloc ].rx_info .frame , mask );
481
577
482
578
Canexcel_Ip_ConfigRx (config -> instance , mb_indx , filter -> id ,
483
579
& data -> rx_cbs [alloc ].rx_info );
484
580
485
581
Canexcel_Ip_ReceiveFD (config -> instance , mb_indx , & data -> rx_msg [alloc ], FALSE);
582
+ #endif
486
583
487
584
Canexcel_Ip_ExitFreezeMode (config -> instance );
488
585
@@ -775,7 +872,6 @@ static void can_nxp_s32_ctrl_callback(const struct device *dev,
775
872
struct can_frame frame = {0 };
776
873
can_tx_callback_t tx_func ;
777
874
can_rx_callback_t rx_func ;
778
- Canexcel_Ip_StatusType status ;
779
875
int alloc ;
780
876
781
877
if (eventType == CANEXCEL_EVENT_TX_COMPLETE ) {
@@ -786,6 +882,33 @@ static void can_nxp_s32_ctrl_callback(const struct device *dev,
786
882
tx_func (dev , 0 , data -> tx_cbs [alloc ].arg );
787
883
k_sem_give (& data -> tx_allocs_sem );
788
884
}
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
789
912
} else if (eventType == CANEXCEL_EVENT_RX_COMPLETE ) {
790
913
alloc = RX_MBIDX_TO_ALLOC_IDX (buffidx );
791
914
rx_func = data -> rx_cbs [alloc ].function ;
@@ -805,12 +928,12 @@ static void can_nxp_s32_ctrl_callback(const struct device *dev,
805
928
806
929
rx_func (dev , & frame , data -> rx_cbs [alloc ].arg );
807
930
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 ) {
811
933
LOG_ERR ("MB %d is not ready for receiving next message" , buffidx );
812
934
}
813
935
}
936
+ #endif
814
937
}
815
938
}
816
939
@@ -925,6 +1048,13 @@ static int can_nxp_s32_init(const struct device *dev)
925
1048
CanXL_SetErrIntCmd (config -> base_sic , CANXL_INT_ERR , TRUE);
926
1049
CanXL_SetErrIntCmd (config -> base_sic , CANXL_INT_BUSOFF , TRUE);
927
1050
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
928
1058
929
1059
config -> irq_config_func ();
930
1060
@@ -1063,30 +1193,57 @@ static const struct can_driver_api can_nxp_s32_driver_api = {
1063
1193
CAN_NXP_S32_ERR_CALLBACK(n) \
1064
1194
CAN_NXP_S32_IRQ_CONFIG(n) \
1065
1195
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];)) \
1066
1205
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, \
1068
1208
.tx_mbdesc = (uint8)CONFIG_CAN_NXP_S32_MAX_TX, \
1069
1209
.CanxlMode = CANEXCEL_LISTEN_ONLY_MODE, \
1070
1210
.fd_enable = (boolean)CAN_NXP_S32_FD_MODE, \
1071
1211
.bitRateSwitch = (boolean)CAN_NXP_S32_BRS, \
1072
1212
.ctrlOptions = (uint32)CAN_NXP_S32_CTRL_OPTIONS, \
1073
1213
.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
+ },)) \
1075
1225
}; \
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]; \
1079
1226
static struct can_nxp_s32_data can_nxp_s32_data_##n = { \
1080
1227
.can_state = (Canexcel_Ip_StateType *)&can_nxp_s32_state##n, \
1081
1228
.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,))\
1083
1235
}; \
1084
1236
static struct can_nxp_s32_config can_nxp_s32_config_##n = { \
1085
1237
.base_sic = (CANXL_SIC_Type *)DT_INST_REG_ADDR_BY_NAME(n, sic), \
1086
1238
.base_grp_ctrl = (CANXL_GRP_CONTROL_Type *) \
1087
1239
DT_INST_REG_ADDR_BY_NAME(n, grp_ctrl), \
1088
1240
.base_dsc_ctrl = (CANXL_DSC_CONTROL_Type *) \
1089
1241
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),)) \
1090
1247
.instance = CAN_NXP_S32_HW_INSTANCE(n), \
1091
1248
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
1092
1249
.clock_subsys = (clock_control_subsys_t) \
0 commit comments