[openwrt/openwrt] realtek: add support for Linksys LGS310C

LEDE Commits lede-commits at lists.infradead.org
Wed Oct 2 11:15:54 PDT 2024


svanheule pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/d03f3dcf3b2801c0ee8d41506a1da64d3077f19b

commit d03f3dcf3b2801c0ee8d41506a1da64d3077f19b
Author: Markus Stockhausen <markus.stockhausen at gmx.de>
AuthorDate: Sat Sep 14 17:17:44 2024 -0400

    realtek: add support for Linksys LGS310C
    
    Hardware specification
    ----------------------
    
    * RTL8380M SoC, 1 MIPS 4KEc core @ 500MHz
    * 256MB DRAM
    * 32MB NOR Flash
    * 8 x 10/100/1000BASE-T ports
    * 2 x SFP ports
    * Power LED, Fault LED
    * Reset button on front panel
    * UART (115200 8N1) via populated standard pin header marked JP1
    
    TODO: The SFP ports use a shared SCL GPIO that the driver cannot handle.
    The left SFP port (lan9) is defined and fully functional while the laser
    on the right SFP port (lan10) is off by default.
    
    UART pinout
    -----------
    
    [o]ooo|JP1
     | ||`------ GND
     | |`------- RX
     | `-------- TX
     `---------- Vcc (3V3)
    
    Installation using OEM webinterface
    -----------------------------------
    
    1. Make sure you are running OEM firmware in secondary slot
    2. Install squashfs-factory.imag to primary slot by upload via http
    
    Installation using serial interface
    -----------------------------------
    
    1. Press "a" "c" "p" during message "Enter correct key to stop autoboot"
    2. Load image with "upgrade runtime <TFTP IP>:squashfs-sysupgrade.bin" command
    3. Switch to primary slot with "setsys bootpartition 0"
    4. Store config with "savesys"
    5. Boot the image with `boota` command
    
    Dual-boot with stock firmware using writable u-boot-env
    -------------------------------------------------------
    
    From stock to OpenWrt / primary image 1 (CLI as admin):
       - > boot system image1
       - > reboot
    
    From OpenWrt to stock / boot image 2: (shell as root)
       - # fw_setsys bootpartition 1
       - # reboot
    
    Debrick using serial interface
    ------------------------------
    
    1. Press "a" "c" "p" during message "Enter correct key to stop autoboot"
    2. Load vendor image with "upgrade runtime <TFTP IP>:LGS310xxxxx.imag"
    3. switch to primary partition "setsys bootpartition 0"
    4. safe config "savesys"
    
    Further documentation
    ---------------------
    See https://openwrt.org/toh/linksys/lgs352c
    
    It has been developed and tested on device with v1 revision.
    
    Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
    Link: https://github.com/openwrt/openwrt/pull/16068
    [Add missing 'w' in name of firmware partition]
    Signed-off-by: Sander Vanheule <sander at svanheule.net>
---
 scripts/belkin-header.py                           |  94 +++++++++
 scripts/linksys-image.sh                           |  76 ++++++++
 .../linux/realtek/dts/rtl8380_linksys_lgs310c.dts  | 212 +++++++++++++++++++++
 target/linux/realtek/image/Makefile                |  13 ++
 target/linux/realtek/image/rtl838x.mk              |  21 ++
 5 files changed, 416 insertions(+)

diff --git a/scripts/belkin-header.py b/scripts/belkin-header.py
new file mode 100755
index 0000000000..4dc3d2652e
--- /dev/null
+++ b/scripts/belkin-header.py
@@ -0,0 +1,94 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 OpenWrt.org
+#
+# ./belkin-header.py <ImageFileIn> <ImageFileOut> <BelkinHeader> <BelkinModel>
+#
+# This script adds an image header for Belkin devices. As of now only Realtek
+# based switches of the Linksys LGS3xxC/LGS3xxMPC series are known to use this
+# format. It resembles a U-Boot legacy format image header, all data in network
+# byte order (aka natural aka big endian).
+#
+# Known values for BelkinHeader are
+#
+# 0x07800001 : RTL838x based switch
+# 0x07600001 : RTL93xx based switch
+#
+# Known values for BelkinModel are
+#
+# BKS-RTL83xx : RTL838x based switch
+# BKS-RTL93xx : RTL93xx based switch
+
+import argparse
+import os
+import zlib
+import array
+import sys
+import time
+
+VERSION1 = 1
+VERSION2 = 1
+VERSION3 = 2
+VERSION4 = 2
+COMPANY = "belkin"
+MODULE = "IMG"
+
+def xcrc32(buf):
+    return (0xffffffff - zlib.crc32(buf, 0xffffffff)).to_bytes(4, 'big')
+
+def encode_model(model):
+    map = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"
+    code = bytearray()
+
+    code.append(map.index(model[:1]))
+    model = model[1:]
+    model = model + " " * (3 - len(model) % 4)
+
+    while model != "":
+        b1 = map.index(model[0:1])
+        b2 = map.index(model[1:2])
+        b3 = map.index(model[2:3])
+        b4 = map.index(model[3:4])
+        model = model[4:]
+
+        code.append(b1 << 2 | b2 >> 4)
+        code.append((b2 & 0xf) << 4 | b3 >> 2)
+        code.append((b3 & 0x3) << 6 | b4)
+
+    return code
+
+def create_header(buf, belkin_header, belkin_model):
+    head = bytearray(32)
+
+    head[0:4] = int(belkin_header, 0).to_bytes(4, 'big')
+    head[8:12] = int(time.time()).to_bytes(4, 'big')
+    head[12:16] = len(buf).to_bytes(4, 'big')
+    head[24:28] = xcrc32(buf)
+    head[28:29] = VERSION1.to_bytes(1)
+    head[29:30] = VERSION2.to_bytes(1)
+    head[30:31] = VERSION3.to_bytes(1)
+    head[31:32] = VERSION4.to_bytes(1)
+    head[16:16 + len(COMPANY)] = bytes(COMPANY,'ascii')
+
+    mod = MODULE + "-{:1d}.{:02d}.{:02d}.{:02d}".format(VERSION1, VERSION2, VERSION3, VERSION4)
+    head.extend(bytes(mod,'ascii'))
+    head.append(0x00)
+    head.extend(encode_model(belkin_model))
+    head.extend(bytes([0x00] * (64 - len(head))))
+
+    head[4:8] = xcrc32(head)
+
+    return head
+
+parser = argparse.ArgumentParser(description='Generate Belkin header.')
+parser.add_argument('source', type=argparse.FileType('r+b'))
+parser.add_argument('dest', type=argparse.FileType('wb'))
+parser.add_argument('belkin_header')
+parser.add_argument('belkin_model')
+args = parser.parse_args()
+
+buf = bytearray(args.source.read())
+head = create_header(buf, args.belkin_header, args.belkin_model)
+args.dest.write(head)
+args.dest.write(buf)
diff --git a/scripts/linksys-image.sh b/scripts/linksys-image.sh
new file mode 100755
index 0000000000..f0398662fb
--- /dev/null
+++ b/scripts/linksys-image.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2024 OpenWrt.org
+#
+# This script creates a tar file for the Linksys switches of the LGS3xxC/LGS3xxMPC
+# series. It contains not only the OpenWrt firmware but additional scripts that
+# are needed for the upgrade.
+#
+# ./linksys-image.py <ImageFile> <ImageFileOut> <LinksysModel>
+#
+# Known values for LinksysModel are currently
+#
+# LGS310MPC		60402010
+# LGS310C		60402060
+# LGS328PC		60401070
+# LGS328PC(RTL8218D)	60401080
+# LGS310MPCv2		60402090
+# LGS328MPC		60412020
+# LGS328C		60412040
+# LGS328MPCv2		60412060
+# LGS352MPC		60422030
+# LGS352C		60422050
+# LGS352MPCv2		60422070
+
+# The check script that verifies if the images matches the hardware model
+gen_imagecheck() {
+	echo '#!/bin/sh'
+	echo 'if [ "$1" = "'${1}'" ]; then'
+	echo 'echo 0'
+	echo 'else'
+	echo 'echo 1'
+	echo 'fi'
+}
+
+# Generic attributes
+gen_fwinfo() {
+	echo 'FW_VERSION=1.01.100\nBOOT_VERSION=01.00.01'
+}
+
+# The central upgrade script. It allows to install OpenWrt only to first partition.
+gen_imageupgrade() {
+	echo '#!/bin/sh'
+	echo 'flash_bank=65536'
+	echo 'filesize=`stat --format=%s ./series_vmlinux.bix`'
+	echo 'num_bank=`expr \( ${filesize} + ${flash_bank} - 1 \) / ${flash_bank}`'
+	echo 'filesize_bank=`expr ${num_bank} \* ${flash_bank}`'
+	echo 'case $1 in'
+	echo '1)'
+	echo 'mtd_debug erase $2 0 ${filesize_bank} >/dev/null 2>&1'
+	echo 'mtd_debug write $2 0 ${filesize} ./series_vmlinux.bix >/dev/null 2>&1'
+	echo 'mtd_debug read $2 0 100 image1.img >/dev/null 2>&1'
+	echo 'CreateImage -r ./image1.img > /tmp/app/image1.txt'
+	echo 'echo 0'
+	echo ';;'
+	echo '*)'
+	echo 'echo 1'
+	echo 'esac'
+}
+
+tmpdir="$( mktemp -d 2> /dev/null )"
+imgdir=$tmpdir/image
+mkdir $imgdir
+
+gen_imagecheck $3 > $imgdir/iss_imagecheck.sh
+gen_imageupgrade > $imgdir/iss_imageupgrade.sh
+gen_fwinfo > $imgdir/firmware_information.txt
+
+chmod +x $imgdir/iss_imagecheck.sh
+chmod +x $imgdir/iss_imageupgrade.sh
+
+cp $1 $imgdir/series_vmlinux.bix
+
+tar cf $2 -C $tmpdir image/
+
+rm -rf $tmpdir
diff --git a/target/linux/realtek/dts/rtl8380_linksys_lgs310c.dts b/target/linux/realtek/dts/rtl8380_linksys_lgs310c.dts
new file mode 100644
index 0000000000..08ef740399
--- /dev/null
+++ b/target/linux/realtek/dts/rtl8380_linksys_lgs310c.dts
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/gpio.h>
+
+#include "rtl838x.dtsi"
+
+/ {
+	compatible = "linksys,lgs310c", "realtek,rtl838x-soc";
+	model = "Linksys LGS310C";
+
+	aliases {
+		led-boot = &led_power;
+		led-failsafe = &led_fault;
+		led-running = &led_power;
+		led-upgrade = &led_power;
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x10000000>;
+	};
+
+	leds: leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinmux_disable_sys_led>;
+		compatible = "gpio-leds";
+
+		led_power: led-0 {
+			function = LED_FUNCTION_POWER;
+			color = <LED_COLOR_ID_GREEN>;
+			gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
+		};
+
+		led_fault: led-1 {
+			function = LED_FUNCTION_FAULT;
+			color = <LED_COLOR_ID_AMBER>;
+			gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
+		};
+
+	};
+
+	/* i2c of the left SFP cage: port 9 */
+	i2c0: i2c-gpio-0 {
+		compatible = "i2c-gpio";
+		sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+		scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+		i2c-gpio,delay-us = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	sfp0: sfp-p9 {
+		compatible = "sff,sfp";
+		i2c-bus = <&i2c0>;
+		los-gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+		mod-def0-gpio = <&gpio1 12 GPIO_ACTIVE_LOW>;
+		tx-disable-gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+	};
+
+	/* i2c of the right SFP cage: port 10 */
+	i2c1: i2c-gpio-1 {
+		compatible = "i2c-gpio";
+		sda-gpios = <&gpio1 7 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+/*
+ * ports 9 & 10 use a shared SCL, and are currently not usable in parallel
+ * So for now disable the SCL on the second port.
+ *
+ *		scl-gpios = <&gpio1 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ */
+		i2c-gpio,scl-open-drain;
+		i2c-gpio,delay-us = <2>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
+	sfp1: sfp-p10 {
+		compatible = "sff,sfp";
+		i2c-bus = <&i2c1>;
+		los-gpio = <&gpio1 14 GPIO_ACTIVE_HIGH>;
+		mod-def0-gpio = <&gpio1 21 GPIO_ACTIVE_LOW>;
+		tx-disable-gpio = <&gpio1 13 GPIO_ACTIVE_HIGH>;
+	};
+
+	keys {
+		compatible = "gpio-keys";
+
+		reset {
+			label = "reset";
+			gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+	};
+
+	gpio1: rtl8231-gpio {
+		compatible = "realtek,rtl8231-gpio";
+		#gpio-cells = <2>;
+		gpio-controller;
+		indirect-access-bus-id = <0>;
+	};
+};
+
+&spi0 {
+	status = "okay";
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition at 0 {
+				label = "u-boot";
+				reg = <0x00000000 0x80000>;
+				read-only;
+			};
+			partition at 80000 {
+				label = "u-boot-env";
+				reg = <0x00080000 0x10000>;
+			};
+			partition at 90000 {
+				label = "u-boot-env2";
+				reg = <0x00090000 0x10000>;
+			};
+			partition at a0000 {
+				label = "jffs2";
+				reg = <0x000a0000 0x500000>;
+			};
+			partition at 5a0000 {
+				label = "firmware";
+				compatible = "openwrt,uimage";
+				reg = <0x005a0000 0xd30000>;
+			};
+			partition at 2d0000 {
+				label = "kernel2";
+				reg = <0x012d0000 0xd30000>;
+			};
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+};
+
+&ethernet0 {
+	mdio: mdio-bus {
+		compatible = "realtek,rtl838x-mdio";
+		regmap = <&ethernet0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		INTERNAL_PHY(8)
+		INTERNAL_PHY(9)
+		INTERNAL_PHY(10)
+		INTERNAL_PHY(11)
+		INTERNAL_PHY(12)
+		INTERNAL_PHY(13)
+		INTERNAL_PHY(14)
+		INTERNAL_PHY(15)
+		INTERNAL_PHY(24)
+		INTERNAL_PHY(26)
+	};
+};
+
+&switch0 {
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		SWITCH_PORT(8, 1, internal)
+		SWITCH_PORT(9, 2, internal)
+		SWITCH_PORT(10, 3, internal)
+		SWITCH_PORT(11, 4, internal)
+		SWITCH_PORT(12, 5, internal)
+		SWITCH_PORT(13, 6, internal)
+		SWITCH_PORT(14, 7, internal)
+		SWITCH_PORT(15, 8, internal)
+
+		port at 24 {
+			reg = <24>;
+			label = "lan9";
+			phy-handle = <&phy24>;
+			phy-mode = "1000base-x";
+			managed = "in-band-status";
+			sfp = <&sfp0>;
+		};
+
+		port at 26 {
+			reg = <26>;
+			label = "lan10";
+			phy-handle = <&phy26>;
+			phy-mode = "1000base-x";
+			managed = "in-band-status";
+			sfp = <&sfp1>;
+		};
+
+		port at 28 {
+			ethernet = <&ethernet0>;
+			reg = <28>;
+			phy-mode = "internal";
+			fixed-link {
+				speed = <1000>;
+				full-duplex;
+			};
+		};
+	};
+};
diff --git a/target/linux/realtek/image/Makefile b/target/linux/realtek/image/Makefile
index 9eed710480..19fab03dba 100644
--- a/target/linux/realtek/image/Makefile
+++ b/target/linux/realtek/image/Makefile
@@ -6,6 +6,8 @@ include $(INCLUDE_DIR)/image.mk
 KERNEL_LOADADDR = 0x80100000
 
 DEVICE_VARS += \
+	BELKIN_HEADER \
+	BELKIN_MODEL \
         CAMEO_BOARD_MODEL \
         CAMEO_BOARD_VERSION \
         CAMEO_CUSTOMER_SIGNATURE \
@@ -14,6 +16,7 @@ DEVICE_VARS += \
         CAMEO_ROOTFS_PART \
         H3C_DEVICE_ID \
         H3C_PRODUCT_ID \
+	LINKSYS_HEADER \
         ZYXEL_VERS
 
 define Build/zyxel-vers
@@ -71,6 +74,16 @@ define Build/h3c-vfs
 	mv $@.new $@
 endef
 
+define Build/belkin-header
+	$(SCRIPT_DIR)/belkin-header.py $(@) $(@).new $(BELKIN_HEADER) ${BELKIN_MODEL}
+	mv $@.new $@
+endef
+
+define Build/linksys-image
+	$(SCRIPT_DIR)/linksys-image.sh $(@) $(@).new $(LINKSYS_MODEL)
+	mv $@.new $@
+endef
+
 define Device/Default
   PROFILES = Default
   KERNEL := \
diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk
index c8e1c481ec..01397af931 100644
--- a/target/linux/realtek/image/rtl838x.mk
+++ b/target/linux/realtek/image/rtl838x.mk
@@ -162,6 +162,27 @@ define Device/iodata_bsh-g24mb
 endef
 TARGET_DEVICES += iodata_bsh-g24mb
 
+define Device/linksys_lgs310c
+  SOC := rtl8380
+  IMAGE_SIZE := 13504k
+  DEVICE_VENDOR := Linksys
+  DEVICE_MODEL := LGS310C
+  BELKIN_MODEL := BKS-RTL83xx
+  BELKIN_HEADER := 0x07800001
+  LINKSYS_MODEL := 60402060
+  IMAGES += factory.imag
+  IMAGE/factory.imag := \
+	append-kernel | \
+	pad-to 64k | \
+	append-rootfs | \
+	pad-rootfs | \
+	check-size | \
+	append-metadata | \
+	linksys-image | \
+	belkin-header
+endef
+TARGET_DEVICES += linksys_lgs310c
+
 # "NGE" refers to the uImage magic
 define Device/netgear_nge
   KERNEL := \




More information about the lede-commits mailing list