Merge patch series "Adjust how autoprobe is implemented"
Simon Glass <sjg@chromium.org> says: This little series makes a minor change to how autoprobe is implemented, as discussed on the list. Link: https://lore.kernel.org/r/20240626235717.272219-1-marex@denx.de Link: https://lore.kernel.org/r/20241120153642.861633-1-sjg@chromium.org
This commit is contained in:
@@ -815,21 +815,26 @@ static int initf_bootstage(void)
|
|||||||
|
|
||||||
static int initf_dm(void)
|
static int initf_dm(void)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_DM) && CONFIG_IS_ENABLED(SYS_MALLOC_F)
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!CONFIG_IS_ENABLED(SYS_MALLOC_F))
|
||||||
|
return 0;
|
||||||
|
|
||||||
bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f");
|
bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f");
|
||||||
ret = dm_init_and_scan(true);
|
ret = dm_init_and_scan(true);
|
||||||
bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);
|
bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = dm_autoprobe();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_TIMER_EARLY)) {
|
if (IS_ENABLED(CONFIG_TIMER_EARLY)) {
|
||||||
ret = dm_timer_init();
|
ret = dm_timer_init();
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -250,7 +250,7 @@ static int initr_dm(void)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return dm_autoprobe();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -500,6 +500,10 @@ static int spl_common_init(bool setup_malloc)
|
|||||||
debug("dm_init_and_scan() returned error %d\n", ret);
|
debug("dm_init_and_scan() returned error %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = dm_autoprobe();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -842,6 +842,23 @@ steps (see device_probe()):
|
|||||||
cause the uclass to do some housekeeping to record the device as
|
cause the uclass to do some housekeeping to record the device as
|
||||||
activated and 'known' by the uclass.
|
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
|
Running stage
|
||||||
^^^^^^^^^^^^^
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@@ -288,26 +288,40 @@ void *dm_priv_to_rw(void *priv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only)
|
/**
|
||||||
|
* 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
|
||||||
|
* Return 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
static int dm_probe_devices(struct udevice *dev)
|
||||||
{
|
{
|
||||||
ofnode node = dev_ofnode(dev);
|
|
||||||
struct udevice *child;
|
struct udevice *child;
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (pre_reloc_only &&
|
|
||||||
(!ofnode_valid(node) || !ofnode_pre_reloc(node)) &&
|
|
||||||
!(dev->driver->flags & DM_FLAG_PRE_RELOC))
|
|
||||||
goto probe_children;
|
|
||||||
|
|
||||||
if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) {
|
if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
ret = device_probe(dev);
|
ret = device_probe(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
probe_children:
|
|
||||||
list_for_each_entry(child, &dev->child_head, sibling_node)
|
list_for_each_entry(child, &dev->child_head, sibling_node)
|
||||||
dm_probe_devices(child, pre_reloc_only);
|
dm_probe_devices(child);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dm_autoprobe(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = dm_probe_devices(gd->dm_root);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("pro", ret);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -344,7 +358,7 @@ static int dm_scan(bool pre_reloc_only)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return dm_probe_devices(gd->dm_root, pre_reloc_only);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dm_init_and_scan(bool pre_reloc_only)
|
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);
|
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
|
* dm_init() - Initialise Driver Model structures
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user