aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Larsson <andreas@gaisler.com>2012-09-20 03:50:41 -0400
committerDavid S. Miller <davem@davemloft.net>2012-09-22 15:26:53 -0400
commit7146b2d9f11e07848050f53b71bafa37a95ae609 (patch)
treebf74b0f0e60b078be7a123cefccf8cb3291c49b3
parentf61bd0585dfc7d99db4936d7467de4ca8e2f7ea0 (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.c31
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