upstream Linux support for Ethernet combo ports via external mux

Daniel Golle daniel at makrotopia.org
Mon Feb 10 15:11:07 PST 2025


Hi,

Looking for ways to support a passive SerDes mux in vanilla Linux I
found Maxime's slides "Multi-port and Multi-PHY Ethernet interfaces"[1].

The case I want to support is probably quite common nowadays but isn't
covered there nor implemented in Linux.

 +----------------------------+
 |            SoC             |
 |    +-----------------+     |
 |    |       MAC       |     |
 |    +----+-------+----+     |
 |         |  PCS  |   +------+
 |         +---=---+   | GPIO |
 +-------------=-------+---=--+
              |            |
           +---=---+       |
           |  Mux  <-------+
           +-=---=-+
             |   |
            /     \
     +-----=-+   +-=-----+
     |  PHY  |   |  SFP  |
     +-------+   +-------+

So other than it was when SoCs didn't have built-in PCSs, now the SFP is
not connected to the PHY, but there is an additional mux IC controlled
by the SoC to connect the serialized MII either to the PHY (in case no
SFP is inserted) or to the SFP (in case a module is inserted).

MediaTek came up with a vendor-specific solution[2] for that which works
well -- but obviously it would be much nicer to have generic, vendor-
agnostic support for such setups in phylink, ideally based on the
existing gpio-mux driver.

So I imagine something like a generic phylink-mux, controlled by hooking
to the module_insert and module_remove remove SFP ops (assuming the
moddef0 signal is connected...).

Before I get my hands dirty, please join my line of thought for one
moment, so we can agree on a sketch:

Does everyone agree that phylink would be the right place to do this?

DT bindings could look like this (option A):
 ...
    mux: mux-controller {
        compatible = "gpio-mux";
        #mux-control-cells = <0>;

        mux-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
    };

    mux0: mii-mux {
        compatible = "mii-mux";
        mux-controls = <&mux>;
        #address-cells = <1>;
        #size-cells = <0>;

        channel at 0 {
            reg = <0>;
            sfp = <&sfp0>;
            managed = "in-band-status";
            module-presence-controls-mux;
        };

        channel at 1 {
            reg = <1>;
            phy-handle = <&phy0>;
            phy-connection-type = "sgmii";
        };
    };
  };

  soc {
      ethernet at 12340000 {
          mii-mux = <&mux0>;
      };
  };
    

or like this (option B):
 ...
    mux: mux-controller {
        compatible = "gpio-mux";
        #mux-control-cells = <0>;

        mux-gpios = <&pio 7 GPIO_ACTIVE_HIGH>;
    };
  };

  soc {
      ethernet at 12340000 {
          sfp = <&sfp0>;
          phy = <&phy0>;
          phy-connection-type = "sgmii";
          mux-controls = <&mux>;
      };
  };


Obviously option A is more expressive, but also more complex, and I'm
not 100% sure if all that complexity is really needed in practise.
However, for "better safe than sorry" reasons I'd opt for option A,
unless anyone comes up with a better idea.

Let me know what you think.


Cheers


Daniel


[1]: https://netdevconf.org/0x17/docs/netdev-0x17-paper2-talk-slides/multi-port-multi-phy-interfaces.pdf
[2]: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/refs/heads/master/autobuild/unified/global/24.10/files/target/linux/mediatek/patches-6.6/999-2708-net-ethernet-mtk_eth_soc-support-ethernet-passive-mu.patch



More information about the Linux-mediatek mailing list