You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/12/08 05:36:18 UTC

[incubator-nuttx] branch master updated: samv7: enable MCAN driver support for both rev A and rev B

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new ae57492  samv7: enable MCAN driver support for both rev A and rev B
ae57492 is described below

commit ae57492189a7f90effce53edde37db3c2630c129
Author: Michal Lenc <mi...@seznam.cz>
AuthorDate: Sun Dec 5 15:14:17 2021 +0100

    samv7: enable MCAN driver support for both rev A and rev B
    
    This commit enables the MCAN driver to function with both rev A and rev B
    version of the chip. The version of the chip is selected automtically from
    SAM_CHIPID_CIDR register so there is no need to predefined it in the
    configuration.
    
    The functonality was tested on rev B version of the chip. The rev A was
    not tested since I do not have the functional board but the code remains
    the same as in the previous NuttX version so it should not cause any
    additional troubles.
    
    The code is co-authored by Miloš Pokorný who wrote the initial transition
    to rev B of the chip.
    
    Signed-off-by: Michal Lenc <mi...@seznam.cz>
    Co-authored-by: Miloš Pokorný <mi...@seznam.cz>
---
 arch/arm/src/samv7/hardware/sam_mcan.h | 257 ++++++++-----------
 arch/arm/src/samv7/sam_mcan.c          | 442 +++++++++++++++++++++++----------
 2 files changed, 413 insertions(+), 286 deletions(-)

diff --git a/arch/arm/src/samv7/hardware/sam_mcan.h b/arch/arm/src/samv7/hardware/sam_mcan.h
index 28ff965..c6829f6 100644
--- a/arch/arm/src/samv7/hardware/sam_mcan.h
+++ b/arch/arm/src/samv7/hardware/sam_mcan.h
@@ -38,11 +38,13 @@
 
                                           /* 0x0000-0x0004 Reserved */
 #define SAM_MCAN_CUST_OFFSET       0x0008 /* Customer Register */
-#define SAM_MCAN_FBTP_OFFSET       0x000c /* Fast Bit Timing and Prescaler Register */
+#define SAM_MCAN_REVA_FBTP_OFFSET  0x000c /* Fast Bit Timing and Prescaler Register (rev A) */
+#define SAM_MCAN_DBTP_OFFSET       0x000c /* Data Bit Timing and Prescaler Register (rev B) */
 #define SAM_MCAN_TEST_OFFSET       0x0010 /* Test Register */
 #define SAM_MCAN_RWD_OFFSET        0x0014 /* RAM Watchdog Register */
 #define SAM_MCAN_CCCR_OFFSET       0x0018 /* CC Control Register */
-#define SAM_MCAN_BTP_OFFSET        0x001c /* Bit Timing and Prescaler Register */
+#define SAM_MCAN_REVA_BTP_OFFSET   0x001c /* Bit Timing and Prescaler Register (rev A) */
+#define SAM_MCAN_NBTP_OFFSET       0x001c /* Nominal Bit Timing and Prescaler Register (rev B) */
 #define SAM_MCAN_TSCC_OFFSET       0x0020 /* Timestamp Counter Configuration Register */
 #define SAM_MCAN_TSCV_OFFSET       0x0024 /* Timestamp Counter Value Register */
 #define SAM_MCAN_TOCC_OFFSET       0x0028 /* Timeout Counter Configuration Register */
@@ -88,120 +90,44 @@
 #define SAM_MCAN_TXEFA_OFFSET      0x00f8 /* Transmit Event FIFO Acknowledge Register */
                                           /* 0x00fc Reserved */
 
-/* MCAN register addresses **************************************************/
-
-#define SAM_MCAN0_CUST             (SAM_MCAN0_BASE+SAM_MCAN_CUST_OFFSET)
-#define SAM_MCAN0_FBTP             (SAM_MCAN0_BASE+SAM_MCAN_FBTP_OFFSET)
-#define SAM_MCAN0_TEST             (SAM_MCAN0_BASE+SAM_MCAN_TEST_OFFSET)
-#define SAM_MCAN0_RWD              (SAM_MCAN0_BASE+SAM_MCAN_RWD_OFFSET)
-#define SAM_MCAN0_CCCR             (SAM_MCAN0_BASE+SAM_MCAN_CCCR_OFFSET)
-#define SAM_MCAN0_BTP              (SAM_MCAN0_BASE+SAM_MCAN_BTP_OFFSET)
-#define SAM_MCAN0_TSCC             (SAM_MCAN0_BASE+SAM_MCAN_TSCC_OFFSET)
-#define SAM_MCAN0_TSCV             (SAM_MCAN0_BASE+SAM_MCAN_TSCV_OFFSET)
-#define SAM_MCAN0_TOCC             (SAM_MCAN0_BASE+SAM_MCAN_TOCC_OFFSET)
-#define SAM_MCAN0_TOCV             (SAM_MCAN0_BASE+SAM_MCAN_TOCV_OFFSET)
-#define SAM_MCAN0_ECR              (SAM_MCAN0_BASE+SAM_MCAN_ECR_OFFSET)
-#define SAM_MCAN0_PSR              (SAM_MCAN0_BASE+SAM_MCAN_PSR_OFFSET)
-#define SAM_MCAN0_IR               (SAM_MCAN0_BASE+SAM_MCAN_IR_OFFSET)
-#define SAM_MCAN0_IE               (SAM_MCAN0_BASE+SAM_MCAN_IE_OFFSET)
-#define SAM_MCAN0_ILS              (SAM_MCAN0_BASE+SAM_MCAN_ILS_OFFSET)
-#define SAM_MCAN0_ILE              (SAM_MCAN0_BASE+SAM_MCAN_ILE_OFFSET)
-#define SAM_MCAN0_GFC              (SAM_MCAN0_BASE+SAM_MCAN_GFC_OFFSET)
-#define SAM_MCAN0_SIDFC            (SAM_MCAN0_BASE+SAM_MCAN_SIDFC_OFFSET)
-#define SAM_MCAN0_XIDFC            (SAM_MCAN0_BASE+SAM_MCAN_XIDFC_OFFSET)
-#define SAM_MCAN0_XIDAM            (SAM_MCAN0_BASE+SAM_MCAN_XIDAM_OFFSET)
-#define SAM_MCAN0_HPMS             (SAM_MCAN0_BASE+SAM_MCAN_HPMS_OFFSET)
-#define SAM_MCAN0_NDAT1            (SAM_MCAN0_BASE+SAM_MCAN_NDAT1_OFFSET)
-#define SAM_MCAN0_NDAT2            (SAM_MCAN0_BASE+SAM_MCAN_NDAT2_OFFSET)
-#define SAM_MCAN0_RXF0C            (SAM_MCAN0_BASE+SAM_MCAN_RXF0C_OFFSET)
-#define SAM_MCAN0_RXF0S            (SAM_MCAN0_BASE+SAM_MCAN_RXF0S_OFFSET)
-#define SAM_MCAN0_RXF0A            (SAM_MCAN0_BASE+SAM_MCAN_RXF0A_OFFSET)
-#define SAM_MCAN0_RXBC             (SAM_MCAN0_BASE+SAM_MCAN_RXBC_OFFSET)
-#define SAM_MCAN0_RXF1C            (SAM_MCAN0_BASE+SAM_MCAN_RXF1C_OFFSET)
-#define SAM_MCAN0_RXF1S            (SAM_MCAN0_BASE+SAM_MCAN_RXF1S_OFFSET)
-#define SAM_MCAN0_RXF1A            (SAM_MCAN0_BASE+SAM_MCAN_RXF1A_OFFSET)
-#define SAM_MCAN0_RXESC            (SAM_MCAN0_BASE+SAM_MCAN_RXESC_OFFSET)
-#define SAM_MCAN0_TXBC             (SAM_MCAN0_BASE+SAM_MCAN_TXBC_OFFSET)
-#define SAM_MCAN0_TXFQS            (SAM_MCAN0_BASE+SAM_MCAN_TXFQS_OFFSET)
-#define SAM_MCAN0_TXESC            (SAM_MCAN0_BASE+SAM_MCAN_TXESC_OFFSET)
-#define SAM_MCAN0_TXBRP            (SAM_MCAN0_BASE+SAM_MCAN_TXBRP_OFFSET)
-#define SAM_MCAN0_TXBAR            (SAM_MCAN0_BASE+SAM_MCAN_TXBAR_OFFSET)
-#define SAM_MCAN0_TXBCR            (SAM_MCAN0_BASE+SAM_MCAN_TXBCR_OFFSET)
-#define SAM_MCAN0_TXBTO            (SAM_MCAN0_BASE+SAM_MCAN_TXBTO_OFFSET)
-#define SAM_MCAN0_TXBCF            (SAM_MCAN0_BASE+SAM_MCAN_TXBCF_OFFSET)
-#define SAM_MCAN0_TXBTIE           (SAM_MCAN0_BASE+SAM_MCAN_TXBTIE_OFFSET)
-#define SAM_MCAN0_TXBCIE           (SAM_MCAN0_BASE+SAM_MCAN_TXBCIE_OFFSET)
-#define SAM_MCAN0_TXEFC            (SAM_MCAN0_BASE+SAM_MCAN_TXEFC_OFFSET)
-#define SAM_MCAN0_TXEFS            (SAM_MCAN0_BASE+SAM_MCAN_TXEFS_OFFSET)
-#define SAM_MCAN0_TXEFA            (SAM_MCAN0_BASE+SAM_MCAN_TXEFA_OFFSET)
-
-#define SAM_MCAN1_CUST             (SAM_MCAN1_BASE+SAM_MCAN_CUST_OFFSET)
-#define SAM_MCAN1_FBTP             (SAM_MCAN1_BASE+SAM_MCAN_FBTP_OFFSET)
-#define SAM_MCAN1_TEST             (SAM_MCAN1_BASE+SAM_MCAN_TEST_OFFSET)
-#define SAM_MCAN1_RWD              (SAM_MCAN1_BASE+SAM_MCAN_RWD_OFFSET)
-#define SAM_MCAN1_CCCR             (SAM_MCAN1_BASE+SAM_MCAN_CCCR_OFFSET)
-#define SAM_MCAN1_BTP              (SAM_MCAN1_BASE+SAM_MCAN_BTP_OFFSET)
-#define SAM_MCAN1_TSCC             (SAM_MCAN1_BASE+SAM_MCAN_TSCC_OFFSET)
-#define SAM_MCAN1_TSCV             (SAM_MCAN1_BASE+SAM_MCAN_TSCV_OFFSET)
-#define SAM_MCAN1_TOCC             (SAM_MCAN1_BASE+SAM_MCAN_TOCC_OFFSET)
-#define SAM_MCAN1_TOCV             (SAM_MCAN1_BASE+SAM_MCAN_TOCV_OFFSET)
-#define SAM_MCAN1_ECR              (SAM_MCAN1_BASE+SAM_MCAN_ECR_OFFSET)
-#define SAM_MCAN1_PSR              (SAM_MCAN1_BASE+SAM_MCAN_PSR_OFFSET)
-#define SAM_MCAN1_IR               (SAM_MCAN1_BASE+SAM_MCAN_IR_OFFSET)
-#define SAM_MCAN1_IE               (SAM_MCAN1_BASE+SAM_MCAN_IE_OFFSET)
-#define SAM_MCAN1_ILS              (SAM_MCAN1_BASE+SAM_MCAN_ILS_OFFSET)
-#define SAM_MCAN1_ILE              (SAM_MCAN1_BASE+SAM_MCAN_ILE_OFFSET)
-#define SAM_MCAN1_GFC              (SAM_MCAN1_BASE+SAM_MCAN_GFC_OFFSET)
-#define SAM_MCAN1_SIDFC            (SAM_MCAN1_BASE+SAM_MCAN_SIDFC_OFFSET)
-#define SAM_MCAN1_XIDFC            (SAM_MCAN1_BASE+SAM_MCAN_XIDFC_OFFSET)
-#define SAM_MCAN1_XIDAM            (SAM_MCAN1_BASE+SAM_MCAN_XIDAM_OFFSET)
-#define SAM_MCAN1_HPMS             (SAM_MCAN1_BASE+SAM_MCAN_HPMS_OFFSET)
-#define SAM_MCAN1_NDAT1            (SAM_MCAN1_BASE+SAM_MCAN_NDAT1_OFFSET)
-#define SAM_MCAN1_NDAT2            (SAM_MCAN1_BASE+SAM_MCAN_NDAT2_OFFSET)
-#define SAM_MCAN1_RXF0C            (SAM_MCAN1_BASE+SAM_MCAN_RXF0C_OFFSET)
-#define SAM_MCAN1_RXF0S            (SAM_MCAN1_BASE+SAM_MCAN_RXF0S_OFFSET)
-#define SAM_MCAN1_RXF0A            (SAM_MCAN1_BASE+SAM_MCAN_RXF0A_OFFSET)
-#define SAM_MCAN1_RXBC             (SAM_MCAN1_BASE+SAM_MCAN_RXBC_OFFSET)
-#define SAM_MCAN1_RXF1C            (SAM_MCAN1_BASE+SAM_MCAN_RXF1C_OFFSET)
-#define SAM_MCAN1_RXF1S            (SAM_MCAN1_BASE+SAM_MCAN_RXF1S_OFFSET)
-#define SAM_MCAN1_RXF1A            (SAM_MCAN1_BASE+SAM_MCAN_RXF1A_OFFSET)
-#define SAM_MCAN1_RXESC            (SAM_MCAN1_BASE+SAM_MCAN_RXESC_OFFSET)
-#define SAM_MCAN1_TXBC             (SAM_MCAN1_BASE+SAM_MCAN_TXBC_OFFSET)
-#define SAM_MCAN1_TXFQS            (SAM_MCAN1_BASE+SAM_MCAN_TXFQS_OFFSET)
-#define SAM_MCAN1_TXESC            (SAM_MCAN1_BASE+SAM_MCAN_TXESC_OFFSET)
-#define SAM_MCAN1_TXBRP            (SAM_MCAN1_BASE+SAM_MCAN_TXBRP_OFFSET)
-#define SAM_MCAN1_TXBAR            (SAM_MCAN1_BASE+SAM_MCAN_TXBAR_OFFSET)
-#define SAM_MCAN1_TXBCR            (SAM_MCAN1_BASE+SAM_MCAN_TXBCR_OFFSET)
-#define SAM_MCAN1_TXBTO            (SAM_MCAN1_BASE+SAM_MCAN_TXBTO_OFFSET)
-#define SAM_MCAN1_TXBCF            (SAM_MCAN1_BASE+SAM_MCAN_TXBCF_OFFSET)
-#define SAM_MCAN1_TXBTIE           (SAM_MCAN1_BASE+SAM_MCAN_TXBTIE_OFFSET)
-#define SAM_MCAN1_TXBCIE           (SAM_MCAN1_BASE+SAM_MCAN_TXBCIE_OFFSET)
-#define SAM_MCAN1_TXEFC            (SAM_MCAN1_BASE+SAM_MCAN_TXEFC_OFFSET)
-#define SAM_MCAN1_TXEFS            (SAM_MCAN1_BASE+SAM_MCAN_TXEFS_OFFSET)
-#define SAM_MCAN1_TXEFA            (SAM_MCAN1_BASE+SAM_MCAN_TXEFA_OFFSET)
-
 /* MCAN register bit definitions ********************************************/
 
 /* Customer Register (32-bit value) */
 
-/* Fast Bit Timing and Prescaler Register */
-
-#define MCAN_FBTP_FSJW_SHIFT       (0)       /* Bits 0-1: Fast (Re) Synchronization Jump Width */
-#define MCAN_FBTP_FSJW_MASK        (3 << MCAN_FBTP_FSJW_SHIFT)
-#  define MCAN_FBTP_FSJW(n)        ((uint32_t)(n) << MCAN_FBTP_FSJW_SHIFT)
-#define MCAN_FBTP_FTSEG2_SHIFT     (4)       /* Bits 4-6: Fast Time Segment After Sample Point */
-#define MCAN_FBTP_FTSEG2_MASK      (7 << MCAN_FBTP_FTSEG2_SHIFT)
-#  define MCAN_FBTP_FTSEG2(n)      ((uint32_t)(n) << MCAN_FBTP_FTSEG2_SHIFT)
-#define MCAN_FBTP_FTSEG1_SHIFT     (8)       /* Bits 8-11: Fast Time Segment Before Sample Point */
-#define MCAN_FBTP_FTSEG1_MASK      (15 << MCAN_FBTP_FTSEG1_SHIFT)
-#  define MCAN_FBTP_FTSEG1(n)      ((uint32_t)(n) << MCAN_FBTP_FTSEG1_SHIFT)
-#define MCAN_FBTP_FBRP_SHIFT       (16)      /* Bits 16-20: Fast Baud Rate Prescaler */
-#define MCAN_FBTP_FBRP_MASK        (31 << MCAN_FBTP_FBRP_SHIFT)
-#  define MCAN_FBTP_FBRP(n)        ((uint32_t)(n) << MCAN_FBTP_FBRP_SHIFT)
-#define MCAN_FBTP_TDC              (1 << 23) /* Bit: 23: Transceiver Delay Compensation */
-#define MCAN_FBTP_TDCO_SHIFT       (24)      /* Bits 24-28: Transceiver Delay Compensation Offset */
-#define MCAN_FBTP_TDCO_MASK        (31 << MCAN_FBTP_TDC_SHIFT)
-#  define MCAN_FBTP_TDCO(n)        ((uint32_t)(n) << MCAN_FBTP_TDC_SHIFT)
+/* Fast Bit Timing and Prescaler Register (rev A) */
+
+#define MCAN_REVA_FBTP_FSJW_SHIFT       (0)       /* Bits 0-1: Fast (Re) Synchronization Jump Width */
+#define MCAN_REVA_FBTP_FSJW_MASK        (0x3 << MCAN_REVA_FBTP_FSJW_SHIFT)
+#  define MCAN_REVA_FBTP_FSJW(n)        ((uint32_t)(n) << MCAN_REVA_FBTP_FSJW_SHIFT)
+#define MCAN_REVA_FBTP_FTSEG2_SHIFT     (4)       /* Bits 4-6: Fast Time Segment After Sample Point */
+#define MCAN_REVA_FBTP_FTSEG2_MASK      (0x7 << MCAN_REVA_FBTP_FTSEG2_SHIFT)
+#  define MCAN_REVA_FBTP_FTSEG2(n)      ((uint32_t)(n) << MCAN_REVA_FBTP_FTSEG2_SHIFT)
+#define MCAN_REVA_FBTP_FTSEG1_SHIFT     (8)       /* Bits 8-11: Fast Time Segment Before Sample Point */
+#define MCAN_REVA_FBTP_FTSEG1_MASK      (0xf << MCAN_REVA_FBTP_FTSEG1_SHIFT)
+#  define MCAN_REVA_FBTP_FTSEG1(n)      ((uint32_t)(n) << MCAN_REVA_FBTP_FTSEG1_SHIFT)
+#define MCAN_REVA_FBTP_FBRP_SHIFT       (16)      /* Bits 16-20: Fast Baud Rate Prescaler */
+#define MCAN_REVA_FBTP_FBRP_MASK        (0x1f << MCAN_REVA_FBTP_FBRP_SHIFT)
+#  define MCAN_REVA_FBTP_FBRP(n)        ((uint32_t)(n) << MCAN_REVA_FBTP_FBRP_SHIFT)
+#define MCAN_REVA_FBTP_TDC              (1 << 23) /* Bit: 23: Transceiver Delay Compensation */
+#define MCAN_REVA_FBTP_TDCO_SHIFT       (24)      /* Bits 24-28: Transceiver Delay Compensation Offset */
+#define MCAN_REVA_FBTP_TDCO_MASK        (0x1f << MCAN_REVA_FBTP_TDC_SHIFT)
+#  define MCAN_REVA_FBTP_TDCO(n)        ((uint32_t)(n) << MCAN_REVA_FBTP_TDC_SHIFT)
+
+/* Data Bit Timing and Prescaler Register (rev B) */
+
+#define MCAN_DBTP_DSJW_SHIFT       (0)       /* Bits 0-2: Data (Re) Synchronization Jump Width */
+#define MCAN_DBTP_DSJW_MASK        (0x7 << MCAN_DBTP_DSJW_SHIFT)
+#  define MCAN_DBTP_DSJW(n)        ((uint32_t)(n) << MCAN_DBTP_DSJW_SHIFT)
+#define MCAN_DBTP_DTSEG2_SHIFT     (4)       /* Bits 4-7: Data Time Segment After Sample Point */
+#define MCAN_DBTP_DTSEG2_MASK      (0xf << MCAN_DBTP_DTSEG2_SHIFT)
+#  define MCAN_DBTP_DTSEG2(n)      ((uint32_t)(n) << MCAN_DBTP_DTSEG2_SHIFT)
+#define MCAN_DBTP_DTSEG1_SHIFT     (8)       /* Bits 8-11: Data Time Segment Before Sample Point */
+#define MCAN_DBTP_DTSEG1_MASK      (0x1f << MCAN_DBTP_DTSEG1_SHIFT)
+#  define MCAN_DBTP_DTSEG1(n)      ((uint32_t)(n) << MCAN_DBTP_DTSEG1_SHIFT)
+#define MCAN_DBTP_DBRP_SHIFT       (16)      /* Bits 16-20: Data Baud Rate Prescaler */
+#define MCAN_DBTP_DBRP_MASK        (0x1f << MCAN_DBTP_DBRP_SHIFT)
+#  define MCAN_DBTP_DBRP(n)        ((uint32_t)(n) << MCAN_DBTP_DBRP_SHIFT)
+#define MCAN_DBTP_TDC              (1 << 23) /* Bit: 23: Transceiver Delay Compensation */
 
 /* Test Register */
 
@@ -214,9 +140,6 @@
 #  define MCAN_TEST_TX_RECESSIVE   (3 << MCAN_TEST_TX_SHIFT) /* Recessive (1) at CANTX. */
 
 #define MCAN_TEST_RX               (1 << 7)  /* Bit 7:  Receive Pin */
-#define MCAN_TEST_TDCV_SHIFT       (8)       /* Bits 8-13: Transceiver Delay Compensation Value */
-#define MCAN_TEST_TDCV_MASK        (0x3f << MCAN_TEST_TDCV_SHIFT)
-#  define MCAN_TEST_TDCV(n)        ((uint32_t)(n) << MCAN_TEST_TDCV_SHIFT)
 
 /* RAM Watchdog Register */
 
@@ -237,37 +160,56 @@
 #define MCAN_CCCR_MON              (1 << 5)  /* Bit 5:  Bus Monitoring Mode */
 #define MCAN_CCCR_DAR              (1 << 6)  /* Bit 6:  Disable Automatic Retransmission */
 #define MCAN_CCCR_TEST             (1 << 7)  /* Bit 7:  Test Mode Enable */
-#define MCAN_CCCR_CME_SHIFT        (8)       /* Bits 8-9: CAN Mode Enable */
+#define MCAN_CCCR_CME_SHIFT        (8)       /* Bits 8-9: CAN Mode Enable  (rev A) */
 #define MCAN_CCCR_CME_MASK         (3 << MCAN_CCCR_CME_SHIFT)
 #  define MCAN_CCCR_CME_ISO11898_1 (0 << MCAN_CCCR_CME_SHIFT) /* CAN operation according to ISO11898-1 enabled */
 #  define MCAN_CCCR_CME_FD         (1 << MCAN_CCCR_CME_SHIFT) /* CAN FD operation enabled */
 #  define MCAN_CCCR_CME_FD_BSW     (2 << MCAN_CCCR_CME_SHIFT) /* CAN FD operation with bit rate switching enabled */
 
-#define MCAN_CCCR_CMR_SHIFT        (10)      /* Bits 10-11: CAN Mode Request */
+#define MCAN_CCCR_FDOE             (1 << 8)  /* Bit 8:  CAN FD Operation Enable (rev B) */
+#define MCAN_CCCR_BRSE             (1 << 9)  /* Bit 9:  Bit Rate Switching Enable (rev B) */
+#define MCAN_CCCR_CMR_SHIFT        (10)      /* Bits 10-11: CAN Mode Request (rev A)*/
 #define MCAN_CCCR_CMR_MASK         (3 << MCAN_CCCR_CMR_SHIFT)
 #  define MCAN_CCCR_CMR_NOCHG      (0 << MCAN_CCCR_CMR_SHIFT) /* No mode change */
 #  define MCAN_CCCR_CMR_FD         (1 << MCAN_CCCR_CMR_SHIFT) /* Request CAN FD operation */
 #  define MCAN_CCCR_CMR_FD_BSW     (2 << MCAN_CCCR_CMR_SHIFT) /* Request CAN FD operation with bit rate switching */
 #  define MCAN_CCCR_CMR_ISO11898_1 (3 << MCAN_CCCR_CMR_SHIFT) /* Request CAN operation according ISO11898-1 */
 
-#define MCAN_CCCR_FDO              (1 << 12) /* Bit 12: CAN FD Operation */
+#define MCAN_CCCR_FDO              (1 << 12) /* Bit 12: CAN FD Operation (rev A) */
+#define MCAN_CCCR_PXHD             (1 << 12) /* Bit 12: Protocol Exception Event Handling (rev B) */
 #define MCAN_CCCR_FDBS             (1 << 13) /* Bit 13: CAN FD Bit Rate Switching */
+#define MCAN_CCCR_EFBI             (1 << 13) /* Bit 13: Edge Filtering during Bus Integration */
 #define MCAN_CCCR_TXP              (1 << 14) /* Bit 14: Transmit Pause */
-
-/* Bit Timing and Prescaler Register */
-
-#define MCAN_BTP_SJW_SHIFT         (0)       /* Bits 0-3: (Re) Synchronization Jump Width */
-#define MCAN_BTP_SJW_MASK          (15 << MCAN_BTP_SJW_SHIFT)
-#  define MCAN_BTP_SJW(n)          ((uint32_t)(n) << MCAN_BTP_SJW_SHIFT)
-#define MCAN_BTP_TSEG2_SHIFT       (4)       /* Bits 4-7: Time Segment After Sample Point */
-#define MCAN_BTP_TSEG2_MASK        (15 << MCAN_BTP_TSEG2_SHIFT)
-#  define MCAN_BTP_TSEG2(n)        ((uint32_t)(n) << MCAN_BTP_TSEG2_SHIFT)
-#define MCAN_BTP_TSEG1_SHIFT       (8)       /* Bits 8-13: Time Segment Before Sample Point */
-#define MCAN_BTP_TSEG1_MASK        (0x3f << MCAN_BTP_TSEG1_SHIFT)
-#  define MCAN_BTP_TSEG1(n)        ((uint32_t)(n) << MCAN_BTP_TSEG1_SHIFT)
-#define MCAN_BTP_BRP_SHIFT         (16)      /* Bits 16-25: Baud Rate Prescaler */
-#define MCAN_BTP_BRP_MASK          (0x3ff << MCAN_BTP_BRP_SHIFT)
-#  define MCAN_BTP_BRP(n)          ((uint32_t)(n) << MCAN_BTP_BRP_SHIFT)
+#define MCAN_CCCR_NISO             (1 << 15) /* Bit 15: Non-ISO Operation (Bosch FD)*/
+
+/* Bit Timing and Prescaler Register (rev A) */
+
+#define MCAN_REVA_BTP_SJW_SHIFT    (0)       /* Bits 0-3: (Re) Synchronization Jump Width */
+#define MCAN_REVA_BTP_SJW_MASK     (0xf << MCAN_REVA_BTP_SJW_SHIFT)
+#  define MCAN_REVA_BTP_SJW(n)     ((uint32_t)(n) << MCAN_REVA_BTP_SJW_SHIFT)
+#define MCAN_REVA_BTP_TSEG2_SHIFT  (4)       /* Bits 4-7: Time Segment After Sample Point */
+#define MCAN_REVA_BTP_TSEG2_MASK   (0xf << MCAN_REVA_BTP_TSEG2_SHIFT)
+#  define MCAN_REVA_BTP_TSEG2(n)   ((uint32_t)(n) << MCAN_REVA_BTP_TSEG2_SHIFT)
+#define MCAN_REVA_BTP_TSEG1_SHIFT  (8)       /* Bits 8-13: Time Segment Before Sample Point */
+#define MCAN_REVA_BTP_TSEG1_MASK   (0x3f << MCAN_REVA_BTP_TSEG1_SHIFT)
+#  define MCAN_REVA_BTP_TSEG1(n)   ((uint32_t)(n) << MCAN_REVA_BTP_TSEG1_SHIFT)
+#define MCAN_REVA_BTP_BRP_SHIFT    (16)      /* Bits 16-25: Baud Rate Prescaler */
+#define MCAN_REVA_BTP_BRP_MASK     (0x3ff << MCAN_REVA_BTP_BRP_SHIFT)
+#  define MCAN_REVA_BTP_BRP(n)     ((uint32_t)(n) << MCAN_REVA_BTP_BRP_SHIFT)
+
+/* Nominal Bit Timing and Prescaler Register (rev B) */
+#define MCAN_NBTP_NTSEG2_SHIFT       (0)       /* Bits 0-6: Nominal Time Segment After Sample Point */
+#define MCAN_NBTP_NTSEG2_MASK        (0x7f << MCAN_NBTP_NTSEG2_SHIFT)
+#  define MCAN_NBTP_NTSEG2(n)        ((uint32_t)(n) << MCAN_NBTP_NTSEG2_SHIFT)
+#define MCAN_NBTP_NTSEG1_SHIFT       (8)       /* Bits 8-15: Nominal Time Segment Before Sample Point */
+#define MCAN_NBTP_NTSEG1_MASK        (0xff << MCAN_NBTP_NTSEG1_SHIFT)
+#  define MCAN_NBTP_NTSEG1(n)        ((uint32_t)(n) << MCAN_NBTP_NTSEG1_SHIFT)
+#define MCAN_NBTP_NBRP_SHIFT         (16)      /* Bits 16-24: Nominal Bit Rate Prescaler */
+#define MCAN_NBTP_NBRP_MASK          (0x1ff << MCAN_NBTP_NBRP_SHIFT)
+#  define MCAN_NBTP_NBRP(n)          ((uint32_t)(n) << MCAN_NBTP_NBRP_SHIFT)
+#define MCAN_NBTP_NSJW_SHIFT         (25)       /* Bits 25-31: Nominal (Re) Synchronization Jump Width */
+#define MCAN_NBTP_NSJW_MASK          (0x7f << MCAN_NBTP_NSJW_SHIFT)
+#  define MCAN_NBTP_NSJW(n)          ((uint32_t)(n) << MCAN_NBTP_NSJW_SHIFT)
 
 /* Timestamp Counter Configuration Register */
 
@@ -330,7 +272,7 @@
 #define MCAN_PSR_EC_NO_CHANGE      (7)       /* No CAN bus event was detected since last read */
 
 #define MCAN_PSR_LEC_SHIFT         (0)       /* Bits 0-2: Last Error Code */
-#define MCAN_PSR_LEC_MASK          (7 << MCAN_PSR_LEC_SHIFT)
+#define MCAN_PSR_LEC_MASK          (0x7 << MCAN_PSR_LEC_SHIFT)
 #  define MCAN_PSR_LEC(n)          ((uint32_t)(n) << MCAN_PSR_LEC_SHIFT) /* See error codes above */
 
 #define MCAN_PSR_ACT_SHIFT         (3)       /* Bits 3-4: Activity */
@@ -343,16 +285,25 @@
 #define MCAN_PSR_EP                (1 << 5)  /* Bit 5:  Error Passive */
 #define MCAN_PSR_EW                (1 << 6)  /* Bit 6:  Warning Status */
 #define MCAN_PSR_BO                (1 << 7)  /* Bit 7:  Bus_Off Status */
-#define MCAN_PSR_FLEC_SHIFT        (8)       /* Bits 8-10: Fast Last Error Code */
-#define MCAN_PSR_FLEC_MASK         (7 << MCAN_PSR_FLEC_SHIFT)
+#define MCAN_PSR_FLEC_SHIFT        (8)       /* Bits 8-10: Fast Last Error Code (rev A) */
+#define MCAN_PSR_FLEC_MASK         (0x7 << MCAN_PSR_FLEC_SHIFT)
 #  define MCAN_PSR_FLEC(n)         ((uint32_t)(n) << MCAN_PSR_FLEC_SHIFT) /* See error codes above */
 
+#define MCAN_PSR_DLEC_SHIFT        (8)       /* Bits 8-10: Data Last Error Code (rev B) */
+#define MCAN_PSR_DLEC_MASK         (0x7 << MCAN_PSR_DLEC_SHIFT)
+#  define MCAN_PSR_DLEC(n)         ((uint32_t)(n) << MCAN_PSR_DLEC_SHIFT) /* See error codes above */
+
 #define MCAN_PSR_RESI              (1 << 11) /* Bit 11: ESI Flag of Last Received CAN FD Message */
 #define MCAN_PSR_RBRS              (1 << 12) /* Bit 12: BRS Flag of Last Received CAN FD Message */
-#define MCAN_PSR_REDL              (1 << 13) /* Bit 13: Received a CAN FD Message */
+#define MCAN_PSR_REDL              (1 << 13) /* Bit 13: Received a CAN FD Message (rev A) */
+#define MCAN_PSR_RFDF              (1 << 13) /* Bit 13: Received a CAN FD Message (rev B) */
+#define MCAN_PSR_PXE               (1 << 14) /* Bit 14: Protocol Exception Event (rev B) */
+#define MCAN_PSR_TDCV_SHIFT        (16)      /* Bits 16-22: Transmitter Delay Compensation Value (rev B) */
+#define MCAN_PSR_TDCV_MASK         (0x7f << MCAN_PSR_TDCV_SHIFT)
+#  define MCAN_PSR_TDCV(n)          ((uint32_t)(n) << MCAN_PSR_TDCV_SHIFT)
 
 /* Common bit definitions for Interrupt Register, Interrupt Enable Register,
- * Interrupt Line Select Register
+ * Interrupt, Line Select Register
  */
 
 #define MCAN_INT_RF0N              (1 << 0)  /* Bit 0:  Receive FIFO 0 New Message */
@@ -380,13 +331,17 @@
 #define MCAN_INT_EW                (1 << 24) /* Bit 24: Warning Status */
 #define MCAN_INT_BO                (1 << 25) /* Bit 25: Bus_Off Status */
 #define MCAN_INT_WDI               (1 << 26) /* Bit 26: Watchdog Interrupt */
-#define MCAN_INT_CRCE              (1 << 27) /* Bit 27: Receive CRC Error */
-#define MCAN_INT_BE                (1 << 28) /* Bit 28: Bit Error */
-#define MCAN_INT_ACKE              (1 << 29) /* Bit 29: Acknowledge Error */
-#define MCAN_INT_FOE               (1 << 30) /* Bit 30: Format Error */
-#define MCAN_INT_STE               (1 << 31) /* Bit 31: Stuff Error */
-
-#define MCAN_INT_ALL               (0xffcfffff)
+#define MCAN_INT_CRCE              (1 << 27) /* Bit 27: Receive CRC Error (rev A) */
+#define MCAN_INT_PEA               (1 << 27) /* Bit 27: Protocol Error in Arbitration Phase (rev B) */
+#define MCAN_INT_BE                (1 << 28) /* Bit 28: Bit Error (rev A) */
+#define MCAN_INT_PED               (1 << 28) /* Bit 28: Protocol Error in Data Phase (rev B) */
+#define MCAN_INT_ACKE              (1 << 29) /* Bit 29: Acknowledge Error (rev A) */
+#define MCAN_INT_ARA               (1 << 29) /* Bit 29: Access to Reserved Address (rev B) */
+#define MCAN_INT_FOE               (1 << 30) /* Bit 30: Format Error (rev A) */
+#define MCAN_INT_STE               (1 << 31) /* Bit 31: Stuff Error (rev A) */
+
+#define MCAN_REVA_INT_ALL          (0xffcfffff)
+#define MCAN_REVB_INT_ALL         (0x3fcfffff)
 
 /* Interrupt Line Enable Register */
 
@@ -632,7 +587,7 @@
 
 /* Transmit Buffer Cancellation Finished Interrupt Enable Register */
 
-#define MCAN_TXBTIE(n)             (1 << (n)) /* Cancellation finished interrupt enable for transmit buffer n, n=0-31 */
+#define MCAN_TXBCIE(n)             (1 << (n)) /* Cancellation finished interrupt enable for transmit buffer n, n=0-31 */
 
 /* Transmit Event FIFO Configuration Register */
 
@@ -695,8 +650,10 @@
 #define BUFFER_R1_DLC_SHIFT        (16)      /* Bits 16-19: Date length code */
 #define BUFFER_R1_DLC_MASK         (15 << BUFFER_R1_DLC_SHIFT)
 #  define BUFFER_R1_DLC(n)         ((uint32_t)(n) << BUFFER_R1_DLC_SHIFT)
-#define BUFFER_R1_BRS              (1 << 20) /* Bit 20: Bit Rate Switch */
-#define BUFFER_R1_EDL              (1 << 21) /* Bit 21: Extended Data Length */
+#define BUFFER_R1_BRS_SHIFT        (20)
+#define BUFFER_R1_EDL_SHIFT        (21)
+#define BUFFER_R1_BRS              (1 << BUFFER_R1_BRS_SHIFT) /* Bit 20: Bit Rate Switch */
+#define BUFFER_R1_EDL              (1 << BUFFER_R1_EDL_SHIFT) /* Bit 21: Extended Data Length */
 
 /* RX buffer/RX FIFOs */
 
@@ -807,8 +764,4 @@
  * Public Data
  ****************************************************************************/
 
-/****************************************************************************
- * Public Functions Prototypes
- ****************************************************************************/
-
 #endif /* __ARCH_ARM_SRC_SAMV7_HARDWARE_SAM_MCAN_H */
diff --git a/arch/arm/src/samv7/sam_mcan.c b/arch/arm/src/samv7/sam_mcan.c
index ead4a51..3d23705 100644
--- a/arch/arm/src/samv7/sam_mcan.c
+++ b/arch/arm/src/samv7/sam_mcan.c
@@ -35,7 +35,6 @@
 #include <inttypes.h>
 #include <stdbool.h>
 #include <string.h>
-#include <assert.h>
 #include <errno.h>
 #include <debug.h>
 
@@ -49,6 +48,7 @@
 #include "arm_arch.h"
 
 #include "hardware/sam_matrix.h"
+#include "hardware/sam_chipid.h"
 #include "hardware/sam_pinmap.h"
 #include "sam_periphclks.h"
 #include "sam_gpio.h"
@@ -138,30 +138,30 @@
 #  define MCAN0_SJW    (CONFIG_SAMV7_MCAN0_FSJW - 1)
 
 #  if MCAN0_TSEG1 > 63
-#    error Invalid MCAN0 TSEG1
+#    error Invalid MCAN0 NTSEG1
 #  endif
 #  if MCAN0_TSEG2 > 15
-#    error Invalid MCAN0 TSEG2
+#    error Invalid MCAN0 NTSEG2
 #  endif
 #  if MCAN0_SJW > 15
-#    error Invalid MCAN0 SJW
+#    error Invalid MCAN0 NSJW
 #  endif
 
-#  define MCAN0_FTSEG1 (CONFIG_SAMV7_MCAN0_FPROPSEG + CONFIG_SAMV7_MCAN0_FPHASESEG1)
-#  define MCAN0_FTSEG2 (CONFIG_SAMV7_MCAN0_FPHASESEG2)
-#  define MCAN0_FBRP   ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
-                       ((float)(MCAN0_FTSEG1 + MCAN0_FTSEG2 + 3) * \
+#  define MCAN0_DTSEG1 (CONFIG_SAMV7_MCAN0_FPROPSEG + CONFIG_SAMV7_MCAN0_FPHASESEG1)
+#  define MCAN0_DTSEG2 (CONFIG_SAMV7_MCAN0_FPHASESEG2)
+#  define MCAN0_DBRP   ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
+                       ((float)(MCAN0_DTSEG1 + MCAN0_DTSEG2 + 3) * \
                         (float)CONFIG_SAMV7_MCAN0_FBITRATE)) - 1))
-#  define MCAN0_FSJW   (CONFIG_SAMV7_MCAN0_FFSJW - 1)
+#  define MCAN0_DSJW   (CONFIG_SAMV7_MCAN0_FFSJW - 1)
 
-#  if MCAN0_FTSEG1 > 15
-#    error Invalid MCAN0 FTSEG1
+#  if MCAN0_DTSEG1 > 15
+#    error Invalid MCAN0 DTSEG1
 #  endif
-#  if MCAN0_FTSEG2 > 7
-#    error Invalid MCAN0 FTSEG2
+#  if MCAN0_DTSEG2 > 7
+#    error Invalid MCAN0 DTSEG2
 #  endif
-#  if MCAN0_FSJW > 3
-#    error Invalid MCAN0 FSJW
+#  if MCAN0_DSJW > 3
+#    error Invalid MCAN0 DSJW
 #  endif
 
 /* MCAN0 RX FIFO0 element size */
@@ -422,31 +422,31 @@
                         (float)CONFIG_SAMV7_MCAN1_BITRATE)) - 1))
 #  define MCAN1_SJW    (CONFIG_SAMV7_MCAN1_FSJW - 1)
 
-#  if MCAN1_TSEG1 > 63
-#    error Invalid MCAN1 TSEG1
+#  if MCAN1_NTSEG1 > 63
+#    error Invalid MCAN1 NTSEG1
 #  endif
-#  if MCAN1_TSEG2 > 15
-#    error Invalid MCAN1 TSEG2
+#  if MCAN1_NTSEG2 > 15
+#    error Invalid MCAN1 NTSEG2
 #  endif
-#  if MCAN1_SJW > 15
-#    error Invalid MCAN1 SJW
+#  if MCAN1_NSJW > 15
+#    error Invalid MCAN1 NSJW
 #  endif
 
-#  define MCAN1_FTSEG1 (CONFIG_SAMV7_MCAN1_FPROPSEG + CONFIG_SAMV7_MCAN1_FPHASESEG1)
-#  define MCAN1_FTSEG2 (CONFIG_SAMV7_MCAN1_FPHASESEG2)
-#  define MCAN1_FBRP   ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
-                       ((float)(MCAN1_FTSEG1 + MCAN1_FTSEG2 + 3) * \
+#  define MCAN1_DTSEG1 (CONFIG_SAMV7_MCAN1_FPROPSEG + CONFIG_SAMV7_MCAN1_FPHASESEG1)
+#  define MCAN1_DTSEG2 (CONFIG_SAMV7_MCAN1_FPHASESEG2)
+#  define MCAN1_DBRP   ((uint32_t)(((float) SAMV7_MCANCLK_FREQUENCY / \
+                       ((float)(MCAN1_DTSEG1 + MCAN1_DTSEG2 + 3) * \
                         (float)CONFIG_SAMV7_MCAN1_FBITRATE)) - 1))
-#  define MCAN1_FSJW   (CONFIG_SAMV7_MCAN1_FFSJW - 1)
+#  define MCAN1_DSJW   (CONFIG_SAMV7_MCAN1_FFSJW - 1)
 
-#if MCAN1_FTSEG1 > 15
-#  error Invalid MCAN1 FTSEG1
+#if MCAN1_DTSEG1 > 15
+#  error Invalid MCAN1 DTSEG1
 #endif
-#if MCAN1_FTSEG2 > 7
-#  error Invalid MCAN1 FTSEG2
+#if MCAN1_DTSEG2 > 7
+#  error Invalid MCAN1 DTSEG2
 #endif
-#if MCAN1_FSJW > 3
-#  error Invalid MCAN1 FSJW
+#if MCAN1_DSJW > 3
+#  error Invalid MCAN1 DSJW
 #endif
 
 /* MCAN1 RX FIFO0 element size */
@@ -726,22 +726,30 @@
  *
  *   MCAN_INT_DRX  - Message stored to Dedicated Receive Buffer
  *
- * Mode-independent RX-related interrupts
+  * Mode-independent RX-related interrupts for revision A
  *
  *   MCAN_INT_CRCE - Receive CRC Error
  *   MCAN_INT_FOE  - Format Error
  *   MCAN_INT_STE  - Stuff Error
+ *
+ * Mode-independent RX-related interrupts for revision B
+ *
+ *   MCAN_INT_PEA - Protocol Error in Arbitration Phase
+ *   MCAN_INT_PED - Protocol Error in Data Phase
  */
 
-#define MCAN_RXCOMMON_INTS (MCAN_INT_CRCE | MCAN_INT_FOE | MCAN_INT_STE)
-#define MCAN_RXFIFO0_INTS  (MCAN_INT_RF0N | MCAN_INT_RF0W | MCAN_INT_RF0L)
-#define MCAN_RXFIFO1_INTS  (MCAN_INT_RF1N | MCAN_INT_RF1W | MCAN_INT_RF1L)
-#define MCAN_RXFIFO_INTS   (MCAN_RXFIFO0_INTS | MCAN_RXFIFO1_INTS | \
-                            MCAN_INT_HPM | MCAN_RXCOMMON_INTS)
-#define MCAN_RXDEDBUF_INTS (MCAN_INT_DRX | MCAN_RXCOMMON_INTS)
+#define MCAN_RXCOMMON_INTS_REVA (MCAN_INT_CRCE | MCAN_INT_FOE | MCAN_INT_STE)
+#define MCAN_RXCOMMON_INTS (MCAN_INT_PEA | MCAN_INT_PED)
+#define MCAN_RXFIFO0_INTS       (MCAN_INT_RF0N | MCAN_INT_RF0W | MCAN_INT_RF0L)
+#define MCAN_RXFIFO1_INTS       (MCAN_INT_RF1N | MCAN_INT_RF1W | MCAN_INT_RF1L)
+#define MCAN_RXFIFO_INTS        (MCAN_RXFIFO0_INTS | MCAN_RXFIFO1_INTS | \
+                                 MCAN_INT_HPM | MCAN_RXCOMMON_INTS)
+#define MCAN_RXDEDBUF_INTS      (MCAN_INT_DRX | MCAN_RXCOMMON_INTS)
 
-#define MCAN_RXERR_INTS    (MCAN_INT_RF0L | MCAN_INT_RF1L | MCAN_INT_CRCE | \
-                            MCAN_INT_FOE | MCAN_INT_STE)
+#define MCAN_RXERR_INTS_REVA    (MCAN_INT_RF0L | MCAN_INT_RF1L | MCAN_INT_CRCE | \
+                                 MCAN_INT_FOE | MCAN_INT_STE)
+#define MCAN_RXERR_INTS    (MCAN_INT_RF0L | MCAN_INT_RF1L | MCAN_INT_PEA | \
+                                 MCAN_INT_PED)
 
 /* TX FIFOQ mode interrupts
  *
@@ -758,18 +766,20 @@
  *
  *   MCAN_INT_TC   - Transmission Completed
  *   MCAN_INT_TCF  - Transmission Cancellation Finished
- *   MCAN_INT_BE   - Bit Error
- *   MCAN_INT_ACKE - Acknowledge Error
+ *   MCAN_INT_BE   - Bit Error (rev A)
+ *   MCAN_INT_ACKE - Acknowledge Error (rev A)
+ *   MCAN_INT_PEA  - Protocol Error in Arbitration Phase (rev B)
+ *   MCAN_INT_PED  - Protocol Error in Data Phase (rev B)
  */
 
-#define MCAN_TXCOMMON_INTS (MCAN_INT_TC | MCAN_INT_TCF | MCAN_INT_BE | \
-                            MCAN_INT_ACKE)
+#define MCAN_TXCOMMON_INTS (MCAN_INT_TC | MCAN_INT_TCF | MCAN_INT_PEA | \
+                            MCAN_INT_PED)
 #define MCAN_TXFIFOQ_INTS  (MCAN_INT_TFE | MCAN_TXCOMMON_INTS)
 #define MCAN_TXEVFIFO_INTS (MCAN_INT_TEFN | MCAN_INT_TEFW | MCAN_INT_TEFF | \
                             MCAN_INT_TEFL)
 #define MCAN_TXDEDBUF_INTS MCAN_TXCOMMON_INTS
 
-#define MCAN_TXERR_INTS    (MCAN_INT_TEFL | MCAN_INT_BE | MCAN_INT_ACKE)
+#define MCAN_TXERR_INTS    (MCAN_INT_TEFL | MCAN_INT_PEA | MCAN_INT_PED)
 
 /* Common-, TX- and RX-Error-Mask */
 
@@ -835,6 +845,9 @@ struct sam_config_s
   uint32_t baud;            /* Configured baud */
   uint32_t btp;             /* Bit timing/prescaler register setting */
   uint32_t fbtp;            /* Fast bit timing/prescaler register setting */
+  uint32_t nbtp;            /* Nominal Bit timing/prescaler register setting */
+  uint32_t dbtp;            /* Data bit timing/prescaler register setting */
+  uint8_t rev;              /* Chip revision (0: A, 1: B) */
   uint8_t port;             /* MCAN port number (1 or 2) */
   uint8_t pid;              /* MCAN peripheral ID */
   uint8_t irq0;             /* MCAN peripheral IRQ number for interrupt line 0 */
@@ -884,6 +897,7 @@ struct sam_mcan_s
   uint32_t fbtp;            /* Current fast bit timing */
   uint32_t rxints;          /* Configured RX interrupts */
   uint32_t txints;          /* Configured TX interrupts */
+  uint8_t rev;              /* Chip revision (0: A, 1: B) */
 
 #ifdef CONFIG_CAN_EXTID
   uint32_t extfilters[2];   /* Extended filter bit allocator.  2*32=64 */
@@ -991,27 +1005,35 @@ static const struct can_ops_s g_mcanops =
 
 static uint32_t g_mcan0_msgram[MCAN0_MSGRAM_WORDS]
 #ifdef CONFIG_ARMV7M_DCACHE
-  aligned_data(MCAN_ALIGN);
+  __attribute__((aligned(MCAN_ALIGN)));
 #else
   ;
 #endif
 
 /* Constant configuration */
 
-static const struct sam_config_s g_mcan0const =
+static struct sam_config_s g_mcan0const =
 {
   .rxpinset         = GPIO_MCAN0_RX,
   .txpinset         = GPIO_MCAN0_TX,
   .base             = SAM_MCAN0_BASE,
   .baud             = CONFIG_SAMV7_MCAN0_BITRATE,
-  .btp              = MCAN_BTP_BRP(MCAN0_BRP) |
-                      MCAN_BTP_TSEG1(MCAN0_TSEG1) |
-                      MCAN_BTP_TSEG2(MCAN0_TSEG2) |
-                      MCAN_BTP_SJW(MCAN0_SJW),
-  .fbtp             = MCAN_FBTP_FBRP(MCAN0_FBRP) |
-                      MCAN_FBTP_FTSEG1(MCAN0_FTSEG1) |
-                      MCAN_FBTP_FTSEG2(MCAN0_FTSEG2) |
-                      MCAN_FBTP_FSJW(MCAN0_FSJW),
+  .btp              = MCAN_REVA_BTP_BRP(MCAN0_BRP) |
+                      MCAN_REVA_BTP_TSEG1(MCAN0_TSEG1) |
+                      MCAN_REVA_BTP_TSEG2(MCAN0_TSEG2) |
+                      MCAN_REVA_BTP_SJW(MCAN0_SJW),
+  .fbtp             = MCAN_REVA_FBTP_FBRP(MCAN0_DBRP) |
+                      MCAN_REVA_FBTP_FTSEG1(MCAN0_DTSEG1) |
+                      MCAN_REVA_FBTP_FTSEG2(MCAN0_DTSEG2) |
+                      MCAN_REVA_FBTP_FSJW(MCAN0_DSJW),
+  .nbtp             = MCAN_NBTP_NBRP(MCAN0_BRP) |
+                      MCAN_NBTP_NTSEG1(MCAN0_TSEG1) |
+                      MCAN_NBTP_NTSEG2(MCAN0_TSEG2) |
+                      MCAN_NBTP_NSJW(MCAN0_SJW),
+  .dbtp             = MCAN_DBTP_DBRP(MCAN0_DBRP) |
+                      MCAN_DBTP_DTSEG1(MCAN0_DTSEG1) |
+                      MCAN_DBTP_DTSEG2(MCAN0_DTSEG2) |
+                      MCAN_DBTP_DSJW(MCAN0_DSJW),
   .port             = 0,
   .pid              = SAM_PID_MCAN00,
   .irq0             = SAM_IRQ_MCAN00,
@@ -1071,27 +1093,35 @@ static struct can_dev_s g_mcan0dev;
 
 static uint32_t g_mcan1_msgram[MCAN1_MSGRAM_WORDS]
 #ifdef CONFIG_ARMV7M_DCACHE
-  aligned_data(MCAN_ALIGN);
+  __attribute__((aligned(MCAN_ALIGN)));
 #else
   ;
 #endif
 
 /* MCAN1 constant configuration */
 
-static const struct sam_config_s g_mcan1const =
+static struct sam_config_s g_mcan1const =
 {
   .rxpinset         = GPIO_MCAN1_RX,
   .txpinset         = GPIO_MCAN1_TX,
   .base             = SAM_MCAN1_BASE,
   .baud             = CONFIG_SAMV7_MCAN1_BITRATE,
-  .btp              = MCAN_BTP_BRP(MCAN1_BRP) |
-                      MCAN_BTP_TSEG1(MCAN1_TSEG1) |
-                      MCAN_BTP_TSEG2(MCAN1_TSEG2) |
-                      MCAN_BTP_SJW(MCAN1_SJW),
-  .fbtp             = MCAN_FBTP_FBRP(MCAN1_FBRP) |
-                      MCAN_FBTP_FTSEG1(MCAN1_FTSEG1) |
-                      MCAN_FBTP_FTSEG2(MCAN1_FTSEG2) |
-                      MCAN_FBTP_FSJW(MCAN1_FSJW),
+  .btp              = MCAN_REVA_BTP_BRP(MCAN1_BRP) |
+                      MCAN_REVA_BTP_TSEG1(MCAN1_TSEG1) |
+                      MCAN_REVA_BTP_TSEG2(MCAN1_TSEG2) |
+                      MCAN_REVA_BTP_SJW(MCAN1_SJW),
+  .fbtp             = MCAN_REVA_FBTP_FBRP(MCAN1_DBRP) |
+                      MCAN_REVA_FBTP_FTSEG1(MCAN1_DTSEG1) |
+                      MCAN_REVA_FBTP_FTSEG2(MCAN1_DTSEG2) |
+                      MCAN_REVA_FBTP_FSJW(MCAN1_DSJW),
+  .nbtp             = MCAN_NBTP_NBRP(MCAN1_BRP) |
+                      MCAN_NBTP_NTSEG1(MCAN1_TSEG1) |
+                      MCAN_NBTP_NTSEG2(MCAN1_TSEG2) |
+                      MCAN_NBTP_NSJW(MCAN1_SJW),
+  .dbtp             = MCAN_DBTP_DBRP(MCAN1_DBRP) |
+                      MCAN_DBTP_DTSEG1(MCAN1_DTSEG1) |
+                      MCAN_DBTP_DTSEG2(MCAN1_DTSEG2) |
+                      MCAN_DBTP_DSJW(MCAN1_DSJW),
   .port             = 1,
   .pid              = SAM_PID_MCAN10,
   .irq0             = SAM_IRQ_MCAN10,
@@ -1289,17 +1319,17 @@ static void mcan_dumpregs(FAR struct sam_mcan_s *priv, FAR const char *msg)
   FAR const struct sam_config_s *config = priv->config;
 
   caninfo("MCAN%d Registers: %s\n", config->port, msg);
-  caninfo("   Base: %08x\n", config->base);
+  caninfo("  Base: %08x\n", config->base);
 
-  caninfo("   CUST: %08x  FBTP: %08x TEST: %08x    RWD: %08x\n",
+  caninfo("  CUST: %08x  DBTP: %08x  TEST: %08x    RWD: %08x\n",
           getreg32(config->base + SAM_MCAN_CUST_OFFSET),
-          getreg32(config->base + SAM_MCAN_FBTP_OFFSET),
+          getreg32(config->base + SAM_MCAN_DBTP_OFFSET),
           getreg32(config->base + SAM_MCAN_TEST_OFFSET),
           getreg32(config->base + SAM_MCAN_RWD_OFFSET));
 
-  caninfo("  CCCR: %08x   BTP: %08x  TSCC: %08x   TSCV: %08x\n",
+  caninfo("  CCCR: %08x  NBTP: %08x  TSCC: %08x   TSCV: %08x\n",
           getreg32(config->base + SAM_MCAN_CCCR_OFFSET),
-          getreg32(config->base + SAM_MCAN_BTP_OFFSET),
+          getreg32(config->base + SAM_MCAN_NBTP_OFFSET),
           getreg32(config->base + SAM_MCAN_TSCC_OFFSET),
           getreg32(config->base + SAM_MCAN_TSCV_OFFSET));
 
@@ -2672,18 +2702,37 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
 
           DEBUGASSERT(bt != NULL);
 
-          regval       = mcan_getreg(priv, SAM_MCAN_BTP_OFFSET);
-          bt->bt_sjw   = ((regval & MCAN_BTP_SJW_MASK) >>
-                          MCAN_BTP_SJW_SHIFT) + 1;
-          bt->bt_tseg1 = ((regval & MCAN_BTP_TSEG1_MASK) >>
-                          MCAN_BTP_TSEG1_SHIFT) + 1;
-          bt->bt_tseg2 = ((regval & MCAN_BTP_TSEG2_MASK) >>
-                          MCAN_BTP_TSEG2_SHIFT) + 1;
+          regval       = mcan_getreg(priv, SAM_MCAN_NBTP_OFFSET);
+
+          if (priv->rev == 0)
+            {
+              /* Revision A */
+
+              bt->bt_sjw   = ((regval & MCAN_REVA_BTP_SJW_MASK) >>
+                              MCAN_REVA_BTP_SJW_SHIFT) + 1;
+              bt->bt_tseg1 = ((regval & MCAN_REVA_BTP_TSEG1_MASK) >>
+                              MCAN_REVA_BTP_TSEG1_SHIFT) + 1;
+              bt->bt_tseg2 = ((regval & MCAN_REVA_BTP_TSEG2_MASK) >>
+                              MCAN_REVA_BTP_TSEG2_SHIFT) + 1;
+              brp          = ((regval & MCAN_REVA_BTP_BRP_MASK) >>
+                              MCAN_REVA_BTP_BRP_SHIFT) + 1;
+            }
+          else
+            {
+              /* Revision B */
+
+              bt->bt_sjw   = ((regval & MCAN_NBTP_NSJW_MASK) >>
+                              MCAN_NBTP_NSJW_SHIFT) + 1;
+              bt->bt_tseg1 = ((regval & MCAN_NBTP_NTSEG1_MASK) >>
+                              MCAN_NBTP_NTSEG1_SHIFT) + 1;
+              bt->bt_tseg2 = ((regval & MCAN_NBTP_NTSEG2_MASK) >>
+                              MCAN_NBTP_NTSEG2_SHIFT) + 1;
+              brp          = ((regval & MCAN_NBTP_NBRP_MASK) >>
+                              MCAN_NBTP_NBRP_SHIFT) + 1;
+            }
 
-          brp          = ((regval & MCAN_BTP_BRP_MASK) >>
-                          MCAN_BTP_BRP_SHIFT) + 1;
           bt->bt_baud  = SAMV7_MCANCLK_FREQUENCY / brp /
-                         (bt->bt_tseg1 + bt->bt_tseg2 + 1);
+                        (bt->bt_tseg1 + bt->bt_tseg2 + 1);
           ret = OK;
         }
         break;
@@ -2736,8 +2785,18 @@ static int mcan_ioctl(FAR struct can_dev_s *dev, int cmd, unsigned long arg)
           /* Save the value of the new bit timing register */
 
           flags = enter_critical_section();
-          priv->btp = MCAN_BTP_BRP(brp) | MCAN_BTP_TSEG1(tseg1) |
-                      MCAN_BTP_TSEG2(tseg2) | MCAN_BTP_SJW(sjw);
+          if (priv->rev == 0)
+            {
+              priv->btp = MCAN_REVA_BTP_BRP(brp) |
+                          MCAN_REVA_BTP_TSEG1(tseg1) |
+                          MCAN_REVA_BTP_TSEG2(tseg2) |
+                          MCAN_REVA_BTP_SJW(sjw);
+            }
+          else
+            {
+              priv->btp = MCAN_NBTP_NBRP(brp) | MCAN_NBTP_NTSEG1(tseg1) |
+                          MCAN_NBTP_NTSEG2(tseg2) | MCAN_NBTP_NSJW(sjw);
+            }
 
           /* We need to reset to instantiate the new timing.  Save
            * current state information so that recover to this
@@ -2988,7 +3047,7 @@ static int mcan_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
 
   /* Format the TX FIFOQ entry
    *
-   * Format word T1:
+   * Format word T0:
    *   Transfer message ID (ID)          - Value from message structure
    *   Remote Transmission Request (RTR) - Value from message structure
    *   Extended Identifier (XTD)         - Depends on configuration.
@@ -3024,6 +3083,19 @@ static int mcan_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
    */
 
   txbuffer[1] = BUFFER_R1_DLC(msg->cm_hdr.ch_dlc);
+
+#ifdef CONFIG_CAN_FD
+  if (msg->cm_hdr.ch_edl)
+    {
+      txbuffer[1] |= BUFFER_R1_EDL;
+    }
+
+  if (msg->cm_hdr.ch_brs)
+    {
+      txbuffer[1] |= BUFFER_R1_BRS;
+    }
+#endif
+
   reginfo("T1: %08x\n", txbuffer[1]);
 
   /* Followed by the amount of data corresponding to the DLC (T2..) */
@@ -3261,6 +3333,8 @@ static void mcan_error(FAR struct can_dev_s *dev, uint32_t status)
   uint16_t errbits;
   uint8_t data[CAN_ERROR_DLC];
   int ret;
+  uint32_t lec;
+  uint32_t dlec;
 
   /* Encode error bits */
 
@@ -3339,43 +3413,54 @@ static void mcan_error(FAR struct can_dev_s *dev, uint32_t status)
       data[1] |= CAN_ERROR1_UNSPEC;
     }
 
-  if ((status & MCAN_INT_CRCE) != 0)
+  if ((status & (MCAN_INT_PEA | MCAN_INT_CRCE)) != 0)
     {
-      /* Receive CRC Error */
+      lec = psr & MCAN_PSR_LEC_MASK;
+      dlec = (psr & MCAN_PSR_DLEC_MASK) >> MCAN_PSR_DLEC_SHIFT;
 
-      errbits |= CAN_ERROR_PROTOCOL;
-      data[3] |= (CAN_ERROR3_CRCSEQ | CAN_ERROR3_CRCDEL);
-    }
+      if ((lec == MCAN_PSR_EC_CRC_ERROR) || (dlec == MCAN_PSR_EC_CRC_ERROR))
+        {
+          /* Receive CRC Error */
 
-  if ((status & MCAN_INT_BE) != 0)
-    {
-      /* Bit Error */
+          errbits |= CAN_ERROR_PROTOCOL;
+          data[3] |= (CAN_ERROR3_CRCSEQ | CAN_ERROR3_CRCDEL);
+        }
 
-      errbits |= CAN_ERROR_PROTOCOL;
-      data[2] |= CAN_ERROR2_BIT;
-    }
+      if ((lec == MCAN_PSR_EC_BIT0_ERROR) || \
+          (lec == MCAN_PSR_EC_BIT1_ERROR) || \
+          (dlec == MCAN_PSR_EC_BIT0_ERROR) || \
+          (dlec == MCAN_PSR_EC_BIT1_ERROR))
+        {
+          /* Bit Error */
 
-  if ((status & MCAN_INT_ACKE) != 0)
-    {
-      /* Acknowledge Error */
+          errbits |= CAN_ERROR_PROTOCOL;
+          data[2] |= CAN_ERROR2_BIT;
+        }
 
-      errbits |= CAN_ERROR_NOACK;
-    }
+      if ((lec == MCAN_PSR_EC_ACK_ERROR) || (dlec == MCAN_PSR_EC_ACK_ERROR))
+        {
+          /* Acknowledge Error */
 
-  if ((status & MCAN_INT_FOE) != 0)
-    {
-      /* Format Error */
+          errbits |= CAN_ERROR_NOACK;
+        }
 
-      errbits |= CAN_ERROR_PROTOCOL;
-      data[2] |= CAN_ERROR2_FORM;
-    }
+      if ((lec == MCAN_PSR_EC_FORM_ERROR) || \
+         (dlec == MCAN_PSR_EC_FORM_ERROR))
+        {
+          /* Format Error */
 
-  if ((status & MCAN_INT_STE) != 0)
-    {
-      /* Stuff Error */
+          errbits |= CAN_ERROR_PROTOCOL;
+          data[2] |= CAN_ERROR2_FORM;
+        }
+
+      if ((lec == MCAN_PSR_EC_STUFF_ERROR) || \
+         (dlec == MCAN_PSR_EC_STUFF_ERROR))
+        {
+          /* Stuff Error */
 
-      errbits |= CAN_ERROR_PROTOCOL;
-      data[2] |= CAN_ERROR2_STUFF;
+          errbits |= CAN_ERROR_PROTOCOL;
+          data[2] |= CAN_ERROR2_STUFF;
+        }
     }
 
   if (errbits != 0)
@@ -3490,6 +3575,11 @@ static void mcan_receive(FAR struct can_dev_s *dev, FAR uint32_t *rxbuffer,
 
   hdr.ch_dlc = (regval & BUFFER_R1_DLC_MASK) >> BUFFER_R1_DLC_SHIFT;
 
+#ifdef CONFIG_CAN_FD
+  hdr.ch_edl = (regval >> BUFFER_R1_EDL_SHIFT) & 1u;
+  hdr.ch_brs = (regval >> BUFFER_R1_BRS_SHIFT) & 1u;
+#endif
+
   /* And provide the CAN message to the upper half logic */
 
   ret = can_receive(dev, &hdr, (FAR uint8_t *)rxbuffer);
@@ -3525,6 +3615,7 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
   unsigned int nelem;
   unsigned int ndx;
   bool handled;
+  uint32_t psr;
 
   DEBUGASSERT(dev != NULL);
   priv = dev->cd_priv;
@@ -3551,8 +3642,9 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
 
           if ((pending & MCAN_CMNERR_INTS) != 0)
             {
-              canerr("ERROR: Common %08"PRIx32"\n",
-                     pending & MCAN_CMNERR_INTS);
+              psr = mcan_getreg(priv, SAM_MCAN_PSR_OFFSET);
+              canerr("ERROR: Common %08"PRIx32", PSR %08"PRIx32"\n",
+                     pending & MCAN_CMNERR_INTS, psr);
 
               /* Clear the error indications */
 
@@ -3563,7 +3655,9 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
 
           if ((pending & MCAN_TXERR_INTS) != 0)
             {
-              canerr("ERROR: TX %08"PRIx32"\n", pending & MCAN_TXERR_INTS);
+              psr = mcan_getreg(priv, SAM_MCAN_PSR_OFFSET);
+              canerr("ERROR: TX %08"PRIx32", PSR %08"PRIx32"\n",
+                     pending & MCAN_TXERR_INTS, psr);
 
               /* An Acknowledge-Error will occur if for example the device
                * is not connected to the bus.
@@ -3571,11 +3665,19 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
                * The CAN-Standard states that the Chip has to retry the
                * message forever, which will produce an ACKE every time.
                * To prevent this Interrupt-Flooding and the high CPU-Load
-               * we disable the ACKE here as long we didn't transfer at
+               * we disable the all errors here as long we didn't transfer at
                * least one message successfully (see MCAN_INT_TC below).
                */
 
-              ie &= ~MCAN_INT_ACKE;
+              if (priv->rev == 0)
+                {
+                  ie &= ~MCAN_INT_ACKE;
+                }
+              else
+                {
+                  ie &= ~(MCAN_INT_PEA | MCAN_INT_PED);
+                }
+
               mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
 
               /* Clear the error indications */
@@ -3597,7 +3699,9 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
 
           if ((pending & MCAN_RXERR_INTS) != 0)
             {
-              canerr("ERROR: RX %08"PRIx32"\n", pending & MCAN_RXERR_INTS);
+              psr = mcan_getreg(priv, SAM_MCAN_PSR_OFFSET);
+              canerr("ERROR: RX %08"PRIx32", PSR %08"PRIx32"\n",
+                     pending & MCAN_RXERR_INTS, psr);
 
               /* To prevent Interrupt-Flooding the current active
                * RX error interrupts are disabled. After successfully
@@ -3634,11 +3738,17 @@ static int mcan_interrupt(int irq, void *context, FAR void *arg)
            * re-enable the error interrupt here again.
            */
 
-          if ((ie & MCAN_INT_ACKE) == 0)
+          if ((priv->rev == 0) && ((ie & MCAN_INT_ACKE) == 0))
             {
                 ie |= MCAN_INT_ACKE;
                 mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
             }
+          else if ((priv->rev == 1) && \
+                  ((ie & (MCAN_INT_PEA | MCAN_INT_PED)) == 0))
+            {
+                ie |= MCAN_INT_PEA | MCAN_INT_PED;
+                mcan_putreg(priv, SAM_MCAN_IE_OFFSET, ie);
+            }
 
           /* Clear the pending TX completion interrupt (and all
            * other TX-related interrupts)
@@ -3847,7 +3957,7 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
   FAR uint32_t *msgram;
   uint32_t regval;
   uint32_t cntr;
-  uint32_t cmr;
+  uint32_t cmr = 0;
 
   caninfo("MCAN%d\n", config->port);
 
@@ -3905,12 +4015,27 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
 
   /* Clear all pending interrupts. */
 
-  mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_INT_ALL);
+  if (priv->rev == 0)
+    {
+      mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_REVA_INT_ALL);
+    }
+  else
+    {
+      mcan_putreg(priv, SAM_MCAN_IR_OFFSET, MCAN_REVB_INT_ALL);
+    }
 
   /* Configure MCAN bit timing */
 
-  mcan_putreg(priv, SAM_MCAN_BTP_OFFSET, priv->btp);
-  mcan_putreg(priv, SAM_MCAN_FBTP_OFFSET, priv->fbtp);
+  if (priv->rev == 0)
+    {
+      mcan_putreg(priv, SAM_MCAN_REVA_BTP_OFFSET, priv->btp);
+      mcan_putreg(priv, SAM_MCAN_REVA_FBTP_OFFSET, priv->fbtp);
+    }
+  else
+    {
+      mcan_putreg(priv, SAM_MCAN_NBTP_OFFSET, priv->btp);
+      mcan_putreg(priv, SAM_MCAN_DBTP_OFFSET, priv->fbtp);
+    }
 
   /* Configure message RAM starting addresses and sizes. */
 
@@ -3989,25 +4114,49 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
    */
 
   regval  = mcan_getreg(priv, SAM_MCAN_CCCR_OFFSET);
-  regval &= ~(MCAN_CCCR_CME_MASK | MCAN_CCCR_CMR_MASK);
+  if (priv->rev == 0)
+    {
+      regval &= ~(MCAN_CCCR_CME_MASK | MCAN_CCCR_CMR_MASK);
+    }
+  else
+    {
+      regval &= ~(MCAN_CCCR_FDOE | MCAN_CCCR_BRSE | MCAN_CCCR_NISO);
+    }
 
   switch (config->mode)
     {
     default:
     case MCAN_ISO11898_1_MODE:
-      regval |= MCAN_CCCR_CME_ISO11898_1;
-      cmr     = MCAN_CCCR_CMR_ISO11898_1;
+      if (priv->rev == 0)
+        {
+          regval |= MCAN_CCCR_CME_ISO11898_1;
+          cmr     = MCAN_CCCR_CMR_ISO11898_1;
+        }
       break;
 
 #ifdef CONFIG_CAN_FD
     case MCAN_FD_MODE:
-      regval |= MCAN_CCCR_CME_FD;
-      cmr     = MCAN_CCCR_CMR_FD;
+      if (priv->rev == 0)
+        {
+          regval |= MCAN_CCCR_CME_FD;
+          cmr     = MCAN_CCCR_CMR_FD;
+        }
+      else
+        {
+          regval |= MCAN_CCCR_FDOE;
+        }
       break;
 
     case MCAN_FD_BSW_MODE:
-      regval |= MCAN_CCCR_CME_FD_BSW;
-      cmr     = MCAN_CCCR_CMR_FD_BSW;
+      if (priv->rev == 0)
+        {
+          regval |= MCAN_CCCR_CME_FD_BSW;
+          cmr     = MCAN_CCCR_CMR_FD_BSW;
+        }
+      else
+        {
+          regval |= (MCAN_CCCR_FDOE | MCAN_CCCR_BRSE);
+        }
       break;
 #endif
     }
@@ -4016,10 +4165,13 @@ static int mcan_hw_initialize(struct sam_mcan_s *priv)
 
   mcan_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval);
 
-  /* Request the mode change */
+  if (priv->rev == 0)
+    {
+      /* Request the mode change */
 
-  regval |= cmr;
-  mcan_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval);
+      regval |= cmr;
+      mcan_putreg(priv, SAM_MCAN_CCCR_OFFSET, regval);
+    }
 
 #if 0 /* Not necessary in initialization mode */
   /* Wait for the mode to take effect */
@@ -4195,12 +4347,34 @@ FAR struct can_dev_s *sam_mcan_initialize(int port)
       memset(priv, 0, sizeof(struct sam_mcan_s));
       priv->config = config;
 
+      /* Get the revision of the chip (A or B ) */
+
+      regval = getreg32(SAM_CHIPID_CIDR);
+      priv->rev = regval & CHIPID_CIDR_VERSION_MASK;
+
       /* Set the initial bit timing.  This might change subsequently
        * due to IOCTL command processing.
        */
 
-      priv->btp    = config->btp;
-      priv->fbtp   = config->fbtp;
+      if (priv->rev == 0)
+        {
+          /* Revision A */
+
+          priv->btp    = config->btp;
+          priv->fbtp   = config->fbtp;
+        }
+      else if (priv->rev == 1)
+        {
+          /* Revision B */
+
+          priv->btp    = config->nbtp;
+          priv->fbtp   = config->dbtp;
+        }
+      else
+        {
+          canerr("ERROR: Incorrect chip revision: %d\n", priv->rev);
+          return NULL;
+        }
 
       /* Initialize semaphores */