On 27/01/2026 11:53, Daniel Golle wrote:
On Tue, Jan 27, 2026 at 11:43:00AM +0100, Caleb James DeLisle wrote:
Hello, thank you Felix.

I have a small update: Even if the switch is otherwise untouched, even in
the bootloader, setting BMCR_ANRESTART is fatal. The bootloader does seem to
set BMCR_ANRESTART during startup, and BMCR_ANENABLE is set during
operation. I gather I should define config_aneg and do some ritual in there,
but mt7530.c and mtk-ge.c don't seem to be doing anything so I'm not sure
where to look.
Are you resetting the PHYs in some way before accessing them?
Ie. either by using a reset register of the switch or by assigning
I use mt7530_setup() which soft-resets the switch, this doesn't seem to break the PHYs but also doesn't solve the problem. There's a reset pin but I'm not at all convinced that it does anything to the external switch. These devices have an SoC switch that's 4FE+1GE and (in gigabit configurations), an MCM switch 5GE.
genphy_soft_reset to .soft_reset.

I just looked at genphy_soft_reset and it seems to set BMCR_ANRESTART | BMCR_RESET. Doing this manually works, the switch still counts incoming bytes on that port.

root@OpenWrt:~# mdio econet_gsw-0 phy 2 0
0x1000
root@OpenWrt:~# mdio econet_gsw-0 phy 2 0 0x9200


But even after that, setting BMCR_ANENABLE | BMCR_ANRESTART still breaks it.


mdio econet_gsw-0 phy 2 0

0x1040

mdio econet_gsw-0 phy 2 0 0x1240

<switch stops counting>


That's kind of a problem because the generic phy seems to like calling genphy_config_aneg() which ends up in genphy_restart_aneg() doing exactly that.


I did discover something: If I down the link and bring it back up, it starts working again. So it might be as simple as the bootloader leaves the PHYs up and Linux doesn't expect that (?)

Would there be any reason not to set BMCR_PDOWN in mt7530_phy_config_init() so we know they're in a consistent state?

Also if you happen to have an MT7621 sitting there running, would you mind setting BMCR_ANENABLE | BMCR_ANRESTART with mdio on a running port to see if it's the same behavior? The port should immediately die and then go into a loop trying to connect every few seconds / minutes depending on what it's connected to.



Especially if you are not sure the PHY is freshly reset before accessing
it from within Linux, check the page select register (0x1f in C22 mode).
root@OpenWrt:~# mdio econet_gsw-0 phy 2 31

0x0000


Thanks,

Caleb



Should that be non-zero you might not actually be touching what you
believe is the AN_RESTART bit, but maybe something entirely different
because you are operating on a different page of registers on which
register 0 isn't BMCR.

Currently working on getting the vendor OS going so I can try resetting the
port and see if I can track down what they're doing.

Thanks,

Caleb


On 27/01/2026 11:05, Felix Baumann wrote:
Hello arinc9,

maybe you have an idea or could help him out? :)

Regards
Felix Baumann

Am 25. Januar 2026 00:53:25 MEZ schrieb Caleb James DeLisle <[email protected]>:
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

_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to