]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
econet: en7528: manage the on-die MT7530 switch with DSA main master 24199/head
authorAhmed Naseef <naseefkm@gmail.com>
Sun, 12 Jul 2026 14:50:05 +0000 (18:50 +0400)
committerJonas Jelonek <jelonek.jonas@gmail.com>
Fri, 31 Jul 2026 07:35:13 +0000 (09:35 +0200)
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 <naseefkm@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/24199
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
package/kernel/econet-eth/Makefile
target/linux/econet/base-files/etc/board.d/02_network
target/linux/econet/dts/en7528.dtsi
target/linux/econet/dts/en7528_dasan_h660gm-a-airtel.dts
target/linux/econet/dts/en7528_dasan_h660gm-a-generic.dts
target/linux/econet/dts/en7528_dasan_h660gm-a.dtsi
target/linux/econet/dts/en7528_generic.dts
target/linux/econet/en7528/config-6.18
target/linux/econet/patches-6.18/781-v7.3-net-dsa-mt7530-add-en7528-support.patch [new file with mode: 0644]

index 356d006d293c3494186df3e8b394cdfe57a9b626..f3c7c37d7ef414f354cfb3832601ef1d972ab1e8 100644 (file)
@@ -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
index 748154eb9be1b34f5636be7c962ff514dde5c827..34d0fb3539869ebe46b035e80c07162e4304ba3b 100644 (file)
@@ -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
index bbd7f9786d82387f3b44d46394fca10b22b20a90..411f92c9bd1394a4504a4af77af925e95610e585 100644 (file)
 
        ethernet: ethernet@1fb50000 {
                compatible = "econet,en7528-eth";
-               reg = <0x1fb50000 0x10000>;
+               reg = <0x1fb50000 0x8000>;
 
                #address-cells = <1>;
                #size-cells = <0>;
                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 {
                        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>;
+                       };
+               };
+       };
 };
index a03ca91217c06443db01842dde8d17bb3a599cb9..cb30326add34e6268e4f5e1a14d4444fea81d0f7 100644 (file)
                };
        };
 };
+
+/* 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";
+};
index 1406e76c69426cac5ad94114037e6e7fa0fe23ff..8e536383a4c75cfc11d74f9a4d1f846f233cd08d 100644 (file)
                };
        };
 };
+
+/* 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";
+};
index bd1901670254cd920b07a97f38c5aa17368dac71..ed547b7c5b2a5e066a498fd56554fabeb15dc30c 100644 (file)
        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;
index 086d0d36b4eb946c2e858c5110e879f6992c8bb9..54019baa35636c3df893acbee58f4858723b54a6 100644 (file)
        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";
 
index cef1186274c41a513b1d610692d9f5b2f1d135b5..6446055d962a6b4be3f89038a911468578cfa4b2 100644 (file)
@@ -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 (file)
index 0000000..b6e6730
--- /dev/null
@@ -0,0 +1,144 @@
+From 8c7dfabd860ab0a6dd771c2bac7b7599eb369a4f Mon Sep 17 00:00:00 2001
+From: Ahmed Naseef <naseefkm@gmail.com>
+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 <naseefkm@gmail.com>
+--- 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