of/flattree: Add of_flat_dt_match() helper function

This patch adds of_flat_dt_match() which tests a node for
compatibility with a list of values and converts the relevant powerpc
platform code to use it.  This approach simplifies the board support
code a bit.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Reviewed-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
This commit is contained in:
Grant Likely 2010-10-30 11:49:09 -04:00
parent 73930a85cf
commit a4f740cf33
11 changed files with 89 additions and 78 deletions

View File

@ -50,7 +50,7 @@ machine_device_initcall(ppc40x_simple, ppc40x_device_probe);
* Again, if your board needs to do things differently then create a * Again, if your board needs to do things differently then create a
* board.c file for it rather than adding it to this list. * board.c file for it rather than adding it to this list.
*/ */
static char *board[] __initdata = { static const char *board[] __initdata = {
"amcc,acadia", "amcc,acadia",
"amcc,haleakala", "amcc,haleakala",
"amcc,kilauea", "amcc,kilauea",
@ -60,14 +60,9 @@ static char *board[] __initdata = {
static int __init ppc40x_probe(void) static int __init ppc40x_probe(void)
{ {
unsigned long root = of_get_flat_dt_root(); if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
int i = 0; ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
return 1;
for (i = 0; i < ARRAY_SIZE(board); i++) {
if (of_flat_dt_is_compatible(root, board[i])) {
ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
return 1;
}
} }
return 0; return 0;

View File

@ -26,7 +26,7 @@
/* /*
* list of supported boards * list of supported boards
*/ */
static char *board[] __initdata = { static const char *board[] __initdata = {
"prt,prtlvt", "prt,prtlvt",
NULL NULL
}; };
@ -36,16 +36,7 @@ static char *board[] __initdata = {
*/ */
static int __init mpc5121_generic_probe(void) static int __init mpc5121_generic_probe(void)
{ {
unsigned long node = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
int i = 0;
while (board[i]) {
if (of_flat_dt_is_compatible(node, board[i]))
break;
i++;
}
return board[i] != NULL;
} }
define_machine(mpc5121_generic) { define_machine(mpc5121_generic) {

View File

@ -172,20 +172,18 @@ static void __init lite5200_setup_arch(void)
mpc52xx_setup_pci(); mpc52xx_setup_pci();
} }
static const char *board[] __initdata = {
"fsl,lite5200",
"fsl,lite5200b",
NULL,
};
/* /*
* Called very early, MMU is off, device-tree isn't unflattened * Called very early, MMU is off, device-tree isn't unflattened
*/ */
static int __init lite5200_probe(void) static int __init lite5200_probe(void)
{ {
unsigned long node = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
const char *model = of_get_flat_dt_prop(node, "model", NULL);
if (!of_flat_dt_is_compatible(node, "fsl,lite5200") &&
!of_flat_dt_is_compatible(node, "fsl,lite5200b"))
return 0;
pr_debug("%s board found\n", model ? model : "unknown");
return 1;
} }
define_machine(lite5200) { define_machine(lite5200) {

View File

@ -239,7 +239,7 @@ static void __init media5200_setup_arch(void)
} }
/* list of the supported boards */ /* list of the supported boards */
static char *board[] __initdata = { static const char *board[] __initdata = {
"fsl,media5200", "fsl,media5200",
NULL NULL
}; };
@ -249,16 +249,7 @@ static char *board[] __initdata = {
*/ */
static int __init media5200_probe(void) static int __init media5200_probe(void)
{ {
unsigned long node = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
int i = 0;
while (board[i]) {
if (of_flat_dt_is_compatible(node, board[i]))
break;
i++;
}
return (board[i] != NULL);
} }
define_machine(media5200_platform) { define_machine(media5200_platform) {

View File

@ -49,7 +49,7 @@ static void __init mpc5200_simple_setup_arch(void)
} }
/* list of the supported boards */ /* list of the supported boards */
static char *board[] __initdata = { static const char *board[] __initdata = {
"intercontrol,digsy-mtc", "intercontrol,digsy-mtc",
"manroland,mucmc52", "manroland,mucmc52",
"manroland,uc101", "manroland,uc101",
@ -66,16 +66,7 @@ static char *board[] __initdata = {
*/ */
static int __init mpc5200_simple_probe(void) static int __init mpc5200_simple_probe(void)
{ {
unsigned long node = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
int i = 0;
while (board[i]) {
if (of_flat_dt_is_compatible(node, board[i]))
break;
i++;
}
return (board[i] != NULL);
} }
define_machine(mpc5200_simple_platform) { define_machine(mpc5200_simple_platform) {

View File

@ -57,16 +57,19 @@ static void __init mpc830x_rdb_init_IRQ(void)
ipic_set_default_priority(); ipic_set_default_priority();
} }
struct const char *board[] __initdata = {
"MPC8308RDB",
"fsl,mpc8308rdb",
"denx,mpc8308_p1m",
NULL
}
/* /*
* Called very early, MMU is off, device-tree isn't unflattened * Called very early, MMU is off, device-tree isn't unflattened
*/ */
static int __init mpc830x_rdb_probe(void) static int __init mpc830x_rdb_probe(void)
{ {
unsigned long root = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
return of_flat_dt_is_compatible(root, "MPC8308RDB") ||
of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") ||
of_flat_dt_is_compatible(root, "denx,mpc8308_p1m");
} }
static struct of_device_id __initdata of_bus_ids[] = { static struct of_device_id __initdata of_bus_ids[] = {

View File

@ -60,15 +60,18 @@ static void __init mpc831x_rdb_init_IRQ(void)
ipic_set_default_priority(); ipic_set_default_priority();
} }
struct const char *board[] __initdata = {
"MPC8313ERDB",
"fsl,mpc8315erdb",
NULL
}
/* /*
* Called very early, MMU is off, device-tree isn't unflattened * Called very early, MMU is off, device-tree isn't unflattened
*/ */
static int __init mpc831x_rdb_probe(void) static int __init mpc831x_rdb_probe(void)
{ {
unsigned long root = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
return of_flat_dt_is_compatible(root, "MPC8313ERDB") ||
of_flat_dt_is_compatible(root, "fsl,mpc8315erdb");
} }
static struct of_device_id __initdata of_bus_ids[] = { static struct of_device_id __initdata of_bus_ids[] = {

View File

@ -101,17 +101,20 @@ static void __init mpc837x_rdb_init_IRQ(void)
ipic_set_default_priority(); ipic_set_default_priority();
} }
static const char *board[] __initdata = {
"fsl,mpc8377rdb",
"fsl,mpc8378rdb",
"fsl,mpc8379rdb",
"fsl,mpc8377wlan",
NULL
};
/* /*
* Called very early, MMU is off, device-tree isn't unflattened * Called very early, MMU is off, device-tree isn't unflattened
*/ */
static int __init mpc837x_rdb_probe(void) static int __init mpc837x_rdb_probe(void)
{ {
unsigned long root = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
return of_flat_dt_is_compatible(root, "fsl,mpc8377rdb") ||
of_flat_dt_is_compatible(root, "fsl,mpc8378rdb") ||
of_flat_dt_is_compatible(root, "fsl,mpc8379rdb") ||
of_flat_dt_is_compatible(root, "fsl,mpc8377wlan");
} }
define_machine(mpc837x_rdb) { define_machine(mpc837x_rdb) {

View File

@ -186,21 +186,21 @@ static int __init declare_of_platform_devices(void)
} }
machine_device_initcall(tqm85xx, declare_of_platform_devices); machine_device_initcall(tqm85xx, declare_of_platform_devices);
static const char *board[] __initdata = {
"tqc,tqm8540",
"tqc,tqm8541",
"tqc,tqm8548",
"tqc,tqm8555",
"tqc,tqm8560",
NULL
};
/* /*
* Called very early, device-tree isn't unflattened * Called very early, device-tree isn't unflattened
*/ */
static int __init tqm85xx_probe(void) static int __init tqm85xx_probe(void)
{ {
unsigned long root = of_get_flat_dt_root(); return of_flat_dt_match(of_get_flat_dt_root(), board);
if ((of_flat_dt_is_compatible(root, "tqc,tqm8540")) ||
(of_flat_dt_is_compatible(root, "tqc,tqm8541")) ||
(of_flat_dt_is_compatible(root, "tqc,tqm8548")) ||
(of_flat_dt_is_compatible(root, "tqc,tqm8555")) ||
(of_flat_dt_is_compatible(root, "tqc,tqm8560")))
return 1;
return 0;
} }
define_machine(tqm85xx) { define_machine(tqm85xx) {

View File

@ -78,19 +78,23 @@ void *of_fdt_get_property(struct boot_param_header *blob,
* @blob: A device tree blob * @blob: A device tree blob
* @node: node to test * @node: node to test
* @compat: compatible string to compare with compatible list. * @compat: compatible string to compare with compatible list.
*
* On match, returns a non-zero value with smaller values returned for more
* specific compatible values.
*/ */
int of_fdt_is_compatible(struct boot_param_header *blob, int of_fdt_is_compatible(struct boot_param_header *blob,
unsigned long node, const char *compat) unsigned long node, const char *compat)
{ {
const char *cp; const char *cp;
unsigned long cplen, l; unsigned long cplen, l, score = 0;
cp = of_fdt_get_property(blob, node, "compatible", &cplen); cp = of_fdt_get_property(blob, node, "compatible", &cplen);
if (cp == NULL) if (cp == NULL)
return 0; return 0;
while (cplen > 0) { while (cplen > 0) {
score++;
if (of_compat_cmp(cp, compat, strlen(compat)) == 0) if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
return 1; return score;
l = strlen(cp) + 1; l = strlen(cp) + 1;
cp += l; cp += l;
cplen -= l; cplen -= l;
@ -99,6 +103,27 @@ int of_fdt_is_compatible(struct boot_param_header *blob,
return 0; return 0;
} }
/**
* of_fdt_match - Return true if node matches a list of compatible values
*/
int of_fdt_match(struct boot_param_header *blob, unsigned long node,
const char **compat)
{
unsigned int tmp, score = 0;
if (!compat)
return 0;
while (*compat) {
tmp = of_fdt_is_compatible(blob, node, *compat);
if (tmp && (score == 0 || (tmp < score)))
score = tmp;
compat++;
}
return score;
}
static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size, static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
unsigned long align) unsigned long align)
{ {
@ -511,6 +536,14 @@ int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
return of_fdt_is_compatible(initial_boot_params, node, compat); return of_fdt_is_compatible(initial_boot_params, node, compat);
} }
/**
* of_flat_dt_match - Return true if node matches a list of compatible values
*/
int __init of_flat_dt_match(unsigned long node, const char **compat)
{
return of_fdt_match(initial_boot_params, node, compat);
}
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
/** /**
* early_init_dt_check_for_initrd - Decode initrd location from flat tree * early_init_dt_check_for_initrd - Decode initrd location from flat tree

View File

@ -68,6 +68,8 @@ extern void *of_fdt_get_property(struct boot_param_header *blob,
extern int of_fdt_is_compatible(struct boot_param_header *blob, extern int of_fdt_is_compatible(struct boot_param_header *blob,
unsigned long node, unsigned long node,
const char *compat); const char *compat);
extern int of_fdt_match(struct boot_param_header *blob, unsigned long node,
const char **compat);
extern void of_fdt_unflatten_tree(unsigned long *blob, extern void of_fdt_unflatten_tree(unsigned long *blob,
struct device_node **mynodes); struct device_node **mynodes);
@ -84,6 +86,7 @@ extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname,
extern void *of_get_flat_dt_prop(unsigned long node, const char *name, extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
unsigned long *size); unsigned long *size);
extern int of_flat_dt_is_compatible(unsigned long node, const char *name); extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
extern int of_flat_dt_match(unsigned long node, const char **matches);
extern unsigned long of_get_flat_dt_root(void); extern unsigned long of_get_flat_dt_root(void);
extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,