From af96395a821c4c87e2026351b5d05de9726df1ef Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 27 Oct 2025 17:33:07 +0100 Subject: [PATCH] clk: renesas: Introduce temporary compound clock for SCP compatibility 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 --- drivers/clk/renesas/Makefile | 4 ++ drivers/clk/renesas/compound-clock.c | 92 ++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 drivers/clk/renesas/compound-clock.c diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 6c742553091..354035baf2d 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -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 index 00000000000..499a2598833 --- /dev/null +++ b/drivers/clk/renesas/compound-clock.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2025 Marek Vasut + */ + +#define LOG_CATEGORY UCLASS_CLK + +#include +#include +#include +#include +#include + +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, +}; -- 2.47.3