aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/can/ifi_canfd/ifi_canfd.c113
1 files changed, 107 insertions, 6 deletions
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index ba6cd43e1bc6..2d1d22eec750 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -52,7 +52,8 @@
52#define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13) 52#define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13)
53 53
54#define IFI_CANFD_INTERRUPT 0xc 54#define IFI_CANFD_INTERRUPT 0xc
55#define IFI_CANFD_INTERRUPT_ERROR_WARNING ((u32)BIT(1)) 55#define IFI_CANFD_INTERRUPT_ERROR_WARNING BIT(1)
56#define IFI_CANFD_INTERRUPT_ERROR_COUNTER BIT(10)
56#define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16) 57#define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16)
57#define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22) 58#define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22)
58#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY BIT(24) 59#define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY BIT(24)
@@ -103,7 +104,26 @@
103 104
104#define IFI_CANFD_RES1 0x40 105#define IFI_CANFD_RES1 0x40
105 106
106#define IFI_CANFD_RES2 0x44 107#define IFI_CANFD_ERROR_CTR 0x44
108#define IFI_CANFD_ERROR_CTR_UNLOCK_MAGIC 0x21302899
109#define IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST BIT(0)
110#define IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST BIT(1)
111#define IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST BIT(2)
112#define IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST BIT(3)
113#define IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST BIT(4)
114#define IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST BIT(5)
115#define IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST BIT(6)
116#define IFI_CANFD_ERROR_CTR_OVERLOAD_ALL BIT(8)
117#define IFI_CANFD_ERROR_CTR_ACK_ERROR_ALL BIT(9)
118#define IFI_CANFD_ERROR_CTR_BIT0_ERROR_ALL BIT(10)
119#define IFI_CANFD_ERROR_CTR_BIT1_ERROR_ALL BIT(11)
120#define IFI_CANFD_ERROR_CTR_STUFF_ERROR_ALL BIT(12)
121#define IFI_CANFD_ERROR_CTR_CRC_ERROR_ALL BIT(13)
122#define IFI_CANFD_ERROR_CTR_FORM_ERROR_ALL BIT(14)
123#define IFI_CANFD_ERROR_CTR_BITPOSITION_OFFSET 16
124#define IFI_CANFD_ERROR_CTR_BITPOSITION_MASK 0xff
125#define IFI_CANFD_ERROR_CTR_ER_RESET BIT(30)
126#define IFI_CANFD_ERROR_CTR_ER_ENABLE ((u32)BIT(31))
107 127
108#define IFI_CANFD_PAR 0x48 128#define IFI_CANFD_PAR 0x48
109 129
@@ -197,6 +217,8 @@ static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable)
197 if (enable) { 217 if (enable) {
198 enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY | 218 enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY |
199 IFI_CANFD_IRQMASK_RXFIFO_NEMPTY; 219 IFI_CANFD_IRQMASK_RXFIFO_NEMPTY;
220 if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
221 enirq |= IFI_CANFD_INTERRUPT_ERROR_COUNTER;
200 } 222 }
201 223
202 writel(IFI_CANFD_IRQMASK_SET_ERR | 224 writel(IFI_CANFD_IRQMASK_SET_ERR |
@@ -335,6 +357,68 @@ static int ifi_canfd_handle_lost_msg(struct net_device *ndev)
335 return 1; 357 return 1;
336} 358}
337 359
360static int ifi_canfd_handle_lec_err(struct net_device *ndev, const u32 errctr)
361{
362 struct ifi_canfd_priv *priv = netdev_priv(ndev);
363 struct net_device_stats *stats = &ndev->stats;
364 struct can_frame *cf;
365 struct sk_buff *skb;
366 const u32 errmask = IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST |
367 IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST |
368 IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST |
369 IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST |
370 IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST |
371 IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST |
372 IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST;
373
374 if (!(errctr & errmask)) /* No error happened. */
375 return 0;
376
377 priv->can.can_stats.bus_error++;
378 stats->rx_errors++;
379
380 /* Propagate the error condition to the CAN stack. */
381 skb = alloc_can_err_skb(ndev, &cf);
382 if (unlikely(!skb))
383 return 0;
384
385 /* Read the error counter register and check for new errors. */
386 cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
387
388 if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST)
389 cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
390
391 if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST)
392 cf->data[3] = CAN_ERR_PROT_LOC_ACK;
393
394 if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST)
395 cf->data[2] |= CAN_ERR_PROT_BIT0;
396
397 if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST)
398 cf->data[2] |= CAN_ERR_PROT_BIT1;
399
400 if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST)
401 cf->data[2] |= CAN_ERR_PROT_STUFF;
402
403 if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST)
404 cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
405
406 if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST)
407 cf->data[2] |= CAN_ERR_PROT_FORM;
408
409 /* Reset the error counter, ack the IRQ and re-enable the counter. */
410 writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
411 writel(IFI_CANFD_INTERRUPT_ERROR_COUNTER,
412 priv->base + IFI_CANFD_INTERRUPT);
413 writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR);
414
415 stats->rx_packets++;
416 stats->rx_bytes += cf->can_dlc;
417 netif_receive_skb(skb);
418
419 return 1;
420}
421
338static int ifi_canfd_get_berr_counter(const struct net_device *ndev, 422static int ifi_canfd_get_berr_counter(const struct net_device *ndev,
339 struct can_berr_counter *bec) 423 struct can_berr_counter *bec)
340{ 424{
@@ -470,6 +554,7 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota)
470 554
471 u32 stcmd = readl(priv->base + IFI_CANFD_STCMD); 555 u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
472 u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD); 556 u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD);
557 u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR);
473 558
474 /* Handle bus state changes */ 559 /* Handle bus state changes */
475 if ((stcmd & stcmd_state_mask) || 560 if ((stcmd & stcmd_state_mask) ||
@@ -480,6 +565,10 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota)
480 if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW) 565 if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW)
481 work_done += ifi_canfd_handle_lost_msg(ndev); 566 work_done += ifi_canfd_handle_lost_msg(ndev);
482 567
568 /* Handle lec errors on the bus */
569 if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
570 work_done += ifi_canfd_handle_lec_err(ndev, errctr);
571
483 /* Handle normal messages on RX */ 572 /* Handle normal messages on RX */
484 if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY)) 573 if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY))
485 work_done += ifi_canfd_do_rx_poll(ndev, quota - work_done); 574 work_done += ifi_canfd_do_rx_poll(ndev, quota - work_done);
@@ -499,11 +588,12 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id)
499 struct net_device_stats *stats = &ndev->stats; 588 struct net_device_stats *stats = &ndev->stats;
500 const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY | 589 const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY |
501 IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER | 590 IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER |
502 IFI_CANFD_INTERRUPT_ERROR_WARNING; 591 IFI_CANFD_INTERRUPT_ERROR_WARNING |
592 IFI_CANFD_INTERRUPT_ERROR_COUNTER;
503 const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY | 593 const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY |
504 IFI_CANFD_INTERRUPT_TXFIFO_REMOVE; 594 IFI_CANFD_INTERRUPT_TXFIFO_REMOVE;
505 const u32 clr_irq_mask = ~(IFI_CANFD_INTERRUPT_SET_IRQ | 595 const u32 clr_irq_mask = ~((u32)(IFI_CANFD_INTERRUPT_SET_IRQ |
506 IFI_CANFD_INTERRUPT_ERROR_WARNING); 596 IFI_CANFD_INTERRUPT_ERROR_WARNING));
507 u32 isr; 597 u32 isr;
508 598
509 isr = readl(priv->base + IFI_CANFD_INTERRUPT); 599 isr = readl(priv->base + IFI_CANFD_INTERRUPT);
@@ -657,6 +747,12 @@ static void ifi_canfd_start(struct net_device *ndev)
657 747
658 ifi_canfd_irq_enable(ndev, 1); 748 ifi_canfd_irq_enable(ndev, 1);
659 749
750 /* Unlock, reset and enable the error counter. */
751 writel(IFI_CANFD_ERROR_CTR_UNLOCK_MAGIC,
752 priv->base + IFI_CANFD_ERROR_CTR);
753 writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
754 writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR);
755
660 /* Enable controller */ 756 /* Enable controller */
661 writel(stcmd, priv->base + IFI_CANFD_STCMD); 757 writel(stcmd, priv->base + IFI_CANFD_STCMD);
662} 758}
@@ -665,6 +761,10 @@ static void ifi_canfd_stop(struct net_device *ndev)
665{ 761{
666 struct ifi_canfd_priv *priv = netdev_priv(ndev); 762 struct ifi_canfd_priv *priv = netdev_priv(ndev);
667 763
764 /* Reset and disable the error counter. */
765 writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
766 writel(0, priv->base + IFI_CANFD_ERROR_CTR);
767
668 /* Reset the IP */ 768 /* Reset the IP */
669 writel(IFI_CANFD_STCMD_HARDRESET, priv->base + IFI_CANFD_STCMD); 769 writel(IFI_CANFD_STCMD_HARDRESET, priv->base + IFI_CANFD_STCMD);
670 770
@@ -868,7 +968,8 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
868 priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | 968 priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
869 CAN_CTRLMODE_LISTENONLY | 969 CAN_CTRLMODE_LISTENONLY |
870 CAN_CTRLMODE_FD | 970 CAN_CTRLMODE_FD |
871 CAN_CTRLMODE_FD_NON_ISO; 971 CAN_CTRLMODE_FD_NON_ISO |
972 CAN_CTRLMODE_BERR_REPORTING;
872 973
873 platform_set_drvdata(pdev, ndev); 974 platform_set_drvdata(pdev, ndev);
874 SET_NETDEV_DEV(ndev, dev); 975 SET_NETDEV_DEV(ndev, dev);