kernel: add at803x workaround for sgmii mode (#950)
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
This commit is contained in:
		
							parent
							
								
									59deb2064d
								
							
						
					
					
						commit
						d54c9c5fb7
					
				
							
								
								
									
										114
									
								
								patches/openwrt/0081-kernel-add-at803x-fix-for-sgmii-mode.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								patches/openwrt/0081-kernel-add-at803x-fix-for-sgmii-mode.patch
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
			
		||||
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
 | 
			
		||||
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 },
 | 
			
		||||
+ 	{ }
 | 
			
		||||
+ };
 | 
			
		||||
+ 
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user