I2C is a synchronous, half-duplex serial peripheral interface made up of two lines, SCL and SDA, and it transfers the MSB first (SPI can do either MSB or LSB first). The transfer speed depends on the SCL frequency. In Linux, the I2C subsystem is the kernel framework that manages I2C bus controllers (adapters), I2C devices (clients), and drivers, handling registration, matching, communication, and unified management. Detailed design notes and API documentation are available in <Linux kernel source>/Documentation/i2c.
The I2C subsystem consists mainly of the following parts:
The Linux I2C subsystem exposes device information and configuration through sysfs. The /sys/bus/i2c/devices directory shows the registered I2C adapters and the devices attached to them, including device addresses, driver bindings, and runtime state. Reading or writing the relevant sysfs nodes lets you query device information, bind and unbind drivers, and manage devices.
The Linux kernel normally creates device nodes under /dev, such as /dev/i2c-0 and /dev/i2c-3, one per I2C adapter. These character device nodes give user-space programs a standard access interface: applications use open(), ioctl(), read(), and write() to talk to a slave device on a given I2C bus, covering register reads and writes, device configuration, and data exchange.

Tip
The I2C rate can be changed by modifying the
clock-frequencyproperty of thei2c_bus0node in the DTS. Rebuild the kernel and reflash after changing it.
# list the I2C buses available in the system
ls /dev/i2c-*
Expected output:
/dev/i2c-0 /dev/i2c-1 /dev/i2c-2 /dev/i2c-3
# inspect the I2C controller
cat /sys/class/i2c-adapter/i2c-0/name
Expected output:
lotus-i2c
dmesg -n 2
# scan all devices on I2C bus 1 (addresses 0x03 ~ 0x77)
i2cdetect -y 1
Expected output:
i2cdetect: warning: can't use SMBus quick write command, will skip some addresses
0 1 2 3 4 5 6 7 8 9 a b c d e f
00:
10:
20:
30: 30 -- -- -- -- -- -- --
40:
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60:
70:
Tip
In the output,
UUmeans the device at that address is already claimed by a kernel driver,--means no device was detected, and a hexadecimal value is the detected device address (for example30means a device at 0x30).
# read register 0x00 (1 byte) of the device at 0x30 on bus 1
i2cget -y 1 0x30 0x00
# read register 0x00 (2 bytes, word mode) of the device at 0x30 on bus 1
i2cget -y 1 0x30 0x00 w
# write 0xaa to register 0x10 of the device at 0x30 on bus 1
i2cset -y 1 0x30 0x10 0xaa
# verify the write
i2cget -y 1 0x30 0x10
# read 256 bytes from the device at 0x30 on bus 1
i2cdump -y 1 0x30