diff options
Diffstat (limited to 'drivers/net/phy/marvell.c')
-rw-r--r-- | drivers/net/phy/marvell.c | 77 |
1 files changed, 74 insertions, 3 deletions
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 5a1bd5db2a93..0101f2bdf400 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c | |||
@@ -68,6 +68,15 @@ | |||
68 | #define MII_M1111_COPPER 0 | 68 | #define MII_M1111_COPPER 0 |
69 | #define MII_M1111_FIBER 1 | 69 | #define MII_M1111_FIBER 1 |
70 | 70 | ||
71 | #define MII_88E1121_PHY_MSCR_PAGE 2 | ||
72 | #define MII_88E1121_PHY_MSCR_REG 21 | ||
73 | #define MII_88E1121_PHY_MSCR_RX_DELAY BIT(5) | ||
74 | #define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4) | ||
75 | #define MII_88E1121_PHY_MSCR_DELAY_MASK (~(0x3 << 4)) | ||
76 | |||
77 | #define MII_88EC048_PHY_MSCR1_REG 16 | ||
78 | #define MII_88EC048_PHY_MSCR1_PAD_ODD BIT(6) | ||
79 | |||
71 | #define MII_88E1121_PHY_LED_CTRL 16 | 80 | #define MII_88E1121_PHY_LED_CTRL 16 |
72 | #define MII_88E1121_PHY_LED_PAGE 3 | 81 | #define MII_88E1121_PHY_LED_PAGE 3 |
73 | #define MII_88E1121_PHY_LED_DEF 0x0030 | 82 | #define MII_88E1121_PHY_LED_DEF 0x0030 |
@@ -179,7 +188,30 @@ static int marvell_config_aneg(struct phy_device *phydev) | |||
179 | 188 | ||
180 | static int m88e1121_config_aneg(struct phy_device *phydev) | 189 | static int m88e1121_config_aneg(struct phy_device *phydev) |
181 | { | 190 | { |
182 | int err, temp; | 191 | int err, oldpage, mscr; |
192 | |||
193 | oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); | ||
194 | |||
195 | err = phy_write(phydev, MII_88E1121_PHY_PAGE, | ||
196 | MII_88E1121_PHY_MSCR_PAGE); | ||
197 | if (err < 0) | ||
198 | return err; | ||
199 | mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG) & | ||
200 | MII_88E1121_PHY_MSCR_DELAY_MASK; | ||
201 | |||
202 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) | ||
203 | mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY | | ||
204 | MII_88E1121_PHY_MSCR_TX_DELAY); | ||
205 | else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) | ||
206 | mscr |= MII_88E1121_PHY_MSCR_RX_DELAY; | ||
207 | else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) | ||
208 | mscr |= MII_88E1121_PHY_MSCR_TX_DELAY; | ||
209 | |||
210 | err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); | ||
211 | if (err < 0) | ||
212 | return err; | ||
213 | |||
214 | phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); | ||
183 | 215 | ||
184 | err = phy_write(phydev, MII_BMCR, BMCR_RESET); | 216 | err = phy_write(phydev, MII_BMCR, BMCR_RESET); |
185 | if (err < 0) | 217 | if (err < 0) |
@@ -190,17 +222,42 @@ static int m88e1121_config_aneg(struct phy_device *phydev) | |||
190 | if (err < 0) | 222 | if (err < 0) |
191 | return err; | 223 | return err; |
192 | 224 | ||
193 | temp = phy_read(phydev, MII_88E1121_PHY_PAGE); | 225 | oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); |
194 | 226 | ||
195 | phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); | 227 | phy_write(phydev, MII_88E1121_PHY_PAGE, MII_88E1121_PHY_LED_PAGE); |
196 | phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); | 228 | phy_write(phydev, MII_88E1121_PHY_LED_CTRL, MII_88E1121_PHY_LED_DEF); |
197 | phy_write(phydev, MII_88E1121_PHY_PAGE, temp); | 229 | phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); |
198 | 230 | ||
199 | err = genphy_config_aneg(phydev); | 231 | err = genphy_config_aneg(phydev); |
200 | 232 | ||
201 | return err; | 233 | return err; |
202 | } | 234 | } |
203 | 235 | ||
236 | static int m88ec048_config_aneg(struct phy_device *phydev) | ||
237 | { | ||
238 | int err, oldpage, mscr; | ||
239 | |||
240 | oldpage = phy_read(phydev, MII_88E1121_PHY_PAGE); | ||
241 | |||
242 | err = phy_write(phydev, MII_88E1121_PHY_PAGE, | ||
243 | MII_88E1121_PHY_MSCR_PAGE); | ||
244 | if (err < 0) | ||
245 | return err; | ||
246 | |||
247 | mscr = phy_read(phydev, MII_88EC048_PHY_MSCR1_REG); | ||
248 | mscr |= MII_88EC048_PHY_MSCR1_PAD_ODD; | ||
249 | |||
250 | err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr); | ||
251 | if (err < 0) | ||
252 | return err; | ||
253 | |||
254 | err = phy_write(phydev, MII_88E1121_PHY_PAGE, oldpage); | ||
255 | if (err < 0) | ||
256 | return err; | ||
257 | |||
258 | return m88e1121_config_aneg(phydev); | ||
259 | } | ||
260 | |||
204 | static int m88e1111_config_init(struct phy_device *phydev) | 261 | static int m88e1111_config_init(struct phy_device *phydev) |
205 | { | 262 | { |
206 | int err; | 263 | int err; |
@@ -595,6 +652,19 @@ static struct phy_driver marvell_drivers[] = { | |||
595 | .driver = { .owner = THIS_MODULE }, | 652 | .driver = { .owner = THIS_MODULE }, |
596 | }, | 653 | }, |
597 | { | 654 | { |
655 | .phy_id = MARVELL_PHY_ID_88EC048, | ||
656 | .phy_id_mask = MARVELL_PHY_ID_MASK, | ||
657 | .name = "Marvell 88EC048", | ||
658 | .features = PHY_GBIT_FEATURES, | ||
659 | .flags = PHY_HAS_INTERRUPT, | ||
660 | .config_aneg = &m88ec048_config_aneg, | ||
661 | .read_status = &marvell_read_status, | ||
662 | .ack_interrupt = &marvell_ack_interrupt, | ||
663 | .config_intr = &marvell_config_intr, | ||
664 | .did_interrupt = &m88e1121_did_interrupt, | ||
665 | .driver = { .owner = THIS_MODULE }, | ||
666 | }, | ||
667 | { | ||
598 | .phy_id = MARVELL_PHY_ID_88E1145, | 668 | .phy_id = MARVELL_PHY_ID_88E1145, |
599 | .phy_id_mask = MARVELL_PHY_ID_MASK, | 669 | .phy_id_mask = MARVELL_PHY_ID_MASK, |
600 | .name = "Marvell 88E1145", | 670 | .name = "Marvell 88E1145", |
@@ -659,6 +729,7 @@ static struct mdio_device_id marvell_tbl[] = { | |||
659 | { 0x01410cb0, 0xfffffff0 }, | 729 | { 0x01410cb0, 0xfffffff0 }, |
660 | { 0x01410cd0, 0xfffffff0 }, | 730 | { 0x01410cd0, 0xfffffff0 }, |
661 | { 0x01410e30, 0xfffffff0 }, | 731 | { 0x01410e30, 0xfffffff0 }, |
732 | { 0x01410e90, 0xfffffff0 }, | ||
662 | { } | 733 | { } |
663 | }; | 734 | }; |
664 | 735 | ||