MediaTek splits its clock controllers into separate DM devices
(apmixedsys, topckgen, infracfg), and a clock in one controller often
has its parent in another. Cross-controller parent lookup goes through a
small provider registry that each controller populates when it probes, so
a provider's registry entry only exists once that provider has probed.

Providers set DM_FLAG_PROBE_AFTER_BIND to be probed early, but that flag
only orders a device against its own bind; it does not guarantee that
every provider peer has been probed before an unrelated early consumer
requests a parent rate.

Concretely, in the SPL boot flow:

  1. The MMC device needs its clock and probes early.
  2. That probes topckgen, which registers itself as a provider.
  3. The MMC source is a topckgen mux whose parent is a PLL in apmixedsys.
  4. apmixedsys has not been probed yet, so its registry slot is NULL.
  5. The parent lookup returns -ENOENT and MMC is configured with an
     invalid source rate.

When a parent type is not registered yet, probe the MediaTek clock
drivers that declare the common provider bind callback. This preserves
the small provider registry while making parent lookup independent of
peer probe order.

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

diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 61d718f162d..3d37d190982 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>
@@ -57,9 +58,35 @@ static enum mtk_clk_tree_type 
mtk_clk_tree_type_from_parent_flags(u16 flags)
 
 static struct udevice *mtk_clk_tree_get_provider(enum mtk_clk_tree_type type)
 {
+       struct uclass *uc;
+       struct udevice *dev;
+       int ret;
+
        if (!mtk_clk_tree_type_is_provider(type))
                return NULL;
 
+       if (!mtk_clk_providers[type]) {
+               ret = uclass_get(UCLASS_CLK, &uc);
+               if (ret)
+                       return ERR_PTR(ret);
+
+               /*
+                * An early consumer can be probed before all provider peers
+                * marked for automatic probing have been visited.
+                */
+               uclass_foreach_dev(dev, uc) {
+                       if (dev->driver->bind != mtk_common_clk_parent_bind)
+                               continue;
+
+                       ret = device_probe(dev);
+                       if (ret)
+                               debug("Failed to probe clock device: %d\n", 
ret);
+
+                       if (mtk_clk_providers[type])
+                               break;
+               }
+       }
+
        return mtk_clk_providers[type] ?: ERR_PTR(-ENOENT);
 }
 

---
base-commit: d0c49353a648e135f269a2953dc9326505ba87de
change-id: 20260723-ccaione-upstream-fix-clk-probe-24a27764927a

Best regards,
--  
Carlo Caione <[email protected]>

Reply via email to