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
7 Move additional functions to shared library in preparation for qca808x
8 PHY Family to be detached from at803x driver.
10 Only the shared defines are moved to the shared qcom.h header.
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>
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(-)
22 --- a/drivers/net/phy/qcom/at803x.c
23 +++ b/drivers/net/phy/qcom/at803x.c
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)
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)
48 -#define QCA808X_SS_SPEED_MASK GENMASK(9, 7)
49 -#define QCA808X_SS_SPEED_2500 4
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)
64 -#define AT803X_INTR_STATUS 0x13
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
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
88 #define AT803X_REG_CHIP_CONFIG 0x1f
89 #define AT803X_BT_BX_REG_SEL 0x8000
92 #define AT803X_CLK_OUT_STRENGTH_HALF 1
93 #define AT803X_CLK_OUT_STRENGTH_QUARTER 2
95 -#define AT803X_DEFAULT_DOWNSHIFT 5
96 -#define AT803X_MIN_DOWNSHIFT 2
97 -#define AT803X_MAX_DOWNSHIFT 9
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");
106 -struct at803x_ss_mask {
114 @@ -470,80 +407,6 @@ static void at803x_context_restore(struc
115 phy_write(phydev, AT803X_LED_CONTROL, context->led_control);
118 -static int at803x_set_wol(struct phy_device *phydev,
119 - struct ethtool_wolinfo *wol)
121 - int ret, irq_enabled;
123 - if (wol->wolopts & WAKE_MAGIC) {
124 - struct net_device *ndev = phydev->attached_dev;
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,
136 - mac = (const u8 *)ndev->dev_addr;
138 - if (!is_valid_ether_addr(mac))
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));
145 - /* Enable WOL interrupt */
146 - ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
150 - /* Disable WOL interrupt */
151 - ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
156 - /* Clear WOL status */
157 - ret = phy_read(phydev, AT803X_INTR_STATUS);
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.
165 - irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
166 - if (irq_enabled < 0)
167 - return irq_enabled;
169 - irq_enabled &= ~AT803X_INTR_ENABLE_WOL;
170 - if (ret & irq_enabled && !phy_polling_mode(phydev))
171 - phy_trigger_machine(phydev);
176 -static void at803x_get_wol(struct phy_device *phydev,
177 - struct ethtool_wolinfo *wol)
181 - wol->supported = WAKE_MAGIC;
184 - value = phy_read(phydev, AT803X_INTR_ENABLE);
188 - if (value & AT803X_INTR_ENABLE_WOL)
189 - wol->wolopts |= WAKE_MAGIC;
192 static int at803x_suspend(struct phy_device *phydev)
195 @@ -816,73 +679,6 @@ static int at803x_config_init(struct phy
196 return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0);
199 -static int at803x_ack_interrupt(struct phy_device *phydev)
203 - err = phy_read(phydev, AT803X_INTR_STATUS);
205 - return (err < 0) ? err : 0;
208 -static int at803x_config_intr(struct phy_device *phydev)
213 - value = phy_read(phydev, AT803X_INTR_ENABLE);
215 - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
216 - /* Clear any pending interrupts */
217 - err = at803x_ack_interrupt(phydev);
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;
227 - err = phy_write(phydev, AT803X_INTR_ENABLE, value);
229 - err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
233 - /* Clear any pending interrupts */
234 - err = at803x_ack_interrupt(phydev);
240 -static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev)
242 - int irq_status, int_enabled;
244 - irq_status = phy_read(phydev, AT803X_INTR_STATUS);
245 - if (irq_status < 0) {
250 - /* Read the current enabled interrupts */
251 - int_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
252 - if (int_enabled < 0) {
257 - /* See if this was one of our enabled interrupts */
258 - if (!(irq_status & int_enabled))
261 - phy_trigger_machine(phydev);
263 - return IRQ_HANDLED;
266 static void at803x_link_change_notify(struct phy_device *phydev)
269 @@ -908,69 +704,6 @@ static void at803x_link_change_notify(st
273 -static int at803x_read_specific_status(struct phy_device *phydev,
274 - struct at803x_ss_mask ss_mask)
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.
282 - ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
286 - if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
289 - sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
293 - speed = ss & ss_mask.speed_mask;
294 - speed >>= ss_mask.speed_shift;
297 - case AT803X_SS_SPEED_10:
298 - phydev->speed = SPEED_10;
300 - case AT803X_SS_SPEED_100:
301 - phydev->speed = SPEED_100;
303 - case AT803X_SS_SPEED_1000:
304 - phydev->speed = SPEED_1000;
306 - case QCA808X_SS_SPEED_2500:
307 - phydev->speed = SPEED_2500;
310 - if (ss & AT803X_SS_DUPLEX)
311 - phydev->duplex = DUPLEX_FULL;
313 - phydev->duplex = DUPLEX_HALF;
315 - if (ss & AT803X_SS_MDIX)
316 - phydev->mdix = ETH_TP_MDI_X;
318 - phydev->mdix = ETH_TP_MDI;
320 - switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) {
321 - case AT803X_SFC_MANUAL_MDI:
322 - phydev->mdix_ctrl = ETH_TP_MDI;
324 - case AT803X_SFC_MANUAL_MDIX:
325 - phydev->mdix_ctrl = ETH_TP_MDI_X;
327 - case AT803X_SFC_AUTOMATIC_CROSSOVER:
328 - phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
336 static int at803x_read_status(struct phy_device *phydev)
338 struct at803x_ss_mask ss_mask = { 0 };
339 @@ -1006,50 +739,6 @@ static int at803x_read_status(struct phy
343 -static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl)
349 - val = AT803X_SFC_MANUAL_MDI;
352 - val = AT803X_SFC_MANUAL_MDIX;
354 - case ETH_TP_MDI_AUTO:
355 - val = AT803X_SFC_AUTOMATIC_CROSSOVER;
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));
366 -static int at803x_prepare_config_aneg(struct phy_device *phydev)
370 - ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
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.
379 - ret = genphy_soft_reset(phydev);
387 static int at803x_config_aneg(struct phy_device *phydev)
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);
394 -static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
398 - val = phy_read(phydev, AT803X_SMART_SPEED);
402 - if (val & AT803X_SMART_SPEED_ENABLE)
403 - *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2;
405 - *d = DOWNSHIFT_DEV_DISABLE;
410 -static int at803x_set_downshift(struct phy_device *phydev, u8 cnt)
416 - case DOWNSHIFT_DEV_DEFAULT_COUNT:
417 - cnt = AT803X_DEFAULT_DOWNSHIFT;
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;
425 - case DOWNSHIFT_DEV_DISABLE:
427 - mask = AT803X_SMART_SPEED_ENABLE |
428 - AT803X_SMART_SPEED_BYPASS_TIMER;
434 - ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set);
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.
441 - ret = phy_init_hw(phydev);
446 -static int at803x_get_tunable(struct phy_device *phydev,
447 - struct ethtool_tunable *tuna, void *data)
449 - switch (tuna->id) {
450 - case ETHTOOL_PHY_DOWNSHIFT:
451 - return at803x_get_downshift(phydev, data);
453 - return -EOPNOTSUPP;
457 -static int at803x_set_tunable(struct phy_device *phydev,
458 - struct ethtool_tunable *tuna, const void *data)
460 - switch (tuna->id) {
461 - case ETHTOOL_PHY_DOWNSHIFT:
462 - return at803x_set_downshift(phydev, *(const u8 *)data);
464 - return -EOPNOTSUPP;
468 static int at803x_cable_test_result_trans(u16 status)
470 switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) {
471 @@ -1170,45 +785,6 @@ static bool at803x_cdt_fault_length_vali
475 -static int at803x_cdt_fault_length(int dt)
477 - /* According to the datasheet the distance to the fault is
478 - * DELTA_TIME * 0.824 meters.
480 - * The author suspect the correct formula is:
482 - * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2
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.
489 - * With a VF of 0.69 we get the factor 0.824 mentioned in the
492 - return (dt * 824) / 10;
495 -static int at803x_cdt_start(struct phy_device *phydev,
498 - return phy_write(phydev, AT803X_CDT, cdt_start);
501 -static int at803x_cdt_wait_for_completion(struct phy_device *phydev,
506 - /* One test run takes about 25ms */
507 - ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
509 - 30000, 100000, true);
511 - return ret < 0 ? ret : 0;
514 static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair)
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
520 #include <linux/phy.h>
521 #include <linux/module.h>
523 +#include <linux/netdevice.h>
524 +#include <linux/etherdevice.h>
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);
532 EXPORT_SYMBOL_GPL(at803x_debug_reg_write);
534 +int at803x_set_wol(struct phy_device *phydev,
535 + struct ethtool_wolinfo *wol)
537 + int ret, irq_enabled;
539 + if (wol->wolopts & WAKE_MAGIC) {
540 + struct net_device *ndev = phydev->attached_dev;
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,
552 + mac = (const u8 *)ndev->dev_addr;
554 + if (!is_valid_ether_addr(mac))
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));
561 + /* Enable WOL interrupt */
562 + ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
566 + /* Disable WOL interrupt */
567 + ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
572 + /* Clear WOL status */
573 + ret = phy_read(phydev, AT803X_INTR_STATUS);
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.
581 + irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
582 + if (irq_enabled < 0)
583 + return irq_enabled;
585 + irq_enabled &= ~AT803X_INTR_ENABLE_WOL;
586 + if (ret & irq_enabled && !phy_polling_mode(phydev))
587 + phy_trigger_machine(phydev);
591 +EXPORT_SYMBOL_GPL(at803x_set_wol);
593 +void at803x_get_wol(struct phy_device *phydev,
594 + struct ethtool_wolinfo *wol)
598 + wol->supported = WAKE_MAGIC;
601 + value = phy_read(phydev, AT803X_INTR_ENABLE);
605 + if (value & AT803X_INTR_ENABLE_WOL)
606 + wol->wolopts |= WAKE_MAGIC;
608 +EXPORT_SYMBOL_GPL(at803x_get_wol);
610 +int at803x_ack_interrupt(struct phy_device *phydev)
614 + err = phy_read(phydev, AT803X_INTR_STATUS);
616 + return (err < 0) ? err : 0;
618 +EXPORT_SYMBOL_GPL(at803x_ack_interrupt);
620 +int at803x_config_intr(struct phy_device *phydev)
625 + value = phy_read(phydev, AT803X_INTR_ENABLE);
627 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
628 + /* Clear any pending interrupts */
629 + err = at803x_ack_interrupt(phydev);
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;
639 + err = phy_write(phydev, AT803X_INTR_ENABLE, value);
641 + err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
645 + /* Clear any pending interrupts */
646 + err = at803x_ack_interrupt(phydev);
651 +EXPORT_SYMBOL_GPL(at803x_config_intr);
653 +irqreturn_t at803x_handle_interrupt(struct phy_device *phydev)
655 + int irq_status, int_enabled;
657 + irq_status = phy_read(phydev, AT803X_INTR_STATUS);
658 + if (irq_status < 0) {
663 + /* Read the current enabled interrupts */
664 + int_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
665 + if (int_enabled < 0) {
670 + /* See if this was one of our enabled interrupts */
671 + if (!(irq_status & int_enabled))
674 + phy_trigger_machine(phydev);
676 + return IRQ_HANDLED;
678 +EXPORT_SYMBOL_GPL(at803x_handle_interrupt);
680 +int at803x_read_specific_status(struct phy_device *phydev,
681 + struct at803x_ss_mask ss_mask)
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.
689 + ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
693 + if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
696 + sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
700 + speed = ss & ss_mask.speed_mask;
701 + speed >>= ss_mask.speed_shift;
704 + case AT803X_SS_SPEED_10:
705 + phydev->speed = SPEED_10;
707 + case AT803X_SS_SPEED_100:
708 + phydev->speed = SPEED_100;
710 + case AT803X_SS_SPEED_1000:
711 + phydev->speed = SPEED_1000;
713 + case QCA808X_SS_SPEED_2500:
714 + phydev->speed = SPEED_2500;
717 + if (ss & AT803X_SS_DUPLEX)
718 + phydev->duplex = DUPLEX_FULL;
720 + phydev->duplex = DUPLEX_HALF;
722 + if (ss & AT803X_SS_MDIX)
723 + phydev->mdix = ETH_TP_MDI_X;
725 + phydev->mdix = ETH_TP_MDI;
727 + switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) {
728 + case AT803X_SFC_MANUAL_MDI:
729 + phydev->mdix_ctrl = ETH_TP_MDI;
731 + case AT803X_SFC_MANUAL_MDIX:
732 + phydev->mdix_ctrl = ETH_TP_MDI_X;
734 + case AT803X_SFC_AUTOMATIC_CROSSOVER:
735 + phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
742 +EXPORT_SYMBOL_GPL(at803x_read_specific_status);
744 +int at803x_config_mdix(struct phy_device *phydev, u8 ctrl)
750 + val = AT803X_SFC_MANUAL_MDI;
753 + val = AT803X_SFC_MANUAL_MDIX;
755 + case ETH_TP_MDI_AUTO:
756 + val = AT803X_SFC_AUTOMATIC_CROSSOVER;
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));
766 +EXPORT_SYMBOL_GPL(at803x_config_mdix);
768 +int at803x_prepare_config_aneg(struct phy_device *phydev)
772 + ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
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.
781 + ret = genphy_soft_reset(phydev);
788 +EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg);
790 +static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
794 + val = phy_read(phydev, AT803X_SMART_SPEED);
798 + if (val & AT803X_SMART_SPEED_ENABLE)
799 + *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2;
801 + *d = DOWNSHIFT_DEV_DISABLE;
806 +static int at803x_set_downshift(struct phy_device *phydev, u8 cnt)
812 + case DOWNSHIFT_DEV_DEFAULT_COUNT:
813 + cnt = AT803X_DEFAULT_DOWNSHIFT;
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;
821 + case DOWNSHIFT_DEV_DISABLE:
823 + mask = AT803X_SMART_SPEED_ENABLE |
824 + AT803X_SMART_SPEED_BYPASS_TIMER;
830 + ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set);
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.
837 + ret = phy_init_hw(phydev);
842 +int at803x_get_tunable(struct phy_device *phydev,
843 + struct ethtool_tunable *tuna, void *data)
845 + switch (tuna->id) {
846 + case ETHTOOL_PHY_DOWNSHIFT:
847 + return at803x_get_downshift(phydev, data);
849 + return -EOPNOTSUPP;
852 +EXPORT_SYMBOL_GPL(at803x_get_tunable);
854 +int at803x_set_tunable(struct phy_device *phydev,
855 + struct ethtool_tunable *tuna, const void *data)
857 + switch (tuna->id) {
858 + case ETHTOOL_PHY_DOWNSHIFT:
859 + return at803x_set_downshift(phydev, *(const u8 *)data);
861 + return -EOPNOTSUPP;
864 +EXPORT_SYMBOL_GPL(at803x_set_tunable);
866 +int at803x_cdt_fault_length(int dt)
868 + /* According to the datasheet the distance to the fault is
869 + * DELTA_TIME * 0.824 meters.
871 + * The author suspect the correct formula is:
873 + * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2
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.
880 + * With a VF of 0.69 we get the factor 0.824 mentioned in the
883 + return (dt * 824) / 10;
885 +EXPORT_SYMBOL_GPL(at803x_cdt_fault_length);
887 +int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start)
889 + return phy_write(phydev, AT803X_CDT, cdt_start);
891 +EXPORT_SYMBOL_GPL(at803x_cdt_start);
893 +int at803x_cdt_wait_for_completion(struct phy_device *phydev,
898 + /* One test run takes about 25ms */
899 + ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
901 + 30000, 100000, true);
903 + return ret < 0 ? ret : 0;
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
909 /* SPDX-License-Identifier: GPL-2.0 */
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)
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)
931 +#define QCA808X_SS_SPEED_MASK GENMASK(9, 7)
932 +#define QCA808X_SS_SPEED_2500 4
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)
947 +#define AT803X_INTR_STATUS 0x13
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)
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)
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
969 #define AT803X_DEBUG_ADDR 0x1D
970 #define AT803X_DEBUG_DATA 0x1E
973 #define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13)
974 #define AT803X_DEBUG_HIB_CTRL_PS_HIB_EN BIT(15)
976 +#define AT803X_DEFAULT_DOWNSHIFT 5
977 +#define AT803X_MIN_DOWNSHIFT 2
978 +#define AT803X_MAX_DOWNSHIFT 9
980 enum stat_access_type {
983 @@ -28,7 +90,31 @@ struct at803x_hw_stat {
984 enum stat_access_type access_type;
987 +struct at803x_ss_mask {
992 int at803x_debug_reg_read(struct phy_device *phydev, u16 reg);
993 int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
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,