aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/clk-uclass.c48
-rw-r--r--drivers/core/device.c2
-rw-r--r--include/clk.h7
3 files changed, 48 insertions, 9 deletions
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 80346987b9d..9aa8537004a 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -178,7 +178,7 @@ bulk_get_err:
return ret;
}
-static int clk_set_default_parents(struct udevice *dev)
+static int clk_set_default_parents(struct udevice *dev, int stage)
{
struct clk clk, parent_clk;
int index;
@@ -214,8 +214,18 @@ static int clk_set_default_parents(struct udevice *dev)
return ret;
}
- ret = clk_set_parent(&clk, &parent_clk);
+ /* This is clk provider device trying to reparent itself
+ * It cannot be done right now but need to wait after the
+ * device is probed
+ */
+ if (stage == 0 && clk.dev == dev)
+ continue;
+
+ if (stage > 0 && clk.dev != dev)
+ /* do not setup twice the parent clocks */
+ continue;
+ ret = clk_set_parent(&clk, &parent_clk);
/*
* Not all drivers may support clock-reparenting (as of now).
* Ignore errors due to this.
@@ -233,7 +243,7 @@ static int clk_set_default_parents(struct udevice *dev)
return 0;
}
-static int clk_set_default_rates(struct udevice *dev)
+static int clk_set_default_rates(struct udevice *dev, int stage)
{
struct clk clk;
int index;
@@ -268,7 +278,19 @@ static int clk_set_default_rates(struct udevice *dev)
continue;
}
+ /* This is clk provider device trying to program itself
+ * It cannot be done right now but need to wait after the
+ * device is probed
+ */
+ if (stage == 0 && clk.dev == dev)
+ continue;
+
+ if (stage > 0 && clk.dev != dev)
+ /* do not setup twice the parent clocks */
+ continue;
+
ret = clk_set_rate(&clk, rates[index]);
+
if (ret < 0) {
debug("%s: failed to set rate on clock index %d (%ld) for %s\n",
__func__, index, clk.id, dev_read_name(dev));
@@ -281,7 +303,7 @@ fail:
return ret;
}
-int clk_set_defaults(struct udevice *dev)
+int clk_set_defaults(struct udevice *dev, int stage)
{
int ret;
@@ -294,11 +316,11 @@ int clk_set_defaults(struct udevice *dev)
debug("%s(%s)\n", __func__, dev_read_name(dev));
- ret = clk_set_default_parents(dev);
+ ret = clk_set_default_parents(dev, stage);
if (ret)
return ret;
- ret = clk_set_default_rates(dev);
+ ret = clk_set_default_rates(dev, stage);
if (ret < 0)
return ret;
@@ -673,7 +695,21 @@ void devm_clk_put(struct udevice *dev, struct clk *clk)
WARN_ON(rc);
}
+int clk_uclass_post_probe(struct udevice *dev)
+{
+ /*
+ * when a clock provider is probed. Call clk_set_defaults()
+ * also after the device is probed. This takes care of cases
+ * where the DT is used to setup default parents and rates
+ * using assigned-clocks
+ */
+ clk_set_defaults(dev, 1);
+
+ return 0;
+}
+
UCLASS_DRIVER(clk) = {
.id = UCLASS_CLK,
.name = "clk",
+ .post_probe = clk_uclass_post_probe,
};
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 95f26efdd3b..8eabaf8b553 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -423,7 +423,7 @@ int device_probe(struct udevice *dev)
* Process 'assigned-{clocks/clock-parents/clock-rates}'
* properties
*/
- ret = clk_set_defaults(dev);
+ ret = clk_set_defaults(dev, 0);
if (ret)
goto fail;
}
diff --git a/include/clk.h b/include/clk.h
index 9be3264113f..a5ee53d94aa 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -244,10 +244,13 @@ static inline int clk_release_all(struct clk *clk, int count)
*
* @dev: A device to process (the ofnode associated with this device
* will be processed).
+ * @stage: A integer. 0 indicates that this is called before the device
+ * is probed. 1 indicates that this is called just after the
+ * device has been probed
*/
-int clk_set_defaults(struct udevice *dev);
+int clk_set_defaults(struct udevice *dev, int stage);
#else
-static inline int clk_set_defaults(struct udevice *dev)
+static inline int clk_set_defaults(struct udevice *dev, int stage)
{
return 0;
}