drivers: can: stm32: fdcan: move register definitions to implementation

Move definitions of the STM32 FDCAN specific registers to the front-end
driver implementation and implement remapping of these registers to/from
the standard Bosch M_CAN registers.

Some of the STM32 FDCAN register bit fields are limited in size compared to
the Bosch M_CAN specification. This is due to hardware limitations on the
number of elements in the various sections of the Message RAM. Add build
assertions to ensure the number of elements specified do not exceed the
hardware limitations instead of using custom definitions for these fields.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
Henrik Brix Andersen 2023-05-07 19:48:21 +02:00 committed by Carles Cufí
commit 3ee2b4c31a
3 changed files with 414 additions and 228 deletions

View file

@ -1200,7 +1200,6 @@ unlock:
k_mutex_unlock(&data->lock);
}
#ifndef CONFIG_CAN_STM32FD
int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba)
{
struct can_mcan_data *data = dev->data;
@ -1289,7 +1288,6 @@ int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba)
return 0;
}
#endif /* !CONFIG_CAN_STM32FD */
int can_mcan_init(const struct device *dev)
{
@ -1391,7 +1389,6 @@ int can_mcan_init(const struct device *dev)
}
#endif /* defined(CONFIG_CAN_DELAY_COMP) && defined(CONFIG_CAN_FD_MODE) */
#ifndef CONFIG_CAN_STM32FD
err = can_mcan_read_reg(dev, CAN_MCAN_GFC, &reg);
if (err != 0) {
return err;
@ -1403,7 +1400,6 @@ int can_mcan_init(const struct device *dev)
if (err != 0) {
return err;
}
#endif /* !CONFIG_CAN_STM32FD */
if (config->sample_point) {
err = can_calc_timing(dev, &timing, config->bus_speed, config->sample_point);
@ -1460,11 +1456,8 @@ int can_mcan_init(const struct device *dev)
if (err != 0) {
return err;
}
#ifdef CONFIG_CAN_STM32FD
reg = CAN_MCAN_ILS_RXFIFO0 | CAN_MCAN_ILS_RXFIFO1;
#else /* CONFIG_CAN_STM32FD */
reg = CAN_MCAN_ILS_RF0NL | CAN_MCAN_ILS_RF1NL;
#endif /* !CONFIG_CAN_STM32FD */
err = can_mcan_write_reg(dev, CAN_MCAN_ILS, reg);
if (err != 0) {
return err;

View file

@ -18,9 +18,6 @@
/*
* The Bosch M_CAN register definitions correspond to those found in the Bosch M_CAN Controller Area
* Network User's Manual, Revision 3.3.0.
*
* The STMicroelectronics STM32 FDCAN definitions correspond to those found in the
* STMicroelectronics STM32G4 Series Reference manual (RM0440), Rev 7.
*/
/* Core Release register */
@ -50,12 +47,10 @@
/* Test register */
#define CAN_MCAN_TEST 0x010
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_TEST_SVAL BIT(21)
#define CAN_MCAN_TEST_TXBNS GENMASK(20, 16)
#define CAN_MCAN_TEST_PVAL BIT(13)
#define CAN_MCAN_TEST_TXBNP GENMASK(12, 8)
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_TEST_RX BIT(7)
#define CAN_MCAN_TEST_TX GENMASK(6, 5)
#define CAN_MCAN_TEST_LBCK BIT(4)
@ -71,10 +66,8 @@
#define CAN_MCAN_CCCR_TXP BIT(14)
#define CAN_MCAN_CCCR_EFBI BIT(13)
#define CAN_MCAN_CCCR_PXHD BIT(12)
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_CCCR_WMM BIT(11)
#define CAN_MCAN_CCCR_UTSU BIT(10)
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_CCCR_BRSE BIT(9)
#define CAN_MCAN_CCCR_FDOE BIT(8)
#define CAN_MCAN_CCCR_TEST BIT(7)
@ -140,32 +133,6 @@
/* Interrupt register */
#define CAN_MCAN_IR 0x050
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_IR_ARA BIT(23)
#define CAN_MCAN_IR_PED BIT(22)
#define CAN_MCAN_IR_PEA BIT(21)
#define CAN_MCAN_IR_WDI BIT(20)
#define CAN_MCAN_IR_BO BIT(19)
#define CAN_MCAN_IR_EW BIT(18)
#define CAN_MCAN_IR_EP BIT(17)
#define CAN_MCAN_IR_ELO BIT(16)
#define CAN_MCAN_IR_TOO BIT(15)
#define CAN_MCAN_IR_MRAF BIT(14)
#define CAN_MCAN_IR_TSW BIT(13)
#define CAN_MCAN_IR_TEFL BIT(12)
#define CAN_MCAN_IR_TEFF BIT(11)
#define CAN_MCAN_IR_TEFN BIT(10)
#define CAN_MCAN_IR_TFE BIT(9)
#define CAN_MCAN_IR_TCF BIT(8)
#define CAN_MCAN_IR_TC BIT(7)
#define CAN_MCAN_IR_HPM BIT(6)
#define CAN_MCAN_IR_RF1L BIT(5)
#define CAN_MCAN_IR_RF1F BIT(4)
#define CAN_MCAN_IR_RF1N BIT(3)
#define CAN_MCAN_IR_RF0L BIT(2)
#define CAN_MCAN_IR_RF0F BIT(1)
#define CAN_MCAN_IR_RF0N BIT(0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_IR_ARA BIT(29)
#define CAN_MCAN_IR_PED BIT(28)
#define CAN_MCAN_IR_PEA BIT(27)
@ -196,36 +163,9 @@
#define CAN_MCAN_IR_RF0F BIT(2)
#define CAN_MCAN_IR_RF0W BIT(1)
#define CAN_MCAN_IR_RF0N BIT(0)
#endif /* !CONFIG_CAN_STM32FD */
/* Interrupt Enable register */
#define CAN_MCAN_IE 0x054
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_IE_ARAE BIT(23)
#define CAN_MCAN_IE_PEDE BIT(22)
#define CAN_MCAN_IE_PEAE BIT(21)
#define CAN_MCAN_IE_WDIE BIT(20)
#define CAN_MCAN_IE_BOE BIT(19)
#define CAN_MCAN_IE_EWE BIT(18)
#define CAN_MCAN_IE_EPE BIT(17)
#define CAN_MCAN_IE_ELOE BIT(16)
#define CAN_MCAN_IE_TOOE BIT(15)
#define CAN_MCAN_IE_MRAFE BIT(14)
#define CAN_MCAN_IE_TSWE BIT(13)
#define CAN_MCAN_IE_TEFLE BIT(12)
#define CAN_MCAN_IE_TEFFE BIT(11)
#define CAN_MCAN_IE_TEFNE BIT(10)
#define CAN_MCAN_IE_TFEE BIT(9)
#define CAN_MCAN_IE_TCFE BIT(8)
#define CAN_MCAN_IE_TCE BIT(7)
#define CAN_MCAN_IE_HPME BIT(6)
#define CAN_MCAN_IE_RF1LE BIT(5)
#define CAN_MCAN_IE_RF1FE BIT(4)
#define CAN_MCAN_IE_RF1NE BIT(3)
#define CAN_MCAN_IE_RF0LE BIT(2)
#define CAN_MCAN_IE_RF0FE BIT(1)
#define CAN_MCAN_IE_RF0NE BIT(0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_IE_ARAE BIT(29)
#define CAN_MCAN_IE_PEDE BIT(28)
#define CAN_MCAN_IE_PEAE BIT(27)
@ -256,19 +196,9 @@
#define CAN_MCAN_IE_RF0FE BIT(2)
#define CAN_MCAN_IE_RF0WE BIT(1)
#define CAN_MCAN_IE_RF0NE BIT(0)
#endif /* !CONFIG_CAN_STM32FD */
/* Interrupt Line Select register */
#define CAN_MCAN_ILS 0x058
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_ILS_PERR BIT(6)
#define CAN_MCAN_ILS_BERR BIT(5)
#define CAN_MCAN_ILS_MISC BIT(4)
#define CAN_MCAN_ILS_TFERR BIT(3)
#define CAN_MCAN_ILS_SMSG BIT(2)
#define CAN_MCAN_ILS_RXFIFO1 BIT(1)
#define CAN_MCAN_ILS_RXFIFO0 BIT(0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_ILS_ARAL BIT(29)
#define CAN_MCAN_ILS_PEDL BIT(28)
#define CAN_MCAN_ILS_PEAL BIT(27)
@ -299,7 +229,6 @@
#define CAN_MCAN_ILS_RF0FL BIT(2)
#define CAN_MCAN_ILS_RF0WL BIT(1)
#define CAN_MCAN_ILS_RF0NL BIT(0)
#endif /* !CONFIG_CAN_STM32FD */
/* Interrupt Line Enable register */
#define CAN_MCAN_ILE 0x05C
@ -307,290 +236,152 @@
#define CAN_MCAN_ILE_EINT0 BIT(0)
/* Global filter configuration register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXGFC 0x080
#define CAN_MCAN_RXGFC_LSE GENMASK(27, 24)
#define CAN_MCAN_RXGFC_LSS GENMASK(20, 16)
#define CAN_MCAN_RXGFC_F0OM BIT(9)
#define CAN_MCAN_RXGFC_F1OM BIT(8)
#define CAN_MCAN_RXGFC_ANFS GENMASK(5, 4)
#define CAN_MCAN_RXGFC_ANFE GENMASK(3, 2)
#define CAN_MCAN_RXGFC_RRFS BIT(1)
#define CAN_MCAN_RXGFC_RRFE BIT(0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_GFC 0x080
#define CAN_MCAN_GFC_ANFS GENMASK(5, 4)
#define CAN_MCAN_GFC_ANFE GENMASK(3, 2)
#define CAN_MCAN_GFC_RRFS BIT(1)
#define CAN_MCAN_GFC_RRFE BIT(0)
#endif /* !CONFIG_CAN_STM32FD */
/* Standard ID Filter Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_SIDFC 0x084
#define CAN_MCAN_SIDFC_LSS GENMASK(23, 16)
#define CAN_MCAN_SIDFC_FLSSA GENMASK(15, 2)
#endif /* !CONFIG_CAN_STM32FD */
/* Extended ID Filter Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_XIDFC 0x088
#define CAN_MCAN_XIDFC_LSS GENMASK(22, 16)
#define CAN_MCAN_XIDFC_FLESA GENMASK(15, 2)
#endif /* !CONFIG_CAN_STM32FD */
/* Extended ID AND Mask register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_XIDAM 0x084
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_XIDAM 0x090
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_XIDAM_EIDM GENMASK(28, 0)
/* HPMS register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_HPMS 0x088
#else /* CONFIG_CAN_STM32FD */
/* High Priority Message Status register */
#define CAN_MCAN_HPMS 0x094
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_HPMS_FLST BIT(15)
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_HPMS_FIDX GENMASK(12, 8)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_HPMS_FIDX GENMASK(14, 8)
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_HPMS_MSI GENMASK(7, 6)
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_HPMS_BIDX GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_HPMS_BIDX GENMASK(5, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* New Data 1 register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_NDAT1 0x098
#define CAN_MCAN_NDAT1_ND GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* New Data 2 register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_NDAT2 0x09C
#define CAN_MCAN_NDAT2_ND GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx FIFO 0 Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF0C 0x0A0
#define CAN_MCAN_RXF0C_F0OM BIT(31)
#define CAN_MCAN_RXF0C_F0WM GENMASK(30, 24)
#define CAN_MCAN_RXF0C_F0S GENMASK(22, 16)
#define CAN_MCAN_RXF0C_F0SA GENMASK(15, 2)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx FIFO 0 Status register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF0S 0x090
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF0S 0x0A4
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF0S_RF0L BIT(25)
#define CAN_MCAN_RXF0S_F0F BIT(24)
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF0S_F0PI GENMASK(17, 16)
#define CAN_MCAN_RXF0S_F0GI GENMASK(9, 8)
#define CAN_MCAN_RXF0S_F0FL GENMASK(3, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF0S_F0PI GENMASK(21, 16)
#define CAN_MCAN_RXF0S_F0GI GENMASK(13, 8)
#define CAN_MCAN_RXF0S_F0FL GENMASK(6, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx FIFO 0 Acknowledge register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF0A 0x094
#define CAN_MCAN_RXF0A_F0AI GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF0A 0x0A8
#define CAN_MCAN_RXF0A_F0AI GENMASK(5, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx Buffer Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXBC 0x0AC
#define CAN_MCAN_RXBC_RBSA GENMASK(15, 2)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx FIFO 1 Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF1C 0x0B0
#define CAN_MCAN_RXF1C_F1OM BIT(31)
#define CAN_MCAN_RXF1C_F1WM GENMASK(30, 24)
#define CAN_MCAN_RXF1C_F1S GENMASK(22, 16)
#define CAN_MCAN_RXF1C_F1SA GENMASK(15, 2)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx FIFO 1 Status register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF1S 0x098
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF1S 0x0B4
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF1S_RF1L BIT(25)
#define CAN_MCAN_RXF1S_F1F BIT(24)
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF1S_F1PI GENMASK(17, 16)
#define CAN_MCAN_RXF1S_F1GI GENMASK(9, 8)
#define CAN_MCAN_RXF1S_F1FL GENMASK(3, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF1S_F1PI GENMASK(21, 16)
#define CAN_MCAN_RXF1S_F1GI GENMASK(13, 8)
#define CAN_MCAN_RXF1S_F1FL GENMASK(6, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx FIFO 1 Acknowledge register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXF1A 0x09C
#define CAN_MCAN_RXF1A_F1AI GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_RXF1A 0x0B8
#define CAN_MCAN_RXF1A_F1AI GENMASK(5, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Rx Buffer/FIFO Element Size Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_RXESC 0x0BC
#define CAN_MCAN_RXESC_RBDS GENMASK(10, 8)
#define CAN_MCAN_RXESC_F1DS GENMASK(6, 4)
#define CAN_MCAN_RXESC_F0DS GENMASK(2, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Configuration register */
#define CAN_MCAN_TXBC 0x0C0
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBC_TFQM BIT(24)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXBC_TFQM BIT(30)
#define CAN_MCAN_TXBC_TFQS GENMASK(29, 24)
#define CAN_MCAN_TXBC_NDTB GENMASK(21, 16)
#define CAN_MCAN_TXBC_TBSA GENMASK(15, 2)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx FIFO/Queue Status register */
#define CAN_MCAN_TXFQS 0x0C4
#define CAN_MCAN_TXFQS_TFQF BIT(21)
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXFQS_TFQPI GENMASK(17, 16)
#define CAN_MCAN_TXFQS_TFGI GENMASK(9, 8)
#define CAN_MCAN_TXFQS_TFFL GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXFQS_TFQPI GENMASK(20, 16)
#define CAN_MCAN_TXFQS_TFGI GENMASK(12, 8)
#define CAN_MCAN_TXFQS_TFFL GENMASK(5, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Element Size Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXESC 0x0C8
#define CAN_MCAN_TXESC_TBDS GENMASK(2, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Request Pending register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBRP 0x0C8
#define CAN_MCAN_TXBRP_TRP GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXBRP 0x0CC
#define CAN_MCAN_TXBRP_TRP GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Add Request register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBAR 0x0CC
#define CAN_MCAN_TXBAR_AR GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXBAR 0x0D0
#define CAN_MCAN_TXBAR_AR GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Cancellation Request register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBCR 0x0D0
#define CAN_MCAN_TXBCR_CR GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXBCR 0x0D4
#define CAN_MCAN_TXBCR_CR GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Transmission Occurred register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBTO 0x0D4
#define CAN_MCAN_TXBTO_TO GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXBTO 0x0D8
#define CAN_MCAN_TXBTO_TO GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Cancellation Finished register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBCF 0x0D8
#define CAN_MCAN_TXBCF_CF GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD*/
#define CAN_MCAN_TXBCF 0x0DC
#define CAN_MCAN_TXBCF_CF GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Transmission Interrupt Enable register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBTIE 0x0DC
#define CAN_MCAN_TXBTIE_TIE GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXBTIE 0x0E0
#define CAN_MCAN_TXBTIE_TIE GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Buffer Cancellation Finished Interrupt Enable register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXBCIE 0x0E0
#define CAN_MCAN_TXBCIE_CFIE GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXBCIE 0x0E4
#define CAN_MCAN_TXBCIE_CFIE GENMASK(31, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Event FIFO Configuration register */
#ifndef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXEFC 0x0F0
#define CAN_MCAN_TXEFC_EFWM GENMASK(29, 24)
#define CAN_MCAN_TXEFC_EFS GENMASK(21, 16)
#define CAN_MCAN_TXEFC_EFSA GENMASK(15, 2)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Event FIFO Status register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXEFS 0x0E4
#else /* CONFIG_CAN_STM32FD*/
#define CAN_MCAN_TXEFS 0x0F4
#endif /* !CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXEFS_TEFL BIT(25)
#define CAN_MCAN_TXEFS_EFF BIT(24)
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXEFS_EFPI GENMASK(17, 16)
#define CAN_MCAN_TXEFS_EFGI GENMASK(9, 8)
#define CAN_MCAN_TXEFS_EFFL GENMASK(2, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXEFS_EFPI GENMASK(20, 16)
#define CAN_MCAN_TXEFS_EFGI GENMASK(12, 8)
#define CAN_MCAN_TXEFS_EFFL GENMASK(5, 0)
#endif /* !CONFIG_CAN_STM32FD */
/* Tx Event FIFO Acknowledge register */
#ifdef CONFIG_CAN_STM32FD
#define CAN_MCAN_TXEFA 0x0E8
#define CAN_MCAN_TXEFA_EFAI GENMASK(1, 0)
#else /* CONFIG_CAN_STM32FD */
#define CAN_MCAN_TXEFA 0x0F8
#define CAN_MCAN_TXEFA_EFAI GENMASK(4, 0)
#endif /* !CONFIG_CAN_STM32FD */
#ifdef CONFIG_CAN_MCUX_MCAN
#define MCAN_DT_PATH DT_NODELABEL(can0)
@ -956,9 +747,7 @@ int can_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val);
* @retval 0 If successful.
* @retval -EIO General input/output error.
*/
#ifndef CONFIG_CAN_STM32FD
int can_mcan_configure_message_ram(const struct device *dev, uintptr_t mrba);
#endif /* !CONFIG_CAN_STM32FD */
int can_mcan_get_capabilities(const struct device *dev, can_mode_t *cap);

View file

@ -10,6 +10,7 @@
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/__assert.h>
#include <soc.h>
#include <stm32_ll_rcc.h>
#include <zephyr/logging/log.h>
@ -21,6 +22,143 @@ LOG_MODULE_REGISTER(can_stm32fd, CONFIG_CAN_LOG_LEVEL);
#define DT_DRV_COMPAT st_stm32_fdcan
/*
* The STMicroelectronics STM32 FDCAN definitions correspond to those found in the
* STMicroelectronics STM32G4 Series Reference manual (RM0440), Rev 7.
*
* This controller uses a Bosch M_CAN like register layout, but some registers are unimplemented,
* some registers are mapped to other register offsets, and some registers have had their bit fields
* remapped.
*
* Apart from the definitions below please note the following limitations:
* - TEST register SVAL, TXBNS, PVAL, and TXBNP bits are not available.
* - CCCR register VMM and UTSU bits are not available.
* - TXBC register TFQS, NDTB, and TBSA fields are not available.
*/
/* Interrupt register */
#define CAN_STM32FD_IR_ARA BIT(23)
#define CAN_STM32FD_IR_PED BIT(22)
#define CAN_STM32FD_IR_PEA BIT(21)
#define CAN_STM32FD_IR_WDI BIT(20)
#define CAN_STM32FD_IR_BO BIT(19)
#define CAN_STM32FD_IR_EW BIT(18)
#define CAN_STM32FD_IR_EP BIT(17)
#define CAN_STM32FD_IR_ELO BIT(16)
#define CAN_STM32FD_IR_TOO BIT(15)
#define CAN_STM32FD_IR_MRAF BIT(14)
#define CAN_STM32FD_IR_TSW BIT(13)
#define CAN_STM32FD_IR_TEFL BIT(12)
#define CAN_STM32FD_IR_TEFF BIT(11)
#define CAN_STM32FD_IR_TEFN BIT(10)
#define CAN_STM32FD_IR_TFE BIT(9)
#define CAN_STM32FD_IR_TCF BIT(8)
#define CAN_STM32FD_IR_TC BIT(7)
#define CAN_STM32FD_IR_HPM BIT(6)
#define CAN_STM32FD_IR_RF1L BIT(5)
#define CAN_STM32FD_IR_RF1F BIT(4)
#define CAN_STM32FD_IR_RF1N BIT(3)
#define CAN_STM32FD_IR_RF0L BIT(2)
#define CAN_STM32FD_IR_RF0F BIT(1)
#define CAN_STM32FD_IR_RF0N BIT(0)
/* Interrupt Enable register */
#define CAN_STM32FD_IE_ARAE BIT(23)
#define CAN_STM32FD_IE_PEDE BIT(22)
#define CAN_STM32FD_IE_PEAE BIT(21)
#define CAN_STM32FD_IE_WDIE BIT(20)
#define CAN_STM32FD_IE_BOE BIT(19)
#define CAN_STM32FD_IE_EWE BIT(18)
#define CAN_STM32FD_IE_EPE BIT(17)
#define CAN_STM32FD_IE_ELOE BIT(16)
#define CAN_STM32FD_IE_TOOE BIT(15)
#define CAN_STM32FD_IE_MRAFE BIT(14)
#define CAN_STM32FD_IE_TSWE BIT(13)
#define CAN_STM32FD_IE_TEFLE BIT(12)
#define CAN_STM32FD_IE_TEFFE BIT(11)
#define CAN_STM32FD_IE_TEFNE BIT(10)
#define CAN_STM32FD_IE_TFEE BIT(9)
#define CAN_STM32FD_IE_TCFE BIT(8)
#define CAN_STM32FD_IE_TCE BIT(7)
#define CAN_STM32FD_IE_HPME BIT(6)
#define CAN_STM32FD_IE_RF1LE BIT(5)
#define CAN_STM32FD_IE_RF1FE BIT(4)
#define CAN_STM32FD_IE_RF1NE BIT(3)
#define CAN_STM32FD_IE_RF0LE BIT(2)
#define CAN_STM32FD_IE_RF0FE BIT(1)
#define CAN_STM32FD_IE_RF0NE BIT(0)
/* Interrupt Line Select register */
#define CAN_STM32FD_ILS_PERR BIT(6)
#define CAN_STM32FD_ILS_BERR BIT(5)
#define CAN_STM32FD_ILS_MISC BIT(4)
#define CAN_STM32FD_ILS_TFERR BIT(3)
#define CAN_STM32FD_ILS_SMSG BIT(2)
#define CAN_STM32FD_ILS_RXFIFO1 BIT(1)
#define CAN_STM32FD_ILS_RXFIFO0 BIT(0)
/* Global filter configuration register */
#define CAN_STM32FD_RXGFC 0x080
#define CAN_STM32FD_RXGFC_LSE GENMASK(27, 24)
#define CAN_STM32FD_RXGFC_LSS GENMASK(20, 16)
#define CAN_STM32FD_RXGFC_F0OM BIT(9)
#define CAN_STM32FD_RXGFC_F1OM BIT(8)
#define CAN_STM32FD_RXGFC_ANFS GENMASK(5, 4)
#define CAN_STM32FD_RXGFC_ANFE GENMASK(3, 2)
#define CAN_STM32FD_RXGFC_RRFS BIT(1)
#define CAN_STM32FD_RXGFC_RRFE BIT(0)
/* Extended ID AND Mask register */
#define CAN_STM32FD_XIDAM 0x084
/* High Priority Message Status register */
#define CAN_STM32FD_HPMS 0x088
/* Rx FIFO 0 Status register */
#define CAN_STM32FD_RXF0S 0x090
/* Rx FIFO 0 Acknowledge register */
#define CAN_STM32FD_RXF0A 0x094
/* Rx FIFO 1 Status register */
#define CAN_STM32FD_RXF1S 0x098
/* Rx FIFO 1 Acknowledge register */
#define CAN_STM32FD_RXF1A 0x09C
/* Tx Buffer Configuration register */
#define CAN_STM32FD_TXBC_TFQM BIT(24)
/* Tx Buffer Request Pending register */
#define CAN_STM32FD_TXBRP 0x0C8
/* Tx Buffer Add Request register */
#define CAN_STM32FD_TXBAR 0x0CC
/* Tx Buffer Cancellation Request register */
#define CAN_STM32FD_TXBCR 0x0D0
/* Tx Buffer Transmission Occurred register */
#define CAN_STM32FD_TXBTO 0x0D4
/* Tx Buffer Cancellation Finished register */
#define CAN_STM32FD_TXBCF 0x0D8
/* Tx Buffer Transmission Interrupt Enable register */
#define CAN_STM32FD_TXBTIE 0x0DC
/* Tx Buffer Cancellation Finished Interrupt Enable register */
#define CAN_STM32FD_TXBCIE 0x0E0
/* Tx Event FIFO Status register */
#define CAN_STM32FD_TXEFS 0x0E4
/* Tx Event FIFO Acknowledge register */
#define CAN_STM32FD_TXEFA 0x0E8
/* Register address indicating unsupported register */
#define CAN_STM32FD_REGISTER_UNSUPPORTED UINT16_MAX
/* This symbol takes the value 1 if one of the device instances */
/* is configured in dts with a domain clock */
#if STM32_DT_INST_DEV_DOMAIN_CLOCK_SUPPORT
@ -38,20 +176,273 @@ struct can_stm32fd_config {
uint8_t clock_divider;
};
static inline uint16_t can_stm32fd_remap_reg(uint16_t reg)
{
uint16_t remap;
switch (reg) {
case CAN_MCAN_SIDFC:
__fallthrough;
case CAN_MCAN_XIDFC:
__fallthrough;
case CAN_MCAN_NDAT1:
__fallthrough;
case CAN_MCAN_NDAT2:
__fallthrough;
case CAN_MCAN_RXF0C:
__fallthrough;
case CAN_MCAN_RXBC:
__fallthrough;
case CAN_MCAN_RXF1C:
__fallthrough;
case CAN_MCAN_RXESC:
__fallthrough;
case CAN_MCAN_TXESC:
__fallthrough;
case CAN_MCAN_TXEFC:
__ASSERT_NO_MSG(false);
remap = CAN_STM32FD_REGISTER_UNSUPPORTED;
case CAN_MCAN_XIDAM:
remap = CAN_STM32FD_XIDAM;
break;
case CAN_MCAN_RXF0S:
remap = CAN_STM32FD_RXF0S;
break;
case CAN_MCAN_RXF0A:
remap = CAN_STM32FD_RXF0A;
break;
case CAN_MCAN_RXF1S:
remap = CAN_STM32FD_RXF1S;
break;
case CAN_MCAN_RXF1A:
remap = CAN_STM32FD_RXF1A;
break;
case CAN_MCAN_TXBRP:
remap = CAN_STM32FD_TXBRP;
break;
case CAN_MCAN_TXBAR:
remap = CAN_STM32FD_TXBAR;
break;
case CAN_MCAN_TXBCR:
remap = CAN_STM32FD_TXBCR;
break;
case CAN_MCAN_TXBTO:
remap = CAN_STM32FD_TXBTO;
break;
case CAN_MCAN_TXBCF:
remap = CAN_STM32FD_TXBCF;
break;
case CAN_MCAN_TXBTIE:
remap = CAN_STM32FD_TXBTIE;
break;
case CAN_MCAN_TXBCIE:
remap = CAN_STM32FD_TXBCIE;
break;
case CAN_MCAN_TXEFS:
remap = CAN_STM32FD_TXEFS;
break;
case CAN_MCAN_TXEFA:
remap = CAN_STM32FD_TXEFA;
break;
default:
/* No register address remap needed */
remap = reg;
break;
};
return remap;
}
static int can_stm32fd_read_reg(const struct device *dev, uint16_t reg, uint32_t *val)
{
const struct can_mcan_config *mcan_config = dev->config;
const struct can_stm32fd_config *stm32fd_config = mcan_config->custom;
uint16_t remap;
uint32_t bits;
int err;
return can_mcan_sys_read_reg(stm32fd_config->base, reg, val);
remap = can_stm32fd_remap_reg(reg);
if (remap == CAN_STM32FD_REGISTER_UNSUPPORTED) {
return -ENOTSUP;
}
err = can_mcan_sys_read_reg(stm32fd_config->base, remap, &bits);
if (err != 0) {
return err;
}
*val = 0U;
switch (reg) {
case CAN_MCAN_IR:
/* Remap IR bits */
*val |= FIELD_PREP(CAN_MCAN_IR_ARA, FIELD_GET(CAN_STM32FD_IR_ARA, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_PED, FIELD_GET(CAN_STM32FD_IR_PED, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_PEA, FIELD_GET(CAN_STM32FD_IR_PEA, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_WDI, FIELD_GET(CAN_STM32FD_IR_WDI, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_BO, FIELD_GET(CAN_STM32FD_IR_BO, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_EW, FIELD_GET(CAN_STM32FD_IR_EW, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_EP, FIELD_GET(CAN_STM32FD_IR_EP, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_ELO, FIELD_GET(CAN_STM32FD_IR_ELO, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TOO, FIELD_GET(CAN_STM32FD_IR_TOO, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_MRAF, FIELD_GET(CAN_STM32FD_IR_MRAF, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TSW, FIELD_GET(CAN_STM32FD_IR_TSW, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TEFL, FIELD_GET(CAN_STM32FD_IR_TEFL, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TEFF, FIELD_GET(CAN_STM32FD_IR_TEFF, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TEFN, FIELD_GET(CAN_STM32FD_IR_TEFN, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TFE, FIELD_GET(CAN_STM32FD_IR_TFE, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TCF, FIELD_GET(CAN_STM32FD_IR_TCF, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_TC, FIELD_GET(CAN_STM32FD_IR_TC, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_HPM, FIELD_GET(CAN_STM32FD_IR_HPM, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_RF1L, FIELD_GET(CAN_STM32FD_IR_RF1L, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_RF1F, FIELD_GET(CAN_STM32FD_IR_RF1F, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_RF1N, FIELD_GET(CAN_STM32FD_IR_RF1N, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_RF0L, FIELD_GET(CAN_STM32FD_IR_RF0L, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_RF0F, FIELD_GET(CAN_STM32FD_IR_RF0F, bits));
*val |= FIELD_PREP(CAN_MCAN_IR_RF0N, FIELD_GET(CAN_STM32FD_IR_RF0N, bits));
break;
case CAN_MCAN_IE:
/* Remap IE bits */
*val |= FIELD_PREP(CAN_MCAN_IE_ARAE, FIELD_GET(CAN_STM32FD_IE_ARAE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_PEDE, FIELD_GET(CAN_STM32FD_IE_PEDE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_PEAE, FIELD_GET(CAN_STM32FD_IE_PEAE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_WDIE, FIELD_GET(CAN_STM32FD_IE_WDIE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_BOE, FIELD_GET(CAN_STM32FD_IE_BOE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_EWE, FIELD_GET(CAN_STM32FD_IE_EWE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_EPE, FIELD_GET(CAN_STM32FD_IE_EPE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_ELOE, FIELD_GET(CAN_STM32FD_IE_ELOE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TOOE, FIELD_GET(CAN_STM32FD_IE_TOOE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_MRAFE, FIELD_GET(CAN_STM32FD_IE_MRAFE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TSWE, FIELD_GET(CAN_STM32FD_IE_TSWE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TEFLE, FIELD_GET(CAN_STM32FD_IE_TEFLE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TEFFE, FIELD_GET(CAN_STM32FD_IE_TEFFE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TEFNE, FIELD_GET(CAN_STM32FD_IE_TEFNE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TFEE, FIELD_GET(CAN_STM32FD_IE_TFEE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TCFE, FIELD_GET(CAN_STM32FD_IE_TCFE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_TCE, FIELD_GET(CAN_STM32FD_IE_TCE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_HPME, FIELD_GET(CAN_STM32FD_IE_HPME, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_RF1LE, FIELD_GET(CAN_STM32FD_IE_RF1LE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_RF1FE, FIELD_GET(CAN_STM32FD_IE_RF1FE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_RF1NE, FIELD_GET(CAN_STM32FD_IE_RF1NE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_RF0LE, FIELD_GET(CAN_STM32FD_IE_RF0LE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_RF0FE, FIELD_GET(CAN_STM32FD_IE_RF0FE, bits));
*val |= FIELD_PREP(CAN_MCAN_IE_RF0NE, FIELD_GET(CAN_STM32FD_IE_RF0NE, bits));
break;
case CAN_MCAN_ILS:
/* Only remap ILS groups used in can_mcan.c */
if ((bits & CAN_STM32FD_ILS_RXFIFO1) != 0U) {
*val |= CAN_MCAN_ILS_RF1LL | CAN_MCAN_ILS_RF1FL | CAN_MCAN_ILS_RF1NL;
}
if ((bits & CAN_STM32FD_ILS_RXFIFO0) != 0U) {
*val |= CAN_MCAN_ILS_RF0LL | CAN_MCAN_ILS_RF0FL | CAN_MCAN_ILS_RF0NL;
}
break;
case CAN_MCAN_GFC:
/* Map fields from RXGFC excluding STM32 FDCAN LSS and LSE fields */
*val = bits & (CAN_MCAN_GFC_ANFS | CAN_MCAN_GFC_ANFE |
CAN_MCAN_GFC_RRFS | CAN_MCAN_GFC_RRFE);
break;
default:
/* No field remap needed */
*val = bits;
break;
};
return 0;
}
static int can_stm32fd_write_reg(const struct device *dev, uint16_t reg, uint32_t val)
{
const struct can_mcan_config *mcan_config = dev->config;
const struct can_stm32fd_config *stm32fd_config = mcan_config->custom;
uint32_t bits = 0U;
uint16_t remap;
return can_mcan_sys_write_reg(stm32fd_config->base, reg, val);
remap = can_stm32fd_remap_reg(reg);
if (remap == CAN_STM32FD_REGISTER_UNSUPPORTED) {
return -ENOTSUP;
}
switch (reg) {
case CAN_MCAN_IR:
/* Remap IR bits, ignoring unsupported bits */
bits |= FIELD_PREP(CAN_STM32FD_IR_ARA, FIELD_GET(CAN_MCAN_IR_ARA, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_PED, FIELD_GET(CAN_MCAN_IR_PED, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_PEA, FIELD_GET(CAN_MCAN_IR_PEA, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_WDI, FIELD_GET(CAN_MCAN_IR_WDI, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_BO, FIELD_GET(CAN_MCAN_IR_BO, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_EW, FIELD_GET(CAN_MCAN_IR_EW, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_EP, FIELD_GET(CAN_MCAN_IR_EP, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_ELO, FIELD_GET(CAN_MCAN_IR_ELO, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TOO, FIELD_GET(CAN_MCAN_IR_TOO, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_MRAF, FIELD_GET(CAN_MCAN_IR_MRAF, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TSW, FIELD_GET(CAN_MCAN_IR_TSW, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TEFL, FIELD_GET(CAN_MCAN_IR_TEFL, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TEFF, FIELD_GET(CAN_MCAN_IR_TEFF, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TEFN, FIELD_GET(CAN_MCAN_IR_TEFN, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TFE, FIELD_GET(CAN_MCAN_IR_TFE, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TCF, FIELD_GET(CAN_MCAN_IR_TCF, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_TC, FIELD_GET(CAN_MCAN_IR_TC, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_HPM, FIELD_GET(CAN_MCAN_IR_HPM, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_RF1L, FIELD_GET(CAN_MCAN_IR_RF1L, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_RF1F, FIELD_GET(CAN_MCAN_IR_RF1F, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_RF1N, FIELD_GET(CAN_MCAN_IR_RF1N, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_RF0L, FIELD_GET(CAN_MCAN_IR_RF0L, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_RF0F, FIELD_GET(CAN_MCAN_IR_RF0F, val));
bits |= FIELD_PREP(CAN_STM32FD_IR_RF0N, FIELD_GET(CAN_MCAN_IR_RF0N, val));
break;
case CAN_MCAN_IE:
/* Remap IE bits, ignoring unsupported bits */
bits |= FIELD_PREP(CAN_STM32FD_IE_ARAE, FIELD_GET(CAN_MCAN_IE_ARAE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_PEDE, FIELD_GET(CAN_MCAN_IE_PEDE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_PEAE, FIELD_GET(CAN_MCAN_IE_PEAE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_WDIE, FIELD_GET(CAN_MCAN_IE_WDIE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_BOE, FIELD_GET(CAN_MCAN_IE_BOE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_EWE, FIELD_GET(CAN_MCAN_IE_EWE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_EPE, FIELD_GET(CAN_MCAN_IE_EPE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_ELOE, FIELD_GET(CAN_MCAN_IE_ELOE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TOOE, FIELD_GET(CAN_MCAN_IE_TOOE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_MRAFE, FIELD_GET(CAN_MCAN_IE_MRAFE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TSWE, FIELD_GET(CAN_MCAN_IE_TSWE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TEFLE, FIELD_GET(CAN_MCAN_IE_TEFLE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TEFFE, FIELD_GET(CAN_MCAN_IE_TEFFE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TEFNE, FIELD_GET(CAN_MCAN_IE_TEFNE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TFEE, FIELD_GET(CAN_MCAN_IE_TFEE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TCFE, FIELD_GET(CAN_MCAN_IE_TCFE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_TCE, FIELD_GET(CAN_MCAN_IE_TCE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_HPME, FIELD_GET(CAN_MCAN_IE_HPME, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_RF1LE, FIELD_GET(CAN_MCAN_IE_RF1LE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_RF1FE, FIELD_GET(CAN_MCAN_IE_RF1FE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_RF1NE, FIELD_GET(CAN_MCAN_IE_RF1NE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_RF0LE, FIELD_GET(CAN_MCAN_IE_RF0LE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_RF0FE, FIELD_GET(CAN_MCAN_IE_RF0FE, val));
bits |= FIELD_PREP(CAN_STM32FD_IE_RF0NE, FIELD_GET(CAN_MCAN_IE_RF0NE, val));
break;
case CAN_MCAN_ILS:
/* Only remap ILS groups used in can_mcan.c */
if ((val & (CAN_MCAN_ILS_RF1LL | CAN_MCAN_ILS_RF1FL | CAN_MCAN_ILS_RF1NL)) != 0U) {
bits |= CAN_STM32FD_ILS_RXFIFO1;
}
if ((val & (CAN_MCAN_ILS_RF0LL | CAN_MCAN_ILS_RF0FL | CAN_MCAN_ILS_RF0NL)) != 0U) {
bits |= CAN_STM32FD_ILS_RXFIFO0;
}
break;
case CAN_MCAN_GFC:
/* Map fields to RXGFC including STM32 FDCAN LSS and LSE fields */
bits |= FIELD_PREP(CAN_STM32FD_RXGFC_LSS, CONFIG_CAN_MAX_STD_ID_FILTER) |
FIELD_PREP(CAN_STM32FD_RXGFC_LSE, CONFIG_CAN_MAX_EXT_ID_FILTER);
bits |= val & (CAN_MCAN_GFC_ANFS | CAN_MCAN_GFC_ANFE |
CAN_MCAN_GFC_RRFS | CAN_MCAN_GFC_RRFE);
break;
default:
/* No field remap needed */
bits = val;
break;
};
return can_mcan_sys_write_reg(stm32fd_config->base, remap, bits);
}
static int can_stm32fd_get_core_clock(const struct device *dev, uint32_t *rate)
@ -130,17 +521,22 @@ static int can_stm32fd_init(const struct device *dev)
can_mcan_enable_configuration_change(dev);
/* Setup STM32 FDCAN Global Filter Configuration Register */
ret = can_mcan_read_reg(dev, CAN_MCAN_RXGFC, &rxgfc);
/* Setup STM32 FDCAN Global Filter Configuration register */
ret = can_mcan_read_reg(dev, CAN_STM32FD_RXGFC, &rxgfc);
if (ret != 0) {
return ret;
}
rxgfc |= FIELD_PREP(CAN_MCAN_RXGFC_LSS, CONFIG_CAN_MAX_STD_ID_FILTER) |
FIELD_PREP(CAN_MCAN_RXGFC_LSE, CONFIG_CAN_MAX_EXT_ID_FILTER) |
FIELD_PREP(CAN_MCAN_RXGFC_ANFS, 0x2) | FIELD_PREP(CAN_MCAN_RXGFC_ANFE, 0x2);
rxgfc |= FIELD_PREP(CAN_STM32FD_RXGFC_LSS, CONFIG_CAN_MAX_STD_ID_FILTER) |
FIELD_PREP(CAN_STM32FD_RXGFC_LSE, CONFIG_CAN_MAX_EXT_ID_FILTER);
ret = can_mcan_write_reg(dev, CAN_MCAN_RXGFC, rxgfc);
ret = can_mcan_write_reg(dev, CAN_STM32FD_RXGFC, rxgfc);
if (ret != 0) {
return ret;
}
/* Setup STM32 FDCAN Tx buffer configuration register */
ret = can_mcan_write_reg(dev, CAN_MCAN_TXBC, CAN_STM32FD_TXBC_TFQM);
if (ret != 0) {
return ret;
}
@ -205,6 +601,14 @@ static const struct can_driver_api can_stm32fd_driver_api = {
#endif /* CONFIG_CAN_FD_MODE */
};
/* Assert that the Message RAM configuration meets the hardware limitiations */
BUILD_ASSERT(NUM_STD_FILTER_ELEMENTS <= 28, "Maximum standard filter elements exceeded");
BUILD_ASSERT(NUM_EXT_FILTER_ELEMENTS <= 8, "Maximum extended filter elements exceeded");
BUILD_ASSERT(NUM_RX_FIFO0_ELEMENTS == 3, "Rx FIFO 0 elements must be 3");
BUILD_ASSERT(NUM_RX_FIFO1_ELEMENTS == 3, "Rx FIFO 1 elements must be 3");
BUILD_ASSERT(NUM_RX_BUF_ELEMENTS == 0, "Rx Buffer elements must be 0");
BUILD_ASSERT(NUM_TX_BUF_ELEMENTS == 3, "Tx Buffer elements must be 0");
#define CAN_STM32FD_IRQ_CFG_FUNCTION(inst) \
static void config_can_##inst##_irq(void) \
{ \