* [PATCH v9 0/2] A proposal to add a gpio-enabled clock driver.
@ 2026-10-15 14:22 Vyacheslav Yurkov via B4 Relay
2026-10-15 14:22 ` [PATCH v9 1/2] dt-bindings: gpio-enabled-clock: Add a new binding Vyacheslav Yurkov via B4 Relay
2026-10-15 14:22 ` [PATCH v9 2/2] clk: Add gpio-enabled clock driver Vyacheslav Yurkov via B4 Relay
0 siblings, 2 replies; 4+ messages in thread
From: Vyacheslav Yurkov via B4 Relay @ 2026-10-15 14:22 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Brian Masney, Brian Masney,
Jerome Brunet, Jyri Sarha
Cc: linux-kernel, linux-clk, devicetree, Vyacheslav Yurkov,
Vyacheslav Yurkov
A gpio-enabled clock represents an input clock, which state is determined
by a GPIO signal. It's similar to a gated-fixed-clock, but GPIO direction
is inverted. Consumers can use the output clock to wait until the clock
is ready and only then initialize / access dependent peripherals.
The usage example for such a driver is when peripherals depend on PLLs in
a FPGA, which can't be directly accessed by the CPU, but need a GPIO pin
to check whether clock is actually usable. E.g. some of the IPs might not
have a proper split between registers and IP core, which means that if an
external clock and/or PLL lock is missing and one tries to access the
registers, the response never comes, thus the CPU stalls.
Signed-off-by: Vyacheslav Yurkov <uvv.mail@gmail.com>
Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
---
Changes in v9:
- Changed wordking from "locked" to "enabled" to be more generic
- Use a separate DT schema file similar to other clock drivers
- Add a timeout for polling in enable()/prepare()
- Depending on whether GPIO can sleep or not use prepare() or enable()
set of ops respectively.
- Decouple the implementation from exisiting drivers
- Link to v8: https://lore.kernel.org/r/20260927-feature-clock-guard-v8-0-630938e302a1@bruker.com
Changes in v8:
- Fix return value of clk_gpio_locked_prepare()
- Link to v7: https://lore.kernel.org/r/20260927-feature-clock-guard-v7-0-8dd19568d9a2@bruker.com
Changes in v7:
- Fix compatibility strings and schema errors.
- Update GPIO pin name
- Link to v6: https://lore.kernel.org/r/20260927-feature-clock-guard-v6-0-007983b13ec2@bruker.com
Changes in v6:
- Debug messages dropped.
- The new driver is now an extension of exising clk-gpio drivers.
- The controller doesn't enable the parent clock, the consumer is
supposed to do that instead.
- Link to v5: https://lore.kernel.org/r/20260915-feature-clock-guard-v5-0-42ab5dc3a6aa@bruker.com
Changes in v5:
- Use existing DT binding with an additional property instead of adding
a new one
- The driver is simplified in a way that it represents the actual HW
desgin without additional unrelated constructs
- Aggregation is removed, now it's one clock input, one clock output
- Link to v4: https://lore.kernel.org/r/20260726-feature-clock-guard-v4-0-e9c8b372b71c@bruker.com
Changes in v4:
- Removed driver specifics from DT binding
- Link to v3: https://lore.kernel.org/r/20260603-feature-clock-guard-v3-0-01cca0aa04a5@bruker.com
Changes in v3:
- Removed unnecessary dt bindings
- Improved HW description and commit messages
- Link to v2: https://lore.kernel.org/r/20260510-feature-clock-guard-v2-0-6c25458d5340@bruker.com
Changes in v2:
- Renamed to clk-gpio-locked to express intent.
- Provide enable() / is_enabled() operations so the clock behaves as
expected
- Fixed DTS errors / warnings
- Link to v1: https://lore.kernel.org/r/20260318-feature-clock-guard-v1-0-6137cb4084b7@bruker.com
---
Vyacheslav Yurkov (2):
dt-bindings: gpio-enabled-clock: Add a new binding
clk: Add gpio-enabled clock driver
.../bindings/clock/gpio-enabled-clock.yaml | 53 +++++++
drivers/clk/clk-gpio.c | 161 +++++++++++++++++++++
2 files changed, 214 insertions(+)
---
base-commit: 0fcb05b72344f40806cbe810de8872f1698bf053
change-id: 20260318-feature-clock-guard-f20a2c35b965
Best regards,
--
Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v9 1/2] dt-bindings: gpio-enabled-clock: Add a new binding
2026-10-15 14:22 [PATCH v9 0/2] A proposal to add a gpio-enabled clock driver Vyacheslav Yurkov via B4 Relay
@ 2026-10-15 14:22 ` Vyacheslav Yurkov via B4 Relay
2026-10-15 19:58 ` Rob Herring (Arm)
2026-10-15 14:22 ` [PATCH v9 2/2] clk: Add gpio-enabled clock driver Vyacheslav Yurkov via B4 Relay
1 sibling, 1 reply; 4+ messages in thread
From: Vyacheslav Yurkov via B4 Relay @ 2026-10-15 14:22 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Brian Masney, Brian Masney,
Jerome Brunet, Jyri Sarha
Cc: linux-kernel, linux-clk, devicetree, Vyacheslav Yurkov,
Vyacheslav Yurkov
From: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
Add the binding for gpio-enabled-clock. A GPIO-enabled clock provider
exposes a clock (can be any type of clock) whose availability depends on
a GPIO status signal.
Some hardware designs provide fixed-frequency clocks generated outside
software control, such as by FPGA-resident PLLs. While the clock rate is
fixed, a separate GPIO signal indicates whether the clock source is enabled
and producing a valid output.
Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
---
.../bindings/clock/gpio-enabled-clock.yaml | 53 ++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/gpio-enabled-clock.yaml b/Documentation/devicetree/bindings/clock/gpio-enabled-clock.yaml
new file mode 100644
index 000000000000..3ab6fa9dd412
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/gpio-enabled-clock.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/gpio-enabled-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPIO Enabled Clock
+
+maintainers:
+ - Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
+
+properties:
+ compatible:
+ const: gpio-enabled-clock
+
+ clocks:
+ maxItems: 1
+
+ "#clock-cells":
+ const: 0
+
+ clock-output-names:
+ maxItems: 1
+
+ enabled-gpios:
+ description: GPIO that indicates whether the clock is enabled or disabled.
+ maxItems: 1
+
+ poll-timeout-us:
+ description: Timeout in microseconds for waiting for a GPIO signal.
+ default: 10
+ minimum: 10
+ maximum: 1000
+
+required:
+ - compatible
+ - clocks
+ - "#clock-cells"
+ - enabled-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ clock {
+ compatible = "gpio-enabled-clock";
+ #clock-cells = <0>;
+ clocks = <&pll>;
+ enabled-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+ poll-timeout-us = <20>;
+ };
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v9 2/2] clk: Add gpio-enabled clock driver
2026-10-15 14:22 [PATCH v9 0/2] A proposal to add a gpio-enabled clock driver Vyacheslav Yurkov via B4 Relay
2026-10-15 14:22 ` [PATCH v9 1/2] dt-bindings: gpio-enabled-clock: Add a new binding Vyacheslav Yurkov via B4 Relay
@ 2026-10-15 14:22 ` Vyacheslav Yurkov via B4 Relay
1 sibling, 0 replies; 4+ messages in thread
From: Vyacheslav Yurkov via B4 Relay @ 2026-10-15 14:22 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Brian Masney, Brian Masney,
Jerome Brunet, Jyri Sarha
Cc: linux-kernel, linux-clk, devicetree, Vyacheslav Yurkov,
Vyacheslav Yurkov
From: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
A gpio-enabled clock exposes a clock, which status is determined by a
GPIO signal. The common use-case is a FPGA-assisted clocking design
where peripheral clocks are generated by FPGA PLLs that are outside
CPU control, with clock-valid/PLL-lock status exposed through GPIO signals.
Consumers can use the output clock to wait until the input clock is enabled
and only then initialize dependent peripherals.
Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
---
drivers/clk/clk-gpio.c | 161 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 161 insertions(+)
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
index 9099c57e2715..c968c1d4cb1c 100644
--- a/drivers/clk/clk-gpio.c
+++ b/drivers/clk/clk-gpio.c
@@ -15,6 +15,7 @@
#include <linux/gpio/consumer.h>
#include <linux/err.h>
#include <linux/device.h>
+#include <linux/iopoll.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
@@ -241,6 +242,166 @@ static struct platform_driver gpio_clk_driver = {
};
builtin_platform_driver(gpio_clk_driver);
+/**
+ * DOC: Clock which status is determined by a GPIO signal
+ * Traits of this clock:
+ * prepare - clk_prepare (is_prepared) checks for a sleeping gpio
+ * enable - clk_enable (is_enabled) checks for a non-sleeping gpio
+ */
+
+/**
+ * struct clk_gpio_enabled - gpio enabled clock
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @gpiod: gpio descriptor
+ * @timeout_us: timeout that is used to get a GPIO value
+ *
+ * Clock, which status is determined by a GPIO signal.
+ *
+ * Implements .enable, .is_enabled or .prepare, .is_prepared
+ */
+struct clk_gpio_enabled {
+ struct clk_hw hw;
+ struct gpio_desc *gpiod;
+ u32 timeout_us;
+};
+
+#define to_clk_gpio_enabled(_hw) container_of(_hw, struct clk_gpio_enabled, hw)
+#define GPIO_ENABLED_TIMEOUT_MIN 10
+#define GPIO_ENABLED_TIMEOUT_MAX 1000
+#define GPIO_ENABLED_TIMEOUT_DEFAULT 10
+
+static int clk_gpio_enabled_sleeping_is_prepared(struct clk_hw *hw)
+{
+ struct clk_gpio_enabled *clk = to_clk_gpio_enabled(hw);
+
+ return gpiod_get_value_cansleep(clk->gpiod) > 0;
+}
+
+/* We can't prepare the clock, but the Common Clock Framework calls only
+ * prepare() not is_prepared(), therefore we fallback on the actual GPIO value.
+ * The function clk_gpio_enabled_sleeping_is_prepared() returns the raw boolean
+ * GPIO status (1 if enabled, 0 if not enabled), but the prepare callback
+ * clk_core_prepare() expects 0 for success and non-zero integer for failure.
+ */
+static int clk_gpio_enabled_sleeping_prepare(struct clk_hw *hw)
+{
+ struct clk_gpio_enabled *clk = to_clk_gpio_enabled(hw);
+ int value = 0;
+
+ readx_poll_timeout(gpiod_get_value_cansleep, clk->gpiod, value,
+ value != 0, 10, clk->timeout_us);
+ if (value == 1)
+ return 0;
+
+ return -EBUSY;
+}
+
+static const struct clk_ops clk_gpio_enabled_sleeping_ops = {
+ .prepare = clk_gpio_enabled_sleeping_prepare,
+ .is_prepared = clk_gpio_enabled_sleeping_is_prepared,
+};
+
+static int clk_gpio_enabled_is_enabled(struct clk_hw *hw)
+{
+ struct clk_gpio_enabled *clk = to_clk_gpio_enabled(hw);
+
+ return gpiod_get_value(clk->gpiod) > 0;
+}
+
+/* We can't enable the clock, but the Common Clock Framework calls only
+ * enable() not is_enabled(), therefore we fallback on the actual GPIO value.
+ * The function clk_gpio_enabled_is_enabled() returns the raw boolean
+ * GPIO status (1 if enabled, 0 if not enabled), but the enable callback
+ * clk_core_enable() expects 0 for success and non-zero integer for failure.
+ */
+static int clk_gpio_enabled_enable(struct clk_hw *hw)
+{
+ struct clk_gpio_enabled *clk = to_clk_gpio_enabled(hw);
+ int value = 0;
+
+ readx_poll_timeout_atomic(gpiod_get_value, clk->gpiod, value,
+ value != 0, 10, clk->timeout_us);
+
+ /* If the reading timed out or return an error,
+ * it means the clock is not ready
+ */
+ if (value == 1)
+ return 0;
+
+ return -EBUSY;
+}
+
+static const struct clk_ops clk_gpio_enabled_ops = {
+ .enable = clk_gpio_enabled_enable,
+ .is_enabled = clk_gpio_enabled_is_enabled,
+};
+
+static int gpio_enabled_clk_driver_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct clk_gpio_enabled *clk;
+ const char *clk_name;
+ const struct clk_ops *ops;
+ const struct clk_parent_data gpio_parent_data[] = {
+ { .index = 0 },
+ };
+ u32 timeout_us = GPIO_ENABLED_TIMEOUT_DEFAULT;
+ int ret = 0;
+
+ clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return -ENOMEM;
+
+ clk->gpiod = devm_gpiod_get(dev, "enabled", GPIOD_IN);
+ if (IS_ERR(clk->gpiod))
+ return dev_err_probe(dev, PTR_ERR(clk->gpiod),
+ "Can't get enabled GPIO property\n");
+
+ ret = device_property_read_string(dev, "clock-output-names", &clk_name);
+ if (ret)
+ clk_name = fwnode_get_name(dev->fwnode);
+
+ device_property_read_u32(dev, "poll-timeout-us", &timeout_us);
+ if (timeout_us < GPIO_ENABLED_TIMEOUT_MIN ||
+ timeout_us > GPIO_ENABLED_TIMEOUT_MAX)
+ return dev_err_probe(dev, -EINVAL,
+ "poll-timeout-us is out of range [%u, %u]\n",
+ GPIO_ENABLED_TIMEOUT_MIN,
+ GPIO_ENABLED_TIMEOUT_MAX);
+ clk->timeout_us = timeout_us;
+
+ if (gpiod_cansleep(clk->gpiod))
+ ops = &clk_gpio_enabled_sleeping_ops;
+ else
+ ops = &clk_gpio_enabled_ops;
+
+ clk->hw.init = CLK_HW_INIT_PARENTS_DATA
+ (clk_name, gpio_parent_data, ops, 0);
+
+ /* register the clock */
+ ret = devm_clk_hw_register(dev, &clk->hw);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to register clock\n");
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &clk->hw);
+}
+
+static const struct of_device_id gpio_enabled_clk_match_table[] = {
+ { .compatible = "gpio-enabled-clock" },
+ { }
+};
+
+static struct platform_driver gpio_enabled_clk_driver = {
+ .probe = gpio_enabled_clk_driver_probe,
+ .driver = {
+ .name = "gpio-enabled-clk",
+ .of_match_table = gpio_enabled_clk_match_table,
+ },
+};
+builtin_platform_driver(gpio_enabled_clk_driver);
+
/**
* DOC: gated fixed clock, controlled with a gpio output and a regulator
* Traits of this clock:
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v9 1/2] dt-bindings: gpio-enabled-clock: Add a new binding
2026-10-15 14:22 ` [PATCH v9 1/2] dt-bindings: gpio-enabled-clock: Add a new binding Vyacheslav Yurkov via B4 Relay
@ 2026-10-15 19:58 ` Rob Herring (Arm)
0 siblings, 0 replies; 4+ messages in thread
From: Rob Herring (Arm) @ 2026-10-15 19:58 UTC (permalink / raw)
To: Vyacheslav Yurkov
Cc: linux-kernel, Conor Dooley, Jyri Sarha, Vyacheslav Yurkov,
Brian Masney, Michael Turquette, Krzysztof Kozlowski, linux-clk,
Jerome Brunet, Brian Masney, Stephen Boyd, devicetree
On Thu, 15 Oct 2026 14:22:50 +0000, Vyacheslav Yurkov wrote:
> Add the binding for gpio-enabled-clock. A GPIO-enabled clock provider
> exposes a clock (can be any type of clock) whose availability depends on
> a GPIO status signal.
>
> Some hardware designs provide fixed-frequency clocks generated outside
> software control, such as by FPGA-resident PLLs. While the clock rate is
> fixed, a separate GPIO signal indicates whether the clock source is enabled
> and producing a valid output.
>
> Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
> ---
> .../bindings/clock/gpio-enabled-clock.yaml | 53 ++++++++++++++++++++++
> 1 file changed, 53 insertions(+)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-10-15 19:58 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-15 14:22 [PATCH v9 0/2] A proposal to add a gpio-enabled clock driver Vyacheslav Yurkov via B4 Relay
2026-10-15 14:22 ` [PATCH v9 1/2] dt-bindings: gpio-enabled-clock: Add a new binding Vyacheslav Yurkov via B4 Relay
2026-10-15 19:58 ` Rob Herring (Arm)
2026-10-15 14:22 ` [PATCH v9 2/2] clk: Add gpio-enabled clock driver Vyacheslav Yurkov via B4 Relay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®