diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2011-03-25 11:41:20 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2011-03-25 11:41:20 -0400 |
commit | 7bf7e370d5919112c223a269462cd0b546903829 (patch) | |
tree | 03ccc715239df14ae168277dbccc9d9cf4d8a2c8 /drivers/net/can | |
parent | 68b1a1e786f29c900fa1c516a402e24f0ece622a (diff) | |
parent | d39dd11c3e6a7af5c20bfac40594db36cf270f42 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-linus-1
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6: (9356 commits)
[media] rc: update for bitop name changes
fs: simplify iget & friends
fs: pull inode->i_lock up out of writeback_single_inode
fs: rename inode_lock to inode_hash_lock
fs: move i_wb_list out from under inode_lock
fs: move i_sb_list out from under inode_lock
fs: remove inode_lock from iput_final and prune_icache
fs: Lock the inode LRU list separately
fs: factor inode disposal
fs: protect inode->i_state with inode->i_lock
lib, arch: add filter argument to show_mem and fix private implementations
SLUB: Write to per cpu data when allocating it
slub: Fix debugobjects with lockless fastpath
autofs4: Do not potentially dereference NULL pointer returned by fget() in autofs_dev_ioctl_setpipefd()
autofs4 - remove autofs4_lock
autofs4 - fix d_manage() return on rcu-walk
autofs4 - fix autofs4_expire_indirect() traversal
autofs4 - fix dentry leak in autofs4_expire_direct()
autofs4 - reinstate last used update on access
vfs - check non-mountpoint dentry might block in __follow_mount_rcu()
...
NOTE!
This merge commit was created to fix compilation error. The block
tree was merged upstream and removed the 'elv_queue_empty()'
function which the new 'mtdswap' driver is using. So a simple
merge of the mtd tree with upstream does not compile. And the
mtd tree has already be published, so re-basing it is not an option.
To fix this unfortunate situation, I had to merge upstream into the
mtd-2.6.git tree without committing, put the fixup patch on top of
this, and then commit this. The result is that we do not have commits
which do not compile.
In other words, this merge commit "merges" 3 things: the MTD tree, the
upstream tree, and the fixup patch.
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/Kconfig | 6 | ||||
-rw-r--r-- | drivers/net/can/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/can/at91_can.c | 138 | ||||
-rw-r--r-- | drivers/net/can/c_can/Kconfig | 15 | ||||
-rw-r--r-- | drivers/net/can/c_can/Makefile | 8 | ||||
-rw-r--r-- | drivers/net/can/c_can/c_can.c | 1158 | ||||
-rw-r--r-- | drivers/net/can/c_can/c_can.h | 86 | ||||
-rw-r--r-- | drivers/net/can/c_can/c_can_platform.c | 215 | ||||
-rw-r--r-- | drivers/net/can/janz-ican3.c | 5 | ||||
-rw-r--r-- | drivers/net/can/mcp251x.c | 2 | ||||
-rw-r--r-- | drivers/net/can/mscan/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/can/mscan/mpc5xxx_can.c | 15 | ||||
-rw-r--r-- | drivers/net/can/pch_can.c | 5 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000_of_platform.c | 9 | ||||
-rw-r--r-- | drivers/net/can/softing/Kconfig | 30 | ||||
-rw-r--r-- | drivers/net/can/softing/Makefile | 6 | ||||
-rw-r--r-- | drivers/net/can/softing/softing.h | 167 | ||||
-rw-r--r-- | drivers/net/can/softing/softing_cs.c | 360 | ||||
-rw-r--r-- | drivers/net/can/softing/softing_fw.c | 691 | ||||
-rw-r--r-- | drivers/net/can/softing/softing_main.c | 894 | ||||
-rw-r--r-- | drivers/net/can/softing/softing_platform.h | 40 | ||||
-rw-r--r-- | drivers/net/can/usb/esd_usb2.c | 6 |
22 files changed, 3813 insertions, 47 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index d5a9db60ade9..1d699e3df547 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig | |||
@@ -23,7 +23,7 @@ config CAN_SLCAN | |||
23 | 23 | ||
24 | As only the sending and receiving of CAN frames is implemented, this | 24 | As only the sending and receiving of CAN frames is implemented, this |
25 | driver should work with the (serial/USB) CAN hardware from: | 25 | driver should work with the (serial/USB) CAN hardware from: |
26 | www.canusb.com / www.can232.com / www.mictronic.com / www.canhack.de | 26 | www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de |
27 | 27 | ||
28 | Userspace tools to attach the SLCAN line discipline (slcan_attach, | 28 | Userspace tools to attach the SLCAN line discipline (slcan_attach, |
29 | slcand) can be found in the can-utils at the SocketCAN SVN, see | 29 | slcand) can be found in the can-utils at the SocketCAN SVN, see |
@@ -115,8 +115,12 @@ source "drivers/net/can/mscan/Kconfig" | |||
115 | 115 | ||
116 | source "drivers/net/can/sja1000/Kconfig" | 116 | source "drivers/net/can/sja1000/Kconfig" |
117 | 117 | ||
118 | source "drivers/net/can/c_can/Kconfig" | ||
119 | |||
118 | source "drivers/net/can/usb/Kconfig" | 120 | source "drivers/net/can/usb/Kconfig" |
119 | 121 | ||
122 | source "drivers/net/can/softing/Kconfig" | ||
123 | |||
120 | config CAN_DEBUG_DEVICES | 124 | config CAN_DEBUG_DEVICES |
121 | bool "CAN devices debugging messages" | 125 | bool "CAN devices debugging messages" |
122 | depends on CAN | 126 | depends on CAN |
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 07ca159ba3f9..24ebfe8d758a 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile | |||
@@ -9,9 +9,11 @@ obj-$(CONFIG_CAN_DEV) += can-dev.o | |||
9 | can-dev-y := dev.o | 9 | can-dev-y := dev.o |
10 | 10 | ||
11 | obj-y += usb/ | 11 | obj-y += usb/ |
12 | obj-y += softing/ | ||
12 | 13 | ||
13 | obj-$(CONFIG_CAN_SJA1000) += sja1000/ | 14 | obj-$(CONFIG_CAN_SJA1000) += sja1000/ |
14 | obj-$(CONFIG_CAN_MSCAN) += mscan/ | 15 | obj-$(CONFIG_CAN_MSCAN) += mscan/ |
16 | obj-$(CONFIG_CAN_C_CAN) += c_can/ | ||
15 | obj-$(CONFIG_CAN_AT91) += at91_can.o | 17 | obj-$(CONFIG_CAN_AT91) += at91_can.o |
16 | obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o | 18 | obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o |
17 | obj-$(CONFIG_CAN_MCP251X) += mcp251x.o | 19 | obj-$(CONFIG_CAN_MCP251X) += mcp251x.o |
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 7ef83d06f7ed..57d2ffbbb433 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * at91_can.c - CAN network driver for AT91 SoC CAN controller | 2 | * at91_can.c - CAN network driver for AT91 SoC CAN controller |
3 | * | 3 | * |
4 | * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> | 4 | * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> |
5 | * (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de> | 5 | * (C) 2008, 2009, 2010, 2011 by Marc Kleine-Budde <kernel@pengutronix.de> |
6 | * | 6 | * |
7 | * This software may be distributed under the terms of the GNU General | 7 | * This software may be distributed under the terms of the GNU General |
8 | * Public License ("GPL") version 2 as distributed in the 'COPYING' | 8 | * Public License ("GPL") version 2 as distributed in the 'COPYING' |
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/netdevice.h> | 31 | #include <linux/netdevice.h> |
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/rtnetlink.h> | ||
33 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
34 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
35 | #include <linux/string.h> | 36 | #include <linux/string.h> |
@@ -40,22 +41,23 @@ | |||
40 | 41 | ||
41 | #include <mach/board.h> | 42 | #include <mach/board.h> |
42 | 43 | ||
43 | #define AT91_NAPI_WEIGHT 12 | 44 | #define AT91_NAPI_WEIGHT 11 |
44 | 45 | ||
45 | /* | 46 | /* |
46 | * RX/TX Mailbox split | 47 | * RX/TX Mailbox split |
47 | * don't dare to touch | 48 | * don't dare to touch |
48 | */ | 49 | */ |
49 | #define AT91_MB_RX_NUM 12 | 50 | #define AT91_MB_RX_NUM 11 |
50 | #define AT91_MB_TX_SHIFT 2 | 51 | #define AT91_MB_TX_SHIFT 2 |
51 | 52 | ||
52 | #define AT91_MB_RX_FIRST 0 | 53 | #define AT91_MB_RX_FIRST 1 |
53 | #define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1) | 54 | #define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1) |
54 | 55 | ||
55 | #define AT91_MB_RX_MASK(i) ((1 << (i)) - 1) | 56 | #define AT91_MB_RX_MASK(i) ((1 << (i)) - 1) |
56 | #define AT91_MB_RX_SPLIT 8 | 57 | #define AT91_MB_RX_SPLIT 8 |
57 | #define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1) | 58 | #define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1) |
58 | #define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT)) | 59 | #define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \ |
60 | ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST)) | ||
59 | 61 | ||
60 | #define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT) | 62 | #define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT) |
61 | #define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1) | 63 | #define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1) |
@@ -168,6 +170,8 @@ struct at91_priv { | |||
168 | 170 | ||
169 | struct clk *clk; | 171 | struct clk *clk; |
170 | struct at91_can_data *pdata; | 172 | struct at91_can_data *pdata; |
173 | |||
174 | canid_t mb0_id; | ||
171 | }; | 175 | }; |
172 | 176 | ||
173 | static struct can_bittiming_const at91_bittiming_const = { | 177 | static struct can_bittiming_const at91_bittiming_const = { |
@@ -220,6 +224,18 @@ static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb, | |||
220 | set_mb_mode_prio(priv, mb, mode, 0); | 224 | set_mb_mode_prio(priv, mb, mode, 0); |
221 | } | 225 | } |
222 | 226 | ||
227 | static inline u32 at91_can_id_to_reg_mid(canid_t can_id) | ||
228 | { | ||
229 | u32 reg_mid; | ||
230 | |||
231 | if (can_id & CAN_EFF_FLAG) | ||
232 | reg_mid = (can_id & CAN_EFF_MASK) | AT91_MID_MIDE; | ||
233 | else | ||
234 | reg_mid = (can_id & CAN_SFF_MASK) << 18; | ||
235 | |||
236 | return reg_mid; | ||
237 | } | ||
238 | |||
223 | /* | 239 | /* |
224 | * Swtich transceiver on or off | 240 | * Swtich transceiver on or off |
225 | */ | 241 | */ |
@@ -233,12 +249,22 @@ static void at91_setup_mailboxes(struct net_device *dev) | |||
233 | { | 249 | { |
234 | struct at91_priv *priv = netdev_priv(dev); | 250 | struct at91_priv *priv = netdev_priv(dev); |
235 | unsigned int i; | 251 | unsigned int i; |
252 | u32 reg_mid; | ||
236 | 253 | ||
237 | /* | 254 | /* |
238 | * The first 12 mailboxes are used as a reception FIFO. The | 255 | * Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first |
239 | * last mailbox is configured with overwrite option. The | 256 | * mailbox is disabled. The next 11 mailboxes are used as a |
240 | * overwrite flag indicates a FIFO overflow. | 257 | * reception FIFO. The last mailbox is configured with |
258 | * overwrite option. The overwrite flag indicates a FIFO | ||
259 | * overflow. | ||
241 | */ | 260 | */ |
261 | reg_mid = at91_can_id_to_reg_mid(priv->mb0_id); | ||
262 | for (i = 0; i < AT91_MB_RX_FIRST; i++) { | ||
263 | set_mb_mode(priv, i, AT91_MB_MODE_DISABLED); | ||
264 | at91_write(priv, AT91_MID(i), reg_mid); | ||
265 | at91_write(priv, AT91_MCR(i), 0x0); /* clear dlc */ | ||
266 | } | ||
267 | |||
242 | for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++) | 268 | for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++) |
243 | set_mb_mode(priv, i, AT91_MB_MODE_RX); | 269 | set_mb_mode(priv, i, AT91_MB_MODE_RX); |
244 | set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR); | 270 | set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR); |
@@ -254,7 +280,8 @@ static void at91_setup_mailboxes(struct net_device *dev) | |||
254 | set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0); | 280 | set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0); |
255 | 281 | ||
256 | /* Reset tx and rx helper pointers */ | 282 | /* Reset tx and rx helper pointers */ |
257 | priv->tx_next = priv->tx_echo = priv->rx_next = 0; | 283 | priv->tx_next = priv->tx_echo = 0; |
284 | priv->rx_next = AT91_MB_RX_FIRST; | ||
258 | } | 285 | } |
259 | 286 | ||
260 | static int at91_set_bittiming(struct net_device *dev) | 287 | static int at91_set_bittiming(struct net_device *dev) |
@@ -372,12 +399,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
372 | netdev_err(dev, "BUG! TX buffer full when queue awake!\n"); | 399 | netdev_err(dev, "BUG! TX buffer full when queue awake!\n"); |
373 | return NETDEV_TX_BUSY; | 400 | return NETDEV_TX_BUSY; |
374 | } | 401 | } |
375 | 402 | reg_mid = at91_can_id_to_reg_mid(cf->can_id); | |
376 | if (cf->can_id & CAN_EFF_FLAG) | ||
377 | reg_mid = (cf->can_id & CAN_EFF_MASK) | AT91_MID_MIDE; | ||
378 | else | ||
379 | reg_mid = (cf->can_id & CAN_SFF_MASK) << 18; | ||
380 | |||
381 | reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) | | 403 | reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) | |
382 | (cf->can_dlc << 16) | AT91_MCR_MTCR; | 404 | (cf->can_dlc << 16) | AT91_MCR_MTCR; |
383 | 405 | ||
@@ -539,27 +561,31 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb) | |||
539 | * | 561 | * |
540 | * Theory of Operation: | 562 | * Theory of Operation: |
541 | * | 563 | * |
542 | * 12 of the 16 mailboxes on the chip are reserved for RX. we split | 564 | * 11 of the 16 mailboxes on the chip are reserved for RX. we split |
543 | * them into 2 groups. The lower group holds 8 and upper 4 mailboxes. | 565 | * them into 2 groups. The lower group holds 7 and upper 4 mailboxes. |
544 | * | 566 | * |
545 | * Like it or not, but the chip always saves a received CAN message | 567 | * Like it or not, but the chip always saves a received CAN message |
546 | * into the first free mailbox it finds (starting with the | 568 | * into the first free mailbox it finds (starting with the |
547 | * lowest). This makes it very difficult to read the messages in the | 569 | * lowest). This makes it very difficult to read the messages in the |
548 | * right order from the chip. This is how we work around that problem: | 570 | * right order from the chip. This is how we work around that problem: |
549 | * | 571 | * |
550 | * The first message goes into mb nr. 0 and issues an interrupt. All | 572 | * The first message goes into mb nr. 1 and issues an interrupt. All |
551 | * rx ints are disabled in the interrupt handler and a napi poll is | 573 | * rx ints are disabled in the interrupt handler and a napi poll is |
552 | * scheduled. We read the mailbox, but do _not_ reenable the mb (to | 574 | * scheduled. We read the mailbox, but do _not_ reenable the mb (to |
553 | * receive another message). | 575 | * receive another message). |
554 | * | 576 | * |
555 | * lower mbxs upper | 577 | * lower mbxs upper |
556 | * ______^______ __^__ | 578 | * ____^______ __^__ |
557 | * / \ / \ | 579 | * / \ / \ |
558 | * +-+-+-+-+-+-+-+-++-+-+-+-+ | 580 | * +-+-+-+-+-+-+-+-++-+-+-+-+ |
559 | * |x|x|x|x|x|x|x|x|| | | | | | 581 | * | |x|x|x|x|x|x|x|| | | | | |
560 | * +-+-+-+-+-+-+-+-++-+-+-+-+ | 582 | * +-+-+-+-+-+-+-+-++-+-+-+-+ |
561 | * 0 0 0 0 0 0 0 0 0 0 1 1 \ mail | 583 | * 0 0 0 0 0 0 0 0 0 0 1 1 \ mail |
562 | * 0 1 2 3 4 5 6 7 8 9 0 1 / box | 584 | * 0 1 2 3 4 5 6 7 8 9 0 1 / box |
585 | * ^ | ||
586 | * | | ||
587 | * \ | ||
588 | * unused, due to chip bug | ||
563 | * | 589 | * |
564 | * The variable priv->rx_next points to the next mailbox to read a | 590 | * The variable priv->rx_next points to the next mailbox to read a |
565 | * message from. As long we're in the lower mailboxes we just read the | 591 | * message from. As long we're in the lower mailboxes we just read the |
@@ -590,10 +616,10 @@ static int at91_poll_rx(struct net_device *dev, int quota) | |||
590 | "order of incoming frames cannot be guaranteed\n"); | 616 | "order of incoming frames cannot be guaranteed\n"); |
591 | 617 | ||
592 | again: | 618 | again: |
593 | for (mb = find_next_bit(addr, AT91_MB_RX_NUM, priv->rx_next); | 619 | for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next); |
594 | mb < AT91_MB_RX_NUM && quota > 0; | 620 | mb < AT91_MB_RX_LAST + 1 && quota > 0; |
595 | reg_sr = at91_read(priv, AT91_SR), | 621 | reg_sr = at91_read(priv, AT91_SR), |
596 | mb = find_next_bit(addr, AT91_MB_RX_NUM, ++priv->rx_next)) { | 622 | mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) { |
597 | at91_read_msg(dev, mb); | 623 | at91_read_msg(dev, mb); |
598 | 624 | ||
599 | /* reactivate mailboxes */ | 625 | /* reactivate mailboxes */ |
@@ -610,8 +636,8 @@ static int at91_poll_rx(struct net_device *dev, int quota) | |||
610 | 636 | ||
611 | /* upper group completed, look again in lower */ | 637 | /* upper group completed, look again in lower */ |
612 | if (priv->rx_next > AT91_MB_RX_LOW_LAST && | 638 | if (priv->rx_next > AT91_MB_RX_LOW_LAST && |
613 | quota > 0 && mb >= AT91_MB_RX_NUM) { | 639 | quota > 0 && mb > AT91_MB_RX_LAST) { |
614 | priv->rx_next = 0; | 640 | priv->rx_next = AT91_MB_RX_FIRST; |
615 | goto again; | 641 | goto again; |
616 | } | 642 | } |
617 | 643 | ||
@@ -1037,6 +1063,64 @@ static const struct net_device_ops at91_netdev_ops = { | |||
1037 | .ndo_start_xmit = at91_start_xmit, | 1063 | .ndo_start_xmit = at91_start_xmit, |
1038 | }; | 1064 | }; |
1039 | 1065 | ||
1066 | static ssize_t at91_sysfs_show_mb0_id(struct device *dev, | ||
1067 | struct device_attribute *attr, char *buf) | ||
1068 | { | ||
1069 | struct at91_priv *priv = netdev_priv(to_net_dev(dev)); | ||
1070 | |||
1071 | if (priv->mb0_id & CAN_EFF_FLAG) | ||
1072 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", priv->mb0_id); | ||
1073 | else | ||
1074 | return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id); | ||
1075 | } | ||
1076 | |||
1077 | static ssize_t at91_sysfs_set_mb0_id(struct device *dev, | ||
1078 | struct device_attribute *attr, const char *buf, size_t count) | ||
1079 | { | ||
1080 | struct net_device *ndev = to_net_dev(dev); | ||
1081 | struct at91_priv *priv = netdev_priv(ndev); | ||
1082 | unsigned long can_id; | ||
1083 | ssize_t ret; | ||
1084 | int err; | ||
1085 | |||
1086 | rtnl_lock(); | ||
1087 | |||
1088 | if (ndev->flags & IFF_UP) { | ||
1089 | ret = -EBUSY; | ||
1090 | goto out; | ||
1091 | } | ||
1092 | |||
1093 | err = strict_strtoul(buf, 0, &can_id); | ||
1094 | if (err) { | ||
1095 | ret = err; | ||
1096 | goto out; | ||
1097 | } | ||
1098 | |||
1099 | if (can_id & CAN_EFF_FLAG) | ||
1100 | can_id &= CAN_EFF_MASK | CAN_EFF_FLAG; | ||
1101 | else | ||
1102 | can_id &= CAN_SFF_MASK; | ||
1103 | |||
1104 | priv->mb0_id = can_id; | ||
1105 | ret = count; | ||
1106 | |||
1107 | out: | ||
1108 | rtnl_unlock(); | ||
1109 | return ret; | ||
1110 | } | ||
1111 | |||
1112 | static DEVICE_ATTR(mb0_id, S_IWUSR | S_IRUGO, | ||
1113 | at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id); | ||
1114 | |||
1115 | static struct attribute *at91_sysfs_attrs[] = { | ||
1116 | &dev_attr_mb0_id.attr, | ||
1117 | NULL, | ||
1118 | }; | ||
1119 | |||
1120 | static struct attribute_group at91_sysfs_attr_group = { | ||
1121 | .attrs = at91_sysfs_attrs, | ||
1122 | }; | ||
1123 | |||
1040 | static int __devinit at91_can_probe(struct platform_device *pdev) | 1124 | static int __devinit at91_can_probe(struct platform_device *pdev) |
1041 | { | 1125 | { |
1042 | struct net_device *dev; | 1126 | struct net_device *dev; |
@@ -1082,6 +1166,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev) | |||
1082 | dev->netdev_ops = &at91_netdev_ops; | 1166 | dev->netdev_ops = &at91_netdev_ops; |
1083 | dev->irq = irq; | 1167 | dev->irq = irq; |
1084 | dev->flags |= IFF_ECHO; | 1168 | dev->flags |= IFF_ECHO; |
1169 | dev->sysfs_groups[0] = &at91_sysfs_attr_group; | ||
1085 | 1170 | ||
1086 | priv = netdev_priv(dev); | 1171 | priv = netdev_priv(dev); |
1087 | priv->can.clock.freq = clk_get_rate(clk); | 1172 | priv->can.clock.freq = clk_get_rate(clk); |
@@ -1093,6 +1178,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev) | |||
1093 | priv->dev = dev; | 1178 | priv->dev = dev; |
1094 | priv->clk = clk; | 1179 | priv->clk = clk; |
1095 | priv->pdata = pdev->dev.platform_data; | 1180 | priv->pdata = pdev->dev.platform_data; |
1181 | priv->mb0_id = 0x7ff; | ||
1096 | 1182 | ||
1097 | netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT); | 1183 | netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT); |
1098 | 1184 | ||
diff --git a/drivers/net/can/c_can/Kconfig b/drivers/net/can/c_can/Kconfig new file mode 100644 index 000000000000..ffb9773d102d --- /dev/null +++ b/drivers/net/can/c_can/Kconfig | |||
@@ -0,0 +1,15 @@ | |||
1 | menuconfig CAN_C_CAN | ||
2 | tristate "Bosch C_CAN devices" | ||
3 | depends on CAN_DEV && HAS_IOMEM | ||
4 | |||
5 | if CAN_C_CAN | ||
6 | |||
7 | config CAN_C_CAN_PLATFORM | ||
8 | tristate "Generic Platform Bus based C_CAN driver" | ||
9 | ---help--- | ||
10 | This driver adds support for the C_CAN chips connected to | ||
11 | the "platform bus" (Linux abstraction for directly to the | ||
12 | processor attached devices) which can be found on various | ||
13 | boards from ST Microelectronics (http://www.st.com) | ||
14 | like the SPEAr1310 and SPEAr320 evaluation boards. | ||
15 | endif | ||
diff --git a/drivers/net/can/c_can/Makefile b/drivers/net/can/c_can/Makefile new file mode 100644 index 000000000000..9273f6d5c4b7 --- /dev/null +++ b/drivers/net/can/c_can/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for the Bosch C_CAN controller drivers. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_CAN_C_CAN) += c_can.o | ||
6 | obj-$(CONFIG_CAN_C_CAN_PLATFORM) += c_can_platform.o | ||
7 | |||
8 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG | ||
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c new file mode 100644 index 000000000000..110eda01843c --- /dev/null +++ b/drivers/net/can/c_can/c_can.c | |||
@@ -0,0 +1,1158 @@ | |||
1 | /* | ||
2 | * CAN bus driver for Bosch C_CAN controller | ||
3 | * | ||
4 | * Copyright (C) 2010 ST Microelectronics | ||
5 | * Bhupesh Sharma <bhupesh.sharma@st.com> | ||
6 | * | ||
7 | * Borrowed heavily from the C_CAN driver originally written by: | ||
8 | * Copyright (C) 2007 | ||
9 | * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de> | ||
10 | * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch> | ||
11 | * | ||
12 | * TX and RX NAPI implementation has been borrowed from at91 CAN driver | ||
13 | * written by: | ||
14 | * Copyright | ||
15 | * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> | ||
16 | * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de> | ||
17 | * | ||
18 | * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B. | ||
19 | * Bosch C_CAN user manual can be obtained from: | ||
20 | * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/ | ||
21 | * users_manual_c_can.pdf | ||
22 | * | ||
23 | * This file is licensed under the terms of the GNU General Public | ||
24 | * License version 2. This program is licensed "as is" without any | ||
25 | * warranty of any kind, whether express or implied. | ||
26 | */ | ||
27 | |||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/version.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/netdevice.h> | ||
34 | #include <linux/if_arp.h> | ||
35 | #include <linux/if_ether.h> | ||
36 | #include <linux/list.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include <linux/io.h> | ||
39 | |||
40 | #include <linux/can.h> | ||
41 | #include <linux/can/dev.h> | ||
42 | #include <linux/can/error.h> | ||
43 | |||
44 | #include "c_can.h" | ||
45 | |||
46 | /* control register */ | ||
47 | #define CONTROL_TEST BIT(7) | ||
48 | #define CONTROL_CCE BIT(6) | ||
49 | #define CONTROL_DISABLE_AR BIT(5) | ||
50 | #define CONTROL_ENABLE_AR (0 << 5) | ||
51 | #define CONTROL_EIE BIT(3) | ||
52 | #define CONTROL_SIE BIT(2) | ||
53 | #define CONTROL_IE BIT(1) | ||
54 | #define CONTROL_INIT BIT(0) | ||
55 | |||
56 | /* test register */ | ||
57 | #define TEST_RX BIT(7) | ||
58 | #define TEST_TX1 BIT(6) | ||
59 | #define TEST_TX2 BIT(5) | ||
60 | #define TEST_LBACK BIT(4) | ||
61 | #define TEST_SILENT BIT(3) | ||
62 | #define TEST_BASIC BIT(2) | ||
63 | |||
64 | /* status register */ | ||
65 | #define STATUS_BOFF BIT(7) | ||
66 | #define STATUS_EWARN BIT(6) | ||
67 | #define STATUS_EPASS BIT(5) | ||
68 | #define STATUS_RXOK BIT(4) | ||
69 | #define STATUS_TXOK BIT(3) | ||
70 | |||
71 | /* error counter register */ | ||
72 | #define ERR_CNT_TEC_MASK 0xff | ||
73 | #define ERR_CNT_TEC_SHIFT 0 | ||
74 | #define ERR_CNT_REC_SHIFT 8 | ||
75 | #define ERR_CNT_REC_MASK (0x7f << ERR_CNT_REC_SHIFT) | ||
76 | #define ERR_CNT_RP_SHIFT 15 | ||
77 | #define ERR_CNT_RP_MASK (0x1 << ERR_CNT_RP_SHIFT) | ||
78 | |||
79 | /* bit-timing register */ | ||
80 | #define BTR_BRP_MASK 0x3f | ||
81 | #define BTR_BRP_SHIFT 0 | ||
82 | #define BTR_SJW_SHIFT 6 | ||
83 | #define BTR_SJW_MASK (0x3 << BTR_SJW_SHIFT) | ||
84 | #define BTR_TSEG1_SHIFT 8 | ||
85 | #define BTR_TSEG1_MASK (0xf << BTR_TSEG1_SHIFT) | ||
86 | #define BTR_TSEG2_SHIFT 12 | ||
87 | #define BTR_TSEG2_MASK (0x7 << BTR_TSEG2_SHIFT) | ||
88 | |||
89 | /* brp extension register */ | ||
90 | #define BRP_EXT_BRPE_MASK 0x0f | ||
91 | #define BRP_EXT_BRPE_SHIFT 0 | ||
92 | |||
93 | /* IFx command request */ | ||
94 | #define IF_COMR_BUSY BIT(15) | ||
95 | |||
96 | /* IFx command mask */ | ||
97 | #define IF_COMM_WR BIT(7) | ||
98 | #define IF_COMM_MASK BIT(6) | ||
99 | #define IF_COMM_ARB BIT(5) | ||
100 | #define IF_COMM_CONTROL BIT(4) | ||
101 | #define IF_COMM_CLR_INT_PND BIT(3) | ||
102 | #define IF_COMM_TXRQST BIT(2) | ||
103 | #define IF_COMM_DATAA BIT(1) | ||
104 | #define IF_COMM_DATAB BIT(0) | ||
105 | #define IF_COMM_ALL (IF_COMM_MASK | IF_COMM_ARB | \ | ||
106 | IF_COMM_CONTROL | IF_COMM_TXRQST | \ | ||
107 | IF_COMM_DATAA | IF_COMM_DATAB) | ||
108 | |||
109 | /* IFx arbitration */ | ||
110 | #define IF_ARB_MSGVAL BIT(15) | ||
111 | #define IF_ARB_MSGXTD BIT(14) | ||
112 | #define IF_ARB_TRANSMIT BIT(13) | ||
113 | |||
114 | /* IFx message control */ | ||
115 | #define IF_MCONT_NEWDAT BIT(15) | ||
116 | #define IF_MCONT_MSGLST BIT(14) | ||
117 | #define IF_MCONT_CLR_MSGLST (0 << 14) | ||
118 | #define IF_MCONT_INTPND BIT(13) | ||
119 | #define IF_MCONT_UMASK BIT(12) | ||
120 | #define IF_MCONT_TXIE BIT(11) | ||
121 | #define IF_MCONT_RXIE BIT(10) | ||
122 | #define IF_MCONT_RMTEN BIT(9) | ||
123 | #define IF_MCONT_TXRQST BIT(8) | ||
124 | #define IF_MCONT_EOB BIT(7) | ||
125 | #define IF_MCONT_DLC_MASK 0xf | ||
126 | |||
127 | /* | ||
128 | * IFx register masks: | ||
129 | * allow easy operation on 16-bit registers when the | ||
130 | * argument is 32-bit instead | ||
131 | */ | ||
132 | #define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF) | ||
133 | #define IFX_WRITE_HIGH_16BIT(x) (((x) & 0xFFFF0000) >> 16) | ||
134 | |||
135 | /* message object split */ | ||
136 | #define C_CAN_NO_OF_OBJECTS 32 | ||
137 | #define C_CAN_MSG_OBJ_RX_NUM 16 | ||
138 | #define C_CAN_MSG_OBJ_TX_NUM 16 | ||
139 | |||
140 | #define C_CAN_MSG_OBJ_RX_FIRST 1 | ||
141 | #define C_CAN_MSG_OBJ_RX_LAST (C_CAN_MSG_OBJ_RX_FIRST + \ | ||
142 | C_CAN_MSG_OBJ_RX_NUM - 1) | ||
143 | |||
144 | #define C_CAN_MSG_OBJ_TX_FIRST (C_CAN_MSG_OBJ_RX_LAST + 1) | ||
145 | #define C_CAN_MSG_OBJ_TX_LAST (C_CAN_MSG_OBJ_TX_FIRST + \ | ||
146 | C_CAN_MSG_OBJ_TX_NUM - 1) | ||
147 | |||
148 | #define C_CAN_MSG_OBJ_RX_SPLIT 9 | ||
149 | #define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1) | ||
150 | |||
151 | #define C_CAN_NEXT_MSG_OBJ_MASK (C_CAN_MSG_OBJ_TX_NUM - 1) | ||
152 | #define RECEIVE_OBJECT_BITS 0x0000ffff | ||
153 | |||
154 | /* status interrupt */ | ||
155 | #define STATUS_INTERRUPT 0x8000 | ||
156 | |||
157 | /* global interrupt masks */ | ||
158 | #define ENABLE_ALL_INTERRUPTS 1 | ||
159 | #define DISABLE_ALL_INTERRUPTS 0 | ||
160 | |||
161 | /* minimum timeout for checking BUSY status */ | ||
162 | #define MIN_TIMEOUT_VALUE 6 | ||
163 | |||
164 | /* napi related */ | ||
165 | #define C_CAN_NAPI_WEIGHT C_CAN_MSG_OBJ_RX_NUM | ||
166 | |||
167 | /* c_can lec values */ | ||
168 | enum c_can_lec_type { | ||
169 | LEC_NO_ERROR = 0, | ||
170 | LEC_STUFF_ERROR, | ||
171 | LEC_FORM_ERROR, | ||
172 | LEC_ACK_ERROR, | ||
173 | LEC_BIT1_ERROR, | ||
174 | LEC_BIT0_ERROR, | ||
175 | LEC_CRC_ERROR, | ||
176 | LEC_UNUSED, | ||
177 | }; | ||
178 | |||
179 | /* | ||
180 | * c_can error types: | ||
181 | * Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported | ||
182 | */ | ||
183 | enum c_can_bus_error_types { | ||
184 | C_CAN_NO_ERROR = 0, | ||
185 | C_CAN_BUS_OFF, | ||
186 | C_CAN_ERROR_WARNING, | ||
187 | C_CAN_ERROR_PASSIVE, | ||
188 | }; | ||
189 | |||
190 | static struct can_bittiming_const c_can_bittiming_const = { | ||
191 | .name = KBUILD_MODNAME, | ||
192 | .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ | ||
193 | .tseg1_max = 16, | ||
194 | .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ | ||
195 | .tseg2_max = 8, | ||
196 | .sjw_max = 4, | ||
197 | .brp_min = 1, | ||
198 | .brp_max = 1024, /* 6-bit BRP field + 4-bit BRPE field*/ | ||
199 | .brp_inc = 1, | ||
200 | }; | ||
201 | |||
202 | static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) | ||
203 | { | ||
204 | return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) + | ||
205 | C_CAN_MSG_OBJ_TX_FIRST; | ||
206 | } | ||
207 | |||
208 | static inline int get_tx_echo_msg_obj(const struct c_can_priv *priv) | ||
209 | { | ||
210 | return (priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) + | ||
211 | C_CAN_MSG_OBJ_TX_FIRST; | ||
212 | } | ||
213 | |||
214 | static u32 c_can_read_reg32(struct c_can_priv *priv, void *reg) | ||
215 | { | ||
216 | u32 val = priv->read_reg(priv, reg); | ||
217 | val |= ((u32) priv->read_reg(priv, reg + 2)) << 16; | ||
218 | return val; | ||
219 | } | ||
220 | |||
221 | static void c_can_enable_all_interrupts(struct c_can_priv *priv, | ||
222 | int enable) | ||
223 | { | ||
224 | unsigned int cntrl_save = priv->read_reg(priv, | ||
225 | &priv->regs->control); | ||
226 | |||
227 | if (enable) | ||
228 | cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE); | ||
229 | else | ||
230 | cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE); | ||
231 | |||
232 | priv->write_reg(priv, &priv->regs->control, cntrl_save); | ||
233 | } | ||
234 | |||
235 | static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface) | ||
236 | { | ||
237 | int count = MIN_TIMEOUT_VALUE; | ||
238 | |||
239 | while (count && priv->read_reg(priv, | ||
240 | &priv->regs->ifregs[iface].com_req) & | ||
241 | IF_COMR_BUSY) { | ||
242 | count--; | ||
243 | udelay(1); | ||
244 | } | ||
245 | |||
246 | if (!count) | ||
247 | return 1; | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static inline void c_can_object_get(struct net_device *dev, | ||
253 | int iface, int objno, int mask) | ||
254 | { | ||
255 | struct c_can_priv *priv = netdev_priv(dev); | ||
256 | |||
257 | /* | ||
258 | * As per specs, after writting the message object number in the | ||
259 | * IF command request register the transfer b/w interface | ||
260 | * register and message RAM must be complete in 6 CAN-CLK | ||
261 | * period. | ||
262 | */ | ||
263 | priv->write_reg(priv, &priv->regs->ifregs[iface].com_mask, | ||
264 | IFX_WRITE_LOW_16BIT(mask)); | ||
265 | priv->write_reg(priv, &priv->regs->ifregs[iface].com_req, | ||
266 | IFX_WRITE_LOW_16BIT(objno)); | ||
267 | |||
268 | if (c_can_msg_obj_is_busy(priv, iface)) | ||
269 | netdev_err(dev, "timed out in object get\n"); | ||
270 | } | ||
271 | |||
272 | static inline void c_can_object_put(struct net_device *dev, | ||
273 | int iface, int objno, int mask) | ||
274 | { | ||
275 | struct c_can_priv *priv = netdev_priv(dev); | ||
276 | |||
277 | /* | ||
278 | * As per specs, after writting the message object number in the | ||
279 | * IF command request register the transfer b/w interface | ||
280 | * register and message RAM must be complete in 6 CAN-CLK | ||
281 | * period. | ||
282 | */ | ||
283 | priv->write_reg(priv, &priv->regs->ifregs[iface].com_mask, | ||
284 | (IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask))); | ||
285 | priv->write_reg(priv, &priv->regs->ifregs[iface].com_req, | ||
286 | IFX_WRITE_LOW_16BIT(objno)); | ||
287 | |||
288 | if (c_can_msg_obj_is_busy(priv, iface)) | ||
289 | netdev_err(dev, "timed out in object put\n"); | ||
290 | } | ||
291 | |||
292 | static void c_can_write_msg_object(struct net_device *dev, | ||
293 | int iface, struct can_frame *frame, int objno) | ||
294 | { | ||
295 | int i; | ||
296 | u16 flags = 0; | ||
297 | unsigned int id; | ||
298 | struct c_can_priv *priv = netdev_priv(dev); | ||
299 | |||
300 | if (!(frame->can_id & CAN_RTR_FLAG)) | ||
301 | flags |= IF_ARB_TRANSMIT; | ||
302 | |||
303 | if (frame->can_id & CAN_EFF_FLAG) { | ||
304 | id = frame->can_id & CAN_EFF_MASK; | ||
305 | flags |= IF_ARB_MSGXTD; | ||
306 | } else | ||
307 | id = ((frame->can_id & CAN_SFF_MASK) << 18); | ||
308 | |||
309 | flags |= IF_ARB_MSGVAL; | ||
310 | |||
311 | priv->write_reg(priv, &priv->regs->ifregs[iface].arb1, | ||
312 | IFX_WRITE_LOW_16BIT(id)); | ||
313 | priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, flags | | ||
314 | IFX_WRITE_HIGH_16BIT(id)); | ||
315 | |||
316 | for (i = 0; i < frame->can_dlc; i += 2) { | ||
317 | priv->write_reg(priv, &priv->regs->ifregs[iface].data[i / 2], | ||
318 | frame->data[i] | (frame->data[i + 1] << 8)); | ||
319 | } | ||
320 | |||
321 | /* enable interrupt for this message object */ | ||
322 | priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, | ||
323 | IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB | | ||
324 | frame->can_dlc); | ||
325 | c_can_object_put(dev, iface, objno, IF_COMM_ALL); | ||
326 | } | ||
327 | |||
328 | static inline void c_can_mark_rx_msg_obj(struct net_device *dev, | ||
329 | int iface, int ctrl_mask, | ||
330 | int obj) | ||
331 | { | ||
332 | struct c_can_priv *priv = netdev_priv(dev); | ||
333 | |||
334 | priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, | ||
335 | ctrl_mask & ~(IF_MCONT_MSGLST | IF_MCONT_INTPND)); | ||
336 | c_can_object_put(dev, iface, obj, IF_COMM_CONTROL); | ||
337 | |||
338 | } | ||
339 | |||
340 | static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev, | ||
341 | int iface, | ||
342 | int ctrl_mask) | ||
343 | { | ||
344 | int i; | ||
345 | struct c_can_priv *priv = netdev_priv(dev); | ||
346 | |||
347 | for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) { | ||
348 | priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, | ||
349 | ctrl_mask & ~(IF_MCONT_MSGLST | | ||
350 | IF_MCONT_INTPND | IF_MCONT_NEWDAT)); | ||
351 | c_can_object_put(dev, iface, i, IF_COMM_CONTROL); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | static inline void c_can_activate_rx_msg_obj(struct net_device *dev, | ||
356 | int iface, int ctrl_mask, | ||
357 | int obj) | ||
358 | { | ||
359 | struct c_can_priv *priv = netdev_priv(dev); | ||
360 | |||
361 | priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, | ||
362 | ctrl_mask & ~(IF_MCONT_MSGLST | | ||
363 | IF_MCONT_INTPND | IF_MCONT_NEWDAT)); | ||
364 | c_can_object_put(dev, iface, obj, IF_COMM_CONTROL); | ||
365 | } | ||
366 | |||
367 | static void c_can_handle_lost_msg_obj(struct net_device *dev, | ||
368 | int iface, int objno) | ||
369 | { | ||
370 | struct c_can_priv *priv = netdev_priv(dev); | ||
371 | struct net_device_stats *stats = &dev->stats; | ||
372 | struct sk_buff *skb; | ||
373 | struct can_frame *frame; | ||
374 | |||
375 | netdev_err(dev, "msg lost in buffer %d\n", objno); | ||
376 | |||
377 | c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); | ||
378 | |||
379 | priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, | ||
380 | IF_MCONT_CLR_MSGLST); | ||
381 | |||
382 | c_can_object_put(dev, 0, objno, IF_COMM_CONTROL); | ||
383 | |||
384 | /* create an error msg */ | ||
385 | skb = alloc_can_err_skb(dev, &frame); | ||
386 | if (unlikely(!skb)) | ||
387 | return; | ||
388 | |||
389 | frame->can_id |= CAN_ERR_CRTL; | ||
390 | frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | ||
391 | stats->rx_errors++; | ||
392 | stats->rx_over_errors++; | ||
393 | |||
394 | netif_receive_skb(skb); | ||
395 | } | ||
396 | |||
397 | static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) | ||
398 | { | ||
399 | u16 flags, data; | ||
400 | int i; | ||
401 | unsigned int val; | ||
402 | struct c_can_priv *priv = netdev_priv(dev); | ||
403 | struct net_device_stats *stats = &dev->stats; | ||
404 | struct sk_buff *skb; | ||
405 | struct can_frame *frame; | ||
406 | |||
407 | skb = alloc_can_skb(dev, &frame); | ||
408 | if (!skb) { | ||
409 | stats->rx_dropped++; | ||
410 | return -ENOMEM; | ||
411 | } | ||
412 | |||
413 | frame->can_dlc = get_can_dlc(ctrl & 0x0F); | ||
414 | |||
415 | flags = priv->read_reg(priv, &priv->regs->ifregs[iface].arb2); | ||
416 | val = priv->read_reg(priv, &priv->regs->ifregs[iface].arb1) | | ||
417 | (flags << 16); | ||
418 | |||
419 | if (flags & IF_ARB_MSGXTD) | ||
420 | frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG; | ||
421 | else | ||
422 | frame->can_id = (val >> 18) & CAN_SFF_MASK; | ||
423 | |||
424 | if (flags & IF_ARB_TRANSMIT) | ||
425 | frame->can_id |= CAN_RTR_FLAG; | ||
426 | else { | ||
427 | for (i = 0; i < frame->can_dlc; i += 2) { | ||
428 | data = priv->read_reg(priv, | ||
429 | &priv->regs->ifregs[iface].data[i / 2]); | ||
430 | frame->data[i] = data; | ||
431 | frame->data[i + 1] = data >> 8; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | netif_receive_skb(skb); | ||
436 | |||
437 | stats->rx_packets++; | ||
438 | stats->rx_bytes += frame->can_dlc; | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static void c_can_setup_receive_object(struct net_device *dev, int iface, | ||
444 | int objno, unsigned int mask, | ||
445 | unsigned int id, unsigned int mcont) | ||
446 | { | ||
447 | struct c_can_priv *priv = netdev_priv(dev); | ||
448 | |||
449 | priv->write_reg(priv, &priv->regs->ifregs[iface].mask1, | ||
450 | IFX_WRITE_LOW_16BIT(mask)); | ||
451 | priv->write_reg(priv, &priv->regs->ifregs[iface].mask2, | ||
452 | IFX_WRITE_HIGH_16BIT(mask)); | ||
453 | |||
454 | priv->write_reg(priv, &priv->regs->ifregs[iface].arb1, | ||
455 | IFX_WRITE_LOW_16BIT(id)); | ||
456 | priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, | ||
457 | (IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id))); | ||
458 | |||
459 | priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, mcont); | ||
460 | c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); | ||
461 | |||
462 | netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, | ||
463 | c_can_read_reg32(priv, &priv->regs->msgval1)); | ||
464 | } | ||
465 | |||
466 | static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno) | ||
467 | { | ||
468 | struct c_can_priv *priv = netdev_priv(dev); | ||
469 | |||
470 | priv->write_reg(priv, &priv->regs->ifregs[iface].arb1, 0); | ||
471 | priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, 0); | ||
472 | priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, 0); | ||
473 | |||
474 | c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL); | ||
475 | |||
476 | netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno, | ||
477 | c_can_read_reg32(priv, &priv->regs->msgval1)); | ||
478 | } | ||
479 | |||
480 | static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno) | ||
481 | { | ||
482 | int val = c_can_read_reg32(priv, &priv->regs->txrqst1); | ||
483 | |||
484 | /* | ||
485 | * as transmission request register's bit n-1 corresponds to | ||
486 | * message object n, we need to handle the same properly. | ||
487 | */ | ||
488 | if (val & (1 << (objno - 1))) | ||
489 | return 1; | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, | ||
495 | struct net_device *dev) | ||
496 | { | ||
497 | u32 msg_obj_no; | ||
498 | struct c_can_priv *priv = netdev_priv(dev); | ||
499 | struct can_frame *frame = (struct can_frame *)skb->data; | ||
500 | |||
501 | if (can_dropped_invalid_skb(dev, skb)) | ||
502 | return NETDEV_TX_OK; | ||
503 | |||
504 | msg_obj_no = get_tx_next_msg_obj(priv); | ||
505 | |||
506 | /* prepare message object for transmission */ | ||
507 | c_can_write_msg_object(dev, 0, frame, msg_obj_no); | ||
508 | can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); | ||
509 | |||
510 | /* | ||
511 | * we have to stop the queue in case of a wrap around or | ||
512 | * if the next TX message object is still in use | ||
513 | */ | ||
514 | priv->tx_next++; | ||
515 | if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) || | ||
516 | (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0) | ||
517 | netif_stop_queue(dev); | ||
518 | |||
519 | return NETDEV_TX_OK; | ||
520 | } | ||
521 | |||
522 | static int c_can_set_bittiming(struct net_device *dev) | ||
523 | { | ||
524 | unsigned int reg_btr, reg_brpe, ctrl_save; | ||
525 | u8 brp, brpe, sjw, tseg1, tseg2; | ||
526 | u32 ten_bit_brp; | ||
527 | struct c_can_priv *priv = netdev_priv(dev); | ||
528 | const struct can_bittiming *bt = &priv->can.bittiming; | ||
529 | |||
530 | /* c_can provides a 6-bit brp and 4-bit brpe fields */ | ||
531 | ten_bit_brp = bt->brp - 1; | ||
532 | brp = ten_bit_brp & BTR_BRP_MASK; | ||
533 | brpe = ten_bit_brp >> 6; | ||
534 | |||
535 | sjw = bt->sjw - 1; | ||
536 | tseg1 = bt->prop_seg + bt->phase_seg1 - 1; | ||
537 | tseg2 = bt->phase_seg2 - 1; | ||
538 | reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) | | ||
539 | (tseg2 << BTR_TSEG2_SHIFT); | ||
540 | reg_brpe = brpe & BRP_EXT_BRPE_MASK; | ||
541 | |||
542 | netdev_info(dev, | ||
543 | "setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe); | ||
544 | |||
545 | ctrl_save = priv->read_reg(priv, &priv->regs->control); | ||
546 | priv->write_reg(priv, &priv->regs->control, | ||
547 | ctrl_save | CONTROL_CCE | CONTROL_INIT); | ||
548 | priv->write_reg(priv, &priv->regs->btr, reg_btr); | ||
549 | priv->write_reg(priv, &priv->regs->brp_ext, reg_brpe); | ||
550 | priv->write_reg(priv, &priv->regs->control, ctrl_save); | ||
551 | |||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | /* | ||
556 | * Configure C_CAN message objects for Tx and Rx purposes: | ||
557 | * C_CAN provides a total of 32 message objects that can be configured | ||
558 | * either for Tx or Rx purposes. Here the first 16 message objects are used as | ||
559 | * a reception FIFO. The end of reception FIFO is signified by the EoB bit | ||
560 | * being SET. The remaining 16 message objects are kept aside for Tx purposes. | ||
561 | * See user guide document for further details on configuring message | ||
562 | * objects. | ||
563 | */ | ||
564 | static void c_can_configure_msg_objects(struct net_device *dev) | ||
565 | { | ||
566 | int i; | ||
567 | |||
568 | /* first invalidate all message objects */ | ||
569 | for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) | ||
570 | c_can_inval_msg_object(dev, 0, i); | ||
571 | |||
572 | /* setup receive message objects */ | ||
573 | for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) | ||
574 | c_can_setup_receive_object(dev, 0, i, 0, 0, | ||
575 | (IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB); | ||
576 | |||
577 | c_can_setup_receive_object(dev, 0, C_CAN_MSG_OBJ_RX_LAST, 0, 0, | ||
578 | IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK); | ||
579 | } | ||
580 | |||
581 | /* | ||
582 | * Configure C_CAN chip: | ||
583 | * - enable/disable auto-retransmission | ||
584 | * - set operating mode | ||
585 | * - configure message objects | ||
586 | */ | ||
587 | static void c_can_chip_config(struct net_device *dev) | ||
588 | { | ||
589 | struct c_can_priv *priv = netdev_priv(dev); | ||
590 | |||
591 | if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) | ||
592 | /* disable automatic retransmission */ | ||
593 | priv->write_reg(priv, &priv->regs->control, | ||
594 | CONTROL_DISABLE_AR); | ||
595 | else | ||
596 | /* enable automatic retransmission */ | ||
597 | priv->write_reg(priv, &priv->regs->control, | ||
598 | CONTROL_ENABLE_AR); | ||
599 | |||
600 | if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & | ||
601 | CAN_CTRLMODE_LOOPBACK)) { | ||
602 | /* loopback + silent mode : useful for hot self-test */ | ||
603 | priv->write_reg(priv, &priv->regs->control, CONTROL_EIE | | ||
604 | CONTROL_SIE | CONTROL_IE | CONTROL_TEST); | ||
605 | priv->write_reg(priv, &priv->regs->test, | ||
606 | TEST_LBACK | TEST_SILENT); | ||
607 | } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { | ||
608 | /* loopback mode : useful for self-test function */ | ||
609 | priv->write_reg(priv, &priv->regs->control, CONTROL_EIE | | ||
610 | CONTROL_SIE | CONTROL_IE | CONTROL_TEST); | ||
611 | priv->write_reg(priv, &priv->regs->test, TEST_LBACK); | ||
612 | } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { | ||
613 | /* silent mode : bus-monitoring mode */ | ||
614 | priv->write_reg(priv, &priv->regs->control, CONTROL_EIE | | ||
615 | CONTROL_SIE | CONTROL_IE | CONTROL_TEST); | ||
616 | priv->write_reg(priv, &priv->regs->test, TEST_SILENT); | ||
617 | } else | ||
618 | /* normal mode*/ | ||
619 | priv->write_reg(priv, &priv->regs->control, | ||
620 | CONTROL_EIE | CONTROL_SIE | CONTROL_IE); | ||
621 | |||
622 | /* configure message objects */ | ||
623 | c_can_configure_msg_objects(dev); | ||
624 | |||
625 | /* set a `lec` value so that we can check for updates later */ | ||
626 | priv->write_reg(priv, &priv->regs->status, LEC_UNUSED); | ||
627 | |||
628 | /* set bittiming params */ | ||
629 | c_can_set_bittiming(dev); | ||
630 | } | ||
631 | |||
632 | static void c_can_start(struct net_device *dev) | ||
633 | { | ||
634 | struct c_can_priv *priv = netdev_priv(dev); | ||
635 | |||
636 | /* basic c_can configuration */ | ||
637 | c_can_chip_config(dev); | ||
638 | |||
639 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
640 | |||
641 | /* reset tx helper pointers */ | ||
642 | priv->tx_next = priv->tx_echo = 0; | ||
643 | |||
644 | /* enable status change, error and module interrupts */ | ||
645 | c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); | ||
646 | } | ||
647 | |||
648 | static void c_can_stop(struct net_device *dev) | ||
649 | { | ||
650 | struct c_can_priv *priv = netdev_priv(dev); | ||
651 | |||
652 | /* disable all interrupts */ | ||
653 | c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); | ||
654 | |||
655 | /* set the state as STOPPED */ | ||
656 | priv->can.state = CAN_STATE_STOPPED; | ||
657 | } | ||
658 | |||
659 | static int c_can_set_mode(struct net_device *dev, enum can_mode mode) | ||
660 | { | ||
661 | switch (mode) { | ||
662 | case CAN_MODE_START: | ||
663 | c_can_start(dev); | ||
664 | netif_wake_queue(dev); | ||
665 | break; | ||
666 | default: | ||
667 | return -EOPNOTSUPP; | ||
668 | } | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | static int c_can_get_berr_counter(const struct net_device *dev, | ||
674 | struct can_berr_counter *bec) | ||
675 | { | ||
676 | unsigned int reg_err_counter; | ||
677 | struct c_can_priv *priv = netdev_priv(dev); | ||
678 | |||
679 | reg_err_counter = priv->read_reg(priv, &priv->regs->err_cnt); | ||
680 | bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >> | ||
681 | ERR_CNT_REC_SHIFT; | ||
682 | bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK; | ||
683 | |||
684 | return 0; | ||
685 | } | ||
686 | |||
687 | /* | ||
688 | * theory of operation: | ||
689 | * | ||
690 | * priv->tx_echo holds the number of the oldest can_frame put for | ||
691 | * transmission into the hardware, but not yet ACKed by the CAN tx | ||
692 | * complete IRQ. | ||
693 | * | ||
694 | * We iterate from priv->tx_echo to priv->tx_next and check if the | ||
695 | * packet has been transmitted, echo it back to the CAN framework. | ||
696 | * If we discover a not yet transmitted package, stop looking for more. | ||
697 | */ | ||
698 | static void c_can_do_tx(struct net_device *dev) | ||
699 | { | ||
700 | u32 val; | ||
701 | u32 msg_obj_no; | ||
702 | struct c_can_priv *priv = netdev_priv(dev); | ||
703 | struct net_device_stats *stats = &dev->stats; | ||
704 | |||
705 | for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { | ||
706 | msg_obj_no = get_tx_echo_msg_obj(priv); | ||
707 | c_can_inval_msg_object(dev, 0, msg_obj_no); | ||
708 | val = c_can_read_reg32(priv, &priv->regs->txrqst1); | ||
709 | if (!(val & (1 << msg_obj_no))) { | ||
710 | can_get_echo_skb(dev, | ||
711 | msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); | ||
712 | stats->tx_bytes += priv->read_reg(priv, | ||
713 | &priv->regs->ifregs[0].msg_cntrl) | ||
714 | & IF_MCONT_DLC_MASK; | ||
715 | stats->tx_packets++; | ||
716 | } | ||
717 | } | ||
718 | |||
719 | /* restart queue if wrap-up or if queue stalled on last pkt */ | ||
720 | if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) || | ||
721 | ((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0)) | ||
722 | netif_wake_queue(dev); | ||
723 | } | ||
724 | |||
725 | /* | ||
726 | * theory of operation: | ||
727 | * | ||
728 | * c_can core saves a received CAN message into the first free message | ||
729 | * object it finds free (starting with the lowest). Bits NEWDAT and | ||
730 | * INTPND are set for this message object indicating that a new message | ||
731 | * has arrived. To work-around this issue, we keep two groups of message | ||
732 | * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT. | ||
733 | * | ||
734 | * To ensure in-order frame reception we use the following | ||
735 | * approach while re-activating a message object to receive further | ||
736 | * frames: | ||
737 | * - if the current message object number is lower than | ||
738 | * C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing | ||
739 | * the INTPND bit. | ||
740 | * - if the current message object number is equal to | ||
741 | * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower | ||
742 | * receive message objects. | ||
743 | * - if the current message object number is greater than | ||
744 | * C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of | ||
745 | * only this message object. | ||
746 | */ | ||
747 | static int c_can_do_rx_poll(struct net_device *dev, int quota) | ||
748 | { | ||
749 | u32 num_rx_pkts = 0; | ||
750 | unsigned int msg_obj, msg_ctrl_save; | ||
751 | struct c_can_priv *priv = netdev_priv(dev); | ||
752 | u32 val = c_can_read_reg32(priv, &priv->regs->intpnd1); | ||
753 | |||
754 | for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST; | ||
755 | msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0; | ||
756 | val = c_can_read_reg32(priv, &priv->regs->intpnd1), | ||
757 | msg_obj++) { | ||
758 | /* | ||
759 | * as interrupt pending register's bit n-1 corresponds to | ||
760 | * message object n, we need to handle the same properly. | ||
761 | */ | ||
762 | if (val & (1 << (msg_obj - 1))) { | ||
763 | c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL & | ||
764 | ~IF_COMM_TXRQST); | ||
765 | msg_ctrl_save = priv->read_reg(priv, | ||
766 | &priv->regs->ifregs[0].msg_cntrl); | ||
767 | |||
768 | if (msg_ctrl_save & IF_MCONT_EOB) | ||
769 | return num_rx_pkts; | ||
770 | |||
771 | if (msg_ctrl_save & IF_MCONT_MSGLST) { | ||
772 | c_can_handle_lost_msg_obj(dev, 0, msg_obj); | ||
773 | num_rx_pkts++; | ||
774 | quota--; | ||
775 | continue; | ||
776 | } | ||
777 | |||
778 | if (!(msg_ctrl_save & IF_MCONT_NEWDAT)) | ||
779 | continue; | ||
780 | |||
781 | /* read the data from the message object */ | ||
782 | c_can_read_msg_object(dev, 0, msg_ctrl_save); | ||
783 | |||
784 | if (msg_obj < C_CAN_MSG_RX_LOW_LAST) | ||
785 | c_can_mark_rx_msg_obj(dev, 0, | ||
786 | msg_ctrl_save, msg_obj); | ||
787 | else if (msg_obj > C_CAN_MSG_RX_LOW_LAST) | ||
788 | /* activate this msg obj */ | ||
789 | c_can_activate_rx_msg_obj(dev, 0, | ||
790 | msg_ctrl_save, msg_obj); | ||
791 | else if (msg_obj == C_CAN_MSG_RX_LOW_LAST) | ||
792 | /* activate all lower message objects */ | ||
793 | c_can_activate_all_lower_rx_msg_obj(dev, | ||
794 | 0, msg_ctrl_save); | ||
795 | |||
796 | num_rx_pkts++; | ||
797 | quota--; | ||
798 | } | ||
799 | } | ||
800 | |||
801 | return num_rx_pkts; | ||
802 | } | ||
803 | |||
804 | static inline int c_can_has_and_handle_berr(struct c_can_priv *priv) | ||
805 | { | ||
806 | return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) && | ||
807 | (priv->current_status & LEC_UNUSED); | ||
808 | } | ||
809 | |||
810 | static int c_can_handle_state_change(struct net_device *dev, | ||
811 | enum c_can_bus_error_types error_type) | ||
812 | { | ||
813 | unsigned int reg_err_counter; | ||
814 | unsigned int rx_err_passive; | ||
815 | struct c_can_priv *priv = netdev_priv(dev); | ||
816 | struct net_device_stats *stats = &dev->stats; | ||
817 | struct can_frame *cf; | ||
818 | struct sk_buff *skb; | ||
819 | struct can_berr_counter bec; | ||
820 | |||
821 | /* propogate the error condition to the CAN stack */ | ||
822 | skb = alloc_can_err_skb(dev, &cf); | ||
823 | if (unlikely(!skb)) | ||
824 | return 0; | ||
825 | |||
826 | c_can_get_berr_counter(dev, &bec); | ||
827 | reg_err_counter = priv->read_reg(priv, &priv->regs->err_cnt); | ||
828 | rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >> | ||
829 | ERR_CNT_RP_SHIFT; | ||
830 | |||
831 | switch (error_type) { | ||
832 | case C_CAN_ERROR_WARNING: | ||
833 | /* error warning state */ | ||
834 | priv->can.can_stats.error_warning++; | ||
835 | priv->can.state = CAN_STATE_ERROR_WARNING; | ||
836 | cf->can_id |= CAN_ERR_CRTL; | ||
837 | cf->data[1] = (bec.txerr > bec.rxerr) ? | ||
838 | CAN_ERR_CRTL_TX_WARNING : | ||
839 | CAN_ERR_CRTL_RX_WARNING; | ||
840 | cf->data[6] = bec.txerr; | ||
841 | cf->data[7] = bec.rxerr; | ||
842 | |||
843 | break; | ||
844 | case C_CAN_ERROR_PASSIVE: | ||
845 | /* error passive state */ | ||
846 | priv->can.can_stats.error_passive++; | ||
847 | priv->can.state = CAN_STATE_ERROR_PASSIVE; | ||
848 | cf->can_id |= CAN_ERR_CRTL; | ||
849 | if (rx_err_passive) | ||
850 | cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; | ||
851 | if (bec.txerr > 127) | ||
852 | cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; | ||
853 | |||
854 | cf->data[6] = bec.txerr; | ||
855 | cf->data[7] = bec.rxerr; | ||
856 | break; | ||
857 | case C_CAN_BUS_OFF: | ||
858 | /* bus-off state */ | ||
859 | priv->can.state = CAN_STATE_BUS_OFF; | ||
860 | cf->can_id |= CAN_ERR_BUSOFF; | ||
861 | /* | ||
862 | * disable all interrupts in bus-off mode to ensure that | ||
863 | * the CPU is not hogged down | ||
864 | */ | ||
865 | c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); | ||
866 | can_bus_off(dev); | ||
867 | break; | ||
868 | default: | ||
869 | break; | ||
870 | } | ||
871 | |||
872 | netif_receive_skb(skb); | ||
873 | stats->rx_packets++; | ||
874 | stats->rx_bytes += cf->can_dlc; | ||
875 | |||
876 | return 1; | ||
877 | } | ||
878 | |||
879 | static int c_can_handle_bus_err(struct net_device *dev, | ||
880 | enum c_can_lec_type lec_type) | ||
881 | { | ||
882 | struct c_can_priv *priv = netdev_priv(dev); | ||
883 | struct net_device_stats *stats = &dev->stats; | ||
884 | struct can_frame *cf; | ||
885 | struct sk_buff *skb; | ||
886 | |||
887 | /* | ||
888 | * early exit if no lec update or no error. | ||
889 | * no lec update means that no CAN bus event has been detected | ||
890 | * since CPU wrote 0x7 value to status reg. | ||
891 | */ | ||
892 | if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR) | ||
893 | return 0; | ||
894 | |||
895 | /* propogate the error condition to the CAN stack */ | ||
896 | skb = alloc_can_err_skb(dev, &cf); | ||
897 | if (unlikely(!skb)) | ||
898 | return 0; | ||
899 | |||
900 | /* | ||
901 | * check for 'last error code' which tells us the | ||
902 | * type of the last error to occur on the CAN bus | ||
903 | */ | ||
904 | |||
905 | /* common for all type of bus errors */ | ||
906 | priv->can.can_stats.bus_error++; | ||
907 | stats->rx_errors++; | ||
908 | cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | ||
909 | cf->data[2] |= CAN_ERR_PROT_UNSPEC; | ||
910 | |||
911 | switch (lec_type) { | ||
912 | case LEC_STUFF_ERROR: | ||
913 | netdev_dbg(dev, "stuff error\n"); | ||
914 | cf->data[2] |= CAN_ERR_PROT_STUFF; | ||
915 | break; | ||
916 | case LEC_FORM_ERROR: | ||
917 | netdev_dbg(dev, "form error\n"); | ||
918 | cf->data[2] |= CAN_ERR_PROT_FORM; | ||
919 | break; | ||
920 | case LEC_ACK_ERROR: | ||
921 | netdev_dbg(dev, "ack error\n"); | ||
922 | cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | | ||
923 | CAN_ERR_PROT_LOC_ACK_DEL); | ||
924 | break; | ||
925 | case LEC_BIT1_ERROR: | ||
926 | netdev_dbg(dev, "bit1 error\n"); | ||
927 | cf->data[2] |= CAN_ERR_PROT_BIT1; | ||
928 | break; | ||
929 | case LEC_BIT0_ERROR: | ||
930 | netdev_dbg(dev, "bit0 error\n"); | ||
931 | cf->data[2] |= CAN_ERR_PROT_BIT0; | ||
932 | break; | ||
933 | case LEC_CRC_ERROR: | ||
934 | netdev_dbg(dev, "CRC error\n"); | ||
935 | cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | | ||
936 | CAN_ERR_PROT_LOC_CRC_DEL); | ||
937 | break; | ||
938 | default: | ||
939 | break; | ||
940 | } | ||
941 | |||
942 | /* set a `lec` value so that we can check for updates later */ | ||
943 | priv->write_reg(priv, &priv->regs->status, LEC_UNUSED); | ||
944 | |||
945 | netif_receive_skb(skb); | ||
946 | stats->rx_packets++; | ||
947 | stats->rx_bytes += cf->can_dlc; | ||
948 | |||
949 | return 1; | ||
950 | } | ||
951 | |||
952 | static int c_can_poll(struct napi_struct *napi, int quota) | ||
953 | { | ||
954 | u16 irqstatus; | ||
955 | int lec_type = 0; | ||
956 | int work_done = 0; | ||
957 | struct net_device *dev = napi->dev; | ||
958 | struct c_can_priv *priv = netdev_priv(dev); | ||
959 | |||
960 | irqstatus = priv->read_reg(priv, &priv->regs->interrupt); | ||
961 | if (!irqstatus) | ||
962 | goto end; | ||
963 | |||
964 | /* status events have the highest priority */ | ||
965 | if (irqstatus == STATUS_INTERRUPT) { | ||
966 | priv->current_status = priv->read_reg(priv, | ||
967 | &priv->regs->status); | ||
968 | |||
969 | /* handle Tx/Rx events */ | ||
970 | if (priv->current_status & STATUS_TXOK) | ||
971 | priv->write_reg(priv, &priv->regs->status, | ||
972 | priv->current_status & ~STATUS_TXOK); | ||
973 | |||
974 | if (priv->current_status & STATUS_RXOK) | ||
975 | priv->write_reg(priv, &priv->regs->status, | ||
976 | priv->current_status & ~STATUS_RXOK); | ||
977 | |||
978 | /* handle state changes */ | ||
979 | if ((priv->current_status & STATUS_EWARN) && | ||
980 | (!(priv->last_status & STATUS_EWARN))) { | ||
981 | netdev_dbg(dev, "entered error warning state\n"); | ||
982 | work_done += c_can_handle_state_change(dev, | ||
983 | C_CAN_ERROR_WARNING); | ||
984 | } | ||
985 | if ((priv->current_status & STATUS_EPASS) && | ||
986 | (!(priv->last_status & STATUS_EPASS))) { | ||
987 | netdev_dbg(dev, "entered error passive state\n"); | ||
988 | work_done += c_can_handle_state_change(dev, | ||
989 | C_CAN_ERROR_PASSIVE); | ||
990 | } | ||
991 | if ((priv->current_status & STATUS_BOFF) && | ||
992 | (!(priv->last_status & STATUS_BOFF))) { | ||
993 | netdev_dbg(dev, "entered bus off state\n"); | ||
994 | work_done += c_can_handle_state_change(dev, | ||
995 | C_CAN_BUS_OFF); | ||
996 | } | ||
997 | |||
998 | /* handle bus recovery events */ | ||
999 | if ((!(priv->current_status & STATUS_BOFF)) && | ||
1000 | (priv->last_status & STATUS_BOFF)) { | ||
1001 | netdev_dbg(dev, "left bus off state\n"); | ||
1002 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
1003 | } | ||
1004 | if ((!(priv->current_status & STATUS_EPASS)) && | ||
1005 | (priv->last_status & STATUS_EPASS)) { | ||
1006 | netdev_dbg(dev, "left error passive state\n"); | ||
1007 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
1008 | } | ||
1009 | |||
1010 | priv->last_status = priv->current_status; | ||
1011 | |||
1012 | /* handle lec errors on the bus */ | ||
1013 | lec_type = c_can_has_and_handle_berr(priv); | ||
1014 | if (lec_type) | ||
1015 | work_done += c_can_handle_bus_err(dev, lec_type); | ||
1016 | } else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) && | ||
1017 | (irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) { | ||
1018 | /* handle events corresponding to receive message objects */ | ||
1019 | work_done += c_can_do_rx_poll(dev, (quota - work_done)); | ||
1020 | } else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) && | ||
1021 | (irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) { | ||
1022 | /* handle events corresponding to transmit message objects */ | ||
1023 | c_can_do_tx(dev); | ||
1024 | } | ||
1025 | |||
1026 | end: | ||
1027 | if (work_done < quota) { | ||
1028 | napi_complete(napi); | ||
1029 | /* enable all IRQs */ | ||
1030 | c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); | ||
1031 | } | ||
1032 | |||
1033 | return work_done; | ||
1034 | } | ||
1035 | |||
1036 | static irqreturn_t c_can_isr(int irq, void *dev_id) | ||
1037 | { | ||
1038 | u16 irqstatus; | ||
1039 | struct net_device *dev = (struct net_device *)dev_id; | ||
1040 | struct c_can_priv *priv = netdev_priv(dev); | ||
1041 | |||
1042 | irqstatus = priv->read_reg(priv, &priv->regs->interrupt); | ||
1043 | if (!irqstatus) | ||
1044 | return IRQ_NONE; | ||
1045 | |||
1046 | /* disable all interrupts and schedule the NAPI */ | ||
1047 | c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); | ||
1048 | napi_schedule(&priv->napi); | ||
1049 | |||
1050 | return IRQ_HANDLED; | ||
1051 | } | ||
1052 | |||
1053 | static int c_can_open(struct net_device *dev) | ||
1054 | { | ||
1055 | int err; | ||
1056 | struct c_can_priv *priv = netdev_priv(dev); | ||
1057 | |||
1058 | /* open the can device */ | ||
1059 | err = open_candev(dev); | ||
1060 | if (err) { | ||
1061 | netdev_err(dev, "failed to open can device\n"); | ||
1062 | return err; | ||
1063 | } | ||
1064 | |||
1065 | /* register interrupt handler */ | ||
1066 | err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name, | ||
1067 | dev); | ||
1068 | if (err < 0) { | ||
1069 | netdev_err(dev, "failed to request interrupt\n"); | ||
1070 | goto exit_irq_fail; | ||
1071 | } | ||
1072 | |||
1073 | /* start the c_can controller */ | ||
1074 | c_can_start(dev); | ||
1075 | |||
1076 | napi_enable(&priv->napi); | ||
1077 | netif_start_queue(dev); | ||
1078 | |||
1079 | return 0; | ||
1080 | |||
1081 | exit_irq_fail: | ||
1082 | close_candev(dev); | ||
1083 | return err; | ||
1084 | } | ||
1085 | |||
1086 | static int c_can_close(struct net_device *dev) | ||
1087 | { | ||
1088 | struct c_can_priv *priv = netdev_priv(dev); | ||
1089 | |||
1090 | netif_stop_queue(dev); | ||
1091 | napi_disable(&priv->napi); | ||
1092 | c_can_stop(dev); | ||
1093 | free_irq(dev->irq, dev); | ||
1094 | close_candev(dev); | ||
1095 | |||
1096 | return 0; | ||
1097 | } | ||
1098 | |||
1099 | struct net_device *alloc_c_can_dev(void) | ||
1100 | { | ||
1101 | struct net_device *dev; | ||
1102 | struct c_can_priv *priv; | ||
1103 | |||
1104 | dev = alloc_candev(sizeof(struct c_can_priv), C_CAN_MSG_OBJ_TX_NUM); | ||
1105 | if (!dev) | ||
1106 | return NULL; | ||
1107 | |||
1108 | priv = netdev_priv(dev); | ||
1109 | netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT); | ||
1110 | |||
1111 | priv->dev = dev; | ||
1112 | priv->can.bittiming_const = &c_can_bittiming_const; | ||
1113 | priv->can.do_set_mode = c_can_set_mode; | ||
1114 | priv->can.do_get_berr_counter = c_can_get_berr_counter; | ||
1115 | priv->can.ctrlmode_supported = CAN_CTRLMODE_ONE_SHOT | | ||
1116 | CAN_CTRLMODE_LOOPBACK | | ||
1117 | CAN_CTRLMODE_LISTENONLY | | ||
1118 | CAN_CTRLMODE_BERR_REPORTING; | ||
1119 | |||
1120 | return dev; | ||
1121 | } | ||
1122 | EXPORT_SYMBOL_GPL(alloc_c_can_dev); | ||
1123 | |||
1124 | void free_c_can_dev(struct net_device *dev) | ||
1125 | { | ||
1126 | free_candev(dev); | ||
1127 | } | ||
1128 | EXPORT_SYMBOL_GPL(free_c_can_dev); | ||
1129 | |||
1130 | static const struct net_device_ops c_can_netdev_ops = { | ||
1131 | .ndo_open = c_can_open, | ||
1132 | .ndo_stop = c_can_close, | ||
1133 | .ndo_start_xmit = c_can_start_xmit, | ||
1134 | }; | ||
1135 | |||
1136 | int register_c_can_dev(struct net_device *dev) | ||
1137 | { | ||
1138 | dev->flags |= IFF_ECHO; /* we support local echo */ | ||
1139 | dev->netdev_ops = &c_can_netdev_ops; | ||
1140 | |||
1141 | return register_candev(dev); | ||
1142 | } | ||
1143 | EXPORT_SYMBOL_GPL(register_c_can_dev); | ||
1144 | |||
1145 | void unregister_c_can_dev(struct net_device *dev) | ||
1146 | { | ||
1147 | struct c_can_priv *priv = netdev_priv(dev); | ||
1148 | |||
1149 | /* disable all interrupts */ | ||
1150 | c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS); | ||
1151 | |||
1152 | unregister_candev(dev); | ||
1153 | } | ||
1154 | EXPORT_SYMBOL_GPL(unregister_c_can_dev); | ||
1155 | |||
1156 | MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>"); | ||
1157 | MODULE_LICENSE("GPL v2"); | ||
1158 | MODULE_DESCRIPTION("CAN bus driver for Bosch C_CAN controller"); | ||
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h new file mode 100644 index 000000000000..9b7fbef3d09a --- /dev/null +++ b/drivers/net/can/c_can/c_can.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * CAN bus driver for Bosch C_CAN controller | ||
3 | * | ||
4 | * Copyright (C) 2010 ST Microelectronics | ||
5 | * Bhupesh Sharma <bhupesh.sharma@st.com> | ||
6 | * | ||
7 | * Borrowed heavily from the C_CAN driver originally written by: | ||
8 | * Copyright (C) 2007 | ||
9 | * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de> | ||
10 | * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch> | ||
11 | * | ||
12 | * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B. | ||
13 | * Bosch C_CAN user manual can be obtained from: | ||
14 | * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/ | ||
15 | * users_manual_c_can.pdf | ||
16 | * | ||
17 | * This file is licensed under the terms of the GNU General Public | ||
18 | * License version 2. This program is licensed "as is" without any | ||
19 | * warranty of any kind, whether express or implied. | ||
20 | */ | ||
21 | |||
22 | #ifndef C_CAN_H | ||
23 | #define C_CAN_H | ||
24 | |||
25 | /* c_can IF registers */ | ||
26 | struct c_can_if_regs { | ||
27 | u16 com_req; | ||
28 | u16 com_mask; | ||
29 | u16 mask1; | ||
30 | u16 mask2; | ||
31 | u16 arb1; | ||
32 | u16 arb2; | ||
33 | u16 msg_cntrl; | ||
34 | u16 data[4]; | ||
35 | u16 _reserved[13]; | ||
36 | }; | ||
37 | |||
38 | /* c_can hardware registers */ | ||
39 | struct c_can_regs { | ||
40 | u16 control; | ||
41 | u16 status; | ||
42 | u16 err_cnt; | ||
43 | u16 btr; | ||
44 | u16 interrupt; | ||
45 | u16 test; | ||
46 | u16 brp_ext; | ||
47 | u16 _reserved1; | ||
48 | struct c_can_if_regs ifregs[2]; /* [0] = IF1 and [1] = IF2 */ | ||
49 | u16 _reserved2[8]; | ||
50 | u16 txrqst1; | ||
51 | u16 txrqst2; | ||
52 | u16 _reserved3[6]; | ||
53 | u16 newdat1; | ||
54 | u16 newdat2; | ||
55 | u16 _reserved4[6]; | ||
56 | u16 intpnd1; | ||
57 | u16 intpnd2; | ||
58 | u16 _reserved5[6]; | ||
59 | u16 msgval1; | ||
60 | u16 msgval2; | ||
61 | u16 _reserved6[6]; | ||
62 | }; | ||
63 | |||
64 | /* c_can private data structure */ | ||
65 | struct c_can_priv { | ||
66 | struct can_priv can; /* must be the first member */ | ||
67 | struct napi_struct napi; | ||
68 | struct net_device *dev; | ||
69 | int tx_object; | ||
70 | int current_status; | ||
71 | int last_status; | ||
72 | u16 (*read_reg) (struct c_can_priv *priv, void *reg); | ||
73 | void (*write_reg) (struct c_can_priv *priv, void *reg, u16 val); | ||
74 | struct c_can_regs __iomem *regs; | ||
75 | unsigned long irq_flags; /* for request_irq() */ | ||
76 | unsigned int tx_next; | ||
77 | unsigned int tx_echo; | ||
78 | void *priv; /* for board-specific data */ | ||
79 | }; | ||
80 | |||
81 | struct net_device *alloc_c_can_dev(void); | ||
82 | void free_c_can_dev(struct net_device *dev); | ||
83 | int register_c_can_dev(struct net_device *dev); | ||
84 | void unregister_c_can_dev(struct net_device *dev); | ||
85 | |||
86 | #endif /* C_CAN_H */ | ||
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c new file mode 100644 index 000000000000..e629b961ae2d --- /dev/null +++ b/drivers/net/can/c_can/c_can_platform.c | |||
@@ -0,0 +1,215 @@ | |||
1 | /* | ||
2 | * Platform CAN bus driver for Bosch C_CAN controller | ||
3 | * | ||
4 | * Copyright (C) 2010 ST Microelectronics | ||
5 | * Bhupesh Sharma <bhupesh.sharma@st.com> | ||
6 | * | ||
7 | * Borrowed heavily from the C_CAN driver originally written by: | ||
8 | * Copyright (C) 2007 | ||
9 | * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de> | ||
10 | * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch> | ||
11 | * | ||
12 | * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B. | ||
13 | * Bosch C_CAN user manual can be obtained from: | ||
14 | * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/ | ||
15 | * users_manual_c_can.pdf | ||
16 | * | ||
17 | * This file is licensed under the terms of the GNU General Public | ||
18 | * License version 2. This program is licensed "as is" without any | ||
19 | * warranty of any kind, whether express or implied. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/version.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <linux/if_arp.h> | ||
29 | #include <linux/if_ether.h> | ||
30 | #include <linux/list.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/io.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/clk.h> | ||
35 | |||
36 | #include <linux/can/dev.h> | ||
37 | |||
38 | #include "c_can.h" | ||
39 | |||
40 | /* | ||
41 | * 16-bit c_can registers can be arranged differently in the memory | ||
42 | * architecture of different implementations. For example: 16-bit | ||
43 | * registers can be aligned to a 16-bit boundary or 32-bit boundary etc. | ||
44 | * Handle the same by providing a common read/write interface. | ||
45 | */ | ||
46 | static u16 c_can_plat_read_reg_aligned_to_16bit(struct c_can_priv *priv, | ||
47 | void *reg) | ||
48 | { | ||
49 | return readw(reg); | ||
50 | } | ||
51 | |||
52 | static void c_can_plat_write_reg_aligned_to_16bit(struct c_can_priv *priv, | ||
53 | void *reg, u16 val) | ||
54 | { | ||
55 | writew(val, reg); | ||
56 | } | ||
57 | |||
58 | static u16 c_can_plat_read_reg_aligned_to_32bit(struct c_can_priv *priv, | ||
59 | void *reg) | ||
60 | { | ||
61 | return readw(reg + (long)reg - (long)priv->regs); | ||
62 | } | ||
63 | |||
64 | static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv, | ||
65 | void *reg, u16 val) | ||
66 | { | ||
67 | writew(val, reg + (long)reg - (long)priv->regs); | ||
68 | } | ||
69 | |||
70 | static int __devinit c_can_plat_probe(struct platform_device *pdev) | ||
71 | { | ||
72 | int ret; | ||
73 | void __iomem *addr; | ||
74 | struct net_device *dev; | ||
75 | struct c_can_priv *priv; | ||
76 | struct resource *mem, *irq; | ||
77 | #ifdef CONFIG_HAVE_CLK | ||
78 | struct clk *clk; | ||
79 | |||
80 | /* get the appropriate clk */ | ||
81 | clk = clk_get(&pdev->dev, NULL); | ||
82 | if (IS_ERR(clk)) { | ||
83 | dev_err(&pdev->dev, "no clock defined\n"); | ||
84 | ret = -ENODEV; | ||
85 | goto exit; | ||
86 | } | ||
87 | #endif | ||
88 | |||
89 | /* get the platform data */ | ||
90 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
91 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
92 | if (!mem || (irq <= 0)) { | ||
93 | ret = -ENODEV; | ||
94 | goto exit_free_clk; | ||
95 | } | ||
96 | |||
97 | if (!request_mem_region(mem->start, resource_size(mem), | ||
98 | KBUILD_MODNAME)) { | ||
99 | dev_err(&pdev->dev, "resource unavailable\n"); | ||
100 | ret = -ENODEV; | ||
101 | goto exit_free_clk; | ||
102 | } | ||
103 | |||
104 | addr = ioremap(mem->start, resource_size(mem)); | ||
105 | if (!addr) { | ||
106 | dev_err(&pdev->dev, "failed to map can port\n"); | ||
107 | ret = -ENOMEM; | ||
108 | goto exit_release_mem; | ||
109 | } | ||
110 | |||
111 | /* allocate the c_can device */ | ||
112 | dev = alloc_c_can_dev(); | ||
113 | if (!dev) { | ||
114 | ret = -ENOMEM; | ||
115 | goto exit_iounmap; | ||
116 | } | ||
117 | |||
118 | priv = netdev_priv(dev); | ||
119 | |||
120 | dev->irq = irq->start; | ||
121 | priv->regs = addr; | ||
122 | #ifdef CONFIG_HAVE_CLK | ||
123 | priv->can.clock.freq = clk_get_rate(clk); | ||
124 | priv->priv = clk; | ||
125 | #endif | ||
126 | |||
127 | switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) { | ||
128 | case IORESOURCE_MEM_32BIT: | ||
129 | priv->read_reg = c_can_plat_read_reg_aligned_to_32bit; | ||
130 | priv->write_reg = c_can_plat_write_reg_aligned_to_32bit; | ||
131 | break; | ||
132 | case IORESOURCE_MEM_16BIT: | ||
133 | default: | ||
134 | priv->read_reg = c_can_plat_read_reg_aligned_to_16bit; | ||
135 | priv->write_reg = c_can_plat_write_reg_aligned_to_16bit; | ||
136 | break; | ||
137 | } | ||
138 | |||
139 | platform_set_drvdata(pdev, dev); | ||
140 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
141 | |||
142 | ret = register_c_can_dev(dev); | ||
143 | if (ret) { | ||
144 | dev_err(&pdev->dev, "registering %s failed (err=%d)\n", | ||
145 | KBUILD_MODNAME, ret); | ||
146 | goto exit_free_device; | ||
147 | } | ||
148 | |||
149 | dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n", | ||
150 | KBUILD_MODNAME, priv->regs, dev->irq); | ||
151 | return 0; | ||
152 | |||
153 | exit_free_device: | ||
154 | platform_set_drvdata(pdev, NULL); | ||
155 | free_c_can_dev(dev); | ||
156 | exit_iounmap: | ||
157 | iounmap(addr); | ||
158 | exit_release_mem: | ||
159 | release_mem_region(mem->start, resource_size(mem)); | ||
160 | exit_free_clk: | ||
161 | #ifdef CONFIG_HAVE_CLK | ||
162 | clk_put(clk); | ||
163 | exit: | ||
164 | #endif | ||
165 | dev_err(&pdev->dev, "probe failed\n"); | ||
166 | |||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | static int __devexit c_can_plat_remove(struct platform_device *pdev) | ||
171 | { | ||
172 | struct net_device *dev = platform_get_drvdata(pdev); | ||
173 | struct c_can_priv *priv = netdev_priv(dev); | ||
174 | struct resource *mem; | ||
175 | |||
176 | unregister_c_can_dev(dev); | ||
177 | platform_set_drvdata(pdev, NULL); | ||
178 | |||
179 | free_c_can_dev(dev); | ||
180 | iounmap(priv->regs); | ||
181 | |||
182 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
183 | release_mem_region(mem->start, resource_size(mem)); | ||
184 | |||
185 | #ifdef CONFIG_HAVE_CLK | ||
186 | clk_put(priv->priv); | ||
187 | #endif | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static struct platform_driver c_can_plat_driver = { | ||
193 | .driver = { | ||
194 | .name = KBUILD_MODNAME, | ||
195 | .owner = THIS_MODULE, | ||
196 | }, | ||
197 | .probe = c_can_plat_probe, | ||
198 | .remove = __devexit_p(c_can_plat_remove), | ||
199 | }; | ||
200 | |||
201 | static int __init c_can_plat_init(void) | ||
202 | { | ||
203 | return platform_driver_register(&c_can_plat_driver); | ||
204 | } | ||
205 | module_init(c_can_plat_init); | ||
206 | |||
207 | static void __exit c_can_plat_exit(void) | ||
208 | { | ||
209 | platform_driver_unregister(&c_can_plat_driver); | ||
210 | } | ||
211 | module_exit(c_can_plat_exit); | ||
212 | |||
213 | MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>"); | ||
214 | MODULE_LICENSE("GPL v2"); | ||
215 | MODULE_DESCRIPTION("Platform CAN bus driver for Bosch C_CAN controller"); | ||
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index b9a6d7a5a739..102b16c6cc97 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/mfd/core.h> | ||
18 | 19 | ||
19 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
20 | #include <linux/can.h> | 21 | #include <linux/can.h> |
@@ -1618,7 +1619,7 @@ static ssize_t ican3_sysfs_set_term(struct device *dev, | |||
1618 | return count; | 1619 | return count; |
1619 | } | 1620 | } |
1620 | 1621 | ||
1621 | static DEVICE_ATTR(termination, S_IWUGO | S_IRUGO, ican3_sysfs_show_term, | 1622 | static DEVICE_ATTR(termination, S_IWUSR | S_IRUGO, ican3_sysfs_show_term, |
1622 | ican3_sysfs_set_term); | 1623 | ican3_sysfs_set_term); |
1623 | 1624 | ||
1624 | static struct attribute *ican3_sysfs_attrs[] = { | 1625 | static struct attribute *ican3_sysfs_attrs[] = { |
@@ -1643,7 +1644,7 @@ static int __devinit ican3_probe(struct platform_device *pdev) | |||
1643 | struct device *dev; | 1644 | struct device *dev; |
1644 | int ret; | 1645 | int ret; |
1645 | 1646 | ||
1646 | pdata = pdev->dev.platform_data; | 1647 | pdata = mfd_get_data(pdev); |
1647 | if (!pdata) | 1648 | if (!pdata) |
1648 | return -ENXIO; | 1649 | return -ENXIO; |
1649 | 1650 | ||
diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 7ab534aee452..7513c4523ac4 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c | |||
@@ -940,7 +940,7 @@ static int mcp251x_open(struct net_device *net) | |||
940 | goto open_unlock; | 940 | goto open_unlock; |
941 | } | 941 | } |
942 | 942 | ||
943 | priv->wq = create_freezeable_workqueue("mcp251x_wq"); | 943 | priv->wq = create_freezable_workqueue("mcp251x_wq"); |
944 | INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); | 944 | INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); |
945 | INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); | 945 | INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); |
946 | 946 | ||
diff --git a/drivers/net/can/mscan/Kconfig b/drivers/net/can/mscan/Kconfig index 27d1d398e25e..d38706958af6 100644 --- a/drivers/net/can/mscan/Kconfig +++ b/drivers/net/can/mscan/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | config CAN_MSCAN | 1 | config CAN_MSCAN |
2 | depends on CAN_DEV && (PPC || M68K || M68KNOMMU) | 2 | depends on CAN_DEV && (PPC || M68K) |
3 | tristate "Support for Freescale MSCAN based chips" | 3 | tristate "Support for Freescale MSCAN based chips" |
4 | ---help--- | 4 | ---help--- |
5 | The Motorola Scalable Controller Area Network (MSCAN) definition | 5 | The Motorola Scalable Controller Area Network (MSCAN) definition |
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 312b9c8f4f3b..c0a1bc5b1435 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c | |||
@@ -247,10 +247,9 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, | |||
247 | } | 247 | } |
248 | #endif /* CONFIG_PPC_MPC512x */ | 248 | #endif /* CONFIG_PPC_MPC512x */ |
249 | 249 | ||
250 | static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev, | 250 | static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev) |
251 | const struct of_device_id *id) | ||
252 | { | 251 | { |
253 | struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data; | 252 | struct mpc5xxx_can_data *data; |
254 | struct device_node *np = ofdev->dev.of_node; | 253 | struct device_node *np = ofdev->dev.of_node; |
255 | struct net_device *dev; | 254 | struct net_device *dev; |
256 | struct mscan_priv *priv; | 255 | struct mscan_priv *priv; |
@@ -259,6 +258,10 @@ static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev, | |||
259 | int irq, mscan_clksrc = 0; | 258 | int irq, mscan_clksrc = 0; |
260 | int err = -ENOMEM; | 259 | int err = -ENOMEM; |
261 | 260 | ||
261 | if (!ofdev->dev.of_match) | ||
262 | return -EINVAL; | ||
263 | data = (struct mpc5xxx_can_data *)of_dev->dev.of_match->data; | ||
264 | |||
262 | base = of_iomap(np, 0); | 265 | base = of_iomap(np, 0); |
263 | if (!base) { | 266 | if (!base) { |
264 | dev_err(&ofdev->dev, "couldn't ioremap\n"); | 267 | dev_err(&ofdev->dev, "couldn't ioremap\n"); |
@@ -391,7 +394,7 @@ static struct of_device_id __devinitdata mpc5xxx_can_table[] = { | |||
391 | {}, | 394 | {}, |
392 | }; | 395 | }; |
393 | 396 | ||
394 | static struct of_platform_driver mpc5xxx_can_driver = { | 397 | static struct platform_driver mpc5xxx_can_driver = { |
395 | .driver = { | 398 | .driver = { |
396 | .name = "mpc5xxx_can", | 399 | .name = "mpc5xxx_can", |
397 | .owner = THIS_MODULE, | 400 | .owner = THIS_MODULE, |
@@ -407,13 +410,13 @@ static struct of_platform_driver mpc5xxx_can_driver = { | |||
407 | 410 | ||
408 | static int __init mpc5xxx_can_init(void) | 411 | static int __init mpc5xxx_can_init(void) |
409 | { | 412 | { |
410 | return of_register_platform_driver(&mpc5xxx_can_driver); | 413 | return platform_driver_register(&mpc5xxx_can_driver); |
411 | } | 414 | } |
412 | module_init(mpc5xxx_can_init); | 415 | module_init(mpc5xxx_can_init); |
413 | 416 | ||
414 | static void __exit mpc5xxx_can_exit(void) | 417 | static void __exit mpc5xxx_can_exit(void) |
415 | { | 418 | { |
416 | return of_unregister_platform_driver(&mpc5xxx_can_driver); | 419 | platform_driver_unregister(&mpc5xxx_can_driver); |
417 | }; | 420 | }; |
418 | module_exit(mpc5xxx_can_exit); | 421 | module_exit(mpc5xxx_can_exit); |
419 | 422 | ||
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index c42e97268248..e54712b22c27 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c | |||
@@ -185,7 +185,7 @@ struct pch_can_priv { | |||
185 | 185 | ||
186 | static struct can_bittiming_const pch_can_bittiming_const = { | 186 | static struct can_bittiming_const pch_can_bittiming_const = { |
187 | .name = KBUILD_MODNAME, | 187 | .name = KBUILD_MODNAME, |
188 | .tseg1_min = 1, | 188 | .tseg1_min = 2, |
189 | .tseg1_max = 16, | 189 | .tseg1_max = 16, |
190 | .tseg2_min = 1, | 190 | .tseg2_min = 1, |
191 | .tseg2_max = 8, | 191 | .tseg2_max = 8, |
@@ -959,13 +959,13 @@ static void __devexit pch_can_remove(struct pci_dev *pdev) | |||
959 | struct pch_can_priv *priv = netdev_priv(ndev); | 959 | struct pch_can_priv *priv = netdev_priv(ndev); |
960 | 960 | ||
961 | unregister_candev(priv->ndev); | 961 | unregister_candev(priv->ndev); |
962 | pci_iounmap(pdev, priv->regs); | ||
963 | if (priv->use_msi) | 962 | if (priv->use_msi) |
964 | pci_disable_msi(priv->dev); | 963 | pci_disable_msi(priv->dev); |
965 | pci_release_regions(pdev); | 964 | pci_release_regions(pdev); |
966 | pci_disable_device(pdev); | 965 | pci_disable_device(pdev); |
967 | pci_set_drvdata(pdev, NULL); | 966 | pci_set_drvdata(pdev, NULL); |
968 | pch_can_reset(priv); | 967 | pch_can_reset(priv); |
968 | pci_iounmap(pdev, priv->regs); | ||
969 | free_candev(priv->ndev); | 969 | free_candev(priv->ndev); |
970 | } | 970 | } |
971 | 971 | ||
@@ -1238,6 +1238,7 @@ static int __devinit pch_can_probe(struct pci_dev *pdev, | |||
1238 | priv->use_msi = 0; | 1238 | priv->use_msi = 0; |
1239 | } else { | 1239 | } else { |
1240 | netdev_err(ndev, "PCH CAN opened with MSI\n"); | 1240 | netdev_err(ndev, "PCH CAN opened with MSI\n"); |
1241 | pci_set_master(pdev); | ||
1241 | priv->use_msi = 1; | 1242 | priv->use_msi = 1; |
1242 | } | 1243 | } |
1243 | 1244 | ||
diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index 09c3e9db9316..9793df6e3455 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c | |||
@@ -87,8 +87,7 @@ static int __devexit sja1000_ofp_remove(struct platform_device *ofdev) | |||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static int __devinit sja1000_ofp_probe(struct platform_device *ofdev, | 90 | static int __devinit sja1000_ofp_probe(struct platform_device *ofdev) |
91 | const struct of_device_id *id) | ||
92 | { | 91 | { |
93 | struct device_node *np = ofdev->dev.of_node; | 92 | struct device_node *np = ofdev->dev.of_node; |
94 | struct net_device *dev; | 93 | struct net_device *dev; |
@@ -210,7 +209,7 @@ static struct of_device_id __devinitdata sja1000_ofp_table[] = { | |||
210 | }; | 209 | }; |
211 | MODULE_DEVICE_TABLE(of, sja1000_ofp_table); | 210 | MODULE_DEVICE_TABLE(of, sja1000_ofp_table); |
212 | 211 | ||
213 | static struct of_platform_driver sja1000_ofp_driver = { | 212 | static struct platform_driver sja1000_ofp_driver = { |
214 | .driver = { | 213 | .driver = { |
215 | .owner = THIS_MODULE, | 214 | .owner = THIS_MODULE, |
216 | .name = DRV_NAME, | 215 | .name = DRV_NAME, |
@@ -222,12 +221,12 @@ static struct of_platform_driver sja1000_ofp_driver = { | |||
222 | 221 | ||
223 | static int __init sja1000_ofp_init(void) | 222 | static int __init sja1000_ofp_init(void) |
224 | { | 223 | { |
225 | return of_register_platform_driver(&sja1000_ofp_driver); | 224 | return platform_driver_register(&sja1000_ofp_driver); |
226 | } | 225 | } |
227 | module_init(sja1000_ofp_init); | 226 | module_init(sja1000_ofp_init); |
228 | 227 | ||
229 | static void __exit sja1000_ofp_exit(void) | 228 | static void __exit sja1000_ofp_exit(void) |
230 | { | 229 | { |
231 | return of_unregister_platform_driver(&sja1000_ofp_driver); | 230 | return platform_driver_unregister(&sja1000_ofp_driver); |
232 | }; | 231 | }; |
233 | module_exit(sja1000_ofp_exit); | 232 | module_exit(sja1000_ofp_exit); |
diff --git a/drivers/net/can/softing/Kconfig b/drivers/net/can/softing/Kconfig new file mode 100644 index 000000000000..5de46a9a77bb --- /dev/null +++ b/drivers/net/can/softing/Kconfig | |||
@@ -0,0 +1,30 @@ | |||
1 | config CAN_SOFTING | ||
2 | tristate "Softing Gmbh CAN generic support" | ||
3 | depends on CAN_DEV && HAS_IOMEM | ||
4 | ---help--- | ||
5 | Support for CAN cards from Softing Gmbh & some cards | ||
6 | from Vector Gmbh. | ||
7 | Softing Gmbh CAN cards come with 1 or 2 physical busses. | ||
8 | Those cards typically use Dual Port RAM to communicate | ||
9 | with the host CPU. The interface is then identical for PCI | ||
10 | and PCMCIA cards. This driver operates on a platform device, | ||
11 | which has been created by softing_cs or softing_pci driver. | ||
12 | Warning: | ||
13 | The API of the card does not allow fine control per bus, but | ||
14 | controls the 2 busses on the card together. | ||
15 | As such, some actions (start/stop/busoff recovery) on 1 bus | ||
16 | must bring down the other bus too temporarily. | ||
17 | |||
18 | config CAN_SOFTING_CS | ||
19 | tristate "Softing Gmbh CAN pcmcia cards" | ||
20 | depends on PCMCIA | ||
21 | depends on CAN_SOFTING | ||
22 | ---help--- | ||
23 | Support for PCMCIA cards from Softing Gmbh & some cards | ||
24 | from Vector Gmbh. | ||
25 | You need firmware for these, which you can get at | ||
26 | http://developer.berlios.de/projects/socketcan/ | ||
27 | This version of the driver is written against | ||
28 | firmware version 4.6 (softing-fw-4.6-binaries.tar.gz) | ||
29 | In order to use the card as CAN device, you need the Softing generic | ||
30 | support too. | ||
diff --git a/drivers/net/can/softing/Makefile b/drivers/net/can/softing/Makefile new file mode 100644 index 000000000000..c5e5016c742e --- /dev/null +++ b/drivers/net/can/softing/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | |||
2 | softing-y := softing_main.o softing_fw.o | ||
3 | obj-$(CONFIG_CAN_SOFTING) += softing.o | ||
4 | obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o | ||
5 | |||
6 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG | ||
diff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h new file mode 100644 index 000000000000..7ec9f4db3d52 --- /dev/null +++ b/drivers/net/can/softing/softing.h | |||
@@ -0,0 +1,167 @@ | |||
1 | /* | ||
2 | * softing common interfaces | ||
3 | * | ||
4 | * by Kurt Van Dijck, 2008-2010 | ||
5 | */ | ||
6 | |||
7 | #include <linux/atomic.h> | ||
8 | #include <linux/netdevice.h> | ||
9 | #include <linux/ktime.h> | ||
10 | #include <linux/mutex.h> | ||
11 | #include <linux/spinlock.h> | ||
12 | #include <linux/can.h> | ||
13 | #include <linux/can/dev.h> | ||
14 | |||
15 | #include "softing_platform.h" | ||
16 | |||
17 | struct softing; | ||
18 | |||
19 | struct softing_priv { | ||
20 | struct can_priv can; /* must be the first member! */ | ||
21 | struct net_device *netdev; | ||
22 | struct softing *card; | ||
23 | struct { | ||
24 | int pending; | ||
25 | /* variables wich hold the circular buffer */ | ||
26 | int echo_put; | ||
27 | int echo_get; | ||
28 | } tx; | ||
29 | struct can_bittiming_const btr_const; | ||
30 | int index; | ||
31 | uint8_t output; | ||
32 | uint16_t chip; | ||
33 | }; | ||
34 | #define netdev2softing(netdev) ((struct softing_priv *)netdev_priv(netdev)) | ||
35 | |||
36 | struct softing { | ||
37 | const struct softing_platform_data *pdat; | ||
38 | struct platform_device *pdev; | ||
39 | struct net_device *net[2]; | ||
40 | spinlock_t spin; /* protect this structure & DPRAM access */ | ||
41 | ktime_t ts_ref; | ||
42 | ktime_t ts_overflow; /* timestamp overflow value, in ktime */ | ||
43 | |||
44 | struct { | ||
45 | /* indication of firmware status */ | ||
46 | int up; | ||
47 | /* protection of the 'up' variable */ | ||
48 | struct mutex lock; | ||
49 | } fw; | ||
50 | struct { | ||
51 | int nr; | ||
52 | int requested; | ||
53 | int svc_count; | ||
54 | unsigned int dpram_position; | ||
55 | } irq; | ||
56 | struct { | ||
57 | int pending; | ||
58 | int last_bus; | ||
59 | /* | ||
60 | * keep the bus that last tx'd a message, | ||
61 | * in order to let every netdev queue resume | ||
62 | */ | ||
63 | } tx; | ||
64 | __iomem uint8_t *dpram; | ||
65 | unsigned long dpram_phys; | ||
66 | unsigned long dpram_size; | ||
67 | struct { | ||
68 | uint16_t fw_version, hw_version, license, serial; | ||
69 | uint16_t chip[2]; | ||
70 | unsigned int freq; /* remote cpu's operating frequency */ | ||
71 | } id; | ||
72 | }; | ||
73 | |||
74 | extern int softing_default_output(struct net_device *netdev); | ||
75 | |||
76 | extern ktime_t softing_raw2ktime(struct softing *card, u32 raw); | ||
77 | |||
78 | extern int softing_chip_poweron(struct softing *card); | ||
79 | |||
80 | extern int softing_bootloader_command(struct softing *card, int16_t cmd, | ||
81 | const char *msg); | ||
82 | |||
83 | /* Load firmware after reset */ | ||
84 | extern int softing_load_fw(const char *file, struct softing *card, | ||
85 | __iomem uint8_t *virt, unsigned int size, int offset); | ||
86 | |||
87 | /* Load final application firmware after bootloader */ | ||
88 | extern int softing_load_app_fw(const char *file, struct softing *card); | ||
89 | |||
90 | /* | ||
91 | * enable or disable irq | ||
92 | * only called with fw.lock locked | ||
93 | */ | ||
94 | extern int softing_enable_irq(struct softing *card, int enable); | ||
95 | |||
96 | /* start/stop 1 bus on card */ | ||
97 | extern int softing_startstop(struct net_device *netdev, int up); | ||
98 | |||
99 | /* netif_rx() */ | ||
100 | extern int softing_netdev_rx(struct net_device *netdev, | ||
101 | const struct can_frame *msg, ktime_t ktime); | ||
102 | |||
103 | /* SOFTING DPRAM mappings */ | ||
104 | #define DPRAM_RX 0x0000 | ||
105 | #define DPRAM_RX_SIZE 32 | ||
106 | #define DPRAM_RX_CNT 16 | ||
107 | #define DPRAM_RX_RD 0x0201 /* uint8_t */ | ||
108 | #define DPRAM_RX_WR 0x0205 /* uint8_t */ | ||
109 | #define DPRAM_RX_LOST 0x0207 /* uint8_t */ | ||
110 | |||
111 | #define DPRAM_FCT_PARAM 0x0300 /* int16_t [20] */ | ||
112 | #define DPRAM_FCT_RESULT 0x0328 /* int16_t */ | ||
113 | #define DPRAM_FCT_HOST 0x032b /* uint16_t */ | ||
114 | |||
115 | #define DPRAM_INFO_BUSSTATE 0x0331 /* uint16_t */ | ||
116 | #define DPRAM_INFO_BUSSTATE2 0x0335 /* uint16_t */ | ||
117 | #define DPRAM_INFO_ERRSTATE 0x0339 /* uint16_t */ | ||
118 | #define DPRAM_INFO_ERRSTATE2 0x033d /* uint16_t */ | ||
119 | #define DPRAM_RESET 0x0341 /* uint16_t */ | ||
120 | #define DPRAM_CLR_RECV_FIFO 0x0345 /* uint16_t */ | ||
121 | #define DPRAM_RESET_TIME 0x034d /* uint16_t */ | ||
122 | #define DPRAM_TIME 0x0350 /* uint64_t */ | ||
123 | #define DPRAM_WR_START 0x0358 /* uint8_t */ | ||
124 | #define DPRAM_WR_END 0x0359 /* uint8_t */ | ||
125 | #define DPRAM_RESET_RX_FIFO 0x0361 /* uint16_t */ | ||
126 | #define DPRAM_RESET_TX_FIFO 0x0364 /* uint8_t */ | ||
127 | #define DPRAM_READ_FIFO_LEVEL 0x0365 /* uint8_t */ | ||
128 | #define DPRAM_RX_FIFO_LEVEL 0x0366 /* uint16_t */ | ||
129 | #define DPRAM_TX_FIFO_LEVEL 0x0366 /* uint16_t */ | ||
130 | |||
131 | #define DPRAM_TX 0x0400 /* uint16_t */ | ||
132 | #define DPRAM_TX_SIZE 16 | ||
133 | #define DPRAM_TX_CNT 32 | ||
134 | #define DPRAM_TX_RD 0x0601 /* uint8_t */ | ||
135 | #define DPRAM_TX_WR 0x0605 /* uint8_t */ | ||
136 | |||
137 | #define DPRAM_COMMAND 0x07e0 /* uint16_t */ | ||
138 | #define DPRAM_RECEIPT 0x07f0 /* uint16_t */ | ||
139 | #define DPRAM_IRQ_TOHOST 0x07fe /* uint8_t */ | ||
140 | #define DPRAM_IRQ_TOCARD 0x07ff /* uint8_t */ | ||
141 | |||
142 | #define DPRAM_V2_RESET 0x0e00 /* uint8_t */ | ||
143 | #define DPRAM_V2_IRQ_TOHOST 0x0e02 /* uint8_t */ | ||
144 | |||
145 | #define TXMAX (DPRAM_TX_CNT - 1) | ||
146 | |||
147 | /* DPRAM return codes */ | ||
148 | #define RES_NONE 0 | ||
149 | #define RES_OK 1 | ||
150 | #define RES_NOK 2 | ||
151 | #define RES_UNKNOWN 3 | ||
152 | /* DPRAM flags */ | ||
153 | #define CMD_TX 0x01 | ||
154 | #define CMD_ACK 0x02 | ||
155 | #define CMD_XTD 0x04 | ||
156 | #define CMD_RTR 0x08 | ||
157 | #define CMD_ERR 0x10 | ||
158 | #define CMD_BUS2 0x80 | ||
159 | |||
160 | /* returned fifo entry bus state masks */ | ||
161 | #define SF_MASK_BUSOFF 0x80 | ||
162 | #define SF_MASK_EPASSIVE 0x60 | ||
163 | |||
164 | /* bus states */ | ||
165 | #define STATE_BUSOFF 2 | ||
166 | #define STATE_EPASSIVE 1 | ||
167 | #define STATE_EACTIVE 0 | ||
diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c new file mode 100644 index 000000000000..c11bb4de8630 --- /dev/null +++ b/drivers/net/can/softing/softing_cs.c | |||
@@ -0,0 +1,360 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2010 | ||
3 | * | ||
4 | * - Kurt Van Dijck, EIA Electronics | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the version 2 of the GNU General Public License | ||
8 | * as published by the Free Software Foundation | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | #include <pcmcia/cistpl.h> | ||
25 | #include <pcmcia/ds.h> | ||
26 | |||
27 | #include "softing_platform.h" | ||
28 | |||
29 | static int softingcs_index; | ||
30 | static spinlock_t softingcs_index_lock; | ||
31 | |||
32 | static int softingcs_reset(struct platform_device *pdev, int v); | ||
33 | static int softingcs_enable_irq(struct platform_device *pdev, int v); | ||
34 | |||
35 | /* | ||
36 | * platform_data descriptions | ||
37 | */ | ||
38 | #define MHZ (1000*1000) | ||
39 | static const struct softing_platform_data softingcs_platform_data[] = { | ||
40 | { | ||
41 | .name = "CANcard", | ||
42 | .manf = 0x0168, .prod = 0x001, | ||
43 | .generation = 1, | ||
44 | .nbus = 2, | ||
45 | .freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4, | ||
46 | .dpram_size = 0x0800, | ||
47 | .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, | ||
48 | .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, | ||
49 | .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, | ||
50 | .reset = softingcs_reset, | ||
51 | .enable_irq = softingcs_enable_irq, | ||
52 | }, { | ||
53 | .name = "CANcard-NEC", | ||
54 | .manf = 0x0168, .prod = 0x002, | ||
55 | .generation = 1, | ||
56 | .nbus = 2, | ||
57 | .freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4, | ||
58 | .dpram_size = 0x0800, | ||
59 | .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, | ||
60 | .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, | ||
61 | .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, | ||
62 | .reset = softingcs_reset, | ||
63 | .enable_irq = softingcs_enable_irq, | ||
64 | }, { | ||
65 | .name = "CANcard-SJA", | ||
66 | .manf = 0x0168, .prod = 0x004, | ||
67 | .generation = 1, | ||
68 | .nbus = 2, | ||
69 | .freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4, | ||
70 | .dpram_size = 0x0800, | ||
71 | .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, | ||
72 | .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, | ||
73 | .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",}, | ||
74 | .reset = softingcs_reset, | ||
75 | .enable_irq = softingcs_enable_irq, | ||
76 | }, { | ||
77 | .name = "CANcard-2", | ||
78 | .manf = 0x0168, .prod = 0x005, | ||
79 | .generation = 2, | ||
80 | .nbus = 2, | ||
81 | .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4, | ||
82 | .dpram_size = 0x1000, | ||
83 | .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",}, | ||
84 | .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",}, | ||
85 | .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",}, | ||
86 | .reset = softingcs_reset, | ||
87 | .enable_irq = NULL, | ||
88 | }, { | ||
89 | .name = "Vector-CANcard", | ||
90 | .manf = 0x0168, .prod = 0x081, | ||
91 | .generation = 1, | ||
92 | .nbus = 2, | ||
93 | .freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4, | ||
94 | .dpram_size = 0x0800, | ||
95 | .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, | ||
96 | .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, | ||
97 | .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, | ||
98 | .reset = softingcs_reset, | ||
99 | .enable_irq = softingcs_enable_irq, | ||
100 | }, { | ||
101 | .name = "Vector-CANcard-SJA", | ||
102 | .manf = 0x0168, .prod = 0x084, | ||
103 | .generation = 1, | ||
104 | .nbus = 2, | ||
105 | .freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4, | ||
106 | .dpram_size = 0x0800, | ||
107 | .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, | ||
108 | .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, | ||
109 | .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",}, | ||
110 | .reset = softingcs_reset, | ||
111 | .enable_irq = softingcs_enable_irq, | ||
112 | }, { | ||
113 | .name = "Vector-CANcard-2", | ||
114 | .manf = 0x0168, .prod = 0x085, | ||
115 | .generation = 2, | ||
116 | .nbus = 2, | ||
117 | .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4, | ||
118 | .dpram_size = 0x1000, | ||
119 | .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",}, | ||
120 | .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",}, | ||
121 | .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",}, | ||
122 | .reset = softingcs_reset, | ||
123 | .enable_irq = NULL, | ||
124 | }, { | ||
125 | .name = "EDICcard-NEC", | ||
126 | .manf = 0x0168, .prod = 0x102, | ||
127 | .generation = 1, | ||
128 | .nbus = 2, | ||
129 | .freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4, | ||
130 | .dpram_size = 0x0800, | ||
131 | .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, | ||
132 | .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, | ||
133 | .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, | ||
134 | .reset = softingcs_reset, | ||
135 | .enable_irq = softingcs_enable_irq, | ||
136 | }, { | ||
137 | .name = "EDICcard-2", | ||
138 | .manf = 0x0168, .prod = 0x105, | ||
139 | .generation = 2, | ||
140 | .nbus = 2, | ||
141 | .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4, | ||
142 | .dpram_size = 0x1000, | ||
143 | .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",}, | ||
144 | .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",}, | ||
145 | .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",}, | ||
146 | .reset = softingcs_reset, | ||
147 | .enable_irq = NULL, | ||
148 | }, { | ||
149 | 0, 0, | ||
150 | }, | ||
151 | }; | ||
152 | |||
153 | MODULE_FIRMWARE(fw_dir "bcard.bin"); | ||
154 | MODULE_FIRMWARE(fw_dir "ldcard.bin"); | ||
155 | MODULE_FIRMWARE(fw_dir "cancard.bin"); | ||
156 | MODULE_FIRMWARE(fw_dir "cansja.bin"); | ||
157 | |||
158 | MODULE_FIRMWARE(fw_dir "bcard2.bin"); | ||
159 | MODULE_FIRMWARE(fw_dir "ldcard2.bin"); | ||
160 | MODULE_FIRMWARE(fw_dir "cancrd2.bin"); | ||
161 | |||
162 | static __devinit const struct softing_platform_data | ||
163 | *softingcs_find_platform_data(unsigned int manf, unsigned int prod) | ||
164 | { | ||
165 | const struct softing_platform_data *lp; | ||
166 | |||
167 | for (lp = softingcs_platform_data; lp->manf; ++lp) { | ||
168 | if ((lp->manf == manf) && (lp->prod == prod)) | ||
169 | return lp; | ||
170 | } | ||
171 | return NULL; | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * platformdata callbacks | ||
176 | */ | ||
177 | static int softingcs_reset(struct platform_device *pdev, int v) | ||
178 | { | ||
179 | struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent); | ||
180 | |||
181 | dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20); | ||
182 | return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20); | ||
183 | } | ||
184 | |||
185 | static int softingcs_enable_irq(struct platform_device *pdev, int v) | ||
186 | { | ||
187 | struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent); | ||
188 | |||
189 | dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0); | ||
190 | return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * pcmcia check | ||
195 | */ | ||
196 | static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia, | ||
197 | void *priv_data) | ||
198 | { | ||
199 | struct softing_platform_data *pdat = priv_data; | ||
200 | struct resource *pres; | ||
201 | int memspeed = 0; | ||
202 | |||
203 | WARN_ON(!pdat); | ||
204 | pres = pcmcia->resource[PCMCIA_IOMEM_0]; | ||
205 | if (resource_size(pres) < 0x1000) | ||
206 | return -ERANGE; | ||
207 | |||
208 | pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE; | ||
209 | if (pdat->generation < 2) { | ||
210 | pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8; | ||
211 | memspeed = 3; | ||
212 | } else { | ||
213 | pres->flags |= WIN_DATA_WIDTH_16; | ||
214 | } | ||
215 | return pcmcia_request_window(pcmcia, pres, memspeed); | ||
216 | } | ||
217 | |||
218 | static __devexit void softingcs_remove(struct pcmcia_device *pcmcia) | ||
219 | { | ||
220 | struct platform_device *pdev = pcmcia->priv; | ||
221 | |||
222 | /* free bits */ | ||
223 | platform_device_unregister(pdev); | ||
224 | /* release pcmcia stuff */ | ||
225 | pcmcia_disable_device(pcmcia); | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * platform_device wrapper | ||
230 | * pdev->resource has 2 entries: io & irq | ||
231 | */ | ||
232 | static void softingcs_pdev_release(struct device *dev) | ||
233 | { | ||
234 | struct platform_device *pdev = to_platform_device(dev); | ||
235 | kfree(pdev); | ||
236 | } | ||
237 | |||
238 | static __devinit int softingcs_probe(struct pcmcia_device *pcmcia) | ||
239 | { | ||
240 | int ret; | ||
241 | struct platform_device *pdev; | ||
242 | const struct softing_platform_data *pdat; | ||
243 | struct resource *pres; | ||
244 | struct dev { | ||
245 | struct platform_device pdev; | ||
246 | struct resource res[2]; | ||
247 | } *dev; | ||
248 | |||
249 | /* find matching platform_data */ | ||
250 | pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id); | ||
251 | if (!pdat) | ||
252 | return -ENOTTY; | ||
253 | |||
254 | /* setup pcmcia device */ | ||
255 | pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM | | ||
256 | CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC; | ||
257 | ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat); | ||
258 | if (ret) | ||
259 | goto pcmcia_failed; | ||
260 | |||
261 | ret = pcmcia_enable_device(pcmcia); | ||
262 | if (ret < 0) | ||
263 | goto pcmcia_failed; | ||
264 | |||
265 | pres = pcmcia->resource[PCMCIA_IOMEM_0]; | ||
266 | if (!pres) { | ||
267 | ret = -EBADF; | ||
268 | goto pcmcia_bad; | ||
269 | } | ||
270 | |||
271 | /* create softing platform device */ | ||
272 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
273 | if (!dev) { | ||
274 | ret = -ENOMEM; | ||
275 | goto mem_failed; | ||
276 | } | ||
277 | dev->pdev.resource = dev->res; | ||
278 | dev->pdev.num_resources = ARRAY_SIZE(dev->res); | ||
279 | dev->pdev.dev.release = softingcs_pdev_release; | ||
280 | |||
281 | pdev = &dev->pdev; | ||
282 | pdev->dev.platform_data = (void *)pdat; | ||
283 | pdev->dev.parent = &pcmcia->dev; | ||
284 | pcmcia->priv = pdev; | ||
285 | |||
286 | /* platform device resources */ | ||
287 | pdev->resource[0].flags = IORESOURCE_MEM; | ||
288 | pdev->resource[0].start = pres->start; | ||
289 | pdev->resource[0].end = pres->end; | ||
290 | |||
291 | pdev->resource[1].flags = IORESOURCE_IRQ; | ||
292 | pdev->resource[1].start = pcmcia->irq; | ||
293 | pdev->resource[1].end = pdev->resource[1].start; | ||
294 | |||
295 | /* platform device setup */ | ||
296 | spin_lock(&softingcs_index_lock); | ||
297 | pdev->id = softingcs_index++; | ||
298 | spin_unlock(&softingcs_index_lock); | ||
299 | pdev->name = "softing"; | ||
300 | dev_set_name(&pdev->dev, "softingcs.%i", pdev->id); | ||
301 | ret = platform_device_register(pdev); | ||
302 | if (ret < 0) | ||
303 | goto platform_failed; | ||
304 | |||
305 | dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev)); | ||
306 | return 0; | ||
307 | |||
308 | platform_failed: | ||
309 | kfree(dev); | ||
310 | mem_failed: | ||
311 | pcmcia_bad: | ||
312 | pcmcia_failed: | ||
313 | pcmcia_disable_device(pcmcia); | ||
314 | pcmcia->priv = NULL; | ||
315 | return ret ?: -ENODEV; | ||
316 | } | ||
317 | |||
318 | static /*const*/ struct pcmcia_device_id softingcs_ids[] = { | ||
319 | /* softing */ | ||
320 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001), | ||
321 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002), | ||
322 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004), | ||
323 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005), | ||
324 | /* vector, manufacturer? */ | ||
325 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081), | ||
326 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084), | ||
327 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085), | ||
328 | /* EDIC */ | ||
329 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102), | ||
330 | PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105), | ||
331 | PCMCIA_DEVICE_NULL, | ||
332 | }; | ||
333 | |||
334 | MODULE_DEVICE_TABLE(pcmcia, softingcs_ids); | ||
335 | |||
336 | static struct pcmcia_driver softingcs_driver = { | ||
337 | .owner = THIS_MODULE, | ||
338 | .name = "softingcs", | ||
339 | .id_table = softingcs_ids, | ||
340 | .probe = softingcs_probe, | ||
341 | .remove = __devexit_p(softingcs_remove), | ||
342 | }; | ||
343 | |||
344 | static int __init softingcs_start(void) | ||
345 | { | ||
346 | spin_lock_init(&softingcs_index_lock); | ||
347 | return pcmcia_register_driver(&softingcs_driver); | ||
348 | } | ||
349 | |||
350 | static void __exit softingcs_stop(void) | ||
351 | { | ||
352 | pcmcia_unregister_driver(&softingcs_driver); | ||
353 | } | ||
354 | |||
355 | module_init(softingcs_start); | ||
356 | module_exit(softingcs_stop); | ||
357 | |||
358 | MODULE_DESCRIPTION("softing CANcard driver" | ||
359 | ", links PCMCIA card to softing driver"); | ||
360 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c new file mode 100644 index 000000000000..b520784fb197 --- /dev/null +++ b/drivers/net/can/softing/softing_fw.c | |||
@@ -0,0 +1,691 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2010 | ||
3 | * | ||
4 | * - Kurt Van Dijck, EIA Electronics | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the version 2 of the GNU General Public License | ||
8 | * as published by the Free Software Foundation | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/firmware.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <asm/div64.h> | ||
23 | |||
24 | #include "softing.h" | ||
25 | |||
26 | /* | ||
27 | * low level DPRAM command. | ||
28 | * Make sure that card->dpram[DPRAM_FCT_HOST] is preset | ||
29 | */ | ||
30 | static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector, | ||
31 | const char *msg) | ||
32 | { | ||
33 | int ret; | ||
34 | unsigned long stamp; | ||
35 | |||
36 | iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]); | ||
37 | iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]); | ||
38 | iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]); | ||
39 | /* be sure to flush this to the card */ | ||
40 | wmb(); | ||
41 | stamp = jiffies + 1 * HZ; | ||
42 | /* wait for card */ | ||
43 | do { | ||
44 | /* DPRAM_FCT_HOST is _not_ aligned */ | ||
45 | ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) + | ||
46 | (ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8); | ||
47 | /* don't have any cached variables */ | ||
48 | rmb(); | ||
49 | if (ret == RES_OK) | ||
50 | /* read return-value now */ | ||
51 | return ioread16(&card->dpram[DPRAM_FCT_RESULT]); | ||
52 | |||
53 | if ((ret != vector) || time_after(jiffies, stamp)) | ||
54 | break; | ||
55 | /* process context => relax */ | ||
56 | usleep_range(500, 10000); | ||
57 | } while (1); | ||
58 | |||
59 | ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED; | ||
60 | dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret); | ||
61 | return ret; | ||
62 | } | ||
63 | |||
64 | static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg) | ||
65 | { | ||
66 | int ret; | ||
67 | |||
68 | ret = _softing_fct_cmd(card, cmd, 0, msg); | ||
69 | if (ret > 0) { | ||
70 | dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret); | ||
71 | ret = -EIO; | ||
72 | } | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | int softing_bootloader_command(struct softing *card, int16_t cmd, | ||
77 | const char *msg) | ||
78 | { | ||
79 | int ret; | ||
80 | unsigned long stamp; | ||
81 | |||
82 | iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]); | ||
83 | iowrite16(cmd, &card->dpram[DPRAM_COMMAND]); | ||
84 | /* be sure to flush this to the card */ | ||
85 | wmb(); | ||
86 | stamp = jiffies + 3 * HZ; | ||
87 | /* wait for card */ | ||
88 | do { | ||
89 | ret = ioread16(&card->dpram[DPRAM_RECEIPT]); | ||
90 | /* don't have any cached variables */ | ||
91 | rmb(); | ||
92 | if (ret == RES_OK) | ||
93 | return 0; | ||
94 | if (time_after(jiffies, stamp)) | ||
95 | break; | ||
96 | /* process context => relax */ | ||
97 | usleep_range(500, 10000); | ||
98 | } while (!signal_pending(current)); | ||
99 | |||
100 | ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED; | ||
101 | dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret); | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr, | ||
106 | uint16_t *plen, const uint8_t **pdat) | ||
107 | { | ||
108 | uint16_t checksum[2]; | ||
109 | const uint8_t *mem; | ||
110 | const uint8_t *end; | ||
111 | |||
112 | /* | ||
113 | * firmware records are a binary, unaligned stream composed of: | ||
114 | * uint16_t type; | ||
115 | * uint32_t addr; | ||
116 | * uint16_t len; | ||
117 | * uint8_t dat[len]; | ||
118 | * uint16_t checksum; | ||
119 | * all values in little endian. | ||
120 | * We could define a struct for this, with __attribute__((packed)), | ||
121 | * but would that solve the alignment in _all_ cases (cfr. the | ||
122 | * struct itself may be an odd address)? | ||
123 | * | ||
124 | * I chose to use leXX_to_cpup() since this solves both | ||
125 | * endianness & alignment. | ||
126 | */ | ||
127 | mem = *pmem; | ||
128 | *ptype = le16_to_cpup((void *)&mem[0]); | ||
129 | *paddr = le32_to_cpup((void *)&mem[2]); | ||
130 | *plen = le16_to_cpup((void *)&mem[6]); | ||
131 | *pdat = &mem[8]; | ||
132 | /* verify checksum */ | ||
133 | end = &mem[8 + *plen]; | ||
134 | checksum[0] = le16_to_cpup((void *)end); | ||
135 | for (checksum[1] = 0; mem < end; ++mem) | ||
136 | checksum[1] += *mem; | ||
137 | if (checksum[0] != checksum[1]) | ||
138 | return -EINVAL; | ||
139 | /* increment */ | ||
140 | *pmem += 10 + *plen; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | int softing_load_fw(const char *file, struct softing *card, | ||
145 | __iomem uint8_t *dpram, unsigned int size, int offset) | ||
146 | { | ||
147 | const struct firmware *fw; | ||
148 | int ret; | ||
149 | const uint8_t *mem, *end, *dat; | ||
150 | uint16_t type, len; | ||
151 | uint32_t addr; | ||
152 | uint8_t *buf = NULL; | ||
153 | int buflen = 0; | ||
154 | int8_t type_end = 0; | ||
155 | |||
156 | ret = request_firmware(&fw, file, &card->pdev->dev); | ||
157 | if (ret < 0) | ||
158 | return ret; | ||
159 | dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes" | ||
160 | ", offset %c0x%04x\n", | ||
161 | card->pdat->name, file, (unsigned int)fw->size, | ||
162 | (offset >= 0) ? '+' : '-', (unsigned int)abs(offset)); | ||
163 | /* parse the firmware */ | ||
164 | mem = fw->data; | ||
165 | end = &mem[fw->size]; | ||
166 | /* look for header record */ | ||
167 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | ||
168 | if (ret < 0) | ||
169 | goto failed; | ||
170 | if (type != 0xffff) | ||
171 | goto failed; | ||
172 | if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) { | ||
173 | ret = -EINVAL; | ||
174 | goto failed; | ||
175 | } | ||
176 | /* ok, we had a header */ | ||
177 | while (mem < end) { | ||
178 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | ||
179 | if (ret < 0) | ||
180 | goto failed; | ||
181 | if (type == 3) { | ||
182 | /* start address, not used here */ | ||
183 | continue; | ||
184 | } else if (type == 1) { | ||
185 | /* eof */ | ||
186 | type_end = 1; | ||
187 | break; | ||
188 | } else if (type != 0) { | ||
189 | ret = -EINVAL; | ||
190 | goto failed; | ||
191 | } | ||
192 | |||
193 | if ((addr + len + offset) > size) | ||
194 | goto failed; | ||
195 | memcpy_toio(&dpram[addr + offset], dat, len); | ||
196 | /* be sure to flush caches from IO space */ | ||
197 | mb(); | ||
198 | if (len > buflen) { | ||
199 | /* align buflen */ | ||
200 | buflen = (len + (1024-1)) & ~(1024-1); | ||
201 | buf = krealloc(buf, buflen, GFP_KERNEL); | ||
202 | if (!buf) { | ||
203 | ret = -ENOMEM; | ||
204 | goto failed; | ||
205 | } | ||
206 | } | ||
207 | /* verify record data */ | ||
208 | memcpy_fromio(buf, &dpram[addr + offset], len); | ||
209 | if (memcmp(buf, dat, len)) { | ||
210 | /* is not ok */ | ||
211 | dev_alert(&card->pdev->dev, "DPRAM readback failed\n"); | ||
212 | ret = -EIO; | ||
213 | goto failed; | ||
214 | } | ||
215 | } | ||
216 | if (!type_end) | ||
217 | /* no end record seen */ | ||
218 | goto failed; | ||
219 | ret = 0; | ||
220 | failed: | ||
221 | kfree(buf); | ||
222 | release_firmware(fw); | ||
223 | if (ret < 0) | ||
224 | dev_info(&card->pdev->dev, "firmware %s failed\n", file); | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | int softing_load_app_fw(const char *file, struct softing *card) | ||
229 | { | ||
230 | const struct firmware *fw; | ||
231 | const uint8_t *mem, *end, *dat; | ||
232 | int ret, j; | ||
233 | uint16_t type, len; | ||
234 | uint32_t addr, start_addr = 0; | ||
235 | unsigned int sum, rx_sum; | ||
236 | int8_t type_end = 0, type_entrypoint = 0; | ||
237 | |||
238 | ret = request_firmware(&fw, file, &card->pdev->dev); | ||
239 | if (ret) { | ||
240 | dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n", | ||
241 | file, ret); | ||
242 | return ret; | ||
243 | } | ||
244 | dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n", | ||
245 | file, (unsigned long)fw->size); | ||
246 | /* parse the firmware */ | ||
247 | mem = fw->data; | ||
248 | end = &mem[fw->size]; | ||
249 | /* look for header record */ | ||
250 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | ||
251 | if (ret) | ||
252 | goto failed; | ||
253 | ret = -EINVAL; | ||
254 | if (type != 0xffff) { | ||
255 | dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n", | ||
256 | type); | ||
257 | goto failed; | ||
258 | } | ||
259 | if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) { | ||
260 | dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n", | ||
261 | len, dat); | ||
262 | goto failed; | ||
263 | } | ||
264 | /* ok, we had a header */ | ||
265 | while (mem < end) { | ||
266 | ret = fw_parse(&mem, &type, &addr, &len, &dat); | ||
267 | if (ret) | ||
268 | goto failed; | ||
269 | |||
270 | if (type == 3) { | ||
271 | /* start address */ | ||
272 | start_addr = addr; | ||
273 | type_entrypoint = 1; | ||
274 | continue; | ||
275 | } else if (type == 1) { | ||
276 | /* eof */ | ||
277 | type_end = 1; | ||
278 | break; | ||
279 | } else if (type != 0) { | ||
280 | dev_alert(&card->pdev->dev, | ||
281 | "unknown record type 0x%04x\n", type); | ||
282 | ret = -EINVAL; | ||
283 | goto failed; | ||
284 | } | ||
285 | |||
286 | /* regualar data */ | ||
287 | for (sum = 0, j = 0; j < len; ++j) | ||
288 | sum += dat[j]; | ||
289 | /* work in 16bit (target) */ | ||
290 | sum &= 0xffff; | ||
291 | |||
292 | memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len); | ||
293 | iowrite32(card->pdat->app.offs + card->pdat->app.addr, | ||
294 | &card->dpram[DPRAM_COMMAND + 2]); | ||
295 | iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]); | ||
296 | iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]); | ||
297 | iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]); | ||
298 | ret = softing_bootloader_command(card, 1, "loading app."); | ||
299 | if (ret < 0) | ||
300 | goto failed; | ||
301 | /* verify checksum */ | ||
302 | rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]); | ||
303 | if (rx_sum != sum) { | ||
304 | dev_alert(&card->pdev->dev, "SRAM seems to be damaged" | ||
305 | ", wanted 0x%04x, got 0x%04x\n", sum, rx_sum); | ||
306 | ret = -EIO; | ||
307 | goto failed; | ||
308 | } | ||
309 | } | ||
310 | if (!type_end || !type_entrypoint) | ||
311 | goto failed; | ||
312 | /* start application in card */ | ||
313 | iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]); | ||
314 | iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]); | ||
315 | ret = softing_bootloader_command(card, 3, "start app."); | ||
316 | if (ret < 0) | ||
317 | goto failed; | ||
318 | ret = 0; | ||
319 | failed: | ||
320 | release_firmware(fw); | ||
321 | if (ret < 0) | ||
322 | dev_info(&card->pdev->dev, "firmware %s failed\n", file); | ||
323 | return ret; | ||
324 | } | ||
325 | |||
326 | static int softing_reset_chip(struct softing *card) | ||
327 | { | ||
328 | int ret; | ||
329 | |||
330 | do { | ||
331 | /* reset chip */ | ||
332 | iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]); | ||
333 | iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]); | ||
334 | iowrite8(1, &card->dpram[DPRAM_RESET]); | ||
335 | iowrite8(0, &card->dpram[DPRAM_RESET+1]); | ||
336 | |||
337 | ret = softing_fct_cmd(card, 0, "reset_can"); | ||
338 | if (!ret) | ||
339 | break; | ||
340 | if (signal_pending(current)) | ||
341 | /* don't wait any longer */ | ||
342 | break; | ||
343 | } while (1); | ||
344 | card->tx.pending = 0; | ||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | int softing_chip_poweron(struct softing *card) | ||
349 | { | ||
350 | int ret; | ||
351 | /* sync */ | ||
352 | ret = _softing_fct_cmd(card, 99, 0x55, "sync-a"); | ||
353 | if (ret < 0) | ||
354 | goto failed; | ||
355 | |||
356 | ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b"); | ||
357 | if (ret < 0) | ||
358 | goto failed; | ||
359 | |||
360 | ret = softing_reset_chip(card); | ||
361 | if (ret < 0) | ||
362 | goto failed; | ||
363 | /* get_serial */ | ||
364 | ret = softing_fct_cmd(card, 43, "get_serial_number"); | ||
365 | if (ret < 0) | ||
366 | goto failed; | ||
367 | card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]); | ||
368 | /* get_version */ | ||
369 | ret = softing_fct_cmd(card, 12, "get_version"); | ||
370 | if (ret < 0) | ||
371 | goto failed; | ||
372 | card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]); | ||
373 | card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]); | ||
374 | card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]); | ||
375 | card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]); | ||
376 | card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]); | ||
377 | return 0; | ||
378 | failed: | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static void softing_initialize_timestamp(struct softing *card) | ||
383 | { | ||
384 | uint64_t ovf; | ||
385 | |||
386 | card->ts_ref = ktime_get(); | ||
387 | |||
388 | /* 16MHz is the reference */ | ||
389 | ovf = 0x100000000ULL * 16; | ||
390 | do_div(ovf, card->pdat->freq ?: 16); | ||
391 | |||
392 | card->ts_overflow = ktime_add_us(ktime_set(0, 0), ovf); | ||
393 | } | ||
394 | |||
395 | ktime_t softing_raw2ktime(struct softing *card, u32 raw) | ||
396 | { | ||
397 | uint64_t rawl; | ||
398 | ktime_t now, real_offset; | ||
399 | ktime_t target; | ||
400 | ktime_t tmp; | ||
401 | |||
402 | now = ktime_get(); | ||
403 | real_offset = ktime_sub(ktime_get_real(), now); | ||
404 | |||
405 | /* find nsec from card */ | ||
406 | rawl = raw * 16; | ||
407 | do_div(rawl, card->pdat->freq ?: 16); | ||
408 | target = ktime_add_us(card->ts_ref, rawl); | ||
409 | /* test for overflows */ | ||
410 | tmp = ktime_add(target, card->ts_overflow); | ||
411 | while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) { | ||
412 | card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow); | ||
413 | target = tmp; | ||
414 | tmp = ktime_add(target, card->ts_overflow); | ||
415 | } | ||
416 | return ktime_add(target, real_offset); | ||
417 | } | ||
418 | |||
419 | static inline int softing_error_reporting(struct net_device *netdev) | ||
420 | { | ||
421 | struct softing_priv *priv = netdev_priv(netdev); | ||
422 | |||
423 | return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) | ||
424 | ? 1 : 0; | ||
425 | } | ||
426 | |||
427 | int softing_startstop(struct net_device *dev, int up) | ||
428 | { | ||
429 | int ret; | ||
430 | struct softing *card; | ||
431 | struct softing_priv *priv; | ||
432 | struct net_device *netdev; | ||
433 | int bus_bitmask_start; | ||
434 | int j, error_reporting; | ||
435 | struct can_frame msg; | ||
436 | const struct can_bittiming *bt; | ||
437 | |||
438 | priv = netdev_priv(dev); | ||
439 | card = priv->card; | ||
440 | |||
441 | if (!card->fw.up) | ||
442 | return -EIO; | ||
443 | |||
444 | ret = mutex_lock_interruptible(&card->fw.lock); | ||
445 | if (ret) | ||
446 | return ret; | ||
447 | |||
448 | bus_bitmask_start = 0; | ||
449 | if (dev && up) | ||
450 | /* prepare to start this bus as well */ | ||
451 | bus_bitmask_start |= (1 << priv->index); | ||
452 | /* bring netdevs down */ | ||
453 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
454 | netdev = card->net[j]; | ||
455 | if (!netdev) | ||
456 | continue; | ||
457 | priv = netdev_priv(netdev); | ||
458 | |||
459 | if (dev != netdev) | ||
460 | netif_stop_queue(netdev); | ||
461 | |||
462 | if (netif_running(netdev)) { | ||
463 | if (dev != netdev) | ||
464 | bus_bitmask_start |= (1 << j); | ||
465 | priv->tx.pending = 0; | ||
466 | priv->tx.echo_put = 0; | ||
467 | priv->tx.echo_get = 0; | ||
468 | /* | ||
469 | * this bus' may just have called open_candev() | ||
470 | * which is rather stupid to call close_candev() | ||
471 | * already | ||
472 | * but we may come here from busoff recovery too | ||
473 | * in which case the echo_skb _needs_ flushing too. | ||
474 | * just be sure to call open_candev() again | ||
475 | */ | ||
476 | close_candev(netdev); | ||
477 | } | ||
478 | priv->can.state = CAN_STATE_STOPPED; | ||
479 | } | ||
480 | card->tx.pending = 0; | ||
481 | |||
482 | softing_enable_irq(card, 0); | ||
483 | ret = softing_reset_chip(card); | ||
484 | if (ret) | ||
485 | goto failed; | ||
486 | if (!bus_bitmask_start) | ||
487 | /* no busses to be brought up */ | ||
488 | goto card_done; | ||
489 | |||
490 | if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2) | ||
491 | && (softing_error_reporting(card->net[0]) | ||
492 | != softing_error_reporting(card->net[1]))) { | ||
493 | dev_alert(&card->pdev->dev, | ||
494 | "err_reporting flag differs for busses\n"); | ||
495 | goto invalid; | ||
496 | } | ||
497 | error_reporting = 0; | ||
498 | if (bus_bitmask_start & 1) { | ||
499 | netdev = card->net[0]; | ||
500 | priv = netdev_priv(netdev); | ||
501 | error_reporting += softing_error_reporting(netdev); | ||
502 | /* init chip 1 */ | ||
503 | bt = &priv->can.bittiming; | ||
504 | iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
505 | iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); | ||
506 | iowrite16(bt->phase_seg1 + bt->prop_seg, | ||
507 | &card->dpram[DPRAM_FCT_PARAM + 6]); | ||
508 | iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); | ||
509 | iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, | ||
510 | &card->dpram[DPRAM_FCT_PARAM + 10]); | ||
511 | ret = softing_fct_cmd(card, 1, "initialize_chip[0]"); | ||
512 | if (ret < 0) | ||
513 | goto failed; | ||
514 | /* set mode */ | ||
515 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
516 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); | ||
517 | ret = softing_fct_cmd(card, 3, "set_mode[0]"); | ||
518 | if (ret < 0) | ||
519 | goto failed; | ||
520 | /* set filter */ | ||
521 | /* 11bit id & mask */ | ||
522 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
523 | iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); | ||
524 | /* 29bit id.lo & mask.lo & id.hi & mask.hi */ | ||
525 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); | ||
526 | iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); | ||
527 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); | ||
528 | iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); | ||
529 | ret = softing_fct_cmd(card, 7, "set_filter[0]"); | ||
530 | if (ret < 0) | ||
531 | goto failed; | ||
532 | /* set output control */ | ||
533 | iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
534 | ret = softing_fct_cmd(card, 5, "set_output[0]"); | ||
535 | if (ret < 0) | ||
536 | goto failed; | ||
537 | } | ||
538 | if (bus_bitmask_start & 2) { | ||
539 | netdev = card->net[1]; | ||
540 | priv = netdev_priv(netdev); | ||
541 | error_reporting += softing_error_reporting(netdev); | ||
542 | /* init chip2 */ | ||
543 | bt = &priv->can.bittiming; | ||
544 | iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
545 | iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); | ||
546 | iowrite16(bt->phase_seg1 + bt->prop_seg, | ||
547 | &card->dpram[DPRAM_FCT_PARAM + 6]); | ||
548 | iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); | ||
549 | iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, | ||
550 | &card->dpram[DPRAM_FCT_PARAM + 10]); | ||
551 | ret = softing_fct_cmd(card, 2, "initialize_chip[1]"); | ||
552 | if (ret < 0) | ||
553 | goto failed; | ||
554 | /* set mode2 */ | ||
555 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
556 | iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); | ||
557 | ret = softing_fct_cmd(card, 4, "set_mode[1]"); | ||
558 | if (ret < 0) | ||
559 | goto failed; | ||
560 | /* set filter2 */ | ||
561 | /* 11bit id & mask */ | ||
562 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
563 | iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); | ||
564 | /* 29bit id.lo & mask.lo & id.hi & mask.hi */ | ||
565 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); | ||
566 | iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); | ||
567 | iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); | ||
568 | iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); | ||
569 | ret = softing_fct_cmd(card, 8, "set_filter[1]"); | ||
570 | if (ret < 0) | ||
571 | goto failed; | ||
572 | /* set output control2 */ | ||
573 | iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
574 | ret = softing_fct_cmd(card, 6, "set_output[1]"); | ||
575 | if (ret < 0) | ||
576 | goto failed; | ||
577 | } | ||
578 | /* enable_error_frame */ | ||
579 | /* | ||
580 | * Error reporting is switched off at the moment since | ||
581 | * the receiving of them is not yet 100% verified | ||
582 | * This should be enabled sooner or later | ||
583 | * | ||
584 | if (error_reporting) { | ||
585 | ret = softing_fct_cmd(card, 51, "enable_error_frame"); | ||
586 | if (ret < 0) | ||
587 | goto failed; | ||
588 | } | ||
589 | */ | ||
590 | /* initialize interface */ | ||
591 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]); | ||
592 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]); | ||
593 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]); | ||
594 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]); | ||
595 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]); | ||
596 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]); | ||
597 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]); | ||
598 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]); | ||
599 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]); | ||
600 | iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]); | ||
601 | ret = softing_fct_cmd(card, 17, "initialize_interface"); | ||
602 | if (ret < 0) | ||
603 | goto failed; | ||
604 | /* enable_fifo */ | ||
605 | ret = softing_fct_cmd(card, 36, "enable_fifo"); | ||
606 | if (ret < 0) | ||
607 | goto failed; | ||
608 | /* enable fifo tx ack */ | ||
609 | ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]"); | ||
610 | if (ret < 0) | ||
611 | goto failed; | ||
612 | /* enable fifo tx ack2 */ | ||
613 | ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]"); | ||
614 | if (ret < 0) | ||
615 | goto failed; | ||
616 | /* start_chip */ | ||
617 | ret = softing_fct_cmd(card, 11, "start_chip"); | ||
618 | if (ret < 0) | ||
619 | goto failed; | ||
620 | iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]); | ||
621 | iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]); | ||
622 | if (card->pdat->generation < 2) { | ||
623 | iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]); | ||
624 | /* flush the DPRAM caches */ | ||
625 | wmb(); | ||
626 | } | ||
627 | |||
628 | softing_initialize_timestamp(card); | ||
629 | |||
630 | /* | ||
631 | * do socketcan notifications/status changes | ||
632 | * from here, no errors should occur, or the failed: part | ||
633 | * must be reviewed | ||
634 | */ | ||
635 | memset(&msg, 0, sizeof(msg)); | ||
636 | msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; | ||
637 | msg.can_dlc = CAN_ERR_DLC; | ||
638 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
639 | if (!(bus_bitmask_start & (1 << j))) | ||
640 | continue; | ||
641 | netdev = card->net[j]; | ||
642 | if (!netdev) | ||
643 | continue; | ||
644 | priv = netdev_priv(netdev); | ||
645 | priv->can.state = CAN_STATE_ERROR_ACTIVE; | ||
646 | open_candev(netdev); | ||
647 | if (dev != netdev) { | ||
648 | /* notify other busses on the restart */ | ||
649 | softing_netdev_rx(netdev, &msg, ktime_set(0, 0)); | ||
650 | ++priv->can.can_stats.restarts; | ||
651 | } | ||
652 | netif_wake_queue(netdev); | ||
653 | } | ||
654 | |||
655 | /* enable interrupts */ | ||
656 | ret = softing_enable_irq(card, 1); | ||
657 | if (ret) | ||
658 | goto failed; | ||
659 | card_done: | ||
660 | mutex_unlock(&card->fw.lock); | ||
661 | return 0; | ||
662 | invalid: | ||
663 | ret = -EINVAL; | ||
664 | failed: | ||
665 | softing_enable_irq(card, 0); | ||
666 | softing_reset_chip(card); | ||
667 | mutex_unlock(&card->fw.lock); | ||
668 | /* bring all other interfaces down */ | ||
669 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
670 | netdev = card->net[j]; | ||
671 | if (!netdev) | ||
672 | continue; | ||
673 | dev_close(netdev); | ||
674 | } | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | int softing_default_output(struct net_device *netdev) | ||
679 | { | ||
680 | struct softing_priv *priv = netdev_priv(netdev); | ||
681 | struct softing *card = priv->card; | ||
682 | |||
683 | switch (priv->chip) { | ||
684 | case 1000: | ||
685 | return (card->pdat->generation < 2) ? 0xfb : 0xfa; | ||
686 | case 5: | ||
687 | return 0x60; | ||
688 | default: | ||
689 | return 0x40; | ||
690 | } | ||
691 | } | ||
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c new file mode 100644 index 000000000000..aeea9f9ff6e8 --- /dev/null +++ b/drivers/net/can/softing/softing_main.c | |||
@@ -0,0 +1,894 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2010 | ||
3 | * | ||
4 | * - Kurt Van Dijck, EIA Electronics | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the version 2 of the GNU General Public License | ||
8 | * as published by the Free Software Foundation | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/version.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | |||
25 | #include "softing.h" | ||
26 | |||
27 | #define TX_ECHO_SKB_MAX (((TXMAX+1)/2)-1) | ||
28 | |||
29 | /* | ||
30 | * test is a specific CAN netdev | ||
31 | * is online (ie. up 'n running, not sleeping, not busoff | ||
32 | */ | ||
33 | static inline int canif_is_active(struct net_device *netdev) | ||
34 | { | ||
35 | struct can_priv *can = netdev_priv(netdev); | ||
36 | |||
37 | if (!netif_running(netdev)) | ||
38 | return 0; | ||
39 | return (can->state <= CAN_STATE_ERROR_PASSIVE); | ||
40 | } | ||
41 | |||
42 | /* reset DPRAM */ | ||
43 | static inline void softing_set_reset_dpram(struct softing *card) | ||
44 | { | ||
45 | if (card->pdat->generation >= 2) { | ||
46 | spin_lock_bh(&card->spin); | ||
47 | iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) & ~1, | ||
48 | &card->dpram[DPRAM_V2_RESET]); | ||
49 | spin_unlock_bh(&card->spin); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | static inline void softing_clr_reset_dpram(struct softing *card) | ||
54 | { | ||
55 | if (card->pdat->generation >= 2) { | ||
56 | spin_lock_bh(&card->spin); | ||
57 | iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) | 1, | ||
58 | &card->dpram[DPRAM_V2_RESET]); | ||
59 | spin_unlock_bh(&card->spin); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | /* trigger the tx queue-ing */ | ||
64 | static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb, | ||
65 | struct net_device *dev) | ||
66 | { | ||
67 | struct softing_priv *priv = netdev_priv(dev); | ||
68 | struct softing *card = priv->card; | ||
69 | int ret; | ||
70 | uint8_t *ptr; | ||
71 | uint8_t fifo_wr, fifo_rd; | ||
72 | struct can_frame *cf = (struct can_frame *)skb->data; | ||
73 | uint8_t buf[DPRAM_TX_SIZE]; | ||
74 | |||
75 | if (can_dropped_invalid_skb(dev, skb)) | ||
76 | return NETDEV_TX_OK; | ||
77 | |||
78 | spin_lock(&card->spin); | ||
79 | |||
80 | ret = NETDEV_TX_BUSY; | ||
81 | if (!card->fw.up || | ||
82 | (card->tx.pending >= TXMAX) || | ||
83 | (priv->tx.pending >= TX_ECHO_SKB_MAX)) | ||
84 | goto xmit_done; | ||
85 | fifo_wr = ioread8(&card->dpram[DPRAM_TX_WR]); | ||
86 | fifo_rd = ioread8(&card->dpram[DPRAM_TX_RD]); | ||
87 | if (fifo_wr == fifo_rd) | ||
88 | /* fifo full */ | ||
89 | goto xmit_done; | ||
90 | memset(buf, 0, sizeof(buf)); | ||
91 | ptr = buf; | ||
92 | *ptr = CMD_TX; | ||
93 | if (cf->can_id & CAN_RTR_FLAG) | ||
94 | *ptr |= CMD_RTR; | ||
95 | if (cf->can_id & CAN_EFF_FLAG) | ||
96 | *ptr |= CMD_XTD; | ||
97 | if (priv->index) | ||
98 | *ptr |= CMD_BUS2; | ||
99 | ++ptr; | ||
100 | *ptr++ = cf->can_dlc; | ||
101 | *ptr++ = (cf->can_id >> 0); | ||
102 | *ptr++ = (cf->can_id >> 8); | ||
103 | if (cf->can_id & CAN_EFF_FLAG) { | ||
104 | *ptr++ = (cf->can_id >> 16); | ||
105 | *ptr++ = (cf->can_id >> 24); | ||
106 | } else { | ||
107 | /* increment 1, not 2 as you might think */ | ||
108 | ptr += 1; | ||
109 | } | ||
110 | if (!(cf->can_id & CAN_RTR_FLAG)) | ||
111 | memcpy(ptr, &cf->data[0], cf->can_dlc); | ||
112 | memcpy_toio(&card->dpram[DPRAM_TX + DPRAM_TX_SIZE * fifo_wr], | ||
113 | buf, DPRAM_TX_SIZE); | ||
114 | if (++fifo_wr >= DPRAM_TX_CNT) | ||
115 | fifo_wr = 0; | ||
116 | iowrite8(fifo_wr, &card->dpram[DPRAM_TX_WR]); | ||
117 | card->tx.last_bus = priv->index; | ||
118 | ++card->tx.pending; | ||
119 | ++priv->tx.pending; | ||
120 | can_put_echo_skb(skb, dev, priv->tx.echo_put); | ||
121 | ++priv->tx.echo_put; | ||
122 | if (priv->tx.echo_put >= TX_ECHO_SKB_MAX) | ||
123 | priv->tx.echo_put = 0; | ||
124 | /* can_put_echo_skb() saves the skb, safe to return TX_OK */ | ||
125 | ret = NETDEV_TX_OK; | ||
126 | xmit_done: | ||
127 | spin_unlock(&card->spin); | ||
128 | if (card->tx.pending >= TXMAX) { | ||
129 | int j; | ||
130 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
131 | if (card->net[j]) | ||
132 | netif_stop_queue(card->net[j]); | ||
133 | } | ||
134 | } | ||
135 | if (ret != NETDEV_TX_OK) | ||
136 | netif_stop_queue(dev); | ||
137 | |||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * shortcut for skb delivery | ||
143 | */ | ||
144 | int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg, | ||
145 | ktime_t ktime) | ||
146 | { | ||
147 | struct sk_buff *skb; | ||
148 | struct can_frame *cf; | ||
149 | |||
150 | skb = alloc_can_skb(netdev, &cf); | ||
151 | if (!skb) | ||
152 | return -ENOMEM; | ||
153 | memcpy(cf, msg, sizeof(*msg)); | ||
154 | skb->tstamp = ktime; | ||
155 | return netif_rx(skb); | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * softing_handle_1 | ||
160 | * pop 1 entry from the DPRAM queue, and process | ||
161 | */ | ||
162 | static int softing_handle_1(struct softing *card) | ||
163 | { | ||
164 | struct net_device *netdev; | ||
165 | struct softing_priv *priv; | ||
166 | ktime_t ktime; | ||
167 | struct can_frame msg; | ||
168 | int cnt = 0, lost_msg; | ||
169 | uint8_t fifo_rd, fifo_wr, cmd; | ||
170 | uint8_t *ptr; | ||
171 | uint32_t tmp_u32; | ||
172 | uint8_t buf[DPRAM_RX_SIZE]; | ||
173 | |||
174 | memset(&msg, 0, sizeof(msg)); | ||
175 | /* test for lost msgs */ | ||
176 | lost_msg = ioread8(&card->dpram[DPRAM_RX_LOST]); | ||
177 | if (lost_msg) { | ||
178 | int j; | ||
179 | /* reset condition */ | ||
180 | iowrite8(0, &card->dpram[DPRAM_RX_LOST]); | ||
181 | /* prepare msg */ | ||
182 | msg.can_id = CAN_ERR_FLAG | CAN_ERR_CRTL; | ||
183 | msg.can_dlc = CAN_ERR_DLC; | ||
184 | msg.data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | ||
185 | /* | ||
186 | * service to all busses, we don't know which it was applicable | ||
187 | * but only service busses that are online | ||
188 | */ | ||
189 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
190 | netdev = card->net[j]; | ||
191 | if (!netdev) | ||
192 | continue; | ||
193 | if (!canif_is_active(netdev)) | ||
194 | /* a dead bus has no overflows */ | ||
195 | continue; | ||
196 | ++netdev->stats.rx_over_errors; | ||
197 | softing_netdev_rx(netdev, &msg, ktime_set(0, 0)); | ||
198 | } | ||
199 | /* prepare for other use */ | ||
200 | memset(&msg, 0, sizeof(msg)); | ||
201 | ++cnt; | ||
202 | } | ||
203 | |||
204 | fifo_rd = ioread8(&card->dpram[DPRAM_RX_RD]); | ||
205 | fifo_wr = ioread8(&card->dpram[DPRAM_RX_WR]); | ||
206 | |||
207 | if (++fifo_rd >= DPRAM_RX_CNT) | ||
208 | fifo_rd = 0; | ||
209 | if (fifo_wr == fifo_rd) | ||
210 | return cnt; | ||
211 | |||
212 | memcpy_fromio(buf, &card->dpram[DPRAM_RX + DPRAM_RX_SIZE*fifo_rd], | ||
213 | DPRAM_RX_SIZE); | ||
214 | mb(); | ||
215 | /* trigger dual port RAM */ | ||
216 | iowrite8(fifo_rd, &card->dpram[DPRAM_RX_RD]); | ||
217 | |||
218 | ptr = buf; | ||
219 | cmd = *ptr++; | ||
220 | if (cmd == 0xff) | ||
221 | /* not quite usefull, probably the card has got out */ | ||
222 | return 0; | ||
223 | netdev = card->net[0]; | ||
224 | if (cmd & CMD_BUS2) | ||
225 | netdev = card->net[1]; | ||
226 | priv = netdev_priv(netdev); | ||
227 | |||
228 | if (cmd & CMD_ERR) { | ||
229 | uint8_t can_state, state; | ||
230 | |||
231 | state = *ptr++; | ||
232 | |||
233 | msg.can_id = CAN_ERR_FLAG; | ||
234 | msg.can_dlc = CAN_ERR_DLC; | ||
235 | |||
236 | if (state & SF_MASK_BUSOFF) { | ||
237 | can_state = CAN_STATE_BUS_OFF; | ||
238 | msg.can_id |= CAN_ERR_BUSOFF; | ||
239 | state = STATE_BUSOFF; | ||
240 | } else if (state & SF_MASK_EPASSIVE) { | ||
241 | can_state = CAN_STATE_ERROR_PASSIVE; | ||
242 | msg.can_id |= CAN_ERR_CRTL; | ||
243 | msg.data[1] = CAN_ERR_CRTL_TX_PASSIVE; | ||
244 | state = STATE_EPASSIVE; | ||
245 | } else { | ||
246 | can_state = CAN_STATE_ERROR_ACTIVE; | ||
247 | msg.can_id |= CAN_ERR_CRTL; | ||
248 | state = STATE_EACTIVE; | ||
249 | } | ||
250 | /* update DPRAM */ | ||
251 | iowrite8(state, &card->dpram[priv->index ? | ||
252 | DPRAM_INFO_BUSSTATE2 : DPRAM_INFO_BUSSTATE]); | ||
253 | /* timestamp */ | ||
254 | tmp_u32 = le32_to_cpup((void *)ptr); | ||
255 | ptr += 4; | ||
256 | ktime = softing_raw2ktime(card, tmp_u32); | ||
257 | |||
258 | ++netdev->stats.rx_errors; | ||
259 | /* update internal status */ | ||
260 | if (can_state != priv->can.state) { | ||
261 | priv->can.state = can_state; | ||
262 | if (can_state == CAN_STATE_ERROR_PASSIVE) | ||
263 | ++priv->can.can_stats.error_passive; | ||
264 | else if (can_state == CAN_STATE_BUS_OFF) { | ||
265 | /* this calls can_close_cleanup() */ | ||
266 | can_bus_off(netdev); | ||
267 | netif_stop_queue(netdev); | ||
268 | } | ||
269 | /* trigger socketcan */ | ||
270 | softing_netdev_rx(netdev, &msg, ktime); | ||
271 | } | ||
272 | |||
273 | } else { | ||
274 | if (cmd & CMD_RTR) | ||
275 | msg.can_id |= CAN_RTR_FLAG; | ||
276 | msg.can_dlc = get_can_dlc(*ptr++); | ||
277 | if (cmd & CMD_XTD) { | ||
278 | msg.can_id |= CAN_EFF_FLAG; | ||
279 | msg.can_id |= le32_to_cpup((void *)ptr); | ||
280 | ptr += 4; | ||
281 | } else { | ||
282 | msg.can_id |= le16_to_cpup((void *)ptr); | ||
283 | ptr += 2; | ||
284 | } | ||
285 | /* timestamp */ | ||
286 | tmp_u32 = le32_to_cpup((void *)ptr); | ||
287 | ptr += 4; | ||
288 | ktime = softing_raw2ktime(card, tmp_u32); | ||
289 | if (!(msg.can_id & CAN_RTR_FLAG)) | ||
290 | memcpy(&msg.data[0], ptr, 8); | ||
291 | ptr += 8; | ||
292 | /* update socket */ | ||
293 | if (cmd & CMD_ACK) { | ||
294 | /* acknowledge, was tx msg */ | ||
295 | struct sk_buff *skb; | ||
296 | skb = priv->can.echo_skb[priv->tx.echo_get]; | ||
297 | if (skb) | ||
298 | skb->tstamp = ktime; | ||
299 | can_get_echo_skb(netdev, priv->tx.echo_get); | ||
300 | ++priv->tx.echo_get; | ||
301 | if (priv->tx.echo_get >= TX_ECHO_SKB_MAX) | ||
302 | priv->tx.echo_get = 0; | ||
303 | if (priv->tx.pending) | ||
304 | --priv->tx.pending; | ||
305 | if (card->tx.pending) | ||
306 | --card->tx.pending; | ||
307 | ++netdev->stats.tx_packets; | ||
308 | if (!(msg.can_id & CAN_RTR_FLAG)) | ||
309 | netdev->stats.tx_bytes += msg.can_dlc; | ||
310 | } else { | ||
311 | int ret; | ||
312 | |||
313 | ret = softing_netdev_rx(netdev, &msg, ktime); | ||
314 | if (ret == NET_RX_SUCCESS) { | ||
315 | ++netdev->stats.rx_packets; | ||
316 | if (!(msg.can_id & CAN_RTR_FLAG)) | ||
317 | netdev->stats.rx_bytes += msg.can_dlc; | ||
318 | } else { | ||
319 | ++netdev->stats.rx_dropped; | ||
320 | } | ||
321 | } | ||
322 | } | ||
323 | ++cnt; | ||
324 | return cnt; | ||
325 | } | ||
326 | |||
327 | /* | ||
328 | * real interrupt handler | ||
329 | */ | ||
330 | static irqreturn_t softing_irq_thread(int irq, void *dev_id) | ||
331 | { | ||
332 | struct softing *card = (struct softing *)dev_id; | ||
333 | struct net_device *netdev; | ||
334 | struct softing_priv *priv; | ||
335 | int j, offset, work_done; | ||
336 | |||
337 | work_done = 0; | ||
338 | spin_lock_bh(&card->spin); | ||
339 | while (softing_handle_1(card) > 0) { | ||
340 | ++card->irq.svc_count; | ||
341 | ++work_done; | ||
342 | } | ||
343 | spin_unlock_bh(&card->spin); | ||
344 | /* resume tx queue's */ | ||
345 | offset = card->tx.last_bus; | ||
346 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
347 | if (card->tx.pending >= TXMAX) | ||
348 | break; | ||
349 | netdev = card->net[(j + offset + 1) % card->pdat->nbus]; | ||
350 | if (!netdev) | ||
351 | continue; | ||
352 | priv = netdev_priv(netdev); | ||
353 | if (!canif_is_active(netdev)) | ||
354 | /* it makes no sense to wake dead busses */ | ||
355 | continue; | ||
356 | if (priv->tx.pending >= TX_ECHO_SKB_MAX) | ||
357 | continue; | ||
358 | ++work_done; | ||
359 | netif_wake_queue(netdev); | ||
360 | } | ||
361 | return work_done ? IRQ_HANDLED : IRQ_NONE; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * interrupt routines: | ||
366 | * schedule the 'real interrupt handler' | ||
367 | */ | ||
368 | static irqreturn_t softing_irq_v2(int irq, void *dev_id) | ||
369 | { | ||
370 | struct softing *card = (struct softing *)dev_id; | ||
371 | uint8_t ir; | ||
372 | |||
373 | ir = ioread8(&card->dpram[DPRAM_V2_IRQ_TOHOST]); | ||
374 | iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]); | ||
375 | return (1 == ir) ? IRQ_WAKE_THREAD : IRQ_NONE; | ||
376 | } | ||
377 | |||
378 | static irqreturn_t softing_irq_v1(int irq, void *dev_id) | ||
379 | { | ||
380 | struct softing *card = (struct softing *)dev_id; | ||
381 | uint8_t ir; | ||
382 | |||
383 | ir = ioread8(&card->dpram[DPRAM_IRQ_TOHOST]); | ||
384 | iowrite8(0, &card->dpram[DPRAM_IRQ_TOHOST]); | ||
385 | return ir ? IRQ_WAKE_THREAD : IRQ_NONE; | ||
386 | } | ||
387 | |||
388 | /* | ||
389 | * netdev/candev inter-operability | ||
390 | */ | ||
391 | static int softing_netdev_open(struct net_device *ndev) | ||
392 | { | ||
393 | int ret; | ||
394 | |||
395 | /* check or determine and set bittime */ | ||
396 | ret = open_candev(ndev); | ||
397 | if (!ret) | ||
398 | ret = softing_startstop(ndev, 1); | ||
399 | return ret; | ||
400 | } | ||
401 | |||
402 | static int softing_netdev_stop(struct net_device *ndev) | ||
403 | { | ||
404 | int ret; | ||
405 | |||
406 | netif_stop_queue(ndev); | ||
407 | |||
408 | /* softing cycle does close_candev() */ | ||
409 | ret = softing_startstop(ndev, 0); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode) | ||
414 | { | ||
415 | int ret; | ||
416 | |||
417 | switch (mode) { | ||
418 | case CAN_MODE_START: | ||
419 | /* softing_startstop does close_candev() */ | ||
420 | ret = softing_startstop(ndev, 1); | ||
421 | return ret; | ||
422 | case CAN_MODE_STOP: | ||
423 | case CAN_MODE_SLEEP: | ||
424 | return -EOPNOTSUPP; | ||
425 | } | ||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | /* | ||
430 | * Softing device management helpers | ||
431 | */ | ||
432 | int softing_enable_irq(struct softing *card, int enable) | ||
433 | { | ||
434 | int ret; | ||
435 | |||
436 | if (!card->irq.nr) { | ||
437 | return 0; | ||
438 | } else if (card->irq.requested && !enable) { | ||
439 | free_irq(card->irq.nr, card); | ||
440 | card->irq.requested = 0; | ||
441 | } else if (!card->irq.requested && enable) { | ||
442 | ret = request_threaded_irq(card->irq.nr, | ||
443 | (card->pdat->generation >= 2) ? | ||
444 | softing_irq_v2 : softing_irq_v1, | ||
445 | softing_irq_thread, IRQF_SHARED, | ||
446 | dev_name(&card->pdev->dev), card); | ||
447 | if (ret) { | ||
448 | dev_alert(&card->pdev->dev, | ||
449 | "request_threaded_irq(%u) failed\n", | ||
450 | card->irq.nr); | ||
451 | return ret; | ||
452 | } | ||
453 | card->irq.requested = 1; | ||
454 | } | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | static void softing_card_shutdown(struct softing *card) | ||
459 | { | ||
460 | int fw_up = 0; | ||
461 | |||
462 | if (mutex_lock_interruptible(&card->fw.lock)) | ||
463 | /* return -ERESTARTSYS */; | ||
464 | fw_up = card->fw.up; | ||
465 | card->fw.up = 0; | ||
466 | |||
467 | if (card->irq.requested && card->irq.nr) { | ||
468 | free_irq(card->irq.nr, card); | ||
469 | card->irq.requested = 0; | ||
470 | } | ||
471 | if (fw_up) { | ||
472 | if (card->pdat->enable_irq) | ||
473 | card->pdat->enable_irq(card->pdev, 0); | ||
474 | softing_set_reset_dpram(card); | ||
475 | if (card->pdat->reset) | ||
476 | card->pdat->reset(card->pdev, 1); | ||
477 | } | ||
478 | mutex_unlock(&card->fw.lock); | ||
479 | } | ||
480 | |||
481 | static __devinit int softing_card_boot(struct softing *card) | ||
482 | { | ||
483 | int ret, j; | ||
484 | static const uint8_t stream[] = { | ||
485 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, }; | ||
486 | unsigned char back[sizeof(stream)]; | ||
487 | |||
488 | if (mutex_lock_interruptible(&card->fw.lock)) | ||
489 | return -ERESTARTSYS; | ||
490 | if (card->fw.up) { | ||
491 | mutex_unlock(&card->fw.lock); | ||
492 | return 0; | ||
493 | } | ||
494 | /* reset board */ | ||
495 | if (card->pdat->enable_irq) | ||
496 | card->pdat->enable_irq(card->pdev, 1); | ||
497 | /* boot card */ | ||
498 | softing_set_reset_dpram(card); | ||
499 | if (card->pdat->reset) | ||
500 | card->pdat->reset(card->pdev, 1); | ||
501 | for (j = 0; (j + sizeof(stream)) < card->dpram_size; | ||
502 | j += sizeof(stream)) { | ||
503 | |||
504 | memcpy_toio(&card->dpram[j], stream, sizeof(stream)); | ||
505 | /* flush IO cache */ | ||
506 | mb(); | ||
507 | memcpy_fromio(back, &card->dpram[j], sizeof(stream)); | ||
508 | |||
509 | if (!memcmp(back, stream, sizeof(stream))) | ||
510 | continue; | ||
511 | /* memory is not equal */ | ||
512 | dev_alert(&card->pdev->dev, "dpram failed at 0x%04x\n", j); | ||
513 | ret = -EIO; | ||
514 | goto failed; | ||
515 | } | ||
516 | wmb(); | ||
517 | /* load boot firmware */ | ||
518 | ret = softing_load_fw(card->pdat->boot.fw, card, card->dpram, | ||
519 | card->dpram_size, | ||
520 | card->pdat->boot.offs - card->pdat->boot.addr); | ||
521 | if (ret < 0) | ||
522 | goto failed; | ||
523 | /* load loader firmware */ | ||
524 | ret = softing_load_fw(card->pdat->load.fw, card, card->dpram, | ||
525 | card->dpram_size, | ||
526 | card->pdat->load.offs - card->pdat->load.addr); | ||
527 | if (ret < 0) | ||
528 | goto failed; | ||
529 | |||
530 | if (card->pdat->reset) | ||
531 | card->pdat->reset(card->pdev, 0); | ||
532 | softing_clr_reset_dpram(card); | ||
533 | ret = softing_bootloader_command(card, 0, "card boot"); | ||
534 | if (ret < 0) | ||
535 | goto failed; | ||
536 | ret = softing_load_app_fw(card->pdat->app.fw, card); | ||
537 | if (ret < 0) | ||
538 | goto failed; | ||
539 | |||
540 | ret = softing_chip_poweron(card); | ||
541 | if (ret < 0) | ||
542 | goto failed; | ||
543 | |||
544 | card->fw.up = 1; | ||
545 | mutex_unlock(&card->fw.lock); | ||
546 | return 0; | ||
547 | failed: | ||
548 | card->fw.up = 0; | ||
549 | if (card->pdat->enable_irq) | ||
550 | card->pdat->enable_irq(card->pdev, 0); | ||
551 | softing_set_reset_dpram(card); | ||
552 | if (card->pdat->reset) | ||
553 | card->pdat->reset(card->pdev, 1); | ||
554 | mutex_unlock(&card->fw.lock); | ||
555 | return ret; | ||
556 | } | ||
557 | |||
558 | /* | ||
559 | * netdev sysfs | ||
560 | */ | ||
561 | static ssize_t show_channel(struct device *dev, struct device_attribute *attr, | ||
562 | char *buf) | ||
563 | { | ||
564 | struct net_device *ndev = to_net_dev(dev); | ||
565 | struct softing_priv *priv = netdev2softing(ndev); | ||
566 | |||
567 | return sprintf(buf, "%i\n", priv->index); | ||
568 | } | ||
569 | |||
570 | static ssize_t show_chip(struct device *dev, struct device_attribute *attr, | ||
571 | char *buf) | ||
572 | { | ||
573 | struct net_device *ndev = to_net_dev(dev); | ||
574 | struct softing_priv *priv = netdev2softing(ndev); | ||
575 | |||
576 | return sprintf(buf, "%i\n", priv->chip); | ||
577 | } | ||
578 | |||
579 | static ssize_t show_output(struct device *dev, struct device_attribute *attr, | ||
580 | char *buf) | ||
581 | { | ||
582 | struct net_device *ndev = to_net_dev(dev); | ||
583 | struct softing_priv *priv = netdev2softing(ndev); | ||
584 | |||
585 | return sprintf(buf, "0x%02x\n", priv->output); | ||
586 | } | ||
587 | |||
588 | static ssize_t store_output(struct device *dev, struct device_attribute *attr, | ||
589 | const char *buf, size_t count) | ||
590 | { | ||
591 | struct net_device *ndev = to_net_dev(dev); | ||
592 | struct softing_priv *priv = netdev2softing(ndev); | ||
593 | struct softing *card = priv->card; | ||
594 | unsigned long val; | ||
595 | int ret; | ||
596 | |||
597 | ret = strict_strtoul(buf, 0, &val); | ||
598 | if (ret < 0) | ||
599 | return ret; | ||
600 | val &= 0xFF; | ||
601 | |||
602 | ret = mutex_lock_interruptible(&card->fw.lock); | ||
603 | if (ret) | ||
604 | return -ERESTARTSYS; | ||
605 | if (netif_running(ndev)) { | ||
606 | mutex_unlock(&card->fw.lock); | ||
607 | return -EBUSY; | ||
608 | } | ||
609 | priv->output = val; | ||
610 | mutex_unlock(&card->fw.lock); | ||
611 | return count; | ||
612 | } | ||
613 | |||
614 | static const DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL); | ||
615 | static const DEVICE_ATTR(chip, S_IRUGO, show_chip, NULL); | ||
616 | static const DEVICE_ATTR(output, S_IRUGO | S_IWUSR, show_output, store_output); | ||
617 | |||
618 | static const struct attribute *const netdev_sysfs_attrs[] = { | ||
619 | &dev_attr_channel.attr, | ||
620 | &dev_attr_chip.attr, | ||
621 | &dev_attr_output.attr, | ||
622 | NULL, | ||
623 | }; | ||
624 | static const struct attribute_group netdev_sysfs_group = { | ||
625 | .name = NULL, | ||
626 | .attrs = (struct attribute **)netdev_sysfs_attrs, | ||
627 | }; | ||
628 | |||
629 | static const struct net_device_ops softing_netdev_ops = { | ||
630 | .ndo_open = softing_netdev_open, | ||
631 | .ndo_stop = softing_netdev_stop, | ||
632 | .ndo_start_xmit = softing_netdev_start_xmit, | ||
633 | }; | ||
634 | |||
635 | static const struct can_bittiming_const softing_btr_const = { | ||
636 | .name = "softing", | ||
637 | .tseg1_min = 1, | ||
638 | .tseg1_max = 16, | ||
639 | .tseg2_min = 1, | ||
640 | .tseg2_max = 8, | ||
641 | .sjw_max = 4, /* overruled */ | ||
642 | .brp_min = 1, | ||
643 | .brp_max = 32, /* overruled */ | ||
644 | .brp_inc = 1, | ||
645 | }; | ||
646 | |||
647 | |||
648 | static __devinit struct net_device *softing_netdev_create(struct softing *card, | ||
649 | uint16_t chip_id) | ||
650 | { | ||
651 | struct net_device *netdev; | ||
652 | struct softing_priv *priv; | ||
653 | |||
654 | netdev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX); | ||
655 | if (!netdev) { | ||
656 | dev_alert(&card->pdev->dev, "alloc_candev failed\n"); | ||
657 | return NULL; | ||
658 | } | ||
659 | priv = netdev_priv(netdev); | ||
660 | priv->netdev = netdev; | ||
661 | priv->card = card; | ||
662 | memcpy(&priv->btr_const, &softing_btr_const, sizeof(priv->btr_const)); | ||
663 | priv->btr_const.brp_max = card->pdat->max_brp; | ||
664 | priv->btr_const.sjw_max = card->pdat->max_sjw; | ||
665 | priv->can.bittiming_const = &priv->btr_const; | ||
666 | priv->can.clock.freq = 8000000; | ||
667 | priv->chip = chip_id; | ||
668 | priv->output = softing_default_output(netdev); | ||
669 | SET_NETDEV_DEV(netdev, &card->pdev->dev); | ||
670 | |||
671 | netdev->flags |= IFF_ECHO; | ||
672 | netdev->netdev_ops = &softing_netdev_ops; | ||
673 | priv->can.do_set_mode = softing_candev_set_mode; | ||
674 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; | ||
675 | |||
676 | return netdev; | ||
677 | } | ||
678 | |||
679 | static __devinit int softing_netdev_register(struct net_device *netdev) | ||
680 | { | ||
681 | int ret; | ||
682 | |||
683 | netdev->sysfs_groups[0] = &netdev_sysfs_group; | ||
684 | ret = register_candev(netdev); | ||
685 | if (ret) { | ||
686 | dev_alert(&netdev->dev, "register failed\n"); | ||
687 | return ret; | ||
688 | } | ||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | static void softing_netdev_cleanup(struct net_device *netdev) | ||
693 | { | ||
694 | unregister_candev(netdev); | ||
695 | free_candev(netdev); | ||
696 | } | ||
697 | |||
698 | /* | ||
699 | * sysfs for Platform device | ||
700 | */ | ||
701 | #define DEV_ATTR_RO(name, member) \ | ||
702 | static ssize_t show_##name(struct device *dev, \ | ||
703 | struct device_attribute *attr, char *buf) \ | ||
704 | { \ | ||
705 | struct softing *card = platform_get_drvdata(to_platform_device(dev)); \ | ||
706 | return sprintf(buf, "%u\n", card->member); \ | ||
707 | } \ | ||
708 | static DEVICE_ATTR(name, 0444, show_##name, NULL) | ||
709 | |||
710 | #define DEV_ATTR_RO_STR(name, member) \ | ||
711 | static ssize_t show_##name(struct device *dev, \ | ||
712 | struct device_attribute *attr, char *buf) \ | ||
713 | { \ | ||
714 | struct softing *card = platform_get_drvdata(to_platform_device(dev)); \ | ||
715 | return sprintf(buf, "%s\n", card->member); \ | ||
716 | } \ | ||
717 | static DEVICE_ATTR(name, 0444, show_##name, NULL) | ||
718 | |||
719 | DEV_ATTR_RO(serial, id.serial); | ||
720 | DEV_ATTR_RO_STR(firmware, pdat->app.fw); | ||
721 | DEV_ATTR_RO(firmware_version, id.fw_version); | ||
722 | DEV_ATTR_RO_STR(hardware, pdat->name); | ||
723 | DEV_ATTR_RO(hardware_version, id.hw_version); | ||
724 | DEV_ATTR_RO(license, id.license); | ||
725 | DEV_ATTR_RO(frequency, id.freq); | ||
726 | DEV_ATTR_RO(txpending, tx.pending); | ||
727 | |||
728 | static struct attribute *softing_pdev_attrs[] = { | ||
729 | &dev_attr_serial.attr, | ||
730 | &dev_attr_firmware.attr, | ||
731 | &dev_attr_firmware_version.attr, | ||
732 | &dev_attr_hardware.attr, | ||
733 | &dev_attr_hardware_version.attr, | ||
734 | &dev_attr_license.attr, | ||
735 | &dev_attr_frequency.attr, | ||
736 | &dev_attr_txpending.attr, | ||
737 | NULL, | ||
738 | }; | ||
739 | |||
740 | static const struct attribute_group softing_pdev_group = { | ||
741 | .name = NULL, | ||
742 | .attrs = softing_pdev_attrs, | ||
743 | }; | ||
744 | |||
745 | /* | ||
746 | * platform driver | ||
747 | */ | ||
748 | static __devexit int softing_pdev_remove(struct platform_device *pdev) | ||
749 | { | ||
750 | struct softing *card = platform_get_drvdata(pdev); | ||
751 | int j; | ||
752 | |||
753 | /* first, disable card*/ | ||
754 | softing_card_shutdown(card); | ||
755 | |||
756 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
757 | if (!card->net[j]) | ||
758 | continue; | ||
759 | softing_netdev_cleanup(card->net[j]); | ||
760 | card->net[j] = NULL; | ||
761 | } | ||
762 | sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group); | ||
763 | |||
764 | iounmap(card->dpram); | ||
765 | kfree(card); | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | static __devinit int softing_pdev_probe(struct platform_device *pdev) | ||
770 | { | ||
771 | const struct softing_platform_data *pdat = pdev->dev.platform_data; | ||
772 | struct softing *card; | ||
773 | struct net_device *netdev; | ||
774 | struct softing_priv *priv; | ||
775 | struct resource *pres; | ||
776 | int ret; | ||
777 | int j; | ||
778 | |||
779 | if (!pdat) { | ||
780 | dev_warn(&pdev->dev, "no platform data\n"); | ||
781 | return -EINVAL; | ||
782 | } | ||
783 | if (pdat->nbus > ARRAY_SIZE(card->net)) { | ||
784 | dev_warn(&pdev->dev, "%u nets??\n", pdat->nbus); | ||
785 | return -EINVAL; | ||
786 | } | ||
787 | |||
788 | card = kzalloc(sizeof(*card), GFP_KERNEL); | ||
789 | if (!card) | ||
790 | return -ENOMEM; | ||
791 | card->pdat = pdat; | ||
792 | card->pdev = pdev; | ||
793 | platform_set_drvdata(pdev, card); | ||
794 | mutex_init(&card->fw.lock); | ||
795 | spin_lock_init(&card->spin); | ||
796 | |||
797 | ret = -EINVAL; | ||
798 | pres = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
799 | if (!pres) | ||
800 | goto platform_resource_failed;; | ||
801 | card->dpram_phys = pres->start; | ||
802 | card->dpram_size = pres->end - pres->start + 1; | ||
803 | card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size); | ||
804 | if (!card->dpram) { | ||
805 | dev_alert(&card->pdev->dev, "dpram ioremap failed\n"); | ||
806 | goto ioremap_failed; | ||
807 | } | ||
808 | |||
809 | pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
810 | if (pres) | ||
811 | card->irq.nr = pres->start; | ||
812 | |||
813 | /* reset card */ | ||
814 | ret = softing_card_boot(card); | ||
815 | if (ret < 0) { | ||
816 | dev_alert(&pdev->dev, "failed to boot\n"); | ||
817 | goto boot_failed; | ||
818 | } | ||
819 | |||
820 | /* only now, the chip's are known */ | ||
821 | card->id.freq = card->pdat->freq; | ||
822 | |||
823 | ret = sysfs_create_group(&pdev->dev.kobj, &softing_pdev_group); | ||
824 | if (ret < 0) { | ||
825 | dev_alert(&card->pdev->dev, "sysfs failed\n"); | ||
826 | goto sysfs_failed; | ||
827 | } | ||
828 | |||
829 | ret = -ENOMEM; | ||
830 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
831 | card->net[j] = netdev = | ||
832 | softing_netdev_create(card, card->id.chip[j]); | ||
833 | if (!netdev) { | ||
834 | dev_alert(&pdev->dev, "failed to make can[%i]", j); | ||
835 | goto netdev_failed; | ||
836 | } | ||
837 | priv = netdev_priv(card->net[j]); | ||
838 | priv->index = j; | ||
839 | ret = softing_netdev_register(netdev); | ||
840 | if (ret) { | ||
841 | free_candev(netdev); | ||
842 | card->net[j] = NULL; | ||
843 | dev_alert(&card->pdev->dev, | ||
844 | "failed to register can[%i]\n", j); | ||
845 | goto netdev_failed; | ||
846 | } | ||
847 | } | ||
848 | dev_info(&card->pdev->dev, "%s ready.\n", card->pdat->name); | ||
849 | return 0; | ||
850 | |||
851 | netdev_failed: | ||
852 | for (j = 0; j < ARRAY_SIZE(card->net); ++j) { | ||
853 | if (!card->net[j]) | ||
854 | continue; | ||
855 | softing_netdev_cleanup(card->net[j]); | ||
856 | } | ||
857 | sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group); | ||
858 | sysfs_failed: | ||
859 | softing_card_shutdown(card); | ||
860 | boot_failed: | ||
861 | iounmap(card->dpram); | ||
862 | ioremap_failed: | ||
863 | platform_resource_failed: | ||
864 | kfree(card); | ||
865 | return ret; | ||
866 | } | ||
867 | |||
868 | static struct platform_driver softing_driver = { | ||
869 | .driver = { | ||
870 | .name = "softing", | ||
871 | .owner = THIS_MODULE, | ||
872 | }, | ||
873 | .probe = softing_pdev_probe, | ||
874 | .remove = __devexit_p(softing_pdev_remove), | ||
875 | }; | ||
876 | |||
877 | MODULE_ALIAS("platform:softing"); | ||
878 | |||
879 | static int __init softing_start(void) | ||
880 | { | ||
881 | return platform_driver_register(&softing_driver); | ||
882 | } | ||
883 | |||
884 | static void __exit softing_stop(void) | ||
885 | { | ||
886 | platform_driver_unregister(&softing_driver); | ||
887 | } | ||
888 | |||
889 | module_init(softing_start); | ||
890 | module_exit(softing_stop); | ||
891 | |||
892 | MODULE_DESCRIPTION("Softing DPRAM CAN driver"); | ||
893 | MODULE_AUTHOR("Kurt Van Dijck <kurt.van.dijck@eia.be>"); | ||
894 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/net/can/softing/softing_platform.h b/drivers/net/can/softing/softing_platform.h new file mode 100644 index 000000000000..ebbf69815623 --- /dev/null +++ b/drivers/net/can/softing/softing_platform.h | |||
@@ -0,0 +1,40 @@ | |||
1 | |||
2 | #include <linux/platform_device.h> | ||
3 | |||
4 | #ifndef _SOFTING_DEVICE_H_ | ||
5 | #define _SOFTING_DEVICE_H_ | ||
6 | |||
7 | /* softing firmware directory prefix */ | ||
8 | #define fw_dir "softing-4.6/" | ||
9 | |||
10 | struct softing_platform_data { | ||
11 | unsigned int manf; | ||
12 | unsigned int prod; | ||
13 | /* | ||
14 | * generation | ||
15 | * 1st with NEC or SJA1000 | ||
16 | * 8bit, exclusive interrupt, ... | ||
17 | * 2nd only SJA1000 | ||
18 | * 16bit, shared interrupt | ||
19 | */ | ||
20 | int generation; | ||
21 | int nbus; /* # busses on device */ | ||
22 | unsigned int freq; /* operating frequency in Hz */ | ||
23 | unsigned int max_brp; | ||
24 | unsigned int max_sjw; | ||
25 | unsigned long dpram_size; | ||
26 | const char *name; | ||
27 | struct { | ||
28 | unsigned long offs; | ||
29 | unsigned long addr; | ||
30 | const char *fw; | ||
31 | } boot, load, app; | ||
32 | /* | ||
33 | * reset() function | ||
34 | * bring pdev in or out of reset, depending on value | ||
35 | */ | ||
36 | int (*reset)(struct platform_device *pdev, int value); | ||
37 | int (*enable_irq)(struct platform_device *pdev, int value); | ||
38 | }; | ||
39 | |||
40 | #endif | ||
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index 05a52754f486..dc53c831ea95 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c | |||
@@ -659,7 +659,7 @@ failed: | |||
659 | static void unlink_all_urbs(struct esd_usb2 *dev) | 659 | static void unlink_all_urbs(struct esd_usb2 *dev) |
660 | { | 660 | { |
661 | struct esd_usb2_net_priv *priv; | 661 | struct esd_usb2_net_priv *priv; |
662 | int i; | 662 | int i, j; |
663 | 663 | ||
664 | usb_kill_anchored_urbs(&dev->rx_submitted); | 664 | usb_kill_anchored_urbs(&dev->rx_submitted); |
665 | for (i = 0; i < dev->net_count; i++) { | 665 | for (i = 0; i < dev->net_count; i++) { |
@@ -668,8 +668,8 @@ static void unlink_all_urbs(struct esd_usb2 *dev) | |||
668 | usb_kill_anchored_urbs(&priv->tx_submitted); | 668 | usb_kill_anchored_urbs(&priv->tx_submitted); |
669 | atomic_set(&priv->active_tx_jobs, 0); | 669 | atomic_set(&priv->active_tx_jobs, 0); |
670 | 670 | ||
671 | for (i = 0; i < MAX_TX_URBS; i++) | 671 | for (j = 0; j < MAX_TX_URBS; j++) |
672 | priv->tx_contexts[i].echo_index = MAX_TX_URBS; | 672 | priv->tx_contexts[j].echo_index = MAX_TX_URBS; |
673 | } | 673 | } |
674 | } | 674 | } |
675 | } | 675 | } |