mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-18 03:06:43 +00:00
net: phy: broadcom: Add IDDQ-SR mode
Add support for putting the PHY into IDDQ Soft Recovery mode by setting the TOP_MISC register bits accordingly. This requires us to implement a custom bcm54xx_suspend() routine which diverges from genphy_suspend() in order to configure the PHY to enter IDDQ with software recovery as well as avoid doing a read/modify/write on the BMCR register. Doing a read/modify/write on the BMCR register means that the auto-negotation bit may remain which interferes with the ability to put the PHY into IDDQ-SR mode. We do software reset upon suspend in order to put the PHY back into its state prior to suspend as recommended by the datasheet. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c595b120eb
commit
d6da08ed14
@ -392,10 +392,50 @@ static int bcm54xx_config_init(struct phy_device *phydev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm54xx_iddq_set(struct phy_device *phydev, bool enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!(phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND))
|
||||
return ret;
|
||||
|
||||
ret = bcm_phy_read_exp(phydev, BCM54XX_TOP_MISC_IDDQ_CTRL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (enable)
|
||||
ret |= BCM54XX_TOP_MISC_IDDQ_SR | BCM54XX_TOP_MISC_IDDQ_LP;
|
||||
else
|
||||
ret &= ~(BCM54XX_TOP_MISC_IDDQ_SR | BCM54XX_TOP_MISC_IDDQ_LP);
|
||||
|
||||
ret = bcm_phy_write_exp(phydev, BCM54XX_TOP_MISC_IDDQ_CTRL, ret);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bcm54xx_suspend(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* We cannot use a read/modify/write here otherwise the PHY gets into
|
||||
* a bad state where its LEDs keep flashing, thus defeating the purpose
|
||||
* of low power mode.
|
||||
*/
|
||||
ret = phy_write(phydev, MII_BMCR, BMCR_PDOWN);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return bcm54xx_iddq_set(phydev, true);
|
||||
}
|
||||
|
||||
static int bcm54xx_resume(struct phy_device *phydev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bcm54xx_iddq_set(phydev, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Writes to register other than BMCR would be ignored
|
||||
* unless we clear the PDOWN bit first
|
||||
*/
|
||||
@ -408,6 +448,15 @@ static int bcm54xx_resume(struct phy_device *phydev)
|
||||
*/
|
||||
fsleep(40);
|
||||
|
||||
/* Issue a soft reset after clearing the power down bit
|
||||
* and before doing any other configuration.
|
||||
*/
|
||||
if (phydev->dev_flags & PHY_BRCM_IDDQ_SUSPEND) {
|
||||
ret = genphy_soft_reset(phydev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return bcm54xx_config_init(phydev);
|
||||
}
|
||||
|
||||
@ -772,6 +821,8 @@ static struct phy_driver broadcom_drivers[] = {
|
||||
.config_intr = bcm_phy_config_intr,
|
||||
.handle_interrupt = bcm_phy_handle_interrupt,
|
||||
.link_change_notify = bcm54xx_link_change_notify,
|
||||
.suspend = bcm54xx_suspend,
|
||||
.resume = bcm54xx_resume,
|
||||
}, {
|
||||
.phy_id = PHY_ID_BCM5461,
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
|
@ -67,6 +67,7 @@
|
||||
#define PHY_BRCM_CLEAR_RGMII_MODE 0x00000004
|
||||
#define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00000008
|
||||
#define PHY_BRCM_EN_MASTER_MODE 0x00000010
|
||||
#define PHY_BRCM_IDDQ_SUSPEND 0x000000220
|
||||
|
||||
/* Broadcom BCM7xxx specific workarounds */
|
||||
#define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff)
|
||||
@ -84,6 +85,7 @@
|
||||
|
||||
#define MII_BCM54XX_EXP_DATA 0x15 /* Expansion register data */
|
||||
#define MII_BCM54XX_EXP_SEL 0x17 /* Expansion register select */
|
||||
#define MII_BCM54XX_EXP_SEL_TOP 0x0d00 /* TOP_MISC expansion register select */
|
||||
#define MII_BCM54XX_EXP_SEL_SSD 0x0e00 /* Secondary SerDes select */
|
||||
#define MII_BCM54XX_EXP_SEL_ER 0x0f00 /* Expansion register select */
|
||||
#define MII_BCM54XX_EXP_SEL_ETC 0x0d00 /* Expansion register spare + 2k mem */
|
||||
@ -243,6 +245,12 @@
|
||||
#define MII_BCM54XX_EXP_EXP97 0x0f97
|
||||
#define MII_BCM54XX_EXP_EXP97_MYST 0x0c0c
|
||||
|
||||
/* Top-MISC expansion registers */
|
||||
#define BCM54XX_TOP_MISC_IDDQ_CTRL (MII_BCM54XX_EXP_SEL_TOP + 0x06)
|
||||
#define BCM54XX_TOP_MISC_IDDQ_LP (1 << 0)
|
||||
#define BCM54XX_TOP_MISC_IDDQ_SD (1 << 2)
|
||||
#define BCM54XX_TOP_MISC_IDDQ_SR (1 << 3)
|
||||
|
||||
/*
|
||||
* BCM5482: Secondary SerDes registers
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user