summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDario Binacchi <dariobin@libero.it>2020-06-03 15:36:25 +0200
committerLukasz Majewski <lukma@denx.de>2020-08-24 11:03:26 +0200
commit12d152620d9de9ea966e1136b7f48f641c981bac (patch)
treeae79e25d72749366f6f39d49c47594168f37722b
parente3b5d74c778a8782f763412679ca4c3cb2d496c3 (diff)
downloadu-boot-12d152620d9de9ea966e1136b7f48f641c981bac.tar.gz
u-boot-12d152620d9de9ea966e1136b7f48f641c981bac.tar.xz
u-boot-12d152620d9de9ea966e1136b7f48f641c981bac.zip
clk: ccf: mux: change the get_rate helper
The previous version of the get_rate helper does not work if the mux clock parent is changed after the probe. This error has not been detected because this condition has not been tested. The error occurs because the set_parent helper does not change the parent of the clock device but only the clock selection register. Since changing the parent of a probed device can be tricky, the new version of the get_rate helper provides the rate of the selected clock and not that of the parent. Signed-off-by: Dario Binacchi <dariobin@libero.it>
-rw-r--r--drivers/clk/clk-mux.c26
-rw-r--r--test/dm/clk_ccf.c24
2 files changed, 49 insertions, 1 deletions
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index e10baaf83b..ec8017b7d2 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -149,8 +149,32 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
return 0;
}
+static ulong clk_mux_get_rate(struct clk *clk)
+{
+ struct clk_mux *mux = to_clk_mux(clk_dev_binded(clk) ?
+ dev_get_clk_ptr(clk->dev) : clk);
+ struct udevice *parent;
+ struct clk *pclk;
+ int err, index;
+
+ index = clk_mux_get_parent(clk);
+ if (index >= mux->num_parents)
+ return -EFAULT;
+
+ err = uclass_get_device_by_name(UCLASS_CLK, mux->parent_names[index],
+ &parent);
+ if (err)
+ return err;
+
+ pclk = dev_get_clk_ptr(parent);
+ if (!pclk)
+ return -ENODEV;
+
+ return clk_get_rate(pclk);
+}
+
const struct clk_ops clk_mux_ops = {
- .get_rate = clk_generic_get_rate,
+ .get_rate = clk_mux_get_rate,
.set_parent = clk_mux_set_parent,
};
diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index 242d2d756f..32bc4d2b8a 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -59,6 +59,18 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
rate = clk_get_parent_rate(clk);
ut_asserteq(rate, 60000000);
+ rate = clk_get_rate(clk);
+ ut_asserteq(rate, 60000000);
+
+ ret = clk_get_by_id(SANDBOX_CLK_PLL3_80M, &pclk);
+ ut_assertok(ret);
+
+ ret = clk_set_parent(clk, pclk);
+ ut_assertok(ret);
+
+ rate = clk_get_rate(clk);
+ ut_asserteq(rate, 80000000);
+
ret = clk_get_by_id(SANDBOX_CLK_USDHC2_SEL, &clk);
ut_assertok(ret);
ut_asserteq_str("usdhc2_sel", clk->dev->name);
@@ -71,6 +83,18 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
ut_asserteq_str("pll3_80m", pclk->dev->name);
ut_asserteq(CLK_SET_RATE_PARENT, pclk->flags);
+ rate = clk_get_rate(clk);
+ ut_asserteq(rate, 80000000);
+
+ ret = clk_get_by_id(SANDBOX_CLK_PLL3_60M, &pclk);
+ ut_assertok(ret);
+
+ ret = clk_set_parent(clk, pclk);
+ ut_assertok(ret);
+
+ rate = clk_get_rate(clk);
+ ut_asserteq(rate, 60000000);
+
/* Test the composite of CCF */
ret = clk_get_by_id(SANDBOX_CLK_I2C, &clk);
ut_assertok(ret);