diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 83aea5c5cd03..add0c4e33425 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -702,6 +702,36 @@ static void bcm54xx_get_stats(struct phy_device *phydev, bcm_phy_get_stats(phydev, priv->stats, stats, data); } +static void bcm54xx_link_change_notify(struct phy_device *phydev) +{ + u16 mask = MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE | + MII_BCM54XX_EXP_EXP08_FORCE_DAC_WAKE; + int ret; + + if (phydev->state != PHY_RUNNING) + return; + + /* Don't change the DAC wake settings if auto power down + * is not requested. + */ + if (!(phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE)) + return; + + ret = bcm_phy_read_exp(phydev, MII_BCM54XX_EXP_EXP08); + if (ret < 0) + return; + + /* Enable/disable 10BaseT auto and forced early DAC wake depending + * on the negotiated speed, those settings should only be done + * for 10Mbits/sec. + */ + if (phydev->speed == SPEED_10) + ret |= mask; + else + ret &= ~mask; + bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_EXP08, ret); +} + static struct phy_driver broadcom_drivers[] = { { .phy_id = PHY_ID_BCM5411, @@ -715,6 +745,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM5421, .phy_id_mask = 0xfffffff0, @@ -727,6 +758,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM54210E, .phy_id_mask = 0xfffffff0, @@ -739,6 +771,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM5461, .phy_id_mask = 0xfffffff0, @@ -751,6 +784,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM54612E, .phy_id_mask = 0xfffffff0, @@ -763,6 +797,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM54616S, .phy_id_mask = 0xfffffff0, @@ -774,6 +809,7 @@ static struct phy_driver broadcom_drivers[] = { .handle_interrupt = bcm_phy_handle_interrupt, .read_status = bcm54616s_read_status, .probe = bcm54616s_probe, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM5464, .phy_id_mask = 0xfffffff0, @@ -788,6 +824,7 @@ static struct phy_driver broadcom_drivers[] = { .handle_interrupt = bcm_phy_handle_interrupt, .suspend = genphy_suspend, .resume = genphy_resume, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM5481, .phy_id_mask = 0xfffffff0, @@ -801,6 +838,7 @@ static struct phy_driver broadcom_drivers[] = { .config_aneg = bcm5481_config_aneg, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM54810, .phy_id_mask = 0xfffffff0, @@ -816,6 +854,7 @@ static struct phy_driver broadcom_drivers[] = { .handle_interrupt = bcm_phy_handle_interrupt, .suspend = genphy_suspend, .resume = bcm54xx_resume, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM54811, .phy_id_mask = 0xfffffff0, @@ -831,6 +870,7 @@ static struct phy_driver broadcom_drivers[] = { .handle_interrupt = bcm_phy_handle_interrupt, .suspend = genphy_suspend, .resume = bcm54xx_resume, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM5482, .phy_id_mask = 0xfffffff0, @@ -843,6 +883,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM50610, .phy_id_mask = 0xfffffff0, @@ -855,6 +896,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM50610M, .phy_id_mask = 0xfffffff0, @@ -867,6 +909,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM57780, .phy_id_mask = 0xfffffff0, @@ -879,6 +922,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCMAC131, .phy_id_mask = 0xfffffff0, @@ -905,6 +949,7 @@ static struct phy_driver broadcom_drivers[] = { .get_strings = bcm_phy_get_strings, .get_stats = bcm54xx_get_stats, .probe = bcm54xx_phy_probe, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM53125, .phy_id_mask = 0xfffffff0, @@ -918,6 +963,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, }, { .phy_id = PHY_ID_BCM89610, .phy_id_mask = 0xfffffff0, @@ -930,6 +976,7 @@ static struct phy_driver broadcom_drivers[] = { .config_init = bcm54xx_config_init, .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, + .link_change_notify = bcm54xx_link_change_notify, } }; module_phy_driver(broadcom_drivers); diff --git a/include/linux/brcmphy.h b/include/linux/brcmphy.h index c2c2147dfeb8..3308cebe1c19 100644 --- a/include/linux/brcmphy.h +++ b/include/linux/brcmphy.h @@ -233,6 +233,7 @@ #define MII_BCM54XX_EXP_EXP08 0x0F08 #define MII_BCM54XX_EXP_EXP08_RJCT_2MHZ 0x0001 #define MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE 0x0200 +#define MII_BCM54XX_EXP_EXP08_FORCE_DAC_WAKE 0x0100 #define MII_BCM54XX_EXP_EXP75 0x0f75 #define MII_BCM54XX_EXP_EXP75_VDACCTRL 0x003c #define MII_BCM54XX_EXP_EXP75_CM_OSC 0x0001