.. | .. |
---|
326 | 326 | return genphy_config_aneg(phydev); |
---|
327 | 327 | } |
---|
328 | 328 | |
---|
| 329 | +static void lan88xx_link_change_notify(struct phy_device *phydev) |
---|
| 330 | +{ |
---|
| 331 | + int temp; |
---|
| 332 | + |
---|
| 333 | + /* At forced 100 F/H mode, chip may fail to set mode correctly |
---|
| 334 | + * when cable is switched between long(~50+m) and short one. |
---|
| 335 | + * As workaround, set to 10 before setting to 100 |
---|
| 336 | + * at forced 100 F/H mode. |
---|
| 337 | + */ |
---|
| 338 | + if (!phydev->autoneg && phydev->speed == 100) { |
---|
| 339 | + /* disable phy interrupt */ |
---|
| 340 | + temp = phy_read(phydev, LAN88XX_INT_MASK); |
---|
| 341 | + temp &= ~LAN88XX_INT_MASK_MDINTPIN_EN_; |
---|
| 342 | + phy_write(phydev, LAN88XX_INT_MASK, temp); |
---|
| 343 | + |
---|
| 344 | + temp = phy_read(phydev, MII_BMCR); |
---|
| 345 | + temp &= ~(BMCR_SPEED100 | BMCR_SPEED1000); |
---|
| 346 | + phy_write(phydev, MII_BMCR, temp); /* set to 10 first */ |
---|
| 347 | + temp |= BMCR_SPEED100; |
---|
| 348 | + phy_write(phydev, MII_BMCR, temp); /* set to 100 later */ |
---|
| 349 | + |
---|
| 350 | + /* clear pending interrupt generated while workaround */ |
---|
| 351 | + temp = phy_read(phydev, LAN88XX_INT_STS); |
---|
| 352 | + |
---|
| 353 | + /* enable phy interrupt back */ |
---|
| 354 | + temp = phy_read(phydev, LAN88XX_INT_MASK); |
---|
| 355 | + temp |= LAN88XX_INT_MASK_MDINTPIN_EN_; |
---|
| 356 | + phy_write(phydev, LAN88XX_INT_MASK, temp); |
---|
| 357 | + } |
---|
| 358 | +} |
---|
| 359 | + |
---|
329 | 360 | static struct phy_driver microchip_phy_driver[] = { |
---|
330 | 361 | { |
---|
331 | 362 | .phy_id = 0x0007c130, |
---|
.. | .. |
---|
339 | 370 | |
---|
340 | 371 | .config_init = lan88xx_config_init, |
---|
341 | 372 | .config_aneg = lan88xx_config_aneg, |
---|
| 373 | + .link_change_notify = lan88xx_link_change_notify, |
---|
342 | 374 | |
---|
343 | 375 | .ack_interrupt = lan88xx_phy_ack_interrupt, |
---|
344 | 376 | .config_intr = lan88xx_phy_config_intr, |
---|