2016-11-29 14:29:19 +00:00
|
|
|
From: Felix Fietkau <nbd@openwrt.org>
|
|
|
|
Date: Sun, 27 Nov 2016 22:49:27 +0100
|
|
|
|
Subject: kernel: add at803x fix for sgmii mode
|
|
|
|
|
|
|
|
Some (possibly broken) bootloaders incorreclty initialize at8033
|
|
|
|
phy. This patch enables sgmii autonegotiation mode.
|
|
|
|
|
|
|
|
Signed-off-by: Roman Yeryomin <roman@advem.lv>
|
|
|
|
|
|
|
|
Origin: backport, https://git.lede-project.org/?p=source.git;a=commit;h=e14d2aee0ab91c43d0bb14baf84cc9b997185870
|
|
|
|
Bug-gluon: https://github.com/freifunk-gluon/gluon/issues/911
|
|
|
|
|
|
|
|
diff --git a/target/linux/ar71xx/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/target/linux/ar71xx/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
|
|
|
|
new file mode 100644
|
2016-12-20 00:09:53 +00:00
|
|
|
index 0000000000000000000000000000000000000000..4a8f532aa36f729339e01ebadd6ea3cb292d7ac9
|
2016-11-29 14:29:19 +00:00
|
|
|
--- /dev/null
|
|
|
|
+++ b/target/linux/ar71xx/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");
|
|
|
|
+@@ -267,6 +271,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)
|
|
|
|
+@@ -393,7 +418,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,
|
|
|
|
+@@ -412,7 +437,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,
|
|
|
|
+@@ -430,8 +455,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,
|
|
|
|
+@@ -465,9 +490,9 @@ module_init(atheros_init);
|
|
|
|
+ module_exit(atheros_exit);
|
|
|
|
+
|
|
|
|
+ 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 },
|
|
|
|
+ { }
|
|
|
|
+ };
|
|
|
|
+
|