Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2220205/?format=api
{ "id": 2220205, "url": "http://patchwork.ozlabs.org/api/patches/2220205/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260406-clk-pwm-gpio-v1-2-40d2f3a20aff@radxa.com/", "project": { "id": 38, "url": "http://patchwork.ozlabs.org/api/projects/38/?format=api", "name": "Linux PWM development", "link_name": "linux-pwm", "list_id": "linux-pwm.vger.kernel.org", "list_email": "linux-pwm@vger.kernel.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260406-clk-pwm-gpio-v1-2-40d2f3a20aff@radxa.com>", "list_archive_url": null, "date": "2026-04-06T15:50:02", "name": "[2/2] pwm: clk-pwm: add GPIO and pinctrl support for constant output levels", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "b75f6ac7a1600a4301de853bbe911243c6d5552b", "submitter": { "id": 90715, "url": "http://patchwork.ozlabs.org/api/people/90715/?format=api", "name": "Xilin Wu", "email": "sophon@radxa.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/linux-pwm/patch/20260406-clk-pwm-gpio-v1-2-40d2f3a20aff@radxa.com/mbox/", "series": [ { "id": 498878, "url": "http://patchwork.ozlabs.org/api/series/498878/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pwm/list/?series=498878", "date": "2026-04-06T15:50:00", "name": "pwm: clk-pwm: Add GPIO support for constant output levels", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/498878/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2220205/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2220205/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-pwm+bounces-8497-incoming=patchwork.ozlabs.org@vger.kernel.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "linux-pwm@vger.kernel.org" ], "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-pwm+bounces-8497-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=18.194.254.142", "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=radxa.com", "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=radxa.com" ], "Received": [ "from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fqDND5pdyz1yFt\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 07 Apr 2026 01:51:56 +1000 (AEST)", "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 7087C3024C81\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 6 Apr 2026 15:51:12 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id A2F332D594F;\n\tMon, 6 Apr 2026 15:51:09 +0000 (UTC)", "from smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 3C75B288C81;\n\tMon, 6 Apr 2026 15:51:05 +0000 (UTC)", "from [192.168.30.32] ( [116.234.14.100])\n\tby bizesmtp.qq.com (ESMTP) with\n\tid ; Mon, 06 Apr 2026 23:50:12 +0800 (CST)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775490669; cv=none;\n b=KBXoCyXPRBH4z7daLNAsYx5bXpIaaSD+o/0kzerON8nn6E8aMV9c8nxdTpfZ+9VRf0y4i0lnXKlYBxMg6/GpH6D5NxuPCmptqozvWrR+yCxsabQOSw6+IJGS7L/OsnAtOfgTyR9P/k/DrJ3q+iJy0JyggqxrBHvb5AcDkpRK6r0=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775490669; c=relaxed/simple;\n\tbh=UBTu/kKo70Jh0+IVyBq78WBUn6kXsLDznnaFIyQAqI8=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=L/wT/45RQghYHfCqhTZYwwxJcHy1e/I/y0HOEI1AWSxzwvHvmyJVlDvxyApNg9rZkbCoc3Iln1NMzHVEBDNp8JUJueUOR6FkKGcb2Q7WHbdbQaZccE7noL+C93WzIpADMXtWTaVzxH5UeaZ104Z7/F6w+H4nLWCQEYuxqkskFzo=", "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=radxa.com;\n spf=pass smtp.mailfrom=radxa.com; arc=none smtp.client-ip=18.194.254.142", "X-QQ-mid": "zesmtpsz5t1775490614t2a71ab47", "X-QQ-Originating-IP": "+bci2OFNhnZPPCdhCYxE7IGxHtXRITc9jF3kaO8N6T4=", "X-QQ-SSF": "0000000000000000000000000000000", "X-QQ-GoodBg": "0", "X-BIZMAIL-ID": "7770315344713574114", "EX-QQ-RecipientCnt": "10", "From": "Xilin Wu <sophon@radxa.com>", "Date": "Mon, 06 Apr 2026 23:50:02 +0800", "Subject": "[PATCH 2/2] pwm: clk-pwm: add GPIO and pinctrl support for\n constant output levels", "Precedence": "bulk", "X-Mailing-List": "linux-pwm@vger.kernel.org", "List-Id": "<linux-pwm.vger.kernel.org>", "List-Subscribe": "<mailto:linux-pwm+subscribe@vger.kernel.org>", "List-Unsubscribe": "<mailto:linux-pwm+unsubscribe@vger.kernel.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "7bit", "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?= <ukleinek@kernel.org>,\n Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,\n Conor Dooley <conor+dt@kernel.org>, Nikita Travkin <nikita@trvn.ru>", "Cc": "linux-pwm@vger.kernel.org, devicetree@vger.kernel.org,\n linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org,\n Xilin Wu <sophon@radxa.com>", "X-Mailer": "b4 0.15.1", "X-Developer-Signature": "v=1; a=openpgp-sha256; l=4950; i=sophon@radxa.com;\n h=from:subject:message-id; bh=UBTu/kKo70Jh0+IVyBq78WBUn6kXsLDznnaFIyQAqI8=;\n b=owGbwMvMwCVmdFg0fe08Iz/G02pJDJmXr+lNF2Lb4XthzqHvhh9Mf5VMU/7i73nvH1eTV/SmX\n x+4Eg6e6ihlYRDjYpAVU2RRiGeYy16Ze+2pWKkezBxWJpAhDFycAjCRzGJGhj1z9/yXs5d5kSh4\n PCo8+l3Bh2mVqr2vlbxN+pZelroe48vwT1na4oy9VcPOnyJpb9h2iFSxXS73n7mn+MWvV/tnSTR\n P4gQA", "X-Developer-Key": "i=sophon@radxa.com; a=openpgp;\n fpr=205F009D07796DD6E516752E32C31567AD9E324E", "X-QQ-SENDSIZE": "520", "Feedback-ID": "zesmtpsz:radxa.com:qybglogicsvrsz:qybglogicsvrsz3b-0", "X-QQ-XMAILINFO": "OCBj5Amv9vLxNlhcrkcEq3PDWYL5zw8G+iXyAhx/HJ4uEV9oDi50Ayno\n\tWBCbJhiRUG6/dr4eq9I+15/6WpibUrzFzm7lKgKaNnDFTmVGeVUQVgxwyOHP3sMuWqsjZ/N\n\taF5D6ZecEwngi8l8ecZkK4eN94zP/0cs/RvETlrLFcxQkH2aI9I5OHlqfxzeEUOYiatYrp5\n\tCKHGaWvmaS5RmG/GdAIpLKdCwU8sawJ9NEHFqjwlPoUwlCP4dWzeYzL1fmWpuF3DnyhnByp\n\tY6q/4kZj9BLBUPa9EYuxqoovBXW64aE9WD3FK3O8TYLGaVXbaJ88gCeRQnjbOR/9Yf+FgOa\n\t1FfUkXNkHYj04RKxF2+EYT35jvL1d40IWCVyC+y8Mjrr5Kvv1cw/IsodE99UtSFCQ/O4/Zq\n\taJIwR9zu404Co0JGZzxtLUSmCH5oaybnvbH7yIcigUnRoctUPYQAScMg0JamhTljX3F9rJ9\n\tJE+z+X/EfF3H1SbNWY+mT4xdNtBO2GHH16sbwNxovPTaVJo37R7+GR3o4SOkSYnd2JpgjD2\n\tl/MTdaW0QZJZ3HDY8DmSt8/PluRaYX6D8uG71Bhv/UGXYwEw8mbmXFFQevJpVteSxjM8x7A\n\tT9mOGqrhkYV3l+p2HztTSQ1dkRvFZPkvljpBPXzHjzIXRikaLnlp7RP/MKYTzLaYhL1TYlN\n\ttJ3ZRa3W3PZp3I8tl4hgru5nbCdiF02Jt0sF+Y6jZilT5q+3tGR+rt6jmECfNVrfj5bAywX\n\tJn2nPWZmTqrffVxkgJmL+tphZXI4B5LmNJHQBpV1PIUuLYSCRJz8UNLUHwEfXDu1GM/ERbI\n\t/TXpviH+t2Td98hiPcfO0lgHNt1Knx7XL6k3LTmskbNZGIzckrkubpxBi2m0xazBR75OR7E\n\tJZ4++PxXPlvHAkO8G631V3P/pYBj3aQ0WJD/AT57wccXj8gWXgfDVH9tAv183q4+ULSSdNn\n\toWxkBTg2TqLo9ZgTNEiCylUZZ3Kut5vPAA2rOY/0jRqqC4xeucDJ022oUJcqEDM50jpbGbm\n\tUgf8CbokTaj7CTZIABooAQY6yTpql0OXmTPSi5p8q0mV7ykrC4fiqUBvRw8oIHUKKyVsIRs\n\tN02p75wCzDDGvUPpl578hc=", "X-QQ-XMRINFO": "MSVp+SPm3vtSI1QTLgDHQqIV1w2oNKDqfg==", "X-QQ-RECHKSPAM": "0" }, "content": "The clk-pwm driver cannot guarantee a defined output level when the\nPWM is disabled or when 0%/100% duty cycle is requested, because the\npin state when the clock is stopped is hardware-dependent.\n\nAdd optional GPIO and pinctrl support: when a GPIO descriptor and\npinctrl states (\"default\" for clock mux, \"gpio\" for GPIO mode) are\nprovided in the device tree, the driver switches the pin to GPIO mode\nand drives the appropriate level for disabled/0%/100% states. For\nnormal PWM output, the pin is switched back to its clock function mux.\n\nIf no GPIO is provided, the driver falls back to the original\nclock-only behavior.\n\nSigned-off-by: Xilin Wu <sophon@radxa.com>\n---\n drivers/pwm/pwm-clk.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++-----\n 1 file changed, 66 insertions(+), 6 deletions(-)", "diff": "diff --git a/drivers/pwm/pwm-clk.c b/drivers/pwm/pwm-clk.c\nindex f8f5af57acba..99821fae54e7 100644\n--- a/drivers/pwm/pwm-clk.c\n+++ b/drivers/pwm/pwm-clk.c\n@@ -10,12 +10,15 @@\n * Limitations:\n * - Due to the fact that exact behavior depends on the underlying\n * clock driver, various limitations are possible.\n- * - Underlying clock may not be able to give 0% or 100% duty cycle\n- * (constant off or on), exact behavior will depend on the clock.\n- * - When the PWM is disabled, the clock will be disabled as well,\n- * line state will depend on the clock.\n * - The clk API doesn't expose the necessary calls to implement\n * .get_state().\n+ *\n+ * Optionally, a GPIO descriptor and pinctrl states (\"default\" and\n+ * \"gpio\") can be provided. When a constant output level is needed\n+ * (0% duty, 100% duty, or disabled), the driver switches the pin to\n+ * GPIO mode and drives the appropriate level. For normal PWM output\n+ * the pin is switched back to its clock function mux. If no GPIO is\n+ * provided, the driver falls back to the original clock-only behavior.\n */\n \n #include <linux/kernel.h>\n@@ -25,11 +28,17 @@\n #include <linux/of.h>\n #include <linux/platform_device.h>\n #include <linux/clk.h>\n+#include <linux/gpio/consumer.h>\n+#include <linux/pinctrl/consumer.h>\n #include <linux/pwm.h>\n \n struct pwm_clk_chip {\n \tstruct clk *clk;\n \tbool clk_enabled;\n+\tstruct pinctrl *pinctrl;\n+\tstruct pinctrl_state *pins_default; /* clock function mux */\n+\tstruct pinctrl_state *pins_gpio; /* GPIO mode */\n+\tstruct gpio_desc *gpiod;\n };\n \n static inline struct pwm_clk_chip *to_pwm_clk_chip(struct pwm_chip *chip)\n@@ -45,14 +54,36 @@ static int pwm_clk_apply(struct pwm_chip *chip, struct pwm_device *pwm,\n \tu32 rate;\n \tu64 period = state->period;\n \tu64 duty_cycle = state->duty_cycle;\n+\tbool constant_level = false;\n+\tint gpio_value = 0;\n \n \tif (!state->enabled) {\n-\t\tif (pwm->state.enabled) {\n+\t\tconstant_level = true;\n+\t\tgpio_value = 0;\n+\t} else if (state->duty_cycle == 0) {\n+\t\tconstant_level = true;\n+\t\tgpio_value = (state->polarity == PWM_POLARITY_INVERSED) ? 1 : 0;\n+\t} else if (state->duty_cycle >= state->period) {\n+\t\tconstant_level = true;\n+\t\tgpio_value = (state->polarity == PWM_POLARITY_INVERSED) ? 0 : 1;\n+\t}\n+\n+\tif (constant_level) {\n+\t\tif (pcchip->gpiod) {\n+\t\t\tpinctrl_select_state(pcchip->pinctrl, pcchip->pins_gpio);\n+\t\t\tgpiod_direction_output(pcchip->gpiod, gpio_value);\n+\t\t}\n+\t\tif (pcchip->clk_enabled) {\n \t\t\tclk_disable(pcchip->clk);\n \t\t\tpcchip->clk_enabled = false;\n \t\t}\n \t\treturn 0;\n-\t} else if (!pwm->state.enabled) {\n+\t}\n+\n+\tif (pcchip->gpiod)\n+\t\tpinctrl_select_state(pcchip->pinctrl, pcchip->pins_default);\n+\n+\tif (!pcchip->clk_enabled) {\n \t\tret = clk_enable(pcchip->clk);\n \t\tif (ret)\n \t\t\treturn ret;\n@@ -97,6 +128,35 @@ static int pwm_clk_probe(struct platform_device *pdev)\n \t\treturn dev_err_probe(&pdev->dev, PTR_ERR(pcchip->clk),\n \t\t\t\t \"Failed to get clock\\n\");\n \n+\tpcchip->pinctrl = devm_pinctrl_get(&pdev->dev);\n+\tif (IS_ERR(pcchip->pinctrl)) {\n+\t\tret = PTR_ERR(pcchip->pinctrl);\n+\t\tpcchip->pinctrl = NULL;\n+\t\tif (ret == -EPROBE_DEFER)\n+\t\t\treturn ret;\n+\t} else {\n+\t\tpcchip->pins_default = pinctrl_lookup_state(pcchip->pinctrl,\n+\t\t\t\t\t\t\t PINCTRL_STATE_DEFAULT);\n+\t\tpcchip->pins_gpio = pinctrl_lookup_state(pcchip->pinctrl,\n+\t\t\t\t\t\t\t \"gpio\");\n+\t\tif (IS_ERR(pcchip->pins_default) || IS_ERR(pcchip->pins_gpio))\n+\t\t\tpcchip->pinctrl = NULL;\n+\t}\n+\n+\t/*\n+\t * Switch to GPIO pinctrl state before requesting the GPIO.\n+\t * The driver core has already applied the \"default\" state, which\n+\t * muxes the pin to the clock function and claims it. We must\n+\t * release that claim first so that gpiolib can request the pin.\n+\t */\n+\tif (pcchip->pinctrl)\n+\t\tpinctrl_select_state(pcchip->pinctrl, pcchip->pins_gpio);\n+\n+\tpcchip->gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, GPIOD_ASIS);\n+\tif (IS_ERR(pcchip->gpiod))\n+\t\treturn dev_err_probe(&pdev->dev, PTR_ERR(pcchip->gpiod),\n+\t\t\t\t \"Failed to get gpio\\n\");\n+\n \tchip->ops = &pwm_clk_ops;\n \n \tret = pwmchip_add(chip);\n", "prefixes": [ "2/2" ] }