From nobody Mon Apr 6 16:48:29 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 EDDCB345CB0; Wed, 18 Mar 2026 17:43:57 +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=1773855838; cv=none; b=jGtaXEsW7FuDnUuquTY7xdBCEUAoTkDBR8BzHiYsH5dloHFCc0rVNvsrag+XoGvThqy6dmsAobdEDHsItTabf3aWT4iHyfhAN6IFPltykF1KY93dyxPp/An6p9ZCHchDnbrAf/NktubzaYNl13CXkBpXeOsvc/U+XJN+AMopbiQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773855838; c=relaxed/simple; bh=dF80BGljkIEhB51ejdowj7JSkqznEOVwJc3YpCS6A60=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=U3iz/+ldeTcyBx4SZEL10O+Ot4YgvYwKmyWoOrhEQqTJoTBhPzqH8NxvmShKBY+KfTstJgIbIyGQ73TTSKI51zJIW2bVYmYe2zW3XfN/woC/cW+8LaKCjZo+FEt1rMxCVTemghIbafAu4M+pu5QFz0ZkKqdNNMailuTCayvwmFg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nSI3oV0V; 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="nSI3oV0V" Received: by smtp.kernel.org (Postfix) with ESMTPS id BAAE5C2BCB5; Wed, 18 Mar 2026 17:43:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773855837; bh=dF80BGljkIEhB51ejdowj7JSkqznEOVwJc3YpCS6A60=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=nSI3oV0VemMpY6xJ+H0Bz6Ab7bzb4LC0+HRqJhYSFN6mUkAe8Gc65NdhcnVDEcidU 2sfOJjmIfLrJEa8VqkLsUd57HtQu/e/pR3XxW2o47VD69qL0z7iyHsHTpoGySzD+/+ NCjCOAYlMZyqyTsRycRi7PpyBpk67IHp37rsWCcmXHRzWFwWXi5dthzOJ/jWUiWS5d j5IX0lCJ6y92Rn9M115wV/QKeEIfv8CFcdC1/OIFhuVr73+YOvyseO+Mu0KAbAcBSV zgu+S6ccuiB6HQvlF3lynyzNWnxc63g9ALvVBc52nrAW7yuNlOBH14dTpdjUSaz9hc JZRxBIagVHBEA== 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 AB3BC10775FC; Wed, 18 Mar 2026 17:43:57 +0000 (UTC) From: Vyacheslav Yurkov via B4 Relay Date: Wed, 18 Mar 2026 17:43:39 +0000 Subject: [PATCH 1/2] clk: Add clock controller guard 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: <20260318-feature-clock-guard-v1-1-6137cb4084b7@bruker.com> References: <20260318-feature-clock-guard-v1-0-6137cb4084b7@bruker.com> In-Reply-To: <20260318-feature-clock-guard-v1-0-6137cb4084b7@bruker.com> To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley 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=1773855836; l=10737; i=V.Yurkov.EXT@bruker.com; s=20260318; h=from:subject:message-id; bh=mEZVB/hxAT8vx7tR9ty8FdN1u+GnxDcrb/K2Fe5DAH0=; b=RWRbmfSVwn0heyex+IozkiKfkhbmCmitYJrzqkclLwfJUP9M+zqV7lgjx3hRJITVgnGYgK1IL sm1AgOu1LXKAhSe08D6XaBtP4A7y7xcVNx9fq8nD2qpK7C/+ICr5zEl 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 clock controller guard driver acts as clock provider and provides only one clock that consumers can check to make sure whether all other conditions are met in order to enable other peripehrals. This can be seen as 1:N clock relation, thus consumers care only about one clock and not about N. Signed-off-by: Vyacheslav Yurkov Signed-off-by: Vyacheslav Yurkov --- drivers/clk/Kconfig | 12 ++ drivers/clk/Makefile | 1 + drivers/clk/clkctrl-guard.c | 334 ++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 347 insertions(+) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 3d803b4cf5c1..4ce61014754b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -499,6 +499,18 @@ config COMMON_CLK_RPMI Support for clocks based on the clock service group defined by the RISC-V platform management interface (RPMI) specification. =20 +config CLKCTRL_GUARD + tristate "Clock controller guard" + depends on COMMON_CLK && OF + default n + help + A virtual clock controller that can be used on platfroms where + several clocks and GPIO signals are required to be enabled first + before peripheral initialization. The signals can be routed to t= his + controller, which simplifies peripheral driver's probe procedure. + + If unsure, say N. + source "drivers/clk/actions/Kconfig" source "drivers/clk/analogbits/Kconfig" source "drivers/clk/aspeed/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f7bce3951a30..7a3adc341c0b 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_CLKCTRL_GUARD) +=3D clkctrl-guard.o endif =20 # KUnit specific helpers diff --git a/drivers/clk/clkctrl-guard.c b/drivers/clk/clkctrl-guard.c new file mode 100644 index 000000000000..6978c36543de --- /dev/null +++ b/drivers/clk/clkctrl-guard.c @@ -0,0 +1,334 @@ +// 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 +#include + +#define MAX_INPUT_GPIO_COUNT 32 + +/** + * struct clkctrl_guard_priv - private state for the whole controller + * @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 clkctrl_guard_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_clkctrl_guard_priv(_hw) \ + container_of(_hw, struct clkctrl_guard_priv, output_hw_clk) + +static int clkctrl_guard_enable(struct clk_hw *hw) +{ + struct clkctrl_guard_priv *priv =3D to_clkctrl_guard_priv(hw); + + dev_dbg(priv->dev, "enable output clk '%s'\n", priv->output_clock_name); + + return clk_bulk_enable(priv->num_clks, priv->clks); +} + +static void clkctrl_guard_disable(struct clk_hw *hw) +{ + struct clkctrl_guard_priv *priv =3D to_clkctrl_guard_priv(hw); + + dev_dbg(priv->dev, "disable output clk '%s'\n", priv->output_clock_name); + + clk_bulk_disable(priv->num_clks, priv->clks); +} + +static int clkctrl_guard_prepare(struct clk_hw *hw) +{ + struct clkctrl_guard_priv *priv =3D to_clkctrl_guard_priv(hw); + + return clk_bulk_prepare(priv->num_clks, priv->clks); +} + +static void clkctrl_guard_unprepare(struct clk_hw *hw) +{ + struct clkctrl_guard_priv *priv =3D to_clkctrl_guard_priv(hw); + + clk_bulk_unprepare(priv->num_clks, priv->clks); +} + +static int is_gpio_ready(struct clkctrl_guard_priv *priv) +{ + unsigned long values[BITS_TO_LONGS(MAX_INPUT_GPIO_COUNT)]; + 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 clkctrl_guard_is_prepared(struct clk_hw *hw) +{ + struct clkctrl_guard_priv *priv =3D to_clkctrl_guard_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_prepared(hw_clk)) { + dev_dbg(priv->dev, "Clock %i (%s) is not ready", + i, priv->clks[i].id); + return -EBUSY; + } + } + + return 0; +} + +/* We have to implement it, but we are not going to control + * parent clock selection + */ +static u8 clkctrl_guard_get_parent(struct clk_hw *hw) +{ + return 0; +} + +static const struct clk_ops clkctrl_guard_ops =3D { + .enable =3D clkctrl_guard_enable, + .disable =3D clkctrl_guard_disable, + .prepare =3D clkctrl_guard_prepare, + .unprepare =3D clkctrl_guard_unprepare, + .is_prepared =3D clkctrl_guard_is_prepared, + .get_parent =3D clkctrl_guard_get_parent, +}; + +static int clkctrl_guard_parse_inputs(struct clkctrl_guard_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 clkctrl_guard_parse_gpios(struct clkctrl_guard_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, NULL, 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 > 32) { + 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 clkctrl_guard_parse_outputs(struct clkctrl_guard_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 &clkctrl_guard_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 clkctrl_guard_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct clkctrl_guard_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 clkctrl_guard_parse_inputs(priv); + if (ret) + return ret; + + ret =3D clkctrl_guard_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 clkctrl_guard_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 clkctrl_guard_remove(struct platform_device *pdev) +{ + dev_dbg(&pdev->dev, "removed\n"); +} + +static const struct of_device_id clkctrl_guard_of_match[] =3D { + { .compatible =3D "clock-controller-guard" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, clkctrl_guard_of_match); + +static struct platform_driver clkctrl_guard_driver =3D { + .probe =3D clkctrl_guard_probe, + .remove =3D clkctrl_guard_remove, + .driver =3D { + .name =3D "clock-controller-guard", + .of_match_table =3D clkctrl_guard_of_match, + }, +}; +module_platform_driver(clkctrl_guard_driver); + +MODULE_AUTHOR("Vyacheslav Yurkov "); +MODULE_DESCRIPTION("GPIO-controlled clock controller driver"); +MODULE_LICENSE("Dual BSD/GPL"); --=20 2.34.1 From nobody Mon Apr 6 16:48:29 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 27097346E40; Wed, 18 Mar 2026 17:43:58 +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=1773855838; cv=none; b=soxbP1bO29GPk6oUN/E1zSPAknXRbVL4HgBLvKmSyQJCeNAs3RFhr6w7HZ4dWok8bjczY43vIJfWx9/YoS0Qk9vldv+BhIiR7ReBqKHBKdjEWR3Oe4wRh94CBqDxHTivW5id8xmurIjdCtZFEF+SAS8+qJTtu1PQd0l0d2MNLV8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773855838; c=relaxed/simple; bh=SKqsviwo7A+gRl+aMrQwi20LwNBzCIOen4gxdDOVVEE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qQpzehiTkesVDUcaDTZ6II/DzOkOEXp2V1i7YS1jdP7+RfZNJbxtgHQrTHkwTAHeePysOxj86g/n1D3Ci6BFDHQcH4ouwT9pInjBqLWQiBVr7MFb8OVXAeQPVVayyyvctVZue7nGNdtFYtE/qDH64oOkgZo5hEqpdzuXRhm8IWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=q8lftdfx; 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="q8lftdfx" Received: by smtp.kernel.org (Postfix) with ESMTPS id C871FC2BCB3; Wed, 18 Mar 2026 17:43:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773855837; bh=SKqsviwo7A+gRl+aMrQwi20LwNBzCIOen4gxdDOVVEE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=q8lftdfxc3thx0Yp0eAVTNaPJgWVeglv+2vDzJRSJnhP5thiXRNp+m6HBmnHvzu/O 0ZA6Ax3VLfr/+n0lbhxSTrD4MSezAmEFKhIPY97rS99XLk+KKWJLC8pA/sFxDlPRmY SykHnzgTsKwijexMIc8x4Ji7kLa69W2H7YKBoTBvXasZIKBdTOcYurzduobF2YHrMm Xg2jDSpc9fqjoSNAcn6EE9aeof+Bi7H+iLnEnqr4HBwzCPS1AhKfDqiPwWeyKe7AcW aXF28bjh/6TV6Btir1w01lQC5DGJba9BG1zjBLrgj14cbdzxArutH+qhCww/u27KuR xATM7MtFPkqdA== 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 B9EA510775F9; Wed, 18 Mar 2026 17:43:57 +0000 (UTC) From: Vyacheslav Yurkov via B4 Relay Date: Wed, 18 Mar 2026 17:43:40 +0000 Subject: [PATCH 2/2] dt-bindings: Add clock guard DT description 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: <20260318-feature-clock-guard-v1-2-6137cb4084b7@bruker.com> References: <20260318-feature-clock-guard-v1-0-6137cb4084b7@bruker.com> In-Reply-To: <20260318-feature-clock-guard-v1-0-6137cb4084b7@bruker.com> To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley 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=1773855836; l=2408; i=V.Yurkov.EXT@bruker.com; s=20260318; h=from:subject:message-id; bh=nftM24g/uBu7svtXQ2MG9cVaqhavKUW1WxRDBq2fT/8=; b=X2/vy2XIiAWf10c3i4jfNnsT3rbtNRB5XzDMQ6dTUyDDEVRFiKnKtPk2VM1XG5imdC/j6VpsM ZWx52GXBR50C/jUU9qkf7h6U6EbGe+uhJ6GJ+vgvqvQTIzlOIf9Gnf+ 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 Describe device tree binding for virtual clock controller guard. Signed-off-by: Vyacheslav Yurkov Signed-off-by: Vyacheslav Yurkov --- .../bindings/clock/clock-controller-guard.yaml | 79 ++++++++++++++++++= ++++ 1 file changed, 79 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/clock-controller-guard= .yaml b/Documentation/devicetree/bindings/clock/clock-controller-guard.yaml new file mode 100644 index 000000000000..71c2d80de1f0 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/clock-controller-guard.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/clock/clock-controller-guard.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Clock Controller Guard + +maintainers: + - Vyacheslav Yurkov + +description: | + Clock controller that guards upstream clocks and/or GPIO + signals and exposes them as a single clock output. + +properties: + compatible: + const: clock-controller-guard + + "#clock-cells": + const: 1 + + clocks: + description: Input clocks that will be guarded. + minItems: 0 + + clock-names: Input clock names. + minItems: 0 + + clock-output-names: + description: Names of the clock provided by this controller. + minItems: 1 + items: + type: string + + gpios: + description: | + GPIOs used to control or guard the clocks. + minItems: 0 + maxItems: 32 + + gpio-names: + description: Names corresponding to each GPIO. + minItems: 0 + maxItems: 32 + + items: + type: string + +required: + - compatible + - "#clock-cells" +anyOf: + - required: + - clocks + - required: + - gpios +dependencies: + gpio-names: [gpios] + clock-names: [clocks] + +additionalProperties: false + +examples: + - | + clkctrl: clock-controller { + compatible =3D "clock-controller-guard"; + #clock-cells =3D <1>; + + clocks =3D <&clk0 0>, <&pll 0>; + + gpios =3D <&gpio0 4 GPIO_ACTIVE_HIGH>, + <&gpio0 5 GPIO_ACTIVE_HIGH>, + <&gpio1 2 GPIO_ACTIVE_LOW>; + + gpio-names =3D "gpio0", "gpio1", "gpio2"; + + clock-output-names =3D "clkout0"; + }; --=20 2.34.1