hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/can/rockchip/rockchip_canfd.c
....@@ -214,6 +214,8 @@
214214 #define CAN_RXFRD_OFFSET(n) (CAN_RXFRD + CAN_RF_SIZE * (n))
215215
216216 #define CAN_RX_FILTER_MASK 0x1fffffff
217
+#define NOACK_ERR_FLAG 0xc200800
218
+#define CAN_BUSOFF_FLAG 0x20
217219
218220 #define DRV_NAME "rockchip_canfd"
219221
....@@ -234,6 +236,7 @@
234236 bool txtorx;
235237 u32 tx_invalid[4];
236238 struct delayed_work tx_err_work;
239
+ u32 delay_time_ms;
237240 };
238241
239242 static inline u32 rockchip_canfd_read(const struct rockchip_canfd *priv,
....@@ -357,6 +360,12 @@
357360
358361 rockchip_canfd_write(rcan, CAN_DBTP, reg_btp);
359362 }
363
+ if (bt->bitrate > 200000)
364
+ rcan->delay_time_ms = 1;
365
+ else if (bt->bitrate > 50000)
366
+ rcan->delay_time_ms = 5;
367
+ else
368
+ rcan->delay_time_ms = 20;
360369
361370 netdev_dbg(ndev, "%s NBTP=0x%08x, DBTP=0x%08x, TDCR=0x%08x\n", __func__,
362371 rockchip_canfd_read(rcan, CAN_NBTP),
....@@ -428,6 +437,10 @@
428437 if (rcan->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
429438 val |= MODE_SELF_TEST | MODE_LBACK;
430439
440
+ /* Listen-only mode */
441
+ if (rcan->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
442
+ val |= MODE_SILENT;
443
+
431444 rockchip_canfd_write(rcan, CAN_MODE, val);
432445
433446 rockchip_canfd_set_bittiming(ndev);
....@@ -487,13 +500,27 @@
487500 {
488501 struct rockchip_canfd *rcan =
489502 container_of(work, struct rockchip_canfd, tx_err_work.work);
490
- u32 mode;
503
+ u32 mode, err_code;
491504
492505 mode = rockchip_canfd_read(rcan, CAN_MODE);
493
- rockchip_canfd_write(rcan, CAN_MODE, 0);
494
- rockchip_canfd_write(rcan, CAN_MODE, mode);
495
- rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);
496
- schedule_delayed_work(&rcan->tx_err_work, 1);
506
+ err_code = rockchip_canfd_read(rcan, CAN_ERR_CODE);
507
+ if ((err_code & NOACK_ERR_FLAG) == NOACK_ERR_FLAG) {
508
+ rockchip_canfd_write(rcan, CAN_MODE,
509
+ rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);
510
+ rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);
511
+ rockchip_canfd_write(rcan, CAN_MODE,
512
+ rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));
513
+ schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));
514
+ } else {
515
+ rockchip_canfd_write(rcan, CAN_MODE, 0);
516
+ rockchip_canfd_write(rcan, CAN_MODE, mode);
517
+ rockchip_canfd_write(rcan, CAN_MODE,
518
+ rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);
519
+ rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);
520
+ rockchip_canfd_write(rcan, CAN_MODE,
521
+ rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));
522
+ schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));
523
+ }
497524 }
498525
499526 /* transmit a CAN message
....@@ -569,10 +596,9 @@
569596 for (i = 0; i < cf->len; i += 4)
570597 rockchip_canfd_write(rcan, CAN_TXDAT0 + i,
571598 *(u32 *)(cf->data + i));
599
+ can_put_echo_skb(skb, ndev, 0);
572600 rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ);
573601 local_irq_restore(flags);
574
- can_put_echo_skb(skb, ndev, 0);
575
-
576602 return NETDEV_TX_OK;
577603 }
578604
....@@ -583,12 +609,13 @@
583609 rockchip_canfd_write(rcan, CAN_TXDAT0 + i,
584610 *(u32 *)(cf->data + i));
585611
586
- rockchip_canfd_write(rcan, CAN_CMD, cmd);
587
-
588
- schedule_delayed_work(&rcan->tx_err_work, 1);
589
-
590612 can_put_echo_skb(skb, ndev, 0);
591
-
613
+ rockchip_canfd_write(rcan, CAN_MODE,
614
+ rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);
615
+ rockchip_canfd_write(rcan, CAN_CMD, cmd);
616
+ rockchip_canfd_write(rcan, CAN_MODE,
617
+ rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));
618
+ schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));
592619 return NETDEV_TX_OK;
593620 }
594621
....@@ -740,9 +767,6 @@
740767 cf->data[7] = rxerr;
741768 }
742769
743
- if (isr & TX_LOSTARB_INT)
744
- schedule_delayed_work(&rcan->tx_err_work, 1);
745
-
746770 if (isr & BUS_OFF_INT) {
747771 rcan->can.state = CAN_STATE_BUS_OFF;
748772 rcan->can.can_stats.bus_off++;
....@@ -772,8 +796,14 @@
772796 }
773797
774798 if (rcan->can.state >= CAN_STATE_BUS_OFF ||
775
- ((sta_reg & 0x20) == 0x20))
776
- can_bus_off(ndev);
799
+ ((sta_reg & CAN_BUSOFF_FLAG) == CAN_BUSOFF_FLAG)) {
800
+ cancel_delayed_work(&rcan->tx_err_work);
801
+ netif_stop_queue(ndev);
802
+ rockchip_canfd_stop(ndev);
803
+ can_free_echo_skb(ndev, 0);
804
+ rockchip_canfd_start(ndev);
805
+ netif_start_queue(ndev);
806
+ }
777807
778808 stats->rx_packets++;
779809 stats->rx_bytes += cf->can_dlc;
....@@ -788,13 +818,14 @@
788818 struct rockchip_canfd *rcan = netdev_priv(ndev);
789819 struct net_device_stats *stats = &ndev->stats;
790820 u32 err_int = ERR_WARN_INT | RX_BUF_OV_INT | PASSIVE_ERR_INT |
791
- TX_LOSTARB_INT | BUS_ERR_INT | BUS_OFF_INT;
821
+ BUS_ERR_INT | BUS_OFF_INT;
792822 u32 isr;
793823 u32 dlc = 0;
794824 u32 quota, work_done = 0;
795825
796826 isr = rockchip_canfd_read(rcan, CAN_INT);
797827 if (isr & TX_FINISH_INT) {
828
+ cancel_delayed_work(&rcan->tx_err_work);
798829 dlc = rockchip_canfd_read(rcan, CAN_TXFIC);
799830 /* transmission complete interrupt */
800831 if (dlc & FDF_MASK)
....@@ -802,7 +833,6 @@
802833 else
803834 stats->tx_bytes += (dlc & DLC_MASK);
804835 stats->tx_packets++;
805
- cancel_delayed_work(&rcan->tx_err_work);
806836 if (rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && dlc & FORMAT_MASK) {
807837 rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, FORMAT_MASK);
808838 quota = rockchip_canfd_get_rx_fifo_cnt(ndev);
....@@ -814,6 +844,10 @@
814844 rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ);
815845 rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, 0);
816846 }
847
+ if (read_poll_timeout_atomic(rockchip_canfd_read, quota,
848
+ !(quota & 0x3),
849
+ 0, 5000000, false, rcan, CAN_CMD))
850
+ netdev_err(ndev, "Warning: wait tx req timeout!\n");
817851 rockchip_canfd_write(rcan, CAN_CMD, 0);
818852 can_get_echo_skb(ndev, 0);
819853 netif_wake_queue(ndev);
....@@ -825,7 +859,10 @@
825859 rockchip_canfd_write(rcan, CAN_INT_MASK, 0x1);
826860 napi_schedule(&rcan->napi);
827861 } else {
828
- quota = rockchip_canfd_get_rx_fifo_cnt(ndev);
862
+ work_done = 0;
863
+ quota = (rockchip_canfd_read(rcan, CAN_RXFC) &
864
+ rcan->rx_fifo_mask) >>
865
+ rcan->rx_fifo_shift;
829866 if (quota) {
830867 while (work_done < quota)
831868 work_done += rockchip_canfd_rx(ndev);