summaryrefslogtreecommitdiff
path: root/drivers/clk
diff options
context:
space:
mode:
authorClaudiu Beznea <claudiu.beznea@microchip.com>2020-09-07 17:46:36 +0300
committerEugen Hristev <eugen.hristev@microchip.com>2020-09-22 11:27:18 +0300
commitb364134f87a2b3d021746b86b1f81278b15fa296 (patch)
tree374ad73dfa7f7b5cd27c0bbaeb189a465596b185 /drivers/clk
parent9a5d59dfc6475c4770bf702e4f30e338499310fd (diff)
downloadu-boot-b364134f87a2b3d021746b86b1f81278b15fa296.tar.xz
clk: get clock pointer before proceeding
clk_get_by_indexed_prop() retrieves a clock with dev member being set with the pointer to the udevice for the clock controller driver. But in case of CCF each clock driver has set in dev member the reference to its parent (the root of the clock tree is a fixed clock, every node in clock tree is a clock registered with clk_register()). In this case the subsequent operations like dev_get_clk_ptr() on clocks retrieved by clk_get_by_indexed_prop() will fail. For this, get the pointer to the proper clock registered (with clk_register()) using clk_get_by_id() before proceeding. Fixes: 1d7993d1d0ef ("clk: Port Linux common clock framework [CCF] for imx6q to U-boot (tag: v5.1.12)") Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers/clk')
-rw-r--r--drivers/clk/clk-uclass.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index b8538f342a..4076535271 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -188,9 +188,26 @@ bulk_get_err:
return ret;
}
+static struct clk *clk_set_default_get_by_id(struct clk *clk)
+{
+ struct clk *c = clk;
+
+ if (CONFIG_IS_ENABLED(CLK_CCF)) {
+ int ret = clk_get_by_id(clk->id, &c);
+
+ if (ret) {
+ debug("%s(): could not get parent clock pointer, id %lu\n",
+ __func__, clk->id);
+ ERR_PTR(ret);
+ }
+ }
+
+ return c;
+}
+
static int clk_set_default_parents(struct udevice *dev, int stage)
{
- struct clk clk, parent_clk;
+ struct clk clk, parent_clk, *c, *p;
int index;
int num_parents;
int ret;
@@ -216,6 +233,10 @@ static int clk_set_default_parents(struct udevice *dev, int stage)
return ret;
}
+ p = clk_set_default_get_by_id(&parent_clk);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
ret = clk_get_by_indexed_prop(dev, "assigned-clocks",
index, &clk);
if (ret) {
@@ -235,7 +256,11 @@ static int clk_set_default_parents(struct udevice *dev, int stage)
/* do not setup twice the parent clocks */
continue;
- ret = clk_set_parent(&clk, &parent_clk);
+ c = clk_set_default_get_by_id(&clk);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+
+ ret = clk_set_parent(c, p);
/*
* Not all drivers may support clock-reparenting (as of now).
* Ignore errors due to this.
@@ -255,7 +280,7 @@ static int clk_set_default_parents(struct udevice *dev, int stage)
static int clk_set_default_rates(struct udevice *dev, int stage)
{
- struct clk clk;
+ struct clk clk, *c;
int index;
int num_rates;
int size;
@@ -299,7 +324,11 @@ static int clk_set_default_rates(struct udevice *dev, int stage)
/* do not setup twice the parent clocks */
continue;
- ret = clk_set_rate(&clk, rates[index]);
+ c = clk_set_default_get_by_id(&clk);
+ if (IS_ERR(c))
+ return PTR_ERR(c);
+
+ ret = clk_set_rate(c, rates[index]);
if (ret < 0) {
debug("%s: failed to set rate on clock index %d (%ld) for %s\n",