When the C_CAN interface is closed it is put in power down mode, but
does not reset the error counters / state. So reset the D_CAN on open,
so the reported state and the actual state match.

According to [1], the C_CAN module doesn't have the software reset.

[1] 
http://www.bosch-semiconductors.com/media/ip_modules/pdf_2/c_can_fd8/users_manual_c_can_fd8_r210_1.pdf

Signed-off-by: Jeroen Hofstee <jhofs...@victronenergy.com>
---
 drivers/net/can/c_can/c_can.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 606b7d8ffe13..502a181d02e7 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -52,6 +52,7 @@
 #define CONTROL_EX_PDR         BIT(8)
 
 /* control register */
+#define CONTROL_SWR            BIT(15)
 #define CONTROL_TEST           BIT(7)
 #define CONTROL_CCE            BIT(6)
 #define CONTROL_DISABLE_AR     BIT(5)
@@ -569,6 +570,26 @@ static void c_can_configure_msg_objects(struct net_device 
*dev)
                                   IF_MCONT_RCV_EOB);
 }
 
+static int software_reset(struct net_device *dev)
+{
+       struct c_can_priv *priv = netdev_priv(dev);
+       int retry = 0;
+
+       if (priv->type != BOSCH_D_CAN)
+               return 0;
+
+       priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_SWR | CONTROL_INIT);
+       while (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_SWR) {
+               msleep(20);
+               if (retry++ > 100) {
+                       netdev_err(dev, "CCTRL: software reset failed\n");
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * Configure C_CAN chip:
  * - enable/disable auto-retransmission
@@ -578,6 +599,11 @@ static void c_can_configure_msg_objects(struct net_device 
*dev)
 static int c_can_chip_config(struct net_device *dev)
 {
        struct c_can_priv *priv = netdev_priv(dev);
+       int err;
+
+       err = software_reset(dev);
+       if (err)
+               return err;
 
        /* enable automatic retransmission */
        priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
-- 
2.17.1

Reply via email to