On 08.02.2021 15:03, Serge Semin wrote: > It has been noticed that RTL8211E PHY stops detecting and reporting events > when EEE is successfully advertised and RXC stopping in LPI is enabled. > The freeze happens right after 3.0.10 bit (PC1R "Clock Stop Enable" > register) is set. At the same time LED2 stops blinking as if EEE mode has > been disabled. Notably the network traffic still flows through the PHY > with no obvious problem. Anyway if any MDIO read procedure is performed > after the "RXC stop in LPI" mode is enabled PHY gets to be unfrozen, LED2 > starts blinking and PHY interrupts happens again. The problem has been > noticed on RTL8211E PHY working together with DW GMAC 3.73a MAC and > reporting its event via a dedicated IRQ signal. (Obviously the problem has > been unnoticed in the polling mode, since it gets naturally fixed by the > periodic MDIO read procedure from the PHY status register - BMSR.) > > In order to fix that problem we suggest to locally re-implement the MMD > write method for RTL8211E PHY and perform a dummy read right after the > PC1R register is accessed to enable the RXC stopping in LPI mode. > > Signed-off-by: Serge Semin <sergey.se...@baikalelectronics.ru> > --- > drivers/net/phy/realtek.c | 37 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 37 insertions(+) > > diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c > index 99ecd6c4c15a..cbb86c257aae 100644 > --- a/drivers/net/phy/realtek.c > +++ b/drivers/net/phy/realtek.c > @@ -559,6 +559,42 @@ static int rtl822x_write_mmd(struct phy_device *phydev, > int devnum, u16 regnum, > return ret; > } > > +static int rtl8211e_write_mmd(struct phy_device *phydev, int devnum, u16 > regnum, > + u16 val) > +{ > + int ret; > + > + /* Write to the MMD registers by using the standard control/data pair. > + * The only difference is that we need to perform a dummy read after > + * the PC1R.CLKSTOP_EN bit is set. It's required to workaround an issue > + * of a partial core freeze so LED2 stops blinking in EEE mode, PHY > + * stops detecting the link change and raising IRQs until any read from > + * its registers performed. That happens only if and right after the PHY > + * is enabled to stop RXC in LPI mode. > + */ > + ret = __phy_write(phydev, MII_MMD_CTRL, devnum); > + if (ret) > + return ret; > + > + ret = __phy_write(phydev, MII_MMD_DATA, regnum); > + if (ret) > + return ret; > + > + ret = __phy_write(phydev, MII_MMD_CTRL, devnum | MII_MMD_CTRL_NOINCR); > + if (ret) > + return ret; > +
Nice analysis. Alternatively to duplicating this code piece we could export mmd_phy_indirect(). But up to you. > + ret = __phy_write(phydev, MII_MMD_DATA, val); > + if (ret) > + return ret; > + > + if (devnum == MDIO_MMD_PCS && regnum == MDIO_CTRL1 && > + val & MDIO_PCS_CTRL1_CLKSTOP_EN) > + ret = __phy_read(phydev, MII_MMD_DATA); > + > + return ret < 0 ? ret : 0; > +} > + > static int rtl822x_get_features(struct phy_device *phydev) > { > int val; > @@ -725,6 +761,7 @@ static struct phy_driver realtek_drvs[] = { > .resume = genphy_resume, > .read_page = rtl821x_read_page, > .write_page = rtl821x_write_page, > + .write_mmd = rtl8211e_write_mmd, > }, { > PHY_ID_MATCH_EXACT(0x001cc916), > .name = "RTL8211F Gigabit Ethernet", >