9c43ad13b4434f5840195b0f8b708c5714ffcc85
[openwrt/staging/blogic.git] /
1 From 249d2b80e4db0e38503ed0ec2af6c7401bc099b9 Mon Sep 17 00:00:00 2001
2 From: Christian Marangi <ansuelsmth@gmail.com>
3 Date: Mon, 29 Jan 2024 15:15:22 +0100
4 Subject: [PATCH 4/5] net: phy: qcom: move additional functions to shared
5 library
6
7 Move additional functions to shared library in preparation for qca808x
8 PHY Family to be detached from at803x driver.
9
10 Only the shared defines are moved to the shared qcom.h header.
11
12 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
13 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
14 Link: https://lore.kernel.org/r/20240129141600.2592-5-ansuelsmth@gmail.com
15 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
16 ---
17 drivers/net/phy/qcom/at803x.c | 426 +---------------------------
18 drivers/net/phy/qcom/qcom-phy-lib.c | 376 ++++++++++++++++++++++++
19 drivers/net/phy/qcom/qcom.h | 86 ++++++
20 3 files changed, 463 insertions(+), 425 deletions(-)
21
22 --- a/drivers/net/phy/qcom/at803x.c
23 +++ b/drivers/net/phy/qcom/at803x.c
24 @@ -24,65 +24,11 @@
25
26 #include "qcom.h"
27
28 -#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10
29 -#define AT803X_SFC_ASSERT_CRS BIT(11)
30 -#define AT803X_SFC_FORCE_LINK BIT(10)
31 -#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5)
32 -#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3
33 -#define AT803X_SFC_MANUAL_MDIX 0x1
34 -#define AT803X_SFC_MANUAL_MDI 0x0
35 -#define AT803X_SFC_SQE_TEST BIT(2)
36 -#define AT803X_SFC_POLARITY_REVERSAL BIT(1)
37 -#define AT803X_SFC_DISABLE_JABBER BIT(0)
38 -
39 -#define AT803X_SPECIFIC_STATUS 0x11
40 -#define AT803X_SS_SPEED_MASK GENMASK(15, 14)
41 -#define AT803X_SS_SPEED_1000 2
42 -#define AT803X_SS_SPEED_100 1
43 -#define AT803X_SS_SPEED_10 0
44 -#define AT803X_SS_DUPLEX BIT(13)
45 -#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
46 -#define AT803X_SS_MDIX BIT(6)
47 -
48 -#define QCA808X_SS_SPEED_MASK GENMASK(9, 7)
49 -#define QCA808X_SS_SPEED_2500 4
50 -
51 -#define AT803X_INTR_ENABLE 0x12
52 -#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
53 -#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
54 -#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13)
55 -#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12)
56 -#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11)
57 -#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10)
58 -#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8)
59 -#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7)
60 -#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5)
61 -#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1)
62 -#define AT803X_INTR_ENABLE_WOL BIT(0)
63 -
64 -#define AT803X_INTR_STATUS 0x13
65 -
66 -#define AT803X_SMART_SPEED 0x14
67 -#define AT803X_SMART_SPEED_ENABLE BIT(5)
68 -#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2)
69 -#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1)
70 -#define AT803X_CDT 0x16
71 -#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8)
72 -#define AT803X_CDT_ENABLE_TEST BIT(0)
73 -#define AT803X_CDT_STATUS 0x1c
74 -#define AT803X_CDT_STATUS_STAT_NORMAL 0
75 -#define AT803X_CDT_STATUS_STAT_SHORT 1
76 -#define AT803X_CDT_STATUS_STAT_OPEN 2
77 -#define AT803X_CDT_STATUS_STAT_FAIL 3
78 -#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8)
79 -#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0)
80 #define AT803X_LED_CONTROL 0x18
81
82 #define AT803X_PHY_MMD3_WOL_CTRL 0x8012
83 #define AT803X_WOL_EN BIT(5)
84 -#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C
85 -#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B
86 -#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A
87 +
88 #define AT803X_REG_CHIP_CONFIG 0x1f
89 #define AT803X_BT_BX_REG_SEL 0x8000
90
91 @@ -138,10 +84,6 @@
92 #define AT803X_CLK_OUT_STRENGTH_HALF 1
93 #define AT803X_CLK_OUT_STRENGTH_QUARTER 2
94
95 -#define AT803X_DEFAULT_DOWNSHIFT 5
96 -#define AT803X_MIN_DOWNSHIFT 2
97 -#define AT803X_MAX_DOWNSHIFT 9
98 -
99 #define AT803X_MMD3_SMARTEEE_CTL1 0x805b
100 #define AT803X_MMD3_SMARTEEE_CTL2 0x805c
101 #define AT803X_MMD3_SMARTEEE_CTL3 0x805d
102 @@ -366,11 +308,6 @@ MODULE_DESCRIPTION("Qualcomm Atheros AR8
103 MODULE_AUTHOR("Matus Ujhelyi");
104 MODULE_LICENSE("GPL");
105
106 -struct at803x_ss_mask {
107 - u16 speed_mask;
108 - u8 speed_shift;
109 -};
110 -
111 struct at803x_priv {
112 int flags;
113 u16 clk_25m_reg;
114 @@ -470,80 +407,6 @@ static void at803x_context_restore(struc
115 phy_write(phydev, AT803X_LED_CONTROL, context->led_control);
116 }
117
118 -static int at803x_set_wol(struct phy_device *phydev,
119 - struct ethtool_wolinfo *wol)
120 -{
121 - int ret, irq_enabled;
122 -
123 - if (wol->wolopts & WAKE_MAGIC) {
124 - struct net_device *ndev = phydev->attached_dev;
125 - const u8 *mac;
126 - unsigned int i;
127 - static const unsigned int offsets[] = {
128 - AT803X_LOC_MAC_ADDR_32_47_OFFSET,
129 - AT803X_LOC_MAC_ADDR_16_31_OFFSET,
130 - AT803X_LOC_MAC_ADDR_0_15_OFFSET,
131 - };
132 -
133 - if (!ndev)
134 - return -ENODEV;
135 -
136 - mac = (const u8 *)ndev->dev_addr;
137 -
138 - if (!is_valid_ether_addr(mac))
139 - return -EINVAL;
140 -
141 - for (i = 0; i < 3; i++)
142 - phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
143 - mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
144 -
145 - /* Enable WOL interrupt */
146 - ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
147 - if (ret)
148 - return ret;
149 - } else {
150 - /* Disable WOL interrupt */
151 - ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
152 - if (ret)
153 - return ret;
154 - }
155 -
156 - /* Clear WOL status */
157 - ret = phy_read(phydev, AT803X_INTR_STATUS);
158 - if (ret < 0)
159 - return ret;
160 -
161 - /* Check if there are other interrupts except for WOL triggered when PHY is
162 - * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can
163 - * be passed up to the interrupt PIN.
164 - */
165 - irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
166 - if (irq_enabled < 0)
167 - return irq_enabled;
168 -
169 - irq_enabled &= ~AT803X_INTR_ENABLE_WOL;
170 - if (ret & irq_enabled && !phy_polling_mode(phydev))
171 - phy_trigger_machine(phydev);
172 -
173 - return 0;
174 -}
175 -
176 -static void at803x_get_wol(struct phy_device *phydev,
177 - struct ethtool_wolinfo *wol)
178 -{
179 - int value;
180 -
181 - wol->supported = WAKE_MAGIC;
182 - wol->wolopts = 0;
183 -
184 - value = phy_read(phydev, AT803X_INTR_ENABLE);
185 - if (value < 0)
186 - return;
187 -
188 - if (value & AT803X_INTR_ENABLE_WOL)
189 - wol->wolopts |= WAKE_MAGIC;
190 -}
191 -
192 static int at803x_suspend(struct phy_device *phydev)
193 {
194 int value;
195 @@ -816,73 +679,6 @@ static int at803x_config_init(struct phy
196 return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0);
197 }
198
199 -static int at803x_ack_interrupt(struct phy_device *phydev)
200 -{
201 - int err;
202 -
203 - err = phy_read(phydev, AT803X_INTR_STATUS);
204 -
205 - return (err < 0) ? err : 0;
206 -}
207 -
208 -static int at803x_config_intr(struct phy_device *phydev)
209 -{
210 - int err;
211 - int value;
212 -
213 - value = phy_read(phydev, AT803X_INTR_ENABLE);
214 -
215 - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
216 - /* Clear any pending interrupts */
217 - err = at803x_ack_interrupt(phydev);
218 - if (err)
219 - return err;
220 -
221 - value |= AT803X_INTR_ENABLE_AUTONEG_ERR;
222 - value |= AT803X_INTR_ENABLE_SPEED_CHANGED;
223 - value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
224 - value |= AT803X_INTR_ENABLE_LINK_FAIL;
225 - value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
226 -
227 - err = phy_write(phydev, AT803X_INTR_ENABLE, value);
228 - } else {
229 - err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
230 - if (err)
231 - return err;
232 -
233 - /* Clear any pending interrupts */
234 - err = at803x_ack_interrupt(phydev);
235 - }
236 -
237 - return err;
238 -}
239 -
240 -static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev)
241 -{
242 - int irq_status, int_enabled;
243 -
244 - irq_status = phy_read(phydev, AT803X_INTR_STATUS);
245 - if (irq_status < 0) {
246 - phy_error(phydev);
247 - return IRQ_NONE;
248 - }
249 -
250 - /* Read the current enabled interrupts */
251 - int_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
252 - if (int_enabled < 0) {
253 - phy_error(phydev);
254 - return IRQ_NONE;
255 - }
256 -
257 - /* See if this was one of our enabled interrupts */
258 - if (!(irq_status & int_enabled))
259 - return IRQ_NONE;
260 -
261 - phy_trigger_machine(phydev);
262 -
263 - return IRQ_HANDLED;
264 -}
265 -
266 static void at803x_link_change_notify(struct phy_device *phydev)
267 {
268 /*
269 @@ -908,69 +704,6 @@ static void at803x_link_change_notify(st
270 }
271 }
272
273 -static int at803x_read_specific_status(struct phy_device *phydev,
274 - struct at803x_ss_mask ss_mask)
275 -{
276 - int ss;
277 -
278 - /* Read the AT8035 PHY-Specific Status register, which indicates the
279 - * speed and duplex that the PHY is actually using, irrespective of
280 - * whether we are in autoneg mode or not.
281 - */
282 - ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
283 - if (ss < 0)
284 - return ss;
285 -
286 - if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
287 - int sfc, speed;
288 -
289 - sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
290 - if (sfc < 0)
291 - return sfc;
292 -
293 - speed = ss & ss_mask.speed_mask;
294 - speed >>= ss_mask.speed_shift;
295 -
296 - switch (speed) {
297 - case AT803X_SS_SPEED_10:
298 - phydev->speed = SPEED_10;
299 - break;
300 - case AT803X_SS_SPEED_100:
301 - phydev->speed = SPEED_100;
302 - break;
303 - case AT803X_SS_SPEED_1000:
304 - phydev->speed = SPEED_1000;
305 - break;
306 - case QCA808X_SS_SPEED_2500:
307 - phydev->speed = SPEED_2500;
308 - break;
309 - }
310 - if (ss & AT803X_SS_DUPLEX)
311 - phydev->duplex = DUPLEX_FULL;
312 - else
313 - phydev->duplex = DUPLEX_HALF;
314 -
315 - if (ss & AT803X_SS_MDIX)
316 - phydev->mdix = ETH_TP_MDI_X;
317 - else
318 - phydev->mdix = ETH_TP_MDI;
319 -
320 - switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) {
321 - case AT803X_SFC_MANUAL_MDI:
322 - phydev->mdix_ctrl = ETH_TP_MDI;
323 - break;
324 - case AT803X_SFC_MANUAL_MDIX:
325 - phydev->mdix_ctrl = ETH_TP_MDI_X;
326 - break;
327 - case AT803X_SFC_AUTOMATIC_CROSSOVER:
328 - phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
329 - break;
330 - }
331 - }
332 -
333 - return 0;
334 -}
335 -
336 static int at803x_read_status(struct phy_device *phydev)
337 {
338 struct at803x_ss_mask ss_mask = { 0 };
339 @@ -1006,50 +739,6 @@ static int at803x_read_status(struct phy
340 return 0;
341 }
342
343 -static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl)
344 -{
345 - u16 val;
346 -
347 - switch (ctrl) {
348 - case ETH_TP_MDI:
349 - val = AT803X_SFC_MANUAL_MDI;
350 - break;
351 - case ETH_TP_MDI_X:
352 - val = AT803X_SFC_MANUAL_MDIX;
353 - break;
354 - case ETH_TP_MDI_AUTO:
355 - val = AT803X_SFC_AUTOMATIC_CROSSOVER;
356 - break;
357 - default:
358 - return 0;
359 - }
360 -
361 - return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL,
362 - AT803X_SFC_MDI_CROSSOVER_MODE_M,
363 - FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val));
364 -}
365 -
366 -static int at803x_prepare_config_aneg(struct phy_device *phydev)
367 -{
368 - int ret;
369 -
370 - ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
371 - if (ret < 0)
372 - return ret;
373 -
374 - /* Changes of the midx bits are disruptive to the normal operation;
375 - * therefore any changes to these registers must be followed by a
376 - * software reset to take effect.
377 - */
378 - if (ret == 1) {
379 - ret = genphy_soft_reset(phydev);
380 - if (ret < 0)
381 - return ret;
382 - }
383 -
384 - return 0;
385 -}
386 -
387 static int at803x_config_aneg(struct phy_device *phydev)
388 {
389 struct at803x_priv *priv = phydev->priv;
390 @@ -1065,80 +754,6 @@ static int at803x_config_aneg(struct phy
391 return genphy_config_aneg(phydev);
392 }
393
394 -static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
395 -{
396 - int val;
397 -
398 - val = phy_read(phydev, AT803X_SMART_SPEED);
399 - if (val < 0)
400 - return val;
401 -
402 - if (val & AT803X_SMART_SPEED_ENABLE)
403 - *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2;
404 - else
405 - *d = DOWNSHIFT_DEV_DISABLE;
406 -
407 - return 0;
408 -}
409 -
410 -static int at803x_set_downshift(struct phy_device *phydev, u8 cnt)
411 -{
412 - u16 mask, set;
413 - int ret;
414 -
415 - switch (cnt) {
416 - case DOWNSHIFT_DEV_DEFAULT_COUNT:
417 - cnt = AT803X_DEFAULT_DOWNSHIFT;
418 - fallthrough;
419 - case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT:
420 - set = AT803X_SMART_SPEED_ENABLE |
421 - AT803X_SMART_SPEED_BYPASS_TIMER |
422 - FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2);
423 - mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK;
424 - break;
425 - case DOWNSHIFT_DEV_DISABLE:
426 - set = 0;
427 - mask = AT803X_SMART_SPEED_ENABLE |
428 - AT803X_SMART_SPEED_BYPASS_TIMER;
429 - break;
430 - default:
431 - return -EINVAL;
432 - }
433 -
434 - ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set);
435 -
436 - /* After changing the smart speed settings, we need to perform a
437 - * software reset, use phy_init_hw() to make sure we set the
438 - * reapply any values which might got lost during software reset.
439 - */
440 - if (ret == 1)
441 - ret = phy_init_hw(phydev);
442 -
443 - return ret;
444 -}
445 -
446 -static int at803x_get_tunable(struct phy_device *phydev,
447 - struct ethtool_tunable *tuna, void *data)
448 -{
449 - switch (tuna->id) {
450 - case ETHTOOL_PHY_DOWNSHIFT:
451 - return at803x_get_downshift(phydev, data);
452 - default:
453 - return -EOPNOTSUPP;
454 - }
455 -}
456 -
457 -static int at803x_set_tunable(struct phy_device *phydev,
458 - struct ethtool_tunable *tuna, const void *data)
459 -{
460 - switch (tuna->id) {
461 - case ETHTOOL_PHY_DOWNSHIFT:
462 - return at803x_set_downshift(phydev, *(const u8 *)data);
463 - default:
464 - return -EOPNOTSUPP;
465 - }
466 -}
467 -
468 static int at803x_cable_test_result_trans(u16 status)
469 {
470 switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) {
471 @@ -1170,45 +785,6 @@ static bool at803x_cdt_fault_length_vali
472 return false;
473 }
474
475 -static int at803x_cdt_fault_length(int dt)
476 -{
477 - /* According to the datasheet the distance to the fault is
478 - * DELTA_TIME * 0.824 meters.
479 - *
480 - * The author suspect the correct formula is:
481 - *
482 - * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2
483 - *
484 - * where c is the speed of light, VF is the velocity factor of
485 - * the twisted pair cable, 125MHz the counter frequency and
486 - * we need to divide by 2 because the hardware will measure the
487 - * round trip time to the fault and back to the PHY.
488 - *
489 - * With a VF of 0.69 we get the factor 0.824 mentioned in the
490 - * datasheet.
491 - */
492 - return (dt * 824) / 10;
493 -}
494 -
495 -static int at803x_cdt_start(struct phy_device *phydev,
496 - u32 cdt_start)
497 -{
498 - return phy_write(phydev, AT803X_CDT, cdt_start);
499 -}
500 -
501 -static int at803x_cdt_wait_for_completion(struct phy_device *phydev,
502 - u32 cdt_en)
503 -{
504 - int val, ret;
505 -
506 - /* One test run takes about 25ms */
507 - ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
508 - !(val & cdt_en),
509 - 30000, 100000, true);
510 -
511 - return ret < 0 ? ret : 0;
512 -}
513 -
514 static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair)
515 {
516 static const int ethtool_pair[] = {
517 --- a/drivers/net/phy/qcom/qcom-phy-lib.c
518 +++ b/drivers/net/phy/qcom/qcom-phy-lib.c
519 @@ -3,6 +3,9 @@
520 #include <linux/phy.h>
521 #include <linux/module.h>
522
523 +#include <linux/netdevice.h>
524 +#include <linux/etherdevice.h>
525 +
526 #include "qcom.h"
527
528 MODULE_DESCRIPTION("Qualcomm PHY driver Common Functions");
529 @@ -51,3 +54,376 @@ int at803x_debug_reg_write(struct phy_de
530 return phy_write(phydev, AT803X_DEBUG_DATA, data);
531 }
532 EXPORT_SYMBOL_GPL(at803x_debug_reg_write);
533 +
534 +int at803x_set_wol(struct phy_device *phydev,
535 + struct ethtool_wolinfo *wol)
536 +{
537 + int ret, irq_enabled;
538 +
539 + if (wol->wolopts & WAKE_MAGIC) {
540 + struct net_device *ndev = phydev->attached_dev;
541 + const u8 *mac;
542 + unsigned int i;
543 + static const unsigned int offsets[] = {
544 + AT803X_LOC_MAC_ADDR_32_47_OFFSET,
545 + AT803X_LOC_MAC_ADDR_16_31_OFFSET,
546 + AT803X_LOC_MAC_ADDR_0_15_OFFSET,
547 + };
548 +
549 + if (!ndev)
550 + return -ENODEV;
551 +
552 + mac = (const u8 *)ndev->dev_addr;
553 +
554 + if (!is_valid_ether_addr(mac))
555 + return -EINVAL;
556 +
557 + for (i = 0; i < 3; i++)
558 + phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
559 + mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
560 +
561 + /* Enable WOL interrupt */
562 + ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
563 + if (ret)
564 + return ret;
565 + } else {
566 + /* Disable WOL interrupt */
567 + ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
568 + if (ret)
569 + return ret;
570 + }
571 +
572 + /* Clear WOL status */
573 + ret = phy_read(phydev, AT803X_INTR_STATUS);
574 + if (ret < 0)
575 + return ret;
576 +
577 + /* Check if there are other interrupts except for WOL triggered when PHY is
578 + * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can
579 + * be passed up to the interrupt PIN.
580 + */
581 + irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
582 + if (irq_enabled < 0)
583 + return irq_enabled;
584 +
585 + irq_enabled &= ~AT803X_INTR_ENABLE_WOL;
586 + if (ret & irq_enabled && !phy_polling_mode(phydev))
587 + phy_trigger_machine(phydev);
588 +
589 + return 0;
590 +}
591 +EXPORT_SYMBOL_GPL(at803x_set_wol);
592 +
593 +void at803x_get_wol(struct phy_device *phydev,
594 + struct ethtool_wolinfo *wol)
595 +{
596 + int value;
597 +
598 + wol->supported = WAKE_MAGIC;
599 + wol->wolopts = 0;
600 +
601 + value = phy_read(phydev, AT803X_INTR_ENABLE);
602 + if (value < 0)
603 + return;
604 +
605 + if (value & AT803X_INTR_ENABLE_WOL)
606 + wol->wolopts |= WAKE_MAGIC;
607 +}
608 +EXPORT_SYMBOL_GPL(at803x_get_wol);
609 +
610 +int at803x_ack_interrupt(struct phy_device *phydev)
611 +{
612 + int err;
613 +
614 + err = phy_read(phydev, AT803X_INTR_STATUS);
615 +
616 + return (err < 0) ? err : 0;
617 +}
618 +EXPORT_SYMBOL_GPL(at803x_ack_interrupt);
619 +
620 +int at803x_config_intr(struct phy_device *phydev)
621 +{
622 + int err;
623 + int value;
624 +
625 + value = phy_read(phydev, AT803X_INTR_ENABLE);
626 +
627 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
628 + /* Clear any pending interrupts */
629 + err = at803x_ack_interrupt(phydev);
630 + if (err)
631 + return err;
632 +
633 + value |= AT803X_INTR_ENABLE_AUTONEG_ERR;
634 + value |= AT803X_INTR_ENABLE_SPEED_CHANGED;
635 + value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
636 + value |= AT803X_INTR_ENABLE_LINK_FAIL;
637 + value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
638 +
639 + err = phy_write(phydev, AT803X_INTR_ENABLE, value);
640 + } else {
641 + err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
642 + if (err)
643 + return err;
644 +
645 + /* Clear any pending interrupts */
646 + err = at803x_ack_interrupt(phydev);
647 + }
648 +
649 + return err;
650 +}
651 +EXPORT_SYMBOL_GPL(at803x_config_intr);
652 +
653 +irqreturn_t at803x_handle_interrupt(struct phy_device *phydev)
654 +{
655 + int irq_status, int_enabled;
656 +
657 + irq_status = phy_read(phydev, AT803X_INTR_STATUS);
658 + if (irq_status < 0) {
659 + phy_error(phydev);
660 + return IRQ_NONE;
661 + }
662 +
663 + /* Read the current enabled interrupts */
664 + int_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
665 + if (int_enabled < 0) {
666 + phy_error(phydev);
667 + return IRQ_NONE;
668 + }
669 +
670 + /* See if this was one of our enabled interrupts */
671 + if (!(irq_status & int_enabled))
672 + return IRQ_NONE;
673 +
674 + phy_trigger_machine(phydev);
675 +
676 + return IRQ_HANDLED;
677 +}
678 +EXPORT_SYMBOL_GPL(at803x_handle_interrupt);
679 +
680 +int at803x_read_specific_status(struct phy_device *phydev,
681 + struct at803x_ss_mask ss_mask)
682 +{
683 + int ss;
684 +
685 + /* Read the AT8035 PHY-Specific Status register, which indicates the
686 + * speed and duplex that the PHY is actually using, irrespective of
687 + * whether we are in autoneg mode or not.
688 + */
689 + ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
690 + if (ss < 0)
691 + return ss;
692 +
693 + if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
694 + int sfc, speed;
695 +
696 + sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
697 + if (sfc < 0)
698 + return sfc;
699 +
700 + speed = ss & ss_mask.speed_mask;
701 + speed >>= ss_mask.speed_shift;
702 +
703 + switch (speed) {
704 + case AT803X_SS_SPEED_10:
705 + phydev->speed = SPEED_10;
706 + break;
707 + case AT803X_SS_SPEED_100:
708 + phydev->speed = SPEED_100;
709 + break;
710 + case AT803X_SS_SPEED_1000:
711 + phydev->speed = SPEED_1000;
712 + break;
713 + case QCA808X_SS_SPEED_2500:
714 + phydev->speed = SPEED_2500;
715 + break;
716 + }
717 + if (ss & AT803X_SS_DUPLEX)
718 + phydev->duplex = DUPLEX_FULL;
719 + else
720 + phydev->duplex = DUPLEX_HALF;
721 +
722 + if (ss & AT803X_SS_MDIX)
723 + phydev->mdix = ETH_TP_MDI_X;
724 + else
725 + phydev->mdix = ETH_TP_MDI;
726 +
727 + switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) {
728 + case AT803X_SFC_MANUAL_MDI:
729 + phydev->mdix_ctrl = ETH_TP_MDI;
730 + break;
731 + case AT803X_SFC_MANUAL_MDIX:
732 + phydev->mdix_ctrl = ETH_TP_MDI_X;
733 + break;
734 + case AT803X_SFC_AUTOMATIC_CROSSOVER:
735 + phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
736 + break;
737 + }
738 + }
739 +
740 + return 0;
741 +}
742 +EXPORT_SYMBOL_GPL(at803x_read_specific_status);
743 +
744 +int at803x_config_mdix(struct phy_device *phydev, u8 ctrl)
745 +{
746 + u16 val;
747 +
748 + switch (ctrl) {
749 + case ETH_TP_MDI:
750 + val = AT803X_SFC_MANUAL_MDI;
751 + break;
752 + case ETH_TP_MDI_X:
753 + val = AT803X_SFC_MANUAL_MDIX;
754 + break;
755 + case ETH_TP_MDI_AUTO:
756 + val = AT803X_SFC_AUTOMATIC_CROSSOVER;
757 + break;
758 + default:
759 + return 0;
760 + }
761 +
762 + return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL,
763 + AT803X_SFC_MDI_CROSSOVER_MODE_M,
764 + FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val));
765 +}
766 +EXPORT_SYMBOL_GPL(at803x_config_mdix);
767 +
768 +int at803x_prepare_config_aneg(struct phy_device *phydev)
769 +{
770 + int ret;
771 +
772 + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
773 + if (ret < 0)
774 + return ret;
775 +
776 + /* Changes of the midx bits are disruptive to the normal operation;
777 + * therefore any changes to these registers must be followed by a
778 + * software reset to take effect.
779 + */
780 + if (ret == 1) {
781 + ret = genphy_soft_reset(phydev);
782 + if (ret < 0)
783 + return ret;
784 + }
785 +
786 + return 0;
787 +}
788 +EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg);
789 +
790 +static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
791 +{
792 + int val;
793 +
794 + val = phy_read(phydev, AT803X_SMART_SPEED);
795 + if (val < 0)
796 + return val;
797 +
798 + if (val & AT803X_SMART_SPEED_ENABLE)
799 + *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2;
800 + else
801 + *d = DOWNSHIFT_DEV_DISABLE;
802 +
803 + return 0;
804 +}
805 +
806 +static int at803x_set_downshift(struct phy_device *phydev, u8 cnt)
807 +{
808 + u16 mask, set;
809 + int ret;
810 +
811 + switch (cnt) {
812 + case DOWNSHIFT_DEV_DEFAULT_COUNT:
813 + cnt = AT803X_DEFAULT_DOWNSHIFT;
814 + fallthrough;
815 + case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT:
816 + set = AT803X_SMART_SPEED_ENABLE |
817 + AT803X_SMART_SPEED_BYPASS_TIMER |
818 + FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2);
819 + mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK;
820 + break;
821 + case DOWNSHIFT_DEV_DISABLE:
822 + set = 0;
823 + mask = AT803X_SMART_SPEED_ENABLE |
824 + AT803X_SMART_SPEED_BYPASS_TIMER;
825 + break;
826 + default:
827 + return -EINVAL;
828 + }
829 +
830 + ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set);
831 +
832 + /* After changing the smart speed settings, we need to perform a
833 + * software reset, use phy_init_hw() to make sure we set the
834 + * reapply any values which might got lost during software reset.
835 + */
836 + if (ret == 1)
837 + ret = phy_init_hw(phydev);
838 +
839 + return ret;
840 +}
841 +
842 +int at803x_get_tunable(struct phy_device *phydev,
843 + struct ethtool_tunable *tuna, void *data)
844 +{
845 + switch (tuna->id) {
846 + case ETHTOOL_PHY_DOWNSHIFT:
847 + return at803x_get_downshift(phydev, data);
848 + default:
849 + return -EOPNOTSUPP;
850 + }
851 +}
852 +EXPORT_SYMBOL_GPL(at803x_get_tunable);
853 +
854 +int at803x_set_tunable(struct phy_device *phydev,
855 + struct ethtool_tunable *tuna, const void *data)
856 +{
857 + switch (tuna->id) {
858 + case ETHTOOL_PHY_DOWNSHIFT:
859 + return at803x_set_downshift(phydev, *(const u8 *)data);
860 + default:
861 + return -EOPNOTSUPP;
862 + }
863 +}
864 +EXPORT_SYMBOL_GPL(at803x_set_tunable);
865 +
866 +int at803x_cdt_fault_length(int dt)
867 +{
868 + /* According to the datasheet the distance to the fault is
869 + * DELTA_TIME * 0.824 meters.
870 + *
871 + * The author suspect the correct formula is:
872 + *
873 + * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2
874 + *
875 + * where c is the speed of light, VF is the velocity factor of
876 + * the twisted pair cable, 125MHz the counter frequency and
877 + * we need to divide by 2 because the hardware will measure the
878 + * round trip time to the fault and back to the PHY.
879 + *
880 + * With a VF of 0.69 we get the factor 0.824 mentioned in the
881 + * datasheet.
882 + */
883 + return (dt * 824) / 10;
884 +}
885 +EXPORT_SYMBOL_GPL(at803x_cdt_fault_length);
886 +
887 +int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start)
888 +{
889 + return phy_write(phydev, AT803X_CDT, cdt_start);
890 +}
891 +EXPORT_SYMBOL_GPL(at803x_cdt_start);
892 +
893 +int at803x_cdt_wait_for_completion(struct phy_device *phydev,
894 + u32 cdt_en)
895 +{
896 + int val, ret;
897 +
898 + /* One test run takes about 25ms */
899 + ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
900 + !(val & cdt_en),
901 + 30000, 100000, true);
902 +
903 + return ret < 0 ? ret : 0;
904 +}
905 +EXPORT_SYMBOL_GPL(at803x_cdt_wait_for_completion);
906 --- a/drivers/net/phy/qcom/qcom.h
907 +++ b/drivers/net/phy/qcom/qcom.h
908 @@ -1,5 +1,63 @@
909 /* SPDX-License-Identifier: GPL-2.0 */
910
911 +#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10
912 +#define AT803X_SFC_ASSERT_CRS BIT(11)
913 +#define AT803X_SFC_FORCE_LINK BIT(10)
914 +#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5)
915 +#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3
916 +#define AT803X_SFC_MANUAL_MDIX 0x1
917 +#define AT803X_SFC_MANUAL_MDI 0x0
918 +#define AT803X_SFC_SQE_TEST BIT(2)
919 +#define AT803X_SFC_POLARITY_REVERSAL BIT(1)
920 +#define AT803X_SFC_DISABLE_JABBER BIT(0)
921 +
922 +#define AT803X_SPECIFIC_STATUS 0x11
923 +#define AT803X_SS_SPEED_MASK GENMASK(15, 14)
924 +#define AT803X_SS_SPEED_1000 2
925 +#define AT803X_SS_SPEED_100 1
926 +#define AT803X_SS_SPEED_10 0
927 +#define AT803X_SS_DUPLEX BIT(13)
928 +#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
929 +#define AT803X_SS_MDIX BIT(6)
930 +
931 +#define QCA808X_SS_SPEED_MASK GENMASK(9, 7)
932 +#define QCA808X_SS_SPEED_2500 4
933 +
934 +#define AT803X_INTR_ENABLE 0x12
935 +#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
936 +#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
937 +#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13)
938 +#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12)
939 +#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11)
940 +#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10)
941 +#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8)
942 +#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7)
943 +#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5)
944 +#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1)
945 +#define AT803X_INTR_ENABLE_WOL BIT(0)
946 +
947 +#define AT803X_INTR_STATUS 0x13
948 +
949 +#define AT803X_SMART_SPEED 0x14
950 +#define AT803X_SMART_SPEED_ENABLE BIT(5)
951 +#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2)
952 +#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1)
953 +
954 +#define AT803X_CDT 0x16
955 +#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8)
956 +#define AT803X_CDT_ENABLE_TEST BIT(0)
957 +#define AT803X_CDT_STATUS 0x1c
958 +#define AT803X_CDT_STATUS_STAT_NORMAL 0
959 +#define AT803X_CDT_STATUS_STAT_SHORT 1
960 +#define AT803X_CDT_STATUS_STAT_OPEN 2
961 +#define AT803X_CDT_STATUS_STAT_FAIL 3
962 +#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8)
963 +#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0)
964 +
965 +#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C
966 +#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B
967 +#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A
968 +
969 #define AT803X_DEBUG_ADDR 0x1D
970 #define AT803X_DEBUG_DATA 0x1E
971
972 @@ -16,6 +74,10 @@
973 #define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13)
974 #define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15)
975
976 +#define AT803X_DEFAULT_DOWNSHIFT 5
977 +#define AT803X_MIN_DOWNSHIFT 2
978 +#define AT803X_MAX_DOWNSHIFT 9
979 +
980 enum stat_access_type {
981 PHY,
982 MMD
983 @@ -28,7 +90,31 @@ struct at803x_hw_stat {
984 enum stat_access_type access_type;
985 };
986
987 +struct at803x_ss_mask {
988 + u16 speed_mask;
989 + u8 speed_shift;
990 +};
991 +
992 int at803x_debug_reg_read(struct phy_device *phydev, u16 reg);
993 int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
994 u16 clear, u16 set);
995 int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data);
996 +int at803x_set_wol(struct phy_device *phydev,
997 + struct ethtool_wolinfo *wol);
998 +void at803x_get_wol(struct phy_device *phydev,
999 + struct ethtool_wolinfo *wol);
1000 +int at803x_ack_interrupt(struct phy_device *phydev);
1001 +int at803x_config_intr(struct phy_device *phydev);
1002 +irqreturn_t at803x_handle_interrupt(struct phy_device *phydev);
1003 +int at803x_read_specific_status(struct phy_device *phydev,
1004 + struct at803x_ss_mask ss_mask);
1005 +int at803x_config_mdix(struct phy_device *phydev, u8 ctrl);
1006 +int at803x_prepare_config_aneg(struct phy_device *phydev);
1007 +int at803x_get_tunable(struct phy_device *phydev,
1008 + struct ethtool_tunable *tuna, void *data);
1009 +int at803x_set_tunable(struct phy_device *phydev,
1010 + struct ethtool_tunable *tuna, const void *data);
1011 +int at803x_cdt_fault_length(int dt);
1012 +int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start);
1013 +int at803x_cdt_wait_for_completion(struct phy_device *phydev,
1014 + u32 cdt_en);