[PATCH 1/3] fdt.c: Add non-boottime device tree functions

Grant Likely grant.likely at secretlab.ca
Thu Nov 18 06:42:03 EST 2010


On Wed, Nov 17, 2010 at 11:15:43AM -0800, Stephen Neuendorffer wrote:
> In preparation for providing run-time handling of device trees, factor
> out some of the basic functions so that they take an arbitrary blob,
> rather than relying on the single boot-time tree.
> 
> Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer at xilinx.com>
> ---
>  drivers/of/fdt.c       |  129 ++++++++++++++++++++++++++++++-----------------
>  include/linux/of_fdt.h |    9 +++
>  2 files changed, 91 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index c1360e0..6ae207a 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -22,6 +22,86 @@
>  
>  #include <asm/page.h>
>  
> +char *fdt_get_string(u32 offset,
> +			  struct boot_param_header *blob)

nitpicking: Encouraged naming convention is of_flat_dt_* for this
file.  Also, I think it makes more sense for blob to be the first
argument in all of these functions.

> +{
> +	return ((char *)blob) +
> +		be32_to_cpu(blob->off_dt_strings) + offset;
> +}
> +
> +/**
> + * of_get_flat_dt_prop_blob - Given a node in the given flat blob, return
> + * the property ptr
> + *
> + * This function can be used within scan_flattened_dt callback to get
> + * access to properties
> + */
> +void *fdt_get_property(unsigned long node, const char *name,
> +				 unsigned long *size,
> +				 struct boot_param_header *blob)

Colocate this function with the defintiion of
of_flat_dt_get_property()

> +{
> +	unsigned long p = node;

I think 'p' can be made type void* to eliminate all the casting in
this function (although I understand that this patch just moves code;
so that change doesn't need to be in this patch.

> +
> +	do {
> +		u32 tag = be32_to_cpup((__be32 *)p);
> +		u32 sz, noff;
> +		const char *nstr;
> +
> +		p += 4;
> +		if (tag == OF_DT_NOP)
> +			continue;
> +		if (tag != OF_DT_PROP)
> +			return NULL;
> +
> +		sz = be32_to_cpup((__be32 *)p);
> +		noff = be32_to_cpup((__be32 *)(p + 4));
> +		p += 8;
> +		if (be32_to_cpu(blob->version) < 0x10)
> +			p = ALIGN(p, sz >= 8 ? 8 : 4);

If you change p to void*, then PTR_ALIGN can be used.

> +
> +		nstr = fdt_get_string(noff, blob);
> +		if (nstr == NULL) {
> +			pr_warning("Can't find property index name !\n");
> +			return NULL;
> +		}
> +		if (strcmp(name, nstr) == 0) {
> +			if (size)
> +				*size = sz;
> +			return (void *)p;
> +		}
> +		p += sz;
> +		p = ALIGN(p, 4);
> +	} while (1);
> +}
> +
> +/**
> + * fdt_is_compatible - Return true if given node from the given blob has
> + * compat in its compatible list
> + * @node: node to test
> + * @compat: compatible string to compare with compatible list.
> + * @blob: A device tree blob
> + */
> +int fdt_is_compatible(unsigned long node, const char *compat,
> +				 struct boot_param_header *blob)

Colocate this definition with of_flat_dt_is_compatible.

> +{
> +	const char *cp;
> +	unsigned long cplen, l;
> +
> +	cp = fdt_get_property(node, "compatible", &cplen, blob);
> +	if (cp == NULL)
> +		return 0;
> +	while (cplen > 0) {
> +		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
> +			return 1;
> +		l = strlen(cp) + 1;
> +		cp += l;
> +		cplen -= l;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Everything below here references initial_boot_params directly. */
>  int __initdata dt_root_addr_cells;
>  int __initdata dt_root_size_cells;
>  
> @@ -121,38 +201,7 @@ unsigned long __init of_get_flat_dt_root(void)
>  void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
>  				 unsigned long *size)
>  {
> -	unsigned long p = node;
> -
> -	do {
> -		u32 tag = be32_to_cpup((__be32 *)p);
> -		u32 sz, noff;
> -		const char *nstr;
> -
> -		p += 4;
> -		if (tag == OF_DT_NOP)
> -			continue;
> -		if (tag != OF_DT_PROP)
> -			return NULL;
> -
> -		sz = be32_to_cpup((__be32 *)p);
> -		noff = be32_to_cpup((__be32 *)(p + 4));
> -		p += 8;
> -		if (be32_to_cpu(initial_boot_params->version) < 0x10)
> -			p = ALIGN(p, sz >= 8 ? 8 : 4);
> -
> -		nstr = find_flat_dt_string(noff);
> -		if (nstr == NULL) {
> -			pr_warning("Can't find property index name !\n");
> -			return NULL;
> -		}
> -		if (strcmp(name, nstr) == 0) {
> -			if (size)
> -				*size = sz;
> -			return (void *)p;
> -		}
> -		p += sz;
> -		p = ALIGN(p, 4);
> -	} while (1);
> +	return fdt_get_property(node, name, size, initial_boot_params);
>  }
>  
>  /**
> @@ -162,21 +211,7 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
>   */
>  int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
>  {
> -	const char *cp;
> -	unsigned long cplen, l;
> -
> -	cp = of_get_flat_dt_prop(node, "compatible", &cplen);
> -	if (cp == NULL)
> -		return 0;
> -	while (cplen > 0) {
> -		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
> -			return 1;
> -		l = strlen(cp) + 1;
> -		cp += l;
> -		cplen -= l;
> -	}
> -
> -	return 0;
> +	return fdt_is_compatible(node, compat, initial_boot_params);
>  }
>  
>  static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
> index 7bbf5b3..864ec47 100644
> --- a/include/linux/of_fdt.h
> +++ b/include/linux/of_fdt.h
> @@ -58,6 +58,15 @@ struct boot_param_header {
>  };
>  
>  #if defined(CONFIG_OF_FLATTREE)
> +/* For scanning an arbitrary device-tree at any time */
> +extern char *fdt_get_string(u32 offset,
> +			    struct boot_param_header *blob);
> +extern void *fdt_get_property(unsigned long node, const char *name,
> +			      unsigned long *size,
> +			      struct boot_param_header *blob);
> +extern int fdt_is_compatible(unsigned long node, const char *name,
> +			     struct boot_param_header *blob);
> +

Other than renaming the functions to match the existing naming
convention, and making 'blob' the first argument, this patch looks
good to me.

g.



More information about the devicetree-discuss mailing list