mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
can: c_can: D_CAN: c_can_chip_config(): perform a sofware reset on open
[ Upstream commit 23c5a9488f ]
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.pdf
Signed-off-by: Jeroen Hofstee <jhofstee@victronenergy.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
@@ -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)
|
||||
@@ -572,6 +573,26 @@ static void c_can_configure_msg_objects(struct net_device *dev)
|
||||
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:
|
||||
* - enable/disable auto-retransmission
|
||||
@@ -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)
|
||||
{
|
||||
struct c_can_priv *priv = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
err = c_can_software_reset(dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* enable automatic retransmission */
|
||||
priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR);
|
||||
|
||||
Reference in New Issue
Block a user