From nobody Sun Dec 14 12:17:30 2025 Received: from mail-m49236.qiye.163.com (mail-m49236.qiye.163.com [45.254.49.236]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC4D9286D45; Fri, 23 May 2025 08:09:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.254.49.236 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747987790; cv=none; b=AOeum++Lc5AOUy63uUznT44FRw1Af9xa7h5PSe0IpT5RfO5acdjiM8pFbRWPC50cdQnf8lYh9Q5TphFFb+Kq5eLssSkONLaLi76nQQf1x9gWulzcDHVGVh+BNbJ8NSBanh1tPDmDLSAwHUsfuqVI9NiKrGzEC6g3Px/s6zA4vsA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747987790; c=relaxed/simple; bh=RThPFsAaD2E0xzlCf7d/TjbxGHfXhIj29Z6UO+WQm2Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=r8yeRa5EAyr0egZyVIr7DEojIQVQGxVJCSAJH9mFSTcVCddBjQ1RrDprf3w1nePYPRHm6AzslWX1B5bIY3Ffk/lAgIoBL+eiTG1iINE2YYIRfOXXJttWxKEIuU5L92589yNnf89MlJbWHpz1cNztLw8M5lGJHwG3zqb+lMaLUhQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com; spf=pass smtp.mailfrom=rock-chips.com; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b=fhxsDPqD; arc=none smtp.client-ip=45.254.49.236 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b="fhxsDPqD" Received: from rockchip.. (unknown [58.22.7.114]) by smtp.qiye.163.com (Hmail) with ESMTP id 1628045cb; Fri, 23 May 2025 15:54:25 +0800 (GMT+08:00) From: Elaine Zhang To: zhangqing@rock-chips.com, mkl@pengutronix.de, kernel@pengutronix.de, mailhol.vincent@wanadoo.fr, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de, cl@rock-chips.com, kever.yang@rock-chips.com Cc: linux-can@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v5 1/4] dt-bindings: can: rockchip_canfd: add rk3576 CAN-FD controller Date: Fri, 23 May 2025 15:54:19 +0800 Message-Id: <20250523075422.4010083-2-zhangqing@rock-chips.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250523075422.4010083-1-zhangqing@rock-chips.com> References: <20250523075422.4010083-1-zhangqing@rock-chips.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFDSUNOT01LS0k3V1ktWUFJV1kPCRoVCBIfWUFZGR5NSlZKSEhJTB1CQx5CSUNWFRQJFh oXVRMBExYaEhckFA4PWVdZGBILWUFZTkNVSUlVTFVKSk9ZV1kWGg8SFR0UWUFZT0tIVUpLSU9PT0 hVSktLVUpCS0tZBg++ X-HM-Tid: 0a96fc22df3003a3kunm893a9d4d11dad6 X-HM-MType: 1 X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6OiI6Nio6OjE3KhUVEh9LDihC TQ5PC05VSlVKTE9MQkNNQ01MTUhPVTMWGhIXVQETGhUcChIVHDsJFBgQVhgTEgsIVRgUFkVZV1kS C1lBWU5DVUlJVUxVSkpPWVdZCAFZQUlOSUI3Bg++ DKIM-Signature: a=rsa-sha256; b=fhxsDPqDmyusPeEvA2QgLAU3lNNOfwIHpFA2l7M3CowNzau62ci9E+z4ZnE3Y4eYvC/9uvHXk8vDS12xFTP3R9ggakF8GPpARpsTj57ID/eTRZ+bdU+oZu7u7zj3yuJvgF35fzpe97vQBeotN4bEaMhMUDncd0eNnm121v008D0=; s=default; c=relaxed/relaxed; d=rock-chips.com; v=1; bh=+khz/o7a5PPghtgkY2ZXtUUFn068QElniJYEgmUtOrI=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" Add documentation for the rockchip rk3576 CAN-FD controller. Signed-off-by: Elaine Zhang --- .../net/can/rockchip,rk3568v2-canfd.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-ca= nfd.yaml b/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canf= d.yaml index a077c0330013..e5dfce382061 100644 --- a/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml +++ b/Documentation/devicetree/bindings/net/can/rockchip,rk3568v2-canfd.yaml @@ -17,6 +17,7 @@ properties: compatible: oneOf: - const: rockchip,rk3568v2-canfd + - const: rockchip,rk3576-canfd - items: - const: rockchip,rk3568v3-canfd - const: rockchip,rk3568v2-canfd @@ -43,6 +44,13 @@ properties: - const: core - const: apb =20 + dmas: + maxItems: 1 + + dma-names: + items: + - const: rx + required: - compatible - reg @@ -72,3 +80,19 @@ examples: reset-names =3D "core", "apb"; }; }; + + - | + soc { + #address-cells =3D <2>; + #size-cells =3D <2>; + + can@2ac00000 { + compatible =3D "rockchip,rk3576-canfd"; + reg =3D <0x0 0x2ac00000 0x0 0x1000>; + interrupts =3D ; + clocks =3D <&cru CLK_CAN0>, <&cru PCLK_CAN0>; + clock-names =3D "baud", "pclk"; + resets =3D <&cru SRST_CAN0>, <&cru SRST_P_CAN0>; + reset-names =3D "core", "apb"; + }; + }; --=20 2.34.1 From nobody Sun Dec 14 12:17:30 2025 Received: from mail-m3284.qiye.163.com (mail-m3284.qiye.163.com [220.197.32.84]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C13B8289378; Fri, 23 May 2025 08:30:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.32.84 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747989006; cv=none; b=uy4HJunFIEqdJZHS6AmWcv2GDgZ7l0E4gD1WLG7tI26CrFJ97dY1E0+W6LDCXLsX5eQvaY8v+AaMKZNit4baPaPsTauAk8bDWvb2QHgINHB5Q7o2sMF7ToHBpZH4/sHv1vRXEvSEcey8dkC+46EUOXiCPBpTnR/xFS79/Jqq8jY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747989006; c=relaxed/simple; bh=kj4jQlmqB1SZpnxitsIoaoVGfaX/o7pbVlB28NgZzoI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gSyVg5wV+q5qT/9ccQDXStLvIBJomzfNwT5EH03s05/GfGGf7j47TCdFB7VjXDz0Ozd6EFJ3FVFTFbi9DS6mFjliDoybYmVID+h3/r1zf0fjWuJnqaYTgneEmHcP8AauKsRUMPujA4+/PezwbcXYDYNM/C2QbDbBEZZvDyrOrdg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com; spf=pass smtp.mailfrom=rock-chips.com; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b=iyt+1rSD; arc=none smtp.client-ip=220.197.32.84 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b="iyt+1rSD" Received: from rockchip.. (unknown [58.22.7.114]) by smtp.qiye.163.com (Hmail) with ESMTP id 1628045d4; Fri, 23 May 2025 15:54:27 +0800 (GMT+08:00) From: Elaine Zhang To: zhangqing@rock-chips.com, mkl@pengutronix.de, kernel@pengutronix.de, mailhol.vincent@wanadoo.fr, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de, cl@rock-chips.com, kever.yang@rock-chips.com Cc: linux-can@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v5 2/4] net: can: rockchip: Refactor the rkcanfd_devtype_data structure Date: Fri, 23 May 2025 15:54:20 +0800 Message-Id: <20250523075422.4010083-3-zhangqing@rock-chips.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250523075422.4010083-1-zhangqing@rock-chips.com> References: <20250523075422.4010083-1-zhangqing@rock-chips.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFDSUNOT01LS0k3V1ktWUFJV1kPCRoVCBIfWUFZGRodTlYYSUJLTkhKTElNHRhWFRQJFh oXVRMBExYaEhckFA4PWVdZGBILWUFZTkNVSUlVTFVKSk9ZV1kWGg8SFR0UWUFZT0tIVUpLSU9PT0 hVSktLVUpCS0tZBg++ X-HM-Tid: 0a96fc22e5fd03a3kunm893a9d4d11db07 X-HM-MType: 1 X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6MVE6OBw4PzEyEBU2KBc8EAgW US8aChNVSlVKTE9MQkNNQ01CSE9PVTMWGhIXVQETGhUcChIVHDsJFBgQVhgTEgsIVRgUFkVZV1kS C1lBWU5DVUlJVUxVSkpPWVdZCAFZQUpLTEJNNwY+ DKIM-Signature: a=rsa-sha256; b=iyt+1rSDl1PlNQ/C6aWfTTeBp2lzCmm9Lc9/P5yRHZUhzQyj1D2NnsTvnr9+l0Wa5XhmLkU9DEIa+ssJXiTd/HhhoMI9AdWBmDJDtgTjpHg612SXqzLN0Ll42gHqA/8+8zLH807+JRXb2y+X2qoUNdvccimhxXaPVGKdInTd7zc=; s=default; c=relaxed/relaxed; d=rock-chips.com; v=1; bh=cNZ812L/zEd1cIoqbpJl43iQgWP0uxPAx+ZrYTs1qD0=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" Add new function pointer: Encapsulate some hardware operation functions into rkcanfd_devtype_data to provide differentiated implementations for different models (such as RK3568v2/v3). Signed-off-by: Elaine Zhang --- .../net/can/rockchip/rockchip_canfd-core.c | 104 ++++++++++-------- drivers/net/can/rockchip/rockchip_canfd.h | 11 ++ 2 files changed, 72 insertions(+), 43 deletions(-) diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/c= an/rockchip/rockchip_canfd-core.c index c3fb3176ce42..c21ca4c1fb9a 100644 --- a/drivers/net/can/rockchip/rockchip_canfd-core.c +++ b/drivers/net/can/rockchip/rockchip_canfd-core.c @@ -24,32 +24,6 @@ =20 #include "rockchip_canfd.h" =20 -static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v2 =3D= { - .model =3D RKCANFD_MODEL_RK3568V2, - .quirks =3D RKCANFD_QUIRK_RK3568_ERRATUM_1 | RKCANFD_QUIRK_RK3568_ERRATUM= _2 | - RKCANFD_QUIRK_RK3568_ERRATUM_3 | RKCANFD_QUIRK_RK3568_ERRATUM_4 | - RKCANFD_QUIRK_RK3568_ERRATUM_5 | RKCANFD_QUIRK_RK3568_ERRATUM_6 | - RKCANFD_QUIRK_RK3568_ERRATUM_7 | RKCANFD_QUIRK_RK3568_ERRATUM_8 | - RKCANFD_QUIRK_RK3568_ERRATUM_9 | RKCANFD_QUIRK_RK3568_ERRATUM_10 | - RKCANFD_QUIRK_RK3568_ERRATUM_11 | RKCANFD_QUIRK_RK3568_ERRATUM_12 | - RKCANFD_QUIRK_CANFD_BROKEN, -}; - -/* The rk3568 CAN-FD errata sheet as of Tue 07 Nov 2023 11:25:31 +08:00 - * states that only the rk3568v2 is affected by erratum 5, but tests - * with the rk3568v2 and rk3568v3 show that the RX_FIFO_CNT is - * sometimes too high. In contrast to the errata sheet mark rk3568v3 - * as effected by erratum 5, too. - */ -static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v3 =3D= { - .model =3D RKCANFD_MODEL_RK3568V3, - .quirks =3D RKCANFD_QUIRK_RK3568_ERRATUM_1 | RKCANFD_QUIRK_RK3568_ERRATUM= _2 | - RKCANFD_QUIRK_RK3568_ERRATUM_5 | RKCANFD_QUIRK_RK3568_ERRATUM_7 | - RKCANFD_QUIRK_RK3568_ERRATUM_8 | RKCANFD_QUIRK_RK3568_ERRATUM_10 | - RKCANFD_QUIRK_RK3568_ERRATUM_11 | RKCANFD_QUIRK_RK3568_ERRATUM_12 | - RKCANFD_QUIRK_CANFD_BROKEN, -}; - static const char *__rkcanfd_get_model_str(enum rkcanfd_model model) { switch (model) { @@ -212,7 +186,7 @@ static int rkcanfd_get_berr_counter(const struct net_de= vice *ndev, if (err) return err; =20 - rkcanfd_get_berr_counter_corrected(priv, bec); + priv->devtype_data.get_berr_counter(priv, bec); =20 pm_runtime_put(ndev->dev.parent); =20 @@ -296,13 +270,13 @@ static void rkcanfd_chip_start(struct rkcanfd_priv *p= riv) =20 memset(&priv->bec, 0x0, sizeof(priv->bec)); =20 - rkcanfd_chip_fifo_setup(priv); + priv->devtype_data.fifo_setup(priv); rkcanfd_timestamp_init(priv); rkcanfd_timestamp_start(priv); =20 rkcanfd_set_bittiming(priv); =20 - rkcanfd_chip_interrupts_disable(priv); + priv->devtype_data.interrupts_disable(priv); rkcanfd_chip_set_work_mode(priv); =20 priv->can.state =3D CAN_STATE_ERROR_ACTIVE; @@ -316,7 +290,7 @@ static void __rkcanfd_chip_stop(struct rkcanfd_priv *pr= iv, const enum can_state priv->can.state =3D state; =20 rkcanfd_chip_set_reset_mode(priv); - rkcanfd_chip_interrupts_disable(priv); + priv->devtype_data.interrupts_disable(priv); } =20 static void rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_st= ate state) @@ -342,8 +316,8 @@ static int rkcanfd_set_mode(struct net_device *ndev, =20 switch (mode) { case CAN_MODE_START: - rkcanfd_chip_start(priv); - rkcanfd_chip_interrupts_enable(priv); + priv->devtype_data.chip_start(priv); + priv->devtype_data.interrupts_enable(priv); netif_wake_queue(ndev); break; =20 @@ -537,7 +511,7 @@ static int rkcanfd_handle_error_int(struct rkcanfd_priv= *priv) if (cf) { struct can_berr_counter bec; =20 - rkcanfd_get_berr_counter_corrected(priv, &bec); + priv->devtype_data.get_berr_counter(priv, &bec); cf->can_id |=3D CAN_ERR_PROT | CAN_ERR_BUSERROR | CAN_ERR_CNT; cf->data[6] =3D bec.txerr; cf->data[7] =3D bec.rxerr; @@ -567,7 +541,7 @@ static int rkcanfd_handle_state_error_int(struct rkcanf= d_priv *priv) u32 timestamp; int err; =20 - rkcanfd_get_berr_counter_corrected(priv, &bec); + priv->devtype_data.get_berr_counter(priv, &bec); can_state_get_by_berr_counter(ndev, &bec, &tx_state, &rx_state); =20 new_state =3D max(tx_state, rx_state); @@ -581,7 +555,7 @@ static int rkcanfd_handle_state_error_int(struct rkcanf= d_priv *priv) can_change_state(ndev, cf, tx_state, rx_state); =20 if (new_state =3D=3D CAN_STATE_BUS_OFF) { - rkcanfd_chip_stop(priv, CAN_STATE_BUS_OFF); + priv->devtype_data.chip_stop(priv, CAN_STATE_BUS_OFF); can_bus_off(ndev); } =20 @@ -620,7 +594,7 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv= *priv) if (!skb) return 0; =20 - rkcanfd_get_berr_counter_corrected(priv, &bec); + priv->devtype_data.get_berr_counter(priv, &bec); =20 cf->can_id |=3D CAN_ERR_CRTL | CAN_ERR_CNT; cf->data[1] =3D CAN_ERR_CRTL_RX_OVERFLOW; @@ -719,21 +693,21 @@ static int rkcanfd_open(struct net_device *ndev) if (err) goto out_close_candev; =20 - rkcanfd_chip_start(priv); + priv->devtype_data.chip_start(priv); can_rx_offload_enable(&priv->offload); =20 - err =3D request_irq(ndev->irq, rkcanfd_irq, IRQF_SHARED, ndev->name, priv= ); + err =3D request_irq(ndev->irq, priv->devtype_data.irq, IRQF_SHARED, ndev-= >name, priv); if (err) goto out_rkcanfd_chip_stop; =20 - rkcanfd_chip_interrupts_enable(priv); + priv->devtype_data.interrupts_enable(priv); =20 netif_start_queue(ndev); =20 return 0; =20 out_rkcanfd_chip_stop: - rkcanfd_chip_stop_sync(priv, CAN_STATE_STOPPED); + priv->devtype_data.chip_stop_sync(priv, CAN_STATE_STOPPED); pm_runtime_put(ndev->dev.parent); out_close_candev: close_candev(ndev); @@ -746,10 +720,10 @@ static int rkcanfd_stop(struct net_device *ndev) =20 netif_stop_queue(ndev); =20 - rkcanfd_chip_interrupts_disable(priv); + priv->devtype_data.interrupts_disable(priv); free_irq(ndev->irq, priv); can_rx_offload_disable(&priv->offload); - rkcanfd_chip_stop_sync(priv, CAN_STATE_STOPPED); + priv->devtype_data.chip_stop_sync(priv, CAN_STATE_STOPPED); close_candev(ndev); =20 pm_runtime_put(ndev->dev.parent); @@ -818,7 +792,7 @@ static int rkcanfd_register(struct rkcanfd_priv *priv) if (err) goto out_pm_runtime_put_sync; =20 - rkcanfd_register_done(priv); + priv->devtype_data.register_done(priv); =20 pm_runtime_put(ndev->dev.parent); =20 @@ -840,6 +814,50 @@ static inline void rkcanfd_unregister(struct rkcanfd_p= riv *priv) pm_runtime_disable(ndev->dev.parent); } =20 +static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v2 =3D= { + .model =3D RKCANFD_MODEL_RK3568V2, + .quirks =3D RKCANFD_QUIRK_RK3568_ERRATUM_1 | RKCANFD_QUIRK_RK3568_ERRATUM= _2 | + RKCANFD_QUIRK_RK3568_ERRATUM_3 | RKCANFD_QUIRK_RK3568_ERRATUM_4 | + RKCANFD_QUIRK_RK3568_ERRATUM_5 | RKCANFD_QUIRK_RK3568_ERRATUM_6 | + RKCANFD_QUIRK_RK3568_ERRATUM_7 | RKCANFD_QUIRK_RK3568_ERRATUM_8 | + RKCANFD_QUIRK_RK3568_ERRATUM_9 | RKCANFD_QUIRK_RK3568_ERRATUM_10 | + RKCANFD_QUIRK_RK3568_ERRATUM_11 | RKCANFD_QUIRK_RK3568_ERRATUM_12 | + RKCANFD_QUIRK_CANFD_BROKEN, + .get_berr_counter =3D rkcanfd_get_berr_counter_corrected, + .interrupts_enable =3D rkcanfd_chip_interrupts_enable, + .interrupts_disable =3D rkcanfd_chip_interrupts_disable, + .fifo_setup =3D rkcanfd_chip_fifo_setup, + .chip_start =3D rkcanfd_chip_start, + .chip_stop =3D rkcanfd_chip_stop, + .chip_stop_sync =3D rkcanfd_chip_stop_sync, + .irq =3D rkcanfd_irq, + .register_done =3D rkcanfd_register_done, +}; + +/* The rk3568 CAN-FD errata sheet as of Tue 07 Nov 2023 11:25:31 +08:00 + * states that only the rk3568v2 is affected by erratum 5, but tests + * with the rk3568v2 and rk3568v3 show that the RX_FIFO_CNT is + * sometimes too high. In contrast to the errata sheet mark rk3568v3 + * as effected by erratum 5, too. + */ +static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3568v3 =3D= { + .model =3D RKCANFD_MODEL_RK3568V3, + .quirks =3D RKCANFD_QUIRK_RK3568_ERRATUM_1 | RKCANFD_QUIRK_RK3568_ERRATUM= _2 | + RKCANFD_QUIRK_RK3568_ERRATUM_5 | RKCANFD_QUIRK_RK3568_ERRATUM_7 | + RKCANFD_QUIRK_RK3568_ERRATUM_8 | RKCANFD_QUIRK_RK3568_ERRATUM_10 | + RKCANFD_QUIRK_RK3568_ERRATUM_11 | RKCANFD_QUIRK_RK3568_ERRATUM_12 | + RKCANFD_QUIRK_CANFD_BROKEN, + .get_berr_counter =3D rkcanfd_get_berr_counter_corrected, + .interrupts_enable =3D rkcanfd_chip_interrupts_enable, + .interrupts_disable =3D rkcanfd_chip_interrupts_disable, + .fifo_setup =3D rkcanfd_chip_fifo_setup, + .chip_start =3D rkcanfd_chip_start, + .chip_stop =3D rkcanfd_chip_stop, + .chip_stop_sync =3D rkcanfd_chip_stop_sync, + .irq =3D rkcanfd_irq, + .register_done =3D rkcanfd_register_done, +}; + static const struct of_device_id rkcanfd_of_match[] =3D { { .compatible =3D "rockchip,rk3568v2-canfd", diff --git a/drivers/net/can/rockchip/rockchip_canfd.h b/drivers/net/can/ro= ckchip/rockchip_canfd.h index 93131c7d7f54..d898260794aa 100644 --- a/drivers/net/can/rockchip/rockchip_canfd.h +++ b/drivers/net/can/rockchip/rockchip_canfd.h @@ -436,9 +436,20 @@ enum rkcanfd_model { RKCANFD_MODEL_RK3568V3 =3D 0x35683, }; =20 +static struct rkcanfd_priv *priv; + struct rkcanfd_devtype_data { enum rkcanfd_model model; u32 quirks; + void (*get_berr_counter)(struct rkcanfd_priv *priv, struct can_berr_count= er *bec); + void (*interrupts_enable)(const struct rkcanfd_priv *priv); + void (*interrupts_disable)(const struct rkcanfd_priv *priv); + void (*fifo_setup)(struct rkcanfd_priv *priv); + void (*chip_start)(struct rkcanfd_priv *priv); + void (*chip_stop)(struct rkcanfd_priv *priv, const enum can_state state); + void (*chip_stop_sync)(struct rkcanfd_priv *priv, const enum can_state st= ate); + irqreturn_t (*irq)(int irq, void *dev_id); + void (*register_done)(const struct rkcanfd_priv *priv); }; =20 struct rkcanfd_fifo_header { --=20 2.34.1 From nobody Sun Dec 14 12:17:30 2025 Received: from mail-m1973184.qiye.163.com (mail-m1973184.qiye.163.com [220.197.31.84]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0555E27FD7D; Fri, 23 May 2025 07:59:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=220.197.31.84 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747987191; cv=none; b=XFMzJfY+vl3wKIw3wlRPfje4s+BHBaUr/wx4V3tFNqgXZiSQg18M+A+2GU25pMFutrLdm7EkNN/f56pEPBvF7fidwzl+ys3y7GRMt+4lIZSNsc2Z00BQqajh/fKKiXwGyTP38356g7icmUhi7P024Hb4sgcsmzVvfOHJAlkGd20= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747987191; c=relaxed/simple; bh=YFMdNDDsF9apCaM1pb7GxF0m7sCwFDQbaNq5hO1ROtg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=uin3YXLRiFjPP04gKxJjncnn2SSK4g/0m8liFB6fhwfuKYBeURzf6unBuC9QcWFqPpw+1e63CNV7310RHlneCYycbzf29uNHMUZpO1Uot8RDMgay2vJCw+y+B2rQsZ0viWw+88sHVLYwvHgkhyikX/9YXVmO8bMfOESiWCIzUuo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com; spf=pass smtp.mailfrom=rock-chips.com; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b=XqoeilKp; arc=none smtp.client-ip=220.197.31.84 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b="XqoeilKp" Received: from rockchip.. (unknown [58.22.7.114]) by smtp.qiye.163.com (Hmail) with ESMTP id 1628045db; Fri, 23 May 2025 15:54:29 +0800 (GMT+08:00) From: Elaine Zhang To: zhangqing@rock-chips.com, mkl@pengutronix.de, kernel@pengutronix.de, mailhol.vincent@wanadoo.fr, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de, cl@rock-chips.com, kever.yang@rock-chips.com Cc: linux-can@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v5 3/4] net: can: rockchip: add can for RK3576 Soc Date: Fri, 23 May 2025 15:54:21 +0800 Message-Id: <20250523075422.4010083-4-zhangqing@rock-chips.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250523075422.4010083-1-zhangqing@rock-chips.com> References: <20250523075422.4010083-1-zhangqing@rock-chips.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFDSUNOT01LS0k3V1ktWUFJV1kPCRoVCBIfWUFZQ0hPGVZLHkhKGE9KS0tPSR5WFRQJFh oXVRMBExYaEhckFA4PWVdZGBILWUFZTkNVSUlVTFVKSk9ZV1kWGg8SFR0UWUFZT0tIVUpLSU9PT0 hVSktLVUpCS0tZBg++ X-HM-Tid: 0a96fc22ecae03a3kunm893a9d4d11db30 X-HM-MType: 1 X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6PBg6HCo5NjE*OhUTOBYLEAkN VhEKChNVSlVKTE9MQkNNQ0xKSU1OVTMWGhIXVQETGhUcChIVHDsJFBgQVhgTEgsIVRgUFkVZV1kS C1lBWU5DVUlJVUxVSkpPWVdZCAFZQUhCTU1DNwY+ DKIM-Signature: a=rsa-sha256; b=XqoeilKpenfmyrAJFLrVaOzvZOvZ6MoFhJFxqzll56jykTPfUk74H4RCpRmKF0DqoqVOEfYvP9xTUcXanFo6erizNVNywndehHFG5VdTHC0hvCUu0HV5Nro3KRkb2vMd6lPm+FQ7yGyvdV1V6FRShyx0HF4oIj2oqwaLp4ApllQ=; s=default; c=relaxed/relaxed; d=rock-chips.com; v=1; bh=CJKE6ef1DhIDYI8WT+jU9yNt/7xCISscs/imMi3YHnc=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" Is new controller, new register layout and Bit position definition: Support CAN and CANFD protocol, ISO 11898-1 Support transmit or receive error count Support acceptance filter, more functional Support interrupt and all interrupt can be masked Support error code check Support self test\silent\loop-back mode Support auto retransmission mode Support auto bus on after bus-off state Support 2 transmit buffers Support Internal Storage Mode Support DMA Signed-off-by: Elaine Zhang --- .../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 | 267 +++++++++++ 4 files changed, 860 insertions(+) diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/c= an/rockchip/rockchip_canfd-core.c index c21ca4c1fb9a..92e260cb2527 100644 --- a/drivers/net/can/rockchip/rockchip_canfd-core.c +++ b/drivers/net/can/rockchip/rockchip_canfd-core.c @@ -31,6 +31,8 @@ static const char *__rkcanfd_get_model_str(enum rkcanfd_m= odel model) return "rk3568v2"; case RKCANFD_MODEL_RK3568V3: return "rk3568v3"; + case RKCANFD_MODEL_RK3576: + return "rk3576"; } =20 return ""; @@ -176,6 +178,30 @@ static void rkcanfd_get_berr_counter_corrected(struct = rkcanfd_priv *priv, !!(reg_state & RKCANFD_REG_STATE_ERROR_WARNING_STATE)); } =20 +static void rk3576canfd_get_berr_counter_corrected(struct rkcanfd_priv *pr= iv, + struct can_berr_counter *bec) +{ + struct can_berr_counter bec_raw; + u32 reg_state; + + bec->rxerr =3D rkcanfd_read(priv, RK3576CANFD_REG_RXERRORCNT); + bec->txerr =3D rkcanfd_read(priv, RK3576CANFD_REG_TXERRORCNT); + bec_raw =3D *bec; + + if (!bec->rxerr && !bec->txerr) + *bec =3D priv->bec; + else + priv->bec =3D *bec; + + reg_state =3D rkcanfd_read(priv, RKCANFD_REG_STATE); + netdev_vdbg(priv->ndev, + "%s: Raw/Cor: txerr=3D%3u/%3u rxerr=3D%3u/%3u Bus Off=3D%u Warning= =3D%u\n", + __func__, + bec_raw.txerr, bec->txerr, bec_raw.rxerr, bec->rxerr, + !!(reg_state & RK3576CANFD_REG_STATE_BUS_OFF_STATE), + !!(reg_state & RK3576CANFD_REG_STATE_ERROR_WARNING_STATE)); +} + static int rkcanfd_get_berr_counter(const struct net_device *ndev, struct can_berr_counter *bec) { @@ -206,6 +232,11 @@ static void rkcanfd_chip_interrupts_disable(const stru= ct rkcanfd_priv *priv) rkcanfd_write(priv, RKCANFD_REG_INT_MASK, RKCANFD_REG_INT_ALL); } =20 +static void rk3576canfd_chip_interrupts_disable(const struct rkcanfd_priv = *priv) +{ + rkcanfd_write(priv, RK3576CANFD_REG_INT_MASK, RK3576CANFD_REG_INT_ALL); +} + static void rkcanfd_chip_fifo_setup(struct rkcanfd_priv *priv) { u32 reg; @@ -220,6 +251,72 @@ static void rkcanfd_chip_fifo_setup(struct rkcanfd_pri= v *priv) netdev_reset_queue(priv->ndev); } =20 +static void rk3576canfd_chip_fifo_setup(struct rkcanfd_priv *priv) +{ + u32 ism =3D 0, water =3D 0; + + ism =3D RK3576CANFD_REG_STR_CTL_ISM_SEL_CANFD_FIXED; + water =3D RK3576CANFD_ISM_WATERMASK_CANFD; + + /* internal sram mode */ + rkcanfd_write(priv, RK3576CANFD_REG_STR_CTL, + (FIELD_PREP(RK3576CANFD_REG_STR_CTL_ISM_SEL, ism) | + RK3576CANFD_REG_STR_CTL_STORAGE_TIMEOUT_MODE)); + rkcanfd_write(priv, RK3576CANFD_REG_STR_WTM, water); + 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] =3D {0}; + u32 dlc =3D 0, dlc_over =3D 0; + + switch (mode) { + case RK3576CANFD_REG_ATFM_MASK_SEL_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, RK3576CANFD_REG_ATFM_ID); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM1, RK3576CANFD_REG_ATFM_ID); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM2, RK3576CANFD_REG_ATFM_ID); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM3, RK3576CANFD_REG_ATFM_ID); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM4, RK3576CANFD_REG_ATFM_ID); + break; + case RK3576CANFD_REG_ATFM_MASK_SEL_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] | RK3576CANFD_REG_ATFM_= MASK_SEL); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM1, id[6] | RK3576CANFD_REG_ATFM_= MASK_SEL); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM2, id[7] | RK3576CANFD_REG_ATFM_= MASK_SEL); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM3, id[8] | RK3576CANFD_REG_ATFM_= MASK_SEL); + rkcanfd_write(priv, RK3576CANFD_REG_ATFM4, id[9] | RK3576CANFD_REG_ATFM_= MASK_SEL); + break; + default: + rkcanfd_write(priv, RK3576CANFD_REG_ATF_CTL, RK3576CANFD_REG_ATF_CTL_ATF= _DIS_ALL); + return -EINVAL; + } + + if (dlc) { + if (dlc_over) + rkcanfd_write(priv, RK3576CANFD_REG_ATF_DLC, + dlc | RK3576CANFD_REG_ATF_DLC_ATF_DLC_EN); + else + rkcanfd_write(priv, RK3576CANFD_REG_ATF_DLC, + dlc | RK3576CANFD_REG_ATF_DLC_ATF_DLC_EN | + RK3576CANFD_REG_ATF_DLC_ATF_DLC_MODE); + } + rkcanfd_write(priv, RK3576CANFD_REG_ATF_CTL, 0); + + return 0; +} + static void rkcanfd_chip_start(struct rkcanfd_priv *priv) { u32 reg; @@ -285,6 +382,68 @@ static void rkcanfd_chip_start(struct rkcanfd_priv *pr= iv) rkcanfd_read(priv, RKCANFD_REG_MODE)); } =20 +static void rk3576canfd_chip_start(struct rkcanfd_priv *priv) + +{ + u32 reg; + + rkcanfd_chip_set_reset_mode(priv); + + /* Receiving Filter: accept all */ + rk3576canfd_atf_config(priv, RK3576CANFD_REG_ATFM_MASK_SEL_MASK_MODE); + + /* enable: + * - CAN_FD: enable CAN-FD + * - AUTO_RETX_MODE: auto retransmission on TX error + * - COVER_MODE: RX-FIFO overwrite mode, do not send OVERLOAD frames + * - RXSTX_MODE: Receive Self Transmit data mode + * - WORK_MODE: transition from reset to working mode + */ + reg =3D rkcanfd_read(priv, RKCANFD_REG_MODE); + priv->reg_mode_default =3D reg | RKCANFD_REG_MODE_WORK_MODE; + + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { + priv->reg_mode_default |=3D RKCANFD_REG_MODE_LBACK_MODE; + rkcanfd_write(priv, RK3576CANFD_REG_ERROR_MASK, + RK3576CANFD_REG_ERROR_MASK_ACK_ERROR); + } + + /* mask, i.e. ignore: + * - TIMESTAMP_COUNTER_OVERFLOW_INT - timestamp counter overflow interrupt + * - TX_ARBIT_FAIL_INT - TX arbitration fail interrupt + * - OVERLOAD_INT - CAN bus overload interrupt + * - TX_FINISH_INT - Transmit finish interrupt + */ + priv->reg_int_mask_default =3D RK3576CANFD_REG_INT_RX_FINISH_INT; + + /* Do not mask the bus error interrupt if the bus error + * reporting is requested. + */ + if (!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) + priv->reg_int_mask_default |=3D RKCANFD_REG_INT_ERROR_INT; + + memset(&priv->bec, 0x0, sizeof(priv->bec)); + + priv->devtype_data.fifo_setup(priv); + + rkcanfd_write(priv, RK3576CANFD_REG_AUTO_RETX_CFG, + RK3576CANFD_REG_AUTO_RETX_CFG_AUTO_RETX_EN); + + rkcanfd_write(priv, RK3576CANFD_REG_BRS_CFG, + RK3576CANFD_REG_BRS_CFG_BRS_NEGSYNC_EN | + RK3576CANFD_REG_BRS_CFG_BRS_POSSYNC_EN); + + rkcanfd_set_bittiming(priv); + + priv->devtype_data.interrupts_disable(priv); + rkcanfd_chip_set_work_mode(priv); + + priv->can.state =3D CAN_STATE_ERROR_ACTIVE; + + netdev_dbg(priv->ndev, "%s: reg_mode=3D0x%08x\n", __func__, + rkcanfd_read(priv, RKCANFD_REG_MODE)); +} + static void __rkcanfd_chip_stop(struct rkcanfd_priv *priv, const enum can_= state state) { priv->can.state =3D state; @@ -301,6 +460,13 @@ static void rkcanfd_chip_stop(struct rkcanfd_priv *pri= v, const enum can_state st __rkcanfd_chip_stop(priv, state); } =20 +static void rk3576canfd_chip_stop(struct rkcanfd_priv *priv, const enum ca= n_state state) +{ + priv->can.state =3D state; + + __rkcanfd_chip_stop(priv, state); +} + static void rkcanfd_chip_stop_sync(struct rkcanfd_priv *priv, const enum c= an_state state) { priv->can.state =3D state; @@ -309,6 +475,13 @@ static void rkcanfd_chip_stop_sync(struct rkcanfd_priv= *priv, const enum can_sta __rkcanfd_chip_stop(priv, state); } =20 +static void rk3576canfd_chip_stop_sync(struct rkcanfd_priv *priv, const en= um can_state state) +{ + priv->can.state =3D state; + + __rkcanfd_chip_stop(priv, state); +} + static int rkcanfd_set_mode(struct net_device *ndev, enum can_mode mode) { @@ -364,6 +537,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) " " : "") =20 +#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_fram= e *cf, const u32 reg_ec) @@ -493,6 +669,128 @@ rkcanfd_handle_error_int_reg_ec(struct rkcanfd_priv *= priv, struct can_frame *cf, } } =20 +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 =3D &priv->ndev->stats; + unsigned int type; + u32 reg_state, reg_cmd; + + type =3D FIELD_GET(RK3576CANFD_REG_ERROR_CODE_TYPE, reg_ec); + reg_cmd =3D rkcanfd_read(priv, RK3576CANFD_REG_CMD); + reg_state =3D 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=3D%u RX=3D%u TX=3D%u Error-Warning= =3D%u Bus-Off=3D%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] =3D CAN_ERR_PROT_LOC_SOF; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ID2_RTR) + cf->data[3] =3D CAN_ERR_PROT_LOC_RTR; + /* RKCANFD_REG_ERROR_CODE_RX_FDF */ + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_RES) + cf->data[3] =3D 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] =3D CAN_ERR_PROT_LOC_DLC; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_DATA) + cf->data[3] =3D 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] =3D CAN_ERR_PROT_LOC_CRC_SEQ; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_CRC_LIM) + cf->data[3] =3D CAN_ERR_PROT_LOC_ACK_DEL; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ACK) + cf->data[3] =3D CAN_ERR_PROT_LOC_ACK; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_ACK_LIM) + cf->data[3] =3D CAN_ERR_PROT_LOC_ACK_DEL; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_EOF) + cf->data[3] =3D CAN_ERR_PROT_LOC_EOF; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_RX_SPACE) + cf->data[3] =3D CAN_ERR_PROT_LOC_EOF; + } else { + cf->data[2] |=3D CAN_ERR_PROT_TX; + + if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_SOF_DLC) + cf->data[3] =3D CAN_ERR_PROT_LOC_SOF; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_DATA) + cf->data[3] =3D 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] =3D CAN_ERR_PROT_LOC_CRC_SEQ; + else if (reg_ec & RK3576CANFD_REG_ERROR_CODE_TX_ACK_EOF) + cf->data[3] =3D 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] |=3D CAN_ERR_PROT_BIT; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_STUFF): + cf->data[2] |=3D CAN_ERR_PROT_STUFF; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_FORM): + cf->data[2] |=3D CAN_ERR_PROT_FORM; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_ACK): + cf->can_id |=3D CAN_ERR_ACK; + break; + case FIELD_PREP_CONST(RK3576CANFD_REG_ERROR_CODE_TYPE, + RK3576CANFD_REG_ERROR_CODE_TYPE_CRC): + cf->data[3] =3D CAN_ERR_PROT_LOC_CRC_SEQ; + break; + } +} + static int rkcanfd_handle_error_int(struct rkcanfd_priv *priv) { struct net_device_stats *stats =3D &priv->ndev->stats; @@ -530,6 +828,41 @@ static int rkcanfd_handle_error_int(struct rkcanfd_pri= v *priv) return 0; } =20 +static int rkcanfd_handle_rk3576_error_int(struct rkcanfd_priv *priv) +{ + struct net_device_stats *stats =3D &priv->ndev->stats; + struct can_frame *cf =3D NULL; + u32 reg_ec; + struct sk_buff *skb; + int err; + + reg_ec =3D rkcanfd_read(priv, RK3576CANFD_REG_ERROR_CODE); + if (!reg_ec) + return 0; + + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) { + skb =3D alloc_can_err_skb(priv->ndev, &cf); + if (cf) { + struct can_berr_counter bec; + + priv->devtype_data.get_berr_counter(priv, &bec); + cf->can_id |=3D CAN_ERR_PROT | CAN_ERR_BUSERROR | CAN_ERR_CNT; + cf->data[6] =3D bec.txerr; + cf->data[7] =3D bec.rxerr; + } + } + + rk3576canfd_handle_error_int_reg_ec(priv, cf, reg_ec); + if (!cf) + return 0; + + err =3D can_rx_offload_queue_tail(&priv->offload, skb); + if (err) + stats->rx_fifo_errors++; + + return 0; +} + static int rkcanfd_handle_state_error_int(struct rkcanfd_priv *priv) { struct net_device_stats *stats =3D &priv->ndev->stats; @@ -575,6 +908,50 @@ static int rkcanfd_handle_state_error_int(struct rkcan= fd_priv *priv) return 0; } =20 +static int rkcanfd_handle_rk3576_state_error_int(struct rkcanfd_priv *priv) +{ + struct net_device_stats *stats =3D &priv->ndev->stats; + enum can_state new_state, rx_state, tx_state; + struct net_device *ndev =3D priv->ndev; + struct can_berr_counter bec; + struct can_frame *cf =3D NULL; + struct sk_buff *skb; + int err; + + priv->devtype_data.get_berr_counter(priv, &bec); + can_state_get_by_berr_counter(ndev, &bec, &tx_state, &rx_state); + + new_state =3D max(tx_state, rx_state); + if (new_state =3D=3D priv->can.state) + return 0; + + /* The skb allocation might fail, but can_change_state() + * handles cf =3D=3D NULL. + */ + skb =3D alloc_can_err_skb(priv->ndev, &cf); + can_change_state(ndev, cf, tx_state, rx_state); + + if (new_state =3D=3D CAN_STATE_BUS_OFF) { + priv->devtype_data.chip_stop(priv, CAN_STATE_BUS_OFF); + can_bus_off(ndev); + } + + if (!skb) + return 0; + + if (new_state !=3D CAN_STATE_BUS_OFF) { + cf->can_id |=3D CAN_ERR_CNT; + cf->data[6] =3D bec.txerr; + cf->data[7] =3D bec.rxerr; + } + + err =3D can_rx_offload_queue_tail(&priv->offload, skb); + if (err) + stats->rx_fifo_errors++; + + return 0; +} + static int rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_priv *priv) { @@ -621,6 +998,55 @@ rkcanfd_handle_rx_fifo_overflow_int(struct rkcanfd_pri= v *priv) err; \ }) =20 +static irqreturn_t rk3576canfd_irq(int irq, void *dev_id) +{ + struct rkcanfd_priv *priv =3D dev_id; + u32 reg_int_unmasked, reg_int; + + reg_int_unmasked =3D rkcanfd_read(priv, RK3576CANFD_REG_INT); + reg_int =3D 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_write(priv, RK3576CANFD_REG_INT_MASK, + priv->reg_int_mask_default | RK3576CANFD_REG_INT_ISM_WTM_INT | + RK3576CANFD_REG_INT_RXSTR_TIMEOUT_INT | + RK3576CANFD_REG_INT_RX_FINISH_INT); + rkcanfd_handle(priv, rk3576_rx_int); + } + + if (reg_int & RK3576CANFD_REG_INT_TX_FINISH_INT) + rkcanfd_handle(priv, rk3576_tx_int); + + if (reg_int & RK3576CANFD_REG_INT_ERROR_INT) + rkcanfd_handle(priv, rk3576_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, rk3576_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 =3D dev_id; @@ -775,6 +1201,16 @@ static void rkcanfd_register_done(const struct rkcanf= d_priv *priv) RKCANFD_ERRATUM_5_SYSCLOCK_HZ_MIN / MEGA); } =20 +static void rk3576canfd_register_done(const struct rkcanfd_priv *priv) +{ + u32 dev_id; + + dev_id =3D rkcanfd_read(priv, RK3576CANFD_REG_RTL_VERSION); + netdev_info(priv->ndev, + "Rockchip-CANFD %s rev%u.\n", + rkcanfd_get_model_str(priv), dev_id); +} + static int rkcanfd_register(struct rkcanfd_priv *priv) { struct net_device *ndev =3D priv->ndev; @@ -858,6 +1294,20 @@ static const struct rkcanfd_devtype_data rkcanfd_devt= ype_data_rk3568v3 =3D { .register_done =3D rkcanfd_register_done, }; =20 +/* The rk3576 CAN-FD */ +static const struct rkcanfd_devtype_data rkcanfd_devtype_data_rk3576 =3D { + .model =3D RKCANFD_MODEL_RK3576, + .get_berr_counter =3D rk3576canfd_get_berr_counter_corrected, + .interrupts_enable =3D rkcanfd_chip_interrupts_enable, + .interrupts_disable =3D rk3576canfd_chip_interrupts_disable, + .fifo_setup =3D rk3576canfd_chip_fifo_setup, + .chip_start =3D rk3576canfd_chip_start, + .chip_stop =3D rk3576canfd_chip_stop, + .chip_stop_sync =3D rk3576canfd_chip_stop_sync, + .irq =3D rk3576canfd_irq, + .register_done =3D rk3576canfd_register_done, +}; + static const struct of_device_id rkcanfd_of_match[] =3D { { .compatible =3D "rockchip,rk3568v2-canfd", @@ -865,6 +1315,9 @@ static const struct of_device_id rkcanfd_of_match[] = =3D { }, { .compatible =3D "rockchip,rk3568v3-canfd", .data =3D &rkcanfd_devtype_data_rk3568v3, + }, { + .compatible =3D "rockchip,rk3576-canfd", + .data =3D &rkcanfd_devtype_data_rk3576, }, { /* sentinel */ }, diff --git a/drivers/net/can/rockchip/rockchip_canfd-rx.c b/drivers/net/can= /rockchip/rockchip_canfd-rx.c index 475c0409e215..8a383cabd9d2 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_p= riv *priv, return len + cfd->len; } =20 +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 =3D sizeof(*cfd) - sizeof(cfd->data); + u8 dlc; + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FRAME_FORMAT) + cfd->can_id =3D FIELD_GET(RKCANFD_REG_FD_ID_EFF, header->id) | + CAN_EFF_FLAG; + else + cfd->can_id =3D FIELD_GET(RKCANFD_REG_FD_ID_SFF, header->id); + + dlc =3D FIELD_GET(RK3576CANFD_REG_RXFRD_FRAMEINFO_DATA_LENGTH, + header->frameinfo); + + /* CAN-FD */ + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FDF) { + cfd->len =3D can_fd_dlc2len(dlc); + + /* The cfd is not allocated by alloc_canfd_skb(), so + * set CANFD_FDF here. + */ + cfd->flags |=3D CANFD_FDF; + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_BRS) + cfd->flags |=3D CANFD_BRS; + } else { + cfd->len =3D can_cc_dlc2len(dlc); + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_RTR) { + cfd->can_id |=3D 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,52 @@ rkcanfd_fifo_header_empty(const struct rkcanfd_fifo_he= ader *header) header->frameinfo =3D=3D header->ts; } =20 +static int rk3576canfd_handle_rx_int_one(struct rkcanfd_priv *priv) +{ + struct net_device_stats *stats =3D &priv->ndev->stats; + struct canfd_frame cfd[1] =3D { }, *skb_cfd; + struct rk3576canfd_fifo_header header[1] =3D { }; + 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, sizeof(cfd->data)); + + len =3D rk3576canfd_fifo_header_to_cfd_header(priv, header, cfd); + + /* Manual handling of CAN Bus Error counters. See + * rkcanfd_get_corrected_berr_counter() for detailed + * explanation. + */ + if (priv->bec.rxerr) + priv->bec.rxerr =3D min(CAN_ERROR_PASSIVE_THRESHOLD, + priv->bec.rxerr) - 1; + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FDF) + skb =3D alloc_canfd_skb(priv->ndev, &skb_cfd); + else + skb =3D alloc_can_skb(priv->ndev, (struct can_frame **)&skb_cfd); + + if (!skb) { + stats->rx_dropped++; + + return 0; + } + + memcpy(skb_cfd, cfd, len); + + err =3D 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 =3D &priv->ndev->stats; @@ -284,6 +371,15 @@ rkcanfd_rx_fifo_get_len(const struct rkcanfd_priv *pri= v) return FIELD_GET(RKCANFD_REG_RX_FIFO_CTRL_RX_FIFO_CNT, reg); } =20 +static inline unsigned int +rk3576canfd_rx_fifo_get_len(const struct rkcanfd_priv *priv) +{ + const u32 reg =3D rkcanfd_read(priv, RK3576CANFD_REG_STR_STATE); + int val =3D FIELD_GET(RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT, reg); + + return DIV_ROUND_UP(val, RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT); +} + int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv) { unsigned int len; @@ -297,3 +393,18 @@ int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv) =20 return 0; } + +int rkcanfd_handle_rk3576_rx_int(struct rkcanfd_priv *priv) +{ + unsigned int len; + int err; + + while ((len =3D rk3576canfd_rx_fifo_get_len(priv))) { + err =3D rk3576canfd_handle_rx_int_one(priv); + if (err) + return err; + } + rkcanfd_write(priv, RK3576CANFD_REG_INT_MASK, priv->reg_int_mask_default); + return 0; +} + diff --git a/drivers/net/can/rockchip/rockchip_canfd-tx.c b/drivers/net/can= /rockchip/rockchip_canfd-tx.c index 865a15e033a9..c19b97cb2296 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 *p= riv, const u32 ts, frame_len_p); stats->tx_packets++; } + +int rkcanfd_handle_rk3576_tx_int(struct rkcanfd_priv *priv) +{ + struct net_device_stats *stats =3D &priv->ndev->stats; + unsigned int tx_tail; + struct sk_buff *skb; + unsigned int frame_len =3D 0; + + tx_tail =3D rkcanfd_get_tx_tail(priv); + skb =3D 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 +=3D + 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/ro= ckchip/rockchip_canfd.h index d898260794aa..ef46837ed573 100644 --- a/drivers/net/can/rockchip/rockchip_canfd.h +++ b/drivers/net/can/rockchip/rockchip_canfd.h @@ -287,6 +287,265 @@ #define RKCANFD_REG_RX_FIFO_RDATA 0x400 #define RKCANFD_REG_TXE_FIFO_RDATA 0x500 =20 +#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_CTL_STORAGE_TIMEOUT_MODE BIT(8) +#define RK3576CANFD_REG_STR_CTL_ESM_SEL_MASK GENMASK(7, 6) +#define RK3576CANFD_REG_STR_CTL_RX_STORAGE_RESET BIT(4) +#define RK3576CANFD_REG_STR_CTL_ISM_SEL GENMASK(3, 2) +#define RK3576CANFD_REG_STR_CTL_ISM_SEL_FLEXIBLE 0x0 +#define RK3576CANFD_REG_STR_CTL_ISM_SEL_CAN_FIXED 0x1 +#define RK3576CANFD_REG_STR_CTL_ISM_SEL_CANFD_FIXED 0x2 +#define RK3576CANFD_REG_STR_CTL_EXT_STORAGE_MODE BIT(1) +#define RK3576CANFD_REG_STR_CTL_BUFFER_MODE_ENABLE BIT(0) + +#define RK3576CANFD_REG_STR_STATE 0x604 +#define RK3576CANFD_REG_STR_STATE_INTM_FRAME_CNT GENMASK(25, 17) +#define RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT GENMASK(16, 8) +#define RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT 18 +#define RK3576CANFD_REG_STR_STATE_EXTM_FULL BIT(3) +#define RK3576CANFD_REG_STR_STATE_EXTM_EMPTY BIT(2) +#define RK3576CANFD_REG_STR_STATE_INTM_FULL BIT(1) +#define RK3576CANFD_REG_STR_STATE_INTM_EMPTY BIT(0) + +#define RK3576CANFD_REG_STR_TIMEOUT 0x608 + +#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_ATFM_MASK_SEL BIT(31) +#define RK3576CANFD_REG_ATFM_RTR_EN BIT(30) +#define RK3576CANFD_REG_ATFM_RTR BIT(29) +#define RK3576CANFD_REG_ATFM_MASK_SEL_MASK_MODE 0x0 +#define RK3576CANFD_REG_ATFM_MASK_SEL_LIST_MODE 0x1 +#define RK3576CANFD_REG_ATFM_ID GENMASK(28, 0) + +#define RK3576CANFD_REG_ATF_DLC 0x728 +#define RK3576CANFD_REG_ATF_DLC_ATF_DLC_MODE BIT(5) +#define RK3576CANFD_REG_ATF_DLC_ATF_DLC_EN BIT(4) +#define RK3576CANFD_REG_ATF_DLC_ATF_DLC GENMASK(3, 0) + +#define RK3576CANFD_REG_ATF_CTL 0x72c +#define RK3576CANFD_REG_ATF_CTL_ATF_DIS(n) BIT(n) +#define RK3576CANFD_REG_ATF_CTL_ATF_DIS_ALL GENMASK(15, 0) + +#define RK3576CANFD_REG_SPACE_CTRL 0x800 + +#define RK3576CANFD_REG_AUTO_RETX_CFG 0x808 +#define RK3576CANFD_REG_AUTO_RETX_CFG_RETX_TIME_LIMIT GENMASK(18, 3) +#define RK3576CANFD_REG_AUTO_RETX_CFG_RETX_LIMIT_EN BIT(1) +#define RK3576CANFD_REG_AUTO_RETX_CFG_AUTO_RETX_EN BIT(0) + +#define RK3576CANFD_REG_AUTO_RETX_STATE0 0x80c +#define RK3576CANFD_REG_AUTO_RETX_STATE0_AUTO_RETX_CNT GENMASK(15, 0) + +#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_REG_ERROR_CODE 0x900 +#define RK3576CANFD_REG_ERROR_MASK 0x904 +#define RK3576CANFD_REG_ERROR_MASK_ACK_ERROR BIT(4) +#define RK3576CANFD_REG_ERROR_MASK_FORM_ERROR BIT(3) +#define RK3576CANFD_REG_ERROR_MASK_CRC_ERROR BIT(2) +#define RK3576CANFD_REG_ERROR_MASK_STUFF_ERROR BIT(1) +#define RK3576CANFD_REG_ERROR_MASK_BIT_ERROR 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_SRAM_MAX_DEPTH 256 /* word */ + +#define RK3576CANFD_CANFD_FILTER GENMASK(28, 0) + +#define RK3576CANFD_CANFD_FIFO_CNT GENMASK(7, 0) + #define DEVICE_NAME "rockchip_canfd" #define RKCANFD_NAPI_WEIGHT 32 #define RKCANFD_TXFIFO_DEPTH 2 @@ -434,6 +693,7 @@ enum rkcanfd_model { RKCANFD_MODEL_RK3568V2 =3D 0x35682, RKCANFD_MODEL_RK3568V3 =3D 0x35683, + RKCANFD_MODEL_RK3576 =3D 0x3576, }; =20 static struct rkcanfd_priv *priv; @@ -458,6 +718,11 @@ struct rkcanfd_fifo_header { u32 ts; }; =20 +struct rk3576canfd_fifo_header { + u32 frameinfo; + u32 id; +}; + struct rkcanfd_stats { struct u64_stats_sync syncp; =20 @@ -547,6 +812,8 @@ rkcanfd_get_tx_free(const struct rkcanfd_priv *priv) void rkcanfd_ethtool_init(struct rkcanfd_priv *priv); =20 int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv); +int rkcanfd_handle_rk3576_tx_int(struct rkcanfd_priv *priv); +int rkcanfd_handle_rk3576_rx_int(struct rkcanfd_priv *priv); =20 void rkcanfd_skb_set_timestamp(const struct rkcanfd_priv *priv, struct sk_buff *skb, const u32 timestamp); --=20 2.34.1 From nobody Sun Dec 14 12:17:30 2025 Received: from mail-m21472.qiye.163.com (mail-m21472.qiye.163.com [117.135.214.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BA5DD28750F; Fri, 23 May 2025 08:09:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.214.72 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747987794; cv=none; b=po5MfLSF479a3QI7QKW5n5s7ahtoKijKuwZkVc/3qBgh46zHHb91nfWcgYCMaxEn9AOzei3CcbjT+kSjnQrbg7EpkcfAsZz5/wZObXYdLrZJfiZOnQ5A7NYCBV5AynYxO6vrp3fh/RANgZNs32gdk+P39PP8ecH+LdqnXnxhjRs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747987794; c=relaxed/simple; bh=0OuT2whnl7ypCfnyu+yaOm4NsPcmkuXu7SxCJ/05RN8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IQ7gi5KxOi/ytXz4ejJ/XkloYUSdTEKKUSEAHqIrzeEhpBICveyOprgd3kUB4rS91mwxGEglu5iO4kxcfrP2tnZwKmoD61gRybqphKcd9NJVtCnsMy1h1F6RAgqLllo3654rRscvHSFyEYNPsroYR6abYSSWmjabfQdCTcG2cyE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com; spf=pass smtp.mailfrom=rock-chips.com; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b=Otywu/bi; arc=none smtp.client-ip=117.135.214.72 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=rock-chips.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=rock-chips.com header.i=@rock-chips.com header.b="Otywu/bi" Received: from rockchip.. (unknown [58.22.7.114]) by smtp.qiye.163.com (Hmail) with ESMTP id 1628045f1; Fri, 23 May 2025 15:54:31 +0800 (GMT+08:00) From: Elaine Zhang To: zhangqing@rock-chips.com, mkl@pengutronix.de, kernel@pengutronix.de, mailhol.vincent@wanadoo.fr, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, heiko@sntech.de, cl@rock-chips.com, kever.yang@rock-chips.com Cc: linux-can@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v5 4/4] net: can: rockchip: support dma for rk3576 rx Date: Fri, 23 May 2025 15:54:22 +0800 Message-Id: <20250523075422.4010083-5-zhangqing@rock-chips.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250523075422.4010083-1-zhangqing@rock-chips.com> References: <20250523075422.4010083-1-zhangqing@rock-chips.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFDSUNOT01LS0k3V1ktWUFJV1kPCRoVCBIfWUFZGR8aGVZDQkofSUpLTxkaH0lWFRQJFh oXVRMBExYaEhckFA4PWVdZGBILWUFZTkNVSUlVTFVKSk9ZV1kWGg8SFR0UWUFZT0tIVUpLSEpKQk 1VSktLVUpCWQY+ X-HM-Tid: 0a96fc22f42903a3kunm893a9d4d11db7f X-HM-MType: 1 X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6Njo6Aio6TjE0NhUcOBcaEE46 FAwaCzdVSlVKTE9MQkNNQ0xJQk5LVTMWGhIXVQETGhUcChIVHDsJFBgQVhgTEgsIVRgUFkVZV1kS C1lBWU5DVUlJVUxVSkpPWVdZCAFZQUNOTko3Bg++ DKIM-Signature: a=rsa-sha256; b=Otywu/bi2Lk4lCDhFSIWywTXixpvAtTFf8q/3Us9Nx3oWEMHGoNp6oHd8kLMd/VPxiS+bqOISluErCXoSSuh7j2YdEIQ+kdCCb42cmJzLwInulKMAzgf4t+XP9ljwdQ+y946DQfeSYY/K28ScNogxWIsAd9+vsb0wEaPc6frGFc=; s=default; c=relaxed/relaxed; d=rock-chips.com; v=1; bh=WHt3ciCOlWWGFv/hHizwXrIrdySa8FGSYcqD3FJvXFI=; h=date:mime-version:subject:message-id:from; Content-Type: text/plain; charset="utf-8" The new can controller of rk3576 supports rx dma. Signed-off-by: Elaine Zhang --- .../net/can/rockchip/rockchip_canfd-core.c | 39 +++++++++ drivers/net/can/rockchip/rockchip_canfd-rx.c | 86 +++++++++++++++++++ drivers/net/can/rockchip/rockchip_canfd.h | 11 +++ 3 files changed, 136 insertions(+) diff --git a/drivers/net/can/rockchip/rockchip_canfd-core.c b/drivers/net/c= an/rockchip/rockchip_canfd-core.c index 92e260cb2527..9ef4a9ae19d8 100644 --- a/drivers/net/can/rockchip/rockchip_canfd-core.c +++ b/drivers/net/can/rockchip/rockchip_canfd-core.c @@ -433,6 +433,9 @@ static void rk3576canfd_chip_start(struct rkcanfd_priv = *priv) RK3576CANFD_REG_BRS_CFG_BRS_NEGSYNC_EN | RK3576CANFD_REG_BRS_CFG_BRS_POSSYNC_EN); =20 + if (priv->use_dma) + rkcanfd_write(priv, RK3576CANFD_REG_DMA_CTRL, + RK3576CANFD_REG_DMA_CTRL_DMA_RX_EN | priv->dma_thr); rkcanfd_set_bittiming(priv); =20 priv->devtype_data.interrupts_disable(priv); @@ -1324,10 +1327,31 @@ static const struct of_device_id rkcanfd_of_match[]= =3D { }; MODULE_DEVICE_TABLE(of, rkcanfd_of_match); =20 +static void rk3576_canfd_dma_init(struct rkcanfd_priv *priv) +{ + struct dma_slave_config rxconf =3D { + .direction =3D DMA_DEV_TO_MEM, + .src_addr =3D priv->rx_dma_src_addr, + .src_addr_width =3D 4, + .dst_addr_width =3D 4, + .src_maxburst =3D 9, + }; + + priv->dma_thr =3D rxconf.src_maxburst - 1; + priv->rxbuf =3D dma_alloc_coherent(priv->dev, priv->dma_size * 14, + &priv->rx_dma_dst_addr, GFP_KERNEL); + if (!priv->rxbuf) { + priv->use_dma =3D 0; + return; + } + dmaengine_slave_config(priv->rxchan, &rxconf); +} + static int rkcanfd_probe(struct platform_device *pdev) { struct rkcanfd_priv *priv; struct net_device *ndev; + struct resource *res; const void *match; int err; =20 @@ -1349,6 +1373,7 @@ static int rkcanfd_probe(struct platform_device *pdev) goto out_free_candev; } =20 + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->regs =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs)) { err =3D PTR_ERR(priv->regs); @@ -1376,6 +1401,7 @@ static int rkcanfd_probe(struct platform_device *pdev) priv->can.do_set_mode =3D rkcanfd_set_mode; priv->can.do_get_berr_counter =3D rkcanfd_get_berr_counter; priv->ndev =3D ndev; + priv->dev =3D &pdev->dev; =20 match =3D device_get_match_data(&pdev->dev); if (match) { @@ -1384,6 +1410,19 @@ static int rkcanfd_probe(struct platform_device *pde= v) priv->can.ctrlmode_supported |=3D CAN_CTRLMODE_FD; } =20 + priv->rxchan =3D dma_request_chan(&pdev->dev, "rx"); + if (IS_ERR(priv->rxchan)) { + dev_warn(&pdev->dev, "Failed to request rxchan\n"); + priv->rxchan =3D NULL; + priv->use_dma =3D 0; + } else { + priv->rx_dma_src_addr =3D res->start + RK3576CANFD_REG_RXFRD; + priv->dma_size =3D RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT * 4; + priv->use_dma =3D 1; + } + if (priv->use_dma) + rk3576_canfd_dma_init(priv); + err =3D can_rx_offload_add_manual(ndev, &priv->offload, RKCANFD_NAPI_WEIGHT); if (err) diff --git a/drivers/net/can/rockchip/rockchip_canfd-rx.c b/drivers/net/can= /rockchip/rockchip_canfd-rx.c index 8a383cabd9d2..18c4970c2573 100644 --- a/drivers/net/can/rockchip/rockchip_canfd-rx.c +++ b/drivers/net/can/rockchip/rockchip_canfd-rx.c @@ -285,6 +285,51 @@ static int rk3576canfd_handle_rx_int_one(struct rkcanf= d_priv *priv) return 0; } =20 +static int rk3576canfd_handle_rx_dma(struct rkcanfd_priv *priv, u32 addr) +{ + struct net_device_stats *stats =3D &priv->ndev->stats; + struct canfd_frame cfd[1] =3D { }, *skb_cfd; + struct rk3576canfd_fifo_header header[1] =3D { }; + struct sk_buff *skb; + unsigned int len; + int i; + + header->frameinfo =3D readl(priv->rxbuf + + addr * RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT); + header->id =3D readl(priv->rxbuf + 1 + + addr * RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT); + for (i =3D 0; i < (RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT - 2); i++) + cfd->data[i] =3D readl(priv->rxbuf + 2 + i + + addr * RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT); + + len =3D rk3576canfd_fifo_header_to_cfd_header(priv, header, cfd); + + /* Manual handling of CAN Bus Error counters. See + * rkcanfd_get_corrected_berr_counter() for detailed + * explanation. + */ + if (priv->bec.rxerr) + priv->bec.rxerr =3D min(CAN_ERROR_PASSIVE_THRESHOLD, + priv->bec.rxerr) - 1; + + if (header->frameinfo & RK3576CANFD_REG_RXFRD_FRAMEINFO_FDF) + skb =3D alloc_canfd_skb(priv->ndev, &skb_cfd); + else + skb =3D alloc_can_skb(priv->ndev, (struct can_frame **)&skb_cfd); + + if (!skb) { + stats->rx_dropped++; + + return 0; + } + + memcpy(skb_cfd, cfd, len); + stats->rx_packets++; + stats->rx_bytes +=3D cfd->len; + netif_rx(skb); + return 0; +} + static int rkcanfd_handle_rx_int_one(struct rkcanfd_priv *priv) { struct net_device_stats *stats =3D &priv->ndev->stats; @@ -380,6 +425,43 @@ rk3576canfd_rx_fifo_get_len(const struct rkcanfd_priv = *priv) return DIV_ROUND_UP(val, RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNIT); } =20 +static void rk3576_canfd_rx_dma_callback(void *data) +{ + struct rkcanfd_priv *priv =3D data; + int i; + + for (i =3D 0; i < priv->quota; i++) + rk3576canfd_handle_rx_dma(priv, i); + + rkcanfd_write(priv, RK3576CANFD_REG_INT_MASK, priv->reg_int_mask_default); +} + +static int rk3576_canfd_rx_dma(struct rkcanfd_priv *priv) +{ + struct dma_async_tx_descriptor *rxdesc =3D NULL; + const u32 reg =3D rkcanfd_read(priv, RK3576CANFD_REG_STR_STATE); + int quota =3D FIELD_GET(RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT, reg); + + quota =3D DIV_ROUND_UP(quota, RK3576CANFD_REG_STR_STATE_INTM_LEFT_CNT_UNI= T); + priv->quota =3D quota; + if (priv->quota =3D=3D 0) { + rkcanfd_write(priv, RK3576CANFD_REG_INT_MASK, priv->reg_int_mask_default= ); + return 0; + } + + rxdesc =3D dmaengine_prep_slave_single(priv->rxchan, priv->rx_dma_dst_add= r, + priv->dma_size * priv->quota, DMA_DEV_TO_MEM, 0); + if (!rxdesc) + return -ENOMSG; + + rxdesc->callback =3D rk3576_canfd_rx_dma_callback; + rxdesc->callback_param =3D priv; + + dmaengine_submit(rxdesc); + dma_async_issue_pending(priv->rxchan); + return 0; +} + int rkcanfd_handle_rx_int(struct rkcanfd_priv *priv) { unsigned int len; @@ -399,6 +481,10 @@ int rkcanfd_handle_rk3576_rx_int(struct rkcanfd_priv *= priv) unsigned int len; int err; =20 + if (priv->use_dma) { + rk3576_canfd_rx_dma(priv); + return 0; + } while ((len =3D rk3576canfd_rx_fifo_get_len(priv))) { err =3D rk3576canfd_handle_rx_int_one(priv); if (err) diff --git a/drivers/net/can/rockchip/rockchip_canfd.h b/drivers/net/can/ro= ckchip/rockchip_canfd.h index ef46837ed573..2ebb3c64e9d4 100644 --- a/drivers/net/can/rockchip/rockchip_canfd.h +++ b/drivers/net/can/rockchip/rockchip_canfd.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -737,6 +739,7 @@ struct rkcanfd_priv { struct can_priv can; struct can_rx_offload offload; struct net_device *ndev; + struct device *dev; =20 void __iomem *regs; unsigned int tx_head; @@ -758,6 +761,14 @@ struct rkcanfd_priv { struct reset_control *reset; struct clk_bulk_data *clks; int clks_num; + bool use_dma; + u32 dma_size; + u32 dma_thr; + int quota; + struct dma_chan *rxchan; + u32 *rxbuf; + dma_addr_t rx_dma_src_addr; + dma_addr_t rx_dma_dst_addr; }; =20 static inline u32 --=20 2.34.1