Last edited 6 months ago

I3C overview

Applicable for STM32MP25x lines

This article provides basic information on the Linux® I3C system and how I3C STM32 driver is plugged upon.

1. Framework purpose[edit | edit source]

This article aims to explain how to use I3C and more accurately:

  • how to activate I3C interface on a Linux® BSP
  • how to access I3C from kernel space
  • how to access I3C from user space.

This article describes Linux® I3C[1] interface in master modes.

An overview of I3C, and more specifically in Linux®[2] is proposed through this external resource.

2. System overview[edit | edit source]

The MIPI® I3C (MIPI Improved Inter-Integrated Circuit) protocol is a versatile, high-speed, and cost-effective interface that facilitates communication between various components in mobile, automotive, and IoT devices.

I3C is the acronym for the microprocessor MIPI® I3C peripheral interface.

The I3C protocol aims to retain the basic framework of I2C while addressing its limitations and adding new features that are critical for modern applications. I3C brings several benefits over I2C, including:

  • Higher data rates: I3C supports data rates up to 12.5 Mbps, which is significantly higher than the standard I2C speeds. This allows for faster data transfer between devices.
  • Improved power efficiency: I3C is designed to be power-efficient, which is essential for battery-powered devices.
  • Better bus utilization: with support for In-Band Interrupts (IBI) and Dynamic Address Assignment (DAA), the I3C bus can be used more efficiently that I2C.
  • Scalability: the protocol can support a larger number of devices on the same bus without significant performance degradation.

Around the microprocessor device, the user can add many MIPI® I3C and I2C external devices to create a custom board. Each external device can be accessed through the I3C from the user space or the kernel space.


I2C toolsI2C libraryApplicationI2C libraryi2c-dev interfaceBoard peripheral driversBoard peripheral driversBoard peripheral driversI<sup>2</sup>C frameworkI3C frameworkSTM32 I3C driverSTM32 I3C peripheralSTM32 I3C peripheralBoard peripheralBoard peripheralBoard peripheral
Implementation architecture

2.1. Component description[edit | edit source]

2.1.1. Board external I3C devices[edit | edit source]

Target devices X are physical devices (connected to STM32 I3C controller via MIPI® I3C bus and/or I2C bus) that behave as Target with respect to STM32.
STM32 remains the controller on the MIPI® I3C bus (and the I2C bus).

2.1.2. STM32 I3C internal peripheral controller[edit | edit source]

It corresponds to STM32 I3C adapter that handles communications with any external device connected on the same bus.
It manages Target MIPI® I3C and I2C devices (if any).

STM32 microprocessor devices usually embed several instances of the I3C internal peripheral allowing to manage multiple I3C buses. A driver is provided that pilots the hardware.

2.1.3. stm32-i3c-master[edit | edit source]

The STM32 I3C controller driver offers ST I3C internal peripheral controller abstraction layer to I3C framework.

It implements all I3C hooks to be used by I3C framework, this includes bus management, I3C devices management, CCC (Control Command Code) transactions, private SDR transfers, I2C devices management and IBI (In-Band Interrupts) management.

2.1.4. I3C framework[edit | edit source]

The core I3C bus driver is the central component of the I3C framework. It manages the I3C bus, ensuring communication between the controller and target devices. The I3C framework provides the necessary hooks and callbacks for device drivers to interact with the I3C subsystem. This includes:

  • A registration mechanism for I3C devices to make themselves known to the core driver.
  • Functions to initiate data transfers, both read and write operations.
  • Callbacks for handling asynchronous events such as in-band interrupts.
  • Support for device-specific operations and configurations.

The I3C framework uses several key data structures to manage the I3C subsystem:

  • i3c_master_controller: This structure represents an I3C master controller. It contains pointers to operations that can be performed by the controller, information about the bus (like the maximum data rate supported), and a list of attached devices.
  • i3c_device: This structure represents an I3C device (either controller or target). It includes the device's address, its capabilities, and the operations it can perform.
  • i3c_bus: This structure represents the I3C bus itself and includes a list of controllers and targets on the bus.
  • i3c_driver: This structure is used by I3C device drivers to register themselves with the core I3C framework.

The I3C framework uses the I2C framework to expose an I2C bus and manage I2C targets.

2.1.5. I2C overview[edit | edit source]

Refer to I2C overview for I2C framework, I2C tools, I2C library and Application.

2.1.6. Board peripheral drivers[edit | edit source]

This layer represents all drivers associated to physical peripherals.

A peripheral driver can be compiled as a kernel module or directly into the kernel (aka built-in).

3. Configuration[edit | edit source]

3.1. Kernel configuration[edit | edit source]

Activate I3C in kernel configuration with Linux Menuconfig tool: Menuconfig or how to configure kernel.

[x] Device Drivers
	[x] I3C support
		[x] STM32 I3C driver

This can be done manually in your kernel:

CONFIG_I3C=y
CONFIG_STM32_I3C_MASTER=y

3.2. Device tree configuration[edit | edit source]

Refer to I3C device tree configuration.

4. How to use the framework[edit | edit source]

This section describes how to use the framework to access I3C peripherals.

The below information focuses on device tree and sysfs.

4.1. Device tree[edit | edit source]

The device tree is a description of the hardware that is used by the kernel to know which devices are connected. In order to add a slave device on an I3C bus, complete the device tree with the information related to the new device.

Example : with a pressure sensor

&i3c4 {
	lsm6dso: imu@6a,208006c0000 {
		reg = <0x6a 0x208 0x6c0000>;
		assigned-address = <0x6a>;
	};
};

The LSM6DSO sensor is now instantiated on the bus i3c-X (X depends on how many adapters are probed at runtime) at address 0x6a and it is compatible with the driver registered with the same property (thanks to the reg property containing PID composed of Manufacturer ID, Part ID, Instance ID and extra information).

From st_lsm6dsx I3C driver drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c :

static const struct i3c_device_id st_lsm6dsx_i3c_ids[] = {
	I3C_DEVICE(0x0104, 0x006C, (void *)ST_LSM6DSO_ID),
	I3C_DEVICE(0x0104, 0x006B, (void *)ST_LSM6DSR_ID),
	{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(i3c, st_lsm6dsx_i3c_ids);
  • 0x208: it is the Manufacturer ID 0x0x104 left-shifted by 1
  • 0x6c: is is the Part ID 0x006C
  • last 0000 contains the Instance ID (0) and no extra information.

Please refer to I3C device tree configuration for proper configuration and explanation.

4.2. sysfs[edit | edit source]

Refer to Documentation/ABI/testing/sysfs-bus-i3c for a full description of files/directories/symlinks exposed by the I3C subsystem in sysfs.
Through sysfs, i2c-core offers the possibility to instantiate and remove a peripheral.
It is also applicable for I2C bus exposed by I3C Framework. Please refer to I2C overview.

5. How to trace and debug the framework[edit | edit source]

In Linux® kernel, there are standard ways to debug and monitor I3C. The debug can take place at different levels: hardware and software.

5.1. How to trace[edit | edit source]

5.1.1. Dynamic trace[edit | edit source]

Detailed dynamic trace is available here How to use the kernel dynamic debug

 echo  "file drivers/i3c/* +p" > /sys/kernel/debug/dynamic_debug/control

This command enables all traces related to I3C core and drivers at runtime.

5.2. How to debug[edit | edit source]

5.2.1. Detect I3C configuration[edit | edit source]

5.2.1.1. sysfs[edit | edit source]

When a peripheral is instantiated, i3c-core and the kernel export different files through sysfs :
/sys/bus/i3c/devices lists all instantiated peripherals. For example, there is a directory named xxx that corresponds to the xxx peripheral at address xxx on bus number xxx.
/sys/bus/i3c/drivers lists all instantiated drivers. Directory named xxx is the driver of xxx.

/sys/bus/i3c/devices/i3c-0
xxx

5.2.2. i2c-tools[edit | edit source]

I3C Framework driver exposes an I2C adapter for I2C transfers over I3C controller.

Check all I2C instantiated adapters:

i2cdetect -l

See i2c-tools for full description.

6. Source code location[edit | edit source]

7. References[edit | edit source]