Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a47d6056 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'can/mcp251x-for-net-next' of git://git.pengutronix.de/git/mkl/linux-2.6

parents d8e62719 9c473fc3
Loading
Loading
Loading
Loading
+70 −25
Original line number Diff line number Diff line
@@ -38,14 +38,14 @@
 * static struct mcp251x_platform_data mcp251x_info = {
 *         .oscillator_frequency = 8000000,
 *         .board_specific_setup = &mcp251x_setup,
 *         .model = CAN_MCP251X_MCP2510,
 *         .power_enable = mcp251x_power_enable,
 *         .transceiver_enable = NULL,
 * };
 *
 * static struct spi_board_info spi_board_info[] = {
 *         {
 *                 .modalias = "mcp251x",
 *                 .modalias = "mcp2510",
 *			// or "mcp2515" depending on your controller
 *                 .platform_data = &mcp251x_info,
 *                 .irq = IRQ_EINT13,
 *                 .max_speed_hz = 2*1000*1000,
@@ -125,6 +125,8 @@
#  define CANINTF_TX0IF 0x04
#  define CANINTF_RX1IF 0x02
#  define CANINTF_RX0IF 0x01
#  define CANINTF_ERR_TX \
	(CANINTF_ERRIF | CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)
#define EFLG	      0x2d
#  define EFLG_EWARN	0x01
#  define EFLG_RXWAR	0x02
@@ -222,10 +224,16 @@ static struct can_bittiming_const mcp251x_bittiming_const = {
	.brp_inc = 1,
};

enum mcp251x_model {
	CAN_MCP251X_MCP2510	= 0x2510,
	CAN_MCP251X_MCP2515	= 0x2515,
};

struct mcp251x_priv {
	struct can_priv	   can;
	struct net_device *net;
	struct spi_device *spi;
	enum mcp251x_model model;

	struct mutex mcp_lock; /* SPI device lock */

@@ -250,6 +258,16 @@ struct mcp251x_priv {
	int restart_tx;
};

#define MCP251X_IS(_model) \
static inline int mcp251x_is_##_model(struct spi_device *spi) \
{ \
	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); \
	return priv->model == CAN_MCP251X_MCP##_model; \
}

MCP251X_IS(2510);
MCP251X_IS(2515);

static void mcp251x_clean(struct net_device *net)
{
	struct mcp251x_priv *priv = netdev_priv(net);
@@ -319,6 +337,20 @@ static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg)
	return val;
}

static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg,
		uint8_t *v1, uint8_t *v2)
{
	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);

	priv->spi_tx_buf[0] = INSTRUCTION_READ;
	priv->spi_tx_buf[1] = reg;

	mcp251x_spi_trans(spi, 4);

	*v1 = priv->spi_rx_buf[2];
	*v2 = priv->spi_rx_buf[3];
}

static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val)
{
	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
@@ -346,10 +378,9 @@ static void mcp251x_write_bits(struct spi_device *spi, u8 reg,
static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,
				int len, int tx_buf_idx)
{
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);

	if (pdata->model == CAN_MCP251X_MCP2510) {
	if (mcp251x_is_2510(spi)) {
		int i;

		for (i = 1; i < TXBDAT_OFF + len; i++)
@@ -392,9 +423,8 @@ static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
				int buf_idx)
{
	struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;

	if (pdata->model == CAN_MCP251X_MCP2510) {
	if (mcp251x_is_2510(spi)) {
		int i, len;

		for (i = 1; i < RXBDAT_OFF; i++)
@@ -451,7 +481,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx)

	priv->net->stats.rx_packets++;
	priv->net->stats.rx_bytes += frame->can_dlc;
	netif_rx(skb);
	netif_rx_ni(skb);
}

static void mcp251x_hw_sleep(struct spi_device *spi)
@@ -676,7 +706,7 @@ static void mcp251x_error_skb(struct net_device *net, int can_id, int data1)
	if (skb) {
		frame->can_id = can_id;
		frame->data[1] = data1;
		netif_rx(skb);
		netif_rx_ni(skb);
	} else {
		dev_err(&net->dev,
			"cannot allocate error skb\n");
@@ -754,24 +784,39 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
	mutex_lock(&priv->mcp_lock);
	while (!priv->force_quit) {
		enum can_state new_state;
		u8 intf = mcp251x_read_reg(spi, CANINTF);
		u8 eflag;
		u8 intf, eflag;
		u8 clear_intf = 0;
		int can_id = 0, data1 = 0;

		mcp251x_read_2regs(spi, CANINTF, &intf, &eflag);

		/* receive buffer 0 */
		if (intf & CANINTF_RX0IF) {
			mcp251x_hw_rx(spi, 0);
			/* Free one buffer ASAP */
			mcp251x_write_bits(spi, CANINTF, intf & CANINTF_RX0IF,
					   0x00);
			/*
			 * Free one buffer ASAP
			 * (The MCP2515 does this automatically.)
			 */
			if (mcp251x_is_2510(spi))
				mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
		}

		if (intf & CANINTF_RX1IF)
		/* receive buffer 1 */
		if (intf & CANINTF_RX1IF) {
			mcp251x_hw_rx(spi, 1);
			/* the MCP2515 does this automatically */
			if (mcp251x_is_2510(spi))
				clear_intf |= CANINTF_RX1IF;
		}

		mcp251x_write_bits(spi, CANINTF, intf, 0x00);
		/* any error or tx interrupt we need to clear? */
		if (intf & CANINTF_ERR_TX)
			clear_intf |= intf & CANINTF_ERR_TX;
		if (clear_intf)
			mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00);

		eflag = mcp251x_read_reg(spi, EFLG);
		mcp251x_write_reg(spi, EFLG, 0x00);
		if (eflag)
			mcp251x_write_bits(spi, EFLG, eflag, 0x00);

		/* Update can state */
		if (eflag & EFLG_TXBO) {
@@ -816,10 +861,14 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
		if (intf & CANINTF_ERRIF) {
			/* Handle overflow counters */
			if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) {
				if (eflag & EFLG_RX0OVR)
				if (eflag & EFLG_RX0OVR) {
					net->stats.rx_over_errors++;
				if (eflag & EFLG_RX1OVR)
					net->stats.rx_errors++;
				}
				if (eflag & EFLG_RX1OVR) {
					net->stats.rx_over_errors++;
					net->stats.rx_errors++;
				}
				can_id |= CAN_ERR_CRTL;
				data1 |= CAN_ERR_CRTL_RX_OVERFLOW;
			}
@@ -921,16 +970,12 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
	struct net_device *net;
	struct mcp251x_priv *priv;
	struct mcp251x_platform_data *pdata = spi->dev.platform_data;
	int model = spi_get_device_id(spi)->driver_data;
	int ret = -ENODEV;

	if (!pdata)
		/* Platform data is required for osc freq */
		goto error_out;

	if (model)
		pdata->model = model;

	/* Allocate can/net device */
	net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
	if (!net) {
@@ -947,6 +992,7 @@ static int __devinit mcp251x_can_probe(struct spi_device *spi)
	priv->can.clock.freq = pdata->oscillator_frequency / 2;
	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
		CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
	priv->model = spi_get_device_id(spi)->driver_data;
	priv->net = net;
	dev_set_drvdata(&spi->dev, priv);

@@ -1120,8 +1166,7 @@ static int mcp251x_can_resume(struct spi_device *spi)
#define mcp251x_can_resume NULL
#endif

static struct spi_device_id mcp251x_id_table[] = {
	{ "mcp251x", 	0 /* Use pdata.model */ },
static const struct spi_device_id mcp251x_id_table[] = {
	{ "mcp2510",	CAN_MCP251X_MCP2510 },
	{ "mcp2515",	CAN_MCP251X_MCP2515 },
	{ },
+0 −4
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@
/**
 * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
 * @oscillator_frequency:       - oscillator frequency in Hz
 * @model:                      - actual type of chip
 * @board_specific_setup:       - called before probing the chip (power,reset)
 * @transceiver_enable:         - called to power on/off the transceiver
 * @power_enable:               - called to power on/off the mcp *and* the
@@ -25,9 +24,6 @@

struct mcp251x_platform_data {
	unsigned long oscillator_frequency;
	int model;
#define CAN_MCP251X_MCP2510 0x2510
#define CAN_MCP251X_MCP2515 0x2515
	int (*board_specific_setup)(struct spi_device *spi);
	int (*transceiver_enable)(int enable);
	int (*power_enable) (int enable);