]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/base/soc.c
Merge tag 'armsoc-defconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[karo-tx-linux.git] / drivers / base / soc.c
index 028cef377fd49959aec641716531a5d14668d141..dc26e5949a3202233ddbeecd6921cd3f1488120b 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/spinlock.h>
 #include <linux/sys_soc.h>
 #include <linux/err.h>
+#include <linux/glob.h>
 
 static DEFINE_IDA(soc_ida);
 
@@ -168,3 +169,72 @@ static int __init soc_bus_register(void)
        return bus_register(&soc_bus_type);
 }
 core_initcall(soc_bus_register);
+
+static int soc_device_match_one(struct device *dev, void *arg)
+{
+       struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
+       const struct soc_device_attribute *match = arg;
+
+       if (match->machine &&
+           (!soc_dev->attr->machine ||
+            !glob_match(match->machine, soc_dev->attr->machine)))
+               return 0;
+
+       if (match->family &&
+           (!soc_dev->attr->family ||
+            !glob_match(match->family, soc_dev->attr->family)))
+               return 0;
+
+       if (match->revision &&
+           (!soc_dev->attr->revision ||
+            !glob_match(match->revision, soc_dev->attr->revision)))
+               return 0;
+
+       if (match->soc_id &&
+           (!soc_dev->attr->soc_id ||
+            !glob_match(match->soc_id, soc_dev->attr->soc_id)))
+               return 0;
+
+       return 1;
+}
+
+/*
+ * soc_device_match - identify the SoC in the machine
+ * @matches: zero-terminated array of possible matches
+ *
+ * returns the first matching entry of the argument array, or NULL
+ * if none of them match.
+ *
+ * This function is meant as a helper in place of of_match_node()
+ * in cases where either no device tree is available or the information
+ * in a device node is insufficient to identify a particular variant
+ * by its compatible strings or other properties. For new devices,
+ * the DT binding should always provide unique compatible strings
+ * that allow the use of of_match_node() instead.
+ *
+ * The calling function can use the .data entry of the
+ * soc_device_attribute to pass a structure or function pointer for
+ * each entry.
+ */
+const struct soc_device_attribute *soc_device_match(
+       const struct soc_device_attribute *matches)
+{
+       int ret = 0;
+
+       if (!matches)
+               return NULL;
+
+       while (!ret) {
+               if (!(matches->machine || matches->family ||
+                     matches->revision || matches->soc_id))
+                       break;
+               ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
+                                      soc_device_match_one);
+               if (!ret)
+                       matches++;
+               else
+                       return matches;
+       }
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(soc_device_match);