From: Ahmed Naseef Date: Sun, 12 Jul 2026 14:50:05 +0000 (+0400) Subject: econet: en7528: manage the on-die MT7530 switch with DSA X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=HEAD;p=thirdparty%2Fopenwrt.git econet: en7528: manage the on-die MT7530 switch with DSA The EN7528 integrates an MT7530 Gigabit switch, memory-mapped in the SoC register space like the built-in switches of the MediaTek MT7988 and Airoha EN7581/AN7583 SoCs. Its chip revision register reads 0x7530, so unlike those three it is a genuine MT7530 core rather than an MT7531 derivative. Until now the out-of-tree econet-eth driver programmed it as a flat "dumb switch" that simply bridged the four LAN ports together and exposed them as a single eth0. Hand it to the upstream mt7530 DSA driver instead, so the ports come up as managed user ports lan1-lan4. - Add an ID_EN7528 variant to the mt7530 driver, bound through the MMIO glue with the "econet,en7528-switch" compatible. It reuses mt7988_setup() and the indirect PHY accessors, but selects the CPU port through the MT7530-style MFC register rather than the MT7531 CFC one, and describes the CPU port as a fixed 1000FDX link to the SoC MAC. The LAN GPHYs advertise EEE, but negotiating it drops frames with some link partners, so the LPI capabilities are left empty and phylink keeps EEE off. - The frame engine and the switch are adjacent but separate blocks. The ethernet node used to describe a single 64K window covering both, which overlaps the switch node and makes the two drivers fight over the region. Size it to the frame engine alone (0x8000) and give the switch its own node, so both keep an exclusive claim: 1fb50000-1fb57fff : 1fb50000.ethernet 1fb58000-1fb5ffff : 1fb58000.switch The GSW reset moves to the switch node with it. - econet-eth acts as the DSA conduit. It derives from the size of its own register resource whether the window still covers the switch, and when it does not, skips the dumb-switch setup and the switch source-MAC write. The econet-eth driver now carries this support, so bump PKG_SOURCE_VERSION to pull it in. EN751221 and EN751627 keep the full window and are unaffected. - Enable the switch on the DASAN H660GM-A. The two variants share a board, but their sockets are not numbered the same way: LAN1 is switch port 1 on the Airtel unit and port 4 on the generic one, so the port labels are assigned per board .dts. Signed-off-by: Ahmed Naseef Link: https://github.com/openwrt/openwrt/pull/24199 Signed-off-by: Jonas Jelonek --- diff --git a/package/kernel/econet-eth/Makefile b/package/kernel/econet-eth/Makefile index 356d006d293..f3c7c37d7ef 100644 --- a/package/kernel/econet-eth/Makefile +++ b/package/kernel/econet-eth/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/cjdelisle/econet_eth.git -PKG_MIRROR_HASH:=b0136345b176f714e28397b8feba372234e9c87fb33879db2e413fb22c1c09c4 -PKG_SOURCE_DATE:=2026-01-27 -PKG_SOURCE_VERSION:=1db74f832563865680ae0b1c25c0a213bbcdf92c +PKG_MIRROR_HASH:=ea8402a4eba5e593a799f63ee4793486520837f0f659f34962e436eefd7c1945 +PKG_SOURCE_DATE:=2026-07-21 +PKG_SOURCE_VERSION:=3ba0abe30cfa0dc1e76e41218140bc061be131fb include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/package.mk diff --git a/target/linux/econet/base-files/etc/board.d/02_network b/target/linux/econet/base-files/etc/board.d/02_network index 748154eb9be..34d0fb35398 100644 --- a/target/linux/econet/base-files/etc/board.d/02_network +++ b/target/linux/econet/base-files/etc/board.d/02_network @@ -7,8 +7,13 @@ econet_setup_interfaces() local board="$1" case "$board" in + dasan,h660gm-a-airtel|\ + dasan,h660gm-a-generic|\ + econet,en7528-generic) + ucidef_set_interface_lan "lan1 lan2 lan3 lan4" + ;; *) - # econet lacks DSA support now + # The remaining boards have no DSA switch driver yet. ucidef_set_interface_lan "eth0" ;; esac diff --git a/target/linux/econet/dts/en7528.dtsi b/target/linux/econet/dts/en7528.dtsi index bbd7f9786d8..411f92c9bd1 100644 --- a/target/linux/econet/dts/en7528.dtsi +++ b/target/linux/econet/dts/en7528.dtsi @@ -251,7 +251,7 @@ ethernet: ethernet@1fb50000 { compatible = "econet,en7528-eth"; - reg = <0x1fb50000 0x10000>; + reg = <0x1fb50000 0x8000>; #address-cells = <1>; #size-cells = <0>; @@ -263,16 +263,15 @@ resets = <&scu EN7523_FE_RST>, <&scu EN7523_FE_PDMA_RST>, <&scu EN7523_FE_QDMA_RST>, - <&scu EN7523_GSW_RST>, <&scu EN7523_XPON_MAC_RST>, <&scu EN7523_XPON_PHY_RST>; - reset-names = "fe", "qdma0", "qdma1", "gsw", + reset-names = "fe", "qdma0", "qdma1", "xpon-mac", "xpon-phy"; gmac0: mac@0 { compatible = "econet,eth-mac"; reg = <0>; - phy-mode = "trgmii"; + phy-mode = "internal"; status = "disabled"; fixed-link { @@ -289,4 +288,85 @@ status = "disabled"; }; }; + + switch: ethernet-switch@1fb58000 { + compatible = "econet,en7528-switch"; + reg = <0x1fb58000 0x8000>; + resets = <&scu EN7523_GSW_RST>; + + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + + ethernet-ports { + #address-cells = <1>; + #size-cells = <0>; + + gsw_port1: ethernet-port@1 { + reg = <1>; + phy-mode = "internal"; + phy-handle = <&gsw_phy1>; + status = "disabled"; + }; + + gsw_port2: ethernet-port@2 { + reg = <2>; + phy-mode = "internal"; + phy-handle = <&gsw_phy2>; + status = "disabled"; + }; + + gsw_port3: ethernet-port@3 { + reg = <3>; + phy-mode = "internal"; + phy-handle = <&gsw_phy3>; + status = "disabled"; + }; + + gsw_port4: ethernet-port@4 { + reg = <4>; + phy-mode = "internal"; + phy-handle = <&gsw_phy4>; + status = "disabled"; + }; + + ethernet-port@6 { + reg = <6>; + ethernet = <&gmac0>; + phy-mode = "internal"; + + fixed-link { + speed = <1000>; + full-duplex; + pause; + }; + }; + }; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + gsw_phy1: ethernet-phy@9 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <9>; + }; + + gsw_phy2: ethernet-phy@a { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <10>; + }; + + gsw_phy3: ethernet-phy@b { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <11>; + }; + + gsw_phy4: ethernet-phy@c { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <12>; + }; + }; + }; }; diff --git a/target/linux/econet/dts/en7528_dasan_h660gm-a-airtel.dts b/target/linux/econet/dts/en7528_dasan_h660gm-a-airtel.dts index a03ca91217c..cb30326add3 100644 --- a/target/linux/econet/dts/en7528_dasan_h660gm-a-airtel.dts +++ b/target/linux/econet/dts/en7528_dasan_h660gm-a-airtel.dts @@ -68,3 +68,20 @@ }; }; }; + +/* Sockets are numbered in switch port order: LAN1 is port 1. */ +&gsw_port1 { + label = "lan1"; +}; + +&gsw_port2 { + label = "lan2"; +}; + +&gsw_port3 { + label = "lan3"; +}; + +&gsw_port4 { + label = "lan4"; +}; diff --git a/target/linux/econet/dts/en7528_dasan_h660gm-a-generic.dts b/target/linux/econet/dts/en7528_dasan_h660gm-a-generic.dts index 1406e76c694..8e536383a4c 100644 --- a/target/linux/econet/dts/en7528_dasan_h660gm-a-generic.dts +++ b/target/linux/econet/dts/en7528_dasan_h660gm-a-generic.dts @@ -106,3 +106,20 @@ }; }; }; + +/* Sockets are numbered in reverse switch port order: LAN1 is port 4. */ +&gsw_port1 { + label = "lan4"; +}; + +&gsw_port2 { + label = "lan3"; +}; + +&gsw_port3 { + label = "lan2"; +}; + +&gsw_port4 { + label = "lan1"; +}; diff --git a/target/linux/econet/dts/en7528_dasan_h660gm-a.dtsi b/target/linux/econet/dts/en7528_dasan_h660gm-a.dtsi index bd190167025..ed547b7c5b2 100644 --- a/target/linux/econet/dts/en7528_dasan_h660gm-a.dtsi +++ b/target/linux/econet/dts/en7528_dasan_h660gm-a.dtsi @@ -147,6 +147,31 @@ nvmem-cell-names = "mac-address"; }; +&switch { + status = "okay"; +}; + +/* + * The switch ports are wired to the same GPHYs on every H660GM-A, but the + * physical sockets are not numbered the same way on all of them, so the + * port labels are assigned in the board .dts files. + */ +&gsw_port1 { + status = "okay"; +}; + +&gsw_port2 { + status = "okay"; +}; + +&gsw_port3 { + status = "okay"; +}; + +&gsw_port4 { + status = "okay"; +}; + &nand { status = "okay"; econet,bmt; diff --git a/target/linux/econet/dts/en7528_generic.dts b/target/linux/econet/dts/en7528_generic.dts index 086d0d36b4e..54019baa356 100644 --- a/target/linux/econet/dts/en7528_generic.dts +++ b/target/linux/econet/dts/en7528_generic.dts @@ -36,6 +36,30 @@ status = "okay"; }; +&switch { + status = "okay"; +}; + +&gsw_port1 { + label = "lan1"; + status = "okay"; +}; + +&gsw_port2 { + label = "lan2"; + status = "okay"; +}; + +&gsw_port3 { + label = "lan3"; + status = "okay"; +}; + +&gsw_port4 { + label = "lan4"; + status = "okay"; +}; + &nand { status = "okay"; diff --git a/target/linux/econet/en7528/config-6.18 b/target/linux/econet/en7528/config-6.18 index cef1186274c..6446055d962 100644 --- a/target/linux/econet/en7528/config-6.18 +++ b/target/linux/econet/en7528/config-6.18 @@ -52,8 +52,10 @@ CONFIG_EARLY_PRINTK_8250=y CONFIG_ECONET=y CONFIG_ECONET_EN751221_TIMER=y CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_FIXED_PHY=y CONFIG_FS_IOMAP=y CONFIG_FUNCTION_ALIGNMENT=0 +CONFIG_FWNODE_MDIO=y CONFIG_FW_LOADER_PAGED_BUF=y CONFIG_FW_LOADER_SYSFS=y CONFIG_GENERIC_ALLOCATOR=y @@ -81,6 +83,7 @@ CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_CDEV=y CONFIG_GPIO_EN7523=y CONFIG_GPIO_GENERIC=y +CONFIG_GRO_CELLS=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y CONFIG_HAS_IOMEM=y @@ -101,6 +104,8 @@ CONFIG_LIBFDT=y CONFIG_LOCK_DEBUGGING_SUPPORT=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y +CONFIG_MDIO_BUS=y +# CONFIG_MEDIATEK_GE_SOC_PHY is not set CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y CONFIG_MIPS=y @@ -135,9 +140,16 @@ CONFIG_MTD_UBI_BLOCK=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_NEED_DMA_MAP_STATE=y CONFIG_NEED_SRCU_NMI_SAFE=y +CONFIG_NET_DEVLINK=y +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MT7530=y +# CONFIG_NET_DSA_MT7530_MDIO is not set +CONFIG_NET_DSA_MT7530_MMIO=y +CONFIG_NET_DSA_TAG_MTK=y CONFIG_NET_EGRESS=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_INGRESS=y +CONFIG_NET_SELFTESTS=y CONFIG_NET_XGRESS=y CONFIG_NLS=y CONFIG_NR_CPUS=4 @@ -151,6 +163,7 @@ CONFIG_OF_FLATTREE=y CONFIG_OF_GPIO=y CONFIG_OF_IRQ=y CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y CONFIG_PADATA=y CONFIG_PAGE_BLOCK_MAX_ORDER=11 CONFIG_PAGE_POOL=y @@ -165,6 +178,9 @@ CONFIG_PCI_MSI=y CONFIG_PCI_MSI_ARCH_FALLBACKS=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y CONFIG_PHY_EN7528_PCIE=y CONFIG_PHY_EN7528_USB=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y @@ -173,6 +189,7 @@ CONFIG_QUEUED_SPINLOCKS=y CONFIG_RANDSTRUCT_NONE=y CONFIG_RATIONAL=y CONFIG_REGMAP=y +CONFIG_REGMAP_IRQ=y CONFIG_REGMAP_MMIO=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y @@ -195,6 +212,7 @@ CONFIG_SPI_AIROHA_SNFI=y CONFIG_SPI_MASTER=y CONFIG_SPI_MEM=y CONFIG_SPLIT_PTE_PTLOCKS=y +CONFIG_SWPHY=y CONFIG_SYNC_R4K=y CONFIG_SYSCTL_EXCEPTION_TRACE=y CONFIG_SYS_HAS_CPU_MIPS32_R1=y diff --git a/target/linux/econet/patches-6.18/781-v7.3-net-dsa-mt7530-add-en7528-support.patch b/target/linux/econet/patches-6.18/781-v7.3-net-dsa-mt7530-add-en7528-support.patch new file mode 100644 index 00000000000..b6e673060d3 --- /dev/null +++ b/target/linux/econet/patches-6.18/781-v7.3-net-dsa-mt7530-add-en7528-support.patch @@ -0,0 +1,144 @@ +From 8c7dfabd860ab0a6dd771c2bac7b7599eb369a4f Mon Sep 17 00:00:00 2001 +From: Ahmed Naseef +Date: Thu, 9 Jul 2026 21:29:45 +0400 +Subject: [PATCH] net: dsa: mt7530: add EN7528 support + +The EcoNet EN7528 SoC integrates an MT7530 switch (the chip revision +register reads 0x7530), memory-mapped in the SoC register space and +reached through the same MMIO glue used for the built-in switches of the +MediaTek MT7988 and Airoha EN7581/AN7583 SoCs. Its reset sequence and its +PHY indirect access registers are the same as on those switches, so add +an ID_EN7528 variant bound with the "econet,en7528-switch" compatible, +reusing mt7988_setup() and the indirect PHY accessors. + +The switch core, however, is an MT7530 and not an MT7531 derivative: the +CPU port to trap frames to is set through the MT7530-style CPU_EN / +CPU_PORT fields of the MFC register rather than the MT7531 CFC register, +so add it to the MT7530 handling in mt753x_conduit_state_change(). For the +same reason the MT7530 mirror and force-mode register layouts already +apply to it as the default of the MT753X_*() macros. + +The four user ports (1-4) are connected to integrated Gigabit PHYs at +MDIO addresses 9-12 of the switch internal MDIO bus. The CPU port (port +6) is connected to the SoC Ethernet MAC at a fixed 1000 Mbps full duplex +link, so the port capabilities cannot be shared with the MT7988 and +EN7581 switches, whose CPU ports run at 10 Gbps. + +The LAN GPHYs advertise EEE by default, but negotiating EEE with some +link partners results in an unstable link with dropped frames. Leave the +LPI capabilities empty for the EN7528 so that phylink disables EEE on +these PHYs and refuses to enable it from userspace. + +Signed-off-by: Ahmed Naseef +--- a/drivers/net/dsa/mt7530-mmio.c ++++ b/drivers/net/dsa/mt7530-mmio.c +@@ -13,6 +13,7 @@ + static const struct of_device_id mt7988_of_match[] = { + { .compatible = "airoha,an7583-switch", .data = &mt753x_table[ID_AN7583], }, + { .compatible = "airoha,en7581-switch", .data = &mt753x_table[ID_EN7581], }, ++ { .compatible = "econet,en7528-switch", .data = &mt753x_table[ID_EN7528], }, + { .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], }, + { /* sentinel */ }, + }; +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2847,6 +2847,30 @@ static void en7581_mac_port_get_caps(str + } + } + ++static void en7528_mac_port_get_caps(struct dsa_switch *ds, int port, ++ struct phylink_config *config) ++{ ++ switch (port) { ++ /* Ports which are connected to switch PHYs. There is no MII pinout. */ ++ case 1 ... 4: ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ ++ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD; ++ break; ++ ++ /* Port 6 is connected to SoC's GMAC at 1000 Mbps full duplex. There ++ * is no MII pinout. ++ */ ++ case 6: ++ __set_bit(PHY_INTERFACE_MODE_INTERNAL, ++ config->supported_interfaces); ++ ++ config->mac_capabilities |= MAC_1000FD; ++ break; ++ } ++} ++ + static void + mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode, + phy_interface_t interface) +@@ -3036,17 +3060,24 @@ static void mt753x_phylink_get_caps(stru + struct phylink_config *config) + { + struct mt7530_priv *priv = ds->priv; +- u32 eeecr; + + config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE; + +- config->lpi_capabilities = MAC_100FD | MAC_1000FD | MAC_2500FD; +- +- eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port)); +- /* tx_lpi_timer should be in microseconds. The time units for +- * LPI threshold are unspecified. ++ /* The EN7528 GPHYs report EEE capability, but negotiating EEE with ++ * common link partners (e.g. Realtek GbE NICs) results in an unstable ++ * link with dropped frames. Leave the LPI capabilities empty so that ++ * phylink disables EEE on these PHYs and refuses to enable it from ++ * userspace. + */ +- config->lpi_timer_default = FIELD_GET(LPI_THRESH_MASK, eeecr); ++ if (priv->id != ID_EN7528) { ++ u32 eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port)); ++ ++ config->lpi_capabilities = MAC_100FD | MAC_1000FD | MAC_2500FD; ++ /* tx_lpi_timer should be in microseconds. The time units for ++ * LPI threshold are unspecified. ++ */ ++ config->lpi_timer_default = FIELD_GET(LPI_THRESH_MASK, eeecr); ++ } + + priv->info->mac_port_get_caps(ds, port, config); + } +@@ -3174,7 +3205,8 @@ mt753x_conduit_state_change(struct dsa_s + * forwarded to the numerically smallest CPU port whose conduit + * interface is up. + */ +- if (priv->id != ID_MT7530 && priv->id != ID_MT7621) ++ if (priv->id != ID_MT7530 && priv->id != ID_MT7621 && ++ priv->id != ID_EN7528) + return; + + mask = BIT(cpu_dp->index); +@@ -3377,6 +3409,16 @@ const struct mt753x_info mt753x_table[] + .phy_write_c45 = mt7531_ind_c45_phy_write, + .mac_port_get_caps = en7581_mac_port_get_caps, + }, ++ [ID_EN7528] = { ++ .id = ID_EN7528, ++ .pcs_ops = &mt7530_pcs_ops, ++ .sw_setup = mt7988_setup, ++ .phy_read_c22 = mt7531_ind_c22_phy_read, ++ .phy_write_c22 = mt7531_ind_c22_phy_write, ++ .phy_read_c45 = mt7531_ind_c45_phy_read, ++ .phy_write_c45 = mt7531_ind_c45_phy_write, ++ .mac_port_get_caps = en7528_mac_port_get_caps, ++ }, + }; + EXPORT_SYMBOL_GPL(mt753x_table); + +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -21,6 +21,7 @@ enum mt753x_id { + ID_MT7988 = 3, + ID_EN7581 = 4, + ID_AN7583 = 5, ++ ID_EN7528 = 6, + }; + + #define NUM_TRGMII_CTRL 5