====== SFP GPON ONU EEPROM Editing ====== ===== Add 2500Base-X ===== Credit: https://github.com/Anime4000/RTL960x/discussions/250#discussion-6288339 ==== Prerequisites ==== * OpenWrt router with: * SFP port(s) (any speed) with I2C bus * Packages ''ethtool-full'' ''i2c-tools'' ==== Steps ==== - SSH into OpenWrt - Run one of the following commands to determine which I2C bus your SFP is on * If your router has **a single SFP**: - ''%%BUS=$(for bus in /sys/bus/i2c/devices/i2c-*; do b=${bus##*-}; i2cdetect -y -r $b 2>/dev/null | grep -q " 50 " && i2cdetect -y -r $b 2>/dev/null | grep -q " 51 " && echo $b; done)%%'' - ''echo $BUS'' and check there is a value before proceeding (you can also run the multiple SFP script below to verify the SFP vendor and S/N) * If your router has **multiple SFPs**: - for bus in /sys/bus/i2c/devices/i2c-*; do b=${bus##*-} if i2cdetect -y -r $b 2>/dev/null | grep -q " 50 " && i2cdetect -y -r $b 2>/dev/null | grep -q " 51 "; then vendor="" for reg in $(seq 20 35); do vendor="$vendor$(printf "\\x$(i2cget -y $b 0x50 $reg | sed 's/0x//')")" done serial="" for reg in $(seq 68 83); do serial="$serial$(printf "\\x$(i2cget -y $b 0x50 $reg | sed 's/0x//')")" done echo "" echo "Bus: $b" echo "├─▶ Vendor: $vendor" echo "└─▶ S/N: $serial" fi done - Determine the correct bus number, e.g. 5 - ''BUS=5'' (replace 5 with the respective bus number) - Run the following commands to set the SFP EEPROM bits in OpenWrt according to the EEPROM Bits table below - ''i2cset -y $BUS 0x50 0x06 0x00'' - ''i2cset -y $BUS 0x50 0x0a 0x05'' - ''i2cset -y $BUS 0x50 0x0c 0x1f'' - ''%%i2cset -y $BUS 0x50 0x3f $(i2cdump -y -r 0-62 $BUS 0x50 b | awk 'NR>1 {for(i=2;i<=NF;i++) if($i~/^[0-9a-f]{2}$/) {cmd="printf \"%d\" 0x"$i; cmd|getline d; close(cmd); sum+=d}} END {printf "0x%02x", sum % 256}')%%'' - Physically re-seat the SFP - Verify the new speeds are detected:\\ ''ethtool -m //**[ethX]**//''\\ Supported link modes: 2500baseX/Full 1000baseX/Full ==== EEPROM Bits ==== ^ Address ^ Field ^ Old Value ^ New Value ^ Reason ^ | ''0x06'' | Ethernet Compliance | ''0x02'' | ''0x00'' | Clear 1000BASE-LX to avoid advertising conflicting speeds alongside 2500BASE-X | | ''0x0A'' | Extended Compliance | ''0x00'' | ''0x05'' | Declare 2500BASE-X support | | ''0x0C'' | Nominal Bit Rate | ''0x0D'' | ''0x1F'' | Set to 3100MBd (correct value for 2500BASE-X) | | ''0x3F'' | CC_BASE Checksum | (varies) | (recalculated by ''awk'') | Sum of bytes 0x00–0x3E mod 256 | | ''0x5F'' | CC_EXT Checksum | (varies) | (unchanged) | Not affected by these changes | ==== EEPROM Bits (XG-PON/XGS-PON) ==== > ⚠️ **Warning:** These settings are untested. Proceed with caution. Notes: * Due to Linux kernel limitations, only a single speed can be advertised via EEPROM for XG-PON/XGS-PON. Multi-rate combinations (e.g. 2.5/5Gbps, 5/10Gbps, 2.5/5/10Gbps) are not achievable through EEPROM editing alone((Linux's SFP bus driver derives supported speeds solely from EEPROM compliance codes, which only allows a single speed to be declared via the compliance code bytes. Multi-rate support requires either a kernel quirk (hardcoded per vendor/part number in ''sfp.c''), a PHY-emulating module that negotiates speeds independently, or a NIC driver that bypasses the generic SFP bus logic entirely.)) * You do not have to update the 0x5F checksum (CC_EXT) unless you edit addresses ''0x40''–''0x5E'', which are out of scope of this guide; but in case you need it, this command will update CC_EXT:\\ ''%%i2cset -y $BUS 0x50 0x5f $(i2cdump -y -r 64-94 $BUS 0x50 b | awk 'NR>1 {for(i=2;i<=NF;i++) if($i~/^[0-9a-f]{2}$/) {cmd="printf \"%d\" 0x"$i; cmd|getline d; close(cmd); sum+=d}} END {printf "0x%02x", sum % 256}')%%'' === Fiber Rates (No PHY) === ^ Address ^ Field ^ Choose only ONE column of values ^^^^^^ ^ ::: ^ ::: ^ 1000BASE-X ^ 2500BASE-X ^ 10GBASE-LR ^ 10GBASE-SR ^ 10GBASE-LRM ^ 10GBASE-ER ^ | ''0x03'' | 10G Ethernet Compliance | ''0x00'' | ''0x00'' | ''0x20'' | ''0x10'' | ''0x40'' | ''0x80'' | | ''0x06'' | Ethernet Compliance | ''0x02'' | ''0x00'' | ''0x00'' | ''0x00'' | ''0x00'' | ''0x00'' | | ''0x0A'' | Extended Compliance | ''0x00'' | ''0x05'' | ''0x00'' | ''0x00'' | ''0x00'' | ''0x00'' | | ''0x0C'' | Nominal Bit Rate | ''0x0D'' (1300MBd) | ''0x1F'' (3100MBd) | ''0x67'' (10300MBd) | ''0x67'' (10300MBd) | ''0x67'' (10300MBd) | ''0x67'' (10300MBd) | | ''0x3F'' | CC_BASE Checksum | (recalculated by ''awk'') |||||| Notes: * Set ''0x06'' to ''0x00'' (clear 1000BASE-LX) for all configurations above except 1000BASE-X, to avoid advertising conflicting speeds alongside the selected rate === Copper Rates (PHY Emulation Required) === ^ Address ^ Field ^ Choose only ONE column of values ^^^^ ^ ::: ^ ::: ^ 2500BASE-T ^ 5GBASE-T ^ 10GBASE-T (SFI) ^ 10GBASE-T (SR, 30m) ^ | ''0x03'' | 10G Ethernet Compliance | ''0x00'' | ''0x00'' | ''0x00'' | ''0x00'' | | ''0x06'' | Ethernet Compliance | ''0x00'' | ''0x00'' | ''0x00'' | ''0x00'' | | ''0x0A'' | Extended Compliance | ''0x1E'' | ''0x1D'' | ''0x16'' | ''0x1C'' | | ''0x0C'' | Nominal Bit Rate | ''0x1F'' (3100MBd) | ''0x32'' (5000MBd) | ''0x67'' (10300MBd) | ''0x67'' (10300MBd) | | ''0x3F'' | CC_BASE Checksum | (recalculated by ''awk'') ||||