of/flattree: Add of_flat_dt_match() helper function
authorGrant Likely <grant.likely@secretlab.ca>
Sat, 30 Oct 2010 15:49:09 +0000 (11:49 -0400)
committerGrant Likely <grant.likely@secretlab.ca>
Sat, 1 Jan 2011 20:03:25 +0000 (13:03 -0700)
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>
arch/powerpc/platforms/40x/ppc40x_simple.c
arch/powerpc/platforms/512x/mpc5121_generic.c
arch/powerpc/platforms/52xx/lite5200.c
arch/powerpc/platforms/52xx/media5200.c
arch/powerpc/platforms/52xx/mpc5200_simple.c
arch/powerpc/platforms/83xx/mpc830x_rdb.c
arch/powerpc/platforms/83xx/mpc831x_rdb.c
arch/powerpc/platforms/83xx/mpc837x_rdb.c
arch/powerpc/platforms/85xx/tqm85xx.c
drivers/of/fdt.c
include/linux/of_fdt.h

index 546bbc229d19dd0d64277aa31b678f5b441eb432..2521d93ef136426d591820dd84995a84f349a27f 100644 (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
  * board.c file for it rather than adding it to this list.
  */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
        "amcc,acadia",
        "amcc,haleakala",
        "amcc,kilauea",
@@ -60,14 +60,9 @@ static char *board[] __initdata = {
 
 static int __init ppc40x_probe(void)
 {
-       unsigned long root = of_get_flat_dt_root();
-       int i = 0;
-
-       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;
-               }
+       if (of_flat_dt_match(of_get_flat_dt_root(), board)) {
+               ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+               return 1;
        }
 
        return 0;
index e487eb06ec6b294410a4650d0775556f8d448f11..926731f1ff01b587901cf88feab77161b4194849 100644 (file)
@@ -26,7 +26,7 @@
 /*
  * list of supported boards
  */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
        "prt,prtlvt",
        NULL
 };
@@ -36,16 +36,7 @@ static char *board[] __initdata = {
  */
 static int __init mpc5121_generic_probe(void)
 {
-       unsigned long node = of_get_flat_dt_root();
-       int i = 0;
-
-       while (board[i]) {
-               if (of_flat_dt_is_compatible(node, board[i]))
-                       break;
-               i++;
-       }
-
-       return board[i] != NULL;
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(mpc5121_generic) {
index de55bc0584b5d6cadaa24572db3302dbd0ea19ea..01ffa64d2aa7faf06582db473c96d4ac305621bd 100644 (file)
@@ -172,20 +172,18 @@ static void __init lite5200_setup_arch(void)
        mpc52xx_setup_pci();
 }
 
+static const char *board[] __initdata = {
+       "fsl,lite5200",
+       "fsl,lite5200b",
+       NULL,
+};
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init lite5200_probe(void)
 {
-       unsigned long node = of_get_flat_dt_root();
-       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;
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(lite5200) {
index 0bac3a3dbecfdf4fe189d897681ce388b584f508..2c7780cb68e598cff0e6817fb9a599a0ade7d821 100644 (file)
@@ -239,7 +239,7 @@ static void __init media5200_setup_arch(void)
 }
 
 /* list of the supported boards */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
        "fsl,media5200",
        NULL
 };
@@ -249,16 +249,7 @@ static char *board[] __initdata = {
  */
 static int __init media5200_probe(void)
 {
-       unsigned long node = of_get_flat_dt_root();
-       int i = 0;
-
-       while (board[i]) {
-               if (of_flat_dt_is_compatible(node, board[i]))
-                       break;
-               i++;
-       }
-
-       return (board[i] != NULL);
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(media5200_platform) {
index d45be5b5ad497baadb007821e479d7898879acab..e36d6e232ae66f4bf3033e5b60363cea25e46008 100644 (file)
@@ -49,7 +49,7 @@ static void __init mpc5200_simple_setup_arch(void)
 }
 
 /* list of the supported boards */
-static char *board[] __initdata = {
+static const char *board[] __initdata = {
        "intercontrol,digsy-mtc",
        "manroland,mucmc52",
        "manroland,uc101",
@@ -66,16 +66,7 @@ static char *board[] __initdata = {
  */
 static int __init mpc5200_simple_probe(void)
 {
-       unsigned long node = of_get_flat_dt_root();
-       int i = 0;
-
-       while (board[i]) {
-               if (of_flat_dt_is_compatible(node, board[i]))
-                       break;
-               i++;
-       }
-       
-       return (board[i] != NULL);
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(mpc5200_simple_platform) {
index 846831d495b57f6c1c9e123308ed9e3f2013848f..661d354e4ff27d15ee97aa18f663110177ab8ca4 100644 (file)
@@ -57,16 +57,19 @@ static void __init mpc830x_rdb_init_IRQ(void)
        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
  */
 static int __init mpc830x_rdb_probe(void)
 {
-       unsigned long root = of_get_flat_dt_root();
-
-       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");
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 static struct of_device_id __initdata of_bus_ids[] = {
index ae525e4745d2af9b3c4406f95458cadae6cf7382..b54cd736a895215250fea8c2c99159a9aa0965b7 100644 (file)
@@ -60,15 +60,18 @@ static void __init mpc831x_rdb_init_IRQ(void)
        ipic_set_default_priority();
 }
 
+struct const char *board[] __initdata = {
+       "MPC8313ERDB",
+       "fsl,mpc8315erdb",
+       NULL
+}
+
 /*
  * Called very early, MMU is off, device-tree isn't unflattened
  */
 static int __init mpc831x_rdb_probe(void)
 {
-       unsigned long root = of_get_flat_dt_root();
-
-       return of_flat_dt_is_compatible(root, "MPC8313ERDB") ||
-              of_flat_dt_is_compatible(root, "fsl,mpc8315erdb");
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 static struct of_device_id __initdata of_bus_ids[] = {
index 910caa6b581056e7a4cb928a00998d2336f24818..7bafbf2ec0f92712aac0a1a259b22e1dd3de4b7f 100644 (file)
@@ -101,17 +101,20 @@ static void __init mpc837x_rdb_init_IRQ(void)
        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
  */
 static int __init mpc837x_rdb_probe(void)
 {
-       unsigned long root = of_get_flat_dt_root();
-
-       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");
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(mpc837x_rdb) {
index 8f29bbce5360447c3a719fb6b74877b417f35aed..5e847d0b47c80b5a63308e7e41a1ec4c8dce8917 100644 (file)
@@ -186,21 +186,21 @@ static int __init declare_of_platform_devices(void)
 }
 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
  */
 static int __init tqm85xx_probe(void)
 {
-       unsigned long root = of_get_flat_dt_root();
-
-       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;
+       return of_flat_dt_match(of_get_flat_dt_root(), board);
 }
 
 define_machine(tqm85xx) {
index 8a90ee42071a784dfd14b6c5dabb75cd4481db9b..c787c3d95c600eb51955dcb4d2e64dca88d559ba 100644 (file)
@@ -78,19 +78,23 @@ void *of_fdt_get_property(struct boot_param_header *blob,
  * @blob: A device tree blob
  * @node: node to test
  * @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,
                      unsigned long node, const char *compat)
 {
        const char *cp;
-       unsigned long cplen, l;
+       unsigned long cplen, l, score = 0;
 
        cp = of_fdt_get_property(blob, node, "compatible", &cplen);
        if (cp == NULL)
                return 0;
        while (cplen > 0) {
+               score++;
                if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
-                       return 1;
+                       return score;
                l = strlen(cp) + 1;
                cp += l;
                cplen -= l;
@@ -99,6 +103,27 @@ int of_fdt_is_compatible(struct boot_param_header *blob,
        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,
                                       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);
 }
 
+/**
+ * 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
 /**
  * early_init_dt_check_for_initrd - Decode initrd location from flat tree
index 9ce5dfd2186ac71651f44f753e0ce3bc7a169722..ee96091f7d2576932cf5a390e36ad2247e778c20 100644 (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,
                                unsigned long node,
                                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,
                               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,
                                 unsigned long *size);
 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 int early_init_dt_scan_chosen(unsigned long node, const char *uname,