Problems with I2C OF support
In Linux, devices and drivers are registered independently in a non-deterministic order, and the kernel keeps a list of registered drivers and devices per bus type and these lists are used to lookup for a match each time that either a driver or a device is registered for a particular bus type.
It's up to each subsystem to define its own device to driver matching logic by defining a struct bus_type .match handler. But most subsystems rely on a set of device ID tables that need to be declared by drivers and these are later used to do the match.
Usually drivers declare a device ID table per device registration mechanism, since the ID for a device may be different depending on the firmware interface that's used to describe the hardware topology.
The I2C subsystem supports the following device ID tables:
- struct i2c_device_id
- - For drivers used in systems where the devices are registered using platform code.
- struct acpi_device_id
- - For drivers used in systems where the devices are registered via ACPI tables.
- struct of_device_id
- - For drivers used in systems where the devices are registered using Open Firmware (Flattened) Device Trees.
So for example if the device supported by a driver can either be present in systems using DT or legacy board files, both an OF and I2C device ID tables should be declared.
Now, subsystems can be lax on this requirement and allow drivers with only some of these tables to be matched even if they don't have the corresponding device ID table for the used registration mechanism.
That's the case for the I2C subsystem, which uses as a fallback the struct i2c_device_id table on a DT system if a driver either doesn't even have a struct of_device_id table or if the device isn't found in the OF table. This allow existing I2C drivers to be used in DT systems with no changes as long as the device part of the compatible string matches a device name in the I2C device ID table.
But this approach leads to the following issues in the I2C core subsystem that now needs to be fixed:
- Vendor prefix in compatible string not used to match for drivers supporting DT
- Many drivers that are meant to be used in DT systems (and may even be DT-only) don't define a struct of_device_id table since in practice isn't needed. This means that the struct i2c_device_id table is used to match, which doesn't take into account the compatible string vendor prefix.
- Wrong compatible strings in Device Tree Source files and DT binding documents
- Some system integrators went even as far as defining DT bindings with compatible strings that don't have a vendor prefix or used the device ID found in the I2C table as compatible strings in Device Tree source files.
- I2C modalias always reported regardless if devices were registered using DT or legacy platform devices
- The device ID tables are not only meant to be used for matching, these are also used by modpost to fill the aliases in driver modules.
- The aliases are used by udev to auto-load a driver module if the kernel reports a modalias uevent that matches these aliases.
- Since a OF device ID table wasn't needed in practice, the I2C core doesn't report a OF modalias and instead always reports a I2C modalias regardless if the device was registered using OF or legacy platform devices.
- This means that even drivers that only are used in DT systems must have an I2C device ID table for the only purpose of having module auto-loading working.
Fixing the I2C core to report a proper OF modalias is trivial, as shown in this RFC patch.
But this can't be changed until all drivers used in DT systems and are relying in the current behaviour (don't declare a struct of_device_id table) are fixed and have a proper OF device ID table to prevent adding module auto-load regressions on these drivers once the I2C core starts reporting OF modaliases.
Since as mentioned some DTS and DT bindings docs use compatible strings with no vendor prefix, it should be discussed with DT maintainers if these DTS and bindings can be fixed or if OF entries with no vendor prefix should be used to maintain backward compatibility.