Debugging EcoNet's MT7530 PHYs
Caleb James DeLisle
cjd at cjdns.fr
Sat Jan 24 15:53:25 PST 2026
Oh sorry, one thing I completely forgot to mention:
I have the reset line labeled "GSW" configured - and it should be
resetting one or maybe both switches. Also of course mt7530.c resets via
MDIO. None of this affects the PHY, it still works until the first time
BMCR_ANRESTART or BMCR_PDOWN is asserted.
Thanks,
Caleb
On 25/01/2026 00:45, Caleb James DeLisle wrote:
> Hello guys,
>
>
> I'm working on the DSA for the EN751221 and I think I'm a bit stuck.
>
>
> Background:
>
> This is a really strange configuration, there are actually two MT7530
> switches. The first one is MMIO (vendor code says it's in the SoC
> die), and the second one is MDIO (identified in vendor code as an
> MCM). AFAICT the SoC switch is configured with only two ports active,
> Port6->CPU and Port5->MCM Switch. The MCM switch and its PHYs are hung
> off of the MDIO bus of the SoC switch, and to avoid collisions of PHY
> numbers, the SoC switch uses PHYs numbered 8,9,10,11,12 in place of
> 0,1,2,3,4. All of the PHYs (for both switches) identify as 03a2.9412,
> except for #12 which ids as 03a2.9451.
>
> I THINK the configuration is that the SoC switch port 5 uses PHY#12
> (borrowed from port4) to talk TRGMII to MCM switch port6, PHY#12 is
> the odd one in terms of ID so it is probably a TRGMII passthrough.
>
> There is vendor code which seems to tune PHY#0 (similar to
> mt7530_setup_port6() from linux/mt7530.c except with different
> frequency), I gather these CORE_PLL_* are not actually modifying PHY#0
> but rather it's a backdoor to controlling the whole switch (?). In the
> vendor code, it also tunes PHY#12 exactly the same way, so I may
> surmise that PHY#12 is the portal from the SoC switch to the MCM switch.
>
> What is clear and has been tested is that traffic flows into one of
> the ports of the MCM switch, then from there it goes to port6 which is
> connected to port5 of the SoC switch, then through port6 of the SoC
> switch to the ETH engine. I just don't know what PHYs are being used
> to do it.
>
> In any case, this isn't what's blocking me right now.
>
>
> The problem:
>
> Right now, I can get traffic to pass if I do not touch the phys at
> all, but of course that's not going to be acceptable in upstream. So
> I'm currently focusing on PHY#2 and trying to make it link up - I have
> a cable plugged in to the relevant port. I gather PHY#2 can't possibly
> be muxed with anything, so I shouldn't need to worry about anything
> except what MDIO messages are sent to PHY#2 (I'm not even trying to
> pass traffic, just see it's linked up, so even the switch could even
> be kaput). Furthermore, since this is an MCM module, I gather it
> should be identical silicon to the MCM switch in the MT7621, so to
> just make it link up, I really shouldn't be having a lot of difficulty
> (I am).
>
> I stubbed mt7530_phy_config_init() so it wouldn't change anything from
> what the bootloader had set, and I isolated the problem to the call to
> BMCR_ANRESTART. If this is not called, basically nothing on the PHY is
> touched except for a small change to the , and I have a stable
> connection. If this is called, I get flapping.
>
> I instrumented the write calls and excluded the c45 emulated reads,
> this narrowed it down to just these writes:
>
> [ 56.471009] libphy: Old ADV = 05e1, new adv 0de0
> [ 56.491279] mt7530-mmio 1fb58000.switch: mt7531_ind_c22_phy_write(02,
> 04, 0de1)
> [ 56.520118] libphy: bsmr =796d
> [ 56.524941] libphy: Old ctrl = 1c00, new ctrl 0200
> [ 56.592583] mt7530-mmio 1fb58000.switch: mt7531_ind_c22_phy_write(02,
> 09, 1e00)
> [ 56.604261] mt7530-mmio 1fb58000.switch: mt7531_ind_c22_phy_write(02,
> 00, 1200)
>
> ADV: Remove ADVERTISE_CSMA, add MAC_ASYM_PAUSE - I commented
> out MAC_ASYM_PAUSE in the code, did not fix.
>
> CTRL1000: Add ADVERTISE_1000FULL - Confusing because vendor code also
> sets ADVERTISE_1000FULL and I doubt MT7530 doesn't support it.
>
> BMCR: BMCR_ANRESTART is added.
>
> Trapping and stubbing out this one write saves the PHY. However, if I
> do this, then bring it down (+BMCR_PDOWN) and back up again
> (-BMCR_PDOWN), it also flaps and is unable to synchronize.
>
>
> Possibly related stuff:
>
> I traced through the vendor code and it seems to do the following on
> setup (I translated it to Linux APIs):
>
> phy_write(phydev, MII_BMCR, BMCR_RESET);
> phy_write_mmd(phydev, MDIO_MMD_VEND2, 0x0417, 0x7775); // mystery
> register + value
> phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL,
> FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3) | 0x50);
> // 0x50 is unknown
> phy_write(phydev, MII_CTRL1000, CTL1000_ENABLE_MASTER |
> CTL1000_AS_MASTER |
> CTL1000_PREFER_MASTER | ADVERTISE_1000FULL);
> phy_write(phydev, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART);
>
> So it sets BMCR_ANRESTART without a problem, is it plausible that
> those other registers need to be hit every time it's reset?
>
>
> Also, the vendor code for configuring the connection between the two
> switches contains this rather ominous line:
>
> mdio_cl22_write(0,0x1f,0x404,0x1d00); /* 362.5MHz*/
>
> I believe this SoC has a normal 25Mhz crystal, so this kind of implies
> the switch is running at a totally unique frequency. This is set in
> the bootloader and I leave it alone (for now), I'm not calling
> mt7530_setup_port5 or mt7530_setup_port6. I didn't pay much attention
> to the registers being hit in the switch itself - I assumed the PHY
> should work even if the switch is messed up, but maybe this is not a
> good assumption? Is there some register I should be paying attention
> to on the switch during setup?
>
> FYI, I tried forcing a call to mt7530_pll_setup() on the MII switch,
> this does not change behavior at all - either way, the PHY works
> unless I touch it.
>
>
> So (sorry for the essay), any thoughts about what I should try next?
>
>
> Thanks,
>
> Caleb
>
More information about the openwrt-devel
mailing list