diff --git a/arch/arm64/src/imx9/imx9_flexcan.c b/arch/arm64/src/imx9/imx9_flexcan.c index 120b52dbafbf9..683822c5b9f6b 100644 --- a/arch/arm64/src/imx9/imx9_flexcan.c +++ b/arch/arm64/src/imx9/imx9_flexcan.c @@ -65,11 +65,11 @@ #define CANRCVWORK HPWORK #define RXMBCOUNT CONFIG_IMX9_FLEXCAN_RXMB -#define TXMBCOUNT (CONFIG_IMX9_FLEXCAN_TXMB + 1) -#define TOTALMBCOUNT RXMBCOUNT + TXMBCOUNT +#define TXMBCOUNT CONFIG_IMX9_FLEXCAN_TXMB +#define TOTALMBCOUNT (RXMBCOUNT + TXMBCOUNT) #define IFLAG1_RX ((1 << RXMBCOUNT)-1) -#define IFLAG1_TX (((1 << TXMBCOUNT)-2) << RXMBCOUNT) +#define IFLAG1_TX (((1 << TXMBCOUNT)-1) << RXMBCOUNT) #define CAN_FIFO_NE (1 << 5) #define CAN_FIFO_OV (1 << 6) @@ -160,8 +160,8 @@ 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; + uint32_t clk_freq; /* Peripheral clock frequency */ bool bifup; /* true:ifup false:ifdown */ #ifdef TX_TIMEOUT_WQ struct wdog_s txtimeout[TXMBCOUNT]; /* TX timeout timer */ @@ -479,7 +479,7 @@ static void imx9_reset(struct imx9_driver_s *priv); static bool imx9_txringfull(struct imx9_driver_s *priv) { - uint32_t mbi = RXMBCOUNT + 1; + uint32_t mbi = RXMBCOUNT; struct mb_s *mb; while (mbi < TOTALMBCOUNT) @@ -536,6 +536,8 @@ static int imx9_transmit(struct imx9_driver_s *priv) struct mb_s *mb = flexcan_get_mb(priv, mbi); _alert("mbi %d cs %x\n", mbi, CAN_MB_CS_CODE(mb->cs)); + _alert("MCR: %x\n", getreg32(priv->base + IMX9_CAN_MCR_OFFSET)); + _alert("ESR1: %x\n", getreg32(priv->base + IMX9_CAN_ESR1_OFFSET)); if (CAN_MB_CS_CODE(mb->cs) != CAN_TXMB_DATAORREMOTE) { break; @@ -641,7 +643,7 @@ static int imx9_transmit(struct imx9_driver_s *priv) } cs |= (frame->can_id & CAN_RTR_FLAG) ? CAN_MB_CS_RTR : 0; - cs |= ((g_len_to_can_dlc[frame->len] << CAN_MB_CS_DLC_SHIFT) & + cs |= ((((uint32_t)g_len_to_can_dlc[frame->len]) << CAN_MB_CS_DLC_SHIFT) & CAN_MB_CS_DLC_MASK); frame_data_word = (uint32_t *)&frame->data[0]; @@ -649,9 +651,13 @@ static int imx9_transmit(struct imx9_driver_s *priv) { mb->data[i] = __builtin_bswap32(frame_data_word[i]); } + + + _alert("payload sz %d\n", frame->len); + _alert("GO: %x\n", (cs | (CAN_TXMB_DATAORREMOTE << CAN_MB_CS_CODE_SHIFT))); } #endif - + mb->cs = (cs | (CAN_TXMB_DATAORREMOTE << CAN_MB_CS_CODE_SHIFT)); /* Go */ /* Enable interrupt */ @@ -939,7 +945,7 @@ static void imx9_txdone(struct imx9_driver_s *priv) /* Process TX completions */ - mbi = RXMBCOUNT + 1; + mbi = RXMBCOUNT; mb_bit = 1 << mbi; #ifdef TX_TIMEOUT_WQ txmb = 0; @@ -1066,29 +1072,21 @@ static int imx9_flexcan_interrupt(int irq, void *context, void *arg) { struct imx9_driver_s *priv = (struct imx9_driver_s *)arg; - + _alert("IRQ\n"); if (irq == priv->irq) { uint32_t flags; flags = getreg32(priv->base + IMX9_CAN_IFLAG1_OFFSET); - flags &= IFLAG1_RX; - if (flags) + if (flags & IFLAG1_RX) { modifyreg32(priv->base + IMX9_CAN_IMASK1_OFFSET, IFLAG1_RX, 0); work_queue(CANRCVWORK, &priv->rcvwork, imx9_flexcan_interrupt_work, priv, 0); } - flags = getreg32(priv->base + IMX9_CAN_IFLAG1_OFFSET); - flags &= IFLAG1_TX; - - if (flags) + if (flags & IFLAG1_TX) { - /* Disable further TX MB CAN interrupts. here can be no race - * condition here. - */ - modifyreg32(priv->base + IMX9_CAN_IMASK1_OFFSET, IFLAG1_TX, 0); work_queue(CANWORK, &priv->irqwork, imx9_txdone_work, priv, 0); } @@ -1516,7 +1514,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, #endif /* CONFIG_NETDEV_IOCTL */ /**************************************************************************** - * Function: imx9_init_eccram + * Function: imx9_init_mbram * * Description: * Initialize FLEXCAN ECC RAM @@ -1531,7 +1529,7 @@ static int imx9_ioctl(struct net_driver_s *dev, int cmd, * ****************************************************************************/ -static int imx9_init_eccram(struct imx9_driver_s *priv) +static int imx9_init_mbram(struct imx9_driver_s *priv) { volatile uint32_t *data = (uint32_t *)(priv->base + IMX9_CAN_MB_OFFSET); const uint32_t *data_end = (uint32_t *)(priv->base + IMX9_CAN_MB_END); @@ -1603,8 +1601,6 @@ static int imx9_initialize(struct imx9_driver_s *priv) { uint32_t i; - imx9_init_eccram(priv); - /* Enable module */ if (!imx9_setenable(priv->base, true)) @@ -1625,6 +1621,21 @@ static int imx9_initialize(struct imx9_driver_s *priv) return ERROR; } + /* Initialize memory buffers */ + + imx9_init_mbram(priv); + + /* Configure MCR */ + + modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, CAN_MCR_MAXMB_MASK, + CAN_MCR_SLFWAK | CAN_MCR_WRNEN | CAN_MCR_SRXDIS | + CAN_MCR_IRMQ | CAN_MCR_AEN | + ((TOTALMBCOUNT << CAN_MCR_MAXMB_SHIFT) & CAN_MCR_MAXMB_MASK)); + + /* Exit supervisor mode */ + + modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, CAN_MCR_SUPV, 0); + if (!priv->canfd_capable) { modifyreg32(priv->base + IMX9_CAN_CTRL1_OFFSET, @@ -1681,6 +1692,12 @@ static int imx9_initialize(struct imx9_driver_s *priv) CAN_CTRL2_ISOCANFDEN); } + + /* Filtering catchall */ + + putreg32(0x3fffffff, priv->base + IMX9_CAN_RX14MASK_OFFSET); + putreg32(0x3fffffff, priv->base + IMX9_CAN_RX15MASK_OFFSET); + putreg32(0x3fffffff, priv->base + IMX9_CAN_RXMGMASK_OFFSET); putreg32(0x0, priv->base + IMX9_CAN_RXFGMASK_OFFSET); for (i = 0; i < TOTALMBCOUNT; i++) @@ -1692,7 +1709,7 @@ static int imx9_initialize(struct imx9_driver_s *priv) { struct mb_s *rx = flexcan_get_mb(priv, i); ninfo("Set MB%" PRIi32 " to receive %p\n", i, rx); - rx->cs = CAN_RXMB_EMPTY << CAN_MB_CS_CODE_SHIFT; + rx->cs = (CAN_RXMB_EMPTY << CAN_MB_CS_CODE_SHIFT) | CAN_MB_CS_IDE; } putreg32(IFLAG1_RX, priv->base + IMX9_CAN_IFLAG1_OFFSET); @@ -1727,9 +1744,6 @@ static int imx9_initialize(struct imx9_driver_s *priv) static void imx9_reset(struct imx9_driver_s *priv) { - uint32_t regval; - uint32_t i; - modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, 0, CAN_MCR_SOFTRST); if (!imx9_waitmcr_change(priv->base, CAN_MCR_SOFTRST, false)) @@ -1737,31 +1751,6 @@ static void imx9_reset(struct imx9_driver_s *priv) nerr("Reset failed"); return; } - - modifyreg32(priv->base + IMX9_CAN_MCR_OFFSET, CAN_MCR_SUPV, 0); - - imx9_init_eccram(priv); - - 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); - - for (i = 0; i < TOTALMBCOUNT; i++) - { - putreg32(0, priv->base + IMX9_CAN_RXIMR_OFFSET(i)); - } - - /* Filtering catchall */ - - putreg32(0x3fffffff, priv->base + IMX9_CAN_RX14MASK_OFFSET); - putreg32(0x3fffffff, priv->base + IMX9_CAN_RX15MASK_OFFSET); - putreg32(0x3fffffff, priv->base + IMX9_CAN_RXMGMASK_OFFSET); - putreg32(0x0, priv->base + IMX9_CAN_RXFGMASK_OFFSET); } /**************************************************************************** @@ -1879,6 +1868,15 @@ int imx9_caninitialize(int intf) return -EAGAIN; } + if (irq_attach(priv->irq + 1, imx9_flexcan_interrupt, priv)) + { + /* We could not attach the ISR to the interrupt */ + + nerr("ERROR: Failed to attach CAN bus error IRQ\n"); + irq_detach(priv->irq); + return -EAGAIN; + } + /* Initialize the driver structure */ priv->dev.d_ifup = imx9_ifup; /* I/F up (new IP address) callback */