The NXP i.MX6UL CPU has four 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 6UL:

  • I2C1 connects internally to the power management IC (PMIC), the on-module Micro Controller Assist (MCA), and the Atmel Cryptochip at the following addresses:

Interface Address (7-bit)

PMIC

0x08

Cryptochip

0x60

MCA

0x7E

  • I2C2, I2C3, and I2C4 are available for peripherals to use (multiplexed with other functionality).

On the ConnectCore 6UL SBC Express:

  • I2C2 is available on the expansion connector and on Grove connector J10.

On the ConnectCore 6UL SBC Pro:

  • I2C1 is available on a connector, which you can use to connect additional devices.

The following table lists the three devices on board the ConnectCore 6UL SBC Pro I2C bus:

Interface Address (7-bit)

Audio codec

0x10

NTAG

0x55

I/O Expander

0x6E

The ConnectCore 6UL SBC Pro device tree defines the following additional I2C devices:

The display touch controller has I2C address 0x10, but since the audio codec on the ConnectCore 6UL SBC Pro also has address 0x10, an I2C address translator on the Video Adapter Board moves the touch controller to address 0x14.

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 6UL 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.MX6UL I2C interface device tree binding is documented at Documentation/devicetree/bindings/i2c/i2c-imx.txt.

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

Example: I2C1

Define the bus

i.MX6UL device tree
i2c1: i2c@021a0000 {
        #address-cells = <1>;
        #size-cells = <0>;
        compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
        reg = <0x021a0000 0x4000>;
        interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&clks IMX6UL_CLK_I2C1>;
        status = "disabled";
};

Configure IOMUX

ConnectCore 6UL device tree
pinctrl_i2c1: i2c1grp {
        fsl,pins = <
                MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
                MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
        >;
};

Enable the bus and define attached client devices

ConnectCore 6UL SBC Pro device tree
&i2c1 {
	[...]

	goodix_touch: gt911@14 {
		compatible = "goodix,gt9271";
		reg = <0x14>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_goodix_touch>;
		interrupt-parent = <&gpio5>;
		interrupts = <2 IRQ_TYPE_EDGE_RISING>;
		irq-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
		reset-gpios = <&mca_ioexp_gpio 29 GPIO_ACTIVE_HIGH>;
		skip-firmware-request;
		reload-fw-on-resume;
	};

	[...]

I2C user space usage examples

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. You must first 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:

Description Tool

Bus scanning

i2cdetect

Device register dumping

i2cdump

Device register reading

i2cget

Device register setting

i2cset

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-0   i2c             21a0000.i2c                             I2C adapter

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

~# i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- UU -- -- -- -- -- -- --
10: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: 60 -- -- -- -- -- -- -- -- -- -- -- -- -- UU --
70: -- -- -- -- -- -- -- --

The example above shows several devices on the bus at addresses 0x08, 0x10, 0x60, and 0x6e. 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 0x60).

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 0 0x60
No size specified (using byte-data access)
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0, address 0x60, mode byte
Continue? [Y/n] y
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: XX XX XX 04 11 33 43 04 11 33 43 04 11 33 43 04    XXX??3C??3C??3C?
10: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
20: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
30: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
40: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
50: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
60: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
70: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
80: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
90: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
a0: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
b0: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
c0: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
d0: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
e0: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?
f0: 11 33 43 04 11 33 43 04 11 33 43 04 11 33 43 04    ?3C??3C??3C??3C?