@@ -661,6 +661,129 @@ int genphy_c45_read_mdix(struct phy_device *phydev)
661661}
662662EXPORT_SYMBOL_GPL (genphy_c45_read_mdix );
663663
664+ /**
665+ * genphy_c45_write_eee_adv - write advertised EEE link modes
666+ * @phydev: target phy_device struct
667+ * @adv: the linkmode advertisement settings
668+ */
669+ int genphy_c45_write_eee_adv (struct phy_device * phydev , unsigned long * adv )
670+ {
671+ int val , changed ;
672+
673+ if (linkmode_intersects (phydev -> supported , PHY_EEE_CAP1_FEATURES )) {
674+ val = linkmode_to_mii_eee_cap1_t (adv );
675+
676+ /* In eee_broken_modes are stored MDIO_AN_EEE_ADV specific raw
677+ * register values.
678+ */
679+ val &= ~phydev -> eee_broken_modes ;
680+
681+ /* IEEE 802.3-2018 45.2.7.13 EEE advertisement 1
682+ * (Register 7.60)
683+ */
684+ val = phy_modify_mmd_changed (phydev , MDIO_MMD_AN ,
685+ MDIO_AN_EEE_ADV ,
686+ MDIO_EEE_100TX | MDIO_EEE_1000T |
687+ MDIO_EEE_10GT | MDIO_EEE_1000KX |
688+ MDIO_EEE_10GKX4 | MDIO_EEE_10GKR ,
689+ val );
690+ if (val < 0 )
691+ return val ;
692+ if (val > 0 )
693+ changed = 1 ;
694+ }
695+
696+ if (linkmode_test_bit (ETHTOOL_LINK_MODE_10baseT1L_Full_BIT ,
697+ phydev -> supported_eee )) {
698+ val = linkmode_adv_to_mii_10base_t1_t (adv );
699+ /* IEEE 802.3cg-2019 45.2.7.25 10BASE-T1 AN control register
700+ * (Register 7.526)
701+ */
702+ val = phy_modify_mmd_changed (phydev , MDIO_MMD_AN ,
703+ MDIO_AN_10BT1_AN_CTRL ,
704+ MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L ,
705+ val );
706+ if (val < 0 )
707+ return val ;
708+ if (val > 0 )
709+ changed = 1 ;
710+ }
711+
712+ return changed ;
713+ }
714+
715+ /**
716+ * genphy_c45_read_eee_adv - read advertised EEE link modes
717+ * @phydev: target phy_device struct
718+ * @adv: the linkmode advertisement status
719+ */
720+ static int genphy_c45_read_eee_adv (struct phy_device * phydev ,
721+ unsigned long * adv )
722+ {
723+ int val ;
724+
725+ if (linkmode_intersects (phydev -> supported , PHY_EEE_CAP1_FEATURES )) {
726+ /* IEEE 802.3-2018 45.2.7.13 EEE advertisement 1
727+ * (Register 7.60)
728+ */
729+ val = phy_read_mmd (phydev , MDIO_MMD_AN , MDIO_AN_EEE_ADV );
730+ if (val < 0 )
731+ return val ;
732+
733+ mii_eee_cap1_mod_linkmode_t (adv , val );
734+ }
735+
736+ if (linkmode_test_bit (ETHTOOL_LINK_MODE_10baseT1L_Full_BIT ,
737+ phydev -> supported_eee )) {
738+ /* IEEE 802.3cg-2019 45.2.7.25 10BASE-T1 AN control register
739+ * (Register 7.526)
740+ */
741+ val = phy_read_mmd (phydev , MDIO_MMD_AN , MDIO_AN_10BT1_AN_CTRL );
742+ if (val < 0 )
743+ return val ;
744+
745+ mii_10base_t1_adv_mod_linkmode_t (adv , val );
746+ }
747+
748+ return 0 ;
749+ }
750+
751+ /**
752+ * genphy_c45_read_eee_lpa - read advertised LP EEE link modes
753+ * @phydev: target phy_device struct
754+ * @lpa: the linkmode LP advertisement status
755+ */
756+ static int genphy_c45_read_eee_lpa (struct phy_device * phydev ,
757+ unsigned long * lpa )
758+ {
759+ int val ;
760+
761+ if (linkmode_intersects (phydev -> supported , PHY_EEE_CAP1_FEATURES )) {
762+ /* IEEE 802.3-2018 45.2.7.14 EEE link partner ability 1
763+ * (Register 7.61)
764+ */
765+ val = phy_read_mmd (phydev , MDIO_MMD_AN , MDIO_AN_EEE_LPABLE );
766+ if (val < 0 )
767+ return val ;
768+
769+ mii_eee_cap1_mod_linkmode_t (lpa , val );
770+ }
771+
772+ if (linkmode_test_bit (ETHTOOL_LINK_MODE_10baseT1L_Full_BIT ,
773+ phydev -> supported_eee )) {
774+ /* IEEE 802.3cg-2019 45.2.7.26 10BASE-T1 AN status register
775+ * (Register 7.527)
776+ */
777+ val = phy_read_mmd (phydev , MDIO_MMD_AN , MDIO_AN_10BT1_AN_STAT );
778+ if (val < 0 )
779+ return val ;
780+
781+ mii_10base_t1_adv_mod_linkmode_t (lpa , val );
782+ }
783+
784+ return 0 ;
785+ }
786+
664787/**
665788 * genphy_c45_read_eee_cap1 - read supported EEE link modes from register 3.20
666789 * @phydev: target phy_device struct
@@ -1194,6 +1317,121 @@ int genphy_c45_plca_get_status(struct phy_device *phydev,
11941317}
11951318EXPORT_SYMBOL_GPL (genphy_c45_plca_get_status );
11961319
1320+ /**
1321+ * genphy_c45_eee_is_active - get EEE status
1322+ * @phydev: target phy_device struct
1323+ * @adv: variable to store advertised linkmodes
1324+ * @lp: variable to store LP advertised linkmodes
1325+ * @is_enabled: variable to store EEE enabled/disabled configuration value
1326+ *
1327+ * Description: this function will read local and link partner PHY
1328+ * advertisements. Compare them return current EEE state.
1329+ */
1330+ int genphy_c45_eee_is_active (struct phy_device * phydev , unsigned long * adv ,
1331+ unsigned long * lp , bool * is_enabled )
1332+ {
1333+ __ETHTOOL_DECLARE_LINK_MODE_MASK (tmp_adv ) = {};
1334+ __ETHTOOL_DECLARE_LINK_MODE_MASK (tmp_lp ) = {};
1335+ __ETHTOOL_DECLARE_LINK_MODE_MASK (common );
1336+ bool eee_enabled , eee_active ;
1337+ int ret ;
1338+
1339+ ret = genphy_c45_read_eee_adv (phydev , tmp_adv );
1340+ if (ret )
1341+ return ret ;
1342+
1343+ ret = genphy_c45_read_eee_lpa (phydev , tmp_lp );
1344+ if (ret )
1345+ return ret ;
1346+
1347+ eee_enabled = !linkmode_empty (tmp_adv );
1348+ linkmode_and (common , tmp_adv , tmp_lp );
1349+ if (eee_enabled && !linkmode_empty (common ))
1350+ eee_active = phy_check_valid (phydev -> speed , phydev -> duplex ,
1351+ common );
1352+ else
1353+ eee_active = false;
1354+
1355+ if (adv )
1356+ linkmode_copy (adv , tmp_adv );
1357+ if (lp )
1358+ linkmode_copy (lp , tmp_lp );
1359+ if (is_enabled )
1360+ * is_enabled = eee_enabled ;
1361+
1362+ return eee_active ;
1363+ }
1364+ EXPORT_SYMBOL (genphy_c45_eee_is_active );
1365+
1366+ /**
1367+ * genphy_c45_ethtool_get_eee - get EEE supported and status
1368+ * @phydev: target phy_device struct
1369+ * @data: ethtool_eee data
1370+ *
1371+ * Description: it reports the Supported/Advertisement/LP Advertisement
1372+ * capabilities.
1373+ */
1374+ int genphy_c45_ethtool_get_eee (struct phy_device * phydev ,
1375+ struct ethtool_eee * data )
1376+ {
1377+ __ETHTOOL_DECLARE_LINK_MODE_MASK (adv ) = {};
1378+ __ETHTOOL_DECLARE_LINK_MODE_MASK (lp ) = {};
1379+ bool overflow = false, is_enabled ;
1380+ int ret ;
1381+
1382+ ret = genphy_c45_eee_is_active (phydev , adv , lp , & is_enabled );
1383+ if (ret < 0 )
1384+ return ret ;
1385+
1386+ data -> eee_enabled = is_enabled ;
1387+ data -> eee_active = ret ;
1388+
1389+ if (!ethtool_convert_link_mode_to_legacy_u32 (& data -> supported ,
1390+ phydev -> supported_eee ))
1391+ overflow = true;
1392+ if (!ethtool_convert_link_mode_to_legacy_u32 (& data -> advertised , adv ))
1393+ overflow = true;
1394+ if (!ethtool_convert_link_mode_to_legacy_u32 (& data -> lp_advertised , lp ))
1395+ overflow = true;
1396+
1397+ if (overflow )
1398+ phydev_warn (phydev , "Not all supported or advertised EEE link modes were passed to the user space\n" );
1399+
1400+ return 0 ;
1401+ }
1402+ EXPORT_SYMBOL (genphy_c45_ethtool_get_eee );
1403+
1404+ /**
1405+ * genphy_c45_ethtool_set_eee - get EEE supported and status
1406+ * @phydev: target phy_device struct
1407+ * @data: ethtool_eee data
1408+ *
1409+ * Description: it reportes the Supported/Advertisement/LP Advertisement
1410+ * capabilities.
1411+ */
1412+ int genphy_c45_ethtool_set_eee (struct phy_device * phydev ,
1413+ struct ethtool_eee * data )
1414+ {
1415+ __ETHTOOL_DECLARE_LINK_MODE_MASK (adv ) = {};
1416+ int ret ;
1417+
1418+ if (data -> eee_enabled ) {
1419+ if (data -> advertised )
1420+ adv [0 ] = data -> advertised ;
1421+ else
1422+ linkmode_copy (adv , phydev -> supported_eee );
1423+ }
1424+
1425+ ret = genphy_c45_write_eee_adv (phydev , adv );
1426+ if (ret < 0 )
1427+ return ret ;
1428+ if (ret > 0 )
1429+ return phy_restart_aneg (phydev );
1430+
1431+ return 0 ;
1432+ }
1433+ EXPORT_SYMBOL (genphy_c45_ethtool_set_eee );
1434+
11971435struct phy_driver genphy_c45_driver = {
11981436 .phy_id = 0xffffffff ,
11991437 .phy_id_mask = 0xffffffff ,
0 commit comments