aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-5.15/9041-amd-xgbe-10G-RJ45-support-on-Fox-platform-with-AN-su.patch
blob: 22a74950342d544f605a755a501e4be296a9efaa (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
From 1fb36bba84ceada142324306c29ff5e158f257cb Mon Sep 17 00:00:00 2001
From: Sudheesh Mavila <sudheesh.mavila@amd.com>
Date: Mon, 25 Apr 2022 12:40:58 +0530
Subject: [PATCH 41/48] amd-xgbe: 10G RJ45 support on Fox platform with AN
 support using MDIO

Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
Signed-off-by: rgaridap <Ramesh.Garidapuri@amd.com>
Change-Id: If19412f51805064b14d9cfd71d9fbeb8ea365bb0
---
 drivers/net/ethernet/amd/xgbe/xgbe-mdio.c   |  10 ++
 drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 110 ++++++++++++++++++--
 drivers/net/ethernet/amd/xgbe/xgbe.h        |   1 +
 3 files changed, 114 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index c370a8027ce3..bc8172c19082 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -1282,6 +1282,12 @@ static int xgbe_phy_reconfig_aneg(struct xgbe_prv_data *pdata)
 
 static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
 {
+	if (pdata->an_mode == XGBE_AN_MODE_MDIO) {
+		if(pdata->phy.link)
+			pdata->an_result = XGBE_AN_COMPLETE;
+		else
+			pdata->an_result = XGBE_AN_NO_LINK;
+	}
 	return (pdata->an_result == XGBE_AN_COMPLETE);
 }
 
@@ -1313,6 +1319,8 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 	else
 		mode = xgbe_phy_status_aneg(pdata);
 
+	if(pdata->an_mode != XGBE_AN_MODE_MDIO) {
+
 	switch (mode) {
 	case XGBE_MODE_SGMII_100:
 		pdata->phy.speed = SPEED_100;
@@ -1334,6 +1342,8 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
 		pdata->phy.speed = SPEED_UNKNOWN;
 	}
 
+
+	}
 	pdata->phy.duplex = DUPLEX_FULL;
 
 	if (xgbe_set_mode(pdata, mode) && pdata->an_again)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index 1a56a52e0079..8b464b268165 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -380,6 +380,7 @@ struct xgbe_phy_data {
 	/* KR AN support */
 	unsigned int phy_cdr_notrack;
 	unsigned int phy_cdr_delay;
+	unsigned int mdio_an_mode;
 };
 
 /* I2C, MDIO and GPIO lines are muxed, so only one device at a time */
@@ -1764,6 +1765,82 @@ 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 = XGBE_MODE_UNKNOWN;
+	unsigned int ad_reg, lp_reg;
+	struct xgbe_phy_data *phy_data = pdata->phy_data;
+	if(phy_data->phydev) {
+
+		/* 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);
+		if (lp_reg & 0x400)
+			XGBE_SET_LP_ADV(lks, Pause);
+		if (lp_reg & 0x800)
+			XGBE_SET_LP_ADV(lks, Asym_Pause);
+
+		if (pdata->phy.pause_autoneg) {
+			/* Set flow control based on auto-negotiation result */
+			pdata->phy.tx_pause = 0;
+			pdata->phy.rx_pause = 0;
+
+			if (ad_reg & lp_reg & 0x400) {
+				pdata->phy.tx_pause = 1;
+				pdata->phy.rx_pause = 1;
+			} else if (ad_reg & lp_reg & 0x800) {
+				if (ad_reg & 0x400)
+					pdata->phy.rx_pause = 1;
+				else if (lp_reg & 0x400)
+					pdata->phy.tx_pause = 1;
+			}
+		}
+
+		switch (phy_data->phydev->interface) {
+		case PHY_INTERFACE_MODE_10GKR:
+			if ((phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000) && (phy_data->phydev->speed == SPEED_10000))
+				mode = XGBE_MODE_KR;
+			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_1000) {
+				if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500)
+				mode =XGBE_MODE_KX_2500;
+			}
+			break;
+		case PHY_INTERFACE_MODE_10GBASER:
+				mode = XGBE_MODE_KR;
+			break;
+		case PHY_INTERFACE_MODE_SGMII:
+			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_1000) {
+				if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500)
+				mode = XGBE_MODE_KX_2500;
+			}
+			break;
+		case PHY_INTERFACE_MODE_2500BASEX:
+			if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500)
+				mode = XGBE_MODE_KX_2500;
+			break;
+		default:
+			mode = XGBE_MODE_KR;
+		break;
+		}
+	}
+	pdata->phy.speed  = phy_data->phydev->speed;
+	return mode;
+}
+
+
 static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
 {
 	switch (pdata->an_mode) {
@@ -1775,6 +1852,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;
 	}
@@ -1910,7 +1989,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:
@@ -2201,7 +2283,8 @@ static enum xgbe_mode xgbe_phy_switch_baset_mode(struct xgbe_prv_data *pdata)
 	/* No switching if not 10GBase-T */
 	if (phy_data->port_mode != XGBE_PORT_MODE_10GBASE_T)
 		return xgbe_phy_cur_mode(pdata);
-
+	else if (phy_data->mdio_an_mode)
+		return XGBE_MODE_KR;
 	switch (xgbe_phy_cur_mode(pdata)) {
 	case XGBE_MODE_SGMII_100:
 	case XGBE_MODE_SGMII_1000:
@@ -2544,16 +2627,26 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_phy_data *phy_data,
 {
 	switch (speed) {
 	case SPEED_100:
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_100)
+			return true;
+		break;
 	case SPEED_1000:
-		return true;
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_1000)
+			return true;
+		break;
 	case SPEED_2500:
-		return ((phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T) ||
-			(phy_data->port_mode == XGBE_PORT_MODE_NBASE_T));
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_2500)
+			return ((phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T) ||
+				(phy_data->port_mode == XGBE_PORT_MODE_NBASE_T));
+		break;
 	case SPEED_10000:
-		return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T);
+		if (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10000)
+			return (phy_data->port_mode == XGBE_PORT_MODE_10GBASE_T);
+		break;
 	default:
 		return false;
 	}
+	return false;
 }
 
 static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_phy_data *phy_data,
@@ -2650,6 +2743,8 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
 
 		if (!phy_data->phydev->link)
 			return 0;
+		if (pdata->an_mode == XGBE_AN_MODE_MDIO)
+			return 1;
 	}
 
 	/* Link status is latched low, so read once to clear
@@ -3339,7 +3434,7 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
 
 	/* 10GBase-T support */
 	case XGBE_PORT_MODE_10GBASE_T:
-		//XGBE_SET_SUP(lks, Autoneg);
+		XGBE_SET_SUP(lks, Autoneg);
 		dev_dbg(pdata->dev, "port mode: 10GBase-T\n");
 		XGBE_SET_SUP(lks, Pause);
 		XGBE_SET_SUP(lks, Asym_Pause);
@@ -3363,6 +3458,7 @@ static int xgbe_phy_init(struct xgbe_prv_data *pdata)
 		}
 
 		phy_data->phydev_mode = XGBE_MDIO_MODE_CL45;
+		phy_data->mdio_an_mode = 1;
 		break;
 
 	/* 10GBase-R support */
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index 3305979a9f7c..bd883f00fad0 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -569,6 +569,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.37.3