In Linux, CCF quite aggressively attempts to reparent orphan clocks, doing so every time a new clock is registered. This makes sense in a dynamic system where modules could be loaded at any point, but is much less necessary in U-Boot.
In U-Boot we don't have to worry about kernel modules being loaded later during boot, we also probe clock provider devices on-demand. As a result there are only two cases where we will fail to find a parent clock: either the clock provider device doesn't actually provide any clocks in which case the clock will be an orphan forever, or the parent clock is provided by the same device and just hasn't been registered yet, in which case it will be available when the device registers itself as an of_provider after all of its clocks have been registerd. With this is mind, we can avoid a bunch of spurious calls to reparent orphans and of_clk_get_hw_from_clkspec() by stashing the error and bailing early if we know this clock can't be found. Signed-off-by: Casey Connolly <[email protected]> --- drivers/clk/ccf/clk.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/clk/ccf/clk.c b/drivers/clk/ccf/clk.c index 83d435dce02b..28692fbc7798 100644 --- a/drivers/clk/ccf/clk.c +++ b/drivers/clk/ccf/clk.c @@ -53,9 +53,17 @@ struct clk_parent_map { const struct clk_hw *hw; struct clk_core *core; const char *fw_name; const char *name; - int index; + int index : 20; + /* + * U-Boot: Avoid repeatedly trying to probe + * missing clock parents. Since we lazily + * probe clock providers, if we get an error + * then trying again later will never work since + * we don't support loadable modules. + */ + int error : 12; }; struct clk_core { const char *name; @@ -285,16 +293,32 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index) /* Only cache it if it's not an error */ if (!IS_ERR(parent)) entry->core = parent; + /* + * U-Boot: save the error so we avoid trying to get this parent again. + * -EPROBE_DEFER probably means the parent is in the same clock device + * and just isn't available yet. + */ + else if (PTR_ERR(parent) != -EPROBE_DEFER) { + entry->error = PTR_ERR(parent); + } } static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core, u8 index) { if (!core || index >= core->num_parents || !core->parents) return NULL; + /* + * U-Boot: if we failed to get a parent before we don't need to + * try again, unlike Linux we don't have modules. + * The only reason this might happen is due to a driver issue. + */ + if (core->parents[index].error) + return NULL; + if (!core->parents[index].core) clk_core_fill_parent_index(core, index); return core->parents[index].core; @@ -1956,9 +1980,13 @@ static int __clk_core_init(struct clk_core *core) goto out_list_del; } } - clk_core_reparent_orphans_nolock(); + /* + * U-Boot: since we probe clk providers on-demand it's enough to only reparent + * orphans when adding providers not for every single clock. + */ + //clk_core_reparent_orphans_nolock(); out_list_del: if (ret) hlist_del(&core->hashtable_node); out: -- 2.55.0
