diff options
-rw-r--r-- | drivers/net/can/ifi_canfd/ifi_canfd.c | 113 |
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 | ||
360 | static 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 | |||
338 | static int ifi_canfd_get_berr_counter(const struct net_device *ndev, | 422 | static 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); |