diff mbox series

[v2,1/2] net: can: rockchip: add can for RK3576 Soc

Message ID 20241219011159.3357530-2-zhangqing@rock-chips.com (mailing list archive)
State New
Headers show
Series rockchip: add can for RK3576 Soc | expand

Commit Message

Elaine Zhang Dec. 19, 2024, 1:11 a.m. UTC
Is new controller:
Support CAN and CANFD protocol.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
---
 .../net/can/rockchip/rockchip_canfd-core.c    | 453 +++++++++++++++---
 drivers/net/can/rockchip/rockchip_canfd-rx.c  | 111 ++++-
 drivers/net/can/rockchip/rockchip_canfd-tx.c  |  29 ++
 drivers/net/can/rockchip/rockchip_canfd.h     | 285 +++++++++++
 4 files changed, 820 insertions(+), 58 deletions(-)

Comments

Marc Kleine-Budde Dec. 20, 2024, 12:06 p.m. UTC | #1
On 19.12.2024 09:11:58, Elaine Zhang wrote:
> Is new controller:
> Support CAN and CANFD protocol.
> 
> Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>

Thanks for porting the rk3576 to the mainline driver. Looking at subtle
differences between the IP cores I'm not sure if you want to add it to
the existing driver or have a dedicated driver. But we can decide on
this later. At least the mainline driver has a better structure than
your original downstream driver.

Why was the timestamp register removed from the registers? Previously
the driver supported hardware timestamping. :(

Some general comments here, a more detailed review will follow.

Why have bits been removed from several registers and the remaining ones
moved? That doesn't make it easier for driver developers to cover new IP
cores. :(

Please use FIELD_GET(), FIELD_PREP() macros instead of open coding shift
and mask operations. See rest of the driver.

Have you actually tested this code in both RX and TX direction? I don't
see rkcanfd_handle_tx_int() being called?

What's the purpose of "rockchip,rx-max-data"?

Why do you add "rx_fifo_depth" to "struct rkcanfd_priv"? It's not used
outside of rkcanfd_probe().

Can you configure the IP core for CAN-2.0 only mode, so that it only
receives CAN-2.0 frames only?

regards,
Marc
diff mbox series

Patch

diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/can/rockchip/rockchip_canfd-core.c
index df18c85fc078..ceae691412d4 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-core.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-core.c
@@ -50,6 +50,11 @@  static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v3 = {
 		RKCANFD_QUIRK_CANFD_BROKEN,
 };
 
+/* The rk3576 CAN-FD */
+static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3576 = {
+	.model = RKCANFD_MODEL_RK3576,
+};
+
 static const char *__rkcanfd_get_model_str(enum rkcanfd_model model)
 {
 	switch (model) {
@@ -57,6 +62,8 @@  static const char *__rkcanfd_get_model_str(enum rkcanfd_model model)
 		return "rk3568v2";
 	case RKCANFD_MODEL_RK3568V3:
 		return "rk3568v3";
+	case RKCANFD_MODEL_RK3576:
+		return "rk3576";
 	}
 
 	return "<unknown>";
@@ -163,10 +170,21 @@  static void rkcanfd_get_berr_counter_corrected(struct rkcanfd_priv *priv,
 					       struct can_berr_counter *bec)
 {
 	struct can_berr_counter bec_raw;
-	u32 reg_state;
+	u32 reg_state, rxerr, txerr, busoff_state, error_war_state;
 
-	bec->rxerr = rkcanfd_read(priv, RKCANFD_REG_RXERRORCNT);
-	bec->txerr = rkcanfd_read(priv, RKCANFD_REG_TXERRORCNT);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) {
+		rxerr = RK3576CANFD_REG_RXERRORCNT;
+		txerr = RK3576CANFD_REG_TXERRORCNT;
+		busoff_state = RK3576CANFD_REG_STATE_BUS_OFF_STATE;
+		error_war_state = RK3576CANFD_REG_STATE_ERROR_WARNING_STATE;
+	} else {
+		rxerr = RKCANFD_REG_RXERRORCNT;
+		txerr = RKCANFD_REG_TXERRORCNT;
+		busoff_state = RKCANFD_REG_STATE_BUS_OFF_STATE;
+		error_war_state = RKCANFD_REG_STATE_ERROR_WARNING_STATE;
+	}
+	bec->rxerr = rkcanfd_read(priv, rxerr);
+	bec->txerr = rkcanfd_read(priv, txerr);
 	bec_raw = *bec;
 
 	/* Tests show that sometimes both CAN bus error counters read
@@ -198,8 +216,8 @@  static void rkcanfd_get_berr_counter_corrected(struct rkcanfd_priv *priv,
 		    "%s: Raw/Cor: txerr=%3u/%3u rxerr=%3u/%3u Bus Off=%u Warning=%u\n",
 		    __func__,
 		    bec_raw.txerr, bec->txerr, bec_raw.rxerr, bec->rxerr,
-		    !!(reg_state & RKCANFD_REG_STATE_BUS_OFF_STATE),
-		    !!(reg_state & RKCANFD_REG_STATE_ERROR_WARNING_STATE));
+		    !!(reg_state & busoff_state),
+		    !!(reg_state & error_war_state));
 }
 
 static int rkcanfd_get_berr_counter(const struct net_device *ndev,
@@ -229,28 +247,106 @@  static void rkcanfd_chip_interrupts_enable(const struct rkcanfd_priv *priv)
 
 static void rkcanfd_chip_interrupts_disable(const struct rkcanfd_priv *priv)
 {
-	rkcanfd_write(priv, RKCANFD_REG_INT_MASK, RKCANFD_REG_INT_ALL);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		rkcanfd_write(priv, RK3576CANFD_REG_INT_MASK, RK3576CANFD_REG_INT_ALL);
+	else
+		rkcanfd_write(priv, RKCANFD_REG_INT_MASK, RKCANFD_REG_INT_ALL);
 }
 
 static void rkcanfd_chip_fifo_setup(struct rkcanfd_priv *priv)
 {
-	u32 reg;
-
-	/* TXE FIFO */
-	reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
-	reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE;
-	rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg);
-
-	/* RX FIFO */
-	reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
-	reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE;
-	rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg);
+	u32 reg, ism = 0, water = 0;
+
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) {
+		if (priv->rx_max_data > 4) {
+			ism = RK3576CANFD_DATA_CANFD_FIXED;
+			water = RK3576CANFD_ISM_WATERMASK_CANFD;
+		} else {
+			ism = RK3576CANFD_DATA_CAN_FIXED;
+			water = RK3576CANFD_ISM_WATERMASK_CAN;
+		}
 
+		/* internal sram mode */
+		rkcanfd_write(priv, RK3576CANFD_REG_STR_CTL,
+			      (ism << RK3576CANFD_ISM_SEL_SHIFT) |
+			      RK3576CANFD_STORAGE_TIMEOUT_MODE);
+		rkcanfd_write(priv, RK3576CANFD_REG_STR_WTM, water);
+	} else {
+		/* TXE FIFO */
+		reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
+		reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE;
+		rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg);
+
+		/* RX FIFO */
+		reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
+		reg |= RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_ENABLE;
+		rkcanfd_write(priv, RKCANFD_REG_RX_FIFO_CTRL, reg);
+	}
 	WRITE_ONCE(priv->tx_head, 0);
 	WRITE_ONCE(priv->tx_tail, 0);
 	netdev_reset_queue(priv->ndev);
 }
 
+static int rk3576canfd_atf_config(struct rkcanfd_priv *priv, int mode)
+{
+	u32 id[10] = {0};
+	u32 dlc = 0, dlc_over = 0;
+
+	switch (mode) {
+	case RK3576CANFD_ATF_MASK_MODE:
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF0, id[0]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF1, id[1]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF2, id[2]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF3, id[3]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF4, id[4]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM0, 0x7fff);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM1, 0x7fff);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM2, 0x7fff);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM3, 0x7fff);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM4, 0x7fff);
+		break;
+	case RK3576CANFD_ATF_LIST_MODE:
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF0, id[0]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF1, id[1]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF2, id[2]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF3, id[3]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF4, id[4]);
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM0, id[5] | (1 << 31));
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM1, id[6] | (1 << 31));
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM2, id[7] | (1 << 31));
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM3, id[8] | (1 << 31));
+		rkcanfd_write(priv, RK3576CANFD_REG_ATFM4, id[9] | (1 << 31));
+		break;
+	default:
+		rkcanfd_write(priv, RK3576CANFD_REG_ATF_CTL, 0xffff);
+		return -EINVAL;
+	}
+
+	if (dlc) {
+		if (dlc_over)
+			rkcanfd_write(priv, RK3576CANFD_REG_ATF_DLC, dlc | (1 << 4));
+		else
+			rkcanfd_write(priv, RK3576CANFD_REG_ATF_DLC, dlc | (1 << 4) | (1 << 5));
+	}
+	rkcanfd_write(priv, RK3576CANFD_REG_ATF_CTL, 0);
+
+	return 0;
+}
+
+static void rk3576canfd_init(struct rkcanfd_priv *priv)
+{
+	rkcanfd_write(priv, RK3576CANFD_REG_AUTO_RETX_CFG,
+		      RK3576CANFD_AUTO_RETX_EN | RK3576CANFD_RETX_LIMIT_EN |
+		      (RK3576CANFD_RETX_TIME_LIMIT_CNT << RK3576CANFD_RETX_TIME_LIMIT_SHIFT));
+
+	rkcanfd_write(priv, RK3576CANFD_REG_BRS_CFG, 0x7);
+
+	rkcanfd_write(priv, RK3576CANFD_REG_BUSOFFRCY_CFG,
+		      RK3576CANFD_BUSOFF_RCY_MODE_EN |
+		      RK3576CANFD_BUSOFF_RCY_CNT_FAST);
+	rkcanfd_write(priv, RK3576CANFD_REG_BUSOFF_RCY_THR, RK3576CANFD_BUSOFF_RCY_TIME_FAST);
+}
+
 static void rkcanfd_chip_start(struct rkcanfd_priv *priv)
 {
 	u32 reg;
@@ -258,8 +354,12 @@  static void rkcanfd_chip_start(struct rkcanfd_priv *priv)
 	rkcanfd_chip_set_reset_mode(priv);
 
 	/* Receiving Filter: accept all */
-	rkcanfd_write(priv, RKCANFD_REG_IDCODE, 0x0);
-	rkcanfd_write(priv, RKCANFD_REG_IDMASK, RKCANFD_REG_IDCODE_EXTENDED_FRAME_ID);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) {
+		rk3576canfd_atf_config(priv, RK3576CANFD_ATF_MASK_MODE);
+	} else {
+		rkcanfd_write(priv, RKCANFD_REG_IDCODE, 0x0);
+		rkcanfd_write(priv, RKCANFD_REG_IDMASK, RKCANFD_REG_IDCODE_EXTENDED_FRAME_ID);
+	}
 
 	/* enable:
 	 * - CAN_FD: enable CAN-FD
@@ -269,17 +369,26 @@  static void rkcanfd_chip_start(struct rkcanfd_priv *priv)
 	 * - WORK_MODE: transition from reset to working mode
 	 */
 	reg = rkcanfd_read(priv, RKCANFD_REG_MODE);
-	priv->reg_mode_default = reg |
-		RKCANFD_REG_MODE_CAN_FD_MODE_ENABLE |
-		RKCANFD_REG_MODE_AUTO_RETX_MODE |
-		RKCANFD_REG_MODE_COVER_MODE |
-		RKCANFD_REG_MODE_RXSTX_MODE |
-		RKCANFD_REG_MODE_WORK_MODE;
-
-	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
-		priv->reg_mode_default |= RKCANFD_REG_MODE_LBACK_MODE |
-			RKCANFD_REG_MODE_SILENT_MODE |
-			RKCANFD_REG_MODE_SELF_TEST;
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		priv->reg_mode_default = reg | RKCANFD_REG_MODE_WORK_MODE;
+	else
+		priv->reg_mode_default = reg |
+			RKCANFD_REG_MODE_CAN_FD_MODE_ENABLE |
+			RKCANFD_REG_MODE_AUTO_RETX_MODE |
+			RKCANFD_REG_MODE_COVER_MODE |
+			RKCANFD_REG_MODE_RXSTX_MODE |
+			RKCANFD_REG_MODE_WORK_MODE;
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+		if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) {
+			priv->reg_mode_default |= RKCANFD_REG_MODE_LBACK_MODE;
+			rkcanfd_write(priv, RK3576CANFD_REG_ERROR_MASK, RK3576CANFD_ACK_ERROR_MASK);
+		} else {
+			priv->reg_mode_default |= RKCANFD_REG_MODE_LBACK_MODE |
+				RKCANFD_REG_MODE_SILENT_MODE |
+				RKCANFD_REG_MODE_SELF_TEST;
+		}
+	}
 
 	/* mask, i.e. ignore:
 	 * - TIMESTAMP_COUNTER_OVERFLOW_INT - timestamp counter overflow interrupt
@@ -287,11 +396,14 @@  static void rkcanfd_chip_start(struct rkcanfd_priv *priv)
 	 * - OVERLOAD_INT - CAN bus overload interrupt
 	 * - TX_FINISH_INT - Transmit finish interrupt
 	 */
-	priv->reg_int_mask_default =
-		RKCANFD_REG_INT_TIMESTAMP_COUNTER_OVERFLOW_INT |
-		RKCANFD_REG_INT_TX_ARBIT_FAIL_INT |
-		RKCANFD_REG_INT_OVERLOAD_INT |
-		RKCANFD_REG_INT_TX_FINISH_INT;
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		priv->reg_int_mask_default = RK3576CANFD_REG_INT_RX_FINISH_INT;
+	else
+		priv->reg_int_mask_default =
+			RKCANFD_REG_INT_TIMESTAMP_COUNTER_OVERFLOW_INT |
+			RKCANFD_REG_INT_TX_ARBIT_FAIL_INT |
+			RKCANFD_REG_INT_OVERLOAD_INT |
+			RKCANFD_REG_INT_TX_FINISH_INT;
 
 	/* Do not mask the bus error interrupt if the bus error
 	 * reporting is requested.
@@ -302,8 +414,13 @@  static void rkcanfd_chip_start(struct rkcanfd_priv *priv)
 	memset(&priv->bec, 0x0, sizeof(priv->bec));
 
 	rkcanfd_chip_fifo_setup(priv);
-	rkcanfd_timestamp_init(priv);
-	rkcanfd_timestamp_start(priv);
+	if (priv->devtype_data.model != RKCANFD_MODEL_RK3576) {
+		rkcanfd_timestamp_init(priv);
+		rkcanfd_timestamp_start(priv);
+	}
+
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		rk3576canfd_init(priv);
 
 	rkcanfd_set_bittiming(priv);
 
@@ -328,7 +445,8 @@  static void rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_state st
 {
 	priv->can.state = state;
 
-	rkcanfd_timestamp_stop(priv);
+	if (priv->devtype_data.model != RKCANFD_MODEL_RK3576)
+		rkcanfd_timestamp_stop(priv);
 	__rkcanfd_chip_stop(priv, state);
 }
 
@@ -336,7 +454,8 @@  static void rkcanfd_chip_stop_sync(struct rkcanfd_priv *priv, const enum can_sta
 {
 	priv->can.state = state;
 
-	rkcanfd_timestamp_stop_sync(priv);
+	if (priv->devtype_data.model != RKCANFD_MODEL_RK3576)
+		rkcanfd_timestamp_stop_sync(priv);
 	__rkcanfd_chip_stop(priv, state);
 }
 
@@ -395,6 +514,9 @@  static const char *rkcanfd_get_error_type_str(unsigned int type)
 #define RKCAN_ERROR_CODE(reg_ec, code) \
 	((reg_ec) & RKCANFD_REG_ERROR_CODE_##code ? __stringify(code) " " : "")
 
+#define RK3576CAN_ERROR_CODE(reg_ec, code) \
+	((reg_ec) & RK3576CANFD_REG_ERROR_CODE_##code ? __stringify(code) " " : "")
+
 static void
 rkcanfd_handle_error_int_reg_ec(struct rkcanfd_priv *priv, struct can_frame *cf,
 				const u32 reg_ec)
@@ -524,6 +646,128 @@  rkcanfd_handle_error_int_reg_ec(struct rkcanfd_priv *priv, struct can_frame *cf,
 	}
 }
 
+static void
+rk3576canfd_handle_error_int_reg_ec(struct rkcanfd_priv *priv, struct can_frame *cf,
+				    const u32 reg_ec)
+{
+	struct net_device_stats *stats = &priv->ndev->stats;
+	unsigned int type;
+	u32 reg_state, reg_cmd;
+
+	type = FIELD_GET(RK3576CANFD_REG_ERROR_CODE_TYPE, reg_ec);
+	reg_cmd = rkcanfd_read(priv, RK3576CANFD_REG_CMD);
+	reg_state = rkcanfd_read(priv, RK3576CANFD_REG_STATE);
+
+	netdev_dbg(priv->ndev, "%s Error in %s %s Phase: %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s(0x%08x) CMD=%u RX=%u TX=%u Error-Warning=%u Bus-Off=%u\n",
+		   rkcanfd_get_error_type_str(type),
+		   reg_ec & RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX ? "RX" : "TX",
+		   reg_ec & RK3576CANFD_REG_ERROR_CODE_PHASE ? "Data" : "Arbitration",
+		   RK3576CAN_ERROR_CODE(reg_ec, TX_ACK_EOF),
+		   RK3576CAN_ERROR_CODE(reg_ec, TX_CRC),
+		   RK3576CAN_ERROR_CODE(reg_ec, TX_STUFF_COUNT),
+		   RK3576CAN_ERROR_CODE(reg_ec, TX_DATA),
+		   RK3576CAN_ERROR_CODE(reg_ec, TX_SOF_DLC),
+		   RK3576CAN_ERROR_CODE(reg_ec, TX_IDLE),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_ERROR),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_OVERLOAD),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_SPACE),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_EOF),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_ACK_LIM),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_ACK),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_CRC_LIM),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_CRC),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_STUFF_COUNT),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_DATA),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_DLC),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_BRS_ESI),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_RES),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_FDF),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_ID2_RTR),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_SOF_IDE),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_BUS_IDLE),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_BUS_INT),
+		   RK3576CAN_ERROR_CODE(reg_ec, RX_STOP),
+		   reg_ec, reg_cmd,
+		   !!(reg_state & RK3576CANFD_REG_STATE_RX_PERIOD),
+		   !!(reg_state & RK3576CANFD_REG_STATE_TX_PERIOD),
+		   !!(reg_state & RK3576CANFD_REG_STATE_ERROR_WARNING_STATE),
+		   !!(reg_state & RK3576CANFD_REG_STATE_BUS_OFF_STATE));
+
+	priv->can.can_stats.bus_error++;
+
+	if (reg_ec & RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX)
+		stats->rx_errors++;
+	else
+		stats->tx_errors++;
+
+	if (!cf)
+		return;
+
+	if (reg_ec & RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX) {
+		if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_SOF_IDE)
+			cf->data[3] = CAN_ERR_PROT_LOC_SOF;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ID2_RTR)
+			cf->data[3] = CAN_ERR_PROT_LOC_RTR;
+		/* RKCANFD_REG_ERROR_CODE_RX_FDF */
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_RES)
+			cf->data[3] = CAN_ERR_PROT_LOC_RES0;
+		/* RKCANFD_REG_ERROR_CODE_RX_BRS_ESI */
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_DLC)
+			cf->data[3] = CAN_ERR_PROT_LOC_DLC;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_DATA)
+			cf->data[3] = CAN_ERR_PROT_LOC_DATA;
+		/* RKCANFD_REG_ERROR_CODE_RX_STUFF_COUNT */
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_CRC)
+			cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_CRC_LIM)
+			cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ACK)
+			cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ACK_LIM)
+			cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_EOF)
+			cf->data[3] = CAN_ERR_PROT_LOC_EOF;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_SPACE)
+			cf->data[3] = CAN_ERR_PROT_LOC_EOF;
+	} else {
+		cf->data[2] |= CAN_ERR_PROT_TX;
+
+		if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_SOF_DLC)
+			cf->data[3] = CAN_ERR_PROT_LOC_SOF;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_DATA)
+			cf->data[3] = CAN_ERR_PROT_LOC_DATA;
+		/* RKCANFD_REG_ERROR_CODE_TX_STUFF_COUNT */
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_CRC)
+			cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+		else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_ACK_EOF)
+			cf->data[3] = CAN_ERR_PROT_LOC_ACK_DEL;
+	}
+
+	switch (reg_ec & RK3576CANFD_REG_ERROR_CODE_TYPE) {
+	case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE,
+			      RK3576CANFD_REG_ERROR_CODE_TYPE_BIT):
+
+		cf->data[2] |= CAN_ERR_PROT_BIT;
+		break;
+	case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE,
+			      RK3576CANFD_REG_ERROR_CODE_TYPE_STUFF):
+		cf->data[2] |= CAN_ERR_PROT_STUFF;
+		break;
+	case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE,
+			      RK3576CANFD_REG_ERROR_CODE_TYPE_FORM):
+		cf->data[2] |= CAN_ERR_PROT_FORM;
+		break;
+	case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE,
+			      RK3576CANFD_REG_ERROR_CODE_TYPE_ACK):
+		cf->can_id |= CAN_ERR_ACK;
+		break;
+	case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE,
+			      RK3576CANFD_REG_ERROR_CODE_TYPE_CRC):
+		cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+		break;
+	}
+}
+
 static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv)
 {
 	struct net_device_stats *stats = &priv->ndev->stats;
@@ -532,13 +776,19 @@  static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv)
 	struct sk_buff *skb;
 	int err;
 
-	reg_ec = rkcanfd_read(priv, RKCANFD_REG_ERROR_CODE);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		reg_ec = rkcanfd_read(priv, RK3576CANFD_REG_ERROR_CODE);
+	else
+		reg_ec = rkcanfd_read(priv, RKCANFD_REG_ERROR_CODE);
 
 	if (!reg_ec)
 		return 0;
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
-		skb = rkcanfd_alloc_can_err_skb(priv, &cf, &timestamp);
+		if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+			skb = alloc_can_err_skb(priv->ndev, &cf);
+		else
+			skb = rkcanfd_alloc_can_err_skb(priv, &cf, &timestamp);
 		if (cf) {
 			struct can_berr_counter bec;
 
@@ -549,12 +799,18 @@  static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv)
 		}
 	}
 
-	rkcanfd_handle_error_int_reg_ec(priv, cf, reg_ec);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		rk3576canfd_handle_error_int_reg_ec(priv, cf, reg_ec);
+	else
+		rkcanfd_handle_error_int_reg_ec(priv, cf, reg_ec);
 
 	if (!cf)
 		return 0;
 
-	err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		err = can_rx_offload_queue_tail(&priv->offload, skb);
+	else
+		err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
 	if (err)
 		stats->rx_fifo_errors++;
 
@@ -582,7 +838,10 @@  static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv)
 	/* The skb allocation might fail, but can_change_state()
 	 * handles cf == NULL.
 	 */
-	skb = rkcanfd_alloc_can_err_skb(priv, &cf, &timestamp);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		skb = alloc_can_err_skb(priv->ndev, &cf);
+	else
+		skb = rkcanfd_alloc_can_err_skb(priv, &cf, &timestamp);
 	can_change_state(ndev, cf, tx_state, rx_state);
 
 	if (new_state == CAN_STATE_BUS_OFF) {
@@ -599,7 +858,10 @@  static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv)
 		cf->data[7] = bec.rxerr;
 	}
 
-	err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		err = can_rx_offload_queue_tail(&priv->offload, skb);
+	else
+		err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
 	if (err)
 		stats->rx_fifo_errors++;
 
@@ -621,7 +883,10 @@  rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv)
 
 	netdev_dbg(priv->ndev, "RX-FIFO overflow\n");
 
-	skb = rkcanfd_alloc_can_err_skb(priv, &cf, &timestamp);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		skb = alloc_can_err_skb(priv->ndev, &cf);
+	else
+		skb = rkcanfd_alloc_can_err_skb(priv, &cf, &timestamp);
 	if (skb)
 		return 0;
 
@@ -632,7 +897,10 @@  rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv)
 	cf->data[6] = bec.txerr;
 	cf->data[7] = bec.rxerr;
 
-	err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		err = can_rx_offload_queue_tail(&priv->offload, skb);
+	else
+		err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
 	if (err)
 		stats->rx_fifo_errors++;
 
@@ -652,11 +920,58 @@  rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv)
 	err; \
 })
 
+static irqreturn_t rk3576canfd_irq(int irq, void *dev_id)
+{
+	struct rkcanfd_priv *priv = dev_id;
+	u32 reg_int_unmasked, reg_int;
+
+	reg_int_unmasked = rkcanfd_read(priv, RK3576CANFD_REG_INT);
+	reg_int = reg_int_unmasked & ~priv->reg_int_mask_default;
+
+	if (!reg_int)
+		return IRQ_NONE;
+
+	rkcanfd_write(priv, RK3576CANFD_REG_INT, reg_int);
+
+	if (reg_int & (RK3576CANFD_REG_INT_RXSTR_TIMEOUT_INT |
+		       RK3576CANFD_REG_INT_ISM_WTM_INT |
+		       RK3576CANFD_REG_INT_RX_FIFO_FULL_INT))
+		rkcanfd_handle(priv, rx_int);
+
+	if (reg_int & RK3576CANFD_REG_INT_TX_FINISH_INT)
+		rkcanfd_handle(priv, tx_int);
+
+	if (reg_int & RK3576CANFD_REG_INT_ERROR_INT)
+		rkcanfd_handle(priv, error_int);
+
+	if (reg_int & (RK3576CANFD_REG_INT_BUS_OFF_INT |
+		       RK3576CANFD_REG_INT_PASSIVE_ERROR_INT |
+		       RK3576CANFD_REG_INT_ERROR_WARNING_INT) ||
+	    priv->can.state > CAN_STATE_ERROR_ACTIVE)
+		rkcanfd_handle(priv, state_error_int);
+
+	if (reg_int & RK3576CANFD_REG_INT_WAKEUP_INT)
+		netdev_info(priv->ndev, "%s: WAKEUP_INT\n", __func__);
+
+	if (reg_int & RK3576CANFD_REG_INT_BUS_OFF_RECOVERY_INT)
+		netdev_info(priv->ndev, "%s: BUS_OFF_RECOVERY_INT\n", __func__);
+
+	if (reg_int & RK3576CANFD_REG_INT_OVERLOAD_INT)
+		netdev_info(priv->ndev, "%s: OVERLOAD_INT\n", __func__);
+
+	can_rx_offload_irq_finish(&priv->offload);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t rkcanfd_irq(int irq, void *dev_id)
 {
 	struct rkcanfd_priv *priv = dev_id;
 	u32 reg_int_unmasked, reg_int;
 
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		return rk3576canfd_irq(irq, dev_id);
+
 	reg_int_unmasked = rkcanfd_read(priv, RKCANFD_REG_INT);
 	reg_int = reg_int_unmasked & ~priv->reg_int_mask_default;
 
@@ -789,14 +1104,21 @@  static void rkcanfd_register_done(const struct rkcanfd_priv *priv)
 {
 	u32 dev_id;
 
-	dev_id = rkcanfd_read(priv, RKCANFD_REG_RTL_VERSION);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) {
+		dev_id = rkcanfd_read(priv, RK3576CANFD_REG_RTL_VERSION);
+		netdev_info(priv->ndev,
+			    "Rockchip-CANFD %s rev%u.\n",
+			    rkcanfd_get_model_str(priv), dev_id);
+	} else {
+		dev_id = rkcanfd_read(priv, RKCANFD_REG_RTL_VERSION);
 
-	netdev_info(priv->ndev,
-		    "Rockchip-CANFD %s rev%lu.%lu (errata 0x%04x) found\n",
-		    rkcanfd_get_model_str(priv),
-		    FIELD_GET(RKCANFD_REG_RTL_VERSION_MAJOR, dev_id),
-		    FIELD_GET(RKCANFD_REG_RTL_VERSION_MINOR, dev_id),
-		    priv->devtype_data.quirks);
+		netdev_info(priv->ndev,
+			    "Rockchip-CANFD %s rev%lu.%lu (errata 0x%04x) found\n",
+			    rkcanfd_get_model_str(priv),
+			    FIELD_GET(RKCANFD_REG_RTL_VERSION_MAJOR, dev_id),
+			    FIELD_GET(RKCANFD_REG_RTL_VERSION_MINOR, dev_id),
+			    priv->devtype_data.quirks);
+	}
 
 	if (priv->devtype_data.quirks & RKCANFD_QUIRK_RK3568_ERRATUM_5 &&
 	    priv->can.clock.freq < RKCANFD_ERRATUM_5_SYSCLOCK_HZ_MIN)
@@ -852,6 +1174,9 @@  static const struct of_device_id rkcanfd_of_match[] = {
 	}, {
 		.compatible = "rockchip,rk3568v3-canfd",
 		.data = &rkcanfd_devtype_data_rk3568v3,
+	},  {
+		.compatible = "rockchip,rk3576-canfd",
+		.data = &rkcanfd_devtype_data_rk3576,
 	}, {
 		/* sentinel */
 	},
@@ -863,7 +1188,7 @@  static int rkcanfd_probe(struct platform_device *pdev)
 	struct rkcanfd_priv *priv;
 	struct net_device *ndev;
 	const void *match;
-	int err;
+	int err, val;
 
 	ndev = alloc_candev(sizeof(struct rkcanfd_priv), RKCANFD_TXFIFO_DEPTH);
 	if (!ndev)
@@ -917,8 +1242,24 @@  static int rkcanfd_probe(struct platform_device *pdev)
 	if (match)
 		priv->devtype_data = *(struct rkcanfd_devtype_data *)match;
 
+	/* rx-max-data only 4 Words or 18 words are supported */
+	if (device_property_read_u32_array(&pdev->dev, "rockchip,rx-max-data", &val, 1))
+		priv->rx_max_data = 18;
+	else
+		priv->rx_max_data = val;
+
+	if (priv->rx_max_data != 4 && priv->rx_max_data != 18) {
+		priv->rx_max_data = 18;
+		dev_warn(&pdev->dev, "rx_max_data is invalid, set to 18 words!\n");
+	}
+	priv->rx_fifo_depth = RK3576CANFD_SRAM_MAX_DEPTH / priv->rx_max_data;
+
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		val = priv->rx_fifo_depth + 1;
+	else
+		val = RKCANFD_NAPI_WEIGHT;
 	err = can_rx_offload_add_manual(ndev, &priv->offload,
-					RKCANFD_NAPI_WEIGHT);
+					val);
 	if (err)
 		goto out_free_candev;
 
diff --git a/drivers/net/can/rockchip/rockchip_canfd-rx.c b/drivers/net/can/rockchip/rockchip_canfd-rx.c
index 475c0409e215..7dad674dc545 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-rx.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-rx.c
@@ -91,6 +91,47 @@  rkcanfd_fifo_header_to_cfd_header(const struct rkcanfd_priv *priv,
 	return len + cfd->len;
 }
 
+static unsigned int
+rk3576canfd_fifo_header_to_cfd_header(const struct rkcanfd_priv *priv,
+				      const struct rk3576canfd_fifo_header *header,
+				      struct canfd_frame *cfd)
+{
+	unsigned int len = sizeof(*cfd) - sizeof(cfd->data);
+	u8 dlc;
+
+	if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FRAME_FORMAT)
+		cfd->can_id = FIELD_GET(RKCANFD_REG_FD_ID_EFF, header->id) |
+			CAN_EFF_FLAG;
+	else
+		cfd->can_id = FIELD_GET(RKCANFD_REG_FD_ID_SFF, header->id);
+
+	dlc = FIELD_GET(RK3576CANFD_REG_RXFRD_FRAMEINFO_DATA_LENGTH,
+			header->frameinfo);
+
+	/* CAN-FD */
+	if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FDF) {
+		cfd->len = can_fd_dlc2len(dlc);
+
+		/* The cfd is not allocated by alloc_canfd_skb(), so
+		 * set CANFD_FDF here.
+		 */
+		cfd->flags |= CANFD_FDF;
+
+		if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_BRS)
+			cfd->flags |= CANFD_BRS;
+	} else {
+		cfd->len = can_cc_dlc2len(dlc);
+
+		if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_RTR) {
+			cfd->can_id |= CAN_RTR_FLAG;
+
+			return len;
+		}
+	}
+
+	return len + cfd->len;
+}
+
 static int rkcanfd_rxstx_filter(struct rkcanfd_priv *priv,
 				const struct canfd_frame *cfd_rx, const u32 ts,
 				bool *tx_done)
@@ -198,6 +239,62 @@  rkcanfd_fifo_header_empty(const struct rkcanfd_fifo_header *header)
 		header->frameinfo == header->ts;
 }
 
+static int rk3576canfd_handle_rx_int_one(struct rkcanfd_priv *priv)
+{
+	struct net_device_stats *stats = &priv->ndev->stats;
+	struct canfd_frame cfd[1] = { }, *skb_cfd;
+	struct rk3576canfd_fifo_header header[1] = { };
+	struct sk_buff *skb;
+	unsigned int len;
+	int err;
+
+	/* read header into separate struct and convert it later */
+	rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA,
+			 header, sizeof(*header));
+	/* read data directly into cfd */
+	rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA,
+			 cfd->data, (priv->rx_max_data - 2) * 4);
+
+	len = rk3576canfd_fifo_header_to_cfd_header(priv, header, cfd);
+
+	/* Drop any received CAN-FD frames if CAN-FD mode is not
+	 * requested.
+	 */
+	if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FDF &&
+	    !(priv->can.ctrlmode & CAN_CTRLMODE_FD)) {
+		stats->rx_dropped++;
+
+		return 0;
+	}
+
+	/* Manual handling of CAN Bus Error counters. See
+	 * rkcanfd_get_corrected_berr_counter() for detailed
+	 * explanation.
+	 */
+	if (priv->bec.rxerr)
+		priv->bec.rxerr = min(CAN_ERROR_PASSIVE_THRESHOLD,
+				      priv->bec.rxerr) - 1;
+
+	if (header->frameinfo & RKCANFD_REG_FD_FRAMEINFO_FDF)
+		skb = alloc_canfd_skb(priv->ndev, &skb_cfd);
+	else
+		skb = alloc_can_skb(priv->ndev, (struct can_frame **)&skb_cfd);
+
+	if (!skb) {
+		stats->rx_dropped++;
+
+		return 0;
+	}
+
+	memcpy(skb_cfd, cfd, len);
+
+	err = can_rx_offload_queue_tail(&priv->offload, skb);
+	if (err)
+		stats->rx_fifo_errors++;
+
+	return 0;
+}
+
 static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv)
 {
 	struct net_device_stats *stats = &priv->ndev->stats;
@@ -207,6 +304,9 @@  static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv)
 	unsigned int len;
 	int err;
 
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576)
+		return rk3576canfd_handle_rx_int_one(priv);
+
 	/* read header into separate struct and convert it later */
 	rkcanfd_read_rep(priv, RKCANFD_REG_RX_FIFO_RDATA,
 			 header, sizeof(*header));
@@ -279,9 +379,16 @@  static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv)
 static inline unsigned int
 rkcanfd_rx_fifo_get_len(const struct rkcanfd_priv *priv)
 {
-	const u32 reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
+	u32 reg, len;
 
-	return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg);
+	if (priv->devtype_data.model == RKCANFD_MODEL_RK3576) {
+		reg = rkcanfd_read(priv, RK3576CANFD_REG_STR_STATE);
+		len = FIELD_GET(RK3576CANFD_REG_INTM_FRAME_CNT, reg);
+	} else {
+		reg = rkcanfd_read(priv, RKCANFD_REG_RX_FIFO_CTRL);
+		len = FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg);
+	}
+	return len;
 }
 
 int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv)
diff --git a/drivers/net/can/rockchip/rockchip_canfd-tx.c b/drivers/net/can/rockchip/rockchip_canfd-tx.c
index 865a15e033a9..e00f3447928f 100644
--- a/drivers/net/can/rockchip/rockchip_canfd-tx.c
+++ b/drivers/net/can/rockchip/rockchip_canfd-tx.c
@@ -165,3 +165,32 @@  void rkcanfd_handle_tx_done_one(struct rkcanfd_priv *priv, const u32 ts,
 							    frame_len_p);
 	stats->tx_packets++;
 }
+
+int rkcanfd_handle_tx_int(struct rkcanfd_priv *priv)
+{
+	struct net_device_stats *stats = &priv->ndev->stats;
+	unsigned int tx_tail;
+	struct sk_buff *skb;
+	unsigned int frame_len = 0;
+
+	tx_tail = rkcanfd_get_tx_tail(priv);
+	skb = priv->can.echo_skb[tx_tail];
+
+	/* Manual handling of CAN Bus Error counters. See
+	 * rkcanfd_get_corrected_berr_counter() for detailed
+	 * explanation.
+	 */
+	if (priv->bec.txerr)
+		priv->bec.txerr--;
+
+	stats->tx_bytes +=
+		can_rx_offload_get_echo_skb_queue_tail(&priv->offload,
+						       tx_tail, &frame_len);
+	stats->tx_packets++;
+	WRITE_ONCE(priv->tx_tail, priv->tx_tail + 1);
+	netif_subqueue_completed_wake(priv->ndev, 0, 1, frame_len,
+				      rkcanfd_get_effective_tx_free(priv),
+				      RKCANFD_TX_START_THRESHOLD);
+	return 0;
+}
+
diff --git a/drivers/net/can/rockchip/rockchip_canfd.h b/drivers/net/can/rockchip/rockchip_canfd.h
index 93131c7d7f54..17f099ee08cf 100644
--- a/drivers/net/can/rockchip/rockchip_canfd.h
+++ b/drivers/net/can/rockchip/rockchip_canfd.h
@@ -287,6 +287,282 @@ 
 #define RKCANFD_REG_RX_FIFO_RDATA 0x400
 #define RKCANFD_REG_TXE_FIFO_RDATA 0x500
 
+#define RK3576CANFD_REG_MODE 0x000
+#define RK3576CANFD_REG_CMD 0x004
+
+#define RK3576CANFD_REG_STATE 0x008
+#define RK3576CANFD_REG_STATE_SLEEP_STATE BIT(5)
+#define RK3576CANFD_REG_STATE_BUS_OFF_STATE BIT(4)
+#define RK3576CANFD_REG_STATE_ERROR_WARNING_STATE BIT(3)
+#define RK3576CANFD_REG_STATE_TX_PERIOD BIT(2)
+#define RK3576CANFD_REG_STATE_RX_PERIOD BIT(1)
+#define RK3576CANFD_REG_STATE_TX_BUFFER_FULL BIT(0)
+
+#define RK3576CANFD_REG_INT 0x00c
+#define RK3576CANFD_REG_INT_BUSOFF_RCY_INT BIT(19)
+#define RK3576CANFD_REG_INT_ESM_WTM_INT BIT(18)
+#define RK3576CANFD_REG_INT_ISM_WTM_INT BIT(17)
+#define RK3576CANFD_REG_INT_BUSINT_INT BIT(16)
+#define RK3576CANFD_REG_INT_RXSTR_TIMEOUT_INT BIT(15)
+#define RK3576CANFD_REG_INT_MFI_TIMEOUT_INT BIT(14)
+#define RK3576CANFD_REG_INT_MFI_INT BIT(13)
+#define RK3576CANFD_REG_INT_AUTO_RETX_FAIL_INT BIT(12)
+#define RK3576CANFD_REG_INT_WAKEUP_INT BIT(11)
+#define RK3576CANFD_REG_INT_BUS_OFF_RECOVERY_INT BIT(10)
+#define RK3576CANFD_REG_INT_BUS_OFF_INT BIT(9)
+#define RK3576CANFD_REG_INT_RX_FIFO_OVERFLOW_INT BIT(8)
+#define RK3576CANFD_REG_INT_RX_FIFO_FULL_INT BIT(7)
+#define RK3576CANFD_REG_INT_ERROR_INT BIT(6)
+#define RK3576CANFD_REG_INT_TX_ARBIT_FAIL_INT BIT(5)
+#define RK3576CANFD_REG_INT_PASSIVE_ERROR_INT BIT(4)
+#define RK3576CANFD_REG_INT_OVERLOAD_INT BIT(3)
+#define RK3576CANFD_REG_INT_ERROR_WARNING_INT BIT(2)
+#define RK3576CANFD_REG_INT_TX_FINISH_INT BIT(1)
+#define RK3576CANFD_REG_INT_RX_FINISH_INT BIT(0)
+
+#define RK3576CANFD_REG_INT_ALL \
+	(RK3576CANFD_REG_INT_BUSOFF_RCY_INT | \
+	 RK3576CANFD_REG_INT_ESM_WTM_INT | \
+	 RK3576CANFD_REG_INT_ISM_WTM_INT | \
+	 RK3576CANFD_REG_INT_BUSINT_INT | \
+	 RK3576CANFD_REG_INT_RXSTR_TIMEOUT_INT | \
+	 RK3576CANFD_REG_INT_MFI_TIMEOUT_INT | \
+	 RK3576CANFD_REG_INT_MFI_INT | \
+	 RK3576CANFD_REG_INT_AUTO_RETX_FAIL_INT | \
+	 RK3576CANFD_REG_INT_WAKEUP_INT | \
+	 RK3576CANFD_REG_INT_BUS_OFF_RECOVERY_INT | \
+	 RK3576CANFD_REG_INT_BUS_OFF_INT | \
+	 RK3576CANFD_REG_INT_RX_FIFO_OVERFLOW_INT | \
+	 RK3576CANFD_REG_INT_RX_FIFO_FULL_INT | \
+	 RK3576CANFD_REG_INT_ERROR_INT | \
+	 RK3576CANFD_REG_INT_TX_ARBIT_FAIL_INT | \
+	 RK3576CANFD_REG_INT_PASSIVE_ERROR_INT | \
+	 RK3576CANFD_REG_INT_OVERLOAD_INT | \
+	 RK3576CANFD_REG_INT_ERROR_WARNING_INT | \
+	 RK3576CANFD_REG_INT_TX_FINISH_INT | \
+	 RK3576CANFD_REG_INT_RX_FINISH_INT)
+
+#define RK3576CANFD_REG_INT_ALL_ERROR \
+	(RK3576CANFD_REG_INT_BUS_OFF_INT | \
+	 RK3576CANFD_REG_INT_ERROR_INT | \
+	 RK3576CANFD_REG_INT_PASSIVE_ERROR_INT | \
+	 RK3576CANFD_REG_INT_ERROR_WARNING_INT)
+
+#define RK3576CANFD_REG_INT_MASK 0x010
+
+#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING 0x100
+#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_SAMPLE_MODE BIT(31)
+#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_SJW GENMASK(30, 24)
+#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_BRP GENMASK(23, 16)
+#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_TSEG2 GENMASK(14, 8)
+#define RK3576CANFD_REG_FD_NOMINAL_BITTIMING_TSEG1 GENMASK(7, 0)
+
+#define RK3576CANFD_REG_FD_DATA_BITTIMING 0x104
+#define RK3576CANFD_REG_FD_DATA_BITTIMING_BRS_TSEG1 GENMASK(31, 24)
+#define RK3576CANFD_REG_FD_DATA_BITTIMING_BRS_MODE BIT(23)
+#define RK3576CANFD_REG_FD_DATA_BITTIMING_ACKSLOT_SYNC_DIS BIT(22)
+#define RK3576CANFD_REG_FD_DATA_BITTIMING_SJW GENMASK(20, 17)
+#define RK3576CANFD_REG_FD_DATA_BITTIMING_BRP GENMASK(16, 9)
+#define RK3576CANFD_REG_FD_DATA_BITTIMING_TSEG2 GENMASK(8, 5)
+#define RK3576CANFD_REG_FD_DATA_BITTIMING_TSEG1 GENMASK(4, 0)
+
+#define RK3576CANFD_REG_TRANSMIT_DELAY_COMPENSATION 0x108
+#define RK3576CANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_OFFSET GENMASK(6, 1)
+#define RK3576CANFD_REG_TRANSMIT_DELAY_COMPENSATION_TDC_ENABLE BIT(0)
+
+#define RK3576CANFD_REG_BRS_CFG 0x10c
+#define RK3576CANFD_REG_BRS_CFG_TRIPLE_SYNC_MODE BIT(31)
+#define RK3576CANFD_REG_BRS_CFG_SP2_DTSEG1 GENMASK(30, 26)
+#define RK3576CANFD_REG_BRS_CFG_SP2_NTSEG1 GENMASK(25, 18)
+#define RK3576CANFD_REG_BRS_CFG_SP1_DTSEG1 GENMASK(17, 13)
+#define RK3576CANFD_REG_BRS_CFG_SP1_NTSEG1 GENMASK(12, 5)
+#define RK3576CANFD_REG_BRS_CFG_RESYNC_MODE BIT(3)
+#define RK3576CANFD_REG_BRS_CFG_BRS_POSSYNC_EN BIT(1)
+#define RK3576CANFD_REG_BRS_CFG_BRS_NEGSYNC_EN BIT(0)
+
+#define RK3576CANFD_REG_LOOP_CNT 0x110
+
+#define RK3576CANFD_REG_DMA_CTRL 0x11c
+#define RK3576CANFD_REG_DMA_CTRL_DMA_RX_EN BIT(9)
+#define RK3576CANFD_REG_DMA_CTRL_DMA_THR GENMASK(8, 0)
+
+#define RK3576CANFD_REG_FD_TXFRAMEINFO 0x200
+
+#define RK3576CANFD_REG_FD_TXID 0x204
+#define RK3576CANFD_REG_FD_ID_EFF GENMASK(28, 0)
+#define RK3576CANFD_REG_FD_ID_SFF GENMASK(11, 0)
+
+#define RK3576CANFD_REG_FD_TXDATA0 0x208
+#define RK3576CANFD_REG_FD_TXDATA1 0x20c
+#define RK3576CANFD_REG_FD_TXDATA2 0x210
+#define RK3576CANFD_REG_FD_TXDATA3 0x214
+#define RK3576CANFD_REG_FD_TXDATA4 0x218
+#define RK3576CANFD_REG_FD_TXDATA5 0x21c
+#define RK3576CANFD_REG_FD_TXDATA6 0x220
+#define RK3576CANFD_REG_FD_TXDATA7 0x224
+#define RK3576CANFD_REG_FD_TXDATA8 0x228
+#define RK3576CANFD_REG_FD_TXDATA9 0x22c
+#define RK3576CANFD_REG_FD_TXDATA10 0x230
+#define RK3576CANFD_REG_FD_TXDATA11 0x234
+#define RK3576CANFD_REG_FD_TXDATA12 0x238
+#define RK3576CANFD_REG_FD_TXDATA13 0x23c
+#define RK3576CANFD_REG_FD_TXDATA14 0x240
+#define RK3576CANFD_REG_FD_TXDATA15 0x244
+
+#define RK3576CANFD_REG_RXFRD 0x400
+#define RK3576CANFD_REG_RXFRD_FRAMEINFO_FRAME_FORMAT BIT(23)
+#define RK3576CANFD_REG_RXFRD_FRAMEINFO_RTR BIT(22)
+#define RK3576CANFD_REG_RXFRD_FRAMEINFO_FDF BIT(21)
+#define RK3576CANFD_REG_RXFRD_FRAMEINFO_BRS BIT(20)
+#define RK3576CANFD_REG_RXFRD_FRAMEINFO_DATA_LENGTH GENMASK(27, 24)
+
+#define RK3576CANFD_REG_STR_CTL 0x600
+#define RK3576CANFD_REG_STR_STATE 0x604
+#define RK3576CANFD_REG_INTM_FRAME_CNT GENMASK(25, 17)
+
+#define RK3576CANFD_REG_STR_TIMEOUT 0x608
+
+#define RK3576CANFD_BUFFER_MODE_ENABLE BIT(0)
+#define RK3576CANFD_EXT_STORAGE_MODE BIT(1)
+#define RK3576CANFD_ISM_SEL_SHIFT 2
+#define RK3576CANFD_ISM_SEL_MASK (0x3 << RK3576CANFD_ISM_SEL_SHIFT)
+#define RK3576CANFD_RX_STORAGE_RESET BIT(4)
+#define RK3576CANFD_ESM_SEL_SHIFT 6
+#define RK3576CANFD_ESM_SEL_MASK (0x3 << RK3576CANFD_ESM_SEL_SHIFT)
+#define RK3576CANFD_STORAGE_TIMEOUT_MODE BIT(8)
+
+#define RK3576CANFD_INTM_CNT_SHIFT 17
+#define RK3576CANFD_INTM_CNT_MASK (0x1ff << RK3576CANFD_INTM_CNT_SHIFT)
+#define RK3576CANFD_INTM_LEFT_CNT_SHIFT 8
+#define RK3576CANFD_INTM_LEFT_CNT_MASK (0x1ff << RK3576CANFD_INTM_LEFT_CNT_SHIFT)
+#define RK3576CANFD_EXTM_FULL BIT(3)
+#define RK3576CANFD_EXTM_EMPTY BIT(2)
+#define RK3576CANFD_INTM_FULL BIT(1)
+#define RK3576CANFD_INTM_EMPTY BIT(0)
+
+#define RK3576CANFD_REG_STR_WTM 0x60c
+#define RK3576CANFD_REG_ATF0 0x700
+#define RK3576CANFD_REG_ATF1 0x704
+#define RK3576CANFD_REG_ATF2 0x708
+#define RK3576CANFD_REG_ATF3 0x70c
+#define RK3576CANFD_REG_ATF4 0x710
+#define RK3576CANFD_REG_ATFM0 0x714
+#define RK3576CANFD_REG_ATFM1 0x718
+#define RK3576CANFD_REG_ATFM2 0x71c
+#define RK3576CANFD_REG_ATFM3 0x720
+#define RK3576CANFD_REG_ATFM4 0x724
+#define RK3576CANFD_REG_ATF_DLC 0x728
+#define RK3576CANFD_REG_ATF_CTL 0x72c
+#define RK3576CANFD_ATF_MASK BIT(31)
+#define RK3576CANFD_ATF_RTR_EN BIT(30)
+#define RK3576CANFD_ATF_RTR BIT(29)
+#define RK3576CANFD_ATF_DLC_MODE BIT(5)
+#define RK3576CANFD_ATF_DLC_EN BIT(4)
+#define RK3576CANFD_ATF_DLC_SHIFT 0
+#define RK3576CANFD_ATF_DLC_MASK (0xf << RK3576CANFD_ATF_DLC_SHIFT)
+#define RK3576CANFD_ATF_DIS(n) BIT(n)
+
+#define RK3576CANFD_REG_SPACE_CTRL 0x800
+
+#define RK3576CANFD_REG_AUTO_RETX_CFG 0x808
+#define RK3576CANFD_RETX_TIME_LIMIT_CNT 0x12c /* 300 */
+#define RK3576CANFD_RETX_TIME_LIMIT_SHIFT 3
+#define RK3576CANFD_RETX_LIMIT_EN BIT(1)
+#define RK3576CANFD_AUTO_RETX_EN BIT(0)
+
+#define RK3576CANFD_REG_AUTO_RETX_STATE0 0x80c
+#define RK3576CANFD_REG_AUTO_RETX_STATE1 0x810
+#define RK3576CANFD_REG_OLF_CFG 0x814
+#define RK3576CANFD_REG_RXINT_CTRL 0x818
+#define RK3576CANFD_REG_RXINT_TIMEOUT 0x81c
+#define RK3576CANFD_REG_OTHER_CFG 0x820
+#define RK3576CANFD_REG_WAVE_FILTER_CFG 0x824
+#define RK3576CANFD_REG_RBC_CFG 0x828
+#define RK3576CANFD_REG_TXCRC_CFG 0x82c
+
+#define RK3576CANFD_REG_BUSOFFRCY_CFG 0x830
+#define RK3576CANFD_REG_BUSOFF_RCY_THR 0x834
+#define RK3576CANFD_BUSOFF_RCY_MODE_EN BIT(8)
+#define RK3576CANFD_BUSOFF_RCY_TIME_CLR BIT(9)
+#define RK3576CANFD_BUSOFF_RCY_CNT_FAST 4
+#define RK3576CANFD_BUSOFF_RCY_CNT_SLOW 5
+#define RK3576CANFD_BUSOFF_RCY_TIME_FAST 0x3d0900 /* 40ms : cnt * (1 / can_clk) */
+#define RK3576CANFD_BUSOFF_RCY_TIME_SLOW 0x1312d00 /* 200ms : cnt * (1 / can_clk) */
+
+#define RK3576CANFD_REG_ERROR_CODE 0x900
+#define RK3576CANFD_REG_ERROR_MASK 0x904
+#define RK3576CANFD_ACK_ERROR_MASK BIT(4)
+#define RK3576CANFD_FORM_ERROR_MASK BIT(3)
+#define RK3576CANFD_CRC_ERROR_MASK BIT(2)
+#define RK3576CANFD_STUFF_ERROR_MASK BIT(1)
+#define RK3576CANFD_BIT_ERROR_MASK BIT(0)
+
+#define RK3576CANFD_REG_RXERRORCNT 0x910
+#define RK3576CANFD_REG_TXERRORCNT 0x914
+#define RK3576CANFD_REG_RX_RXSRAM_RDATA 0xc00
+#define RK3576CANFD_REG_RTL_VERSION 0xf0c
+
+#define RK3576CANFD_REG_ERROR_CODE_PHASE BIT(29)
+#define RK3576CANFD_REG_ERROR_CODE_TYPE GENMASK(28, 26)
+#define RK3576CANFD_REG_ERROR_CODE_TYPE_BIT 0x0
+#define RK3576CANFD_REG_ERROR_CODE_TYPE_STUFF 0x1
+#define RK3576CANFD_REG_ERROR_CODE_TYPE_FORM 0x2
+#define RK3576CANFD_REG_ERROR_CODE_TYPE_ACK 0x3
+#define RK3576CANFD_REG_ERROR_CODE_TYPE_CRC 0x4
+#define RK3576CANFD_REG_ERROR_CODE_DIRECTION_RX BIT(25)
+#define RK3576CANFD_REG_ERROR_CODE_TX GENMASK(24, 19)
+#define RK3576CANFD_REG_ERROR_CODE_TX_ACK_EOF BIT(24)
+#define RK3576CANFD_REG_ERROR_CODE_TX_CRC BIT(23)
+#define RK3576CANFD_REG_ERROR_CODE_TX_STUFF_COUNT BIT(22)
+#define RK3576CANFD_REG_ERROR_CODE_TX_DATA BIT(21)
+#define RK3576CANFD_REG_ERROR_CODE_TX_SOF_DLC BIT(20)
+#define RK3576CANFD_REG_ERROR_CODE_TX_IDLE BIT(19)
+#define RK3576CANFD_REG_ERROR_CODE_RX GENMASK(18, 0)
+#define RK3576CANFD_REG_ERROR_CODE_RX_ERROR BIT(18)
+#define RK3576CANFD_REG_ERROR_CODE_RX_OVERLOAD BIT(17)
+#define RK3576CANFD_REG_ERROR_CODE_RX_SPACE BIT(16)
+#define RK3576CANFD_REG_ERROR_CODE_RX_EOF BIT(15)
+#define RK3576CANFD_REG_ERROR_CODE_RX_ACK_LIM BIT(14)
+#define RK3576CANFD_REG_ERROR_CODE_RX_ACK BIT(13)
+#define RK3576CANFD_REG_ERROR_CODE_RX_CRC_LIM BIT(12)
+#define RK3576CANFD_REG_ERROR_CODE_RX_CRC BIT(11)
+#define RK3576CANFD_REG_ERROR_CODE_RX_STUFF_COUNT BIT(10)
+#define RK3576CANFD_REG_ERROR_CODE_RX_DATA BIT(9)
+#define RK3576CANFD_REG_ERROR_CODE_RX_DLC BIT(8)
+#define RK3576CANFD_REG_ERROR_CODE_RX_BRS_ESI BIT(7)
+#define RK3576CANFD_REG_ERROR_CODE_RX_RES BIT(6)
+#define RK3576CANFD_REG_ERROR_CODE_RX_FDF BIT(5)
+#define RK3576CANFD_REG_ERROR_CODE_RX_ID2_RTR BIT(4)
+#define RK3576CANFD_REG_ERROR_CODE_RX_SOF_IDE BIT(3)
+#define RK3576CANFD_REG_ERROR_CODE_RX_BUS_IDLE BIT(2)
+#define RK3576CANFD_REG_ERROR_CODE_RX_BUS_INT BIT(1)
+#define RK3576CANFD_REG_ERROR_CODE_RX_STOP BIT(0)
+
+#define RK3576CANFD_ISM_WATERMASK_CAN 0x6c /* word */
+#define RK3576CANFD_ISM_WATERMASK_CANFD 0x6c /* word */
+#define RK3576CANFD_ESM_WATERMASK (0x50 << 8) /* word */
+
+#define RK3576CANFD_SRAM_MAX_DEPTH 256 /* word */
+#define RK3576CANFD_EXT_MEM_SIZE 0x2000 /* 8KByte */
+
+#define RK3576CANFD_CANFD_FILTER_MASK 0x1fffffff
+
+#define RK3576CANFD_CANFD_FIFO_CNT_MASK 0xff
+
+#define RK3576CANFD_CANBUSOFF_RCY_SLOW 200 /* ms */
+#define RK3576CANFD_CANBUSOFF_RCY_FAST 30 /* ms */
+
+enum rk3576canfd_atf_mode {
+	RK3576CANFD_ATF_MASK_MODE = 0,
+	RK3576CANFD_ATF_LIST_MODE,
+};
+
+enum rk3576canfd_storage_mode {
+	RK3576CANFD_DATA_FLEXIBLE = 0,
+	RK3576CANFD_DATA_CAN_FIXED,
+	RK3576CANFD_DATA_CANFD_FIXED,
+};
+
 #define DEVICE_NAME "rockchip_canfd"
 #define RKCANFD_NAPI_WEIGHT 32
 #define RKCANFD_TXFIFO_DEPTH 2
@@ -434,6 +710,7 @@ 
 enum rkcanfd_model {
 	RKCANFD_MODEL_RK3568V2 = 0x35682,
 	RKCANFD_MODEL_RK3568V3 = 0x35683,
+	RKCANFD_MODEL_RK3576 = 0x3576,
 };
 
 struct rkcanfd_devtype_data {
@@ -447,6 +724,11 @@  struct rkcanfd_fifo_header {
 	u32 ts;
 };
 
+struct rk3576canfd_fifo_header {
+	u32 frameinfo;
+	u32 id;
+};
+
 struct rkcanfd_stats {
 	struct u64_stats_sync syncp;
 
@@ -482,6 +764,8 @@  struct rkcanfd_priv {
 	struct reset_control *reset;
 	struct clk_bulk_data *clks;
 	int clks_num;
+	int rx_fifo_depth;
+	int rx_max_data;
 };
 
 static inline u32
@@ -536,6 +820,7 @@  rkcanfd_get_tx_free(const struct rkcanfd_priv *priv)
 void rkcanfd_ethtool_init(struct rkcanfd_priv *priv);
 
 int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv);
+int rkcanfd_handle_tx_int(struct rkcanfd_priv *priv);
 
 void rkcanfd_skb_set_timestamp(const struct rkcanfd_priv *priv,
 			       struct sk_buff *skb, const u32 timestamp);