|
66 | 66 | #define MII_M1111_PHY_LED_DIRECT 0x4100 |
67 | 67 | #define MII_M1111_PHY_LED_COMBINE 0x411c |
68 | 68 | #define MII_M1111_PHY_EXT_CR 0x14 |
| 69 | +#define MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK GENMASK(11, 9) |
| 70 | +#define MII_M1111_PHY_EXT_CR_DOWNSHIFT_MAX 8 |
| 71 | +#define MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN BIT(8) |
69 | 72 | #define MII_M1111_RGMII_RX_DELAY BIT(7) |
70 | 73 | #define MII_M1111_RGMII_TX_DELAY BIT(1) |
71 | 74 | #define MII_M1111_PHY_EXT_SR 0x1b |
@@ -784,6 +787,64 @@ static int m88e1111_config_init(struct phy_device *phydev) |
784 | 787 | return genphy_soft_reset(phydev); |
785 | 788 | } |
786 | 789 |
|
| 790 | +static int m88e1111_get_downshift(struct phy_device *phydev, u8 *data) |
| 791 | +{ |
| 792 | + int val, cnt, enable; |
| 793 | + |
| 794 | + val = phy_read(phydev, MII_M1111_PHY_EXT_CR); |
| 795 | + if (val < 0) |
| 796 | + return val; |
| 797 | + |
| 798 | + enable = FIELD_GET(MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN, val); |
| 799 | + cnt = FIELD_GET(MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK, val) + 1; |
| 800 | + |
| 801 | + *data = enable ? cnt : DOWNSHIFT_DEV_DISABLE; |
| 802 | + |
| 803 | + return 0; |
| 804 | +} |
| 805 | + |
| 806 | +static int m88e1111_set_downshift(struct phy_device *phydev, u8 cnt) |
| 807 | +{ |
| 808 | + int val; |
| 809 | + |
| 810 | + if (cnt > MII_M1111_PHY_EXT_CR_DOWNSHIFT_MAX) |
| 811 | + return -E2BIG; |
| 812 | + |
| 813 | + if (!cnt) |
| 814 | + return phy_clear_bits(phydev, MII_M1111_PHY_EXT_CR, |
| 815 | + MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN); |
| 816 | + |
| 817 | + val = MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN; |
| 818 | + val |= FIELD_PREP(MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK, cnt - 1); |
| 819 | + |
| 820 | + return phy_modify(phydev, MII_M1111_PHY_EXT_CR, |
| 821 | + MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN | |
| 822 | + MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK, |
| 823 | + val); |
| 824 | +} |
| 825 | + |
| 826 | +static int m88e1111_get_tunable(struct phy_device *phydev, |
| 827 | + struct ethtool_tunable *tuna, void *data) |
| 828 | +{ |
| 829 | + switch (tuna->id) { |
| 830 | + case ETHTOOL_PHY_DOWNSHIFT: |
| 831 | + return m88e1111_get_downshift(phydev, data); |
| 832 | + default: |
| 833 | + return -EOPNOTSUPP; |
| 834 | + } |
| 835 | +} |
| 836 | + |
| 837 | +static int m88e1111_set_tunable(struct phy_device *phydev, |
| 838 | + struct ethtool_tunable *tuna, const void *data) |
| 839 | +{ |
| 840 | + switch (tuna->id) { |
| 841 | + case ETHTOOL_PHY_DOWNSHIFT: |
| 842 | + return m88e1111_set_downshift(phydev, *(const u8 *)data); |
| 843 | + default: |
| 844 | + return -EOPNOTSUPP; |
| 845 | + } |
| 846 | +} |
| 847 | + |
787 | 848 | static int m88e1011_get_downshift(struct phy_device *phydev, u8 *data) |
788 | 849 | { |
789 | 850 | int val, cnt, enable; |
@@ -2245,6 +2306,9 @@ static struct phy_driver marvell_drivers[] = { |
2245 | 2306 | .get_sset_count = marvell_get_sset_count, |
2246 | 2307 | .get_strings = marvell_get_strings, |
2247 | 2308 | .get_stats = marvell_get_stats, |
| 2309 | + .get_tunable = m88e1111_get_tunable, |
| 2310 | + .set_tunable = m88e1111_set_tunable, |
| 2311 | + .link_change_notify = m88e1011_link_change_notify, |
2248 | 2312 | }, |
2249 | 2313 | { |
2250 | 2314 | .phy_id = MARVELL_PHY_ID_88E1118, |
|
0 commit comments