#define FLEXCAN_MB_CODE_MASK           (0xf0ffffff)
 
+/* FLEXCAN hardware feature flags */
+#define FLEXCAN_HAS_V10_FEATURES       BIT(1) /* For core version >= 10 */
+#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* Broken error state handling */
+
 /* Structure of the message buffer */
 struct flexcan_mb {
        u32 can_ctrl;
 };
 
 struct flexcan_devtype_data {
-       u32 hw_ver;     /* hardware controller version */
+       u32 features;   /* hardware controller features */
 };
 
 struct flexcan_priv {
 };
 
 static struct flexcan_devtype_data fsl_p1010_devtype_data = {
-       .hw_ver = 3,
+       .features = FLEXCAN_HAS_BROKEN_ERR_STATE,
 };
-
+static struct flexcan_devtype_data fsl_imx28_devtype_data;
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-       .hw_ver = 10,
+       .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
         * enable tx and rx warning interrupt
         * enable bus off interrupt
         * (== FLEXCAN_CTRL_ERR_STATE)
-        *
-        * _note_: we enable the "error interrupt"
-        * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any
-        * warning or bus passive interrupts.
         */
        reg_ctrl = flexcan_read(®s->ctrl);
        reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
        reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
-               FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK;
+               FLEXCAN_CTRL_ERR_STATE;
+       /*
+        * enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
+        * on most Flexcan cores, too. Otherwise we don't get
+        * any error warning or passive interrupts.
+        */
+       if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE ||
+           priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
+               reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
 
        /* save for later use */
        priv->reg_ctrl_default = reg_ctrl;
        flexcan_write(0x0, ®s->rx14mask);
        flexcan_write(0x0, ®s->rx15mask);
 
-       if (priv->devtype_data->hw_ver >= 10)
+       if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES)
                flexcan_write(0x0, ®s->rxfgmask);
 
        flexcan_transceiver_switch(priv, 1);
 
 static const struct of_device_id flexcan_of_match[] = {
        { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
+       { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
        { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
        { /* sentinel */ },
 };