From: Jonas Jelonek Date: Sun, 4 Jan 2026 21:04:53 +0000 (+0000) Subject: realtek: add support for Zyxel XS1930-12HP X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a8d5544c8349fe78e99954e948827d1c699ac5da;p=thirdparty%2Fopenwrt.git realtek: add support for Zyxel XS1930-12HP Add support for RTL9313-based Zyxel XS1930-12HP, a 12-port Multi-Gig switch with 10x 100M/1G/2.5G/5G/10G RJ45 and 2x 1G/10G SFP+ ports. Hardware ======== - RTL9313 SoC - 256MiB DDR3 RAM (Winbond W632GU6MB) - 32MiB SPI-NOR Flash (Macronix MX25L25645G) - 8x 100M/1G/2.5G/5G/10G RJ45 (Aquantia AQR813) - 2x 100M/1G/2.5G/5G/10G RJ45 (2x Aquantia AQR113C) - 2x 1G/10G SFP+ - PoE: - Ports 1-8 with PoE++/802.3bt - 2x RTL8239 + GigaDevice FD32F103 MCU - RTL8231 for port LEDs - LM96000 I2C hardware monitor - 3-pin fans - Front LEDs: PWR, SYS, CLOUD, LOCATOR, POE USAGE - Console: TTL 3.3V, 115200 8N1 - Software chain: - Bootbase/stripped-down U-Boot - BootExt - RAS/ZyNOS Console ======= The console port is a 4-pin header reachable without opening case. Looking at the front port-side of the device, turn the device 90 degrees clockwise. On this side, there's a rectangular opening in the honeycomb structure. Pinout is (from left/front to right/back): GND RX TX VCC Hardware quirks =============== * The SFP signals RX_LOS, MOD_ABS and TX_FAULT do not have dedicated GPIO lines each. Instead, there's a multiplexer (using GPIO12 and GPIO14) which - depending on its state - connect this single GPIO line to RX_LOS, MOD_ABS or TX_FAULT (GPIO19 for SFP1, GPIO27 for SFP2). This requires a special adapter driver (which is backed by a gpio-mux) that makes this hardware design and Linux' SFP core work together. * SFP slots are disabled by default. GPIO6 and GPIO7 seems to be gates for SFP1 and SFP2 respectively. The need to be pulled low to make SFP modules work (i.e. respond to I2C requests and pass GPIO signals). * Fan can only be set to SLOW or FAST mode, no real speed/PWM control. Disclaimer ========== PoE not yet supported. Flashing OpenWrt will overwrite BootExtension + ZyNOS. BootExtension functionality (e.g. initramfs boot as mentioned below) is not available anymore then. The U-boot/Bootbase still has some limited functionality which can be used in emergency cases. Installation ============ Simple web upgrade: 1. Take the OpenWrt factory.bin image generated by the build. 2. In the ZyNOS web UI, login and go to Maintenance -> Firmware Upgrade. 3. Under "Boot Image", make sure the Config Boot Image is set to 1. In other words, make sure the switch booted from firmware image 1 or it will do so on next reboot. This is crucial, otherwise OpenWrt cannot boot. 4. Below, select and upload the factory.bin image. After clicking upgrade, the image will be flashed. 5. After flashing has finished, reboot the switch. It will now boot into OpenWrt. Initramfs boot ============== NOTE: You need to use Xmodem transfer, the bootloader doesn't support Ymodem nor any networking. This only works as long as the default ZyNOS firmware is installed. 1. Connect to the switch using serial and interrupt the boot process to enter debug/recovery mode. 2. You need to unlock the bootloader. Use known methods [1] and [2] to obtain the unlock code and unlock the bootloader with: > ATEN 1, 3. Upload the initramfs image using Xmodem: > ATUP
,
: you may use any RAM address >= 0x80300000 : length of image in bytes 4. After the transfer has finished, boot the image with: > ATGO
5. Wait for OpenWrt to boot. At this stage, it might be wise to create a backup/dump of the Flash partitions. Return to stock firmware ======================== 1. Download the firmware for the switch from Zyxel website. 2. Unzip the download, there should be a .bin file with a alphanumeric name. 3. Upload this file to running OpenWrt. 4. Run (use -F since the image doesn't have image metadata): > sysupgrade -F .bin 5. Wait for the sysupgrade to succeed and the switch reboot. At the next boot, ZyNOS should come up again. Recovery ======== The Bootbase loader is actually a modified U-Boot variant. You can enter it by spamming $ during the DRAM test. The U-Boot shell can be unlocked with [1] and [2]. Note that the command is slightly different, using a space instead of a comma, and lowercase: > aten 1 You should now have more-or-less a standard RTK-U-boot shell from where you can upload and write a new image to flash. Use e.g.: > upgradeY image2 81000000 115200 Wait for the upgrade process to finish and reboot the switch. === [1] https://akao.co.uk/tools/zyxel_unlocker/ [2] https://www.ixo.de/info/zyxel_uclinux/ Signed-off-by: Jonas Jelonek Link: https://github.com/openwrt/openwrt/pull/22909 Signed-off-by: Robert Marko --- diff --git a/target/linux/realtek/base-files/lib/upgrade/platform.sh b/target/linux/realtek/base-files/lib/upgrade/platform.sh index c5bf860e4c5..c2b11bceac1 100644 --- a/target/linux/realtek/base-files/lib/upgrade/platform.sh +++ b/target/linux/realtek/base-files/lib/upgrade/platform.sh @@ -45,7 +45,8 @@ platform_do_upgrade() { nand_do_upgrade "$1" ;; zyxel,xs1930-10|\ - zyxel,xs1930-12f) + zyxel,xs1930-12f|\ + zyxel,xs1930-12hp) PART_NAME="factory" default_do_upgrade "$1" ;; diff --git a/target/linux/realtek/dts/rtl9313_zyxel_xs1930-12hp.dts b/target/linux/realtek/dts/rtl9313_zyxel_xs1930-12hp.dts new file mode 100644 index 00000000000..1eab2398ea4 --- /dev/null +++ b/target/linux/realtek/dts/rtl9313_zyxel_xs1930-12hp.dts @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/dts-v1/; + +#include "rtl9313_zyxel_xs1930.dtsi" + +#include +#include +#include +#include + +/ { + compatible = "zyxel,xs1930-12hp", "realtek,rtl9313-soc"; + model = "Zyxel XS1930-12HP"; + + leds { + led_pwr_green: led-2 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + led_pwr_red: led-3 { + color = ; + function = LED_FUNCTION_POWER; + gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; + }; + led_cloud_green: led-4 { + color = ; + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + }; + led_cloud_red: led-5 { + color = ; + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + }; + led_locator: led-6 { + color = ; + function = LED_FUNCTION_INDICATOR; + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + }; + }; + + led_set: led_set@0 { + compatible = "realtek,rtl9300-leds"; + active-low; + + /* Blue | Green | Red */ + led_set0 = <(RTL93XX_LED_SET_10G | RTL93XX_LED_SET_5G | RTL93XX_LED_SET_2P5G | + RTL93XX_LED_SET_LINK | RTL93XX_LED_SET_ACT) + (RTL93XX_LED_SET_2P5G | RTL93XX_LED_SET_1G | RTL93XX_LED_SET_100M | + RTL93XX_LED_SET_LINK | RTL93XX_LED_SET_ACT) + (RTL93XX_LED_SET_5G | RTL93XX_LED_SET_100M | RTL93XX_LED_SET_LINK | + RTL93XX_LED_SET_ACT)>; + /* Phantom port chain padding (2 LEDs) */ + led_set1 = ; + + /* The LED PCB has two daisy-chained RTL8231 in scan mode. + * Net LEDs for P3-P12 are on the first RTL8231, P1/P2 + * net LEDs are on the second. The 12 real ports provide + * 36 LED bits but the chain requires 65 bits to correctly + * span both chips. Phantom ports 1-7, 9-10 (set0, 3 LEDs + * each) and port 11 (set1, 2 LEDs) pad the chain with + * the remaining 29 bits. + */ + realtek,led-set0-force-port-mask = <0x00000000 0x000006FE>; + realtek,led-set1-force-port-mask = <0x00000000 0x00000800>; + }; + + sfp_gpio_mux: gpio-mux { + compatible = "gpio-mux"; + mux-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>, + <&gpio0 14 GPIO_ACTIVE_HIGH>; + #mux-control-cells = <0>; + idle-state = ; + }; + + sfp1_gpio: sfp-gpio-1 { + compatible = "gpio-line-mux"; + gpio-controller; + #gpio-cells = <2>; + + mux-controls = <&sfp_gpio_mux>; + muxed-gpio = <&gpio0 19 GPIO_ACTIVE_HIGH>; + + gpio-line-names = "SFP1_LOS", "SFP1_MOD_ABS", "SFP1_TX_FAULT"; + gpio-line-mux-states = <0>, <1>, <3>; + }; + + sfp2_gpio: sfp-gpio-2 { + compatible = "gpio-line-mux"; + gpio-controller; + #gpio-cells = <2>; + + mux-controls = <&sfp_gpio_mux>; + muxed-gpio = <&gpio0 27 GPIO_ACTIVE_HIGH>; + + gpio-line-names = "SFP2_LOS", "SFP2_MOD_ABS", "SFP2_TX_FAULT"; + gpio-line-mux-states = <0>, <1>, <3>; + }; + + sfp1: sfp-p1 { + compatible = "sff,sfp"; + i2c-bus = <&i2c0>; + los-gpio = <&sfp1_gpio 0 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&sfp1_gpio 1 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio0 5 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&sfp1_gpio 2 GPIO_ACTIVE_HIGH>; + }; + + sfp2: sfp-p2 { + compatible = "sff,sfp"; + i2c-bus = <&i2c1>; + los-gpio = <&sfp2_gpio 0 GPIO_ACTIVE_HIGH>; + mod-def0-gpio = <&sfp2_gpio 1 GPIO_ACTIVE_LOW>; + tx-disable-gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>; + tx-fault-gpio = <&sfp2_gpio 2 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio0 { + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_disable_jtag>; + + sfp_enable_hog { + gpio-hog; + gpios = <6 GPIO_ACTIVE_LOW>, + <7 GPIO_ACTIVE_LOW>; + output-high; + line-name = "sfp-enable"; + }; + poe_enable_hog { + gpio-hog; + gpios = <10 GPIO_ACTIVE_HIGH>; + output-high; + line-name = "poe-enable"; + }; +}; + +&i2c_mst1 { + status = "okay"; + + i2c0: i2c@0 { + reg = <0>; + }; + + i2c1: i2c@1 { + reg = <1>; + }; + + i2c2: i2c@2 { + reg = <2>; + + lm96000: lm96000@2e { + compatible = "national,lm85"; + reg = <0x2e>; + }; + }; + + /* PoE management MCU sits here */ + i2c3: i2c@3 { + reg = <3>; + }; +}; + +&mdio_ctrl { + pinctrl-names = "default"; + pinctrl-0 = <&pinmux_enable_mdc_mdio_0>, + <&pinmux_enable_mdc_mdio_1>, + <&pinmux_enable_mdc_mdio_2>; +}; + +&mdio_bus0 { + /* AQR813 */ + PHY_C45(0, 8) + PHY_C45(8, 9) + PHY_C45(16, 10) + PHY_C45(24, 11) + PHY_C45(32, 12) + PHY_C45(40, 13) + PHY_C45(48, 14) + PHY_C45(50, 15) +}; + +&mdio_bus1 { + PHY_C45(52, 0) /* AQR113C */ +}; + +&mdio_bus2 { + PHY_C45(53, 8) /* AQR113C */ +}; + +&switch0 { + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + /* Copper ports behind AQR813 */ + SWITCH_PORT_LED(0, 1, 2, 0, usxgmii) + SWITCH_PORT_LED(8, 2, 3, 0, usxgmii) + SWITCH_PORT_LED(16, 3, 4, 0, usxgmii) + SWITCH_PORT_LED(24, 4, 5, 0, usxgmii) + SWITCH_PORT_LED(32, 5, 6, 0, usxgmii) + SWITCH_PORT_LED(40, 6, 7, 0, usxgmii) + SWITCH_PORT_LED(48, 7, 8, 0, usxgmii) + SWITCH_PORT_LED(50, 8, 9, 0, usxgmii) + + /* Copper ports behind AQR113C */ + SWITCH_PORT_LED(52, 9, 10, 0, usxgmii) + SWITCH_PORT_LED(53, 10, 11, 0, usxgmii) + + /* SFP+ ports */ + SWITCH_PORT_SFP(54, 11, 12, 0, 1) + SWITCH_PORT_SFP(55, 12, 13, 0, 2) + + /* CPU port */ + port@56 { + ethernet = <ðernet0>; + reg = <56>; + phy-mode = "internal"; + fixed-link { + speed = <1000>; + full-duplex; + }; + }; + }; +}; + +&port0 { + managed = "in-band-status"; +}; + +&port8 { + managed = "in-band-status"; +}; + +&port16 { + managed = "in-band-status"; +}; + +&port24 { + managed = "in-band-status"; +}; + +&port32 { + managed = "in-band-status"; +}; + +&port40 { + managed = "in-band-status"; +}; + +&port48 { + managed = "in-band-status"; +}; + +&port50 { + managed = "in-band-status"; +}; + +&port52 { + managed = "in-band-status"; +}; + +&port53 { + managed = "in-band-status"; +}; + +&serdes6 { + realtek,pnswap-rx; + realtek,pnswap-tx; +}; + +&serdes7 { + realtek,pnswap-rx; + realtek,pnswap-tx; +}; + +&serdes8 { + realtek,pnswap-rx; + realtek,pnswap-tx; +}; + +&serdes9 { + realtek,pnswap-rx; + realtek,pnswap-tx; +}; + +&serdes10 { + realtek,pnswap-tx; +}; + +&serdes11 { + realtek,pnswap-tx; +}; + +&serdes12 { + realtek,pnswap-tx; +}; + +&serdes13 { + realtek,pnswap-tx; +}; diff --git a/target/linux/realtek/image/rtl931x.mk b/target/linux/realtek/image/rtl931x.mk index 6592a3aa8fb..a824376b0fd 100644 --- a/target/linux/realtek/image/rtl931x.mk +++ b/target/linux/realtek/image/rtl931x.mk @@ -67,3 +67,9 @@ define Device/zyxel_xs1930-12f $(Device/zyxel_xs1930) endef TARGET_DEVICES += zyxel_xs1930-12f + +define Device/zyxel_xs1930-12hp + DEVICE_MODEL := XS1930-12HP + $(Device/zyxel_xs1930) +endef +TARGET_DEVICES += zyxel_xs1930-12hp