My understanding of this is fairly minimal so bear with me. From what I gather so far, the i2c subsystem on Linux identifies devices that are attached, and then matches them against loaded driver modules somehow. Where it identifies a match, it calls that driver's probe function which actually kicks off the driver setup.

I'm struggling to debug a non-functional camera; I can see that the i2c subsystem sees that it exists and has built directories for it in /sys/bus/i2c/i2c-7, and I can tell that the .probe_new() function for this driver is not called, because I added a bunch of debug messages to it. I am guessing therefore that the step where device is linked to driver is missing, but I can't figure out how that works.

Can anyone explain how the i2c-subsystem performs the device -> driver matching?


For clarity here; I know the driver declares that it's called "ov2680":

static const struct i2c_device_id ov2680[] = {
    {"ov2680", 0},
MODULE_DEVICE_TABLE(i2c, ov2680_id);

What I don't know is how does the i2c subsystem pick up a value from the device to try to match it against that declared device id in the drivers?


I²C doesn’t support device enumeration, so the kernel provides four different ways of initialising I²C devices:

  • listing them in a devicetree (the Warp i.MX7 Board does this with ov2680), in ACPI tables, or in board files (ignore the latter, it’s only provided for backward compatibility);
  • instantiating them explicitly, when the hardware “knows” they exist (this is common on TV adapters for example, which use an internal I²C bus to connect their various components);
  • probing for them during bus initialisation;
  • setting them up from user space.

The latter should allow you to force the device to be probed, if you know its address on the bus:

echo ov2680 0x50 > /sys/bus/i2c/devices/i2c-7/new_device

Once you’ve verified that that works, you can then figure out where you need to add information for the device to be initialised automatically, using either devicetree or bus-based probing. The kernel documentation (see the first link above) should get you going in the right direction.

Based on your comment referring to OVTI2680, I suspect the issue here is that there are two OmniVision OV2680 drivers, drivers/media/i2c/ov2680.c and drivers/staging/media/atomisp/i2c/atomisp-ov2680.c. The former is found using devicetree, the latter using ACPI, and the presence of an OVTI2680 file in your i2c directory suggests that the latter is being loaded.

  • thanks very much; I tried that command, and it does indeed trigger the probe command to be called. I am slightly confused though; prior to running that command there's already an OVTI2680:00 directory inside /sys/bus/i2c/devices/i2c-7...doesn't that mean the device was already initialised? I expected that that step had already been performed properly and that the problem was a mismatch in device id and driver id or something – Dan Scally Aug 5 '20 at 10:11
  • OK, that suggests the staging driver is being loaded; could that explain things? – Stephen Kitt Aug 5 '20 at 11:21
  • No it's the former driver being loaded rather than the staging one. Actually when I change the ov2680_id struct to contain OVTI2680:00 (matching the name file in /sys/bus/i2c/devices/i2c-7/OVTI2680:00) and then reboot it actually does automatically probe on reboot. So, I guess the chip itself says it's name is OVTI2680, and the former driver is intended to be mapped via devicetree like you say, which is why they don't see each other? Hadn't seen the staging driver! I'm going to try that out. – Dan Scally Aug 5 '20 at 11:58
  • I don’t think the chip itself can give its name, at least not over I²C. What kind of platform is this? Does it have ACPI? – Stephen Kitt Aug 5 '20 at 12:00
  • A laptop: Lenovo Miix 510. I believe it does yes – Dan Scally Aug 5 '20 at 12:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.