e935725630c445678703c091c89bd59557d260b6
[openwrt/staging/blogic.git] /
1 From 737eb75a815f9c08dcbb6631db57f4f4b0540a5b Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Tue, 6 Feb 2024 18:31:07 +0100
4 Subject: [PATCH 04/10] net: phy: qcom: move more function to shared library
5
6 Move more function to shared library in preparation for introduction of
7 new PHY Family qca807x that will make use of both functions from at803x
8 and qca808x as it's a transition PHY with some implementation of at803x
9 and some from the new qca808x.
10
11 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
12 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
13 Signed-off-by: David S. Miller <davem@davemloft.net>
14 ---
15 drivers/net/phy/qcom/at803x.c | 35 -----
16 drivers/net/phy/qcom/qca808x.c | 205 ----------------------------
17 drivers/net/phy/qcom/qcom-phy-lib.c | 193 ++++++++++++++++++++++++++
18 drivers/net/phy/qcom/qcom.h | 51 +++++++
19 4 files changed, 244 insertions(+), 240 deletions(-)
20
21 --- a/drivers/net/phy/qcom/at803x.c
22 +++ b/drivers/net/phy/qcom/at803x.c
23 @@ -504,41 +504,6 @@ static void at803x_link_change_notify(st
24 }
25 }
26
27 -static int at803x_read_status(struct phy_device *phydev)
28 -{
29 - struct at803x_ss_mask ss_mask = { 0 };
30 - int err, old_link = phydev->link;
31 -
32 - /* Update the link, but return if there was an error */
33 - err = genphy_update_link(phydev);
34 - if (err)
35 - return err;
36 -
37 - /* why bother the PHY if nothing can have changed */
38 - if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
39 - return 0;
40 -
41 - phydev->speed = SPEED_UNKNOWN;
42 - phydev->duplex = DUPLEX_UNKNOWN;
43 - phydev->pause = 0;
44 - phydev->asym_pause = 0;
45 -
46 - err = genphy_read_lpa(phydev);
47 - if (err < 0)
48 - return err;
49 -
50 - ss_mask.speed_mask = AT803X_SS_SPEED_MASK;
51 - ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK);
52 - err = at803x_read_specific_status(phydev, ss_mask);
53 - if (err < 0)
54 - return err;
55 -
56 - if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
57 - phy_resolve_aneg_pause(phydev);
58 -
59 - return 0;
60 -}
61 -
62 static int at803x_config_aneg(struct phy_device *phydev)
63 {
64 struct at803x_priv *priv = phydev->priv;
65 --- a/drivers/net/phy/qcom/qca808x.c
66 +++ b/drivers/net/phy/qcom/qca808x.c
67 @@ -2,7 +2,6 @@
68
69 #include <linux/phy.h>
70 #include <linux/module.h>
71 -#include <linux/ethtool_netlink.h>
72
73 #include "qcom.h"
74
75 @@ -63,55 +62,6 @@
76 #define QCA808X_DBG_AN_TEST 0xb
77 #define QCA808X_HIBERNATION_EN BIT(15)
78
79 -#define QCA808X_CDT_ENABLE_TEST BIT(15)
80 -#define QCA808X_CDT_INTER_CHECK_DIS BIT(13)
81 -#define QCA808X_CDT_STATUS BIT(11)
82 -#define QCA808X_CDT_LENGTH_UNIT BIT(10)
83 -
84 -#define QCA808X_MMD3_CDT_STATUS 0x8064
85 -#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065
86 -#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066
87 -#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067
88 -#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068
89 -#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8)
90 -#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0)
91 -
92 -#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12)
93 -#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8)
94 -#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4)
95 -#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0)
96 -
97 -#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0)
98 -#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0)
99 -#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1)
100 -#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2)
101 -#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3)
102 -
103 -#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2)
104 -#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1)
105 -#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2)
106 -#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3)
107 -
108 -/* NORMAL are MDI with type set to 0 */
109 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1
110 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\
111 - QCA808X_CDT_STATUS_STAT_MDI1)
112 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\
113 - QCA808X_CDT_STATUS_STAT_MDI1)
114 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2
115 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\
116 - QCA808X_CDT_STATUS_STAT_MDI2)
117 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\
118 - QCA808X_CDT_STATUS_STAT_MDI2)
119 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3
120 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\
121 - QCA808X_CDT_STATUS_STAT_MDI3)
122 -#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\
123 - QCA808X_CDT_STATUS_STAT_MDI3)
124 -
125 -/* Added for reference of existence but should be handled by wait_for_completion already */
126 -#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3))
127 -
128 #define QCA808X_MMD7_LED_GLOBAL 0x8073
129 #define QCA808X_LED_BLINK_1 GENMASK(11, 6)
130 #define QCA808X_LED_BLINK_2 GENMASK(5, 0)
131 @@ -406,86 +356,6 @@ static int qca808x_soft_reset(struct phy
132 return ret;
133 }
134
135 -static bool qca808x_cdt_fault_length_valid(int cdt_code)
136 -{
137 - switch (cdt_code) {
138 - case QCA808X_CDT_STATUS_STAT_SAME_SHORT:
139 - case QCA808X_CDT_STATUS_STAT_SAME_OPEN:
140 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL:
141 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN:
142 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT:
143 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL:
144 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN:
145 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT:
146 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL:
147 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN:
148 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT:
149 - return true;
150 - default:
151 - return false;
152 - }
153 -}
154 -
155 -static int qca808x_cable_test_result_trans(int cdt_code)
156 -{
157 - switch (cdt_code) {
158 - case QCA808X_CDT_STATUS_STAT_NORMAL:
159 - return ETHTOOL_A_CABLE_RESULT_CODE_OK;
160 - case QCA808X_CDT_STATUS_STAT_SAME_SHORT:
161 - return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
162 - case QCA808X_CDT_STATUS_STAT_SAME_OPEN:
163 - return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
164 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL:
165 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN:
166 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT:
167 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL:
168 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN:
169 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT:
170 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL:
171 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN:
172 - case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT:
173 - return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
174 - case QCA808X_CDT_STATUS_STAT_FAIL:
175 - default:
176 - return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
177 - }
178 -}
179 -
180 -static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair,
181 - int result)
182 -{
183 - int val;
184 - u32 cdt_length_reg = 0;
185 -
186 - switch (pair) {
187 - case ETHTOOL_A_CABLE_PAIR_A:
188 - cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A;
189 - break;
190 - case ETHTOOL_A_CABLE_PAIR_B:
191 - cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B;
192 - break;
193 - case ETHTOOL_A_CABLE_PAIR_C:
194 - cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C;
195 - break;
196 - case ETHTOOL_A_CABLE_PAIR_D:
197 - cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D;
198 - break;
199 - default:
200 - return -EINVAL;
201 - }
202 -
203 - val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg);
204 - if (val < 0)
205 - return val;
206 -
207 - if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT)
208 - val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val);
209 - else
210 - val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val);
211 -
212 - return at803x_cdt_fault_length(val);
213 -}
214 -
215 static int qca808x_cable_test_start(struct phy_device *phydev)
216 {
217 int ret;
218 @@ -526,81 +396,6 @@ static int qca808x_cable_test_start(stru
219
220 return 0;
221 }
222 -
223 -static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair,
224 - u16 status)
225 -{
226 - int length, result;
227 - u16 pair_code;
228 -
229 - switch (pair) {
230 - case ETHTOOL_A_CABLE_PAIR_A:
231 - pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status);
232 - break;
233 - case ETHTOOL_A_CABLE_PAIR_B:
234 - pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status);
235 - break;
236 - case ETHTOOL_A_CABLE_PAIR_C:
237 - pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status);
238 - break;
239 - case ETHTOOL_A_CABLE_PAIR_D:
240 - pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status);
241 - break;
242 - default:
243 - return -EINVAL;
244 - }
245 -
246 - result = qca808x_cable_test_result_trans(pair_code);
247 - ethnl_cable_test_result(phydev, pair, result);
248 -
249 - if (qca808x_cdt_fault_length_valid(pair_code)) {
250 - length = qca808x_cdt_fault_length(phydev, pair, result);
251 - ethnl_cable_test_fault_length(phydev, pair, length);
252 - }
253 -
254 - return 0;
255 -}
256 -
257 -static int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished)
258 -{
259 - int ret, val;
260 -
261 - *finished = false;
262 -
263 - val = QCA808X_CDT_ENABLE_TEST |
264 - QCA808X_CDT_LENGTH_UNIT;
265 - ret = at803x_cdt_start(phydev, val);
266 - if (ret)
267 - return ret;
268 -
269 - ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST);
270 - if (ret)
271 - return ret;
272 -
273 - val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS);
274 - if (val < 0)
275 - return val;
276 -
277 - ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val);
278 - if (ret)
279 - return ret;
280 -
281 - ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val);
282 - if (ret)
283 - return ret;
284 -
285 - ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val);
286 - if (ret)
287 - return ret;
288 -
289 - ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val);
290 - if (ret)
291 - return ret;
292 -
293 - *finished = true;
294 -
295 - return 0;
296 -}
297
298 static int qca808x_get_features(struct phy_device *phydev)
299 {
300 --- a/drivers/net/phy/qcom/qcom-phy-lib.c
301 +++ b/drivers/net/phy/qcom/qcom-phy-lib.c
302 @@ -5,6 +5,7 @@
303
304 #include <linux/netdevice.h>
305 #include <linux/etherdevice.h>
306 +#include <linux/ethtool_netlink.h>
307
308 #include "qcom.h"
309
310 @@ -311,6 +312,42 @@ int at803x_prepare_config_aneg(struct ph
311 }
312 EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg);
313
314 +int at803x_read_status(struct phy_device *phydev)
315 +{
316 + struct at803x_ss_mask ss_mask = { 0 };
317 + int err, old_link = phydev->link;
318 +
319 + /* Update the link, but return if there was an error */
320 + err = genphy_update_link(phydev);
321 + if (err)
322 + return err;
323 +
324 + /* why bother the PHY if nothing can have changed */
325 + if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
326 + return 0;
327 +
328 + phydev->speed = SPEED_UNKNOWN;
329 + phydev->duplex = DUPLEX_UNKNOWN;
330 + phydev->pause = 0;
331 + phydev->asym_pause = 0;
332 +
333 + err = genphy_read_lpa(phydev);
334 + if (err < 0)
335 + return err;
336 +
337 + ss_mask.speed_mask = AT803X_SS_SPEED_MASK;
338 + ss_mask.speed_shift = __bf_shf(AT803X_SS_SPEED_MASK);
339 + err = at803x_read_specific_status(phydev, ss_mask);
340 + if (err < 0)
341 + return err;
342 +
343 + if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
344 + phy_resolve_aneg_pause(phydev);
345 +
346 + return 0;
347 +}
348 +EXPORT_SYMBOL_GPL(at803x_read_status);
349 +
350 static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
351 {
352 int val;
353 @@ -427,3 +464,159 @@ int at803x_cdt_wait_for_completion(struc
354 return ret < 0 ? ret : 0;
355 }
356 EXPORT_SYMBOL_GPL(at803x_cdt_wait_for_completion);
357 +
358 +static bool qca808x_cdt_fault_length_valid(int cdt_code)
359 +{
360 + switch (cdt_code) {
361 + case QCA808X_CDT_STATUS_STAT_SAME_SHORT:
362 + case QCA808X_CDT_STATUS_STAT_SAME_OPEN:
363 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL:
364 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN:
365 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT:
366 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL:
367 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN:
368 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT:
369 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL:
370 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN:
371 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT:
372 + return true;
373 + default:
374 + return false;
375 + }
376 +}
377 +
378 +static int qca808x_cable_test_result_trans(int cdt_code)
379 +{
380 + switch (cdt_code) {
381 + case QCA808X_CDT_STATUS_STAT_NORMAL:
382 + return ETHTOOL_A_CABLE_RESULT_CODE_OK;
383 + case QCA808X_CDT_STATUS_STAT_SAME_SHORT:
384 + return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
385 + case QCA808X_CDT_STATUS_STAT_SAME_OPEN:
386 + return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
387 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL:
388 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN:
389 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT:
390 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL:
391 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN:
392 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT:
393 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL:
394 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN:
395 + case QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT:
396 + return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
397 + case QCA808X_CDT_STATUS_STAT_FAIL:
398 + default:
399 + return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
400 + }
401 +}
402 +
403 +static int qca808x_cdt_fault_length(struct phy_device *phydev, int pair,
404 + int result)
405 +{
406 + int val;
407 + u32 cdt_length_reg = 0;
408 +
409 + switch (pair) {
410 + case ETHTOOL_A_CABLE_PAIR_A:
411 + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_A;
412 + break;
413 + case ETHTOOL_A_CABLE_PAIR_B:
414 + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_B;
415 + break;
416 + case ETHTOOL_A_CABLE_PAIR_C:
417 + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_C;
418 + break;
419 + case ETHTOOL_A_CABLE_PAIR_D:
420 + cdt_length_reg = QCA808X_MMD3_CDT_DIAG_PAIR_D;
421 + break;
422 + default:
423 + return -EINVAL;
424 + }
425 +
426 + val = phy_read_mmd(phydev, MDIO_MMD_PCS, cdt_length_reg);
427 + if (val < 0)
428 + return val;
429 +
430 + if (result == ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT)
431 + val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_SAME_SHORT, val);
432 + else
433 + val = FIELD_GET(QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT, val);
434 +
435 + return at803x_cdt_fault_length(val);
436 +}
437 +
438 +static int qca808x_cable_test_get_pair_status(struct phy_device *phydev, u8 pair,
439 + u16 status)
440 +{
441 + int length, result;
442 + u16 pair_code;
443 +
444 + switch (pair) {
445 + case ETHTOOL_A_CABLE_PAIR_A:
446 + pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_A, status);
447 + break;
448 + case ETHTOOL_A_CABLE_PAIR_B:
449 + pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_B, status);
450 + break;
451 + case ETHTOOL_A_CABLE_PAIR_C:
452 + pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_C, status);
453 + break;
454 + case ETHTOOL_A_CABLE_PAIR_D:
455 + pair_code = FIELD_GET(QCA808X_CDT_CODE_PAIR_D, status);
456 + break;
457 + default:
458 + return -EINVAL;
459 + }
460 +
461 + result = qca808x_cable_test_result_trans(pair_code);
462 + ethnl_cable_test_result(phydev, pair, result);
463 +
464 + if (qca808x_cdt_fault_length_valid(pair_code)) {
465 + length = qca808x_cdt_fault_length(phydev, pair, result);
466 + ethnl_cable_test_fault_length(phydev, pair, length);
467 + }
468 +
469 + return 0;
470 +}
471 +
472 +int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished)
473 +{
474 + int ret, val;
475 +
476 + *finished = false;
477 +
478 + val = QCA808X_CDT_ENABLE_TEST |
479 + QCA808X_CDT_LENGTH_UNIT;
480 + ret = at803x_cdt_start(phydev, val);
481 + if (ret)
482 + return ret;
483 +
484 + ret = at803x_cdt_wait_for_completion(phydev, QCA808X_CDT_ENABLE_TEST);
485 + if (ret)
486 + return ret;
487 +
488 + val = phy_read_mmd(phydev, MDIO_MMD_PCS, QCA808X_MMD3_CDT_STATUS);
489 + if (val < 0)
490 + return val;
491 +
492 + ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_A, val);
493 + if (ret)
494 + return ret;
495 +
496 + ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_B, val);
497 + if (ret)
498 + return ret;
499 +
500 + ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_C, val);
501 + if (ret)
502 + return ret;
503 +
504 + ret = qca808x_cable_test_get_pair_status(phydev, ETHTOOL_A_CABLE_PAIR_D, val);
505 + if (ret)
506 + return ret;
507 +
508 + *finished = true;
509 +
510 + return 0;
511 +}
512 +EXPORT_SYMBOL_GPL(qca808x_cable_test_get_status);
513 --- a/drivers/net/phy/qcom/qcom.h
514 +++ b/drivers/net/phy/qcom/qcom.h
515 @@ -54,6 +54,55 @@
516 #define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8)
517 #define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0)
518
519 +#define QCA808X_CDT_ENABLE_TEST BIT(15)
520 +#define QCA808X_CDT_INTER_CHECK_DIS BIT(13)
521 +#define QCA808X_CDT_STATUS BIT(11)
522 +#define QCA808X_CDT_LENGTH_UNIT BIT(10)
523 +
524 +#define QCA808X_MMD3_CDT_STATUS 0x8064
525 +#define QCA808X_MMD3_CDT_DIAG_PAIR_A 0x8065
526 +#define QCA808X_MMD3_CDT_DIAG_PAIR_B 0x8066
527 +#define QCA808X_MMD3_CDT_DIAG_PAIR_C 0x8067
528 +#define QCA808X_MMD3_CDT_DIAG_PAIR_D 0x8068
529 +#define QCA808X_CDT_DIAG_LENGTH_SAME_SHORT GENMASK(15, 8)
530 +#define QCA808X_CDT_DIAG_LENGTH_CROSS_SHORT GENMASK(7, 0)
531 +
532 +#define QCA808X_CDT_CODE_PAIR_A GENMASK(15, 12)
533 +#define QCA808X_CDT_CODE_PAIR_B GENMASK(11, 8)
534 +#define QCA808X_CDT_CODE_PAIR_C GENMASK(7, 4)
535 +#define QCA808X_CDT_CODE_PAIR_D GENMASK(3, 0)
536 +
537 +#define QCA808X_CDT_STATUS_STAT_TYPE GENMASK(1, 0)
538 +#define QCA808X_CDT_STATUS_STAT_FAIL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 0)
539 +#define QCA808X_CDT_STATUS_STAT_NORMAL FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 1)
540 +#define QCA808X_CDT_STATUS_STAT_SAME_OPEN FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 2)
541 +#define QCA808X_CDT_STATUS_STAT_SAME_SHORT FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_TYPE, 3)
542 +
543 +#define QCA808X_CDT_STATUS_STAT_MDI GENMASK(3, 2)
544 +#define QCA808X_CDT_STATUS_STAT_MDI1 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 1)
545 +#define QCA808X_CDT_STATUS_STAT_MDI2 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 2)
546 +#define QCA808X_CDT_STATUS_STAT_MDI3 FIELD_PREP_CONST(QCA808X_CDT_STATUS_STAT_MDI, 3)
547 +
548 +/* NORMAL are MDI with type set to 0 */
549 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI1
550 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\
551 + QCA808X_CDT_STATUS_STAT_MDI1)
552 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI1_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\
553 + QCA808X_CDT_STATUS_STAT_MDI1)
554 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI2
555 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\
556 + QCA808X_CDT_STATUS_STAT_MDI2)
557 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI2_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\
558 + QCA808X_CDT_STATUS_STAT_MDI2)
559 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_NORMAL QCA808X_CDT_STATUS_STAT_MDI3
560 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_OPEN (QCA808X_CDT_STATUS_STAT_SAME_OPEN |\
561 + QCA808X_CDT_STATUS_STAT_MDI3)
562 +#define QCA808X_CDT_STATUS_STAT_CROSS_SHORT_WITH_MDI3_SAME_SHORT (QCA808X_CDT_STATUS_STAT_SAME_SHORT |\
563 + QCA808X_CDT_STATUS_STAT_MDI3)
564 +
565 +/* Added for reference of existence but should be handled by wait_for_completion already */
566 +#define QCA808X_CDT_STATUS_STAT_BUSY (BIT(1) | BIT(3))
567 +
568 #define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C
569 #define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B
570 #define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A
571 @@ -110,6 +159,7 @@ int at803x_read_specific_status(struct p
572 struct at803x_ss_mask ss_mask);
573 int at803x_config_mdix(struct phy_device *phydev, u8 ctrl);
574 int at803x_prepare_config_aneg(struct phy_device *phydev);
575 +int at803x_read_status(struct phy_device *phydev);
576 int at803x_get_tunable(struct phy_device *phydev,
577 struct ethtool_tunable *tuna, void *data);
578 int at803x_set_tunable(struct phy_device *phydev,
579 @@ -118,3 +168,4 @@ int at803x_cdt_fault_length(int dt);
580 int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start);
581 int at803x_cdt_wait_for_completion(struct phy_device *phydev,
582 u32 cdt_en);
583 +int qca808x_cable_test_get_status(struct phy_device *phydev, bool *finished);