mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
can: sja1000: Validate initialization state in start method
When sja1000 is not compiled as module the SJA1000 chip is only initialized during device registration on kernel boot. Should the chip get a hardware reset there is no way to reinitialize it without re- booting the Linux kernel. This patch adds a check in sja1000_start if the chip is initialized, if not we initialize it. Signed-off-by: Mirza Krak <mirza.krak@hostmobility.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
parent
02784f1b05
commit
9e37bc6c63
@ -172,6 +172,35 @@ static void set_normal_mode(struct net_device *dev)
|
|||||||
netdev_err(dev, "setting SJA1000 into normal mode failed!\n");
|
netdev_err(dev, "setting SJA1000 into normal mode failed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize SJA1000 chip:
|
||||||
|
* - reset chip
|
||||||
|
* - set output mode
|
||||||
|
* - set baudrate
|
||||||
|
* - enable interrupts
|
||||||
|
* - start operating mode
|
||||||
|
*/
|
||||||
|
static void chipset_init(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct sja1000_priv *priv = netdev_priv(dev);
|
||||||
|
|
||||||
|
/* set clock divider and output control register */
|
||||||
|
priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
|
||||||
|
|
||||||
|
/* set acceptance filter (accept all) */
|
||||||
|
priv->write_reg(priv, SJA1000_ACCC0, 0x00);
|
||||||
|
priv->write_reg(priv, SJA1000_ACCC1, 0x00);
|
||||||
|
priv->write_reg(priv, SJA1000_ACCC2, 0x00);
|
||||||
|
priv->write_reg(priv, SJA1000_ACCC3, 0x00);
|
||||||
|
|
||||||
|
priv->write_reg(priv, SJA1000_ACCM0, 0xFF);
|
||||||
|
priv->write_reg(priv, SJA1000_ACCM1, 0xFF);
|
||||||
|
priv->write_reg(priv, SJA1000_ACCM2, 0xFF);
|
||||||
|
priv->write_reg(priv, SJA1000_ACCM3, 0xFF);
|
||||||
|
|
||||||
|
priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
static void sja1000_start(struct net_device *dev)
|
static void sja1000_start(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct sja1000_priv *priv = netdev_priv(dev);
|
struct sja1000_priv *priv = netdev_priv(dev);
|
||||||
@ -180,6 +209,10 @@ static void sja1000_start(struct net_device *dev)
|
|||||||
if (priv->can.state != CAN_STATE_STOPPED)
|
if (priv->can.state != CAN_STATE_STOPPED)
|
||||||
set_reset_mode(dev);
|
set_reset_mode(dev);
|
||||||
|
|
||||||
|
/* Initialize chip if uninitialized at this stage */
|
||||||
|
if (!(priv->read_reg(priv, SJA1000_CDR) & CDR_PELICAN))
|
||||||
|
chipset_init(dev);
|
||||||
|
|
||||||
/* Clear error counters and error code capture */
|
/* Clear error counters and error code capture */
|
||||||
priv->write_reg(priv, SJA1000_TXERR, 0x0);
|
priv->write_reg(priv, SJA1000_TXERR, 0x0);
|
||||||
priv->write_reg(priv, SJA1000_RXERR, 0x0);
|
priv->write_reg(priv, SJA1000_RXERR, 0x0);
|
||||||
@ -236,35 +269,6 @@ static int sja1000_get_berr_counter(const struct net_device *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* initialize SJA1000 chip:
|
|
||||||
* - reset chip
|
|
||||||
* - set output mode
|
|
||||||
* - set baudrate
|
|
||||||
* - enable interrupts
|
|
||||||
* - start operating mode
|
|
||||||
*/
|
|
||||||
static void chipset_init(struct net_device *dev)
|
|
||||||
{
|
|
||||||
struct sja1000_priv *priv = netdev_priv(dev);
|
|
||||||
|
|
||||||
/* set clock divider and output control register */
|
|
||||||
priv->write_reg(priv, SJA1000_CDR, priv->cdr | CDR_PELICAN);
|
|
||||||
|
|
||||||
/* set acceptance filter (accept all) */
|
|
||||||
priv->write_reg(priv, SJA1000_ACCC0, 0x00);
|
|
||||||
priv->write_reg(priv, SJA1000_ACCC1, 0x00);
|
|
||||||
priv->write_reg(priv, SJA1000_ACCC2, 0x00);
|
|
||||||
priv->write_reg(priv, SJA1000_ACCC3, 0x00);
|
|
||||||
|
|
||||||
priv->write_reg(priv, SJA1000_ACCM0, 0xFF);
|
|
||||||
priv->write_reg(priv, SJA1000_ACCM1, 0xFF);
|
|
||||||
priv->write_reg(priv, SJA1000_ACCM2, 0xFF);
|
|
||||||
priv->write_reg(priv, SJA1000_ACCM3, 0xFF);
|
|
||||||
|
|
||||||
priv->write_reg(priv, SJA1000_OCR, priv->ocr | OCR_MODE_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* transmit a CAN message
|
* transmit a CAN message
|
||||||
* message layout in the sk_buff should be like this:
|
* message layout in the sk_buff should be like this:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user