|
@@ -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,68 @@ 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 &&
|
|
|
+ !glob_match(match->machine, soc_dev->attr->machine))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (match->family &&
|
|
|
+ !glob_match(match->family, soc_dev->attr->family))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (match->revision &&
|
|
|
+ !glob_match(match->revision, soc_dev->attr->revision))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (match->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);
|