diff options
author | Andreas Larsson <andreas@gaisler.com> | 2012-09-20 03:50:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-09-22 15:26:53 -0400 |
commit | 7146b2d9f11e07848050f53b71bafa37a95ae609 (patch) | |
tree | bf74b0f0e60b078be7a123cefccf8cb3291c49b3 | |
parent | f61bd0585dfc7d99db4936d7467de4ca8e2f7ea0 (diff) |
can: sja1000: Add support for listen-only mode and one-shot mode
One-shot mode uses the TCS bit of the status register to discern
whether a transmission was successful or not. On a failed
transmission, the frame is not echoed back.
Signed-off-by: Andreas Larsson <andreas@gaisler.com>
Acked-by: Wolfgang Grandegger <wg@grandegger.com>
Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 4c4f33d482d2..25011dbe1b96 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c | |||
@@ -156,8 +156,13 @@ static void set_normal_mode(struct net_device *dev) | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* set chip to normal mode */ | 158 | /* set chip to normal mode */ |
159 | priv->write_reg(priv, REG_MOD, 0x00); | 159 | if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) |
160 | priv->write_reg(priv, REG_MOD, MOD_LOM); | ||
161 | else | ||
162 | priv->write_reg(priv, REG_MOD, 0x00); | ||
163 | |||
160 | udelay(10); | 164 | udelay(10); |
165 | |||
161 | status = priv->read_reg(priv, REG_MOD); | 166 | status = priv->read_reg(priv, REG_MOD); |
162 | } | 167 | } |
163 | 168 | ||
@@ -310,7 +315,10 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb, | |||
310 | 315 | ||
311 | can_put_echo_skb(skb, dev, 0); | 316 | can_put_echo_skb(skb, dev, 0); |
312 | 317 | ||
313 | sja1000_write_cmdreg(priv, CMD_TR); | 318 | if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) |
319 | sja1000_write_cmdreg(priv, CMD_TR | CMD_AT); | ||
320 | else | ||
321 | sja1000_write_cmdreg(priv, CMD_TR); | ||
314 | 322 | ||
315 | return NETDEV_TX_OK; | 323 | return NETDEV_TX_OK; |
316 | } | 324 | } |
@@ -505,10 +513,18 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) | |||
505 | netdev_warn(dev, "wakeup interrupt\n"); | 513 | netdev_warn(dev, "wakeup interrupt\n"); |
506 | 514 | ||
507 | if (isrc & IRQ_TI) { | 515 | if (isrc & IRQ_TI) { |
508 | /* transmission complete interrupt */ | 516 | /* transmission buffer released */ |
509 | stats->tx_bytes += priv->read_reg(priv, REG_FI) & 0xf; | 517 | if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT && |
510 | stats->tx_packets++; | 518 | !(status & SR_TCS)) { |
511 | can_get_echo_skb(dev, 0); | 519 | stats->tx_errors++; |
520 | can_free_echo_skb(dev, 0); | ||
521 | } else { | ||
522 | /* transmission complete */ | ||
523 | stats->tx_bytes += | ||
524 | priv->read_reg(priv, REG_FI) & 0xf; | ||
525 | stats->tx_packets++; | ||
526 | can_get_echo_skb(dev, 0); | ||
527 | } | ||
512 | netif_wake_queue(dev); | 528 | netif_wake_queue(dev); |
513 | } | 529 | } |
514 | if (isrc & IRQ_RI) { | 530 | if (isrc & IRQ_RI) { |
@@ -605,7 +621,8 @@ struct net_device *alloc_sja1000dev(int sizeof_priv) | |||
605 | priv->can.do_set_mode = sja1000_set_mode; | 621 | priv->can.do_set_mode = sja1000_set_mode; |
606 | priv->can.do_get_berr_counter = sja1000_get_berr_counter; | 622 | priv->can.do_get_berr_counter = sja1000_get_berr_counter; |
607 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | | 623 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | |
608 | CAN_CTRLMODE_BERR_REPORTING; | 624 | CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_LISTENONLY | |
625 | CAN_CTRLMODE_ONE_SHOT; | ||
609 | 626 | ||
610 | spin_lock_init(&priv->cmdreg_lock); | 627 | spin_lock_init(&priv->cmdreg_lock); |
611 | 628 | ||