Skip to content

Commit

Permalink
can: sja1000: Validate initialization state in start method
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Mirza Krak authored and Marc Kleine-Budde committed Aug 21, 2014
1 parent 02784f1 commit 9e37bc6
Showing 1 changed file with 33 additions and 29 deletions.
62 changes: 33 additions & 29 deletions drivers/net/can/sja1000/sja1000.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,35 @@ static void set_normal_mode(struct net_device *dev)
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)
{
struct sja1000_priv *priv = netdev_priv(dev);
Expand All @@ -180,6 +209,10 @@ static void sja1000_start(struct net_device *dev)
if (priv->can.state != CAN_STATE_STOPPED)
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 */
priv->write_reg(priv, SJA1000_TXERR, 0x0);
priv->write_reg(priv, SJA1000_RXERR, 0x0);
Expand Down Expand Up @@ -236,35 +269,6 @@ static int sja1000_get_berr_counter(const struct net_device *dev,
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
* message layout in the sk_buff should be like this:
Expand Down

0 comments on commit 9e37bc6

Please sign in to comment.