aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4103-modifying-link-and-led-state-with-respect-to-cable-c.patch
blob: 447629ee039381fe39a3e3e46230be2202911194 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
From 89a9f6eee64e54ce282584cfc7bedcdd944f7c4b Mon Sep 17 00:00:00 2001
From: Pavan Kumar Ramayanam <pavan.ramayanam@amd.com>
Date: Tue, 12 Nov 2019 18:15:16 +0530
Subject: [PATCH 4103/4736] modifying link and led state with respect to cable
 connection

 Enable Marvell PHY 10G linkup on Bilby. The current
 10G linkup happens only in backplane mode, meaning there will be no sideband
 to talk to the external PHY connected onboard. So, when the driver reads the
 port property as BACKPLANE, technically we are not supposed to go and read
 what is the external PHY connected through MDIO. This changes are only a
 workaround to read the external phy through MDIO in backplane mode.
---
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 30 ++++++--
 drivers/net/phy/marvell10g.c                | 80 ++++++++++++++++++++-
 2 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 9cddcc8433e1..a6fb6754984f 100755
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -156,6 +156,11 @@
 /* RRC frequency during link status check */
 #define XGBE_RRC_FREQUENCY		10
 
+/* Enable Marvell PHY writes by forcing the MDIO connections */
+static int force_mdio_mv_bp_con = 1;
+module_param(force_mdio_mv_bp_con, uint, 0644);
+MODULE_PARM_DESC(force_mdio_mv_bp_con,
+                 " Enable Marvell PHY writes by forcing the MDIO connections");
 enum xgbe_port_mode {
 	XGBE_PORT_MODE_RSVD = 0,
 	XGBE_PORT_MODE_BACKPLANE,
@@ -985,8 +990,15 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
 	pdata->an_again = 0;
 
 	/* Check for the use of an external PHY */
-	if (phy_data->phydev_mode == XGBE_MDIO_MODE_NONE)
-		return 0;
+	if (phy_data->phydev_mode == XGBE_MDIO_MODE_NONE) {
+		if(force_mdio_mv_bp_con) {
+			phy_data->phydev_mode = XGBE_MDIO_MODE_CL45;
+			phy_data->conn_type = XGBE_CONN_TYPE_MDIO;
+			netif_dbg(pdata, drv, pdata->netdev, "*** DEBUG: %s - bypass phydev_mode check\n", __func__);
+		} else {
+			return 0;
+		}
+	}
 
 	/* For SFP, only use an external PHY if available */
 	if ((phy_data->port_mode == XGBE_PORT_MODE_SFP) &&
@@ -1011,7 +1023,7 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
 		return -ENODEV;
 	}
 	netif_dbg(pdata, drv, pdata->netdev, "external PHY id is %#010x\n",
-		  phydev->phy_id);
+		 (phy_data->phydev_mode == XGBE_MDIO_MODE_CL45) ? phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] : phydev->phy_id);
 
 	/*TODO: If c45, add request_module based on one of the MMD ids? */
 
@@ -1034,6 +1046,14 @@ static int xgbe_phy_find_phy_device(struct xgbe_prv_data *pdata)
 
 	xgbe_phy_external_phy_quirks(pdata);
 
+	if(force_mdio_mv_bp_con) {
+		phy_data->phydev_mode = XGBE_MDIO_MODE_NONE;
+		phy_data->conn_type = XGBE_CONN_TYPE_BACKPLANE;
+		netif_dbg(pdata, drv, pdata->netdev, "phy_dev removed!\n");
+		xgbe_phy_free_phy_device(pdata);
+		return 0;
+	}
+
 	ethtool_convert_link_mode_to_legacy_u32(&advertising,
 						lks->link_modes.advertising);
 	phydev->advertising &= advertising;
@@ -2551,8 +2571,10 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
 			return 0;
 
 		if ((pdata->phy.autoneg == AUTONEG_ENABLE) &&
-		    !phy_aneg_done(phy_data->phydev))
+		    !phy_aneg_done(phy_data->phydev)) {
+			netif_dbg(pdata, drv, pdata->netdev,"%s Ext phy AN not complete!\n", __func__);
 			return 0;
+               }
 
 		if (!phy_data->phydev->link)
 			return 0;
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index f77a2d9e7f9d..080272a3d2b6 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -25,6 +25,7 @@
 #include <linux/hwmon.h>
 #include <linux/marvell_phy.h>
 #include <linux/phy.h>
+#include <linux/delay.h>
 
 enum {
 	MV_PCS_BASE_T		= 0x0000,
@@ -48,7 +49,12 @@ enum {
 	MV_V2_TEMP_CTRL_MASK	= 0xc000,
 	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
 	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
+	MV_V2_MODE_CFG		= 0xf000,
+	MV_V2_PORT_CTRL		= 0xf001,
+	MV_V2_LED0_CTRL		= 0xf020,
 	MV_V2_TEMP		= 0xf08c,
+	MV_V2_HOST_KR_ENABLE    = 0xf084,
+	MV_V2_HOST_KR_TUNE      = 0xf07c,
 	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
 };
 
@@ -75,7 +81,7 @@ static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
 	return ret < 0 ? ret : 1;
 }
 
-#ifdef CONFIG_HWMON
+#ifdef CONFIG_HWMON_MV
 static umode_t mv3310_hwmon_is_visible(const void *data,
 				       enum hwmon_sensor_types type,
 				       u32 attr, int channel)
@@ -249,6 +255,77 @@ static int mv3310_resume(struct phy_device *phydev)
 	return mv3310_hwmon_config(phydev, true);
 }
 
+
+/* Some PHYs within the Alaska family like 88x3310 has problems with the
+ * KR Auto-negotiation. marvell datasheet for 88x3310 section 6.2.11 says that
+ * KR auto-negotitaion can be enabled to adapt to the incoming SERDES by writing
+ * to autoneg registers and the PMA/PMD registers
+ */
+static int mv3310_amd_quirk(struct phy_device *phydev)
+{
+	int reg=0, count=0;
+	int version, subversion;
+
+	version = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, 0xC011);
+	subversion = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, 0xC012);
+	dev_dbg(&phydev->mdio.dev,"%s: Marvell FW Version: %x.%x \n", __func__, version, subversion);
+
+	if(subversion != 0x400)
+		return 0;
+
+	reg = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MV_V2_HOST_KR_ENABLE);
+	reg |= 0x8000;
+	phy_write_mmd(phydev, MDIO_MMD_PHYXS, MV_V2_HOST_KR_ENABLE, reg);
+
+	reg = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MV_V2_HOST_KR_TUNE);
+	reg = (reg & ~0x8000) | 0x4000;
+	phy_write_mmd(phydev, MDIO_MMD_PHYXS, MV_V2_HOST_KR_TUNE, reg);
+
+	if((reg & BIT(8)) && (reg & BIT(11))) {
+		reg = phy_read_mmd(phydev, MDIO_MMD_AN, MV_PCS_BASE_R);
+		/* disable BASE-R */
+		phy_write_mmd(phydev, MDIO_MMD_AN, MV_PCS_BASE_R, reg);
+	} else {
+		reg = phy_read_mmd(phydev, MDIO_MMD_AN, MV_PCS_BASE_R);
+		/* enable BASE-R for KR initiation */
+		reg |= 0x1000;
+		phy_write_mmd(phydev, MDIO_MMD_AN, MV_PCS_BASE_R, reg);
+	}
+
+	/* down the port if no link */
+	reg = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_MODE_CFG);
+	reg &= 0xFFF7;
+	phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_MODE_CFG, reg);
+
+	/* reset port to effect above change */
+	reg = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
+	reg |= 0x8000;
+	phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, reg);
+
+	/* wait till reset complete */
+	count = 50;
+	do {
+		msleep(10);
+		reg = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
+	} while ((reg & 0x8000) && --count);
+
+	if(reg & 0x8000){
+		dev_warn(&phydev->mdio.dev,"%s: Port Reset taking long time\n", __func__);
+		return -ETIMEDOUT;
+	}
+
+	/* LED0 Amber light On-Off settings [1:0]=01 */
+	reg = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_LED0_CTRL);
+	if((reg & 0x3) != 0x1) {
+		reg &= 0xFFFC;
+		reg |= 0x1;
+		phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_LED0_CTRL, reg);
+	}
+
+	dev_dbg(&phydev->mdio.dev,"%s: quirk applied\n", __func__);
+	return 0;
+}
+
 static int mv3310_config_init(struct phy_device *phydev)
 {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
@@ -274,6 +351,7 @@ static int mv3310_config_init(struct phy_device *phydev)
 			__set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
 	}
 
+	mv3310_amd_quirk(phydev);
 	val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
 	if (val < 0)
 		return val;
-- 
2.17.1