From 3d9a3f35be0bb83ecb986a76d34cc5f1623340df Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 29 Nov 2016 15:29:19 +0100 Subject: [PATCH] kernel: add at803x workaround for sgmii mode (#949) Some (possibly broken) bootloaders incorrectly initialize the at8033 phy. This breaks auto-negotation on these SGMII devices. The mode has therefore to be set back in to a valid configuration by Linux. Fixes #911 --- ...kernel-add-at803x-fix-for-sgmii-mode.patch | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 patches/openwrt/0081-kernel-add-at803x-fix-for-sgmii-mode.patch diff --git a/patches/openwrt/0081-kernel-add-at803x-fix-for-sgmii-mode.patch b/patches/openwrt/0081-kernel-add-at803x-fix-for-sgmii-mode.patch new file mode 100644 index 00000000..f2967b1a --- /dev/null +++ b/patches/openwrt/0081-kernel-add-at803x-fix-for-sgmii-mode.patch @@ -0,0 +1,114 @@ +From: Felix Fietkau +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 + +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 +index 0000000..4a8f532 +--- /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 }, ++ { } ++ }; ++