Merge tag 'powerpc-6.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc...
[sfrench/cifs-2.6.git] / drivers / of / base.c
index b0ad8fc06e80e099ab6eba7ebe10039875bc85c4..8856c67c466acd4dc98aee218f3ceaebf250a7a9 100644 (file)
@@ -395,25 +395,57 @@ int of_device_compatible_match(const struct device_node *device,
 EXPORT_SYMBOL_GPL(of_device_compatible_match);
 
 /**
- * of_machine_is_compatible - Test root of device tree for a given compatible value
- * @compat: compatible string to look for in root node's compatible property.
+ * of_machine_compatible_match - Test root of device tree against a compatible array
+ * @compats: NULL terminated array of compatible strings to look for in root node's compatible property.
  *
- * Return: A positive integer if the root node has the given value in its
+ * Returns true if the root node has any of the given compatible values in its
  * compatible property.
  */
-int of_machine_is_compatible(const char *compat)
+bool of_machine_compatible_match(const char *const *compats)
 {
        struct device_node *root;
        int rc = 0;
 
        root = of_find_node_by_path("/");
        if (root) {
-               rc = of_device_is_compatible(root, compat);
+               rc = of_device_compatible_match(root, compats);
                of_node_put(root);
        }
-       return rc;
+
+       return rc != 0;
+}
+EXPORT_SYMBOL(of_machine_compatible_match);
+
+static bool __of_device_is_status(const struct device_node *device,
+                                 const char * const*strings)
+{
+       const char *status;
+       int statlen;
+
+       if (!device)
+               return false;
+
+       status = __of_get_property(device, "status", &statlen);
+       if (status == NULL)
+               return false;
+
+       if (statlen > 0) {
+               while (*strings) {
+                       unsigned int len = strlen(*strings);
+
+                       if ((*strings)[len - 1] == '-') {
+                               if (!strncmp(status, *strings, len))
+                                       return true;
+                       } else {
+                               if (!strcmp(status, *strings))
+                                       return true;
+                       }
+                       strings++;
+               }
+       }
+
+       return false;
 }
-EXPORT_SYMBOL(of_machine_is_compatible);
 
 /**
  *  __of_device_is_available - check if a device is available for use
@@ -425,22 +457,27 @@ EXPORT_SYMBOL(of_machine_is_compatible);
  */
 static bool __of_device_is_available(const struct device_node *device)
 {
-       const char *status;
-       int statlen;
+       static const char * const ok[] = {"okay", "ok", NULL};
 
        if (!device)
                return false;
 
-       status = __of_get_property(device, "status", &statlen);
-       if (status == NULL)
-               return true;
+       return !__of_get_property(device, "status", NULL) ||
+               __of_device_is_status(device, ok);
+}
 
-       if (statlen > 0) {
-               if (!strcmp(status, "okay") || !strcmp(status, "ok"))
-                       return true;
-       }
+/**
+ *  __of_device_is_reserved - check if a device is reserved
+ *
+ *  @device: Node to check for availability, with locks already held
+ *
+ *  Return: True if the status property is set to "reserved", false otherwise
+ */
+static bool __of_device_is_reserved(const struct device_node *device)
+{
+       static const char * const reserved[] = {"reserved", NULL};
 
-       return false;
+       return __of_device_is_status(device, reserved);
 }
 
 /**
@@ -474,16 +511,9 @@ EXPORT_SYMBOL(of_device_is_available);
  */
 static bool __of_device_is_fail(const struct device_node *device)
 {
-       const char *status;
+       static const char * const fail[] = {"fail", "fail-", NULL};
 
-       if (!device)
-               return false;
-
-       status = __of_get_property(device, "status", NULL);
-       if (status == NULL)
-               return false;
-
-       return !strcmp(status, "fail") || !strncmp(status, "fail-", 5);
+       return __of_device_is_status(device, fail);
 }
 
 /**
@@ -597,16 +627,9 @@ struct device_node *of_get_next_child(const struct device_node *node,
 }
 EXPORT_SYMBOL(of_get_next_child);
 
-/**
- * of_get_next_available_child - Find the next available child node
- * @node:      parent node
- * @prev:      previous child of the parent node, or NULL to get first
- *
- * This function is like of_get_next_child(), except that it
- * automatically skips any disabled nodes (i.e. status = "disabled").
- */
-struct device_node *of_get_next_available_child(const struct device_node *node,
-       struct device_node *prev)
+static struct device_node *of_get_next_status_child(const struct device_node *node,
+                                                   struct device_node *prev,
+                                                   bool (*checker)(const struct device_node *))
 {
        struct device_node *next;
        unsigned long flags;
@@ -617,7 +640,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
        raw_spin_lock_irqsave(&devtree_lock, flags);
        next = prev ? prev->sibling : node->child;
        for (; next; next = next->sibling) {
-               if (!__of_device_is_available(next))
+               if (!checker(next))
                        continue;
                if (of_node_get(next))
                        break;
@@ -626,8 +649,37 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return next;
 }
+
+/**
+ * of_get_next_available_child - Find the next available child node
+ * @node:      parent node
+ * @prev:      previous child of the parent node, or NULL to get first
+ *
+ * This function is like of_get_next_child(), except that it
+ * automatically skips any disabled nodes (i.e. status = "disabled").
+ */
+struct device_node *of_get_next_available_child(const struct device_node *node,
+       struct device_node *prev)
+{
+       return of_get_next_status_child(node, prev, __of_device_is_available);
+}
 EXPORT_SYMBOL(of_get_next_available_child);
 
+/**
+ * of_get_next_reserved_child - Find the next reserved child node
+ * @node:      parent node
+ * @prev:      previous child of the parent node, or NULL to get first
+ *
+ * This function is like of_get_next_child(), except that it
+ * automatically skips any disabled nodes (i.e. status = "disabled").
+ */
+struct device_node *of_get_next_reserved_child(const struct device_node *node,
+                                               struct device_node *prev)
+{
+       return of_get_next_status_child(node, prev, __of_device_is_reserved);
+}
+EXPORT_SYMBOL(of_get_next_reserved_child);
+
 /**
  * of_get_next_cpu_node - Iterate on cpu nodes
  * @prev:      previous child of the /cpus node, or NULL to get first
@@ -1345,8 +1397,8 @@ int of_parse_phandle_with_args_map(const struct device_node *np,
        char *pass_name = NULL;
        struct device_node *cur, *new = NULL;
        const __be32 *map, *mask, *pass;
-       static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
-       static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
+       static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
+       static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(0) };
        __be32 initial_match_array[MAX_PHANDLE_ARGS];
        const __be32 *match_array = initial_match_array;
        int i, ret, map_len, match;