aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch')
-rw-r--r--target/linux/generic/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch96
1 files changed, 96 insertions, 0 deletions
diff --git a/target/linux/generic/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/target/linux/generic/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
new file mode 100644
index 0000000000..117f15d634
--- /dev/null
+++ b/target/linux/generic/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
@@ -0,0 +1,96 @@
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -36,6 +36,9 @@
+ #define AT803X_INER 0x0012
+ #define AT803X_INER_INIT 0xec00
+ #define AT803X_INSR 0x0013
++#define AT803X_REG_CHIP_CONFIG 0x1f
++#define AT803X_BT_BX_REG_SEL 0x8000
++#define AT803X_SGMII_ANEG_EN 0x1000
+
+ #define AT803X_PCS_SMART_EEE_CTRL3 0x805D
+ #define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK 0x3
+@@ -49,9 +52,10 @@
+ #define AT803X_DEBUG_SYSTEM_MODE_CTRL 0x05
+ #define AT803X_DEBUG_RGMII_TX_CLK_DLY BIT(8)
+
+-#define ATH8030_PHY_ID 0x004dd076
+-#define ATH8031_PHY_ID 0x004dd074
+-#define ATH8035_PHY_ID 0x004dd072
++#define AT803X_PHY_ID_MASK 0xffffffef
++#define ATH8030_PHY_ID 0x004dd076
++#define ATH8031_PHY_ID 0x004dd074
++#define ATH8035_PHY_ID 0x004dd072
+
+ MODULE_DESCRIPTION("Atheros 803x PHY driver");
+ MODULE_AUTHOR("Matus Ujhelyi");
+@@ -268,6 +272,27 @@ static int at803x_config_init(struct phy
+ {
+ struct at803x_platform_data *pdata;
+ int ret;
++ u32 v;
++
++ if (phydev->drv->phy_id == ATH8031_PHY_ID &&
++ phydev->interface == PHY_INTERFACE_MODE_SGMII)
++ {
++ v = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
++ /* select SGMII/fiber page */
++ ret = phy_write(phydev, AT803X_REG_CHIP_CONFIG,
++ v & ~AT803X_BT_BX_REG_SEL);
++ if (ret)
++ return ret;
++ /* enable SGMII autonegotiation */
++ ret = phy_write(phydev, MII_BMCR, AT803X_SGMII_ANEG_EN);
++ if (ret)
++ return ret;
++ /* select copper page */
++ ret = phy_write(phydev, AT803X_REG_CHIP_CONFIG,
++ v | AT803X_BT_BX_REG_SEL);
++ if (ret)
++ return ret;
++ }
+
+ ret = genphy_config_init(phydev);
+ if (ret < 0)
+@@ -394,7 +419,7 @@ static struct phy_driver at803x_driver[]
+ /* ATHEROS 8035 */
+ .phy_id = ATH8035_PHY_ID,
+ .name = "Atheros 8035 ethernet",
+- .phy_id_mask = 0xffffffef,
++ .phy_id_mask = AT803X_PHY_ID_MASK,
+ .probe = at803x_probe,
+ .config_init = at803x_config_init,
+ .link_change_notify = at803x_link_change_notify,
+@@ -413,7 +438,7 @@ static struct phy_driver at803x_driver[]
+ /* ATHEROS 8030 */
+ .phy_id = ATH8030_PHY_ID,
+ .name = "Atheros 8030 ethernet",
+- .phy_id_mask = 0xffffffef,
++ .phy_id_mask = AT803X_PHY_ID_MASK,
+ .probe = at803x_probe,
+ .config_init = at803x_config_init,
+ .link_change_notify = at803x_link_change_notify,
+@@ -431,8 +456,8 @@ static struct phy_driver at803x_driver[]
+ }, {
+ /* ATHEROS 8031 */
+ .phy_id = ATH8031_PHY_ID,
+- .name = "Atheros 8031 ethernet",
+- .phy_id_mask = 0xffffffef,
++ .name = "Atheros 8031/8033 ethernet",
++ .phy_id_mask = AT803X_PHY_ID_MASK,
+ .probe = at803x_probe,
+ .config_init = at803x_config_init,
+ .link_change_notify = at803x_link_change_notify,
+@@ -454,9 +479,9 @@ static struct phy_driver at803x_driver[]
+ module_phy_driver(at803x_driver);
+
+ static struct mdio_device_id __maybe_unused atheros_tbl[] = {
+- { ATH8030_PHY_ID, 0xffffffef },
+- { ATH8031_PHY_ID, 0xffffffef },
+- { ATH8035_PHY_ID, 0xffffffef },
++ { ATH8030_PHY_ID, AT803X_PHY_ID_MASK },
++ { ATH8031_PHY_ID, AT803X_PHY_ID_MASK },
++ { ATH8035_PHY_ID, AT803X_PHY_ID_MASK },
+ { }
+ };
+