aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ibm_newemac/phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ibm_newemac/phy.c')
-rw-r--r--drivers/net/ibm_newemac/phy.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
index 9164abb72d9b..c40cd8df2212 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
41static 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
46static 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
41int emac_mii_reset_phy(struct mii_phy *phy) 51int 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
75int 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
65static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise) 106static 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
376static 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
335static int et1011c_init(struct mii_phy *phy) 403static 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
455static 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
463static 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
387static struct mii_phy_def *mii_phy_table[] = { 470static 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};