]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
can: m_can: set init flag earlier in probe
authorMatthias Schiffer <matthias.schiffer@ew.tq-group.com>
Mon, 7 Oct 2024 08:23:58 +0000 (10:23 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Wed, 18 Dec 2024 08:30:52 +0000 (09:30 +0100)
While an m_can controller usually already has the init flag from a
hardware reset, no such reset happens on the integrated m_can_pci of the
Intel Elkhart Lake. If the CAN controller is found in an active state,
m_can_dev_setup() would fail because m_can_niso_supported() calls
m_can_cccr_update_bits(), which refuses to modify any other configuration
bits when CCCR_INIT is not set.

To avoid this issue, set CCCR_INIT before attempting to modify any other
configuration flags.

Fixes: cd5a46ce6fa6 ("can: m_can: don't enable transceiver when probing")
Signed-off-by: Matthias Schiffer <matthias.schiffer@ew.tq-group.com>
Reviewed-by: Markus Schneider-Pargmann <msp@baylibre.com>
Link: https://patch.msgid.link/e247f331cb72829fcbdfda74f31a59cbad1a6006.1728288535.git.matthias.schiffer@ew.tq-group.com
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/m_can/m_can.c

index 533bcb77c9f934e5840b076ded948f8256ad2ad0..67c404fbe16672b2765840b362d120fb81337ff4 100644 (file)
@@ -1695,6 +1695,14 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
                return -EINVAL;
        }
 
+       /* Write the INIT bit, in case no hardware reset has happened before
+        * the probe (for example, it was observed that the Intel Elkhart Lake
+        * SoCs do not properly reset the CAN controllers on reboot)
+        */
+       err = m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
+       if (err)
+               return err;
+
        if (!cdev->is_peripheral)
                netif_napi_add(dev, &cdev->napi, m_can_poll);
 
@@ -1746,11 +1754,7 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
                return -EINVAL;
        }
 
-       /* Forcing standby mode should be redundant, as the chip should be in
-        * standby after a reset. Write the INIT bit anyways, should the chip
-        * be configured by previous stage.
-        */
-       return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
+       return 0;
 }
 
 static void m_can_stop(struct net_device *dev)