Adding OpenWrt support for Zyxel EX5601-T0

Try removing the reset stuff from MDIO and PHY completely, just to try and see if the PHY is then detected properly (this is what we have to achieve: the MaxLinear PHY showing up as being detected).

I tried with this.

&eth {
	status = "okay";

	gmac0: mac@0 {
		compatible = "mediatek,eth-mac";
		reg = <0>;
		phy-mode = "2500base-x";

		fixed-link {
			speed = <2500>;
			full-duplex;
			pause;
		};
	};

	gmac1: mac@1 {
		compatible = "mediatek,eth-mac";
		reg = <1>;
		phy-mode = "2500base-x";
		phy = <&phy6>;
	};

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

		phy5: phy@5 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <5>;
			phy-mode = "2500base-x";
			maxlinear,led-reg = <1008 0 0 0>; /* enable led0 for all link/act, and disable led1~3 */
		};

		phy6: phy@6 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <6>;
			phy-mode = "2500base-x";
			maxlinear,led-reg = <240 0 0 0>; /* enable led0 and no pulsing with TX, RX, and disable led1~3 */
			ifname = "eth1";
		};

		switch@0 {
			compatible = "mediatek,mt7531";
			reg = <31>;
			reset-gpios = <&pio 5 0>;

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

				port@1 {
					reg = <1>;
					label = "lan1";
				};

				port@2 {
					reg = <2>;
					label = "lan2";
				};

				port@3 {
					reg = <3>;
					label = "lan3";
				};

				port@5 {
					reg = <5>;
					label = "lan5";
					phy-mode = "2500base-x";
					phy = <&phy5>;
				};

				port@6 {
					reg = <6>;
					label = "cpu";
					ethernet = <&gmac0>;
					phy-mode = "2500base-x";

					fixed-link {
						speed = <2500>;
						full-duplex;
						pause;
					};
				};
			};
		};
	};
};

bootlog:

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 5.15.107 (piameruo@compiler) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 12.2.0 r22419-42a5917786) 12.2.0, GNU ld (GNU Binutils) 2.40.0) #0 SMP Tue Apr 18 23:02:26 2023
[    0.000000] Machine model: Zyxel EX5601-T0
[    0.000000] Zone ranges:
[    0.000000]   DMA      [mem 0x0000000040000000-0x000000007fffffff]
[    0.000000]   DMA32    empty
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000040000000-0x0000000042ffffff]
[    0.000000]   node   0: [mem 0x0000000043000000-0x000000004302ffff]
[    0.000000]   node   0: [mem 0x0000000043030000-0x000000004fbfffff]
[    0.000000]   node   0: [mem 0x000000004fc00000-0x000000004ffbffff]
[    0.000000]   node   0: [mem 0x000000004ffc0000-0x000000007fffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000040000000-0x000000007fffffff]
[    0.000000] psci: probing for conduit method from DT.
[    0.000000] psci: PSCIv1.1 detected in firmware.
[    0.000000] psci: Using standard PSCI v0.2 function IDs
[    0.000000] psci: MIGRATE_INFO_TYPE not supported.
[    0.000000] psci: SMC Calling Convention v1.2
[    0.000000] percpu: Embedded 17 pages/cpu s29656 r8192 d31784 u69632
[    0.000000] pcpu-alloc: s29656 r8192 d31784 u69632 alloc=17*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3
[    0.000000] Detected VIPT I-cache on CPU0
[    0.000000] CPU features: detected: GIC system register CPU interface
[    0.000000] CPU features: kernel page table isolation disabled by kernel configuration
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 258048
[    0.000000] Kernel command line:
[    0.000000] Dentry cache hash table entries: 131072 (order: 8, 1048576 bytes, linear)
[    0.000000] Inode-cache hash table entries: 65536 (order: 7, 524288 bytes, linear)
[    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.000000] Memory: 981900K/1048576K available (8512K kernel code, 896K rwdata, 2252K rodata, 30080K init, 297K bss, 66676K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
[    0.000000] rcu: Hierarchical RCU implementation.
[    0.000000]  Tracing variant of Tasks RCU enabled.
[    0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
[    0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.000000] GICv3: GIC: Using split EOI/Deactivate mode
[    0.000000] GICv3: 640 SPIs implemented
[    0.000000] GICv3: 0 Extended SPIs implemented
[    0.000000] GICv3: Distributor has no Range Selector support
[    0.000000] Root IRQ handler: gic_handle_irq
[    0.000000] GICv3: 16 PPIs implemented
[    0.000000] GICv3: CPU0: found redistributor 0 region 0:0x000000000c080000
[    0.000000] arch_timer: cp15 timer(s) running at 13.00MHz (phys).
[    0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x2ff89eacb, max_idle_ns: 440795202429 ns
[    0.000000] sched_clock: 56 bits at 13MHz, resolution 76ns, wraps every 4398046511101ns
[    0.000138] Calibrating delay loop (skipped), value calculated using timer frequency.. 26.00 BogoMIPS (lpj=130000)
[    0.000146] pid_max: default: 32768 minimum: 301
[    0.000230] Mount-cache hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.000239] Mountpoint-cache hash table entries: 2048 (order: 2, 16384 bytes, linear)
[    0.001133] rcu: Hierarchical SRCU implementation.
[    0.001216] dyndbg: Ignore empty _ddebug table in a CONFIG_DYNAMIC_DEBUG_CORE build
[    0.001418] smp: Bringing up secondary CPUs ...
[    0.001656] Detected VIPT I-cache on CPU1
[    0.001680] GICv3: CPU1: found redistributor 1 region 0:0x000000000c0a0000
[    0.001708] CPU1: Booted secondary processor 0x0000000001 [0x410fd034]
[    0.001973] Detected VIPT I-cache on CPU2
[    0.001985] GICv3: CPU2: found redistributor 2 region 0:0x000000000c0c0000
[    0.001996] CPU2: Booted secondary processor 0x0000000002 [0x410fd034]
[    0.002219] Detected VIPT I-cache on CPU3
[    0.002228] GICv3: CPU3: found redistributor 3 region 0:0x000000000c0e0000
[    0.002238] CPU3: Booted secondary processor 0x0000000003 [0x410fd034]
[    0.002263] smp: Brought up 1 node, 4 CPUs
[    0.002276] SMP: Total of 4 processors activated.
[    0.002279] CPU features: detected: 32-bit EL0 Support
[    0.002283] CPU features: detected: CRC32 instructions
[    0.002357] CPU: All CPU(s) started at EL2
[    0.002368] alternatives: patching kernel code
[    0.004569] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.004591] futex hash table entries: 1024 (order: 4, 65536 bytes, linear)
[    0.004705] pinctrl core: initialized pinctrl subsystem
[    0.005152] NET: Registered PF_NETLINK/PF_ROUTE protocol family
[    0.005352] DMA: preallocated 128 KiB GFP_KERNEL pool for atomic allocations
[    0.005373] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
[    0.005391] DMA: preallocated 128 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.005618] thermal_sys: Registered thermal governor 'fair_share'
[    0.005621] thermal_sys: Registered thermal governor 'bang_bang'
[    0.005624] thermal_sys: Registered thermal governor 'step_wise'
[    0.005628] thermal_sys: Registered thermal governor 'user_space'
[    0.005798] ASID allocator initialised with 65536 entries
[    0.006048] pstore: Registered ramoops as persistent store backend
[    0.006052] ramoops: using 0x10000@0x42ff0000, ecc: 0
[    0.014212] cryptd: max_cpu_qlen set to 1000
[    0.015974] SCSI subsystem initialized
[    0.016049] libata version 3.00 loaded.
[    0.016397] Advanced Linux Sound Architecture Driver Initialized.
[    0.016819] clocksource: Switched to clocksource arch_sys_counter
[    0.017239] NET: Registered PF_INET protocol family
[    0.017322] IP idents hash table entries: 16384 (order: 5, 131072 bytes, linear)
[    0.017728] tcp_listen_portaddr_hash hash table entries: 512 (order: 1, 8192 bytes, linear)
[    0.017744] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
[    0.017751] TCP established hash table entries: 8192 (order: 4, 65536 bytes, linear)
[    0.017788] TCP bind hash table entries: 8192 (order: 5, 131072 bytes, linear)
[    0.017869] TCP: Hash tables configured (established 8192 bind 8192)
[    0.017937] UDP hash table entries: 512 (order: 2, 16384 bytes, linear)
[    0.017954] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes, linear)
[    0.018040] NET: Registered PF_UNIX/PF_LOCAL protocol family
[    0.018059] PCI: CLS 0 bytes, default 64
[    0.038812] workingset: timestamp_bits=46 max_order=18 bucket_order=0
[    0.041058] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.041081] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc.
[    0.064680] mtk-pcie-gen3 11280000.pcie: host bridge /soc/pcie@11280000 ranges:
[    0.064709] mtk-pcie-gen3 11280000.pcie: Parsing ranges property...
[    0.064719] mtk-pcie-gen3 11280000.pcie:      MEM 0x0020000000..0x002fffffff -> 0x0020000000
[    0.064773] phy phy-soc:t-phy@11c00000.0: u3 auto load valid efuse: ENABLE with value: 1
[    0.064805] phy phy-soc:t-phy@11c00000.0: pcie auto load valid efuse: ENABLE with value: 1
[    0.064829] phy phy-soc:t-phy@11c00000.0: u3 lane1 efuse - intr 28, rx_imp f, tx_imp e
[    0.064887] /soc/pcie@11280000: Failed to get clk index: 0 ret: -517
[    0.064897] mtk-pcie-gen3 11280000.pcie: failed to get clocks
[    0.067283] Serial: 8250/16550 driver, 3 ports, IRQ sharing disabled
[    0.067828] printk: console [ttyS0] disabled
[    0.088019] 11002000.serial: ttyS0 at MMIO 0x11002000 (irq = 121, base_baud = 2500000) is a ST16650V2
[    0.782356] printk: console [ttyS0] enabled
[    0.807143] 11003000.serial: ttyS1 at MMIO 0x11003000 (irq = 122, base_baud = 1625000) is a ST16650V2
[    0.836855] 11004000.serial: ttyS2 at MMIO 0x11004000 (irq = 123, base_baud = 1625000) is a ST16650V2
[    0.846628] mtk_rng 1020f000.trng: registered RNG driver
[    0.846687] hwrng: no data available
[    0.852181] cacheinfo: Unable to detect cache hierarchy for CPU 0
[    0.863416] loop: module loaded
[    0.867796] spi-nand spi0.1: Micron SPI NAND was found.
[    0.873015] spi-nand spi0.1: 512 MiB, block size: 256 KiB, page size: 4096, OOB size: 256
[    0.885625] 5 fixed-partitions partitions found on MTD device spi0.1
[    0.891995] Creating 5 MTD partitions on "spi0.1":
[    0.896770] 0x000000000000-0x000000100000 : "BL2"
[    0.903020] 0x000000100000-0x000000180000 : "u-boot-env"
[    0.909163] 0x000000180000-0x000000380000 : "Factory"
[    0.916737] 0x000000380000-0x000000580000 : "FIP"
[    0.924048] 0x000000580000-0x000004580000 : "ubi"
[    1.146214] mtk_soc_eth 15100000.ethernet: generated random MAC address da:14:44:32:2e:fd
[    1.154969] mtk_soc_eth 15100000.ethernet eth0: mediatek frame engine at 0xffffffc00b380000, irq 133
[    1.164152] mtk_soc_eth 15100000.ethernet: generated random MAC address 32:bf:46:ef:f6:52
[    1.172920] mtk_soc_eth 15100000.ethernet eth1: mediatek frame engine at 0xffffffc00b380000, irq 133
[    1.182436] i2c_dev: i2c /dev entries driver
[    1.187661] mtk-wdt 1001c000.watchdog: Watchdog enabled (timeout=31 sec, nowayout=0)
[    1.196247] NET: Registered PF_INET6 protocol family
[    1.201833] Segment Routing with IPv6
[    1.205504] In-situ OAM (IOAM) with IPv6
[    1.209452] NET: Registered PF_PACKET protocol family
[    1.223290] NET: Registered PF_RXRPC protocol family
[    1.228289] Key type rxrpc registered
[    1.231935] Key type rxrpc_s registered
[    1.235771] 8021q: 802.1Q VLAN Support v1.8
[    1.240826] pstore: Using crash dump compression: deflate
[    1.251069] mtk-pcie-gen3 11280000.pcie: host bridge /soc/pcie@11280000 ranges:
[    1.258405] mtk-pcie-gen3 11280000.pcie: Parsing ranges property...
[    1.264655] mtk-pcie-gen3 11280000.pcie:      MEM 0x0020000000..0x002fffffff -> 0x0020000000
[    1.273134] phy phy-soc:t-phy@11c00000.0: u3 auto load valid efuse: ENABLE with value: 1
[    1.281234] phy phy-soc:t-phy@11c00000.0: pcie auto load valid efuse: ENABLE with value: 1
[    1.289498] phy phy-soc:t-phy@11c00000.0: u3 lane1 efuse - intr 28, rx_imp f, tx_imp e
[    1.516829] mtk-pcie-gen3 11280000.pcie: PCIe link down, ltssm reg val: 0x1000001
[    1.524314] mtk-pcie-gen3: probe of 11280000.pcie failed with error -110
[    1.568417] mt7530 mdio-bus:1f: no interrupt support
[    1.595509] mt7530 mdio-bus:1f: configuring for fixed/2500base-x link mode
[    1.604634] mt7530 mdio-bus:1f: Link is Up - 2.5Gbps/Full - flow control rx/tx
[    1.613832] mt7530 mdio-bus:1f lan1 (uninitialized): PHY [mt7530-0:01] driver [MediaTek MT7531 PHY] (irq=POLL)
[    1.633643] mt7530 mdio-bus:1f lan2 (uninitialized): PHY [mt7530-0:02] driver [MediaTek MT7531 PHY] (irq=POLL)
[    1.653205] mt7530 mdio-bus:1f lan3 (uninitialized): PHY [mt7530-0:03] driver [MediaTek MT7531 PHY] (irq=POLL)
[    1.664210] mt7530 mdio-bus:1f lan5 (uninitialized): validation of  with support 0000000,00000000,00006000 and advertisement 0000000,00000000,00000000 failed: -22
[    1.678738] mt7530 mdio-bus:1f lan5 (uninitialized): failed to connect to PHY: -EINVAL
[    1.686636] mt7530 mdio-bus:1f lan5 (uninitialized): error -22 setting up PHY for tree 0, switch 0, port 5
[    1.696312] DSA: tree 0 setup
[    1.703174] UBI: auto-attach mtd4
[    1.706483] ubi0: default fastmap pool size: 10
[    1.711011] ubi0: default fastmap WL pool size: 5
[    1.715697] ubi0: attaching mtd4
[    3.548760] ubi0: scanning is finished
[    3.595557] ubi0 warning: ubi_eba_init: cannot reserve enough PEBs for bad PEB handling, reserved 36, need 40
[    3.605810] ubi0: attached mtd4 (name "ubi", size 64 MiB)
[    3.611206] ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
[    3.618062] ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
[    3.624829] ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
[    3.631771] ubi0: good PEBs: 256, bad PEBs: 0, corrupted PEBs: 0
[    3.637761] ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
[    3.644960] ubi0: max/mean erase counter: 50/13, WL threshold: 4096, image sequence number: 1658393161
[    3.654243] ubi0: available PEBs: 0, total reserved PEBs: 256, PEBs reserved for bad PEB handling: 36
[    3.663447] ubi0: background thread "ubi_bgt0d" started, PID 456
[    3.671178] block ubiblock0_1: created from ubi0:1(rootfs)
[    3.676653] ubiblock: device ubiblock0_1 (rootfs) set to be root filesystem
[    3.684020] ALSA device list:
[    3.686980]   No soundcards found.
[    3.700447] Freeing unused kernel memory: 30080K
[    3.736868] Run /init as init process
[    3.740515]   with arguments:
[    3.743465]     /init
[    3.745722]   with environment:
[    3.748857]     HOME=/
[    3.751201]     TERM=linux
[    3.910727] init: Console is alive
[    3.914210] init: - watchdog -
[    3.921501] kmodloader: loading kernel modules from /etc/modules-boot.d/*
[    3.931737] usbcore: registered new interface driver usbfs
[    3.937268] usbcore: registered new interface driver hub
[    3.942595] usbcore: registered new device driver usb
[    3.951287] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    3.958318] fsl-ehci: Freescale EHCI Host controller driver
[    3.964333] ehci-platform: EHCI generic platform driver
[    3.970798] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[    3.977385] ohci-platform: OHCI generic platform driver
[    3.985204] phy phy-soc:t-phy@11e10000.1: u2 auto load valid efuse: ENABLE with value: 1
[    3.993363] phy phy-soc:t-phy@11e10000.2: u3 auto load valid efuse: ENABLE with value: 1
[    4.001497] phy phy-soc:t-phy@11e10000.3: u2 auto load valid efuse: ENABLE with value: 1
[    4.010043] xhci-mtk 11200000.usb: xHCI Host Controller
[    4.015260] xhci-mtk 11200000.usb: new USB bus registered, assigned bus number 1
[    4.025715] xhci-mtk 11200000.usb: hcc params 0x01403f99 hci version 0x110 quirks 0x0000000000210010
[    4.034949] xhci-mtk 11200000.usb: irq 126, io mem 0x11200000
[    4.040786] xhci-mtk 11200000.usb: xHCI Host Controller
[    4.046000] xhci-mtk 11200000.usb: new USB bus registered, assigned bus number 2
[    4.053387] xhci-mtk 11200000.usb: Host supports USB 3.2 Enhanced SuperSpeed
[    4.060780] hub 1-0:1.0: USB hub found
[    4.064539] hub 1-0:1.0: 2 ports detected
[    4.068838] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
[    4.077145] hub 2-0:1.0: USB hub found
[    4.080893] hub 2-0:1.0: 1 port detected
[    4.087930] usbcore: registered new interface driver usb-storage
[    4.094113] kmodloader: done loading kernel modules from /etc/modules-boot.d/*
[    4.109203] init: - preinit -
[    4.149234] mtk_soc_eth 15100000.ethernet eth0: configuring for fixed/2500base-x link mode
[    4.157675] mtk_soc_eth 15100000.ethernet eth0: Link is Up - 2.5Gbps/Full - flow control rx/tx
[    4.165970] mt7530 mdio-bus:1f lan1: configuring for phy/gmii link mode
Press the [f] key and hit [enter] to enter failsafe mode
Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level
[    5.210087] mt7530 mdio-bus:1f lan1: Link is Up - 1Gbps/Full - flow control rx/tx
[    5.217596] IPv6: ADDRCONF(NETDEV_CHANGE): lan1: link becomes ready
[   11.367076] random: crng init done
[   14.238739] mt7530 mdio-bus:1f lan1: Link is Down
[   14.246022] procd: - early -
[   14.248974] procd: - watchdog -
[   14.762321] procd: - watchdog -
[   14.765593] procd: - ubus -
[   14.818634] procd: - init -
Please press Enter to activate this console.
[   14.890321] urngd: v1.0.2 started.
[   14.906612] kmodloader: loading kernel modules from /etc/modules.d/*
[   14.916224] NET: Registered PF_ATMPVC protocol family
[   14.921408] NET: Registered PF_ATMSVC protocol family
[   14.928160] ntfs: driver 2.1.32 [Flags: R/O MODULE].
[   14.938780] crypto-safexcel 10320000.crypto: EIP97:230(0,1,4,4)-HIA:270(0,5,5),PE:150/433(alg:7fcdfc00)/0/0/0
[   14.953333] usbcore: registered new interface driver cdc_acm
[   14.959165] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[   14.967955] usbcore: registered new interface driver cdc_wdm
[   14.973866] Loading modules backported from Linux version v6.1.24-0-g0102425ac76b
[   14.981340] Backport generated by backports.git v5.15.92-1-44-gd6ea70fafd36
[   14.989139] hso: drivers/net/usb/hso.c: Option Wireless
[   14.994419] usbcore: registered new interface driver hso
[   15.004408] usbcore: registered new interface driver usblp
[   15.011948] usbcore: registered new interface driver usbserial_generic
[   15.018509] usbserial: USB Serial support registered for generic
[   15.025049] usbcore: registered new interface driver cdc_ether
[   15.031864] usbcore: registered new interface driver cdc_ncm
[   15.390164] mt7986-wmac 18000000.wmac: HW/SW Version: 0x8a108a10, Build Time: 20221012174648a
[   15.390164]
[   15.408441] mt7986-wmac 18000000.wmac: WM Firmware Version: ____000000, Build Time: 20221012174725
[   15.447671] mt7986-wmac 18000000.wmac: WA Firmware Version: DEV_000000, Build Time: 20221012174937
[   19.378364] PPP generic driver version 2.4.2
[   19.383266] NET: Registered PF_PPPOX protocol family
[   19.389148] usbcore: registered new interface driver qmi_wwan
[   19.395631] usbcore: registered new interface driver rndis_host
[   19.404086] usbcore: registered new interface driver option
[   19.409716] usbserial: USB Serial support registered for GSM modem (1-port)
[   19.418204] kmodloader: done loading kernel modules from /etc/modules.d/*
[   22.185607] mtk_soc_eth 15100000.ethernet eth0: Link is Down
[   22.198403] mtk_soc_eth 15100000.ethernet eth0: configuring for fixed/2500base-x link mode
[   22.206879] mtk_soc_eth 15100000.ethernet eth0: Link is Up - 2.5Gbps/Full - flow control rx/tx
[   22.207054] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
[   22.222617] mt7530 mdio-bus:1f lan1: configuring for phy/gmii link mode
[   22.236330] br-lan: port 1(lan1) entered blocking state
[   22.241632] br-lan: port 1(lan1) entered disabled state
[   22.248527] device lan1 entered promiscuous mode
[   22.253144] device eth0 entered promiscuous mode
[   22.268361] mt7530 mdio-bus:1f lan2: configuring for phy/gmii link mode
[   22.278332] br-lan: port 2(lan2) entered blocking state
[   22.283557] br-lan: port 2(lan2) entered disabled state
[   22.290916] device lan2 entered promiscuous mode
[   22.300738] mt7530 mdio-bus:1f lan3: configuring for phy/gmii link mode
[   22.310602] br-lan: port 3(lan3) entered blocking state
[   22.315836] br-lan: port 3(lan3) entered disabled state
[   22.322945] device lan3 entered promiscuous mode
[   25.371353] mt7530 mdio-bus:1f lan1: Link is Up - 1Gbps/Full - flow control rx/tx
[   25.378868] br-lan: port 1(lan1) entered blocking state
[   25.384079] br-lan: port 1(lan1) entered forwarding state
[   25.389926] IPv6: ADDRCONF(NETDEV_CHANGE): br-lan: link becomes ready

root@OpenWrt:/# ethtool eth1
Settings for eth1:
        Supported ports: [ TP    AUI     MII     FIBRE   BNC     Backplane ]
        Supported link modes:   2500baseX/Full
                                2500baseT/Full
        Supported pause frame use: Symmetric Receive-only
        Supports auto-negotiation: Yes
        Supported FEC modes: Not reported
        Advertised link modes:  Not reported
        Advertised pause frame use: No
        Advertised auto-negotiation: No
        Advertised FEC modes: Not reported
        Speed: Unknown!
        Duplex: Half
        Auto-negotiation: off
        Port: MII
        PHYAD: 0
        Transceiver: internal
        Current message level: 0x000000ff (255)
                               drv probe link timer ifdown ifup rx_err tx_err
        Link detected: no
root@OpenWrt:/# mdio mdio-bus mmd 5:1 raw 18
0x0000
root@OpenWrt:/# mdio mdio-bus mmd 6:1 raw 18
0x0000
root@OpenWrt:/# ^C

root@OpenWrt:/# ethtool lan5
netlink error: no device matches name (offset 24)
netlink error: No such device
netlink error: no device matches name (offset 24)
netlink error: No such device
netlink error: no device matches name (offset 24)
netlink error: No such device
netlink error: no device matches name (offset 24)
netlink error: No such device
netlink error: no device matches name (offset 24)
netlink error: No such device
No data available


root@OpenWrt:/#
root@OpenWrt:/# mdio mdio-bus mmd 6:1 raw 18
0x0000
root@OpenWrt:/# mdio mdio-bus mmd 5:1 raw 18
0x0000
root@OpenWrt:/#

So as you can see that assert - deassert timings are for phy5 ony I guess...

The result is that lan5 is not available at all in ifconfig or ethtool
eth1 (phy6) instead I can see it and if I put it into a bridge to fake-turnitup you read this:

root@OpenWrt:/# [  258.250440] mtk_soc_eth 15100000.ethernet eth1: validation of  with support 0000000,00000000,00006000 and advertisement 0000000,00000000,00000000 failed: -22
[  258.264588] mtk_soc_eth 15100000.ethernet eth1: mtk_open: could not attach PHY: -22
[  258.272429] br-lan: port 4(eth1) entered blocking state
[  258.277665] br-lan: port 4(eth1) entered disabled state
[  258.283027] device eth1 entered promiscuous mode

@daniel I don't know if you read the entire thread, just to recap the information of all the available ports:

3 gbit ports
1 lan 5 2.5 gbit port
1 wan 2.5 gbit port ethernet/sfp xor port

I think that the lan 2.5 gbit port is xor because form the picture i posted there are 2 sfp slots.

That's why I need to poke around with the regs at boot with mdio-tools.

Hi @daniel sorry but I m trying an impossibile number of combinations.

I noticed instead that from 5.4 to 5.15 mt7986a.dtsi the following has been dropped


		ethsysrst: reset-controller {
			compatible = "ti,syscon-reset";
			#reset-cells = <1>;
			ti,reset-bits = <0x34 4 0x34 4 0x34 4 (ASSERT_SET | DEASSERT_CLEAR | STATUS_SET)>;
		};

Can you help me understand if I can totally exclude this as a possible problem?

Pretty sure you need to run the reset stuff before the phys are probed, like

But I've mostly given up here. This thread is about re-inventing the wheel, in a square shape

I think I tried that

Ok so I have it working but now I've a question:

dts with no fixed link 2500 on lan4:

&eth {
	status = "okay";

	gmac0: mac@0 {
		compatible = "mediatek,eth-mac";
		reg = <0>;
		phy-mode = "2500base-x";

		fixed-link {
			speed = <2500>;
			full-duplex;
			pause;
		};
	};

	gmac1: mac@1 {
		compatible = "mediatek,eth-mac";
		reg = <1>;
		phy-mode = "2500base-x";
		phy = <&phy6>;
	};

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

		phy5: phy@5 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <5>;
			reset-gpios = <&pio 6 1>;
			reset-assert-us = <50000>;
			reset-deassert-us = <20000>;
			phy-mode = "2500base-x";
		};

		phy6: phy@6 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <6>;
			phy-mode = "2500base-x";
		};

		switch@0 {
			compatible = "mediatek,mt7531";
			reg = <31>;
			reset-gpios = <&pio 5 0>;

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

				port@1 {
					reg = <1>;
					label = "lan1";
				};

				port@2 {
					reg = <2>;
					label = "lan2";
				};

				port@3 {
					reg = <3>;
					label = "lan3";
				};

				port@5 {
					reg = <5>;
					label = "lan4";
					phy-mode = "2500base-x";
					phy = <&phy5>;
				};

				port@6 {
					reg = <6>;
					label = "cpu";
					ethernet = <&gmac0>;
					phy-mode = "2500base-x";

					fixed-link {
						speed = <2500>;
						full-duplex;
						pause;
					};
				};
			};
		};
	};
};
root@OpenWrt:/# ethtool lan4
Settings for lan4:
	Supported ports: [  ]
	Supported link modes:   10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
	                        1000baseT/Full
	                        2500baseT/Full
	Supported pause frame use: Symmetric Receive-only
	Supports auto-negotiation: No
	Supported FEC modes: Not reported
	Advertised link modes:  10baseT/Half 10baseT/Full
	                        100baseT/Half 100baseT/Full
	                        1000baseT/Full
	Advertised pause frame use: Symmetric Receive-only
	Advertised auto-negotiation: No
	Advertised FEC modes: Not reported
	Speed: Unknown!
	Duplex: Unknown! (255)
	Auto-negotiation: on
	Port: MII
	PHYAD: 5
	Transceiver: external
	Supports Wake-on: d
	Wake-on: d
	Link detected: no
root@OpenWrt:/# root@OpenWrt:/# mdio mdio-bus mmd 5:0 raw 0x0018
0x0003
root@OpenWrt:/# 

Bootlog shows Generic Clause 45 PHY

DTS with fixed link 2500

&eth {
	status = "okay";

	gmac0: mac@0 {
		compatible = "mediatek,eth-mac";
		reg = <0>;
		phy-mode = "2500base-x";

		fixed-link {
			speed = <2500>;
			full-duplex;
			pause;
		};
	};

	gmac1: mac@1 {
		compatible = "mediatek,eth-mac";
		reg = <1>;
		phy-mode = "2500base-x";
		phy = <&phy6>;
	};

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

		phy5: phy@5 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <5>;
			reset-gpios = <&pio 6 1>;
			reset-assert-us = <50000>;
			reset-deassert-us = <20000>;
			phy-mode = "2500base-x";
		};

		phy6: phy@6 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <6>;
			phy-mode = "2500base-x";
		};

		switch@0 {
			compatible = "mediatek,mt7531";
			reg = <31>;
			reset-gpios = <&pio 5 0>;

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

				port@1 {
					reg = <1>;
					label = "lan1";
				};

				port@2 {
					reg = <2>;
					label = "lan2";
				};

				port@3 {
					reg = <3>;
					label = "lan3";
				};

				port@5 {
					reg = <5>;
					label = "lan4";
					phy-mode = "2500base-x";
					phy = <&phy5>;
					fixed-link {
						speed = <2500>;
						full-duplex;
						pause;
					}
				};

				port@6 {
					reg = <6>;
					label = "cpu";
					ethernet = <&gmac0>;
					phy-mode = "2500base-x";

					fixed-link {
						speed = <2500>;
						full-duplex;
						pause;
					};
				};
			};
		};
	};
};
root@OpenWrt:/# ethtool lan4
Settings for lan4:
	Supported ports: [ MII ]
	Supported link modes:   2500baseT/Full
	Supported pause frame use: Symmetric Receive-only
	Supports auto-negotiation: Yes
	Supported FEC modes: Not reported
	Advertised link modes:  2500baseT/Full
	Advertised pause frame use: Symmetric Receive-only
	Advertised auto-negotiation: Yes
	Advertised FEC modes: Not reported
	Link partner advertised link modes:  2500baseT/Full
	Link partner advertised pause frame use: Symmetric
	Link partner advertised auto-negotiation: No
	Link partner advertised FEC modes: Not reported
	Speed: 2500Mb/s
	Duplex: Full
	Auto-negotiation: on
	Port: MII
	PHYAD: 0
	Transceiver: internal
	Supports Wake-on: d
	Wake-on: d
	Link detected: yes
root@OpenWrt:/# mdio mdio-bus mmd 5:0 raw 0x0018
0x0003

Bootlog with fixed_link:

In both the cases I can set the register with the correct mdio sintax:

mdio mdio-bus mmd 5:30 raw 0x0008 0xA4E2

the lan5 starts working

@daniel in your opinion what DTS config should I use? with or without the fixedlink stuff on port lan4?
Is it correct that with fixed link 2500 the right driver is loaded? Or why without fixed link the lan4 port is recognized as Generic clause 45?

Thank you

I know that using fixed link and rate adapter mode may work -- however, this is a waste of energy when operating the port in 10M/100M/1000M. We still need to find why the PHY doesn't detected as GPY211 during boot, which definitely has to do with the timing of the reset. Maybe try increasing the reset-deassert-us significantly and as the reset will be used for both PHYs, have it sit under the mdio-bus. Needing to use fixed-link or having it detected as Generic Clause-45 PHY means that something is still not right.

1 Like

ok thank you now one last thing while i go back to compiling.

Ps these are 10/100/1000/2500 ports

what's the correct sintax:

This coming from the original 5.4 zyxel DTS

reset-gpios = <&pio 6 1>;
reset-assert-us = <50000>;
reset-deassert-us = <20000>;

Or this suggested from bmork:

	reset-gpios = <&pio 6 GPIO_ACTIVE_LOW>;
	reset-delay-us = <50000>;
	reset-post-delay-us = <20000>;

Yes, and we want the GMAC<->PHY link to follow the link speed rather than the PHY doing rate-adaption to 2500Base-X no matter what the speed on the twisted-pair RJ-45 port is. For that the PHY driver needs to recognize the PHY and read back its status, and switch the mode of the MAC SerDes interface between Cisco SGMII for 10M/100M/1000M and 2500Base-X for 2500M speed.

Edit: The stock firmware may use rate-adapter mode (ie. always drive the MAC<->PHY link at 2500Base-X), which means more energy consumption due to the higher clock rate when using 10M/100M/1000M link speed, and also slightly worse performance in the <2500M speeds.

1 Like

This is as expected due to your misplacement of the reset. It runs while phy5 is being probed, which is too late. The result is that the phy is not ready and therefore not detected. Probing of the next phy works because they share reset and the delays configured ensures that phy6 becomes ready while phy5 is being probed.

Fixing this is as simple as moving the reset to the mdio bus where it will run before any of the phys are being probed.

Yes, this requires different attributes.

The vendor code never got this working properly and just hard coded the id's. That's plain stupid and not something to copy.

Like most of the vendor code, this part of the dts is obviously written without any understanding whatsoever of the hardware or software involved.

1 Like

@daniel @bmork thank you for your persistence, you know I'm a new learner here and I learnt the hard way thanks to your help.

&eth {
	status = "okay";

	gmac0: mac@0 {
		compatible = "mediatek,eth-mac";
		reg = <0>;
		phy-mode = "2500base-x";

		fixed-link {
			speed = <2500>;
			full-duplex;
			pause;
		};
	};

	gmac1: mac@1 {
		compatible = "mediatek,eth-mac";
		reg = <1>;
		phy-mode = "2500base-x";
		phy = <&phy6>;
	};

	mdio: mdio-bus {
		#address-cells = <1>;
		#size-cells = <0>;
		reset-gpios = <&pio 6 1>;
		reset-delay-us = <1500000>;
		reset-post-delay-us = <1000000>;

		phy5: phy@5 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <5>;
			phy-mode = "2500base-x";
		};

		phy6: phy@6 {
			compatible = "ethernet-phy-ieee802.3-c45";
			reg = <6>;
			phy-mode = "2500base-x";
		};

		switch@0 {
			compatible = "mediatek,mt7531";
			reg = <31>;
			reset-gpios = <&pio 5 0>;

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

				port@1 {
					reg = <1>;
					label = "lan1";
				};

				port@2 {
					reg = <2>;
					label = "lan2";
				};

				port@3 {
					reg = <3>;
					label = "lan3";
				};

				port@5 {
					reg = <5>;
					label = "lan4";
					phy-mode = "2500base-x";
					phy = <&phy5>;
				};

				port@6 {
					reg = <6>;
					label = "cpu";
					ethernet = <&gmac0>;
					phy-mode = "2500base-x";

					fixed-link {
						speed = <2500>;
						full-duplex;
						pause;
					};
				};
			};
		};
	};
};
[    4.709231] mt7530 mdio-bus:1f: no interrupt support
[    4.737644] mt7530 mdio-bus:1f: configuring for fixed/2500base-x link mode
[    4.746756] mt7530 mdio-bus:1f: Link is Up - 2.5Gbps/Full - flow control rx/tx
[    4.755952] mt7530 mdio-bus:1f lan1 (uninitialized): PHY [mt7530-0:01] driver [MediaTek MT7531 PHY] (irq=POLL)
[    4.775770] mt7530 mdio-bus:1f lan2 (uninitialized): PHY [mt7530-0:02] driver [MediaTek MT7531 PHY] (irq=POLL)
[    4.795316] mt7530 mdio-bus:1f lan3 (uninitialized): PHY [mt7530-0:03] driver [MediaTek MT7531 PHY] (irq=POLL)
[    4.806410] mt7530 mdio-bus:1f lan4 (uninitialized): PHY [mdio-bus:05] driver [Maxlinear Ethernet GPY211B] (irq=POLL)
root@OpenWrt:/# [   63.590589] mtk_soc_eth 15100000.ethernet eth1: PHY [mdio-bus:06] driver [Maxlinear Ethernet GPY211B] (irq=POLL)
[   63.600787] mtk_soc_eth 15100000.ethernet eth1: configuring for phy/2500base-x link mode
[   63.611112] br-lan: port 5(eth1) entered blocking state
[   63.616352] br-lan: port 5(eth1) entered disabled state
[   63.621710] device eth1 entered promiscuous mode

And the great thing is, no more mdio commands when starting up the router to fix the phys at 2500 (0xA4E2 this was setting the phy at fixed 2500 in the zyxel firmware)

1 Like

I'm here back again with a problem finalizing the flash process.

To recap I've a working 5.15 sysupgrade which unfortunately can't be directly flashed or booted because of the missing zyfwinfo metadata file.
I'm analyzing it and the zyfwinfo binary from the zyxel sources is calculating checksums of root and kernel and adding additional informations regarding builda date,time version and so on.

Here is what it looks like when you run it manually:

pietro@ubuntu:/srv/tftp$ ./zyfwinfo_sh
Usage:	./zyfwinfo_sh [-dtskrffehv] [--help] [--version]
	example:
	zyfwinfo -d 01/01/1970 -t 00:00:00 -f zyfwinfo.bin
	where:
	[-n] sequence number
	[-d] build date
	[-t] build time
	[-s] firmware version
	[-S] external firmware version
	[-k] kernel image name
	[-r] rootfs image name
	[-p] product name
	[-m] model id
	[-o] output image name
	[-e] target endianess
	[-h] help
	[-v] version

pietro@ubuntu:/srv/tftp$ ./zyfwinfo_sh -o out.bin
====Dump input====
seqNum=0
=====ZY_FW_INFO result was===
magic=0x5a595845
version=2
length=256
buildInfo=00 00 00 00 00 00 00 00 00 00 
productName=
Internal firmwareVersion=
External firmwareVersion=
kernelChecksum=0x0000
rootFSChecksum=0x0000
modelId=00 00 00 00 
zy_checksum=0x0153

There are some fixed parameters like magix (EXYZ), version (the version of the zyfwinfo binary?) and lenght (256, the fixed file size).

I was able to take a zyfwinfo file from another firmware and add it into the sysupgrade tar and flash it directly from the zyxel webgui. Which means that the real checks are related to the required informations
Magic, firmware version and root/kernel checksums. How the zy_checksum is really calculated I don't know...

Here is what in hex looks like a good zyfwinfo file:
image

This would never be accepted of course in plain openwrt because of zyxel stuff that needs to be added later after the compilation into sysupgrade hence i started looking into skipping zloader and changing the bootargs in MT7986> (u-boot)

No matter what the bootargs parameter i set are always inconditionally ignored

root@OpenWrt:~# fw_printenv
EngDebugFlag=1
FeatureBit=0
FeatureBits=040A0005ffffffff0000000000000000ffffffffffffffffffffffffa2f7
ProductName=EX5601-T0
VendorName=ZYXEL Communication Corp
baudrate=115200
bootdelay=3
countryCode=0
d2key=
ethact=ethernet@15100000
ethaddr=10:71:b3:75:64:10
fdtcontroladdr=7ffc5c80
initrd_end=0
initrd_start=0
ipaddr=192.168.1.1
mtdids=nmbm0=nmbm0
mtdparts=nmbm0:1024k(bl2),512k(u-boot-env),2048k(factory),1792k(fip),256k(zloader),65536k(ubi),65536k(ubi2),354816k(zyubi)
netmask=255.255.255.0
nummacaddrs=11
serverip=192.168.1.99
stderr=serial@11002000
stdin=serial@11002000
stdout=serial@11002000
zld_date=07/21/2022
zld_time=10:17:53
zld_ver=2.3
bootargs=console=ttyS0,115200n1 loglevel=8 earlycon=uart8250,mmio32,0x11002000 rootfstype=ubifs ubi.mtd=ubi ubi.mtd=ubi2 rw root=ubi:rootfs rw

Any hints?

Thank you

After analyzing the FIP partition I've found the following commands hardcoded

mtd read zloader 0x46000000
bootm

So the router boots BL2 which loads FIP (U-Boot) which loads zloader which is loading ubi or ubi2 with all the checks related to the zyfwinfo passing the cmdline to the kernel.

It seems like Zyxel hardcoded the zloader in the bootloader and disabled reading bootargs from u-boot-env.

I guess the only option here is reproducing the zyfwinfo file or replacing the bootloader

:frowning:

If both the OEM firmware updater and bootloader accepts a zyfwinfo file taken from another image, then there can't be any problem reimplementing a tool creating one? It means that none of the size/checksum fields are actually verified, with the fields protecting the zyfwinfo itself as the only possible exception. That should be fairly easy to figure out.

There are plenty of such tools already in the firmware-utils repo. I don't think any of them matches this 'EXYZ' magic, but several of them are very similar. Pretty sure they didn't do anything extra-ordinary here. It's probably just another variant of some well known firmware header.

As usual you are correct.

The minimum required informations are only:

magic = EXYZ
version = 2 in hex
lenght = 256 in hex
checksum is calculated and must be correct.

by opening the file with an hex editor:

45 58 59 5A is the magic ZYXE or EXYZ in little endian format
02 00 is the version 2 in hex little endian
00 00 is the seqNum (0) again in hex little endian
00 01 is the file lenght (256) in hex little endian.

All the other zeros i think are referring to the empty values.

At the end:
53 01 is 0x0153 (zy_checksum) which still I need to understand how that's calculated.

I tried manually creating a binary file with the same content in little endian format and it works so the zyxel binary is not needed.... still how the hell is the checksum calculated....

#ifndef ZYFWINFO
#define ZYFWINFO

#include <stdint.h>

#define ZYFWINFI_PRODUCTNAME_LEN           32
#define ZYFWINFI_BUILDINFO_LEN             10
#define ZYFWINFI_FIRMWAREVERSION_LEN       30
#define ZYFWINFI_MODELID_LEN               4

#define DEFAULT_ZLOADER_VER_MAJ  1
#define DEFAULT_ZLOADER_VER_MIN  0
#define DEFAULT_ZLOADER_VER_ECO  0

#define ZYXEL_MAGIC	0x5a595845	// 'Z', 'Y', 'X', 'E'
#define ZYFWINFI_VERSION 2

#define ZYFWINFI_MAX_SEQNUM 9999
#define ZYFWINFI_MIN_SEQNUM 0

typedef struct
{
	uint32_t magic;
	uint16_t version;
	uint16_t seq_num; // sequence number, should be 0 ~ 9999
	uint16_t length;
	char buildInfo[ZYFWINFI_BUILDINFO_LEN];
	char productName[ZYFWINFI_PRODUCTNAME_LEN];
	char firmwareVersion[ZYFWINFI_FIRMWAREVERSION_LEN];
	char firmwareVersionEx[ZYFWINFI_FIRMWAREVERSION_LEN];
	uint16_t kernelChecksum;
	uint16_t rootFSChecksum;
	char modelId[ZYFWINFI_MODELID_LEN];
	char chUnused[134];
	uint16_t zy_checksum;
} ZY_FW_INFO, *PZY_FW_INFO;
#define ZY_FW_INFO_SIZE sizeof(ZY_FW_INFO)	//should be 256 bytes

#define OPT_LEN_IS_VALID(_maxLen) ( strlen(optarg) < (_maxLen) )

#endif

According to this struct it should be a integer converted in hex which means that 0x0153 is 339... still not a useful information

ps. I tried building a 256byte 00 file (all zeros), it flashes (probably because the CRC is ok 00) but at next reboot zloader will automatically load the other partition with the error message saying "Zyxel magic number incorrect" or things like that, which makes the magic and crc a must to be able to flash and boot correctly with zloader.

I believe the sum is pretty stupid - it's simply the sum of all bytes...

0x45 + 0x58 + 0x59 + 0x5A + 2 + 1 = 0x153

You might want to verify this assumption with a few more fields set.

You are probably correct.

I tried with the following:

where -n 1 is the sequence number that in the previous example is 0

So the result is 0x0185

0x45+ 0x58 + 0x59 + 0x5a + 2 +1 +1 + 0x31 = 185.

Why didn't I think about that earlier... ¯_(ツ)_/¯

Super!

@daniel I've a question for a weird issue I have.

PHY6 is my wan interface which is an xor between sfp and ethernet.
The router boots and everything is good, the ethernet wan interface is working in autosense.
Let's say that I want to swap to use the sfp.

The way to do this is by exporting pins 57 and 10 on the board
Pin 57 probes if an sfp is inserted into the cage
pin 10 is used to swap between ethernet and sfp
if pin 57 is 0 it means that an sfp is inserted, hence i can swap manually pin 10 to 0 too and the sfp starts working, but, I need to keep the ethernet cable attached to the wan port with a link up for the sfp to work

as soon as I disconnect the cable or the link on the wan ethernet goes down the logs say:

root@OpenWrt:/# [  416.753743] mtk_soc_eth 15100000.ethernet eth1: Link is Down
[  416.760237] br-lan: port 1(eth1) entered disabled state

and the sfp is not reachable anymore (i'm pinging it just to test into the br-lan)

as soon as i reconnect the cable to the ethernet wan (any cable with any link) the sfp is immediately reachable

I've tried looking for something with mdio and changing things into the registers based on the datasheet but I had no luck.

could there be a way to "fake" keep the eth1 up for mtk_soc_eth to be able to use the sfp?

At this point there is no infrastructure in the Linux kernel to control such a mux for SerDes lanes, but probably it will not be too hard to do.
So as you say pin 57 is Moddef0 of the SFP cage, are the other pins (Moddef1 and Moddef2 for I2C, TX_FAULT and link indicator) available as well and have you figured them out already? I guess in that case you should wire up the SFP cage in device tree first of all, so the module is detected and identified first of all. Controlling the SerDes mux via GPIO 10 will require some additions to phylink afaik.

Do you have an example for doing this?

Regarding the pin mappings I've been troubleshooting how the zyxel oem firmware does the swap...
No DTS stuff first of all regarding the SFP cage.

I've identified a script that does the following
https://raw.githubusercontent.com/pameruoso/zyxel-ex5601t0/V5.70(ACDZ.0)C0/target/linux/mediatek/ex5601t0/base-files/bin/sfp_wan.sh

Here the pins are exported

########################  PLATFORMSETUP START
GPIOBASE=`cat /sys/class/gpio/gpiochip*/base | head -n1`
set_gpio() {
  GPIO_PIN=`expr $1 + $GPIOBASE`
  if [ -d /sys/class/gpio/gpio$GPIO_PIN ]; then
    echo "pin${GPIO_PIN} already be exported."
  else
    echo $GPIO_PIN > /sys/class/gpio/export;
    if [ $? != 0 ]; then
      echo "export pin${GPIO_PIN} fail."
    fi
  fi

  if [ "$3" != "" ]; then
    { [ "$3" = "0" ] && echo "low" || echo "high"; } \
      >"/sys/class/gpio/gpio$GPIO_PIN/direction"
  else
    echo in > /sys/class/gpio/gpio$GPIO_PIN/direction
  fi
}
# SFP: AE_MOD_ABS_1V8(GPIO_57), AE_RX_LOS_3V3(GPIO_23), AE_TX_FAULT_3V3(GPIO_28)
GPIO_INPUT_LIST="23 28 57"
# SFP: SFP_EWAN_SEL GPIO 10, HIGH for 2.5G PHY, LOW for SFP
GPIO_OUT_H_LIST="10"
# SFP: AE_TX_DIS_3V3(GPIO_26)
GPIO_OUT_L_LIST="26"
function init_sfp_gpios(){
    for i in $GPIO_INPUT_LIST; do
        set_gpio $i in
    done
    for i in $GPIO_OUT_H_LIST; do
        set_gpio $i out 1
    done
    for i in $GPIO_OUT_L_LIST; do
        set_gpio $i out 0
    done
}
########################  PLATFORMSETUP END

This is pin 57 which checks if the SFP is inserted:

function is_sfp_present(){
    MOD_ABS_VALUE=`cat /sys/class/gpio/gpio468/value`
    if [ "$MOD_ABS_VALUE" = "0" ]; then
        echo 1
    else
        echo 0
    fi
}

If that is true than the scripts swaps pin 10

function set_sfp_ethwan_sel(){
    case "$1" in
        "sfp")
            echo "Switch SGMII1 to SFP Mode"
            echo 0 > /sys/class/gpio/gpio421/value
            ;;
        "ethwan")
            echo "Switch SGMII1 to 2.5G PHY Mode"
            echo 1 > /sys/class/gpio/gpio421/value
            ;;
        *) echo "unknow select"
    esac
}

The script is doing additional checks too, like if the sfp is copper or fiber, gather the vendor, serial number and force 2500 mode...

After swapping the pin 10 to sfp mode it shuts down the ethernet too with:

power_down_ext_phy() {
    TMP_VAL=`mii_mgr_cl45 -g -p 0x6 -d 0x0 -r 0x0 | cut -d '=' -f 2 | tr -d ' '`
    WRITE_VAL=$(( $TMP_VAL | (1 << 0xb) ))
    WRITE_VAL_HEX=$(printf "%x" $WRITE_VAL)
    mii_mgr_cl45 -s -p 0x6 -d 0x0 -r 0x0 -v $WRITE_VAL_HEX >> /dev/null
}

I've simplified the original script to simply export the pins and swap if pin 57 is sfp true.... it's working but I've to keep the ethernet link up with something.

I decided to better troubleshoot what the OEM firmware does and it seems like Zyxel hardcoded a service called ESMD ( zyxel-ex5601t0/esmd.h at V5.70(ACDZ.0)C0 · pameruoso/zyxel-ex5601t0 · GitHub)
When inserting the SFP i read some logs regarding a new interface being created (eth1.2) and some stuff regarding vlans.... I guess they are probably forcing the link up with vlans or custom stuff...

still I was not able to find a way to keep the link up in a fake way....

any hints on how to achieve this?