The NXP i.MX95 CPU has eight I2C buses that operate at up to 400 Kbps. The CPU facilitates the functionality of both I2C master and slave according to the I2C Bus Specification v2.1, but the Linux kernel only contains an I2C bus master driver.

On the ConnectCore 95 SMT SOM:

  • LPI2C1 connects internally to the power management IC (PMIC) at the following address:

    Interface Address (7-bit)

    PMIC

    0x08

LPI2C1 is reserved and used internally by the System Manager (SM).

On the ConnectCore 95 SMARC SOM:

  • LPI2C1 is routed to I2C_PM of the SMARC connector (reserved for System Manager)

  • LPI2C2 is routed to I2C_GP of the SMARC connector

  • LPI2C4 is routed to I2C_CAM0 of the SMARC connector

  • LPI2C5 is routed to I2C_CAM1 of the SMARC connector

  • LPI2C7 is routed to I2C_LCD of the SMARC connector

  • LPI2C8 connects internally to the MCA at the following address:

    Interface Address (7-bit)

    MCA

    0x20

On the ConnectCore 95 Development Kit:

  • LPI2C2 is connected to:

    • the HDMI connector

    • the LT8912B MIPI-to-HDMI

    • the MIPI camera connector

  • LPI2C4 is connected to:

    • M.2 E-Key connector

    • the audio chip

  • LPI2C5 is connected to:

    • I2C connector

  • LPI2C7 is connected to:

    • the USB Type C

    • LVDS0 connector (for touchscreen)

    • LVDS1 connector (for touchscreen)

Kernel configuration

You can manage the I2C driver support through the kernel configuration:

  • IMX I2C interface (CONFIG_I2C_IMX)

This kernel configuration option is enabled as built-in on the default ConnectCore 95 kernel configuration file.

Kernel driver

The driver for the I2C interface is located at:

File Description

drivers/i2c/busses/i2c-imx.c

i.MX I2C controller driver

Device tree bindings and customization

The i.MX95 I2C interface device tree binding is documented at Documentation/devicetree/bindings/i2c/i2c-imx.yaml.

The I2C interfaces are defined in the CPU, system-on-module, and carrier board device tree files.

Example: LPI2C3

Define the bus

i.MX95 device tree
lpi2c3: i2c@42530000 {
	compatible = "fsl,imx95-lpi2c", "fsl,imx7ulp-lpi2c";
	reg = <0x42530000 0x10000>;
	interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
	clocks = <&scmi_clk IMX95_CLK_LPI2C3>,
		<&scmi_clk IMX95_CLK_BUSWAKEUP>;
	clock-names = "per", "ipg";
	dmas = <&edma2 9 0 1>, <&edma2 8 0 0>;
	dma-names = "rx", "tx";
	status = "disabled";
};

Configure IOMUX

ConnectCore 95 Development Kit device tree
&iomuxc {

	[...]

	pinctrl_lpi2c4: lpi2c4grp {
		fsl,pins = <
			IMX95_PAD_GPIO_IO30__LPI2C4_SDA		0x40000b9e
			IMX95_PAD_GPIO_IO31__LPI2C4_SCL		0x40000b9e
		>;
	};

Enable the bus and define attached client devices

ConnectCore 95 Development Kit device tree
&lpi2c4 {
	#address-cells = <1>;
	#size-cells = <0>;
	clock-frequency = <400000>;
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&pinctrl_lpi2c4>;
	pinctrl-1 = <&pinctrl_lpi2c4>;
	status = "okay";

	max98089: codec@10 {
		[...]
	};
};

Use the I2C bus

The I2C bus driver exposes device data through the sysfs at /sys/class/i2c-dev/.

The correct way to access an I2C device is through a kernel driver. Accessing the I2C bus from the file system can confuse your I2C bus and cause data loss on devices like EEPROMs. The following tools are recommended for debugging purposes only.

I2C device interface

You can access I2C devices on an adapter from user space, through the /dev interface. This support requires that you enable the kernel configuration option I2C device interface (CONFIG_I2C_CHARDEV).

Once you have enabled the option, you can use the /dev/i2c-N device node where N corresponds to the adapter number, starting at zero.

i2c-tools

You can install the i2c-tools package to access the I2C devices from user space. The package contains the following tools:

Tool Description

i2cdetect

Bus scanning

i2cdump

Device register dumping

i2cget

Device register reading

i2cset

Device register setting

All I2C tools operate on a specific I2C bus which is identified by number.

To obtain a formatted list of all I2C adapters on your system, run:

# i2cdetect -l
i2c-3   i2c             42540000.i2c                            I2C adapter
i2c-1   i2c             44350000.i2c                            I2C adapter
i2c-6   i2c             426d0000.i2c                            I2C adapter
i2c-7   i2c             426e0000.i2c                            I2C adapter

Query the I2C bus using the I2C bus number to find devices connected to that bus:

# i2cdetect 3
i2cdetect: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- UU 49 4a 4b -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

The example above shows several devices on the bus at addresses 0x10, 0x48, 0x49, 0x4a, and 0x4b. The ones showing UU denote this address is currently in use by a driver, while devices without a registered driver show the address (in the example 0x49, 0x4a, and 0x4b).

You can dump the registers of any of these devices using the i2cdump command with the I2C bus number as the first argument and the chip address as the second argument:

# i2cdump 3 0x49
i2cdump: WARNING! This program can confuse your I2C bus
Continue? [y/N] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 01 97 08 95 00 00 16 2d 00 5d 02 01 be 1b d3 00    ????..?-.]?????.
10: 01 0a 04 00 00 00 00 00 2c 05 03 03 80 07 4f 5e    ???.....,?????O^
20: 01 2c 01 fa 00 c8 00 5e 01 2c 01 fa 00 c8 00 0c    ?,??.?.^?,??.?.?
30: 00 00 00 00 98 08 65 04 04 00 24 00 94 00 58 00    ....??e??.$.?.X.
40: 00 00 64 00 04 00 59 00 f2 06 00 72 45 00 6a ad    ..d.?.Y.??.rE.j?
50: f3 00 08 00 b2 00 e4 0d 00 e4 8a 00 34 00 00 00    ?.?.?.??.??.4...
60: c8 00 01 00 ff ff ff ff ff ff ff ff ff ff ff ff    ?.?.............
70: 00 07 12 7a 00 24 d0 e0 12 5a 0d 23 3e 06 06 06    .??z.$???Z?#>???
80: 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06    ????????????????
90: 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06    ????????????????
a0: 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06    ????????????????
b0: 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06 06    ????????????????
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

Accessing the I2C bus using Digi APIx

An example application called apix-i2c-example is included in the dey-examples-digiapix recipe (part of dey-examples package) of the meta-digi layer. This application is an example of how to write data to an external EEPROM (24FC1026) and read it back using Digi APIx library on the ConnectCore 95 platform.

Go to GitHub to see the application instructions and source code.

See I2C API for more information about the I2C APIx.