100 Commits
Author SHA1 Message Date
Jonas Jelonek 4894562049 realtek: pcs: drop unneeded pointer cast
The return value of device_get_match_data was still explicitly casted to
the driver-internal type. However, since this function returns 'const
void *' and in C void pointers are automatically casted, this isn't
needed. Thus, drop it.

Link: https://github.com/openwrt/openwrt/pull/24310
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-20 15:45:54 +02:00
Jonas Jelonek e1a6d77124 realtek: pcs: rtl930x: apply only needed patching
For 10GBase-R and 2500Base-X, the patching sequences for the slower
modes are also applied. This mirrors the SDK which uses some automatic
detection and only does a one-time initialization. However, Linux works
different. The PCS is configured to a specific mode on demand. Thus,
there is no need to apply the other patching when it isn't really
needed.

Those patching sequences seem to initialize AFE blocks within the
SerDes, thus a 1G AFE shouldn't be needed for 10GBase-R. Testing
confirms this so far, no difference in any link characteristics when
e.g. 1G and 2.5G sequences aren't applied for a 10GBase-R link.

Link: https://github.com/openwrt/openwrt/pull/24310
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-20 15:45:54 +02:00
Jonas Jelonek e05153e47e realtek: pcs: rtl931x: do not configure 1000Base-X for 10GBase-R
So far, the 10GBase-R configuration mirrored the SDK which in addition
also sets up 1000Base-X and lets it run in a special mode having
autodetection of 10G/1G. This doesn't make that much sense given that
Linux will trigger PCS reconfiguration once the interface mode has
changed. Thus, we should only provide that for each mode standalone, not
for some proprietary and special mixed auto mode.

Link: https://github.com/openwrt/openwrt/pull/24310
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-20 15:45:54 +02:00
Jonas Jelonek b253af3698 realtek: pcs: rtl931x: add info to config bits
Give two SerDes register writes some meaningful information, since they
line up with usual PHY registers.

Link: https://github.com/openwrt/openwrt/pull/24310
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-20 15:45:53 +02:00
Jonas Jelonek b489ab0d86 realtek: pcs: rtl931x: drop RX channel resets during USXGMII config
The mode configuration calls LEQ/DFE reset and RX reset before doing
USXGMII configuration. Though the SDK does that similar, these calls are
actually unneeded because essentially the same is executed later again
in the attachment configuration. This is also the place where it
rather belongs. Thus, drop those calls in mode configuration.

Link: https://github.com/openwrt/openwrt/pull/24310
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-20 15:45:53 +02:00
Jonas Jelonek d9fdf451f1 realtek: pcs: rtl931x: drop unused helper
Drop the unused helper rtpcs_931x_sds_reset because it is unused and -
if it was used - would actively mess with the defined SerDes
deactivation/activation in pcs_config.

Link: https://github.com/openwrt/openwrt/pull/24310
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-20 15:45:53 +02:00
Jonas Jelonek 39cd3f8954 realtek: pcs: rtl931x: fix 1000Base-X config
Commit 7899dfa6ef ("realtek: pcs: rtl931x: separate and reuse
1000base-x config") introduced an issue by accident, using the register
value 0x12 instead of 0x13. A regression hasn't been noticed before, for
yet unknown reasons the 1000Base-X still worked here and there. Probably
due to some external setup.

However, this currently breaks 1000Base-X functionality on at least one
switch. Correcting the register value instantly restores 1000Base-X,
allowing the link to come up. It is unclear yet what this field means,
according to the SerDes register defines from related RTL8295 this might
be TX mode configuration field.

Also add another write which is present in several SDK versions.
Referring from related RTL8295, this might be a field called
EN_LINK_FIB1G, enabling 1000Base-X operation.

Fixes: 7899dfa6ef ("realtek: pcs: rtl931x: separate and reuse 1000base-x config")
Link: https://github.com/openwrt/openwrt/pull/24310
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-20 15:45:52 +02:00
Jonas Jelonek 3ec398f0c3 tools: firmware-utils: update to Git HEAD (2026-07-19)
1ab209233682 mkzynfw: rename macros from RTL93XX to RTL_OTTO
606f25ef3ca2 mkzynfw: add board definitions for Zyxel GS1920 v2 series
162fa533b309 mkzynfw: add board definitions for GS2210 series
b2d46a825a53 mkzynfw: add board definitions for Zyxel GS1920 v1 series
5c5df244b8a1 Revert "mkzynfw: add board definitions for Zyxel GS1920 v1 series"
7f28bfbc4b5a Revert "mkzynfw: add board definitions for GS2210 series"
5e1b83d1fc2b mkzynfw: add board definitions for GS2210 series
3e6b426938e8 mkzynfw: add board definitions for Zyxel GS1920 v1 series

Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-19 21:45:08 +00:00
Jonas Jelonek 52c0274e55 realtek: add PoE support for GS1920-24HP
Add PoE support for GS1920-24HP by providing the device tree
definition and selecting the Realtek PSE MCU driver package for build.
Support includes both versions of the device since they basically share
the same PSE frontend. The common DTSI includes the shared definitions,
the device DTS files then set the correct compatibles.

Link: https://github.com/openwrt/openwrt/pull/24239
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-17 19:34:46 +02:00
Jonas Jelonek b76acc1b1a realtek: add PoE support for USW XG Pro 8 PoE
Add device tree definition for PoE support using the Realtek PSE MCU
driver. Select the kernel package for the driver in DEVICE_PACKAGES
accordingly.

Link: https://github.com/openwrt/openwrt/pull/24239
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-17 19:34:46 +02:00
Jonas Jelonek d3e2f2df83 realtek: add PoE support for XGS1930-28HP
Add support for PoE on Zyxel XGS1930-28HP by leveraging the new Realtek
PSE driver. Define the PSE controller with all its properties in DTS of
the device and link it to the PHYs.

Link: https://github.com/openwrt/openwrt/pull/24239
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-17 19:34:45 +02:00
Jonas Jelonek 5b527dc7a4 realtek: switch to PSE driver for Plasma Cloud PSX28
Use the kernel PSE driver for PoE functionality on this device instead
relying on userspace apps. Drop the automatic selection for poemgr in
favor of the driver module.

Link: https://github.com/openwrt/openwrt/pull/24239
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-17 19:34:45 +02:00
Jonas JelonekandJan-Henrik Bruhn f306a19481 realtek: add PoE support for Linksys LGS328MPCv2
Add PoE support to Linksys LGS328MPCv2 by adding the required device
tree definition and select the needed kernel module package, making use
of the Realtek PSE MCU driver.

Co-authored-by: Jan-Henrik Bruhn <git@jhbruhn.de>
Link: https://github.com/openwrt/openwrt/pull/24239
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-17 19:34:45 +02:00
Jonas Jelonek 2f9484a2d8 realtek: add macro for pse-pi
Add a macro PSE_PI for the common pse-pi definition, helping with
devices which make use of the Realtek PSE MCU driver. While those
definitions stay manageable for low port counts, this adds too much
visual boilerplate with 24 or even 48 ports. The macro keeps it short
with one line per pse-pi.

Also make use of this macro directly for the two devices XS1930-12HP and
XMG1915-10EP.

Link: https://github.com/openwrt/openwrt/pull/24239
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-17 19:34:44 +02:00
Jonas Jelonek 464560fc35 realtek: fix fan control for Plasma Cloud PSX28/ESX28
Commit 82ddc472d7 ("realtek: dts: convert to upstream switch
notation") adjusted the switch description in the device tree to match
upstream. This was a correct change, however it broke the fan control
script for Plasma Cloud PSX28/ESX28 devices because it uses a
full-fledged platform device path including the switch node (because the
I2C is a child of the switch):

/sys/devices/platform/1b000000.switchcore/1b000000.switchcore:i2c@100c/i2c-4/4-002e/hwmon/

Since the mentioned change, this path doesn't exist anymore. Instead of
just changing the intermediate parts to match the DT structure again, do
not rely on that at all. Instead, use

/sys/bus/i2c/devices/4-002e/hwmon/

as the path which relies less on the DT structure and still points to
the same device. This makes fan control on those device work again,
reducing the fan speed during boot which has been broken since the
commit.

Fixes: 82ddc472d7 ("realtek: dts: convert to upstream switch notation")
Fixes: 2b5555c195 ("realtek: rtl931x: Add support for Plasma Cloud PSX28 Switch")
Link: https://github.com/openwrt/openwrt/pull/24248
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-16 22:22:07 +02:00
Jonas Jelonek 0f1019db1d realtek: pcs: rtl930x: gate WDIG 10G-mode bit on real baud rate
This bit was set unconditionally for any 10G-capable SerDes regardless
of hw_mode, including SGMII/1000BASEX/2500BASEX running on 10G-capable
silicon. The vendor SDK's dal_longan_construct_mac_default_10gmedia_fiber
gates it on the port's declared protocol class instead, applying it to
PHY-attached XSGMII/USXGMII as well as genuine fiber - the "medium to
fiber" naming doesn't match its actual condition.

Gate on speed == RTPCS_SDS_PLL_SPD_10000 instead, matching the real
10G-class protocol family, and actively clear it for 1G/2.5G modes so a
prior 10G-class configuration doesn't leave it stuck across a runtime
downshift. 0 also matches this register's confirmed hardware reset
default on an unconfigured SerDes.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:37:01 +02:00
Jonas Jelonek 7f063b1f95 realtek: pcs: rtl930x: gate TX tuning on attachment and baud rate
TX amp/pre-emphasis tuning depends on the SerDes' real baud rate class
rather than hw_mode, so key config_attachment's dispatch on that instead.

At 1G/2.5G, attachment doesn't change meaningful: even a non-adaptive
fiber receiver needs little compensation on a short trace, so
PHY-attached and fiber links already use the same config there. At 10G,
real channel loss is high enough that it matters: PHY-attached links
equalize on the PHY's own far-end receiver and need less amp drive,
while genuine fiber/DAC links, which have no adaptive receiver
downstream, need the full config. Real DAC-vs-fiber detection doesn't
exist yet, so both of those still share one config for now.

Make use of the PLL speed enum for now, though it is a bit blurry and
may not represent the real baud rate in some cases, e.g. QSGMII (1.25G
PLL with multiplier -> 5G).

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:37:01 +02:00
Jonas Jelonek 629c5c8b11 realtek: pcs: rtl930x: refactor TX config
Replace the on-stack, hardcoded pre/main/post-amp locals with static
const rtpcs_sds_tx_config data, one struct per speed class (1g, 2g5,
10g), instead of duplicating the same literals inline on every call.

Move the decision logic about which values are applied to the
config_media function. The tx_config should only be about what is set,
decision logic is handled one layer above. This also prepares further
refactoring.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:37:01 +02:00
Jonas Jelonek f8afbb637b realtek: pcs: rtl93xx: commit attachment only after successful config
sds->attachment was written right after selection, before
config_attachment() ran, so a failed config call would leave it
reflecting a value that was never actually applied to hardware. Move
the assignment after the call succeeds, matching how sds->hw_mode is
only committed after set_hw_mode() succeeds.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:37:00 +02:00
Jonas Jelonek 8d2bd202c4 realtek: pcs: rtl93xx: rename media to attachment
"media" doesn't fit well once PHY sits alongside FIBER/DAC_SHORT/
DAC_LONG as a value: a PHY isn't a transmission medium, whereas what
actually matters here is what electrically terminates the SerDes lane
on the other end. Rename the enum, struct field, ops vtable member,
and both variants' config functions accordingly. Calling it 'attachment'
better fits what it actually is, doesn't confuse with the variants and
also fits to the PMA (Physical Medium Attachment) sublayer that lives
below PCS.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:37:00 +02:00
Jonas Jelonek 5f6896209d realtek: pcs: rtl93xx: rename MEDIA_PCB to MEDIA_PHY
Every SerDes lane runs over some PCB trace before reaching the port,
even fiber/DAC ones, so PCB doesn't describe what actually
distinguishes this case: the SerDes terminates directly into a PHY
chip rather than a fiber module or DAC cable.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:37:00 +02:00
Jonas Jelonek 4212598948 realtek: pcs: rtl930x: classify SGMII as PHY-attached media
SGMII always terminates in a PHY, whether on-board or embedded in an
SFP copper module, so it belongs with QSGMII/XSGMII/USXGMII rather
than the direct fiber/DAC modes. The PHY equalizes on its own far-end
receiver in either case, so no media-dependent TX tuning is needed.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:36:59 +02:00
Jonas Jelonek bf2c9a5d8b realtek: pcs: rtl930x: only apply TX config for 10G SerDes
So far, there was only a misleading and confusing gate to avoid applying
the TX config to SerDes which do not need it or where it even breaks
some modes. This is achieved by not applying any configuration for
QSGMII mode. While this fits the real-world cases we know so far where
QSGMII is only used on SerDes 0/1 but never on others, it implicates
that this is true too for QSGMII on 10G SerDes. Looking at the SDK, this
assumption doesn't hold.

To fix this, drop out of config_media in case a non-10G SerDes is
delivered. The SDK does the same in various ways, ending up with the
config just being applied for SerDes 2 - 9.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:36:59 +02:00
Jonas Jelonek 8eaa84d2e9 realtek: pcs: rtl930x: use cmu_page getter for tx_config
Derive the CMU page from rtpcs_93xx_sds_get_cmu_page() instead of
hardcoding it per hw_mode case. Also change the function to return
int and propagate errors instead of silently doing nothing.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:36:59 +02:00
Jonas Jelonek 146d0fb6e0 realtek: pcs: rtl93xx: make cmu_page getter generic
Rename rtpcs_931x_sds_cmu_page_get() to rtpcs_93xx_sds_get_cmu_page()
and move it next to the other 93xx-shared helpers, so RTL930X can
reuse it instead of duplicating the same hw_mode-to-CMU-page switch.
Also fix the wrong -ENOTSUPP return to -EOPNOTSUPP.

Link: https://github.com/openwrt/openwrt/pull/24232
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-15 19:36:58 +02:00
Jonas Jelonek e9aa5bea9f realtek: add PoE support for XS1930-12HP
Add support for PoE functionality using the realtek-pse-mcu driver
(kmod-pse-realtek-mcu-i2c) interfacing the on-board PoE MCU and RTL8239
PSE chips.

This doesn't include any support for PoE-related LEDs.

Link: https://github.com/openwrt/openwrt/pull/23222
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-14 23:45:30 +02:00
Jonas Jelonek f57de02350 realtek: use realtek-pse-mcu kernel driver for PoE on XMG1915-10EP
Instead of relying on the userspace implementation, make this device the
first user of the new realtek-pse kernel driver (kmod-pse-realtek-mcu-uart)
based on the PSE-PD framework to interface PoE functionality of that
switch. Control of PoE functionality happens via ethtool / netifd now.
Drop selecting realtek-poe for this device.

This doesn't include any support for PoE-related LEDs.

Link: https://github.com/openwrt/openwrt/pull/23222
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-14 23:45:30 +02:00
Jonas Jelonek 184f70a44d realtek: pse: add patch for sysfs detection control
Add a patch which modifies the Realtek PSE MCU driver backport to add a
sysfs control to control detection mode per port. Some older,
bad-designed devices aren't detected properly in standard mode on some
switches, though vendor firmware powers them properly. Testing shows
that enabling the detection of legacy PDs by allowing wider resistance,
more input capacitance and using a wider detection window, solves this
issue.

The legacy detection can be activated by writing 1 to
portN/detection_legacy in the device's sysfs, e.g.

  echo 1 > /sys/bus/i2c/devices/3-0020/port0/detection_legacy

This patch is kept downstream for now, upstreaming will be attempted
though it is likely that upstream prefers a generic pse-pd approach.

Link: https://github.com/openwrt/openwrt/pull/23222
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-14 23:45:29 +02:00
Jonas Jelonek 301d98f81f realtek: add Realtek PSE MCU driver
Add pending patches which add a PSE driver for the PSE setup found on
most of Realtek-based switches. An MCU with a Realtek-defined firmware
and protocol fronts one or more PSE chips (from Realtek or Broadcom) as
a management controller.

The driver provides both I2C/SMBus and UART communication, which varies
among our supported switches. There is no need for complicated userspace
handling anymore, the PSE setup is defined in the device tree and
interfaced in userspace via ethtool, netlink and netifd support.

Those patches have progressed far enough upstream, the bindings are
reviewed. Thus, we can keep this intermediate version downstream to open
it up earlier for usage. Only little changes are expected til the final
version lands.

Link: https://github.com/openwrt/openwrt/pull/23222
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-14 23:45:29 +02:00
Jonas Jelonek 96ecf8dd24 generic: pse-pd: add patches for module-based PSE drivers
Add a backport patch and pending patches needed by upcoming PSE drivers
which are built as modules and probed after the MAC/PHY.

The net effect for module-built PSE controllers: attachment to PHYs
happens via the lifecycle notifier rather than via probe-time
-EPROBE_DEFER coupling, so the MDIO/DSA probe no longer sees any
PSE-originated -EPROBE_DEFER and the probe-retry storm is gone.

Link: https://github.com/openwrt/openwrt/pull/23222
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-14 23:45:29 +02:00
Jonas Jelonek 32e4796045 Revert "realtek: add support for Ubiquiti UniFi USW Pro Max 24 PoE"
This reverts commit b519bc3b76.

The partition layout wasn't tested properly on the device and has major
issues, possibly soft-bricking the device on first boot. Thus, the
installation procedure in the commit message is faulty. Revert for now.

Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-09 10:47:21 +02:00
Jonas Jelonek b519bc3b76 realtek: add support for Ubiquiti UniFi USW Pro Max 24 PoE
Add support for RTL9302B-based Ubiquiti UniFi USW Pro Max 24 PoE switch
with 16x GbE and 8x 2.5G RJ45 ports, 2x SFP+, and a front display.

Hardware
========

  - RTL9302B switch SoC
  - 512 MiB RAM
  - 32 MiB SPI-NOR flash
  - 16x 100M/1G RJ45 ports via 2x RTL8218E
  - 8x 100M/1G/2.5G RJ45 ports via 2x RTL8224
  - PoE:
      - 400W total budget
      - 8x 802.3at, 32W per port (ports 1-8)
      - 16x 802.3bt, 60W per port (ports 9-24)
  - 2x SFP+ ports
  - Buttons: 1x Reset
  - LEDs: RGBW LED per port (Etherlighting)
  - Front touch display via USB ACM (see below)
  - Console: TTL 3.3V, 115200 8N1 (internal pin header close to SoC;
    layout front to back: VCC RX TX GND)
  - Etherlighting feature (lighting patterns and color control)
  - Vendor firmware: U-Boot + LEDE-based Ubiquiti OS

MAC address
===========

Single MAC address in EEPROM partition, applied to all ports.

Front touch display
===================

The unit has a touch-capable front display, driven by a dedicated
STM32-based MCU. Unlike other Ubiquiti switches where the MCU is
connected to the SoC via UART directly, here it is exposed as a USB
CDC-ACM serial device through an on-board Genesys Logic GL850G USB hub.
The MCU runs Ubiquiti's LCM firmware and exposes a high-level JSON
protocol (page selection, button-press events, etc.); arbitrary
pixel-level control is not possible without replacing the MCU firmware.
Display support therefore depends on both USB host support and a driver
for the LCM protocol, neither of which is currently available.

Known issues
============

  - PoE not available, depends on WIP Realtek PSE MCU driver
  - Etherlighting not controllable, driver WIP. Port LEDs for link work
    though. By default, the controller keeps the LEDs in a breathing
    state, gated by the link state delivered by the Realtek SoC.

Disclaimer
==========

Stock firmware uses a dual-bank layout (kernel0/kernel1, ~15 MiB each).
OpenWrt replaces both banks with a single contiguous firmware partition.
Flashing OpenWrt overwrites both stock kernel slots; U-Boot remains
intact and can be used for recovery.

Installation
============

1. Enable SSH on the stock UniFi OS and log in with user account.

2. Copy the OpenWrt sysupgrade image to /tmp on the switch (e.g. via
   scp).

3. Adjust IMG below to point at the copied file, then run the block as a
   whole. It writes kernel0, splits into kernel1 if the image is larger
   than that slot (otherwise invalidates kernel1 so U-Boot cannot pick
   a stale bank), and reboots:

   IMG=/tmp/openwrt-realtek-rtl930x-ubnt_usw-pro-max-24-poe-squashfs-sysupgrade.bin
   K0_BLOCKS=$((0xec0000 / 0x10000))

   dd if="$IMG" of=/dev/mtdblock2 bs=64k count=$K0_BLOCKS conv=fsync
   if [ "$(wc -c < "$IMG")" -gt $((0xec0000)) ]; then
       dd if="$IMG" of=/dev/mtdblock3 bs=64k skip=$K0_BLOCKS conv=fsync
   else
       dd if=/dev/zero of=/dev/mtdblock3 bs=64k count=1 conv=fsync
   fi
   sync
   reboot

   The switch comes up in OpenWrt after reboot.

4. It is recommended to modify the bootcmd to speed up the boot and
   prevent any issues due to the dual-boot selection. Since U-Boot by
   default uses bootubnt which does a lot of (unneeded) RTK
   initialization, quite some time passes until Linux is started.
   Additionally, the U-Boot logic fiddles with some bits on flash which
   causes JFFS2 errors in OpenWrt. While this doesn't seem to cause
   issues yet, be defensive and set the bootcmd to:

     bootm 0xb4150000

   This directly boots the uImage from flash, without doing all the
   initialization. OpenWrt is able to bootstrap the networking
   completely on its own.

It does not matter which bank stock booted from when the dd block
runs: both banks are touched in the same pass (kernel0 written, kernel1
either written or invalidated). With kernel1 invalidated, U-Boot's
internal fallback kicks in and permanently switches to kernel0 on the
next boot, so the device stays on OpenWrt as long as kernel0 is
bootable.

Recovery
========

Since the installation procedure invalidates or partially overwrites
the second bank, recovery requires serial console access (see Hardware
above for pinout).

1. Interrupt U-Boot autoboot by spamming a key during early boot to
   drop into the U-Boot prompt.

2. Bring up networking:

   rtk network on

3. Transfer an OpenWrt initramfs image via TFTP and boot it:

   tftpboot 0x82000000 <server>:<initramfs.bin>
   bootm 0x82000000

4. From the running initramfs OpenWrt, do a sysupgrade to reflash
   OpenWrt or whatever you want to recover. There is no need for the
   complicated procedure from installation since OpenWrt sees the
   firmware partition already as a whole.

Return to stock firmware
========================

There is no fully-supported revert path. The stock firmware blob is a
Ubiquiti UBNT archive (header + parts, see firmware-utils' fw.h) that
embeds a u-boot and a kernel0 uImage payload; only the latter is
relevant when writing back to the kernel partitions.

The snippet below extracts the kernel0 uImage from such a blob by
locating the uImage magic and using the size carried in the uImage
header itself, without parsing any UBNT framing. It is provided as a
best-effort starting point; verify the result before flashing,
otherwise you're on your own:

   BLOB=<firmware.bin>
   OFF=$(grep -aboF $'\x27\x05\x19\x56' "$BLOB" | head -1 | cut -d: -f1)
   SIZE=$(( $(dd if="$BLOB" bs=1 skip=$((OFF + 12)) count=4 2>/dev/null \
               | hexdump -e '1/4 "%u"') + 64 ))
   dd if="$BLOB" of=kernel0.uImage bs=1 skip="$OFF" count="$SIZE"

Once you have a clean uImage, write it to the kernel partition from
within OpenWrt. If you adjusted the bootcmd during installation, make
sure to restore it to the default "bootcmd=bootubnt". After a reboot,
Ubiquiti's firmware should boot.

Or, if you made backups of the flash before installation, just write
the backup back to flash.

Link: https://github.com/openwrt/openwrt/pull/24110
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-08 23:17:13 +02:00
Jonas Jelonek f03899aef4 realtek: add support for Ubiquiti UniFi USW Pro XG 8 PoE
Add support for RTL9313-based Ubiquiti UniFi USW Pro XG 8 PoE switch
with 8x 10G RJ45 and 2x SFP+ ports.

Hardware
========

  - RTL9313 switch SoC
  - 512 MiB RAM
  - 32 MiB SPI-NOR flash
  - 8x 100M/1G/2.5G/5G/10G RJ45 ports via 2x RTL8264B
  - PoE: 8x 802.3bt, 60W per port, 155W total budget
  - 2x 1G/2.5G/10G SFP+ ports
  - Buttons: 1x Reset
  - LEDs:
    - System LED white/blue
    - RGBW LED per port
  - Console: TTL 3.3V, 115200 8N1, populated 4-pin header
    (device must be opened to access header)
  - Etherlighting feature (lighting patterns and color control)
  - Vendor firmware: U-Boot + LEDE-based Ubiquiti OS

MAC address
===========

Single MAC address in EEPROM partition, applied to all ports.

Known issues
============

  - PoE not available, depends on WIP Realtek PSE MCU driver
  - Etherlighting not controllable, driver WIP. Port LEDs for link work
    though. By default, the controller keeps the LEDs in a breathing
    state, gated by the link state delivered by the Realtek SoC.

Disclaimer
==========

Stock firmware uses a dual-bank layout (kernel0/kernel1, ~15 MiB each).
OpenWrt replaces both banks with a single contiguous firmware partition.
Flashing OpenWrt overwrites both stock kernel slots; U-Boot remains
intact and can be used for recovery.

Installation
============

1. Enable SSH on the stock UniFi OS and log in with user account.

(at this stage you may make backups of the flash, just to be sure)

2. Copy the OpenWrt sysupgrade image to /tmp on the switch (e.g. via
   scp).

3. Adjust IMG below to point at the copied file, then run the block as a
   whole. It writes kernel0, splits into kernel1 if the image is larger
   than that slot (otherwise invalidates kernel1 so U-Boot cannot pick
   a stale bank), and reboots:

   IMG=/tmp/openwrt-realtek-rtl931x-ubnt_usw-pro-xg-8-poe-squashfs-sysupgrade.bin
   K0_BLOCKS=$((0xec0000 / 0x10000))

   dd if="$IMG" of=/dev/mtdblock2 bs=64k count=$K0_BLOCKS conv=fsync
   if [ "$(wc -c < "$IMG")" -gt $((0xec0000)) ]; then
       dd if="$IMG" of=/dev/mtdblock3 bs=64k skip=$K0_BLOCKS conv=fsync
   else
       dd if=/dev/zero of=/dev/mtdblock3 bs=64k count=1 conv=fsync
   fi
   sync

   Then reboot the switch, it comes up in OpenWrt after reboot.

   You may also install the image in any other way, just make sure to
   write it to the kernel0 partition and if the image is larger than
   16MiB, write the rest to the kernel1 partition, otherwise invalidate
   it so U-Boot cannot boot from the second bank.

4. It is recommended to modify the bootcmd to speedup the boot and prevent
   any issues due to the dual-boot selection. Since U-Boot by default
   uses bootubnt which does a lot of (unneeded) RTK initialization,
   quite some time passes until Linux is started. Additionally, the
   U-boot logic fiddles with some bits on flash which causes JFFS2
   errors in OpenWrt. While this doesn't seem to cause issues yet, be
   defensive and set the bootcmd to:

     bootm 0xb4150000

   This directly boots the uImage from flash, without doing all the
   initialization. OpenWrt is able to bootstrap the networking completely
   on its own.

It does not matter which bank stock booted from when the dd block
runs: both banks are touched in the same pass (kernel0 written, kernel1
either written or invalidated). With kernel1 invalidated, U-Boot's
internal fallback kicks in and permanently switches to kernel0 on the
next boot, so the device stays on OpenWrt as long as kernel0 is
bootable.

Recovery
========

Since the installation procedure invalidates or partially overwrites
the second bank, recovery requires serial console access (see Hardware
above for pinout).

1. Interrupt U-Boot autoboot by spamming a key during early boot to
   drop into the U-Boot prompt.

2. Bring up networking:

   rtk network on

3. Transfer an OpenWrt initramfs image via TFTP and boot it:

   tftpboot 0x82000000 <server>:<initramfs.bin>
   bootm 0x82000000

4. From the running initramfs OpenWrt, do a sysupgrade to reflash
   OpenWrt or whatever you want to recover. There is no need for the
   complicated procedure from installation since OpenWrt sees the
   firmware partition already as a whole.

Return to stock firmware
========================

There is no fully-supported revert path. The stock firmware blob is a
Ubiquiti UBNT archive (header + parts, see firmware-utils' fw.h) that
embeds a u-boot and a kernel0 uImage payload; only the latter is
relevant when writing back to the kernel partitions.

The snippet below extracts the kernel0 uImage from such a blob by
locating the uImage magic and using the size carried in the uImage
header itself, without parsing any UBNT framing. It is provided as a
best-effort starting point; verify the result before flashing,
otherwise you're on your own:

   BLOB=US3.rtl93xx_7.4.1+X.Y.Z.bin
   OFF=$(grep -aboF $'\x27\x05\x19\x56' "$BLOB" | head -1 | cut -d: -f1)
   SIZE=$(( $(dd if="$BLOB" bs=1 skip=$((OFF + 12)) count=4 2>/dev/null \
               | hexdump -e '1/4 "%u"') + 64 ))
   dd if="$BLOB" of=kernel0.uImage bs=1 skip="$OFF" count="$SIZE"

Once you have a clean uImage, it can be written to the kernel partition
from within OpenWrt. If you adjusted the bootcmd during installation,
make sure to restore it to the default "bootcmd=bootubnt". After a reboot,
Ubiquiti's firmware should boot.

Or, if you did backups of the flash before, just write the backup to the
flash.

Link: https://github.com/openwrt/openwrt/pull/24010
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:38:13 +02:00
Jonas Jelonek ba2467954e realtek: pcs: rtl930x: some more calibration init cleanup
Some more cleanup for the calibration cleanup, removing some stray
whitespaces and collapsing subsequent writes in the same registers. The
former aren't helping anymore after the page -> named field conversion.
The latter can be collapsed because there is no reason to keep them
separate and thus, calls can be reduced.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:25 +02:00
Jonas Jelonek c56a15b149 realtek: pcs: rtl930x: replace mdelay with msleep/usleep_range
All calibration and SerDes config code runs in process context, so
busy-waiting with mdelay is unnecessary. Use usleep_range for delays
up to 10ms and msleep for longer ones to yield the CPU instead.

Add explicit linux/delay.h include to document the dependency.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:24 +02:00
Jonas Jelonek b1cb70feb0 realtek: pcs: rtl930x: add some context to calibration init
Replace SDK-style step numbering (1.1.1, 1.1.2, ...) with descriptive
section headers and inline register name comments. This makes it easier
to follow the calibration sequence without cross-referencing the SDK.
Also correct the LEQ acronym expansion and tidy up variable comments.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:24 +02:00
Jonas Jelonek eb857ca10e realtek: pcs: rtl930x: use VTH/TAP helpers in calibration init
Replace the raw register writes in rxcal_init with the previously
cleaned-up VTH and TAP helpers. Beyond readability, this also fixes two
latent bugs in the original tap4 initialisation: tap4_even was written
twice (both to PAGE_ANA_10G_EXT 0x01[5:0]) and tap4_odd was never
written at all (PAGE_ANA_10G 0x06[11:6]). Using tap_set_value(sds, 4,
0, 0) writes both fields correctly.

Also apply stage-then-latch ordering to the VTH init: write the value
registers before asserting the manual bit, consistent with the rest of
the calibration lock path.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:24 +02:00
Jonas Jelonek 89f145112b realtek: pcs: rtl930x: cleanup TAP helpers
Split tap_manual() into tap_set_adapt() and tap_set_value(), separating
mode control from value writes. Replace manual sign-magnitude bit
manipulation with rtpcs_sign_mag_encode/decode helpers. Update tap_get()
to use individual signed output pointers instead of an array and add
error propagation. Apply stage-then-latch ordering consistently: value
is written before the manual bit is set.

Remove the usleep from tap_set_adapt(enable=true). Callers already
carry explicit delays: vth_tap0_adapt_lock has msleep(200) and
dfe_taps_adapt has msleep(30) after enabling auto-adapt. The 10ms per
call was redundant and added 40ms to dfe_taps_adapt needlessly.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:23 +02:00
Jonas Jelonek 75de4464fa realtek: pcs: rtl930x: cleanup VTH helpers
Split vth_manual() into vth_set_adapt() and vth_set_value(), separating
mode control from value writes, consistent with DCVS and LEQ helpers.
Rename vth_get() to match and switch from an array parameter to
individual pointers. Invert the manual boolean to 'enable' (true means
auto-adapt is running). Add error propagation throughout and demote the
read-out print from pr_info to pr_debug.

Remove the usleep from vth_set_adapt(enable=true). The only caller is
vth_tap0_adapt_lock which already has an explicit msleep(200) to wait
for adaptation to complete, making the embedded 10ms redundant. Delay
belongs at the call site, not baked into the setter.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:23 +02:00
Jonas Jelonek 8d6a9e10d2 realtek: pcs: rtl930x: cleanup LEQ helpers
Split leq_manual() into leq_set_adapt() and leq_set_coef(), separating
mode control from coefficient writes, consistent with the DCVS helpers.
Rename leq_get() to leq_get_coef() and leq_get_bin() to
leq_get_coef_bin() to match. Add error propagation throughout.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:23 +02:00
Jonas Jelonek cfa212ad79 realtek: pcs: rtl930x: use DCVS helpers in calibration init
Replace the nine raw register writes that enable auto-adapt for all six
DCVS channels with a loop over dcvs_set_adapt(), consistent with how
TAP and VTH init was already converted.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:22 +02:00
Jonas Jelonek 4fc1dea129 realtek: pcs: rtl930x: cleanup DCVS helpers
Split the DCVS setter into two functions, separating mode control from
coefficient setting. The old pattern, combining everything in one
function, was still kept from the SDK but is rather confusing and makes
the function rather complex. Splitting this simplifies it a lot.

Cleanup the DCVS getter, making it consistent with the setters. Though
not used right now, kept for documentation purpose. So at least keep it
in a good style.

Remove the usleep from dcvs_set_adapt(enable=true). There is no lock
flow for DCVS that polls a result after enabling auto-adapt, so no
caller needs the delay. rxcal_init also enables VTH and TAP auto-adapt
via the load_in_init bulk write with no delay, confirming it is not
needed here either.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:22 +02:00
Jonas Jelonek 27d6b62fda realtek: pcs: rtl930x: fix DCVS setter
The (currently unused) DCVS setter (_dcvs_manual) is still based on the
XGS1210 SDK. Comparing this with other SDKs we have available (DMS1250,
TEG7124WS), a discrepancy between the setters can be seen. The variant
from XGS1210 SDK uses different fields for DCVS0 and DCVS4. They do not
match the other SDK variants, and also not the settings in
do_rx_calibration_1 where DCVS is initialized.

Adjust that to what the majority of SDK variants uses and to what makes
it consistent overall.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:22 +02:00
Jonas Jelonek ab49df2643 realtek: pcs: rtl930x: carve out debug selection
The three SerDes writes setting a debug output is heavily used by the
calibration code. But right now, it is duplicated in every user site. To
reduce duplication, carve out into a dedicated helper.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:21 +02:00
Jonas Jelonek 87e02936a4 realtek: pcs: rtl930x: rename last numbered calibration function
One calibration function was renamed from the numbered naming before,
mostly because its full purpose wasn't known yet. This has changed now,
so rename that function to "rxcal_init" to reflect what it's doing.

Link: https://github.com/openwrt/openwrt/pull/24091
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-07-06 22:36:21 +02:00
Jonas Jelonek 8b0ce8e4e3 realtek: pcs: rtl930x: simplify DCVS/VTH/TAP calibration helpers
Reduce repetition in dcvs_manual, dcvs_get, vth_manual and tap_manual
by hoisting the per-channel enable bit write out of per-case branches
and encoding per-channel register/bit mappings as lookup tables where
the pattern is uniform across channels.

This also fixes two bugs in dcvs_get that were hidden in the switch:

- DCVS1 read never populated dcvs_sign_out; it wrote the sign bit read
  (0x14[4:4]) into dcvs_coef_bin and then immediately overwrote it with
  the coefficient read, leaving the sign always zero for that channel.

- DCVS3 assigned the manual bit read directly to a bool without the !!
  normalisation applied to all other cases.

Link: https://github.com/openwrt/openwrt/pull/23983
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-28 23:38:37 +02:00
Jonas Jelonek 393d5b01fb realtek: pcs: rtl930x: fix LEQ calibration to use media type
Replace the mode-based approximation in the LEQ adapt+lock step with
proper media-based logic using the newly stored sds->media field. Those
adjustments are based on SDK code and digging through some basics of
signal conditioning.

PCB connections route through an external PHY (PHY-attached); that PHY
handles its own equalization so the SerDes LEQ is left in free-running
auto-adapt with no correction offset. DAC and fiber SFP connect directly
to the SerDes without an intermediate PHY and require a calibrated lock.

Replace the SDK's dacLongCableOffset/eqHoldEnable variable pair with a
single direct_serdes bool and encode the full per-media LEQ correction
into one switch: fiber +3 (direct SerDes, no cable), DAC short +4
(base 3 + 1), DAC long +6 (base 3 + 3).

Fix the MAXHOLD_EN bit (0x17[7]) and the 0x0c[8] write to be gated on
direct_serdes; both were previously conditioned on PCB which is the
PHY-attached case and thus wrong. Fix the LEQ lock to apply to all
direct SerDes connections (DAC + fiber), not just PCB. Also drop the
spurious dead-code branch that was an artifact of the original
transplanting.

No behavioral change because this particular function of calibration is
not used right now but will be in the future.

Link: https://github.com/openwrt/openwrt/pull/23983
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-28 23:38:36 +02:00
Jonas Jelonek 8dd1c280ae realtek: pcs: store active media type in SerDes state
Track the resolved media type in struct rtpcs_serdes alongside hw_mode,
storing it as soon as rtpcs_sds_select_media() resolves it so all
subsequent ops (set_hw_mode, activate, post_config) can access it.

This is unused for now and will be used only in dead code in next
patches. Though, this dead code is going to be used with subsequent
patches.

Link: https://github.com/openwrt/openwrt/pull/23983
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-28 23:38:36 +02:00
Jonas Jelonek d5615c1df6 realtek: pcs: rtl930x: give some calibration functions meaningful names
Adapted from the SDK, the calibration functions are just named after
their sequential logic and with a numbering scheme. This doesn't help
understanding what the code is doing. Instead, give some of them
meaningful names where possible, revealing kind of a logical structure.

Link: https://github.com/openwrt/openwrt/pull/23983
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-28 23:38:36 +02:00
Jonas Jelonek f33b49d0a7 realtek: pcs: rtl930x: reduce calibration code nesting
The calibration code is deeply nested with multiple function using
numeric nesting. Though it tries to follow the SDK pattern, this makes
it just unnecessarily complex and confusing. Dissolve some of this
unneeded nesting, together with some minor cleanup here and there.

Link: https://github.com/openwrt/openwrt/pull/23983
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-28 23:38:35 +02:00
Jonas Jelonek 6b16b96e43 realtek: dsa: rtl93xx: allow to adjust LED_CLK
The LED_GLB_CTRL register has a field to select the clock used for LED
output, either for serial LED output or for the external auxiliary MDIO
to connect a RTL8231. While the default value for the period time of
400ns is the correct one for most applications, some special devices
require a dedicated setting, e.g. UniFi switches with Etherlighting.

Support the generic DT property "clock-frequency" within the LED node,
and read + apply during LED configuration. In case the property isn't
specified, no change is applied to keep previous behavior. In case an
unsupported value is supplied, the default is used as a fallback

Link: https://github.com/openwrt/openwrt/pull/23944
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-27 10:24:21 +02:00
Jonas Jelonek 55efd11f27 layerscape: drop 6.12 files
Remove kernel configs and patches for 6.12, now that layerscape target
was switched to 6.18. This was missed during the 6.12 -> 6.18 PR.

Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-26 18:57:52 +02:00
Jonas Jelonek 47aa3ec222 realtek: mdio: add polling setup support for RTL8264B
Add polling setup support for RTL8264B PHY to avoid 'skip polling'
message during boot. Rely on the default register values for polling for
now, similar to RTL8261.

Link: https://github.com/openwrt/openwrt/pull/23946
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-26 17:34:38 +02:00
Jonas Jelonek 82f26df15c toolchain: binutils: change default to 2.46
Change default to latest upstream release.

Link: https://github.com/openwrt/openwrt/pull/23907
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-26 14:51:16 +02:00
Jonas Jelonek 4a31f8e544 realtek: pcs: replace hardcoded page values with named fields
Replace all hardcoded page values in various calls and definitions with
the previously added defines. This should help readability, giving those
various values a name and making it easier to compare and track within
the context of what is being set.

Link: https://github.com/openwrt/openwrt/pull/23915
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-26 11:54:56 +02:00
Jonas Jelonek fe5edcf985 realtek: pcs: add SerDes page definitions
To reduce having magic values all over the place in the whole driver,
add definitions for the SerDes register pages. They are equal among all
variants and can be clearly named, as already done in the debugfs output
of the realtek-otto-serdes-mdio driver. This should ease comparison,
code understanding and very likely is a step forward towards
upstream-readyness.

Also define two macros to cover the special cases for RTL931x's digital
SerDes via 0x40/0x80 page offset.

Link: https://github.com/openwrt/openwrt/pull/23915
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-26 11:54:55 +02:00
Jonas Jelonek 8ebf189e60 realtek: pcs: drop unused cmu_band code
For RTL930x and RTL931x, there were some functions to get and set the
CMU band. However, they were used nearly nowhere and even the SDK
doesn't use them for active SerDes configuration. Drop them to reduce
dead code.

Dropping the cmu_band_set call from RTL931x configuration has no
negative effect. We do not know where this call originally came from.
It was introduced 51c8f76612 ("realtek: improve MAC config handling for
all SoCs") but without any explanation why and where it came from. The
SDK doesn't have it and it may be overwritten again in the later CMU
setup when parts of the SerDes are reset.

Link: https://github.com/openwrt/openwrt/pull/23904
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:02:07 +02:00
Jonas Jelonek 0a7becdce1 realtek: pcs: rtl931x: use xsg_write instead of open-coded pattern
The xsg_write operation for RTL931x already offers the correct procedure
writing to both page + 0x40 and page + 0x80. Though, this wasn't used
so far because this pattern was still open-coded where needed. Replace
that with the xsg_write helper call.

In clear_symerr, this deliberately changes the exact sequence of
operations a bit. However, this shouldn't have any practical effect and
testing shows no issues.

Link: https://github.com/openwrt/openwrt/pull/23904
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:02:07 +02:00
Jonas Jelonek f3b7cfcb58 realtek: pcs: rename 'determine_hw_mode' to 'select_hw_mode'
Rename the 'determine_hw_mode' to 'select_hw_mode' to better express
what the function does. Based on the requested interface, the number of
links on a SerDes and the capabilities, it selects a suitable hardware
mode. 'determine' is clunkier and less expressive in this case.

Link: https://github.com/openwrt/openwrt/pull/23904
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:02:06 +02:00
Jonas Jelonek 4ac14efb86 realtek: pcs: drop wrong __maybe_unused
Some functions specify __maybe_unused from former times although they
are clearly used. Remove those attributes.

Link: https://github.com/openwrt/openwrt/pull/23904
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:02:06 +02:00
Jonas Jelonek 06cb5f1b21 realtek: pcs: drop unused modify helper
Drop the unused rtpcs_sds_modify helper. Other helpers already provide
what we need.

Link: https://github.com/openwrt/openwrt/pull/23904
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:02:06 +02:00
Jonas Jelonek 9be7947ac3 realtek: pcs: add macro for USXGMII AN opcode
Instead of hardcoding the USXGMII AN opcode values and potentially
losing track of what they actually mean, add a define for them. Actually
only one is used, however the other one gets a macro too for
documentation purpose.

Link: https://github.com/openwrt/openwrt/pull/23904
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:02:06 +02:00
Jonas Jelonek 947e0d8c63 realtek: pcs: fix comment
A comment sentence misses a word which likely confuses readers. Add the
missing word before everyone forgets what it might be.

Link: https://github.com/openwrt/openwrt/pull/23904
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:02:05 +02:00
Jonas Jelonek 47d1bf564f tools: bc: update to 1.08.2
Changelog included in source tar.

Removed patches:
- 000-getopt-prototype.patch
- 001-getopt-declaration.patch

Both patch changes are included upstream in this version.

Link: https://github.com/openwrt/openwrt/pull/23911
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 13:01:20 +02:00
Jonas Jelonek 4e2920fc08 package: nftables: replace patch with proper backport
A patch was added without proper header and not obvious that it's a
backport. Replace that patch with a backport of the upstream commit.

Patch 001-build-simplify-the-instantiation-of-nftversion-h.patch
rebased, all others refreshed.

Fixes: 255f4c8e60 ("packages: nftables: fix build on host with busybox ash")
Link: https://github.com/openwrt/openwrt/pull/23910
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-22 11:52:58 +02:00
Jonas Jelonek 9f385a71a7 package: nftables: bump PKG_RELEASE
Bump the PKG_RELEASE as it was missed when adding a patch.

Fixes: 255f4c8e60 ("packages: nftables: fix build on host with busybox ash")
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-21 17:49:40 +02:00
Jonas Jelonek 4ec2d6dd97 realtek: pcs: drop setup_serdes
Introducing the setup_serdes hook in the PCS driver was always intended
to be only a temporary solution. It was needed to be able to collect all
scattered code in the PCS driver first. Later, refactoring can be done
to bring everything into a proper shape.

Now we've reached the point where the setup of all variants has been
refactored in such a way that all share the same high-level sequence.
This is fully orchestrated in pcs_config now. Thus, the setup_serdes hook
is no longer needed. Move the last piece out of it into another SerDes
op hook, then drop setup_serdes.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:31 +02:00
Jonas Jelonek f6d95ca8c2 realtek: pcs: rtl931x: call CMU config from hw mode config
One deviating piece left is the extra call in 931x's setup_serdes to
config_cmu. It is called right after the hw mode configuration, in
contrast to 930x. Until we find a better home, move it to the end of
config_hw_mode to retain behavior but to pave the way for the final
unification steps.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:31 +02:00
Jonas Jelonek 84b63cfa75 realtek: pcs: move media configuration to pcs_config
As next step, move the media configuration to pcs_config by adding
another optional SerDes ops hook which is called from pcs_config. Drop
the redundant call sites in setup_serdes then.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:30 +02:00
Jonas Jelonek 9156053a1a realtek: pcs: rtl931x: adjust function naming
Rename the RTL931x function _sds_set_media to _sds_config_media to (1)
match the RTL930x name and (2) better express what it's doing. It's not
just setting the media type, it's configuring media-specific parameters.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:30 +02:00
Jonas Jelonek 97b48adb0f realtek: pcs: encapsule rtl930x media config in function
Move the two pieces for media configuration from RTL930x's setup_serdes
into a separate function, having the same encapsulation as RTL931x. This
will further allow to unify the setup sequence, and play a central role
in refactoring of the whole calibration code later.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:30 +02:00
Jonas Jelonek 458e498c1f realtek: pcs: carve out media selection as generic
So far, RTL931x implemented its media selection logic within
setup_serdes, unavailable to potential other users. One of those is
RTL930x which needs this too. To easy further refactoring, carve out the
logic to a generic helper providing the equal selection for all variants
anyway.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:29 +02:00
Jonas Jelonek 3aca9acdb3 realtek: pcs: move mode setting to pcs_config
Right now, setting the hardware mode of a SerDes is always the last step
in setup_serdes for each variant and more or less does exactly the same.
Drop that redundancy, replacing it with a ops hook and unified call from
pcs_config.

This changes behavior for RTL839x. Before, setup for 5G SerDes was
skipped entirely. Now, the mode is set properly. Tested on a device,
this has no negative effect.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:29 +02:00
Jonas Jelonek 6590a3d656 realtek: pcs: rtl83xx: move reset into activation
RTL838x and RTL839x call a reset at the end of their setup procedure
while RTL93xx do not do that. Since this is another hurdle for unifying
the setup procedure, move them to the activation hooks for now.

This retains behavior for both variants. Though something is called now
for RTL839x, the reset still skips 5G SerDes.

Link: https://github.com/openwrt/openwrt/pull/23861
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-18 22:23:29 +02:00
Jonas Jelonek 4a0e6aa95c generic: mips: replace pending patch with backport
The pending patch fixing reboot behavior on Realtek MIPS (and possibly
other MIPS targets) has been accepted upstream. Replace with a proper
backport.

Link: https://github.com/openwrt/openwrt/pull/23831
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-16 18:31:42 +02:00
Jonas Jelonek 24ec5ff687 realtek: replace pending SFP patches with backport
The SFP SMBus patches to access SFP modules with more than just byte
access have finally been accepted upstream. Replace them with the
upstreamed version, reorder them before our still downstream SMBus MDIO
patches and refresh all.

Link: https://github.com/openwrt/openwrt/pull/23825
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-16 18:30:58 +02:00
Jonas Jelonek 390276a846 realtek: pcs: improve lock and error handling in pcs_config
Make use of scoped_guard macro to ease lock and error handling in
pcs_config by having a dedicated scope and no need for gotos.

While being here, replace -ENOTSUPP with preferred -EOPNOTSUPP and drop
{ } brackets for single statement block.

Link: https://github.com/openwrt/openwrt/pull/23759
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-14 15:11:45 +02:00
Jonas Jelonek 77c750faad realtek: pcs: add activate/deactivate sds_ops hooks
Add the mandatory activate/deactivate bring-up hooks to rtpcs_sds_ops
and let rtpcs_pcs_config() drive the full sequence around the variant
configuration:

	deactivate -> setup_serdes -> activate -> post_config

The per-variant calls that were open-coded at the start and end of the
setup_serdes() functions are removed in favour of these indirections.
RTL839X never powered the SerDes down/up, so it gets no-op stubs to
satisfy the contract for now. Execution order is preserved for all
variants.

Link: https://github.com/openwrt/openwrt/pull/23759
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-14 15:11:45 +02:00
Jonas Jelonek 2e4d128ebf realtek: pcs: add post_config sds_ops hook
Some variants need finalization that must run only after the SerDes is
powered up: RTL838X performs a one-shot switch queue reset on first
start, RTL930X runs RX calibration and the TX config. So far this lived
at the tail of the variant setup_serdes() functions.

Add an optional post_config hook to rtpcs_sds_ops and call it from
rtpcs_pcs_config() right after setup_serdes(), then relocate the
RTL838X and RTL930X tail work into it. As activate() still runs at the
end of setup_serdes() here, the execution order is unchanged.

Link: https://github.com/openwrt/openwrt/pull/23759
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-14 15:11:45 +02:00
Jonas Jelonek 2d60ef16ad realtek: pcs: rtl930x: apply tx config before activation
In RTL930x setup, tx config was called at then end of the procedure
after configuration and calibration ran. This is still a leftover from
the old code located in DSA/PHY. However, applying TX configuration like
amplification factors, etc. doesn't make sense after calibration, it
should run before. Moreover the call was commented with "leave loopback
mode" which is just wrong and doesn't describe what the function does.
Fix this misery.

Testing on device with different interface modes shows no difference so
far, especially no negative effects.

Link: https://github.com/openwrt/openwrt/pull/23759
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-14 15:11:45 +02:00
Jonas Jelonek f8feda8c1b realtek: pcs: rtl838x: drop redundant reset writes
Sometimes redundancy is so obvious that one likely misses it. Trying to
bring all SerDes setup into a unified shape, one thinks twice if
something is really needed or not.

For the RTL838x case, the single writes for take/release reset were still
an outlier. Looking closer at them one can see that the same bits are all
covered already in deactivate/activate. So before, they have been put
into the desired state but those outlier writes mess with them again.

[0, 3, 0x7146/0x7106] just deals with the SOFT_RST bit that is already
covered by rtpcs_838x_sds_reset.

[0, 0, 0xc00] touches multiple bits, amongst the EN_RX/EN_TX bits
already covered in deactivate/active. Moreover, it potentially forces
other bits into a state causing broken functionality, e.g.
INV_HSI/INV_HSO which deal with the polarity. This has no effect right
no right now but might be a latent issue in the future.

Also move the reset call down to the end of the function, doing a
soft/RX reset after every configuration is done. This is likely what the
SDK also intended, and mirrors the 839x behavior.

Link: https://github.com/openwrt/openwrt/pull/23746
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-12 09:42:31 +02:00
Jonas Jelonek 541d2161a4 realtek: pcs: rtl838x: replace literal with macro
Replace 0 with MII_BMCR because in this context, it maps cleanly to
normal PHY register structure. BMCR_PDOWN is already used there to show
which bits are set.

Link: https://github.com/openwrt/openwrt/pull/23746
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-12 09:42:30 +02:00
Jonas Jelonek 8f23d97650 realtek: pcs: rtl838x: merge and simplify patching
Reduce the per-SerDes patching to a per-mode patching since they share a
lot of similarities, especially for QSGMII.

For fiber patching, the differences are bigger. This takes an approach
to merge the sequences completely despite applying some settings which
weren't applied before on one of the SerDes. Testing and SerDes dumps
showed no or minimal differences, and no practical effect on
functionality. A look at the SerDes register documentation we have shows
reordering the writes isn't problematic because most of the bits aren't
any trigger bits.

With all its users gone, we can now drop also the workaround SDS macro.

Link: https://github.com/openwrt/openwrt/pull/23741
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-11 20:27:30 +02:00
Jonas Jelonek 5c9f370a47 realtek: pcs: rtl838x: carve out writes for SerDes 0/1
For an attempt to simplify and reduce patching, carve out two special
writes for SerDes 0/1. While their exact purpose isn't fully known, they
need to match to make QSGMII on those two SerDes work. In order to be
able to merge the per-SerDes QSGMII patching sequences, carve them out
to the patching function one level above.

Link: https://github.com/openwrt/openwrt/pull/23741
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-11 20:27:30 +02:00
Jonas Jelonek 77ca8616fc realtek: pcs: rtl838x: set mode after patching
In order to have a unified SerDes setup sequence, align RTL838x to all
other variants. Set the mode after patching has been applied. Testing on
devices showed the order is rather irrelevant.

Link: https://github.com/openwrt/openwrt/pull/23741
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-11 20:27:30 +02:00
Jonas Jelonek f10f423e2b realtek: pcs: rtl838x: carve out latching writes
Carve out two latching writes present in all patching sequences at the
end. They are redundant and can be moved to the caller.

Link: https://github.com/openwrt/openwrt/pull/23741
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-11 20:27:29 +02:00
Jonas Jelonek 057314a5d2 realtek: pcs: rtl838x: fold lane enables and fiber path into {de,}activate
Expand the 838x deactivate/activate helpers to also cover the analog lane
enables (REG0 EN_RX/EN_TX) and the fiber path power-down (FIB_REG0
CFG_FIB_PDOWN), which are operational-state concerns rather than reset
concerns:

 - _deactivate: clear EN_RX/EN_TX and set CFG_FIB_PDOWN in addition to
   block-level power off.
 - _activate: clear CFG_FIB_PDOWN and set EN_RX/EN_TX before block-level
   power on. The pulse-start EN=0 is omitted since _deactivate already
   established EN=0 and nothing in between touches REG0[1:0].

Shrink rtpcs_838x_sds_reset() accordingly: it now owns only the SOFT_RST
toggle, making it a pure digital reset primitive. The stale "SerDes %d
reset" dev_info was dropped along with the analog/fiber writes.

Behavioural note: the EN and FIB_PDOWN writes now happen *after* the
SOFT_RST release inside rtpcs_838x_sds_reset(), rather than before it as
in the old combined sds_reset. This creates a brief window where the
SerDes is out of digital reset with lanes still disabled, before
activate re-enables them. Consistent with the new
power_off/deactivate -> configure -> reset -> activate/power_on phase
structure, but diverges from the SDK ordering (EN pulse before SOFT_RST
release). Testing on real hardware shows no difference.

Link: https://github.com/openwrt/openwrt/pull/23741
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-11 20:27:29 +02:00
Jonas Jelonek 9b3f3a7174 realtek: pcs: replace __free() auto-cleanup stuff
Upstream netdev maintainers disregard both variable declarations
mid-function and usage of __free() for auto-cleanup [1]. To avoid any
pain when trying to upstream the PCS driver at some point, adjust that
now before forgetting it.

[1] https://www.kernel.org/doc/html/next/process/maintainer-netdev.html#using-device-managed-and-cleanup-h-constructs

Link: https://github.com/openwrt/openwrt/pull/23694
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-07 19:03:43 +02:00
Jonas Jelonek 5d45f53966 realtek: pcs: rtl931x: enable XSGMII setup
The setup path has been adjusted before to at least not break a working
XSGMII setup. On the currently single affected device, the U-boot
pre-init runs unconditionally anyway. Thus, we can drop the top-level
gate and let our driver "setup" this mode. This enables further
structural changes.

Link: https://github.com/openwrt/openwrt/pull/23674
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-06 09:54:58 +02:00
Jonas Jelonek ef8302fb13 realtek: pcs: rtl931x: fix media config for XSGMII
While this doesn't claim to be a standalone setup for XSGMII, at least
it doesn't break the working XSGMII setup from U-boot on Linksys
LGS352C, the currently only supported device using this mode. Later
during further refactoring, this should be improved to make sure
everything is properly set.

Link: https://github.com/openwrt/openwrt/pull/23674
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-06 09:54:58 +02:00
Jonas Jelonek 3750c83341 realtek: pcs: rtl931x: release IP mode force-lock for XSGMII
rtpcs_931x_sds_deactivate() forces the SerDes IP mode register to OFF
(force-bit set, mode OFF) via apply_ip_mode(OFF). For IP-driven modes a
subsequent bring-up re-asserts the force-bit with the target mode, so the
lock is released. XSGMII, however, is MAC-driven: rtpcs_931x_sds_set_mode
only wrote the MAC mode and never released the IP force-lock, leaving the
IP block pinned OFF. XSGMII therefore only worked when the bootloader had
already configured the SerDes before deactivate ran.

Route the XSGMII branch through rtpcs_93xx_sds_set_mac_driven_mode(),
which unforces the IP mode (page 0x1f reg 0x09 bit 6) before writing the
MAC mode -- the same fix applied to RTL930x in 383c4469e4.

Link: https://github.com/openwrt/openwrt/pull/23674
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-06 09:54:58 +02:00
Jonas Jelonek 28e6a5e280 realtek: pcs: rtl93xx: extract MAC-driven mode bring-up helper
The MAC-driven set_mode path on RTL930x performs three steps: release the
IP mode force-lock so the MAC side takes over (deactivate forces IP=OFF),
write the MAC mode, then apply the USXGMII submode for modes that need
one. Pull these into a shared rtpcs_93xx_sds_set_mac_driven_mode() helper.

No functional change: rtpcs_930x_sds_set_mode now calls the helper instead
of open-coding the sequence. This prepares the helper for reuse by the
RTL931x XSGMII path, which currently lacks the IP force-unlock and so is
left pinned OFF by a preceding deactivate.

Link: https://github.com/openwrt/openwrt/pull/23674
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-06 09:54:57 +02:00
Jonas Jelonek b115da38b3 generic: mips: add pending patch to fix reboot
Add a pending hotfix to fix reboot functionality on MIPS platforms, at
least the Realtek target being affected.

The kernel bump from 6.18.33 to 6.18.34 introduced a backported commit
intending to fix a use-after-free issue [1]. As a side effect, it also
causes RCU to wait for CPUs which are already dead but RCU doesn't know
of.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-6.18.y&id=18c0456ea2615b1a743a6db739c74411c3b42bc6

Fixes: 94f3f9a845 ("kernel: bump 6.18 to 6.18.34")
Link: https://github.com/openwrt/openwrt/pull/23656
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-05 21:51:41 +02:00
Jonas Jelonek 80a44d6a52 realtek: pcs: reject SerDes modes unsupported by the instance
Add a per-SerDes supported_modes bitmap, filled at probe by each
variant from the SerDes id or type, and reject unsupported modes in
determine_hw_mode() via test_bit().

This replaces the rtl838x is_hw_mode_supported() switch and adds the
same gating to rtl839x/rtl93xx, which previously relied only on the
per-variant mode-value table. Unlike that table, the bitmap is per
SerDes instance, so it also rejects modes the table can encode but that
a given SerDes cannot actually use. Rejection uses the uapi -EOPNOTSUPP
instead of the internal -ENOTSUPP.

Link: https://github.com/openwrt/openwrt/pull/23608
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-01 09:17:15 +02:00
Jonas Jelonek e74d236e07 realtek: pcs: drop dead SerDes modes
SerDes modes HISGMII and QHSGMII are practically dead but were added/kept
for documentation purposes. However, these modes will likely never be
used and we have other documentation than in the code. Drop them to
reduce the modes to what we actually use.

Link: https://github.com/openwrt/openwrt/pull/23608
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-06-01 09:17:15 +02:00
Jonas Jelonek ed2a36afae realtek: fix macro usage in F1100W-4SX-4XGT DTSI
A recent target-wide change missed the DTSI for a few devices causing a
build issue for RTL930x. Fix that.

Fixes: 43562f97e7 ("realtek: dts: add link index cell to pcs-handle phandles")
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-05-31 12:51:56 +00:00
Jonas Jelonek ee6e8c88dc realtek: dsa,pcs: drop rtpcs_create
Drop the shared rtpcs_create function and references in both drivers
since that is now done via the fwnode PCS provider framework.

Link: https://github.com/openwrt/openwrt/pull/23539
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-05-31 12:52:41 +02:00
Jonas Jelonek a4965dbf48 realtek: migrate PCS to fwnode_pcs provider/consumer API
PCS driver registers each SerDes as an fwnode_pcs provider in probe;
the resolver returns the cached or freshly-allocated rtpcs_link for
the requested (sds, link_idx) cell. DSA glue stops calling
rtpcs_create directly, drops .mac_select_pcs, and instead populates
phylink_config.num_available_pcs / fill_available_pcs from each
port's pcs-handle in phylink_get_caps. The rtl838x_port.pcs pointer
becomes a has_pcs bool populated at port probe via fwnode_property_
present, since nothing assigns the actual phylink_pcs anymore but the
"does this port use a PCS?" checks elsewhere still need a presence
flag.

Without .mac_select_pcs, phylink_major_config only searches the
pcs_list when state->interface is set in phylink_config.pcs_interfaces
(drivers/net/phy/phylink.c:1378). Populate it per port whenever the
port has a pcs-handle, listing the SerDes-routable interface modes for
each SoC variant -- without this, pcs_config / pcs_link_up are never
called and the SerDes is left unconfigured.

pcs_get_state still needs the MAC port number to index per-port link
status registers. Recover it at probe via rtpcs_map_links: walk the
sibling switch's ethernet-ports subtree (same backwards topology
lookup the sibling MDIO driver does for phy-handle), and for every
port whose pcs-handle resolves to one of our SerDes, store the port's
reg in sds->link_port[]. The resolver consults link_port[] when
allocating rtpcs_link and fails with -ENODEV if a consumer requested
a link the map step didn't record. Avoids a driver-side port_base
table that would have to encode per-SoC SerDes-to-port wiring (and
would silently break on non-contiguous variants); the DT is the
single source of truth.

Kconfig selects FWNODE_PCS.

Assisted-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23539
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-05-31 12:52:41 +02:00
Jonas Jelonek c4f5c34fa4 realtek: pcs: add per-link port storage to rtpcs_serdes
Add an s16 link_port[] array to struct rtpcs_serdes, initialised to
-1 in probe. This is preparatory storage for the port number that
each link serves; it will be populated in the follow-up fwnode_pcs
migration commit by scanning consumer DT nodes for their reg, and
consumed by the resolver when allocating rtpcs_link.

Assisted-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Link: https://github.com/openwrt/openwrt/pull/23539
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-05-31 12:52:41 +02:00
Jonas Jelonek dbd9a35bf3 realtek: pcs: index links per SerDes via pcs-handle cell
Move the rtpcs_link pointer array from rtpcs_ctrl (keyed by global
DSA port) into rtpcs_serdes (keyed by the per-SerDes link index).
This matches how the hardware is structured -- a SerDes hosts up to
RTPCS_MAX_LINKS_PER_SDS PCS links -- and aligns the in-driver
addressing with the cell the DTSes just gained on pcs-handle, so the
upcoming fwnode_pcs resolver becomes a direct sds->link[cell] lookup.

rtpcs_create() takes a new link_idx parameter and stores into
sds->link[link_idx] instead of ctrl->link[port]; the DSA glue switches
its phandle lookup to of_parse_phandle_with_args() and forwards the
cell. The port number stays on rtpcs_link for legacy callers that
still need it. Bounds and double-bind checks (-EINVAL, -EBUSY) guard
against malformed DT references that would otherwise OOB or silently
overwrite an existing link.

Drops RTPCS_PORT_CNT, whose only user was the relocated array, and
fixes a pre-existing of_node_put leak on the pcs-handle phandle in
the DSA glue as a side effect of the parse-with-args conversion.

Link: https://github.com/openwrt/openwrt/pull/23539
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
2026-05-31 12:52:40 +02:00