* [PATCH v8 0/2] A proposal to add a gpio-locked clock driver.
@ 2026-09-27 14:59 Vyacheslav Yurkov via B4 Relay
2026-09-27 14:59 ` [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string Vyacheslav Yurkov via B4 Relay
2026-09-27 14:59 ` [PATCH v8 2/2] clk: Add gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
0 siblings, 2 replies; 7+ messages in thread
From: Vyacheslav Yurkov via B4 Relay @ 2026-09-27 14:59 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-locked 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 all input
clocks are locked 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 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: clock: gpio-gate-clock: Add a new compatible string
clk: Add gpio-locked clock driver
.../devicetree/bindings/clock/gpio-gate-clock.yaml | 32 +++++++++++++-
drivers/clk/clk-gpio.c | 50 ++++++++++++++++++++--
2 files changed, 77 insertions(+), 5 deletions(-)
---
base-commit: fd179f8a05be3ccae366b9b96e176b51fbe54aab
change-id: 20260318-feature-clock-guard-f20a2c35b965
Best regards,
--
Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string
2026-09-27 14:59 [PATCH v8 0/2] A proposal to add a gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
@ 2026-09-27 14:59 ` Vyacheslav Yurkov via B4 Relay
2026-09-27 15:08 ` sashiko-bot
2026-10-05 14:27 ` Jerome Brunet
2026-09-27 14:59 ` [PATCH v8 2/2] clk: Add gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
1 sibling, 2 replies; 7+ messages in thread
From: Vyacheslav Yurkov via B4 Relay @ 2026-09-27 14:59 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>
Extend the binding to be used also for gpio-locked-fixed-clock.
A GPIO-locked fixed clock provider exposes a fixed-rate clock whose
availability depends on one or more GPIO lock-status signals.
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
locked and producing a valid output.
Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
---
.../devicetree/bindings/clock/gpio-gate-clock.yaml | 32 ++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
index d09d0e3f0c6e..1ad87c8b36b9 100644
--- a/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
@@ -11,7 +11,9 @@ maintainers:
properties:
compatible:
- const: gpio-gate-clock
+ enum:
+ - gpio-gate-clock
+ - gpio-locked-clock
clocks:
maxItems: 1
@@ -23,10 +25,29 @@ properties:
description: GPIO reference for enabling and disabling the clock.
maxItems: 1
+ enabled-gpios:
+ description: GPIO that indicates whether the clock is enabled or disabled.
+ maxItems: 1
+
required:
- compatible
- '#clock-cells'
- - enable-gpios
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ const: gpio-gate-clock
+ then:
+ required:
+ - enable-gpios
+ - if:
+ properties:
+ compatible:
+ const: gpio-locked-clock
+ then:
+ required:
+ - enabled-gpios
additionalProperties: false
@@ -40,3 +61,10 @@ examples:
#clock-cells = <0>;
enable-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
};
+
+ clk_gpio_locked {
+ compatible = "gpio-locked-clock";
+ #clock-cells = <0>;
+ clocks = <&pll>;
+ enabled-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v8 2/2] clk: Add gpio-locked clock driver
2026-09-27 14:59 [PATCH v8 0/2] A proposal to add a gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
2026-09-27 14:59 ` [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string Vyacheslav Yurkov via B4 Relay
@ 2026-09-27 14:59 ` Vyacheslav Yurkov via B4 Relay
2026-09-27 15:09 ` sashiko-bot
2026-10-05 14:27 ` Jerome Brunet
1 sibling, 2 replies; 7+ messages in thread
From: Vyacheslav Yurkov via B4 Relay @ 2026-09-27 14:59 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-locked 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 locked
and only then initialize dependent peripherals.
Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
---
drivers/clk/clk-gpio.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 47 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
index 9099c57e2715..db68b8bc44c5 100644
--- a/drivers/clk/clk-gpio.c
+++ b/drivers/clk/clk-gpio.c
@@ -138,6 +138,25 @@ static const struct clk_ops clk_gpio_mux_ops = {
.determine_rate = __clk_mux_determine_rate,
};
+/* We can't prepare the clock, but the Common Clock Framework calls only
+ * prepare() not is_prepared(), therefore we fallback on the actuall GPIO value.
+ * The function clk_sleeping_gpio_gate_is_prepared() returns the raw boolean
+ * GPIO status (1 if locked, 0 if unlocked), but the prepare callback
+ * clk_core_prepare() expects 0 for success and non-zero integer for failure.
+ */
+static int clk_gpio_locked_prepare(struct clk_hw *hw)
+{
+ if (clk_sleeping_gpio_gate_is_prepared(hw))
+ return 0;
+
+ return -EBUSY;
+}
+
+static const struct clk_ops clk_gpio_locked_ops = {
+ .prepare = clk_gpio_locked_prepare,
+ .is_prepared = clk_sleeping_gpio_gate_is_prepared,
+};
+
static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
struct gpio_desc *gpiod,
const struct clk_ops *clk_gpio_ops)
@@ -146,6 +165,7 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
struct clk_hw *hw;
struct clk_init_data init = {};
int err;
+ const char *clk_name;
const struct clk_parent_data gpio_parent_data[] = {
{ .index = 0 },
{ .index = 1 },
@@ -155,7 +175,11 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
if (!clk_gpio)
return ERR_PTR(-ENOMEM);
- init.name = dev->of_node->name;
+ err = device_property_read_string(dev, "clock-output-names", &clk_name);
+ if (err)
+ clk_name = fwnode_get_name(dev->fwnode);
+
+ init.name = clk_name;
init.ops = clk_gpio_ops;
init.parent_data = gpio_parent_data;
init.num_parents = num_parents;
@@ -192,6 +216,12 @@ static struct clk_hw *clk_hw_register_gpio_mux(struct device *dev,
return clk_register_gpio(dev, 2, gpiod, &clk_gpio_mux_ops);
}
+static struct clk_hw *clk_hw_register_gpio_locked(struct device *dev,
+ struct gpio_desc *gpiod)
+{
+ return clk_register_gpio(dev, 1, gpiod, &clk_gpio_locked_ops);
+}
+
static int gpio_clk_driver_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -201,8 +231,11 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
struct gpio_desc *gpiod;
struct clk_hw *hw;
bool is_mux;
+ bool is_gpio_locked;
+ enum gpiod_flags gpio_flags;
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
+ is_gpio_locked = of_device_is_compatible(node, "gpio-locked-clock");
num_parents = of_clk_get_parent_count(node);
if (is_mux && num_parents != 2) {
@@ -210,14 +243,24 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
return -EINVAL;
}
- gpio_name = is_mux ? "select" : "enable";
- gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW);
+ if (is_mux)
+ gpio_name = "select";
+ else if (is_gpio_locked)
+ gpio_name = "enabled";
+ else
+ gpio_name = "enable";
+
+ gpio_flags = is_gpio_locked ? GPIOD_IN : GPIOD_OUT_LOW;
+
+ gpiod = devm_gpiod_get(dev, gpio_name, gpio_flags);
if (IS_ERR(gpiod))
return dev_err_probe(dev, PTR_ERR(gpiod),
"Can't get '%s' named GPIO property\n", gpio_name);
if (is_mux)
hw = clk_hw_register_gpio_mux(dev, gpiod);
+ else if (is_gpio_locked)
+ hw = clk_hw_register_gpio_locked(dev, gpiod);
else
hw = clk_hw_register_gpio_gate(dev, num_parents, gpiod);
if (IS_ERR(hw))
@@ -229,6 +272,7 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
static const struct of_device_id gpio_clk_match_table[] = {
{ .compatible = "gpio-mux-clock" },
{ .compatible = "gpio-gate-clock" },
+ { .compatible = "gpio-locked-clock" },
{ }
};
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string
2026-09-27 14:59 ` [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string Vyacheslav Yurkov via B4 Relay
@ 2026-09-27 15:08 ` sashiko-bot
2026-10-05 14:27 ` Jerome Brunet
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-09-27 15:08 UTC (permalink / raw)
To: Vyacheslav Yurkov; +Cc: robh, linux-clk, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Medium] dt-bindings: clock: mismatch between commit message and compatible string
- [Medium] dt-bindings: clock: enabled-gpios maxItems restricted to 1 contradicting commit
- [Low] dt-bindings: clock: example node name uses invalid underscore characters
--
commit 27371721055a09fb1d350d670a8c103b2d13f3cd
Author: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
dt-bindings: clock: gpio-gate-clock: Add a new compatible string
This commit extends the gpio-gate-clock binding to support a GPIO-locked
fixed clock provider. The provider exposes a fixed-rate clock whose
availability depends on GPIO lock-status signals.
> diff --git a/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
> index d09d0e3f0c6ec..1ad87c8b36b9f 100644
> --- a/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
> +++ b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
> @@ -11,7 +11,9 @@ maintainers:
>
> properties:
> compatible:
> - const: gpio-gate-clock
> + enum:
> + - gpio-gate-clock
> + - gpio-locked-clock
[Severity: Medium]
In the properties:compatible definition, the enum defines the string as
"gpio-locked-clock". The commit message states the binding is being extended
for "gpio-locked-fixed-clock". Could this mismatch cause confusion for users
and developers reading the commit log who might assume the compatible string
is "gpio-locked-fixed-clock" and attempt to use it?
[ ... ]
> @@ -23,10 +25,29 @@ properties:
> description: GPIO reference for enabling and disabling the clock.
> maxItems: 1
>
> + enabled-gpios:
> + description: GPIO that indicates whether the clock is enabled or disabled.
> + maxItems: 1
[Severity: Medium]
Does this maxItems constraint in properties:enabled-gpios match the intended
design? The commit message indicates the clock availability depends on "one
or more GPIO lock-status signals", but this property restricts the
configuration to a maximum of 1 item. Users attempting to provide more than
one GPIO based on the commit message will encounter schema validation
failures.
[ ... ]
> @@ -40,3 +61,10 @@ examples:
> #clock-cells = <0>;
> enable-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
> };
> +
> + clk_gpio_locked {
> + compatible = "gpio-locked-clock";
[Severity: Low]
In the examples section, is this node name compliant with device tree
conventions? Node names containing underscores generally trigger warnings
during device tree compilation (such as from dtc -W node_name_chars_strict).
> + #clock-cells = <0>;
> + clocks = <&pll>;
> + enabled-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
> + };
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260927-feature-clock-guard-v8-0-630938e302a1@bruker.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v8 2/2] clk: Add gpio-locked clock driver
2026-09-27 14:59 ` [PATCH v8 2/2] clk: Add gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
@ 2026-09-27 15:09 ` sashiko-bot
2026-10-05 14:27 ` Jerome Brunet
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-09-27 15:09 UTC (permalink / raw)
To: Vyacheslav Yurkov; +Cc: conor+dt, linux-clk, robh, devicetree
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] clk: gpio: negative error code from GPIO read evaluated as success
- [Medium] clk: gpio: clk_prepare callback violates CCF abstraction by failing to block
- [Medium] clk: gpio: gpio-locked-clock ignores DT num_parents, forcing orphan state
--
commit 8ac8202cfc07fde8ca8b25fa51d26b883f03b432
Author: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
clk: Add gpio-locked clock driver
This commit adds a gpio-locked clock driver where the clock's valid status
is determined by a GPIO signal. It allows consumers to wait on the clock
lock before initializing dependent peripherals.
> diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
> index 9099c57e27156..db68b8bc44c5a 100644
> --- a/drivers/clk/clk-gpio.c
> +++ b/drivers/clk/clk-gpio.c
> @@ -138,6 +138,25 @@ static const struct clk_ops clk_gpio_mux_ops = {
[ ... ]
> +/* We can't prepare the clock, but the Common Clock Framework calls only
> + * prepare() not is_prepared(), therefore we fallback on the actuall GPIO value.
> + * The function clk_sleeping_gpio_gate_is_prepared() returns the raw boolean
> + * GPIO status (1 if locked, 0 if unlocked), but the prepare callback
> + * clk_core_prepare() expects 0 for success and non-zero integer for failure.
> + */
> +static int clk_gpio_locked_prepare(struct clk_hw *hw)
> +{
> + if (clk_sleeping_gpio_gate_is_prepared(hw))
> + return 0;
[Severity: High]
Will this evaluate a negative error code as a success?
The underlying function clk_sleeping_gpio_gate_is_prepared() calls
gpiod_get_value_cansleep():
static int clk_sleeping_gpio_gate_is_prepared(struct clk_hw *hw)
{
struct clk_gpio *clk = to_clk_gpio(hw);
return gpiod_get_value_cansleep(clk->gpiod);
}
If gpiod_get_value_cansleep() returns a negative error code (such as -EIO)
due to a hardware read failure, the if condition here will evaluate it as
true.
This would return 0 (success) to the Common Clock Framework, incorrectly
masking the hardware error and falsely signaling that the PLL/clock lock
was successfully acquired.
> +
> + return -EBUSY;
[Severity: Medium]
Does returning -EBUSY here violate the Common Clock Framework abstraction?
The clk_prepare callback is permitted to sleep and is generally expected
to block until the hardware is ready. By returning an error immediately
instead of blocking until the clock is locked, standard device drivers
calling clk_prepare_enable() might permanently fail their probe sequence.
Will this force consumers to implement non-standard polling logic to
handle the -EBUSY return value?
> +}
> +
> +static const struct clk_ops clk_gpio_locked_ops = {
[ ... ]
> @@ -192,6 +216,12 @@ static struct clk_hw *clk_hw_register_gpio_mux(struct device *dev,
> return clk_register_gpio(dev, 2, gpiod, &clk_gpio_mux_ops);
> }
>
> +static struct clk_hw *clk_hw_register_gpio_locked(struct device *dev,
> + struct gpio_desc *gpiod)
> +{
> + return clk_register_gpio(dev, 1, gpiod, &clk_gpio_locked_ops);
[Severity: Medium]
Is it intentional to hardcode the number of parents to 1 here?
In the gpio_clk_driver_probe() function, the true parent count is parsed
from the device tree:
num_parents = of_clk_get_parent_count(node);
If the clock is configured in the device tree as an independent root clock
(for example, an FPGA PLL with no parent clock, meaning num_parents is 0),
hardcoding it to 1 here will cause CCF to attempt to resolve a parent at
index 0.
Could this cause clk_core_get() to fail internal lookups, leading the clock
to silently fall back to an orphan state?
> +}
> +
> static int gpio_clk_driver_probe(struct platform_device *pdev)
> {
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260927-feature-clock-guard-v8-0-630938e302a1@bruker.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v8 2/2] clk: Add gpio-locked clock driver
2026-09-27 14:59 ` [PATCH v8 2/2] clk: Add gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
2026-09-27 15:09 ` sashiko-bot
@ 2026-10-05 14:27 ` Jerome Brunet
1 sibling, 0 replies; 7+ messages in thread
From: Jerome Brunet @ 2026-10-05 14:27 UTC (permalink / raw)
To: Vyacheslav Yurkov via B4 Relay, 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
On Sun 27 Sep 2026 at 14:59, Vyacheslav Yurkov via B4 Relay <devnull+V.Yurkov.EXT.bruker.com@kernel.org> wrote:
> From: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
>
> A gpio-locked 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 locked
> and only then initialize dependent peripherals.
>
> Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
> ---
> drivers/clk/clk-gpio.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 47 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c
> index 9099c57e2715..db68b8bc44c5 100644
> --- a/drivers/clk/clk-gpio.c
> +++ b/drivers/clk/clk-gpio.c
> @@ -138,6 +138,25 @@ static const struct clk_ops clk_gpio_mux_ops = {
> .determine_rate = __clk_mux_determine_rate,
> };
>
> +/* We can't prepare the clock, but the Common Clock Framework calls only
> + * prepare() not is_prepared(), therefore we fallback on the actuall GPIO value.
> + * The function clk_sleeping_gpio_gate_is_prepared() returns the raw boolean
> + * GPIO status (1 if locked, 0 if unlocked), but the prepare callback
> + * clk_core_prepare() expects 0 for success and non-zero integer for failure.
> + */
> +static int clk_gpio_locked_prepare(struct clk_hw *hw)
> +{
> + if (clk_sleeping_gpio_gate_is_prepared(hw))
> + return 0;
> +
> + return -EBUSY;
> +}
I was apparently not clear - probably my fault since I was initially
confused with what the driver was supposed to do.
Please do not modify the gate driver. Just provide gpio-enabled-clock
clock driver along the gate and mux in there.
> +
> +static const struct clk_ops clk_gpio_locked_ops = {
> + .prepare = clk_gpio_locked_prepare,
> + .is_prepared = clk_sleeping_gpio_gate_is_prepared,
> +};
Please implement the ops you've be testing, fast or slow (or both :D if
you can test both)
> +
> static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
> struct gpio_desc *gpiod,
> const struct clk_ops *clk_gpio_ops)
> @@ -146,6 +165,7 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
> struct clk_hw *hw;
> struct clk_init_data init = {};
> int err;
> + const char *clk_name;
> const struct clk_parent_data gpio_parent_data[] = {
> { .index = 0 },
> { .index = 1 },
> @@ -155,7 +175,11 @@ static struct clk_hw *clk_register_gpio(struct device *dev, u8 num_parents,
> if (!clk_gpio)
> return ERR_PTR(-ENOMEM);
>
> - init.name = dev->of_node->name;
> + err = device_property_read_string(dev, "clock-output-names", &clk_name);
> + if (err)
> + clk_name = fwnode_get_name(dev->fwnode);
> +
> + init.name = clk_name;
> init.ops = clk_gpio_ops;
> init.parent_data = gpio_parent_data;
> init.num_parents = num_parents;
> @@ -192,6 +216,12 @@ static struct clk_hw *clk_hw_register_gpio_mux(struct device *dev,
> return clk_register_gpio(dev, 2, gpiod, &clk_gpio_mux_ops);
> }
>
> +static struct clk_hw *clk_hw_register_gpio_locked(struct device *dev,
> + struct gpio_desc *gpiod)
> +{
> + return clk_register_gpio(dev, 1, gpiod, &clk_gpio_locked_ops);
> +}
> +
> static int gpio_clk_driver_probe(struct platform_device *pdev)
> {
> struct device *dev = &pdev->dev;
> @@ -201,8 +231,11 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
> struct gpio_desc *gpiod;
> struct clk_hw *hw;
> bool is_mux;
> + bool is_gpio_locked;
> + enum gpiod_flags gpio_flags;
>
> is_mux = of_device_is_compatible(node, "gpio-mux-clock");
> + is_gpio_locked = of_device_is_compatible(node, "gpio-locked-clock");
>
> num_parents = of_clk_get_parent_count(node);
> if (is_mux && num_parents != 2) {
> @@ -210,14 +243,24 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
> return -EINVAL;
> }
>
> - gpio_name = is_mux ? "select" : "enable";
> - gpiod = devm_gpiod_get(dev, gpio_name, GPIOD_OUT_LOW);
> + if (is_mux)
> + gpio_name = "select";
> + else if (is_gpio_locked)
> + gpio_name = "enabled";
> + else
> + gpio_name = "enable";
> +
> + gpio_flags = is_gpio_locked ? GPIOD_IN : GPIOD_OUT_LOW;
> +
> + gpiod = devm_gpiod_get(dev, gpio_name, gpio_flags);
> if (IS_ERR(gpiod))
> return dev_err_probe(dev, PTR_ERR(gpiod),
> "Can't get '%s' named GPIO property\n", gpio_name);
>
> if (is_mux)
> hw = clk_hw_register_gpio_mux(dev, gpiod);
> + else if (is_gpio_locked)
> + hw = clk_hw_register_gpio_locked(dev, gpiod);
> else
> hw = clk_hw_register_gpio_gate(dev, num_parents, gpiod);
> if (IS_ERR(hw))
> @@ -229,6 +272,7 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
> static const struct of_device_id gpio_clk_match_table[] = {
> { .compatible = "gpio-mux-clock" },
> { .compatible = "gpio-gate-clock" },
> + { .compatible = "gpio-locked-clock" },
> { }
> };
>
>
> --
> 2.34.1
>
>
--
Jerome
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string
2026-09-27 14:59 ` [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string Vyacheslav Yurkov via B4 Relay
2026-09-27 15:08 ` sashiko-bot
@ 2026-10-05 14:27 ` Jerome Brunet
1 sibling, 0 replies; 7+ messages in thread
From: Jerome Brunet @ 2026-10-05 14:27 UTC (permalink / raw)
To: Vyacheslav Yurkov via B4 Relay, 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
On Sun 27 Sep 2026 at 14:59, Vyacheslav Yurkov via B4 Relay <devnull+V.Yurkov.EXT.bruker.com@kernel.org> wrote:
> From: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
>
> Extend the binding to be used also for gpio-locked-fixed-clock.
> A GPIO-locked fixed clock provider exposes a fixed-rate clock whose
> availability depends on one or more GPIO lock-status signals.
>
> 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
> locked and producing a valid output.
>
> Signed-off-by: Vyacheslav Yurkov <V.Yurkov.EXT@bruker.com>
> ---
> .../devicetree/bindings/clock/gpio-gate-clock.yaml | 32 ++++++++++++++++++++--
> 1 file changed, 30 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
> index d09d0e3f0c6e..1ad87c8b36b9 100644
> --- a/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
> +++ b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml
> @@ -11,7 +11,9 @@ maintainers:
>
> properties:
> compatible:
> - const: gpio-gate-clock
> + enum:
> + - gpio-gate-clock
> + - gpio-locked-clock
I think this name does not illustrate well what your driver does
anymore. As I noted before, locked if very much PLL centric. enabled ?
While the driver sits in the same C file (clk-gpio), I don't the binding doc
should. I'll defer to the DT folks on this but I think it would more
approriate with a different yaml. clk-gpio-gate and clk-gpio-mux have
their own binding doc
>
> clocks:
> maxItems: 1
> @@ -23,10 +25,29 @@ properties:
> description: GPIO reference for enabling and disabling the clock.
> maxItems: 1
>
> + enabled-gpios:
> + description: GPIO that indicates whether the clock is enabled or disabled.
> + maxItems: 1
> +
> required:
> - compatible
> - '#clock-cells'
> - - enable-gpios
> +
> +allOf:
> + - if:
> + properties:
> + compatible:
> + const: gpio-gate-clock
> + then:
> + required:
> + - enable-gpios
> + - if:
> + properties:
> + compatible:
> + const: gpio-locked-clock
I think there should be a property in here to express how long you are
willing to wait for the clock to be enabled. IOW the lock timeout.
> + then:
> + required:
> + - enabled-gpios
>
> additionalProperties: false
>
> @@ -40,3 +61,10 @@ examples:
> #clock-cells = <0>;
> enable-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
> };
> +
> + clk_gpio_locked {
> + compatible = "gpio-locked-clock";
> + #clock-cells = <0>;
> + clocks = <&pll>;
> + enabled-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
> + };
>
> --
> 2.34.1
>
>
--
Jerome
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-10-05 14:27 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-27 14:59 [PATCH v8 0/2] A proposal to add a gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
2026-09-27 14:59 ` [PATCH v8 1/2] dt-bindings: clock: gpio-gate-clock: Add a new compatible string Vyacheslav Yurkov via B4 Relay
2026-09-27 15:08 ` sashiko-bot
2026-10-05 14:27 ` Jerome Brunet
2026-09-27 14:59 ` [PATCH v8 2/2] clk: Add gpio-locked clock driver Vyacheslav Yurkov via B4 Relay
2026-09-27 15:09 ` sashiko-bot
2026-10-05 14:27 ` Jerome Brunet
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox