diff options
Diffstat (limited to '')
-rw-r--r-- | drivers/net/can/flexcan.c | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index e86925134009..fbdd9a8c9374 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -214,6 +214,7 @@ * MX53 FlexCAN2 03.00.00.00 yes no no no no no * MX6s FlexCAN3 10.00.12.00 yes yes no no yes no * MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes + * MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes * VF610 FlexCAN3 ? no yes no yes yes? no * LS1021A FlexCAN2 03.00.04.00 no yes no no yes no * LX2160A FlexCAN3 03.00.23.00 no yes no no yes yes @@ -239,6 +240,8 @@ #define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8) /* Support CAN-FD mode */ #define FLEXCAN_QUIRK_SUPPORT_FD BIT(9) +/* support memory detection and correction */ +#define FLEXCAN_QUIRK_SUPPORT_ECC BIT(10) /* Structure of the message buffer */ struct flexcan_mb { @@ -292,7 +295,16 @@ struct flexcan_regs { u32 rximr[64]; /* 0x880 - Not affected by Soft Reset */ u32 _reserved5[24]; /* 0x980 */ u32 gfwr_mx6; /* 0x9e0 - MX6 */ - u32 _reserved6[63]; /* 0x9e4 */ + u32 _reserved6[39]; /* 0x9e4 */ + u32 _rxfir[6]; /* 0xa80 */ + u32 _reserved8[2]; /* 0xa98 */ + u32 _rxmgmask; /* 0xaa0 */ + u32 _rxfgmask; /* 0xaa4 */ + u32 _rx14mask; /* 0xaa8 */ + u32 _rx15mask; /* 0xaac */ + u32 tx_smb[4]; /* 0xab0 */ + u32 rx_smb0[4]; /* 0xac0 */ + u32 rx_smb1[4]; /* 0xad0 */ u32 mecr; /* 0xae0 */ u32 erriar; /* 0xae4 */ u32 erridpr; /* 0xae8 */ @@ -305,9 +317,13 @@ struct flexcan_regs { u32 fdctrl; /* 0xc00 - Not affected by Soft Reset */ u32 fdcbt; /* 0xc04 - Not affected by Soft Reset */ u32 fdcrc; /* 0xc08 */ + u32 _reserved9[199]; /* 0xc0c */ + u32 tx_smb_fd[18]; /* 0xf28 */ + u32 rx_smb0_fd[18]; /* 0xf70 */ + u32 rx_smb1_fd[18]; /* 0xfb8 */ }; -static_assert(sizeof(struct flexcan_regs) == 0x4 + 0xc08); +static_assert(sizeof(struct flexcan_regs) == 0x4 * 18 + 0xfb8); struct flexcan_devtype_data { u32 quirks; /* quirks needed for different IP cores */ @@ -376,6 +392,13 @@ static const struct flexcan_devtype_data fsl_imx8qm_devtype_data = { FLEXCAN_QUIRK_SUPPORT_FD, }; +static struct flexcan_devtype_data fsl_imx8mp_devtype_data = { + .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | + FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | + FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SETUP_STOP_MODE | + FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC, +}; + static const struct flexcan_devtype_data fsl_vf610_devtype_data = { .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | @@ -1292,6 +1315,37 @@ static void flexcan_set_bittiming(struct net_device *dev) return flexcan_set_bittiming_ctrl(dev); } +static void flexcan_ram_init(struct net_device *dev) +{ + struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->regs; + u32 reg_ctrl2; + + /* 11.8.3.13 Detection and correction of memory errors: + * CTRL2[WRMFRZ] grants write access to all memory positions + * that require initialization, ranging from 0x080 to 0xADF + * and from 0xF28 to 0xFFF when the CAN FD feature is enabled. + * The RXMGMASK, RX14MASK, RX15MASK, and RXFGMASK registers + * need to be initialized as well. MCR[RFEN] must not be set + * during memory initialization. + */ + reg_ctrl2 = priv->read(®s->ctrl2); + reg_ctrl2 |= FLEXCAN_CTRL2_WRMFRZ; + priv->write(reg_ctrl2, ®s->ctrl2); + + memset_io(®s->mb[0][0], 0, + offsetof(struct flexcan_regs, rx_smb1[3]) - + offsetof(struct flexcan_regs, mb[0][0]) + 0x4); + + if (priv->can.ctrlmode & CAN_CTRLMODE_FD) + memset_io(®s->tx_smb_fd[0], 0, + offsetof(struct flexcan_regs, rx_smb1_fd[17]) - + offsetof(struct flexcan_regs, tx_smb_fd[0]) + 0x4); + + reg_ctrl2 &= ~FLEXCAN_CTRL2_WRMFRZ; + priv->write(reg_ctrl2, ®s->ctrl2); +} + /* flexcan_chip_start * * this functions is entered with clocks enabled @@ -1316,6 +1370,9 @@ static int flexcan_chip_start(struct net_device *dev) if (err) goto out_chip_disable; + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_ECC) + flexcan_ram_init(dev); + flexcan_set_bittiming(dev); /* MCR @@ -1845,6 +1902,7 @@ out_put_node: static const struct of_device_id flexcan_of_match[] = { { .compatible = "fsl,imx8qm-flexcan", .data = &fsl_imx8qm_devtype_data, }, + { .compatible = "fsl,imx8mp-flexcan", .data = &fsl_imx8mp_devtype_data, }, { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, }, { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, }, { .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, }, @@ -1999,6 +2057,8 @@ static int flexcan_probe(struct platform_device *pdev) return 0; failed_register: + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(&pdev->dev); free_candev(dev); return err; } |