From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 18F0B27B357; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=cby+UyM7UD/DSiFWSdtmE4La0P3Ce91BVjguGqERc5Sx9tWVNi6cMkl4a1cWP0sLI1n9/TlrA+n5o75+x9f8123+gDpYTmMsEJzbn1+M2HGK0QKG4WGCnasLAKe28X172tflnnDvKE2M1eaH4f1hB+YyWVRVmCrj3tTQTiXWHfY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=YFvqcq/2EL5NjJ0I4Ow1yGNyZwdpiGWa5I9vDyoHhPM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aScE32gssX0u0rksk2iitkiYOahiNgsuCOcUYadc8PCkopzjpbE5Gcop7cjjSqD8ltEFces60SOj8xD4gqdLAE+H37L5u9lbZ4fd4yG8MCX+U9g4aKbhw0jr/tI2jem5DLAWBE3WCor5GJvqeD2I9gjh/CCd0Phmwbj2t2S2qwk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Og/baEEG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Og/baEEG" Received: by smtp.kernel.org (Postfix) with ESMTPS id E1079C4CEE7; Thu, 18 Sep 2025 18:49:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=YFvqcq/2EL5NjJ0I4Ow1yGNyZwdpiGWa5I9vDyoHhPM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Og/baEEG7RJIWsGueDpHJH38aV26kd+cei0lHMvj4xuiNJJ/EUHRWhGkpf+wsXzZY 6AVErdVzIuyyvjB6h9w6JkeJqoOuFONih7ykIxjunInVSd6KjpKNvnhOY8fAH7xpCF l4odM4vXM772c6cdpNLBGXG6RP8cYUP0wOJ4Xd1rzcR8Rc/D4LFpal/Mwq5AUjLDrj bm1IsbXoHx6i/Dfb3immgF2oCpJdfILx423U6yEwxsatvq2ECS2kWqbGnKRo/KaQef x/zEdMl5HWXXB1ww6kxMqVTKHF9k3G0iIRjZHghjWJfLaJRSiGn0GjspvwpgxDOtVO kzvp0gRnXvapQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id D029FCAC59A; Thu, 18 Sep 2025 18:49:57 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:41 +0700 Subject: [PATCH 01/10] dt-bindings: gpio: rda: Make interrupts optional Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-1-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh , Conor Dooley X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=820; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=2bdyJSmNfA84cD9RwcJK/nl1FiNGvBo/u1np6F84KKc=; b=DyZRaXM1kMO4Bvn2OOUEuGjeJosLpZO+vdO4EV+4Kzk2toTVfVMNwOFax9Lh/KERoSAaQrAAn gTzEsgHiZT0Cc3CM6CRQ0mx/+FPllcXT0qx3PI+xw69zxFy6ReLEoiV X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh The GPIO controller from the modem does not have an interrupt. Acked-by: Conor Dooley Signed-off-by: Dang Huynh --- Documentation/devicetree/bindings/gpio/gpio-rda.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/gpio-rda.yaml b/Documen= tation/devicetree/bindings/gpio/gpio-rda.yaml index 6ece555f074f84b396537917d7149d4061724dcc..dbb73b4d33ed39aa65024376b1a= f0c4e2fb896db 100644 --- a/Documentation/devicetree/bindings/gpio/gpio-rda.yaml +++ b/Documentation/devicetree/bindings/gpio/gpio-rda.yaml @@ -41,9 +41,6 @@ required: - gpio-controller - "#gpio-cells" - ngpios - - interrupt-controller - - "#interrupt-cells" - - interrupts =20 additionalProperties: false =20 --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 4B8D12D23A9; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=jOXArOORi8W/vq1lEP7yMXeBoNvMxDwIdL4hbiu+xtYiCqclbJHjVZsRJOFbUWoOr7Gnondi7PDf24K/8rlWkIQB1JegkNvMCgcAr9169nSC+qSCUBWcXBdZH9oBmJ0BguiJlKSjECvaqq8fq/o84yvoJATLpYJG7K+11nq2oDo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=m6XC20l3ClTl8r0l+5xVZWE4dMGQNb50oPXH+vTTgX0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AwdWn6O2hbD9YnLsxcduYWsPEQ2BDrI/p8GkmzjltWTl84EVx2vebJxCQXOTbIWoWikuYav0TheFjAyCrXweAyeTDCDGJ2a+Q/BenXPNB5StsSEZ+LL57t9HAxi14MdI5YBDbx1RBDNx2WYQt2j66aR+JYwoATVz/8T3VpKV64s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Y3Svp6kh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Y3Svp6kh" Received: by smtp.kernel.org (Postfix) with ESMTPS id ED381C4AF0C; Thu, 18 Sep 2025 18:49:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=m6XC20l3ClTl8r0l+5xVZWE4dMGQNb50oPXH+vTTgX0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Y3Svp6khvN7yWzF7yJAnb/6eZx8XPiIFDzCLqmaRfQN8Nt/HeWW6aIiyluudJpf92 WTk0Bwpk4SYMm67ZUlmAGCk3xxCZhz7Y1d2txvccyvKoH3PBcXFRtBZX5CqePDdBpi ExHW4ymOD/m9rx9ufzSxcj4EYIGdqhXOwdipAhwXNe5vg489e+TGAsroIpfHImbRp2 iEU0boEJYjE2GdxB8HD135UAdIegHrIvu3ytVTiuG01JiCyvjaHK+Nc7GZeh2Qnd6y 4KBrXDzfd6BX9AmoOs6baZJO9REcAJsuufHR5nz0iU2J6qAZjMg8OI/50LGptUEu9T LRePwLcGITJcg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E21BCCAC5A7; Thu, 18 Sep 2025 18:49:57 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:42 +0700 Subject: [PATCH 02/10] dt-bindings: clock: Add RDA Micro RDA8810PL clock/reset controller Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-2-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=3620; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=yG1beL4lbbZE3Cyw7kV4xFP4ZLuCcjFcdAuQ/q4oW2c=; b=JF6dfaJsAusUyjBVwoIXfKUz19P5AWybOy4EvgWhd2pjj31nJtH6FOD0h+2fiLlOazh9s+xlj HEwzlje4oP5DeSea12PeZ2gEI5kYukFumlHp1Rs2zLRm4HdqCrnp6ZZ X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh Add documentation describing the RDA8810PL Clock and Reset controller. Signed-off-by: Dang Huynh --- .../bindings/clock/rda,8810pl-apsyscon.yaml | 43 +++++++++++++ include/dt-bindings/clock/rda,8810pl-apclk.h | 70 ++++++++++++++++++= ++++ 2 files changed, 113 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/rda,8810pl-apsyscon.ya= ml b/Documentation/devicetree/bindings/clock/rda,8810pl-apsyscon.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d90dae8ebaa270aa822e4855d2a= 4a892168c5eea --- /dev/null +++ b/Documentation/devicetree/bindings/clock/rda,8810pl-apsyscon.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/rda,8810pl-apsyscon.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RDA Micro RDA8810PL AP Clock Controller + +maintainers: + - Dang Huynh + +properties: + compatible: + items: + - const: rda,8810pl-apsyscon + - const: syscon + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + +required: + - compatible + - reg + - '#clock-cells' + - '#reset-cells' + +additionalProperties: false + +examples: + - | + #include + syscon@0 { + compatible =3D "rda,8810pl-apsyscon", "syscon"; + reg =3D <0x0 0x1000>; + #clock-cells =3D <1>; + #reset-cells =3D <1>; + }; diff --git a/include/dt-bindings/clock/rda,8810pl-apclk.h b/include/dt-bind= ings/clock/rda,8810pl-apclk.h new file mode 100644 index 0000000000000000000000000000000000000000..b6d68af9596a7ef827f6d18f1f1= 9ed359e147629 --- /dev/null +++ b/include/dt-bindings/clock/rda,8810pl-apclk.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ + +#ifndef _DT_BINDINGS_CLK_RDA8810_H_ +#define _DT_BINDINGS_CLK_RDA8810_H_ + +/* soc clocks */ +#define CLK_CPU 0 +#define CLK_BUS 1 +#define CLK_MEM 2 +#define CLK_USB 3 +#define CLK_AXI 4 +#define CLK_GCG 5 +#define CLK_AHB1 6 +#define CLK_APB1 7 +#define CLK_APB2 8 +#define CLK_GPU 9 +#define CLK_VPU 10 +#define CLK_VOC 11 +#define CLK_SFLSH 12 +#define CLK_UART1 13 +#define CLK_UART2 14 +#define CLK_UART3 15 +#define CLK_VOC2 16 +#define CLK_EMMC 17 + +/* resets */ +#define RST_CPU 0 + +#define RST_AXI_VOC 1 +#define RST_AXI_DMA 2 +#define RST_AXI_CONNECT 3 +#define RST_AXI_VPU 4 + +#define RST_GCG_GOUDA 5 +#define RST_GCG_CAMERA 6 +#define RST_GCG_LCDC 7 + +#define RST_AHB1_USBC 8 +#define RST_AHB1_SPIFLASH 9 +#define RST_APB1_TIMER 10 +#define RST_APB1_KEYPAD 11 +#define RST_APB1_GPIO 12 +#define RST_APB1_PWM 13 +#define RST_APB1_AIF 14 +#define RST_APB1_AUIFC 15 +#define RST_APB1_I2C1 16 +#define RST_APB1_I2C2 17 +#define RST_APB1_I2C3 18 +#define RST_APB1_COMREGS 19 +#define RST_APB1_DMC 20 +#define RST_APB1_DDRPHY_P 21 + +#define RST_APB2_IFC 22 +#define RST_APB2_UART1 23 +#define RST_APB2_UART2 24 +#define RST_APB2_UART3 25 +#define RST_APB2_SPI1 26 +#define RST_APB2_SPI2 27 +#define RST_APB2_SPI3 28 +#define RST_APB2_SDMMC1 29 +#define RST_APB2_SDMMC2 30 +#define RST_APB2_SDMMC3 31 +#define RST_APB2_NAND 32 + +#define RST_MEM_GPU 33 +#define RST_MEM_VPU 34 +#define RST_MEM_DMC 35 +#define RST_MEM_DDRPHY_P 36 + +#endif /* _DT_BINDINGS_CLK_RDA8810_H_ */ --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 9FC1B2D8774; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=DnMS9lxiX5HQlnCoXe+vZQL+K4vy2tWU/SO9V6PrUpevSfNMuPM/SrdoOeaMbmgDGh4iatn4Ot2apOO5RZUAjJf9dWzB05MXOF/n8V5ve2dwzzunUSd/CdwPlfKyXBhWrQ9BcMohFJKdiFYGrHYMee/N//fUhdyCYEGWBi3CPr8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=Htg5Xkrs9v7XuZNYgTVERiSjoemIaBO0jN/nY/LLRAU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Nj4ajWTsIOdCyTSzz5rvCitZZaF+mieQzT8W7vlncmqzSRRacS2zNcSlNpFN+hUWmqLPkj6R4mZFEcwoiS288a1J8imQWXKlroM85YQx4q/JTdNCAFgvEnYZxzV0+MdYosRbeW/Bqpvl2TOexZmzrqUd7E4disTMN26OXsNcg+w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kSeEVrWa; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kSeEVrWa" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0EE02C4CEF1; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=Htg5Xkrs9v7XuZNYgTVERiSjoemIaBO0jN/nY/LLRAU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=kSeEVrWav2PG5BgRSfOW1+KN7xeUTx2UR9FezgyY5IT12g/PUtMp2vUOvtErW5Hqz L4lvjDfIh822AGzZF8Rc2+bR7WtWU5MBxHmv5rB+YNEP/IKaalXx4JuIMSxnMrs/z6 MIjIc22S0O87HdVQThIwIAucZnr+aIDqboY09i5RZOwt2llByAFZiaFdVfQ1xxAGKA u13ap5mUeHsygRDzLGDJAun08wJnZBlmCtScaJyTZnhWpHIgNvQKMiyPAiYZTShAuh oghbtZY3/4l4751hxq9OUirOKjeRtV9IpiF8V65IvFuEG3YWwrsZmcXquKxP6mcVUV /RpETgjRTJXPg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2FE7CA1013; Thu, 18 Sep 2025 18:49:57 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:43 +0700 Subject: [PATCH 03/10] dt-bindings: dma: Add RDA IFC DMA Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-3-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=2618; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=fdIibseK6J9eF4DEbb0by9y6/svLXlDdAKxdYmnzlAc=; b=QviwbPBtxpdoWdT5r4lpY8XknciVPiPjmERLRTaOaBzvDTRddjvGsVcO6iHE8kT4emUpiQt4E 1MLJW+wwCTHAOBt+3nucNpqiToQ4PDL0uwMLtxtR+eUzpkVGgG8tCe2 X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh The Intelligent Flow Controller (IFC) is a scatter/gather DMA controller. Signed-off-by: Dang Huynh --- Documentation/devicetree/bindings/dma/rda,ifc.yaml | 45 ++++++++++++++++++= ++++ include/dt-bindings/dma/rda-ifc.h | 28 ++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/rda,ifc.yaml b/Documenta= tion/devicetree/bindings/dma/rda,ifc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..323e1e87cee09cfc7b64bf44bef= 61e4d1e91afa5 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/rda,ifc.yaml @@ -0,0 +1,45 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/rda,ifc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RDA Intelligent Flow Controller (IFC) + +maintainers: + - Dang Huynh + +description: | + RDA IFC is a DMA controller, it only supports scatter/gather lists. + +allOf: + - $ref: dma-controller.yaml# + +properties: + compatible: + items: + - enum: + - rda,8810pl-ifc + - const: rda,ifc + + reg: + maxItems: 1 + + "#dma-cells": + const: 1 + description: + The cell corresponding to DMA request ID + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + dma-controller@f0000 { + compatible =3D "rda,8810pl-ifc", "rda,ifc"; + reg =3D <0xf0000 0x1000>; + #dma-cells =3D <1>; + }; diff --git a/include/dt-bindings/dma/rda-ifc.h b/include/dt-bindings/dma/rd= a-ifc.h new file mode 100644 index 0000000000000000000000000000000000000000..af4bae0542aa71690351e2406d0= 945a61eff72c1 --- /dev/null +++ b/include/dt-bindings/dma/rda-ifc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */ + +#ifndef __DT_BINDINGS_DMA_RDA_IFC_H__ +#define __DT_BINDINGS_DMA_RDA_IFC_H__ + +#define IFC_UART1_TX 0 +#define IFC_UART1_RX 1 +#define IFC_UART2_TX 2 +#define IFC_UART2_RX 3 +#define IFC_SPI1_TX 4 +#define IFC_SPI1_RX 5 +#define IFC_SPI2_TX 6 +#define IFC_SPI2_RX 7 +#define IFC_SPI3_TX 8 +#define IFC_SPI3_RX 9 +#define IFC_SDMMC1_TX 10 +#define IFC_SDMMC1_RX 11 +#define IFC_SDMMC2_TX 12 +#define IFC_SDMMC2_RX 13 +#define IFC_SDMMC3_TX 14 +#define IFC_SDMMC3_RX 15 +#define IFC_NFSC_TX 16 +#define IFC_NFSC_RX 17 +#define IFC_UART3_TX 18 +#define IFC_UART3_RX 19 +#define IFC_NO_REQUEST 20 + +#endif /* __DT_BINDINGS_DMA_RDA_IFC_H__ */ --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 8CD2F2D7DE5; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=csdl7mu3Z3z11j+7mfHfuE1AAImtNfVjhAbudOzk44Ki5W1ml2CiM6ZBv/MalbRd+yzwcmr+05DqOo223RpGJatVrrsQava0B0UZIQ25vQbM2sL5IJTF0fuIYYhDnjJU+wQv+xDDf36UHiSJR+hBLddssLOjMVdW/h5IWNQ7mIw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=KkndGZ2cFeTM19fVBhPaNoLbiQh6UVaVfyXkJUdBXsk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RD5f5Ea8xKqw+giVxfDZ2mZqFNkhwMikdNNW0jc41PZjhVrZqY0Zelj4WHLKasY4b2Z0frO+YfB+OZLaNkwHPc0vtie9S3FLWJENz2VYlAAGCpD/bYdMlRyU6PPxUNMmIgvJ9wrfRdw84STwIwYcCwKhGnb9rIbKdgMs5e57fhY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=q+G1lq5e; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="q+G1lq5e" Received: by smtp.kernel.org (Postfix) with ESMTPS id 17B7DC4AF13; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=KkndGZ2cFeTM19fVBhPaNoLbiQh6UVaVfyXkJUdBXsk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=q+G1lq5eX76T2uqv5/HptLwuHYisvdH2xVJ/ZCMJJY6xr2aJTQXo9pEOxrZnnjCIS 4Jcyw/H5/f1UeJ0rIJ+Isukjgkqa6HA7uhIjZIn3KtTAJk8CS/F4A32JKiKo2NEBSj NjEjRSWTo/j1UwN6t5HQhkjaXOwZtYrFJrO186EFXZ8UeYsCKYC52J9VGlbkrnLrM9 R1myopw6va0UYQlS1Aiiun+qE8l3JmQ3vz41yX+kjaWgjBbtd+/4ZCXsMNCfBYdtCh nG5Y1pYE8wXAmoaASW2Xp+nMDEYtmrAMLaXpt9fjKXmapvLMRRqfWQhXKAMTWv9FHN T7PiVg/UCQfWQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0F57CCAC59A; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:44 +0700 Subject: [PATCH 04/10] dt-bindings: mmc: Add RDA SDMMC controller Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-4-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=2667; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=AsSx2jfyiIl9tD1PzUkU8B/80/dNLISAbs6T475/JWo=; b=m1jZ5iiJdDLR2oNGhbZc1KvGaZ/RhK/lM0bAsauM7cx684WiuGLwZlK4HFh7moDg6YJ4FQU+R ttMceldPwaYBD+EGfHCFOX0uBSgU42qv2H8yNPUABQPx0Skg+RH4jnz X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh Add documentation describing the SD/MMC controller in RDA Micro RDA8810PL SoC. Signed-off-by: Dang Huynh --- Documentation/devicetree/bindings/mmc/rda,mmc.yaml | 92 ++++++++++++++++++= ++++ 1 file changed, 92 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/rda,mmc.yaml b/Documenta= tion/devicetree/bindings/mmc/rda,mmc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f3cda38abd66023ca9bc94d1c29= df5ae9e211e7c --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/rda,mmc.yaml @@ -0,0 +1,92 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/rda,mmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RDA Micro SD/MMC Controller + +allOf: + - $ref: mmc-controller.yaml + +maintainers: + - Dang Huynh + +properties: + compatible: + items: + - enum: + - rda,8810pl-mmc + - const: rda,mmc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: mclk + + resets: + maxItems: 1 + + dmas: + maxItems: 2 + + dma-names: + items: + - const: tx + - const: rx + + rda,mclk-adj: + $ref: /schemas/types.yaml#/definitions/uint8 + description: + Some board need MCLK output to be delayed for the card to work. + If not present, MCLK output is not delayed. + minimum: 0 + maximum: 255 + + rda,mclk-inv: + $ref: /schemas/types.yaml#/definitions/flag + description: + Some board need MCLK to be inverted for the card to work. + If not present, MCLK is not inverted. + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - resets + - dmas + - dma-names + - vmmc-supply + +unevaluatedProperties: false + +examples: + - | + #include + #include + #include + #include + mmc@20950000 { + compatible =3D "rda,8810pl-mmc", "rda,mmc"; + reg =3D <0x20950000 0x1000>; + interrupts =3D <3 IRQ_TYPE_LEVEL_HIGH>; + clocks =3D <&ap_syscon CLK_APB2>; + clock-names =3D "mclk"; + resets =3D <&ap_syscon RST_APB2_SDMMC1>; + dmas =3D <&ifc IFC_SDMMC1_TX>, <&ifc IFC_SDMMC1_RX>; + dma-names =3D "tx", "rx"; + vmmc-supply =3D <&vdd_sdmmc>; + rda,mclk-adj =3D /bits/ 8 <1>; + rda,mclk-inv; + }; + +... --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 9E3DD2D8767; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=PWIV3XQvskw/tTMMoc/Of2xc+Xo9MYfINjMOQYtmc8a/nlL0AoBRnmqOBEBxtzHhebGwgvQXbUtMYH/HwH43mIdlamBswIX1mH0Xta2luv0G20TLkll1qGnSZhEztvz01s6luVogDyblfK6WarqsawAgFKIcOcB8bE7pBDxOVGs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=xFZzw0dxkId4PpzWi4rCIk0ujR41JrlCk231RXGFPjY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ahXMbyAuh5DgtPi7tJSt9n9XzF3TEKAozr7+V99Av30tdst3KU2O+DHkPa7yC4C3lhtTwBee2ntKLkiK7Nvbz2m0TNag8qCm1rydQoJaCroCZdX9fv2nGPTceiH1TPD00oPg05dHCqs7hMlnlZkbP7j7P+XOOOGuHbTub031b0s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YauvTm6a; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YauvTm6a" Received: by smtp.kernel.org (Postfix) with ESMTPS id 26CE1C19422; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=xFZzw0dxkId4PpzWi4rCIk0ujR41JrlCk231RXGFPjY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=YauvTm6aF85Rf2LnVgDHgqBJ8NYqPiAc/R+nTvtZFu0rxjVNHIazKwd5d3gGv0cu4 7Bi8nThF/VZmTZfDKJJIYIG9okGui02mQ0GcDfIfTOdThWAFVzo8Lbwlt+ozcGAAYi J8ToHTT2PE9TwbTX441/VaxVY77yVY7FuvL3W9ZmkuxsJ2W3otNn6r1ilyvWs3KC4S Bn1AfAPGFmI6cHEE35u2F07KP/320MoekbWNfiSXgCNj/QMb4QQk0dgJul6Uwf1Hxz 6RP5FBz05/3Eijz1AEtGowJys/7ZaEz4qSJI+qwOG7Cw2avpsAqSjMEFA5OAuzvAV0 AYl3fLnfSG6PQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E980CAC5A9; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:45 +0700 Subject: [PATCH 05/10] gpio: rda: Make IRQ optional Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-5-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=961; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=MpdOunzwRix8r+I6dz4W5XzomAmmpf9+SZqztmWlQWc=; b=gcu6tm5gzmZ+ZMKsRV7i/uxjKVCVaCUgL333lVwfm3e0f8wM4biBdYwyH2e1IKu/7nMS5khcs Tc0z4jijgshB0EsAQMfMy7L+Jji9rFMHcG7B3mt7gpRIFlwxVXF0BM1 X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh Not all GPIO have IRQ. When we use this driver with GPIOC (handled by modem) we get: rda-gpio 11a08000.gpioc: error -ENXIO: IRQ index 0 not found Let's mark IRQ as optional so this error doesn't show up. Signed-off-by: Dang Huynh --- drivers/gpio/gpio-rda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-rda.c b/drivers/gpio/gpio-rda.c index fb479d13eb01a49218ad4229e7d4f70f096f5a2e..7d20dbbb6ec41149a1dbf4d9ef9= ac86449773c35 100644 --- a/drivers/gpio/gpio-rda.c +++ b/drivers/gpio/gpio-rda.c @@ -229,7 +229,7 @@ static int rda_gpio_probe(struct platform_device *pdev) * RDA8810PL, GPIOC doesn't support interrupt. So we must handle * those also. */ - rda_gpio->irq =3D platform_get_irq(pdev, 0); + rda_gpio->irq =3D platform_get_irq_optional(pdev, 0); =20 rda_gpio->base =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rda_gpio->base)) --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 A136B2D8776; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=CMIDvglwvWCL9r9W0sjovIXbOx+Xh0EPBxR2ypkCvI9FalTbjWkSQDSfNBQFqWsbmTUR322kF6dSNUW+0b/iXO+zwkmWYZfEErk8/XIUsD32Mhd2JFWA2raovv0zxiA/8Y0v6VEdhZJflOmXyQ2VkZNGCyCitMBZSDKeh1VSxts= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=0toEdpgdrAHwzWBocpkLTIinw0pb9FWHXvtuM2MoRow=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fyvbR/6h6P2gX/pu7AVL4kPsqzSLe64U+iDGqJ+KyMoKkkPyVPlLI0TsyuVRDPAnmcXpf/ogbGDNpR5vSX09In8wzKX6YgmvBWkeNqxgTlsitCn/9WMHdu87Kw1lc2BwwpBqfQ3uqZJYALLD5mD3WvixaJcdzxs4hrVsevE9DfU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mXTa/7ZT; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mXTa/7ZT" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3B556C116B1; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=0toEdpgdrAHwzWBocpkLTIinw0pb9FWHXvtuM2MoRow=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=mXTa/7ZTSyoRUPq0LQumllP2bsy6xtHw59fnlRGrCpAMMrQy4Uls6SEbrDebF3128 YpCJ1745BR8ndtD5NrHPFLqZD56yFrg463l+6bPD7F3ty+ZC8Q9ei3PjQkEVxD8KEd yZ7nhF7sgZ3vLyKHqeXo0DuVFBEh+NUdy4XZ4BxklfDLOhcSlJz3e4twocACzX0PCN wcim4j1KWKTIqVnbKUuUz65L7FokbPceYxlodBk66B0/LiHvtNCdsfluXDHoXXUJGl +DkO1/0KzhaBKatU7mmbBoW21zDgo3tPmXfjRsR2y6xhXodHQji0MdbqW01qnlIV7Y NMAB2bTu2PQQQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D1E0CAC5A7; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:46 +0700 Subject: [PATCH 06/10] gpio: rda: Make direction register unreadable Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-6-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=985; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=VMMKg4HONUFRzO6+25FovvsxOlucUttBjgwEeb3Ns7Q=; b=iAakQHayFHGXZ7IKRgsLgfpt3RDZjxa0+TASp4ZeKYUKatPRehTsYyn/QN0h83ue75flIlEEa Z292tJSmrBCA/7rCRSbbK0qIuX2/EJRrE+U7wNAYUXGkbpIODs8+5p8 X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh The register doesn't like to be read and would cause all the input to be switched to output. This causes the SD Card Detect GPIO to misbehaves in the OS and/or may cause hardware to malfunction. Signed-off-by: Dang Huynh --- drivers/gpio/gpio-rda.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-rda.c b/drivers/gpio/gpio-rda.c index 7d20dbbb6ec41149a1dbf4d9ef9ac86449773c35..ae2efa22755986b5445fdb8d4f0= 04d595c189590 100644 --- a/drivers/gpio/gpio-rda.c +++ b/drivers/gpio/gpio-rda.c @@ -245,7 +245,7 @@ static int rda_gpio_probe(struct platform_device *pdev) .clr =3D rda_gpio->base + RDA_GPIO_CLR, .dirout =3D rda_gpio->base + RDA_GPIO_OEN_SET_OUT, .dirin =3D rda_gpio->base + RDA_GPIO_OEN_SET_IN, - .flags =3D BGPIOF_READ_OUTPUT_REG_SET, + .flags =3D BGPIOF_READ_OUTPUT_REG_SET | BGPIOF_UNREADABLE_REG_DIR, }; =20 ret =3D gpio_generic_chip_init(&rda_gpio->chip, &config); --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 C391F2D94B8; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=d0xtclZEICiARjjLMy0V30GhWiT2X1/dlSgXIeTqOcva+5FcViTTM6lj7uOvxX/hWQ/4/ZfhJypgKPPFBLgjjaDe6O5Ncv2ATRFtO01Hp+9IUrqfhA4ZA6FON8oF5BbFOUc1oWpDqhcJhrQn4EpK5QAvKD620RGGrRxfnbQb7h0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=ohlcFbPtKmd6hrVvoOnC65XlpriD3T31l/t/8TTOy4M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oye3woRcplVlKd/6JkcHFK8asE+0ZhHtmFxH4QWvc7qfNv6LdaxYFlzLmS6mNUWaZCacSVAEOWdmEoaQxcxqzo6mKXZjoauxlJ8ffgs8zEZ3Q/B0kPWd8zGB5eQRcgEPdYxFU1dRy8dUTW3vxsMWJqy70qxhdJp/St1ZNAdMxzY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VcI/Kqlw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="VcI/Kqlw" Received: by smtp.kernel.org (Postfix) with ESMTPS id 49FA3C2BCB0; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=ohlcFbPtKmd6hrVvoOnC65XlpriD3T31l/t/8TTOy4M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=VcI/KqlwaUz3pzRY2vSkreJU/lnbr9uVzPm2ZpZmHqy3g4XpVzUbb0Y2gLulGPVH7 1xQYCISUFMx9MoeJdKXb50gV5szekq8VcTJJqsuBu/WEFdOFvOmzoCrTW3tXQ0R7v6 NPhvpAnz26EsK4oiMgxeUDKBwgvlw74oNpa/rzoAsO07LAGPL090KdVdWFGY8xgAVG LuDK7QYKhkQktyI0U/na2G2KkStZ2cDjjSOcMt07JjZ8+lB5GlhTeSjYn6zSNiV/dc 5G82PRCr5+ca0aGlnuKhVdblbCpsOyLbXCFt7sdx/IhnTstmIhlHlCdRo59LEsLR0N /i8l85YIl56Dw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40B71CAC59A; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:47 +0700 Subject: [PATCH 07/10] clk: Add Clock and Reset Driver for RDA Micro RDA8810PL SoC Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-7-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=26561; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=CvcBXgkQGoS86dp3bss1ffFLI1ZZup5pOtQeoJAC0UY=; b=EcTki2KHo91GML0NzHo8REuqpG2umkkwffUzzeHjvqHD58XhIKrIv0So1Go41BF5W17FTGt9h CzEk13FqLiCDmYPkDlNZdlLWHat2UW+GbSu0yVQ/iJKJ3Hcjy5x3UrO X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh Add a clock/reset driver for RDA8810PL SoC, which provides clocks for various subsystems. Signed-off-by: Dang Huynh --- MAINTAINERS | 6 + drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/rda/Kconfig | 14 + drivers/clk/rda/Makefile | 2 + drivers/clk/rda/clk-rda8810.c | 769 ++++++++++++++++++++++++++++++++++++++= ++++ 6 files changed, 793 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8886d66bd8242ae76ca52393af3958435bf6b9a5..56f9d19fbf421eefffe554987e1= 4604c764daab2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21418,6 +21418,12 @@ S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/rcu/linux.git rcu/dev F: tools/testing/selftests/rcutorture =20 +RDA MICRO CLOCK AND RESET DRIVER +M: Dang Huynh +S: Maintained +F: Documentation/devicetree/bindings/clock/rda,8810pl-apsyscon.yaml +F: drivers/clk/rda/clk-rda8810.c + RDACM20 Camera Sensor M: Jacopo Mondi M: Kieran Bingham diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index b1425aed659387a676bd933fe50ac4894c7156fe..15f5bc9108b565acb1c3c6e978a= d0e5a71f5550d 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -520,6 +520,7 @@ source "drivers/clk/nuvoton/Kconfig" source "drivers/clk/pistachio/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/ralink/Kconfig" +source "drivers/clk/rda/Kconfig" source "drivers/clk/renesas/Kconfig" source "drivers/clk/rockchip/Kconfig" source "drivers/clk/samsung/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 18ed29cfdc1133b6c254190c6092eb263366d5ac..8241bb7f88daaebde766ba92d71= 8b2ca710d6b5f 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -141,6 +141,7 @@ obj-$(CONFIG_COMMON_CLK_PISTACHIO) +=3D pistachio/ obj-$(CONFIG_COMMON_CLK_PXA) +=3D pxa/ obj-$(CONFIG_COMMON_CLK_QCOM) +=3D qcom/ obj-y +=3D ralink/ +obj-y +=3D rda/ obj-y +=3D renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) +=3D rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) +=3D samsung/ diff --git a/drivers/clk/rda/Kconfig b/drivers/clk/rda/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..b505e3e552cef1e7ea3da4aa46d= 61d0d0a3d5db0 --- /dev/null +++ b/drivers/clk/rda/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0-only +config CLK_RDA8810 + bool "RDA Micro RDA8810PL Clock and Reset Controller" + depends on ARCH_RDA || COMPILE_TEST + select MFD_SYSCON + select REGMAP_MMIO + select RESET_CONTROLLER + help + This driver supports clock and reset for RDA Micro RDA8810 platform. + If you have a board with the RDA8810PL SoC, say Y to use most of the + board peripherals. + + If unsure, say N. + diff --git a/drivers/clk/rda/Makefile b/drivers/clk/rda/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..98848dccabe5d2199d5e9469d6b= de154b2b3d86a --- /dev/null +++ b/drivers/clk/rda/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_CLK_RDA8810) +=3D clk-rda8810.o diff --git a/drivers/clk/rda/clk-rda8810.c b/drivers/clk/rda/clk-rda8810.c new file mode 100644 index 0000000000000000000000000000000000000000..8d844f30a0deede267fe531dbf7= b370a8328cff0 --- /dev/null +++ b/drivers/clk/rda/clk-rda8810.c @@ -0,0 +1,769 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * RDA8810PL Clock and Reset driver + * + * Copyright (C) 2013 RDA Microelectronics Inc. + * Copyright (c) 2025 Dang Huynh + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MHZ 1000000U + +/* + * Some registers are protected, we need to write AP_CTRL_PROTECT_UNLOCK to + * AP_REG_DBG then we can make changes to them. + */ +#define AP_CTRL_PROTECT_LOCK 0xA50000 +#define AP_CTRL_PROTECT_UNLOCK 0xA50001 + +/* Register Base */ +#define AP_REG_DBG 0x0 +#define AP_REG_CPU_ENABLE 0x60 +#define AP_REG_AXI_ENABLE 0x6C +#define AP_REG_AXIDIV2_ENABLE 0x78 +#define AP_REG_GCG_ENABLE 0x84 +#define AP_REG_AHB1_ENABLE 0x90 +#define AP_REG_APB1_ENABLE 0x9C +#define AP_REG_APB2_ENABLE 0xA8 +#define AP_REG_MEM_ENABLE 0xB4 +#define AP_REG_APO_ENABLE 0xC0 + +/* AP Clk Config Bits */ +#define AP_PERI_SRC_DIV BIT(12) + +/* UART Clock Bits */ +#define AP_UART_DIVIDER GENMASK(9, 0) +#define AP_UART_SET_PLL BIT(12) + +/* AP Clk Enable */ +#define AP_ENABLE_CPU_CORE BIT(0) +#define AP_ENABLE_CPU_DUMMY BIT(1) +#define AP_ENABLE_AHB0_CONF BIT(0) +#define AP_ENABLE_APB0_CONF BIT(1) +#define AP_ENABLE_AXI_VOC BIT(2) +#define AP_ENABLE_AXI_DMA BIT(3) +#define AP_ENABLE_AXI_ALWAYS BIT(4) +#define AP_ENABLE_AXI_CONNECT BIT(5) +#define AP_ENABLE_APB0_IRQ BIT(6) +#define AP_ENABLE_AXIDIV2_IMEM BIT(0) +#define AP_ENABLE_AXIDIV2_ALWAYS BIT(1) +#define AP_ENABLE_AXIDIV2_CONNECT BIT(2) +#define AP_ENABLE_AXIDIV2_VPU BIT(3) +#define AP_ENABLE_GCG_APB_CONF BIT(0) +#define AP_ENABLE_GCG_GOUDA BIT(1) +#define AP_ENABLE_GCG_CAMERA BIT(2) +#define AP_ENABLE_GCG_ALWAYS BIT(3) +#define AP_ENABLE_GCG_CONNECT BIT(4) +#define AP_ENABLE_GCG_DPI BIT(7) +#define AP_ENABLE_AHB1_USBC BIT(0) +#define AP_ENABLE_AHB1_ALWAYS BIT(1) +#define AP_ENABLE_AHB1_SPIFLASH BIT(2) +#define AP_ENABLE_APB1_CONF BIT(0) +#define AP_ENABLE_APB1_AIF BIT(1) +#define AP_ENABLE_APB1_AUIFC BIT(2) +#define AP_ENABLE_APB1_AUIFC_CH0 BIT(3) +#define AP_ENABLE_APB1_AUIFC_CH1 BIT(4) +#define AP_ENABLE_APB1_I2C1 BIT(5) +#define AP_ENABLE_APB1_I2C2 BIT(6) +#define AP_ENABLE_APB1_I2C3 BIT(7) +#define AP_ENABLE_APB1D_OSC BIT(8) +#define AP_ENABLE_APB1D_PWM BIT(9) +#define AP_ENABLE_APB1_ALWAYS BIT(10) +#define AP_ENABLE_APB1_DAPLITE BIT(11) +#define AP_ENABLE_APB1_TIMER BIT(12) +#define AP_ENABLE_APB1_GPIO BIT(13) +#define AP_ENABLE_APB2_CONF BIT(0) +#define AP_ENABLE_APB2_IFC BIT(1) +#define AP_ENABLE_APB2_IFC_CH0 BIT(2) +#define AP_ENABLE_APB2_IFC_CH1 BIT(3) +#define AP_ENABLE_APB2_IFC_CH2 BIT(4) +#define AP_ENABLE_APB2_IFC_CH3 BIT(5) +#define AP_ENABLE_APB2_IFC_CH4 BIT(6) +#define AP_ENABLE_APB2_IFC_CH5 BIT(7) +#define AP_ENABLE_APB2_IFC_CH6 BIT(8) +#define AP_ENABLE_APB2_IFC_CH7 BIT(9) +#define AP_ENABLE_APB2_UART1 BIT(10) +#define AP_ENABLE_APB2_UART2 BIT(11) +#define AP_ENABLE_APB2_UART3 BIT(12) +#define AP_ENABLE_APB2_SPI1 BIT(13) +#define AP_ENABLE_APB2_SPI2 BIT(14) +#define AP_ENABLE_APB2_SPI3 BIT(15) +#define AP_ENABLE_APB2_SDMMC1 BIT(16) +#define AP_ENABLE_APB2_SDMMC2 BIT(17) +#define AP_ENABLE_APB2_SDMMC3 BIT(18) +#define AP_ENABLE_APB2_ALWAYS BIT(19) +#define AP_ENABLE_APB2_NANDFLASH BIT(20) +#define AP_ENABLE_MEM_CONF BIT(0) +#define AP_ENABLE_MEM_DMC BIT(1) +#define AP_ENABLE_MEM_GPU BIT(2) +#define AP_ENABLE_MEM_VPU BIT(3) +#define AP_ENABLE_MEM_DDRPHY_P BIT(4) +#define AP_ENABLE_MEM_CONNECT BIT(5) +#define AP_ENABLE_APOC_VPU BIT(0) +#define AP_ENABLE_APOC_BCK BIT(1) +#define AP_ENABLE_APOC_UART1 BIT(2) +#define AP_ENABLE_APOC_UART2 BIT(3) +#define AP_ENABLE_APOC_UART3 BIT(4) +#define AP_ENABLE_APOC_VOC_CORE BIT(5) +#define AP_ENABLE_APOC_VOC BIT(6) +#define AP_ENABLE_APOC_VOC_ALWAYS BIT(7) +#define AP_ENABLE_APOC_DDRPHY_N BIT(8) +#define AP_ENABLE_APOC_DDRPHY2XP BIT(9) +#define AP_ENABLE_APOC_DDRPHY2XN BIT(10) +#define AP_ENABLE_APOC_GPU BIT(11) +#define AP_ENABLE_APOC_USBPHY BIT(12) +#define AP_ENABLE_APOC_CSI BIT(13) +#define AP_ENABLE_APOC_DSI BIT(14) +#define AP_ENABLE_APOC_GPIO BIT(15) +#define AP_ENABLE_APOC_SPIFLASH BIT(16) +#define AP_ENABLE_APOC_PIX BIT(17) +#define AP_ENABLE_APOC_PDGB BIT(18) + +/* AP Reset */ +#define AP_RST_CPU_REG 0x1C +#define AP_RST_AXI_REG 0x24 +#define AP_RST_AXIDIV2_REG 0x2C +#define AP_RST_GCG_REG 0x34 +#define AP_RST_AHB1_REG 0x3C +#define AP_RST_APB1_REG 0x44 +#define AP_RST_APB2_REG 0x4C +#define AP_RST_MEM_REG 0x54 + +/* Bits */ +#define AP_RST_CPU_CORE BIT(0) +#define AP_RST_CPU_SYS BIT(1) +#define AP_RST_AXI_VOC BIT(0) +#define AP_RST_AXI_DMA BIT(1) +#define AP_RST_AXI_SYS BIT(2) +#define AP_RST_AXI_CONNECT BIT(3) +#define AP_RST_AXI_VPU BIT(5) +#define AP_RST_AXIDIV2_IMEM BIT(0) +#define AP_RST_AXIDIV2_SYS BIT(1) +#define AP_RST_AXIDIV2_VPU BIT(2) +#define AP_RST_GCG_SYS BIT(0) +#define AP_RST_GCG_GOUDA BIT(1) +#define AP_RST_GCG_CAMERA BIT(2) +#define AP_RST_GCG_LCDC BIT(4) +#define AP_RST_AHB1_SYS BIT(0) +#define AP_RST_AHB1_USBC BIT(1) +#define AP_RST_AHB1_SPIFLASH BIT(2) +#define AP_RST_APB1_SYS BIT(0) +#define AP_RST_APB1_TIMER BIT(1) +#define AP_RST_APB1_KEYPAD BIT(2) +#define AP_RST_APB1_GPIO BIT(3) +#define AP_RST_APB1_PWM BIT(4) +#define AP_RST_APB1_AIF BIT(5) +#define AP_RST_APB1_AUIFC BIT(6) +#define AP_RST_APB1_I2C1 BIT(7) +#define AP_RST_APB1_I2C2 BIT(8) +#define AP_RST_APB1_I2C3 BIT(9) +#define AP_RST_APB1_COMREGS BIT(10) +#define AP_RST_APB1_DMC BIT(11) +#define AP_RST_APB1_DDRPHY_P BIT(12) +#define AP_RST_APB2_SYS BIT(0) +#define AP_RST_APB2_IFC BIT(1) +#define AP_RST_APB2_UART1 BIT(2) +#define AP_RST_APB2_UART2 BIT(3) +#define AP_RST_APB2_UART3 BIT(4) +#define AP_RST_APB2_SPI1 BIT(5) +#define AP_RST_APB2_SPI2 BIT(6) +#define AP_RST_APB2_SPI3 BIT(7) +#define AP_RST_APB2_SDMMC1 BIT(8) +#define AP_RST_APB2_SDMMC2 BIT(9) +#define AP_RST_APB2_SDMMC3 BIT(10) +#define AP_RST_APB2_NANDFLASH BIT(11) +#define AP_RST_MEM_SYS BIT(0) +#define AP_RST_MEM_GPU BIT(1) +#define AP_RST_MEM_VPU BIT(2) +#define AP_RST_MEM_DMC BIT(3) +#define AP_RST_MEM_DDRPHY_P BIT(4) + +/* Default PLL frequency */ +#define AP_PLL_CPU_FREQ (988 * MHZ) +#define AP_PLL_BUS_FREQ (800 * MHZ) +#define AP_PLL_MEM_FREQ (260 * MHZ) +#define AP_PLL_USB_FREQ (480 * MHZ) + +struct rda8810_reset_list { + int reg; + int bit; +}; + +struct rda_clk_priv { + struct device *dev; + struct regmap *regmap; + struct clk_hw_onecell_data *onecell; + struct reset_controller_dev rstctl; + const struct rda8810_reset_list *rstlist; +}; + +struct rda_clk_hw { + int id; + int reg; + struct clk_hw hw; + + int ena_reg; + int ena_bit; + + struct rda_clk_priv *priv; +}; + +struct rda_clk_matchdata { + const struct rda_clk_hw *clk_list; + int max_clocks; +}; + +static const struct clk_ops rda8810_clk_ops; + +#define RDA_CLK_INIT(_id, _name, _parent, _flags, _reg, _ena_reg, _ena_bit= ) { \ + .id =3D _id, \ + .reg =3D _reg, \ + .ena_reg =3D _ena_reg, \ + .ena_bit =3D _ena_bit, \ + .hw.init =3D CLK_HW_INIT_PARENTS_DATA(_name, \ + _parent, \ + &rda8810_clk_ops, \ + _flags) \ +} + +#define RDA_CLK_INIT_NO_PARENT(_id, _name, _flags, _reg, _ena_reg, _ena_bi= t) { \ + .id =3D _id, \ + .reg =3D _reg, \ + .ena_reg =3D _ena_reg, \ + .ena_bit =3D _ena_bit, \ + .hw.init =3D CLK_HW_INIT_NO_PARENT(_name, &rda8810_clk_ops, _flags) \ +} + +#define to_rda_rst(p) container_of(p, struct rda_clk_priv, rstctl) + +static inline struct rda_clk_hw *to_rda_hw(struct clk_hw *hw) +{ + return container_of(hw, struct rda_clk_hw, hw); +} + +/* clock division value map */ +static const u8 clk_div_map[] =3D { + 4*60, /* 0 */ + 4*60, /* 1 */ + 4*60, /* 2 */ + 4*60, /* 3 */ + 4*60, /* 4 */ + 4*60, /* 5 */ + 4*60, /* 6 */ + 4*60, /* 7 */ + 4*40, /* 8 */ + 4*30, /* 9 */ + 4*24, /* 10 */ + 4*20, /* 11 */ + 4*17, /* 12 */ + 4*15, /* 13 */ + 4*13, /* 14 */ + 4*12, /* 15 */ + 4*11, /* 16 */ + 4*10, /* 17 */ + 4*9, /* 18 */ + 4*8, /* 19 */ + 4*7, /* 20 */ + 4*13/2, /* 21 */ + 4*6, /* 22 */ + 4*11/2, /* 23 */ + 4*5, /* 24 */ + 4*9/2, /* 25 */ + 4*4, /* 26 */ + 4*7/2, /* 27 */ + 4*3, /* 28 */ + 4*5/2, /* 29 */ + 4*2, /* 30 */ + 4*1, /* 31 */ +}; + +static u32 apsys_get_divreg(u32 basefreq, u32 reqfreq, u32 *pdiv2) +{ + int i; + int index; + u32 adiv; + u32 ndiv; + + adiv =3D basefreq / (reqfreq >> 2); + if (pdiv2) { + /* try div2 mode first */ + ndiv =3D adiv >> 1; + } else { + ndiv =3D adiv; + } + + for (i =3D ARRAY_SIZE(clk_div_map) - 1; i >=3D 1; i--) + if (ndiv < ((clk_div_map[i] + clk_div_map[i-1]) >> 1)) + break; + index =3D i; + + if (pdiv2) { + if (adiv =3D=3D (clk_div_map[index] << 1)) { + /* div2 mode is OK */ + *pdiv2 =3D 1; + } else { + /* try div1 mode */ + for (i =3D ARRAY_SIZE(clk_div_map) - 1; i >=3D 1; i--) + if (adiv < ((clk_div_map[i] + clk_div_map[i-1]) >> 1)) + break; + /* compare the results between div1 and div2 */ + if (abs(adiv - (clk_div_map[index] << 1)) <=3D + abs(adiv - clk_div_map[i])) { + *pdiv2 =3D 1; + } else { + *pdiv2 =3D 0; + index =3D i; + } + } + } + + return index; +} + +static u32 apsys_cal_freq_by_divreg(u32 basefreq, u32 reg, u32 div2) +{ + u32 newfreq; + + if (reg >=3D ARRAY_SIZE(clk_div_map)) + reg =3D ARRAY_SIZE(clk_div_map) - 1; + + /* Assuming basefreq is smaller than 2^31 (2.147G Hz) */ + newfreq =3D (basefreq << (div2 ? 0 : 1)) / (clk_div_map[reg] >> 1); + return newfreq; +} + +static void apsys_get_reg_div(struct rda_clk_hw *rda_hw, u32 *reg, u32 *di= v2) +{ + struct rda_clk_priv *priv =3D rda_hw->priv; + int tmp_reg, tmp_div2; + int ret; + + ret =3D regmap_read(priv->regmap, rda_hw->reg, &tmp_reg); + if (ret) + return; + + tmp_div2 =3D tmp_reg & AP_PERI_SRC_DIV; + + *reg =3D tmp_reg; + *div2 =3D tmp_div2; +} + +static int apsys_get_uart_clock(unsigned long parent_rate, u32 *reg) +{ + int clksrc =3D 26000000; + u32 div; + int rate =3D 0; + + if (*reg & AP_UART_SET_PLL) + clksrc =3D parent_rate / 8; + + div =3D FIELD_GET(AP_UART_DIVIDER, *reg); + + /* rate =3D clksrc / divmode / (div+2) */ + rate =3D clksrc / 4 / (div + 2); + + return rate; +} + +static int apsys_cal_uart_clock(int freq) +{ + int new_freq =3D freq; + + /* + * To calculate maximum clock: + * freq =3D 26 MHz / div / (0 + 2) + * + * For lowest clock: + * freq =3D 26 MHz / div / (0x3FF + 2) + */ + if (freq > 3250000) + new_freq =3D 3250000; + else if (freq < 6342) + new_freq =3D 6342; + + new_freq =3D (26000000 + 4 / 2 * new_freq) / (4 * new_freq) - 2; + + return new_freq; +} + +static int rda8810_clk_set_rate(struct clk_hw *clk, unsigned long rate, + unsigned long parent_rate) +{ + struct rda_clk_hw *rda_hw =3D to_rda_hw(clk); + struct rda_clk_priv *priv =3D rda_hw->priv; + struct device *dev =3D priv->dev; + int val, div2 =3D 0; + int ret; + + switch (rda_hw->id) { + case CLK_CPU: + val =3D apsys_get_divreg(AP_PLL_CPU_FREQ, rate, NULL); + break; + case CLK_AXI: + case CLK_AHB1: + case CLK_APB1: + case CLK_APB2: + case CLK_GCG: + case CLK_GPU: + case CLK_SFLSH: + case CLK_VOC: + case CLK_VPU: + val =3D apsys_get_divreg(parent_rate, rate, &div2); + break; + case CLK_UART1: + case CLK_UART2: + case CLK_UART3: + val =3D apsys_cal_uart_clock(rate); + if (val =3D=3D 0) + return -EINVAL; + break; + default: + return -EINVAL; + } + + if (div2) + val |=3D AP_PERI_SRC_DIV; + + dev_dbg(dev, "clk_id: %d - rate: %ld - parent rate: %ld - val: %d - div: = %d\n", + rda_hw->id, rate, parent_rate, val, div2); + + ret =3D regmap_write(priv->regmap, rda_hw->reg, val); + if (ret < 0) + return ret; + + return rate; +} + +static unsigned long rda8810_clk_recalc_rate(struct clk_hw *clk, + unsigned long parent_rate) +{ + struct rda_clk_hw *rda_hw =3D to_rda_hw(clk); + u32 reg, div2; + + apsys_get_reg_div(rda_hw, ®, &div2); + + switch (rda_hw->id) { + case CLK_CPU: + return apsys_cal_freq_by_divreg(AP_PLL_CPU_FREQ, reg, 0); + case CLK_BUS: + return AP_PLL_BUS_FREQ; + case CLK_MEM: + return AP_PLL_MEM_FREQ >> (2 + div2); + /* Bus peripherals */ + case CLK_USB: + return AP_PLL_USB_FREQ; + case CLK_AXI: + case CLK_AHB1: + case CLK_APB1: + case CLK_APB2: + case CLK_GCG: + case CLK_GPU: + case CLK_SFLSH: + case CLK_VOC: + case CLK_VPU: + return apsys_cal_freq_by_divreg(parent_rate, reg, div2); + /* For UART clocks, we'll have to do more calculation */ + case CLK_UART1: + case CLK_UART2: + case CLK_UART3: + return apsys_get_uart_clock(parent_rate, ®); + default: + return 0; + } +} + +static long rda8810_clk_round_rate(struct clk_hw *clk, unsigned long rate, + unsigned long *parent_rate) +{ + return rate; +} + +static int rda8810_clk_enable(struct clk_hw *clk) +{ + struct rda_clk_hw *rda_hw =3D to_rda_hw(clk); + struct rda_clk_priv *priv =3D rda_hw->priv; + + if (rda_hw->ena_reg < 0 || rda_hw->ena_bit < 0) + return 0; + + return regmap_write(priv->regmap, rda_hw->ena_reg, rda_hw->ena_bit); +} + +static void rda8810_clk_disable(struct clk_hw *clk) +{ + struct rda_clk_hw *rda_hw =3D to_rda_hw(clk); + struct rda_clk_priv *priv =3D rda_hw->priv; + + if (rda_hw->ena_reg < 0 || rda_hw->ena_bit < 0) + return; + + regmap_write(priv->regmap, rda_hw->ena_reg + 4, rda_hw->ena_bit); +} + +static const struct clk_ops rda8810_clk_ops =3D { + .enable =3D rda8810_clk_enable, + .disable =3D rda8810_clk_disable, + + .recalc_rate =3D rda8810_clk_recalc_rate, + .round_rate =3D rda8810_clk_round_rate, + .set_rate =3D rda8810_clk_set_rate, +}; + +/* Root clocks */ +static struct rda_clk_hw rda8810_clk_cpu_desc =3D +RDA_CLK_INIT_NO_PARENT(CLK_CPU, "cpu", CLK_IS_CRITICAL, 0xC8, + AP_REG_CPU_ENABLE, AP_ENABLE_CPU_CORE); +static struct rda_clk_hw rda8810_clk_mem_desc =3D +RDA_CLK_INIT_NO_PARENT(CLK_MEM, "mem", CLK_IS_CRITICAL, 0xE0, -1, -1); + +static struct rda_clk_hw rda8810_clk_bus_desc =3D +RDA_CLK_INIT_NO_PARENT(CLK_BUS, "bus", CLK_IS_CRITICAL, -1, -1, -1); + +/* Bus clocks */ +static struct rda_clk_hw rda8810_clk_usb_desc =3D RDA_CLK_INIT(CLK_USB, "u= sb", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, -1, -1, -1); +static struct rda_clk_hw rda8810_clk_axi_desc =3D RDA_CLK_INIT(CLK_AXI, "a= xi", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xCC, -1, -1); +static struct rda_clk_hw rda8810_clk_gcg_desc =3D RDA_CLK_INIT(CLK_GCG, "g= cg", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xD0, -1, -1); +static struct rda_clk_hw rda8810_clk_ahb1_desc =3D RDA_CLK_INIT(CLK_AHB1, = "ahb1", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xD4, -1, -1); +static struct rda_clk_hw rda8810_clk_apb1_desc =3D RDA_CLK_INIT(CLK_APB1, = "apb1", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xD8, -1, -1); +static struct rda_clk_hw rda8810_clk_apb2_desc =3D RDA_CLK_INIT(CLK_APB2, = "apb2", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xDC, -1, -1); +static struct rda_clk_hw rda8810_clk_gpu_desc =3D RDA_CLK_INIT(CLK_GPU, "g= pu", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xE4, AP_REG_APO_ENABLE, AP_ENABLE_APOC_GPU); +static struct rda_clk_hw rda8810_clk_vpu_desc =3D RDA_CLK_INIT(CLK_VPU, "v= pu", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xE8, AP_REG_APO_ENABLE, AP_ENABLE_APOC_VPU); +static struct rda_clk_hw rda8810_clk_voc_desc =3D RDA_CLK_INIT(CLK_VOC, "v= oc", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_bus_desc.hw } = }, + 0, 0xEC, AP_REG_APO_ENABLE, + AP_ENABLE_APOC_VOC | AP_ENABLE_APOC_VOC_CORE | AP_ENABLE_APOC_VOC_ALWAYS= ); + +/* APB1 peripherals */ +static struct rda_clk_hw rda8810_clk_spiflash_desc =3D RDA_CLK_INIT(CLK_SF= LSH, "spiflash", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_apb1_desc.hw }= }, + 0, 0xF0, AP_REG_APO_ENABLE, AP_ENABLE_APOC_SPIFLASH); + +/* APB2 peripherals */ +static struct rda_clk_hw rda8810_clk_uart_desc[] =3D { + RDA_CLK_INIT(CLK_UART1, "uart1", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_apb2_desc.hw = } }, + 0, 0xF4, + AP_REG_APO_ENABLE, AP_ENABLE_APOC_UART1), + RDA_CLK_INIT(CLK_UART2, "uart2", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_apb2_desc.hw = } }, + 0, 0xF8, + AP_REG_APO_ENABLE, AP_ENABLE_APOC_UART2), + RDA_CLK_INIT(CLK_UART3, "uart3", + (const struct clk_parent_data[]) { { .hw =3D &rda8810_clk_apb2_desc.hw = } }, + 0, 0xFC, + AP_REG_APO_ENABLE, AP_ENABLE_APOC_UART3), +}; + +static struct rda_clk_hw *const rda8810_clk_list[] =3D { + &rda8810_clk_cpu_desc, + &rda8810_clk_bus_desc, + &rda8810_clk_mem_desc, + + &rda8810_clk_usb_desc, + &rda8810_clk_axi_desc, + &rda8810_clk_gcg_desc, + &rda8810_clk_ahb1_desc, + &rda8810_clk_apb1_desc, + &rda8810_clk_apb2_desc, + + &rda8810_clk_gpu_desc, + &rda8810_clk_vpu_desc, + &rda8810_clk_voc_desc, + + &rda8810_clk_spiflash_desc, + + &rda8810_clk_uart_desc[0], + &rda8810_clk_uart_desc[1], + &rda8810_clk_uart_desc[2], +}; + +static const struct rda8810_reset_list rda8810_rst_data[] =3D { + /* ID, REG */ + + /* CPU */ + [RST_CPU] =3D { AP_RST_CPU_REG, AP_RST_CPU_CORE }, + + /* AXI */ + [RST_AXI_VOC] =3D { AP_RST_AXI_REG, AP_RST_AXI_VOC }, + [RST_AXI_DMA] =3D { AP_RST_AXI_REG, AP_RST_AXI_DMA }, + [RST_AXI_CONNECT] =3D { AP_RST_AXI_REG, AP_RST_AXI_CONNECT }, + [RST_AXI_VPU] =3D { AP_RST_AXI_REG, AP_RST_AXI_VPU }, + + /* GCG */ + [RST_GCG_GOUDA] =3D { AP_RST_GCG_REG, AP_RST_GCG_GOUDA }, + [RST_GCG_CAMERA] =3D { AP_RST_GCG_REG, AP_RST_GCG_CAMERA }, + [RST_GCG_LCDC] =3D { AP_RST_GCG_REG, AP_RST_GCG_LCDC }, + + /* AHB1 */ + [RST_AHB1_USBC] =3D { AP_RST_AHB1_REG, AP_RST_AHB1_USBC }, + [RST_AHB1_SPIFLASH] =3D { AP_RST_AHB1_REG, AP_RST_AHB1_SPIFLASH }, + + /* APB1 */ + [RST_APB1_TIMER] =3D { AP_RST_APB1_REG, AP_RST_APB1_TIMER }, + [RST_APB1_KEYPAD] =3D { AP_RST_APB1_REG, AP_RST_APB1_KEYPAD }, + [RST_APB1_GPIO] =3D { AP_RST_APB1_REG, AP_RST_APB1_GPIO }, + [RST_APB1_PWM] =3D { AP_RST_APB1_REG, AP_RST_APB1_PWM }, + [RST_APB1_AIF] =3D { AP_RST_APB1_REG, AP_RST_APB1_AIF }, + [RST_APB1_AUIFC] =3D { AP_RST_APB1_REG, AP_RST_APB1_AUIFC }, + [RST_APB1_I2C1] =3D { AP_RST_APB1_REG, AP_RST_APB1_I2C1 }, + [RST_APB1_I2C2] =3D { AP_RST_APB1_REG, AP_RST_APB1_I2C2 }, + [RST_APB1_I2C3] =3D { AP_RST_APB1_REG, AP_RST_APB1_I2C3 }, + [RST_APB1_COMREGS] =3D { AP_RST_APB1_REG, AP_RST_APB1_COMREGS }, + [RST_APB1_DMC] =3D { AP_RST_APB1_REG, AP_RST_APB1_DMC }, + [RST_APB1_DDRPHY_P] =3D { AP_RST_APB1_REG, AP_RST_APB1_DDRPHY_P }, + + /* APB2 */ + [RST_APB2_IFC] =3D { AP_RST_APB2_REG, AP_RST_APB2_IFC }, + [RST_APB2_UART1] =3D { AP_RST_APB2_REG, AP_RST_APB2_UART1 }, + [RST_APB2_UART2] =3D { AP_RST_APB2_REG, AP_RST_APB2_UART2 }, + [RST_APB2_UART3] =3D { AP_RST_APB2_REG, AP_RST_APB2_UART3 }, + [RST_APB2_SPI1] =3D { AP_RST_APB2_REG, AP_RST_APB2_SPI1 }, + [RST_APB2_SPI2] =3D { AP_RST_APB2_REG, AP_RST_APB2_SPI2 }, + [RST_APB2_SPI3] =3D { AP_RST_APB2_REG, AP_RST_APB2_SPI3 }, + [RST_APB2_SDMMC1] =3D { AP_RST_APB2_REG, AP_RST_APB2_SDMMC1 }, + [RST_APB2_SDMMC2] =3D { AP_RST_APB2_REG, AP_RST_APB2_SDMMC2 }, + [RST_APB2_SDMMC3] =3D { AP_RST_APB2_REG, AP_RST_APB2_SDMMC3 }, + [RST_APB2_NAND] =3D { AP_RST_APB2_REG, AP_RST_APB2_NANDFLASH }, + + /* MEM */ + [RST_MEM_GPU] =3D { AP_RST_MEM_REG, AP_RST_MEM_GPU }, + [RST_MEM_VPU] =3D { AP_RST_MEM_REG, AP_RST_MEM_VPU }, + [RST_MEM_DMC] =3D { AP_RST_MEM_REG, AP_RST_MEM_DMC }, + [RST_MEM_DDRPHY_P] =3D { AP_RST_MEM_REG, AP_RST_MEM_DDRPHY_P }, +}; + +static int rda8810_reset_assert(struct reset_controller_dev *rstctl, unsig= ned long id) +{ + struct rda_clk_priv *priv =3D to_rda_rst(rstctl); + + return regmap_write(priv->regmap, rda8810_rst_data[id].reg, rda8810_rst_d= ata[id].bit); +} + +static int rda8810_reset_deassert(struct reset_controller_dev *rstctl, uns= igned long id) +{ + struct rda_clk_priv *priv =3D to_rda_rst(rstctl); + + return regmap_write(priv->regmap, rda8810_rst_data[id].reg + 4, rda8810_r= st_data[id].bit); +} + +static const struct reset_control_ops rda8810_rst_ops =3D { + .assert =3D &rda8810_reset_assert, + .deassert =3D &rda8810_reset_deassert, +}; + +static int rda8810_clk_register(struct rda_clk_priv *priv) +{ + struct device *dev =3D priv->dev; + struct clk_hw_onecell_data *onecell_data; + int ret; + int i; + + onecell_data =3D devm_kzalloc(dev, + struct_size(onecell_data, hws, ARRAY_SIZE(rda8810_clk_list)), + GFP_KERNEL); + if (!onecell_data) + return -ENOMEM; + + for (i =3D 0; i < ARRAY_SIZE(rda8810_clk_list); i++) { + rda8810_clk_list[i]->priv =3D priv; + + ret =3D devm_clk_hw_register(dev, &rda8810_clk_list[i]->hw); + if (ret) { + dev_err(dev, "Failed to register clock: %d\n", ret); + return ret; + } + onecell_data->hws[i] =3D &rda8810_clk_list[i]->hw; + } + onecell_data->num =3D i; + priv->onecell =3D onecell_data; + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, onecell_da= ta); +} + +static int rda8810_rst_register(struct rda_clk_priv *priv) +{ + struct device *dev =3D priv->dev; + + priv->rstctl.dev =3D priv->dev; + priv->rstctl.nr_resets =3D 37; + priv->rstctl.of_node =3D priv->dev->of_node; + priv->rstctl.ops =3D &rda8810_rst_ops; + priv->rstctl.owner =3D THIS_MODULE; + + return devm_reset_controller_register(dev, &priv->rstctl); +} + +static int rda8810_clk_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct rda_clk_priv *priv; + int ret; + + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return dev_err_probe(dev, -ENOMEM, "Cannot allocate memory\n"); + + priv->dev =3D dev; + + priv->regmap =3D syscon_node_to_regmap(dev->of_node); + if (IS_ERR(priv->regmap)) + return dev_err_probe(dev, -ENOMEM, "Cannot initialize regmap\n"); + + ret =3D rda8810_clk_register(priv); + if (ret) + return dev_err_probe(dev, -EINVAL, "Failed to setup clock: %d\n", ret); + + ret =3D rda8810_rst_register(priv); + if (ret) + return dev_err_probe(dev, -EINVAL, "Failed to setup reset: %d\n", ret); + + platform_set_drvdata(pdev, priv); + + return 0; +} + +static const struct of_device_id rda8810_clk_of_match_table[] =3D { + { .compatible =3D "rda,8810pl-apsyscon", }, + { } +}; +MODULE_DEVICE_TABLE(of, rda8810_clk_of_match_table); + +static struct platform_driver rda8810_clk_driver =3D { + .probe =3D rda8810_clk_probe, + .driver =3D { + .name =3D "rda8810-clk", + .of_match_table =3D rda8810_clk_of_match_table, + }, +}; +module_platform_driver(rda8810_clk_driver); + +MODULE_AUTHOR("Dang Huynh "); +MODULE_DESCRIPTION("RDA8810PL clock and reset driver"); +MODULE_LICENSE("GPL"); --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 C38502D94B4; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=mPx3ujCNr+CUz9NISn6rUuR6U+E+uSJqFeWDbgrUMT6JJNaPTxNe3ekT9IE28GlPem+D8NDqvFNOd95tTavaVp2Sbew6PSJHGnoS0z/4Sl6LcEFDQ0/C1LE7u83vYWwwOhhegCjOPvBBVbFph8Kg7IrMBZyks3mZ4zuDqpuQFpk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=yNTiQno8EMpzb+4TM3qaxKc6MHmeWetWrmZsuenD5aY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LWvsf61mw2Z3AGdUNuYWRkNXK+Cx3ZWuB4NAHq/FON0Sr3R5NY5KEbaUKalYIuyQJJhP3/aaM7R5BsSQzUuzl4CC8xy1kmm8K8q9SxnjCZbOZ4R/WdW4QRTPazTOF9mPBGo5szqO5F1X/R5AN9OPw0eNUWSA3jRFosvGcUpYQBE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=c0hKYFdK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="c0hKYFdK" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5CF80C2BCB1; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=yNTiQno8EMpzb+4TM3qaxKc6MHmeWetWrmZsuenD5aY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=c0hKYFdKYKhSlSu/I2sX0hLtIQIIsv/JUCHqpRVYHyIsi03GqQM0MlY2LFU5TIFpA +cugHeUTemcLhwdjTdXLh0qZ20QB1yk1lHhOYJ2Y4lxAv4v0QffDS3Xjunc98afWnw OKl2s7qdmgShl3MO/ml6O8vzLkDZsuewM0OkOtBFntmzSVNmm4f1/+9l7HtWGtFnUY g/BInG5hYatbk2x8UnU9Z4qSFLhQyV3iLFn4K7FPKWv9K65Kwet1ofirh3vRPdIV8O AI+B7RS97WjL2+cxlKc2+ZbnUK7nk5d7XrV8Acs47G0s4EX7Uhsnt33Wyg/+Je9Z8F ImBBppn3rUkOw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 523E6CAC597; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:48 +0700 Subject: [PATCH 08/10] dmaengine: Add RDA IFC driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-8-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=14920; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=iJgPtPu12ozNppbSOcC9VU0IgABxZvXIWrb3FjIHPOU=; b=lUwSgTrYVqNWGOWIoc6XEBBlk+WCXq6r/3mzPM/qenzyQUwim9Yr5n6xtUTj2/b51cSnAYmHj Q93fr5lCj5RDF0Y0UqIpdWkaFnp87yqHf1VKOvwUzMFSvTwi4advmjX X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh IFC stands for Intelligent Flow Control, a scatter/gather DMA controller. Signed-off-by: Dang Huynh --- MAINTAINERS | 6 + drivers/dma/Kconfig | 10 ++ drivers/dma/Makefile | 1 + drivers/dma/rda-ifc.c | 450 ++++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 467 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 56f9d19fbf421eefffe554987e14604c764daab2..923101a9d6c2edea339d1211b1c= fdf4b917d1208 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21424,6 +21424,12 @@ S: Maintained F: Documentation/devicetree/bindings/clock/rda,8810pl-apsyscon.yaml F: drivers/clk/rda/clk-rda8810.c =20 +RDA MICRO INTELLIGENT FLOW CONTROLLER DRIVER +M: Dang Huynh +S: Maintained +F: Documentation/devicetree/bindings/dma/rda,ifc.yaml +F: drivers/dma/rda-ifc.c + RDACM20 Camera Sensor M: Jacopo Mondi M: Kieran Bingham diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index b8a74b1798ba1d44b26553990428c065de6fc535..b6b94cb053bd0d6a15d3c603bfa= b9b515020fad8 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -571,6 +571,16 @@ config PLX_DMA These are exposed via extra functions on the switch's upstream port. Each function exposes one DMA channel. =20 +config RDA_IFC + bool "RDA IFC support" + depends on ARCH_RDA || COMPILE_TEST + select DMA_ENGINE + help + Support RDA Intelligent Flow Controller for RDA Micro SoC. + The Intelligent Flow Controller is a scatter/gather DMA controller. + + If unsure, say N. + config SOPHGO_CV1800B_DMAMUX tristate "Sophgo CV1800/SG2000 series SoC DMA multiplexer support" depends on MFD_SYSCON diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index a54d7688392b1a0e956fa5d23633507f52f017d9..40f6c61dcce739f3ffd064fbdc2= 3388cfca83184 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_PL330_DMA) +=3D pl330.o obj-$(CONFIG_PLX_DMA) +=3D plx_dma.o obj-$(CONFIG_PPC_BESTCOMM) +=3D bestcomm/ obj-$(CONFIG_PXA_DMA) +=3D pxa_dma.o +obj-$(CONFIG_RDA_IFC) +=3D rda-ifc.o obj-$(CONFIG_RENESAS_DMA) +=3D sh/ obj-$(CONFIG_SF_PDMA) +=3D sf-pdma/ obj-$(CONFIG_SOPHGO_CV1800B_DMAMUX) +=3D cv1800b-dmamux.o diff --git a/drivers/dma/rda-ifc.c b/drivers/dma/rda-ifc.c new file mode 100644 index 0000000000000000000000000000000000000000..ff7f59876a5895fbdc1adf584e1= 1519bcfcfdb11 --- /dev/null +++ b/drivers/dma/rda-ifc.c @@ -0,0 +1,450 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * RDA Micro Intelligent Flow Controller + * + * Copyright (C) 2013 RDA Microelectronics Inc. + * Copyright (C) 2025 Dang Huynh + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dmaengine.h" + +#include + +/* Registers */ +#define IFC_REG_GET_CH 0x0 +#define IFC_REG_DMA_STATUS 0x4 +#define IFC_REG_DEBUG_STATUS 0x8 + +/* Channel registers */ +#define IFC_REG_SG_CONTROL 0x0 +#define IFC_REG_SG_STATUS 0x4 +#define IFC_REG_SG_START_ADDR 0x8 +#define IFC_REG_SG_TC 0xC + +#define IFC_REG_CH_RFSPI_CONTROL 0x80 +#define IFC_REG_CH_RFSPI_STATUS 0x84 +#define IFC_REG_CH_RFSPI_START_ADDR 0x88 +#define IFC_REG_CH_RFSPI_END_ADDR 0x8C +#define IFC_REG_CH_RFSPI_TC 0x90 + +/* Bits */ +/* DMA_STATUS */ +#define IFC_DMA_CH_ENABLE GENMASK(8, 0) +#define IFC_DMA_CH_BUSY GENMASK(23, 16) +/* DEBUG_STATUS */ +#define IFC_DBG_STATUS BIT(0) +/* CONTROL */ +#define IFC_CTL_ENABLE BIT(0) +#define IFC_CTL_DISABLE BIT(1) +#define IFC_CTL_CH_RD_HW_EXCH BIT(2) +#define IFC_CTL_CH_WR_HW_EXCH BIT(3) +#define IFC_CTL_AUTODISABLE BIT(4) +#define IFC_CTL_SIZE GENMASK(7, 5) /* byte: 0 - halfword: 1 - word: 2 */ +#define IFC_CTL_REQ_SRC GENMASK(15, 8) +#define IFC_CTL_FLUSH BIT(16) +#define IFC_CTL_SG_NUM GENMASK(24, 17) +/* STATUS */ +#define IFC_STATUS_ENABLE BIT(0) +#define IFC_STATUS_FIFO_EMPTY BIT(4) + +/* + * An available IFC channel can be obtained by reading IFC_REG_GET_CH regi= ster, + * if no channel are available the register reads 0xF. + * + * Memory map for each channel (starts at 0x10): + * + * [IFC_REG_SG_CONTROL] + * [IFC_REG_SG_STATUS] + * [IFC_REG_SG_START_ADDR] (1st sg_table) + * [IFC_REG_SG_TC] + * ... + * + * Depends on the hardware, it might support more than one sg table. If it + * does, the next sg table is right next to previous table. + * + * The next channel is right after the memory map above. + * + * The DMA channel MUST be disabled after the transaction is done or some = IP + * might misbehaves. + */ + +struct rda_ifc_chan { + struct rda_ifc *rda_ifc; + void __iomem *chan_base; + spinlock_t lock; + + struct dma_chan chan; + unsigned int request_id; + + enum dma_transfer_direction direction; + struct dma_slave_config sconfig; + struct dma_async_tx_descriptor tx; +}; + +struct rda_ifc { + struct device *dev; + void __iomem *base; + + struct dma_device ddev; + + int sg_max; + int max_chan; + struct rda_ifc_chan channels[] __counted_by(max_chan); +}; + +struct rda_ifc_platinfo { + int sg_max; + int std_channb; +}; + +static struct rda_ifc_chan *to_ifc_chan(struct dma_chan *chan) +{ + return container_of(chan, struct rda_ifc_chan, chan); +} + +static int rda_ifc_device_config(struct dma_chan *chan, struct dma_slave_c= onfig *config) +{ + struct rda_ifc_chan *ifc_chan =3D to_ifc_chan(chan); + + ifc_chan->direction =3D (ifc_chan->request_id & 1) ? DMA_DEV_TO_MEM : DMA= _MEM_TO_DEV; + memcpy(&ifc_chan->sconfig, config, sizeof(*config)); + + return 0; +} + +static void rda_ifc_issue_pending(struct dma_chan *chan) +{ + struct rda_ifc_chan *ifc_chan =3D to_ifc_chan(chan); + unsigned long flags; + u32 control; + + spin_lock_irqsave(&ifc_chan->lock, flags); + + control =3D readl(ifc_chan->chan_base); + control |=3D IFC_CTL_ENABLE; + writel(control, ifc_chan->chan_base); + + spin_unlock_irqrestore(&ifc_chan->lock, flags); +} + +static dma_cookie_t rda_ifc_tx_submit(struct dma_async_tx_descriptor *tx) +{ + return dma_cookie_assign(tx); +} + +static struct dma_async_tx_descriptor *rda_ifc_prep_slave_sg(struct dma_ch= an *chan, + struct scatterlist *sgl, unsigned int sg_len, + enum dma_transfer_direction direction, unsigned long dma_flags, + void *context) +{ + struct rda_ifc_chan *ifc_chan =3D to_ifc_chan(chan); + struct rda_ifc *ifc =3D ifc_chan->rda_ifc; + struct device *dev =3D dmaengine_get_dma_device(chan); + struct scatterlist *sg; + unsigned long flags; + u32 control =3D 0; + int width; + int i; + + if (sg_len > ifc->sg_max) { + dev_err(dev, "sg_len %d overflowed (max sg %d)\n", + sg_len, ifc->sg_max); + return NULL; + } + + if (direction !=3D ifc_chan->direction) { + dev_err(dev, "Inconsistent transfer direction\n"); + return NULL; + } + + spin_lock_irqsave(&ifc_chan->lock, flags); + + if (ifc_chan->direction =3D=3D DMA_DEV_TO_MEM) + width =3D ifc_chan->sconfig.src_addr_width; + else + width =3D ifc_chan->sconfig.dst_addr_width; + + switch (width) { + case DMA_SLAVE_BUSWIDTH_1_BYTE: + control |=3D FIELD_PREP(IFC_CTL_SIZE, 0); + break; + case DMA_SLAVE_BUSWIDTH_2_BYTES: + control |=3D FIELD_PREP(IFC_CTL_SIZE, 1); + break; + case DMA_SLAVE_BUSWIDTH_4_BYTES: + control |=3D FIELD_PREP(IFC_CTL_SIZE, 2); + break; + default: + return NULL; + } + + for_each_sg(sgl, sg, sg_len, i) { + if (!IS_ALIGNED(sg_dma_address(sg), width)) { + dev_err(dev, "Unaligned DMA address\n"); + spin_unlock_irqrestore(&ifc_chan->lock, flags); + return NULL; + } + + writel(sg_dma_address(sg), ifc_chan->chan_base + IFC_REG_SG_START_ADDR += (8 * i)); + writel(sg_dma_len(sg), ifc_chan->chan_base + IFC_REG_SG_TC + (8 * i)); + } + + control |=3D FIELD_PREP(IFC_CTL_REQ_SRC, ifc_chan->request_id) | + IFC_CTL_CH_RD_HW_EXCH | + FIELD_PREP(IFC_CTL_SG_NUM, sg_len-1); + writel(control, ifc_chan->chan_base); + + spin_unlock_irqrestore(&ifc_chan->lock, flags); + + dma_async_tx_descriptor_init(&ifc_chan->tx, chan); + ifc_chan->tx.tx_submit =3D rda_ifc_tx_submit; + + return &ifc_chan->tx; +} + +static enum dma_status rda_ifc_tx_status(struct dma_chan *chan, dma_cookie= _t cookie, + struct dma_tx_state *tx_state) +{ + struct rda_ifc_chan *ifc_chan =3D to_ifc_chan(chan); + enum dma_status dmaret; + unsigned long flags; + u32 status; + int residue =3D 0; + int tmp_residue =3D 0; + int i; + + dmaret =3D dma_cookie_status(chan, cookie, tx_state); + if (!tx_state || (dmaret =3D=3D DMA_COMPLETE)) + return dmaret; + + spin_lock_irqsave(&ifc_chan->lock, flags); + + status =3D readl(ifc_chan->chan_base + 4); + + if (status & IFC_STATUS_FIFO_EMPTY) + dmaret =3D DMA_COMPLETE; + else + dmaret =3D DMA_IN_PROGRESS; + + if (dmaret =3D=3D DMA_IN_PROGRESS) { + /* gather residue from all sg */ + for (i =3D 0; i < ifc_chan->rda_ifc->sg_max; i++) { + tmp_residue =3D readl(ifc_chan->chan_base + 12 + (8 * i)); + residue +=3D tmp_residue; + } + + dma_set_residue(tx_state, residue); + } + + spin_unlock_irqrestore(&ifc_chan->lock, flags); + + return dmaret; +} + +static int rda_ifc_terminate_all(struct dma_chan *chan) +{ + struct rda_ifc_chan *ifc_chan =3D to_ifc_chan(chan); + struct device *dev =3D dmaengine_get_dma_device(chan); + unsigned long flags; + u32 status, control; + int ret; + int i; + + spin_lock_irqsave(&ifc_chan->lock, flags); + + status =3D readl(ifc_chan->chan_base + 4); + + /* Flush operation only supports read requests */ + if (ifc_chan->direction =3D=3D DMA_DEV_TO_MEM) { + if (status & IFC_STATUS_FIFO_EMPTY) + goto clear_chan; + + control =3D readl(ifc_chan->chan_base); + control |=3D IFC_CTL_FLUSH; + writel(control, ifc_chan->chan_base); + + ret =3D readl_poll_timeout(ifc_chan->chan_base + 4, status, + (status & IFC_STATUS_FIFO_EMPTY), 100, 1000*1000); + if (ret < 0) + dev_err(dev, "Timed out flushing FIFO\n"); + } + +clear_chan: + control =3D readl(ifc_chan->chan_base); + control |=3D IFC_CTL_DISABLE; + writel(control, ifc_chan->chan_base); + + for (i =3D 0; i < ifc_chan->rda_ifc->sg_max; i++) + writel(0, ifc_chan->chan_base + 12 + (8 * i)); + + spin_unlock_irqrestore(&ifc_chan->lock, flags); + return 0; +} + +static int rda_ifc_chan_init(struct rda_ifc *ifc, struct dma_device *ddev, + int id) +{ + struct rda_ifc_chan *chan =3D &ifc->channels[id]; + + spin_lock_init(&chan->lock); + chan->rda_ifc =3D ifc; + chan->chan.chan_id =3D id; + chan->chan.device =3D &ifc->ddev; + chan->chan_base =3D ifc->base + 0x10 + (id * (8 + (8 * ifc->sg_max))); + + list_add_tail(&chan->chan.device_node, &ddev->channels); + return 0; +} + +static int rda_ifc_ddev_init(struct rda_ifc *ifc, struct dma_device *ddev) +{ + int ret; + int i; + + dma_cap_zero(ddev->cap_mask); + dma_cap_set(DMA_SLAVE, ddev->cap_mask); + dma_cap_set(DMA_PRIVATE, ddev->cap_mask); + + /* IFC maximum segment size is 32 MB */ + dma_set_max_seg_size(ddev->dev, 0x1FFFFFF); + dma_set_mask_and_coherent(ddev->dev, DMA_BIT_MASK(32)); + + /* IFC supports 8-bit and 32-bit transfers */ + ddev->copy_align =3D DMAENGINE_ALIGN_4_BYTES; + ddev->src_addr_widths =3D BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + ddev->dst_addr_widths =3D BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | + BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | + BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); + ddev->directions =3D BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM); + + ddev->device_config =3D rda_ifc_device_config; + ddev->device_issue_pending =3D rda_ifc_issue_pending; + ddev->device_prep_slave_sg =3D rda_ifc_prep_slave_sg; + ddev->device_terminate_all =3D rda_ifc_terminate_all; + ddev->device_tx_status =3D rda_ifc_tx_status; + ddev->residue_granularity =3D DMA_RESIDUE_GRANULARITY_BURST; + + INIT_LIST_HEAD(&ddev->channels); + for (i =3D 0; i < ifc->max_chan; i++) { + ret =3D rda_ifc_chan_init(ifc, ddev, i); + if (ret) + return ret; + } + ddev->chancnt =3D i; + + return 0; +} + +static struct dma_chan *rda_ifc_xlate(struct of_phandle_args *dma_spec, + struct of_dma *of_dma) +{ + struct rda_ifc *ifc =3D of_dma->of_dma_data; + struct rda_ifc_chan *ifc_chan; + struct dma_chan *chan; + unsigned int request; + + if (dma_spec->args_count !=3D 1) + return NULL; + + request =3D dma_spec->args[0]; + if (request >=3D IFC_NO_REQUEST) + return NULL; + + chan =3D dma_get_any_slave_channel(&ifc->ddev); + if (!chan) + return NULL; + + ifc_chan =3D to_ifc_chan(chan); + ifc_chan->request_id =3D request; + + return chan; +} + +static int rda_ifc_probe(struct platform_device *pdev) +{ + const struct rda_ifc_platinfo *platinfo; + struct rda_ifc *ifc; + struct dma_device *ddev; + int ret; + + platinfo =3D of_device_get_match_data(&pdev->dev); + if (!platinfo) + return -EINVAL; + + ifc =3D devm_kzalloc(&pdev->dev, + struct_size(ifc, channels, platinfo->std_channb), + GFP_KERNEL); + if (!ifc) + return dev_err_probe(&pdev->dev, -ENOMEM, "Failed to allocate memory\n"); + + ifc->base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(ifc->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(ifc->base), "Cannot get base ad= dress\n"); + + ifc->max_chan =3D platinfo->std_channb; + ifc->sg_max =3D platinfo->sg_max; + + ddev =3D &ifc->ddev; + ddev->dev =3D &pdev->dev; + ret =3D rda_ifc_ddev_init(ifc, ddev); + if (ret) + return ret; + + platform_set_drvdata(pdev, ifc); + + ret =3D dma_async_device_register(ddev); + if (ret) + return ret; + + ret =3D of_dma_controller_register(pdev->dev.of_node, rda_ifc_xlate, ifc); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, "Cannot register DMA controller\n"= ); + + return 0; +} + +static void rda_ifc_remove(struct platform_device *pdev) +{ + struct rda_ifc *ifc =3D platform_get_drvdata(pdev); + + dma_async_device_unregister(&ifc->ddev); + of_dma_controller_free(pdev->dev.of_node); +} + +static const struct rda_ifc_platinfo rda8810pl_data =3D { + .sg_max =3D 1, + .std_channb =3D 7 +}; + +static const struct of_device_id rda_ifc_of_match[] =3D { + { .compatible =3D "rda,8810pl-ifc", .data =3D &rda8810pl_data }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rda_ifc_of_match); + +static struct platform_driver rda_ifc_driver =3D { + .probe =3D rda_ifc_probe, + .remove =3D rda_ifc_remove, + .driver =3D { + .name =3D "rda-ifc", + .of_match_table =3D rda_ifc_of_match, + }, +}; +module_platform_driver(rda_ifc_driver); + +MODULE_AUTHOR("Dang Huynh "); +MODULE_DESCRIPTION("RDA IFC driver"); +MODULE_LICENSE("GPL"); --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E3A272E4254; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221399; cv=none; b=eXvDWtxPRrZN++F1v1pfWkEqwhW6DJk5QC0FIQTAhsZ+G/44il3qWwokRwYaGTuKzWHH6TEncKtJh+9RQ9v98D9KlViTjLOsjmVZjiESGgnSScf/rhqoqUBG8VaYhvb2o6eoFmdTVibugPfGM/fOAUKGtQZ4SFEuz/xbTvplsHk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221399; c=relaxed/simple; bh=HO9M1gqAmkedloD4e1WufTU6OTInMuNZp/STHr6F4po=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=BTz1e6yOg84iQ2vDXcSGTnDthxozjzG4RvbkTydc9Ggz70zPWaTAamkA9irJOPNkxAwU3ugBVFYFhkVQG//HXWa0fFonlEunjT8r9CxQld20pi9ENZehkqTo7Sk4vAH/TO1Jrgyaj42LDWIaPD0aqqyXkcm2PuIn9ASRQTKGHZM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hWWBKqW6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hWWBKqW6" Received: by smtp.kernel.org (Postfix) with ESMTPS id 6F3E5C4CEFA; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=HO9M1gqAmkedloD4e1WufTU6OTInMuNZp/STHr6F4po=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hWWBKqW6x9IUy5NONhmz2MaT/yy3Obk6yKDvBwGQXfu5QVXi1EIaTft9EnLuhqFr/ 5WVb2YhBqbFsI/f3l3bv83rQduFuJh8xYb0kGCo/rNqxHl+w4I1pjL0q5LakoSAvDf P2suH5qMxRZKd/4R5daKR/PLTHqVAzVYy4qDvWDEY/lYQUMkjvZGIyqfSGfgTDXU5h fUOk2WueJ+1GpQkXWpkA4XjqrQdtAIcu2WJn0Lx5yTH5rcwkytI2k3Fa5ZHQEWvPAC Moxft11ACwzlzNTy1hSBpyPC4NHoI8PLU3kybK/hRkMv3TBJ/cDHnLw+aM+KAfKICk j1p59Dhh7HzKA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 66D69CAC5A7; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:49 +0700 Subject: [PATCH 09/10] mmc: host: Add RDA Micro SD/MMC driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-9-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=25600; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=pujIKNt46d1gPhDnz39Vr3APD9a5atxh6tawcy6nGJU=; b=urz0X8k8z3u6iJ42hwSdmgJrAG5JKD/cepql0yYhlvpN6JEfnqwlocudhhuUXVEfyj79iEPKG kvSxaJPbfUBBZAuinEz+hX0lEyY/2Yeqz8lt1gt84B2zrjZ1rIvx4sX X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh RDA Micro RDA8810PL includes an SD/MMC controller. This controller supports SD/SDIO/MMC interface. Signed-off-by: Dang Huynh --- MAINTAINERS | 6 + drivers/mmc/host/Kconfig | 12 + drivers/mmc/host/Makefile | 1 + drivers/mmc/host/rda-mmc.c | 853 +++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 872 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 923101a9d6c2edea339d1211b1cfdf4b917d1208..442dc8218541c1c05c03383f13b= 3f062f06cdae9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21430,6 +21430,12 @@ S: Maintained F: Documentation/devicetree/bindings/dma/rda,ifc.yaml F: drivers/dma/rda-ifc.c =20 +RDA MICRO SECURE DIGITAL AND MULTIMEDIA CARD DRIVER +M: Dang Huynh +S: Maintained +F: Documentation/devicetree/bindings/mmc/rda,mmc.yaml +F: drivers/mmc/host/rda-mmc.c + RDACM20 Camera Sensor M: Jacopo Mondi M: Kieran Bingham diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 4afa0130779d97ca9d1c0ed2102b0babdedcaeeb..e7e747ef9a860cbe88dc8fac101= 5a915a62f10d3 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -1040,6 +1040,18 @@ config MMC_MTK This is needed if support for any SD/SDIO/MMC devices is required. If unsure, say N. =20 +config MMC_RDA + tristate "RDA Micro SD/MMC Card Interface support" + depends on ARCH_RDA || COMPILE_TEST + depends on COMMON_CLK + depends on HAS_DMA + help + This selects the RDA Micro Secure digital and Multimedia card interface= . The + controller supports SD/SDIO/MMC interface. + If you have a board with RDA SoC and it uses this interface, say Y or M= here. + + If unsure, say N. + config MMC_SDHCI_MICROCHIP_PIC32 tristate "Microchip PIC32MZDA SDHCI support" depends on MMC_SDHCI && PIC32MZDA && MMC_SDHCI_PLTFM diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 5057fea8afb696e210e465a6a2aafc68adad7854..d819e18a478e35cb7de6d67b1cf= 827e1b3d09815 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -29,6 +29,7 @@ obj-$(CONFIG_MMC_ALCOR) +=3D alcor.o obj-$(CONFIG_MMC_MTK) +=3D mtk-sd.o obj-$(CONFIG_MMC_OMAP) +=3D omap.o obj-$(CONFIG_MMC_OMAP_HS) +=3D omap_hsmmc.o +obj-$(CONFIG_MMC_RDA) +=3D rda-mmc.o obj-$(CONFIG_MMC_ATMELMCI) +=3D atmel-mci.o obj-$(CONFIG_MMC_TIFM_SD) +=3D tifm_sd.o obj-$(CONFIG_MMC_MVSDIO) +=3D mvsdio.o diff --git a/drivers/mmc/host/rda-mmc.c b/drivers/mmc/host/rda-mmc.c new file mode 100644 index 0000000000000000000000000000000000000000..c358d170a930cbb7bf93a906604= 4c3b7ac957229 --- /dev/null +++ b/drivers/mmc/host/rda-mmc.c @@ -0,0 +1,853 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * SD/MMC driver for RDA Micro platform + * + * Copyright (C) 2013 RDA Microelectronics Inc. + * Copyright (c) 2025 Dang Huynh + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Registers Definitions */ +#define SDMMC_REG_CTRL 0x0 +#define SDMMC_REG_FIFO_TXRX 0x8 +#define SDMMC_REG_CONFIG 0x800 +#define SDMMC_REG_STATUS 0x804 +#define SDMMC_REG_CMD_INDEX 0x808 +#define SDMMC_REG_CMD_ARG 0x80C +#define SDMMC_REG_RESP_INDEX 0x810 +#define SDMMC_REG_RESP_ARG3 0x814 +#define SDMMC_REG_RESP_ARG2 0x818 +#define SDMMC_REG_RESP_ARG1 0x81C +#define SDMMC_REG_RESP_ARG0 0x820 +#define SDMMC_REG_DATA_WIDTH 0x824 +#define SDMMC_REG_BLOCK_SIZE 0x828 +#define SDMMC_REG_BLOCK_COUNT 0x82C +#define SDMMC_REG_INT_STATUS 0x830 +#define SDMMC_REG_INT_MASK 0x834 +#define SDMMC_REG_INT_CLEAR 0x838 +#define SDMMC_REG_TRANS_SPEED 0x83C +#define SDMMC_REG_MCLK_ADJUST 0x840 + +/* Bits def */ +/* CTRL */ +#define SDMMC_CTRL_ENDIAN GENMASK(2, 0) +#define SDMMC_CTRL_SOFTRST_L BIT(3) + +/* CONFIG */ +#define SDMMC_CFG_SENDCMD BIT(0) +#define SDMMC_CFG_SUSPEND BIT(1) +#define SDMMC_CFG_RSP_EN BIT(4) +#define SDMMC_CFG_RSP_SEL GENMASK(6, 5) +#define SDMMC_CFG_RD_WT_EN BIT(8) +#define SDMMC_CFG_RD_WT_SEL BIT(9) +#define SDMMC_CFG_S_M_SEL BIT(10) +#define SDMMC_CFG_AUTO_FLAG_EN BIT(16) +#define SDMMC_CFG_SAMPLE_EDGE_SEL_FALL_EN BIT(17) + +/* STATUS */ +#define SDMMC_STATUS_NOTOVER BIT(0) +#define SDMMC_STATUS_BUSY BIT(1) +#define SDMMC_STATUS_DLBUSY BIT(2) +#define SDMMC_STATUS_SUSPEND BIT(3) +#define SDMMC_STATUS_RSP_ERR BIT(8) +#define SDMMC_STATUS_NO_RSP_ERR BIT(9) +#define SDMMC_STATUS_CRC_STATUS GENMASK(14, 12) +#define SDMMC_STATUS_DATA_ERROR GENMASK(23, 16) +#define SDMMC_STATUS_DAT3_VAL BIT(24) + +/* INTERRUPTS */ +/* Mask and Clear */ +#define SDMMC_INT_NO_RSP BIT(0) +#define SDMMC_INT_RSP_ERR BIT(1) +#define SDMMC_INT_RD_ERR BIT(2) +#define SDMMC_INT_WR_ERR BIT(3) +#define SDMMC_INT_DAT_OVER BIT(4) +#define SDMMC_INT_TXDMA_DONE BIT(5) +#define SDMMC_INT_RXDMA_DONE BIT(6) +#define SDMMC_INT_SDIO BIT(7) + +#define SDMMC_MCLK_INVERT BIT(4) +#define SDMMC_MCLK_DISABLE BIT(5) + +struct rda_mmc_host { + struct device *dev; + + struct mmc_host *mmc; + struct mmc_request *mrq; + + unsigned int clock; + unsigned int bus_width; + unsigned int power_mode; + struct regulator *vmmc; + + void __iomem *base; + int irq; + + struct clk *clk; + struct reset_control *reset; + + dma_cookie_t dma_cookie; + struct dma_chan *dma_tx; + struct dma_chan *dma_rx; + + bool sdio_irq; + bool sdio_irq_trigger; + + spinlock_t lock; + struct completion c; + + /* device tree properties */ + bool mclk_inv; + u8 mclk_adj; +}; + +static int rda_mmc_hw_init(struct rda_mmc_host *priv) +{ + void __iomem *base =3D priv->base; + + disable_irq(priv->irq); + + writel(FIELD_PREP(SDMMC_CTRL_ENDIAN, 1) | SDMMC_CTRL_SOFTRST_L, + base + SDMMC_REG_CTRL); + writel(SDMMC_INT_RD_ERR | SDMMC_INT_WR_ERR | SDMMC_INT_DAT_OVER, + base + SDMMC_REG_INT_MASK); + writel(0xFFFFFFFF, base + SDMMC_REG_INT_CLEAR); + + enable_irq(priv->irq); + + return 0; +} + +static void rda_mmc_reset(struct rda_mmc_host *priv) +{ + reset_control_assert(priv->reset); + mdelay(1); + reset_control_deassert(priv->reset); + mdelay(1); +} + +static void rda_mmc_recv_resp(struct mmc_host *host, struct mmc_command *c= md) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + struct device *dev =3D mmc_dev(host); + void __iomem *base =3D priv->base; + u32 status; + int ret; + + /* If the controller is busy, wait until it finishes */ + ret =3D readl_poll_timeout(base + SDMMC_REG_STATUS, status, + !(status & SDMMC_STATUS_NOTOVER), 50, 1000 * 1000); + if (ret) { + dev_err(dev, "Timed out waiting for the controller\n"); + cmd->error =3D ret; + return; + } + + if (status & SDMMC_STATUS_NO_RSP_ERR) + return; + + if (status & SDMMC_STATUS_RSP_ERR) { + cmd->error =3D -EILSEQ; + return; + } + + if (mmc_resp_type(cmd) & MMC_RSP_R2) { + cmd->resp[0] =3D readl_relaxed(base + SDMMC_REG_RESP_ARG3); + cmd->resp[1] =3D readl_relaxed(base + SDMMC_REG_RESP_ARG2); + cmd->resp[2] =3D readl_relaxed(base + SDMMC_REG_RESP_ARG1); + cmd->resp[3] =3D readl_relaxed(base + SDMMC_REG_RESP_ARG0) << 1; + } else { + cmd->resp[0] =3D readl_relaxed(base + SDMMC_REG_RESP_ARG3); + } + + dev_dbg(dev, "response: resp[0] =3D 0x%x, resp[1] =3D 0x%x, resp[2] =3D 0= x%x, resp[3] =3D 0x%x\n", + cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); +} + +static inline struct dma_chan *rda_mmc_get_dma_chan(struct rda_mmc_host *p= riv, + struct mmc_data *data) +{ + if (data->flags & MMC_DATA_WRITE) + return priv->dma_tx; + else + return priv->dma_rx; +} + +static int rda_mmc_send_data(struct mmc_host *host, struct mmc_data *data) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + struct device *dev =3D mmc_dev(host); + struct dma_slave_config slave_config; + struct dma_async_tx_descriptor *desc; + struct dma_chan *chan; + int ret; + + if (!data) { + dev_err(dev, "No MMC request or data\n"); + goto fail; + } + + if (data->flags & MMC_DATA_WRITE) { + slave_config.dst_addr_width =3D DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.direction =3D DMA_MEM_TO_DEV; + } else { + slave_config.src_addr_width =3D DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.direction =3D DMA_DEV_TO_MEM; + } + + data->sg_count =3D dma_map_sg(dev, data->sg, data->sg_len, mmc_get_dma_di= r(data)); + if (data->sg_count =3D=3D 0) { + ret =3D -ENOMEM; + goto fail; + } + + chan =3D rda_mmc_get_dma_chan(priv, data); + + ret =3D dmaengine_slave_config(chan, &slave_config); + if (ret) { + dev_err(dev, "Failed to configure DMAC\n"); + goto fail_dma; + } + + desc =3D dmaengine_prep_slave_sg(chan, data->sg, data->sg_count, + slave_config.direction, DMA_CTRL_ACK); + if (!desc) { + dev_err(dev, "Failed to allocate DMA descriptor\n"); + goto fail_dma; + } + + priv->dma_cookie =3D dmaengine_submit(desc); + if (!priv->dma_cookie) { + dev_err(dev, "Failed to submit DMA request\n"); + goto fail_dma; + } + + dma_async_issue_pending(chan); + + return 0; + +fail_dma: + dma_unmap_sg(dev, data->sg, data->sg_len, mmc_get_dma_dir(data)); +fail: + return -EINVAL; +} + +static int rda_mmc_prepare_data(struct mmc_host *host, struct mmc_command = *cmd, + struct mmc_data *data, u32 *cfg) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + struct device *dev =3D mmc_dev(host); + void __iomem *base =3D priv->base; + int hw_blksz =3D 2; /* 1 word */ + int i =3D 0; + + /* If we're still here, we'll assume there's data ops */ + *cfg |=3D SDMMC_CFG_RD_WT_EN; + + /* Tell the controller we have a write operation */ + if (data->flags & MMC_DATA_WRITE) + *cfg |=3D SDMMC_CFG_RD_WT_SEL; + + /* Multiple data read/write */ + if (mmc_op_multi(cmd->opcode) || data->blocks > 1) { + *cfg |=3D SDMMC_CFG_S_M_SEL; + + /* + * Tell the controller to automatically issue CMD12 when the last block + * transfer is completed on non-SDIO cards. + */ + if (!mmc_card_sdio(host->card)) + *cfg |=3D SDMMC_CFG_AUTO_FLAG_EN; + } + + /* Blocksize on this IP is calculated by how many words are requested */ + if (data->blksz > 4) { + for (i =3D 4; i < data->blksz; i <<=3D 1) + hw_blksz++; + } + + if (unlikely(hw_blksz > 11)) { + dev_err(dev, "Requested %d but hardware can only support 11!\n", hw_blks= z); + return -EINVAL; + } + + writel_relaxed(data->blocks, base + SDMMC_REG_BLOCK_COUNT); + writel_relaxed(hw_blksz, base + SDMMC_REG_BLOCK_SIZE); + + return 0; +} + +static int rda_mmc_send_cmd(struct mmc_host *host, struct mmc_command *cmd, + struct mmc_data *data) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + void __iomem *base =3D priv->base; + u32 cfg =3D SDMMC_CFG_SENDCMD; + int ret; + + switch (mmc_resp_type(cmd)) { + case MMC_RSP_R2: + cfg |=3D SDMMC_CFG_RSP_EN | FIELD_PREP(SDMMC_CFG_RSP_SEL, 2); + break; + case MMC_RSP_R3: + cfg |=3D SDMMC_CFG_RSP_EN | FIELD_PREP(SDMMC_CFG_RSP_SEL, 1); + break; + default: + cfg |=3D SDMMC_CFG_RSP_EN; + break; + } + + /* No data */ + if (!data) + goto send_to_soc; + + /* Data operations */ + ret =3D rda_mmc_prepare_data(host, cmd, data, &cfg); + if (ret < 0) + return -EINVAL; + + ret =3D rda_mmc_send_data(host, data); + if (ret < 0) + return -EINVAL; + +send_to_soc: + writel(cmd->opcode, base + SDMMC_REG_CMD_INDEX); + writel(cmd->arg, base + SDMMC_REG_CMD_ARG); + writel(cfg, base + SDMMC_REG_CONFIG); + + dev_dbg(priv->dev, "mmc_resp_type =3D %d, cmd->opcode =3D 0x%x, cmd->arg = =3D 0x%x - cfg: 0x%x\n", + mmc_resp_type(cmd), cmd->opcode, cmd->arg, cfg); + + rda_mmc_recv_resp(host, cmd); + + return 0; +} + +/* + * Once data transfer failed (or aborted), the controller needs to be + * cleaned up. + */ +static void rda_mmc_data_abort(struct mmc_host *host, struct mmc_request *= mrq) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + struct device *dev =3D mmc_dev(host); + void __iomem *base =3D priv->base; + struct mmc_command stop; + int ret; + + writel_relaxed(0, base + SDMMC_REG_BLOCK_COUNT); + writel_relaxed(0, base + SDMMC_REG_BLOCK_SIZE); + + if (!host->card) + return; + + /* + * Issue a stop command first, because if the controller timed out, + * it'll not return an IRQ or any indicator. + */ + if (!mmc_card_sdio(host->card)) { + if (!mrq->stop) { + stop.opcode =3D MMC_STOP_TRANSMISSION; + stop.arg =3D 0; + stop.flags =3D MMC_RSP_R1B | MMC_CMD_AC; + ret =3D rda_mmc_send_cmd(host, &stop, NULL); + } else { + ret =3D rda_mmc_send_cmd(host, mrq->stop, NULL); + } + + if (ret < 0) + dev_err(dev, "Failed to send stop command\n"); + } +} + +static void rda_mmc_request(struct mmc_host *host, struct mmc_request *req) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + struct device *dev =3D mmc_dev(host); + struct mmc_data *data =3D NULL; + struct dma_chan *chan; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + + WARN_ON(priv->mrq); + priv->mrq =3D req; + + if (req->data) { + dev_dbg(dev, "Block size =3D %d - Blocks =3D %d - Offset: %d - Length: %= d\n", + req->data->blksz, req->data->blocks, + req->data->sg->offset, req->data->sg->length); + data =3D req->data; + } + + if (rda_mmc_send_cmd(host, req->cmd, data) < 0) { + req->cmd->error =3D -EINVAL; + if (data) + req->data->error =3D -EINVAL; + + goto done_irqunlock; + } + + /* Interrupt will pick up on this */ + if (!data) + goto done_irqunlock; + + spin_unlock_irqrestore(&priv->lock, flags); + + /* + * On a data operation, we rely on our interrupt to tell us + * when the transmission is finished (or failed). + * + * However with this IP, if the operation timed out, it will + * not trigger an IRQ and we'll not return. + */ + if (data) { + if (wait_for_completion_timeout(&priv->c, + msecs_to_jiffies(5000)) =3D=3D 0) { + spin_lock_irqsave(&priv->lock, flags); + priv->mrq =3D NULL; + + dma_unmap_sg(dev, data->sg, data->sg_len, + mmc_get_dma_dir(data)); + + chan =3D rda_mmc_get_dma_chan(priv, data); + + dmaengine_terminate_sync(chan); + rda_mmc_data_abort(host, req); + + req->cmd->error =3D -ETIMEDOUT; + req->data->error =3D -ETIMEDOUT; + goto done_irqunlock; + } + } + + return; + +done_irqunlock: + priv->mrq =3D NULL; + spin_unlock_irqrestore(&priv->lock, flags); + mmc_request_done(host, req); +} + +static void rda_mmc_set_ios(struct mmc_host *host, struct mmc_ios *ios) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + struct device *dev =3D mmc_dev(host); + void __iomem *base =3D priv->base; + unsigned long mclk_rate; + unsigned int clk_div; + unsigned long flags; + u32 reg_mclk =3D 0; + int ret; + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->bus_width !=3D ios->bus_width) { + priv->bus_width =3D ios->bus_width; + writel(BIT(priv->bus_width), base + SDMMC_REG_DATA_WIDTH); + } + + if (priv->power_mode !=3D ios->power_mode) { + priv->power_mode =3D ios->power_mode; + if (priv->power_mode =3D=3D MMC_POWER_UP) { + ret =3D regulator_enable(priv->vmmc); + if (ret) + dev_err(dev, "Failed to turn on vmmc\n"); + } else if (priv->power_mode =3D=3D MMC_POWER_OFF) { + ret =3D regulator_disable(priv->vmmc); + if (ret) + dev_err(dev, "Failed to turn off vmmc\n"); + } + } + + if (priv->clock !=3D ios->clock) { + priv->clock =3D ios->clock; + if (ios->clock) { + /* trans speed */ + mclk_rate =3D clk_get_rate(priv->clk); + if (mclk_rate =3D=3D 0) { + dev_err(dev, "Invalid MCLK rate\n"); + goto bailout; + } + + clk_div =3D mclk_rate / (2 * ios->clock); + if (mclk_rate % (2 * ios->clock)) + clk_div++; + + if (clk_div >=3D 1) + clk_div -=3D 1; + + if (clk_div > 255) + clk_div =3D 255; + + /* mclk adjust */ + if (priv->mclk_inv) + reg_mclk =3D SDMMC_MCLK_INVERT; + + reg_mclk |=3D priv->mclk_adj; + + writel_relaxed(clk_div, base + SDMMC_REG_TRANS_SPEED); + writel_relaxed(reg_mclk, base + SDMMC_REG_MCLK_ADJUST); + + dev_dbg(dev, "set clk =3D %d - mclk =3D %ld - divider =3D %d\n", + ios->clock, mclk_rate, clk_div); + } else { + writel_relaxed(SDMMC_MCLK_DISABLE, base + SDMMC_REG_MCLK_ADJUST); + } + } + +bailout: + dev_dbg(dev, "buswidth=3D%d, clock=3D%d, power=3D%d\n", + ios->bus_width, ios->clock, ios->power_mode); + + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void rda_mmc_crc_status(struct mmc_host *host) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + struct device *dev =3D mmc_dev(host); + void __iomem *base =3D priv->base; + const char *crc_error; + u32 status; + + status =3D readl_relaxed(base + SDMMC_REG_STATUS); + + switch (FIELD_GET(SDMMC_STATUS_CRC_STATUS, status)) { + case 0b101: + crc_error =3D "Transmission Error"; + break; + case 0b010: + crc_error =3D "Transmission Right"; + break; + case 0b111: + crc_error =3D "Flash Programming Error"; + break; + default: + crc_error =3D "Unknown"; + break; + } + + dev_err(dev, "CRC Error: %s - DATA_ERROR: 0x%lx\n", crc_error, + FIELD_GET(SDMMC_STATUS_DATA_ERROR, status)); +} + +static irqreturn_t rda_mmc_irq(int irq, void *dev_id) +{ + struct rda_mmc_host *priv =3D dev_id; + struct mmc_host *host =3D mmc_from_priv(priv); + struct device *dev =3D mmc_dev(host); + void __iomem *base =3D priv->base; + struct mmc_request *mrq; + u32 status; + irqreturn_t irqret =3D IRQ_NONE; + + status =3D readl(base + SDMMC_REG_INT_STATUS); + writel((status & 0xFF), base + SDMMC_REG_INT_CLEAR); + + dev_dbg(dev, "IRQ requested - status: 0x%x\n", status); + + if (!priv->mrq || !priv->mrq->data) + goto irq_done; + + mrq =3D priv->mrq; + + if (mrq->data && ((status & SDMMC_INT_RD_ERR) || (status & SDMMC_INT_WR_E= RR))) + mrq->data->error =3D -EILSEQ; + + if (priv->sdio_irq && (status & SDMMC_INT_SDIO)) + priv->sdio_irq_trigger =3D true; + + irqret =3D IRQ_WAKE_THREAD; + + /* We got an error, no need to do the additional checks */ + if (mrq->data->error) + goto irq_done; + + /* + * If we don't have any error but DAT_OVER isn't triggered, then we'll as= sume + * that we got an unexpected IRQ (during a data transfer) + */ + if (!mrq->data->error && !(status & SDMMC_INT_DAT_OVER)) + irqret =3D IRQ_HANDLED; + +irq_done: + if (irqret =3D=3D IRQ_NONE) + dev_info(dev, + "Unexpected IRQ - was a data transfer requested? IRQ: 0x%x\n", status); + + return irqret; +} + +static irqreturn_t rda_mmc_irq_fn(int irq, void *dev_id) +{ + struct rda_mmc_host *priv =3D dev_id; + struct mmc_host *host =3D mmc_from_priv(priv); + struct device *dev =3D mmc_dev(host); + struct mmc_request *mrq; + struct dma_chan *chan; + struct dma_tx_state state; + enum dma_status dma_status; + unsigned long flags; + + if (WARN_ON(!priv->mrq)) + return IRQ_NONE; + + spin_lock_irqsave(&priv->lock, flags); + + mrq =3D priv->mrq; + + if (mrq->data) { + chan =3D rda_mmc_get_dma_chan(priv, mrq->data); + + if (mrq->data->error) { + mrq->data->bytes_xfered =3D 0; + rda_mmc_crc_status(host); + dmaengine_terminate_sync(chan); + rda_mmc_data_abort(host, mrq); + } else { + mrq->data->bytes_xfered =3D + mrq->data->blocks * mrq->data->blksz; + + /* + * With this IP, just because a TXDMA/RXDMA interrupt is triggered, + * doesn't mean the MMC is fully processed. + */ + dma_status =3D dmaengine_tx_status(chan, priv->dma_cookie, &state); + dev_dbg(mmc_dev(host), "DMA Status: %d\n", dma_status); + if (dma_status !=3D DMA_COMPLETE) { + dev_err(dev, "Transmit IRQ triggered but DMA is not finished\n"); + mrq->data->error =3D -ETIMEDOUT; + mrq->data->bytes_xfered =3D 0; + dmaengine_terminate_sync(chan); + rda_mmc_data_abort(host, mrq); + } + } + + /* + * Since we told the controller to automatically send a stop command, + * we don't have to send a stop command here. + */ + dma_unmap_sg(dev, mrq->data->sg, mrq->data->sg_len, + mmc_get_dma_dir(mrq->data)); + dmaengine_terminate_sync(chan); + } + + priv->mrq =3D NULL; + spin_unlock_irqrestore(&priv->lock, flags); + + complete(&priv->c); + mmc_request_done(host, mrq); + + if (priv->sdio_irq && priv->sdio_irq_trigger) + mmc_signal_sdio_irq(host); + + return IRQ_HANDLED; +} + +static int rda_mmc_card_busy(struct mmc_host *host) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + void __iomem *base =3D priv->base; + u32 status =3D readl(base + SDMMC_REG_STATUS); + + return (status & SDMMC_STATUS_DLBUSY); +} + +static void rda_mmc_sdio_enable_irq(struct mmc_host *host, int enable) +{ + struct rda_mmc_host *priv =3D mmc_priv(host); + void __iomem *base =3D priv->base; + u32 intmask =3D readl(base + SDMMC_REG_INT_MASK); + + if (enable) { + intmask |=3D SDMMC_INT_SDIO; + priv->sdio_irq =3D true; + } else { + intmask &=3D ~SDMMC_INT_SDIO; + priv->sdio_irq =3D false; + } + + priv->sdio_irq_trigger =3D false; + + writel(intmask, base + SDMMC_REG_INT_MASK); +} + +static const struct mmc_host_ops rda_mmc_ops =3D { + .request =3D rda_mmc_request, + .set_ios =3D rda_mmc_set_ios, + .get_cd =3D mmc_gpio_get_cd, + .get_ro =3D mmc_gpio_get_ro, + .card_busy =3D rda_mmc_card_busy, + .enable_sdio_irq =3D rda_mmc_sdio_enable_irq, +}; + +static void rda_mmc_of_parse(struct device_node *np, struct rda_mmc_host *= priv) +{ + bool mclk_inv =3D false; + u8 mclk_adj =3D 1; + + if (of_property_present(np, "rda,mclk-inv")) + mclk_inv =3D true; + + of_property_read_u8(np, "rda,mclk-adj", &mclk_adj); + + priv->mclk_inv =3D mclk_inv; + priv->mclk_adj =3D mclk_adj; +} + +static int rda_mmc_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct rda_mmc_host *priv; + struct mmc_host *mmc; + struct clk *clk; + struct reset_control *reset; + struct dma_chan *tx, *rx; + struct regulator *vmmc; + void __iomem *base; + int irq; + int ret; + + base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), "Cannot get iomap\n"); + + irq =3D platform_get_irq(pdev, 0); + if (irq < 0) + return dev_err_probe(dev, irq, "Cannot get IRQ: %d\n", irq); + + clk =3D devm_clk_get_enabled(dev, "mclk"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "Cannot get clock device\n"); + + vmmc =3D devm_regulator_get(dev, "vmmc"); + if (IS_ERR(vmmc)) + return dev_err_probe(dev, PTR_ERR(vmmc), "Failed to obtain regulator\n"); + + reset =3D devm_reset_control_get_by_index(dev, 0); + if (IS_ERR(reset)) + return dev_err_probe(dev, PTR_ERR(reset), "Failed to obtain reset\n"); + + tx =3D dma_request_chan(dev, "tx"); + if (IS_ERR(tx)) + return dev_err_probe(dev, PTR_ERR(tx), "Failed to request tx channel\n"); + + rx =3D dma_request_chan(dev, "rx"); + if (IS_ERR(rx)) + return dev_err_probe(dev, PTR_ERR(rx), "Failed to request rx channel\n"); + + mmc =3D devm_mmc_alloc_host(dev, sizeof(*priv)); + if (IS_ERR(mmc)) { + dev_err(dev, "Cannot allocate memory for MMC\n"); + ret =3D PTR_ERR(mmc); + goto fail_release_dma; + } + + priv =3D mmc_priv(mmc); + priv->dev =3D dev; + priv->base =3D base; + priv->irq =3D irq; + priv->clk =3D clk; + priv->reset =3D reset; + priv->dma_tx =3D tx; + priv->dma_rx =3D rx; + priv->vmmc =3D vmmc; + spin_lock_init(&priv->lock); + init_completion(&priv->c); + + mmc->ops =3D &rda_mmc_ops; + + mmc->max_segs =3D 1; + mmc->max_blk_size =3D 4096; + mmc->max_blk_count =3D 0xFFFF; + mmc->max_req_size =3D 0xFFFF; + mmc->max_seg_size =3D 0xFFFF; + + mmc->f_min =3D 1000000; + mmc->caps =3D MMC_CAP_4_BIT_DATA; + mmc->ocr_avail =3D MMC_VDD_32_33 | MMC_VDD_33_34; + + rda_mmc_of_parse(dev->of_node, priv); + + ret =3D mmc_of_parse(mmc); + if (ret) { + dev_err(dev, "Failed to parse device tree: %d\n", ret); + goto fail_release_dma; + } + + rda_mmc_reset(priv); + rda_mmc_hw_init(priv); + + priv->bus_width =3D -1; + + ret =3D devm_request_threaded_irq(dev, irq, rda_mmc_irq, rda_mmc_irq_fn, + IRQF_ONESHOT, mmc_hostname(mmc), priv); + if (ret) { + dev_err(dev, "Failed to request IRQ: %d\n", ret); + goto fail_release_dma; + } + + ret =3D mmc_add_host(mmc); + if (ret) { + dev_err(dev, "Failed to add MMC host: %d\n", ret); + goto fail_release_dma; + } + + platform_set_drvdata(pdev, mmc); + return 0; + +fail_release_dma: + dma_release_channel(rx); + dma_release_channel(tx); + return ret; +} + +static void rda_mmc_remove(struct platform_device *pdev) +{ + struct rda_mmc_host *host =3D platform_get_drvdata(pdev); + + mmc_remove_host(host->mmc); + dma_release_channel(host->dma_rx); + dma_release_channel(host->dma_tx); +} + +static const struct of_device_id rda_mmc_dt_ids[] =3D { + { .compatible =3D "rda,8810pl-mmc", }, + { .compatible =3D "rda,mmc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rda_mmc_dt_ids); + +static struct platform_driver rda_mmc_driver =3D { + .probe =3D rda_mmc_probe, + .remove =3D rda_mmc_remove, + .driver =3D { + .name =3D "rda-mmc", + .probe_type =3D PROBE_PREFER_ASYNCHRONOUS, + .of_match_table =3D rda_mmc_dt_ids, + }, +}; +module_platform_driver(rda_mmc_driver); + +MODULE_AUTHOR("Dang Huynh "); +MODULE_DESCRIPTION("RDA Micro SD/MMC driver"); +MODULE_LICENSE("GPL"); --=20 2.51.0 From nobody Thu Oct 2 07:43:54 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 CC97B2D97BF; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; cv=none; b=LR5sd+PrL5hY+JA+Mij/g9/NTSxx8P4Akjj/Q62E8DO0x+T3tHLvAmceodW+/JyW0L3YgisDAi9FXefUscg17zhDN2wIJevajMbr8YvURbrCJbMqosKKZ/AHmXZkyksTQKW9S3Mqh9Ep9On8DpZz5sCi4x1vOhaqmsAd415ZSfw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758221398; c=relaxed/simple; bh=65t1RPp0ka+Y5SQw4gZNb7wOM4Xg/4h5FQ+MMy0If5o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=i2TMGQu5fA8CBSMpvZaC+bFTmeaoE0MZtOt8576sOO6FcvnyxYEPJw09Zyz/vH6lVkWRdhFolP0T9uGlJ7QpTfLtkiTF8g55b860SmYsPGhv61ZHl4jFA60poqUNICQXvMLBnXIa0AZ2VMlIrx6oOn5zhXbC4VtP+4EhpIhvbr0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cPYRYtUx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cPYRYtUx" Received: by smtp.kernel.org (Postfix) with ESMTPS id 800EFC19421; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1758221398; bh=65t1RPp0ka+Y5SQw4gZNb7wOM4Xg/4h5FQ+MMy0If5o=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=cPYRYtUxsRVr9TyEYjCtAQTqYPvJrV1iY9MI6vrjRkwS/ofN48fRnHmKGT2MPRLOX 8+G8kJGwfWV4aaqZnUoR79jTLrXH9wC3uNTdABh5TW2aLaa1hdcmPX2502qAaqlz1y KOZ4/9SR648YUuTRIkWyrCHqwwTKxIs/64TmBhMQOZfJx9NcvHvvuxZjNYdeaumcc9 RRm9kTWVHnUIwBEbKBQ07vlUQTmpUSg4+1i7RBP8RWQ15G2U/9Ho+8wToWa+iTo9Yj 7yYZbXR7dGaRGMHGVEcAa21cE7q7XAzRSdVvHWnUXimqBTPu8bz1v9tJLeBjYUnJO1 bOCeMGi+vT0aA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76D83CA1013; Thu, 18 Sep 2025 18:49:58 +0000 (UTC) From: Dang Huynh via B4 Relay Date: Fri, 19 Sep 2025 01:48:50 +0700 Subject: [PATCH 10/10] ARM: dts: unisoc: rda8810pl: Add SDMMC controllers Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250919-rda8810pl-mmc-v1-10-d4f08a05ba4d@mainlining.org> References: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> In-Reply-To: <20250919-rda8810pl-mmc-v1-0-d4f08a05ba4d@mainlining.org> To: Manivannan Sadhasivam , Linus Walleij , Bartosz Golaszewski , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Vinod Koul , Ulf Hansson , Philipp Zabel , Kees Cook , "Gustavo A. R. Silva" Cc: linux-arm-kernel@lists.infradead.org, linux-unisoc@lists.infradead.org, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, dmaengine@vger.kernel.org, linux-mmc@vger.kernel.org, linux-hardening@vger.kernel.org, Dang Huynh X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758221395; l=5720; i=dang.huynh@mainlining.org; s=20250917; h=from:subject:message-id; bh=zi1lBIjsLiJ+MvStlhu52N5g0U+YipGaIL9gPvgvEPE=; b=l77vToHDcYswIc8WztAJWYO/+3IYOVrmTQlZnFRvjc0lKarYC0h4XR0hoxgA2q3ZB98uFJham quoNd+aQB2RCTuhZ8oSMEutdqzVeCxtTOtcZpguuNT9Z4JHuV24Oxly X-Developer-Key: i=dang.huynh@mainlining.org; a=ed25519; pk=RyzH4CL4YU/ItXYUurA51EVBidfx4lIy8/E4EKRJCUk= X-Endpoint-Received: by B4 Relay for dang.huynh@mainlining.org/20250917 with auth_id=526 X-Original-From: Dang Huynh Reply-To: dang.huynh@mainlining.org From: Dang Huynh Add SDMMC1 and 2 controllers for the RDA8810PL platform and enable it on the Orange Pi i96 and 2G-IOT. Signed-off-by: Dang Huynh --- .../boot/dts/unisoc/rda8810pl-orangepi-2g-iot.dts | 20 +++++++++ .../arm/boot/dts/unisoc/rda8810pl-orangepi-i96.dts | 20 +++++++++ arch/arm/boot/dts/unisoc/rda8810pl.dtsi | 47 ++++++++++++++++++= ++-- 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-2g-iot.dts b/arch/= arm/boot/dts/unisoc/rda8810pl-orangepi-2g-iot.dts index 98e34248ae80b1fcd673ff01fe045db412d5bcc9..b462057ec0d1eb1877eb770afa6= aced99efd84b7 100644 --- a/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-2g-iot.dts +++ b/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-2g-iot.dts @@ -6,6 +6,7 @@ =20 /dts-v1/; =20 +#include #include "rda8810pl.dtsi" =20 / { @@ -27,6 +28,13 @@ memory@80000000 { reg =3D <0x80000000 0x10000000>; }; =20 + vdd_sdmmc: regulator-fixed { + compatible =3D "regulator-fixed"; + regulator-name =3D "vdd_sdmmc"; + regulator-min-microvolt =3D <2800000>; + regulator-max-microvolt =3D <2800000>; + }; + uart_clk: uart-clk { compatible =3D "fixed-clock"; clock-frequency =3D <921600>; @@ -34,6 +42,18 @@ uart_clk: uart-clk { }; }; =20 +&mmc1 { + status =3D "okay"; + no-sdio; + no-mmc; + bus-width =3D <4>; + max-frequency =3D <30000000>; + cd-gpios =3D <&gpiob 4 GPIO_ACTIVE_LOW>; + vmmc-supply =3D <&vdd_sdmmc>; + rda,mclk-adj =3D /bits/ 8 <1>; + rda,mclk-inv; +}; + &uart1 { status =3D "okay"; clocks =3D <&uart_clk>; diff --git a/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-i96.dts b/arch/arm= /boot/dts/unisoc/rda8810pl-orangepi-i96.dts index 728f76931b995fdfc036b586f899b15a7f07528b..cf4b75f114b33b27fad0ead4951= b15abb1f5cabd 100644 --- a/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-i96.dts +++ b/arch/arm/boot/dts/unisoc/rda8810pl-orangepi-i96.dts @@ -6,6 +6,7 @@ =20 /dts-v1/; =20 +#include #include "rda8810pl.dtsi" =20 / { @@ -27,6 +28,13 @@ memory@80000000 { reg =3D <0x80000000 0x10000000>; }; =20 + vdd_sdmmc: regulator-fixed { + compatible =3D "regulator-fixed"; + regulator-name =3D "vdd_sdmmc"; + regulator-min-microvolt =3D <2800000>; + regulator-max-microvolt =3D <2800000>; + }; + uart_clk: uart-clk { compatible =3D "fixed-clock"; clock-frequency =3D <921600>; @@ -34,6 +42,18 @@ uart_clk: uart-clk { }; }; =20 +&mmc1 { + status =3D "okay"; + no-sdio; + no-mmc; + bus-width =3D <4>; + max-frequency =3D <30000000>; + cd-gpios =3D <&gpiob 4 GPIO_ACTIVE_LOW>; + vmmc-supply =3D <&vdd_sdmmc>; + rda,mclk-adj =3D /bits/ 8 <1>; + rda,mclk-inv; +}; + &uart1 { status =3D "okay"; clocks =3D <&uart_clk>; diff --git a/arch/arm/boot/dts/unisoc/rda8810pl.dtsi b/arch/arm/boot/dts/un= isoc/rda8810pl.dtsi index f30d6ece49fb33d9c5c3ad9522c83bb8e4f8b488..438be79a89060655e4a12edc6d3= c42574748108b 100644 --- a/arch/arm/boot/dts/unisoc/rda8810pl.dtsi +++ b/arch/arm/boot/dts/unisoc/rda8810pl.dtsi @@ -7,6 +7,8 @@ */ =20 #include +#include +#include =20 / { compatible =3D "rda,8810pl"; @@ -39,7 +41,7 @@ modem@10000000 { #size-cells =3D <1>; ranges =3D <0x0 0x10000000 0xfffffff>; =20 - gpioc@1a08000 { + gpioc: gpioc@1a08000 { compatible =3D "rda,8810pl-gpio"; reg =3D <0x1a08000 0x1000>; gpio-controller; @@ -68,6 +70,13 @@ apb@20900000 { #size-cells =3D <1>; ranges =3D <0x0 0x20900000 0x100000>; =20 + ap_syscon: syscon@0 { + compatible =3D "rda,8810pl-apsyscon", "syscon"; + reg =3D <0x0 0x1000>; + #clock-cells =3D <1>; + #reset-cells =3D <1>; + }; + timer@10000 { compatible =3D "rda,8810pl-timer"; reg =3D <0x10000 0x1000>; @@ -76,7 +85,7 @@ timer@10000 { interrupt-names =3D "hwtimer", "ostimer"; }; =20 - gpioa@30000 { + gpioa: gpioa@30000 { compatible =3D "rda,8810pl-gpio"; reg =3D <0x30000 0x1000>; gpio-controller; @@ -87,7 +96,7 @@ gpioa@30000 { interrupts =3D <12 IRQ_TYPE_LEVEL_HIGH>; }; =20 - gpiob@31000 { + gpiob: gpiob@31000 { compatible =3D "rda,8810pl-gpio"; reg =3D <0x31000 0x1000>; gpio-controller; @@ -98,7 +107,7 @@ gpiob@31000 { interrupts =3D <13 IRQ_TYPE_LEVEL_HIGH>; }; =20 - gpiod@32000 { + gpiod: gpiod@32000 { compatible =3D "rda,8810pl-gpio"; reg =3D <0x32000 0x1000>; gpio-controller; @@ -123,6 +132,30 @@ uart1: serial@0 { status =3D "disabled"; }; =20 + mmc1: mmc@50000 { + compatible =3D "rda,8810pl-mmc", "rda,mmc"; + reg =3D <0x50000 0x1000>; + interrupts =3D <3 IRQ_TYPE_LEVEL_HIGH>; + clocks =3D <&ap_syscon CLK_APB2>; + clock-names =3D "mclk"; + resets =3D <&ap_syscon RST_APB2_SDMMC1>; + dmas =3D <&ifc IFC_SDMMC1_TX>, <&ifc IFC_SDMMC1_RX>; + dma-names =3D "tx", "rx"; + status =3D "disabled"; + }; + + mmc2: mmc@60000 { + compatible =3D "rda,8810pl-mmc", "rda,mmc"; + reg =3D <0x60000 0x1000>; + interrupts =3D <4 IRQ_TYPE_LEVEL_HIGH>; + clocks =3D <&ap_syscon CLK_APB2>; + clock-names =3D "mclk"; + resets =3D <&ap_syscon RST_APB2_SDMMC2>; + dmas =3D <&ifc IFC_SDMMC2_TX>, <&ifc IFC_SDMMC2_RX>; + dma-names =3D "tx", "rx"; + status =3D "disabled"; + }; + uart2: serial@10000 { compatible =3D "rda,8810pl-uart"; reg =3D <0x10000 0x1000>; @@ -136,6 +169,12 @@ uart3: serial@90000 { interrupts =3D <11 IRQ_TYPE_LEVEL_HIGH>; status =3D "disabled"; }; + + ifc: dma-controller@f0000 { + compatible =3D "rda,8810pl-ifc", "rda,ifc"; + reg =3D <0xf0000 0x1000>; + #dma-cells =3D <1>; + }; }; =20 l2: cache-controller@21100000 { --=20 2.51.0