From 31473c286cc09720c0238d085c9de2b890ddb965 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 28 Mar 2014 14:14:44 +0400 Subject: can: mcp251x: Check return value of spi_setup() This patch moves setup of SPI bus a bit earlier and adds check for spi_setup() result to be sure SPI bus is communicating with the device properly. Signed-off-by: Alexander Shiyan Tested-by: Alexander Shiyan Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mcp251x.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 28c11f815245..356d3da0c5e2 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -1032,8 +1032,8 @@ static int mcp251x_can_probe(struct spi_device *spi) struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); struct net_device *net; struct mcp251x_priv *priv; - int freq, ret = -ENODEV; struct clk *clk; + int freq, ret; clk = devm_clk_get(&spi->dev, NULL); if (IS_ERR(clk)) { @@ -1076,6 +1076,18 @@ static int mcp251x_can_probe(struct spi_device *spi) priv->net = net; priv->clk = clk; + spi_set_drvdata(spi, priv); + + /* Configure the SPI bus */ + spi->bits_per_word = 8; + if (mcp251x_is_2510(spi)) + spi->max_speed_hz = spi->max_speed_hz ? : 5 * 1000 * 1000; + else + spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000; + ret = spi_setup(spi); + if (ret) + goto out_clk; + priv->power = devm_regulator_get(&spi->dev, "vdd"); priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || @@ -1088,8 +1100,6 @@ static int mcp251x_can_probe(struct spi_device *spi) if (ret) goto out_clk; - spi_set_drvdata(spi, priv); - priv->spi = spi; mutex_init(&priv->mcp_lock); @@ -1134,15 +1144,6 @@ static int mcp251x_can_probe(struct spi_device *spi) SET_NETDEV_DEV(net, &spi->dev); - /* Configure the SPI bus */ - spi->mode = spi->mode ? : SPI_MODE_0; - if (mcp251x_is_2510(spi)) - spi->max_speed_hz = spi->max_speed_hz ? : 5 * 1000 * 1000; - else - spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000; - spi->bits_per_word = 8; - spi_setup(spi); - /* Here is OK to not lock the MCP, no one knows about it yet */ if (!mcp251x_hw_probe(spi)) { ret = -ENODEV; -- cgit v1.2.3 From ff06d611a31c4b687c7859e3c7516a38194d4d25 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 28 Mar 2014 14:14:45 +0400 Subject: can: mcp251x: Improve mcp251x_hw_reset() The MCP251x utilizes an oscillator startup timer (OST), which holds the chip in reset, to insure that the oscillator has stabilized before the internal state machine begins to operate. The OST maintains reset for the first 128 OSC clock cycles after power up or reset. So, this patch removes unnecessary loops and reduce delay for power on and reset to the safe value. Signed-off-by: Alexander Shiyan Tested-by: Alexander Shiyan Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mcp251x.c | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 356d3da0c5e2..9a8fd9456979 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -214,6 +214,8 @@ #define TX_ECHO_SKB_MAX 1 +#define MCP251X_OST_DELAY_MS (5) + #define DEVICE_NAME "mcp251x" static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */ @@ -624,28 +626,24 @@ static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv, static int mcp251x_hw_reset(struct spi_device *spi) { struct mcp251x_priv *priv = spi_get_drvdata(spi); + u8 reg; int ret; - unsigned long timeout; + + /* Wait for oscillator startup timer after power up */ + mdelay(MCP251X_OST_DELAY_MS); priv->spi_tx_buf[0] = INSTRUCTION_RESET; - ret = spi_write(spi, priv->spi_tx_buf, 1); - if (ret) { - dev_err(&spi->dev, "reset failed: ret = %d\n", ret); - return -EIO; - } + ret = mcp251x_spi_trans(spi, 1); + if (ret) + return ret; + + /* Wait for oscillator startup timer after reset */ + mdelay(MCP251X_OST_DELAY_MS); + + reg = mcp251x_read_reg(spi, CANSTAT); + if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) + return -ENODEV; - /* Wait for reset to finish */ - timeout = jiffies + HZ; - mdelay(10); - while ((mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) - != CANCTRL_REQOP_CONF) { - schedule(); - if (time_after(jiffies, timeout)) { - dev_err(&spi->dev, "MCP251x didn't" - " enter in conf mode after reset\n"); - return -EBUSY; - } - } return 0; } @@ -776,7 +774,6 @@ static void mcp251x_restart_work_handler(struct work_struct *ws) mutex_lock(&priv->mcp_lock); if (priv->after_suspend) { - mdelay(10); mcp251x_hw_reset(spi); mcp251x_setup(net, priv, spi); if (priv->after_suspend & AFTER_SUSPEND_RESTART) { -- cgit v1.2.3 From ee967fffd91031f18dbe36bf6a273d8a75f663cf Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Fri, 28 Mar 2014 14:14:46 +0400 Subject: can: mcp251x: Improve mcp251x_hw_probe() This patch adds check for mcp251x_hw_reset() result on startup and removes unnecessary checking for CANSTAT register since this value is being checked in mcp251x_hw_reset(). Signed-off-by: Alexander Shiyan Tested-by: Alexander Shiyan Signed-off-by: Marc Kleine-Budde --- drivers/net/can/mcp251x.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 9a8fd9456979..bc235f9dc754 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -649,23 +649,22 @@ static int mcp251x_hw_reset(struct spi_device *spi) static int mcp251x_hw_probe(struct spi_device *spi) { - int st1, st2; + u8 ctrl; + int ret; - mcp251x_hw_reset(spi); + ret = mcp251x_hw_reset(spi); + if (ret) + return ret; - /* - * Please note that these are "magic values" based on after - * reset defaults taken from data sheet which allows us to see - * if we really have a chip on the bus (we avoid common all - * zeroes or all ones situations) - */ - st1 = mcp251x_read_reg(spi, CANSTAT) & 0xEE; - st2 = mcp251x_read_reg(spi, CANCTRL) & 0x17; + ctrl = mcp251x_read_reg(spi, CANCTRL); + + dev_dbg(&spi->dev, "CANCTRL 0x%02x\n", ctrl); - dev_dbg(&spi->dev, "CANSTAT 0x%02x CANCTRL 0x%02x\n", st1, st2); + /* Check for power up default value */ + if ((ctrl & 0x17) != 0x07) + return -ENODEV; - /* Check for power up default values */ - return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; + return 0; } static int mcp251x_power_enable(struct regulator *reg, int enable) @@ -1142,10 +1141,10 @@ static int mcp251x_can_probe(struct spi_device *spi) SET_NETDEV_DEV(net, &spi->dev); /* Here is OK to not lock the MCP, no one knows about it yet */ - if (!mcp251x_hw_probe(spi)) { - ret = -ENODEV; + ret = mcp251x_hw_probe(spi); + if (ret) goto error_probe; - } + mcp251x_hw_sleep(spi); ret = register_candev(net); @@ -1154,7 +1153,7 @@ static int mcp251x_can_probe(struct spi_device *spi) devm_can_led_init(net); - return ret; + return 0; error_probe: if (mcp251x_enable_dma) -- cgit v1.2.3 From 869ba1e67a894f45ba3da32af66f25104fab7d8f Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Tue, 25 Mar 2014 15:30:21 +0100 Subject: can: move SPI drivers into a separate directory Create a directory for all CAN drivers using SPI and move mcp251x driver there. Signed-off-by: Stefano Babic Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- drivers/net/can/Kconfig | 8 +- drivers/net/can/Makefile | 2 +- drivers/net/can/mcp251x.c | 1266 ----------------------------------------- drivers/net/can/spi/Kconfig | 10 + drivers/net/can/spi/Makefile | 8 + drivers/net/can/spi/mcp251x.c | 1266 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1287 insertions(+), 1273 deletions(-) delete mode 100644 drivers/net/can/mcp251x.c create mode 100644 drivers/net/can/spi/Kconfig create mode 100644 drivers/net/can/spi/Makefile create mode 100644 drivers/net/can/spi/mcp251x.c diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 9e7d95dae2c7..4aacaa9b478a 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -77,12 +77,6 @@ config CAN_TI_HECC Driver for TI HECC (High End CAN Controller) module found on many TI devices. The device specifications are available from www.ti.com -config CAN_MCP251X - tristate "Microchip MCP251x SPI CAN controllers" - depends on SPI && HAS_DMA - ---help--- - Driver for the Microchip MCP251x SPI CAN controllers. - config CAN_BFIN depends on BF534 || BF536 || BF537 || BF538 || BF539 || BF54x tristate "Analog Devices Blackfin on-chip CAN" @@ -133,6 +127,8 @@ source "drivers/net/can/c_can/Kconfig" source "drivers/net/can/cc770/Kconfig" +source "drivers/net/can/spi/Kconfig" + source "drivers/net/can/usb/Kconfig" source "drivers/net/can/softing/Kconfig" diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index c7440392adbb..c42058868b0f 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -10,6 +10,7 @@ can-dev-y := dev.o can-dev-$(CONFIG_CAN_LEDS) += led.o +obj-y += spi/ obj-y += usb/ obj-y += softing/ @@ -19,7 +20,6 @@ obj-$(CONFIG_CAN_C_CAN) += c_can/ obj-$(CONFIG_CAN_CC770) += cc770/ obj-$(CONFIG_CAN_AT91) += at91_can.o obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o -obj-$(CONFIG_CAN_MCP251X) += mcp251x.o obj-$(CONFIG_CAN_BFIN) += bfin_can.o obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o obj-$(CONFIG_CAN_FLEXCAN) += flexcan.o diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c deleted file mode 100644 index bc235f9dc754..000000000000 --- a/drivers/net/can/mcp251x.c +++ /dev/null @@ -1,1266 +0,0 @@ -/* - * CAN bus driver for Microchip 251x CAN Controller with SPI Interface - * - * MCP2510 support and bug fixes by Christian Pellegrin - * - * - * Copyright 2009 Christian Pellegrin EVOL S.r.l. - * - * Copyright 2007 Raymarine UK, Ltd. All Rights Reserved. - * Written under contract by: - * Chris Elston, Katalix Systems, Ltd. - * - * Based on Microchip MCP251x CAN controller driver written by - * David Vrabel, Copyright 2006 Arcom Control Systems Ltd. - * - * Based on CAN bus driver for the CCAN controller written by - * - Sascha Hauer, Marc Kleine-Budde, Pengutronix - * - Simon Kallweit, intefo AG - * Copyright 2007 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - * - * - * - * Your platform definition file should specify something like: - * - * static struct mcp251x_platform_data mcp251x_info = { - * .oscillator_frequency = 8000000, - * }; - * - * static struct spi_board_info spi_board_info[] = { - * { - * .modalias = "mcp2510", - * // or "mcp2515" depending on your controller - * .platform_data = &mcp251x_info, - * .irq = IRQ_EINT13, - * .max_speed_hz = 2*1000*1000, - * .chip_select = 2, - * }, - * }; - * - * Please see mcp251x.h for a description of the fields in - * struct mcp251x_platform_data. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* SPI interface instruction set */ -#define INSTRUCTION_WRITE 0x02 -#define INSTRUCTION_READ 0x03 -#define INSTRUCTION_BIT_MODIFY 0x05 -#define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) -#define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) -#define INSTRUCTION_RESET 0xC0 -#define RTS_TXB0 0x01 -#define RTS_TXB1 0x02 -#define RTS_TXB2 0x04 -#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) - - -/* MPC251x registers */ -#define CANSTAT 0x0e -#define CANCTRL 0x0f -# define CANCTRL_REQOP_MASK 0xe0 -# define CANCTRL_REQOP_CONF 0x80 -# define CANCTRL_REQOP_LISTEN_ONLY 0x60 -# define CANCTRL_REQOP_LOOPBACK 0x40 -# define CANCTRL_REQOP_SLEEP 0x20 -# define CANCTRL_REQOP_NORMAL 0x00 -# define CANCTRL_OSM 0x08 -# define CANCTRL_ABAT 0x10 -#define TEC 0x1c -#define REC 0x1d -#define CNF1 0x2a -# define CNF1_SJW_SHIFT 6 -#define CNF2 0x29 -# define CNF2_BTLMODE 0x80 -# define CNF2_SAM 0x40 -# define CNF2_PS1_SHIFT 3 -#define CNF3 0x28 -# define CNF3_SOF 0x08 -# define CNF3_WAKFIL 0x04 -# define CNF3_PHSEG2_MASK 0x07 -#define CANINTE 0x2b -# define CANINTE_MERRE 0x80 -# define CANINTE_WAKIE 0x40 -# define CANINTE_ERRIE 0x20 -# define CANINTE_TX2IE 0x10 -# define CANINTE_TX1IE 0x08 -# define CANINTE_TX0IE 0x04 -# define CANINTE_RX1IE 0x02 -# define CANINTE_RX0IE 0x01 -#define CANINTF 0x2c -# define CANINTF_MERRF 0x80 -# define CANINTF_WAKIF 0x40 -# define CANINTF_ERRIF 0x20 -# define CANINTF_TX2IF 0x10 -# define CANINTF_TX1IF 0x08 -# define CANINTF_TX0IF 0x04 -# define CANINTF_RX1IF 0x02 -# define CANINTF_RX0IF 0x01 -# define CANINTF_RX (CANINTF_RX0IF | CANINTF_RX1IF) -# define CANINTF_TX (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF) -# define CANINTF_ERR (CANINTF_ERRIF) -#define EFLG 0x2d -# define EFLG_EWARN 0x01 -# define EFLG_RXWAR 0x02 -# define EFLG_TXWAR 0x04 -# define EFLG_RXEP 0x08 -# define EFLG_TXEP 0x10 -# define EFLG_TXBO 0x20 -# define EFLG_RX0OVR 0x40 -# define EFLG_RX1OVR 0x80 -#define TXBCTRL(n) (((n) * 0x10) + 0x30 + TXBCTRL_OFF) -# define TXBCTRL_ABTF 0x40 -# define TXBCTRL_MLOA 0x20 -# define TXBCTRL_TXERR 0x10 -# define TXBCTRL_TXREQ 0x08 -#define TXBSIDH(n) (((n) * 0x10) + 0x30 + TXBSIDH_OFF) -# define SIDH_SHIFT 3 -#define TXBSIDL(n) (((n) * 0x10) + 0x30 + TXBSIDL_OFF) -# define SIDL_SID_MASK 7 -# define SIDL_SID_SHIFT 5 -# define SIDL_EXIDE_SHIFT 3 -# define SIDL_EID_SHIFT 16 -# define SIDL_EID_MASK 3 -#define TXBEID8(n) (((n) * 0x10) + 0x30 + TXBEID8_OFF) -#define TXBEID0(n) (((n) * 0x10) + 0x30 + TXBEID0_OFF) -#define TXBDLC(n) (((n) * 0x10) + 0x30 + TXBDLC_OFF) -# define DLC_RTR_SHIFT 6 -#define TXBCTRL_OFF 0 -#define TXBSIDH_OFF 1 -#define TXBSIDL_OFF 2 -#define TXBEID8_OFF 3 -#define TXBEID0_OFF 4 -#define TXBDLC_OFF 5 -#define TXBDAT_OFF 6 -#define RXBCTRL(n) (((n) * 0x10) + 0x60 + RXBCTRL_OFF) -# define RXBCTRL_BUKT 0x04 -# define RXBCTRL_RXM0 0x20 -# define RXBCTRL_RXM1 0x40 -#define RXBSIDH(n) (((n) * 0x10) + 0x60 + RXBSIDH_OFF) -# define RXBSIDH_SHIFT 3 -#define RXBSIDL(n) (((n) * 0x10) + 0x60 + RXBSIDL_OFF) -# define RXBSIDL_IDE 0x08 -# define RXBSIDL_SRR 0x10 -# define RXBSIDL_EID 3 -# define RXBSIDL_SHIFT 5 -#define RXBEID8(n) (((n) * 0x10) + 0x60 + RXBEID8_OFF) -#define RXBEID0(n) (((n) * 0x10) + 0x60 + RXBEID0_OFF) -#define RXBDLC(n) (((n) * 0x10) + 0x60 + RXBDLC_OFF) -# define RXBDLC_LEN_MASK 0x0f -# define RXBDLC_RTR 0x40 -#define RXBCTRL_OFF 0 -#define RXBSIDH_OFF 1 -#define RXBSIDL_OFF 2 -#define RXBEID8_OFF 3 -#define RXBEID0_OFF 4 -#define RXBDLC_OFF 5 -#define RXBDAT_OFF 6 -#define RXFSIDH(n) ((n) * 4) -#define RXFSIDL(n) ((n) * 4 + 1) -#define RXFEID8(n) ((n) * 4 + 2) -#define RXFEID0(n) ((n) * 4 + 3) -#define RXMSIDH(n) ((n) * 4 + 0x20) -#define RXMSIDL(n) ((n) * 4 + 0x21) -#define RXMEID8(n) ((n) * 4 + 0x22) -#define RXMEID0(n) ((n) * 4 + 0x23) - -#define GET_BYTE(val, byte) \ - (((val) >> ((byte) * 8)) & 0xff) -#define SET_BYTE(val, byte) \ - (((val) & 0xff) << ((byte) * 8)) - -/* - * Buffer size required for the largest SPI transfer (i.e., reading a - * frame) - */ -#define CAN_FRAME_MAX_DATA_LEN 8 -#define SPI_TRANSFER_BUF_LEN (6 + CAN_FRAME_MAX_DATA_LEN) -#define CAN_FRAME_MAX_BITS 128 - -#define TX_ECHO_SKB_MAX 1 - -#define MCP251X_OST_DELAY_MS (5) - -#define DEVICE_NAME "mcp251x" - -static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */ -module_param(mcp251x_enable_dma, int, S_IRUGO); -MODULE_PARM_DESC(mcp251x_enable_dma, "Enable SPI DMA. Default: 0 (Off)"); - -static const struct can_bittiming_const mcp251x_bittiming_const = { - .name = DEVICE_NAME, - .tseg1_min = 3, - .tseg1_max = 16, - .tseg2_min = 2, - .tseg2_max = 8, - .sjw_max = 4, - .brp_min = 1, - .brp_max = 64, - .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 */ - - u8 *spi_tx_buf; - u8 *spi_rx_buf; - dma_addr_t spi_tx_dma; - dma_addr_t spi_rx_dma; - - struct sk_buff *tx_skb; - int tx_len; - - struct workqueue_struct *wq; - struct work_struct tx_work; - struct work_struct restart_work; - - int force_quit; - int after_suspend; -#define AFTER_SUSPEND_UP 1 -#define AFTER_SUSPEND_DOWN 2 -#define AFTER_SUSPEND_POWER 4 -#define AFTER_SUSPEND_RESTART 8 - int restart_tx; - struct regulator *power; - struct regulator *transceiver; - struct clk *clk; -}; - -#define MCP251X_IS(_model) \ -static inline int mcp251x_is_##_model(struct spi_device *spi) \ -{ \ - struct mcp251x_priv *priv = spi_get_drvdata(spi); \ - 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); - - if (priv->tx_skb || priv->tx_len) - net->stats.tx_errors++; - if (priv->tx_skb) - dev_kfree_skb(priv->tx_skb); - if (priv->tx_len) - can_free_echo_skb(priv->net, 0); - priv->tx_skb = NULL; - priv->tx_len = 0; -} - -/* - * Note about handling of error return of mcp251x_spi_trans: accessing - * registers via SPI is not really different conceptually than using - * normal I/O assembler instructions, although it's much more - * complicated from a practical POV. So it's not advisable to always - * check the return value of this function. Imagine that every - * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0) - * error();", it would be a great mess (well there are some situation - * when exception handling C++ like could be useful after all). So we - * just check that transfers are OK at the beginning of our - * conversation with the chip and to avoid doing really nasty things - * (like injecting bogus packets in the network stack). - */ -static int mcp251x_spi_trans(struct spi_device *spi, int len) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - struct spi_transfer t = { - .tx_buf = priv->spi_tx_buf, - .rx_buf = priv->spi_rx_buf, - .len = len, - .cs_change = 0, - }; - struct spi_message m; - int ret; - - spi_message_init(&m); - - if (mcp251x_enable_dma) { - t.tx_dma = priv->spi_tx_dma; - t.rx_dma = priv->spi_rx_dma; - m.is_dma_mapped = 1; - } - - spi_message_add_tail(&t, &m); - - ret = spi_sync(spi, &m); - if (ret) - dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret); - return ret; -} - -static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - u8 val = 0; - - priv->spi_tx_buf[0] = INSTRUCTION_READ; - priv->spi_tx_buf[1] = reg; - - mcp251x_spi_trans(spi, 3); - val = priv->spi_rx_buf[2]; - - return val; -} - -static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg, - uint8_t *v1, uint8_t *v2) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - - 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 = spi_get_drvdata(spi); - - priv->spi_tx_buf[0] = INSTRUCTION_WRITE; - priv->spi_tx_buf[1] = reg; - priv->spi_tx_buf[2] = val; - - mcp251x_spi_trans(spi, 3); -} - -static void mcp251x_write_bits(struct spi_device *spi, u8 reg, - u8 mask, uint8_t val) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - - priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY; - priv->spi_tx_buf[1] = reg; - priv->spi_tx_buf[2] = mask; - priv->spi_tx_buf[3] = val; - - mcp251x_spi_trans(spi, 4); -} - -static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, - int len, int tx_buf_idx) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - - if (mcp251x_is_2510(spi)) { - int i; - - for (i = 1; i < TXBDAT_OFF + len; i++) - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + i, - buf[i]); - } else { - memcpy(priv->spi_tx_buf, buf, TXBDAT_OFF + len); - mcp251x_spi_trans(spi, TXBDAT_OFF + len); - } -} - -static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, - int tx_buf_idx) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - u32 sid, eid, exide, rtr; - u8 buf[SPI_TRANSFER_BUF_LEN]; - - exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; /* Extended ID Enable */ - if (exide) - sid = (frame->can_id & CAN_EFF_MASK) >> 18; - else - sid = frame->can_id & CAN_SFF_MASK; /* Standard ID */ - eid = frame->can_id & CAN_EFF_MASK; /* Extended ID */ - rtr = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; /* Remote transmission */ - - buf[TXBCTRL_OFF] = INSTRUCTION_LOAD_TXB(tx_buf_idx); - buf[TXBSIDH_OFF] = sid >> SIDH_SHIFT; - buf[TXBSIDL_OFF] = ((sid & SIDL_SID_MASK) << SIDL_SID_SHIFT) | - (exide << SIDL_EXIDE_SHIFT) | - ((eid >> SIDL_EID_SHIFT) & SIDL_EID_MASK); - buf[TXBEID8_OFF] = GET_BYTE(eid, 1); - buf[TXBEID0_OFF] = GET_BYTE(eid, 0); - buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; - memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); - mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - - /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ - priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); - mcp251x_spi_trans(priv->spi, 1); -} - -static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, - int buf_idx) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - - if (mcp251x_is_2510(spi)) { - int i, len; - - for (i = 1; i < RXBDAT_OFF; i++) - buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); - - len = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK); - for (; i < (RXBDAT_OFF + len); i++) - buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); - } else { - priv->spi_tx_buf[RXBCTRL_OFF] = INSTRUCTION_READ_RXB(buf_idx); - mcp251x_spi_trans(spi, SPI_TRANSFER_BUF_LEN); - memcpy(buf, priv->spi_rx_buf, SPI_TRANSFER_BUF_LEN); - } -} - -static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - struct sk_buff *skb; - struct can_frame *frame; - u8 buf[SPI_TRANSFER_BUF_LEN]; - - skb = alloc_can_skb(priv->net, &frame); - if (!skb) { - dev_err(&spi->dev, "cannot allocate RX skb\n"); - priv->net->stats.rx_dropped++; - return; - } - - mcp251x_hw_rx_frame(spi, buf, buf_idx); - if (buf[RXBSIDL_OFF] & RXBSIDL_IDE) { - /* Extended ID format */ - frame->can_id = CAN_EFF_FLAG; - frame->can_id |= - /* Extended ID part */ - SET_BYTE(buf[RXBSIDL_OFF] & RXBSIDL_EID, 2) | - SET_BYTE(buf[RXBEID8_OFF], 1) | - SET_BYTE(buf[RXBEID0_OFF], 0) | - /* Standard ID part */ - (((buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | - (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT)) << 18); - /* Remote transmission request */ - if (buf[RXBDLC_OFF] & RXBDLC_RTR) - frame->can_id |= CAN_RTR_FLAG; - } else { - /* Standard ID format */ - frame->can_id = - (buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | - (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT); - if (buf[RXBSIDL_OFF] & RXBSIDL_SRR) - frame->can_id |= CAN_RTR_FLAG; - } - /* Data length */ - frame->can_dlc = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK); - memcpy(frame->data, buf + RXBDAT_OFF, frame->can_dlc); - - priv->net->stats.rx_packets++; - priv->net->stats.rx_bytes += frame->can_dlc; - - can_led_event(priv->net, CAN_LED_EVENT_RX); - - netif_rx_ni(skb); -} - -static void mcp251x_hw_sleep(struct spi_device *spi) -{ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP); -} - -static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, - struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct spi_device *spi = priv->spi; - - if (priv->tx_skb || priv->tx_len) { - dev_warn(&spi->dev, "hard_xmit called while tx busy\n"); - return NETDEV_TX_BUSY; - } - - if (can_dropped_invalid_skb(net, skb)) - return NETDEV_TX_OK; - - netif_stop_queue(net); - priv->tx_skb = skb; - queue_work(priv->wq, &priv->tx_work); - - return NETDEV_TX_OK; -} - -static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode) -{ - struct mcp251x_priv *priv = netdev_priv(net); - - switch (mode) { - case CAN_MODE_START: - mcp251x_clean(net); - /* We have to delay work since SPI I/O may sleep */ - priv->can.state = CAN_STATE_ERROR_ACTIVE; - priv->restart_tx = 1; - if (priv->can.restart_ms == 0) - priv->after_suspend = AFTER_SUSPEND_RESTART; - queue_work(priv->wq, &priv->restart_work); - break; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int mcp251x_set_normal_mode(struct spi_device *spi) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - unsigned long timeout; - - /* Enable interrupts */ - mcp251x_write_reg(spi, CANINTE, - CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE | - CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE); - - if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { - /* Put device into loopback mode */ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK); - } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { - /* Put device into listen-only mode */ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY); - } else { - /* Put device into normal mode */ - mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL); - - /* Wait for the device to enter normal mode */ - timeout = jiffies + HZ; - while (mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) { - schedule(); - if (time_after(jiffies, timeout)) { - dev_err(&spi->dev, "MCP251x didn't" - " enter in normal mode\n"); - return -EBUSY; - } - } - } - priv->can.state = CAN_STATE_ERROR_ACTIVE; - return 0; -} - -static int mcp251x_do_set_bittiming(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct can_bittiming *bt = &priv->can.bittiming; - struct spi_device *spi = priv->spi; - - mcp251x_write_reg(spi, CNF1, ((bt->sjw - 1) << CNF1_SJW_SHIFT) | - (bt->brp - 1)); - mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | - (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ? - CNF2_SAM : 0) | - ((bt->phase_seg1 - 1) << CNF2_PS1_SHIFT) | - (bt->prop_seg - 1)); - mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, - (bt->phase_seg2 - 1)); - dev_dbg(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n", - mcp251x_read_reg(spi, CNF1), - mcp251x_read_reg(spi, CNF2), - mcp251x_read_reg(spi, CNF3)); - - return 0; -} - -static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv, - struct spi_device *spi) -{ - mcp251x_do_set_bittiming(net); - - mcp251x_write_reg(spi, RXBCTRL(0), - RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1); - mcp251x_write_reg(spi, RXBCTRL(1), - RXBCTRL_RXM0 | RXBCTRL_RXM1); - return 0; -} - -static int mcp251x_hw_reset(struct spi_device *spi) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - u8 reg; - int ret; - - /* Wait for oscillator startup timer after power up */ - mdelay(MCP251X_OST_DELAY_MS); - - priv->spi_tx_buf[0] = INSTRUCTION_RESET; - ret = mcp251x_spi_trans(spi, 1); - if (ret) - return ret; - - /* Wait for oscillator startup timer after reset */ - mdelay(MCP251X_OST_DELAY_MS); - - reg = mcp251x_read_reg(spi, CANSTAT); - if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) - return -ENODEV; - - return 0; -} - -static int mcp251x_hw_probe(struct spi_device *spi) -{ - u8 ctrl; - int ret; - - ret = mcp251x_hw_reset(spi); - if (ret) - return ret; - - ctrl = mcp251x_read_reg(spi, CANCTRL); - - dev_dbg(&spi->dev, "CANCTRL 0x%02x\n", ctrl); - - /* Check for power up default value */ - if ((ctrl & 0x17) != 0x07) - return -ENODEV; - - return 0; -} - -static int mcp251x_power_enable(struct regulator *reg, int enable) -{ - if (IS_ERR_OR_NULL(reg)) - return 0; - - if (enable) - return regulator_enable(reg); - else - return regulator_disable(reg); -} - -static void mcp251x_open_clean(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct spi_device *spi = priv->spi; - - free_irq(spi->irq, priv); - mcp251x_hw_sleep(spi); - mcp251x_power_enable(priv->transceiver, 0); - close_candev(net); -} - -static int mcp251x_stop(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct spi_device *spi = priv->spi; - - close_candev(net); - - priv->force_quit = 1; - free_irq(spi->irq, priv); - destroy_workqueue(priv->wq); - priv->wq = NULL; - - mutex_lock(&priv->mcp_lock); - - /* Disable and clear pending interrupts */ - mcp251x_write_reg(spi, CANINTE, 0x00); - mcp251x_write_reg(spi, CANINTF, 0x00); - - mcp251x_write_reg(spi, TXBCTRL(0), 0); - mcp251x_clean(net); - - mcp251x_hw_sleep(spi); - - mcp251x_power_enable(priv->transceiver, 0); - - priv->can.state = CAN_STATE_STOPPED; - - mutex_unlock(&priv->mcp_lock); - - can_led_event(net, CAN_LED_EVENT_STOP); - - return 0; -} - -static void mcp251x_error_skb(struct net_device *net, int can_id, int data1) -{ - struct sk_buff *skb; - struct can_frame *frame; - - skb = alloc_can_err_skb(net, &frame); - if (skb) { - frame->can_id |= can_id; - frame->data[1] = data1; - netif_rx_ni(skb); - } else { - netdev_err(net, "cannot allocate error skb\n"); - } -} - -static void mcp251x_tx_work_handler(struct work_struct *ws) -{ - struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, - tx_work); - struct spi_device *spi = priv->spi; - struct net_device *net = priv->net; - struct can_frame *frame; - - mutex_lock(&priv->mcp_lock); - if (priv->tx_skb) { - if (priv->can.state == CAN_STATE_BUS_OFF) { - mcp251x_clean(net); - } else { - frame = (struct can_frame *)priv->tx_skb->data; - - if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN) - frame->can_dlc = CAN_FRAME_MAX_DATA_LEN; - mcp251x_hw_tx(spi, frame, 0); - priv->tx_len = 1 + frame->can_dlc; - can_put_echo_skb(priv->tx_skb, net, 0); - priv->tx_skb = NULL; - } - } - mutex_unlock(&priv->mcp_lock); -} - -static void mcp251x_restart_work_handler(struct work_struct *ws) -{ - struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, - restart_work); - struct spi_device *spi = priv->spi; - struct net_device *net = priv->net; - - mutex_lock(&priv->mcp_lock); - if (priv->after_suspend) { - mcp251x_hw_reset(spi); - mcp251x_setup(net, priv, spi); - if (priv->after_suspend & AFTER_SUSPEND_RESTART) { - mcp251x_set_normal_mode(spi); - } else if (priv->after_suspend & AFTER_SUSPEND_UP) { - netif_device_attach(net); - mcp251x_clean(net); - mcp251x_set_normal_mode(spi); - netif_wake_queue(net); - } else { - mcp251x_hw_sleep(spi); - } - priv->after_suspend = 0; - priv->force_quit = 0; - } - - if (priv->restart_tx) { - priv->restart_tx = 0; - mcp251x_write_reg(spi, TXBCTRL(0), 0); - mcp251x_clean(net); - netif_wake_queue(net); - mcp251x_error_skb(net, CAN_ERR_RESTARTED, 0); - } - mutex_unlock(&priv->mcp_lock); -} - -static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) -{ - struct mcp251x_priv *priv = dev_id; - struct spi_device *spi = priv->spi; - struct net_device *net = priv->net; - - mutex_lock(&priv->mcp_lock); - while (!priv->force_quit) { - enum can_state new_state; - u8 intf, eflag; - u8 clear_intf = 0; - int can_id = 0, data1 = 0; - - mcp251x_read_2regs(spi, CANINTF, &intf, &eflag); - - /* mask out flags we don't care about */ - intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR; - - /* receive buffer 0 */ - if (intf & CANINTF_RX0IF) { - mcp251x_hw_rx(spi, 0); - /* - * Free one buffer ASAP - * (The MCP2515 does this automatically.) - */ - if (mcp251x_is_2510(spi)) - mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); - } - - /* 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; - } - - /* any error or tx interrupt we need to clear? */ - if (intf & (CANINTF_ERR | CANINTF_TX)) - clear_intf |= intf & (CANINTF_ERR | CANINTF_TX); - if (clear_intf) - mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00); - - if (eflag) - mcp251x_write_bits(spi, EFLG, eflag, 0x00); - - /* Update can state */ - if (eflag & EFLG_TXBO) { - new_state = CAN_STATE_BUS_OFF; - can_id |= CAN_ERR_BUSOFF; - } else if (eflag & EFLG_TXEP) { - new_state = CAN_STATE_ERROR_PASSIVE; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_TX_PASSIVE; - } else if (eflag & EFLG_RXEP) { - new_state = CAN_STATE_ERROR_PASSIVE; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_RX_PASSIVE; - } else if (eflag & EFLG_TXWAR) { - new_state = CAN_STATE_ERROR_WARNING; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_TX_WARNING; - } else if (eflag & EFLG_RXWAR) { - new_state = CAN_STATE_ERROR_WARNING; - can_id |= CAN_ERR_CRTL; - data1 |= CAN_ERR_CRTL_RX_WARNING; - } else { - new_state = CAN_STATE_ERROR_ACTIVE; - } - - /* Update can state statistics */ - switch (priv->can.state) { - case CAN_STATE_ERROR_ACTIVE: - if (new_state >= CAN_STATE_ERROR_WARNING && - new_state <= CAN_STATE_BUS_OFF) - priv->can.can_stats.error_warning++; - case CAN_STATE_ERROR_WARNING: /* fallthrough */ - if (new_state >= CAN_STATE_ERROR_PASSIVE && - new_state <= CAN_STATE_BUS_OFF) - priv->can.can_stats.error_passive++; - break; - default: - break; - } - priv->can.state = new_state; - - if (intf & CANINTF_ERRIF) { - /* Handle overflow counters */ - if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { - if (eflag & EFLG_RX0OVR) { - net->stats.rx_over_errors++; - 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; - } - mcp251x_error_skb(net, can_id, data1); - } - - if (priv->can.state == CAN_STATE_BUS_OFF) { - if (priv->can.restart_ms == 0) { - priv->force_quit = 1; - can_bus_off(net); - mcp251x_hw_sleep(spi); - break; - } - } - - if (intf == 0) - break; - - if (intf & CANINTF_TX) { - net->stats.tx_packets++; - net->stats.tx_bytes += priv->tx_len - 1; - can_led_event(net, CAN_LED_EVENT_TX); - if (priv->tx_len) { - can_get_echo_skb(net, 0); - priv->tx_len = 0; - } - netif_wake_queue(net); - } - - } - mutex_unlock(&priv->mcp_lock); - return IRQ_HANDLED; -} - -static int mcp251x_open(struct net_device *net) -{ - struct mcp251x_priv *priv = netdev_priv(net); - struct spi_device *spi = priv->spi; - unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_FALLING; - int ret; - - ret = open_candev(net); - if (ret) { - dev_err(&spi->dev, "unable to set initial baudrate!\n"); - return ret; - } - - mutex_lock(&priv->mcp_lock); - mcp251x_power_enable(priv->transceiver, 1); - - priv->force_quit = 0; - priv->tx_skb = NULL; - priv->tx_len = 0; - - ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist, - flags, DEVICE_NAME, priv); - if (ret) { - dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); - mcp251x_power_enable(priv->transceiver, 0); - close_candev(net); - goto open_unlock; - } - - priv->wq = create_freezable_workqueue("mcp251x_wq"); - INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); - INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); - - ret = mcp251x_hw_reset(spi); - if (ret) { - mcp251x_open_clean(net); - goto open_unlock; - } - ret = mcp251x_setup(net, priv, spi); - if (ret) { - mcp251x_open_clean(net); - goto open_unlock; - } - ret = mcp251x_set_normal_mode(spi); - if (ret) { - mcp251x_open_clean(net); - goto open_unlock; - } - - can_led_event(net, CAN_LED_EVENT_OPEN); - - netif_wake_queue(net); - -open_unlock: - mutex_unlock(&priv->mcp_lock); - return ret; -} - -static const struct net_device_ops mcp251x_netdev_ops = { - .ndo_open = mcp251x_open, - .ndo_stop = mcp251x_stop, - .ndo_start_xmit = mcp251x_hard_start_xmit, - .ndo_change_mtu = can_change_mtu, -}; - -static const struct of_device_id mcp251x_of_match[] = { - { - .compatible = "microchip,mcp2510", - .data = (void *)CAN_MCP251X_MCP2510, - }, - { - .compatible = "microchip,mcp2515", - .data = (void *)CAN_MCP251X_MCP2515, - }, - { } -}; -MODULE_DEVICE_TABLE(of, mcp251x_of_match); - -static const struct spi_device_id mcp251x_id_table[] = { - { - .name = "mcp2510", - .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2510, - }, - { - .name = "mcp2515", - .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515, - }, - { } -}; -MODULE_DEVICE_TABLE(spi, mcp251x_id_table); - -static int mcp251x_can_probe(struct spi_device *spi) -{ - const struct of_device_id *of_id = of_match_device(mcp251x_of_match, - &spi->dev); - struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); - struct net_device *net; - struct mcp251x_priv *priv; - struct clk *clk; - int freq, ret; - - clk = devm_clk_get(&spi->dev, NULL); - if (IS_ERR(clk)) { - if (pdata) - freq = pdata->oscillator_frequency; - else - return PTR_ERR(clk); - } else { - freq = clk_get_rate(clk); - } - - /* Sanity check */ - if (freq < 1000000 || freq > 25000000) - return -ERANGE; - - /* Allocate can/net device */ - net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); - if (!net) - return -ENOMEM; - - if (!IS_ERR(clk)) { - ret = clk_prepare_enable(clk); - if (ret) - goto out_free; - } - - net->netdev_ops = &mcp251x_netdev_ops; - net->flags |= IFF_ECHO; - - priv = netdev_priv(net); - priv->can.bittiming_const = &mcp251x_bittiming_const; - priv->can.do_set_mode = mcp251x_do_set_mode; - priv->can.clock.freq = freq / 2; - priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | - CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; - if (of_id) - priv->model = (enum mcp251x_model)of_id->data; - else - priv->model = spi_get_device_id(spi)->driver_data; - priv->net = net; - priv->clk = clk; - - spi_set_drvdata(spi, priv); - - /* Configure the SPI bus */ - spi->bits_per_word = 8; - if (mcp251x_is_2510(spi)) - spi->max_speed_hz = spi->max_speed_hz ? : 5 * 1000 * 1000; - else - spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000; - ret = spi_setup(spi); - if (ret) - goto out_clk; - - priv->power = devm_regulator_get(&spi->dev, "vdd"); - priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); - if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || - (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { - ret = -EPROBE_DEFER; - goto out_clk; - } - - ret = mcp251x_power_enable(priv->power, 1); - if (ret) - goto out_clk; - - priv->spi = spi; - mutex_init(&priv->mcp_lock); - - /* If requested, allocate DMA buffers */ - if (mcp251x_enable_dma) { - spi->dev.coherent_dma_mask = ~0; - - /* - * Minimum coherent DMA allocation is PAGE_SIZE, so allocate - * that much and share it between Tx and Rx DMA buffers. - */ - priv->spi_tx_buf = dma_alloc_coherent(&spi->dev, - PAGE_SIZE, - &priv->spi_tx_dma, - GFP_DMA); - - if (priv->spi_tx_buf) { - priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2)); - priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma + - (PAGE_SIZE / 2)); - } else { - /* Fall back to non-DMA */ - mcp251x_enable_dma = 0; - } - } - - /* Allocate non-DMA buffers */ - if (!mcp251x_enable_dma) { - priv->spi_tx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, - GFP_KERNEL); - if (!priv->spi_tx_buf) { - ret = -ENOMEM; - goto error_probe; - } - priv->spi_rx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, - GFP_KERNEL); - if (!priv->spi_rx_buf) { - ret = -ENOMEM; - goto error_probe; - } - } - - SET_NETDEV_DEV(net, &spi->dev); - - /* Here is OK to not lock the MCP, no one knows about it yet */ - ret = mcp251x_hw_probe(spi); - if (ret) - goto error_probe; - - mcp251x_hw_sleep(spi); - - ret = register_candev(net); - if (ret) - goto error_probe; - - devm_can_led_init(net); - - return 0; - -error_probe: - if (mcp251x_enable_dma) - dma_free_coherent(&spi->dev, PAGE_SIZE, - priv->spi_tx_buf, priv->spi_tx_dma); - mcp251x_power_enable(priv->power, 0); - -out_clk: - if (!IS_ERR(clk)) - clk_disable_unprepare(clk); - -out_free: - free_candev(net); - - return ret; -} - -static int mcp251x_can_remove(struct spi_device *spi) -{ - struct mcp251x_priv *priv = spi_get_drvdata(spi); - struct net_device *net = priv->net; - - unregister_candev(net); - - if (mcp251x_enable_dma) { - dma_free_coherent(&spi->dev, PAGE_SIZE, - priv->spi_tx_buf, priv->spi_tx_dma); - } - - mcp251x_power_enable(priv->power, 0); - - if (!IS_ERR(priv->clk)) - clk_disable_unprepare(priv->clk); - - free_candev(net); - - return 0; -} - -static int __maybe_unused mcp251x_can_suspend(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct mcp251x_priv *priv = spi_get_drvdata(spi); - struct net_device *net = priv->net; - - priv->force_quit = 1; - disable_irq(spi->irq); - /* - * Note: at this point neither IST nor workqueues are running. - * open/stop cannot be called anyway so locking is not needed - */ - if (netif_running(net)) { - netif_device_detach(net); - - mcp251x_hw_sleep(spi); - mcp251x_power_enable(priv->transceiver, 0); - priv->after_suspend = AFTER_SUSPEND_UP; - } else { - priv->after_suspend = AFTER_SUSPEND_DOWN; - } - - if (!IS_ERR_OR_NULL(priv->power)) { - regulator_disable(priv->power); - priv->after_suspend |= AFTER_SUSPEND_POWER; - } - - return 0; -} - -static int __maybe_unused mcp251x_can_resume(struct device *dev) -{ - struct spi_device *spi = to_spi_device(dev); - struct mcp251x_priv *priv = spi_get_drvdata(spi); - - if (priv->after_suspend & AFTER_SUSPEND_POWER) { - mcp251x_power_enable(priv->power, 1); - queue_work(priv->wq, &priv->restart_work); - } else { - if (priv->after_suspend & AFTER_SUSPEND_UP) { - mcp251x_power_enable(priv->transceiver, 1); - queue_work(priv->wq, &priv->restart_work); - } else { - priv->after_suspend = 0; - } - } - priv->force_quit = 0; - enable_irq(spi->irq); - return 0; -} - -static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend, - mcp251x_can_resume); - -static struct spi_driver mcp251x_can_driver = { - .driver = { - .name = DEVICE_NAME, - .owner = THIS_MODULE, - .of_match_table = mcp251x_of_match, - .pm = &mcp251x_can_pm_ops, - }, - .id_table = mcp251x_id_table, - .probe = mcp251x_can_probe, - .remove = mcp251x_can_remove, -}; -module_spi_driver(mcp251x_can_driver); - -MODULE_AUTHOR("Chris Elston , " - "Christian Pellegrin "); -MODULE_DESCRIPTION("Microchip 251x CAN driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig new file mode 100644 index 000000000000..148cae5871a6 --- /dev/null +++ b/drivers/net/can/spi/Kconfig @@ -0,0 +1,10 @@ +menu "CAN SPI interfaces" + depends on SPI + +config CAN_MCP251X + tristate "Microchip MCP251x SPI CAN controllers" + depends on HAS_DMA + ---help--- + Driver for the Microchip MCP251x SPI CAN controllers. + +endmenu diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile new file mode 100644 index 000000000000..90bcacffbc65 --- /dev/null +++ b/drivers/net/can/spi/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Linux Controller Area Network SPI drivers. +# + + +obj-$(CONFIG_CAN_MCP251X) += mcp251x.o + +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c new file mode 100644 index 000000000000..bc235f9dc754 --- /dev/null +++ b/drivers/net/can/spi/mcp251x.c @@ -0,0 +1,1266 @@ +/* + * CAN bus driver for Microchip 251x CAN Controller with SPI Interface + * + * MCP2510 support and bug fixes by Christian Pellegrin + * + * + * Copyright 2009 Christian Pellegrin EVOL S.r.l. + * + * Copyright 2007 Raymarine UK, Ltd. All Rights Reserved. + * Written under contract by: + * Chris Elston, Katalix Systems, Ltd. + * + * Based on Microchip MCP251x CAN controller driver written by + * David Vrabel, Copyright 2006 Arcom Control Systems Ltd. + * + * Based on CAN bus driver for the CCAN controller written by + * - Sascha Hauer, Marc Kleine-Budde, Pengutronix + * - Simon Kallweit, intefo AG + * Copyright 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * + * + * Your platform definition file should specify something like: + * + * static struct mcp251x_platform_data mcp251x_info = { + * .oscillator_frequency = 8000000, + * }; + * + * static struct spi_board_info spi_board_info[] = { + * { + * .modalias = "mcp2510", + * // or "mcp2515" depending on your controller + * .platform_data = &mcp251x_info, + * .irq = IRQ_EINT13, + * .max_speed_hz = 2*1000*1000, + * .chip_select = 2, + * }, + * }; + * + * Please see mcp251x.h for a description of the fields in + * struct mcp251x_platform_data. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* SPI interface instruction set */ +#define INSTRUCTION_WRITE 0x02 +#define INSTRUCTION_READ 0x03 +#define INSTRUCTION_BIT_MODIFY 0x05 +#define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) +#define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) +#define INSTRUCTION_RESET 0xC0 +#define RTS_TXB0 0x01 +#define RTS_TXB1 0x02 +#define RTS_TXB2 0x04 +#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) + + +/* MPC251x registers */ +#define CANSTAT 0x0e +#define CANCTRL 0x0f +# define CANCTRL_REQOP_MASK 0xe0 +# define CANCTRL_REQOP_CONF 0x80 +# define CANCTRL_REQOP_LISTEN_ONLY 0x60 +# define CANCTRL_REQOP_LOOPBACK 0x40 +# define CANCTRL_REQOP_SLEEP 0x20 +# define CANCTRL_REQOP_NORMAL 0x00 +# define CANCTRL_OSM 0x08 +# define CANCTRL_ABAT 0x10 +#define TEC 0x1c +#define REC 0x1d +#define CNF1 0x2a +# define CNF1_SJW_SHIFT 6 +#define CNF2 0x29 +# define CNF2_BTLMODE 0x80 +# define CNF2_SAM 0x40 +# define CNF2_PS1_SHIFT 3 +#define CNF3 0x28 +# define CNF3_SOF 0x08 +# define CNF3_WAKFIL 0x04 +# define CNF3_PHSEG2_MASK 0x07 +#define CANINTE 0x2b +# define CANINTE_MERRE 0x80 +# define CANINTE_WAKIE 0x40 +# define CANINTE_ERRIE 0x20 +# define CANINTE_TX2IE 0x10 +# define CANINTE_TX1IE 0x08 +# define CANINTE_TX0IE 0x04 +# define CANINTE_RX1IE 0x02 +# define CANINTE_RX0IE 0x01 +#define CANINTF 0x2c +# define CANINTF_MERRF 0x80 +# define CANINTF_WAKIF 0x40 +# define CANINTF_ERRIF 0x20 +# define CANINTF_TX2IF 0x10 +# define CANINTF_TX1IF 0x08 +# define CANINTF_TX0IF 0x04 +# define CANINTF_RX1IF 0x02 +# define CANINTF_RX0IF 0x01 +# define CANINTF_RX (CANINTF_RX0IF | CANINTF_RX1IF) +# define CANINTF_TX (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF) +# define CANINTF_ERR (CANINTF_ERRIF) +#define EFLG 0x2d +# define EFLG_EWARN 0x01 +# define EFLG_RXWAR 0x02 +# define EFLG_TXWAR 0x04 +# define EFLG_RXEP 0x08 +# define EFLG_TXEP 0x10 +# define EFLG_TXBO 0x20 +# define EFLG_RX0OVR 0x40 +# define EFLG_RX1OVR 0x80 +#define TXBCTRL(n) (((n) * 0x10) + 0x30 + TXBCTRL_OFF) +# define TXBCTRL_ABTF 0x40 +# define TXBCTRL_MLOA 0x20 +# define TXBCTRL_TXERR 0x10 +# define TXBCTRL_TXREQ 0x08 +#define TXBSIDH(n) (((n) * 0x10) + 0x30 + TXBSIDH_OFF) +# define SIDH_SHIFT 3 +#define TXBSIDL(n) (((n) * 0x10) + 0x30 + TXBSIDL_OFF) +# define SIDL_SID_MASK 7 +# define SIDL_SID_SHIFT 5 +# define SIDL_EXIDE_SHIFT 3 +# define SIDL_EID_SHIFT 16 +# define SIDL_EID_MASK 3 +#define TXBEID8(n) (((n) * 0x10) + 0x30 + TXBEID8_OFF) +#define TXBEID0(n) (((n) * 0x10) + 0x30 + TXBEID0_OFF) +#define TXBDLC(n) (((n) * 0x10) + 0x30 + TXBDLC_OFF) +# define DLC_RTR_SHIFT 6 +#define TXBCTRL_OFF 0 +#define TXBSIDH_OFF 1 +#define TXBSIDL_OFF 2 +#define TXBEID8_OFF 3 +#define TXBEID0_OFF 4 +#define TXBDLC_OFF 5 +#define TXBDAT_OFF 6 +#define RXBCTRL(n) (((n) * 0x10) + 0x60 + RXBCTRL_OFF) +# define RXBCTRL_BUKT 0x04 +# define RXBCTRL_RXM0 0x20 +# define RXBCTRL_RXM1 0x40 +#define RXBSIDH(n) (((n) * 0x10) + 0x60 + RXBSIDH_OFF) +# define RXBSIDH_SHIFT 3 +#define RXBSIDL(n) (((n) * 0x10) + 0x60 + RXBSIDL_OFF) +# define RXBSIDL_IDE 0x08 +# define RXBSIDL_SRR 0x10 +# define RXBSIDL_EID 3 +# define RXBSIDL_SHIFT 5 +#define RXBEID8(n) (((n) * 0x10) + 0x60 + RXBEID8_OFF) +#define RXBEID0(n) (((n) * 0x10) + 0x60 + RXBEID0_OFF) +#define RXBDLC(n) (((n) * 0x10) + 0x60 + RXBDLC_OFF) +# define RXBDLC_LEN_MASK 0x0f +# define RXBDLC_RTR 0x40 +#define RXBCTRL_OFF 0 +#define RXBSIDH_OFF 1 +#define RXBSIDL_OFF 2 +#define RXBEID8_OFF 3 +#define RXBEID0_OFF 4 +#define RXBDLC_OFF 5 +#define RXBDAT_OFF 6 +#define RXFSIDH(n) ((n) * 4) +#define RXFSIDL(n) ((n) * 4 + 1) +#define RXFEID8(n) ((n) * 4 + 2) +#define RXFEID0(n) ((n) * 4 + 3) +#define RXMSIDH(n) ((n) * 4 + 0x20) +#define RXMSIDL(n) ((n) * 4 + 0x21) +#define RXMEID8(n) ((n) * 4 + 0x22) +#define RXMEID0(n) ((n) * 4 + 0x23) + +#define GET_BYTE(val, byte) \ + (((val) >> ((byte) * 8)) & 0xff) +#define SET_BYTE(val, byte) \ + (((val) & 0xff) << ((byte) * 8)) + +/* + * Buffer size required for the largest SPI transfer (i.e., reading a + * frame) + */ +#define CAN_FRAME_MAX_DATA_LEN 8 +#define SPI_TRANSFER_BUF_LEN (6 + CAN_FRAME_MAX_DATA_LEN) +#define CAN_FRAME_MAX_BITS 128 + +#define TX_ECHO_SKB_MAX 1 + +#define MCP251X_OST_DELAY_MS (5) + +#define DEVICE_NAME "mcp251x" + +static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */ +module_param(mcp251x_enable_dma, int, S_IRUGO); +MODULE_PARM_DESC(mcp251x_enable_dma, "Enable SPI DMA. Default: 0 (Off)"); + +static const struct can_bittiming_const mcp251x_bittiming_const = { + .name = DEVICE_NAME, + .tseg1_min = 3, + .tseg1_max = 16, + .tseg2_min = 2, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .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 */ + + u8 *spi_tx_buf; + u8 *spi_rx_buf; + dma_addr_t spi_tx_dma; + dma_addr_t spi_rx_dma; + + struct sk_buff *tx_skb; + int tx_len; + + struct workqueue_struct *wq; + struct work_struct tx_work; + struct work_struct restart_work; + + int force_quit; + int after_suspend; +#define AFTER_SUSPEND_UP 1 +#define AFTER_SUSPEND_DOWN 2 +#define AFTER_SUSPEND_POWER 4 +#define AFTER_SUSPEND_RESTART 8 + int restart_tx; + struct regulator *power; + struct regulator *transceiver; + struct clk *clk; +}; + +#define MCP251X_IS(_model) \ +static inline int mcp251x_is_##_model(struct spi_device *spi) \ +{ \ + struct mcp251x_priv *priv = spi_get_drvdata(spi); \ + 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); + + if (priv->tx_skb || priv->tx_len) + net->stats.tx_errors++; + if (priv->tx_skb) + dev_kfree_skb(priv->tx_skb); + if (priv->tx_len) + can_free_echo_skb(priv->net, 0); + priv->tx_skb = NULL; + priv->tx_len = 0; +} + +/* + * Note about handling of error return of mcp251x_spi_trans: accessing + * registers via SPI is not really different conceptually than using + * normal I/O assembler instructions, although it's much more + * complicated from a practical POV. So it's not advisable to always + * check the return value of this function. Imagine that every + * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0) + * error();", it would be a great mess (well there are some situation + * when exception handling C++ like could be useful after all). So we + * just check that transfers are OK at the beginning of our + * conversation with the chip and to avoid doing really nasty things + * (like injecting bogus packets in the network stack). + */ +static int mcp251x_spi_trans(struct spi_device *spi, int len) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + struct spi_transfer t = { + .tx_buf = priv->spi_tx_buf, + .rx_buf = priv->spi_rx_buf, + .len = len, + .cs_change = 0, + }; + struct spi_message m; + int ret; + + spi_message_init(&m); + + if (mcp251x_enable_dma) { + t.tx_dma = priv->spi_tx_dma; + t.rx_dma = priv->spi_rx_dma; + m.is_dma_mapped = 1; + } + + spi_message_add_tail(&t, &m); + + ret = spi_sync(spi, &m); + if (ret) + dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret); + return ret; +} + +static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + u8 val = 0; + + priv->spi_tx_buf[0] = INSTRUCTION_READ; + priv->spi_tx_buf[1] = reg; + + mcp251x_spi_trans(spi, 3); + val = priv->spi_rx_buf[2]; + + return val; +} + +static void mcp251x_read_2regs(struct spi_device *spi, uint8_t reg, + uint8_t *v1, uint8_t *v2) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + + 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 = spi_get_drvdata(spi); + + priv->spi_tx_buf[0] = INSTRUCTION_WRITE; + priv->spi_tx_buf[1] = reg; + priv->spi_tx_buf[2] = val; + + mcp251x_spi_trans(spi, 3); +} + +static void mcp251x_write_bits(struct spi_device *spi, u8 reg, + u8 mask, uint8_t val) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + + priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY; + priv->spi_tx_buf[1] = reg; + priv->spi_tx_buf[2] = mask; + priv->spi_tx_buf[3] = val; + + mcp251x_spi_trans(spi, 4); +} + +static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, + int len, int tx_buf_idx) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + + if (mcp251x_is_2510(spi)) { + int i; + + for (i = 1; i < TXBDAT_OFF + len; i++) + mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + i, + buf[i]); + } else { + memcpy(priv->spi_tx_buf, buf, TXBDAT_OFF + len); + mcp251x_spi_trans(spi, TXBDAT_OFF + len); + } +} + +static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, + int tx_buf_idx) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + u32 sid, eid, exide, rtr; + u8 buf[SPI_TRANSFER_BUF_LEN]; + + exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; /* Extended ID Enable */ + if (exide) + sid = (frame->can_id & CAN_EFF_MASK) >> 18; + else + sid = frame->can_id & CAN_SFF_MASK; /* Standard ID */ + eid = frame->can_id & CAN_EFF_MASK; /* Extended ID */ + rtr = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; /* Remote transmission */ + + buf[TXBCTRL_OFF] = INSTRUCTION_LOAD_TXB(tx_buf_idx); + buf[TXBSIDH_OFF] = sid >> SIDH_SHIFT; + buf[TXBSIDL_OFF] = ((sid & SIDL_SID_MASK) << SIDL_SID_SHIFT) | + (exide << SIDL_EXIDE_SHIFT) | + ((eid >> SIDL_EID_SHIFT) & SIDL_EID_MASK); + buf[TXBEID8_OFF] = GET_BYTE(eid, 1); + buf[TXBEID0_OFF] = GET_BYTE(eid, 0); + buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; + memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); + mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); + + /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); + mcp251x_spi_trans(priv->spi, 1); +} + +static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, + int buf_idx) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + + if (mcp251x_is_2510(spi)) { + int i, len; + + for (i = 1; i < RXBDAT_OFF; i++) + buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); + + len = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK); + for (; i < (RXBDAT_OFF + len); i++) + buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); + } else { + priv->spi_tx_buf[RXBCTRL_OFF] = INSTRUCTION_READ_RXB(buf_idx); + mcp251x_spi_trans(spi, SPI_TRANSFER_BUF_LEN); + memcpy(buf, priv->spi_rx_buf, SPI_TRANSFER_BUF_LEN); + } +} + +static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + struct sk_buff *skb; + struct can_frame *frame; + u8 buf[SPI_TRANSFER_BUF_LEN]; + + skb = alloc_can_skb(priv->net, &frame); + if (!skb) { + dev_err(&spi->dev, "cannot allocate RX skb\n"); + priv->net->stats.rx_dropped++; + return; + } + + mcp251x_hw_rx_frame(spi, buf, buf_idx); + if (buf[RXBSIDL_OFF] & RXBSIDL_IDE) { + /* Extended ID format */ + frame->can_id = CAN_EFF_FLAG; + frame->can_id |= + /* Extended ID part */ + SET_BYTE(buf[RXBSIDL_OFF] & RXBSIDL_EID, 2) | + SET_BYTE(buf[RXBEID8_OFF], 1) | + SET_BYTE(buf[RXBEID0_OFF], 0) | + /* Standard ID part */ + (((buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | + (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT)) << 18); + /* Remote transmission request */ + if (buf[RXBDLC_OFF] & RXBDLC_RTR) + frame->can_id |= CAN_RTR_FLAG; + } else { + /* Standard ID format */ + frame->can_id = + (buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | + (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT); + if (buf[RXBSIDL_OFF] & RXBSIDL_SRR) + frame->can_id |= CAN_RTR_FLAG; + } + /* Data length */ + frame->can_dlc = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK); + memcpy(frame->data, buf + RXBDAT_OFF, frame->can_dlc); + + priv->net->stats.rx_packets++; + priv->net->stats.rx_bytes += frame->can_dlc; + + can_led_event(priv->net, CAN_LED_EVENT_RX); + + netif_rx_ni(skb); +} + +static void mcp251x_hw_sleep(struct spi_device *spi) +{ + mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP); +} + +static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, + struct net_device *net) +{ + struct mcp251x_priv *priv = netdev_priv(net); + struct spi_device *spi = priv->spi; + + if (priv->tx_skb || priv->tx_len) { + dev_warn(&spi->dev, "hard_xmit called while tx busy\n"); + return NETDEV_TX_BUSY; + } + + if (can_dropped_invalid_skb(net, skb)) + return NETDEV_TX_OK; + + netif_stop_queue(net); + priv->tx_skb = skb; + queue_work(priv->wq, &priv->tx_work); + + return NETDEV_TX_OK; +} + +static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode) +{ + struct mcp251x_priv *priv = netdev_priv(net); + + switch (mode) { + case CAN_MODE_START: + mcp251x_clean(net); + /* We have to delay work since SPI I/O may sleep */ + priv->can.state = CAN_STATE_ERROR_ACTIVE; + priv->restart_tx = 1; + if (priv->can.restart_ms == 0) + priv->after_suspend = AFTER_SUSPEND_RESTART; + queue_work(priv->wq, &priv->restart_work); + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int mcp251x_set_normal_mode(struct spi_device *spi) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + unsigned long timeout; + + /* Enable interrupts */ + mcp251x_write_reg(spi, CANINTE, + CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE | + CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE); + + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { + /* Put device into loopback mode */ + mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK); + } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { + /* Put device into listen-only mode */ + mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY); + } else { + /* Put device into normal mode */ + mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL); + + /* Wait for the device to enter normal mode */ + timeout = jiffies + HZ; + while (mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) { + schedule(); + if (time_after(jiffies, timeout)) { + dev_err(&spi->dev, "MCP251x didn't" + " enter in normal mode\n"); + return -EBUSY; + } + } + } + priv->can.state = CAN_STATE_ERROR_ACTIVE; + return 0; +} + +static int mcp251x_do_set_bittiming(struct net_device *net) +{ + struct mcp251x_priv *priv = netdev_priv(net); + struct can_bittiming *bt = &priv->can.bittiming; + struct spi_device *spi = priv->spi; + + mcp251x_write_reg(spi, CNF1, ((bt->sjw - 1) << CNF1_SJW_SHIFT) | + (bt->brp - 1)); + mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | + (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ? + CNF2_SAM : 0) | + ((bt->phase_seg1 - 1) << CNF2_PS1_SHIFT) | + (bt->prop_seg - 1)); + mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, + (bt->phase_seg2 - 1)); + dev_dbg(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n", + mcp251x_read_reg(spi, CNF1), + mcp251x_read_reg(spi, CNF2), + mcp251x_read_reg(spi, CNF3)); + + return 0; +} + +static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv, + struct spi_device *spi) +{ + mcp251x_do_set_bittiming(net); + + mcp251x_write_reg(spi, RXBCTRL(0), + RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1); + mcp251x_write_reg(spi, RXBCTRL(1), + RXBCTRL_RXM0 | RXBCTRL_RXM1); + return 0; +} + +static int mcp251x_hw_reset(struct spi_device *spi) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + u8 reg; + int ret; + + /* Wait for oscillator startup timer after power up */ + mdelay(MCP251X_OST_DELAY_MS); + + priv->spi_tx_buf[0] = INSTRUCTION_RESET; + ret = mcp251x_spi_trans(spi, 1); + if (ret) + return ret; + + /* Wait for oscillator startup timer after reset */ + mdelay(MCP251X_OST_DELAY_MS); + + reg = mcp251x_read_reg(spi, CANSTAT); + if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) + return -ENODEV; + + return 0; +} + +static int mcp251x_hw_probe(struct spi_device *spi) +{ + u8 ctrl; + int ret; + + ret = mcp251x_hw_reset(spi); + if (ret) + return ret; + + ctrl = mcp251x_read_reg(spi, CANCTRL); + + dev_dbg(&spi->dev, "CANCTRL 0x%02x\n", ctrl); + + /* Check for power up default value */ + if ((ctrl & 0x17) != 0x07) + return -ENODEV; + + return 0; +} + +static int mcp251x_power_enable(struct regulator *reg, int enable) +{ + if (IS_ERR_OR_NULL(reg)) + return 0; + + if (enable) + return regulator_enable(reg); + else + return regulator_disable(reg); +} + +static void mcp251x_open_clean(struct net_device *net) +{ + struct mcp251x_priv *priv = netdev_priv(net); + struct spi_device *spi = priv->spi; + + free_irq(spi->irq, priv); + mcp251x_hw_sleep(spi); + mcp251x_power_enable(priv->transceiver, 0); + close_candev(net); +} + +static int mcp251x_stop(struct net_device *net) +{ + struct mcp251x_priv *priv = netdev_priv(net); + struct spi_device *spi = priv->spi; + + close_candev(net); + + priv->force_quit = 1; + free_irq(spi->irq, priv); + destroy_workqueue(priv->wq); + priv->wq = NULL; + + mutex_lock(&priv->mcp_lock); + + /* Disable and clear pending interrupts */ + mcp251x_write_reg(spi, CANINTE, 0x00); + mcp251x_write_reg(spi, CANINTF, 0x00); + + mcp251x_write_reg(spi, TXBCTRL(0), 0); + mcp251x_clean(net); + + mcp251x_hw_sleep(spi); + + mcp251x_power_enable(priv->transceiver, 0); + + priv->can.state = CAN_STATE_STOPPED; + + mutex_unlock(&priv->mcp_lock); + + can_led_event(net, CAN_LED_EVENT_STOP); + + return 0; +} + +static void mcp251x_error_skb(struct net_device *net, int can_id, int data1) +{ + struct sk_buff *skb; + struct can_frame *frame; + + skb = alloc_can_err_skb(net, &frame); + if (skb) { + frame->can_id |= can_id; + frame->data[1] = data1; + netif_rx_ni(skb); + } else { + netdev_err(net, "cannot allocate error skb\n"); + } +} + +static void mcp251x_tx_work_handler(struct work_struct *ws) +{ + struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, + tx_work); + struct spi_device *spi = priv->spi; + struct net_device *net = priv->net; + struct can_frame *frame; + + mutex_lock(&priv->mcp_lock); + if (priv->tx_skb) { + if (priv->can.state == CAN_STATE_BUS_OFF) { + mcp251x_clean(net); + } else { + frame = (struct can_frame *)priv->tx_skb->data; + + if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN) + frame->can_dlc = CAN_FRAME_MAX_DATA_LEN; + mcp251x_hw_tx(spi, frame, 0); + priv->tx_len = 1 + frame->can_dlc; + can_put_echo_skb(priv->tx_skb, net, 0); + priv->tx_skb = NULL; + } + } + mutex_unlock(&priv->mcp_lock); +} + +static void mcp251x_restart_work_handler(struct work_struct *ws) +{ + struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, + restart_work); + struct spi_device *spi = priv->spi; + struct net_device *net = priv->net; + + mutex_lock(&priv->mcp_lock); + if (priv->after_suspend) { + mcp251x_hw_reset(spi); + mcp251x_setup(net, priv, spi); + if (priv->after_suspend & AFTER_SUSPEND_RESTART) { + mcp251x_set_normal_mode(spi); + } else if (priv->after_suspend & AFTER_SUSPEND_UP) { + netif_device_attach(net); + mcp251x_clean(net); + mcp251x_set_normal_mode(spi); + netif_wake_queue(net); + } else { + mcp251x_hw_sleep(spi); + } + priv->after_suspend = 0; + priv->force_quit = 0; + } + + if (priv->restart_tx) { + priv->restart_tx = 0; + mcp251x_write_reg(spi, TXBCTRL(0), 0); + mcp251x_clean(net); + netif_wake_queue(net); + mcp251x_error_skb(net, CAN_ERR_RESTARTED, 0); + } + mutex_unlock(&priv->mcp_lock); +} + +static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) +{ + struct mcp251x_priv *priv = dev_id; + struct spi_device *spi = priv->spi; + struct net_device *net = priv->net; + + mutex_lock(&priv->mcp_lock); + while (!priv->force_quit) { + enum can_state new_state; + u8 intf, eflag; + u8 clear_intf = 0; + int can_id = 0, data1 = 0; + + mcp251x_read_2regs(spi, CANINTF, &intf, &eflag); + + /* mask out flags we don't care about */ + intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR; + + /* receive buffer 0 */ + if (intf & CANINTF_RX0IF) { + mcp251x_hw_rx(spi, 0); + /* + * Free one buffer ASAP + * (The MCP2515 does this automatically.) + */ + if (mcp251x_is_2510(spi)) + mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); + } + + /* 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; + } + + /* any error or tx interrupt we need to clear? */ + if (intf & (CANINTF_ERR | CANINTF_TX)) + clear_intf |= intf & (CANINTF_ERR | CANINTF_TX); + if (clear_intf) + mcp251x_write_bits(spi, CANINTF, clear_intf, 0x00); + + if (eflag) + mcp251x_write_bits(spi, EFLG, eflag, 0x00); + + /* Update can state */ + if (eflag & EFLG_TXBO) { + new_state = CAN_STATE_BUS_OFF; + can_id |= CAN_ERR_BUSOFF; + } else if (eflag & EFLG_TXEP) { + new_state = CAN_STATE_ERROR_PASSIVE; + can_id |= CAN_ERR_CRTL; + data1 |= CAN_ERR_CRTL_TX_PASSIVE; + } else if (eflag & EFLG_RXEP) { + new_state = CAN_STATE_ERROR_PASSIVE; + can_id |= CAN_ERR_CRTL; + data1 |= CAN_ERR_CRTL_RX_PASSIVE; + } else if (eflag & EFLG_TXWAR) { + new_state = CAN_STATE_ERROR_WARNING; + can_id |= CAN_ERR_CRTL; + data1 |= CAN_ERR_CRTL_TX_WARNING; + } else if (eflag & EFLG_RXWAR) { + new_state = CAN_STATE_ERROR_WARNING; + can_id |= CAN_ERR_CRTL; + data1 |= CAN_ERR_CRTL_RX_WARNING; + } else { + new_state = CAN_STATE_ERROR_ACTIVE; + } + + /* Update can state statistics */ + switch (priv->can.state) { + case CAN_STATE_ERROR_ACTIVE: + if (new_state >= CAN_STATE_ERROR_WARNING && + new_state <= CAN_STATE_BUS_OFF) + priv->can.can_stats.error_warning++; + case CAN_STATE_ERROR_WARNING: /* fallthrough */ + if (new_state >= CAN_STATE_ERROR_PASSIVE && + new_state <= CAN_STATE_BUS_OFF) + priv->can.can_stats.error_passive++; + break; + default: + break; + } + priv->can.state = new_state; + + if (intf & CANINTF_ERRIF) { + /* Handle overflow counters */ + if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { + if (eflag & EFLG_RX0OVR) { + net->stats.rx_over_errors++; + 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; + } + mcp251x_error_skb(net, can_id, data1); + } + + if (priv->can.state == CAN_STATE_BUS_OFF) { + if (priv->can.restart_ms == 0) { + priv->force_quit = 1; + can_bus_off(net); + mcp251x_hw_sleep(spi); + break; + } + } + + if (intf == 0) + break; + + if (intf & CANINTF_TX) { + net->stats.tx_packets++; + net->stats.tx_bytes += priv->tx_len - 1; + can_led_event(net, CAN_LED_EVENT_TX); + if (priv->tx_len) { + can_get_echo_skb(net, 0); + priv->tx_len = 0; + } + netif_wake_queue(net); + } + + } + mutex_unlock(&priv->mcp_lock); + return IRQ_HANDLED; +} + +static int mcp251x_open(struct net_device *net) +{ + struct mcp251x_priv *priv = netdev_priv(net); + struct spi_device *spi = priv->spi; + unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_FALLING; + int ret; + + ret = open_candev(net); + if (ret) { + dev_err(&spi->dev, "unable to set initial baudrate!\n"); + return ret; + } + + mutex_lock(&priv->mcp_lock); + mcp251x_power_enable(priv->transceiver, 1); + + priv->force_quit = 0; + priv->tx_skb = NULL; + priv->tx_len = 0; + + ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist, + flags, DEVICE_NAME, priv); + if (ret) { + dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); + mcp251x_power_enable(priv->transceiver, 0); + close_candev(net); + goto open_unlock; + } + + priv->wq = create_freezable_workqueue("mcp251x_wq"); + INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); + INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); + + ret = mcp251x_hw_reset(spi); + if (ret) { + mcp251x_open_clean(net); + goto open_unlock; + } + ret = mcp251x_setup(net, priv, spi); + if (ret) { + mcp251x_open_clean(net); + goto open_unlock; + } + ret = mcp251x_set_normal_mode(spi); + if (ret) { + mcp251x_open_clean(net); + goto open_unlock; + } + + can_led_event(net, CAN_LED_EVENT_OPEN); + + netif_wake_queue(net); + +open_unlock: + mutex_unlock(&priv->mcp_lock); + return ret; +} + +static const struct net_device_ops mcp251x_netdev_ops = { + .ndo_open = mcp251x_open, + .ndo_stop = mcp251x_stop, + .ndo_start_xmit = mcp251x_hard_start_xmit, + .ndo_change_mtu = can_change_mtu, +}; + +static const struct of_device_id mcp251x_of_match[] = { + { + .compatible = "microchip,mcp2510", + .data = (void *)CAN_MCP251X_MCP2510, + }, + { + .compatible = "microchip,mcp2515", + .data = (void *)CAN_MCP251X_MCP2515, + }, + { } +}; +MODULE_DEVICE_TABLE(of, mcp251x_of_match); + +static const struct spi_device_id mcp251x_id_table[] = { + { + .name = "mcp2510", + .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2510, + }, + { + .name = "mcp2515", + .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515, + }, + { } +}; +MODULE_DEVICE_TABLE(spi, mcp251x_id_table); + +static int mcp251x_can_probe(struct spi_device *spi) +{ + const struct of_device_id *of_id = of_match_device(mcp251x_of_match, + &spi->dev); + struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev); + struct net_device *net; + struct mcp251x_priv *priv; + struct clk *clk; + int freq, ret; + + clk = devm_clk_get(&spi->dev, NULL); + if (IS_ERR(clk)) { + if (pdata) + freq = pdata->oscillator_frequency; + else + return PTR_ERR(clk); + } else { + freq = clk_get_rate(clk); + } + + /* Sanity check */ + if (freq < 1000000 || freq > 25000000) + return -ERANGE; + + /* Allocate can/net device */ + net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); + if (!net) + return -ENOMEM; + + if (!IS_ERR(clk)) { + ret = clk_prepare_enable(clk); + if (ret) + goto out_free; + } + + net->netdev_ops = &mcp251x_netdev_ops; + net->flags |= IFF_ECHO; + + priv = netdev_priv(net); + priv->can.bittiming_const = &mcp251x_bittiming_const; + priv->can.do_set_mode = mcp251x_do_set_mode; + priv->can.clock.freq = freq / 2; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; + if (of_id) + priv->model = (enum mcp251x_model)of_id->data; + else + priv->model = spi_get_device_id(spi)->driver_data; + priv->net = net; + priv->clk = clk; + + spi_set_drvdata(spi, priv); + + /* Configure the SPI bus */ + spi->bits_per_word = 8; + if (mcp251x_is_2510(spi)) + spi->max_speed_hz = spi->max_speed_hz ? : 5 * 1000 * 1000; + else + spi->max_speed_hz = spi->max_speed_hz ? : 10 * 1000 * 1000; + ret = spi_setup(spi); + if (ret) + goto out_clk; + + priv->power = devm_regulator_get(&spi->dev, "vdd"); + priv->transceiver = devm_regulator_get(&spi->dev, "xceiver"); + if ((PTR_ERR(priv->power) == -EPROBE_DEFER) || + (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) { + ret = -EPROBE_DEFER; + goto out_clk; + } + + ret = mcp251x_power_enable(priv->power, 1); + if (ret) + goto out_clk; + + priv->spi = spi; + mutex_init(&priv->mcp_lock); + + /* If requested, allocate DMA buffers */ + if (mcp251x_enable_dma) { + spi->dev.coherent_dma_mask = ~0; + + /* + * Minimum coherent DMA allocation is PAGE_SIZE, so allocate + * that much and share it between Tx and Rx DMA buffers. + */ + priv->spi_tx_buf = dma_alloc_coherent(&spi->dev, + PAGE_SIZE, + &priv->spi_tx_dma, + GFP_DMA); + + if (priv->spi_tx_buf) { + priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2)); + priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma + + (PAGE_SIZE / 2)); + } else { + /* Fall back to non-DMA */ + mcp251x_enable_dma = 0; + } + } + + /* Allocate non-DMA buffers */ + if (!mcp251x_enable_dma) { + priv->spi_tx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, + GFP_KERNEL); + if (!priv->spi_tx_buf) { + ret = -ENOMEM; + goto error_probe; + } + priv->spi_rx_buf = devm_kzalloc(&spi->dev, SPI_TRANSFER_BUF_LEN, + GFP_KERNEL); + if (!priv->spi_rx_buf) { + ret = -ENOMEM; + goto error_probe; + } + } + + SET_NETDEV_DEV(net, &spi->dev); + + /* Here is OK to not lock the MCP, no one knows about it yet */ + ret = mcp251x_hw_probe(spi); + if (ret) + goto error_probe; + + mcp251x_hw_sleep(spi); + + ret = register_candev(net); + if (ret) + goto error_probe; + + devm_can_led_init(net); + + return 0; + +error_probe: + if (mcp251x_enable_dma) + dma_free_coherent(&spi->dev, PAGE_SIZE, + priv->spi_tx_buf, priv->spi_tx_dma); + mcp251x_power_enable(priv->power, 0); + +out_clk: + if (!IS_ERR(clk)) + clk_disable_unprepare(clk); + +out_free: + free_candev(net); + + return ret; +} + +static int mcp251x_can_remove(struct spi_device *spi) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + struct net_device *net = priv->net; + + unregister_candev(net); + + if (mcp251x_enable_dma) { + dma_free_coherent(&spi->dev, PAGE_SIZE, + priv->spi_tx_buf, priv->spi_tx_dma); + } + + mcp251x_power_enable(priv->power, 0); + + if (!IS_ERR(priv->clk)) + clk_disable_unprepare(priv->clk); + + free_candev(net); + + return 0; +} + +static int __maybe_unused mcp251x_can_suspend(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct mcp251x_priv *priv = spi_get_drvdata(spi); + struct net_device *net = priv->net; + + priv->force_quit = 1; + disable_irq(spi->irq); + /* + * Note: at this point neither IST nor workqueues are running. + * open/stop cannot be called anyway so locking is not needed + */ + if (netif_running(net)) { + netif_device_detach(net); + + mcp251x_hw_sleep(spi); + mcp251x_power_enable(priv->transceiver, 0); + priv->after_suspend = AFTER_SUSPEND_UP; + } else { + priv->after_suspend = AFTER_SUSPEND_DOWN; + } + + if (!IS_ERR_OR_NULL(priv->power)) { + regulator_disable(priv->power); + priv->after_suspend |= AFTER_SUSPEND_POWER; + } + + return 0; +} + +static int __maybe_unused mcp251x_can_resume(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct mcp251x_priv *priv = spi_get_drvdata(spi); + + if (priv->after_suspend & AFTER_SUSPEND_POWER) { + mcp251x_power_enable(priv->power, 1); + queue_work(priv->wq, &priv->restart_work); + } else { + if (priv->after_suspend & AFTER_SUSPEND_UP) { + mcp251x_power_enable(priv->transceiver, 1); + queue_work(priv->wq, &priv->restart_work); + } else { + priv->after_suspend = 0; + } + } + priv->force_quit = 0; + enable_irq(spi->irq); + return 0; +} + +static SIMPLE_DEV_PM_OPS(mcp251x_can_pm_ops, mcp251x_can_suspend, + mcp251x_can_resume); + +static struct spi_driver mcp251x_can_driver = { + .driver = { + .name = DEVICE_NAME, + .owner = THIS_MODULE, + .of_match_table = mcp251x_of_match, + .pm = &mcp251x_can_pm_ops, + }, + .id_table = mcp251x_id_table, + .probe = mcp251x_can_probe, + .remove = mcp251x_can_remove, +}; +module_spi_driver(mcp251x_can_driver); + +MODULE_AUTHOR("Chris Elston , " + "Christian Pellegrin "); +MODULE_DESCRIPTION("Microchip 251x CAN driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From e59e36e7333702d1d835113ced85243bb7f30f99 Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Thu, 10 Apr 2014 21:44:21 +0200 Subject: can: kvaser_usb: add retries/timeout to kvaser_usb_wait_msg() On some Kvaser hardware, the firmware returns extra messages after the request for card info. For instance on a Leaf Light v2: --> CMD_GET_CARD_INFO <-- CMD_USB_THROTTLE <-- CMD_GET_CARD_INFO2 <-- CMD_GET_CARD_INFO_REQ When it happens, the probing function fails because we only read the first usb message. To overcome this issue, we add a mechanism of retries to the kvaser_usb_wait_msg() function. I tested this patch with the following hardware: - Kvaser Leaf Light - Kvaser Leaf Light v2 - Kvaser USBCan R This patch is necessary for the Leaf Light v2 hardware. Signed-off-by: Olivier Sobrie Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/kvaser_usb.c | 49 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 4ca46edc061d..7a1c5ec23268 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -379,38 +379,43 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id, void *buf; int actual_len; int err; - int pos = 0; + int pos; + unsigned long to = jiffies + msecs_to_jiffies(USB_RECV_TIMEOUT); buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; - err = usb_bulk_msg(dev->udev, - usb_rcvbulkpipe(dev->udev, - dev->bulk_in->bEndpointAddress), - buf, RX_BUFFER_SIZE, &actual_len, - USB_RECV_TIMEOUT); - if (err < 0) - goto end; + do { + err = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, + dev->bulk_in->bEndpointAddress), + buf, RX_BUFFER_SIZE, &actual_len, + USB_RECV_TIMEOUT); + if (err < 0) + goto end; - while (pos <= actual_len - MSG_HEADER_LEN) { - tmp = buf + pos; + pos = 0; + while (pos <= actual_len - MSG_HEADER_LEN) { + tmp = buf + pos; - if (!tmp->len) - break; + if (!tmp->len) + break; - if (pos + tmp->len > actual_len) { - dev_err(dev->udev->dev.parent, "Format error\n"); - break; - } + if (pos + tmp->len > actual_len) { + dev_err(dev->udev->dev.parent, + "Format error\n"); + break; + } - if (tmp->id == id) { - memcpy(msg, tmp, tmp->len); - goto end; - } + if (tmp->id == id) { + memcpy(msg, tmp, tmp->len); + goto end; + } - pos += tmp->len; - } + pos += tmp->len; + } + } while (time_before(jiffies, to)); err = -EINVAL; -- cgit v1.2.3 From b4f20130af23621f0d1e553db0375e7c6cb49c1f Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Thu, 10 Apr 2014 21:44:22 +0200 Subject: can: kvaser_usb: add support for Kvaser Leaf v2 and usb mini PCIe This patch adds support for the Kvaser Leaf v2 and Leaf usb mini PCIe card. Signed-off-by: Olivier Sobrie Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/kvaser_usb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 7a1c5ec23268..541fb7a05625 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -53,6 +53,8 @@ #define USB_OEM_MERCURY_PRODUCT_ID 34 #define USB_OEM_LEAF_PRODUCT_ID 35 #define USB_CAN_R_PRODUCT_ID 39 +#define USB_LEAF_LITE_V2_PRODUCT_ID 288 +#define USB_MINI_PCIE_HS_PRODUCT_ID 289 /* USB devices features */ #define KVASER_HAS_SILENT_MODE BIT(0) @@ -356,6 +358,8 @@ static const struct usb_device_id kvaser_usb_table[] = { .driver_info = KVASER_HAS_TXRX_ERRORS }, { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID), .driver_info = KVASER_HAS_TXRX_ERRORS }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_V2_PRODUCT_ID) }, + { USB_DEVICE(KVASER_VENDOR_ID, USB_MINI_PCIE_HS_PRODUCT_ID) }, { } }; MODULE_DEVICE_TABLE(usb, kvaser_usb_table); -- cgit v1.2.3 From 8e964fe21d8186d410353c295df14623a5ed8745 Mon Sep 17 00:00:00 2001 From: Olivier Sobrie Date: Thu, 10 Apr 2014 21:44:23 +0200 Subject: can: usb: Kconfig: Improve help for CAN_KVASER_USB Add two new USB devices supported by the driver and fix bad english. Signed-off-by: Olivier Sobrie Signed-off-by: Marc Kleine-Budde --- drivers/net/can/usb/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index fc96a3d83ebe..0b918ebad76b 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -19,7 +19,7 @@ config CAN_KVASER_USB This driver adds support for Kvaser CAN/USB devices like Kvaser Leaf Light. - The driver gives support for the following devices: + The driver provides support for the following devices: - Kvaser Leaf Light - Kvaser Leaf Professional HS - Kvaser Leaf SemiPro HS @@ -36,6 +36,8 @@ config CAN_KVASER_USB - Kvaser Leaf Light "China" - Kvaser BlackBird SemiPro - Kvaser USBcan R + - Kvaser Leaf Light v2 + - Kvaser Mini PCI Express HS If unsure, say N. -- cgit v1.2.3 From abcd7f750a7e978a60c745e7c41dc468949365c2 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Mon, 7 Apr 2014 08:52:03 +0200 Subject: can: c_can: Add support for eg20t (pch_can) Signed-off-by: Alexander Stein Acked-by: Wolfgang Grandegger Signed-off-by: Marc Kleine-Budde --- drivers/net/can/c_can/c_can_pci.c | 51 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index bce0be54c2f5..7ab384f59e7e 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -19,9 +19,13 @@ #include "c_can.h" +#define PCI_DEVICE_ID_PCH_CAN 0x8818 +#define PCH_PCI_SOFT_RESET 0x01fc + enum c_can_pci_reg_align { C_CAN_REG_ALIGN_16, C_CAN_REG_ALIGN_32, + C_CAN_REG_32, }; struct c_can_pci_data { @@ -31,6 +35,10 @@ struct c_can_pci_data { enum c_can_pci_reg_align reg_align; /* Set the frequency */ unsigned int freq; + /* PCI bar number */ + int bar; + /* Callback for reset */ + void (*init)(const struct c_can_priv *priv, bool enable); }; /* @@ -63,6 +71,29 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv, writew(val, priv->base + 2 * priv->regs[index]); } +static u16 c_can_pci_read_reg_32bit(struct c_can_priv *priv, + enum reg index) +{ + return (u16)ioread32(priv->base + 2 * priv->regs[index]); +} + +static void c_can_pci_write_reg_32bit(struct c_can_priv *priv, + enum reg index, u16 val) +{ + iowrite32((u32)val, priv->base + 2 * priv->regs[index]); +} + +static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable) +{ + if (enable) { + u32 __iomem *addr = priv->base + PCH_PCI_SOFT_RESET; + + /* write to sw reset register */ + iowrite32(1, addr); + iowrite32(0, addr); + } +} + static int c_can_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -87,7 +118,8 @@ static int c_can_pci_probe(struct pci_dev *pdev, pci_set_master(pdev); pci_enable_msi(pdev); - addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0)); + addr = pci_iomap(pdev, c_can_pci_data->bar, + pci_resource_len(pdev, c_can_pci_data->bar)); if (!addr) { dev_err(&pdev->dev, "device has no PCI memory resources, " @@ -142,11 +174,17 @@ static int c_can_pci_probe(struct pci_dev *pdev, priv->read_reg = c_can_pci_read_reg_aligned_to_16bit; priv->write_reg = c_can_pci_write_reg_aligned_to_16bit; break; + case C_CAN_REG_32: + priv->read_reg = c_can_pci_read_reg_32bit; + priv->write_reg = c_can_pci_write_reg_32bit; + break; default: ret = -EINVAL; goto out_free_c_can; } + priv->raminit = c_can_pci_data->init; + ret = register_c_can_dev(dev); if (ret) { dev_err(&pdev->dev, "registering %s failed (err=%d)\n", @@ -193,6 +231,15 @@ static struct c_can_pci_data c_can_sta2x11= { .type = BOSCH_C_CAN, .reg_align = C_CAN_REG_ALIGN_32, .freq = 52000000, /* 52 Mhz */ + .bar = 0, +}; + +static struct c_can_pci_data c_can_pch = { + .type = BOSCH_C_CAN, + .reg_align = C_CAN_REG_32, + .freq = 50000000, /* 50 MHz */ + .init = c_can_pci_reset_pch, + .bar = 1, }; #define C_CAN_ID(_vend, _dev, _driverdata) { \ @@ -202,6 +249,8 @@ static struct c_can_pci_data c_can_sta2x11= { static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = { C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN, c_can_sta2x11), + C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN, + c_can_pch), {}, }; static struct pci_driver c_can_pci_driver = { -- cgit v1.2.3 From ec2e11ed3faf9cf87f57031f1ed236888e2e4c64 Mon Sep 17 00:00:00 2001 From: Kurt Van Dijck Date: Wed, 2 Apr 2014 21:17:47 +0200 Subject: can: softing: drop 'channel' sysfs attribute netdev->dev_id obsoletes this property. None of the remaining properties contribute to udev detection methods. The regular calls for the sysfs group can thus safely be restored. Signed-off-by: Kurt Van Dijck Signed-off-by: Marc Kleine-Budde --- drivers/net/can/softing/softing_main.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index 7d8c8f3672dd..532330bfb30f 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -556,15 +556,6 @@ failed: /* * netdev sysfs */ -static ssize_t show_channel(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct net_device *ndev = to_net_dev(dev); - struct softing_priv *priv = netdev2softing(ndev); - - return sprintf(buf, "%i\n", priv->index); -} - static ssize_t show_chip(struct device *dev, struct device_attribute *attr, char *buf) { @@ -609,12 +600,10 @@ static ssize_t store_output(struct device *dev, struct device_attribute *attr, return count; } -static const DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL); static const DEVICE_ATTR(chip, S_IRUGO, show_chip, NULL); static const DEVICE_ATTR(output, S_IRUGO | S_IWUSR, show_output, store_output); static const struct attribute *const netdev_sysfs_attrs[] = { - &dev_attr_channel.attr, &dev_attr_chip.attr, &dev_attr_output.attr, NULL, @@ -679,17 +668,20 @@ static int softing_netdev_register(struct net_device *netdev) { int ret; - netdev->sysfs_groups[0] = &netdev_sysfs_group; ret = register_candev(netdev); if (ret) { dev_alert(&netdev->dev, "register failed\n"); return ret; } + if (sysfs_create_group(&netdev->dev.kobj, &netdev_sysfs_group) < 0) + netdev_alert(netdev, "sysfs group failed\n"); + return 0; } static void softing_netdev_cleanup(struct net_device *netdev) { + sysfs_remove_group(&netdev->dev.kobj, &netdev_sysfs_group); unregister_candev(netdev); free_candev(netdev); } -- cgit v1.2.3 From 0f8dced5ef49159698a98f744e809a3fff32b827 Mon Sep 17 00:00:00 2001 From: Kurt Van Dijck Date: Wed, 2 Apr 2014 21:17:48 +0200 Subject: can: softing: remove unused sysfs attributes 'frequency' indicates the embedded cpu's frequency, but that should not be necessary for any purpose. 'txpending' is an attribute for debugging. Signed-off-by: Kurt Van Dijck Signed-off-by: Marc Kleine-Budde --- drivers/net/can/softing/softing_main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index 532330bfb30f..bacd236ce306 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -713,8 +713,6 @@ DEV_ATTR_RO(firmware_version, id.fw_version); DEV_ATTR_RO_STR(hardware, pdat->name); DEV_ATTR_RO(hardware_version, id.hw_version); DEV_ATTR_RO(license, id.license); -DEV_ATTR_RO(frequency, id.freq); -DEV_ATTR_RO(txpending, tx.pending); static struct attribute *softing_pdev_attrs[] = { &dev_attr_serial.attr, @@ -723,8 +721,6 @@ static struct attribute *softing_pdev_attrs[] = { &dev_attr_hardware.attr, &dev_attr_hardware_version.attr, &dev_attr_license.attr, - &dev_attr_frequency.attr, - &dev_attr_txpending.attr, NULL, }; -- cgit v1.2.3