The PCA954X is a family of I2C multiplexers/switches that allow you to control multiple I2C devices using a single I2C bus. In this section, we will explore how to manually switch between different channels of the PCA954X I2C mux.
Using the i2c-tools
The i2c-tools package provides a set of command-line tools for interacting with I2C devices in Linux. We will be using three main tools: i2cdetect
, i2cdump
, and i2cset
. Make sure you have the i2c-tools package installed on your system before proceeding.
i2cdetect
The i2cdetect
tool allows you to scan the I2C bus and detect devices connected to it. It provides a grid view with addresses and corresponding symbols indicating the presence of I2C devices. Here’s an example output:
1 | root@albertlin:~# i2cdetect -y 4 |
The symbols used in the output have the following meanings:
- “–”: The address was probed, but no chip responded.
- “UU”: Probing was skipped because this address is currently in use by a driver, suggesting the presence of a chip.
- Hexadecimal address: Indicates the presence of a chip at that address.
i2cdump
The i2cdump
tool allows you to read and display the content of registers on an I2C device. You need to provide the bus number and the address of the device you want to dump. Here’s an example usage:
1 | root@albertlin:~# i2cdump -y 4 0x16 |
This output displays the content of the registers starting from address 0x00.
i2cset
The i2cset
tool allows you to set the content of registers on an I2C device. You need to provide the bus number, the address of the device, and the data you want to write. Here’s an example usage:
1 | root@albertlin:~# i2cset -y 4 0x70 0x00 0x04 |
In this example, we are writing the value 0x04 to register address 0x00 of the device at address 0x70 on bus 4.
PCA954X I2C Mux
The PCA954X is a family of I2C multiplexers/switches. You can find the datasheet for PCA9545A/B/C here.
Changing DTS through Yocto
If you’re using Yocto to build your Linux image, you can customize the Linux kernel configuration by following these steps:
Open a terminal and navigate to your Yocto build directory.
Run the following command to enter the Linux kernel menuconfig:
1 | bitbake -c menuconfig virtual/kernel |
- Make the necessary changes in the menuconfig interface. Once you’re
done, save and exit.
- Additionally, you can generate a defconfig file by running the following command:
1 | bitbake -c savedefconfig virtual/kernel |
Writing I2C Mux Device Tree Bindings
To configure the PCA954X I2C mux in the device tree, you can refer to the following documentation:
You can also check out an example of using the PCA954X I2C mux in the device tree in the aspeed-bmc-facebook-minipack.dts file.
Using new_device
and delete_device
To add or remove I2C devices dynamically, you can use the new_device
and delete_device
attributes in the sysfs interface. Here’s an example:
1 | root@albertlin:/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a300.i2c-bus/i2c-5/i2c-16/i2c-20# ls |
In the above example, delete_device
is used to remove the device with address 0x49, and new_device
is used to add a device named “tmp75” at address 0x49.
Reading Kernel Configuration at Runtime
To view the kernel configuration at runtime, you can use the following command:
1 | zcat /proc/config.gz |
This command will display the configuration options of the running kernel.
Switching PCA954X Channels
To manually switch the channel of an I2C mux, you can use the i2cset
command with the appropriate parameters. Here’s an example:
1 | i2cset -y 5 0x70 0x01 # Switch to channel 0 |
In the above commands, -y 5
specifies the I2C bus number (5 in this case), 0x70
is the address of the I2C mux device, and 0x01
, 0x02
, and 0x04
are the channel values representing channel 0, channel 1, and channel 2, respectively.
Here’s an example of how you can use these commands:
1 | root@albertlin:~# i2cset -y 5 0x70 1 # Switch to channel 0 |
In the above example, we first switch to channel 0 by using i2cset -y 5 0x70 1
, then we scan for devices on the I2C bus using i2cdetect -y 5
. After that, we switch to channel 1 with i2cset -y 5 0x71 0
and perform another scan using i2cdetect -y 5
. Finally, we switch to channel 2 with i2cset -y 5 0x71 2
and perform a scan again.