common: Move autoprobe out to board init
Rather than doing autoprobe within the driver model code, move it out to
the board-init code. This makes it clear that it is a separate step from
binding devices.
For now this is always done twice, before and after relocation, but we
should discuss whether it might be possible to drop the post-relocation
probe.
For boards with SPL, the autoprobe is still done there as well.
Note that with this change, autoprobe happens after the
EVT_DM_POST_INIT_R/F events are sent, rather than before.
Link: https://lore.kernel.org/u-boot/20240626235717.272219-1-marex@denx.de/
Signed-off-by: Simon Glass <sjg@chromium.org>
(cherry picked from commit 6995f2c8be)
This commit is contained in:
@@ -829,10 +829,14 @@ static int initf_dm(void)
|
||||
|
||||
bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f");
|
||||
ret = dm_init_and_scan(true);
|
||||
bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dm_autoprobe();
|
||||
if (ret)
|
||||
return ret;
|
||||
bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);
|
||||
|
||||
if (IS_ENABLED(CONFIG_TIMER_EARLY)) {
|
||||
ret = dm_timer_init();
|
||||
if (ret)
|
||||
|
||||
@@ -254,7 +254,7 @@ static int initr_dm(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return dm_autoprobe();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -565,6 +565,10 @@ static int spl_common_init(bool setup_malloc)
|
||||
debug("dm_init_and_scan() returned error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dm_autoprobe();
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -842,6 +842,23 @@ steps (see device_probe()):
|
||||
cause the uclass to do some housekeeping to record the device as
|
||||
activated and 'known' by the uclass.
|
||||
|
||||
For some platforms, certain devices must be probed to get the platform into
|
||||
a working state. To help with this, drivers marked with DM_FLAG_PROBE_AFTER_BIND
|
||||
will be probed immediately after all devices are bound. For now, this happens in
|
||||
SPL, before relocation and after relocation. See the call to ``dm_autoprobe()``
|
||||
for where this is done.
|
||||
|
||||
The auto-probe feature is tricky because it bypasses the normal ordering of
|
||||
probing. General, if device A (e.g. video) needs device B (e.g. clock), then
|
||||
A's probe() method uses ``clk_get_by_index()`` and B is probed before A. But
|
||||
A is only probed when it is used. Therefore care should be taken when using
|
||||
auto-probe, limiting it to devices which truly are essential, such as power
|
||||
domains or critical clocks.
|
||||
|
||||
See here for more discussion of this feature:
|
||||
|
||||
:Link: https://patchwork.ozlabs.org/project/uboot/patch/20240626235717.272219-1-marex@denx.de/
|
||||
|
||||
Running stage
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -288,6 +288,16 @@ void *dm_priv_to_rw(void *priv)
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* dm_probe_devices() - Check whether to probe a device and all children
|
||||
*
|
||||
* Probes the device if DM_FLAG_PROBE_AFTER_BIND is enabled for it. Then scans
|
||||
* all its children recursively to do the same.
|
||||
*
|
||||
* @dev: Device to (maybe) probe
|
||||
* @pre_reloc_only: Probe only devices marked with the DM_FLAG_PRE_RELOC flag
|
||||
* Return 0 if OK, -ve on error
|
||||
*/
|
||||
static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only)
|
||||
{
|
||||
ofnode node = dev_ofnode(dev);
|
||||
@@ -312,6 +322,17 @@ probe_children:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_autoprobe(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = dm_probe_devices(gd->dm_root, !(gd->flags & GD_FLG_RELOC));
|
||||
if (ret)
|
||||
return log_msg_ret("pro", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_scan() - Scan tables to bind devices
|
||||
*
|
||||
@@ -344,7 +365,7 @@ static int dm_scan(bool pre_reloc_only)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return dm_probe_devices(gd->dm_root, pre_reloc_only);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dm_init_and_scan(bool pre_reloc_only)
|
||||
|
||||
@@ -136,6 +136,21 @@ int dm_scan_other(bool pre_reloc_only);
|
||||
*/
|
||||
int dm_init_and_scan(bool pre_reloc_only);
|
||||
|
||||
/**
|
||||
* dm_autoprobe() - Probe devices which are marked for probe-after-bind
|
||||
*
|
||||
* This probes all devices with a DM_FLAG_PROBE_AFTER_BIND flag. It checks the
|
||||
* entire tree, so parent nodes need not have the flag set.
|
||||
*
|
||||
* It recursively probes parent nodes, so they do not need to have the flag
|
||||
* set themselves. Since parents are always probed before children, if a child
|
||||
* has the flag set, then its parent (and any devices up the chain to the root
|
||||
* device) will be probed too.
|
||||
*
|
||||
* Return: 0 if OK, -ve on error
|
||||
*/
|
||||
int dm_autoprobe(void);
|
||||
|
||||
/**
|
||||
* dm_init() - Initialise Driver Model structures
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user