@@ -39,10 +39,19 @@ enum {
3939 MV_PCS_BASE_R = 0x1000 ,
4040 MV_PCS_1000BASEX = 0x2000 ,
4141
42- MV_PCS_PAIRSWAP = 0x8182 ,
43- MV_PCS_PAIRSWAP_MASK = 0x0003 ,
44- MV_PCS_PAIRSWAP_AB = 0x0002 ,
45- MV_PCS_PAIRSWAP_NONE = 0x0003 ,
42+ MV_PCS_CSSR1 = 0x8008 ,
43+ MV_PCS_CSSR1_SPD1_MASK = 0xc000 ,
44+ MV_PCS_CSSR1_SPD1_SPD2 = 0xc000 ,
45+ MV_PCS_CSSR1_SPD1_1000 = 0x8000 ,
46+ MV_PCS_CSSR1_SPD1_100 = 0x4000 ,
47+ MV_PCS_CSSR1_SPD1_10 = 0x0000 ,
48+ MV_PCS_CSSR1_DUPLEX_FULL = BIT (13 ),
49+ MV_PCS_CSSR1_RESOLVED = BIT (11 ),
50+ MV_PCS_CSSR1_MDIX = BIT (6 ),
51+ MV_PCS_CSSR1_SPD2_MASK = 0x000c ,
52+ MV_PCS_CSSR1_SPD2_5000 = 0x0008 ,
53+ MV_PCS_CSSR1_SPD2_2500 = 0x0004 ,
54+ MV_PCS_CSSR1_SPD2_10000 = 0x0000 ,
4655
4756 /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
4857 * registers appear to set themselves to the 0x800X when AN is
@@ -413,35 +422,18 @@ static void mv3310_update_interface(struct phy_device *phydev)
413422}
414423
415424/* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
416- static int mv3310_read_10gbr_status (struct phy_device * phydev )
425+ static int mv3310_read_status_10gbaser (struct phy_device * phydev )
417426{
418427 phydev -> link = 1 ;
419428 phydev -> speed = SPEED_10000 ;
420429 phydev -> duplex = DUPLEX_FULL ;
421430
422- mv3310_update_interface (phydev );
423-
424431 return 0 ;
425432}
426433
427- static int mv3310_read_status (struct phy_device * phydev )
434+ static int mv3310_read_status_copper (struct phy_device * phydev )
428435{
429- int val ;
430-
431- phydev -> speed = SPEED_UNKNOWN ;
432- phydev -> duplex = DUPLEX_UNKNOWN ;
433- linkmode_zero (phydev -> lp_advertising );
434- phydev -> link = 0 ;
435- phydev -> pause = 0 ;
436- phydev -> asym_pause = 0 ;
437- phydev -> mdix = 0 ;
438-
439- val = phy_read_mmd (phydev , MDIO_MMD_PCS , MV_PCS_BASE_R + MDIO_STAT1 );
440- if (val < 0 )
441- return val ;
442-
443- if (val & MDIO_STAT1_LSTATUS )
444- return mv3310_read_10gbr_status (phydev );
436+ int cssr1 , speed , val ;
445437
446438 val = genphy_c45_read_link (phydev );
447439 if (val < 0 )
@@ -451,6 +443,52 @@ static int mv3310_read_status(struct phy_device *phydev)
451443 if (val < 0 )
452444 return val ;
453445
446+ cssr1 = phy_read_mmd (phydev , MDIO_MMD_PCS , MV_PCS_CSSR1 );
447+ if (cssr1 < 0 )
448+ return val ;
449+
450+ /* If the link settings are not resolved, mark the link down */
451+ if (!(cssr1 & MV_PCS_CSSR1_RESOLVED )) {
452+ phydev -> link = 0 ;
453+ return 0 ;
454+ }
455+
456+ /* Read the copper link settings */
457+ speed = cssr1 & MV_PCS_CSSR1_SPD1_MASK ;
458+ if (speed == MV_PCS_CSSR1_SPD1_SPD2 )
459+ speed |= cssr1 & MV_PCS_CSSR1_SPD2_MASK ;
460+
461+ switch (speed ) {
462+ case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_10000 :
463+ phydev -> speed = SPEED_10000 ;
464+ break ;
465+
466+ case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_5000 :
467+ phydev -> speed = SPEED_5000 ;
468+ break ;
469+
470+ case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_2500 :
471+ phydev -> speed = SPEED_2500 ;
472+ break ;
473+
474+ case MV_PCS_CSSR1_SPD1_1000 :
475+ phydev -> speed = SPEED_1000 ;
476+ break ;
477+
478+ case MV_PCS_CSSR1_SPD1_100 :
479+ phydev -> speed = SPEED_100 ;
480+ break ;
481+
482+ case MV_PCS_CSSR1_SPD1_10 :
483+ phydev -> speed = SPEED_10 ;
484+ break ;
485+ }
486+
487+ phydev -> duplex = cssr1 & MV_PCS_CSSR1_DUPLEX_FULL ?
488+ DUPLEX_FULL : DUPLEX_HALF ;
489+ phydev -> mdix = cssr1 & MV_PCS_CSSR1_MDIX ?
490+ ETH_TP_MDI_X : ETH_TP_MDI ;
491+
454492 if (val & MDIO_AN_STAT1_COMPLETE ) {
455493 val = genphy_c45_read_lpa (phydev );
456494 if (val < 0 )
@@ -463,39 +501,38 @@ static int mv3310_read_status(struct phy_device *phydev)
463501
464502 mii_stat1000_mod_linkmode_lpa_t (phydev -> lp_advertising , val );
465503
466- if ( phydev -> autoneg == AUTONEG_ENABLE )
467- phy_resolve_aneg_linkmode (phydev );
504+ /* Update the pause status */
505+ phy_resolve_aneg_pause (phydev );
468506 }
469507
470- if (phydev -> autoneg != AUTONEG_ENABLE ) {
471- val = genphy_c45_read_pma (phydev );
472- if (val < 0 )
473- return val ;
474- }
508+ return 0 ;
509+ }
475510
476- if (phydev -> speed == SPEED_10000 ) {
477- val = genphy_c45_read_mdix (phydev );
478- if (val < 0 )
479- return val ;
480- } else {
481- val = phy_read_mmd (phydev , MDIO_MMD_PCS , MV_PCS_PAIRSWAP );
482- if (val < 0 )
483- return val ;
511+ static int mv3310_read_status (struct phy_device * phydev )
512+ {
513+ int err , val ;
484514
485- switch (val & MV_PCS_PAIRSWAP_MASK ) {
486- case MV_PCS_PAIRSWAP_AB :
487- phydev -> mdix = ETH_TP_MDI_X ;
488- break ;
489- case MV_PCS_PAIRSWAP_NONE :
490- phydev -> mdix = ETH_TP_MDI ;
491- break ;
492- default :
493- phydev -> mdix = ETH_TP_MDI_INVALID ;
494- break ;
495- }
496- }
515+ phydev -> speed = SPEED_UNKNOWN ;
516+ phydev -> duplex = DUPLEX_UNKNOWN ;
517+ linkmode_zero (phydev -> lp_advertising );
518+ phydev -> link = 0 ;
519+ phydev -> pause = 0 ;
520+ phydev -> asym_pause = 0 ;
521+ phydev -> mdix = ETH_TP_MDI_INVALID ;
497522
498- mv3310_update_interface (phydev );
523+ val = phy_read_mmd (phydev , MDIO_MMD_PCS , MV_PCS_BASE_R + MDIO_STAT1 );
524+ if (val < 0 )
525+ return val ;
526+
527+ if (val & MDIO_STAT1_LSTATUS )
528+ err = mv3310_read_status_10gbaser (phydev );
529+ else
530+ err = mv3310_read_status_copper (phydev );
531+ if (err < 0 )
532+ return err ;
533+
534+ if (phydev -> link )
535+ mv3310_update_interface (phydev );
499536
500537 return 0 ;
501538}
0 commit comments