@@ -661,6 +661,129 @@ int genphy_c45_read_mdix(struct phy_device *phydev)
661
661
}
662
662
EXPORT_SYMBOL_GPL (genphy_c45_read_mdix );
663
663
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
+
664
787
/**
665
788
* genphy_c45_read_eee_cap1 - read supported EEE link modes from register 3.20
666
789
* @phydev: target phy_device struct
@@ -1194,6 +1317,121 @@ int genphy_c45_plca_get_status(struct phy_device *phydev,
1194
1317
}
1195
1318
EXPORT_SYMBOL_GPL (genphy_c45_plca_get_status );
1196
1319
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
+
1197
1435
struct phy_driver genphy_c45_driver = {
1198
1436
.phy_id = 0xffffffff ,
1199
1437
.phy_id_mask = 0xffffffff ,
0 commit comments