Linux I2C slave interface description

by Wolfram Sang <wsa@sang-engineering.com> in 2014-15

Linux can also be an I2C slave if the I2C controller in use has slavefunctionality. For that to work, one needs slave support in the bus driver plusa hardware independent software backend providing the actual functionality. Anexample for the latter is the slave-eeprom driver, which acts as a dual memorydriver. While another I2C master on the bus can access it like a regularEEPROM, the Linux I2C slave can access the content via sysfs and handle data asneeded. The backend driver and the I2C bus driver communicate via events. Hereis a small graph visualizing the data flow and the means by which data istransported. The dotted line marks only one example. The backend could alsouse a character device, be in-kernel only, or something completely different:

            e.g. sysfs        I2C slave events        I/O registers+-----------+   v    +---------+     v     +--------+  v  +------------+| Userspace +........+ Backend +-----------+ Driver +-----+ Controller |+-----------+        +---------+           +--------+     +------------+                                                              | |----------------------------------------------------------------+--  I2C--------------------------------------------------------------+----  Bus

Note: Technically, there is also the I2C core between the backend and thedriver. However, at this time of writing, the layer is transparent.

User manual

I2C slave backends behave like standard I2C clients. So, you can instantiatethem as described in the documentHow to instantiate I2C devices. The onlydifference is that i2c slave backends have their own address space. So, youhave to add 0x1000 to the address you would originally request. An example forinstantiating the slave-eeprom driver from userspace at the 7 bit address 0x64on bus 1:

# echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device

Each backend should come with separate documentation to describe its specificbehaviour and setup.

Developer manual

First, the events which are used by the bus driver and the backend will bedescribed in detail. After that, some implementation hints for extending busdrivers and writing backends will be given.

I2C slave events

The bus driver sends an event to the backend using the following function:

ret = i2c_slave_event(client, event, &val)

‘client’ describes the I2C slave device. ‘event’ is one of the special eventtypes described hereafter. ‘val’ holds an u8 value for the data byte to beread/written and is thus bidirectional. The pointer to val must always beprovided even if val is not used for an event, i.e. don’t use NULL here. ‘ret’is the return value from the backend. Mandatory events must be provided by thebus drivers and must be checked for by backend drivers.

Event types:

  • I2C_SLAVE_WRITE_REQUESTED (mandatory)

    ‘val’: unused

    ‘ret’: 0 if the backend is ready, otherwise some errno

Another I2C master wants to write data to us. This event should be sent onceour own address and the write bit was detected. The data did not arrive yet, sothere is nothing to process or return. After returning, the bus driver mustalways ack the address phase. If ‘ret’ is zero, backend initialization orwakeup is done and further data may be received. If ‘ret’ is an errno, the busdriver should nack all incoming bytes until the next stop condition to enforcea retry of the transmission.

  • I2C_SLAVE_READ_REQUESTED (mandatory)

    ‘val’: backend returns first byte to be sent

    ‘ret’: always 0

Another I2C master wants to read data from us. This event should be sent onceour own address and the read bit was detected. After returning, the bus drivershould transmit the first byte.

  • I2C_SLAVE_WRITE_RECEIVED (mandatory)

    ‘val’: bus driver delivers received byte

    ‘ret’: 0 if the byte should be acked, some errno if the byte should be nacked

Another I2C master has sent a byte to us which needs to be set in ‘val’. If ‘ret’is zero, the bus driver should ack this byte. If ‘ret’ is an errno, then the byteshould be nacked.

  • I2C_SLAVE_READ_PROCESSED (mandatory)

    ‘val’: backend returns next byte to be sent

    ‘ret’: always 0

The bus driver requests the next byte to be sent to another I2C master in‘val’. Important: This does not mean that the previous byte has been acked, itonly means that the previous byte is shifted out to the bus! To ensure seamlesstransmission, most hardware requests the next byte when the previous one isstill shifted out. If the master sends NACK and stops reading after the bytecurrently shifted out, this byte requested here is never used. It very likelyneeds to be sent again on the next I2C_SLAVE_READ_REQUEST, depending a bit onyour backend, though.

  • I2C_SLAVE_STOP (mandatory)

    ‘val’: unused

    ‘ret’: always 0

A stop condition was received. This can happen anytime and the backend shouldreset its state machine for I2C transfers to be able to receive new requests.

Software backends

If you want to write a software backend:

  • use a standard i2c_driver and its matching mechanisms

  • write the slave_callback which handles the above slave events(best using a state machine)

  • register this callback viai2c_slave_register()

Check the i2c-slave-eeprom driver as an example.

Bus driver support

If you want to add slave support to the bus driver:

  • implement calls to register/unregister the slave and add those to thestructi2c_algorithm. When registering, you probably need to set the I2Cslave address and enable slave specific interrupts. If you use runtime pm, youshould usepm_runtime_get_sync() because your device usually needs to bepowered on always to be able to detect its slave address. When unregistering,do the inverse of the above.

  • Catch the slave interrupts and send appropriate i2c_slave_events to the backend.

Note that most hardware supports being master _and_ slave on the same bus. So,if you extend a bus driver, please make sure that the driver supports that aswell. In almost all cases, slave support does not need to disable the masterfunctionality.

Check the i2c-rcar driver as an example.

About ACK/NACK

It is good behaviour to always ACK the address phase, so the master knows if adevice is basically present or if it mysteriously disappeared. Using NACK tostate being busy is troublesome. SMBus demands to always ACK the address phase,while the I2C specification is more loose on that. Most I2C controllers alsoautomatically ACK when detecting their slave addresses, so there is no optionto NACK them. For those reasons, this API does not support NACK in the addressphase.

Currently, there is no slave event to report if the master did ACK or NACK abyte when it reads from us. We could make this an optional event if the needarises. However, cases should be extremely rare because the master is expectedto send STOP after that and we have an event for that. Also, keep in mind notall I2C controllers have the possibility to report that event.

About buffers

During development of this API, the question of using buffers instead of justbytes came up. Such an extension might be possible, usefulness is unclear atthis time of writing. Some points to keep in mind when using buffers:

  • Buffers should be opt-in and backend drivers will always have to supportbyte-based transactions as the ultimate fallback anyhow because this is howthe majority of HW works.

  • For backends simulating hardware registers, buffers are largely not helpfulbecause after each byte written an action should be immediately triggered.For reads, the data kept in the buffer might get stale if the backend justupdated a register because of internal processing.

  • A master can send STOP at any time. For partially transferred buffers, thismeans additional code to handle this exception. Such code tends to beerror-prone.