diff --git a/arch/arm64/src/imx9/hardware/imx9_flexcan.h b/arch/arm64/src/imx9/hardware/imx9_flexcan.h index e1dc42f31a774..5d29d474b41af 100644 --- a/arch/arm64/src/imx9/hardware/imx9_flexcan.h +++ b/arch/arm64/src/imx9/hardware/imx9_flexcan.h @@ -58,6 +58,10 @@ #define IMX9_CAN_ET_OFFSET 0x0078 /* External Timer Register */ #define IMX9_CAN_FLTC_IE_OFFSET 0x007c /* Fault Confinement Interrupt Enable Register */ +#define IMX9_CAN_MB_OFFSET 0x0080 /* CAN MB register */ +#define IMX9_CAN_MB_SIZE 0x0600 +#define IMX9_CAN_MB_END (IMX9_CAN_MB_OFFSET + IMX9_CAN_MB_SIZE) + #define IMX9_CAN_RXIMR_OFFSET(n) (0x0880+((n)<<2)) /* Rn Individual Mask Registers */ #define IMX9_CAN_MECR_OFFSET 0x0ae0 /* Memory Error Control Register */ diff --git a/arch/arm64/src/imx9/imx9_flexcan.c b/arch/arm64/src/imx9/imx9_flexcan.c index 46d09ffb8f5b2..9c31d35465d23 100644 --- a/arch/arm64/src/imx9/imx9_flexcan.c +++ b/arch/arm64/src/imx9/imx9_flexcan.c @@ -86,7 +86,6 @@ #define MSG_DATA sizeof(struct timeval) /* CAN bit timing values */ -#define CLK_FREQ 24000000 #define PRESDIV_MAX 256 #define SEG_MAX 8 @@ -221,6 +220,7 @@ struct imx9_driver_s const uintptr_t base; /* FLEXCAN base address */ const int irq; /* irq number */ + const uint32_t clk_freq; /* Peripheral clock frequency */ const bool canfd_capable; const int mb_address_offset; bool bifup; /* true:ifup false:ifdown */ @@ -373,7 +373,8 @@ static inline uint32_t arm64_lsb(unsigned int value) uint32_t imx9_bitratetotimeseg(struct flexcan_timeseg *timeseg, int32_t sp_tolerance, - uint32_t can_fd) + uint32_t can_fd, + uint32_t clk_freq) { int32_t tmppresdiv; int32_t numtq; @@ -391,7 +392,7 @@ uint32_t imx9_bitratetotimeseg(struct flexcan_timeseg *timeseg, for (tmppresdiv = 0; tmppresdiv < PRESDIV_MAX; tmppresdiv++) { - numtq = (CLK_FREQ / ((tmppresdiv + 1) * timeseg->bitrate)); + numtq = (clk_freq / ((tmppresdiv + 1) * timeseg->bitrate)); if (numtq == 0) { @@ -402,7 +403,7 @@ uint32_t imx9_bitratetotimeseg(struct flexcan_timeseg *timeseg, * lower than the one supported */ - if ((CLK_FREQ / ((tmppresdiv + 1) * numtq) == timeseg->bitrate) + if ((clk_freq / ((tmppresdiv + 1) * numtq) == timeseg->bitrate) && (numtq >= 8) && (numtq < NUMTQMAX)) { /* Compute time segments based on the value of the sampling point */ @@ -479,11 +480,11 @@ static int imx9_txpoll(struct net_driver_s *dev); /* Helper functions */ -static void imx9_setenable(uint32_t base, uint32_t enable); -static void imx9_setfreeze(uint32_t base, uint32_t freeze); -static uint32_t imx9_waitmcr_change(uint32_t base, - uint32_t mask, - uint32_t target_state); +static bool imx9_setenable(uint32_t base, bool enable); +static bool imx9_setfreeze(uint32_t base, bool freeze); +static bool imx9_waitmcr_change(uint32_t base, + uint32_t mask, + bool target_state); static struct mb_s *flexcan_get_mb(struct imx9_driver_s *priv, uint32_t mbi); @@ -586,7 +587,6 @@ static int imx9_transmit(struct imx9_driver_s *priv) uint32_t mbi = 0; uint32_t mb_bit; - uint32_t regval; #ifdef CONFIG_NET_CAN_CANFD uint32_t *frame_data_word; uint32_t i; @@ -665,6 +665,13 @@ static int imx9_transmit(struct imx9_driver_s *priv) peak_tx_mailbox_index_ = (peak_tx_mailbox_index_ > mbi ? peak_tx_mailbox_index_ : mbi); + /* Check if interrupt flag is pending, clear */ + + if (getreg32(priv->base + IMX9_CAN_IFLAG1_OFFSET) & IFLAG1_TX) + { + modifyreg32(priv->base + IMX9_CAN_IMASK1_OFFSET, IFLAG1_TX, 0); + } + union cs_e cs; cs.code = CAN_TXMB_DATAORREMOTE; struct mb_s *mb = flexcan_get_mb(priv, mbi); @@ -725,9 +732,7 @@ static int imx9_transmit(struct imx9_driver_s *priv) struct mb_s *buffer = flexcan_get_mb(priv, RXMBCOUNT); buffer->cs.code = CAN_TXMB_DATAORREMOTE; - regval = getreg32(priv->base + IMX9_CAN_IMASK1_OFFSET); - regval |= mb_bit; - putreg32(regval, priv->base + IMX9_CAN_IMASK1_OFFSET); + modifyreg32(priv->base + IMX9_CAN_IMASK1_OFFSET, 0, mb_bit); /* Increment statistics */ @@ -1250,57 +1255,44 @@ static void imx9_txtimeout_expiry(wdparm_t arg) #endif -static void imx9_setenable(uint32_t base, uint32_t enable) +static bool imx9_setenable(uint32_t base, bool enable) { - uint32_t regval; - if (enable) { - regval = getreg32(base + IMX9_CAN_MCR_OFFSET); - regval &= ~(CAN_MCR_MDIS); - putreg32(regval, base + IMX9_CAN_MCR_OFFSET); + modifyreg32(base + IMX9_CAN_MCR_OFFSET, CAN_MCR_MDIS, 0); } else { - regval = getreg32(base + IMX9_CAN_MCR_OFFSET); - regval |= CAN_MCR_MDIS; - putreg32(regval, base + IMX9_CAN_MCR_OFFSET); + modifyreg32(base + IMX9_CAN_MCR_OFFSET, 0, CAN_MCR_MDIS); } - imx9_waitmcr_change(base, CAN_MCR_LPMACK, 1); + return imx9_waitmcr_change(base, CAN_MCR_LPMACK, !enable); } -static void imx9_setfreeze(uint32_t base, uint32_t freeze) +static bool imx9_setfreeze(uint32_t base, bool freeze) { - uint32_t regval; if (freeze) { - /* Enter freeze mode */ - - regval = getreg32(base + IMX9_CAN_MCR_OFFSET); - regval |= (CAN_MCR_HALT | CAN_MCR_FRZ); - putreg32(regval, base + IMX9_CAN_MCR_OFFSET); + modifyreg32(base + IMX9_CAN_MCR_OFFSET, 0, CAN_MCR_HALT | CAN_MCR_FRZ); } else { - /* Exit freeze mode */ - - regval = getreg32(base + IMX9_CAN_MCR_OFFSET); - regval &= ~(CAN_MCR_HALT | CAN_MCR_FRZ); - putreg32(regval, base + IMX9_CAN_MCR_OFFSET); + modifyreg32(base + IMX9_CAN_MCR_OFFSET, CAN_MCR_HALT | CAN_MCR_FRZ, 0); } + + return imx9_waitmcr_change(base, CAN_MCR_FRZACK, freeze); } -static uint32_t imx9_waitmcr_change(uint32_t base, uint32_t mask, - uint32_t target_state) +static bool imx9_waitmcr_change(uint32_t base, uint32_t mask, + bool target_state) { const uint32_t timeout = 1000; uint32_t wait_ack; + bool state; for (wait_ack = 0; wait_ack < timeout; wait_ack++) { - const bool state = (getreg32(base + IMX9_CAN_MCR_OFFSET) & mask) - != 0; + state = (getreg32(base + IMX9_CAN_MCR_OFFSET) & mask) != 0; if (state == target_state) { return true; @@ -1312,17 +1304,12 @@ static uint32_t imx9_waitmcr_change(uint32_t base, uint32_t mask, return false; } -static uint32_t imx9_waitfreezeack_change(uint32_t base, - uint32_t target_state) -{ - return imx9_waitmcr_change(base, CAN_MCR_FRZACK, target_state); -} - static struct mb_s *flexcan_get_mb(struct imx9_driver_s *priv, uint32_t mbi) { - return (struct mb_s *)(priv->base + - (mb_address[priv->mb_address_offset + mbi] << 3)); + return (struct mb_s *) + (priv->base + + ((uintptr_t)mb_address[priv->mb_address_offset + mbi] << 3)); } /**************************************************************************** @@ -1336,7 +1323,7 @@ static struct mb_s *flexcan_get_mb(struct imx9_driver_s *priv, * dev - Reference to the NuttX driver state structure * * Returned Value: - * None + * OK or ERROR * * Assumptions: * @@ -1346,10 +1333,10 @@ static int imx9_ifup(struct net_driver_s *dev) { struct imx9_driver_s *priv = (struct imx9_driver_s *)dev; - if (!imx9_initialize(priv)) + if (imx9_initialize(priv) != OK) { nerr("initialize failed"); - return -1; + return ERROR; } priv->bifup = true; @@ -1539,12 +1526,13 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, arbi_timing.bitrate = req->arbi_bitrate * 1000; arbi_timing.samplep = req->arbi_samplep; - ret = imx9_bitratetotimeseg(&arbi_timing, 10, 0); + ret = imx9_bitratetotimeseg(&arbi_timing, 10, 0, priv->clk_freq); if (ret == OK && priv->canfd_capable) { data_timing.bitrate = req->data_bitrate * 1000; data_timing.samplep = req->data_samplep; - ret = imx9_bitratetotimeseg(&data_timing, 10, 1); + ret = imx9_bitratetotimeseg(&data_timing, 10, 1, + priv->clk_freq); } if (ret == OK) @@ -1571,8 +1559,6 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, } #endif /* CONFIG_NETDEV_IOCTL */ -#ifdef CONFIG_IMX9_FLEXCAN_ECC - /**************************************************************************** * Function: imx9_init_eccram * @@ -1592,42 +1578,28 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, static int imx9_init_eccram(struct imx9_driver_s *priv) { uint32_t i; - uint32_t regval; irqstate_t flags; flags = enter_critical_section(); - regval = getreg32(priv->base + IMX9_CAN_CTRL2_OFFSET); - /* Set WRMFRZ bit in CTRL2 Register to grant write access to memory */ - regval |= CAN_CTRL2_WRMFRZ; - - putreg32(regval, priv->base + IMX9_CAN_CTRL2_OFFSET); + modifyreg32(priv->base + IMX9_CAN_CTRL2_OFFSET, 0, CAN_CTRL2_WRMFRZ); for (i = IMX9_CAN_MB_OFFSET; i < IMX9_CAN_MB_END; i += 4) { putreg32(0, priv->base + i); } - for (i = IMX9_CAN_MB2_OFFSET; i < IMX9_CAN_MB2_END; i += 4) - { - putreg32(0, priv->base + i); - } - - regval = getreg32(priv->base + IMX9_CAN_CTRL2_OFFSET); - /* Clear WRMFRZ bit in CTRL2 Register */ - regval &= ~CAN_CTRL2_WRMFRZ; + modifyreg32(priv->base + IMX9_CAN_CTRL2_OFFSET, CAN_CTRL2_WRMFRZ, 0); leave_critical_section(flags); return 0; } -#endif - /**************************************************************************** * Function: imx9_initalize * @@ -1638,7 +1610,7 @@ static int imx9_init_eccram(struct imx9_driver_s *priv) * priv - Reference to the private FLEXCAN driver state structure * * Returned Value: - * None + * OK or ERROR * * Assumptions: * @@ -1646,90 +1618,84 @@ static int imx9_init_eccram(struct imx9_driver_s *priv) static int imx9_initialize(struct imx9_driver_s *priv) { - uint32_t regval; uint32_t i; - /* initialize CAN device */ + imx9_init_eccram(priv); - imx9_setenable(priv->base, 1); + /* Enable module */ -#ifdef CONFIG_IMX9_FLEXCAN_ECC - imx9_init_eccram(priv); -#endif + if (!imx9_setenable(priv->base, true)) + { + nerr("FLEXCAN: enable fail\n"); + return ERROR; + } + + /* Reset */ imx9_reset(priv); /* Enter freeze mode */ - imx9_setfreeze(priv->base, 1); - if (!imx9_waitfreezeack_change(priv->base, 1)) + if (!imx9_setfreeze(priv->base, true)) { nerr("FLEXCAN: freeze fail\n"); - return -1; + return ERROR; } if (!priv->canfd_capable) { - regval = getreg32(priv->base + IMX9_CAN_CTRL1_OFFSET); - regval &= ~(CAN_CTRL1_PRESDIV_MASK | CAN_CTRL1_PROPSEG_MASK | + modifyreg32(priv->base + IMX9_CAN_CTRL1_OFFSET, + CAN_CTRL1_PRESDIV_MASK | CAN_CTRL1_PROPSEG_MASK | CAN_CTRL1_PSEG1_MASK | CAN_CTRL1_PSEG2_MASK | - CAN_CTRL1_RJW_MASK); - regval |= (CAN_CTRL1_PRESDIV(priv->arbi_timing.presdiv) | /* Prescaler divisor factor */ - CAN_CTRL1_PROPSEG(priv->arbi_timing.propseg) | /* Propagation segment */ - CAN_CTRL1_PSEG1(priv->arbi_timing.pseg1) | /* Phase buffer segment 1 */ - CAN_CTRL1_PSEG2(priv->arbi_timing.pseg2) | /* Phase buffer segment 2 */ - CAN_CTRL1_RJW(1)); /* Resynchronization jump width */ - putreg32(regval, priv->base + IMX9_CAN_CTRL1_OFFSET); + CAN_CTRL1_RJW_MASK, + CAN_CTRL1_PRESDIV(priv->arbi_timing.presdiv) | /* Prescaler divisor factor */ + CAN_CTRL1_PROPSEG(priv->arbi_timing.propseg) | /* Propagation segment */ + CAN_CTRL1_PSEG1(priv->arbi_timing.pseg1) | /* Phase buffer segment 1 */ + CAN_CTRL1_PSEG2(priv->arbi_timing.pseg2) | /* Phase buffer segment 2 */ + CAN_CTRL1_RJW(1)); /* Resynchronization jump width */ } else { - regval = getreg32(priv->base + IMX9_CAN_CBT_OFFSET); - regval &= ~(CAN_CBT_EPRESDIV_MASK | CAN_CBT_EPROPSEG_MASK | + modifyreg32(priv->base + IMX9_CAN_CBT_OFFSET, + CAN_CBT_EPRESDIV_MASK | CAN_CBT_EPROPSEG_MASK | CAN_CBT_EPSEG1_MASK | CAN_CBT_EPSEG2_MASK | - CAN_CBT_ERJW_MASK); - regval |= (CAN_CBT_BTF | /* Enable extended bit timing - * configurations for CAN-FD for setting up - * separately nominal and data phase */ - CAN_CBT_EPRESDIV(priv->arbi_timing.presdiv) | /* Prescaler divisor factor */ - CAN_CBT_EPROPSEG(priv->arbi_timing.propseg) | /* Propagation segment */ - CAN_CBT_EPSEG1(priv->arbi_timing.pseg1) | /* Phase buffer segment 1 */ - CAN_CBT_EPSEG2(priv->arbi_timing.pseg2) | /* Phase buffer segment 2 */ - CAN_CBT_ERJW(1)); /* Resynchronization jump width */ - putreg32(regval, priv->base + IMX9_CAN_CBT_OFFSET); + CAN_CBT_ERJW_MASK, + CAN_CBT_BTF | /* Enable extended bit timing + * configurations for CAN-FD for setting up + * separately nominal and data phase */ + CAN_CBT_EPRESDIV(priv->arbi_timing.presdiv) | /* Prescaler divisor factor */ + CAN_CBT_EPROPSEG(priv->arbi_timing.propseg) | /* Propagation segment */ + CAN_CBT_EPSEG1(priv->arbi_timing.pseg1) | /* Phase buffer segment 1 */ + CAN_CBT_EPSEG2(priv->arbi_timing.pseg2) | /* Phase buffer segment 2 */ + CAN_CBT_ERJW(1)); /* Resynchronization jump width */ /* Enable CAN FD feature */ - regval = getreg32(priv->base + IMX9_CAN_MCR_OFFSET); - regval |= CAN_MCR_FDEN; - putreg32(regval, priv->base + IMX9_CAN_MCR_OFFSET); + modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, 0, CAN_MCR_FDEN); - regval = getreg32(priv->base + IMX9_CAN_FDCBT_OFFSET); - regval &= ~(CAN_FDCBT_FPRESDIV_MASK | CAN_FDCBT_FPROPSEG_MASK | + modifyreg32(priv->base + IMX9_CAN_FDCBT_OFFSET, + CAN_FDCBT_FPRESDIV_MASK | CAN_FDCBT_FPROPSEG_MASK | CAN_FDCBT_FPSEG1_MASK | CAN_FDCBT_FPSEG2_MASK | - CAN_FDCBT_FRJW_MASK); - regval |= (CAN_FDCBT_FPRESDIV(priv->data_timing.presdiv) | /* Prescaler divisor factor of 1 */ - CAN_FDCBT_FPROPSEG(priv->data_timing.propseg) | /* Propagation - * segment (only register that doesn't add 1) */ - CAN_FDCBT_FPSEG1(priv->data_timing.pseg1) | /* Phase buffer segment 1 */ - CAN_FDCBT_FPSEG2(priv->data_timing.pseg2) | /* Phase buffer segment 2 */ - CAN_FDCBT_FRJW(priv->data_timing.pseg2)); /* Resynchorinzation jump width same as PSEG2 */ - putreg32(regval, priv->base + IMX9_CAN_FDCBT_OFFSET); + CAN_FDCBT_FRJW_MASK, + CAN_FDCBT_FPRESDIV(priv->data_timing.presdiv) | /* Prescaler divisor factor of 1 */ + CAN_FDCBT_FPROPSEG(priv->data_timing.propseg) | /* Propagation + * segment (only register that doesn't add 1) */ + CAN_FDCBT_FPSEG1(priv->data_timing.pseg1) | /* Phase buffer segment 1 */ + CAN_FDCBT_FPSEG2(priv->data_timing.pseg2) | /* Phase buffer segment 2 */ + CAN_FDCBT_FRJW(priv->data_timing.pseg2)); /* Resynchorinzation jump width same as PSEG2 */ /* Additional CAN-FD configurations */ - regval = getreg32(priv->base + IMX9_CAN_FDCTRL_OFFSET); - - regval |= (CAN_FDCTRL_FDRATE | /* Enable bit rate switch in data phase of frame */ - CAN_FDCTRL_TDCEN | /* Enable transceiver delay compensation */ - CAN_FDCTRL_TDCOFF(5) | /* Setup 5 cycles for data phase sampling delay */ - CAN_FDCTRL_MSBSR0(3) | /* Setup 64 bytes per MB 0-6 */ - CAN_FDCTRL_MSBSR1(3) | /* Setup 64 bytes per MB 7-13 */ - CAN_FDCTRL_MSBSR2(3)); /* Setup 64 bytes per MB 14-20 */ - putreg32(regval, priv->base + IMX9_CAN_FDCTRL_OFFSET); + modifyreg32(priv->base + IMX9_CAN_FDCTRL_OFFSET, 0, + CAN_FDCTRL_FDRATE | /* Enable bit rate switch in data phase of frame */ + CAN_FDCTRL_TDCEN | /* Enable transceiver delay compensation */ + CAN_FDCTRL_TDCOFF(5) | /* Setup 5 cycles for data phase sampling delay */ + CAN_FDCTRL_MSBSR0(3) | /* Setup 64 bytes per MB 0-6 */ + CAN_FDCTRL_MSBSR1(3) | /* Setup 64 bytes per MB 7-13 */ + CAN_FDCTRL_MSBSR2(3)); /* Setup 64 bytes per MB 14-20 */ - regval = getreg32(priv->base + IMX9_CAN_CTRL2_OFFSET); - regval |= CAN_CTRL2_ISOCANFDEN; - putreg32(regval, priv->base + IMX9_CAN_CTRL2_OFFSET); + modifyreg32(priv->base + IMX9_CAN_CTRL2_OFFSET, 0, + CAN_CTRL2_ISOCANFDEN); } struct mb_s *buffer = flexcan_get_mb(priv, RXMBCOUNT); @@ -1760,14 +1726,13 @@ static int imx9_initialize(struct imx9_driver_s *priv) /* Exit freeze mode */ - imx9_setfreeze(priv->base, 0); - if (!imx9_waitfreezeack_change(priv->base, 0)) + if (!imx9_setfreeze(priv->base, false)) { nerr("FLEXCAN: unfreeze fail\n"); - return -1; + return ERROR; } - return 1; + return OK; } /**************************************************************************** @@ -1791,19 +1756,15 @@ static void imx9_reset(struct imx9_driver_s *priv) uint32_t regval; uint32_t i; - regval = getreg32(priv->base + IMX9_CAN_MCR_OFFSET); - regval |= CAN_MCR_SOFTRST; - putreg32(regval, priv->base + IMX9_CAN_MCR_OFFSET); + modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, 0, CAN_MCR_SOFTRST); - if (!imx9_waitmcr_change(priv->base, CAN_MCR_SOFTRST, 0)) + if (!imx9_waitmcr_change(priv->base, CAN_MCR_SOFTRST, false)) { nerr("Reset failed"); return; } - regval = getreg32(priv->base + IMX9_CAN_MCR_OFFSET); - regval &= ~(CAN_MCR_SUPV); - putreg32(regval, priv->base + IMX9_CAN_MCR_OFFSET); + modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, CAN_MCR_SUPV, 0); /* Initialize all MB rx and tx */ @@ -1818,12 +1779,11 @@ static void imx9_reset(struct imx9_driver_s *priv) rx->data[1].w00 = 0x0; } - regval = getreg32(priv->base + IMX9_CAN_MCR_OFFSET); - regval |= (CAN_MCR_SLFWAK | CAN_MCR_WRNEN | CAN_MCR_SRXDIS | - CAN_MCR_IRMQ | CAN_MCR_AEN | - (((TOTALMBCOUNT - 1) << CAN_MCR_MAXMB_SHIFT) & - CAN_MCR_MAXMB_MASK)); - putreg32(regval, priv->base + IMX9_CAN_MCR_OFFSET); + modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, 0, + CAN_MCR_SLFWAK | CAN_MCR_WRNEN | CAN_MCR_SRXDIS | + CAN_MCR_IRMQ | CAN_MCR_AEN | + (((TOTALMBCOUNT - 1) << CAN_MCR_MAXMB_SHIFT) & + CAN_MCR_MAXMB_MASK)); regval = CAN_CTRL2_RRS | CAN_CTRL2_EACEN; putreg32(regval, priv->base + IMX9_CAN_CTRL2_OFFSET); @@ -1846,7 +1806,7 @@ static void imx9_reset(struct imx9_driver_s *priv) * * Description: * Mux the pins used for CAN RX&TX - * + *ยง * Input Parameters: * None * @@ -1896,15 +1856,15 @@ int imx9_caninitialize(int intf) struct imx9_driver_s *priv; int ret; - /* Select device, configure root clock to 24MHz OSC and enable peripheral - * clock + /* Select device, configure root clock to PLL1PFD1DIV2 / 5 and enable + * peripheral clock */ switch (intf) { #ifdef CONFIG_IMX9_FLEXCAN1 case 1: - imx9_ccm_configure_root_clock(CCM_CR_CAN1, OSC_24M, 1); + imx9_ccm_configure_root_clock(CCM_CR_CAN1, SYS_PLL1PFD1DIV2, 5); imx9_ccm_gate_on(CCM_LPCG_CAN1, true); priv = &g_flexcan1; break; @@ -1912,7 +1872,7 @@ int imx9_caninitialize(int intf) #ifdef CONFIG_IMX9_FLEXCAN2 case 2: - imx9_ccm_configure_root_clock(CCM_CR_CAN2, OSC_24M, 1); + imx9_ccm_configure_root_clock(CCM_CR_CAN2, SYS_PLL1PFD1DIV2, 5); imx9_ccm_gate_on(CCM_LPCG_CAN2, true); priv = &g_flexcan2; break; @@ -1922,7 +1882,11 @@ int imx9_caninitialize(int intf) return -ENODEV; } - if (imx9_bitratetotimeseg(&priv->arbi_timing, 1, 0) != OK) + /* Get and store the clock (should be 80 MHz now) */ + + imx9_get_rootclock(CCM_CR_CAN1, &priv->clk_freq); + + if (imx9_bitratetotimeseg(&priv->arbi_timing, 1, 0, priv->clk_freq) != OK) { nerr("ERROR: Invalid CAN timings please try another sample point " "or refer to the reference manual\n"); @@ -1931,7 +1895,8 @@ int imx9_caninitialize(int intf) if (priv->canfd_capable) { - if (imx9_bitratetotimeseg(&priv->data_timing, 1, 1) != OK) + if (imx9_bitratetotimeseg(&priv->data_timing, 1, 1, + priv->clk_freq) != OK) { nerr("ERROR: Invalid CAN data phase timings please try another " "sample point or refer to the reference manual\n");