From: Uwe Kleine-König <u.kleine-koe...@pengutronix.de>

In commit 88462d2a7830 ("can: flexcan: Remodel FlexCAN register r/w APIs
for big endian FlexCAN controllers.") the following logic was
implemented:

        if the dt property "big-endian" is given or
           the device is compatible to "fsl,p1010-flexcan":
                use big-endian mode;
        else
                use little-endian mode;

This relies on commit d50f4630c2e1 ("arm: dts: Remove p1010-flexcan
compatible from imx series dts") which was applied a few commits later.
Without this commit (or an old device tree used for booting a new
kernel) the flexcan devices on i.MX25, i.MX28, i.MX35 and i.MX53 match
the 'the device is compatible to "fsl,p1010-flexcan"' test and so are
switched erroneously to big endian mode.

Instead of the check above put a quirk in devtype data and rely on
of_match_device yielding the most compatible match

Fixes: 88462d2a7830 ("can: flexcan: Remodel FlexCAN register r/w APIs for big 
endian FlexCAN controllers.")
Signed-off-by: Uwe Kleine-König <u.kleine-koe...@pengutronix.de>
Tested-by: Gavin Schenk <g.sch...@eckelmann.de>
Cc: linux-stable <sta...@vger.kernel.org> # >= v4.16
Signed-off-by: Marc Kleine-Budde <m...@pengutronix.de>
---
 drivers/net/can/flexcan.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 634c51e6b8ae..d53a45bf2a72 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -200,6 +200,7 @@
 #define FLEXCAN_QUIRK_DISABLE_MECR     BIT(4) /* Disable Memory error 
detection */
 #define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP        BIT(5) /* Use timestamp based 
offloading */
 #define FLEXCAN_QUIRK_BROKEN_PERR_STATE        BIT(6) /* No interrupt for 
error passive */
+#define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN       BIT(7) /* default to BE 
register access */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -287,6 +288,12 @@ struct flexcan_priv {
 };
 
 static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
+       .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
+               FLEXCAN_QUIRK_BROKEN_PERR_STATE |
+               FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN,
+};
+
+static const struct flexcan_devtype_data fsl_imx25_devtype_data = {
        .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
                FLEXCAN_QUIRK_BROKEN_PERR_STATE,
 };
@@ -1251,9 +1258,9 @@ static void unregister_flexcandev(struct net_device *dev)
 static const struct of_device_id flexcan_of_match[] = {
        { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
        { .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
-       { .compatible = "fsl,imx53-flexcan", .data = &fsl_p1010_devtype_data, },
-       { .compatible = "fsl,imx35-flexcan", .data = &fsl_p1010_devtype_data, },
-       { .compatible = "fsl,imx25-flexcan", .data = &fsl_p1010_devtype_data, },
+       { .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
+       { .compatible = "fsl,imx35-flexcan", .data = &fsl_imx25_devtype_data, },
+       { .compatible = "fsl,imx25-flexcan", .data = &fsl_imx25_devtype_data, },
        { .compatible = "fsl,p1010-flexcan", .data = &fsl_p1010_devtype_data, },
        { .compatible = "fsl,vf610-flexcan", .data = &fsl_vf610_devtype_data, },
        { .compatible = "fsl,ls1021ar2-flexcan", .data = 
&fsl_ls1021a_r2_devtype_data, },
@@ -1337,18 +1344,13 @@ static int flexcan_probe(struct platform_device *pdev)
 
        priv = netdev_priv(dev);
 
-       if (of_property_read_bool(pdev->dev.of_node, "big-endian")) {
+       if (of_property_read_bool(pdev->dev.of_node, "big-endian") ||
+           devtype_data->quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN) {
                priv->read = flexcan_read_be;
                priv->write = flexcan_write_be;
        } else {
-               if (of_device_is_compatible(pdev->dev.of_node,
-                                           "fsl,p1010-flexcan")) {
-                       priv->read = flexcan_read_be;
-                       priv->write = flexcan_write_be;
-               } else {
-                       priv->read = flexcan_read_le;
-                       priv->write = flexcan_write_le;
-               }
+               priv->read = flexcan_read_le;
+               priv->write = flexcan_write_le;
        }
 
        priv->can.clock.freq = clock_freq;
-- 
2.17.0

Reply via email to