From nobody Sat Sep 26 06:20:40 2026 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 2F73C41684D; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=ide/CVUZ9njCrRcJzHEecb6RCGuSQRH4mlRG8COzTxTzNjN7MoO0OZW8qe6ekDedcIeNybiX21r8xNeVoenY8CkOHAbxAy4MsyHfaVuZ213Vr7Ogi8c5FxJM5mpmmu3q+mXYD2D4kfJDDy7lkjSKKAXupASFIcXJxQCk6a57XSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=bBo2EYuFMiPEg5+TDMdIErdYoSUfwyw/F22EJeOZDYA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iJgTfEHQhAbBrbKzz4TR/TzITdA8rm22p0FDrg+/goy6dHhj+D5cQHpXBR/bNRX7C+iDQNYSjV1G669Jw8ENZzFFGU53r5rQwrKXY0q5xfQs1gLNeU1iJSzKVSgViw48xHGNOjVJVmBAhBGLD4ekKUuhuvglDniNy0likNDoO5c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VEKBMLjJ; 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="VEKBMLjJ" Received: by smtp.kernel.org (Postfix) with ESMTPS id C6DE8C2BCC7; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503953; bh=bBo2EYuFMiPEg5+TDMdIErdYoSUfwyw/F22EJeOZDYA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=VEKBMLjJYE8kNq048VFwm0lGC+ZF8jCNfDvM60GZcKMFe2qbhC+84XpR03lUn/hJ8 /3lUgs8++1AzWMyQhBPTscr4Ke3XJw0AQuu+0IQNXNgu4HMf64233Y1VAbj+9ffBni WiWcoBcp0I1S84MpB721O0uKW/tQ2AFfcwYE+bibcB0275Bh8cMQ4Meg3ROo4H0KBo guaV20LZoFDpHuqvco4nor36bgwUr6vYFqrcEoFwoU2szV35+KT+W3Zag6JyCluXT2 NU9NbFWjmQIHWgRkYzETT/y1iH9nUxdBsPdd/AlCtxUO8RyMkF48t4clX2Vtzaqd++ lBrMsWacI6lbw== 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 A253BC79F80; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:08 +0800 Subject: [PATCH v6 01/13] dt-bindings: arm: add Ambarella CV75 platforms 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: <20260904-cv75-v5-v6-1-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Krzysztof Kozlowski X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=1828; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=YCSbMKhFe2paSe+SbS/++piT5GFUx/NTLE9tewoMf1g=; b=KuuDEbbSvd+a45QhI6lH1lN5yplbA12BoKFyusqBK7CzPlX3N4jk9HUHNpgG/rMY2AT8DeLcO FI6TJtWFCiUCkyEFvKhdPYaiWsLj+5sOj5yIjUKUwzUlQZFWkViRQKw X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Add the Ambarella vendor prefix and CV75 EVK board compatible for the initial SoC bring-up. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Long Zhao Reviewed-by: Linus Walleij --- .../devicetree/bindings/arm/ambarella.yaml | 24 ++++++++++++++++++= ++++ .../devicetree/bindings/vendor-prefixes.yaml | 2 ++ 2 files changed, 26 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/ambarella.yaml b/Documen= tation/devicetree/bindings/arm/ambarella.yaml new file mode 100644 index 000000000000..72946e94fa76 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/ambarella.yaml @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/ambarella.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ambarella SoC platforms + +maintainers: + - Long Zhao + +properties: + $nodename: + const: "/" + + compatible: + oneOf: + - description: Ambarella CV75 boards + items: + - enum: + - ambarella,cv75-evk + - const: ambarella,cv75 + +additionalProperties: true diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Docum= entation/devicetree/bindings/vendor-prefixes.yaml index 85a27937832e..f48aa6dabbe9 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -112,6 +112,8 @@ patternProperties: description: Amarula Solutions "^amazon,.*": description: Amazon.com, Inc. + "^ambarella,.*": + description: Ambarella, Inc. "^amcc,.*": description: Applied Micro Circuits Corporation (APM, formally AMCC) "^amd,.*": --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 4795741A4F8; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=L5+iOLSoqZtWRKQMFQqhxJ1/NR53zvFHzZ8/sFa71HvmETGuxj0JxDI0aBTaPqM6R6v3Kxwy689MK15sIh7uXLN7sU1+0haAZntDpZP1tWY0HsMs+2dOdBzARfYdvKfyKA/QArn77ZPbz3izWqqzJO5thg4B4gHOmUqm1PElYzo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=QVo13gwqTD4KZzt9imrEAhoQPNNjElG0xmVDlRWUyNI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hAqtJDYaFpJn6hIIzRv2kuAbNW81q6v4GQaK4xaOaGeOojSR2nWwLEIVbBMZOOmIJNuEWH5zgxoYkXrPvzOXYW94yzHa8vb3+D6Ab6ze5wV9V4flL+CyLuuOFtARNnk6VCpGOfuRQqoB+hM/N5XQZNkTMP/LGmD6a/iSmpae+NI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=G992KqID; 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="G992KqID" Received: by smtp.kernel.org (Postfix) with ESMTPS id D4D26C2BCFF; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503953; bh=QVo13gwqTD4KZzt9imrEAhoQPNNjElG0xmVDlRWUyNI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=G992KqID7ViHJDqHPpmDi8wbGTaEghik1XU/Wo1YDkCHDvcwnAWFjIv+HmfbMLUQh tg/SIX5IBJJKgfnh3+3jN59m6vGs1urtHhokZ/fSLMnyb4Al8fZFIJu6ykfRGkcfoM G/6X6iEmak9aQtwKW7nBs5m2esuikdz2JLNa9urvP4d7uSvZW/+ConO7K0LF1uFfKm ZidMEIdczAk1uuhzR+Ziuvj9vEdeiNzf7/QpybsToB81gt3UgC+0Wum7DwrmySv3By ZHU0NBvOpAfw5AmbYLlYDHsR8iIQPtC0FSuPSyZC0Wmgo4YlNWh+lL5gYrvpyr7S4i FB+AQNaPoAQGg== 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 B6175C79F83; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:09 +0800 Subject: [PATCH v6 02/13] dt-bindings: mfd: syscon: add Ambarella CV75 secure scratchpad 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: <20260904-cv75-v5-v6-2-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=864; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=UZUyXXBBt/U6PUqQu+CGVwiN2KK9z5EYeOVD1g3SxZg=; b=CwSlga0ruE0ibNmpezfeIz539kTYoK34X+29YUwGVEo6zU4HI3MTunq5Ln7NuQyWCzNCCviYR hqw2hJVwMFCDwN7qMQAtZgvZRzmyFdfxjcD/vZIc2q1nI8OWH7EWbJ1 X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Allow ambarella,cv75-sec-scratchpad as a syscon for the shared secure scratchpad registers on CV75. Signed-off-by: Long Zhao Acked-by: Krzysztof Kozlowski --- Documentation/devicetree/bindings/mfd/syscon.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/mfd/syscon.yaml b/Documentat= ion/devicetree/bindings/mfd/syscon.yaml index fe882d3f828b..9ebf702c06f1 100644 --- a/Documentation/devicetree/bindings/mfd/syscon.yaml +++ b/Documentation/devicetree/bindings/mfd/syscon.yaml @@ -32,6 +32,7 @@ properties: - allwinner,sun50i-a64-system-controller - altr,l3regs - altr,sdr-ctl + - ambarella,cv75-sec-scratchpad - amd,pensando-elba-syscon - amlogic,meson-mx-assist - amlogic,meson-mx-bootrom --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 3CC88419FC5; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=hQ/BOk+qCSu9yIGHcDE6uhkAIj5bh9qgMIko2ZDMujv8nUIdcHAosUPFkQtRGGizy8wcuUHgpKnGdoO8QpYH4d+SCIQKi5MVIbhd1P9bdvXRLHhkYINv2npDW26sAk9DmZKsBuI/17uhp2quJDm684Lc7lbB5EjhqcJ96QlOgL4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=qyVshHRuCCOkA2u7nSXH/iNQWiGB5/QfjU2PD/ghsck=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EFPm5Q1jMBTMEn2pbX5u2iqL1v5u4M86p6UdPchrBTM7+zOYUKF3M3mIPFP7YJyIMsNkHBqS1PGdzYuEwpzC1vx3QFnbAVptPSwvCXRIjW7XzZc27qXnUXoftQNgYNJRD04glA2VYPVilcFE0nIdR3LYZRKzD6eLaYVi3o4GM9Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Dfgmehhd; 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="Dfgmehhd" Received: by smtp.kernel.org (Postfix) with ESMTPS id E1150C2BD00; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503953; bh=qyVshHRuCCOkA2u7nSXH/iNQWiGB5/QfjU2PD/ghsck=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=DfgmehhdsO4iMT2TaJh6/W1y5H2Dwzffu514Ynj0rHVdsRyeTgFrlyN625Ew7NIfl /tVogKrdwEEWttlFmDCkAPbaTHaBJWn12wbZIXAYd5CUYPzh4pKkN75bXFtZINx6yh CB7FIKo3D/c60wlqMIB8BYWw6lbf05NKux+zr4DMl62Mf72qH7MNKU+oPH48PZXnmy +OZ4M5XqH18WQj8DrFCn1Gy5YHNdJZRlYx+m6v0rWUJSApGw7F3aciBU8E1tXoxWxD ONDkYSRIbZM+lkCU84u5lJkbuyORj+Lea+so5AH24WlfJNooOqlh+FEAdWYswHdF0f DhJc9nkFb0zdw== 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 C80E9C79F84; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:10 +0800 Subject: [PATCH v6 03/13] dt-bindings: clock: add Ambarella CV75 RCT 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: <20260904-cv75-v5-v6-3-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=2922; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=IfB6TqzFSGYeGBH84xUTlmOh5ENNJFiu39W0pCucfH0=; b=WADi6d0wVnF7mW2flUngTABNZqQ4lolKyumD4Dv7bC+5LDWbly4Q6jQQUgn3PAxJ8JrHCITIr Cm9GHGiVlqRBmkRywaXAG9sj+4vA2ZWhKpZt6bgduuGkgr9CjiMMNLW X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Document the CV75 RCT clock controller and the clock ID header used by DT consumers. Document #reset-cells for the RCT reset-provider role. Soft-reset line IDs and the reset provider driver are deferred; this series has no resets=3D consumers. Signed-off-by: Long Zhao Reviewed-by: Krzysztof Kozlowski --- .../bindings/clock/ambarella,cv75-rct.yaml | 64 ++++++++++++++++++= ++++ include/dt-bindings/clock/ambarella,cv75-rct.h | 15 +++++ 2 files changed, 79 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/ambarella,cv75-rct.yam= l b/Documentation/devicetree/bindings/clock/ambarella,cv75-rct.yaml new file mode 100644 index 000000000000..be89bd75f9e2 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/ambarella,cv75-rct.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/ambarella,cv75-rct.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ambarella CV75 RCT Clock Controller + +maintainers: + - Long Zhao + +description: | + The RCT (Reset and Clock Tree) block on the Ambarella CV75 SoC provides + PLLs, clock muxes, dividers and soft-reset controls for on-chip + peripherals. + + The same register region is also exposed as a syscon for other SoC + blocks (e.g. pin drive-strength), hence the "syscon" compatible. + + Clock indices are defined in include/dt-bindings/clock/ambarella,cv75-rc= t.h. + +properties: + + compatible: + items: + - const: ambarella,cv75-rct + - const: syscon + + reg: + maxItems: 1 + + clocks: + description: Reference crystal oscillator (typically 24 MHz) + maxItems: 1 + + clock-names: + const: osc + + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - "#clock-cells" + - "#reset-cells" + +additionalProperties: false + +examples: + - | + clock-controller@ed080000 { + compatible =3D "ambarella,cv75-rct", "syscon"; + reg =3D <0xed080000 0x1000>; + clocks =3D <&osc>; + clock-names =3D "osc"; + #clock-cells =3D <1>; + #reset-cells =3D <1>; + }; diff --git a/include/dt-bindings/clock/ambarella,cv75-rct.h b/include/dt-bi= ndings/clock/ambarella,cv75-rct.h new file mode 100644 index 000000000000..0a6e946c9108 --- /dev/null +++ b/include/dt-bindings/clock/ambarella,cv75-rct.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (C) 2026 Ambarella, Inc. + */ + +#ifndef _DT_BINDINGS_CLOCK_AMBARELLA_CV75_RCT_H +#define _DT_BINDINGS_CLOCK_AMBARELLA_CV75_RCT_H + +/* Boot / bus clocks */ +#define CV75_GCLK_UART0 0 +#define CV75_GCLK_CORE 1 +#define CV75_GCLK_AHB 2 +#define CV75_GCLK_APB 3 + +#endif --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 66C2641D108; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=t8cXKxrpJpwEHk4WpeuJxHb1KfH4Bno1nCSIb+CAR12Wu4QG8QT7XVcTLPILdRXeyvDj5W+S5hDX+0NdeUGqrHnRQSyxyeYZeT4t4i2qd8lc0nmFkTVVhIJhnEu5riaPX5zmZMbenSQnqQAZm45bkLnXSdkmeKnfVRhRfi9TNQA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=hp7bqmHn9P6jHYwnNUYIruS99llCyau/ChCTrkE9I+E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HhT6jOi8ZYD+79XpLArLrIGSuS9SLEkOht0hrhN4/cRfctZusdqAn78reVNgnYOSksNjjS4x+/3/5S05WzQfs3Je/w5qsacwP8MURZLCFsjOkk4jAcEPXVL7Hu239ofwc/xygr9bDu117P5C0K9qQv5jLOQrnzTbvpikKGe5FW4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oPL32G+Z; 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="oPL32G+Z" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0341FC32786; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=hp7bqmHn9P6jHYwnNUYIruS99llCyau/ChCTrkE9I+E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=oPL32G+ZuZtggFJ398oR+poRz623D+8RQ71t+9NLK03kNPBIjD/uup3O32ZZJizY+ iSief4NGkLXdHw/BOxigBSqsr++2hYvFcf+8h+QSxUt3BaD0fEp91x5WE/UrTQ0NtS zJtVTRLzixVC6p92AxsXvO40l+kX/9hhoP+dsGseAXYx/RtEf6+YBPrSWDAhVBllrE g5XTLV5RsGhHSZVvQXfT+AAi1uYnMNwF94BWmAfstFFHj134Z8gyBS7jbCwcFouwGd YivqHt4TQNhawTQ9Cz0lj/dypOXlp/ZPNPdb4So07ApmYNUZcM5RiT53I3hqWFQA48 3do3HpoxLVElQ== 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 DAD4CC79F82; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:11 +0800 Subject: [PATCH v6 04/13] dt-bindings: pinctrl: add Ambarella CV75 pinctrl 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: <20260904-cv75-v5-v6-4-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=6330; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=XEvKncSGovDF7OgNkB6DKQG+ZkDy9YW2XQhMlWM+4n0=; b=J85/StinRj7wAPEfbN+dp3uPD4R+wEdU/zQ/jETw4vUnxggpithWNm1aXZWtOyc1Fq6bsa7B7 IjYvYIV9HyCBW/Lq+AoURDZm5qv0zCEcn5pXsb1RIkUcpBuXRctnFKe X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Document the CV75 pin controller binding using generic function and groups properties for pinmux configuration. Signed-off-by: Long Zhao Reviewed-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij --- .../bindings/pinctrl/ambarella,cv75-pinctrl.yaml | 239 +++++++++++++++++= ++++ 1 file changed, 239 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/ambarella,cv75-pinct= rl.yaml b/Documentation/devicetree/bindings/pinctrl/ambarella,cv75-pinctrl.= yaml new file mode 100644 index 000000000000..34054bc56c3b --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/ambarella,cv75-pinctrl.yaml @@ -0,0 +1,239 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/ambarella,cv75-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Ambarella CV75 Pin Controller + +maintainers: + - Long Zhao + +description: + The Ambarella CV75 pin controller configures pin multiplexing, bias and + drive strength for the main GPIO banks. Pin groups and their mux settings + are defined by the pin controller driver and selected by function and gr= oup + names. + +allOf: + - $ref: pinctrl.yaml# + +properties: + compatible: + const: ambarella,cv75-pinctrl + + reg: + maxItems: 1 + description: IOMUX registers + + ambarella,drive-strength-syscon: + $ref: /schemas/types.yaml#/definitions/phandle + description: RCT syscon containing the drive-strength registers. + + ambarella,pull-syscon: + $ref: /schemas/types.yaml#/definitions/phandle + description: Secure scratchpad syscon containing the pull registers. + +patternProperties: + "^[a-z0-9-]+-pins$": + type: object + allOf: + - $ref: pinmux-node.yaml# + - $ref: pincfg-node.yaml# + additionalProperties: false + + properties: + function: + enum: + - can0 + - can1 + - clk_au + - dmic0 + - enet0 + - hsync0 + - hsync1 + - i2c0 + - i2c1 + - i2c2 + - i2c3 + - i2cs + - i2s0 + - i2s1 + - ir + - pwm0 + - pwm1 + - pwm2 + - pwm3 + - pwm4 + - pwm5 + - pwm6 + - pwm7 + - pwm8 + - pwm9 + - pwm10 + - pwm11 + - sdmmc0 + - sdmmc1 + - snand + - spi0 + - spi1 + - spi2 + - spi3 + - spi_slave + - spinor + - uart0 + - uart1 + - uart2 + - uart3 + - uart4 + - vin_master_sync + - vsync0 + - vsync1 + - vsync2 + - vsync3 + - wdt + + groups: + items: + enum: + - can0 + - can1 + - clk_au + - dmic0 + - enet_2nd_ref_clk_a + - enet_2nd_ref_clk_b + - enet_ext_osc_clk + - enet0_ptp_pps_o + - hsync0 + - hsync1 + - i2c0_a + - i2c0_b + - i2c1_a + - i2c1_b + - i2c2 + - i2c3_a + - i2c3_b + - i2c3_c + - i2cs_a + - i2cs_b + - i2cs_c + - i2cs_d + - i2s0 + - i2s1 + - ir + - pwm0 + - pwm1 + - pwm2 + - pwm3 + - pwm4_a + - pwm4_b + - pwm5_a + - pwm5_b + - pwm6_a + - pwm6_b + - pwm7_a + - pwm7_b + - pwm8_a + - pwm8_b + - pwm9_a + - pwm9_b + - pwm10_a + - pwm10_b + - pwm11_a + - pwm11_b + - rgmii0 + - rmii0 + - sdmmc0_1bit + - sdmmc0_4bit + - sdmmc0_cd + - sdmmc0_hs_sel + - sdmmc0_reset + - sdmmc0_wp + - sdmmc1_1bit + - sdmmc1_4bit + - sdmmc1_cd + - sdmmc1_hs_sel + - sdmmc1_reset + - sdmmc1_wp + - snand + - spi0 + - spi1 + - spi2 + - spi3_a + - spi3_b + - spi3_c + - spi_slave_a + - spi_slave_b + - spi_slave_c + - spi_slave_d + - spi_slave_e + - spinor + - uart0 + - uart1 + - uart1_flow + - uart2_a + - uart2_b + - uart2_c + - uart2_flow_a + - uart2_flow_b + - uart3_a + - uart3_b + - uart3_flow_a + - uart3_flow_b + - uart4_a + - uart4_b + - uart4_flow_a + - uart4_flow_b + - vin_master_sync_a + - vin_master_sync_b + - vin_master_sync_c + - vin_master_sync_d + - vin_master_sync_e + - vsync0 + - vsync1 + - vsync2 + - vsync3 + - wdt_a + - wdt_b + - wdt_c + - wdt_d + - wdt_e + - wdt_f + minItems: 1 + maxItems: 6 + uniqueItems: true + + bias-disable: true + bias-pull-down: true + bias-pull-up: true + + drive-strength: + enum: [3, 4, 5, 6, 7, 8, 9, 12] + + required: + - function + - groups + +required: + - compatible + - reg + - ambarella,drive-strength-syscon + - ambarella,pull-syscon + +unevaluatedProperties: false + +examples: + - | + pinctrl: pinctrl@e4010000 { + compatible =3D "ambarella,cv75-pinctrl"; + reg =3D <0xe4010000 0x1000>; + ambarella,drive-strength-syscon =3D <&rct>; + ambarella,pull-syscon =3D <&scratchpad>; + + uart0-pins { + function =3D "uart0"; + groups =3D "uart0"; + bias-disable; + drive-strength =3D <8>; + }; + }; --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 64BD541C2FF; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=A2uqiF8+ntvSKx4ebieVuvjiR+B/IdL9AZYi5YFRn+z8myMqlxYFtokbTtawalH8kP8vBu7DqyZrSrO6olita3EdLOsDiKmI5yxKa+A9MwxVjMqzZ/Q/nPEDdQ65e3a5TqTB8nUxXVtcnsCswEOzmk1yBQCStIYY4zut4y7ppDc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=yPJ/Wf+HqVabQxtpcgjsXKaO54YJ3TI9hIUNNN34bvM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Kpln8kQndQTJEsJXNqnzc0zXtpfD8p6cfyPdnOoLS9w5DZRMkIsuH9eNvJeZXNN35YBiF+FbuhAaseuLs9La3V4JnmIkkqz4PlpxXaRjxJpgU+bHOjccWtMeq2iAggQBffQnYXdfolKxHIDBSNerQdTgwt3HgfAPQ74Jz1UfwEw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N7jN0ARs; 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="N7jN0ARs" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0C71EC4AF1C; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=yPJ/Wf+HqVabQxtpcgjsXKaO54YJ3TI9hIUNNN34bvM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=N7jN0ARsJvZivzubVuu8vqdYKE2MBEKomLG6QyMyEgivK2BULXuX3bp96CMnvwPAC qiohHR1/eNoNSPyDMrVaL0AYOb8ITlReDblabihli9Y96XO8wgquyyixu80gGVKs4c WR1XIiHIRmchYO7mKhc5/BPieu1YGc3yJwJCIrrGTS5AxmDOeQaPh4ovFEjd6/NCC7 OrwrC662+DTGOR+83ucVAGMM5ETuvYfgbTSpbkD8o9dTsNCrfgc6jhdkMQ//RyJr3F eXCVdxodLpP5fckFTKekqwZVvtDfGqls5s46fP4Xho72AjJhjpXRpUaqsD89BYpE/U 0Zb/QBx6ssKzg== 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 EBC34C79F85; Fri, 4 Sep 2026 06:39:13 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:12 +0800 Subject: [PATCH v6 05/13] dt-bindings: gpio: pl061: add Ambarella CV75 variant 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: <20260904-cv75-v5-v6-5-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=1865; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=IvHuWjRWqe2GmNP+ujYSmH5KztId+5pd7GEzVRxQiIc=; b=9awv2H/6OPgoOrKIfYBIBsoB6+FPJzmgGLFpuHhv3d4js+dye2ijWwVDlPOZIE3v2V7yW+OSB gmWcsT5soz0BKXkrXyes6HqLyDuCI2/JiKqCR8FlP+DOeCtp553Ss+g X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Document the Ambarella CV75 GPIO bank compatible and the synthetic arm,primecell-periphid used with the PL061 binding. Signed-off-by: Long Zhao --- .../devicetree/bindings/gpio/pl061-gpio.yaml | 32 ++++++++++++++++++= +--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/gpio/pl061-gpio.yaml b/Docum= entation/devicetree/bindings/gpio/pl061-gpio.yaml index 4d970e55104b..5a6d95e84df2 100644 --- a/Documentation/devicetree/bindings/gpio/pl061-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/pl061-gpio.yaml @@ -15,7 +15,9 @@ select: properties: compatible: contains: - const: arm,pl061 + enum: + - arm,pl061 + - ambarella,cv75-gpio required: - compatible =20 @@ -24,9 +26,13 @@ properties: pattern: "^gpio@[0-9a-f]+$" =20 compatible: - items: - - const: arm,pl061 - - const: arm,primecell + oneOf: + - items: + - const: arm,pl061 + - const: arm,primecell + - items: + - const: ambarella,cv75-gpio + - const: arm,primecell =20 reg: maxItems: 1 @@ -46,6 +52,10 @@ properties: =20 clock-names: true =20 + arm,primecell-periphid: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Override for the PrimeCell peripheral ID. + "#gpio-cells": const: 2 =20 @@ -64,6 +74,20 @@ required: - "#gpio-cells" - gpio-controller =20 +allOf: + - if: + properties: + compatible: + contains: + const: ambarella,cv75-gpio + then: + properties: + arm,primecell-periphid: + const: 0x000e8061 + required: + - arm,primecell-periphid + - gpio-ranges + additionalProperties: false =20 ... --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 6A8BA41D121; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=WUrF0zAy7hYywaxEtOlOl5GefNtXGdgAreJYUM1aA2t723C0jJ8GX98icerH6SOfPUd0cRIl13RUgTwfqvkGKdd2yFJ0gQMihTQpeWTtZ7Bt5+NNRMIQFo9GhRCbu1dDYY+Q9Ty2q1wBELJRG9m+ngQfjb33zOFLJMNjLqnKqko= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=YRtuINaeeg+H3XFSuIJVNYHLS6Z7t0vhSOvvVH0L3HQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=q16U94rcz/kg8WAN6CAFvb2UiIHDanZNRKHapP+LNv1vnYt9fKtfErDsKGpG8r/+7w56KmBvYbAr7XUy2O2B9daSVBvVb9H83SCe1gVMdY+v7b/tt3Ypt5zsNywmTfA3Dk7CJHPS4vqSiCU4omXEIyPzc5rEaZ6H1pQS6Y8gNSw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MVjHyt5g; 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="MVjHyt5g" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1C7DEC4AF0F; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=YRtuINaeeg+H3XFSuIJVNYHLS6Z7t0vhSOvvVH0L3HQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=MVjHyt5gDwOkBcnDzLO64lWK0+72jzhMlVHf+0UxjD9qwVRe99+eAi+8pZbVyY4xh 3+Se2nw5WEhlr0E14S2eSE8F3YWzSHqxqo951eHA9ysCZnHbi3yqe85NyiD70Qocpi ogsztGaJ3WLEzF4zJnD+mloianH7rK2pvsrwP6W9KyFM4mXXBTnTm91qKs5w2Ch6DU WhFCgY7AHQ/U0gxBe5vaRgAF6CeRsWrDyHQBmgCLNGDj7zShQt1zMvyx9S2Z980Dii DYLwQ1iHB56iDe7BnTc74uY8fldtfvjZsB16mAnPpD/Plvpc2hNBFxb74kmXPDbaar 2AkbS7veKpUFw== 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 09237C61DD6; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:13 +0800 Subject: [PATCH v6 06/13] dt-bindings: serial: snps-dw-apb-uart: add ambarella,cv75-uart 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: <20260904-cv75-v5-v6-6-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=954; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=9H5T2CAaecrbxe1XZGmzDHUwCx/pDCa6CR6TyCM/1dU=; b=XXOx+PGosTen142j//farUwoWwOnOTOPuVxEH1dTawpqdUI2vhhMrMwC7T6z3DEC8TOxtPWgD vQdhQXPJndzBsxLC9NrgB+T4uhiJzGTj3DrWDeTgTjlQ/9JjeWRUE0k X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Add the Ambarella CV75 compatible string to the Synopsys DW APB UART binding. The block is Ambarella IP with a DW-like register map, so it is described as a DW APB UART variant. Signed-off-by: Long Zhao Acked-by: Krzysztof Kozlowski Reviewed-by: Linus Walleij --- Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml= b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml index 49f51b002879..cec5c679f1a9 100644 --- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml +++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml @@ -51,6 +51,7 @@ properties: - const: renesas,rzn1-uart - items: - enum: + - ambarella,cv75-uart - anlogic,dr1v90-uart - brcm,bcm11351-dw-apb-uart - brcm,bcm21664-dw-apb-uart --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 8469E41D63C; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=degmBz6isfAXMn4eR12lXtQmQvhhXn4LNzC4tpZbOyPlzU1448G46J6PJmJy/2sMSnF9zoqcSjmdOnl/Q/N7XHB97qjTIk6RRiXwfCT/4BIzDV5YxFT3Ok8Yxna1kxwcbHKleE0Wa94WJU9nCHWWUqigmYrvb+Pipv8NclyTPyQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=qzWoSh8qS3D6DEc0hsDkzK6kHJGmD3lb9vElj7+y2p8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lnNjdhRRSYt3647/P1x0BK3e8VCY6V2oD0KOF1KTsplz2Hh+9tZLeYexvb2TDCLAotZHJl/tnAtnuUydiTqG6vg+QY/CfC1E0z0a1LDlCHOqlvDnVMk5dDQByAB6XmyVhKqF/8Y7wSAj9mriIWYxRTJ+mPx7uPXaOmWYy4VYQ20= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=RTV+s7J/; 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="RTV+s7J/" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3286AC4AF54; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=qzWoSh8qS3D6DEc0hsDkzK6kHJGmD3lb9vElj7+y2p8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=RTV+s7J/HGrlpn/P+TNOppYiq/KRpwl8pPixfJO0brlNNsAMVai6khF2bWlZnCiKu LeD3nUj3wY2pDFlPRi8QByGrpQeejHuKveq+Z7Jm5UYm+xiDL2zDW6WGoaB5XHLwpq DQysRSbzfITBb7ozjX0C2plrvFm82XRuZMD1CWlGqoJ5rtYBbM0QgRVTJ5o3cmaIwd thlNkrpk9JCuEq9DajxSL5w4X5alx8IfS0kwgJeJYur8YZCHqRkUooTAs08+SuvWII Vsv87yToUCFcId7Q195gkY7hG0HB+bRMvtvvzJSx9JrmcWKJbs0CvebIBp1ao+pD1j gyRaGTR3no8WQ== 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 1E1FAC79F80; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:14 +0800 Subject: [PATCH v6 07/13] clk: ambarella: add CV75 CCU 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: <20260904-cv75-v5-v6-7-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=34308; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=fa1qmpnXDBk9Jmnsl4vEEvE9GNr9O+K6mhrOaymx1mQ=; b=fHhyAqg1yjMvn3vtDFu78ct6C6gZBJ7+oUnXv/moen29EQy5yXDmcFIKWeEy6Fxqy/DhVZD0L yrXDa809cfZDNthHdu+OZtrNOF1+LsbruWpsrZ+z2XngE02WIWL5xJN X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Add the Ambarella CV75 clock driver covering the core PLL and the UART0 / AHB / APB clocks needed for early console bring-up. Signed-off-by: Long Zhao --- drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/ambarella/Kconfig | 13 ++ drivers/clk/ambarella/Makefile | 6 + drivers/clk/ambarella/ccu-cv75.c | 296 +++++++++++++++++++++++++ drivers/clk/ambarella/ccu_common.c | 60 +++++ drivers/clk/ambarella/ccu_common.h | 25 +++ drivers/clk/ambarella/ccu_mux_div.c | 234 ++++++++++++++++++++ drivers/clk/ambarella/ccu_mux_div.h | 35 +++ drivers/clk/ambarella/ccu_pll.c | 421 ++++++++++++++++++++++++++++++++= ++++ drivers/clk/ambarella/ccu_pll.h | 70 ++++++ 11 files changed, 1162 insertions(+) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 1717ce75a907..fbbf4963716c 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -506,6 +506,7 @@ config COMMON_CLK_RPMI the RISC-V platform management interface (RPMI) specification. =20 source "drivers/clk/actions/Kconfig" +source "drivers/clk/ambarella/Kconfig" source "drivers/clk/analogbits/Kconfig" source "drivers/clk/aspeed/Kconfig" source "drivers/clk/bcm/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index cc108a75a900..30d823ee606f 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -112,6 +112,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE) +=3D clk-xgene.o =20 # please keep this section sorted lexicographically by directory path name obj-y +=3D actions/ +obj-y +=3D ambarella/ obj-y +=3D analogbits/ obj-y +=3D aspeed/ obj-$(CONFIG_COMMON_CLK_AT91) +=3D at91/ diff --git a/drivers/clk/ambarella/Kconfig b/drivers/clk/ambarella/Kconfig new file mode 100644 index 000000000000..d79bb4bd6df5 --- /dev/null +++ b/drivers/clk/ambarella/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config CLK_AMBARELLA_CV75 + bool "Ambarella CV75 RCT clock controller" + depends on ARCH_AMBARELLA || COMPILE_TEST + select CLK_AMBARELLA_CCU + default ARCH_AMBARELLA + help + Say Y to enable the Ambarella CV75 RCT clock controller. + +config CLK_AMBARELLA_CCU + bool + select REGMAP_MMIO diff --git a/drivers/clk/ambarella/Makefile b/drivers/clk/ambarella/Makefile new file mode 100644 index 000000000000..36e96326ea97 --- /dev/null +++ b/drivers/clk/ambarella/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for ambarella specific clk +# + +obj-$(CONFIG_CLK_AMBARELLA_CCU) +=3D ccu_common.o ccu_mux_div.o ccu_pll.o +obj-$(CONFIG_CLK_AMBARELLA_CV75) +=3D ccu-cv75.o diff --git a/drivers/clk/ambarella/ccu-cv75.c b/drivers/clk/ambarella/ccu-c= v75.c new file mode 100644 index 000000000000..c4828be598be --- /dev/null +++ b/drivers/clk/ambarella/ccu-cv75.c @@ -0,0 +1,296 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Ambarella, Inc. + * + * CV75 RCT clock controller for boot clocks. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include "ccu_common.h" +#include "ccu_mux_div.h" +#include "ccu_pll.h" + +enum amb_cv75_clk_type { + AMB_CV75_CLK_FIXED_RATE, + AMB_CV75_CLK_FIXED_FACTOR, + AMB_CV75_CLK_PLL, + AMB_CV75_CLK_DIV, + AMB_CV75_CLK_MUX_DIV, +}; + +enum amb_cv75_clk_ref { + AMB_CV75_CLK_REF_OSC =3D -1, + AMB_CV75_CLK_REF_DUMMY =3D -2, +}; + +/* PLL version for CV75 (ambarella,clkpll-v1 in vendor DTS) */ +static const struct amb_pll_soc_data cv75_pll_soc_data =3D { + .pll_version =3D 1, + .fsout_mask =3D CTRL2_FSOUT_DIV2, + .fsout_val =3D CTRL2_FSOUT_DIV2, + .fsdiv_mask =3D CTRL2_FSDIV_DIV2, + .fsdiv_val =3D CTRL2_FSDIV_DIV2, + .vcodiv_mask =3D CTRL2_VCODIV_DIV2, + .vcodiv_val =3D CTRL2_VCODIV_DIV2, + .vco_max_mhz =3D 2600UL, + .vco_min_mhz =3D 850UL, + .vco_range =3D { 1800UL, 1400UL, 1100UL, 0UL }, +}; + +struct amb_cv75_clk_desc { + int id; + enum amb_cv75_clk_type type; + const char *name; + int parent; + + union { + struct { + unsigned long rate; + } fixed_rate; + struct { + unsigned long flags; + unsigned int mult; + unsigned int div; + } fixed_factor; + struct { + u32 reg_offset[REG_NUM]; + const struct amb_pll_soc_data *soc_data; + } pll; + struct { + u32 reg; + u32 shift; + u32 width; + u32 flags; + u32 fix_divider; + } div; + struct amb_mux_div_desc mux_div; + }; +}; + +static const struct amb_cv75_clk_desc cv75_clks[] =3D { + { + .id =3D AMB_CV75_CLK_REF_DUMMY, + .type =3D AMB_CV75_CLK_FIXED_RATE, + .name =3D "dummy", + .fixed_rate.rate =3D 0, + }, + { + .id =3D CV75_GCLK_CORE, + .type =3D AMB_CV75_CLK_PLL, + .name =3D "core", + .parent =3D AMB_CV75_CLK_REF_OSC, + .pll =3D { + .reg_offset =3D { + 0x000, 0x004, 0x100, + 0x104, 0x000, 0x000, + }, + .soc_data =3D &cv75_pll_soc_data, + }, + }, + { + .id =3D CV75_GCLK_AHB, + .type =3D AMB_CV75_CLK_FIXED_FACTOR, + .name =3D "ahb", + .parent =3D CV75_GCLK_CORE, + .fixed_factor =3D { + .flags =3D 0, + .mult =3D 1, + .div =3D 2, + }, + }, + { + .id =3D CV75_GCLK_APB, + .type =3D AMB_CV75_CLK_FIXED_FACTOR, + .name =3D "apb", + .parent =3D CV75_GCLK_CORE, + .fixed_factor =3D { + .flags =3D 0, + .mult =3D 1, + .div =3D 4, + }, + }, + { + .id =3D CV75_GCLK_UART0, + .type =3D AMB_CV75_CLK_MUX_DIV, + .name =3D "uart0", + .mux_div =3D { + .name =3D "uart0", + .parents =3D (const int[]) { + AMB_CV75_CLK_REF_OSC, CV75_GCLK_CORE, + AMB_CV75_CLK_REF_DUMMY, AMB_CV75_CLK_REF_DUMMY, + }, + .num_parents =3D 4, + .mux_reg =3D 0x1c8, + .mux_shift =3D 0, + .mux_mask =3D 0x3, + .div_reg =3D 0x038, + .div_shift =3D 0, + .div_width =3D 24, + .div_flags =3D CLK_DIVIDER_ONE_BASED, + .fix_divider =3D 1, + }, + }, +}; + +static struct clk_hw *amb_cv75_get_parent(struct amb_ccu *ccu, + struct clk_hw *osc, + struct clk_hw *dummy, + int parent) +{ + if (parent =3D=3D AMB_CV75_CLK_REF_OSC) + return osc; + if (parent =3D=3D AMB_CV75_CLK_REF_DUMMY) + return dummy; + + if (parent < 0 || parent >=3D ccu->data->num) + return ERR_PTR(-EINVAL); + + if (!ccu->data->hws[parent]) + return ERR_PTR(-EPROBE_DEFER); + + return ccu->data->hws[parent]; +} + +static struct clk_hw *amb_cv75_register_mux_div(struct device *dev, + struct amb_ccu *ccu, + const struct amb_cv75_clk_desc *desc, + struct clk_hw *osc, + struct clk_hw *dummy) +{ + const struct amb_mux_div_desc *md =3D &desc->mux_div; + struct clk_parent_data *pdata; + struct clk_hw *parent; + u8 i; + + pdata =3D devm_kcalloc(dev, md->num_parents, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return ERR_PTR(-ENOMEM); + + for (i =3D 0; i < md->num_parents; i++) { + if (md->parents[i] =3D=3D AMB_CV75_CLK_REF_OSC) { + pdata[i].fw_name =3D "osc"; + continue; + } + + parent =3D amb_cv75_get_parent(ccu, osc, dummy, md->parents[i]); + if (IS_ERR(parent)) + return parent; + + pdata[i].hw =3D parent; + } + + return amb_mux_div_register(dev, ccu->map, md, pdata); +} + +static struct clk_hw *amb_cv75_register_clk(struct device *dev, + struct amb_ccu *ccu, + const struct amb_cv75_clk_desc *desc, + struct clk_hw *osc, + struct clk_hw *dummy) +{ + struct amb_pll_desc pll_desc; + struct clk_hw *parent; + + switch (desc->type) { + case AMB_CV75_CLK_FIXED_RATE: + return devm_clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, + desc->fixed_rate.rate); + case AMB_CV75_CLK_FIXED_FACTOR: + parent =3D amb_cv75_get_parent(ccu, osc, dummy, desc->parent); + if (IS_ERR(parent)) + return parent; + + return devm_clk_hw_register_fixed_factor_parent_hw(dev, + desc->name, parent, + desc->fixed_factor.flags, + desc->fixed_factor.mult, + desc->fixed_factor.div); + case AMB_CV75_CLK_PLL: + parent =3D amb_cv75_get_parent(ccu, osc, dummy, desc->parent); + if (IS_ERR(parent)) + return parent; + + pll_desc.name =3D desc->name; + pll_desc.parent =3D parent; + memcpy(pll_desc.reg_offset, desc->pll.reg_offset, + sizeof(pll_desc.reg_offset)); + pll_desc.soc_data =3D desc->pll.soc_data; + pll_desc.frac_mode =3D false; + + return amb_pll_register(dev, ccu->map, &pll_desc); + case AMB_CV75_CLK_DIV: + parent =3D amb_cv75_get_parent(ccu, osc, dummy, desc->parent); + if (IS_ERR(parent)) + return parent; + + return amb_div_register(dev, ccu->map, desc->name, parent, + desc->div.reg, desc->div.shift, + desc->div.width, desc->div.flags, + desc->div.fix_divider); + case AMB_CV75_CLK_MUX_DIV: + return amb_cv75_register_mux_div(dev, ccu, desc, osc, dummy); + default: + return ERR_PTR(-EINVAL); + } +} + +static int amb_cv75_rct_probe(struct platform_device *pdev) +{ + struct amb_ccu *ccu; + struct clk *osc_clk; + struct clk_hw *osc, *dummy =3D NULL, *hw; + int i; + + ccu =3D amb_ccu_init(pdev, ARRAY_SIZE(cv75_clks)); + if (IS_ERR(ccu)) + return PTR_ERR(ccu); + + osc_clk =3D devm_clk_get(&pdev->dev, "osc"); + if (IS_ERR(osc_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(osc_clk), + "missing osc clock\n"); + osc =3D __clk_get_hw(osc_clk); + + for (i =3D 0; i < ARRAY_SIZE(cv75_clks); i++) { + hw =3D amb_cv75_register_clk(&pdev->dev, ccu, &cv75_clks[i], + osc, dummy); + if (IS_ERR(hw)) + return dev_err_probe(&pdev->dev, PTR_ERR(hw), + "failed to register %s\n", + cv75_clks[i].name); + + if (cv75_clks[i].id =3D=3D AMB_CV75_CLK_REF_DUMMY) + dummy =3D hw; + else + ccu->data->hws[cv75_clks[i].id] =3D hw; + } + + return amb_ccu_register(ccu); +} + +static const struct of_device_id amb_cv75_rct_match[] =3D { + { .compatible =3D "ambarella,cv75-rct" }, + { } +}; +MODULE_DEVICE_TABLE(of, amb_cv75_rct_match); + +static struct platform_driver amb_cv75_rct_driver =3D { + .probe =3D amb_cv75_rct_probe, + .driver =3D { + .name =3D "ambarella-cv75-rct", + .of_match_table =3D amb_cv75_rct_match, + }, +}; +module_platform_driver(amb_cv75_rct_driver); + +MODULE_AUTHOR("Ambarella Inc."); +MODULE_DESCRIPTION("Ambarella CV75 RCT clock controller"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/ambarella/ccu_common.c b/drivers/clk/ambarella/ccu= _common.c new file mode 100644 index 000000000000..78587c5f2ce1 --- /dev/null +++ b/drivers/clk/ambarella/ccu_common.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Ambarella, Inc. + */ + +#include +#include +#include +#include +#include + +#include "ccu_common.h" + +static const struct regmap_config amb_rct_regmap_config =3D { + .reg_bits =3D 32, + .val_bits =3D 32, + .reg_stride =3D 4, + .max_register =3D AMB_RCT_REG_SIZE - 4, +}; + +struct amb_ccu *amb_ccu_init(struct platform_device *pdev, + unsigned int num_clks) +{ + struct amb_ccu *ccu; + void __iomem *base; + + if (!num_clks) + return ERR_PTR(-EINVAL); + + ccu =3D devm_kzalloc(&pdev->dev, sizeof(*ccu), GFP_KERNEL); + if (!ccu) + return ERR_PTR(-ENOMEM); + + ccu->dev =3D &pdev->dev; + + ccu->data =3D devm_kzalloc(&pdev->dev, + struct_size(ccu->data, hws, num_clks), + GFP_KERNEL); + if (!ccu->data) + return ERR_PTR(-ENOMEM); + + ccu->data->num =3D num_clks; + + base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return ERR_CAST(base); + + ccu->map =3D devm_regmap_init_mmio(&pdev->dev, base, + &amb_rct_regmap_config); + if (IS_ERR(ccu->map)) + return ERR_CAST(ccu->map); + + return ccu; +} + +int amb_ccu_register(struct amb_ccu *ccu) +{ + return devm_of_clk_add_hw_provider(ccu->dev, of_clk_hw_onecell_get, + ccu->data); +} diff --git a/drivers/clk/ambarella/ccu_common.h b/drivers/clk/ambarella/ccu= _common.h new file mode 100644 index 000000000000..f2bf9d1f06d7 --- /dev/null +++ b/drivers/clk/ambarella/ccu_common.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 Ambarella, Inc. + */ + +#ifndef __CCU_COMMON_H +#define __CCU_COMMON_H + +#include +#include +#include + +#define AMB_RCT_REG_SIZE 0x1000 + +struct amb_ccu { + struct device *dev; + struct regmap *map; + struct clk_hw_onecell_data *data; +}; + +struct amb_ccu *amb_ccu_init(struct platform_device *pdev, + unsigned int num_clks); +int amb_ccu_register(struct amb_ccu *ccu); + +#endif diff --git a/drivers/clk/ambarella/ccu_mux_div.c b/drivers/clk/ambarella/cc= u_mux_div.c new file mode 100644 index 000000000000..d5259bc347e4 --- /dev/null +++ b/drivers/clk/ambarella/ccu_mux_div.c @@ -0,0 +1,234 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Ambarella, Inc. + * + * Regmap-backed mux + divider, derived from the vendor composite-clock dr= iver. + */ + +#include +#include +#include +#include + +#include "ccu_mux_div.h" + +struct amb_mux { + struct clk_hw hw; + struct regmap *map; + u32 offset; + u32 mask; + u32 shift; +}; + +struct amb_div { + struct clk_hw hw; + struct regmap *map; + u32 offset; + u32 shift; + u32 width; + u32 flags; + u32 fix_divider; +}; + +#define to_amb_mux(_hw) container_of(_hw, struct amb_mux, hw) +#define to_amb_div(_hw) container_of(_hw, struct amb_div, hw) + +static u8 amb_mux_get_parent(struct clk_hw *hw) +{ + struct amb_mux *mux =3D to_amb_mux(hw); + u32 val; + + regmap_read(mux->map, mux->offset, &val); + val >>=3D mux->shift; + val &=3D mux->mask; + + return val; +} + +static int amb_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct amb_mux *mux =3D to_amb_mux(hw); + + return regmap_update_bits(mux->map, mux->offset, + mux->mask << mux->shift, + index << mux->shift); +} + +static const struct clk_ops amb_mux_ops =3D { + .get_parent =3D amb_mux_get_parent, + .set_parent =3D amb_mux_set_parent, +}; + +static unsigned long amb_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct amb_div *div =3D to_amb_div(hw); + unsigned long rate; + u32 val; + + regmap_read(div->map, div->offset, &val); + + /* Divider reset/disable bit sits above the field at shift+width. */ + if (val & (BIT(div->width) << div->shift)) + return 0; + + val >>=3D div->shift; + val &=3D clk_div_mask(div->width); + + rate =3D divider_recalc_rate(hw, parent_rate, val, NULL, + div->flags, div->width); + if (div->fix_divider) + rate =3D div_u64(rate, div->fix_divider); + + return rate; +} + +static int amb_div_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct amb_div *div =3D to_amb_div(hw); + struct clk_rate_request scaled =3D *req; + int ret; + + if (!req->rate && (div->flags & CLK_DIVIDER_ONE_BASED)) + return 0; + + if (div->fix_divider) { + scaled.rate =3D min(req->rate, + ULONG_MAX / div->fix_divider) * + div->fix_divider; + scaled.min_rate =3D min(req->min_rate, + ULONG_MAX / div->fix_divider) * + div->fix_divider; + scaled.max_rate =3D min(req->max_rate, + ULONG_MAX / div->fix_divider) * + div->fix_divider; + } + + ret =3D divider_determine_rate(hw, &scaled, NULL, div->width, + div->flags); + if (ret) + return ret; + + req->rate =3D scaled.rate; + req->best_parent_rate =3D scaled.best_parent_rate; + req->best_parent_hw =3D scaled.best_parent_hw; + if (div->fix_divider) + req->rate =3D div_u64(req->rate, div->fix_divider); + + return 0; +} + +static int amb_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct amb_div *div =3D to_amb_div(hw); + int val, mask; + + if (div->fix_divider) + rate *=3D div->fix_divider; + + if (!rate) { + /* Assert the reset/disable bit above the divider field. */ + val =3D BIT(div->width); + mask =3D clk_div_mask(div->width + 1); + } else { + val =3D divider_get_val(rate, parent_rate, NULL, + div->width, div->flags); + if (val < 0) + return val; + + /* + * Include the disable bit in the mask so a later non-zero + * set_rate clears a previous rate=3D=3D0 disable assert. + */ + mask =3D clk_div_mask(div->width + 1); + } + + regmap_update_bits(div->map, div->offset, mask << div->shift, + val << div->shift); + + /* + * Non-ONE_BASED dividers use bit 0 as a write-enable strobe. Skip the + * pulse when shift =3D=3D 0 so we do not corrupt the divider field itsel= f. + */ + if (!(div->flags & CLK_DIVIDER_ONE_BASED) && div->shift) { + regmap_update_bits(div->map, div->offset, BIT(0), BIT(0)); + regmap_update_bits(div->map, div->offset, BIT(0), 0); + } + + return 0; +} + +static const struct clk_ops amb_div_ops =3D { + .recalc_rate =3D amb_div_recalc_rate, + .determine_rate =3D amb_div_determine_rate, + .set_rate =3D amb_div_set_rate, +}; + +struct clk_hw *amb_div_register(struct device *dev, struct regmap *map, + const char *name, const struct clk_hw *parent, + u32 div_reg, u32 div_shift, u32 div_width, + u32 div_flags, u32 fix_divider) +{ + struct amb_div *div; + struct clk_init_data init =3D {}; + int ret; + + div =3D devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + div->map =3D map; + div->offset =3D div_reg; + div->shift =3D div_shift; + div->width =3D div_width; + div->flags =3D div_flags; + div->fix_divider =3D fix_divider; + + init.name =3D name; + init.ops =3D &amb_div_ops; + init.parent_hws =3D &parent; + init.num_parents =3D 1; + + div->hw.init =3D &init; + + ret =3D devm_clk_hw_register(dev, &div->hw); + if (ret) + return ERR_PTR(ret); + + return &div->hw; +} + +struct clk_hw *amb_mux_div_register(struct device *dev, struct regmap *map, + const struct amb_mux_div_desc *desc, + const struct clk_parent_data *parent_data) +{ + struct amb_mux *mux; + struct amb_div *div; + + mux =3D devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); + div =3D devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); + if (!mux || !div) + return ERR_PTR(-ENOMEM); + + mux->map =3D map; + mux->offset =3D desc->mux_reg; + mux->shift =3D desc->mux_shift; + mux->mask =3D desc->mux_mask; + + div->map =3D map; + div->offset =3D desc->div_reg; + div->shift =3D desc->div_shift; + div->width =3D desc->div_width; + div->flags =3D desc->div_flags; + div->fix_divider =3D desc->fix_divider; + + return devm_clk_hw_register_composite_pdata(dev, desc->name, + parent_data, + desc->num_parents, + &mux->hw, &amb_mux_ops, + &div->hw, &amb_div_ops, + NULL, NULL, + CLK_SET_RATE_NO_REPARENT); +} diff --git a/drivers/clk/ambarella/ccu_mux_div.h b/drivers/clk/ambarella/cc= u_mux_div.h new file mode 100644 index 000000000000..abaefff1201a --- /dev/null +++ b/drivers/clk/ambarella/ccu_mux_div.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 Ambarella, Inc. + */ + +#ifndef __CCU_MUX_DIV_H +#define __CCU_MUX_DIV_H + +#include +#include + +struct amb_mux_div_desc { + const char *name; + const int *parents; + u8 num_parents; + u32 mux_reg; + u32 mux_shift; + u32 mux_mask; + u32 div_reg; + u32 div_shift; + u32 div_width; + u32 div_flags; + u32 fix_divider; +}; + +struct clk_hw *amb_mux_div_register(struct device *dev, struct regmap *map, + const struct amb_mux_div_desc *desc, + const struct clk_parent_data *parent_data); + +struct clk_hw *amb_div_register(struct device *dev, struct regmap *map, + const char *name, const struct clk_hw *parent, + u32 div_reg, u32 div_shift, u32 div_width, + u32 div_flags, u32 fix_divider); + +#endif diff --git a/drivers/clk/ambarella/ccu_pll.c b/drivers/clk/ambarella/ccu_pl= l.c new file mode 100644 index 000000000000..76452003bb0d --- /dev/null +++ b/drivers/clk/ambarella/ccu_pll.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2026 Ambarella, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "ccu_pll.h" + +#define AMB_PLL_MAX_SOUT 16UL +#define AMB_PLL_MAX_SDIV 16UL + +struct amb_pll { + struct clk_hw hw; + struct regmap *map; + u32 reg_offset[REG_NUM]; + const struct amb_pll_soc_data *soc_data; + u32 fix_divider; + bool frac_mode; +}; + +#define to_amb_pll(_hw) container_of(_hw, struct amb_pll, hw) + +static void amb_pll_write_enable(struct regmap *map, u32 offset, u32 val) +{ + regmap_write(map, offset, val); + regmap_write(map, offset, val | CTRL_WRITE_ENABLE); + regmap_write(map, offset, val); +} + +static unsigned long amb_pll_calc_vco(struct amb_pll *pll, + unsigned long parent_rate) +{ + const struct amb_pll_soc_data *soc_data =3D pll->soc_data; + u32 *reg =3D pll->reg_offset; + u32 pre_scaler =3D 1; + u32 ctrl_val, ctrl2_val =3D 0, frac_val; + u32 intp, sdiv, vcodiv, fsdiv; + u64 frac =3D 0, vco; + + if (reg[PRES_OFFSET]) { + regmap_read(pll->map, reg[PRES_OFFSET], &pre_scaler); + pre_scaler =3D (pre_scaler >> 4) + 1; + } + + regmap_read(pll->map, reg[CTRL_OFFSET], &ctrl_val); + intp =3D ((ctrl_val >> 24) & 0x7f) + 1; + sdiv =3D ((ctrl_val >> 12) & 0xf) + 1; + + if (soc_data->pll_version >=3D 2) { + vcodiv =3D (ctrl_val & soc_data->vcodiv_mask) =3D=3D + soc_data->vcodiv_val ? 2 : 1; + fsdiv =3D (ctrl_val & soc_data->fsdiv_mask) =3D=3D + soc_data->fsdiv_val ? 2 : 1; + } else { + regmap_read(pll->map, reg[CTRL2_OFFSET], &ctrl2_val); + vcodiv =3D (ctrl2_val & soc_data->vcodiv_mask) =3D=3D + soc_data->vcodiv_val ? 2 : 1; + fsdiv =3D (ctrl2_val & soc_data->fsdiv_mask) =3D=3D + soc_data->fsdiv_val ? 2 : 1; + } + + vco =3D (u64)parent_rate * vcodiv * fsdiv * intp * sdiv; + vco =3D div_u64(vco, pre_scaler); + + if (ctrl_val & CTRL_FRAC_MODE) { + regmap_read(pll->map, reg[FRAC_OFFSET], &frac_val); + frac =3D (u64)parent_rate * vcodiv * fsdiv * sdiv * frac_val; + frac =3D div_u64(frac, pre_scaler) >> 32; + } + + return vco + frac; +} + +static unsigned long amb_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct amb_pll *pll =3D to_amb_pll(hw); + const struct amb_pll_soc_data *soc_data =3D pll->soc_data; + u32 *reg =3D pll->reg_offset; + u32 pre_scaler =3D 1, post_scaler =3D 1; + u32 ctrl_val, ctrl2_val =3D 0; + u32 vcodiv, fsout, sout; + u64 rate; + + regmap_read(pll->map, reg[CTRL_OFFSET], &ctrl_val); + if (ctrl_val & (CTRL_POWER_DOWN | CTRL_HALT_VCO | CTRL_FORCE_RESET)) + return 0; + + if (reg[PRES_OFFSET]) { + regmap_read(pll->map, reg[PRES_OFFSET], &pre_scaler); + pre_scaler =3D (pre_scaler >> 4) + 1; + } + + if (reg[POST_OFFSET]) { + regmap_read(pll->map, reg[POST_OFFSET], &post_scaler); + post_scaler =3D (post_scaler >> 4) + 1; + } + + if (ctrl_val & CTRL_BYPASS) + return parent_rate / pre_scaler / post_scaler; + + if (soc_data->pll_version >=3D 2) { + vcodiv =3D (ctrl_val & soc_data->vcodiv_mask) =3D=3D + soc_data->vcodiv_val ? 2 : 1; + fsout =3D (ctrl_val & soc_data->fsout_mask) =3D=3D + soc_data->fsout_val ? 2 : 1; + } else { + regmap_read(pll->map, reg[CTRL2_OFFSET], &ctrl2_val); + vcodiv =3D (ctrl2_val & soc_data->vcodiv_mask) =3D=3D + soc_data->vcodiv_val ? 2 : 1; + fsout =3D (ctrl2_val & soc_data->fsout_mask) =3D=3D + soc_data->fsout_val ? 2 : 1; + } + + sout =3D ((ctrl_val >> 16) & 0xf) + 1; + rate =3D amb_pll_calc_vco(pll, parent_rate); + + if (soc_data->pll_version >=3D 2) { + if (!(ctrl_val & CTRL_BYPASS_HSDIV)) + rate =3D div_u64(rate, vcodiv * fsout * sout); + } else { + if (!(ctrl2_val & CTRL2_BYPASS_HSDIV)) + rate =3D div_u64(rate, vcodiv * fsout * sout); + } + + rate =3D div_u64(rate, pll->fix_divider * post_scaler); + + return rate; +} + +static int amb_pll_calc_params(struct amb_pll *pll, unsigned long rate, + unsigned long parent_rate, u32 ctrl2_val, + u32 *intp, u32 *sdiv, u32 *sout, + u32 *vcodiv, u32 *fsdiv, u32 *fsout) +{ + const struct amb_pll_soc_data *soc_data =3D pll->soc_data; + unsigned long max_numerator, max_denominator; + unsigned long intp_ul, sout_ul, rate_tmp, parent_scaled; + u32 ctrl_val; + + if (!parent_rate) + return -EINVAL; + + *sdiv =3D 1; + + if (soc_data->pll_version >=3D 2) { + ctrl_val =3D 0; + *vcodiv =3D (ctrl_val & soc_data->vcodiv_mask) =3D=3D + soc_data->vcodiv_val ? 2 : 1; + *fsdiv =3D (ctrl_val & soc_data->fsdiv_mask) =3D=3D + soc_data->fsdiv_val ? 2 : 1; + *fsout =3D (ctrl_val & soc_data->fsout_mask) =3D=3D + soc_data->fsout_val ? 2 : 1; + } else { + *vcodiv =3D (ctrl2_val & soc_data->vcodiv_mask) =3D=3D + soc_data->vcodiv_val ? 2 : 1; + *fsdiv =3D (ctrl2_val & soc_data->fsdiv_mask) =3D=3D + soc_data->fsdiv_val ? 2 : 1; + *fsout =3D (ctrl2_val & soc_data->fsout_mask) =3D=3D + soc_data->fsout_val ? 2 : 1; + } + + if (rate < parent_rate) + return -EINVAL; + + max_numerator =3D soc_data->vco_max_mhz; + max_numerator =3D div_u64(max_numerator * 1000000ULL, parent_rate); + max_numerator =3D div_u64(max_numerator, *vcodiv * *fsdiv); + max_numerator =3D min(128UL, max_numerator); + if (!max_numerator) + return -EINVAL; + + /* + * Approximate intp/sout against the fsdiv/fsout-scaled parent so the + * initial guess matches the hardware frequency equation. + */ + max_denominator =3D AMB_PLL_MAX_SOUT; + parent_scaled =3D parent_rate * *fsdiv / *fsout; + if (!parent_scaled) + return -EINVAL; + rate_tmp =3D rate; + rational_best_approximation(rate_tmp, parent_scaled, max_numerator, + max_denominator, &intp_ul, &sout_ul); + + while (parent_rate * *fsdiv * intp_ul * *sdiv / *fsout / sout_ul > + rate) { + unsigned long resolution =3D parent_scaled / AMB_PLL_MAX_SOUT; + + /* Avoid an infinite loop when parent_rate < AMB_PLL_MAX_SOUT. */ + if (!resolution) + resolution =3D 1; + + if (rate_tmp <=3D resolution) + return -EINVAL; + + rate_tmp -=3D resolution; + rational_best_approximation(rate_tmp, parent_scaled, + max_numerator, max_denominator, + &intp_ul, &sout_ul); + } + + while (parent_rate / 1000000 * *vcodiv * *fsdiv * intp_ul * *sdiv < + soc_data->vco_min_mhz) { + if (sout_ul > 8 || intp_ul > 64) + break; + + intp_ul *=3D 2; + sout_ul *=3D 2; + } + + if (intp_ul > max_numerator || sout_ul > max_denominator || + *sdiv > AMB_PLL_MAX_SDIV) + return -EINVAL; + + *intp =3D intp_ul; + *sout =3D sout_ul; + + return 0; +} + +static int amb_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct amb_pll *pll =3D to_amb_pll(hw); + const struct amb_pll_soc_data *soc_data =3D pll->soc_data; + u32 ctrl2_val =3D 0; + u32 intp, sdiv, sout, vcodiv, fsdiv, fsout; + unsigned long rate; + u64 rounded; + int ret; + + if (!req->best_parent_rate) + return -EINVAL; + + if (!req->rate || pll->frac_mode) + return 0; + + if (req->rate > ULONG_MAX / pll->fix_divider) + return -ERANGE; + + rate =3D req->rate * pll->fix_divider; + if (soc_data->ctrl2_val) + ctrl2_val =3D soc_data->ctrl2_val; + else + regmap_read(pll->map, pll->reg_offset[CTRL2_OFFSET], + &ctrl2_val); + + ret =3D amb_pll_calc_params(pll, rate, req->best_parent_rate, + ctrl2_val, &intp, &sdiv, &sout, &vcodiv, + &fsdiv, &fsout); + if (ret) + return ret; + + rounded =3D (u64)req->best_parent_rate * fsdiv * intp * sdiv; + rounded =3D div64_u64(rounded, (u64)fsout * sout); + rounded =3D div64_u64(rounded, pll->fix_divider); + if (rounded < req->min_rate || rounded > req->max_rate) + return -EINVAL; + + req->rate =3D rounded; + + return 0; +} + +static int amb_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct amb_pll *pll =3D to_amb_pll(hw); + const struct amb_pll_soc_data *soc_data =3D pll->soc_data; + u32 *reg =3D pll->reg_offset; + u32 ctrl_val, ctrl2_val =3D 0, ctrl3_val, frac_val =3D 0; + u32 intp, sdiv, sout, vcodiv, fsdiv, fsout; + unsigned long old_rate, new_rate, rate_tmp; + int ret; + + if (!rate) { + regmap_read(pll->map, reg[CTRL_OFFSET], &ctrl_val); + ctrl_val |=3D CTRL_POWER_DOWN | CTRL_HALT_VCO; + amb_pll_write_enable(pll->map, reg[CTRL_OFFSET], ctrl_val); + return 0; + } + + if (!parent_rate) + return -EINVAL; + + rate *=3D pll->fix_divider; + + if (soc_data->ctrl2_val) + ctrl2_val =3D soc_data->ctrl2_val; + else + regmap_read(pll->map, reg[CTRL2_OFFSET], &ctrl2_val); + + ret =3D amb_pll_calc_params(pll, rate, parent_rate, ctrl2_val, + &intp, &sdiv, &sout, &vcodiv, &fsdiv, + &fsout); + if (ret) + return ret; + + if (soc_data->ctrl2_val) + regmap_write(pll->map, reg[CTRL2_OFFSET], soc_data->ctrl2_val); + + ctrl_val =3D ((intp - 1) & 0x7f) << 24; + ctrl_val |=3D ((sdiv - 1) & 0xf) << 12; + ctrl_val |=3D ((sout - 1) & 0xf) << 16; + if (soc_data->pll_version >=3D 2) { + ctrl_val |=3D vcodiv =3D=3D 2 ? soc_data->vcodiv_val : 0; + ctrl_val |=3D fsdiv =3D=3D 2 ? soc_data->fsdiv_val : 0; + ctrl_val |=3D fsout =3D=3D 2 ? soc_data->fsout_val : 0; + } + + regmap_write(pll->map, reg[CTRL_OFFSET], ctrl_val); + regmap_write(pll->map, reg[FRAC_OFFSET], 0); + + old_rate =3D amb_pll_recalc_rate(hw, parent_rate) * pll->fix_divider; + rate_tmp =3D old_rate > rate ? 0 : rate - old_rate; + if (rate_tmp && pll->frac_mode) { + u64 dividend, divider; + + dividend =3D (u64)rate_tmp * sout * fsout; + dividend <<=3D 32; + divider =3D (u64)sdiv * fsdiv * parent_rate; + frac_val =3D DIV64_U64_ROUND_CLOSEST(dividend, divider); + regmap_write(pll->map, reg[FRAC_OFFSET], frac_val); + ctrl_val |=3D CTRL_FRAC_MODE; + } + + if (soc_data->pll_version >=3D 2) { + ctrl3_val =3D soc_data->ctrl3_val; + regmap_write(pll->map, reg[CTRL3_OFFSET], + ctrl3_val | CTRL3_VCO_CLAMP); + regmap_write(pll->map, reg[CTRL_OFFSET], + ctrl_val | CTRL_FORCE_RESET); + ndelay(100); + regmap_write(pll->map, reg[CTRL_OFFSET], + ctrl_val & ~CTRL_FORCE_RESET); + ndelay(100); + regmap_write(pll->map, reg[CTRL3_OFFSET], + ctrl3_val & ~CTRL3_VCO_CLAMP); + } else { + u32 fvco_mhz, range; + + fvco_mhz =3D amb_pll_calc_vco(pll, parent_rate) / 1000000UL; + for (range =3D 0; range < ARRAY_SIZE(soc_data->vco_range); + range++) { + if (fvco_mhz > soc_data->vco_range[range]) + break; + } + if (range =3D=3D ARRAY_SIZE(soc_data->vco_range)) + range =3D 0; + else + range =3D ARRAY_SIZE(soc_data->vco_range) - range - 1; + + regmap_read(pll->map, reg[CTRL3_OFFSET], &ctrl3_val); + ctrl3_val &=3D ~CTRL3_VCO_RANGE_MASK; + ctrl3_val |=3D range << 1; + regmap_write(pll->map, reg[CTRL3_OFFSET], ctrl3_val); + + if (frac_val) { + ctrl_val |=3D CTRL_FORCE_RESET; + amb_pll_write_enable(pll->map, reg[CTRL_OFFSET], + ctrl_val); + } + + ctrl_val &=3D ~CTRL_FORCE_RESET; + amb_pll_write_enable(pll->map, reg[CTRL_OFFSET], ctrl_val); + } + + new_rate =3D amb_pll_recalc_rate(hw, parent_rate); + rate_tmp =3D rate / pll->fix_divider; + if (max(new_rate, rate_tmp) - min(new_rate, rate_tmp) > 10) + pr_warn("%s: requested %lu, got %lu\n", clk_hw_get_name(hw), + rate_tmp, new_rate); + + return 0; +} + +static const struct clk_ops amb_pll_ops =3D { + .recalc_rate =3D amb_pll_recalc_rate, + .determine_rate =3D amb_pll_determine_rate, + .set_rate =3D amb_pll_set_rate, +}; + +struct clk_hw *amb_pll_register(struct device *dev, struct regmap *map, + const struct amb_pll_desc *desc) +{ + struct amb_pll *pll; + struct clk_init_data init =3D {}; + const struct clk_hw *parent =3D desc->parent; + int ret; + + pll =3D devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->map =3D map; + memcpy(pll->reg_offset, desc->reg_offset, sizeof(pll->reg_offset)); + pll->soc_data =3D desc->soc_data; + pll->fix_divider =3D 1; + pll->frac_mode =3D desc->frac_mode; + + init.name =3D desc->name; + init.ops =3D &amb_pll_ops; + init.flags =3D CLK_GET_RATE_NOCACHE | CLK_IS_CRITICAL; + init.parent_hws =3D &parent; + init.num_parents =3D 1; + + pll->hw.init =3D &init; + + ret =3D devm_clk_hw_register(dev, &pll->hw); + if (ret) + return ERR_PTR(ret); + + return &pll->hw; +} diff --git a/drivers/clk/ambarella/ccu_pll.h b/drivers/clk/ambarella/ccu_pl= l.h new file mode 100644 index 000000000000..6d901e88f410 --- /dev/null +++ b/drivers/clk/ambarella/ccu_pll.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2026 Ambarella, Inc. + */ + +#ifndef __CCU_PLL_H +#define __CCU_PLL_H + +#include +#include +#include +#include +#include + +enum { + CTRL_OFFSET =3D 0, + FRAC_OFFSET, + CTRL2_OFFSET, + CTRL3_OFFSET, + PRES_OFFSET, + POST_OFFSET, + REG_NUM, +}; + +#define CTRL_BYPASS BIT(2) +#define CTRL_WRITE_ENABLE BIT(0) +#define CTRL_FRAC_MODE BIT(3) +#define CTRL_FORCE_RESET BIT(4) +#define CTRL_POWER_DOWN BIT(5) +#define CTRL_HALT_VCO BIT(6) +#define CTRL_VCODIV_DIV2 BIT(8) +#define CTRL_FSDIV_DIV2 BIT(9) +#define CTRL_FSOUT_DIV2 BIT(10) +#define CTRL_BYPASS_HSDIV BIT(11) + +#define CTRL2_VCODIV_DIV2 BIT(8) +#define CTRL2_FSDIV_DIV2 BIT(9) +#define CTRL2_FSOUT_DIV2 BIT(11) +#define CTRL2_BYPASS_HSDIV BIT(12) + +#define CTRL3_VCO_RANGE_MASK 0x6 +#define CTRL3_VCO_CLAMP 0x8 + +struct amb_pll_soc_data { + u32 pll_version; + u32 fsout_mask; + u32 fsout_val; + u32 fsdiv_mask; + u32 fsdiv_val; + u32 vcodiv_mask; + u32 vcodiv_val; + u32 vco_max_mhz; + u32 vco_min_mhz; + u32 vco_range[4]; + u32 ctrl2_val; + u32 ctrl3_val; +}; + +struct amb_pll_desc { + const char *name; + const struct clk_hw *parent; + u32 reg_offset[REG_NUM]; + const struct amb_pll_soc_data *soc_data; + bool frac_mode; +}; + +struct clk_hw *amb_pll_register(struct device *dev, struct regmap *map, + const struct amb_pll_desc *desc); + +#endif --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 877AF41DE15; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=esHAGyFTLQsSXUpGD9G13P9LGNQUxGQK6+HoCtGkaHARXjg5ip+jXjTndN74RsrFSbNN+6kCRhD+s1jOYHDtpjPO9ukhd3z0r7KxcbPCbrTYxz9BF6EMHa7XlHVOjLbSr2FxnDJuX+YD8LmqLE90TAqww8s/8wS1yfOtL+rvHGo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=fTYrlYc/jDOyyW1JHqcXVgR7s43Ok1EE/6NxZ45lwiI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bYJ/UyAQVDTE9b8bq4lwAOf8kaF9pL4K+ZTkUV6+wFbAg/+MRa4AjCyMHGR/vj0/0UlQ/U3yXAgce4tXzA+Q1RjsJ4jM4QM9QummsOMhmanvnIYtnUXZ+gJXeLVhcpmngv3uxNHilG99eITLb1NKmxaYhrPV5XsfDGOJIjzTW5E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=duUIYKs6; 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="duUIYKs6" Received: by smtp.kernel.org (Postfix) with ESMTPS id 48586C2BD04; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=fTYrlYc/jDOyyW1JHqcXVgR7s43Ok1EE/6NxZ45lwiI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=duUIYKs6eNciXHDXf3PrPNgOzFM9CWwZAHcSMGmIJflXJ5SDdwfBi5RF8E+fZBnao x6z+vZjO9GIUj4G1OiAXkHqeVC0uX8rOApEpVkqnqsh6wgVxACRcpXb7XSvs1yOYsV fS97DuXLuG6AeVJgfkNKtWiuFTquLDPiPkuHvnPQF7jOZAWLNlY2DvFXSrtWrA/Fu2 T2qlwk/pVbO5ZEaNWf9MjcB8WR5An2vw0S2zA5l0kH93NjYmk9/Ja8JT7qNukyLaMH CagptAK4RqDhkn2nvJIqcVezzdkAIuTro0zZwLjh3vu0+oeqwAn7ZqfgY7i8naE3Hf vXzQZAvDY+r/A== 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 33E05C79F85; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:15 +0800 Subject: [PATCH v6 08/13] gpio: regmap: support write_data_after_dir and girq 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: <20260904-cv75-v5-v6-8-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=4540; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=KycT9tCUaJK+3T2peLT5loHlf/DpTwIq3Pwde6A3W6c=; b=Yb23nkmcQvpXY7/MoTocT7QJWIK3F4m2m54gDR1qN0PDiBGMbkb4FJ/91BRR5mrthdQi1qzVs qx5/ITDsDUhCeZu4N+N6Qx+4OV8CtPULThI0gb+Vf3gmmR6jYjN3Izw X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Add an optional write-after-direction-output quirk for controllers that ignore data-register writes while a line is still configured as input, and allow drivers to pass an existing gpio_irq_chip through gpio_regmap_register() so IRQ setup can stay with the caller. Signed-off-by: Long Zhao --- drivers/gpio/gpio-regmap.c | 24 +++++++++++++++++++++++- include/linux/gpio/regmap.h | 13 +++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-regmap.c b/drivers/gpio/gpio-regmap.c index 51b4d69b8740..b4b492a1765c 100644 --- a/drivers/gpio/gpio-regmap.c +++ b/drivers/gpio/gpio-regmap.c @@ -33,6 +33,7 @@ struct gpio_regmap { unsigned int reg_dir_out_base; unsigned long *fixed_direction_mask; unsigned long *fixed_direction_output; + bool write_data_after_dir; =20 #ifdef CONFIG_REGMAP_IRQ int regmap_irq_line; @@ -273,7 +274,15 @@ static int gpio_regmap_direction_output(struct gpio_ch= ip *chip, =20 gpio_regmap_set(chip, offset, value); =20 - return gpio_regmap_set_direction(chip, offset, true); + ret =3D gpio_regmap_set_direction(chip, offset, true); + if (ret) + return ret; + + /* Some controllers ignore data writes while the line is still an input. = */ + if (gpio->write_data_after_dir) + gpio_regmap_set(chip, offset, value); + + return 0; } =20 void *gpio_regmap_get_drvdata(struct gpio_regmap *gpio) @@ -311,6 +320,14 @@ struct gpio_regmap *gpio_regmap_register(const struct = gpio_regmap_config *config if (config->reg_dir_out_base && config->reg_dir_in_base) return ERR_PTR(-EINVAL); =20 + if (config->girq && config->irq_domain) + return ERR_PTR(-EINVAL); + +#ifdef CONFIG_REGMAP_IRQ + if (config->girq && config->regmap_irq_chip) + return ERR_PTR(-EINVAL); +#endif + gpio =3D kzalloc_obj(*gpio); if (!gpio) return ERR_PTR(-ENOMEM); @@ -376,6 +393,8 @@ struct gpio_regmap *gpio_regmap_register(const struct g= pio_regmap_config *config config->fixed_direction_output, chip->ngpio); } =20 + gpio->write_data_after_dir =3D config->write_data_after_dir; + /* if not set, assume there is only one register */ gpio->ngpio_per_reg =3D config->ngpio_per_reg; if (!gpio->ngpio_per_reg) @@ -390,6 +409,9 @@ struct gpio_regmap *gpio_regmap_register(const struct g= pio_regmap_config *config if (!gpio->reg_mask_xlate) gpio->reg_mask_xlate =3D gpio_regmap_simple_xlate; =20 + if (config->girq) + chip->irq =3D *config->girq; + ret =3D gpiochip_add_data(chip, gpio); if (ret < 0) goto err_free_bitmap_output; diff --git a/include/linux/gpio/regmap.h b/include/linux/gpio/regmap.h index 06255756710d..f94dd95d330f 100644 --- a/include/linux/gpio/regmap.h +++ b/include/linux/gpio/regmap.h @@ -7,6 +7,7 @@ struct device; struct fwnode_handle; struct gpio_regmap; struct gpio_chip; +struct gpio_irq_chip; struct irq_domain; struct regmap; =20 @@ -34,6 +35,11 @@ struct regmap; * @ngpio_per_reg: (Optional) Number of GPIOs per register * @irq_domain: (Optional) IRQ domain if the controller is * interrupt-capable + * @girq: (Optional) Interrupt chip settings for the gpio_chip, + * prepared by the driver as for a direct gpiochip + * registration. The gpio_chip will then create and + * manage its own IRQ domain. Mutually exclusive with + * @irq_domain and @regmap_irq_chip. * @reg_mask_xlate: (Optional) Translates base address and GPIO * offset to a register/bitmask pair. If not * given the default gpio_regmap_simple_xlate() @@ -48,6 +54,11 @@ struct regmap; * (Optional) Bitmap representing the fixed direction of * the GPIO lines. Useful when there are GPIO lines with a * fixed direction mixed together in the same register. + * @write_data_after_dir: + * (Optional) Write the output value again after + * switching a line to output in ->direction_output(). + * Needed for hardware which ignores data register + * writes while the line is configured as an input. * @drvdata: (Optional) Pointer to driver specific data which is * not used by gpio-remap but is provided "as is" to the * driver callback(s). @@ -95,8 +106,10 @@ struct gpio_regmap_config { int reg_stride; int ngpio_per_reg; struct irq_domain *irq_domain; + const struct gpio_irq_chip *girq; unsigned long *fixed_direction_mask; unsigned long *fixed_direction_output; + bool write_data_after_dir; =20 #ifdef CONFIG_REGMAP_IRQ struct regmap_irq_chip *regmap_irq_chip; --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 A047D41F5D7; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=KC+Zl8F35w1U6+TeXDaIajpfm3viLziZf2H4lkHHpqRdedR0CMKKqyHoIbD9iSEMBsFAVivSwsYei47Op13YtLIj00FNEHRJ/ZqaS8MsAW2XVGCS+WXR9CPGz/+4dirVzMKcdOjLnQJLHo/Kg+hATO1nKODbd4b0+A1YVoaLQQ4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=r4yme7FRSW8qMCF1+BSpasmdZD2Vf8zFJ46MWRuLUqo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jn8cciVS3e+sZcZN1RW9NQ+AHdbyZBLr/qowKk+xsEzgmciprvws7BWdXPn+ezio7rGDe4oAYUCsZjtO5xt+uKkPvnJVmdjBvonJmd6aTxOlTfwzxWled6HWkUxCfabZrCb032bOfyH5zedCPsB6noolQr58is1ecXBa34rfPag= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NNV6JFOg; 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="NNV6JFOg" Received: by smtp.kernel.org (Postfix) with ESMTPS id 5EC82C4AF10; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=r4yme7FRSW8qMCF1+BSpasmdZD2Vf8zFJ46MWRuLUqo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=NNV6JFOgP/JIDypWO+NQSAvjMBmz21LmtiAbhhU/zStKxI77G8Ip1URXcNNFqKRjH E6kiS7eEL1KLu8lsQlb7qJ41Pv0sKAu+FBXFfohPRf4v9nwjBHlL4xu70EGh7vuhfr oW0ARFgJt3fFG26aNXvsbPHG2bhIsbgsCLzCs95qF1vaBIFhVjZiMlkDN5K8E8kBxT sEy5nOxndMp6e9A9z8AuAGIBwxwkqfU7Rn9KpWCWleWw5soo1b9dmFZa7edYX/n/RY LZfJFcB6EPy32SraTClN6G8asxPbTydFMXO8AveAd0kGeo6z2nhHcN4h2/0xHiulXU 04LtLETXyc9NQ== 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 48067C79F82; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:16 +0800 Subject: [PATCH v6 09/13] gpio: pl061: use gpio-regmap and add Ambarella layout 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: <20260904-cv75-v5-v6-9-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=18274; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=V1wgVvwkEs+6fWnu6vAzP061lTGyxowJwkCsFwebUoA=; b=WSk9h9IAGipLjwvvCloqfx8Qa9bZ7od7bKIDIJU0zD1keqZaZRzw1tXXuIW4G0DCnRqcmXGld 3GJVg5tcEFID81ggrOz88Qa6FT9k07WOBC2PQ0wQ6h1vyXsDN+ODUaA X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Convert PL061 data and direction handling to gpio-regmap while keeping the existing PL061 irqchip path. Add an Ambarella CV75 register layout variant on the AMBA bus, without claiming unverified GPIO suspend/resume support for Ambarella. Signed-off-by: Long Zhao --- drivers/gpio/Kconfig | 2 + drivers/gpio/gpio-pl061.c | 342 ++++++++++++++++++++++++++++--------------= ---- include/linux/amba/bus.h | 1 + 3 files changed, 212 insertions(+), 133 deletions(-) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f03c05288376..55a129836158 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -583,6 +583,8 @@ config GPIO_PL061 depends on ARM_AMBA || COMPILE_TEST select IRQ_DOMAIN select GPIOLIB_IRQCHIP + select GPIO_REGMAP + select REGMAP_MMIO help Say yes here to support the PrimeCell PL061 GPIO device. =20 diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c index 919cf86fd590..6b09031f8664 100644 --- a/drivers/gpio/gpio-pl061.c +++ b/drivers/gpio/gpio-pl061.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -22,20 +23,36 @@ #include #include #include +#include #include #include #include =20 -#define GPIODIR 0x400 -#define GPIOIS 0x404 -#define GPIOIBE 0x408 -#define GPIOIEV 0x40C -#define GPIOIE 0x410 -#define GPIORIS 0x414 -#define GPIOMIS 0x418 -#define GPIOIC 0x41C - -#define PL061_GPIO_NR 8 +#define PL061_REG_NONE ((unsigned int)-1) + +#define PL061_GPIO_NR 8 +#define AMBARELLA_GPIO_NR 32 + +struct pl061_variant_data { + unsigned int data; + unsigned int dir; + unsigned int is; + unsigned int ibe; + unsigned int iev; + unsigned int ie; + unsigned int ris; + unsigned int mis; + unsigned int ic; + unsigned int mask; + unsigned int enable; + unsigned int ngpio; + bool access_32bit; + bool masked_data_address; + bool write_data_after_dir; + bool clear_irq_on_type; + bool pm_save_restore; + const struct regmap_config *regmap_config; +}; =20 struct pl061_context_save_regs { u8 gpio_data; @@ -48,74 +65,47 @@ struct pl061_context_save_regs { =20 struct pl061 { raw_spinlock_t lock; - void __iomem *base; - struct gpio_chip gc; + const struct pl061_variant_data *variant; + struct gpio_irq_chip girq; int parent_irq; =20 struct pl061_context_save_regs csave_regs; }; =20 -static int pl061_get_direction(struct gpio_chip *gc, unsigned offset) -{ - struct pl061 *pl061 =3D gpiochip_get_data(gc); - - if (readb(pl061->base + GPIODIR) & BIT(offset)) - return GPIO_LINE_DIRECTION_OUT; - - return GPIO_LINE_DIRECTION_IN; -} - -static int pl061_direction_input(struct gpio_chip *gc, unsigned offset) +static struct pl061 *pl061_from_gpio_chip(struct gpio_chip *gc) { - struct pl061 *pl061 =3D gpiochip_get_data(gc); - unsigned long flags; - unsigned char gpiodir; - - raw_spin_lock_irqsave(&pl061->lock, flags); - gpiodir =3D readb(pl061->base + GPIODIR); - gpiodir &=3D ~(BIT(offset)); - writeb(gpiodir, pl061->base + GPIODIR); - raw_spin_unlock_irqrestore(&pl061->lock, flags); - - return 0; + return gpio_regmap_get_drvdata(gpiochip_get_data(gc)); } =20 -static int pl061_direction_output(struct gpio_chip *gc, unsigned offset, - int value) +static u32 pl061_read(struct pl061 *pl061, unsigned int reg) { - struct pl061 *pl061 =3D gpiochip_get_data(gc); - unsigned long flags; - unsigned char gpiodir; + if (pl061->variant->access_32bit) + return readl(pl061->base + reg); =20 - raw_spin_lock_irqsave(&pl061->lock, flags); - writeb(!!value << offset, pl061->base + (BIT(offset + 2))); - gpiodir =3D readb(pl061->base + GPIODIR); - gpiodir |=3D BIT(offset); - writeb(gpiodir, pl061->base + GPIODIR); - - /* - * gpio value is set again, because pl061 doesn't allow to set value of - * a gpio pin before configuring it in OUT mode. - */ - writeb(!!value << offset, pl061->base + (BIT(offset + 2))); - raw_spin_unlock_irqrestore(&pl061->lock, flags); - - return 0; + return readb(pl061->base + reg); } =20 -static int pl061_get_value(struct gpio_chip *gc, unsigned offset) +static void pl061_write(struct pl061 *pl061, u32 value, unsigned int reg) { - struct pl061 *pl061 =3D gpiochip_get_data(gc); - - return !!readb(pl061->base + (BIT(offset + 2))); + if (pl061->variant->access_32bit) + writel(value, pl061->base + reg); + else + writeb(value, pl061->base + reg); } =20 -static int pl061_set_value(struct gpio_chip *gc, unsigned int offset, int = value) +static int pl061_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int bas= e, + unsigned int offset, unsigned int *reg, + unsigned int *mask) { - struct pl061 *pl061 =3D gpiochip_get_data(gc); + struct pl061 *pl061 =3D gpio_regmap_get_drvdata(gpio); =20 - writeb(!!value << offset, pl061->base + (BIT(offset + 2))); + /* ARM PL061 data bits use masked addresses: bits [9:2] select pins. */ + if (base =3D=3D pl061->variant->data) + *reg =3D BIT(offset + 2); + else + *reg =3D base; + *mask =3D BIT(offset); =20 return 0; } @@ -123,18 +113,17 @@ static int pl061_set_value(struct gpio_chip *gc, unsi= gned int offset, int value) static int pl061_irq_type(struct irq_data *d, unsigned trigger) { struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct pl061 *pl061 =3D gpiochip_get_data(gc); + struct pl061 *pl061 =3D pl061_from_gpio_chip(gc); + const struct pl061_variant_data *variant =3D pl061->variant; int offset =3D irqd_to_hwirq(d); unsigned long flags; - u8 gpiois, gpioibe, gpioiev; - u8 bit =3D BIT(offset); + u32 gpiois, gpioibe, gpioiev; + u32 bit =3D BIT(offset); =20 - if (offset < 0 || offset >=3D PL061_GPIO_NR) + if (offset < 0 || offset >=3D (int)gc->ngpio) return -EINVAL; =20 - if ((trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) && - (trigger & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))) - { + if ((trigger & IRQ_TYPE_LEVEL_MASK) && (trigger & IRQ_TYPE_EDGE_BOTH)) { dev_err(gc->parent, "trying to configure line %d for both level and edge " "detection, choose one!\n", @@ -142,14 +131,13 @@ static int pl061_irq_type(struct irq_data *d, unsigne= d trigger) return -EINVAL; } =20 - raw_spin_lock_irqsave(&pl061->lock, flags); =20 - gpioiev =3D readb(pl061->base + GPIOIEV); - gpiois =3D readb(pl061->base + GPIOIS); - gpioibe =3D readb(pl061->base + GPIOIBE); + gpioiev =3D pl061_read(pl061, variant->iev); + gpiois =3D pl061_read(pl061, variant->is); + gpioibe =3D pl061_read(pl061, variant->ibe); =20 - if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) { + if (trigger & IRQ_TYPE_LEVEL_MASK) { bool polarity =3D trigger & IRQ_TYPE_LEVEL_HIGH; =20 /* Disable edge detection */ @@ -199,9 +187,11 @@ static int pl061_irq_type(struct irq_data *d, unsigned= trigger) offset); } =20 - writeb(gpiois, pl061->base + GPIOIS); - writeb(gpioibe, pl061->base + GPIOIBE); - writeb(gpioiev, pl061->base + GPIOIEV); + pl061_write(pl061, gpiois, variant->is); + pl061_write(pl061, gpioibe, variant->ibe); + pl061_write(pl061, gpioiev, variant->iev); + if (variant->clear_irq_on_type) + pl061_write(pl061, bit, variant->ic); =20 raw_spin_unlock_irqrestore(&pl061->lock, flags); =20 @@ -213,16 +203,15 @@ static void pl061_irq_handler(struct irq_desc *desc) unsigned long pending; int offset; struct gpio_chip *gc =3D irq_desc_get_handler_data(desc); - struct pl061 *pl061 =3D gpiochip_get_data(gc); + struct pl061 *pl061 =3D pl061_from_gpio_chip(gc); struct irq_chip *irqchip =3D irq_desc_get_chip(desc); =20 chained_irq_enter(irqchip, desc); =20 - pending =3D readb(pl061->base + GPIOMIS); + pending =3D pl061_read(pl061, pl061->variant->mis); if (pending) { - for_each_set_bit(offset, &pending, PL061_GPIO_NR) - generic_handle_domain_irq(gc->irq.domain, - offset); + for_each_set_bit(offset, &pending, gc->ngpio) + generic_handle_domain_irq(gc->irq.domain, offset); } =20 chained_irq_exit(irqchip, desc); @@ -231,13 +220,13 @@ static void pl061_irq_handler(struct irq_desc *desc) static void pl061_irq_mask(struct irq_data *d) { struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct pl061 *pl061 =3D gpiochip_get_data(gc); - u8 mask =3D BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); - u8 gpioie; + struct pl061 *pl061 =3D pl061_from_gpio_chip(gc); + u32 mask =3D BIT(irqd_to_hwirq(d) % gc->ngpio); + u32 gpioie; =20 raw_spin_lock(&pl061->lock); - gpioie =3D readb(pl061->base + GPIOIE) & ~mask; - writeb(gpioie, pl061->base + GPIOIE); + gpioie =3D pl061_read(pl061, pl061->variant->ie) & ~mask; + pl061_write(pl061, gpioie, pl061->variant->ie); raw_spin_unlock(&pl061->lock); =20 gpiochip_disable_irq(gc, d->hwirq); @@ -246,15 +235,15 @@ static void pl061_irq_mask(struct irq_data *d) static void pl061_irq_unmask(struct irq_data *d) { struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct pl061 *pl061 =3D gpiochip_get_data(gc); - u8 mask =3D BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); - u8 gpioie; + struct pl061 *pl061 =3D pl061_from_gpio_chip(gc); + u32 mask =3D BIT(irqd_to_hwirq(d) % gc->ngpio); + u32 gpioie; =20 gpiochip_enable_irq(gc, d->hwirq); =20 raw_spin_lock(&pl061->lock); - gpioie =3D readb(pl061->base + GPIOIE) | mask; - writeb(gpioie, pl061->base + GPIOIE); + gpioie =3D pl061_read(pl061, pl061->variant->ie) | mask; + pl061_write(pl061, gpioie, pl061->variant->ie); raw_spin_unlock(&pl061->lock); } =20 @@ -269,18 +258,18 @@ static void pl061_irq_unmask(struct irq_data *d) static void pl061_irq_ack(struct irq_data *d) { struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct pl061 *pl061 =3D gpiochip_get_data(gc); - u8 mask =3D BIT(irqd_to_hwirq(d) % PL061_GPIO_NR); + struct pl061 *pl061 =3D pl061_from_gpio_chip(gc); + u32 mask =3D BIT(irqd_to_hwirq(d) % gc->ngpio); =20 raw_spin_lock(&pl061->lock); - writeb(mask, pl061->base + GPIOIC); + pl061_write(pl061, mask, pl061->variant->ic); raw_spin_unlock(&pl061->lock); } =20 static int pl061_irq_set_wake(struct irq_data *d, unsigned int state) { struct gpio_chip *gc =3D irq_data_get_irq_chip_data(d); - struct pl061 *pl061 =3D gpiochip_get_data(gc); + struct pl061 *pl061 =3D pl061_from_gpio_chip(gc); =20 return irq_set_irq_wake(pl061->parent_irq, state); } @@ -306,42 +295,41 @@ static const struct irq_chip pl061_irq_chip =3D { static int pl061_probe(struct amba_device *adev, const struct amba_id *id) { struct device *dev =3D &adev->dev; + struct gpio_regmap_config config =3D {}; + const struct pl061_variant_data *variant =3D id->data; struct pl061 *pl061; struct gpio_irq_chip *girq; + struct regmap *regmap; int ret, irq; =20 pl061 =3D devm_kzalloc(dev, sizeof(*pl061), GFP_KERNEL); if (pl061 =3D=3D NULL) return -ENOMEM; =20 + pl061->variant =3D variant; + pl061->base =3D devm_ioremap_resource(dev, &adev->res); if (IS_ERR(pl061->base)) return PTR_ERR(pl061->base); =20 raw_spin_lock_init(&pl061->lock); - pl061->gc.request =3D gpiochip_generic_request; - pl061->gc.free =3D gpiochip_generic_free; - pl061->gc.base =3D -1; - pl061->gc.get_direction =3D pl061_get_direction; - pl061->gc.direction_input =3D pl061_direction_input; - pl061->gc.direction_output =3D pl061_direction_output; - pl061->gc.get =3D pl061_get_value; - pl061->gc.set =3D pl061_set_value; - pl061->gc.ngpio =3D PL061_GPIO_NR; - pl061->gc.label =3D dev_name(dev); - pl061->gc.parent =3D dev; - pl061->gc.owner =3D THIS_MODULE; - - /* - * irq_chip support - */ - writeb(0, pl061->base + GPIOIE); /* disable irqs */ + + regmap =3D devm_regmap_init_mmio(dev, pl061->base, variant->regmap_config= ); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + pl061_write(pl061, 0, variant->ie); /* disable irqs */ + if (variant->mask !=3D PL061_REG_NONE) + pl061_write(pl061, GENMASK(variant->ngpio - 1, 0), variant->mask); + if (variant->enable !=3D PL061_REG_NONE) + pl061_write(pl061, GENMASK(variant->ngpio - 1, 0), variant->enable); + irq =3D adev->irq[0]; if (!irq) dev_warn(&adev->dev, "IRQ support disabled\n"); pl061->parent_irq =3D irq; =20 - girq =3D &pl061->gc.irq; + girq =3D &pl061->girq; gpio_irq_chip_set_chip(girq, &pl061_irq_chip); girq->parent_handler =3D pl061_irq_handler; girq->num_parents =3D 1; @@ -353,7 +341,19 @@ static int pl061_probe(struct amba_device *adev, const= struct amba_id *id) girq->default_type =3D IRQ_TYPE_NONE; girq->handler =3D handle_bad_irq; =20 - ret =3D devm_gpiochip_add_data(dev, &pl061->gc, pl061); + config.parent =3D dev; + config.regmap =3D regmap; + config.ngpio =3D variant->ngpio; + config.reg_dat_base =3D GPIO_REGMAP_ADDR(variant->data); + config.reg_set_base =3D GPIO_REGMAP_ADDR(variant->data); + config.reg_dir_out_base =3D variant->dir; + if (variant->masked_data_address) + config.reg_mask_xlate =3D pl061_reg_mask_xlate; + config.write_data_after_dir =3D variant->write_data_after_dir; + config.girq =3D girq; + config.drvdata =3D pl061; + + ret =3D PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &config)); if (ret) return ret; =20 @@ -366,19 +366,23 @@ static int pl061_probe(struct amba_device *adev, cons= t struct amba_id *id) static int pl061_suspend(struct device *dev) { struct pl061 *pl061 =3D dev_get_drvdata(dev); + const struct pl061_variant_data *variant =3D pl061->variant; int offset; =20 + if (!variant->pm_save_restore) + return 0; + pl061->csave_regs.gpio_data =3D 0; - pl061->csave_regs.gpio_dir =3D readb(pl061->base + GPIODIR); - pl061->csave_regs.gpio_is =3D readb(pl061->base + GPIOIS); - pl061->csave_regs.gpio_ibe =3D readb(pl061->base + GPIOIBE); - pl061->csave_regs.gpio_iev =3D readb(pl061->base + GPIOIEV); - pl061->csave_regs.gpio_ie =3D readb(pl061->base + GPIOIE); - - for (offset =3D 0; offset < PL061_GPIO_NR; offset++) { - if (pl061->csave_regs.gpio_dir & (BIT(offset))) + pl061->csave_regs.gpio_dir =3D pl061_read(pl061, variant->dir); + pl061->csave_regs.gpio_is =3D pl061_read(pl061, variant->is); + pl061->csave_regs.gpio_ibe =3D pl061_read(pl061, variant->ibe); + pl061->csave_regs.gpio_iev =3D pl061_read(pl061, variant->iev); + pl061->csave_regs.gpio_ie =3D pl061_read(pl061, variant->ie); + + for (offset =3D 0; offset < variant->ngpio; offset++) { + if (pl061->csave_regs.gpio_dir & BIT(offset)) pl061->csave_regs.gpio_data |=3D - pl061_get_value(&pl061->gc, offset) << offset; + pl061_read(pl061, BIT(offset + 2)); } =20 return 0; @@ -387,31 +391,103 @@ static int pl061_suspend(struct device *dev) static int pl061_resume(struct device *dev) { struct pl061 *pl061 =3D dev_get_drvdata(dev); + const struct pl061_variant_data *variant =3D pl061->variant; int offset; =20 - for (offset =3D 0; offset < PL061_GPIO_NR; offset++) { - if (pl061->csave_regs.gpio_dir & (BIT(offset))) - pl061_direction_output(&pl061->gc, offset, - pl061->csave_regs.gpio_data & - (BIT(offset))); - else - pl061_direction_input(&pl061->gc, offset); + if (!variant->pm_save_restore) + return 0; + + for (offset =3D 0; offset < variant->ngpio; offset++) { + u32 dir =3D pl061_read(pl061, variant->dir); + + if (pl061->csave_regs.gpio_dir & BIT(offset)) { + u32 value =3D !!(pl061->csave_regs.gpio_data & BIT(offset)) << offset; + + pl061_write(pl061, value, BIT(offset + 2)); + pl061_write(pl061, dir | BIT(offset), variant->dir); + /* + * gpio value is set again, because pl061 doesn't allow to set value of + * a gpio pin before configuring it in OUT mode. + */ + pl061_write(pl061, value, BIT(offset + 2)); + } else { + pl061_write(pl061, dir & ~BIT(offset), variant->dir); + } } =20 - writeb(pl061->csave_regs.gpio_is, pl061->base + GPIOIS); - writeb(pl061->csave_regs.gpio_ibe, pl061->base + GPIOIBE); - writeb(pl061->csave_regs.gpio_iev, pl061->base + GPIOIEV); - writeb(pl061->csave_regs.gpio_ie, pl061->base + GPIOIE); + pl061_write(pl061, pl061->csave_regs.gpio_is, variant->is); + pl061_write(pl061, pl061->csave_regs.gpio_ibe, variant->ibe); + pl061_write(pl061, pl061->csave_regs.gpio_iev, variant->iev); + pl061_write(pl061, pl061->csave_regs.gpio_ie, variant->ie); =20 return 0; } =20 static DEFINE_SIMPLE_DEV_PM_OPS(pl061_dev_pm_ops, pl061_suspend, pl061_res= ume); =20 +static const struct regmap_config pl061_arm_regmap_config =3D { + .reg_bits =3D 16, + .val_bits =3D 8, + .reg_stride =3D 4, + .max_register =3D 0x400, + .fast_io =3D true, +}; + +static const struct regmap_config pl061_ambarella_regmap_config =3D { + .reg_bits =3D 32, + .val_bits =3D 32, + .reg_stride =3D 4, + .max_register =3D 0x2c, + .fast_io =3D true, +}; + +static struct pl061_variant_data pl061_arm =3D { + .data =3D 0x000, + .dir =3D 0x400, + .is =3D 0x404, + .ibe =3D 0x408, + .iev =3D 0x40c, + .ie =3D 0x410, + .ris =3D 0x414, + .mis =3D 0x418, + .ic =3D 0x41c, + .mask =3D PL061_REG_NONE, + .enable =3D PL061_REG_NONE, + .ngpio =3D PL061_GPIO_NR, + .masked_data_address =3D true, + .write_data_after_dir =3D true, + .pm_save_restore =3D true, + .regmap_config =3D &pl061_arm_regmap_config, +}; + +static struct pl061_variant_data pl061_ambarella =3D { + .data =3D 0x00, + .dir =3D 0x04, + .is =3D 0x08, + .ibe =3D 0x0c, + .iev =3D 0x10, + .ie =3D 0x14, + .ris =3D 0x1c, + .mis =3D 0x20, + .ic =3D 0x24, + .mask =3D 0x28, + .enable =3D 0x2c, + .ngpio =3D AMBARELLA_GPIO_NR, + .access_32bit =3D true, + .clear_irq_on_type =3D true, + .regmap_config =3D &pl061_ambarella_regmap_config, +}; + static const struct amba_id pl061_ids[] =3D { { .id =3D 0x00041061, .mask =3D 0x000fffff, + .data =3D &pl061_arm, + }, + { + .id =3D (AMBA_VENDOR_AMBARELLA << 12) | 0x061, + .mask =3D 0x000fffff, + .data =3D &pl061_ambarella, }, { 0, 0 }, }; diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 80a74cd2da7e..411533bfa61d 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -98,6 +98,7 @@ enum amba_vendor { AMBA_VENDOR_ST =3D 0x80, AMBA_VENDOR_QCOM =3D 0x51, AMBA_VENDOR_LSI =3D 0xb6, + AMBA_VENDOR_AMBARELLA =3D 0xe8, }; =20 extern const struct bus_type amba_bustype; --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 A0C8A41F5EA; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=qWlcD9ZN38M28PnEhal5jHrMHvEvRy5gu8BPPWnVWe0i47YO+vktvg6/zs1FD+ctTfrH32Da8GnFbdiQFdXCwcegFpkMP3VX+akL6Zl38Afy9Jk7/0xt+LQShFQpvad1Ar+LZugJyF4MiEaNj0vrKaAM56HXa1Y3Zb2Wu/yaduI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=2+PhdLTAzV53K64247zevsubwKSWmIg0RPBGAPu+zPQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pwLw4xFs+FFQnHYE1SHw8xFk3BATX5NbNBnh4famQXqnIneZLxqkc2Hnz78wGhS0S3uFlbCqwDbzLN4SFkP01xHEKQo2hF7ws7+6BFSgYLhPWIWZ5bp5LdlnMtXBr7fCRbtfF10KpJqcaEvXbR3zZTyK3sjTi7yGn6LKh7RdF0E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vNwUkkXC; 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="vNwUkkXC" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7AE6BC2BCC7; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=2+PhdLTAzV53K64247zevsubwKSWmIg0RPBGAPu+zPQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=vNwUkkXCeLJtz+JF30Sq/1D/i0B+GyE6rkefb5xKJBe9S+0kBEn7Ziqvl7pDXMk4O lRyv4jTX0aSW1ze12/MMP6125hrCq0tmdl2ZQxZ/nHjkT5RfY7xM8rh1FFNQd89nvf pR3A3zJn9eCa82ZOyoFXUQ8tXuMI3r4w/AiD7YsLSoFXHtlAFs9vjX7lfPh9RrcjvY c0Ue/h8rz3N/0EYmyVuZA7RwPsTPRDVOP2bGTMycrlVjLIiiEz9pFmlBH5toiybq// 1tk7v5TZkiEzFgfwrCppsrBws+j2G4yj5QQZ2uLkSjGjL5Bev0wwBs2RioSUAsBAG5 UnMXZFwwJSYQg== 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 62D95C79F80; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:17 +0800 Subject: [PATCH v6 10/13] pinctrl: ambarella: add CV75 pin 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: <20260904-cv75-v5-v6-10-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=42984; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=W6KoEeymJZb9FmMkSfo8vfZ0/WbrD2s5CDjpadVtcE0=; b=HTQTYXLzDwQYa6RrHRcQvHMp8gGmuGW6TJKzpXgDEpcsnJaK/veXB1AZSwrZmkyoYZ5FoDJw3 kf9i+KajlidAXz3VqCQl7cm6Mcp+HdnHr6LDQKwN4ptVGN0avzvGy1T X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Add an Ambarella pinmux-only pinctrl driver with CV75 function/group tables. GPIO is handled by the PL061 driver. Signed-off-by: Long Zhao --- drivers/pinctrl/Kconfig | 15 + drivers/pinctrl/Makefile | 2 + drivers/pinctrl/pinctrl-ambarella-cv75.c | 561 +++++++++++++++++++++++ drivers/pinctrl/pinctrl-ambarella.c | 761 +++++++++++++++++++++++++++= ++++ drivers/pinctrl/pinctrl-ambarella.h | 50 ++ 5 files changed, 1389 insertions(+) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index c2cdd7b2c49b..da423792b5fa 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -37,6 +37,21 @@ config DEBUG_PINCTRL help Say Y here to add some extra checks and diagnostics to PINCTRL calls. =20 +config PINCTRL_AMB + bool "Ambarella pin controller support" + depends on ARCH_AMBARELLA || COMPILE_TEST + depends on HAS_IOMEM + default y if ARCH_AMBARELLA + select GENERIC_PINCONF + select GPIOLIB + select GPIOLIB_IRQCHIP + select GPIO_PL061 + select MFD_SYSCON + select PINCONF + select PINMUX + help + Say Y here to enable the Ambarella pin controller driver. + config PINCTRL_AMD bool "AMD GPIO pin control" depends on HAS_IOMEM diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index a35d71135abf..ce0825f4fc1b 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -10,6 +10,8 @@ obj-$(CONFIG_GENERIC_PINCONF) +=3D pinconf-generic.o obj-$(CONFIG_GENERIC_PINCTRL) +=3D pinctrl-generic.o obj-$(CONFIG_OF) +=3D devicetree.o =20 +obj-$(CONFIG_PINCTRL_AMB) +=3D pinctrl-ambarella.o +obj-$(CONFIG_PINCTRL_AMB) +=3D pinctrl-ambarella-cv75.o obj-$(CONFIG_PINCTRL_AMD) +=3D pinctrl-amd.o obj-$(CONFIG_PINCTRL_AMDISP) +=3D pinctrl-amdisp.o obj-$(CONFIG_PINCTRL_APPLE_GPIO) +=3D pinctrl-apple-gpio.o diff --git a/drivers/pinctrl/pinctrl-ambarella-cv75.c b/drivers/pinctrl/pin= ctrl-ambarella-cv75.c new file mode 100644 index 000000000000..e617f0717b31 --- /dev/null +++ b/drivers/pinctrl/pinctrl-ambarella-cv75.c @@ -0,0 +1,561 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Ambarella CV75 pinctrl data + * + * Copyright (C) 2026, Ambarella, Inc. + */ + +#include + +#include "pinctrl-ambarella.h" + +#define CV75_PINMUX_GROUP(_name, ...) \ + static const u32 cv75_##_name##_pinmux[] =3D { __VA_ARGS__ } + +#define CV75_GROUP(_name) \ + { \ + .name =3D #_name, \ + .pinmux =3D cv75_##_name##_pinmux, \ + .num_pins =3D ARRAY_SIZE(cv75_##_name##_pinmux), \ + } + +#define CV75_FUNCTION(_name) \ + { \ + .name =3D #_name, \ + .groups =3D cv75_##_name##_groups, \ + .num_groups =3D ARRAY_SIZE(cv75_##_name##_groups), \ + } + +/* UART */ +CV75_PINMUX_GROUP(uart0, AMBA_PINMUX(44, 1), AMBA_PINMUX(45, 1)); +CV75_PINMUX_GROUP(uart1, AMBA_PINMUX(46, 1), AMBA_PINMUX(47, 1)); +CV75_PINMUX_GROUP(uart1_flow, AMBA_PINMUX(48, 1), AMBA_PINMUX(49, 1)); +CV75_PINMUX_GROUP(uart2_a, AMBA_PINMUX(46, 2), AMBA_PINMUX(47, 2)); +CV75_PINMUX_GROUP(uart2_b, AMBA_PINMUX(50, 2), AMBA_PINMUX(51, 2)); +CV75_PINMUX_GROUP(uart2_c, AMBA_PINMUX(66, 2), AMBA_PINMUX(68, 2)); +CV75_PINMUX_GROUP(uart2_flow_a, AMBA_PINMUX(48, 2), AMBA_PINMUX(49, 2)); +CV75_PINMUX_GROUP(uart2_flow_b, AMBA_PINMUX(65, 3), AMBA_PINMUX(67, 3)); +CV75_PINMUX_GROUP(uart3_a, AMBA_PINMUX(70, 3), AMBA_PINMUX(72, 3)); +CV75_PINMUX_GROUP(uart3_b, AMBA_PINMUX(80, 3), AMBA_PINMUX(79, 3)); +CV75_PINMUX_GROUP(uart3_flow_a, AMBA_PINMUX(71, 3), AMBA_PINMUX(69, 3)); +CV75_PINMUX_GROUP(uart3_flow_b, AMBA_PINMUX(81, 3), AMBA_PINMUX(82, 3)); +CV75_PINMUX_GROUP(uart4_a, AMBA_PINMUX(29, 3), AMBA_PINMUX(30, 3)); +CV75_PINMUX_GROUP(uart4_b, AMBA_PINMUX(76, 3), AMBA_PINMUX(77, 3)); +CV75_PINMUX_GROUP(uart4_flow_a, AMBA_PINMUX(28, 3), AMBA_PINMUX(31, 3)); +CV75_PINMUX_GROUP(uart4_flow_b, AMBA_PINMUX(74, 3), AMBA_PINMUX(75, 3)); + +/* Flash */ +CV75_PINMUX_GROUP(snand, AMBA_PINMUX(79, 1), AMBA_PINMUX(80, 1), + AMBA_PINMUX(81, 1), AMBA_PINMUX(82, 1), + AMBA_PINMUX(83, 1), AMBA_PINMUX(84, 1)); +CV75_PINMUX_GROUP(spinor, AMBA_PINMUX(79, 2), AMBA_PINMUX(80, 2), + AMBA_PINMUX(81, 2), AMBA_PINMUX(82, 2), + AMBA_PINMUX(83, 2), AMBA_PINMUX(84, 2), + AMBA_PINMUX(85, 2)); + +/* SD/MMC */ +CV75_PINMUX_GROUP(sdmmc0_cd, AMBA_PINMUX(6, 1)); +CV75_PINMUX_GROUP(sdmmc0_wp, AMBA_PINMUX(7, 1)); +CV75_PINMUX_GROUP(sdmmc0_reset, AMBA_PINMUX(8, 1)); +CV75_PINMUX_GROUP(sdmmc0_hs_sel, AMBA_PINMUX(93, 1)); +CV75_PINMUX_GROUP(sdmmc0_1bit, AMBA_PINMUX(0, 1), AMBA_PINMUX(4, 1), + AMBA_PINMUX(5, 1)); +CV75_PINMUX_GROUP(sdmmc0_4bit, AMBA_PINMUX(0, 1), AMBA_PINMUX(1, 1), + AMBA_PINMUX(2, 1), AMBA_PINMUX(3, 1), + AMBA_PINMUX(4, 1), AMBA_PINMUX(5, 1)); +CV75_PINMUX_GROUP(sdmmc1_cd, AMBA_PINMUX(15, 1)); +CV75_PINMUX_GROUP(sdmmc1_wp, AMBA_PINMUX(16, 1)); +CV75_PINMUX_GROUP(sdmmc1_reset, AMBA_PINMUX(17, 1)); +CV75_PINMUX_GROUP(sdmmc1_hs_sel, AMBA_PINMUX(94, 1)); +CV75_PINMUX_GROUP(sdmmc1_1bit, AMBA_PINMUX(9, 1), AMBA_PINMUX(13, 1), + AMBA_PINMUX(14, 1)); +CV75_PINMUX_GROUP(sdmmc1_4bit, AMBA_PINMUX(9, 1), AMBA_PINMUX(10, 1), + AMBA_PINMUX(11, 1), AMBA_PINMUX(12, 1), + AMBA_PINMUX(13, 1), AMBA_PINMUX(14, 1)); + +/* Ethernet */ +CV75_PINMUX_GROUP(enet_ext_osc_clk, AMBA_PINMUX(77, 1)); +CV75_PINMUX_GROUP(enet_2nd_ref_clk_a, AMBA_PINMUX(78, 1)); +CV75_PINMUX_GROUP(enet_2nd_ref_clk_b, AMBA_PINMUX(76, 2)); +CV75_PINMUX_GROUP(enet0_ptp_pps_o, AMBA_PINMUX(74, 1)); +CV75_PINMUX_GROUP(rgmii0, AMBA_PINMUX(62, 1), AMBA_PINMUX(63, 1), + AMBA_PINMUX(64, 1), AMBA_PINMUX(65, 1), + AMBA_PINMUX(66, 1), AMBA_PINMUX(67, 1), + AMBA_PINMUX(68, 1), AMBA_PINMUX(69, 1), + AMBA_PINMUX(70, 1), AMBA_PINMUX(71, 1), + AMBA_PINMUX(72, 1), AMBA_PINMUX(73, 1), + AMBA_PINMUX(75, 1), AMBA_PINMUX(76, 1)); +CV75_PINMUX_GROUP(rmii0, AMBA_PINMUX(62, 1), AMBA_PINMUX(63, 1), + AMBA_PINMUX(64, 1), AMBA_PINMUX(67, 1), + AMBA_PINMUX(68, 1), AMBA_PINMUX(71, 1), + AMBA_PINMUX(72, 1), AMBA_PINMUX(73, 1), + AMBA_PINMUX(75, 2)); + +/* I2C */ +CV75_PINMUX_GROUP(i2c0_a, AMBA_PINMUX(67, 2), AMBA_PINMUX(68, 2)); +CV75_PINMUX_GROUP(i2c0_b, AMBA_PINMUX(86, 1), AMBA_PINMUX(87, 1)); +CV75_PINMUX_GROUP(i2c1_a, AMBA_PINMUX(22, 2), AMBA_PINMUX(23, 2)); +CV75_PINMUX_GROUP(i2c1_b, AMBA_PINMUX(69, 2), AMBA_PINMUX(70, 2)); +CV75_PINMUX_GROUP(i2c2, AMBA_PINMUX(88, 1), AMBA_PINMUX(89, 1)); +CV75_PINMUX_GROUP(i2c3_a, AMBA_PINMUX(24, 2), AMBA_PINMUX(25, 2)); +CV75_PINMUX_GROUP(i2c3_b, AMBA_PINMUX(48, 3), AMBA_PINMUX(49, 3)); +CV75_PINMUX_GROUP(i2c3_c, AMBA_PINMUX(58, 3), AMBA_PINMUX(59, 3)); +CV75_PINMUX_GROUP(i2cs_a, AMBA_PINMUX(19, 2), AMBA_PINMUX(21, 2)); +CV75_PINMUX_GROUP(i2cs_b, AMBA_PINMUX(60, 3), AMBA_PINMUX(61, 3)); +CV75_PINMUX_GROUP(i2cs_c, AMBA_PINMUX(71, 2), AMBA_PINMUX(72, 2)); +CV75_PINMUX_GROUP(i2cs_d, AMBA_PINMUX(86, 2), AMBA_PINMUX(87, 2)); + +/* CAN, IR, WDT */ +CV75_PINMUX_GROUP(can0, AMBA_PINMUX(50, 1), AMBA_PINMUX(51, 1)); +CV75_PINMUX_GROUP(can1, AMBA_PINMUX(52, 1), AMBA_PINMUX(53, 1)); +CV75_PINMUX_GROUP(ir, AMBA_PINMUX(18, 1)); +CV75_PINMUX_GROUP(wdt_a, AMBA_PINMUX(20, 2)); +CV75_PINMUX_GROUP(wdt_b, AMBA_PINMUX(27, 3)); +CV75_PINMUX_GROUP(wdt_c, AMBA_PINMUX(39, 2)); +CV75_PINMUX_GROUP(wdt_d, AMBA_PINMUX(83, 3)); +CV75_PINMUX_GROUP(wdt_e, AMBA_PINMUX(85, 4)); +CV75_PINMUX_GROUP(wdt_f, AMBA_PINMUX(90, 1)); + +/* I2S */ +CV75_PINMUX_GROUP(i2s0, AMBA_PINMUX(54, 1), AMBA_PINMUX(55, 1), + AMBA_PINMUX(56, 1), AMBA_PINMUX(57, 1)); +CV75_PINMUX_GROUP(i2s1, AMBA_PINMUX(58, 1), AMBA_PINMUX(59, 1), + AMBA_PINMUX(60, 1), AMBA_PINMUX(61, 1)); +CV75_PINMUX_GROUP(clk_au, AMBA_PINMUX(96, 1)); +CV75_PINMUX_GROUP(dmic0, AMBA_PINMUX(54, 2), AMBA_PINMUX(55, 2)); + +/* PWM */ +CV75_PINMUX_GROUP(pwm0, AMBA_PINMUX(40, 1)); +CV75_PINMUX_GROUP(pwm1, AMBA_PINMUX(41, 1)); +CV75_PINMUX_GROUP(pwm2, AMBA_PINMUX(42, 1)); +CV75_PINMUX_GROUP(pwm3, AMBA_PINMUX(43, 1)); +CV75_PINMUX_GROUP(pwm4_a, AMBA_PINMUX(19, 3)); +CV75_PINMUX_GROUP(pwm4_b, AMBA_PINMUX(32, 4)); +CV75_PINMUX_GROUP(pwm5_a, AMBA_PINMUX(20, 3)); +CV75_PINMUX_GROUP(pwm5_b, AMBA_PINMUX(33, 4)); +CV75_PINMUX_GROUP(pwm6_a, AMBA_PINMUX(21, 3)); +CV75_PINMUX_GROUP(pwm6_b, AMBA_PINMUX(34, 4)); +CV75_PINMUX_GROUP(pwm7_a, AMBA_PINMUX(22, 3)); +CV75_PINMUX_GROUP(pwm7_b, AMBA_PINMUX(35, 4)); +CV75_PINMUX_GROUP(pwm8_a, AMBA_PINMUX(23, 3)); +CV75_PINMUX_GROUP(pwm8_b, AMBA_PINMUX(36, 4)); +CV75_PINMUX_GROUP(pwm9_a, AMBA_PINMUX(24, 3)); +CV75_PINMUX_GROUP(pwm9_b, AMBA_PINMUX(37, 4)); +CV75_PINMUX_GROUP(pwm10_a, AMBA_PINMUX(25, 3)); +CV75_PINMUX_GROUP(pwm10_b, AMBA_PINMUX(38, 4)); +CV75_PINMUX_GROUP(pwm11_a, AMBA_PINMUX(26, 3)); +CV75_PINMUX_GROUP(pwm11_b, AMBA_PINMUX(39, 4)); + +/* SPI */ +CV75_PINMUX_GROUP(spi0, AMBA_PINMUX(19, 1), AMBA_PINMUX(20, 1), + AMBA_PINMUX(21, 1)); +CV75_PINMUX_GROUP(spi1, AMBA_PINMUX(24, 1), AMBA_PINMUX(25, 1), + AMBA_PINMUX(26, 1)); +CV75_PINMUX_GROUP(spi2, AMBA_PINMUX(28, 1), AMBA_PINMUX(29, 1), + AMBA_PINMUX(30, 1)); +CV75_PINMUX_GROUP(spi3_a, AMBA_PINMUX(32, 5), AMBA_PINMUX(33, 5), + AMBA_PINMUX(34, 5)); +CV75_PINMUX_GROUP(spi3_b, AMBA_PINMUX(40, 2), AMBA_PINMUX(41, 2), + AMBA_PINMUX(43, 2)); +CV75_PINMUX_GROUP(spi3_c, AMBA_PINMUX(58, 2), AMBA_PINMUX(59, 2), + AMBA_PINMUX(60, 2)); +CV75_PINMUX_GROUP(spi_slave_a, AMBA_PINMUX(24, 4), AMBA_PINMUX(25, 4), + AMBA_PINMUX(26, 4), AMBA_PINMUX(27, 4)); +CV75_PINMUX_GROUP(spi_slave_b, AMBA_PINMUX(28, 2), AMBA_PINMUX(29, 2), + AMBA_PINMUX(30, 2), AMBA_PINMUX(31, 2)); +CV75_PINMUX_GROUP(spi_slave_c, AMBA_PINMUX(36, 5), AMBA_PINMUX(37, 5), + AMBA_PINMUX(38, 5), AMBA_PINMUX(39, 5)); +CV75_PINMUX_GROUP(spi_slave_d, AMBA_PINMUX(50, 3), AMBA_PINMUX(51, 3), + AMBA_PINMUX(52, 3), AMBA_PINMUX(53, 3)); +CV75_PINMUX_GROUP(spi_slave_e, AMBA_PINMUX(81, 4), AMBA_PINMUX(82, 4), + AMBA_PINMUX(83, 4), AMBA_PINMUX(84, 4)); + +/* VIN master sync */ +CV75_PINMUX_GROUP(vin_master_sync_a, AMBA_PINMUX(91, 1), + AMBA_PINMUX(92, 1)); +CV75_PINMUX_GROUP(vin_master_sync_b, AMBA_PINMUX(91, 2), + AMBA_PINMUX(92, 2)); +CV75_PINMUX_GROUP(vin_master_sync_c, AMBA_PINMUX(40, 3), + AMBA_PINMUX(41, 3)); +CV75_PINMUX_GROUP(vin_master_sync_d, AMBA_PINMUX(46, 3), + AMBA_PINMUX(47, 3)); +CV75_PINMUX_GROUP(vin_master_sync_e, AMBA_PINMUX(79, 4), + AMBA_PINMUX(80, 4)); +CV75_PINMUX_GROUP(vsync0, AMBA_PINMUX(32, 1)); +CV75_PINMUX_GROUP(vsync1, AMBA_PINMUX(33, 1)); +CV75_PINMUX_GROUP(vsync2, AMBA_PINMUX(34, 1)); +CV75_PINMUX_GROUP(vsync3, AMBA_PINMUX(35, 1)); +CV75_PINMUX_GROUP(hsync0, AMBA_PINMUX(36, 1)); +CV75_PINMUX_GROUP(hsync1, AMBA_PINMUX(37, 1)); + +static const struct ambpin_group_desc cv75_pin_groups[] =3D { + CV75_GROUP(uart0), + CV75_GROUP(uart1), CV75_GROUP(uart1_flow), + CV75_GROUP(uart2_a), CV75_GROUP(uart2_b), CV75_GROUP(uart2_c), + CV75_GROUP(uart2_flow_a), CV75_GROUP(uart2_flow_b), + CV75_GROUP(uart3_a), CV75_GROUP(uart3_b), + CV75_GROUP(uart3_flow_a), CV75_GROUP(uart3_flow_b), + CV75_GROUP(uart4_a), CV75_GROUP(uart4_b), + CV75_GROUP(uart4_flow_a), CV75_GROUP(uart4_flow_b), + CV75_GROUP(snand), CV75_GROUP(spinor), + CV75_GROUP(sdmmc0_cd), CV75_GROUP(sdmmc0_wp), + CV75_GROUP(sdmmc0_reset), CV75_GROUP(sdmmc0_hs_sel), + CV75_GROUP(sdmmc0_1bit), CV75_GROUP(sdmmc0_4bit), + CV75_GROUP(sdmmc1_cd), CV75_GROUP(sdmmc1_wp), + CV75_GROUP(sdmmc1_reset), CV75_GROUP(sdmmc1_hs_sel), + CV75_GROUP(sdmmc1_1bit), CV75_GROUP(sdmmc1_4bit), + CV75_GROUP(enet_ext_osc_clk), CV75_GROUP(enet_2nd_ref_clk_a), + CV75_GROUP(enet_2nd_ref_clk_b), CV75_GROUP(enet0_ptp_pps_o), + CV75_GROUP(rgmii0), CV75_GROUP(rmii0), + CV75_GROUP(i2c0_a), CV75_GROUP(i2c0_b), + CV75_GROUP(i2c1_a), CV75_GROUP(i2c1_b), CV75_GROUP(i2c2), + CV75_GROUP(i2c3_a), CV75_GROUP(i2c3_b), CV75_GROUP(i2c3_c), + CV75_GROUP(i2cs_a), CV75_GROUP(i2cs_b), + CV75_GROUP(i2cs_c), CV75_GROUP(i2cs_d), + CV75_GROUP(can0), CV75_GROUP(can1), CV75_GROUP(ir), + CV75_GROUP(wdt_a), CV75_GROUP(wdt_b), CV75_GROUP(wdt_c), + CV75_GROUP(wdt_d), CV75_GROUP(wdt_e), CV75_GROUP(wdt_f), + CV75_GROUP(i2s0), CV75_GROUP(i2s1), + CV75_GROUP(clk_au), CV75_GROUP(dmic0), + CV75_GROUP(pwm0), CV75_GROUP(pwm1), + CV75_GROUP(pwm2), CV75_GROUP(pwm3), + CV75_GROUP(pwm4_a), CV75_GROUP(pwm4_b), + CV75_GROUP(pwm5_a), CV75_GROUP(pwm5_b), + CV75_GROUP(pwm6_a), CV75_GROUP(pwm6_b), + CV75_GROUP(pwm7_a), CV75_GROUP(pwm7_b), + CV75_GROUP(pwm8_a), CV75_GROUP(pwm8_b), + CV75_GROUP(pwm9_a), CV75_GROUP(pwm9_b), + CV75_GROUP(pwm10_a), CV75_GROUP(pwm10_b), + CV75_GROUP(pwm11_a), CV75_GROUP(pwm11_b), + CV75_GROUP(spi0), CV75_GROUP(spi1), CV75_GROUP(spi2), + CV75_GROUP(spi3_a), CV75_GROUP(spi3_b), CV75_GROUP(spi3_c), + CV75_GROUP(spi_slave_a), CV75_GROUP(spi_slave_b), + CV75_GROUP(spi_slave_c), CV75_GROUP(spi_slave_d), + CV75_GROUP(spi_slave_e), + CV75_GROUP(vin_master_sync_a), CV75_GROUP(vin_master_sync_b), + CV75_GROUP(vin_master_sync_c), CV75_GROUP(vin_master_sync_d), + CV75_GROUP(vin_master_sync_e), + CV75_GROUP(vsync0), CV75_GROUP(vsync1), + CV75_GROUP(vsync2), CV75_GROUP(vsync3), + CV75_GROUP(hsync0), CV75_GROUP(hsync1), +}; + +static const char * const cv75_uart0_groups[] =3D { + "uart0", +}; + +static const char * const cv75_uart1_groups[] =3D { + "uart1", + "uart1_flow", +}; + +static const char * const cv75_uart2_groups[] =3D { + "uart2_a", + "uart2_b", + "uart2_c", + "uart2_flow_a", + "uart2_flow_b", +}; + +static const char * const cv75_uart3_groups[] =3D { + "uart3_a", + "uart3_b", + "uart3_flow_a", + "uart3_flow_b", +}; + +static const char * const cv75_uart4_groups[] =3D { + "uart4_a", + "uart4_b", + "uart4_flow_a", + "uart4_flow_b", +}; + +static const char * const cv75_snand_groups[] =3D { + "snand", +}; + +static const char * const cv75_spinor_groups[] =3D { + "spinor", +}; + +static const char * const cv75_sdmmc0_groups[] =3D { + "sdmmc0_cd", + "sdmmc0_wp", + "sdmmc0_reset", + "sdmmc0_hs_sel", + "sdmmc0_1bit", + "sdmmc0_4bit", +}; + +static const char * const cv75_sdmmc1_groups[] =3D { + "sdmmc1_cd", + "sdmmc1_wp", + "sdmmc1_reset", + "sdmmc1_hs_sel", + "sdmmc1_1bit", + "sdmmc1_4bit", +}; + +static const char * const cv75_enet0_groups[] =3D { + "enet_ext_osc_clk", + "enet_2nd_ref_clk_a", + "enet_2nd_ref_clk_b", + "enet0_ptp_pps_o", + "rgmii0", + "rmii0", +}; + +static const char * const cv75_i2c0_groups[] =3D { + "i2c0_a", + "i2c0_b", +}; + +static const char * const cv75_i2c1_groups[] =3D { + "i2c1_a", + "i2c1_b", +}; + +static const char * const cv75_i2c2_groups[] =3D { + "i2c2", +}; + +static const char * const cv75_i2c3_groups[] =3D { + "i2c3_a", + "i2c3_b", + "i2c3_c", +}; + +static const char * const cv75_i2cs_groups[] =3D { + "i2cs_a", + "i2cs_b", + "i2cs_c", + "i2cs_d", +}; + +static const char * const cv75_can0_groups[] =3D { + "can0", +}; + +static const char * const cv75_can1_groups[] =3D { + "can1", +}; + +static const char * const cv75_ir_groups[] =3D { + "ir", +}; + +static const char * const cv75_wdt_groups[] =3D { + "wdt_a", + "wdt_b", + "wdt_c", + "wdt_d", + "wdt_e", + "wdt_f", +}; + +static const char * const cv75_i2s0_groups[] =3D { + "i2s0", +}; + +static const char * const cv75_i2s1_groups[] =3D { + "i2s1", +}; + +static const char * const cv75_clk_au_groups[] =3D { + "clk_au", +}; + +static const char * const cv75_dmic0_groups[] =3D { + "dmic0", +}; + +static const char * const cv75_pwm0_groups[] =3D { + "pwm0", +}; + +static const char * const cv75_pwm1_groups[] =3D { + "pwm1", +}; + +static const char * const cv75_pwm2_groups[] =3D { + "pwm2", +}; + +static const char * const cv75_pwm3_groups[] =3D { + "pwm3", +}; + +static const char * const cv75_pwm4_groups[] =3D { + "pwm4_a", + "pwm4_b", +}; + +static const char * const cv75_pwm5_groups[] =3D { + "pwm5_a", + "pwm5_b", +}; + +static const char * const cv75_pwm6_groups[] =3D { + "pwm6_a", + "pwm6_b", +}; + +static const char * const cv75_pwm7_groups[] =3D { + "pwm7_a", + "pwm7_b", +}; + +static const char * const cv75_pwm8_groups[] =3D { + "pwm8_a", + "pwm8_b", +}; + +static const char * const cv75_pwm9_groups[] =3D { + "pwm9_a", + "pwm9_b", +}; + +static const char * const cv75_pwm10_groups[] =3D { + "pwm10_a", + "pwm10_b", +}; + +static const char * const cv75_pwm11_groups[] =3D { + "pwm11_a", + "pwm11_b", +}; + +static const char * const cv75_spi0_groups[] =3D { + "spi0", +}; + +static const char * const cv75_spi1_groups[] =3D { + "spi1", +}; + +static const char * const cv75_spi2_groups[] =3D { + "spi2", +}; + +static const char * const cv75_spi3_groups[] =3D { + "spi3_a", + "spi3_b", + "spi3_c", +}; + +static const char * const cv75_spi_slave_groups[] =3D { + "spi_slave_a", + "spi_slave_b", + "spi_slave_c", + "spi_slave_d", + "spi_slave_e", +}; + +static const char * const cv75_vin_master_sync_groups[] =3D { + "vin_master_sync_a", + "vin_master_sync_b", + "vin_master_sync_c", + "vin_master_sync_d", + "vin_master_sync_e", +}; + +static const char * const cv75_vsync0_groups[] =3D { + "vsync0", +}; + +static const char * const cv75_vsync1_groups[] =3D { + "vsync1", +}; + +static const char * const cv75_vsync2_groups[] =3D { + "vsync2", +}; + +static const char * const cv75_vsync3_groups[] =3D { + "vsync3", +}; + +static const char * const cv75_hsync0_groups[] =3D { + "hsync0", +}; + +static const char * const cv75_hsync1_groups[] =3D { + "hsync1", +}; + +static const struct ambpin_function cv75_pin_functions[] =3D { + CV75_FUNCTION(uart0), + CV75_FUNCTION(uart1), + CV75_FUNCTION(uart2), + CV75_FUNCTION(uart3), + CV75_FUNCTION(uart4), + CV75_FUNCTION(snand), + CV75_FUNCTION(spinor), + CV75_FUNCTION(sdmmc0), + CV75_FUNCTION(sdmmc1), + CV75_FUNCTION(enet0), + CV75_FUNCTION(i2c0), + CV75_FUNCTION(i2c1), + CV75_FUNCTION(i2c2), + CV75_FUNCTION(i2c3), + CV75_FUNCTION(i2cs), + CV75_FUNCTION(can0), + CV75_FUNCTION(can1), + CV75_FUNCTION(ir), + CV75_FUNCTION(wdt), + CV75_FUNCTION(i2s0), + CV75_FUNCTION(i2s1), + CV75_FUNCTION(clk_au), + CV75_FUNCTION(dmic0), + CV75_FUNCTION(pwm0), + CV75_FUNCTION(pwm1), + CV75_FUNCTION(pwm2), + CV75_FUNCTION(pwm3), + CV75_FUNCTION(pwm4), + CV75_FUNCTION(pwm5), + CV75_FUNCTION(pwm6), + CV75_FUNCTION(pwm7), + CV75_FUNCTION(pwm8), + CV75_FUNCTION(pwm9), + CV75_FUNCTION(pwm10), + CV75_FUNCTION(pwm11), + CV75_FUNCTION(spi0), + CV75_FUNCTION(spi1), + CV75_FUNCTION(spi2), + CV75_FUNCTION(spi3), + CV75_FUNCTION(spi_slave), + CV75_FUNCTION(vin_master_sync), + CV75_FUNCTION(vsync0), + CV75_FUNCTION(vsync1), + CV75_FUNCTION(vsync2), + CV75_FUNCTION(vsync3), + CV75_FUNCTION(hsync0), + CV75_FUNCTION(hsync1), +}; + +const struct amb_pinctrl_data ambarella_cv75_pinctrl_data =3D { + .ds0 =3D { + 0x314, 0x320, 0x32c, + }, + .ds1 =3D { + 0x318, 0x324, 0x330, + }, + .ds2 =3D { + 0x31c, 0x328, 0x334, + }, + .pull_en =3D { + 0x60, 0x64, 0x68, + }, + .pull_dir =3D { + 0x7c, 0x80, 0x84, + }, + .have_ds2 =3D true, + .clk_au_dedicated_pin =3D 96, + .nr_banks =3D 3, + .npins =3D 97, + .groups =3D cv75_pin_groups, + .nr_groups =3D ARRAY_SIZE(cv75_pin_groups), + .functions =3D cv75_pin_functions, + .nr_functions =3D ARRAY_SIZE(cv75_pin_functions), +}; diff --git a/drivers/pinctrl/pinctrl-ambarella.c b/drivers/pinctrl/pinctrl-= ambarella.c new file mode 100644 index 000000000000..a4a068271e8f --- /dev/null +++ b/drivers/pinctrl/pinctrl-ambarella.c @@ -0,0 +1,761 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Pinctrl driver for Ambarella SoCs + * + * History: + * 2013/12/18 - [Cao Rongrong] created file + * + * Copyright (C) 2012-2026, Ambarella, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pinconf.h" +#include "pinctrl-ambarella.h" + +/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D*/ + +#define IOMUX_OFFSET(bank, n) (((bank) * 0xc) + ((n) * 4)) +#define IOMUX_CTRL_SET_OFFSET 0xf0 + +/* =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D*/ + +#define AMBA_MAX_PINS (AMBA_MAX_BANKS * 32) + +#define PINID_TO_BANK(p) ((p) >> 5) +#define PINID_TO_OFFSET(p) ((p) & 0x1f) + +struct ambpin_group { + const char *name; + const u32 *pinmux; + unsigned int *pins; + unsigned int num_pins; +}; + +struct amb_pinctrl_soc_data { + struct device *dev; + const struct amb_pinctrl_data *data; + void __iomem *iomux_base; + struct regmap *ds_regmap; + struct regmap *pull_regmap; + unsigned int npins; + unsigned long used[BITS_TO_LONGS(AMBA_MAX_PINS)]; + raw_spinlock_t lock; + + struct pinctrl_dev *pctl; + + const struct ambpin_function *functions; + unsigned int nr_functions; + struct ambpin_group *groups; + unsigned int nr_groups; +}; + +/* check if the selector is a valid pin group selector */ +static int amb_get_group_count(struct pinctrl_dev *pctldev) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + return soc->nr_groups; +} + +/* return the name of the group selected by the group selector */ +static const char *amb_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + return soc->groups[selector].name; +} + +/* return the pin numbers associated with the specified group */ +static int amb_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, const unsigned int **pins, + unsigned int *num_pins) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + *pins =3D soc->groups[selector].pins; + *num_pins =3D soc->groups[selector].num_pins; + + return 0; +} + +#if IS_ENABLED(CONFIG_DEBUG_FS) +static void amb_pin_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned int pin) +{ + seq_printf(s, " %s", pinctrl_dev_get_devname(pctldev)); +} +#endif + +/* list of pinctrl callbacks for the pinctrl core */ +static const struct pinctrl_ops amb_pctrl_ops =3D { + .get_groups_count =3D amb_get_group_count, + .get_group_name =3D amb_get_group_name, + .get_group_pins =3D amb_get_group_pins, +#if IS_ENABLED(CONFIG_DEBUG_FS) + .pin_dbg_show =3D amb_pin_dbg_show, +#endif + .dt_node_to_map =3D pinconf_generic_dt_node_to_map_all, + .dt_free_map =3D pinconf_generic_dt_free_map, +}; + +/* check if the selector is a valid pin function selector */ +static int amb_pinmux_request(struct pinctrl_dev *pctldev, unsigned int pi= n) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + if (test_and_set_bit(pin, soc->used)) + return -EBUSY; + + return 0; +} + +/* check if the selector is a valid pin function selector */ +static int amb_pinmux_free(struct pinctrl_dev *pctldev, unsigned int pin) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + clear_bit(pin, soc->used); + + return 0; +} + +/* check if the selector is a valid pin function selector */ +static int amb_pinmux_get_fcount(struct pinctrl_dev *pctldev) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + return soc->nr_functions; +} + +/* return the name of the pin function specified */ +static const char *amb_pinmux_get_fname(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + return soc->functions[selector].name; +} + +/* return the groups associated for the specified function selector */ +static int amb_pinmux_get_groups(struct pinctrl_dev *pctldev, + unsigned int selector, + const char * const **groups, + unsigned int * const num_groups) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + *groups =3D soc->functions[selector].groups; + *num_groups =3D soc->functions[selector].num_groups; + + return 0; +} + +static bool amb_iomux_accessible(const struct amb_pinctrl_soc_data *soc) +{ + return soc->data->hsm_domain_id =3D=3D 0; +} + +static void amb_iomux_commit(struct amb_pinctrl_soc_data *soc) +{ + if (!amb_iomux_accessible(soc)) + return; + + writel_relaxed(0x1, soc->iomux_base + IOMUX_CTRL_SET_OFFSET); + writel_relaxed(0x0, soc->iomux_base + IOMUX_CTRL_SET_OFFSET); +} + +static void amb_pinmux_set_altfunc(struct amb_pinctrl_soc_data *soc, + u32 bank, u32 offset, u32 altfunc) +{ + u32 i, data; + + if (!amb_iomux_accessible(soc)) + return; + + for (i =3D 0; i < 3; i++) { + data =3D readl_relaxed(soc->iomux_base + IOMUX_OFFSET(bank, i)); + data &=3D ~BIT(offset); + data |=3D ((altfunc >> i) & 1U) << offset; + writel_relaxed(data, soc->iomux_base + IOMUX_OFFSET(bank, i)); + } +} + +/* enable a specified pinmux by writing to registers */ +static int amb_pinmux_set_mux(struct pinctrl_dev *pctldev, + unsigned int selector, unsigned int group) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + const struct ambpin_group *grp; + u32 i, pin, alt, bank, offset; + unsigned long flags; + + grp =3D &soc->groups[group]; + + raw_spin_lock_irqsave(&soc->lock, flags); + for (i =3D 0; i < grp->num_pins; i++) { + pin =3D AMBA_PINMUX_TO_PIN(grp->pinmux[i]); + alt =3D AMBA_PINMUX_TO_ALT(grp->pinmux[i]); + bank =3D PINID_TO_BANK(pin); + offset =3D PINID_TO_OFFSET(pin); + amb_pinmux_set_altfunc(soc, bank, offset, alt); + } + /* One commit after the whole group is programmed. */ + amb_iomux_commit(soc); + raw_spin_unlock_irqrestore(&soc->lock, flags); + + return 0; +} + +static int amb_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int pin) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + u32 bank, offset; + unsigned long flags; + + if (!range || !range->gc) { + dev_err(soc->dev, "invalid range: %p\n", range); + return -EINVAL; + } + + if (test_and_set_bit(pin, soc->used)) + return -EBUSY; + + bank =3D PINID_TO_BANK(pin); + offset =3D PINID_TO_OFFSET(pin); + + raw_spin_lock_irqsave(&soc->lock, flags); + amb_pinmux_set_altfunc(soc, bank, offset, 0); + amb_iomux_commit(soc); + raw_spin_unlock_irqrestore(&soc->lock, flags); + + return 0; +} + +static void amb_pinmux_gpio_disable_free(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, + unsigned int pin) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + + dev_dbg(soc->dev, "disable pin %u as GPIO\n", pin); + /* Set the pin to some default state, GPIO is usually default */ + + clear_bit(pin, soc->used); +} + +/* list of pinmux callbacks for the pinmux vertical in pinctrl core */ +static const struct pinmux_ops amb_pinmux_ops =3D { + .request =3D amb_pinmux_request, + .free =3D amb_pinmux_free, + .get_functions_count =3D amb_pinmux_get_fcount, + .get_function_name =3D amb_pinmux_get_fname, + .get_function_groups =3D amb_pinmux_get_groups, + .set_mux =3D amb_pinmux_set_mux, + .gpio_request_enable =3D amb_pinmux_gpio_request_enable, + .gpio_disable_free =3D amb_pinmux_gpio_disable_free, +}; + +static int amb_drive_strength_to_reg(struct amb_pinctrl_soc_data *soc, + u32 strength) +{ + if (soc->data->have_ds2) { + switch (strength) { + case 3: + return 0; + case 4: + case 5: + return 1; + case 6: + return 2; + case 7: + case 8: + return 3; + case 9: + return 4; + case 12: + return 5; + default: + return -EINVAL; + } + } + + switch (strength) { + case 2: + return 0; + case 4: + return 1; + case 8: + return 2; + case 12: + return 3; + default: + return -EINVAL; + } +} + +static int amb_reg_to_drive_strength(struct amb_pinctrl_soc_data *soc, u32= ds) +{ + static const int ds2_ma[] =3D { 3, 4, 6, 8, 9, 12 }; + static const int ds_ma[] =3D { 2, 4, 8, 12 }; + + if (soc->data->have_ds2) { + if (ds >=3D ARRAY_SIZE(ds2_ma)) + return -EINVAL; + + return ds2_ma[ds]; + } + + if (ds >=3D ARRAY_SIZE(ds_ma)) + return -EINVAL; + + return ds_ma[ds]; +} + +/* set the pin config settings for a specified pin */ +static int amb_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *configs, unsigned int num_configs) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + u32 i, bank, offset; + unsigned long config; + enum pin_config_param param; + u32 arg; + int ds; + + bank =3D PINID_TO_BANK(pin); + if (bank >=3D soc->data->nr_banks) + return -EINVAL; + + offset =3D PINID_TO_OFFSET(pin); + + for (i =3D 0; i < num_configs; i++) { + config =3D configs[i]; + param =3D pinconf_to_config_param(config); + arg =3D pinconf_to_config_argument(config); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + regmap_update_bits(soc->pull_regmap, + soc->data->pull_en[bank], BIT(offset), 0); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + regmap_update_bits(soc->pull_regmap, soc->data->pull_dir[bank], + BIT(offset), + (param =3D=3D PIN_CONFIG_BIAS_PULL_UP) ? + BIT(offset) : 0); + regmap_update_bits(soc->pull_regmap, soc->data->pull_en[bank], + BIT(offset), BIT(offset)); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + ds =3D amb_drive_strength_to_reg(soc, arg); + if (ds < 0) + return ds; + if (soc->data->have_ds2) { + regmap_update_bits(soc->ds_regmap, + soc->data->ds0[bank], BIT(offset), + (ds & BIT(0)) ? BIT(offset) : 0); + regmap_update_bits(soc->ds_regmap, + soc->data->ds1[bank], BIT(offset), + (ds & BIT(1)) ? BIT(offset) : 0); + regmap_update_bits(soc->ds_regmap, + soc->data->ds2[bank], BIT(offset), + (ds & BIT(2)) ? BIT(offset) : 0); + } else { + regmap_update_bits(soc->ds_regmap, + soc->data->ds0[bank], BIT(offset), + (ds & BIT(1)) ? BIT(offset) : 0); + regmap_update_bits(soc->ds_regmap, + soc->data->ds1[bank], BIT(offset), + (ds & BIT(0)) ? BIT(offset) : 0); + } + break; + default: + return -EOPNOTSUPP; + } + } + + return 0; +} + +static int amb_pinconf_group_set(struct pinctrl_dev *pctldev, + unsigned int selector, + unsigned long *configs, + unsigned int num_configs) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + const struct ambpin_group *grp =3D &soc->groups[selector]; + int ret; + u32 i; + + for (i =3D 0; i < grp->num_pins; i++) { + ret =3D amb_pinconf_set(pctldev, grp->pins[i], configs, + num_configs); + if (ret) + return ret; + } + + return 0; +} + +/* get the pin config settings for a specified pin */ +static int amb_pinconf_get(struct pinctrl_dev *pctldev, + unsigned int pin, unsigned long *config) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param =3D pinconf_to_config_param(*config); + u32 bank, offset, pull_en, pull_dir, ds0, ds1, ds2, ds; + int ret, strength; + + bank =3D PINID_TO_BANK(pin); + if (bank >=3D soc->data->nr_banks) + return -EINVAL; + + offset =3D PINID_TO_OFFSET(pin); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_PULL_UP: + ret =3D regmap_read(soc->pull_regmap, soc->data->pull_en[bank], + &pull_en); + if (ret) + return ret; + + ret =3D regmap_read(soc->pull_regmap, soc->data->pull_dir[bank], + &pull_dir); + if (ret) + return ret; + + pull_en =3D (pull_en >> offset) & 1; + pull_dir =3D (pull_dir >> offset) & 1; + + if (param =3D=3D PIN_CONFIG_BIAS_DISABLE) { + if (pull_en) + return -EINVAL; + *config =3D pinconf_to_config_packed(param, 0); + return 0; + } + + if (!pull_en) + return -EINVAL; + if (param =3D=3D PIN_CONFIG_BIAS_PULL_UP && !pull_dir) + return -EINVAL; + if (param =3D=3D PIN_CONFIG_BIAS_PULL_DOWN && pull_dir) + return -EINVAL; + + *config =3D pinconf_to_config_packed(param, 1); + return 0; + + case PIN_CONFIG_DRIVE_STRENGTH: + ret =3D regmap_read(soc->ds_regmap, soc->data->ds0[bank], &ds0); + if (ret) + return ret; + + ret =3D regmap_read(soc->ds_regmap, soc->data->ds1[bank], &ds1); + if (ret) + return ret; + + ds0 =3D (ds0 >> offset) & 1; + ds1 =3D (ds1 >> offset) & 1; + if (soc->data->have_ds2) { + ret =3D regmap_read(soc->ds_regmap, soc->data->ds2[bank], &ds2); + if (ret) + return ret; + + ds2 =3D (ds2 >> offset) & 1; + ds =3D (ds2 << 2) | (ds1 << 1) | ds0; + } else { + ds =3D (ds0 << 1) | ds1; + } + + strength =3D amb_reg_to_drive_strength(soc, ds); + if (strength < 0) + return strength; + + *config =3D pinconf_to_config_packed(param, strength); + return 0; + + default: + return -EOPNOTSUPP; + } +} + +#if IS_ENABLED(CONFIG_DEBUG_FS) +static void amb_pinconf_dbg_show(struct pinctrl_dev *pctldev, + struct seq_file *s, unsigned int pin) +{ + struct amb_pinctrl_soc_data *soc =3D pinctrl_dev_get_drvdata(pctldev); + u32 pull_en, pull_dir, ds0, ds1, ds2 =3D 0, ds; + u32 bank, offset; + int strength, ret; + + bank =3D PINID_TO_BANK(pin); + if (bank >=3D soc->data->nr_banks) { + seq_puts(s, " (no pinconf)"); + return; + } + + offset =3D PINID_TO_OFFSET(pin); + + ret =3D regmap_read(soc->pull_regmap, soc->data->pull_en[bank], + &pull_en); + if (ret) { + seq_puts(s, " pull: "); + return; + } + ret =3D regmap_read(soc->pull_regmap, soc->data->pull_dir[bank], + &pull_dir); + if (ret) { + seq_puts(s, " pull: "); + return; + } + pull_en =3D (pull_en >> offset) & 1; + pull_dir =3D (pull_dir >> offset) & 1; + seq_printf(s, " pull: %s,", + pull_en ? (pull_dir ? "up" : "down") : "disable"); + + ret =3D regmap_read(soc->ds_regmap, soc->data->ds0[bank], &ds0); + if (ret) { + seq_puts(s, " drive-strength: "); + return; + } + ret =3D regmap_read(soc->ds_regmap, soc->data->ds1[bank], &ds1); + if (ret) { + seq_puts(s, " drive-strength: "); + return; + } + ds0 =3D (ds0 >> offset) & 1; + ds1 =3D (ds1 >> offset) & 1; + if (soc->data->have_ds2) { + ret =3D regmap_read(soc->ds_regmap, soc->data->ds2[bank], &ds2); + if (ret) { + seq_puts(s, " drive-strength: "); + return; + } + ds2 =3D (ds2 >> offset) & 1; + ds =3D (ds2 << 2) | (ds1 << 1) | ds0; + } else { + ds =3D (ds0 << 1) | ds1; + } + + strength =3D amb_reg_to_drive_strength(soc, ds); + if (strength < 0) + seq_puts(s, " drive-strength: invalid"); + else + seq_printf(s, " drive-strength: %dmA", strength); +} +#endif + +/* list of pinconfig callbacks for pinconfig vertical in the pinctrl code = */ +static const struct pinconf_ops amb_pinconf_ops =3D { + .is_generic =3D true, + .pin_config_get =3D amb_pinconf_get, + .pin_config_set =3D amb_pinconf_set, + .pin_config_group_set =3D amb_pinconf_group_set, +#if IS_ENABLED(CONFIG_DEBUG_FS) + .pin_config_dbg_show =3D amb_pinconf_dbg_show, +#endif +}; + +/* register the pinctrl interface with the pinctrl subsystem */ +static int amb_pinctrl_register(struct amb_pinctrl_soc_data *soc) +{ + struct pinctrl_pin_desc *pindesc; + struct pinctrl_desc *amb_pinctrl_desc; + unsigned int pin; + + /* dynamically populate the pin number and pin name for pindesc */ + pindesc =3D devm_kcalloc(soc->dev, soc->npins, sizeof(*pindesc), + GFP_KERNEL); + if (!pindesc) + return -ENOMEM; + + for (pin =3D 0; pin < soc->npins; pin++) { + pindesc[pin].number =3D pin; + pindesc[pin].name =3D devm_kasprintf(soc->dev, GFP_KERNEL, + "io%u", pin); + if (!pindesc[pin].name) + return -ENOMEM; + } + + amb_pinctrl_desc =3D devm_kzalloc(soc->dev, sizeof(*amb_pinctrl_desc), GF= P_KERNEL); + if (!amb_pinctrl_desc) + return -ENOMEM; + + amb_pinctrl_desc->name =3D dev_name(soc->dev); + amb_pinctrl_desc->pins =3D pindesc; + amb_pinctrl_desc->npins =3D soc->npins; + amb_pinctrl_desc->pctlops =3D &amb_pctrl_ops; + amb_pinctrl_desc->pmxops =3D &amb_pinmux_ops; + amb_pinctrl_desc->confops =3D &amb_pinconf_ops; + amb_pinctrl_desc->owner =3D THIS_MODULE; + + soc->pctl =3D devm_pinctrl_register(soc->dev, amb_pinctrl_desc, soc); + if (IS_ERR(soc->pctl)) { + dev_err(soc->dev, "could not register pinctrl driver\n"); + return PTR_ERR(soc->pctl); + } + + return 0; +} + +static int amb_pinctrl_probe(struct platform_device *pdev) +{ + struct amb_pinctrl_soc_data *soc; + struct device_node *np; + unsigned int *group_pins; + unsigned int group, group_pin; + size_t nr_group_pins =3D 0; + int rval; + + soc =3D devm_kzalloc(&pdev->dev, sizeof(*soc), GFP_KERNEL); + if (!soc) + return -ENOMEM; + + soc->dev =3D &pdev->dev; + soc->data =3D of_device_get_match_data(&pdev->dev); + if (!soc->data) + return dev_err_probe(&pdev->dev, -EINVAL, "missing soc data"); + if (!soc->data->nr_banks || + soc->data->nr_banks > AMBA_MAX_BANKS || + !soc->data->npins || + soc->data->npins > AMBA_MAX_PINS || + soc->data->nr_banks * 32 > soc->data->npins || + soc->data->clk_au_dedicated_pin >=3D soc->data->npins || + PINID_TO_BANK(soc->data->clk_au_dedicated_pin) >=3D AMBA_MAX_BANKS) + return dev_err_probe(&pdev->dev, -EINVAL, + "invalid bank or pin count\n"); + + soc->npins =3D soc->data->npins; + + np =3D pdev->dev.of_node; + soc->iomux_base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(soc->iomux_base)) + return dev_err_probe(&pdev->dev, PTR_ERR(soc->iomux_base), + "couldn't get iomux reg"); + + soc->ds_regmap =3D syscon_regmap_lookup_by_phandle(np, "ambarella,drive-s= trength-syscon"); + if (IS_ERR(soc->ds_regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(soc->ds_regmap), + "couldn't get drive-strength regmap"); + + soc->pull_regmap =3D syscon_regmap_lookup_by_phandle(np, "ambarella,pull-= syscon"); + if (IS_ERR(soc->pull_regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(soc->pull_regmap), + "couldn't get pull regmap"); + + soc->nr_groups =3D soc->data->nr_groups; + soc->functions =3D soc->data->functions; + soc->nr_functions =3D soc->data->nr_functions; + if (!soc->data->groups || !soc->nr_groups || + !soc->functions || !soc->nr_functions) + return dev_err_probe(&pdev->dev, -EINVAL, + "missing pin groups or functions\n"); + + soc->groups =3D devm_kcalloc(&pdev->dev, soc->nr_groups, + sizeof(*soc->groups), GFP_KERNEL); + if (!soc->groups) + return -ENOMEM; + + for (group =3D 0; group < soc->nr_groups; group++) { + const struct ambpin_group_desc *desc =3D + &soc->data->groups[group]; + + if (!desc->name || !desc->pinmux || !desc->num_pins) + return dev_err_probe(&pdev->dev, -EINVAL, + "invalid pin group %u\n", group); + + nr_group_pins +=3D desc->num_pins; + } + + group_pins =3D devm_kcalloc(&pdev->dev, nr_group_pins, + sizeof(*group_pins), GFP_KERNEL); + if (!group_pins) + return -ENOMEM; + + for (group =3D 0; group < soc->nr_groups; group++) { + const struct ambpin_group_desc *desc =3D + &soc->data->groups[group]; + struct ambpin_group *grp =3D &soc->groups[group]; + + grp->name =3D desc->name; + grp->pinmux =3D desc->pinmux; + grp->pins =3D group_pins; + grp->num_pins =3D desc->num_pins; + for (group_pin =3D 0; + group_pin < grp->num_pins; + group_pin++) { + u32 pinmux =3D grp->pinmux[group_pin]; + unsigned int pin =3D AMBA_PINMUX_TO_PIN(pinmux); + unsigned int alt =3D AMBA_PINMUX_TO_ALT(pinmux); + + if (pin >=3D soc->npins || alt > 7) + return dev_err_probe(&pdev->dev, -EINVAL, + "group %s has invalid pinmux %#x\n", + grp->name, pinmux); + + grp->pins[group_pin] =3D pin; + } + group_pins +=3D grp->num_pins; + } + + raw_spin_lock_init(&soc->lock); + + /* Mark all pins unavailable, then clear pins that exist. */ + bitmap_fill(soc->used, AMBA_MAX_PINS); + bitmap_clear(soc->used, 0, soc->data->nr_banks * 32); + clear_bit(soc->data->clk_au_dedicated_pin, soc->used); + + rval =3D amb_pinctrl_register(soc); + if (rval) + return dev_err_probe(&pdev->dev, rval, "pinctrl register failed!"); + + dev_info(&pdev->dev, "Ambarella pinctrl driver registered"); + + return 0; +} + +static const struct of_device_id amb_pinctrl_dt_match[] =3D { + { + .compatible =3D "ambarella,cv75-pinctrl", + .data =3D &ambarella_cv75_pinctrl_data, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, amb_pinctrl_dt_match); + +static struct platform_driver amb_pinctrl_driver =3D { + .probe =3D amb_pinctrl_probe, + .driver =3D { + .name =3D "ambarella-pinctrl", + .of_match_table =3D of_match_ptr(amb_pinctrl_dt_match), + }, +}; + +static int __init amb_pinctrl_drv_register(void) +{ + return platform_driver_register(&amb_pinctrl_driver); +} +arch_initcall(amb_pinctrl_drv_register); + +MODULE_AUTHOR("Cao Rongrong "); +MODULE_DESCRIPTION("Ambarella SoC pinctrl driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/pinctrl/pinctrl-ambarella.h b/drivers/pinctrl/pinctrl-= ambarella.h new file mode 100644 index 000000000000..094639627131 --- /dev/null +++ b/drivers/pinctrl/pinctrl-ambarella.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Ambarella pinctrl common data definitions + * + * Copyright (C) 2012-2026, Ambarella, Inc. + */ + +#ifndef _PINCTRL_AMBARELLA_H +#define _PINCTRL_AMBARELLA_H + +#include + +#define AMBA_MAX_BANKS 8 + +#define AMBA_PINMUX(pin, alt) (((alt) << 12) | (pin)) +#define AMBA_PINMUX_TO_PIN(mux) ((mux) & 0xfff) +#define AMBA_PINMUX_TO_ALT(mux) (((mux) >> 12) & 0xf) + +struct ambpin_group_desc { + const char *name; + const u32 *pinmux; + unsigned int num_pins; +}; + +struct ambpin_function { + const char *name; + const char * const *groups; + unsigned int num_groups; +}; + +struct amb_pinctrl_data { + unsigned int ds0[AMBA_MAX_BANKS]; + unsigned int ds1[AMBA_MAX_BANKS]; + unsigned int ds2[AMBA_MAX_BANKS]; + unsigned int pull_en[AMBA_MAX_BANKS]; + unsigned int pull_dir[AMBA_MAX_BANKS]; + bool have_ds2; + u32 hsm_domain_id; + u32 clk_au_dedicated_pin; + unsigned int nr_banks; + unsigned int npins; + const struct ambpin_group_desc *groups; + unsigned int nr_groups; + const struct ambpin_function *functions; + unsigned int nr_functions; +}; + +extern const struct amb_pinctrl_data ambarella_cv75_pinctrl_data; + +#endif /* _PINCTRL_AMBARELLA_H */ --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 C1BAD4229B0; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=Vw+8VUk1pMAzEWf9+kXncn1fTddRBxXlyadz73O+opEFr6oEO2lDg52zcgWELglJG33NjNSqRjKPE/2hdBEnwdm/71MuVTXYh1M+dJ5amfeD99mx6quebWp7xS8ttT1ywR9T7KvZsT9R77Ts6eUHXBsxaxsIwtRhNJGSBOX3kgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=Ey6hHEAKzHtbiSwYiAX2p23FeQWcW7aXVVQjV1l8O20=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GoyutrtmeAH48L2Qp0RORzYSkDvgA0xZjfKjGIZQsbXVw5annlS5zyaUoMIN8US5H7/QTdvjLo3CngOyZmc0pXb63Qrka8QJHFeL0SX5QlDek9dw7lrfEELfDqNH+IzCCwQgL5HXJyczUqLQ7VdlMKz29n1/PhGQSA81pV5S5V8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fQIH/ico; 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="fQIH/ico" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8AFCEC2BD05; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=Ey6hHEAKzHtbiSwYiAX2p23FeQWcW7aXVVQjV1l8O20=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=fQIH/icosV8X2Qiqs7f3y7AaNSU7mUW8Rqdeue+uVZnDTwzzpe7RYlldFtht7YHR3 p5h/Ez0eLpA6aoe5MG4udWOdFeuBXAb3bkAIMc4eqQDk/2TapwvW/Rd9bHM8qO3jOj us4FcvRayFHRNRnlDWcKzOswzyhyJOlEWMBtlJuMVbEQ8QdTFBbfXKvccvNX/DxBj5 Z104H0OMN4cYKW5gBtfZ5fSULxu4ClZcudUrERCUNVH1HSXNCJISYANiraT+prERXA FoJPZEYNI/Blarry5Mm4uGXEP/mk6iSWYRYc0K8c80AUCbic0yk9LH459GQLL4Hf9C enqLL7x7JAOCA== 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 75A8BC61DD6; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:18 +0800 Subject: [PATCH v6 11/13] serial: 8250_dw: add Ambarella CV75 quirks 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: <20260904-cv75-v5-v6-11-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=3281; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=Z5nzeIPvLPUzlAn30nqY+z7UiEoVXDand3R1os5q42Q=; b=xJ3lb4R3PdX4OCLG6tIEbcBo62x+owepbHCBd7hLxw13rzqXb19saOwGcjzuxfdOWZgy6qLCn +E/ccfIZMOTCz+l5VdlDnnEp9HHYjH41kSPIxNeuVTW2hxaFlvXdbS2 X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao The Ambarella CV75 UART is Ambarella IP, not a Synopsys DesignWare licensed block. At the register level it is close enough to DW APB UART that a full custom UART driver is unnecessary: reuse 8250_dw with a small platform quirk. Quirks: - keep IER ETOI (bit 5) set for RX timeout behaviour - skip set_rate; baud clock is managed outside the UART block Signed-off-by: Long Zhao Reviewed-by: Andy Shevchenko Reviewed-by: Linus Walleij --- drivers/tty/serial/8250/8250_dw.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/82= 50_dw.c index 5fba913f3301..b15de40d1e2a 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -43,6 +43,9 @@ #define RZN1_UART_xDMACR_8_WORD_BURST (2 << 1) #define RZN1_UART_xDMACR_BLK_SZ(x) ((x) << 3) =20 +/* Ambarella IER: receive timeout interrupt enable */ +#define AMBARELLA_UART_IER_ETOI BIT(5) + /* Quirks */ #define DW_UART_QUIRK_OCTEON BIT(0) #define DW_UART_QUIRK_ARMADA_38X BIT(1) @@ -60,6 +63,7 @@ =20 struct dw8250_platform_data { u8 usr_reg; + u8 ier_mask; u32 cpr_value; unsigned int quirks; }; @@ -572,6 +576,27 @@ static void dw8250_prepare_rx_dma(struct uart_8250_por= t *p) dw8250_writel_ext(up, RZN1_UART_RDMACR, val); } =20 +static int dw8250_ier_mask_startup(struct uart_port *p) +{ + struct dw8250_data *d =3D to_dw8250_data(p->private_data); + struct uart_8250_port *up =3D up_to_u8250p(p); + int ret; + + ret =3D serial8250_do_startup(p); + if (ret) + return ret; + + /* + * Ambarella keeps variant IER bits (e.g. ETOI) set for correct RX + * timeout behaviour. Force them into the 8250 IER shadow so later + * generic IER updates do not clear them. + */ + up->ier |=3D d->pdata->ier_mask; + serial_port_out(p, UART_IER, up->ier); + + return 0; +} + static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) { unsigned int quirks =3D data->pdata->quirks; @@ -606,6 +631,8 @@ static void dw8250_quirks(struct uart_port *p, struct d= w8250_data *data) p->serial_in =3D dw8250_serial_in32; data->uart_16550_compatible =3D true; } + if (data->pdata->ier_mask) + p->startup =3D dw8250_ier_mask_startup; } =20 static void dw8250_reset_control_assert(void *data) @@ -879,6 +906,12 @@ static const struct dw8250_platform_data dw8250_intc10= ee =3D { .quirks =3D DW_UART_QUIRK_IER_KICK, }; =20 +static const struct dw8250_platform_data dw8250_ambarella_cv75_data =3D { + .usr_reg =3D DW_UART_USR, + .ier_mask =3D AMBARELLA_UART_IER_ETOI, + .quirks =3D DW_UART_QUIRK_SKIP_SET_RATE, +}; + static const struct dw8250_platform_data dw8250_ultrarisc_dp1000_data =3D { .usr_reg =3D DW_UART_USR, .cpr_value =3D FIELD_PREP_CONST(DW_UART_CPR_ABP_DATA_WIDTH, 2) | @@ -889,6 +922,7 @@ static const struct dw8250_platform_data dw8250_ultrari= sc_dp1000_data =3D { }; =20 static const struct of_device_id dw8250_of_match[] =3D { + { .compatible =3D "ambarella,cv75-uart", .data =3D &dw8250_ambarella_cv75= _data }, { .compatible =3D "snps,dw-apb-uart", .data =3D &dw8250_dw_apb }, { .compatible =3D "cavium,octeon-3860-uart", .data =3D &dw8250_octeon_386= 0_data }, { .compatible =3D "marvell,armada-38x-uart", .data =3D &dw8250_armada_38x= _data }, --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 D9DE1423E9A; Fri, 4 Sep 2026 06:39:14 +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=1788503954; cv=none; b=fiRheVpvfLLFYn2NdsxWkK5FpiDlaEx2nC7Z0kjSWOgE8nlxjW4TDCxOTM3zDJkprdFw/bKUmqyVpHYoG6ch1xaHof6su9fxeivew2eDKkfsKlKoRt+H91b/k7pCXujnrk4vsW2sTozq94MIU5b0KvhVqdelIdkKlI6Gjeep+Pg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503954; c=relaxed/simple; bh=R+lKcLFLoJm1Ld9aWAwyIbEP5wstiA7F2ghODRPvZ6U=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hBe8C8L+p0m5QyEhHYYCVr5p9rVB6wBzLQUcEHaxsd+l/xMFRW9vsdKmEJOdUzXHqOAx9+qO/zmZ+dXtG7gaL6aIjrvpWwEvZm7/Sym0h068pGiFF5DRjsxgiEp9brZG8vBjjXFMW1x0qRdozzkXXQqSKv8p2/gVERfqGRaN4wM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bj+PhlOv; 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="bj+PhlOv" Received: by smtp.kernel.org (Postfix) with ESMTPS id A052DC4AF18; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=R+lKcLFLoJm1Ld9aWAwyIbEP5wstiA7F2ghODRPvZ6U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=bj+PhlOv1QjphXlUoGB9IzzEEoqmZgpDM7g8YICwePjWYrLN2k1vYbCZzDxTwCNAI Wf9ssI4V78z8QbZte6NT9GE9oxAjXTqDzRqvtHC8odBJU07HO+ykaIl3qOnzHZwRCN nRMzbNVDr2yttTEOM2w57sdiGJ7kQZ74nNsqqfcgD/T0zKXeT16U59arwxnb8oB+Yg WQvFtwTfeVX43MYGXSWNx7t9gdAbvVK/H+ALOVGmGR3+T18aGnmW41tuEmctQC7Gzk aNwLutzz7goUfUMWHPXdqY/tFDlewhmRgUYAX1fri1uFaYU4COLZJcqTqYWrjrsVQU qgpxMKN5zBWVg== 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 89D76C79F87; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:19 +0800 Subject: [PATCH v6 12/13] arm64: ambarella: add ARCH_AMBARELLA and CV75 EVK DT 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: <20260904-cv75-v5-v6-12-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=8059; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=9ADmB3uZTKZnKQXTjGNmZfv6b5ugBQAknwN0jZpggVQ=; b=GhwTQV5b0y8a6OuJ2CACcpaoqMeo6RRC0K7DQwjM2M5yggPhAlygNLgVCD2QIu6rLjJOV1MHM kE5uvdyLTU+DHQ1msYNfN6UTREYL24CJgqdmPQZFm+X6RpXCcWbzRiy X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Enable ARCH_AMBARELLA and add a minimal CV75 SoC / EVK device tree for console bring-up with the RCT clocks, UART, pinctrl and GPIO banks. Signed-off-by: Long Zhao Reviewed-by: Linus Walleij --- arch/arm64/Kconfig.platforms | 6 + arch/arm64/boot/dts/Makefile | 1 + arch/arm64/boot/dts/ambarella/Makefile | 3 + arch/arm64/boot/dts/ambarella/cv75-evk.dts | 30 +++++ arch/arm64/boot/dts/ambarella/cv75.dtsi | 177 +++++++++++++++++++++++++= ++++ arch/arm64/configs/defconfig | 1 + 6 files changed, 218 insertions(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index d2acfac73003..16d7e3a4c2d6 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -26,6 +26,12 @@ config ARCH_SUNXI help This enables support for Allwinner sunxi based SoCs like the A64. =20 +config ARCH_AMBARELLA + bool "Ambarella SoC family" + select PINCTRL + help + This enables support for the ARM64 based Ambarella SoCs like CV75. + config ARCH_ALPINE bool "Annapurna Labs Alpine platform" select ALPINE_MSI if PCI diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index fc726b215f12..f1709eb5d915 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -4,6 +4,7 @@ subdir-y +=3D airoha subdir-y +=3D allwinner subdir-y +=3D altera subdir-y +=3D amazon +subdir-y +=3D ambarella subdir-y +=3D amd subdir-y +=3D amlogic subdir-y +=3D apm diff --git a/arch/arm64/boot/dts/ambarella/Makefile b/arch/arm64/boot/dts/a= mbarella/Makefile new file mode 100644 index 000000000000..ddca3d7b18cc --- /dev/null +++ b/arch/arm64/boot/dts/ambarella/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +dtb-$(CONFIG_ARCH_AMBARELLA) +=3D cv75-evk.dtb diff --git a/arch/arm64/boot/dts/ambarella/cv75-evk.dts b/arch/arm64/boot/d= ts/ambarella/cv75-evk.dts new file mode 100644 index 000000000000..42a0fe24b83b --- /dev/null +++ b/arch/arm64/boot/dts/ambarella/cv75-evk.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Ambarella CV75 EVK board + */ + +/dts-v1/; + +#include "cv75.dtsi" + +/ { + model =3D "Ambarella CV75 EVK Board"; + compatible =3D "ambarella,cv75-evk", "ambarella,cv75"; + + aliases { + serial0 =3D &uart0; + }; + + chosen { + stdout-path =3D &uart0; + }; + + memory@200000 { + device_type =3D "memory"; + reg =3D <0x0 0x00200000 0x0 0x07e00000>; + }; +}; + +&uart0 { + status =3D "okay"; +}; diff --git a/arch/arm64/boot/dts/ambarella/cv75.dtsi b/arch/arm64/boot/dts/= ambarella/cv75.dtsi new file mode 100644 index 000000000000..c36b6af48237 --- /dev/null +++ b/arch/arm64/boot/dts/ambarella/cv75.dtsi @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Ambarella CV75 SoC + * + * Boot peripheral: UART0 console. + * Clocks: a single ambarella,cv75-rct provider. + */ + +#include +#include + +/ { + compatible =3D "ambarella,cv75"; + interrupt-parent =3D <&gic>; + #address-cells =3D <2>; + #size-cells =3D <2>; + + cpus { + #address-cells =3D <1>; + #size-cells =3D <0>; + + cpu@0 { + compatible =3D "arm,cortex-a76"; + device_type =3D "cpu"; + reg =3D <0x000>; + enable-method =3D "psci"; + }; + + cpu@1 { + compatible =3D "arm,cortex-a76"; + device_type =3D "cpu"; + reg =3D <0x100>; + enable-method =3D "psci"; + }; + }; + + osc: oscillator { + compatible =3D "fixed-clock"; + #clock-cells =3D <0>; + clock-frequency =3D <24000000>; + clock-output-names =3D "osc"; + }; + + psci { + compatible =3D "arm,psci-0.2"; + method =3D "smc"; + }; + + soc { + compatible =3D "simple-bus"; + #address-cells =3D <2>; + #size-cells =3D <2>; + ranges; + + ahb@ffe0000000 { + compatible =3D "simple-bus"; + reg =3D <0xff 0xe0000000 0x0 0x01000000>; + ranges =3D <0xe0000000 0xff 0xe0000000 0x01000000>; + #address-cells =3D <1>; + #size-cells =3D <1>; + + s_scratchpad_syscon: scratchpad@e002e000 { + compatible =3D "ambarella,cv75-sec-scratchpad", "syscon"; + reg =3D <0xe002e000 0x1000>; + }; + }; + + apb@ffe4000000 { + compatible =3D "simple-bus"; + reg =3D <0xff 0xe4000000 0x0 0x01000000>; + ranges =3D <0xe4000000 0xff 0xe4000000 0x01000000>; + #address-cells =3D <1>; + #size-cells =3D <1>; + + uart0: serial@e4000000 { + compatible =3D "ambarella,cv75-uart", "snps,dw-apb-uart"; + reg =3D <0xe4000000 0x1000>; + clocks =3D <&rct CV75_GCLK_UART0>; + interrupts =3D ; + reg-shift =3D <2>; + reg-io-width =3D <4>; + pinctrl-names =3D "default"; + pinctrl-0 =3D <&uart0_pins>; + + status =3D "disabled"; + }; + + pinctrl: pinctrl@e4010000 { + compatible =3D "ambarella,cv75-pinctrl"; + reg =3D <0xe4010000 0x1000>; + ambarella,drive-strength-syscon =3D <&rct>; + ambarella,pull-syscon =3D <&s_scratchpad_syscon>; + + uart0_pins: uart0-pins { + function =3D "uart0"; + groups =3D "uart0"; + }; + }; + + gpio0: gpio@e4013000 { + compatible =3D "ambarella,cv75-gpio", "arm,primecell"; + reg =3D <0xe4013000 0x1000>; + clocks =3D <&rct CV75_GCLK_APB>; + clock-names =3D "apb_pclk"; + interrupts =3D ; + gpio-controller; + #gpio-cells =3D <2>; + gpio-ranges =3D <&pinctrl 0 0 32>; + interrupt-controller; + #interrupt-cells =3D <2>; + arm,primecell-periphid =3D <0x000e8061>; + }; + + gpio1: gpio@e4014000 { + compatible =3D "ambarella,cv75-gpio", "arm,primecell"; + reg =3D <0xe4014000 0x1000>; + clocks =3D <&rct CV75_GCLK_APB>; + clock-names =3D "apb_pclk"; + interrupts =3D ; + gpio-controller; + #gpio-cells =3D <2>; + gpio-ranges =3D <&pinctrl 0 32 32>; + interrupt-controller; + #interrupt-cells =3D <2>; + arm,primecell-periphid =3D <0x000e8061>; + }; + + gpio2: gpio@e4015000 { + compatible =3D "ambarella,cv75-gpio", "arm,primecell"; + reg =3D <0xe4015000 0x1000>; + clocks =3D <&rct CV75_GCLK_APB>; + clock-names =3D "apb_pclk"; + interrupts =3D ; + gpio-controller; + #gpio-cells =3D <2>; + gpio-ranges =3D <&pinctrl 0 64 32>; + interrupt-controller; + #interrupt-cells =3D <2>; + arm,primecell-periphid =3D <0x000e8061>; + }; + }; + + rct: clock-controller@ffed080000 { + compatible =3D "ambarella,cv75-rct", "syscon"; + reg =3D <0xff 0xed080000 0x0 0x1000>; + clocks =3D <&osc>; + clock-names =3D "osc"; + #clock-cells =3D <1>; + #reset-cells =3D <1>; + assigned-clocks =3D <&rct CV75_GCLK_UART0>; + assigned-clock-parents =3D <&osc>; + assigned-clock-rates =3D <24000000>; + }; + + gic: interrupt-controller@fff0101000 { + compatible =3D "arm,gic-400"; + reg =3D <0xff 0xf0101000 0x0 0x1000>, + <0xff 0xf0102000 0x0 0x2000>, + <0xff 0xf0104000 0x0 0x2000>, + <0xff 0xf0106000 0x0 0x2000>; + interrupt-controller; + #interrupt-cells =3D <3>; + #address-cells =3D <0>; + interrupts =3D ; + }; + }; + + timer { + compatible =3D "arm,armv8-timer"; + interrupts =3D , + , + , + , + ; + }; +}; diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index ad3bd3d9507b..454f07a6a6a6 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -36,6 +36,7 @@ CONFIG_CRASH_DUMP=3Dy CONFIG_ARCH_ACTIONS=3Dy CONFIG_ARCH_AIROHA=3Dy CONFIG_ARCH_SUNXI=3Dy +CONFIG_ARCH_AMBARELLA=3Dy CONFIG_ARCH_ALPINE=3Dy CONFIG_ARCH_APPLE=3Dy CONFIG_ARCH_ARTPEC=3Dy --=20 2.34.1 From nobody Sat Sep 26 06:20:40 2026 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 EC17E424D65; Fri, 4 Sep 2026 06:39:14 +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=1788503955; cv=none; b=KUd9HB7KG+6DIOPPyjGv9WzMGsGndDis+tBgEDaZ7Fo/pdwyGUW6vyL5RG08BmCgh+8bwR4QwngbbQh1POJ25Tw8Ra8ye6VWeVz0ZboUgv8vFJWa7LoHp3104UeHzCjU6ac2jchucIdnybzI2BGy98WyGYWq9xzMqsEWS3drT5E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788503955; c=relaxed/simple; bh=u1O2yyg4IFgXvWdBWEfBf7DSbFAtEAmAyY6MwVpsw88=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EiDPc3P0q3Zre3YfTPIVPevOUJ1YroTl1A/rUSMQryp1tymSQ/eqKJNFQglqrOoJ4sOw3Bj/9Go9nx1BJNko1O+e3Tn1Vu5WXOERq/4mPPbL6MS7L6qgoJ5YOPLXNjBMsT96uECO3otd5LjLQ1fWKOGU1g28DeDEq8OqekV/j/E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J6x4XMEQ; 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="J6x4XMEQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id B0313C2BCFB; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1788503954; bh=u1O2yyg4IFgXvWdBWEfBf7DSbFAtEAmAyY6MwVpsw88=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=J6x4XMEQrbSig3dyY7G2WKP5LuW7mNQWZ6oFtmcWY5zHfTJ9omOcBnQPrvssoNKyu u4sx4PLmyPshXjxkD+HNXF8P3z2wAjfyzkfngefe1J6PxlALJe38Tq1/NKu3N9pzvY J1oIauK5BRpeFh1y4ori1dMlhwxGXX6p5j1KYVz0asbB3YArhQL0aV42ts7m7xbdG9 uOBWDWatJZjjxtvAPH4Ug+ebL6u7tF5n8bV/pupj4+ijnfCsOTkIgoIWxotI5wGcRo b4UkjM8EkCADfnIVBG8FFFPAX/67mauX0CnHeBqy9SXKkR/cFgKx4WZF5CHCRhnsbZ y441fpKfnjYzA== 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 9BA5EC79F82; Fri, 4 Sep 2026 06:39:14 +0000 (UTC) From: Long Zhao via B4 Relay Date: Fri, 04 Sep 2026 14:38:20 +0800 Subject: [PATCH v6 13/13] MAINTAINERS: add ARM/AMBARELLA SoC support 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: <20260904-cv75-v5-v6-13-e918514cb3b1@ambarella.com> References: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> In-Reply-To: <20260904-cv75-v5-v6-0-e918514cb3b1@ambarella.com> To: Arnd Bergmann , Krzysztof Kozlowski , Alexandre Belloni , soc@lists.linux.dev, linux-arm-kernel@lists.infradead.org Cc: Long Zhao , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Greg Kroah-Hartman , Jiri Slaby , Andy Shevchenko , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Catalin Marinas , Will Deacon , Long Zhao , Lee Jones , mfd@lists.linux.dev, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1788503951; l=1193; i=longzhao@ambarella.com; s=20260730; h=from:subject:message-id; bh=FMdxZub31R7avQT3Ojw4RWRGTKHK7OVLHXgrDSDBBvo=; b=J20AxAQaqy7Qb3wZitsadbnYGTVQMan5SDPyQ+DqSnV+k1kaVX6z5mKQ4xl+txmE+cBAzqFwj r//YYyCQx1pARbXn3QbLcQ8xktjp5ktrUbMtqy+KG1o+7+u+jYSNZBp X-Developer-Key: i=longzhao@ambarella.com; a=ed25519; pk=/xGhPTOX0/eYsyTWzyjjgAIW1Z/YD+IlnOnvcdRozow= X-Endpoint-Received: by B4 Relay for longzhao@ambarella.com/20260730 with auth_id=903 X-Original-From: Long Zhao Reply-To: longzhao@ambarella.com From: Long Zhao Add a maintainer entry covering Ambarella CV75 bindings, DTS and related drivers. Signed-off-by: Long Zhao Reviewed-by: Linus Walleij --- MAINTAINERS | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 803b60ad628f..59e5b32d7a02 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2502,6 +2502,20 @@ F: drivers/clocksource/asm9260_timer.c F: drivers/rtc/rtc-asm9260.c F: drivers/watchdog/asm9260_wdt.c =20 +ARM/AMBARELLA SOC SUPPORT +M: Long Zhao +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +L: devicetree@vger.kernel.org +S: Maintained +F: Documentation/devicetree/bindings/arm/ambarella.yaml +F: Documentation/devicetree/bindings/clock/ambarella,cv75-rct.yaml +F: Documentation/devicetree/bindings/pinctrl/ambarella,cv75-pinctrl.yaml +F: arch/arm64/boot/dts/ambarella/ +F: drivers/clk/ambarella/ +F: drivers/pinctrl/pinctrl-ambarella* +F: include/dt-bindings/clock/ambarella,cv75-rct.h +N: ambarella + ARM/AMD PENSANDO ARM64 ARCHITECTURE M: Brad Larson L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) --=20 2.34.1