From nobody Sun Jun 14 21:21:51 2026 Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) (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 1CD1F2D0614; Mon, 6 Apr 2026 15:51:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.206.16.166 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775490666; cv=none; b=nVUSpRjPj2nitlMjNGxt/L3JV3NMWfGS+tZdoXj7vNQQW0QYeyR2S1M4WQr2XLgh/CFufA+uzbtdykAhXqPp9P/rET8YHohSev2cY2GtEsB+Phm9xObyCNzwQTNxcZdtMtdEH4+ECrlgA65cRNQcgaVKw1t6NU4YrA31YPL0nIk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775490666; c=relaxed/simple; bh=hyoSGNKO8z6d1axQ29oBEAL7xl1kP5y9LqcBAulHLMQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=U/TRO5IFZ/jcP9G1pndzGryIkcqoVZMzlJd6VKVTNgjQ799n0mHj65p8Xd3vWU0sTknBX/hQnEk784C1HfA9/DWl9GXDlIbYXtZJx3Sn22rdGJ03qOQZINnwVOzmOHxNruon8UttAt54xg7S8jO6D+mW8HI+pccXQSHFpuljBIA= 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.206.16.166 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: zesmtpsz5t1775490611t88c1fc21 X-QQ-Originating-IP: O33DW5ODZGKddTF7xRQ7Ge2Lc2xYEoUlTwU0BzXScsQ= Received: from [192.168.30.32] ( [116.234.14.100]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 06 Apr 2026 23:50:09 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 13515617376988754846 EX-QQ-RecipientCnt: 10 From: Xilin Wu Date: Mon, 06 Apr 2026 23:50:01 +0800 Subject: [PATCH 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: <20260406-clk-pwm-gpio-v1-1-40d2f3a20aff@radxa.com> References: <20260406-clk-pwm-gpio-v1-0-40d2f3a20aff@radxa.com> In-Reply-To: <20260406-clk-pwm-gpio-v1-0-40d2f3a20aff@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/G02pJDJmXr+lpz6zwPig603O36Y01rG92GuQbLL22/F3exIhDM +ZqJnM97ihlYRDjYpAVU2RRiGeYy16Ze+2pWKkezBxWJpAhDFycAjARfilGhnMfXbY9Y5qecXqP bpyVtt9TtUtui1+Z2vj5BE1h+3tonSojQ2Nl8f3PZayTn729HX3u4uSXczjWC8xJPS4Verb445d gXX4A 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: Ob+yvR0lmunCxlEdJ5yqfcfe8D1O7uVqXJxhN3Hhst+k/5IQeBIBSRM3 +3E2ec4Wc1MlrG32fFTxY3WUlFtXsOcmUyBH1eShzav/1q0vFc9LJtvujKXsJKMCXk4RkbN p4kgrmLqTRTTn8qYPKoRv5mzJeZI71rL7Wi/lIN73AWDhP4Vk7qFY1EX4H1cDW5kiBU8jUQ M2c+nmM7qNb3Q3U2KcAcdlhSStCvXYu+KWU4dc+2vVcl6KgkolxVRJHpr6JGRAa0nMGxlIy Jq37eEkjz3nmOZ49UfS9bs24pmUFKh23V6+hLKsaMEVY4zenBrNzDRaF97r8IBygcTwKbjA PON12jYLZYkBu/0jJeZm1x/tEvQBDO4GgBRVM/zGS4MOyKEYRbf6Xk9HJasdrcdqChsA9w6 +gclveBuOMOPqq7Q+8wc8Znboi3/YTWAo3c3i4QvG3vVaz+mujYO2gDkSbtgpLz3UmUgDX8 HwS1UeW731icaVKqclJIZ1D3cPinN0mRtNvrqF5K7d0lbZ6ebpMmzXI6MmnUnKy/ruAORQl TSaoJYNg0zzL323Zbp2Xhc568VXFK+UIwhA+dqu6Wq/Bv2s3xdwCVwgSOLuqQNFv2f9sc4L MoXQhHCuHruYVfcIAUBTq2Gk3bfwt2tWpPTssqSQvh/0WEYBENK05ylu+q3sRNVcD2CaXuU h2qipZP6kBzkvCkQuNoVSKIiMMXg3giiUvMmyWsXJDrAG32Mot3cUmnNvhjg5/uw0Y+sdnB 6jAmsZ7g5x8oNXKR1FN742ULKglIjP8sBTKLA/nHYosk9FJjWRM7vP9vW+6eVsXQoInOr7g vwdG7Y+HCXxE52sD/A/L22PWKBw1yn2/ZzTTTm2nK8JOLaOCGMCb9mSjwOBN5bIFVt1Goek g671OtWHJcdBAJR7gAPSUrLTju8vFvSOX6xexrOKrBdsQJJrea1JDclGeTHD4vFjWeQHakX H9T8ZAikdH60rzfzly0H9wfXzBavhQduqvJiA3EweqTPMticSePv9gcxV1EaQzwkVp020ig VuKU+cCdgKOEG8dM4BIZKWfwCeu4vzcVctX8lIs7xw0/rvkpVIvBAZfhFvF9qErQFQ58nWp nKcX6iTvtlNgiCNMz5YtJE/AC2sRysPqQ== X-QQ-XMRINFO: Mp0Kj//9VHAxzExpfF+O8yhSrljjwrznVg== 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 Acked-by: Conor Dooley --- 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 smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142]) (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 3C75B288C81; Mon, 6 Apr 2026 15:51:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=18.194.254.142 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775490669; cv=none; b=KBXoCyXPRBH4z7daLNAsYx5bXpIaaSD+o/0kzerON8nn6E8aMV9c8nxdTpfZ+9VRf0y4i0lnXKlYBxMg6/GpH6D5NxuPCmptqozvWrR+yCxsabQOSw6+IJGS7L/OsnAtOfgTyR9P/k/DrJ3q+iJy0JyggqxrBHvb5AcDkpRK6r0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775490669; c=relaxed/simple; bh=UBTu/kKo70Jh0+IVyBq78WBUn6kXsLDznnaFIyQAqI8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=L/wT/45RQghYHfCqhTZYwwxJcHy1e/I/y0HOEI1AWSxzwvHvmyJVlDvxyApNg9rZkbCoc3Iln1NMzHVEBDNp8JUJueUOR6FkKGcb2Q7WHbdbQaZccE7noL+C93WzIpADMXtWTaVzxH5UeaZ104Z7/F6w+H4nLWCQEYuxqkskFzo= 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=18.194.254.142 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: zesmtpsz5t1775490614t2a71ab47 X-QQ-Originating-IP: +bci2OFNhnZPPCdhCYxE7IGxHtXRITc9jF3kaO8N6T4= Received: from [192.168.30.32] ( [116.234.14.100]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 06 Apr 2026 23:50:12 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 7770315344713574114 EX-QQ-RecipientCnt: 10 From: Xilin Wu Date: Mon, 06 Apr 2026 23:50:02 +0800 Subject: [PATCH 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: <20260406-clk-pwm-gpio-v1-2-40d2f3a20aff@radxa.com> References: <20260406-clk-pwm-gpio-v1-0-40d2f3a20aff@radxa.com> In-Reply-To: <20260406-clk-pwm-gpio-v1-0-40d2f3a20aff@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=4950; i=sophon@radxa.com; h=from:subject:message-id; bh=UBTu/kKo70Jh0+IVyBq78WBUn6kXsLDznnaFIyQAqI8=; b=owGbwMvMwCVmdFg0fe08Iz/G02pJDJmXr+lNF2Lb4XthzqHvhh9Mf5VMU/7i73nvH1eTV/SmX x+4Eg6e6ihlYRDjYpAVU2RRiGeYy16Ze+2pWKkezBxWJpAhDFycAjCRzGJGhj1z9/yXs5d5kSh4 PCo8+l3Bh2mVqr2vlbxN+pZelroe48vwT1na4oy9VcPOnyJpb9h2iFSxXS73n7mn+MWvV/tnSTR P4gQA 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: OCBj5Amv9vLxNlhcrkcEq3PDWYL5zw8G+iXyAhx/HJ4uEV9oDi50Ayno WBCbJhiRUG6/dr4eq9I+15/6WpibUrzFzm7lKgKaNnDFTmVGeVUQVgxwyOHP3sMuWqsjZ/N aF5D6ZecEwngi8l8ecZkK4eN94zP/0cs/RvETlrLFcxQkH2aI9I5OHlqfxzeEUOYiatYrp5 CKHGaWvmaS5RmG/GdAIpLKdCwU8sawJ9NEHFqjwlPoUwlCP4dWzeYzL1fmWpuF3DnyhnByp Y6q/4kZj9BLBUPa9EYuxqoovBXW64aE9WD3FK3O8TYLGaVXbaJ88gCeRQnjbOR/9Yf+FgOa 1FfUkXNkHYj04RKxF2+EYT35jvL1d40IWCVyC+y8Mjrr5Kvv1cw/IsodE99UtSFCQ/O4/Zq aJIwR9zu404Co0JGZzxtLUSmCH5oaybnvbH7yIcigUnRoctUPYQAScMg0JamhTljX3F9rJ9 JE+z+X/EfF3H1SbNWY+mT4xdNtBO2GHH16sbwNxovPTaVJo37R7+GR3o4SOkSYnd2JpgjD2 l/MTdaW0QZJZ3HDY8DmSt8/PluRaYX6D8uG71Bhv/UGXYwEw8mbmXFFQevJpVteSxjM8x7A T9mOGqrhkYV3l+p2HztTSQ1dkRvFZPkvljpBPXzHjzIXRikaLnlp7RP/MKYTzLaYhL1TYlN tJ3ZRa3W3PZp3I8tl4hgru5nbCdiF02Jt0sF+Y6jZilT5q+3tGR+rt6jmECfNVrfj5bAywX Jn2nPWZmTqrffVxkgJmL+tphZXI4B5LmNJHQBpV1PIUuLYSCRJz8UNLUHwEfXDu1GM/ERbI /TXpviH+t2Td98hiPcfO0lgHNt1Knx7XL6k3LTmskbNZGIzckrkubpxBi2m0xazBR75OR7E JZ4++PxXPlvHAkO8G631V3P/pYBj3aQ0WJD/AT57wccXj8gWXgfDVH9tAv183q4+ULSSdNn oWxkBTg2TqLo9ZgTNEiCylUZZ3Kut5vPAA2rOY/0jRqqC4xeucDJ022oUJcqEDM50jpbGbm Ugf8CbokTaj7CTZIABooAQY6yTpql0OXmTPSi5p8q0mV7ykrC4fiqUBvRw8oIHUKKyVsIRs N02p75wCzDDGvUPpl578hc= X-QQ-XMRINFO: MSVp+SPm3vtSI1QTLgDHQqIV1w2oNKDqfg== 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 | 72 ++++++++++++++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c index f8f5af57acba..99821fae54e7 100644 --- a/drivers/pwm/pwm-clk.c +++ b/drivers/pwm/pwm-clk.c @@ -10,12 +10,15 @@ * Limitations: * - 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. - * - When the PWM is disabled, the clock will be disabled as well, - * line state will depend on the clock. * - 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 +28,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 +54,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) { + pinctrl_select_state(pcchip->pinctrl, pcchip->pins_gpio); + gpiod_direction_output(pcchip->gpiod, gpio_value); + } + 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 +128,35 @@ 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"); + chip->ops =3D &pwm_clk_ops; =20 ret =3D pwmchip_add(chip); --=20 2.53.0