|
@@ -385,3 +385,91 @@ struct device_node *of_find_matching_node(struct device_node *from,
|
|
|
return np;
|
|
|
}
|
|
|
EXPORT_SYMBOL(of_find_matching_node);
|
|
|
+
|
|
|
+/**
|
|
|
+ * of_modalias_table: Table of explicit compatible ==> modalias mappings
|
|
|
+ *
|
|
|
+ * This table allows particulare compatible property values to be mapped
|
|
|
+ * to modalias strings. This is useful for busses which do not directly
|
|
|
+ * understand the OF device tree but are populated based on data contained
|
|
|
+ * within the device tree. SPI and I2C are the two current users of this
|
|
|
+ * table.
|
|
|
+ *
|
|
|
+ * In most cases, devices do not need to be listed in this table because
|
|
|
+ * the modalias value can be derived directly from the compatible table.
|
|
|
+ * However, if for any reason a value cannot be derived, then this table
|
|
|
+ * provides a method to override the implicit derivation.
|
|
|
+ *
|
|
|
+ * At the moment, a single table is used for all bus types because it is
|
|
|
+ * assumed that the data size is small and that the compatible values
|
|
|
+ * should already be distinct enough to differentiate between SPI, I2C
|
|
|
+ * and other devices.
|
|
|
+ */
|
|
|
+struct of_modalias_table {
|
|
|
+ char *of_device;
|
|
|
+ char *modalias;
|
|
|
+};
|
|
|
+static struct of_modalias_table of_modalias_table[] = {
|
|
|
+ /* Empty for now; add entries as needed */
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * of_modalias_node - Lookup appropriate modalias for a device node
|
|
|
+ * @node: pointer to a device tree node
|
|
|
+ * @modalias: Pointer to buffer that modalias value will be copied into
|
|
|
+ * @len: Length of modalias value
|
|
|
+ *
|
|
|
+ * Based on the value of the compatible property, this routine will determine
|
|
|
+ * an appropriate modalias value for a particular device tree node. Three
|
|
|
+ * separate methods are used to derive a modalias value.
|
|
|
+ *
|
|
|
+ * First method is to lookup the compatible value in of_modalias_table.
|
|
|
+ * Second is to look for a "linux,<modalias>" entry in the compatible list
|
|
|
+ * and used that for modalias. Third is to strip off the manufacturer
|
|
|
+ * prefix from the first compatible entry and use the remainder as modalias
|
|
|
+ *
|
|
|
+ * This routine returns 0 on success
|
|
|
+ */
|
|
|
+int of_modalias_node(struct device_node *node, char *modalias, int len)
|
|
|
+{
|
|
|
+ int i, cplen;
|
|
|
+ const char *compatible;
|
|
|
+ const char *p;
|
|
|
+
|
|
|
+ /* 1. search for exception list entry */
|
|
|
+ for (i = 0; i < ARRAY_SIZE(of_modalias_table); i++) {
|
|
|
+ compatible = of_modalias_table[i].of_device;
|
|
|
+ if (!of_device_is_compatible(node, compatible))
|
|
|
+ continue;
|
|
|
+ strlcpy(modalias, of_modalias_table[i].modalias, len);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ compatible = of_get_property(node, "compatible", &cplen);
|
|
|
+ if (!compatible)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ /* 2. search for linux,<modalias> entry */
|
|
|
+ p = compatible;
|
|
|
+ while (cplen > 0) {
|
|
|
+ if (!strncmp(p, "linux,", 6)) {
|
|
|
+ p += 6;
|
|
|
+ strlcpy(modalias, p, len);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ i = strlen(p) + 1;
|
|
|
+ p += i;
|
|
|
+ cplen -= i;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 3. take first compatible entry and strip manufacturer */
|
|
|
+ p = strchr(compatible, ',');
|
|
|
+ if (!p)
|
|
|
+ return -ENODEV;
|
|
|
+ p++;
|
|
|
+ strlcpy(modalias, p, len);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(of_modalias_node);
|
|
|
+
|