@@ -50,11 +50,22 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
5050}
5151
5252static int mv88e6xxx_serdes_pcs_get_state (struct mv88e6xxx_chip * chip ,
53- u16 status , u16 lpa ,
53+ u16 ctrl , u16 status , u16 lpa ,
5454 struct phylink_link_state * state )
5555{
56+ state -> link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK );
57+
5658 if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID ) {
57- state -> link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK );
59+ /* The Spped and Duplex Resolved register is 1 if AN is enabled
60+ * and complete, or if AN is disabled. So with disabled AN we
61+ * still get here on link up. But we want to set an_complete
62+ * only if AN was enabled, thus we look at BMCR_ANENABLE.
63+ * (According to 802.3-2008 section 22.2.4.2.10, we should be
64+ * able to get this same value from BMSR_ANEGCAPABLE, but tests
65+ * show that these Marvell PHYs don't conform to this part of
66+ * the specificaion - BMSR_ANEGCAPABLE is simply always 1.)
67+ */
68+ state -> an_complete = !!(ctrl & BMCR_ANENABLE );
5869 state -> duplex = status &
5970 MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
6071 DUPLEX_FULL : DUPLEX_HALF ;
@@ -81,6 +92,18 @@ static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,
8192 dev_err (chip -> dev , "invalid PHY speed\n" );
8293 return - EINVAL ;
8394 }
95+ } else if (state -> link &&
96+ state -> interface != PHY_INTERFACE_MODE_SGMII ) {
97+ /* If Speed and Duplex Resolved register is 0 and link is up, it
98+ * means that AN was enabled, but link partner had it disabled
99+ * and the PHY invoked the Auto-Negotiation Bypass feature and
100+ * linked anyway.
101+ */
102+ state -> duplex = DUPLEX_FULL ;
103+ if (state -> interface == PHY_INTERFACE_MODE_2500BASEX )
104+ state -> speed = SPEED_2500 ;
105+ else
106+ state -> speed = SPEED_1000 ;
84107 } else {
85108 state -> link = false;
86109 }
@@ -168,9 +191,15 @@ int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
168191int mv88e6352_serdes_pcs_get_state (struct mv88e6xxx_chip * chip , int port ,
169192 int lane , struct phylink_link_state * state )
170193{
171- u16 lpa , status ;
194+ u16 lpa , status , ctrl ;
172195 int err ;
173196
197+ err = mv88e6352_serdes_read (chip , MII_BMCR , & ctrl );
198+ if (err ) {
199+ dev_err (chip -> dev , "can't read Serdes PHY control: %d\n" , err );
200+ return err ;
201+ }
202+
174203 err = mv88e6352_serdes_read (chip , 0x11 , & status );
175204 if (err ) {
176205 dev_err (chip -> dev , "can't read Serdes PHY status: %d\n" , err );
@@ -183,7 +212,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
183212 return err ;
184213 }
185214
186- return mv88e6xxx_serdes_pcs_get_state (chip , status , lpa , state );
215+ return mv88e6xxx_serdes_pcs_get_state (chip , ctrl , status , lpa , state );
187216}
188217
189218int mv88e6352_serdes_pcs_an_restart (struct mv88e6xxx_chip * chip , int port ,
@@ -883,9 +912,16 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
883912static int mv88e6390_serdes_pcs_get_state_sgmii (struct mv88e6xxx_chip * chip ,
884913 int port , int lane , struct phylink_link_state * state )
885914{
886- u16 lpa , status ;
915+ u16 lpa , status , ctrl ;
887916 int err ;
888917
918+ err = mv88e6390_serdes_read (chip , lane , MDIO_MMD_PHYXS ,
919+ MV88E6390_SGMII_BMCR , & ctrl );
920+ if (err ) {
921+ dev_err (chip -> dev , "can't read Serdes PHY control: %d\n" , err );
922+ return err ;
923+ }
924+
889925 err = mv88e6390_serdes_read (chip , lane , MDIO_MMD_PHYXS ,
890926 MV88E6390_SGMII_PHY_STATUS , & status );
891927 if (err ) {
@@ -900,7 +936,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
900936 return err ;
901937 }
902938
903- return mv88e6xxx_serdes_pcs_get_state (chip , status , lpa , state );
939+ return mv88e6xxx_serdes_pcs_get_state (chip , ctrl , status , lpa , state );
904940}
905941
906942static int mv88e6390_serdes_pcs_get_state_10g (struct mv88e6xxx_chip * chip ,
@@ -1271,9 +1307,31 @@ void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p)
12711307 }
12721308}
12731309
1274- static int mv88e6393x_serdes_port_errata (struct mv88e6xxx_chip * chip , int lane )
1310+ static int mv88e6393x_serdes_power_lane (struct mv88e6xxx_chip * chip , int lane ,
1311+ bool on )
12751312{
1276- u16 reg , pcs ;
1313+ u16 reg ;
1314+ int err ;
1315+
1316+ err = mv88e6390_serdes_read (chip , lane , MDIO_MMD_PHYXS ,
1317+ MV88E6393X_SERDES_CTRL1 , & reg );
1318+ if (err )
1319+ return err ;
1320+
1321+ if (on )
1322+ reg &= ~(MV88E6393X_SERDES_CTRL1_TX_PDOWN |
1323+ MV88E6393X_SERDES_CTRL1_RX_PDOWN );
1324+ else
1325+ reg |= MV88E6393X_SERDES_CTRL1_TX_PDOWN |
1326+ MV88E6393X_SERDES_CTRL1_RX_PDOWN ;
1327+
1328+ return mv88e6390_serdes_write (chip , lane , MDIO_MMD_PHYXS ,
1329+ MV88E6393X_SERDES_CTRL1 , reg );
1330+ }
1331+
1332+ static int mv88e6393x_serdes_erratum_4_6 (struct mv88e6xxx_chip * chip , int lane )
1333+ {
1334+ u16 reg ;
12771335 int err ;
12781336
12791337 /* mv88e6393x family errata 4.6:
@@ -1284,26 +1342,45 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane)
12841342 * It seems that after this workaround the SERDES is automatically
12851343 * powered up (the bit is cleared), so power it down.
12861344 */
1287- if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE ||
1288- lane == MV88E6393X_PORT10_LANE ) {
1289- err = mv88e6390_serdes_read (chip , lane ,
1290- MDIO_MMD_PHYXS ,
1291- MV88E6393X_SERDES_POC , & reg );
1292- if (err )
1293- return err ;
1345+ err = mv88e6390_serdes_read (chip , lane , MDIO_MMD_PHYXS ,
1346+ MV88E6393X_SERDES_POC , & reg );
1347+ if (err )
1348+ return err ;
12941349
1295- reg &= ~MV88E6393X_SERDES_POC_PDOWN ;
1296- reg |= MV88E6393X_SERDES_POC_RESET ;
1350+ reg &= ~MV88E6393X_SERDES_POC_PDOWN ;
1351+ reg |= MV88E6393X_SERDES_POC_RESET ;
12971352
1298- err = mv88e6390_serdes_write (chip , lane , MDIO_MMD_PHYXS ,
1299- MV88E6393X_SERDES_POC , reg );
1300- if (err )
1301- return err ;
1353+ err = mv88e6390_serdes_write (chip , lane , MDIO_MMD_PHYXS ,
1354+ MV88E6393X_SERDES_POC , reg );
1355+ if (err )
1356+ return err ;
13021357
1303- err = mv88e6390_serdes_power_sgmii (chip , lane , false);
1304- if (err )
1305- return err ;
1306- }
1358+ err = mv88e6390_serdes_power_sgmii (chip , lane , false);
1359+ if (err )
1360+ return err ;
1361+
1362+ return mv88e6393x_serdes_power_lane (chip , lane , false);
1363+ }
1364+
1365+ int mv88e6393x_serdes_setup_errata (struct mv88e6xxx_chip * chip )
1366+ {
1367+ int err ;
1368+
1369+ err = mv88e6393x_serdes_erratum_4_6 (chip , MV88E6393X_PORT0_LANE );
1370+ if (err )
1371+ return err ;
1372+
1373+ err = mv88e6393x_serdes_erratum_4_6 (chip , MV88E6393X_PORT9_LANE );
1374+ if (err )
1375+ return err ;
1376+
1377+ return mv88e6393x_serdes_erratum_4_6 (chip , MV88E6393X_PORT10_LANE );
1378+ }
1379+
1380+ static int mv88e6393x_serdes_erratum_4_8 (struct mv88e6xxx_chip * chip , int lane )
1381+ {
1382+ u16 reg , pcs ;
1383+ int err ;
13071384
13081385 /* mv88e6393x family errata 4.8:
13091386 * When a SERDES port is operating in 1000BASE-X or SGMII mode link may
@@ -1334,38 +1411,149 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane)
13341411 MV88E6393X_ERRATA_4_8_REG , reg );
13351412}
13361413
1337- int mv88e6393x_serdes_setup_errata (struct mv88e6xxx_chip * chip )
1414+ static int mv88e6393x_serdes_erratum_5_2 (struct mv88e6xxx_chip * chip , int lane ,
1415+ u8 cmode )
1416+ {
1417+ static const struct {
1418+ u16 dev , reg , val , mask ;
1419+ } fixes [] = {
1420+ { MDIO_MMD_VEND1 , 0x8093 , 0xcb5a , 0xffff },
1421+ { MDIO_MMD_VEND1 , 0x8171 , 0x7088 , 0xffff },
1422+ { MDIO_MMD_VEND1 , 0x80c9 , 0x311a , 0xffff },
1423+ { MDIO_MMD_VEND1 , 0x80a2 , 0x8000 , 0xff7f },
1424+ { MDIO_MMD_VEND1 , 0x80a9 , 0x0000 , 0xfff0 },
1425+ { MDIO_MMD_VEND1 , 0x80a3 , 0x0000 , 0xf8ff },
1426+ { MDIO_MMD_PHYXS , MV88E6393X_SERDES_POC ,
1427+ MV88E6393X_SERDES_POC_RESET , MV88E6393X_SERDES_POC_RESET },
1428+ };
1429+ int err , i ;
1430+ u16 reg ;
1431+
1432+ /* mv88e6393x family errata 5.2:
1433+ * For optimal signal integrity the following sequence should be applied
1434+ * to SERDES operating in 10G mode. These registers only apply to 10G
1435+ * operation and have no effect on other speeds.
1436+ */
1437+ if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER )
1438+ return 0 ;
1439+
1440+ for (i = 0 ; i < ARRAY_SIZE (fixes ); ++ i ) {
1441+ err = mv88e6390_serdes_read (chip , lane , fixes [i ].dev ,
1442+ fixes [i ].reg , & reg );
1443+ if (err )
1444+ return err ;
1445+
1446+ reg &= ~fixes [i ].mask ;
1447+ reg |= fixes [i ].val ;
1448+
1449+ err = mv88e6390_serdes_write (chip , lane , fixes [i ].dev ,
1450+ fixes [i ].reg , reg );
1451+ if (err )
1452+ return err ;
1453+ }
1454+
1455+ return 0 ;
1456+ }
1457+
1458+ static int mv88e6393x_serdes_fix_2500basex_an (struct mv88e6xxx_chip * chip ,
1459+ int lane , u8 cmode , bool on )
13381460{
1461+ u16 reg ;
13391462 int err ;
13401463
1341- err = mv88e6393x_serdes_port_errata (chip , MV88E6393X_PORT0_LANE );
1464+ if (cmode != MV88E6XXX_PORT_STS_CMODE_2500BASEX )
1465+ return 0 ;
1466+
1467+ /* Inband AN is broken on Amethyst in 2500base-x mode when set by
1468+ * standard mechanism (via cmode).
1469+ * We can get around this by configuring the PCS mode to 1000base-x
1470+ * and then writing value 0x58 to register 1e.8000. (This must be done
1471+ * while SerDes receiver and transmitter are disabled, which is, when
1472+ * this function is called.)
1473+ * It seem that when we do this configuration to 2500base-x mode (by
1474+ * changing PCS mode to 1000base-x and frequency to 3.125 GHz from
1475+ * 1.25 GHz) and then configure to sgmii or 1000base-x, the device
1476+ * thinks that it already has SerDes at 1.25 GHz and does not change
1477+ * the 1e.8000 register, leaving SerDes at 3.125 GHz.
1478+ * To avoid this, change PCS mode back to 2500base-x when disabling
1479+ * SerDes from 2500base-x mode.
1480+ */
1481+ err = mv88e6390_serdes_read (chip , lane , MDIO_MMD_PHYXS ,
1482+ MV88E6393X_SERDES_POC , & reg );
1483+ if (err )
1484+ return err ;
1485+
1486+ reg &= ~(MV88E6393X_SERDES_POC_PCS_MASK | MV88E6393X_SERDES_POC_AN );
1487+ if (on )
1488+ reg |= MV88E6393X_SERDES_POC_PCS_1000BASEX |
1489+ MV88E6393X_SERDES_POC_AN ;
1490+ else
1491+ reg |= MV88E6393X_SERDES_POC_PCS_2500BASEX ;
1492+ reg |= MV88E6393X_SERDES_POC_RESET ;
1493+
1494+ err = mv88e6390_serdes_write (chip , lane , MDIO_MMD_PHYXS ,
1495+ MV88E6393X_SERDES_POC , reg );
13421496 if (err )
13431497 return err ;
13441498
1345- err = mv88e6393x_serdes_port_errata (chip , MV88E6393X_PORT9_LANE );
1499+ err = mv88e6390_serdes_write (chip , lane , MDIO_MMD_VEND1 , 0x8000 , 0x58 );
13461500 if (err )
13471501 return err ;
13481502
1349- return mv88e6393x_serdes_port_errata ( chip , MV88E6393X_PORT10_LANE ) ;
1503+ return 0 ;
13501504}
13511505
13521506int mv88e6393x_serdes_power (struct mv88e6xxx_chip * chip , int port , int lane ,
13531507 bool on )
13541508{
13551509 u8 cmode = chip -> ports [port ].cmode ;
1510+ int err ;
13561511
13571512 if (port != 0 && port != 9 && port != 10 )
13581513 return - EOPNOTSUPP ;
13591514
1515+ if (on ) {
1516+ err = mv88e6393x_serdes_erratum_4_8 (chip , lane );
1517+ if (err )
1518+ return err ;
1519+
1520+ err = mv88e6393x_serdes_erratum_5_2 (chip , lane , cmode );
1521+ if (err )
1522+ return err ;
1523+
1524+ err = mv88e6393x_serdes_fix_2500basex_an (chip , lane , cmode ,
1525+ true);
1526+ if (err )
1527+ return err ;
1528+
1529+ err = mv88e6393x_serdes_power_lane (chip , lane , true);
1530+ if (err )
1531+ return err ;
1532+ }
1533+
13601534 switch (cmode ) {
13611535 case MV88E6XXX_PORT_STS_CMODE_SGMII :
13621536 case MV88E6XXX_PORT_STS_CMODE_1000BASEX :
13631537 case MV88E6XXX_PORT_STS_CMODE_2500BASEX :
1364- return mv88e6390_serdes_power_sgmii (chip , lane , on );
1538+ err = mv88e6390_serdes_power_sgmii (chip , lane , on );
1539+ break ;
13651540 case MV88E6393X_PORT_STS_CMODE_5GBASER :
13661541 case MV88E6393X_PORT_STS_CMODE_10GBASER :
1367- return mv88e6390_serdes_power_10g (chip , lane , on );
1542+ err = mv88e6390_serdes_power_10g (chip , lane , on );
1543+ break ;
13681544 }
13691545
1370- return 0 ;
1546+ if (err )
1547+ return err ;
1548+
1549+ if (!on ) {
1550+ err = mv88e6393x_serdes_power_lane (chip , lane , false);
1551+ if (err )
1552+ return err ;
1553+
1554+ err = mv88e6393x_serdes_fix_2500basex_an (chip , lane , cmode ,
1555+ false);
1556+ }
1557+
1558+ return err ;
13711559}
0 commit comments