[RFC PATCH 2/2 v1] drivers: core: lists.c: Bind drivers using bootph* property in subnodes

Kumar, Udit u-kumar1 at ti.com
Wed Feb 12 15:59:32 CET 2025


Hello Moteen

On 2/12/2025 2:48 PM, Moteen Shah wrote:
> Add a function to scan through all the subnodes of a given node
> recusively for bootph* property. If found, propagate it to all
> of its parent node up the hierarchy so as to bind the respective
> drivers of the nodes in the pre-relocation stage.
>
> The current model skips the node if there is no bootph* found in
> it, even if the property is present in one of the subnodes. The
> issue is tracked in [0].
>
> Signed-off-by: Moteen Shah <m-shah at ti.com>
>
> References:
> [0] https://source.denx.de/u-boot/custodians/u-boot-dm/-/issues/21
>
> ---
>   drivers/core/lists.c | 88 +++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 86 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/core/lists.c b/drivers/core/lists.c
> index c7be504b6fc..5be556ea951 100644
> --- a/drivers/core/lists.c
> +++ b/drivers/core/lists.c
> @@ -17,6 +17,7 @@
>   #include <dm/platdata.h>
>   #include <dm/uclass.h>
>   #include <dm/util.h>
> +#include <fdt_support.h>
>   #include <fdtdec.h>
>   #include <linux/compiler.h>
>   
> @@ -196,6 +197,80 @@ static int driver_check_compatible(const struct udevice_id *of_match,
>   	return -ENOENT;
>   }
>   
> +/**
> + * scan_and_prop_bootph() - Check if a driver matches a compatible string
> + *
> + * @param of_node:	Parent node for child traversal
> + * @param fdt:	Blob to use
> + */
> +static int scan_and_prop_bootph(ofnode node, void *fdt)
> +{
> +	static int bootph_index = -1;
> +	static const char * const bootph_props[] = {
> +		"bootph-all",
> +		"bootph-some-ram",
> +		"bootph-pre-ram",
> +		"bootph-pre-sram",
> +	};
> +	int offset;
> +	int ret = -ENOENT;
> +	ofnode subnode;
> +
> +	/* Note the index where bootph-* was found and return success */
> +	for (int i = 0; i < ARRAY_SIZE(bootph_props); i++) {
> +		if (ofnode_read_bool(node, bootph_props[i])) {
> +			bootph_index = i;
> +			return 0;
> +		}
> +	}
> +
> +	ofnode_for_each_subnode(subnode, node) {
> +		if (!ofnode_valid(subnode))
> +			continue;
> +
> +		ret = scan_and_prop_bootph(subnode, fdt);
> +		if (ret != -ENOENT && ret)
> +			return ret;
> +
> +		/*
> +		 * Break the search if bootph-* is found in any of the subnodes.
> +		 * Breaking the loop early helps in avoiding unnecessary traversal
> +		 * of the sibling node given that bootph-* has been found in previous
> +		 * sibling node.
> +		 */
> +		if (!ret)
> +			break;
> +	}
> +
> +	/* If no bootph-* found then return no such entry */
> +	if (ret)
> +		return -ENOENT;
> +
> +	if (bootph_index != -1) {
> +		offset = ofnode_to_offset(node);
> +		if (offset < 0) {
> +			log_err("Failed to get offset %d\n", offset);
> +			return -EINVAL;
> +		}
> +
> +		ret = fdt_increase_size(fdt, 32);
> +		if (ret) {
> +			log_err("Cannot increase FDT size!\n");
> +			return ret;
> +		}

I understand you are trying to carry bootph to parent,so that parent can 
be probed.

In case, you are failing here then you need to tune memory map or in 
worse case you end up

not probing needed driver and hang.

then why not to override , we have u-boot specific DTs.



> +
> +		ret = fdt_setprop_empty(fdt, offset, bootph_props[bootph_index]);
> +		if (ret) {
> +			log_err("Failed to add bootph prop to node:%s ret=%d\n",
> +				ofnode_get_name(node), ret);
> +			return ret;
> +		}
> +		bootph_index = -1;
> +	}
> +
> +	return ret;
> +}
> +
>   int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
>   		   struct driver *drv, bool pre_reloc_only)
>   {
> @@ -205,6 +280,7 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
>   	struct driver *entry;
>   	struct udevice *dev;
>   	bool found = false;
> +	void *fdt = (void *)gd->fdt_blob;
>   	const char *name, *compat_list, *compat;
>   	int compat_length, i;
>   	int result = 0;
> @@ -256,8 +332,16 @@ int lists_bind_fdt(struct udevice *parent, ofnode node, struct udevice **devp,
>   		if (pre_reloc_only) {
>   			if (!ofnode_pre_reloc(node) &&
>   			    !(entry->flags & DM_FLAG_PRE_RELOC)) {
> -				log_debug("Skipping device pre-relocation\n");
> -				return 0;
> +				if (IS_ENABLED(CONFIG_BIND_FROM_CHILD_BOOTPH)) {
> +					ret = scan_and_prop_bootph(node, fdt);
> +					if (ret) {
> +						log_debug("Skipping device pre-relocation\n");
> +						return 0;
> +					}
> +				} else {
> +					log_debug("Skipping device pre-relocation\n");
> +					return 0;
> +				}
>   			}
>   		}
>   


More information about the U-Boot mailing list