Enable 2nd eth in device-tree for Apalis i.MX8QM with Micrel KSZ9031RNX as phy

We did get it working.

There are multiple things that went wrong.
NOTE: we upgraded to BSP 5.6.0 in the mean time

Wrong voltage levels

we configure 1.8V when our board actually expects 2.5V

...
&reg_ext_rgmii {
	regulator-min-microvolt = <2500000>;
	regulator-max-microvolt = <2500000>;
	power-domains = <&pd IMX_SC_R_BOARD_R3>;

	regulator-state-mem {
		regulator-off-in-suspend;
	};
};
...

We did not mux the reset pin

Even if we do not control it via a dedicated GPIO, we still need to mux it.

...
&iomuxc {
	pinctrl-names = "default";
	/* NOTE: most of these labels come from imx8-apalis-v1.1.dtsi, the rest is defined here */
	pinctrl-0 = <&pinctrl_reset_moci>, ...
...

Reset timings need to be configured in nested phy node

&fec2 {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&pinctrl_fec2>;
	pinctrl-1 = <&pinctrl_fec2_sleep>;

	fsl,magic-packet;
	fsl,mii-exclusive;

	phy-supply = <&reg_ext_rgmii>;
	phy-handle = <&ethphy1>;
	phy-mode = "rgmii-id";

	status = "okay";

	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ethphy1: ethernet-phy@7 {
			compatible = "ethernet-phy-ieee802.3-c22";
			interrupt-parent = <&lsio_gpio0>;
			interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
			micrel,led-mode = <0>;

			/* these seem to be popular for KSZ9031*/
			reset-assert-us = <10000>;
			reset-deassert-us = <10000>;
			reset-gpios = <&lsio_gpio0 30 GPIO_ACTIVE_LOW>;
			reset-names = "phy-reset";

			reg = <7>;
		};
	};
};

Notes

  • After some discussion with toradex, they suggested using a dedicated GPIO to trigger the reset like they do with eth0
  • We pull ETH_INT to the wrong voltage on our board. It just happens to work and we should fix it, perhaps with a level changer.

Tips

  • Carefully measuring the interaction between our reset and the assertion of the phys MODE pins on was really helpful in verifiying the correct reset timings etc.
  • Sample with a high enough frequency when trying to capture MDIO traffic