So here’s the setup:
We have one 3-channel analog I2C mux at a fixed location. Access to each of the three mux channels is controlled by each of three GPIO pins, of which are located on different I/O expanders. Declaring the setup in device tree according to i2c-mux-gpio bindings allow everything to work correctly. The device tree node looks like this:
i2cmux-57226000.i2c {
compatible = "i2c-mux-gpio";
#address-cells = <1>;
#size-cells = <0>;
mux-gpios = <&pca9674_1 7 GPIO_ACTIVE_LOW &pca9674_2 7 GPIO_ACTIVE_LOW &pca9674_3 7 GPIO_ACTIVE_LOW>;
i2c-parent = <&i2c0_mipi1>;
i2c@1 {
reg = <1>; /* 0 0 1 */
#address-cells = <1>;
#size-cells = <0>;
};
i2c@2 {
reg = <2>; /* 0 1 0 */
#address-cells = <1>;
#size-cells = <0>;
};
i2c@4 {
reg = <4>; /* 1 0 0 */
#address-cells = <1>;
#size-cells = <0>;
};
};
The problem:
During runtime, the third I/O expander, pca9674_3
, which is necessary for the enumeration of the mux may not exist. This situation is not specific to a single setup, and can change from boot to boot depending on circumstances which can only be determined during runtime. We would like to account for this volatility by allowing the mux to work with or without pca9674_3
. In the case where pca9674_3
does not exist, we want a 2-channel mux to be enumerated instead of a 3-channel mux.
We attempted to solve this issue by declaring a 2-channel mux node underneath the 3-channel mux node in the device tree. This 2-channel mux node only occupies the required GPIO lines on pca9674_1
and pca9674_2
. The resulting device tree looks like this:
i2cmux-threechannel-57226000.i2c {
compatible = "i2c-mux-gpio";
#address-cells = <1>;
#size-cells = <0>;
mux-gpios = <&pca9674_1 7 GPIO_ACTIVE_LOW &pca9674_2 7 GPIO_ACTIVE_LOW &pca9674_3 7 GPIO_ACTIVE_LOW>;
i2c-parent = <&i2c0_mipi1>;
i2c@1 {
reg = <1>; /* 0 0 1 */
#address-cells = <1>;
#size-cells = <0>;
};
i2c@2 {
reg = <2>; /* 0 1 0 */
#address-cells = <1>;
#size-cells = <0>;
};
i2c@4 {
reg = <4>; /* 1 0 0 */
#address-cells = <1>;
#size-cells = <0>;
};
};
i2cmux-twochannel-57226000.i2c {
compatible = "i2c-mux-gpio";
#address-cells = <1>;
#size-cells = <0>;
mux-gpios = <&pca9674_1 7 GPIO_ACTIVE_LOW &pca9674_2 7 GPIO_ACTIVE_LOW>;
i2c-parent = <&i2c0_mipi1>;
i2c@1 {
reg = <1>; /* 0 1 */
#address-cells = <1>;
#size-cells = <0>;
};
i2c@2 {
reg = <2>; /* 1 0 */
#address-cells = <1>;
#size-cells = <0>;
};
};
So far this has worked for us. During each boot, if the enumeration of the 3-channel mux fails due to the absent pca9674_3
at runtime, enumeration of the 2-channel mux takes place and the mux is able to continue operating.
However, we have concerns that this hack is highly dependent on the order of declaration of the nodes in the device tree. In our testing, moving the declaration of the 2-channel mux node above the 3-channel mux node causes the enumeration of the 2-channel mux to take place prior to the 3-channel mux, which is not what we want. We have not found any documentation which defines how the order of declaration of nodes in the device tree affects the order of initialization of these devices during runtime.
Posting this thread in hopes to get some input on whether what we are currently doing is a good idea, or should be avoided.
Thanks,
Hatsy Rei
P.S. We have looked into device tree overlays, but our understanding is that we’ll still need to somehow know if the third I/O expander exists beforehand, then set the overlay accordingly. This doesn’t blend well with the unpredictable situation we are forced to work with. Modifying the i2c-mux-gpio driver may work, but unless absolutely necessary, we’d like to look at other options before going there.