4

I saw one scenario where "struct of_device_id" is not defined in the driver, but in the device tree(dts) file compatible string added for the same device entry.

Following is the sample device tree entry for the chip.

&i2c1 {

    ...

    adv7ex: adv7ex@4a {
            compatible = "adv7ex";
            reg = <0x4a>;
    };

    ...

 };

Following is sample code snippet for the driver of the chip which is registering as a I2C driver.

static struct i2c_device_id adv7ex_id[] = {
    { "adv7ex", ADV7EX },
    { }
};
MODULE_DEVICE_TABLE(i2c, adv7ex_id);

static struct i2c_driver adv7ex_driver = {
    .driver = {
        .owner = THIS_MODULE,
        .name = "adv7ex",
    },
    .probe = adv7ex_probe,
    .remove = adv7ex_remove,
    .id_table = adv7ex_id,
};

module_i2c_driver(adv7ex_driver);

Could you please help me to understand how device to driver binding is happened in this case as there no "of_device_id" structure definition in the driver.

user3693586
  • 1,227
  • 5
  • 18
  • 40
  • I guess you are looking for something like: i2c_register_adapter() -> of_i2c_register_devices() -> of_i2c_register_device() -> of_modalias_node(). – 0andriy Feb 09 '15 at 13:30
  • I am not sure the purpose of of_i2c_register_device(), my doubht here is if there is no compatible string filled in the bare driver structure(struct device_driver), then how device tree core will bind the device entry with the driver. – user3693586 Feb 09 '15 at 13:40
  • In kernel there is only one mapping, i.e by name (or modalias which is an alias to the name). So, you have to provide in both device tree and driver the same name. The question is probably how to match them. – 0andriy Feb 09 '15 at 13:43
  • that is true, but in the scenario where I saw only name was updated for the device entry in the device tree, but no name was updated in the driver(shown above). my guess here is I2C core will take care of binding the device to the drive, and device tree core will not involve in binding the device to driver. is this correct? – user3693586 Feb 09 '15 at 14:20
  • And how i2c core will know what the driver to load? They are both involved. – 0andriy Feb 09 '15 at 15:27

3 Answers3

3

I have a similar case and finally found the explanation: There seems to be an undocumented twist in the device tree i2c device binding.

Lets look at i2c_device_match() (i2c-core-base.c):

/* Attempt an OF style match */
if (i2c_of_match_device(drv->of_match_table, client))
    return 1;

And what actually happens in i2c_of_match_device() (i2c-core-of.c)?:

*i2c_of_match_device(const struct of_device_id *matches,
         struct i2c_client *client){ 
const struct of_device_id *match;

if (!(client && matches))
    return NULL;

match = of_match_device(matches, &client->dev);
if (match)
    return match;

return i2c_of_match_device_sysfs(matches, client); }

Hmm, we first try Open Firmware-style match with compatible fields, but if that fails, we still call i2c_of_match_device_sysfs(). And what does it do?

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; }

BINGO! As you can see in the code, i2c_of_match_device_sysfs() compares the compatible string from the Device Tree to name field of the driver i2c_device_id. In addition, if there is a comma in the compatible field, the matching will be done for the part following the comma.

So in your case, device tree data

compatible = "adv7ex"

is matched against "adv7ex" in

static struct i2c_device_id adv7ex_id[] = {
{ "adv7ex", ADV7EX },
{ } };
MODULE_DEVICE_TABLE(i2c, adv7ex_id);

Even if your compatible would be "acme-inc,adv7ex", as is the recommended notation for Device tree, it would still be matched.

Juha Lipponen
  • 188
  • 1
  • 8
1

Actually, it is not kernel that will load your driver, but userspace tools:

MODULE_DEVICE_TABLE(i2c, adv7ex_id);

This macro adds specific symbol names in your final compiled module (ie: .ko file) that will be parsed by depmod tool, that will then add a "reference" to your driver in module.alias and finally your driver will be loaded by your user hotplug tool.

Reference: https://www.kernel.org/doc/ols/2001/hotplug.pdf Section 5.

alexghiti
  • 91
  • 4
0

As you can see here, i2c_device_match() function first tries to match device by compatible string (OF style, which is Device Tree). And if it fails, it then tries to match device by id table.

Jagdish
  • 1,848
  • 3
  • 22
  • 33