diff mbox series

[4/4] clk: ccf: mux: change the get_rate helper

Message ID 20200502155834.27481-5-dariobin@libero.it
State Accepted
Commit 12d152620d9de9ea966e1136b7f48f641c981bac
Headers show
Series change the clk-mux get_rate helper | expand

Commit Message

Dario Binacchi May 2, 2020, 3:58 p.m. UTC
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 at libero.it>

---

 drivers/clk/clk-mux.c | 26 +++++++++++++++++++++++++-
 test/dm/clk_ccf.c     | 24 ++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

Comments

Simon Glass May 3, 2020, 2:26 a.m. UTC | #1
+Stephen Warren

On Sat, 2 May 2020 at 09:59, Dario Binacchi <dariobin at libero.it> wrote:
>
> 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 at libero.it>
>
> ---
>
>  drivers/clk/clk-mux.c | 26 +++++++++++++++++++++++++-
>  test/dm/clk_ccf.c     | 24 ++++++++++++++++++++++++
>  2 files changed, 49 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg at chromium.org>
diff mbox series

Patch

diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 8f85e84ae9..1f2dab647f 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -152,8 +152,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 ae3a4d8a76..bf99776ac1 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -46,6 +46,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);
@@ -56,6 +68,18 @@  static int dm_test_clk_ccf(struct unit_test_state *uts)
 	pclk = clk_get_parent(clk);
 	ut_asserteq_str("pll3_80m", pclk->dev->name);
 
+	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);