From nobody Sun Jun 14 21:21:51 2026 Received: from smtpbgeu1.qq.com (smtpbgeu1.qq.com [52.59.177.22]) (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 EBB393B9DAD; Wed, 8 Apr 2026 10:08:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.59.177.22 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775642915; cv=none; b=bqmx6eWOOvWYEgnAsk5AvLo2F7qHK7QOTlb3O+mN7rqnzH+f9skpmp0dsMz8tSYSmUgdZCYpiix742F+hG+Zjaj7t6K9z2ibtV8hHPqI2BaCWLBWrMGnT8KqWiTU9GL81teDzL4UF2J1bPK/71BgMaHbA/SreB2bARQBWDbDDow= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775642915; c=relaxed/simple; bh=hyoSGNKO8z6d1axQ29oBEAL7xl1kP5y9LqcBAulHLMQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GlhXrLFl7kwZpqY/42HDdmQoCaPfo8yWM3igBtca0DkqScM9pGSa1lm79cb9lrCxPzTNtPDpFmI7CkLwqTmudtDX7i95sVQA+0XgH7YOgZkUfFRXr/G/h5jGgvOBChsNKpDg9itIdMWFbL8Pku/qGw5NTp1yYhJXwV6++6QLCN0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=radxa.com; spf=pass smtp.mailfrom=radxa.com; arc=none smtp.client-ip=52.59.177.22 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=radxa.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=radxa.com X-QQ-mid: zesmtpsz5t1775642866t6935ec97 X-QQ-Originating-IP: 4qODUJGb35PW82fgR5f0LCmXadzWoz4xrJ1L5pcMYPQ= Received: from [192.168.30.32] ( [116.234.85.158]) by bizesmtp.qq.com (ESMTP) with id ; Wed, 08 Apr 2026 18:07:45 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 12296274181211464006 EX-QQ-RecipientCnt: 10 From: Xilin Wu Date: Wed, 08 Apr 2026 18:07:32 +0800 Subject: [PATCH v2 1/2] dt-bindings: pwm: clk-pwm: add optional GPIO and pinctrl properties 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: <20260408-clk-pwm-gpio-v2-1-d22f1f3498a0@radxa.com> References: <20260408-clk-pwm-gpio-v2-0-d22f1f3498a0@radxa.com> In-Reply-To: <20260408-clk-pwm-gpio-v2-0-d22f1f3498a0@radxa.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nikita Travkin Cc: linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Xilin Wu X-Mailer: b4 0.15.1 X-Developer-Signature: v=1; a=openpgp-sha256; l=2512; i=sophon@radxa.com; h=from:subject:message-id; bh=hyoSGNKO8z6d1axQ29oBEAL7xl1kP5y9LqcBAulHLMQ=; b=owGbwMvMwCVmdFg0fe08Iz/G02pJDJnXNN7tfMb07W11zRRXxo6iZPGW6CMH153PYW5f+LO+d EL4SqspHaUsDGJcDLJiiiwK8Qxz2Stzrz0VK9WDmcPKBDKEgYtTACZSsJKRYf6DAzsys7caqdZY 2kQncL+cU6uf2DJ9gejd3QuPidf9qmZk6Nk0U7Ds+H+VFKUDKZe21dq1STLF2n349/H+d1W3R28 1eAE= X-Developer-Key: i=sophon@radxa.com; a=openpgp; fpr=205F009D07796DD6E516752E32C31567AD9E324E X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpsz:radxa.com:qybglogicsvrsz:qybglogicsvrsz3b-0 X-QQ-XMAILINFO: N8r2YJN/ffrjkob54fqR58thY4A5iwbaYUjMjFmkKQCx3HXYzDhzaaGa ZAtQq5IYnwTQb5DZRPvhrkelCsRvCXFs3zbXmbgyc+JqxeRvalRcwCZ2ejudG6y/dB9ZVYl ExRQvOcedBy9t/THaoNDgoF73SGGOxEWGbrAK6fQqg9madUAKdZuCzcrk4zLxsw+BW71HQy eIs/dk2WcI0Yy2CgG18lIilrZfPTrojkSrsxWBNKAnAB2+rngP2jvxbuUU/djTlIQJ8PD9q AUkBlBoBS9d7TfE2FB8tFOplzOcEHDp/zcZeWnZ1pweEOI1vLUtDBb6GxORc0N0rtR6hCgf Eoj9KcciX9lDXJliAngN63b40PsAHSXhMXi7vC0iLG6UgnlfSGBpdOCd+8r54pdeXgg1Xt2 F5hA5hG+9c5iemgEFUzE9ngVOXPi6Y2A1uEeVVjMPkfVnKQdALidp/lFUj5KaP7v5PjV42y FhMnd9WGDVkqfP5cVrN8ovhb0yGkC/HUivo0xu5CHFHTs9lVW4LbdONtVE8DdCChesuQ5ZM yXoIno/dZ/FIn3TZVn0gF0W3C5zGRHBju0JWZRABxs/06hwoOQIQ6/oH9IUwKQqJXpae0tn LhvxDqI4QAnYSQvGfSIu8q9bnlJALV1j4OpDQrxd4oJIj/35TYZknjrZ6izLWrBX+Wp5caQ Ls9/Pif5i2zdRgkGnH1BaXpGgyyYZiyXKy6NYAkgUmjc1bRX7t22nupv5iLKHaz7hbJeJh3 0GydDhw2sQfq5zE04pEMitrWbElLGMHuXDCjSgKuXV6doB2wsC5WPy7VYJyNXmh/1RYDhO7 7Ts5RisMU/uXyU2kFoWdrdVUw4EZ/PG53ByX+mpE2/6I9PaMXTq4T7CZwITZeuKkZs25E5U Cs7gRY1iSDWrFPLm73edyUvaoLL8+5/hhPOMGNXSuYGmK8xtd0pmnIhLajbj9X7rB6XWMWZ XuRCVy9wB3QmhwYEq2qzIUoHtj5xJ64NydVxK5z5fzfnM8dSDh2RaPeEtd47hd+fRhZcbZk j29jsOHpCmys/+3VvbUzmdJl4iRa5r/lm9jHf97ECTC+F7tcF6 X-QQ-XMRINFO: OWPUhxQsoeAVwkVaQIEGSKwwgKCxK/fD5g== X-QQ-RECHKSPAM: 0 The clk-pwm driver cannot produce constant output levels (0% or 100% duty cycle, or disabled state) through the clock hardware alone - the actual pin level when the clock is off is undefined and hardware-dependent. Document optional gpios, pinctrl-names, pinctrl-0, and pinctrl-1 properties that allow the driver to switch the pin between clock function mux (for normal PWM output) and GPIO mode (to drive a deterministic constant level). Signed-off-by: Xilin Wu --- Documentation/devicetree/bindings/pwm/clk-pwm.yaml | 36 ++++++++++++++++++= +++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/pwm/clk-pwm.yaml b/Documenta= tion/devicetree/bindings/pwm/clk-pwm.yaml index ec1768291503..2a0e3e02d27b 100644 --- a/Documentation/devicetree/bindings/pwm/clk-pwm.yaml +++ b/Documentation/devicetree/bindings/pwm/clk-pwm.yaml @@ -15,6 +15,11 @@ description: | It's often possible to control duty-cycle of such clocks which makes them suitable for generating PWM signal. =20 + Optionally, a GPIO and pinctrl states can be provided. When a constant + output level is needed (0%, 100%, or disabled), the pin is switched to + GPIO mode to drive the level directly. For normal PWM output the pin is + switched back to its clock function mux. + allOf: - $ref: pwm.yaml# =20 @@ -29,6 +34,26 @@ properties: "#pwm-cells": const: 2 =20 + gpios: + description: + Optional GPIO used to drive a constant level when the PWM output is + disabled or set to 0% / 100% duty cycle. When provided, pinctrl stat= es + "default" (clock mux) and "gpio" must also be defined. + maxItems: 1 + + pinctrl-names: true + + pinctrl-0: + description: Pin configuration for clock function mux (normal PWM). + maxItems: 1 + + pinctrl-1: + description: Pin configuration for GPIO mode (constant level output). + maxItems: 1 + +dependencies: + gpios: [ pinctrl-0, pinctrl-1 ] + unevaluatedProperties: false =20 required: @@ -41,6 +66,15 @@ examples: compatible =3D "clk-pwm"; #pwm-cells =3D <2>; clocks =3D <&gcc 0>; - pinctrl-names =3D "default"; + }; + + - | + pwm { + compatible =3D "clk-pwm"; + #pwm-cells =3D <2>; + clocks =3D <&gcc 0>; + pinctrl-names =3D "default", "gpio"; pinctrl-0 =3D <&pwm_clk_flash_default>; + pinctrl-1 =3D <&pwm_clk_flash_gpio>; + gpios =3D <&tlmm 32 0>; }; --=20 2.53.0 From nobody Sun Jun 14 21:21:51 2026 Received: from smtpbgjp3.qq.com (smtpbgjp3.qq.com [54.92.39.34]) (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 728193B7B9D; Wed, 8 Apr 2026 10:08:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.92.39.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775642909; cv=none; b=MGd5x8PR5CAlE1y1r+s4EtUrxS7p7YgdS6DoLmhoAj+FhpQd/KwKXNKmMv94Yea1jXj2BgLovRu5s+R5CFPaJyLxrFVZMlMK9lc6AD6MkLc/jP7Hb+Y/Z7RPM6MohB1vOszuA+Dj5sxVdq3KuXy4vo2/h57LoWsIFjd379uEdrI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775642909; c=relaxed/simple; bh=bf7ZoBSpgft9/08PUygckkjtp3WdMH5q0ySBEpu7Pkg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Mft04QAuTT76c5avaXuTyEwa4egr7EWL/yKdb1OQySHHrCc1lsbsQXc18WaYzhvcFI4uPzZFAnd8L0OzLXHduTD4yfXVxvUdTM7OrAal/LdH4tK6rfuMnCGY0H/wVcLkpE69BBc/3txokoW6mrUKWiaa2LgWGtiPEQv44iCe5D0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=radxa.com; spf=pass smtp.mailfrom=radxa.com; arc=none smtp.client-ip=54.92.39.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=radxa.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=radxa.com X-QQ-mid: zesmtpsz5t1775642869tf0c51b98 X-QQ-Originating-IP: 8YUueAQUunnoETQUxQJHdFGBSMHHBpmko3OfnVz9bH0= Received: from [192.168.30.32] ( [116.234.85.158]) by bizesmtp.qq.com (ESMTP) with id ; Wed, 08 Apr 2026 18:07:48 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 3240142203164254093 EX-QQ-RecipientCnt: 10 From: Xilin Wu Date: Wed, 08 Apr 2026 18:07:33 +0800 Subject: [PATCH v2 2/2] pwm: clk-pwm: add GPIO and pinctrl support for constant output levels 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: <20260408-clk-pwm-gpio-v2-2-d22f1f3498a0@radxa.com> References: <20260408-clk-pwm-gpio-v2-0-d22f1f3498a0@radxa.com> In-Reply-To: <20260408-clk-pwm-gpio-v2-0-d22f1f3498a0@radxa.com> To: =?utf-8?q?Uwe_Kleine-K=C3=B6nig?= , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Nikita Travkin Cc: linux-pwm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Xilin Wu X-Mailer: b4 0.15.1 X-Developer-Signature: v=1; a=openpgp-sha256; l=5507; i=sophon@radxa.com; h=from:subject:message-id; bh=bf7ZoBSpgft9/08PUygckkjtp3WdMH5q0ySBEpu7Pkg=; b=owGbwMvMwCVmdFg0fe08Iz/G02pJDJnXNN6V50ctMuv9s/lFrcgOK7stb2fcmL0y8cn9ojIv2 evLTmv96ChlYRDjYpAVU2RRiGeYy16Ze+2pWKkezBxWJpAhDFycAjARy3UM/+sDdfzD8rcldrlG q/TKsMmL/65jvGR1uO/X8rvLqg6+u8bwP4UjPd4t0PrL66bYGttZE35adu09v9fp642LDGXCcs7 FPAA= X-Developer-Key: i=sophon@radxa.com; a=openpgp; fpr=205F009D07796DD6E516752E32C31567AD9E324E X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpsz:radxa.com:qybglogicsvrsz:qybglogicsvrsz3b-0 X-QQ-XMAILINFO: NhFh/C1ssL5whRx5PRA2G5KKtSOqvbdhRjfO88Q5NbtuB862ylDshZEc HPwzV3AIB2okbWyF8wYXy8xtEP1dxV0IdkHxWnOOL5slZOsiArw0XoRTBc+xmpT1atMAXz1 2wse9D7qAvP673tuyp0I0OMrtLAEtWhvBXR+g0CiRp8ihj/l9HYW1++0zA+A2f5h6WyAezT GNBwcoDG1wNhnKpFylq56fk0gFSt0Q/3eae+YdY0OoL7XqLs2weAMmUDiAOHxVc0CwMavtl 8LOSeSZFCakvm1bCNmrzASHbfxJcDgefo8hVN+8z8V9ioxA3SrlGI3GRUIgrbaJioSYDfRP Koy1zYFDFYXCtSlAZ/K5Wztv/EP7ojiVxgCR1xdBY73fHP/fLJCu5gBCtYRrfzdnwFttnE2 2vfo14HNlolJp79fzbBLwvv6R9emRidUDkN0WGJSETFKQIoRe03ue6ow7da21CKw81cS4So u94aYcrMlDz0nibf2/gXoo9txhI6QgzLJRQ1TCjH82MoysmTIXFXZYRKaaxyeLJuUN0AzAr 5YutVFgZp7kx4civJXTojgABFTLGkqDyXD/JONjLsy+HscVZlcWdEBzDfZ0YpFXsiSuCIMR 0tm1avyf1ZpJTZ7V/sQWjyyv1g1W9rwplgbnDTo8m29A9bRTuJ3aFl4xXSSRT6rAzm5mkmR wMQzDBeYzU7OmKPP+2ffuvXsZtvzh0DF7j5uGaCOOF28R83lLpN+hh1cPSvfr/+DiXbGy+V dr5/lchwus/Gf4e9FXqNCrjydvMIPRTBjzyNYgc/wwSuQO8iFBMfITWUqdDJWezEIRcmSGy 9DYmTAAxy49jy6AzbxN/ii93xw2wlaf4ST+4KWWH2x9Oly8I0MGmX+Wky0UorZ836kwOtw/ Fq07/IwSNx4762l9DI5E3nS0ZpC9cRd5PZWhwV0pWTGTenOeD9zikzRgTczqqknQrOavhT2 3p4f2+7S7vTrfUeB+rHjTcB8jDm3TmWH4/tdN8T/vpDxVmFlhW1O61/YMhls8FgI5XOkdkm 7blRN3oBROd+28Jk0SEx7nBvfslIha4oK3lqG0e9ysOsMKEj4tUj0aJqugCGr8t2/JxV3rD ENznNBxrgWv X-QQ-XMRINFO: MPJ6Tf5t3I/ylTmHUqvI8+Wpn+Gzalws3A== X-QQ-RECHKSPAM: 0 The clk-pwm driver cannot guarantee a defined output level when the PWM is disabled or when 0%/100% duty cycle is requested, because the pin state when the clock is stopped is hardware-dependent. Add optional GPIO and pinctrl support: when a GPIO descriptor and pinctrl states ("default" for clock mux, "gpio" for GPIO mode) are provided in the device tree, the driver switches the pin to GPIO mode and drives the appropriate level for disabled/0%/100% states. For normal PWM output, the pin is switched back to its clock function mux. If no GPIO is provided, the driver falls back to the original clock-only behavior. Signed-off-by: Xilin Wu --- drivers/pwm/pwm-clk.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++= +--- 1 file changed, 80 insertions(+), 4 deletions(-) diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c index f8f5af57acba..d7d8d2c2dd0f 100644 --- a/drivers/pwm/pwm-clk.c +++ b/drivers/pwm/pwm-clk.c @@ -11,11 +11,20 @@ * - Due to the fact that exact behavior depends on the underlying * clock driver, various limitations are possible. * - Underlying clock may not be able to give 0% or 100% duty cycle - * (constant off or on), exact behavior will depend on the clock. + * (constant off or on), exact behavior will depend on the clock, + * unless a gpio pinctrl state is supplied. * - When the PWM is disabled, the clock will be disabled as well, - * line state will depend on the clock. + * line state will depend on the clock, unless a gpio pinctrl + * state is supplied. * - The clk API doesn't expose the necessary calls to implement * .get_state(). + * + * Optionally, a GPIO descriptor and pinctrl states ("default" and + * "gpio") can be provided. When a constant output level is needed + * (0% duty, 100% duty, or disabled), the driver switches the pin to + * GPIO mode and drives the appropriate level. For normal PWM output + * the pin is switched back to its clock function mux. If no GPIO is + * provided, the driver falls back to the original clock-only behavior. */ =20 #include @@ -25,11 +34,17 @@ #include #include #include +#include +#include #include =20 struct pwm_clk_chip { struct clk *clk; bool clk_enabled; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; /* clock function mux */ + struct pinctrl_state *pins_gpio; /* GPIO mode */ + struct gpio_desc *gpiod; }; =20 static inline struct pwm_clk_chip *to_pwm_clk_chip(struct pwm_chip *chip) @@ -45,14 +60,36 @@ static int pwm_clk_apply(struct pwm_chip *chip, struct = pwm_device *pwm, u32 rate; u64 period =3D state->period; u64 duty_cycle =3D state->duty_cycle; + bool constant_level =3D false; + int gpio_value =3D 0; =20 if (!state->enabled) { - if (pwm->state.enabled) { + constant_level =3D true; + gpio_value =3D 0; + } else if (state->duty_cycle =3D=3D 0) { + constant_level =3D true; + gpio_value =3D (state->polarity =3D=3D PWM_POLARITY_INVERSED) ? 1 : 0; + } else if (state->duty_cycle >=3D state->period) { + constant_level =3D true; + gpio_value =3D (state->polarity =3D=3D PWM_POLARITY_INVERSED) ? 0 : 1; + } + + if (constant_level) { + if (pcchip->gpiod) { + gpiod_direction_output(pcchip->gpiod, gpio_value); + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_gpio); + } + if (pcchip->clk_enabled) { clk_disable(pcchip->clk); pcchip->clk_enabled =3D false; } return 0; - } else if (!pwm->state.enabled) { + } + + if (pcchip->gpiod) + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_default); + + if (!pcchip->clk_enabled) { ret =3D clk_enable(pcchip->clk); if (ret) return ret; @@ -97,6 +134,45 @@ static int pwm_clk_probe(struct platform_device *pdev) return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->clk), "Failed to get clock\n"); =20 + pcchip->pinctrl =3D devm_pinctrl_get(&pdev->dev); + if (IS_ERR(pcchip->pinctrl)) { + ret =3D PTR_ERR(pcchip->pinctrl); + pcchip->pinctrl =3D NULL; + if (ret =3D=3D -EPROBE_DEFER) + return ret; + } else { + pcchip->pins_default =3D pinctrl_lookup_state(pcchip->pinctrl, + PINCTRL_STATE_DEFAULT); + pcchip->pins_gpio =3D pinctrl_lookup_state(pcchip->pinctrl, + "gpio"); + if (IS_ERR(pcchip->pins_default) || IS_ERR(pcchip->pins_gpio)) + pcchip->pinctrl =3D NULL; + } + + /* + * Switch to GPIO pinctrl state before requesting the GPIO. + * The driver core has already applied the "default" state, which + * muxes the pin to the clock function and claims it. We must + * release that claim first so that gpiolib can request the pin. + */ + if (pcchip->pinctrl) + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_gpio); + + pcchip->gpiod =3D devm_gpiod_get_optional(&pdev->dev, NULL, GPIOD_ASIS); + if (IS_ERR(pcchip->gpiod)) + return dev_err_probe(&pdev->dev, PTR_ERR(pcchip->gpiod), + "Failed to get gpio\n"); + + /* + * If pinctrl states were found but no GPIO was provided, the pin is + * stuck in GPIO mode from the switch above. Restore the default + * (clock-function) mux and fall back to clock-only operation. + */ + if (pcchip->pinctrl && !pcchip->gpiod) { + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_default); + pcchip->pinctrl =3D NULL; + } + chip->ops =3D &pwm_clk_ops; =20 ret =3D pwmchip_add(chip); --=20 2.53.0