@jonasj reverse engineered the watchdog and we are trying to fix it currently. Your hardware is essentially the same as my s1300WP-8xgt-4s+ (you got 2 more10GT ports instead of SFP+). The watchdog is a hardware watchdog via i2c.
I (or rather Gemini) got OpenWRT working on yet another similar RTL9303 device: The "ZX-SWTGW2C8F". Judging from Aliexpress, this is also one floating around under different branding but likely the exact same hardware. This one requires far less intrusive changes, so I started preparing / opening PRs.
I also took some notes on how I set up the environment for AI driven porting, which should basically apply to any of these RTL93xx-based devices: https://mensi.ch/blog/articles/letting-ai-implement-openwrt-support-for-managed-switches
So if someone hooks up a new device to ConsolePi to power cycle the device, giving serial access and running a TFTP server. Then they can grant access to someones SSH key and there is a good chance for automated bring up? Nice!
Ah interesting, I have two of these sitting here and took them apart just a few days ago. How did you get serial, did you solder a RJ45 connector to the board, or JTAG?
Edit: ah I see the photo in your blog post ![]()
I just spent some more time on getting another patch ready for the "ZX-SWTGW2C8F": It uses 2 RTL8231 GPIO expanders, and I see that both RTL930x and RTL931x have support for 2 in their external GPIO block (MDX2/MDX3 or MDX4/MDX5 respectively). As far as I understand, the current patches from @svanheule do not implement this engine switching yet, which the SDK seems to do based on whether the address is 0 or not.
Now since all this Linux/OpenWRT patching is new to me, I'm a bit confused: I can't find https://github.com/openwrt/openwrt/blob/main/target/linux/realtek/patches-6.18/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch upstream or on LKML, is this patch intended to live only in OpenWRT and I should therefore just add support for the dual engine setup there? Or how does this work? ![]()
Yes there’s patches everywhere that aren’t yet upstreamed, or will never be upstreamed. See the naming scheme here: https://openwrt.org/docs/guide-developer/toolchain/use-patches-with-buildsystem#naming_patches
Upstreaming is very desirable, but sometimes other concerns take priority ![]()
Be careful with plainly porting over SDK concepts to the kernel if you want patches to be upstreamable. I don't know what this "engine switching" entails, but if the expanders live on physically different MDIO busses, then these should be described accordingly in the devicetree and the driver. If there some sort of mux, then that can be modeled on top.
Looking at the RTL930x register map, I see there is the LED_INDRT_ACCESS_CTRL register at offset 0xCCCC which isn't in the driver and which doesn't support the read-failure flag. Maybe you could add a realtek,rtl9300-aux-basic-mdio compatible where the rcmd mask is empty. Then you could simply instantiate a second MDIO bus in the devicetree; one with the "full" compatible, one with the "basic" compatible.
Got my Horaco ZX-SW82TS-L2 and had a first look. I think I'm seeing similar things as a few of you throughout this thread:
- Stopping u-boot via CTRL+C, z, h
- The board model is set to
RTL9302D_2x8224_2XGE, though that is not listed inrtk show hw_profile_list. Sortk network ondoes not result in any connectivity. No luck with picking values from the profile list, though I did not go through all 28 options systematically. - The watchdog that reboots after a couple of minutes. As I can't tftp anything (because of the previous point), I tried to dump the firmware using
md.bbut with the watchdog rebooting the device I can only get a few hundred K. loadyand sending something via ymodem let's me upload ~850K before the watchdog kicks in.
Going by some of the addresses mentioned to be possibly related to the watchdog:
b80032f8: 00000000 00000000 00ffffff 00000000 ................
b8003308: 00000000 0063fffe 00000000 00000000 .....c..........
Without a clue of what I'm doing, I tried overriding those with zeroes via
mw.l 0xb80032f8 0 3 (no effect observed) and mw.l 0xb8003309 0 1 (device hung, and rebooted eventually).
I looked at @mensi's uboot_boot.py but I need some more mental cycles to make sense of it tbh.
Any pointers on what I could try next are very very welcome. I might try to open up the device, perhaps get a SOIC-8 clip, eventually. But hopefully there is more stuff I can try with just my serial cable.
Other info for reference, fwiw:
U-Boot 2011.12.(3.6.8.55120) (Jul 11 2024 - 14:44:22)
Board: RTL9300 CPU:800MHz LX:175MHz DDR:600MHz
DRAM: 512 MB
SPI-F: MXIC/C22019/MMIO32-4/ModeC 1x32 MB (plr_flash_info @ 83f9a094)
Loading 65536B env. variables from offset 0xe0000
Net: Net Initialization Skipped
No ethernet found.
RTL9300# # flshow
=============== FLASH Partition Layout ===============
Index Name Size Address
------------------------------------------------------
0 LOADER 0xe0000 0xb4000000-0xb40dffff
1 BDINFO 0x10000 0xb40e0000-0xb40effff
2 SYSINFO 0x10000 0xb40f0000-0xb40fffff
3 JFFS2_CFG 0x100000 0xb4100000-0xb41fffff
4 JFFS2_LOG 0x100000 0xb4200000-0xb42fffff
5 RUNTIME1 0xe80000 0xb4300000-0xb517ffff
6 RUNTIME2 0xe80000 0xb5180000-0xb5ffffff
======================================================
rtk show hw_profile_list
Available profiles are:
RTL9301_2x8214QF_4XGE (9300001)
RTL9301_3x8218B_4XGE (9300002)
RTL9301_8218B_4XGE (9300003)
RTL9301_8218B_4XGE_CASCADE (9300004)
RTL9301_2x8214QF_4XGE_CASCADE (9300005)
RTL9301_14QF_4XGE_18B_4XGE_CASCADE (9300006)
RTL9301_3x8218D_4XGE (9300007)
RTL9301_6x8214QF_4XGE (9300008)
RTL9301_2x8214FC_4x8214QF_4XGE (9300009)
RTL9301_6x8218D_2x8295R_CASCADE (9300010)
RTL9301_2x8218B_4x8218D_2x8295R_CASCADE (9300011)
RTL9302B_2x8218D_2xCUST1_4xGE (9300012)
RTL9302C_4xCUST1 (9300013)
RTL9303_2xCUST1 (9300014)
RTL9303_8XGE (9300015)
RTL9303_8X2_5G (9300025)
RTL9303_8X8226 (9300020)
RTL9303_5X8226_2XGE (9300021)
RTL9303_2x8264_ZHIHUI (9300022)
RTL9303_5x8261BE_2XGE_ZHIHUI (9300023)
RTL9302DE_2XRTL8284 (9300016)
RTL9302C_2xRTL8284_2XGE (9300017)
RTL9302C_4xRTL8284_4XGE (9300018)
RTL9302B_2x8218D_2x8284_4xGE (9300019)
RTL9301_3x8218D_2x8226CARD_2XGE (9300024)
RTL9301_3x8218E_4XGE (9300026)
RTL9303_2X8254L_DEMO (9300027)
RTL9303_6x8254L_6xSPI (9300028)
(uboot: setenv boardmodel 'YOUR_HARDWARE_PROFILE_NAME')
## Booting image from partition ... 0
## Booting kernel from Legacy Image at 81000000 ...
Image Name: RTK_SDK
Created: 2025-12-17 14:35:31 UTC
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 6305290 Bytes = 6 MB
Load Address: 80000000
Entry Point: 803169a0
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
Starting kernel ...
My recommendation would be:
- Clone https://github.com/mensi/rtl930x_tools
- Clone and checkout this branch: https://github.com/mensi/openwrt/tree/horaco-dev2
make menuconfig, select the right model, and any packages you want, e.g. ethtool- Build the image with
make - Something like
rtl930x_tools/imi-firmware/uboot_boot.py --disable-watchdog --ymodem PATH_TO_IMAGE_YOU_BUILT
I sometimes had some issues with ymodem when the console cable was too close to noisy power supplies / cable, so make sure you either have a better cable than I have or it's far away from electrical noise.
Thanks! I was a bit hesitant to try the script because of the warning at the top in the version you linked earlier. Something about the GPIO pins and possibly shorting things? All of this is still somewhat out of my comfort zone, so perhaps I'm being over cautious for no reason.
Ideally I'd like to first manually verify that the values in the script do make sense for my non-POE model as well (they probably do), if only to educate myself. I'll see if I can make sense of it in that way, and otherwise just run the script of the aforementioned warning is not applicable anymore(?).
Thanks @mensi. That actually worked.
Initially, I tried to rebase your later horaco-pr-support branch, but with that, networking never actually came up. Not sure whether it was your branch or my rebase which broke it.
Concerning your uboot_boot.py script, I just had to add some more delays to your i2c_set_ and update_ functions. Otherwise, in my environment, I could never get it to successfully disable the watchdog. And yes, I also had to change the load address to 0x84f00000, as the LZMA decompressor otherwise stumbled over itself. Let me send you a pull request with that. Here you go:
Thanks again and looking forward to having this all properly upstreamed ![]()