[PATCH 2/2] clk: imx95-blk-ctrl: Resolve scmi clk before using it

Peng Fan (OSS) peng.fan at oss.nxp.com
Thu Dec 11 09:31:44 CET 2025


From: Peng Fan <peng.fan at nxp.com>

With commit 3547e315c188 ("clk: scmi: Defer issue of SCMI_CLOCK_ATTRIBUTES"),
there is error log:
imx95_blkctrl_clk syscon at 4c0100c0: Failed to resolve clk hsiopll

clk_register use parent name "hsiopll", however this name does not
exist. The valid name at the moment is "scmi-[0-9*]". So need to first
resolve the scmi clk before using it.

Fixes: 3547e315c188 ("clk: scmi: Defer issue of SCMI_CLOCK_ATTRIBUTES")
Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/clk/imx/Makefile            |  6 ++++-
 drivers/clk/imx/clk-imx95-blkctrl.c | 48 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
index f2fd6ff8ca0..619a523cf96 100644
--- a/drivers/clk/imx/Makefile
+++ b/drivers/clk/imx/Makefile
@@ -25,4 +25,8 @@ obj-$(CONFIG_$(PHASE_)CLK_IMX93) += clk-imx93.o clk-fracn-gppll.o \
 obj-$(CONFIG_$(PHASE_)CLK_IMXRT1020) += clk-imxrt1020.o
 obj-$(CONFIG_$(PHASE_)CLK_IMXRT1050) += clk-imxrt1050.o
 obj-$(CONFIG_$(PHASE_)CLK_IMXRT1170) += clk-imxrt1170.o
-obj-$(CONFIG_CLK_IMX95_BLKCTRL) += clk-imx95-blkctrl.o
+
+ifdef CONFIG_CLK_IMX95_BLKCTRL
+ccflags-y += -I$(srctree)/dts/upstream/src/arm64/freescale/
+obj-y += clk-imx95-blkctrl.o
+endif
diff --git a/drivers/clk/imx/clk-imx95-blkctrl.c b/drivers/clk/imx/clk-imx95-blkctrl.c
index 3e6f53b4a16..f6563539402 100644
--- a/drivers/clk/imx/clk-imx95-blkctrl.c
+++ b/drivers/clk/imx/clk-imx95-blkctrl.c
@@ -6,9 +6,11 @@
 
 #include <asm/io.h>
 #include <clk-uclass.h>
+#include <clk/scmi.h>
 #include <dm.h>
 #include <dm/device_compat.h>
 #include <dt-bindings/clock/nxp,imx95-clock.h>
+#include <imx95-clock.h>
 #include <linux/clk-provider.h>
 
 #include "clk.h"
@@ -19,9 +21,11 @@ enum {
 	CLK_MUX,
 };
 
+#define MAX_NUM_PARENTS 4
 struct imx95_blk_ctl_clk_dev_data {
 	const char *name;
 	const char * const *parent_names;
+	u32 clk_parent_ids[4];
 	u32 num_parents;
 	u32 reg;
 	u32 bit_idx;
@@ -41,6 +45,7 @@ static const struct imx95_blk_ctl_clk_dev_data hsio_blk_ctl_clk_dev_data[] = {
 	[0] = {
 		.name = "hsio_blk_ctl_clk",
 		.parent_names = (const char *[]){ "hsiopll", },
+		.clk_parent_ids = { IMX95_CLK_HSIOPLL, },
 		.num_parents = 1,
 		.reg = 0,
 		.bit_idx = 6,
@@ -59,6 +64,7 @@ static const struct imx95_blk_ctl_clk_dev_data imx95_lvds_clk_dev_data[] = {
 	[IMX95_CLK_DISPMIX_LVDS_PHY_DIV] = {
 		.name = "ldb_phy_div",
 		.parent_names = (const char *[]){ "ldbpll", },
+		.clk_parent_ids = { IMX95_CLK_LDBPLL, },
 		.num_parents = 1,
 		.reg = 0,
 		.bit_idx = 0,
@@ -69,6 +75,7 @@ static const struct imx95_blk_ctl_clk_dev_data imx95_lvds_clk_dev_data[] = {
 	[IMX95_CLK_DISPMIX_LVDS_CH0_GATE] = {
 		.name = "lvds_ch0_gate",
 		.parent_names = (const char *[]){ "ldb_phy_div", },
+		.clk_parent_ids = { ~0U, },
 		.num_parents = 1,
 		.reg = 0,
 		.bit_idx = 1,
@@ -79,6 +86,7 @@ static const struct imx95_blk_ctl_clk_dev_data imx95_lvds_clk_dev_data[] = {
 	[IMX95_CLK_DISPMIX_LVDS_CH1_GATE] = {
 		.name = "lvds_ch1_gate",
 		.parent_names = (const char *[]){ "ldb_phy_div", },
+		.clk_parent_ids = { ~0U, },
 		.num_parents = 1,
 		.reg = 0,
 		.bit_idx = 2,
@@ -89,6 +97,7 @@ static const struct imx95_blk_ctl_clk_dev_data imx95_lvds_clk_dev_data[] = {
 	[IMX95_CLK_DISPMIX_PIX_DI0_GATE] = {
 		.name = "lvds_di0_gate",
 		.parent_names = (const char *[]){ "ldb_pll_div7", },
+		.clk_parent_ids = { ~0U, },
 		.num_parents = 1,
 		.reg = 0,
 		.bit_idx = 3,
@@ -99,6 +108,7 @@ static const struct imx95_blk_ctl_clk_dev_data imx95_lvds_clk_dev_data[] = {
 	[IMX95_CLK_DISPMIX_PIX_DI1_GATE] = {
 		.name = "lvds_di1_gate",
 		.parent_names = (const char *[]){ "ldb_pll_div7", },
+		.clk_parent_ids = { ~0U, },
 		.num_parents = 1,
 		.reg = 0,
 		.bit_idx = 4,
@@ -116,10 +126,11 @@ static const struct imx95_blk_ctl_dev_data imx95_lvds_csr_dev_data = {
 
 static int imx95_blkctrl_clk_probe(struct udevice *dev)
 {
-	int i;
+	int i, j, ret;
 	void __iomem *addr;
 	struct imx95_blk_ctl_dev_data *dev_data = (void *)dev_get_driver_data(dev);
 	const struct imx95_blk_ctl_clk_dev_data *clk_dev_data;
+	struct udevice *scmi_clk_dev;
 
 	addr = dev_read_addr_ptr(dev);
 	if (addr == (void *)FDT_ADDR_T_NONE) {
@@ -132,7 +143,42 @@ static int imx95_blkctrl_clk_probe(struct udevice *dev)
 		return -EINVAL;
 	}
 
+	ret = uclass_get_device_by_name(UCLASS_CLK, "protocol at 14", &scmi_clk_dev);
+	if (ret) {
+		dev_err(dev, "Failed to find procotol at 14\n");
+		return ret;
+	}
+
 	clk_dev_data = dev_data->clk_dev_data;
+	for (i = 0; i < dev_data->num_clks; i++) {
+		ulong id;
+		if (clk_dev_data[i].clk_type == CLK_GATE ||
+		    clk_dev_data[i].clk_type == CLK_DIVIDER) {
+			if (clk_dev_data[i].clk_parent_ids[0] == ~0U)
+				continue;
+
+			id = CLK_ID(scmi_clk_dev, clk_dev_data[i].clk_parent_ids[0]);
+			ret = scmi_clk_resolve_attr(id, NULL);
+			if (ret) {
+				dev_err(dev, "Failed to resolve clk %s\n",
+					clk_dev_data[i].parent_names[0]);
+				return ret;
+			}
+		} else if (clk_dev_data[i].clk_type == CLK_MUX) {
+			for (j = 0; j < clk_dev_data[i].num_parents; j++) {
+				if (clk_dev_data[i].clk_parent_ids[j] == ~0U)
+					continue;
+				id = CLK_ID(scmi_clk_dev, clk_dev_data[i].clk_parent_ids[j]);
+				ret = scmi_clk_resolve_attr(id, NULL);
+				if (ret) {
+					dev_err(dev, "Failed to resolve clk %s\n",
+						clk_dev_data[i].parent_names[0]);
+					return ret;
+				}
+			}
+		}
+	}
+
 	for (i = 0; i < dev_data->num_clks; i++) {
 		if (clk_dev_data[i].clk_type == CLK_GATE) {
 			dev_clk_dm(dev, i,

-- 
2.51.0



More information about the U-Boot mailing list