Merge branch 'Fix-88x3310-leaving-power-save-mode'
Russell King says: ==================== Fix 88x3310 leaving power save mode This series fixes a problem with the 88x3310 PHY on Macchiatobin coming out of powersave mode noticed by Matteo Croce. It seems that certain PHY firmwares do not properly exit powersave mode, resulting in a fibre link not coming up. The solution appears to be to soft-reset the PHY after clearing the powersave bit. We add support for reporting the PHY firmware version to the kernel log, and use it to trigger this new behaviour if we have v0.3.x.x or more recent firmware on the PHY. This, however, is a guess as the firmware revision documentation does not mention this issue, and we know that v0.2.1.0 works without this fix but v0.3.3.0 and later does not. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
91fac45cd0
|
@ -33,6 +33,8 @@
|
|||
#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
|
||||
|
||||
enum {
|
||||
MV_PMA_FW_VER0 = 0xc011,
|
||||
MV_PMA_FW_VER1 = 0xc012,
|
||||
MV_PMA_BOOT = 0xc050,
|
||||
MV_PMA_BOOT_FATAL = BIT(0),
|
||||
|
||||
|
@ -73,7 +75,8 @@ enum {
|
|||
|
||||
/* Vendor2 MMD registers */
|
||||
MV_V2_PORT_CTRL = 0xf001,
|
||||
MV_V2_PORT_CTRL_PWRDOWN = 0x0800,
|
||||
MV_V2_PORT_CTRL_SWRST = BIT(15),
|
||||
MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
|
||||
MV_V2_TEMP_CTRL = 0xf08a,
|
||||
MV_V2_TEMP_CTRL_MASK = 0xc000,
|
||||
MV_V2_TEMP_CTRL_SAMPLE = 0x0000,
|
||||
|
@ -83,6 +86,8 @@ enum {
|
|||
};
|
||||
|
||||
struct mv3310_priv {
|
||||
u32 firmware_ver;
|
||||
|
||||
struct device *hwmon_dev;
|
||||
char *hwmon_name;
|
||||
};
|
||||
|
@ -235,8 +240,17 @@ static int mv3310_power_down(struct phy_device *phydev)
|
|||
|
||||
static int mv3310_power_up(struct phy_device *phydev)
|
||||
{
|
||||
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
|
||||
MV_V2_PORT_CTRL_PWRDOWN);
|
||||
struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
|
||||
int ret;
|
||||
|
||||
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
|
||||
MV_V2_PORT_CTRL_PWRDOWN);
|
||||
|
||||
if (priv->firmware_ver < 0x00030000)
|
||||
return ret;
|
||||
|
||||
return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
|
||||
MV_V2_PORT_CTRL_SWRST);
|
||||
}
|
||||
|
||||
static int mv3310_reset(struct phy_device *phydev, u32 unit)
|
||||
|
@ -355,6 +369,22 @@ static int mv3310_probe(struct phy_device *phydev)
|
|||
|
||||
dev_set_drvdata(&phydev->mdio.dev, priv);
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->firmware_ver = ret << 16;
|
||||
|
||||
ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->firmware_ver |= ret;
|
||||
|
||||
phydev_info(phydev, "Firmware version %u.%u.%u.%u\n",
|
||||
priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
|
||||
(priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
|
||||
|
||||
/* Powering down the port when not in use saves about 600mW */
|
||||
ret = mv3310_power_down(phydev);
|
||||
if (ret)
|
||||
|
|
Loading…
Reference in New Issue