i2c: Add the ability to match device to compatible string without an of_node
authorLee Jones <lee.jones@linaro.org>
Mon, 7 Nov 2016 12:47:37 +0000 (12:47 +0000)
committerWolfram Sang <wsa@the-dreams.de>
Thu, 17 Nov 2016 15:07:26 +0000 (16:07 +0100)
A great deal of I2C devices are currently matched via DT node name, and
as such the compatible naming convention of '<vendor>,<device>' has gone
somewhat awry - some nodes don't supply one, some supply an arbitrary
string and others the correct device name with an arbitrary vendor prefix.

In an effort to correct this problem we have to supply a mechanism to
match a device by compatible string AND by simple device name.  This
function strips off the '<vendor>,' part of a supplied compatible string
and attempts to match without it.

It is also used for sysfs, where a user can choose to instantiate a
device on an i2c bus using the sysfs interface by providing a string and
address to match and communicate with the device on the bus. Presently
this string is only matched against the old i2c device id style strings,
even in the presence of full device tree compatible strings with vendor
prefixes.

Providing a vendor-prefixed string to the sysfs interface will not match
against the device tree of_match_device() calls as there is no device
tree node to parse from the sysfs interface.

This function can match both vendor prefixed and stripped compatible
strings on the sysfs interface.

Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Tested-by: Javier Martinez Canillas <javier@osg.samsung.com>
Signed-off-by: Kieran Bingham <kieran@bingham.xyz>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/i2c/i2c-core.c

index 86083e5e552029f1020519537e95728d84a8a0aa..c588a8504c99f56769fae732b0f56cefc47b1ce5 100644 (file)
@@ -1769,6 +1769,36 @@ struct i2c_adapter *of_get_i2c_adapter_by_node(struct device_node *node)
        return adapter;
 }
 EXPORT_SYMBOL(of_get_i2c_adapter_by_node);
+
+static const struct of_device_id*
+i2c_of_match_device_sysfs(const struct of_device_id *matches,
+                                 struct i2c_client *client)
+{
+       const char *name;
+
+       for (; matches->compatible[0]; matches++) {
+               /*
+                * Adding devices through the i2c sysfs interface provides us
+                * a string to match which may be compatible with the device
+                * tree compatible strings, however with no actual of_node the
+                * of_match_device() will not match
+                */
+               if (sysfs_streq(client->name, matches->compatible))
+                       return matches;
+
+               name = strchr(matches->compatible, ',');
+               if (!name)
+                       name = matches->compatible;
+               else
+                       name++;
+
+               if (sysfs_streq(client->name, name))
+                       return matches;
+       }
+
+       return NULL;
+}
+
 #else
 static void of_i2c_register_devices(struct i2c_adapter *adap) { }
 #endif /* CONFIG_OF */