clk: renesas: Introduce temporary compound clock for SCP compatibility
authorMarek Vasut <marek.vasut+renesas@mailbox.org>
Mon, 27 Oct 2025 16:33:07 +0000 (17:33 +0100)
committerMarek Vasut <marek.vasut+renesas@mailbox.org>
Tue, 2 Dec 2025 23:17:15 +0000 (00:17 +0100)
The current state of SCP on Renesas R-Car Gen5 is not yet final and
is still missing full clock control, the clock control is exposed as
separate enable/disable and rate controls.

Temporarily introduce custom local compound clock, which are used as
an adaptation layer between U-Boot clock tree and current state of
SCP, and which bind two SCP clock into a single compound clock, which
provides both enable/disable and rate controls.

This is mainly meant to be used by SD/eMMC controller, to allow the
driver to both turn its clock on and off, and also obtain the current
clock rate. This is going to be removed once the SCP clock protocol
solidifies.

Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
drivers/clk/renesas/Makefile
drivers/clk/renesas/compound-clock.c [new file with mode: 0644]

index 6c74255..354035b 100644 (file)
@@ -26,3 +26,7 @@ obj-$(CONFIG_CLK_R8A779H0) += r8a779h0-cpg-mssr.o
 obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
 obj-$(CONFIG_CLK_RZG2L) += rzg2l-cpg.o
 obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o
+
+# Temporary stub clock used for SCP compatibility.
+# This is going to be removed once SCP solidifies.
+obj-$(CONFIG_R8A78000) += compound-clock.o
diff --git a/drivers/clk/renesas/compound-clock.c b/drivers/clk/renesas/compound-clock.c
new file mode 100644 (file)
index 0000000..499a259
--- /dev/null
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2025 Marek Vasut <marek.vasut+renesas@mailbox.org>
+ */
+
+#define LOG_CATEGORY UCLASS_CLK
+
+#include <clk-uclass.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <linux/clk-provider.h>
+#include <log.h>
+
+struct clk_compound_rate {
+       struct clk clk;         /* This clock */
+       struct clk mdlc;        /* MDLC parent module clock */
+       struct clk per;         /* Peripheral parent clock */
+};
+
+static struct clk_compound_rate *to_clk_compound_rate(struct clk *clk)
+{
+       return (struct clk_compound_rate *)dev_get_plat(clk->dev);
+}
+
+static int clk_compound_rate_enable(struct clk *clk)
+{
+       struct clk_compound_rate *cc = to_clk_compound_rate(clk);
+
+       return clk_enable(&cc->mdlc);
+}
+
+static int clk_compound_rate_disable(struct clk *clk)
+{
+       struct clk_compound_rate *cc = to_clk_compound_rate(clk);
+
+       return clk_disable(&cc->mdlc);
+}
+
+static ulong clk_compound_rate_get_rate(struct clk *clk)
+{
+       struct clk_compound_rate *cc = to_clk_compound_rate(clk);
+
+       return clk_get_rate(&cc->per);
+}
+
+static ulong clk_compound_rate_set_rate(struct clk *clk, ulong rate)
+{
+       return 0;       /* Set rate is not forwarded to SCP */
+}
+
+const struct clk_ops clk_compound_rate_ops = {
+       .enable         = clk_compound_rate_enable,
+       .disable        = clk_compound_rate_disable,
+       .get_rate       = clk_compound_rate_get_rate,
+       .set_rate       = clk_compound_rate_set_rate,
+};
+
+static int clk_compound_rate_of_to_plat(struct udevice *dev)
+{
+       struct clk_compound_rate *cc = (struct clk_compound_rate *)dev_get_plat(dev);
+       struct clk *clk = &cc->clk;
+       int ret;
+
+       clk->dev = dev;
+       clk->id = CLK_ID(dev, 0);
+       clk->enable_count = 0;
+
+       ret = clk_get_by_index(dev, 0, &cc->mdlc);
+       if (ret)
+               return ret;
+
+       ret = clk_get_by_index(dev, 1, &cc->per);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static const struct udevice_id clk_compound_rate_match[] = {
+       { .compatible = "renesas,compound-clock", },
+       { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(renesas_compound_clock) = {
+       .name = "compound-clock",
+       .id = UCLASS_CLK,
+       .of_match = clk_compound_rate_match,
+       .of_to_plat = clk_compound_rate_of_to_plat,
+       .plat_auto      = sizeof(struct clk_compound_rate),
+       .ops = &clk_compound_rate_ops,
+       .flags = DM_FLAG_PRE_RELOC,
+};