Re: [PATCH v4 net-next] net: phy: mediatek: support MT7530 PHYs on EN71221 MCM

From: Daniel Golle

Date: Tue Sep 15 2026 - 07:18:44 EST


On Tue, Sep 15, 2026 at 10:35:50AM +0000, Caleb James DeLisle wrote:
> The EcoNet EN751221 multi-chip module implementation of the MT7530
> requires some additional configuration of the PHYs on startup.
> The reason for this is not known, but it is possible that it has
> to do with the fact that the EN751221 MCM implementation of the
> MT7530 runs at an abnormal PLL frequency (362.5Mhz).
>
> Detect whether the MT7530 PHY is attached to the MDIO bus of an
> EcoNet EN751221 switch and if so, apply the necessary register
> updates. Additionally, never attempt to configure an MT7530
> identified PHY which does not have gigabit support because the same
> ID is used for another (FE) PHY.
>
> Co-developed-by: Matheus Sampaio Queiroga <srherobrine20@xxxxxxxxx>
> Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@xxxxxxxxx>
> Signed-off-by: Caleb James DeLisle <cjd@xxxxxxxx>

> [...]
> +static bool en751221_is_mcm_phy(struct phy_device *phydev)
> +{
> + struct device *parent = phydev->mdio.bus->parent;
> +
> + return parent && parent->of_node &&
> + of_device_is_compatible(parent->of_node, "econet,en751221");

I thought you had found better options than using the parent of_node...?

> +}
> +
> +/*
> + * MTK_GPHY_ID_MT7530 ID is also used for an EcoNet SoC FE phy, but that PHY
> + * does not advertise ESTATUS_1000_TFULL.
> + */
> +static int mt7530_phy_match(struct phy_device *phydev,
> + const struct phy_driver *phydrv)
> +{

You miss the check for the PHY ID, see also below.

I'd suggest something like
int ret;

ret = genphy_match_phy_device(phydev, phydrv);
if (!ret)
return 0;

> + return (phy_read(phydev, MII_ESTATUS) & ESTATUS_1000_TFULL) != 0 &&

The above should be helper function used by both .match_phy_device ops.

> + !en751221_is_mcm_phy(phydev);
> +}
> +
> +static int en751221_phy_match(struct phy_device *phydev,
> + const struct phy_driver *phydrv)
> +{
> + return (phy_read(phydev, MII_ESTATUS) & ESTATUS_1000_TFULL) != 0 &&
> + en751221_is_mcm_phy(phydev);
> +}
> +
> static int mt7531_phy_config_init(struct phy_device *phydev)
> {
> mtk_gephy_config_init(phydev);
> @@ -135,6 +195,23 @@ static struct phy_driver mtk_gephy_driver[] = {
> */
> .config_intr = genphy_no_config_intr,
> .handle_interrupt = genphy_handle_interrupt_no_ack,
> + .match_phy_device = mt7530_phy_match,
> + .suspend = genphy_suspend,
> + .resume = genphy_resume,
> + .read_page = mtk_phy_read_page,
> + .write_page = mtk_phy_write_page,
> + },
> + {
> + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),

This assigns phy_id and phy_id_mask, which are used by
genphy_match_phy_device(). However, you are setting a .match_phy_device
op which doesn't call genphy_match_phy_device(), so this is ignored.

> + .name = "EcoNet EN751221 MCM PHY",
> + .probe = mt7530_phy_probe,
> + .config_init = en751221_mcm_phy_config_init,
> + /* Interrupts are handled by the switch, not the PHY
> + * itself.
> + */
> + .config_intr = genphy_no_config_intr,
> + .handle_interrupt = genphy_handle_interrupt_no_ack,
> + .match_phy_device = en751221_phy_match,
> .suspend = genphy_suspend,
> .resume = genphy_resume,
> .read_page = mtk_phy_read_page,
> --
> 2.39.5
>