| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1 | /* | 
|  | 2 | * CAN bus driver for Microchip 251x CAN Controller with SPI Interface | 
|  | 3 | * | 
|  | 4 | * MCP2510 support and bug fixes by Christian Pellegrin | 
|  | 5 | * <chripell@evolware.org> | 
|  | 6 | * | 
|  | 7 | * Copyright 2009 Christian Pellegrin EVOL S.r.l. | 
|  | 8 | * | 
|  | 9 | * Copyright 2007 Raymarine UK, Ltd. All Rights Reserved. | 
|  | 10 | * Written under contract by: | 
|  | 11 | *   Chris Elston, Katalix Systems, Ltd. | 
|  | 12 | * | 
|  | 13 | * Based on Microchip MCP251x CAN controller driver written by | 
|  | 14 | * David Vrabel, Copyright 2006 Arcom Control Systems Ltd. | 
|  | 15 | * | 
|  | 16 | * Based on CAN bus driver for the CCAN controller written by | 
|  | 17 | * - Sascha Hauer, Marc Kleine-Budde, Pengutronix | 
|  | 18 | * - Simon Kallweit, intefo AG | 
|  | 19 | * Copyright 2007 | 
|  | 20 | * | 
|  | 21 | * This program is free software; you can redistribute it and/or modify | 
|  | 22 | * it under the terms of the version 2 of the GNU General Public License | 
|  | 23 | * as published by the Free Software Foundation | 
|  | 24 | * | 
|  | 25 | * This program is distributed in the hope that it will be useful, | 
|  | 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
|  | 28 | * GNU General Public License for more details. | 
|  | 29 | * | 
|  | 30 | * You should have received a copy of the GNU General Public License | 
|  | 31 | * along with this program; if not, write to the Free Software | 
|  | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|  | 33 | * | 
|  | 34 | * | 
|  | 35 | * | 
|  | 36 | * Your platform definition file should specify something like: | 
|  | 37 | * | 
|  | 38 | * static struct mcp251x_platform_data mcp251x_info = { | 
|  | 39 | *         .oscillator_frequency = 8000000, | 
|  | 40 | *         .board_specific_setup = &mcp251x_setup, | 
|  | 41 | *         .model = CAN_MCP251X_MCP2510, | 
|  | 42 | *         .power_enable = mcp251x_power_enable, | 
|  | 43 | *         .transceiver_enable = NULL, | 
|  | 44 | * }; | 
|  | 45 | * | 
|  | 46 | * static struct spi_board_info spi_board_info[] = { | 
|  | 47 | *         { | 
|  | 48 | *                 .modalias = "mcp251x", | 
|  | 49 | *                 .platform_data = &mcp251x_info, | 
|  | 50 | *                 .irq = IRQ_EINT13, | 
|  | 51 | *                 .max_speed_hz = 2*1000*1000, | 
|  | 52 | *                 .chip_select = 2, | 
|  | 53 | *         }, | 
|  | 54 | * }; | 
|  | 55 | * | 
|  | 56 | * Please see mcp251x.h for a description of the fields in | 
|  | 57 | * struct mcp251x_platform_data. | 
|  | 58 | * | 
|  | 59 | */ | 
|  | 60 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 61 | #include <linux/can/core.h> | 
|  | 62 | #include <linux/can/dev.h> | 
|  | 63 | #include <linux/can/platform/mcp251x.h> | 
|  | 64 | #include <linux/completion.h> | 
|  | 65 | #include <linux/delay.h> | 
|  | 66 | #include <linux/device.h> | 
|  | 67 | #include <linux/dma-mapping.h> | 
|  | 68 | #include <linux/freezer.h> | 
|  | 69 | #include <linux/interrupt.h> | 
|  | 70 | #include <linux/io.h> | 
|  | 71 | #include <linux/kernel.h> | 
|  | 72 | #include <linux/module.h> | 
|  | 73 | #include <linux/netdevice.h> | 
|  | 74 | #include <linux/platform_device.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 75 | #include <linux/slab.h> | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 76 | #include <linux/spi/spi.h> | 
|  | 77 | #include <linux/uaccess.h> | 
|  | 78 |  | 
|  | 79 | /* SPI interface instruction set */ | 
|  | 80 | #define INSTRUCTION_WRITE	0x02 | 
|  | 81 | #define INSTRUCTION_READ	0x03 | 
|  | 82 | #define INSTRUCTION_BIT_MODIFY	0x05 | 
|  | 83 | #define INSTRUCTION_LOAD_TXB(n)	(0x40 + 2 * (n)) | 
|  | 84 | #define INSTRUCTION_READ_RXB(n)	(((n) == 0) ? 0x90 : 0x94) | 
|  | 85 | #define INSTRUCTION_RESET	0xC0 | 
|  | 86 |  | 
|  | 87 | /* MPC251x registers */ | 
|  | 88 | #define CANSTAT	      0x0e | 
|  | 89 | #define CANCTRL	      0x0f | 
|  | 90 | #  define CANCTRL_REQOP_MASK	    0xe0 | 
|  | 91 | #  define CANCTRL_REQOP_CONF	    0x80 | 
|  | 92 | #  define CANCTRL_REQOP_LISTEN_ONLY 0x60 | 
|  | 93 | #  define CANCTRL_REQOP_LOOPBACK    0x40 | 
|  | 94 | #  define CANCTRL_REQOP_SLEEP	    0x20 | 
|  | 95 | #  define CANCTRL_REQOP_NORMAL	    0x00 | 
|  | 96 | #  define CANCTRL_OSM		    0x08 | 
|  | 97 | #  define CANCTRL_ABAT		    0x10 | 
|  | 98 | #define TEC	      0x1c | 
|  | 99 | #define REC	      0x1d | 
|  | 100 | #define CNF1	      0x2a | 
|  | 101 | #  define CNF1_SJW_SHIFT   6 | 
|  | 102 | #define CNF2	      0x29 | 
|  | 103 | #  define CNF2_BTLMODE	   0x80 | 
|  | 104 | #  define CNF2_SAM         0x40 | 
|  | 105 | #  define CNF2_PS1_SHIFT   3 | 
|  | 106 | #define CNF3	      0x28 | 
|  | 107 | #  define CNF3_SOF	   0x08 | 
|  | 108 | #  define CNF3_WAKFIL	   0x04 | 
|  | 109 | #  define CNF3_PHSEG2_MASK 0x07 | 
|  | 110 | #define CANINTE	      0x2b | 
|  | 111 | #  define CANINTE_MERRE 0x80 | 
|  | 112 | #  define CANINTE_WAKIE 0x40 | 
|  | 113 | #  define CANINTE_ERRIE 0x20 | 
|  | 114 | #  define CANINTE_TX2IE 0x10 | 
|  | 115 | #  define CANINTE_TX1IE 0x08 | 
|  | 116 | #  define CANINTE_TX0IE 0x04 | 
|  | 117 | #  define CANINTE_RX1IE 0x02 | 
|  | 118 | #  define CANINTE_RX0IE 0x01 | 
|  | 119 | #define CANINTF	      0x2c | 
|  | 120 | #  define CANINTF_MERRF 0x80 | 
|  | 121 | #  define CANINTF_WAKIF 0x40 | 
|  | 122 | #  define CANINTF_ERRIF 0x20 | 
|  | 123 | #  define CANINTF_TX2IF 0x10 | 
|  | 124 | #  define CANINTF_TX1IF 0x08 | 
|  | 125 | #  define CANINTF_TX0IF 0x04 | 
|  | 126 | #  define CANINTF_RX1IF 0x02 | 
|  | 127 | #  define CANINTF_RX0IF 0x01 | 
|  | 128 | #define EFLG	      0x2d | 
|  | 129 | #  define EFLG_EWARN	0x01 | 
|  | 130 | #  define EFLG_RXWAR	0x02 | 
|  | 131 | #  define EFLG_TXWAR	0x04 | 
|  | 132 | #  define EFLG_RXEP	0x08 | 
|  | 133 | #  define EFLG_TXEP	0x10 | 
|  | 134 | #  define EFLG_TXBO	0x20 | 
|  | 135 | #  define EFLG_RX0OVR	0x40 | 
|  | 136 | #  define EFLG_RX1OVR	0x80 | 
|  | 137 | #define TXBCTRL(n)  (((n) * 0x10) + 0x30 + TXBCTRL_OFF) | 
|  | 138 | #  define TXBCTRL_ABTF	0x40 | 
|  | 139 | #  define TXBCTRL_MLOA	0x20 | 
|  | 140 | #  define TXBCTRL_TXERR 0x10 | 
|  | 141 | #  define TXBCTRL_TXREQ 0x08 | 
|  | 142 | #define TXBSIDH(n)  (((n) * 0x10) + 0x30 + TXBSIDH_OFF) | 
|  | 143 | #  define SIDH_SHIFT    3 | 
|  | 144 | #define TXBSIDL(n)  (((n) * 0x10) + 0x30 + TXBSIDL_OFF) | 
|  | 145 | #  define SIDL_SID_MASK    7 | 
|  | 146 | #  define SIDL_SID_SHIFT   5 | 
|  | 147 | #  define SIDL_EXIDE_SHIFT 3 | 
|  | 148 | #  define SIDL_EID_SHIFT   16 | 
|  | 149 | #  define SIDL_EID_MASK    3 | 
|  | 150 | #define TXBEID8(n)  (((n) * 0x10) + 0x30 + TXBEID8_OFF) | 
|  | 151 | #define TXBEID0(n)  (((n) * 0x10) + 0x30 + TXBEID0_OFF) | 
|  | 152 | #define TXBDLC(n)   (((n) * 0x10) + 0x30 + TXBDLC_OFF) | 
|  | 153 | #  define DLC_RTR_SHIFT    6 | 
|  | 154 | #define TXBCTRL_OFF 0 | 
|  | 155 | #define TXBSIDH_OFF 1 | 
|  | 156 | #define TXBSIDL_OFF 2 | 
|  | 157 | #define TXBEID8_OFF 3 | 
|  | 158 | #define TXBEID0_OFF 4 | 
|  | 159 | #define TXBDLC_OFF  5 | 
|  | 160 | #define TXBDAT_OFF  6 | 
|  | 161 | #define RXBCTRL(n)  (((n) * 0x10) + 0x60 + RXBCTRL_OFF) | 
|  | 162 | #  define RXBCTRL_BUKT	0x04 | 
|  | 163 | #  define RXBCTRL_RXM0	0x20 | 
|  | 164 | #  define RXBCTRL_RXM1	0x40 | 
|  | 165 | #define RXBSIDH(n)  (((n) * 0x10) + 0x60 + RXBSIDH_OFF) | 
|  | 166 | #  define RXBSIDH_SHIFT 3 | 
|  | 167 | #define RXBSIDL(n)  (((n) * 0x10) + 0x60 + RXBSIDL_OFF) | 
|  | 168 | #  define RXBSIDL_IDE   0x08 | 
|  | 169 | #  define RXBSIDL_EID   3 | 
|  | 170 | #  define RXBSIDL_SHIFT 5 | 
|  | 171 | #define RXBEID8(n)  (((n) * 0x10) + 0x60 + RXBEID8_OFF) | 
|  | 172 | #define RXBEID0(n)  (((n) * 0x10) + 0x60 + RXBEID0_OFF) | 
|  | 173 | #define RXBDLC(n)   (((n) * 0x10) + 0x60 + RXBDLC_OFF) | 
|  | 174 | #  define RXBDLC_LEN_MASK  0x0f | 
|  | 175 | #  define RXBDLC_RTR       0x40 | 
|  | 176 | #define RXBCTRL_OFF 0 | 
|  | 177 | #define RXBSIDH_OFF 1 | 
|  | 178 | #define RXBSIDL_OFF 2 | 
|  | 179 | #define RXBEID8_OFF 3 | 
|  | 180 | #define RXBEID0_OFF 4 | 
|  | 181 | #define RXBDLC_OFF  5 | 
|  | 182 | #define RXBDAT_OFF  6 | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 183 | #define RXFSIDH(n) ((n) * 4) | 
|  | 184 | #define RXFSIDL(n) ((n) * 4 + 1) | 
|  | 185 | #define RXFEID8(n) ((n) * 4 + 2) | 
|  | 186 | #define RXFEID0(n) ((n) * 4 + 3) | 
|  | 187 | #define RXMSIDH(n) ((n) * 4 + 0x20) | 
|  | 188 | #define RXMSIDL(n) ((n) * 4 + 0x21) | 
|  | 189 | #define RXMEID8(n) ((n) * 4 + 0x22) | 
|  | 190 | #define RXMEID0(n) ((n) * 4 + 0x23) | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 191 |  | 
|  | 192 | #define GET_BYTE(val, byte)			\ | 
|  | 193 | (((val) >> ((byte) * 8)) & 0xff) | 
|  | 194 | #define SET_BYTE(val, byte)			\ | 
|  | 195 | (((val) & 0xff) << ((byte) * 8)) | 
|  | 196 |  | 
|  | 197 | /* | 
|  | 198 | * Buffer size required for the largest SPI transfer (i.e., reading a | 
|  | 199 | * frame) | 
|  | 200 | */ | 
|  | 201 | #define CAN_FRAME_MAX_DATA_LEN	8 | 
|  | 202 | #define SPI_TRANSFER_BUF_LEN	(6 + CAN_FRAME_MAX_DATA_LEN) | 
|  | 203 | #define CAN_FRAME_MAX_BITS	128 | 
|  | 204 |  | 
|  | 205 | #define TX_ECHO_SKB_MAX	1 | 
|  | 206 |  | 
|  | 207 | #define DEVICE_NAME "mcp251x" | 
|  | 208 |  | 
|  | 209 | static int mcp251x_enable_dma; /* Enable SPI DMA. Default: 0 (Off) */ | 
|  | 210 | module_param(mcp251x_enable_dma, int, S_IRUGO); | 
|  | 211 | MODULE_PARM_DESC(mcp251x_enable_dma, "Enable SPI DMA. Default: 0 (Off)"); | 
|  | 212 |  | 
|  | 213 | static struct can_bittiming_const mcp251x_bittiming_const = { | 
|  | 214 | .name = DEVICE_NAME, | 
|  | 215 | .tseg1_min = 3, | 
|  | 216 | .tseg1_max = 16, | 
|  | 217 | .tseg2_min = 2, | 
|  | 218 | .tseg2_max = 8, | 
|  | 219 | .sjw_max = 4, | 
|  | 220 | .brp_min = 1, | 
|  | 221 | .brp_max = 64, | 
|  | 222 | .brp_inc = 1, | 
|  | 223 | }; | 
|  | 224 |  | 
|  | 225 | struct mcp251x_priv { | 
|  | 226 | struct can_priv	   can; | 
|  | 227 | struct net_device *net; | 
|  | 228 | struct spi_device *spi; | 
|  | 229 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 230 | struct mutex mcp_lock; /* SPI device lock */ | 
|  | 231 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 232 | u8 *spi_tx_buf; | 
|  | 233 | u8 *spi_rx_buf; | 
|  | 234 | dma_addr_t spi_tx_dma; | 
|  | 235 | dma_addr_t spi_rx_dma; | 
|  | 236 |  | 
|  | 237 | struct sk_buff *tx_skb; | 
|  | 238 | int tx_len; | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 239 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 240 | struct workqueue_struct *wq; | 
|  | 241 | struct work_struct tx_work; | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 242 | struct work_struct restart_work; | 
|  | 243 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 244 | int force_quit; | 
|  | 245 | int after_suspend; | 
|  | 246 | #define AFTER_SUSPEND_UP 1 | 
|  | 247 | #define AFTER_SUSPEND_DOWN 2 | 
|  | 248 | #define AFTER_SUSPEND_POWER 4 | 
|  | 249 | #define AFTER_SUSPEND_RESTART 8 | 
|  | 250 | int restart_tx; | 
|  | 251 | }; | 
|  | 252 |  | 
|  | 253 | static void mcp251x_clean(struct net_device *net) | 
|  | 254 | { | 
|  | 255 | struct mcp251x_priv *priv = netdev_priv(net); | 
|  | 256 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 257 | if (priv->tx_skb || priv->tx_len) | 
|  | 258 | net->stats.tx_errors++; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 259 | if (priv->tx_skb) | 
|  | 260 | dev_kfree_skb(priv->tx_skb); | 
|  | 261 | if (priv->tx_len) | 
|  | 262 | can_free_echo_skb(priv->net, 0); | 
|  | 263 | priv->tx_skb = NULL; | 
|  | 264 | priv->tx_len = 0; | 
|  | 265 | } | 
|  | 266 |  | 
|  | 267 | /* | 
|  | 268 | * Note about handling of error return of mcp251x_spi_trans: accessing | 
|  | 269 | * registers via SPI is not really different conceptually than using | 
|  | 270 | * normal I/O assembler instructions, although it's much more | 
|  | 271 | * complicated from a practical POV. So it's not advisable to always | 
|  | 272 | * check the return value of this function. Imagine that every | 
|  | 273 | * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0) | 
|  | 274 | * error();", it would be a great mess (well there are some situation | 
|  | 275 | * when exception handling C++ like could be useful after all). So we | 
|  | 276 | * just check that transfers are OK at the beginning of our | 
|  | 277 | * conversation with the chip and to avoid doing really nasty things | 
|  | 278 | * (like injecting bogus packets in the network stack). | 
|  | 279 | */ | 
|  | 280 | static int mcp251x_spi_trans(struct spi_device *spi, int len) | 
|  | 281 | { | 
|  | 282 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 283 | struct spi_transfer t = { | 
|  | 284 | .tx_buf = priv->spi_tx_buf, | 
|  | 285 | .rx_buf = priv->spi_rx_buf, | 
|  | 286 | .len = len, | 
|  | 287 | .cs_change = 0, | 
|  | 288 | }; | 
|  | 289 | struct spi_message m; | 
|  | 290 | int ret; | 
|  | 291 |  | 
|  | 292 | spi_message_init(&m); | 
|  | 293 |  | 
|  | 294 | if (mcp251x_enable_dma) { | 
|  | 295 | t.tx_dma = priv->spi_tx_dma; | 
|  | 296 | t.rx_dma = priv->spi_rx_dma; | 
|  | 297 | m.is_dma_mapped = 1; | 
|  | 298 | } | 
|  | 299 |  | 
|  | 300 | spi_message_add_tail(&t, &m); | 
|  | 301 |  | 
|  | 302 | ret = spi_sync(spi, &m); | 
|  | 303 | if (ret) | 
|  | 304 | dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret); | 
|  | 305 | return ret; | 
|  | 306 | } | 
|  | 307 |  | 
|  | 308 | static u8 mcp251x_read_reg(struct spi_device *spi, uint8_t reg) | 
|  | 309 | { | 
|  | 310 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 311 | u8 val = 0; | 
|  | 312 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 313 | priv->spi_tx_buf[0] = INSTRUCTION_READ; | 
|  | 314 | priv->spi_tx_buf[1] = reg; | 
|  | 315 |  | 
|  | 316 | mcp251x_spi_trans(spi, 3); | 
|  | 317 | val = priv->spi_rx_buf[2]; | 
|  | 318 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 319 | return val; | 
|  | 320 | } | 
|  | 321 |  | 
|  | 322 | static void mcp251x_write_reg(struct spi_device *spi, u8 reg, uint8_t val) | 
|  | 323 | { | 
|  | 324 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 325 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 326 | priv->spi_tx_buf[0] = INSTRUCTION_WRITE; | 
|  | 327 | priv->spi_tx_buf[1] = reg; | 
|  | 328 | priv->spi_tx_buf[2] = val; | 
|  | 329 |  | 
|  | 330 | mcp251x_spi_trans(spi, 3); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 331 | } | 
|  | 332 |  | 
|  | 333 | static void mcp251x_write_bits(struct spi_device *spi, u8 reg, | 
|  | 334 | u8 mask, uint8_t val) | 
|  | 335 | { | 
|  | 336 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 337 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 338 | priv->spi_tx_buf[0] = INSTRUCTION_BIT_MODIFY; | 
|  | 339 | priv->spi_tx_buf[1] = reg; | 
|  | 340 | priv->spi_tx_buf[2] = mask; | 
|  | 341 | priv->spi_tx_buf[3] = val; | 
|  | 342 |  | 
|  | 343 | mcp251x_spi_trans(spi, 4); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 344 | } | 
|  | 345 |  | 
|  | 346 | static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, | 
|  | 347 | int len, int tx_buf_idx) | 
|  | 348 | { | 
|  | 349 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
|  | 350 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 351 |  | 
|  | 352 | if (pdata->model == CAN_MCP251X_MCP2510) { | 
|  | 353 | int i; | 
|  | 354 |  | 
|  | 355 | for (i = 1; i < TXBDAT_OFF + len; i++) | 
|  | 356 | mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx) + i, | 
|  | 357 | buf[i]); | 
|  | 358 | } else { | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 359 | memcpy(priv->spi_tx_buf, buf, TXBDAT_OFF + len); | 
|  | 360 | mcp251x_spi_trans(spi, TXBDAT_OFF + len); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 361 | } | 
|  | 362 | } | 
|  | 363 |  | 
|  | 364 | static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, | 
|  | 365 | int tx_buf_idx) | 
|  | 366 | { | 
|  | 367 | u32 sid, eid, exide, rtr; | 
|  | 368 | u8 buf[SPI_TRANSFER_BUF_LEN]; | 
|  | 369 |  | 
|  | 370 | exide = (frame->can_id & CAN_EFF_FLAG) ? 1 : 0; /* Extended ID Enable */ | 
|  | 371 | if (exide) | 
|  | 372 | sid = (frame->can_id & CAN_EFF_MASK) >> 18; | 
|  | 373 | else | 
|  | 374 | sid = frame->can_id & CAN_SFF_MASK; /* Standard ID */ | 
|  | 375 | eid = frame->can_id & CAN_EFF_MASK; /* Extended ID */ | 
|  | 376 | rtr = (frame->can_id & CAN_RTR_FLAG) ? 1 : 0; /* Remote transmission */ | 
|  | 377 |  | 
|  | 378 | buf[TXBCTRL_OFF] = INSTRUCTION_LOAD_TXB(tx_buf_idx); | 
|  | 379 | buf[TXBSIDH_OFF] = sid >> SIDH_SHIFT; | 
|  | 380 | buf[TXBSIDL_OFF] = ((sid & SIDL_SID_MASK) << SIDL_SID_SHIFT) | | 
|  | 381 | (exide << SIDL_EXIDE_SHIFT) | | 
|  | 382 | ((eid >> SIDL_EID_SHIFT) & SIDL_EID_MASK); | 
|  | 383 | buf[TXBEID8_OFF] = GET_BYTE(eid, 1); | 
|  | 384 | buf[TXBEID0_OFF] = GET_BYTE(eid, 0); | 
|  | 385 | buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; | 
|  | 386 | memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); | 
|  | 387 | mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); | 
|  | 388 | mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); | 
|  | 389 | } | 
|  | 390 |  | 
|  | 391 | static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, | 
|  | 392 | int buf_idx) | 
|  | 393 | { | 
|  | 394 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 395 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
|  | 396 |  | 
|  | 397 | if (pdata->model == CAN_MCP251X_MCP2510) { | 
|  | 398 | int i, len; | 
|  | 399 |  | 
|  | 400 | for (i = 1; i < RXBDAT_OFF; i++) | 
|  | 401 | buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); | 
| Oliver Hartkopp | c7cd606 | 2009-12-12 04:13:21 +0000 | [diff] [blame] | 402 |  | 
|  | 403 | len = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 404 | for (; i < (RXBDAT_OFF + len); i++) | 
|  | 405 | buf[i] = mcp251x_read_reg(spi, RXBCTRL(buf_idx) + i); | 
|  | 406 | } else { | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 407 | priv->spi_tx_buf[RXBCTRL_OFF] = INSTRUCTION_READ_RXB(buf_idx); | 
|  | 408 | mcp251x_spi_trans(spi, SPI_TRANSFER_BUF_LEN); | 
|  | 409 | memcpy(buf, priv->spi_rx_buf, SPI_TRANSFER_BUF_LEN); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 410 | } | 
|  | 411 | } | 
|  | 412 |  | 
|  | 413 | static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) | 
|  | 414 | { | 
|  | 415 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 416 | struct sk_buff *skb; | 
|  | 417 | struct can_frame *frame; | 
|  | 418 | u8 buf[SPI_TRANSFER_BUF_LEN]; | 
|  | 419 |  | 
|  | 420 | skb = alloc_can_skb(priv->net, &frame); | 
|  | 421 | if (!skb) { | 
|  | 422 | dev_err(&spi->dev, "cannot allocate RX skb\n"); | 
|  | 423 | priv->net->stats.rx_dropped++; | 
|  | 424 | return; | 
|  | 425 | } | 
|  | 426 |  | 
|  | 427 | mcp251x_hw_rx_frame(spi, buf, buf_idx); | 
|  | 428 | if (buf[RXBSIDL_OFF] & RXBSIDL_IDE) { | 
|  | 429 | /* Extended ID format */ | 
|  | 430 | frame->can_id = CAN_EFF_FLAG; | 
|  | 431 | frame->can_id |= | 
|  | 432 | /* Extended ID part */ | 
|  | 433 | SET_BYTE(buf[RXBSIDL_OFF] & RXBSIDL_EID, 2) | | 
|  | 434 | SET_BYTE(buf[RXBEID8_OFF], 1) | | 
|  | 435 | SET_BYTE(buf[RXBEID0_OFF], 0) | | 
|  | 436 | /* Standard ID part */ | 
|  | 437 | (((buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | | 
|  | 438 | (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT)) << 18); | 
|  | 439 | /* Remote transmission request */ | 
|  | 440 | if (buf[RXBDLC_OFF] & RXBDLC_RTR) | 
|  | 441 | frame->can_id |= CAN_RTR_FLAG; | 
|  | 442 | } else { | 
|  | 443 | /* Standard ID format */ | 
|  | 444 | frame->can_id = | 
|  | 445 | (buf[RXBSIDH_OFF] << RXBSIDH_SHIFT) | | 
|  | 446 | (buf[RXBSIDL_OFF] >> RXBSIDL_SHIFT); | 
|  | 447 | } | 
|  | 448 | /* Data length */ | 
| Oliver Hartkopp | c7cd606 | 2009-12-12 04:13:21 +0000 | [diff] [blame] | 449 | frame->can_dlc = get_can_dlc(buf[RXBDLC_OFF] & RXBDLC_LEN_MASK); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 450 | memcpy(frame->data, buf + RXBDAT_OFF, frame->can_dlc); | 
|  | 451 |  | 
|  | 452 | priv->net->stats.rx_packets++; | 
|  | 453 | priv->net->stats.rx_bytes += frame->can_dlc; | 
|  | 454 | netif_rx(skb); | 
|  | 455 | } | 
|  | 456 |  | 
|  | 457 | static void mcp251x_hw_sleep(struct spi_device *spi) | 
|  | 458 | { | 
|  | 459 | mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_SLEEP); | 
|  | 460 | } | 
|  | 461 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 462 | static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, | 
|  | 463 | struct net_device *net) | 
|  | 464 | { | 
|  | 465 | struct mcp251x_priv *priv = netdev_priv(net); | 
|  | 466 | struct spi_device *spi = priv->spi; | 
|  | 467 |  | 
|  | 468 | if (priv->tx_skb || priv->tx_len) { | 
|  | 469 | dev_warn(&spi->dev, "hard_xmit called while tx busy\n"); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 470 | return NETDEV_TX_BUSY; | 
|  | 471 | } | 
|  | 472 |  | 
| Oliver Hartkopp | 3ccd4c6 | 2010-01-12 02:00:46 -0800 | [diff] [blame] | 473 | if (can_dropped_invalid_skb(net, skb)) | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 474 | return NETDEV_TX_OK; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 475 |  | 
|  | 476 | netif_stop_queue(net); | 
|  | 477 | priv->tx_skb = skb; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 478 | queue_work(priv->wq, &priv->tx_work); | 
|  | 479 |  | 
|  | 480 | return NETDEV_TX_OK; | 
|  | 481 | } | 
|  | 482 |  | 
|  | 483 | static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode) | 
|  | 484 | { | 
|  | 485 | struct mcp251x_priv *priv = netdev_priv(net); | 
|  | 486 |  | 
|  | 487 | switch (mode) { | 
|  | 488 | case CAN_MODE_START: | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 489 | mcp251x_clean(net); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 490 | /* We have to delay work since SPI I/O may sleep */ | 
|  | 491 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | 
|  | 492 | priv->restart_tx = 1; | 
|  | 493 | if (priv->can.restart_ms == 0) | 
|  | 494 | priv->after_suspend = AFTER_SUSPEND_RESTART; | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 495 | queue_work(priv->wq, &priv->restart_work); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 496 | break; | 
|  | 497 | default: | 
|  | 498 | return -EOPNOTSUPP; | 
|  | 499 | } | 
|  | 500 |  | 
|  | 501 | return 0; | 
|  | 502 | } | 
|  | 503 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 504 | static int mcp251x_set_normal_mode(struct spi_device *spi) | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 505 | { | 
|  | 506 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 507 | unsigned long timeout; | 
|  | 508 |  | 
|  | 509 | /* Enable interrupts */ | 
|  | 510 | mcp251x_write_reg(spi, CANINTE, | 
|  | 511 | CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE | | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 512 | CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 513 |  | 
|  | 514 | if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { | 
|  | 515 | /* Put device into loopback mode */ | 
|  | 516 | mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LOOPBACK); | 
| Christian Pellegrin | ad72c34 | 2010-01-14 07:08:34 +0000 | [diff] [blame] | 517 | } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { | 
|  | 518 | /* Put device into listen-only mode */ | 
|  | 519 | mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_LISTEN_ONLY); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 520 | } else { | 
|  | 521 | /* Put device into normal mode */ | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 522 | mcp251x_write_reg(spi, CANCTRL, CANCTRL_REQOP_NORMAL); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 523 |  | 
|  | 524 | /* Wait for the device to enter normal mode */ | 
|  | 525 | timeout = jiffies + HZ; | 
|  | 526 | while (mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) { | 
|  | 527 | schedule(); | 
|  | 528 | if (time_after(jiffies, timeout)) { | 
|  | 529 | dev_err(&spi->dev, "MCP251x didn't" | 
|  | 530 | " enter in normal mode\n"); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 531 | return -EBUSY; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 532 | } | 
|  | 533 | } | 
|  | 534 | } | 
|  | 535 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 536 | return 0; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 537 | } | 
|  | 538 |  | 
|  | 539 | static int mcp251x_do_set_bittiming(struct net_device *net) | 
|  | 540 | { | 
|  | 541 | struct mcp251x_priv *priv = netdev_priv(net); | 
|  | 542 | struct can_bittiming *bt = &priv->can.bittiming; | 
|  | 543 | struct spi_device *spi = priv->spi; | 
|  | 544 |  | 
|  | 545 | mcp251x_write_reg(spi, CNF1, ((bt->sjw - 1) << CNF1_SJW_SHIFT) | | 
|  | 546 | (bt->brp - 1)); | 
|  | 547 | mcp251x_write_reg(spi, CNF2, CNF2_BTLMODE | | 
|  | 548 | (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ? | 
|  | 549 | CNF2_SAM : 0) | | 
|  | 550 | ((bt->phase_seg1 - 1) << CNF2_PS1_SHIFT) | | 
|  | 551 | (bt->prop_seg - 1)); | 
|  | 552 | mcp251x_write_bits(spi, CNF3, CNF3_PHSEG2_MASK, | 
|  | 553 | (bt->phase_seg2 - 1)); | 
|  | 554 | dev_info(&spi->dev, "CNF: 0x%02x 0x%02x 0x%02x\n", | 
|  | 555 | mcp251x_read_reg(spi, CNF1), | 
|  | 556 | mcp251x_read_reg(spi, CNF2), | 
|  | 557 | mcp251x_read_reg(spi, CNF3)); | 
|  | 558 |  | 
|  | 559 | return 0; | 
|  | 560 | } | 
|  | 561 |  | 
|  | 562 | static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv, | 
|  | 563 | struct spi_device *spi) | 
|  | 564 | { | 
| Christian Pellegrin | 615534b | 2009-11-17 06:20:44 +0000 | [diff] [blame] | 565 | mcp251x_do_set_bittiming(net); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 566 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 567 | mcp251x_write_reg(spi, RXBCTRL(0), | 
|  | 568 | RXBCTRL_BUKT | RXBCTRL_RXM0 | RXBCTRL_RXM1); | 
|  | 569 | mcp251x_write_reg(spi, RXBCTRL(1), | 
|  | 570 | RXBCTRL_RXM0 | RXBCTRL_RXM1); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 571 | return 0; | 
|  | 572 | } | 
|  | 573 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 574 | static int mcp251x_hw_reset(struct spi_device *spi) | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 575 | { | 
|  | 576 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 577 | int ret; | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 578 | unsigned long timeout; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 579 |  | 
|  | 580 | priv->spi_tx_buf[0] = INSTRUCTION_RESET; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 581 | ret = spi_write(spi, priv->spi_tx_buf, 1); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 582 | if (ret) { | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 583 | dev_err(&spi->dev, "reset failed: ret = %d\n", ret); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 584 | return -EIO; | 
|  | 585 | } | 
|  | 586 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 587 | /* Wait for reset to finish */ | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 588 | timeout = jiffies + HZ; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 589 | mdelay(10); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 590 | while ((mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) | 
|  | 591 | != CANCTRL_REQOP_CONF) { | 
|  | 592 | schedule(); | 
|  | 593 | if (time_after(jiffies, timeout)) { | 
|  | 594 | dev_err(&spi->dev, "MCP251x didn't" | 
|  | 595 | " enter in conf mode after reset\n"); | 
|  | 596 | return -EBUSY; | 
|  | 597 | } | 
|  | 598 | } | 
|  | 599 | return 0; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 600 | } | 
|  | 601 |  | 
|  | 602 | static int mcp251x_hw_probe(struct spi_device *spi) | 
|  | 603 | { | 
|  | 604 | int st1, st2; | 
|  | 605 |  | 
|  | 606 | mcp251x_hw_reset(spi); | 
|  | 607 |  | 
|  | 608 | /* | 
|  | 609 | * Please note that these are "magic values" based on after | 
|  | 610 | * reset defaults taken from data sheet which allows us to see | 
|  | 611 | * if we really have a chip on the bus (we avoid common all | 
|  | 612 | * zeroes or all ones situations) | 
|  | 613 | */ | 
|  | 614 | st1 = mcp251x_read_reg(spi, CANSTAT) & 0xEE; | 
|  | 615 | st2 = mcp251x_read_reg(spi, CANCTRL) & 0x17; | 
|  | 616 |  | 
|  | 617 | dev_dbg(&spi->dev, "CANSTAT 0x%02x CANCTRL 0x%02x\n", st1, st2); | 
|  | 618 |  | 
|  | 619 | /* Check for power up default values */ | 
|  | 620 | return (st1 == 0x80 && st2 == 0x07) ? 1 : 0; | 
|  | 621 | } | 
|  | 622 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 623 | static void mcp251x_open_clean(struct net_device *net) | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 624 | { | 
|  | 625 | struct mcp251x_priv *priv = netdev_priv(net); | 
|  | 626 | struct spi_device *spi = priv->spi; | 
|  | 627 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 628 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 629 | free_irq(spi->irq, priv); | 
|  | 630 | mcp251x_hw_sleep(spi); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 631 | if (pdata->transceiver_enable) | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 632 | pdata->transceiver_enable(0); | 
|  | 633 | close_candev(net); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 634 | } | 
|  | 635 |  | 
|  | 636 | static int mcp251x_stop(struct net_device *net) | 
|  | 637 | { | 
|  | 638 | struct mcp251x_priv *priv = netdev_priv(net); | 
|  | 639 | struct spi_device *spi = priv->spi; | 
|  | 640 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
|  | 641 |  | 
|  | 642 | close_candev(net); | 
|  | 643 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 644 | priv->force_quit = 1; | 
|  | 645 | free_irq(spi->irq, priv); | 
|  | 646 | destroy_workqueue(priv->wq); | 
|  | 647 | priv->wq = NULL; | 
|  | 648 |  | 
|  | 649 | mutex_lock(&priv->mcp_lock); | 
|  | 650 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 651 | /* Disable and clear pending interrupts */ | 
|  | 652 | mcp251x_write_reg(spi, CANINTE, 0x00); | 
|  | 653 | mcp251x_write_reg(spi, CANINTF, 0x00); | 
|  | 654 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 655 | mcp251x_write_reg(spi, TXBCTRL(0), 0); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 656 | mcp251x_clean(net); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 657 |  | 
|  | 658 | mcp251x_hw_sleep(spi); | 
|  | 659 |  | 
|  | 660 | if (pdata->transceiver_enable) | 
|  | 661 | pdata->transceiver_enable(0); | 
|  | 662 |  | 
|  | 663 | priv->can.state = CAN_STATE_STOPPED; | 
|  | 664 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 665 | mutex_unlock(&priv->mcp_lock); | 
|  | 666 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 667 | return 0; | 
|  | 668 | } | 
|  | 669 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 670 | static void mcp251x_error_skb(struct net_device *net, int can_id, int data1) | 
|  | 671 | { | 
|  | 672 | struct sk_buff *skb; | 
|  | 673 | struct can_frame *frame; | 
|  | 674 |  | 
|  | 675 | skb = alloc_can_err_skb(net, &frame); | 
|  | 676 | if (skb) { | 
|  | 677 | frame->can_id = can_id; | 
|  | 678 | frame->data[1] = data1; | 
|  | 679 | netif_rx(skb); | 
|  | 680 | } else { | 
|  | 681 | dev_err(&net->dev, | 
|  | 682 | "cannot allocate error skb\n"); | 
|  | 683 | } | 
|  | 684 | } | 
|  | 685 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 686 | static void mcp251x_tx_work_handler(struct work_struct *ws) | 
|  | 687 | { | 
|  | 688 | struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, | 
|  | 689 | tx_work); | 
|  | 690 | struct spi_device *spi = priv->spi; | 
|  | 691 | struct net_device *net = priv->net; | 
|  | 692 | struct can_frame *frame; | 
|  | 693 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 694 | mutex_lock(&priv->mcp_lock); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 695 | if (priv->tx_skb) { | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 696 | if (priv->can.state == CAN_STATE_BUS_OFF) { | 
|  | 697 | mcp251x_clean(net); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 698 | } else { | 
|  | 699 | frame = (struct can_frame *)priv->tx_skb->data; | 
|  | 700 |  | 
|  | 701 | if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN) | 
|  | 702 | frame->can_dlc = CAN_FRAME_MAX_DATA_LEN; | 
|  | 703 | mcp251x_hw_tx(spi, frame, 0); | 
|  | 704 | priv->tx_len = 1 + frame->can_dlc; | 
|  | 705 | can_put_echo_skb(priv->tx_skb, net, 0); | 
|  | 706 | priv->tx_skb = NULL; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 707 | } | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 708 | } | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 709 | mutex_unlock(&priv->mcp_lock); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 710 | } | 
|  | 711 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 712 | static void mcp251x_restart_work_handler(struct work_struct *ws) | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 713 | { | 
|  | 714 | struct mcp251x_priv *priv = container_of(ws, struct mcp251x_priv, | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 715 | restart_work); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 716 | struct spi_device *spi = priv->spi; | 
|  | 717 | struct net_device *net = priv->net; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 718 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 719 | mutex_lock(&priv->mcp_lock); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 720 | if (priv->after_suspend) { | 
|  | 721 | mdelay(10); | 
|  | 722 | mcp251x_hw_reset(spi); | 
|  | 723 | mcp251x_setup(net, priv, spi); | 
|  | 724 | if (priv->after_suspend & AFTER_SUSPEND_RESTART) { | 
|  | 725 | mcp251x_set_normal_mode(spi); | 
|  | 726 | } else if (priv->after_suspend & AFTER_SUSPEND_UP) { | 
|  | 727 | netif_device_attach(net); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 728 | mcp251x_clean(net); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 729 | mcp251x_set_normal_mode(spi); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 730 | netif_wake_queue(net); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 731 | } else { | 
|  | 732 | mcp251x_hw_sleep(spi); | 
|  | 733 | } | 
|  | 734 | priv->after_suspend = 0; | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 735 | priv->force_quit = 0; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 736 | } | 
|  | 737 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 738 | if (priv->restart_tx) { | 
|  | 739 | priv->restart_tx = 0; | 
|  | 740 | mcp251x_write_reg(spi, TXBCTRL(0), 0); | 
|  | 741 | mcp251x_clean(net); | 
|  | 742 | netif_wake_queue(net); | 
|  | 743 | mcp251x_error_skb(net, CAN_ERR_RESTARTED, 0); | 
|  | 744 | } | 
|  | 745 | mutex_unlock(&priv->mcp_lock); | 
|  | 746 | } | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 747 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 748 | static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) | 
|  | 749 | { | 
|  | 750 | struct mcp251x_priv *priv = dev_id; | 
|  | 751 | struct spi_device *spi = priv->spi; | 
|  | 752 | struct net_device *net = priv->net; | 
|  | 753 |  | 
|  | 754 | mutex_lock(&priv->mcp_lock); | 
|  | 755 | while (!priv->force_quit) { | 
|  | 756 | enum can_state new_state; | 
|  | 757 | u8 intf = mcp251x_read_reg(spi, CANINTF); | 
|  | 758 | u8 eflag; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 759 | int can_id = 0, data1 = 0; | 
|  | 760 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 761 | if (intf & CANINTF_RX0IF) { | 
|  | 762 | mcp251x_hw_rx(spi, 0); | 
|  | 763 | /* Free one buffer ASAP */ | 
|  | 764 | mcp251x_write_bits(spi, CANINTF, intf & CANINTF_RX0IF, | 
|  | 765 | 0x00); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 766 | } | 
|  | 767 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 768 | if (intf & CANINTF_RX1IF) | 
|  | 769 | mcp251x_hw_rx(spi, 1); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 770 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 771 | mcp251x_write_bits(spi, CANINTF, intf, 0x00); | 
|  | 772 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 773 | eflag = mcp251x_read_reg(spi, EFLG); | 
|  | 774 | mcp251x_write_reg(spi, EFLG, 0x00); | 
|  | 775 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 776 | /* Update can state */ | 
|  | 777 | if (eflag & EFLG_TXBO) { | 
|  | 778 | new_state = CAN_STATE_BUS_OFF; | 
|  | 779 | can_id |= CAN_ERR_BUSOFF; | 
|  | 780 | } else if (eflag & EFLG_TXEP) { | 
|  | 781 | new_state = CAN_STATE_ERROR_PASSIVE; | 
|  | 782 | can_id |= CAN_ERR_CRTL; | 
|  | 783 | data1 |= CAN_ERR_CRTL_TX_PASSIVE; | 
|  | 784 | } else if (eflag & EFLG_RXEP) { | 
|  | 785 | new_state = CAN_STATE_ERROR_PASSIVE; | 
|  | 786 | can_id |= CAN_ERR_CRTL; | 
|  | 787 | data1 |= CAN_ERR_CRTL_RX_PASSIVE; | 
|  | 788 | } else if (eflag & EFLG_TXWAR) { | 
|  | 789 | new_state = CAN_STATE_ERROR_WARNING; | 
|  | 790 | can_id |= CAN_ERR_CRTL; | 
|  | 791 | data1 |= CAN_ERR_CRTL_TX_WARNING; | 
|  | 792 | } else if (eflag & EFLG_RXWAR) { | 
|  | 793 | new_state = CAN_STATE_ERROR_WARNING; | 
|  | 794 | can_id |= CAN_ERR_CRTL; | 
|  | 795 | data1 |= CAN_ERR_CRTL_RX_WARNING; | 
|  | 796 | } else { | 
|  | 797 | new_state = CAN_STATE_ERROR_ACTIVE; | 
|  | 798 | } | 
|  | 799 |  | 
|  | 800 | /* Update can state statistics */ | 
|  | 801 | switch (priv->can.state) { | 
|  | 802 | case CAN_STATE_ERROR_ACTIVE: | 
|  | 803 | if (new_state >= CAN_STATE_ERROR_WARNING && | 
|  | 804 | new_state <= CAN_STATE_BUS_OFF) | 
|  | 805 | priv->can.can_stats.error_warning++; | 
|  | 806 | case CAN_STATE_ERROR_WARNING:	/* fallthrough */ | 
|  | 807 | if (new_state >= CAN_STATE_ERROR_PASSIVE && | 
|  | 808 | new_state <= CAN_STATE_BUS_OFF) | 
|  | 809 | priv->can.can_stats.error_passive++; | 
|  | 810 | break; | 
|  | 811 | default: | 
|  | 812 | break; | 
|  | 813 | } | 
|  | 814 | priv->can.state = new_state; | 
|  | 815 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 816 | if (intf & CANINTF_ERRIF) { | 
|  | 817 | /* Handle overflow counters */ | 
|  | 818 | if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) { | 
|  | 819 | if (eflag & EFLG_RX0OVR) | 
|  | 820 | net->stats.rx_over_errors++; | 
|  | 821 | if (eflag & EFLG_RX1OVR) | 
|  | 822 | net->stats.rx_over_errors++; | 
|  | 823 | can_id |= CAN_ERR_CRTL; | 
|  | 824 | data1 |= CAN_ERR_CRTL_RX_OVERFLOW; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 825 | } | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 826 | mcp251x_error_skb(net, can_id, data1); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 827 | } | 
|  | 828 |  | 
|  | 829 | if (priv->can.state == CAN_STATE_BUS_OFF) { | 
|  | 830 | if (priv->can.restart_ms == 0) { | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 831 | priv->force_quit = 1; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 832 | can_bus_off(net); | 
|  | 833 | mcp251x_hw_sleep(spi); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 834 | break; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 835 | } | 
|  | 836 | } | 
|  | 837 |  | 
|  | 838 | if (intf == 0) | 
|  | 839 | break; | 
|  | 840 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 841 | if (intf & (CANINTF_TX2IF | CANINTF_TX1IF | CANINTF_TX0IF)) { | 
|  | 842 | net->stats.tx_packets++; | 
|  | 843 | net->stats.tx_bytes += priv->tx_len - 1; | 
|  | 844 | if (priv->tx_len) { | 
|  | 845 | can_get_echo_skb(net, 0); | 
|  | 846 | priv->tx_len = 0; | 
|  | 847 | } | 
|  | 848 | netif_wake_queue(net); | 
|  | 849 | } | 
|  | 850 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 851 | } | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 852 | mutex_unlock(&priv->mcp_lock); | 
|  | 853 | return IRQ_HANDLED; | 
|  | 854 | } | 
|  | 855 |  | 
|  | 856 | static int mcp251x_open(struct net_device *net) | 
|  | 857 | { | 
|  | 858 | struct mcp251x_priv *priv = netdev_priv(net); | 
|  | 859 | struct spi_device *spi = priv->spi; | 
|  | 860 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
|  | 861 | int ret; | 
|  | 862 |  | 
|  | 863 | ret = open_candev(net); | 
|  | 864 | if (ret) { | 
|  | 865 | dev_err(&spi->dev, "unable to set initial baudrate!\n"); | 
|  | 866 | return ret; | 
|  | 867 | } | 
|  | 868 |  | 
|  | 869 | mutex_lock(&priv->mcp_lock); | 
|  | 870 | if (pdata->transceiver_enable) | 
|  | 871 | pdata->transceiver_enable(1); | 
|  | 872 |  | 
|  | 873 | priv->force_quit = 0; | 
|  | 874 | priv->tx_skb = NULL; | 
|  | 875 | priv->tx_len = 0; | 
|  | 876 |  | 
|  | 877 | ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist, | 
|  | 878 | IRQF_TRIGGER_FALLING, DEVICE_NAME, priv); | 
|  | 879 | if (ret) { | 
|  | 880 | dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq); | 
|  | 881 | if (pdata->transceiver_enable) | 
|  | 882 | pdata->transceiver_enable(0); | 
|  | 883 | close_candev(net); | 
|  | 884 | goto open_unlock; | 
|  | 885 | } | 
|  | 886 |  | 
|  | 887 | priv->wq = create_freezeable_workqueue("mcp251x_wq"); | 
|  | 888 | INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); | 
|  | 889 | INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); | 
|  | 890 |  | 
|  | 891 | ret = mcp251x_hw_reset(spi); | 
|  | 892 | if (ret) { | 
|  | 893 | mcp251x_open_clean(net); | 
|  | 894 | goto open_unlock; | 
|  | 895 | } | 
|  | 896 | ret = mcp251x_setup(net, priv, spi); | 
|  | 897 | if (ret) { | 
|  | 898 | mcp251x_open_clean(net); | 
|  | 899 | goto open_unlock; | 
|  | 900 | } | 
|  | 901 | ret = mcp251x_set_normal_mode(spi); | 
|  | 902 | if (ret) { | 
|  | 903 | mcp251x_open_clean(net); | 
|  | 904 | goto open_unlock; | 
|  | 905 | } | 
|  | 906 | netif_wake_queue(net); | 
|  | 907 |  | 
|  | 908 | open_unlock: | 
|  | 909 | mutex_unlock(&priv->mcp_lock); | 
|  | 910 | return ret; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 911 | } | 
|  | 912 |  | 
|  | 913 | static const struct net_device_ops mcp251x_netdev_ops = { | 
|  | 914 | .ndo_open = mcp251x_open, | 
|  | 915 | .ndo_stop = mcp251x_stop, | 
|  | 916 | .ndo_start_xmit = mcp251x_hard_start_xmit, | 
|  | 917 | }; | 
|  | 918 |  | 
|  | 919 | static int __devinit mcp251x_can_probe(struct spi_device *spi) | 
|  | 920 | { | 
|  | 921 | struct net_device *net; | 
|  | 922 | struct mcp251x_priv *priv; | 
|  | 923 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
| Marc Zyngier | e446630 | 2010-03-29 08:57:56 +0000 | [diff] [blame] | 924 | int model = spi_get_device_id(spi)->driver_data; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 925 | int ret = -ENODEV; | 
|  | 926 |  | 
|  | 927 | if (!pdata) | 
|  | 928 | /* Platform data is required for osc freq */ | 
|  | 929 | goto error_out; | 
|  | 930 |  | 
| Marc Zyngier | e446630 | 2010-03-29 08:57:56 +0000 | [diff] [blame] | 931 | if (model) | 
|  | 932 | pdata->model = model; | 
|  | 933 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 934 | /* Allocate can/net device */ | 
|  | 935 | net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX); | 
|  | 936 | if (!net) { | 
|  | 937 | ret = -ENOMEM; | 
|  | 938 | goto error_alloc; | 
|  | 939 | } | 
|  | 940 |  | 
|  | 941 | net->netdev_ops = &mcp251x_netdev_ops; | 
|  | 942 | net->flags |= IFF_ECHO; | 
|  | 943 |  | 
|  | 944 | priv = netdev_priv(net); | 
|  | 945 | priv->can.bittiming_const = &mcp251x_bittiming_const; | 
|  | 946 | priv->can.do_set_mode = mcp251x_do_set_mode; | 
|  | 947 | priv->can.clock.freq = pdata->oscillator_frequency / 2; | 
| Christian Pellegrin | ad72c34 | 2010-01-14 07:08:34 +0000 | [diff] [blame] | 948 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | | 
|  | 949 | CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY; | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 950 | priv->net = net; | 
|  | 951 | dev_set_drvdata(&spi->dev, priv); | 
|  | 952 |  | 
|  | 953 | priv->spi = spi; | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 954 | mutex_init(&priv->mcp_lock); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 955 |  | 
|  | 956 | /* If requested, allocate DMA buffers */ | 
|  | 957 | if (mcp251x_enable_dma) { | 
|  | 958 | spi->dev.coherent_dma_mask = ~0; | 
|  | 959 |  | 
|  | 960 | /* | 
|  | 961 | * Minimum coherent DMA allocation is PAGE_SIZE, so allocate | 
|  | 962 | * that much and share it between Tx and Rx DMA buffers. | 
|  | 963 | */ | 
|  | 964 | priv->spi_tx_buf = dma_alloc_coherent(&spi->dev, | 
|  | 965 | PAGE_SIZE, | 
|  | 966 | &priv->spi_tx_dma, | 
|  | 967 | GFP_DMA); | 
|  | 968 |  | 
|  | 969 | if (priv->spi_tx_buf) { | 
|  | 970 | priv->spi_rx_buf = (u8 *)(priv->spi_tx_buf + | 
|  | 971 | (PAGE_SIZE / 2)); | 
|  | 972 | priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma + | 
|  | 973 | (PAGE_SIZE / 2)); | 
|  | 974 | } else { | 
|  | 975 | /* Fall back to non-DMA */ | 
|  | 976 | mcp251x_enable_dma = 0; | 
|  | 977 | } | 
|  | 978 | } | 
|  | 979 |  | 
|  | 980 | /* Allocate non-DMA buffers */ | 
|  | 981 | if (!mcp251x_enable_dma) { | 
|  | 982 | priv->spi_tx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); | 
|  | 983 | if (!priv->spi_tx_buf) { | 
|  | 984 | ret = -ENOMEM; | 
|  | 985 | goto error_tx_buf; | 
|  | 986 | } | 
|  | 987 | priv->spi_rx_buf = kmalloc(SPI_TRANSFER_BUF_LEN, GFP_KERNEL); | 
| Julia Lawall | ce739b4 | 2009-12-27 11:27:44 +0000 | [diff] [blame] | 988 | if (!priv->spi_rx_buf) { | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 989 | ret = -ENOMEM; | 
|  | 990 | goto error_rx_buf; | 
|  | 991 | } | 
|  | 992 | } | 
|  | 993 |  | 
|  | 994 | if (pdata->power_enable) | 
|  | 995 | pdata->power_enable(1); | 
|  | 996 |  | 
|  | 997 | /* Call out to platform specific setup */ | 
|  | 998 | if (pdata->board_specific_setup) | 
|  | 999 | pdata->board_specific_setup(spi); | 
|  | 1000 |  | 
|  | 1001 | SET_NETDEV_DEV(net, &spi->dev); | 
|  | 1002 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1003 | /* Configure the SPI bus */ | 
|  | 1004 | spi->mode = SPI_MODE_0; | 
|  | 1005 | spi->bits_per_word = 8; | 
|  | 1006 | spi_setup(spi); | 
|  | 1007 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 1008 | /* Here is OK to not lock the MCP, no one knows about it yet */ | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1009 | if (!mcp251x_hw_probe(spi)) { | 
|  | 1010 | dev_info(&spi->dev, "Probe failed\n"); | 
|  | 1011 | goto error_probe; | 
|  | 1012 | } | 
|  | 1013 | mcp251x_hw_sleep(spi); | 
|  | 1014 |  | 
|  | 1015 | if (pdata->transceiver_enable) | 
|  | 1016 | pdata->transceiver_enable(0); | 
|  | 1017 |  | 
|  | 1018 | ret = register_candev(net); | 
|  | 1019 | if (!ret) { | 
|  | 1020 | dev_info(&spi->dev, "probed\n"); | 
|  | 1021 | return ret; | 
|  | 1022 | } | 
|  | 1023 | error_probe: | 
|  | 1024 | if (!mcp251x_enable_dma) | 
|  | 1025 | kfree(priv->spi_rx_buf); | 
|  | 1026 | error_rx_buf: | 
|  | 1027 | if (!mcp251x_enable_dma) | 
|  | 1028 | kfree(priv->spi_tx_buf); | 
|  | 1029 | error_tx_buf: | 
|  | 1030 | free_candev(net); | 
|  | 1031 | if (mcp251x_enable_dma) | 
|  | 1032 | dma_free_coherent(&spi->dev, PAGE_SIZE, | 
|  | 1033 | priv->spi_tx_buf, priv->spi_tx_dma); | 
|  | 1034 | error_alloc: | 
|  | 1035 | if (pdata->power_enable) | 
|  | 1036 | pdata->power_enable(0); | 
|  | 1037 | dev_err(&spi->dev, "probe failed\n"); | 
|  | 1038 | error_out: | 
|  | 1039 | return ret; | 
|  | 1040 | } | 
|  | 1041 |  | 
|  | 1042 | static int __devexit mcp251x_can_remove(struct spi_device *spi) | 
|  | 1043 | { | 
|  | 1044 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
|  | 1045 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 1046 | struct net_device *net = priv->net; | 
|  | 1047 |  | 
|  | 1048 | unregister_candev(net); | 
|  | 1049 | free_candev(net); | 
|  | 1050 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1051 | if (mcp251x_enable_dma) { | 
|  | 1052 | dma_free_coherent(&spi->dev, PAGE_SIZE, | 
|  | 1053 | priv->spi_tx_buf, priv->spi_tx_dma); | 
|  | 1054 | } else { | 
|  | 1055 | kfree(priv->spi_tx_buf); | 
|  | 1056 | kfree(priv->spi_rx_buf); | 
|  | 1057 | } | 
|  | 1058 |  | 
|  | 1059 | if (pdata->power_enable) | 
|  | 1060 | pdata->power_enable(0); | 
|  | 1061 |  | 
|  | 1062 | return 0; | 
|  | 1063 | } | 
|  | 1064 |  | 
|  | 1065 | #ifdef CONFIG_PM | 
|  | 1066 | static int mcp251x_can_suspend(struct spi_device *spi, pm_message_t state) | 
|  | 1067 | { | 
|  | 1068 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
|  | 1069 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 1070 | struct net_device *net = priv->net; | 
|  | 1071 |  | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 1072 | priv->force_quit = 1; | 
|  | 1073 | disable_irq(spi->irq); | 
|  | 1074 | /* | 
|  | 1075 | * Note: at this point neither IST nor workqueues are running. | 
|  | 1076 | * open/stop cannot be called anyway so locking is not needed | 
|  | 1077 | */ | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1078 | if (netif_running(net)) { | 
|  | 1079 | netif_device_detach(net); | 
|  | 1080 |  | 
|  | 1081 | mcp251x_hw_sleep(spi); | 
|  | 1082 | if (pdata->transceiver_enable) | 
|  | 1083 | pdata->transceiver_enable(0); | 
|  | 1084 | priv->after_suspend = AFTER_SUSPEND_UP; | 
|  | 1085 | } else { | 
|  | 1086 | priv->after_suspend = AFTER_SUSPEND_DOWN; | 
|  | 1087 | } | 
|  | 1088 |  | 
|  | 1089 | if (pdata->power_enable) { | 
|  | 1090 | pdata->power_enable(0); | 
|  | 1091 | priv->after_suspend |= AFTER_SUSPEND_POWER; | 
|  | 1092 | } | 
|  | 1093 |  | 
|  | 1094 | return 0; | 
|  | 1095 | } | 
|  | 1096 |  | 
|  | 1097 | static int mcp251x_can_resume(struct spi_device *spi) | 
|  | 1098 | { | 
|  | 1099 | struct mcp251x_platform_data *pdata = spi->dev.platform_data; | 
|  | 1100 | struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); | 
|  | 1101 |  | 
|  | 1102 | if (priv->after_suspend & AFTER_SUSPEND_POWER) { | 
|  | 1103 | pdata->power_enable(1); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 1104 | queue_work(priv->wq, &priv->restart_work); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1105 | } else { | 
|  | 1106 | if (priv->after_suspend & AFTER_SUSPEND_UP) { | 
|  | 1107 | if (pdata->transceiver_enable) | 
|  | 1108 | pdata->transceiver_enable(1); | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 1109 | queue_work(priv->wq, &priv->restart_work); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1110 | } else { | 
|  | 1111 | priv->after_suspend = 0; | 
|  | 1112 | } | 
|  | 1113 | } | 
| Christian Pellegrin | bf66f37 | 2010-02-03 07:39:54 +0000 | [diff] [blame] | 1114 | priv->force_quit = 0; | 
|  | 1115 | enable_irq(spi->irq); | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1116 | return 0; | 
|  | 1117 | } | 
|  | 1118 | #else | 
|  | 1119 | #define mcp251x_can_suspend NULL | 
|  | 1120 | #define mcp251x_can_resume NULL | 
|  | 1121 | #endif | 
|  | 1122 |  | 
| Marc Zyngier | e446630 | 2010-03-29 08:57:56 +0000 | [diff] [blame] | 1123 | static struct spi_device_id mcp251x_id_table[] = { | 
|  | 1124 | { "mcp251x", 	0 /* Use pdata.model */ }, | 
|  | 1125 | { "mcp2510",	CAN_MCP251X_MCP2510 }, | 
|  | 1126 | { "mcp2515",	CAN_MCP251X_MCP2515 }, | 
|  | 1127 | { }, | 
|  | 1128 | }; | 
|  | 1129 |  | 
|  | 1130 | MODULE_DEVICE_TABLE(spi, mcp251x_id_table); | 
|  | 1131 |  | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1132 | static struct spi_driver mcp251x_can_driver = { | 
|  | 1133 | .driver = { | 
|  | 1134 | .name = DEVICE_NAME, | 
|  | 1135 | .bus = &spi_bus_type, | 
|  | 1136 | .owner = THIS_MODULE, | 
|  | 1137 | }, | 
|  | 1138 |  | 
| Marc Zyngier | e446630 | 2010-03-29 08:57:56 +0000 | [diff] [blame] | 1139 | .id_table = mcp251x_id_table, | 
| Christian Pellegrin | e000016 | 2009-11-02 23:07:00 +0000 | [diff] [blame] | 1140 | .probe = mcp251x_can_probe, | 
|  | 1141 | .remove = __devexit_p(mcp251x_can_remove), | 
|  | 1142 | .suspend = mcp251x_can_suspend, | 
|  | 1143 | .resume = mcp251x_can_resume, | 
|  | 1144 | }; | 
|  | 1145 |  | 
|  | 1146 | static int __init mcp251x_can_init(void) | 
|  | 1147 | { | 
|  | 1148 | return spi_register_driver(&mcp251x_can_driver); | 
|  | 1149 | } | 
|  | 1150 |  | 
|  | 1151 | static void __exit mcp251x_can_exit(void) | 
|  | 1152 | { | 
|  | 1153 | spi_unregister_driver(&mcp251x_can_driver); | 
|  | 1154 | } | 
|  | 1155 |  | 
|  | 1156 | module_init(mcp251x_can_init); | 
|  | 1157 | module_exit(mcp251x_can_exit); | 
|  | 1158 |  | 
|  | 1159 | MODULE_AUTHOR("Chris Elston <celston@katalix.com>, " | 
|  | 1160 | "Christian Pellegrin <chripell@evolware.org>"); | 
|  | 1161 | MODULE_DESCRIPTION("Microchip 251x CAN driver"); | 
|  | 1162 | MODULE_LICENSE("GPL v2"); |