Verdin IMX8MP and KSZ8873

I have ethernet switch KSZ8873RLLI connected via RMII to Verdin IMX8MP.
What is needed to be configured at all?

I have in U-Boot:

  • in DTS changed MDIO address from 7 to 2
  • disabled RGMII TX clk output (I need TX CLK input, KSZ is output)

In u-boot i see eth interface on MDIO:
Net: eth1: ethernet@30be0000, eth0: ethernet@30bf0000 [PRIME]

Verdin iMX8MP # mdio list
2 - Generic PHY <--> ethernet@30be0000

In linux kernel:

  • changed DTS changed MDIO address from 7 to 2
/* Verdin ETH_2_RGMII */
&fec {
	phy-handle = <&ethphy1>;
	phy-mode = "mii";
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&pinctrl_fec>;
	pinctrl-1 = <&pinctrl_fec_sleep>;

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

		ethphy1: ethernet-phy@2 {
			compatible = "ethernet-phy-ieee802.3-c22";
			interrupt-parent = <&gpio4>;
			interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
			micrel,led-mode = <0>;
			reg = <2>;

Nothing abou FEC or second ethernet found in dmesg or kernel messages.
What steps are needed to have KSZ8873 working?


Hi @msv_zitnik,

Thanks for reaching out.

I assume you are using your own carrier board am I right?

Can you maybe share a snippet of the schematic on how the phy is connected?

Best Regards

Hi @kevin.tx,

yes, we have our own carrier board. This is our RMII connection:

Hi @msv_hofmann,

can you share the the whole ethernet part also the connector?
best regards,


Hi, @matthias.tx,
the KSZ8873 switch has two 100BASE-TX ports (names PORT 1 and PORT 2) and one RMII port (name PORT 3). Because in our carrier board, the PORT 1 and PORT 2 are not solved with regular RJ-45 connectors (the connections are solved with DIN 41612 connector to other cards in rack), the schematic of PORT 1 and PORT 2 is quite irrelevant.

However I made a test of PORTS 1 & 2 connectivity & status:

  1. Our carrier board was powered on and the Verdin booting was stopped in bootloader by sending spaces to the terminal.
  2. With our custom cables I connected the company LAN to PORT 1 and my laptop to PORT 2. I also disabled Wi-Fi in my laptop and checked, that I am connected only with the cable trough KSZ8873 eth switch on our carrier board.
  3. I am sending this post connected as described above, the LINK/ACT LEDs of KSZ8873 on the carrier boad are blinking.
  4. With Verdin terminal I checked the state of MDIO registers:
Verdin iMX8MP # mii device FEC1
Verdin iMX8MP # mii read 1 0
Verdin iMX8MP # mii read 1 1
Verdin iMX8MP # mii read 2 0
Verdin iMX8MP # mii read 2 1

So MDIO (MIIM) interface is working and according to the registers the PORT 1 & 2 links are both ON. You can check the status in the KSZ8873 datasheet, pages 39, 40. What is not working is only PORT 3 connection between KSZ8873 and Verdin, which is realized by RMII.

In the previous schematic the ref. 50MHz clock was provided from KSZ to Verdin. We slightely changed the connection, so now the ref. 50MHz clock is provided from Verdin. So R108 was removed and the ref. 50 MHz was also connected to X1 (pin 17). The XTAL1 was removed. Also few strapping resistors had to be modified. The test described above was made with this changed connection (CLK sourced from Verdin).

The information about Linux configuration can provide my SW colleague @msv_zitnik.

Q1: Both variants of the 50 MHz clock sourcing are acceptable for us so please let us know, which variant is better from the compatibility point of view. From the EMC point of view, the variant with Verding sourcing ref. 50 MHz clock is better because the lack of noisy 25 MHz clock genetaror.

Today We made measurement of RMII interface with logic analyzer.

50 MHz ref. clock is sourced by Verdin.

Ping attempt from external laptop connected to PORT 1:
The CRS, RX0 and RX1 signals from KSZ8873 to Verdin looks good from my point of view. The data signals are changed with rising edge of REF CLK and probably should be sampled by Verdin with falling edge of REF CLK. There is just one bit per clock cycle. There is something bad happenning on signals TXEN and TX0.

ARP attempt to get IP from external DHCP initiated from Verdin:
Something which looks like data appears on TX1, however there is “inverted 50 MHz clock with duty cycle > 0,5” on TX0 and TXEN, which definitely should not be there. The data on TX1 also has much lower frequency than REF CLK.

It seems Verdin ignores recieved data on CRS, RX0 and RX1, because there is no reply. Also the data on TXEN, TX0 and TX1 are totally different, then it should look like.

TX0 and TXEN signals are high-Z in Verdin, so 50 MHz ref. CLK is somehow coupled to them. I checked them with osciloscope and there is something like 0,7 V on them, so the logic analyzer was picking the noise.

Why are TX0 and TXEN set to high-Z and not to OUT to drive the signals?

hi @msv_hofmann,

you need to connect ETH_2_RGMII_MDC and ETH_2_RGMII_MDIO to be able to access the registries of the switch. What you get from the mii command on Uboot are is most likely from the on-module Phy for the first ethernet. I also can find FEC1 with my Verdin iMX8MP on Yavia Board (which only has 1 Ethernet).

I am supporting @KDehren on this thread. Feel free to follow.

@matthias.tx can continue to support you if you need more help on the hardware side.

Hi @andi.tx,
ETH_2_RGMII_MDC and ETH_2_RGMII_MDIO are, in fact, connected to the switch. Sorry for the confusing schematic snippet in my first post, where these signals on Verdin were shown as disconnected. This was from the initial prototype of our board, where the switch management was intended to be done via SPI (as we did on our older board with KSZ8873 & STM32H753 MCU). Because the Verdin seems to manage the Ethernet PHYs with MDC/MDIO by default and the interface was disconnected, Verdin didn’t even initiate communication on RMII (it wasn’t aware of any connected PHY).

So, we rewired the connection. The MDC/MDIO are now connected, and strapping resistors on the PHY have been adjusted accordingly.

I am confident that with these commands:

I communicated with the KSZ8873. The onboard Ethernet of the Verdin wasn’t even connected. Also, the status bits changed accordingly to the KSZ8873 PORT 1 & PORT 2 link statuses.

Would you like us to provide any codes or configuration files from our Verdin operating system?

Hi @andi.tx,

This is our U-Boot device tree:

&fec {
	phy-handle = <&ethphy1>;
	phy-mode = "rmii";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_fec>;
	status = "okay";

	/* configure 50MHz REF and PHY_REF clock */
	assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_266M>,
					<&clk IMX8MP_SYS_PLL2_100M>,
					<&clk IMX8MP_SYS_PLL2_50M>;
	assigned-clock-rates = <0>, <100000000>, <50000000>, <0>;

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

		ethphy1: ethernet-phy@1 {
			compatible = "ethernet-phy-ieee802.3-c22";
			micrel,led-mode = <0>;
			reg = <1>;

			interrupt-parent = <&gpio3>;
			interrupts = <IRQ_TYPE_LEVEL_LOW>;

			reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>;
			reset-assert-us = <1000>; /* see datasheet TABLE 5-8 */
			reset-deassert-us = <10>; /* see datasheet TABLE 5-8 */

			status = "okay";


	pinctrl_fec: fecgrp {
		fsl,pins = <
			MX8MP_IOMUXC_SAI1_TXD6__ENET1_RX_ER		0x00000090 /* ETH_AUX_RXER */
			MX8MP_IOMUXC_HDMI_DDC_SDA__GPIO3_IO27		0x00000046 /* !ETH_AUX_INT */
			MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20		0x00000006 /* !ETH_AUX_PHY_RESET */

In board/toradex/verdin-imx8mp/verdin-imx8mp.c we have configured GPR1 to 50MHZ output clock:

static int setup_fec(void)
	struct iomuxc_gpr_base_regs *gpr =
		(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;

	// power down to 1
	gpio_request(FEC_EN, "FEC_EN");
	gpio_direction_output(FEC_EN, 1);

	/* Enable RGMII TX clk output */
	setbits_le32(&gpr->gpr[1], BIT(22));
	setbits_le32(&gpr->gpr[1], IOMUXC_GPR_GPR1_GPR_ENET1_TX_CLK_SEL_MASK);
	printf("SETUP FEC BIT22 -> 1\n");
	return 0;

MDIO seems to be woking perfectly in U-Boot.

Net:   eth1: ethernet@30be0000, eth0: ethernet@30bf0000 [PRIME]
Verdin iMX8MP # mdio list
1 - Generic PHY <--> ethernet@30be0000

In linux kernel messages is nothing about FEC or second ethernet instead of this:

[    1.328458] reg-fixed-voltage regulator-module-eth1phy: Failed to register regulator: -517

I tried steps and DTS from similar post Enabling second ethernet connection to a fully hardware configured switch IC
with no success.

Hi @msv_zitnik, @msv_hofmann

yes, indeed I see both ethernet addresses showing up with mdio list command. Can you try to modify your device tree to include the new .dts modification one I posted here Enabling second ethernet connection to a fully hardware configured switch IC - #4 by andi.tx?

I did some mistakes with the first suggestion. @KDehren could confirm that it works with overlay. (EDIT: it hasn’t worked yet, but still I suggest you try it in your .dts)

I understood that you change the device tree for U-Boot? Do you need the switch to be available in U-Boot already? Your changes in the U-Boot device tree won’t be passed to the Linux Kernel

Hi @andi.tx
I modified both DTS: u-boot and linux. Modified dts below. I don’t need FEC working in U-Boot.
linux_imx8mp-verdin-wifi-dev.dts (467 Bytes)
linux_imx8mp-verdin.dtsi (39.1 KB)
uboot_imx8mp-verdin.dts (16.5 KB)

If is mismatch in pins configuration in DTS, kernel prints this messages:
root@verdin-imx8mp-07106920:~# dmesg | grep -i fec
[ 1.512441] imx8mp-pinctrl 30330000.pinctrl: could not request pin 76 (MX8MP_IOMUXC_SAI5_RXC) from group fecgrp on device 30330000.pinctrl
[ 1.531074] fec 30be0000.ethernet: Error applying setting, reverse things back
[ 1.538322] fec: probe of 30be0000.ethernet failed with error -22

If pins are configured correctly, no message from kernel about FEC or ETH
root@verdin-imx8mp-07106920:~# dmesg | grep -i fec

root@verdin-imx8mp-07106920:~# dmesg | grep -i eth

(first ethernet is disabled for testing purpose in DTS)

hi @msv_zitnik ,

in that case, I won’t touch uboot device tree and I wouldn’t modify imx8mp-verdin.dtsi as well. Keep thing simple and modify only in one place e.g. in your linux_imx8mp-verdin-wifi-dev.dts. Did you try my suggestion in the other post? It compiled fine and it shows in dmesg for me (I use Verdin iMX8M Plus + Yavia board)

torizon@verdin-imx8mp-15139719:~$ dmesg | grep -i fec
[    1.097467] fec 30be0000.ethernet eth0: registered PHC device 0
[    5.990845] fec 30be0000.ethernet ethernet1: renamed from eth0
[    7.477089] fec 30be0000.ethernet ethernet1: Link is Up - 100Mbps/Full - flow control off

Keep the structure as I suggested in that post: create your own .dts and do modification only there. Also, you are using the device tree for U-Boot. I am not that familiar with the format, but it is different fom the one that is used by Linux. Maybe it works, but just to be on the safe side, use the one for Linux here: freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis, Colibri and Verdin modules.

Again, I am not so familiar with this switch. I recommend contacting Microchip to have your design reviewed MicroCHECK Design Review Service | Microchip Technology.

Hi @andi.tx ,
Now, when I adapted your DTS, have FEC partially working:

root@verdin-imx8mp-07106920:~# dmesg | grep -i fec
[    0.828682] fec 30be0000.ethernet eth0: registered PHC device 0
[    4.739103] fec 30be0000.ethernet eth0: Link is Up - 100Mbps/Full - flow control off

But, I have no clock signal (50Mhz) on ENET1_TX_CLK (SODIMM 38). In our board design it would be better to provide 50Mhz from IMX8MP to PHY.

What setting in DTS provides this clock?

Thank you.

hi @msv_zitnik ,

I think if you include MX8MP_IOMUXC_SAI1_MCLK__ENET1_TX_CLK in pinctrl_fec node and pinctrl_fec_sleep, maybe it will work already. Set the IOMUXC_SW_PAD_CTL_PAD_SAI1_MCLK register value according to the reference manual.

If it still doesn’t work, you can try to add this to your fec node:
assigned-clock-rates = <0>, <100000000>, <125000000>, <50000000>;

Also, remember to disable any node that is using SODIMM 38 pin (e.g. sai1 node if it is enabled somewhere).

Can you share the full modified .dts you have?

Hi @andi.tx,

Thank you for advice, we’ve moved a little step forward! Now, we have the clock working.

However with your setting:

assigned-clock-rates = <0>, <100000000>, <125000000>, <50000000>;

the clock was 41.66 Mhz, so I modified clock rates and clock parents (and don’t know if correctly) to:

assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_266M>,
                               <&clk IMX8MP_SYS_PLL2_100M>,
                               <&clk IMX8MP_SYS_PLL2_100M>;
assigned-clock-rates = <0>, <100000000>, <50000000>, <50000000>;

Now we have 50 MHz ref. clock supplied from Verdin finally working! However we still have the problem with TX0, TX1 and TXEN signals from Verdin. For reference you can look to my second post: Verdin IMX8MP and KSZ8873 - #6 by msv_hofmann (the waweforms are quite similar now).

  • REF: now provided from Verdin, OK
  • CRS, RX0, RX1: signals from PHY (KSZ8873) seems working when trying ping from external device connected to PORT1, probably OK
  • TXEN, TX0: the signals looks like high-Z in Verdin (The ref CLK is coupled to these floating signals so the logic analyzer interprets them as roughly 50 MHz. There’s no “hard” signal there in reality /it’s checked by osciloscope/!)
  • TX1: looks like set to LOW in Verdin (the signal stays LOW even when we try ping intitiated from Verdin)

For port names reference:

Can You, please, help with enabling signals TXEN, TX0 and TX1 in Verdin? We are almost there, I suppose! :slight_smile:

Our current DTS:
imx8mp-verdin-wifi-dev.dts (4.1 KB)

hi @msv_zitnik ,

after digging a bit I found a really nice application note from NXP about ethernet controller and I recommend to read it up! I think you will get much better understanding about what is happening under the hood. There is also a patch suggested for RMII mode to work properly by configuring IOMUXC_GPR_GPR1 register properly. You can download it from NXP website AN14149 - Ethernet Controller Configuration on i.MX 8MP and i.MX 93 Processors

Here is a good depiction of the clock coming from the on-chip generator which is loopback to EQOS controller (the first ethernet. It looks similar for the FEC controller in our case):

The SYSTEM_PLL2_DIV20 clock source is equivalent with IMX8MP_SYS_PLL2_50M in the device tree to generate 50MHz clock to the pad/pin for the switch and the FEC controller as well and therefore, the SION bit should be put to 1. This is what we do with the value 0x40000000 offset by 16 in this line in the pinctrl_fec node in the device tree:

The device tree adjustment needed should look like this:

/* Verdin ETH_2_RGMII */
&fec {
	#address-cells = <1>;
	#size-cells = <0>;
	phy-mode = "rmii";
	/delete-property/ phy-supply; //no need; supplied directly from SOM supply
	/delete-property/ phy-handle; //Otherwise, the kernel will log shows an error message about not being able to connect to the PHY

	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_fec>;
	/* adjusted the clock according to the app note*/
	assigned-clocks =   <&clk IMX8MP_CLK_ENET_AXI>,
						<&clk IMX8MP_CLK_ENET_TIMER>,
						<&clk IMX8MP_CLK_ENET_REF>,
						<&clk IMX8MP_CLK_ENET_PHY_REF>;
	assigned-clock-parents =    <&clk IMX8MP_SYS_PLL1_266M>,
								<&clk IMX8MP_SYS_PLL2_100M>,
								<&clk IMX8MP_SYS_PLL2_50M>;
	assigned-clock-rates = <0>, <100000000>, <50000000>;

	fixed-link {
			speed = <100>;

	/* I took this device tree as example:
	This is also a relevant binding:,ksz.yaml?h=toradex_5.15-2.2.x-imx
	mdio {
		#address-cells = <1>;
		#size-cells = <0>;

		ksz8873@0 {
			compatible = "microchip,ksz8873";
			reg = <0>;

			/* optional: you can define interrupt signal that can be used by the switch - Pin 41 INTRN on KSZ8873RLL */
			interrupt-parent = <&gpio3>; //are you sure this is the right interrupt line?
			interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
			/* added these properties below according to the app note */       
			#interrupt-cells = <2>;

			/* optional: you can define reset signal that can be used for the switch - Pin 62 RSTN on KSZ8873RLL
			Alternatively, you can use CTRL_RESET_MOCI# on SODIMM 258 as we do it on for our KSZ9131
			refer to page 24 to know more about power management feature of our module */
			reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; // I didn't touch this line - make sure you put the right reset line if you need it!

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

				ports@0 {
					reg = <0>;
					phy-mode = "internal";
					label = "lan1";

				ports@1 {
					reg = <1>;
					phy-mode = "internal";
					label = "lan2";

				ports@2 {
					reg = <2>;
					label = "cpu";
					ethernet = <&fec>;
					phy-mode = "rmii";

					fixed-link {
						speed = <100>;

	/* Connection Carrier Board PHY ETH_2 - I matched the IOMUXC_SW_MUX_CTL_PAD_SAI1_MCLK register value to the ones from application note. If you modified them for your design, feel free to keep them */
	pinctrl_fec: fecgrp {
		fsl,pins = <
			/* I didn't touch the registers given by you below*/
			MX8MP_IOMUXC_SAI1_TXD6__ENET1_RX_ER		    0x00000090 /* ETH_AUX_RXER */
			MX8MP_IOMUXC_HDMI_DDC_SDA__GPIO3_IO27		0x00000046 /* !ETH_AUX_INT */
			MX8MP_IOMUXC_SAI5_RXC__GPIO3_IO20   		0x00000006 /* !ETH_AUX_PHY_RESET */

For the completeness’ sake, this is the patch needed for RMII mode according to the app note:

+		struct regmap *gpr;
		fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
		/* Init network device */
@@ -4303,7 +4311,14 @@ fec_probe(struct platform_device *pdev)
				goto failed_clk;
		fep->clk_ref_rate = clk_get_rate(fep->clk_ref);
+		if((fep->clk_enet_out != NULL)&&(fep->clk_ref != NULL)) {
+				gpr = syscon_regmap_lookup_by_compatible("fsl,imx8mp-iomuxcgpr");
+				if (IS_ERR(gpr)) {
+						dev_err(&pdev->dev, "cannot find iomuxc registers\n");
+						return PTR_ERR(gpr);
+ 				}
+				regmap_update_bits(gpr, 0x4/*IOMUXC_GPR1*/, 0x2000, 0x2000/*bit
+		}

Let us know if these work and maybe also what you did to help others here :slight_smile:

hi @msv_zitnik,

it’s been a while. Did you manage to get the Ethernet working as intended?

Hi @andi.tx,

We were supposed to work on different projects, and originally, we aimed to provide a fully working and tested solution here. However, we are still encountering issues with the KSZ. As you mentioned, it’s been a while, so I will assess our current progress.

Firstly, I would like to extend thanks from @msv_zitnik for the datasheet you provided:
AN14149 - Ethernet Controller Configuration on i.MX 8MP and i.MX 93 Processors
It has been incredibly helpful! (The RMII mode patch was also beneficial.)

Regarding our issue with high-Z on TXEN and TX0 signals, it was my fault. I likely damaged the series resistors on the signals while installing logic analyzer probes or during subsequent handling of the board on the workbench. After editing the DTS and repairing the series resistors, the RMII Ethernet connection finally started working!

Our current DTS: imx8mp-verdin-msv-mcr.dts (3.6 KB)

Updated schematic (with Verdin supplying 50 MHz ref. CLK):

However, there are still a few problems we need to address:

  1. We had to remove PHY reset from DTS:
    /* reset-gpios = <&gpio3 20 GPIO_ACTIVE_LOW>; */
    The Verdin releases the PHY reset right after boot and starts supplying the reference CLK after a while. According to the KSZ datasheet, the reset should be released after the CLK is running and stable. Currently, we control the PHY reset manually as GPIO. We plan to automate this process in the future.
  2. We tested packet loss due to @KDehren’s notice about KSZ8873 Errata. The packet loss is 0%, but we only tested it on one device and on the workbench. We still need to test it across the entire working temperature range. Additionally, the data on RXD0 and RXD1 changes on the rising edge of the reference CLK. This seems incorrect, so I anticipate a potential issue in the future. We plan to revert back to the KSZ supplying the reference CLK and compare the situation with our current working solution (Verdin supplying the reference CLK).

I think that reversing the ref. CLK in Verdin is something we should be able to handle ourselves with the help of the AN14149 you provided. If we encounter any issues, I’ll let you know. Either way, we’ll be happy to share the results with you.