[PATCH v2] ARM: dts: aspeed: msx4: describe the I2C5 mux tree

Ender Hsieh andhsieh at nvidia.com
Fri Sep 4 02:34:12 PDT 2026


The MSX4 carries four PCA9548 8-channel muxes on I2C5, and a PCA9546
4-channel mux behind channels 1 and 5 of the mux at 0x70 and channels 3
and 7 of the mux at 0x73. None of that is described here, so the muxes
are created from userspace and their channels are numbered in the order
userspace happens to create them.

That makes a channel's bus number a function of discovery order rather
than of where the channel sits in the topology, so anything that wants
to identify a device by its position has nothing stable to key on.

Describe the tree and give every channel an alias so the numbering comes
from the description instead. The aliases reproduce the numbers the
current userspace instantiation produces, so existing configuration
keeps working.

The four PCA9546 all answer at 0x72, and two of them sit behind
different PCA9548 on the same parent bus, so both can be exposed at once
if their parents are left selected. i2c-mux-idle-disconnect prevents
that.

I2C5 is shared with the host, which configures the voltage regulators
on it during POST, and a mux inside the CPLD decides which side reaches
the segment. The BMC is handed the bus once POST completes, so the muxes
described here do not necessarily answer when the kernel first probes
them, and the platform binds them once the CPLD reports the buses ready.

The reset line the four PCA9548 share is left out for the same reason.
A driver asserting it has no way to tell whether the bus is currently
the BMC's, and the reset cannot help at boot anyway: what fails there is
reaching the muxes at all, not their state.

Booted on an MSX4 from both a warm reboot and a cold power cycle. All
eight muxes register, the channels come up as i2c-16 through i2c-63
exactly as the aliases name them, and the eight FRU EEPROMs behind the
second level read as before. On the cold power cycle the kernel's probe
of the four PCA9548 fails at 1.7s, and they are bound once the CPLD
reports the buses ready 2150s later.

Cc: Marc Olberding <molberding at nvidia.com>
Signed-off-by: Ender Hsieh <andhsieh at nvidia.com>
---
Changes in v2:
- Drop reset-gpios. Measured on an MSX4, that line is shared: pulsing it
  clears the channel selection of the muxes at 0x70, 0x71, 0x73 and 0x75
  together, and leaves the four PCA9546 behind them untouched. Naming it
  on one mux alone was therefore wrong. Naming it on all four would
  describe the hardware correctly, but I2C5 is arbitrated between the
  host and the BMC by a mux inside the CPLD, and a driver asserting the
  reset cannot tell whose the bus currently is, so the line is left out
  of the description entirely.
- Say in the commit message that the bus is shared with the host, so it
  is clear why the muxes may not answer when the kernel first probes
  them.

v1: https://lore.kernel.org/all/20260903105956.1709114-1-andhsieh@nvidia.com/
 .../dts/aspeed/aspeed-bmc-nvidia-msx4-bmc.dts | 401 ++++++++++++++++++
 1 file changed, 401 insertions(+)

diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-msx4-bmc.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-msx4-bmc.dts
index 29f56176e2ca..a473bb2ccd0f 100644
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-msx4-bmc.dts
+++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-nvidia-msx4-bmc.dts
@@ -15,6 +15,55 @@ aliases {
 		serial2 = &uart3;
 		serial3 = &uart4;
 		serial4 = &uart5;
+
+		i2c16 = &i2c5mux0chn0;
+		i2c17 = &i2c5mux0chn1;
+		i2c18 = &i2c5mux0chn2;
+		i2c19 = &i2c5mux0chn3;
+		i2c20 = &i2c5mux0chn4;
+		i2c21 = &i2c5mux0chn5;
+		i2c22 = &i2c5mux0chn6;
+		i2c23 = &i2c5mux0chn7;
+		i2c24 = &i2c5mux1chn0;
+		i2c25 = &i2c5mux1chn1;
+		i2c26 = &i2c5mux1chn2;
+		i2c27 = &i2c5mux1chn3;
+		i2c28 = &i2c5mux1chn4;
+		i2c29 = &i2c5mux1chn5;
+		i2c30 = &i2c5mux1chn6;
+		i2c31 = &i2c5mux1chn7;
+		i2c32 = &i2c5mux2chn0;
+		i2c33 = &i2c5mux2chn1;
+		i2c34 = &i2c5mux2chn2;
+		i2c35 = &i2c5mux2chn3;
+		i2c36 = &i2c5mux2chn4;
+		i2c37 = &i2c5mux2chn5;
+		i2c38 = &i2c5mux2chn6;
+		i2c39 = &i2c5mux2chn7;
+		i2c40 = &i2c5mux3chn0;
+		i2c41 = &i2c5mux3chn1;
+		i2c42 = &i2c5mux3chn2;
+		i2c43 = &i2c5mux3chn3;
+		i2c44 = &i2c5mux3chn4;
+		i2c45 = &i2c5mux3chn5;
+		i2c46 = &i2c5mux3chn6;
+		i2c47 = &i2c5mux3chn7;
+		i2c48 = &i2c17mux0chn0;
+		i2c49 = &i2c17mux0chn1;
+		i2c50 = &i2c17mux0chn2;
+		i2c51 = &i2c17mux0chn3;
+		i2c52 = &i2c21mux0chn0;
+		i2c53 = &i2c21mux0chn1;
+		i2c54 = &i2c21mux0chn2;
+		i2c55 = &i2c21mux0chn3;
+		i2c56 = &i2c35mux0chn0;
+		i2c57 = &i2c35mux0chn1;
+		i2c58 = &i2c35mux0chn2;
+		i2c59 = &i2c35mux0chn3;
+		i2c60 = &i2c39mux0chn0;
+		i2c61 = &i2c39mux0chn1;
+		i2c62 = &i2c39mux0chn2;
+		i2c63 = &i2c39mux0chn3;
 	};
 
 	chosen {
@@ -151,6 +200,358 @@ eeprom at 51 {
 
 &i2c5 {
 	status = "okay";
+
+	i2c-mux at 70 {
+		compatible = "nxp,pca9548";
+		reg = <0x70>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c5mux0chn0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		i2c5mux0chn1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			i2c-mux at 72 {
+				compatible = "nxp,pca9546";
+				reg = <0x72>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				i2c-mux-idle-disconnect;
+
+				i2c17mux0chn0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c17mux0chn1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c17mux0chn2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c17mux0chn3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		i2c5mux0chn2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		i2c5mux0chn3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+
+		i2c5mux0chn4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+		};
+
+		i2c5mux0chn5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+
+			i2c-mux at 72 {
+				compatible = "nxp,pca9546";
+				reg = <0x72>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				i2c-mux-idle-disconnect;
+
+				i2c21mux0chn0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c21mux0chn1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c21mux0chn2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c21mux0chn3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		i2c5mux0chn6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+		};
+
+		i2c5mux0chn7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+		};
+	};
+
+	i2c-mux at 71 {
+		compatible = "nxp,pca9548";
+		reg = <0x71>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c5mux1chn0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		i2c5mux1chn1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		i2c5mux1chn2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		i2c5mux1chn3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+
+		i2c5mux1chn4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+		};
+
+		i2c5mux1chn5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+		};
+
+		i2c5mux1chn6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+		};
+
+		i2c5mux1chn7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+		};
+	};
+
+	i2c-mux at 73 {
+		compatible = "nxp,pca9548";
+		reg = <0x73>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c5mux2chn0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		i2c5mux2chn1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		i2c5mux2chn2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		i2c5mux2chn3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+
+			i2c-mux at 72 {
+				compatible = "nxp,pca9546";
+				reg = <0x72>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				i2c-mux-idle-disconnect;
+
+				i2c35mux0chn0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c35mux0chn1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c35mux0chn2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c35mux0chn3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+
+		i2c5mux2chn4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+		};
+
+		i2c5mux2chn5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+		};
+
+		i2c5mux2chn6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+		};
+
+		i2c5mux2chn7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+
+			i2c-mux at 72 {
+				compatible = "nxp,pca9546";
+				reg = <0x72>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				i2c-mux-idle-disconnect;
+
+				i2c39mux0chn0: i2c at 0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <0>;
+				};
+
+				i2c39mux0chn1: i2c at 1 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <1>;
+				};
+
+				i2c39mux0chn2: i2c at 2 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <2>;
+				};
+
+				i2c39mux0chn3: i2c at 3 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					reg = <3>;
+				};
+			};
+		};
+	};
+
+	i2c-mux at 75 {
+		compatible = "nxp,pca9548";
+		reg = <0x75>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		i2c-mux-idle-disconnect;
+
+		i2c5mux3chn0: i2c at 0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+		};
+
+		i2c5mux3chn1: i2c at 1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+		};
+
+		i2c5mux3chn2: i2c at 2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <2>;
+		};
+
+		i2c5mux3chn3: i2c at 3 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <3>;
+		};
+
+		i2c5mux3chn4: i2c at 4 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <4>;
+		};
+
+		i2c5mux3chn5: i2c at 5 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <5>;
+		};
+
+		i2c5mux3chn6: i2c at 6 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <6>;
+		};
+
+		i2c5mux3chn7: i2c at 7 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <7>;
+		};
+	};
 };
 
 &i2c6 {
-- 
2.34.1




More information about the linux-arm-kernel mailing list