diff options
Diffstat (limited to 'drivers/net/phy/at803x.c')
-rw-r--r-- | drivers/net/phy/at803x.c | 65 |
1 files changed, 39 insertions, 26 deletions
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c index f279a897a5c7..a52b560e428b 100644 --- a/drivers/net/phy/at803x.c +++ b/drivers/net/phy/at803x.c | |||
@@ -42,19 +42,24 @@ | |||
42 | #define AT803X_MMD_ACCESS_CONTROL 0x0D | 42 | #define AT803X_MMD_ACCESS_CONTROL 0x0D |
43 | #define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E | 43 | #define AT803X_MMD_ACCESS_CONTROL_DATA 0x0E |
44 | #define AT803X_FUNC_DATA 0x4003 | 44 | #define AT803X_FUNC_DATA 0x4003 |
45 | #define AT803X_REG_CHIP_CONFIG 0x1f | ||
46 | #define AT803X_BT_BX_REG_SEL 0x8000 | ||
45 | 47 | ||
46 | #define AT803X_DEBUG_ADDR 0x1D | 48 | #define AT803X_DEBUG_ADDR 0x1D |
47 | #define AT803X_DEBUG_DATA 0x1E | 49 | #define AT803X_DEBUG_DATA 0x1E |
48 | 50 | ||
51 | #define AT803X_MODE_CFG_MASK 0x0F | ||
52 | #define AT803X_MODE_CFG_SGMII 0x01 | ||
53 | |||
54 | #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/ | ||
55 | #define AT803X_PSSR_MR_AN_COMPLETE 0x0200 | ||
56 | |||
49 | #define AT803X_DEBUG_REG_0 0x00 | 57 | #define AT803X_DEBUG_REG_0 0x00 |
50 | #define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) | 58 | #define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15) |
51 | 59 | ||
52 | #define AT803X_DEBUG_REG_5 0x05 | 60 | #define AT803X_DEBUG_REG_5 0x05 |
53 | #define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) | 61 | #define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8) |
54 | 62 | ||
55 | #define AT803X_REG_CHIP_CONFIG 0x1f | ||
56 | #define AT803X_BT_BX_REG_SEL 0x8000 | ||
57 | |||
58 | #define ATH8030_PHY_ID 0x004dd076 | 63 | #define ATH8030_PHY_ID 0x004dd076 |
59 | #define ATH8031_PHY_ID 0x004dd074 | 64 | #define ATH8031_PHY_ID 0x004dd074 |
60 | #define ATH8035_PHY_ID 0x004dd072 | 65 | #define ATH8035_PHY_ID 0x004dd072 |
@@ -209,7 +214,6 @@ static int at803x_suspend(struct phy_device *phydev) | |||
209 | { | 214 | { |
210 | int value; | 215 | int value; |
211 | int wol_enabled; | 216 | int wol_enabled; |
212 | int ccr; | ||
213 | 217 | ||
214 | mutex_lock(&phydev->lock); | 218 | mutex_lock(&phydev->lock); |
215 | 219 | ||
@@ -225,16 +229,6 @@ static int at803x_suspend(struct phy_device *phydev) | |||
225 | 229 | ||
226 | phy_write(phydev, MII_BMCR, value); | 230 | phy_write(phydev, MII_BMCR, value); |
227 | 231 | ||
228 | if (phydev->interface != PHY_INTERFACE_MODE_SGMII) | ||
229 | goto done; | ||
230 | |||
231 | /* also power-down SGMII interface */ | ||
232 | ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); | ||
233 | phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL); | ||
234 | phy_write(phydev, MII_BMCR, phy_read(phydev, MII_BMCR) | BMCR_PDOWN); | ||
235 | phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL); | ||
236 | |||
237 | done: | ||
238 | mutex_unlock(&phydev->lock); | 232 | mutex_unlock(&phydev->lock); |
239 | 233 | ||
240 | return 0; | 234 | return 0; |
@@ -243,7 +237,6 @@ done: | |||
243 | static int at803x_resume(struct phy_device *phydev) | 237 | static int at803x_resume(struct phy_device *phydev) |
244 | { | 238 | { |
245 | int value; | 239 | int value; |
246 | int ccr; | ||
247 | 240 | ||
248 | mutex_lock(&phydev->lock); | 241 | mutex_lock(&phydev->lock); |
249 | 242 | ||
@@ -251,17 +244,6 @@ static int at803x_resume(struct phy_device *phydev) | |||
251 | value &= ~(BMCR_PDOWN | BMCR_ISOLATE); | 244 | value &= ~(BMCR_PDOWN | BMCR_ISOLATE); |
252 | phy_write(phydev, MII_BMCR, value); | 245 | phy_write(phydev, MII_BMCR, value); |
253 | 246 | ||
254 | if (phydev->interface != PHY_INTERFACE_MODE_SGMII) | ||
255 | goto done; | ||
256 | |||
257 | /* also power-up SGMII interface */ | ||
258 | ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); | ||
259 | phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL); | ||
260 | value = phy_read(phydev, MII_BMCR) & ~(BMCR_PDOWN | BMCR_ISOLATE); | ||
261 | phy_write(phydev, MII_BMCR, value); | ||
262 | phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL); | ||
263 | |||
264 | done: | ||
265 | mutex_unlock(&phydev->lock); | 247 | mutex_unlock(&phydev->lock); |
266 | 248 | ||
267 | return 0; | 249 | return 0; |
@@ -381,6 +363,36 @@ static void at803x_link_change_notify(struct phy_device *phydev) | |||
381 | } | 363 | } |
382 | } | 364 | } |
383 | 365 | ||
366 | static int at803x_aneg_done(struct phy_device *phydev) | ||
367 | { | ||
368 | int ccr; | ||
369 | |||
370 | int aneg_done = genphy_aneg_done(phydev); | ||
371 | if (aneg_done != BMSR_ANEGCOMPLETE) | ||
372 | return aneg_done; | ||
373 | |||
374 | /* | ||
375 | * in SGMII mode, if copper side autoneg is successful, | ||
376 | * also check SGMII side autoneg result | ||
377 | */ | ||
378 | ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG); | ||
379 | if ((ccr & AT803X_MODE_CFG_MASK) != AT803X_MODE_CFG_SGMII) | ||
380 | return aneg_done; | ||
381 | |||
382 | /* switch to SGMII/fiber page */ | ||
383 | phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL); | ||
384 | |||
385 | /* check if the SGMII link is OK. */ | ||
386 | if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) { | ||
387 | pr_warn("803x_aneg_done: SGMII link is not ok\n"); | ||
388 | aneg_done = 0; | ||
389 | } | ||
390 | /* switch back to copper page */ | ||
391 | phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL); | ||
392 | |||
393 | return aneg_done; | ||
394 | } | ||
395 | |||
384 | static struct phy_driver at803x_driver[] = { | 396 | static struct phy_driver at803x_driver[] = { |
385 | { | 397 | { |
386 | /* ATHEROS 8035 */ | 398 | /* ATHEROS 8035 */ |
@@ -432,6 +444,7 @@ static struct phy_driver at803x_driver[] = { | |||
432 | .flags = PHY_HAS_INTERRUPT, | 444 | .flags = PHY_HAS_INTERRUPT, |
433 | .config_aneg = genphy_config_aneg, | 445 | .config_aneg = genphy_config_aneg, |
434 | .read_status = genphy_read_status, | 446 | .read_status = genphy_read_status, |
447 | .aneg_done = at803x_aneg_done, | ||
435 | .ack_interrupt = &at803x_ack_interrupt, | 448 | .ack_interrupt = &at803x_ack_interrupt, |
436 | .config_intr = &at803x_config_intr, | 449 | .config_intr = &at803x_config_intr, |
437 | } }; | 450 | } }; |