MediaTek clock trees can reference parents provided by a different clock
controller. The provider registry is populated when each controller
probes, so an early consumer can request a parent before its provider has
been registered.

When lookup misses, find the MediaTek clock device whose operations and
clock-tree type match the requested provider, then probe that device.
This removes the probe-order dependency without probing unrelated clock
controllers or treating a driver's bind callback as a type marker.

Co-developed-by: David Lechner <[email protected]>
Signed-off-by: David Lechner <[email protected]>
Signed-off-by: Carlo Caione <[email protected]>
---
 drivers/clk/mediatek/clk-mtk.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 1da89b3cc48..9d2f2414b27 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -9,6 +9,7 @@
 #include <clk-uclass.h>
 #include <div64.h>
 #include <dm.h>
+#include <dm/device-internal.h>
 #include <asm/io.h>
 #include <linux/bitops.h>
 #include <linux/delay.h>
@@ -60,6 +61,40 @@ static struct udevice *mtk_clk_tree_get_provider(enum 
mtk_clk_tree_type type)
        if (!mtk_clk_tree_type_is_provider(type))
                return NULL;
 
+       if (!mtk_clk_providers[type]) {
+               struct udevice *dev;
+               struct uclass *uc;
+               int ret;
+
+               /* Lazily probe and register the requested provider. */
+               ret = uclass_get(UCLASS_CLK, &uc);
+               if (ret)
+                       return ERR_PTR(ret);
+
+               uclass_foreach_dev(dev, uc) {
+                       const struct mtk_clk_tree *tree;
+                       const void *ops;
+
+                       ops = dev_get_driver_ops(dev);
+                       if (ops != &mtk_clk_apmixedsys_ops &&
+                           ops != &mtk_clk_fixed_pll_ops &&
+                           ops != &mtk_clk_topckgen_ops &&
+                           ops != &mtk_clk_infrasys_ops)
+                               continue;
+
+                       tree = (const void *)dev_get_driver_data(dev);
+                       if (tree->type != type)
+                               continue;
+
+                       /* Probe will add it to mtk_clk_providers[type]. */
+                       ret = device_probe(dev);
+                       if (ret)
+                               return ERR_PTR(ret);
+
+                       break;
+               }
+       }
+
        return mtk_clk_providers[type] ?: ERR_PTR(-ENOENT);
 }
 

-- 
2.55.0

Reply via email to