blob: 8039703481a74ba4f182c8ef726a7d8c6f001e6f [file] [log] [blame]
Barry Songbbb84612009-12-10 23:46:28 +00001/*
2 * Blackfin On-Chip CAN Driver
3 *
4 * Copyright 2004-2009 Analog Devices Inc.
5 *
6 * Enter bugs at http://blackfin.uclinux.org/
7 *
8 * Licensed under the GPL-2 or later.
9 */
10
11#include <linux/module.h>
Barry Songbbb84612009-12-10 23:46:28 +000012#include <linux/kernel.h>
13#include <linux/bitops.h>
14#include <linux/interrupt.h>
15#include <linux/errno.h>
16#include <linux/netdevice.h>
17#include <linux/skbuff.h>
18#include <linux/platform_device.h>
19
Barry Songbbb84612009-12-10 23:46:28 +000020#include <linux/can/dev.h>
21#include <linux/can/error.h>
22
Mike Frysinger21afc272010-03-21 21:06:01 +000023#include <asm/bfin_can.h>
Barry Songbbb84612009-12-10 23:46:28 +000024#include <asm/portmux.h>
25
26#define DRV_NAME "bfin_can"
27#define BFIN_CAN_TIMEOUT 100
Barry Songe9dcd162010-03-08 12:13:57 -080028#define TX_ECHO_SKB_MAX 1
Barry Songbbb84612009-12-10 23:46:28 +000029
30/*
Barry Songbbb84612009-12-10 23:46:28 +000031 * bfin can private data
32 */
33struct bfin_can_priv {
34 struct can_priv can; /* must be the first member */
35 struct net_device *dev;
36 void __iomem *membase;
37 int rx_irq;
38 int tx_irq;
39 int err_irq;
40 unsigned short *pin_list;
41};
42
43/*
44 * bfin can timing parameters
45 */
Marc Kleine-Budde194b9a42012-07-16 12:58:31 +020046static const struct can_bittiming_const bfin_can_bittiming_const = {
Barry Songbbb84612009-12-10 23:46:28 +000047 .name = DRV_NAME,
48 .tseg1_min = 1,
49 .tseg1_max = 16,
50 .tseg2_min = 1,
51 .tseg2_max = 8,
52 .sjw_max = 4,
53 /*
54 * Although the BRP field can be set to any value, it is recommended
55 * that the value be greater than or equal to 4, as restrictions
56 * apply to the bit timing configuration when BRP is less than 4.
57 */
58 .brp_min = 4,
59 .brp_max = 1024,
60 .brp_inc = 1,
61};
62
63static int bfin_can_set_bittiming(struct net_device *dev)
64{
65 struct bfin_can_priv *priv = netdev_priv(dev);
66 struct bfin_can_regs __iomem *reg = priv->membase;
67 struct can_bittiming *bt = &priv->can.bittiming;
68 u16 clk, timing;
69
70 clk = bt->brp - 1;
71 timing = ((bt->sjw - 1) << 8) | (bt->prop_seg + bt->phase_seg1 - 1) |
72 ((bt->phase_seg2 - 1) << 4);
73
74 /*
75 * If the SAM bit is set, the input signal is oversampled three times
76 * at the SCLK rate.
77 */
78 if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
79 timing |= SAM;
80
Aaron Wue4936e02015-02-10 17:40:34 +080081 writew(clk, &reg->clock);
82 writew(timing, &reg->timing);
Barry Songbbb84612009-12-10 23:46:28 +000083
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +010084 netdev_info(dev, "setting CLOCK=0x%04x TIMING=0x%04x\n", clk, timing);
Barry Songbbb84612009-12-10 23:46:28 +000085
86 return 0;
87}
88
89static void bfin_can_set_reset_mode(struct net_device *dev)
90{
91 struct bfin_can_priv *priv = netdev_priv(dev);
92 struct bfin_can_regs __iomem *reg = priv->membase;
93 int timeout = BFIN_CAN_TIMEOUT;
94 int i;
95
96 /* disable interrupts */
Aaron Wue4936e02015-02-10 17:40:34 +080097 writew(0, &reg->mbim1);
98 writew(0, &reg->mbim2);
99 writew(0, &reg->gim);
Barry Songbbb84612009-12-10 23:46:28 +0000100
101 /* reset can and enter configuration mode */
Aaron Wue4936e02015-02-10 17:40:34 +0800102 writew(SRS | CCR, &reg->control);
103 writew(CCR, &reg->control);
104 while (!(readw(&reg->control) & CCA)) {
Barry Songbbb84612009-12-10 23:46:28 +0000105 udelay(10);
106 if (--timeout == 0) {
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +0100107 netdev_err(dev, "fail to enter configuration mode\n");
Barry Songbbb84612009-12-10 23:46:28 +0000108 BUG();
109 }
110 }
111
112 /*
113 * All mailbox configurations are marked as inactive
114 * by writing to CAN Mailbox Configuration Registers 1 and 2
115 * For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
116 */
Aaron Wue4936e02015-02-10 17:40:34 +0800117 writew(0, &reg->mc1);
118 writew(0, &reg->mc2);
Barry Songbbb84612009-12-10 23:46:28 +0000119
120 /* Set Mailbox Direction */
Aaron Wue4936e02015-02-10 17:40:34 +0800121 writew(0xFFFF, &reg->md1); /* mailbox 1-16 are RX */
122 writew(0, &reg->md2); /* mailbox 17-32 are TX */
Barry Songbbb84612009-12-10 23:46:28 +0000123
124 /* RECEIVE_STD_CHL */
125 for (i = 0; i < 2; i++) {
Aaron Wue4936e02015-02-10 17:40:34 +0800126 writew(0, &reg->chl[RECEIVE_STD_CHL + i].id0);
127 writew(AME, &reg->chl[RECEIVE_STD_CHL + i].id1);
128 writew(0, &reg->chl[RECEIVE_STD_CHL + i].dlc);
129 writew(0x1FFF, &reg->msk[RECEIVE_STD_CHL + i].amh);
130 writew(0xFFFF, &reg->msk[RECEIVE_STD_CHL + i].aml);
Barry Songbbb84612009-12-10 23:46:28 +0000131 }
132
133 /* RECEIVE_EXT_CHL */
134 for (i = 0; i < 2; i++) {
Aaron Wue4936e02015-02-10 17:40:34 +0800135 writew(0, &reg->chl[RECEIVE_EXT_CHL + i].id0);
136 writew(AME | IDE, &reg->chl[RECEIVE_EXT_CHL + i].id1);
137 writew(0, &reg->chl[RECEIVE_EXT_CHL + i].dlc);
138 writew(0x1FFF, &reg->msk[RECEIVE_EXT_CHL + i].amh);
139 writew(0xFFFF, &reg->msk[RECEIVE_EXT_CHL + i].aml);
Barry Songbbb84612009-12-10 23:46:28 +0000140 }
141
Aaron Wue4936e02015-02-10 17:40:34 +0800142 writew(BIT(TRANSMIT_CHL - 16), &reg->mc2);
143 writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), &reg->mc1);
Barry Songbbb84612009-12-10 23:46:28 +0000144
145 priv->can.state = CAN_STATE_STOPPED;
146}
147
148static void bfin_can_set_normal_mode(struct net_device *dev)
149{
150 struct bfin_can_priv *priv = netdev_priv(dev);
151 struct bfin_can_regs __iomem *reg = priv->membase;
152 int timeout = BFIN_CAN_TIMEOUT;
153
154 /*
155 * leave configuration mode
156 */
Aaron Wue4936e02015-02-10 17:40:34 +0800157 writew(readw(&reg->control) & ~CCR, &reg->control);
Barry Songbbb84612009-12-10 23:46:28 +0000158
Aaron Wue4936e02015-02-10 17:40:34 +0800159 while (readw(&reg->status) & CCA) {
Barry Songbbb84612009-12-10 23:46:28 +0000160 udelay(10);
161 if (--timeout == 0) {
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +0100162 netdev_err(dev, "fail to leave configuration mode\n");
Barry Songbbb84612009-12-10 23:46:28 +0000163 BUG();
164 }
165 }
166
167 /*
168 * clear _All_ tx and rx interrupts
169 */
Aaron Wue4936e02015-02-10 17:40:34 +0800170 writew(0xFFFF, &reg->mbtif1);
171 writew(0xFFFF, &reg->mbtif2);
172 writew(0xFFFF, &reg->mbrif1);
173 writew(0xFFFF, &reg->mbrif2);
Barry Songbbb84612009-12-10 23:46:28 +0000174
175 /*
176 * clear global interrupt status register
177 */
Aaron Wue4936e02015-02-10 17:40:34 +0800178 writew(0x7FF, &reg->gis); /* overwrites with '1' */
Barry Songbbb84612009-12-10 23:46:28 +0000179
180 /*
181 * Initialize Interrupts
182 * - set bits in the mailbox interrupt mask register
183 * - global interrupt mask
184 */
Aaron Wue4936e02015-02-10 17:40:34 +0800185 writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), &reg->mbim1);
186 writew(BIT(TRANSMIT_CHL - 16), &reg->mbim2);
Barry Songbbb84612009-12-10 23:46:28 +0000187
Aaron Wue4936e02015-02-10 17:40:34 +0800188 writew(EPIM | BOIM | RMLIM, &reg->gim);
Barry Songbbb84612009-12-10 23:46:28 +0000189}
190
191static void bfin_can_start(struct net_device *dev)
192{
193 struct bfin_can_priv *priv = netdev_priv(dev);
194
195 /* enter reset mode */
196 if (priv->can.state != CAN_STATE_STOPPED)
197 bfin_can_set_reset_mode(dev);
198
199 /* leave reset mode */
200 bfin_can_set_normal_mode(dev);
201}
202
203static int bfin_can_set_mode(struct net_device *dev, enum can_mode mode)
204{
205 switch (mode) {
206 case CAN_MODE_START:
207 bfin_can_start(dev);
208 if (netif_queue_stopped(dev))
209 netif_wake_queue(dev);
210 break;
211
212 default:
213 return -EOPNOTSUPP;
214 }
215
216 return 0;
217}
218
Wolfgang Grandegger79d0d8a2012-02-01 11:14:13 +0100219static int bfin_can_get_berr_counter(const struct net_device *dev,
220 struct can_berr_counter *bec)
221{
222 struct bfin_can_priv *priv = netdev_priv(dev);
223 struct bfin_can_regs __iomem *reg = priv->membase;
224
Aaron Wue4936e02015-02-10 17:40:34 +0800225 u16 cec = readw(&reg->cec);
Wolfgang Grandegger79d0d8a2012-02-01 11:14:13 +0100226
227 bec->txerr = cec >> 8;
228 bec->rxerr = cec;
229
230 return 0;
231}
232
Barry Songbbb84612009-12-10 23:46:28 +0000233static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
234{
235 struct bfin_can_priv *priv = netdev_priv(dev);
236 struct bfin_can_regs __iomem *reg = priv->membase;
237 struct can_frame *cf = (struct can_frame *)skb->data;
238 u8 dlc = cf->can_dlc;
239 canid_t id = cf->can_id;
240 u8 *data = cf->data;
241 u16 val;
242 int i;
243
Oliver Hartkopp3ccd4c62010-01-12 02:00:46 -0800244 if (can_dropped_invalid_skb(dev, skb))
245 return NETDEV_TX_OK;
246
Barry Songbbb84612009-12-10 23:46:28 +0000247 netif_stop_queue(dev);
248
249 /* fill id */
250 if (id & CAN_EFF_FLAG) {
Aaron Wue4936e02015-02-10 17:40:34 +0800251 writew(id, &reg->chl[TRANSMIT_CHL].id0);
Mike Frysinger9118f082011-06-24 04:33:01 +0000252 val = ((id & 0x1FFF0000) >> 16) | IDE;
253 } else
254 val = (id << 2);
255 if (id & CAN_RTR_FLAG)
256 val |= RTR;
Aaron Wue4936e02015-02-10 17:40:34 +0800257 writew(val | AME, &reg->chl[TRANSMIT_CHL].id1);
Barry Songbbb84612009-12-10 23:46:28 +0000258
259 /* fill payload */
260 for (i = 0; i < 8; i += 2) {
261 val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
262 ((6 - i) < dlc ? (data[6 - i] << 8) : 0);
Aaron Wue4936e02015-02-10 17:40:34 +0800263 writew(val, &reg->chl[TRANSMIT_CHL].data[i]);
Barry Songbbb84612009-12-10 23:46:28 +0000264 }
265
266 /* fill data length code */
Aaron Wue4936e02015-02-10 17:40:34 +0800267 writew(dlc, &reg->chl[TRANSMIT_CHL].dlc);
Barry Songbbb84612009-12-10 23:46:28 +0000268
Barry Songbbb84612009-12-10 23:46:28 +0000269 can_put_echo_skb(skb, dev, 0);
270
271 /* set transmit request */
Aaron Wue4936e02015-02-10 17:40:34 +0800272 writew(BIT(TRANSMIT_CHL - 16), &reg->trs2);
Barry Songbbb84612009-12-10 23:46:28 +0000273
274 return 0;
275}
276
277static void bfin_can_rx(struct net_device *dev, u16 isrc)
278{
279 struct bfin_can_priv *priv = netdev_priv(dev);
280 struct net_device_stats *stats = &dev->stats;
281 struct bfin_can_regs __iomem *reg = priv->membase;
282 struct can_frame *cf;
283 struct sk_buff *skb;
284 int obj;
285 int i;
286 u16 val;
287
288 skb = alloc_can_skb(dev, &cf);
289 if (skb == NULL)
290 return;
291
292 /* get id */
293 if (isrc & BIT(RECEIVE_EXT_CHL)) {
294 /* extended frame format (EFF) */
Aaron Wue4936e02015-02-10 17:40:34 +0800295 cf->can_id = ((readw(&reg->chl[RECEIVE_EXT_CHL].id1)
Barry Songbbb84612009-12-10 23:46:28 +0000296 & 0x1FFF) << 16)
Aaron Wue4936e02015-02-10 17:40:34 +0800297 + readw(&reg->chl[RECEIVE_EXT_CHL].id0);
Barry Songbbb84612009-12-10 23:46:28 +0000298 cf->can_id |= CAN_EFF_FLAG;
299 obj = RECEIVE_EXT_CHL;
300 } else {
301 /* standard frame format (SFF) */
Aaron Wue4936e02015-02-10 17:40:34 +0800302 cf->can_id = (readw(&reg->chl[RECEIVE_STD_CHL].id1)
Barry Songbbb84612009-12-10 23:46:28 +0000303 & 0x1ffc) >> 2;
304 obj = RECEIVE_STD_CHL;
305 }
Aaron Wue4936e02015-02-10 17:40:34 +0800306 if (readw(&reg->chl[obj].id1) & RTR)
Barry Songbbb84612009-12-10 23:46:28 +0000307 cf->can_id |= CAN_RTR_FLAG;
308
309 /* get data length code */
Aaron Wue4936e02015-02-10 17:40:34 +0800310 cf->can_dlc = get_can_dlc(readw(&reg->chl[obj].dlc) & 0xF);
Barry Songbbb84612009-12-10 23:46:28 +0000311
312 /* get payload */
313 for (i = 0; i < 8; i += 2) {
Aaron Wue4936e02015-02-10 17:40:34 +0800314 val = readw(&reg->chl[obj].data[i]);
Barry Songbbb84612009-12-10 23:46:28 +0000315 cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
316 cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
317 }
318
319 netif_rx(skb);
320
321 stats->rx_packets++;
322 stats->rx_bytes += cf->can_dlc;
323}
324
325static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
326{
327 struct bfin_can_priv *priv = netdev_priv(dev);
328 struct bfin_can_regs __iomem *reg = priv->membase;
329 struct net_device_stats *stats = &dev->stats;
330 struct can_frame *cf;
331 struct sk_buff *skb;
332 enum can_state state = priv->can.state;
333
334 skb = alloc_can_err_skb(dev, &cf);
335 if (skb == NULL)
336 return -ENOMEM;
337
338 if (isrc & RMLIS) {
339 /* data overrun interrupt */
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +0100340 netdev_dbg(dev, "data overrun interrupt\n");
Barry Songbbb84612009-12-10 23:46:28 +0000341 cf->can_id |= CAN_ERR_CRTL;
342 cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
343 stats->rx_over_errors++;
344 stats->rx_errors++;
345 }
346
347 if (isrc & BOIS) {
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +0100348 netdev_dbg(dev, "bus-off mode interrupt\n");
Barry Songbbb84612009-12-10 23:46:28 +0000349 state = CAN_STATE_BUS_OFF;
350 cf->can_id |= CAN_ERR_BUSOFF;
Andri Yngvasonbe38a6f2015-01-16 14:30:28 +0000351 priv->can.can_stats.bus_off++;
Barry Songbbb84612009-12-10 23:46:28 +0000352 can_bus_off(dev);
353 }
354
355 if (isrc & EPIS) {
356 /* error passive interrupt */
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +0100357 netdev_dbg(dev, "error passive interrupt\n");
Barry Songbbb84612009-12-10 23:46:28 +0000358 state = CAN_STATE_ERROR_PASSIVE;
359 }
360
361 if ((isrc & EWTIS) || (isrc & EWRIS)) {
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +0100362 netdev_dbg(dev, "Error Warning Transmit/Receive Interrupt\n");
Barry Songbbb84612009-12-10 23:46:28 +0000363 state = CAN_STATE_ERROR_WARNING;
364 }
365
366 if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
367 state == CAN_STATE_ERROR_PASSIVE)) {
Aaron Wue4936e02015-02-10 17:40:34 +0800368 u16 cec = readw(&reg->cec);
Barry Songbbb84612009-12-10 23:46:28 +0000369 u8 rxerr = cec;
370 u8 txerr = cec >> 8;
371
372 cf->can_id |= CAN_ERR_CRTL;
373 if (state == CAN_STATE_ERROR_WARNING) {
374 priv->can.can_stats.error_warning++;
375 cf->data[1] = (txerr > rxerr) ?
376 CAN_ERR_CRTL_TX_WARNING :
377 CAN_ERR_CRTL_RX_WARNING;
378 } else {
379 priv->can.can_stats.error_passive++;
380 cf->data[1] = (txerr > rxerr) ?
381 CAN_ERR_CRTL_TX_PASSIVE :
382 CAN_ERR_CRTL_RX_PASSIVE;
383 }
384 }
385
386 if (status) {
387 priv->can.can_stats.bus_error++;
388
389 cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
390
391 if (status & BEF)
392 cf->data[2] |= CAN_ERR_PROT_BIT;
393 else if (status & FER)
394 cf->data[2] |= CAN_ERR_PROT_FORM;
395 else if (status & SER)
396 cf->data[2] |= CAN_ERR_PROT_STUFF;
397 else
398 cf->data[2] |= CAN_ERR_PROT_UNSPEC;
399 }
400
401 priv->can.state = state;
402
403 netif_rx(skb);
404
405 stats->rx_packets++;
406 stats->rx_bytes += cf->can_dlc;
407
408 return 0;
409}
410
Marc Kleine-Budde21c11bc2012-10-11 23:20:27 +0200411static irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
Barry Songbbb84612009-12-10 23:46:28 +0000412{
413 struct net_device *dev = dev_id;
414 struct bfin_can_priv *priv = netdev_priv(dev);
415 struct bfin_can_regs __iomem *reg = priv->membase;
416 struct net_device_stats *stats = &dev->stats;
417 u16 status, isrc;
418
Aaron Wue4936e02015-02-10 17:40:34 +0800419 if ((irq == priv->tx_irq) && readw(&reg->mbtif2)) {
Barry Songbbb84612009-12-10 23:46:28 +0000420 /* transmission complete interrupt */
Aaron Wue4936e02015-02-10 17:40:34 +0800421 writew(0xFFFF, &reg->mbtif2);
Barry Songbbb84612009-12-10 23:46:28 +0000422 stats->tx_packets++;
Aaron Wue4936e02015-02-10 17:40:34 +0800423 stats->tx_bytes += readw(&reg->chl[TRANSMIT_CHL].dlc);
Barry Songbbb84612009-12-10 23:46:28 +0000424 can_get_echo_skb(dev, 0);
425 netif_wake_queue(dev);
Aaron Wue4936e02015-02-10 17:40:34 +0800426 } else if ((irq == priv->rx_irq) && readw(&reg->mbrif1)) {
Barry Songbbb84612009-12-10 23:46:28 +0000427 /* receive interrupt */
Aaron Wue4936e02015-02-10 17:40:34 +0800428 isrc = readw(&reg->mbrif1);
429 writew(0xFFFF, &reg->mbrif1);
Barry Songbbb84612009-12-10 23:46:28 +0000430 bfin_can_rx(dev, isrc);
Aaron Wue4936e02015-02-10 17:40:34 +0800431 } else if ((irq == priv->err_irq) && readw(&reg->gis)) {
Barry Songbbb84612009-12-10 23:46:28 +0000432 /* error interrupt */
Aaron Wue4936e02015-02-10 17:40:34 +0800433 isrc = readw(&reg->gis);
434 status = readw(&reg->esr);
435 writew(0x7FF, &reg->gis);
Barry Songbbb84612009-12-10 23:46:28 +0000436 bfin_can_err(dev, isrc, status);
437 } else {
438 return IRQ_NONE;
439 }
440
441 return IRQ_HANDLED;
442}
443
444static int bfin_can_open(struct net_device *dev)
445{
446 struct bfin_can_priv *priv = netdev_priv(dev);
447 int err;
448
449 /* set chip into reset mode */
450 bfin_can_set_reset_mode(dev);
451
452 /* common open */
453 err = open_candev(dev);
454 if (err)
455 goto exit_open;
456
457 /* register interrupt handler */
458 err = request_irq(priv->rx_irq, &bfin_can_interrupt, 0,
459 "bfin-can-rx", dev);
460 if (err)
461 goto exit_rx_irq;
462 err = request_irq(priv->tx_irq, &bfin_can_interrupt, 0,
463 "bfin-can-tx", dev);
464 if (err)
465 goto exit_tx_irq;
466 err = request_irq(priv->err_irq, &bfin_can_interrupt, 0,
467 "bfin-can-err", dev);
468 if (err)
469 goto exit_err_irq;
470
471 bfin_can_start(dev);
472
473 netif_start_queue(dev);
474
475 return 0;
476
477exit_err_irq:
478 free_irq(priv->tx_irq, dev);
479exit_tx_irq:
480 free_irq(priv->rx_irq, dev);
481exit_rx_irq:
482 close_candev(dev);
483exit_open:
484 return err;
485}
486
487static int bfin_can_close(struct net_device *dev)
488{
489 struct bfin_can_priv *priv = netdev_priv(dev);
490
491 netif_stop_queue(dev);
492 bfin_can_set_reset_mode(dev);
493
494 close_candev(dev);
495
496 free_irq(priv->rx_irq, dev);
497 free_irq(priv->tx_irq, dev);
498 free_irq(priv->err_irq, dev);
499
500 return 0;
501}
502
Marc Kleine-Budde21c11bc2012-10-11 23:20:27 +0200503static struct net_device *alloc_bfin_candev(void)
Barry Songbbb84612009-12-10 23:46:28 +0000504{
505 struct net_device *dev;
506 struct bfin_can_priv *priv;
507
Barry Songe9dcd162010-03-08 12:13:57 -0800508 dev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);
Barry Songbbb84612009-12-10 23:46:28 +0000509 if (!dev)
510 return NULL;
511
512 priv = netdev_priv(dev);
513
514 priv->dev = dev;
515 priv->can.bittiming_const = &bfin_can_bittiming_const;
516 priv->can.do_set_bittiming = bfin_can_set_bittiming;
517 priv->can.do_set_mode = bfin_can_set_mode;
Wolfgang Grandegger79d0d8a2012-02-01 11:14:13 +0100518 priv->can.do_get_berr_counter = bfin_can_get_berr_counter;
Christian Pellegrinad72c342010-01-14 07:08:34 +0000519 priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
Barry Songbbb84612009-12-10 23:46:28 +0000520
521 return dev;
522}
523
524static const struct net_device_ops bfin_can_netdev_ops = {
525 .ndo_open = bfin_can_open,
526 .ndo_stop = bfin_can_close,
527 .ndo_start_xmit = bfin_can_start_xmit,
Oliver Hartkoppc971fa22014-03-07 09:23:41 +0100528 .ndo_change_mtu = can_change_mtu,
Barry Songbbb84612009-12-10 23:46:28 +0000529};
530
Bill Pemberton3c8ac0f2012-12-03 09:22:44 -0500531static int bfin_can_probe(struct platform_device *pdev)
Barry Songbbb84612009-12-10 23:46:28 +0000532{
533 int err;
534 struct net_device *dev;
535 struct bfin_can_priv *priv;
536 struct resource *res_mem, *rx_irq, *tx_irq, *err_irq;
537 unsigned short *pdata;
538
Jingoo Han321165c2013-09-10 17:40:42 +0900539 pdata = dev_get_platdata(&pdev->dev);
Barry Songbbb84612009-12-10 23:46:28 +0000540 if (!pdata) {
541 dev_err(&pdev->dev, "No platform data provided!\n");
542 err = -EINVAL;
543 goto exit;
544 }
545
546 res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
547 rx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
548 tx_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
549 err_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
550 if (!res_mem || !rx_irq || !tx_irq || !err_irq) {
551 err = -EINVAL;
552 goto exit;
553 }
554
Barry Songbbb84612009-12-10 23:46:28 +0000555 /* request peripheral pins */
556 err = peripheral_request_list(pdata, dev_name(&pdev->dev));
557 if (err)
Aaron Wudead8382015-02-10 17:40:35 +0800558 goto exit;
Barry Songbbb84612009-12-10 23:46:28 +0000559
560 dev = alloc_bfin_candev();
561 if (!dev) {
562 err = -ENOMEM;
563 goto exit_peri_pin_free;
564 }
565
566 priv = netdev_priv(dev);
Aaron Wudead8382015-02-10 17:40:35 +0800567
568 priv->membase = devm_ioremap_resource(&pdev->dev, res_mem);
569 if (IS_ERR(priv->membase)) {
570 err = PTR_ERR(priv->membase);
571 goto exit_peri_pin_free;
572 }
573
Barry Songbbb84612009-12-10 23:46:28 +0000574 priv->rx_irq = rx_irq->start;
575 priv->tx_irq = tx_irq->start;
576 priv->err_irq = err_irq->start;
577 priv->pin_list = pdata;
578 priv->can.clock.freq = get_sclk();
579
Jingoo Han00e4bbc2013-05-23 19:47:58 +0900580 platform_set_drvdata(pdev, dev);
Barry Songbbb84612009-12-10 23:46:28 +0000581 SET_NETDEV_DEV(dev, &pdev->dev);
582
583 dev->flags |= IFF_ECHO; /* we support local echo */
584 dev->netdev_ops = &bfin_can_netdev_ops;
585
586 bfin_can_set_reset_mode(dev);
587
588 err = register_candev(dev);
589 if (err) {
590 dev_err(&pdev->dev, "registering failed (err=%d)\n", err);
591 goto exit_candev_free;
592 }
593
594 dev_info(&pdev->dev,
595 "%s device registered"
596 "(&reg_base=%p, rx_irq=%d, tx_irq=%d, err_irq=%d, sclk=%d)\n",
Joe Perchesc2fd03a2012-06-04 12:44:18 +0000597 DRV_NAME, priv->membase, priv->rx_irq,
Barry Songbbb84612009-12-10 23:46:28 +0000598 priv->tx_irq, priv->err_irq, priv->can.clock.freq);
599 return 0;
600
601exit_candev_free:
602 free_candev(dev);
603exit_peri_pin_free:
604 peripheral_free_list(pdata);
Barry Songbbb84612009-12-10 23:46:28 +0000605exit:
606 return err;
607}
608
Bill Pemberton3c8ac0f2012-12-03 09:22:44 -0500609static int bfin_can_remove(struct platform_device *pdev)
Barry Songbbb84612009-12-10 23:46:28 +0000610{
Jingoo Han00e4bbc2013-05-23 19:47:58 +0900611 struct net_device *dev = platform_get_drvdata(pdev);
Barry Songbbb84612009-12-10 23:46:28 +0000612 struct bfin_can_priv *priv = netdev_priv(dev);
Barry Songbbb84612009-12-10 23:46:28 +0000613
614 bfin_can_set_reset_mode(dev);
615
616 unregister_candev(dev);
617
Barry Songbbb84612009-12-10 23:46:28 +0000618 peripheral_free_list(priv->pin_list);
619
620 free_candev(dev);
621 return 0;
622}
623
624#ifdef CONFIG_PM
625static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
626{
Jingoo Han00e4bbc2013-05-23 19:47:58 +0900627 struct net_device *dev = platform_get_drvdata(pdev);
Barry Songbbb84612009-12-10 23:46:28 +0000628 struct bfin_can_priv *priv = netdev_priv(dev);
629 struct bfin_can_regs __iomem *reg = priv->membase;
630 int timeout = BFIN_CAN_TIMEOUT;
631
632 if (netif_running(dev)) {
633 /* enter sleep mode */
Aaron Wue4936e02015-02-10 17:40:34 +0800634 writew(readw(&reg->control) | SMR, &reg->control);
635 while (!(readw(&reg->intr) & SMACK)) {
Barry Songbbb84612009-12-10 23:46:28 +0000636 udelay(10);
637 if (--timeout == 0) {
Wolfgang Grandeggeraabdfd62012-02-01 11:02:05 +0100638 netdev_err(dev, "fail to enter sleep mode\n");
Barry Songbbb84612009-12-10 23:46:28 +0000639 BUG();
640 }
641 }
642 }
643
644 return 0;
645}
646
647static int bfin_can_resume(struct platform_device *pdev)
648{
Jingoo Han00e4bbc2013-05-23 19:47:58 +0900649 struct net_device *dev = platform_get_drvdata(pdev);
Barry Songbbb84612009-12-10 23:46:28 +0000650 struct bfin_can_priv *priv = netdev_priv(dev);
651 struct bfin_can_regs __iomem *reg = priv->membase;
652
653 if (netif_running(dev)) {
654 /* leave sleep mode */
Aaron Wue4936e02015-02-10 17:40:34 +0800655 writew(0, &reg->intr);
Barry Songbbb84612009-12-10 23:46:28 +0000656 }
657
658 return 0;
659}
660#else
661#define bfin_can_suspend NULL
662#define bfin_can_resume NULL
663#endif /* CONFIG_PM */
664
665static struct platform_driver bfin_can_driver = {
666 .probe = bfin_can_probe,
Bill Pemberton3c8ac0f2012-12-03 09:22:44 -0500667 .remove = bfin_can_remove,
Barry Songbbb84612009-12-10 23:46:28 +0000668 .suspend = bfin_can_suspend,
669 .resume = bfin_can_resume,
670 .driver = {
671 .name = DRV_NAME,
Barry Songbbb84612009-12-10 23:46:28 +0000672 },
673};
674
Axel Lin871d3372011-11-27 15:42:31 +0000675module_platform_driver(bfin_can_driver);
Barry Songbbb84612009-12-10 23:46:28 +0000676
677MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
678MODULE_LICENSE("GPL");
679MODULE_DESCRIPTION("Blackfin on-chip CAN netdevice driver");
Marc Kleine-Budde73ae9492012-10-12 09:45:14 +0200680MODULE_ALIAS("platform:" DRV_NAME);