Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: phy: at803x: add mdix configuration support for AR9331 and AR8035

This patch add MDIX configuration ability for AR9331 and AR8035. Theoretically
it should work on other Atheros PHYs, but I was able to test only this
two.

Since I have no certified reference HW able to detect or configure MDIX, this
functionality was confirmed by oscilloscope.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Oleksij Rempel and committed by
David S. Miller
7dce80c2 ff9a8c48

+78
+78
drivers/net/phy/at803x.c
··· 21 21 #include <linux/regulator/consumer.h> 22 22 #include <dt-bindings/net/qca-ar803x.h> 23 23 24 + #define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10 25 + #define AT803X_SFC_ASSERT_CRS BIT(11) 26 + #define AT803X_SFC_FORCE_LINK BIT(10) 27 + #define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5) 28 + #define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3 29 + #define AT803X_SFC_MANUAL_MDIX 0x1 30 + #define AT803X_SFC_MANUAL_MDI 0x0 31 + #define AT803X_SFC_SQE_TEST BIT(2) 32 + #define AT803X_SFC_POLARITY_REVERSAL BIT(1) 33 + #define AT803X_SFC_DISABLE_JABBER BIT(0) 34 + 24 35 #define AT803X_SPECIFIC_STATUS 0x11 25 36 #define AT803X_SS_SPEED_MASK (3 << 14) 26 37 #define AT803X_SS_SPEED_1000 (2 << 14) ··· 714 703 return ss; 715 704 716 705 if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) { 706 + int sfc; 707 + 708 + sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL); 709 + if (sfc < 0) 710 + return sfc; 711 + 717 712 switch (ss & AT803X_SS_SPEED_MASK) { 718 713 case AT803X_SS_SPEED_10: 719 714 phydev->speed = SPEED_10; ··· 735 718 phydev->duplex = DUPLEX_FULL; 736 719 else 737 720 phydev->duplex = DUPLEX_HALF; 721 + 738 722 if (ss & AT803X_SS_MDIX) 739 723 phydev->mdix = ETH_TP_MDI_X; 740 724 else 741 725 phydev->mdix = ETH_TP_MDI; 726 + 727 + switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) { 728 + case AT803X_SFC_MANUAL_MDI: 729 + phydev->mdix_ctrl = ETH_TP_MDI; 730 + break; 731 + case AT803X_SFC_MANUAL_MDIX: 732 + phydev->mdix_ctrl = ETH_TP_MDI_X; 733 + break; 734 + case AT803X_SFC_AUTOMATIC_CROSSOVER: 735 + phydev->mdix_ctrl = ETH_TP_MDI_AUTO; 736 + break; 737 + } 742 738 } 743 739 744 740 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) 745 741 phy_resolve_aneg_pause(phydev); 746 742 747 743 return 0; 744 + } 745 + 746 + static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl) 747 + { 748 + u16 val; 749 + 750 + switch (ctrl) { 751 + case ETH_TP_MDI: 752 + val = AT803X_SFC_MANUAL_MDI; 753 + break; 754 + case ETH_TP_MDI_X: 755 + val = AT803X_SFC_MANUAL_MDIX; 756 + break; 757 + case ETH_TP_MDI_AUTO: 758 + val = AT803X_SFC_AUTOMATIC_CROSSOVER; 759 + break; 760 + default: 761 + return 0; 762 + } 763 + 764 + return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL, 765 + AT803X_SFC_MDI_CROSSOVER_MODE_M, 766 + FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val)); 767 + } 768 + 769 + static int at803x_config_aneg(struct phy_device *phydev) 770 + { 771 + int ret; 772 + 773 + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl); 774 + if (ret < 0) 775 + return ret; 776 + 777 + /* Changes of the midx bits are disruptive to the normal operation; 778 + * therefore any changes to these registers must be followed by a 779 + * software reset to take effect. 780 + */ 781 + if (ret == 1) { 782 + ret = genphy_soft_reset(phydev); 783 + if (ret < 0) 784 + return ret; 785 + } 786 + 787 + return genphy_config_aneg(phydev); 748 788 } 749 789 750 790 static int at803x_get_downshift(struct phy_device *phydev, u8 *d) ··· 1053 979 .flags = PHY_POLL_CABLE_TEST, 1054 980 .probe = at803x_probe, 1055 981 .remove = at803x_remove, 982 + .config_aneg = at803x_config_aneg, 1056 983 .config_init = at803x_config_init, 1057 984 .soft_reset = genphy_soft_reset, 1058 985 .set_wol = at803x_set_wol, ··· 1136 1061 .config_intr = &at803x_config_intr, 1137 1062 .cable_test_start = at803x_cable_test_start, 1138 1063 .cable_test_get_status = at803x_cable_test_get_status, 1064 + .read_status = at803x_read_status, 1065 + .soft_reset = genphy_soft_reset, 1066 + .config_aneg = at803x_config_aneg, 1139 1067 } }; 1140 1068 1141 1069 module_phy_driver(at803x_driver);