[OpenWrt-Devel] [PATCH 2/2] kernel: add at803x fix for sgmii mode

Roman Yeryomin leroi.lists at gmail.com
Sat Dec 19 19:30:39 EST 2015


Some (possibly broken) bootloaders incorreclty initialize at8033
phy. This patch enables sgmii autonegotiation mode.

Signed-off-by: Roman Yeryomin <roman at advem.lv>
---
 .../735-net-phy-at803x-fix-at8033-sgmii-mode.patch | 96 ++++++++++++++++++++++
 .../735-net-phy-at803x-fix-at8033-sgmii-mode.patch | 96 ++++++++++++++++++++++
 .../735-net-phy-at803x-fix-at8033-sgmii-mode.patch | 96 ++++++++++++++++++++++
 .../735-net-phy-at803x-fix-at8033-sgmii-mode.patch | 96 ++++++++++++++++++++++
 4 files changed, 384 insertions(+)
 create mode 100644 target/linux/generic/patches-3.18/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
 create mode 100644 target/linux/generic/patches-4.1/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
 create mode 100644 target/linux/generic/patches-4.3/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
 create mode 100644 target/linux/generic/patches-4.4/735-net-phy-at803x-fix-at8033-sgmii-mode.patch

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 0000000..117f15d
--- /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 },
+ 	{ }
+ };
+ 
diff --git a/target/linux/generic/patches-4.1/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/target/linux/generic/patches-4.1/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
new file mode 100644
index 0000000..117f15d
--- /dev/null
+++ b/target/linux/generic/patches-4.1/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 },
+ 	{ }
+ };
+ 
diff --git a/target/linux/generic/patches-4.3/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/target/linux/generic/patches-4.3/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
new file mode 100644
index 0000000..117f15d
--- /dev/null
+++ b/target/linux/generic/patches-4.3/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 },
+ 	{ }
+ };
+ 
diff --git a/target/linux/generic/patches-4.4/735-net-phy-at803x-fix-at8033-sgmii-mode.patch b/target/linux/generic/patches-4.4/735-net-phy-at803x-fix-at8033-sgmii-mode.patch
new file mode 100644
index 0000000..117f15d
--- /dev/null
+++ b/target/linux/generic/patches-4.4/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 },
+ 	{ }
+ };
+ 
-- 
2.5.0
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list