From 2f7c68cb55ecb7331f2381deb497c27155f32faf Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 03 Jan 2024 09:43:39 +0000
Subject: [PATCH] update kernel to 5.10.198

---
 kernel/drivers/net/can/rockchip/rockchip_canfd.c |   77 ++++++++++++++++++++++++++++----------
 1 files changed, 57 insertions(+), 20 deletions(-)

diff --git a/kernel/drivers/net/can/rockchip/rockchip_canfd.c b/kernel/drivers/net/can/rockchip/rockchip_canfd.c
index abdcdb5..dba7f14 100644
--- a/kernel/drivers/net/can/rockchip/rockchip_canfd.c
+++ b/kernel/drivers/net/can/rockchip/rockchip_canfd.c
@@ -214,6 +214,8 @@
 #define CAN_RXFRD_OFFSET(n)	(CAN_RXFRD + CAN_RF_SIZE * (n))
 
 #define CAN_RX_FILTER_MASK	0x1fffffff
+#define NOACK_ERR_FLAG		0xc200800
+#define CAN_BUSOFF_FLAG		0x20
 
 #define DRV_NAME	"rockchip_canfd"
 
@@ -234,6 +236,7 @@
 	bool txtorx;
 	u32 tx_invalid[4];
 	struct delayed_work tx_err_work;
+	u32 delay_time_ms;
 };
 
 static inline u32 rockchip_canfd_read(const struct rockchip_canfd *priv,
@@ -357,6 +360,12 @@
 
 		rockchip_canfd_write(rcan, CAN_DBTP, reg_btp);
 	}
+	if (bt->bitrate > 200000)
+		rcan->delay_time_ms = 1;
+	else if (bt->bitrate > 50000)
+		rcan->delay_time_ms = 5;
+	else
+		rcan->delay_time_ms = 20;
 
 	netdev_dbg(ndev, "%s NBTP=0x%08x, DBTP=0x%08x, TDCR=0x%08x\n", __func__,
 		   rockchip_canfd_read(rcan, CAN_NBTP),
@@ -428,6 +437,10 @@
 	if (rcan->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
 		val |= MODE_SELF_TEST | MODE_LBACK;
 
+	/* Listen-only mode */
+	if (rcan->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+		val |= MODE_SILENT;
+
 	rockchip_canfd_write(rcan, CAN_MODE, val);
 
 	rockchip_canfd_set_bittiming(ndev);
@@ -487,13 +500,27 @@
 {
 	struct rockchip_canfd *rcan =
 		container_of(work, struct rockchip_canfd, tx_err_work.work);
-	u32 mode;
+	u32 mode, err_code;
 
 	mode = rockchip_canfd_read(rcan, CAN_MODE);
-	rockchip_canfd_write(rcan, CAN_MODE, 0);
-	rockchip_canfd_write(rcan, CAN_MODE, mode);
-	rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);
-	schedule_delayed_work(&rcan->tx_err_work, 1);
+	err_code = rockchip_canfd_read(rcan, CAN_ERR_CODE);
+	if ((err_code & NOACK_ERR_FLAG) == NOACK_ERR_FLAG) {
+		rockchip_canfd_write(rcan, CAN_MODE,
+				     rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);
+		rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);
+		rockchip_canfd_write(rcan, CAN_MODE,
+				     rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));
+		schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));
+	} else {
+		rockchip_canfd_write(rcan, CAN_MODE, 0);
+		rockchip_canfd_write(rcan, CAN_MODE, mode);
+		rockchip_canfd_write(rcan, CAN_MODE,
+				     rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);
+		rockchip_canfd_write(rcan, CAN_CMD, CAN_TX0_REQ);
+		rockchip_canfd_write(rcan, CAN_MODE,
+				     rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));
+		schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));
+	}
 }
 
 /* transmit a CAN message
@@ -569,10 +596,9 @@
 		for (i = 0; i < cf->len; i += 4)
 			rockchip_canfd_write(rcan, CAN_TXDAT0 + i,
 					     *(u32 *)(cf->data + i));
+		can_put_echo_skb(skb, ndev, 0);
 		rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ);
 		local_irq_restore(flags);
-		can_put_echo_skb(skb, ndev, 0);
-
 		return NETDEV_TX_OK;
 	}
 
@@ -583,12 +609,13 @@
 		rockchip_canfd_write(rcan, CAN_TXDAT0 + i,
 				     *(u32 *)(cf->data + i));
 
-	rockchip_canfd_write(rcan, CAN_CMD, cmd);
-
-	schedule_delayed_work(&rcan->tx_err_work, 1);
-
 	can_put_echo_skb(skb, ndev, 0);
-
+	rockchip_canfd_write(rcan, CAN_MODE,
+			     rockchip_canfd_read(rcan, CAN_MODE) | MODE_SPACE_RX);
+	rockchip_canfd_write(rcan, CAN_CMD, cmd);
+	rockchip_canfd_write(rcan, CAN_MODE,
+			     rockchip_canfd_read(rcan, CAN_MODE) & (~MODE_SPACE_RX));
+	schedule_delayed_work(&rcan->tx_err_work, msecs_to_jiffies(rcan->delay_time_ms));
 	return NETDEV_TX_OK;
 }
 
@@ -740,9 +767,6 @@
 		cf->data[7] = rxerr;
 	}
 
-	if (isr & TX_LOSTARB_INT)
-		schedule_delayed_work(&rcan->tx_err_work, 1);
-
 	if (isr & BUS_OFF_INT) {
 		rcan->can.state = CAN_STATE_BUS_OFF;
 		rcan->can.can_stats.bus_off++;
@@ -772,8 +796,14 @@
 	}
 
 	if (rcan->can.state >= CAN_STATE_BUS_OFF ||
-	    ((sta_reg & 0x20) == 0x20))
-		can_bus_off(ndev);
+	    ((sta_reg & CAN_BUSOFF_FLAG) == CAN_BUSOFF_FLAG)) {
+		cancel_delayed_work(&rcan->tx_err_work);
+		netif_stop_queue(ndev);
+		rockchip_canfd_stop(ndev);
+		can_free_echo_skb(ndev, 0);
+		rockchip_canfd_start(ndev);
+		netif_start_queue(ndev);
+	}
 
 	stats->rx_packets++;
 	stats->rx_bytes += cf->can_dlc;
@@ -788,13 +818,14 @@
 	struct rockchip_canfd *rcan = netdev_priv(ndev);
 	struct net_device_stats *stats = &ndev->stats;
 	u32 err_int = ERR_WARN_INT | RX_BUF_OV_INT | PASSIVE_ERR_INT |
-		      TX_LOSTARB_INT | BUS_ERR_INT | BUS_OFF_INT;
+		      BUS_ERR_INT | BUS_OFF_INT;
 	u32 isr;
 	u32 dlc = 0;
 	u32 quota, work_done = 0;
 
 	isr = rockchip_canfd_read(rcan, CAN_INT);
 	if (isr & TX_FINISH_INT) {
+		cancel_delayed_work(&rcan->tx_err_work);
 		dlc = rockchip_canfd_read(rcan, CAN_TXFIC);
 		/* transmission complete interrupt */
 		if (dlc & FDF_MASK)
@@ -802,7 +833,6 @@
 		else
 			stats->tx_bytes += (dlc & DLC_MASK);
 		stats->tx_packets++;
-		cancel_delayed_work(&rcan->tx_err_work);
 		if (rcan->txtorx && rcan->mode <= ROCKCHIP_RK3568_CAN_MODE && dlc & FORMAT_MASK) {
 			rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, FORMAT_MASK);
 			quota = rockchip_canfd_get_rx_fifo_cnt(ndev);
@@ -814,6 +844,10 @@
 				rockchip_canfd_write(rcan, CAN_CMD, CAN_TX1_REQ);
 			rockchip_canfd_write(rcan, CAN_TX_CHECK_FIC, 0);
 		}
+		if (read_poll_timeout_atomic(rockchip_canfd_read, quota,
+					     !(quota & 0x3),
+					     0, 5000000, false, rcan, CAN_CMD))
+			netdev_err(ndev, "Warning: wait tx req timeout!\n");
 		rockchip_canfd_write(rcan, CAN_CMD, 0);
 		can_get_echo_skb(ndev, 0);
 		netif_wake_queue(ndev);
@@ -825,7 +859,10 @@
 			rockchip_canfd_write(rcan, CAN_INT_MASK, 0x1);
 			napi_schedule(&rcan->napi);
 		} else {
-			quota = rockchip_canfd_get_rx_fifo_cnt(ndev);
+			work_done = 0;
+			quota = (rockchip_canfd_read(rcan, CAN_RXFC) &
+				 rcan->rx_fifo_mask) >>
+				rcan->rx_fifo_shift;
 			if (quota) {
 				while (work_done < quota)
 					work_done += rockchip_canfd_rx(ndev);

--
Gitblit v1.6.2