Merge tag 'clk-2024.01-rc5' of https://source.denx.de/u-boot/custodians/u-boot-clk

clock changes for u-boot/master

This has some clock fixes which should go in before the release. It's a bit
late in the cycle, but most of these have tests to go along with them.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index c719779..a3a865d 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -631,9 +631,10 @@
 		clocks = <&clk_fixed>,
 			 <&clk_sandbox 1>,
 			 <&clk_sandbox 0>,
+			 <&ccf 11>,
 			 <&clk_sandbox 3>,
 			 <&clk_sandbox 2>;
-		clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
+		clock-names = "fixed", "i2c", "spi", "i2c_root", "uart2", "uart1";
 	};
 
 	clk-test2 {
@@ -654,6 +655,7 @@
 
 	ccf: clk-ccf {
 		compatible = "sandbox,clk-ccf";
+		#clock-cells = <1>;
 	};
 
 	efi-media {
diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
index df7156f..1daf2e7 100644
--- a/arch/sandbox/include/asm/clk.h
+++ b/arch/sandbox/include/asm/clk.h
@@ -39,6 +39,7 @@
 	SANDBOX_CLK_TEST_ID_FIXED,
 	SANDBOX_CLK_TEST_ID_SPI,
 	SANDBOX_CLK_TEST_ID_I2C,
+	SANDBOX_CLK_TEST_ID_I2C_ROOT,
 	SANDBOX_CLK_TEST_ID_DEVM1,
 	SANDBOX_CLK_TEST_ID_DEVM2,
 	SANDBOX_CLK_TEST_ID_DEVM_NULL,
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index 6eb2b81..d2e5a1a 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -66,7 +66,7 @@
 	const struct clk_ops *rate_ops = composite->rate_ops;
 	struct clk *clk_rate = composite->rate;
 
-	if (rate && rate_ops)
+	if (rate && rate_ops && rate_ops->set_rate)
 		return rate_ops->set_rate(clk_rate, rate);
 	else
 		return clk_get_rate(clk);
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 3b5e3f9..3e9d68f 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -640,6 +640,7 @@
 	if (CONFIG_IS_ENABLED(CLK_CCF)) {
 		/* Take id 0 as a non-valid clk, such as dummy */
 		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
+			ops = clk_dev_ops(clkp->dev);
 			if (clkp->enable_count) {
 				clkp->enable_count++;
 				return 0;
@@ -699,6 +700,7 @@
 
 	if (CONFIG_IS_ENABLED(CLK_CCF)) {
 		if (clk->id && !clk_get_by_id(clk->id, &clkp)) {
+			ops = clk_dev_ops(clkp->dev);
 			if (clkp->flags & CLK_IS_CRITICAL)
 				return 0;
 
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a5a3461..6ede1b4 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -18,17 +18,19 @@
 int clk_register(struct clk *clk, const char *drv_name,
 		 const char *name, const char *parent_name)
 {
-	struct udevice *parent;
+	struct udevice *parent = NULL;
 	struct driver *drv;
 	int ret;
 
-	ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, &parent);
-	if (ret) {
-		log_err("%s: failed to get %s device (parent of %s)\n",
-			__func__, parent_name, name);
-	} else {
-		log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, name,
-			  parent->name, parent);
+	if (parent_name) {
+		ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, &parent);
+		if (ret) {
+			log_err("%s: failed to get %s device (parent of %s)\n",
+				__func__, parent_name, name);
+		} else {
+			log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, name,
+				  parent->name, parent);
+		}
 	}
 
 	drv = lists_driver_lookup_name(drv_name);
diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c
index fedcdd4..38184e2 100644
--- a/drivers/clk/clk_sandbox_ccf.c
+++ b/drivers/clk/clk_sandbox_ccf.c
@@ -284,6 +284,7 @@
 U_BOOT_DRIVER(sandbox_clk_ccf) = {
 	.name = "sandbox_clk_ccf",
 	.id = UCLASS_CLK,
+	.ops = &ccf_clk_ops,
 	.probe = sandbox_clk_ccf_probe,
 	.of_match = sandbox_clk_ccf_test_ids,
 };
diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
index 5807a45..c695b69 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -15,6 +15,7 @@
 	[SANDBOX_CLK_TEST_ID_FIXED] = "fixed",
 	[SANDBOX_CLK_TEST_ID_SPI] = "spi",
 	[SANDBOX_CLK_TEST_ID_I2C] = "i2c",
+	[SANDBOX_CLK_TEST_ID_I2C_ROOT] = "i2c_root",
 };
 
 int sandbox_clk_test_get(struct udevice *dev)
diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index e4ebb93..61dad8d 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -19,16 +19,18 @@
 static int dm_test_clk_ccf(struct unit_test_state *uts)
 {
 	struct clk *clk, *pclk;
-	struct udevice *dev;
+	struct udevice *dev, *test_dev;
 	long long rate;
 	int ret;
 #if CONFIG_IS_ENABLED(CLK_CCF)
+	struct clk clk_ccf;
 	const char *clkname;
 	int clkid, i;
 #endif
 
 	/* Get the device using the clk device */
 	ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-ccf", &dev));
+	ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", &test_dev));
 
 	/* Test for clk_get_by_id() */
 	ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, &clk);
@@ -63,6 +65,9 @@
 	rate = clk_get_parent_rate(clk);
 	ut_asserteq(rate, 60000000);
 
+	rate = clk_set_rate(clk, 60000000);
+	ut_asserteq(rate, -ENOSYS);
+
 	rate = clk_get_rate(clk);
 	ut_asserteq(rate, 60000000);
 
@@ -87,6 +92,9 @@
 	ut_asserteq_str("pll3_80m", pclk->dev->name);
 	ut_asserteq(CLK_SET_RATE_PARENT, pclk->flags);
 
+	rate = clk_set_rate(clk, 80000000);
+	ut_asserteq(rate, -ENOSYS);
+
 	rate = clk_get_rate(clk);
 	ut_asserteq(rate, 80000000);
 
@@ -108,13 +116,23 @@
 	rate = clk_get_rate(clk);
 	ut_asserteq(rate, 60000000);
 
+	rate = clk_set_rate(clk, 60000000);
+	ut_asserteq(rate, 60000000);
+
 #if CONFIG_IS_ENABLED(CLK_CCF)
 	/* Test clk tree enable/disable */
+
+	ret = clk_get_by_index(test_dev, SANDBOX_CLK_TEST_ID_I2C_ROOT, &clk_ccf);
+	ut_assertok(ret);
+	ut_asserteq_str("clk-ccf", clk_ccf.dev->name);
+	ut_asserteq(clk_ccf.id, SANDBOX_CLK_I2C_ROOT);
+
 	ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, &clk);
 	ut_assertok(ret);
 	ut_asserteq_str("i2c_root", clk->dev->name);
+	ut_asserteq(clk->id, SANDBOX_CLK_I2C_ROOT);
 
-	ret = clk_enable(clk);
+	ret = clk_enable(&clk_ccf);
 	ut_assertok(ret);
 
 	ret = sandbox_clk_enable_count(clk);