]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: add support for Zyxel XGS1930-28HP 23389/head
authorJonas Jelonek <jelonek.jonas@gmail.com>
Thu, 30 Apr 2026 09:13:11 +0000 (09:13 +0000)
committerRobert Marko <robimarko@gmail.com>
Sun, 17 May 2026 11:12:18 +0000 (13:12 +0200)
Add support for the RTL9301-based Zyxel XGS1930-28HP, a 28-port Gigabit
PoE+ switch. The XGS1930 is an EOL Zyxel series of RTL9301-based
switches available with 28 or 52 ports, with and without PoE.

Hardware
========

  - RTL9301 SoC
  - 512 MiB DDR3 RAM
  - 32 MiB SPI-NOR flash
  - 24x 10/100/1000M RJ45 ports
  - 4x 1G/10G SFP+ cages
  - PoE:
    - 802.3af/at on all 24 RJ45 ports
    - 375 W total power budget
  - RTL8231 for port LEDs
  - Front LEDs: PWR, SYS, CLOUD, LOCATOR, PoE usage bar (5 steps)
  - Buttons: 1x "Restore"
  - Console: TTL 3.3V, 115200 8N1, 4-pin header
    - pinout (front to back): GND RX TX -
  - Software chain:
    - Bootbase/stripped-down U-Boot
    - RAS/ZyNOS

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

Single MAC address derived from the board partition. Applied to all
switch ports.

Disclaimer
==========

PoE is not yet supported.

Flashing OpenWrt overwrites ZyNOS. The Bootbase/U-Boot remains intact
and can be used for recovery.

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. If the device runs ZyNOS 5.00, untick "Enhanced firmware integrity
   check sha256sum". Otherwise the upload check will reject the image.

4. Select and upload the factory.bin image and click upgrade.

5. After flashing has finished, reboot the switch. It will now boot
   into OpenWrt.

Initramfs boot
==============

Luckily the switch uses a standard design, thus networking works with
a default hardware profile of RTK U-boot.

1. Connect to the serial console and interrupt the boot process by
   spamming '$' during the DRAM test to drop into Bootbase/U-Boot.

2. Bring up the network:

   > rtk network on

   Use a copper port; the SFP+ cages are likely not usable from the
   bootloader.

3. Load the initramfs image via TFTP:

   > tftpboot 0x82000000 <server>:<image>

4. Run the image (not bootm, the image has no uImage header):

   > go 0x82000000

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

1. Download the stock firmware for the switch from the Zyxel website
   and unzip it; there should be a .bin file with an alphanumeric name.

2. Upload that file to the running OpenWrt instance.

3. Flash it (use -F since the image has no OpenWrt metadata):

   > sysupgrade -F <stock-firmware>.bin

4. Wait for sysupgrade to finish and the switch to reboot. ZyNOS should
  come up again.

Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/23389
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/base-files/lib/upgrade/platform.sh
target/linux/realtek/dts/rtl9301_zyxel_xgs1930-28hp.dts [new file with mode: 0644]
target/linux/realtek/image/rtl930x.mk

index cddf5315b75c46bd5b6347d74ff4f3007ce4de57..549f96d70d2326a065249ce747cfef10c5caa09c 100644 (file)
@@ -44,6 +44,7 @@ platform_do_upgrade() {
        linksys,lgs352c)
                nand_do_upgrade "$1"
                ;;
+       zyxel,xgs1930-28hp|\
        zyxel,xmg1915-10e|\
        zyxel,xmg1915-10ep|\
        zyxel,xs1930-10|\
diff --git a/target/linux/realtek/dts/rtl9301_zyxel_xgs1930-28hp.dts b/target/linux/realtek/dts/rtl9301_zyxel_xgs1930-28hp.dts
new file mode 100644 (file)
index 0000000..13aef60
--- /dev/null
@@ -0,0 +1,427 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later or MIT)
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+#include "rtl930x.dtsi"
+
+/ {
+       compatible = "zyxel,xgs1930-28hp", "realtek,rtl9301-soc";
+       model = "Zyxel XGS1930-28HP";
+
+       aliases {
+               label-mac-device = &ethernet0;
+               led-boot = &led_sys_green;
+               led-running = &led_sys_green;
+               led-failsafe = &led_sys_red;
+               led-upgrade = &led_sys_green;
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x00000000 0x10000000>, /* 256 MiB lowmem */
+                     <0x20000000 0x10000000>; /* 256 MiB highmem */
+       };
+
+       led_set@0 {
+               compatible = "realtek,rtl9300-leds";
+               active-low;
+
+               led_set0 = <RTL93XX_LED_SET_NONE /* PoE led */
+                           RTL93XX_LED_SET_NONE /* PoE led */
+                           (RTL93XX_LED_SET_1G | RTL93XX_LED_SET_LINK | RTL93XX_LED_SET_ACT)
+                           (RTL93XX_LED_SET_100M | RTL93XX_LED_SET_10M | RTL93XX_LED_SET_LINK |
+                            RTL93XX_LED_SET_ACT)>;
+               led_set1 = <(RTL93XX_LED_SET_10G | RTL93XX_LED_SET_LINK | RTL93XX_LED_SET_ACT)
+                           (RTL93XX_LED_SET_1G | RTL93XX_LED_SET_LINK | RTL93XX_LED_SET_ACT)>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinmux_disable_sys_led>;
+
+               led-0 {
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = LED_FUNCTION_POWER;
+                       gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+
+               led-1 {
+                       color = <LED_COLOR_ID_AMBER>;
+                       function = LED_FUNCTION_POWER;
+                       gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
+                       default-state = "off";
+               };
+
+               led_sys_green: led-2 {
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = LED_FUNCTION_STATUS;
+                       gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
+               };
+
+               led_sys_red: led-3 {
+                       color = <LED_COLOR_ID_RED>;
+                       function = LED_FUNCTION_STATUS;
+                       gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
+               };
+
+               led-4 { /* PoE usage - bar 1 (from bottom) */
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = "poe-usage";
+                       function-enumerator = <1>;
+                       gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+               };
+
+               led-5 { /* PoE usage - bar 2 */
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = "poe-usage";
+                       function-enumerator = <2>;
+                       gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+               };
+
+               led-6 { /* PoE usage - bar 3 */
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = "poe-usage";
+                       function-enumerator = <3>;
+                       gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+               };
+
+               led-7 { /* PoE usage - bar 4 */
+                       color = <LED_COLOR_ID_AMBER>;
+                       function = "poe-usage";
+                       function-enumerator = <4>;
+                       gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+               };
+
+               led-8 { /* PoE usage - bar 5 */
+                       color = <LED_COLOR_ID_RED>;
+                       function = "poe-usage";
+                       function-enumerator = <5>;
+                       gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+               };
+
+               led-9 { /* Locator */
+                       color = <LED_COLOR_ID_BLUE>;
+                       function = "locator";
+                       gpios = <&gpio1 35 GPIO_ACTIVE_HIGH>;
+               };
+
+               led-10 { /* Cloud (amber) */
+                       color = <LED_COLOR_ID_AMBER>;
+                       function = "cloud";
+                       gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
+               };
+
+               led-11 { /* Cloud (green) */
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = "cloud";
+                       gpios = <&gpio1 7 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       fan0: gpio-fan {
+               compatible = "gpio-fan";
+               gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
+
+               gpio-fan,speed-map =
+                       <0 0>,  /* slow - GPIO LOW */
+                       <1 1>;  /* fast - GPIO HIGH */
+               #cooling-cells = <2>;
+       };
+
+       keys {
+               compatible = "gpio-keys";
+
+               restore {
+                       label = "restore";
+                       gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
+                       linux,code = <BTN_0>;
+               };
+       };
+
+       sfp0: sfp-p25 {
+               compatible = "sff,sfp";
+               i2c-bus = <&i2c4>;
+               mod-def0-gpio = <&gpio1 1 GPIO_ACTIVE_LOW>;
+               tx-disable-gpio = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+               tx-fault-gpio = <&gpio1 25 GPIO_ACTIVE_HIGH>;
+               los-gpio = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+       };
+       sfp1: sfp-p26 {
+               compatible = "sff,sfp";
+               i2c-bus = <&i2c5>;
+               mod-def0-gpio = <&gpio1 2 GPIO_ACTIVE_LOW>;
+               tx-disable-gpio = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+               tx-fault-gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+               los-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+       };
+       sfp2: sfp-p27 {
+               compatible = "sff,sfp";
+               i2c-bus = <&i2c6>;
+               mod-def0-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
+               tx-disable-gpio = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+               tx-fault-gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+               los-gpio = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+       };
+       sfp3: sfp-p28 {
+               compatible = "sff,sfp";
+               i2c-bus = <&i2c7>;
+               mod-def0-gpio = <&gpio1 11 GPIO_ACTIVE_LOW>;
+               tx-disable-gpio = <&gpio1 32 GPIO_ACTIVE_HIGH>;
+               tx-fault-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+               los-gpio = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+       };
+};
+
+&gpio0 {
+       sfp_enable_hog {
+               gpio-hog;
+               gpios = <7 GPIO_ACTIVE_HIGH>;
+               output-high;
+               line-name = "sfp-enable";
+       };
+
+       poe_mcu_enable_hog {
+               gpio-hog;
+               gpios = <19 GPIO_ACTIVE_HIGH>;
+               output-high;
+               line-name = "poe-mcu-enable";
+       };
+};
+
+&i2c_mst1 {
+       status = "okay";
+
+       i2c0: i2c@0 {
+               reg = <0>;
+               /* PoE MCU sits here at 0x20 */
+       };
+};
+
+&i2c_mst2 {
+       status = "okay";
+
+       i2c4: i2c@4 {
+               reg = <4>;
+       };
+       i2c5: i2c@5 {
+               reg = <5>;
+       };
+       i2c6: i2c@6 {
+               reg = <6>;
+       };
+       i2c7: i2c@7 {
+               reg = <7>;
+       };
+};
+
+&mdio_aux {
+       status = "okay";
+
+       gpio1: gpio@0 {
+               compatible = "realtek,rtl8231";
+               reg = <0>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+               gpio-ranges = <&gpio1 0 0 37>;
+
+               led-controller {
+                       compatible = "realtek,rtl8231-leds";
+                       status = "disabled";
+               };
+
+               poe_enable_hog {
+                       gpio-hog;
+                       gpios = <12 GPIO_ACTIVE_HIGH>;
+                       output-high;
+                       line-name = "poe-enable";
+               };
+       };
+};
+
+/*
+ * GPIO 4 on RTL8231 is the global reset shared by all PHYs across all
+ * MDIO busses. It is intentionally not declared as reset-gpios on any
+ * bus: the MDIO driver / phylink only support a reset GPIO per bus, not
+ * on the parent controller. Attaching it to a single bus would still
+ * reset the PHYs on the other busses as a side effect, leaving their
+ * software state out of sync with the hardware and likely breaking them.
+ */
+
+&mdio_bus0 {
+       PHY_C22(0, 0)
+       PHY_C22(1, 1)
+       PHY_C22(2, 2)
+       PHY_C22(3, 3)
+       PHY_C22(4, 4)
+       PHY_C22(5, 5)
+       PHY_C22(6, 6)
+       PHY_C22(7, 7)
+};
+
+&mdio_bus1 {
+       PHY_C22(8, 8)
+       PHY_C22(9, 9)
+       PHY_C22(10, 10)
+       PHY_C22(11, 11)
+       PHY_C22(12, 12)
+       PHY_C22(13, 13)
+       PHY_C22(14, 14)
+       PHY_C22(15, 15)
+};
+
+&mdio_bus2 {
+       PHY_C22(16, 16)
+       PHY_C22(17, 17)
+       PHY_C22(18, 18)
+       PHY_C22(19, 19)
+       PHY_C22(20, 20)
+       PHY_C22(21, 21)
+       PHY_C22(22, 22)
+       PHY_C22(23, 23)
+};
+
+&spi0 {
+       status = "okay";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <10000000>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       partition@0 {
+                               label = "BootBase";
+                               reg = <0x0 0x80000>;
+                               read-only;
+
+                               nvmem-layout {
+                                       compatible = "fixed-layout";
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       factory_macaddr: macaddr@7fff8 {
+                                               reg = <0x7fff8 0x6>;
+                                       };
+                               };
+                       };
+
+                       /* DbgArea */
+                       partition@80000 {
+                               label = "reserved";
+                               reg = <0x80000 0x20000>;
+                               read-only;
+                       };
+
+                       partition@a0000 {
+                               label = "RomDir2";
+                               reg = <0xa0000 0x120000>;
+                               read-only;
+
+                               /* boot image index at offset 0x151 */
+                               nvmem-layout {
+                                       compatible = "fixed-layout";
+                                       #address-cells = <1>;
+                                       #size-cells = <1>;
+
+                                       boot_selector: boot-selector@151 {
+                                               reg = <0x151 0x1>;
+                                       };
+                               };
+                       };
+
+                       partition@1c0000 {
+                               label = "reserved";
+                               reg = <0x1c0000 0xa0000>;
+                               read-only;
+                       };
+
+                       /* BootBase has dual-image support. Second partition starts at
+                        * 0x1260000 and has same layout as first partition but smaller size
+                        */
+                       partition@260000 {
+                               reg = <0x260000 0x1da0000>;
+                               label = "factory";
+
+                               compatible = "fixed-partitions";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+
+                               partition@0 {
+                                       label = "loader";
+                                       reg = <0x0 0x10000>;
+                               };
+
+                               partition@10000 {
+                                       label = "firmware";
+                                       reg = <0x10000 0x1d90000>;
+                                       compatible = "openwrt,uimage", "denx,uimage";
+                               };
+                       };
+               };
+       };
+};
+
+&switch0 {
+       ethernet-ports {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               SWITCH_PORT_LED(0, 1, 0, 0, qsgmii)
+               SWITCH_PORT_LED(1, 2, 0, 0, qsgmii)
+               SWITCH_PORT_LED(2, 3, 0, 0, qsgmii)
+               SWITCH_PORT_LED(3, 4, 0, 0, qsgmii)
+               SWITCH_PORT_LED(4, 5, 1, 0, qsgmii)
+               SWITCH_PORT_LED(5, 6, 1, 0, qsgmii)
+               SWITCH_PORT_LED(6, 7, 1, 0, qsgmii)
+               SWITCH_PORT_LED(7, 8, 1, 0, qsgmii)
+
+               SWITCH_PORT_LED(8, 9, 2, 0, usxgmii)
+               SWITCH_PORT_LED(9, 10, 2, 0, usxgmii)
+               SWITCH_PORT_LED(10, 11, 2, 0, usxgmii)
+               SWITCH_PORT_LED(11, 12, 2, 0, usxgmii)
+               SWITCH_PORT_LED(12, 13, 2, 0, usxgmii)
+               SWITCH_PORT_LED(13, 14, 2, 0, usxgmii)
+               SWITCH_PORT_LED(14, 15, 2, 0, usxgmii)
+               SWITCH_PORT_LED(15, 16, 2, 0, usxgmii)
+
+               SWITCH_PORT_LED(16, 17, 3, 0, usxgmii)
+               SWITCH_PORT_LED(17, 18, 3, 0, usxgmii)
+               SWITCH_PORT_LED(18, 19, 3, 0, usxgmii)
+               SWITCH_PORT_LED(19, 20, 3, 0, usxgmii)
+               SWITCH_PORT_LED(20, 21, 3, 0, usxgmii)
+               SWITCH_PORT_LED(21, 22, 3, 0, usxgmii)
+               SWITCH_PORT_LED(22, 23, 3, 0, usxgmii)
+               SWITCH_PORT_LED(23, 24, 3, 0, usxgmii)
+
+               SWITCH_PORT_SFP(24, 25, 4, 1, 0)
+               SWITCH_PORT_SFP(25, 26, 6, 1, 1)
+               SWITCH_PORT_SFP(26, 27, 8, 1, 2)
+               SWITCH_PORT_SFP(27, 28, 9, 1, 3)
+
+               port@28 {
+                       reg = <28>;
+                       ethernet = <&ethernet0>;
+                       phy-mode = "internal";
+                       fixed-link {
+                               speed = <1000>;
+                               full-duplex;
+                       };
+               };
+       };
+};
+
+&ethernet0 {
+       nvmem-cells = <&factory_macaddr>;
+       nvmem-cell-names = "mac-address";
+};
index 36fe61111e430dcc534dc0f6b2ab4ed8a9dcf991..acf8a2582d83b6c02de3081942d27e301d8c52c0 100644 (file)
@@ -253,6 +253,17 @@ define Device/zyxel_xgs1250-12-b1
 endef
 TARGET_DEVICES += zyxel_xgs1250-12-b1
 
+define Device/zyxel_xgs1930-28hp
+  SOC := rtl9301
+  DEVICE_MODEL := XGS1930-28HP
+  DEVICE_PACKAGES := kmod-hwmon-gpiofan
+  FLASH_ADDR := 0xb4260000
+  IMAGE_SIZE := 30336k
+  ZYNFW_ALIGN := 0x10000
+  $(Device/zyxel_zynos)
+endef
+TARGET_DEVICES += zyxel_xgs1930-28hp
+
 define Device/zyxel_xmg1915
   SOC := rtl9302
   FLASH_ADDR := 0xb4270000