Commit 66e21b7b authored by Jeroen Hofstee's avatar Jeroen Hofstee Committed by Greg Kroah-Hartman

can: c_can: D_CAN: c_can_chip_config(): perform a sofware reset on open

[ Upstream commit 23c5a948 ]

When the CAN interface is closed it the hardwre is put in power down
mode, but does not reset the error counters / state. 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.pdfSigned-off-by: default avatarJeroen Hofstee <jhofstee@victronenergy.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 7559e68c
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#define CONTROL_EX_PDR BIT(8) #define CONTROL_EX_PDR BIT(8)
/* control register */ /* control register */
#define CONTROL_SWR BIT(15)
#define CONTROL_TEST BIT(7) #define CONTROL_TEST BIT(7)
#define CONTROL_CCE BIT(6) #define CONTROL_CCE BIT(6)
#define CONTROL_DISABLE_AR BIT(5) #define CONTROL_DISABLE_AR BIT(5)
...@@ -572,6 +573,26 @@ static void c_can_configure_msg_objects(struct net_device *dev) ...@@ -572,6 +573,26 @@ static void c_can_configure_msg_objects(struct net_device *dev)
IF_MCONT_RCV_EOB); IF_MCONT_RCV_EOB);
} }
static int c_can_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: * Configure C_CAN chip:
* - enable/disable auto-retransmission * - enable/disable auto-retransmission
...@@ -581,6 +602,11 @@ static void c_can_configure_msg_objects(struct net_device *dev) ...@@ -581,6 +602,11 @@ static void c_can_configure_msg_objects(struct net_device *dev)
static int c_can_chip_config(struct net_device *dev) static int c_can_chip_config(struct net_device *dev)
{ {
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
int err;
err = c_can_software_reset(dev);
if (err)
return err;
/* enable automatic retransmission */ /* enable automatic retransmission */
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment