Search code examples
linuxembedded-linuxi2c

Linux - Is it necessary to register (instantiate) i2c devices before using them?


I'm confused on how userspace programs using Linux's i2c dev interface is able to register (instantiate?) i2c devices.

From my understanding by reading this: https://www.kernel.org/doc/Documentation/i2c/instantiating-devices, it seems we need to either:

  1. Define a i2c_board_info struct with name and address of the i2c device, do a i2c_register_board_info()

  2. Have a devicetree entry such as this:

    i2c1: i2c@400a0000 {
        /* ... master properties skipped ... */
        clock-frequency = <100000>;
    
        flash@50 {
            compatible = "atmel,24c256";
            reg = <0x50>;
        };
    
        pca9532: gpio@60 {
            compatible = "nxp,pca9532";
            gpio-controller;
            #gpio-cells = <2>;
            reg = <0x60>;
        };
    };
    
  3. Instantiate devies explicitly by defining a i2c_board_info struct, then call i2c_new_device() in the init of the i2c device driver


But how is this done for user space programs using the i2c-dev interface described here https://www.kernel.org/doc/Documentation/i2c/dev-interface?

I don't have a devicetree entry, and when I grep the code for i2c_board_info, i2c_register_board_info(), or i2c_new_device() I don't find anything. But the code below still works, how?

#include <linux/i2c-dev.h>

void read_from_device(uint8_t *read_data)
{
  int result;

  file_desc = open("/dev/i2c-2", O_RDWR);

  ioctl(file_desc, I2C_SLAVE, device_address);

  i2c_smbus_write_byte_data(file_desc, DEVICE_PAGE_ADDRESS, page_number);

  result = i2c_smbus_read_byte_data(file_desc, device_register_address);

  *read_data = result;

  close(file_desc);
}

Does this mean we don't necessarily have to register (instantiate) i2c devices in order to use them? Does that apply to both i2c drivers as well as userspace programs using i2c-dev interface?


Solution

  • The i2c-dev driver binds to the bus (i2c_adapter), not a specific i2c device (i2c_client). So you only need to create the bus device to use i2c-dev and adding devices for the clients isn't necessary. In fact, you'll find i2c-dev will not let you use an I2C address bound to another driver unless you use the I2C_SLAVE_FORCE ioctl.

    This is the opposite to the spidev driver, which binds to a specific spi slave device and not the bus as a whole. I2C predates the modern Linux device model and some things are different than is done in other places.

    If you want a kernel driver to control the I2C device then there needs to be a device for the driver to bind to. The exception would be so-called "old style" I2C drivers which probe a set of addresses and bind to devices if any are found that appear to be the correct kind.