of/flattree: Add non-boottime device tree functions
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. V2: - functions have of_fdt_* names - removed find_flat_dt_string - blob argument is first Signed-off-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
This commit is contained in:
parent
e6ce1324e4
commit
9706a36e35
133
drivers/of/fdt.c
133
drivers/of/fdt.c
@ -22,6 +22,82 @@
|
|||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
|
char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
|
||||||
|
{
|
||||||
|
return ((char *)blob) +
|
||||||
|
be32_to_cpu(blob->off_dt_strings) + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* of_fdt_get_property - Given a node in the given flat blob, return
|
||||||
|
* the property ptr
|
||||||
|
*/
|
||||||
|
void *of_fdt_get_property(struct boot_param_header *blob,
|
||||||
|
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(blob->version) < 0x10)
|
||||||
|
p = ALIGN(p, sz >= 8 ? 8 : 4);
|
||||||
|
|
||||||
|
nstr = of_fdt_get_string(blob, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* of_fdt_is_compatible - Return true if given node from the given blob has
|
||||||
|
* compat in its compatible list
|
||||||
|
* @blob: A device tree blob
|
||||||
|
* @node: node to test
|
||||||
|
* @compat: compatible string to compare with compatible list.
|
||||||
|
*/
|
||||||
|
int of_fdt_is_compatible(struct boot_param_header *blob,
|
||||||
|
unsigned long node, const char *compat)
|
||||||
|
{
|
||||||
|
const char *cp;
|
||||||
|
unsigned long cplen, l;
|
||||||
|
|
||||||
|
cp = of_fdt_get_property(blob, 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Everything below here references initial_boot_params directly. */
|
||||||
int __initdata dt_root_addr_cells;
|
int __initdata dt_root_addr_cells;
|
||||||
int __initdata dt_root_size_cells;
|
int __initdata dt_root_size_cells;
|
||||||
|
|
||||||
@ -29,12 +105,6 @@ struct boot_param_header *initial_boot_params;
|
|||||||
|
|
||||||
#ifdef CONFIG_OF_EARLY_FLATTREE
|
#ifdef CONFIG_OF_EARLY_FLATTREE
|
||||||
|
|
||||||
char *find_flat_dt_string(u32 offset)
|
|
||||||
{
|
|
||||||
return ((char *)initial_boot_params) +
|
|
||||||
be32_to_cpu(initial_boot_params->off_dt_strings) + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_scan_flat_dt - scan flattened tree blob and call callback on each.
|
* of_scan_flat_dt - scan flattened tree blob and call callback on each.
|
||||||
* @it: callback function
|
* @it: callback function
|
||||||
@ -123,38 +193,7 @@ unsigned long __init of_get_flat_dt_root(void)
|
|||||||
void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
|
void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
|
||||||
unsigned long *size)
|
unsigned long *size)
|
||||||
{
|
{
|
||||||
unsigned long p = node;
|
return of_fdt_get_property(initial_boot_params, node, name, size);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,21 +203,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)
|
int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
|
||||||
{
|
{
|
||||||
const char *cp;
|
return of_fdt_is_compatible(initial_boot_params, node, compat);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
|
static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
|
||||||
@ -303,7 +328,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
|
|||||||
if (be32_to_cpu(initial_boot_params->version) < 0x10)
|
if (be32_to_cpu(initial_boot_params->version) < 0x10)
|
||||||
*p = ALIGN(*p, sz >= 8 ? 8 : 4);
|
*p = ALIGN(*p, sz >= 8 ? 8 : 4);
|
||||||
|
|
||||||
pname = find_flat_dt_string(noff);
|
pname = of_fdt_get_string(initial_boot_params, noff);
|
||||||
if (pname == NULL) {
|
if (pname == NULL) {
|
||||||
pr_info("Can't find property name in list !\n");
|
pr_info("Can't find property name in list !\n");
|
||||||
break;
|
break;
|
||||||
|
@ -58,6 +58,17 @@ struct boot_param_header {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if defined(CONFIG_OF_FLATTREE)
|
#if defined(CONFIG_OF_FLATTREE)
|
||||||
|
|
||||||
|
/* For scanning an arbitrary device-tree at any time */
|
||||||
|
extern char *of_fdt_get_string(struct boot_param_header *blob, u32 offset);
|
||||||
|
extern void *of_fdt_get_property(struct boot_param_header *blob,
|
||||||
|
unsigned long node,
|
||||||
|
const char *name,
|
||||||
|
unsigned long *size);
|
||||||
|
extern int of_fdt_is_compatible(struct boot_param_header *blob,
|
||||||
|
unsigned long node,
|
||||||
|
const char *compat);
|
||||||
|
|
||||||
/* TBD: Temporary export of fdt globals - remove when code fully merged */
|
/* TBD: Temporary export of fdt globals - remove when code fully merged */
|
||||||
extern int __initdata dt_root_addr_cells;
|
extern int __initdata dt_root_addr_cells;
|
||||||
extern int __initdata dt_root_size_cells;
|
extern int __initdata dt_root_size_cells;
|
||||||
|
Loading…
Reference in New Issue
Block a user