aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux-6.6/linux-yocto-6.6/0022-amd-xgbe-V2-extend-driver-functionality-to-support-1.patch
blob: 4b783a5ffdbc70f804fdcfb640938762a0022476 (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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
From 3edf0a8c28a1cf3cf5b6019cf2b4650a9cabf5e5 Mon Sep 17 00:00:00 2001
From: Raju Rangoju <Raju.Rangoju@amd.com>
Date: Thu, 7 Sep 2023 16:16:15 +0530
Subject: [PATCH 22/31] amd-xgbe: V2: extend driver functionality to support
 10GBaseT

The current xgbe driver supports 10GBaseT using 10GBaseKR (with
CL73/CL72 AN). However, most of the PHYs supports only 10GBaseR and do
not support 10GBaseKR. Hence, extend the amd-xgbe driver fucntionality
to support 10GBaseT using other interfaces such as SGMII, 1000KX and
10GBaseR. This implementation uses MDIO sideband interface depending
on the PHY capability.

Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
Signed-off-by: Ramesh Garidapuri <ramesh.garidapuri@amd.com>
Change-Id: I151844807abd097af24746e79cfbb3ccb3ea9ea5
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |   5 +
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 159 +++++++++++++++++---
 drivers/net/ethernet/amd/xgbe/xgbe.h        |   1 +
 3 files changed, 145 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index f514a443ec4e..837427b6423d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -1330,6 +1330,7 @@ static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
 	link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
 	if (time_after(jiffies, link_timeout)) {
 		if ((xgbe_cur_mode(pdata) == XGBE_MODE_KR) &&
+		    (pdata->an_mode != XGBE_AN_MODE_MDIO) &&
 		    pdata->phy.autoneg == AUTONEG_ENABLE) {
 			/* AN restart should not happen while KR training is in progress.
 			 * The while loop ensures no AN restart during KR training,
@@ -1370,6 +1371,9 @@ static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 	else
 		mode = xgbe_phy_status_aneg(pdata);
 
+	if(pdata->an_mode == XGBE_AN_MODE_MDIO)
+		goto skip_speed_set;
+
 	switch (mode) {
 	case XGBE_MODE_SGMII_10:
 		pdata->phy.speed = SPEED_10;
@@ -1394,6 +1398,7 @@ static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 		pdata->phy.speed = SPEED_UNKNOWN;
 	}
 
+skip_speed_set:
 	pdata->phy.duplex = DUPLEX_FULL;
 
 	if (!xgbe_set_mode(pdata, mode))
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index ef97bf99f283..d69486552cf6 100755
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -382,6 +382,8 @@ struct xgbe_phy_data {
 	/* KR AN support */
 	unsigned int phy_cdr_notrack;
 	unsigned int phy_cdr_delay;
+
+	bool mdio_an_mode;
 };
 
 /* I2C, MDIO and GPIO lines are muxed, so only one device at a time */
@@ -1862,15 +1864,11 @@ static enum xgbe_mode xgbe_phy_an73_redrv_outcome(struct xgbe_prv_data *pdata)
 	return mode;
 }
 
-static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
+static void  xgbe_phy_get_an_outcome(struct xgbe_prv_data *pdata,
+				    struct ethtool_link_ksettings *lks)
 {
-	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
-	enum xgbe_mode mode;
 	unsigned int ad_reg, lp_reg;
 
-	XGBE_SET_LP_ADV(lks, Autoneg);
-	XGBE_SET_LP_ADV(lks, Backplane);
-
 	/* Compare Advertisement and Link Partner register 1 */
 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
 	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
@@ -1894,6 +1892,18 @@ static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
 				pdata->phy.tx_pause = 1;
 		}
 	}
+}
+
+static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
+{
+	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
+	enum xgbe_mode mode;
+	unsigned int ad_reg, lp_reg;
+
+	XGBE_SET_LP_ADV(lks, Autoneg);
+	XGBE_SET_LP_ADV(lks, Backplane);
+
+	xgbe_phy_get_an_outcome(pdata, lks);
 
 	/* Compare Advertisement and Link Partner register 2 */
 	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
@@ -1920,6 +1930,79 @@ static enum xgbe_mode xgbe_phy_an73_outcome(struct xgbe_prv_data *pdata)
 	return mode;
 }
 
+static enum xgbe_mode xgbe_phy_mdio_an_outcome(struct xgbe_prv_data *pdata)
+{
+	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
+	enum xgbe_mode mode;
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	int speed;
+
+	if (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T){
+		if (!phy_aneg_done(phy_data->phydev)) {
+			pdata->en_rx_adap = 0;
+			phy_data->mdio_an_mode = true;
+			return phy_data->cur_mode;
+		}
+	} else {
+		phy_data->mdio_an_mode = false;
+		return phy_data->cur_mode;
+	}
+
+	if (phy_data->phydev)
+		xgbe_phy_get_an_outcome(pdata, lks);
+
+	phy_data->phydev->interface == PHY_INTERFACE_MODE_10GKR ?
+					(phy_data->mdio_an_mode = false):
+					(phy_data->mdio_an_mode = true);
+
+	switch (phy_data->phydev->interface) {
+		case PHY_INTERFACE_MODE_10GKR:
+			pdata->en_rx_adap = 0;
+			mode = XGBE_MODE_KR;
+			break;
+		case PHY_INTERFACE_MODE_10GBASER:
+			mode = XGBE_MODE_KR;
+			break;
+		case PHY_INTERFACE_MODE_SGMII:
+			pdata->en_rx_adap = 0;
+			if (phy_data->phydev->speed == SPEED_10) {
+				if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10)
+					mode = XGBE_MODE_SGMII_10;
+			} else if (phy_data->phydev->speed == SPEED_100) {
+				if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
+					mode = XGBE_MODE_SGMII_100;
+			} else if (phy_data->phydev->speed == SPEED_1000) {
+				if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+					mode = XGBE_MODE_SGMII_1000;
+			} else if (phy_data->phydev->speed == SPEED_2500) {
+				if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500)
+					mode = XGBE_MODE_KX_2500;
+			} else
+				mode = XGBE_MODE_SGMII_1000;
+			break;
+		case PHY_INTERFACE_MODE_2500BASEX:
+			pdata->en_rx_adap = 0;
+			mode = XGBE_MODE_KX_2500;
+			break;
+		default:
+			pdata->en_rx_adap = 0;
+			mode = XGBE_MODE_SGMII_1000;
+			goto err;
+			break;
+	}
+
+	pdata->phy.speed  = phy_data->phydev->speed;
+	if (mode != phy_data->cur_mode) {
+		if(mode == XGBE_MODE_KR || mode == XGBE_MODE_SFI)
+			speed = SPEED_10000;
+		else
+			speed = pdata->phy.speed;
+		pdata->hw_if.set_speed(pdata, speed);
+	}
+err:
+	return mode;
+}
+
 static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
 {
 	switch (pdata->an_mode) {
@@ -1931,6 +2014,8 @@ static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
 		return xgbe_phy_an37_outcome(pdata);
 	case XGBE_AN_MODE_CL37_SGMII:
 		return xgbe_phy_an37_sgmii_outcome(pdata);
+	case XGBE_AN_MODE_MDIO:
+		return xgbe_phy_mdio_an_outcome(pdata);
 	default:
 		return XGBE_MODE_UNKNOWN;
 	}
@@ -2080,7 +2165,10 @@ static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
 	case XGBE_PORT_MODE_NBASE_T:
 		return XGBE_AN_MODE_CL37_SGMII;
 	case XGBE_PORT_MODE_10GBASE_T:
-		return XGBE_AN_MODE_CL73;
+		if (phy_data->mdio_an_mode)
+			return XGBE_AN_MODE_MDIO;
+		else
+			return XGBE_AN_MODE_CL73;
 	case XGBE_PORT_MODE_10GBASE_R:
 		return XGBE_AN_MODE_NONE;
 	case XGBE_PORT_MODE_SFP:
@@ -2255,8 +2343,10 @@ static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata)
 
 static void xgbe_phy_pll_ctrl(struct xgbe_prv_data *pdata, bool enable)
 {
-	/* PLL_CTRL feature needs to be enabled for fixed PHY modes (Non-Autoneg) only */
-	if (pdata->phy.autoneg != AUTONEG_DISABLE)
+	/* PLL_CTRL feature needs to be enabled for
+	 * fixed PHY modes (Non-Autoneg) and mdio mode only */
+	if ((pdata->phy.autoneg != AUTONEG_DISABLE) &&
+	    (pdata->an_mode != XGBE_AN_MODE_MDIO))
 		return;
 
 	XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_VEND2_PMA_MISC_CTRL0,
@@ -2358,7 +2448,7 @@ static bool enable_rx_adap(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
 
 	/* Rx-Adaptation is not supported on older platforms(< 0x30H) */
 	ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER);
-	if (ver < 0x30)
+	if (ver < 0x30 /*&& ver != 0x21*/)
 		return false;
 
 	/* Re-driver models 4223 && 4227 do not support Rx-Adaptation */
@@ -2369,7 +2459,8 @@ static bool enable_rx_adap(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
 
 	/* 10G KR mode with AN does not support Rx-Adaptation */
 	if (mode == XGBE_MODE_KR &&
-	    phy_data->port_mode != XGBE_PORT_MODE_BACKPLANE_NO_AUTONEG)
+	    (!phy_data->mdio_an_mode &&
+	    phy_data->port_mode != XGBE_PORT_MODE_BACKPLANE_NO_AUTONEG))
 		return false;
 
 	pdata->en_rx_adap = 1;
@@ -2715,6 +2806,11 @@ static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
 static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
 				enum xgbe_mode mode, bool advert)
 {
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+
+	if (phy_data->mdio_an_mode)
+		return (mode == xgbe_phy_mdio_an_outcome(pdata)) ? true : false;
+
 	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
 		return advert;
 	} else {
@@ -2990,25 +3086,46 @@ static int xgbe_get_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart
 			return 0;
 		}
 
-		if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los) {
-			if (pdata->en_rx_adap)
-				pdata->rx_adapt_done = false;
-			return 0;
-		}
+		if (phy_data->sfp_mod_absent || phy_data->sfp_rx_los)
+			goto out;
 	}
 
 	if (phy_data->phydev) {
 		/* Check external PHY */
 		ret = phy_read_status(phy_data->phydev);
 		if (ret < 0)
-			return 0;
+			goto out;
 
 		if ((pdata->phy.autoneg == AUTONEG_ENABLE) &&
-		    !phy_aneg_done(phy_data->phydev))
-			return 0;
+		    !phy_aneg_done(phy_data->phydev)) {
+			if ((phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T) &&
+			    (pdata->phy_speed != SPEED_UNKNOWN)) {
+				pdata->phy_speed = SPEED_UNKNOWN;
+				netif_carrier_off(pdata->netdev);
+			}
+			goto out;
+		}
 
 		if (!phy_data->phydev->link)
-			return 0;
+			goto out;
+	}
+
+	if (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T) {
+		enum xgbe_mode mode;
+		mode  = xgbe_phy_mdio_an_outcome(pdata);
+		if (mode != xgbe_phy_cur_mode(pdata)) {
+			netif_dbg(pdata, link, pdata->netdev, "Ext PHY changed interface mode to %d so AN is needed\n", mode);
+			*an_restart = 1;
+			goto out;
+		}
+
+		if (pdata->an_mode == XGBE_AN_MODE_MDIO)
+			pdata->an_result = XGBE_AN_COMPLETE;
+
+		if (enable_rx_adap(pdata, mode) && !pdata->rx_adapt_done) {
+			xgbe_phy_rx_adaptation(pdata);
+			msleep(200);
+		}
 	}
 
 	/* Link status is latched low, so read once to clear
@@ -3075,6 +3192,8 @@ static int xgbe_get_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart
 		xgbe_phy_rrc(pdata);
 	}
 
+out:
+	pdata->rx_adapt_done = false;
 	return 0;
 }
 
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 358061c4417f..125701fe85f3 100755
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -582,6 +582,7 @@ enum xgbe_an_mode {
 	XGBE_AN_MODE_CL73_REDRV,
 	XGBE_AN_MODE_CL37,
 	XGBE_AN_MODE_CL37_SGMII,
+	XGBE_AN_MODE_MDIO,
 	XGBE_AN_MODE_NONE,
 };
 
-- 
2.34.1