diff options
Diffstat (limited to 'drivers/net/ibm_newemac/phy.c')
-rw-r--r-- | drivers/net/ibm_newemac/phy.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c index 37bfeea8788a..606db53ef78e 100644 --- a/drivers/net/ibm_newemac/phy.c +++ b/drivers/net/ibm_newemac/phy.c | |||
@@ -38,6 +38,16 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val) | |||
38 | phy->mdio_write(phy->dev, phy->address, reg, val); | 38 | phy->mdio_write(phy->dev, phy->address, reg, val); |
39 | } | 39 | } |
40 | 40 | ||
41 | static inline int gpcs_phy_read(struct mii_phy *phy, int reg) | ||
42 | { | ||
43 | return phy->mdio_read(phy->dev, phy->gpcs_address, reg); | ||
44 | } | ||
45 | |||
46 | static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val) | ||
47 | { | ||
48 | phy->mdio_write(phy->dev, phy->gpcs_address, reg, val); | ||
49 | } | ||
50 | |||
41 | int emac_mii_reset_phy(struct mii_phy *phy) | 51 | int emac_mii_reset_phy(struct mii_phy *phy) |
42 | { | 52 | { |
43 | int val; | 53 | int val; |
@@ -62,6 +72,37 @@ int emac_mii_reset_phy(struct mii_phy *phy) | |||
62 | return limit <= 0; | 72 | return limit <= 0; |
63 | } | 73 | } |
64 | 74 | ||
75 | int emac_mii_reset_gpcs(struct mii_phy *phy) | ||
76 | { | ||
77 | int val; | ||
78 | int limit = 10000; | ||
79 | |||
80 | val = gpcs_phy_read(phy, MII_BMCR); | ||
81 | val &= ~(BMCR_ISOLATE | BMCR_ANENABLE); | ||
82 | val |= BMCR_RESET; | ||
83 | gpcs_phy_write(phy, MII_BMCR, val); | ||
84 | |||
85 | udelay(300); | ||
86 | |||
87 | while (limit--) { | ||
88 | val = gpcs_phy_read(phy, MII_BMCR); | ||
89 | if (val >= 0 && (val & BMCR_RESET) == 0) | ||
90 | break; | ||
91 | udelay(10); | ||
92 | } | ||
93 | if ((val & BMCR_ISOLATE) && limit > 0) | ||
94 | gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE); | ||
95 | |||
96 | if (limit > 0 && phy->mode == PHY_MODE_SGMII) { | ||
97 | /* Configure GPCS interface to recommended setting for SGMII */ | ||
98 | gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */ | ||
99 | gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */ | ||
100 | gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX */ | ||
101 | } | ||
102 | |||
103 | return limit <= 0; | ||
104 | } | ||
105 | |||
65 | static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) | 106 | static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) |
66 | { | 107 | { |
67 | int ctl, adv; | 108 | int ctl, adv; |
@@ -332,6 +373,33 @@ static int m88e1111_init(struct mii_phy *phy) | |||
332 | return 0; | 373 | return 0; |
333 | } | 374 | } |
334 | 375 | ||
376 | static int m88e1112_init(struct mii_phy *phy) | ||
377 | { | ||
378 | /* | ||
379 | * Marvell 88E1112 PHY needs to have the SGMII MAC | ||
380 | * interace (page 2) properly configured to | ||
381 | * communicate with the 460EX/GT GPCS interface. | ||
382 | */ | ||
383 | |||
384 | u16 reg_short; | ||
385 | |||
386 | pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__); | ||
387 | |||
388 | /* Set access to Page 2 */ | ||
389 | phy_write(phy, 0x16, 0x0002); | ||
390 | |||
391 | phy_write(phy, 0x00, 0x0040); /* 1Gbps */ | ||
392 | reg_short = (u16)(phy_read(phy, 0x1a)); | ||
393 | reg_short |= 0x8000; /* bypass Auto-Negotiation */ | ||
394 | phy_write(phy, 0x1a, reg_short); | ||
395 | emac_mii_reset_phy(phy); /* reset MAC interface */ | ||
396 | |||
397 | /* Reset access to Page 0 */ | ||
398 | phy_write(phy, 0x16, 0x0000); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
335 | static int et1011c_init(struct mii_phy *phy) | 403 | static int et1011c_init(struct mii_phy *phy) |
336 | { | 404 | { |
337 | u16 reg_short; | 405 | u16 reg_short; |
@@ -384,11 +452,27 @@ static struct mii_phy_def m88e1111_phy_def = { | |||
384 | .ops = &m88e1111_phy_ops, | 452 | .ops = &m88e1111_phy_ops, |
385 | }; | 453 | }; |
386 | 454 | ||
455 | static struct mii_phy_ops m88e1112_phy_ops = { | ||
456 | .init = m88e1112_init, | ||
457 | .setup_aneg = genmii_setup_aneg, | ||
458 | .setup_forced = genmii_setup_forced, | ||
459 | .poll_link = genmii_poll_link, | ||
460 | .read_link = genmii_read_link | ||
461 | }; | ||
462 | |||
463 | static struct mii_phy_def m88e1112_phy_def = { | ||
464 | .phy_id = 0x01410C90, | ||
465 | .phy_id_mask = 0x0ffffff0, | ||
466 | .name = "Marvell 88E1112 Ethernet", | ||
467 | .ops = &m88e1112_phy_ops, | ||
468 | }; | ||
469 | |||
387 | static struct mii_phy_def *mii_phy_table[] = { | 470 | static struct mii_phy_def *mii_phy_table[] = { |
388 | &et1011c_phy_def, | 471 | &et1011c_phy_def, |
389 | &cis8201_phy_def, | 472 | &cis8201_phy_def, |
390 | &bcm5248_phy_def, | 473 | &bcm5248_phy_def, |
391 | &m88e1111_phy_def, | 474 | &m88e1111_phy_def, |
475 | &m88e1112_phy_def, | ||
392 | &genmii_phy_def, | 476 | &genmii_phy_def, |
393 | NULL | 477 | NULL |
394 | }; | 478 | }; |