Linux I2C Slave Driver

We will discuss about the Linux implementation of the I2C slave device drivers. We will investigate the example driver and also browse through the implementation of the driver to understand the I2C client/slave drivers in detail.


I2C is the protocol of communication between two ICs. One IC refers to the master and the other IC refers to the slave. Let us take an example of the board if a new slave device is connected on the board on an already existing I2C BUS. The I2C bus is controlled by the I2C master. Connecting a new device requires the introduction of the I2C client driver in the Linux OS. Though, without the I2C slave driver, the device can be accessed with the i2c-utils through the I2C master but those access are purely I2C data/messages.

To understand it in more details, let us take an example of the eeprom device which is an I2C slave device. Once the eeprom is connected on the board, if the user queries through, the “i2cdetect” logs show the slave device on the bus with the eeprom slave address. But if this lower level I2C communication needs to be transparent to the user, the user can introduce the I2C slave driver for eeprom. The user need not to access the eeprom with the raw I2C commands through the i2c-utils. The user can access the eeprom through the device file and to the simple read/write to manipulate the data.

0 seconds of 0 secondsVolume 0%

Loading ad

The Linux framework for the I2C slave driver expects the object for the “i2c_driver” struct with the proper values as the following example:

static struct i2c_driver eeprom_driver = {
    .driver = {
        .name   = “eeprom”,
        .of_match_table = eeprom_of_match,
    .probe      = eeprom_probe,
    .id_table   = eeprom_id,

.driver: This field takes the name of the driver and compatible string that are required for probe().

.probe: This is the probe function for the driver.

.id_table; This is the device ID for the device which is passed to the macro “MODULE_DEVICE_TABLE”.

Once this structure is populated, the driver can be registered through the following call:


The device ID creation can be done as follows:

static const struct i2c_device_id eeprom_id[] = {
 { “eeprom”, eeprom },
 { }
MODULE_DEVICE_TABLE(i2c, eeprom_id);

Next, the important piece is the probe function for the driver. When the driver binds with the device, it calls the probe function. The probe function does all the setup of the resources and prepares the device for the functioning. The example of tasks which are done in the probe function are as follows:

  1. Allocating the memory resources
  2. Registering of interrupts if the device supports IRQ
  3. Device’s hardware programming…. etc.

The probe function is called only once when the device and the driver binding is happening. Once the binding of the device and driver is done, the device is ready for further read/write functions.

The standard prototype for the I2C slave driver in the Linux I2C framework is as follows:

static int eeprom_probe(struct i2c_client *client)





Let us elaborate more on the probe function by considering the eeprom device. In the probe function, the driver can expose the device file and can register the read and write functions through “ioctl” or “sysfs”.

If the user reads or writes to the device file, this driver processes those requests through the read and write functions of the driver. We will discuss the read and write function of the driver further. For now, let us focus on the probe function. Setting up of this infrastructure creation of the device file and registering those read/write function with the device file is done in the probe function. Along with these, the device supports the interrupts. Then, the IRQ line request should be done and the registration of interrupt for this device to the IRQ table should also be done in the probe function. This is completely device dependent. For eeprom device, the general interrupts are not required.

Now, let us take the read/write functions for the I2C slave driver. There is no standard prototype that is defined for this but the lower level that is called to access the device should be done through the I2C function calls of the adapter since this is the slave device and it is associated with the I2C bus master. The I2C bus master is used to access the device. The example function for the I2C master communication is i2c_transfer() though there are many functions that exist. To use the i2c_transfer() function, one should create the “i2c_msg” object and pass the reference to the object to the i2c_transfer().

Leave a Reply

Your email address will not be published. Required fields are marked *