[PATCH net-next v2 3/3] net: phy: mediatek: add driver for built-in 2.5G ethernet PHY on MT7988

SkyLake Huang (黃啟澤) SkyLake.Huang at mediatek.com
Tue May 13 03:55:57 PDT 2025


On Wed, 2025-02-19 at 16:47 +0100, Andrew Lunn wrote:
> 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> > +config MEDIATEK_2P5GE_PHY
> > +     tristate "MediaTek 2.5Gb Ethernet PHYs"
> > +     depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
> > +     select MTK_NET_PHYLIB
> > +     help
> > +       Supports MediaTek SoC built-in 2.5Gb Ethernet PHYs.
> > +
> > +       This will load necessary firmware and add appropriate time
> > delay.
> > +       Accelerate this procedure through internal pbus instead of
> > MDIO
> > +       bus. Certain link-up issues will also be fixed here.
> 
> Please keep the file sorted, this should be the first entry.
> 
I'll sort in this way in v3:
config MEDIATEK_2P5GE_PHY
...
config MEDIATEK_GE_SOC_PHY
...
config MTK_NET_PHYLIB
...
config MEDIATEK_GE_PHY
...

> > diff --git a/drivers/net/phy/mediatek/Makefile
> > b/drivers/net/phy/mediatek/Makefile
> > index 814879d0abe5..c6db8abd2c9c 100644
> > --- a/drivers/net/phy/mediatek/Makefile
> > +++ b/drivers/net/phy/mediatek/Makefile
> > @@ -2,3 +2,4 @@
> >  obj-$(CONFIG_MTK_NET_PHYLIB)         += mtk-phy-lib.o
> >  obj-$(CONFIG_MEDIATEK_GE_PHY)                += mtk-ge.o
> >  obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)    += mtk-ge-soc.o
> > +obj-$(CONFIG_MEDIATEK_2P5GE_PHY)     += mtk-2p5ge.o
> 
> I suppose you could say this file is sorted in reverse order so is
> correct?
> 
I'll change this in v3 in this way:
obj-$(CONFIG_MEDIATEK_2P5GE_PHY)     += mtk-2p5ge.o
obj-$(CONFIG_MEDIATEK_GE_SOC_PHY)    += mtk-ge-soc.o
obj-$(CONFIG_MTK_NET_PHYLIB)         += mtk-phy-lib.o
obj-$(CONFIG_MEDIATEK_GE_PHY)        += mtk-ge.o

> > diff --git a/drivers/net/phy/mediatek/mtk-2p5ge.c
> > b/drivers/net/phy/mediatek/mtk-2p5ge.c
> > new file mode 100644
> > index 000000000000..adb03df331ab
> > --- /dev/null
> > +++ b/drivers/net/phy/mediatek/mtk-2p5ge.c
> > @@ -0,0 +1,346 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +#include <linux/bitfield.h>
> > +#include <linux/firmware.h>
> > +#include <linux/module.h>
> > +#include <linux/nvmem-consumer.h>
> 
> Is this header needed?
> 
> > +#include <linux/of_address.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/pinctrl/consumer.h>
> > +#include <linux/phy.h>
> > +#include <linux/pm_domain.h>
> > +#include <linux/pm_runtime.h>
> 
> And these two? Please only use those that are needed.
> 
I'll remove linux/nvmem-
consumer.h>/<linux/pm_domain.h>/<linux/pm_runtime.h> in v3. I forgot
removing them after developing this driver.

> > +static int mt798x_2p5ge_phy_load_fw(struct phy_device *phydev)
> > +{
> > +
> > +     writew(reg & ~MD32_EN, mcu_csr_base + MD32_EN_CFG);
> > +     writew(reg | MD32_EN, mcu_csr_base + MD32_EN_CFG);
> > +     phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
> > +     /* We need a delay here to stabilize initialization of MCU */
> > +     usleep_range(7000, 8000);
> 
> Does the reset bit clear when the MCU is ready? That is what 802.3
> defines. phy_poll_reset() might do what you need.

CL22 reset bit will be cleared right after I set it on MT7988.
usleep_range() here is used to allow the MCU to stabilize, rather than
to wait for the reset to complete.
> 
> > +     dev_info(dev, "Firmware loading/trigger ok.\n");
> 
> dev_dbg(), if at all. You have already spammed the log with the
> firmware version, so this adds nothing useful.

Well then... In v3, I'll remove this line and print firmware version at
last like this:

for (i = 0; i < MT7988_2P5GE_PMB_FW_SIZE - 1; i += 4)
	writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);

writew(reg & ~MD32_EN, mcu_csr_base + MD32_EN_CFG);
writew(reg | MD32_EN, mcu_csr_base + MD32_EN_CFG);
phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
/* We need a delay here to stabilize initialization of MCU */
usleep_range(7000, 8000);

dev_info(dev, "Firmware date code: %x/%x/%x, version: %x.%x\n",
	 be16_to_cpu(*((__be16 *)(fw->data +
				  MT7988_2P5GE_PMB_FW_SIZE - 8))),
	 *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 6),
	 *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 5),
	 *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 2),
	 *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 1));

priv->fw_loaded = true;

> > +             phydev->duplex = DUPLEX_FULL;
> > +             /* FIXME:
> > +              * The current firmware always enables rate
> > adaptation mode.
> > +              */
> > +             phydev->rate_matching = RATE_MATCH_PAUSE;
> 
> Can we tell current firmware for future firmware? Is this actually
> fixable?
> 
We decided to always enable rate adaptation mode for MT7988's current
and future built-in 2.5GbE firmware. I'll remove FIXME comment here in
v3.

> > +     }
> > +
> > +     return 0;
> > +}
> > +
> 
> 
> 
> > +static int mt798x_2p5ge_phy_probe(struct phy_device *phydev)
> > +{
> > +     struct mtk_i2p5ge_phy_priv *priv;
> > +
> > +     priv = devm_kzalloc(&phydev->mdio.dev,
> > +                         sizeof(struct mtk_i2p5ge_phy_priv),
> > GFP_KERNEL);
> > +     if (!priv)
> > +             return -ENOMEM;
> > +
> > +     switch (phydev->drv->phy_id) {
> > +     case MTK_2P5GPHY_ID_MT7988:
> > +             /* The original hardware only sets MDIO_DEVS_PMAPMD
> > */
> 
> What do you mean by "original hardware"?
> 
> You use PHY_ID_MATCH_MODEL(MTK_2P5GPHY_ID_MT7988), so do you mean
> revision 0 is broken, but revision 1 fixed it?
> 
I'll fix this ambiguous comment to:
/* This built-in 2.5GbE hardware only sets MDIO_DEVS_PMAPMD. Set the  *
rest by this driver since PCS/AN/VEND1/VEND2 mmds exist.
 */

> 
> > +             phydev->c45_ids.mmds_present |= MDIO_DEVS_PCS |
> > +                                             MDIO_DEVS_AN |
> > +                                             MDIO_DEVS_VEND1 |
> > +                                             MDIO_DEVS_VEND2;
> > +             break;
> > +     default:
> > +             return -EINVAL;
> > +     }
> > +
> > +     priv->fw_loaded = false;
> > +     phydev->priv = priv;
> > +
> > +     mtk_phy_leds_state_init(phydev);
> 
> The LEDs work without firmware?
> 
>     Andrew
> 
> ---
> pw-bot: cr
I'll remove this line v3 and propose LED part in later patchset.

BRs,
Sky


More information about the Linux-mediatek mailing list