From nobody Mon Jun 8 07:24:45 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 C0DC6331203; Wed, 3 Jun 2026 11:16:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780485408; cv=none; b=V7CXbdn6FIZ1/XpCyIOHMOznEXj3H6hs/kZ+WtzIPyMdeG6NsLbbOwUIg5E8GOTOYlreuAMbtefSz+Hsf2YUWPwTGcr6Mo57x2lZreElqxEh/n1upAs8DM5q8cTvtCpvNVSJXxwmRn6FcE9d2R7dd6864VQZwdU2dgL7JQZPC3U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780485408; c=relaxed/simple; bh=0YKayESYLdoep8fZ/BpdE1Gj/VtDT+F/VawTAY27mXo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Cl5ayQpz6WwItyDYp6ATzx9Jh6vb5z6X4Y+3takuBp/7Dloh/4UrZ/Tg2+ZZ08MDgi/9Rc1eoAz0YjRG7QA2wRe5YU23JHZZK4v+8E3A+AHOR/nlybGjaU4p2xA100sO1ikkDXchVvhE+YvXdI2yjNc91n7pcBT1U905w1Vc1js= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FX2xBByG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FX2xBByG" Received: by smtp.kernel.org (Postfix) with ESMTPS id 59568C2BCC6; Wed, 3 Jun 2026 11:16:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1780485408; bh=0YKayESYLdoep8fZ/BpdE1Gj/VtDT+F/VawTAY27mXo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=FX2xBByGjJ6PekC/oy72//l+GlJItcJnUGN32ej1Dubso8psW+vG4uSes8IkiqyVo mQ8gbwPfT9uXKGHRt6VyR6C4czkK0pTZl0hMyhzE5rJh5W/jcEp56TlW3PFwKebiQX EXk6kgOgbhn+24xNfyl1KbIGMEpPhr4nMgICjZVa1NpKJw4fZgveqnTC+HaDLNBY8d TgIvQL7Q7G/cirPuP/fleGJAb9V4c5MNqRM+fason9bpEhnrJClnc++2ARnhQlBGnx vcUfRQuWJEO1Hq5WA92QDc0sa8L3tlbt3IILPAMeAxJpG4ImwtjEfe01OahJxEZf3O zrV9No7HsRDNw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43216CD6E56; Wed, 3 Jun 2026 11:16:48 +0000 (UTC) From: Vyacheslav Yurkov via B4 Relay Date: Wed, 03 Jun 2026 11:16:42 +0000 Subject: [PATCH v3 1/2] dt-bindings: Add GPIO-locked fixed clock 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: <20260603-feature-clock-guard-v3-1-01cca0aa04a5@bruker.com> References: <20260603-feature-clock-guard-v3-0-01cca0aa04a5@bruker.com> In-Reply-To: <20260603-feature-clock-guard-v3-0-01cca0aa04a5@bruker.com> To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Brian Masney Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, devicetree@vger.kernel.org, Vyacheslav Yurkov , Vyacheslav Yurkov X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1780485407; l=2817; i=V.Yurkov.EXT@bruker.com; s=20260318; h=from:subject:message-id; bh=iHRb7fBmSmETe2+oHkt2rJtsp8K/mu9bMS++HcMLWAg=; b=QAyCwjFnk+SBMikLZQpp4n32gxXiduFG9py82nppOle736/Uj92YJIgBQRfBaBjJBc30x7nhN Ncc45wc2udUCbx6jx75NmVFbGdvH0HgRoPW2gjGjX0C0YvFikkfoiA2 X-Developer-Key: i=V.Yurkov.EXT@bruker.com; a=ed25519; pk=snJmgYVOKlp7aQtK9tWnEI7QTYxpPpJJvxdVsnxA7Fk= X-Endpoint-Received: by B4 Relay for V.Yurkov.EXT@bruker.com/20260318 with auth_id=686 X-Original-From: Vyacheslav Yurkov Reply-To: V.Yurkov.EXT@bruker.com From: Vyacheslav Yurkov 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. Describe a GPIO-locked fixed clock provider that exposes a fixed-rate clock whose availability depends on one or more GPIO lock-status signals. Signed-off-by: Vyacheslav Yurkov Signed-off-by: Vyacheslav Yurkov --- .../bindings/clock/gpio-locked-fixed-clock.yaml | 70 ++++++++++++++++++= ++++ 1 file changed, 70 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/gpio-locked-fixed-cloc= k.yaml b/Documentation/devicetree/bindings/clock/gpio-locked-fixed-clock.ya= ml new file mode 100644 index 000000000000..9106b800b673 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/gpio-locked-fixed-clock.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/gpio-locked-fixed-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GPIO Locked Fixed Clock + +maintainers: + - Vyacheslav Yurkov + +description: | + Provides a clock output whose availability depends on a set of + prerequisite conditions. These conditions include the presence of + one or more parent clocks and the asserted state of one or more + GPIO lock indicators. An example of such clocks is FPGA clock that + are outside CPU control, with the lock status exposed through GPIO + signal. + + The output clock is considered available only when all configured + prerequisites are satisfied. + +properties: + compatible: + const: gpio-locked-fixed-clock + + "#clock-cells": + const: 0 + + clocks: + description: Input clocks whose validity is monitored by this provider. + + clock-output-names: + description: Names of the clock provided by this controller. + maxItems: 1 + + locked-gpios: + description: | + GPIOs to check the lock state. + minItems: 1 + maxItems: 32 + +required: + - compatible + - "#clock-cells" + +anyOf: + - required: + - clocks + - required: + - locked-gpios + +additionalProperties: false + +examples: + - | + #include + + clk_gpio_locked: gpio-locked-fixed-clock { + compatible =3D "gpio-locked-fixed-clock"; + #clock-cells =3D <0>; + + clocks =3D <&clk0 0>, <&pll 0>; + + locked-gpios =3D <&gpio0 4 GPIO_ACTIVE_HIGH>, + <&gpio0 5 GPIO_ACTIVE_HIGH>, + <&gpio1 2 GPIO_ACTIVE_LOW>; + + clock-output-names =3D "clkout0"; + }; --=20 2.34.1 From nobody Mon Jun 8 07:24:45 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 E01774508E0; Wed, 3 Jun 2026 11:16:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780485411; cv=none; b=o0TwMjTjaea7s5fDRG0vzLPqujjk95CecYljiTCH9hzFbNywrbWv98LnRYZad41u2a/cNuho8uujM8iVydDkh2lKWMdahBAyfoYtsvH1U58oTAwTXn/Sj1qKS4uJor3giuOiofPUVohGdn7h/oFDSX32ZcrCQ5xV5VZj44iiRlA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780485411; c=relaxed/simple; bh=dNFTTHDuY+Om6VmhdSLSv1xmv0DWBxzrVmPGrzuqlh8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mGTlDabbMxb67ym3M1kZRBtg/rMHbWUPpCCQE2CQP4KbPcBzPvT1zJS3moajhx3d8DF3kRRvgx1rJIaf3genXpJUIMgwQV5TlvnF+YJ157W3Y0ED7FGta808ZrG45Mj5qmO+iLadbNbxQoZFu+mOe0PMSthnfcr3sSkNyJg+V2U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=USDi7DNn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="USDi7DNn" Received: by smtp.kernel.org (Postfix) with ESMTPS id 67582C2BCC7; Wed, 3 Jun 2026 11:16:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1780485408; bh=dNFTTHDuY+Om6VmhdSLSv1xmv0DWBxzrVmPGrzuqlh8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=USDi7DNnaG5BiCIhIRpB6gHa3HyU8dBqP3T14/UMre6bDbHM8ybqP2+zyhHYRQLz5 ub6da/aNNjmF1Ng6vyEVGYx/zX4hjCQWZrUtv5967xTuBUneOGkeYS+f8W8wxq10fB Dj1gEoX5M2BoroapezBksU9vgItMdhxZROSqLGMvm/UYWKVrzqzYLPvm2sE+I4SvJR E2PkJr5WRXJgDA6vUuAGVcsKZB1nK2NbQwsm+24gCWLM/2PusySwcrkeohv4NdqTsU ByiavUimjpf1s1+RXSdOQm4jX9v+KGcgFrVwEttIPQ1OpLA2Grlr6UPwohisXxpG1/ +z2Vfw7vITREA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51D07CD6E6A; Wed, 3 Jun 2026 11:16:48 +0000 (UTC) From: Vyacheslav Yurkov via B4 Relay Date: Wed, 03 Jun 2026 11:16:43 +0000 Subject: [PATCH v3 2/2] clk: Add gpio-locked fixed clock driver 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: <20260603-feature-clock-guard-v3-2-01cca0aa04a5@bruker.com> References: <20260603-feature-clock-guard-v3-0-01cca0aa04a5@bruker.com> In-Reply-To: <20260603-feature-clock-guard-v3-0-01cca0aa04a5@bruker.com> To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Brian Masney Cc: linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, devicetree@vger.kernel.org, Vyacheslav Yurkov , Vyacheslav Yurkov X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1780485407; l=9156; i=V.Yurkov.EXT@bruker.com; s=20260318; h=from:subject:message-id; bh=K53Ou1Wv2xlXRrlhO3njWZoK913ers18g+GoLE+qDXg=; b=1ukFdBjLrmRVjTLC/xBhZDQoJ4Aj+iYjiSqn7yiBIIRKuYU4V4jpOKMyXBfnaPz8SAwTGNF/B iE6khMC5U1UCuIypbTeOzYSJI6HpsjAiGDMyp3XfsI+PXbBvXGcdlWR X-Developer-Key: i=V.Yurkov.EXT@bruker.com; a=ed25519; pk=snJmgYVOKlp7aQtK9tWnEI7QTYxpPpJJvxdVsnxA7Fk= X-Endpoint-Received: by B4 Relay for V.Yurkov.EXT@bruker.com/20260318 with auth_id=686 X-Original-From: Vyacheslav Yurkov Reply-To: V.Yurkov.EXT@bruker.com From: Vyacheslav Yurkov A gpio-locked clock aggregates one or more input clocks and/or one or more GPIOs. It's 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 all input clocks are locked and only then initialize dependent peripherals. Signed-off-by: Vyacheslav Yurkov Signed-off-by: Vyacheslav Yurkov --- drivers/clk/Makefile | 1 + drivers/clk/clk-gpio-locked.c | 306 ++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 307 insertions(+) diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index a3e2862ebd7e..464ca1c1d8a8 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -35,6 +35,7 @@ obj-$(CONFIG_CLK_FD_KUNIT_TEST) +=3D clk-fractional-divid= er_test.o obj-$(CONFIG_COMMON_CLK) +=3D clk-gpio.o ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) +=3D clk-conf.o +obj-$(CONFIG_COMMON_CLK) +=3D clk-gpio-locked.o endif =20 # KUnit specific helpers diff --git a/drivers/clk/clk-gpio-locked.c b/drivers/clk/clk-gpio-locked.c new file mode 100644 index 000000000000..79098f9b6532 --- /dev/null +++ b/drivers/clk/clk-gpio-locked.c @@ -0,0 +1,306 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +/* + * Clock Controller Guard Driver + * + * Copyright 2026 Bruker Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_INPUT_GPIO_COUNT 32 + +/** + * struct gpio_locked_clk_priv - private state for the whole driver + * @dev: platform device + * + * @clks: array of input clock descriptors + * @num_clks: number of entries in @inputs + * + * @gpios: array of GPIO descriptors + * @gpio_names: GPIO names + * @num_gpios: number of input GPIOs + * + * @output_hw_clk: output clock HW descriptor + * @output_clock_name: output clock name + */ +struct gpio_locked_clk_priv { + struct device *dev; + + struct clk_bulk_data *clks; + int num_clks; + + struct gpio_descs *gpios; + const char **gpio_names; + int num_gpios; + + struct clk_hw output_hw_clk; + const char *output_clock_name; +}; + +#define to_gpio_locked_clk_priv(_hw) \ + container_of(_hw, struct gpio_locked_clk_priv, output_hw_clk) + +static int is_gpio_ready(struct gpio_locked_clk_priv *priv) +{ + unsigned long values[BITS_TO_LONGS(MAX_INPUT_GPIO_COUNT)] =3D {0}; + int ret =3D 0; + + if (priv->num_gpios =3D=3D 0) + return 0; + + ret =3D gpiod_get_array_value(priv->gpios->ndescs, + priv->gpios->desc, + priv->gpios->info, + values); + + if (ret) { + dev_err(priv->dev, "Failed to read GPIOs"); + return -EIO; + } + + for (int i =3D 0; i < priv->gpios->ndescs; i++) { + if (!test_bit(i, values)) { + dev_warn(priv->dev, "GPIO %s is not ready", priv->gpio_names[i]); + return -EBUSY; + } + } + + return 0; +} + +static int gpio_locked_clk_is_enabled(struct clk_hw *hw) +{ + struct gpio_locked_clk_priv *priv =3D to_gpio_locked_clk_priv(hw); + int ret =3D 0; + + if (priv->num_gpios > 0) { + ret =3D is_gpio_ready(priv); + if (ret < 0) + return ret; + } + + // Now check for the clocks + for (int i =3D 0; i < priv->num_clks; i++) { + struct clk_hw *hw_clk =3D __clk_get_hw(priv->clks[i].clk); + + if (!clk_hw_is_enabled(hw_clk)) { + dev_dbg(priv->dev, "Clock %i (%s) is not ready", + i, priv->clks[i].id); + return -EBUSY; + } + } + + return 0; +} + +/* We can't enable the clock, but the Common Clock Framework calls only + * enable() not is_enabled() + */ +static int gpio_locked_clk_enable(struct clk_hw *hw) +{ + return gpio_locked_clk_is_enabled(hw); +} + +/* We have to implement it, but we are not going to control + * parent clock selection + */ +static u8 gpio_locked_clk_get_parent(struct clk_hw *hw) +{ + return 0; +} + +static const struct clk_ops gpio_locked_clk_ops =3D { + .enable =3D gpio_locked_clk_enable, + .is_enabled =3D gpio_locked_clk_is_enabled, + .get_parent =3D gpio_locked_clk_get_parent, +}; + +static int gpio_locked_clk_parse_inputs(struct gpio_locked_clk_priv *priv) +{ + struct device *dev =3D priv->dev; + int ret; + + ret =3D devm_clk_bulk_get_all(dev, &priv->clks); + if (ret < 0) { + dev_err(dev, "failed to get input clocks: %d\n", ret); + return ret ? ret : -ENOENT; + } + + priv->num_clks =3D ret; + + if (priv->num_clks =3D=3D 0) + dev_info(dev, "No input clocks provided\n"); + + for (int i =3D 0; i < priv->num_clks; i++) + dev_dbg(dev, "input clk[%d]: name=3D'%s' rate=3D%lu Hz\n", + i, priv->clks[i].id, + clk_get_rate(priv->clks[i].clk)); + + return 0; +} + +static int gpio_locked_clk_parse_gpios(struct gpio_locked_clk_priv *priv) +{ + struct device *dev =3D priv->dev; + struct device_node *np =3D dev->of_node; + int i; + + priv->gpios =3D devm_gpiod_get_array_optional(dev, "locked", GPIOD_ASIS); + if (IS_ERR(priv->gpios)) { + dev_err(dev, "failed to get GPIO array: %ld\n", + PTR_ERR(priv->gpios)); + return PTR_ERR(priv->gpios); + } + + if (!priv->gpios) { + dev_info(dev, "No GPIOs provided, continue\n"); + priv->num_gpios =3D 0; + return 0; + } + + priv->num_gpios =3D priv->gpios->ndescs; + if (priv->num_gpios > MAX_INPUT_GPIO_COUNT) { + dev_err(priv->dev, "Maximum number of input GPIOs is 32\n"); + return -EINVAL; + } + + /* gpio_descs carries no names, so read "gpio-names" separately */ + priv->gpio_names =3D devm_kcalloc(dev, priv->num_gpios, sizeof(*priv->gpi= o_names), + GFP_KERNEL); + if (!priv->gpio_names) + return -ENOMEM; + + for (i =3D 0; i < priv->num_gpios; i++) { + of_property_read_string_index(np, "gpio-names", i, + &priv->gpio_names[i]); + + dev_dbg(dev, "gpio[%d]: name=3D'%s'\n", + i, priv->gpio_names[i] ? priv->gpio_names[i] : "(unnamed)"); + } + + return 0; +} + +static int gpio_locked_clk_parse_outputs(struct gpio_locked_clk_priv *priv) +{ + struct device *dev =3D priv->dev; + struct device_node *np =3D dev->of_node; + struct clk_init_data init =3D {}; + int ret; + + of_property_read_string_index(np, "clock-output-names", 0, + &priv->output_clock_name); + + if (!priv->output_clock_name) + priv->output_clock_name =3D dev_name(priv->dev); + + init.name =3D priv->output_clock_name; + init.ops =3D &gpio_locked_clk_ops; + init.flags =3D 0; + init.num_parents =3D priv->num_clks; + + if (priv->num_clks) { + const char **parent_names; + int j; + + parent_names =3D devm_kcalloc(dev, priv->num_clks, + sizeof(*parent_names), + GFP_KERNEL); + if (!parent_names) + return -ENOMEM; + + for (j =3D 0; j < priv->num_clks; j++) + parent_names[j] =3D priv->clks[j].id; + + init.parent_names =3D parent_names; + } + + priv->output_hw_clk.init =3D &init; + + ret =3D devm_clk_hw_register(dev, &priv->output_hw_clk); + if (ret) { + dev_err(dev, "failed to register output clk'%s': %d\n", + priv->output_clock_name, ret); + return ret; + } + + dev_info(priv->dev, "Output clock '%s' registered\n", priv->output_clock_= name); + + return 0; +} + +static int gpio_locked_clk_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct gpio_locked_clk_priv *priv; + int ret; + + priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev =3D dev; + platform_set_drvdata(pdev, priv); + + ret =3D gpio_locked_clk_parse_inputs(priv); + if (ret) + return ret; + + ret =3D gpio_locked_clk_parse_gpios(priv); + if (ret) + return ret; + + if (priv->num_clks =3D=3D 0 && priv->num_gpios =3D=3D 0) { + dev_err(priv->dev, "At least 1 input clock or input GPIO is required\n"); + return -EINVAL; + } + + ret =3D gpio_locked_clk_parse_outputs(priv); + if (ret) + return ret; + + ret =3D devm_of_clk_add_hw_provider(priv->dev, of_clk_hw_simple_get, + &priv->output_hw_clk); + if (ret) { + dev_err(priv->dev, "failed to register clock provider '%s': %d\n", + priv->output_clock_name, ret); + return ret; + } + + dev_info(dev, "registered %u input clocks, %u GPIOs\n", + priv->num_clks, priv->num_gpios); + + return 0; +} + +static void gpio_locked_clk_remove(struct platform_device *pdev) +{ + dev_dbg(&pdev->dev, "removed\n"); +} + +static const struct of_device_id gpio_locked_clk_of_match[] =3D { + { .compatible =3D "gpio-locked-fixed-clock" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, gpio_locked_clk_of_match); + +static struct platform_driver gpio_locked_clk_driver =3D { + .probe =3D gpio_locked_clk_probe, + .remove =3D gpio_locked_clk_remove, + .driver =3D { + .name =3D "gpio-locked-fixed-clock", + .of_match_table =3D gpio_locked_clk_of_match, + }, +}; +module_platform_driver(gpio_locked_clk_driver); + +MODULE_AUTHOR("Vyacheslav Yurkov "); +MODULE_DESCRIPTION("GPIO-locked clock driver"); +MODULE_LICENSE("Dual BSD/GPL"); --=20 2.34.1