8b54881ab04dc43ec275f4674744b5907e404918
[openwrt/staging/wigyori.git] /
1 From cffac22c9215f1883d3848c788f9b03656dced27 Mon Sep 17 00:00:00 2001
2 From: Robert Marko <robimarko@gmail.com>
3 Date: Sun, 11 Feb 2024 18:39:19 +0100
4 Subject: [PATCH] net: phy: aquantia: clear PMD Global Transmit Disable bit
5 during init
6
7 PMD Global Transmit Disable bit should be cleared for normal operation.
8 This should be HW default, however I found that on Asus RT-AX89X that uses
9 AQR113C PHY and firmware 5.4 this bit is set by default.
10
11 With this bit set the AQR cannot achieve a link with its link-partner and
12 it took me multiple hours of digging through the vendor GPL source to find
13 this out, so lets always clear this bit during .config_init() to avoid a
14 situation like this in the future.
15
16 aqr107_wait_processor_intensive_op() is moved up because datasheet notes
17 that any changes to this bit are processor intensive.
18
19 Signed-off-by: Robert Marko <robimarko@gmail.com>
20 ---
21 drivers/net/phy/aquantia/aquantia_main.c | 57 ++++++++++++++----------
22 1 file changed, 33 insertions(+), 24 deletions(-)
23
24 --- a/drivers/net/phy/aquantia/aquantia_main.c
25 +++ b/drivers/net/phy/aquantia/aquantia_main.c
26 @@ -473,6 +473,30 @@ static void aqr107_chip_info(struct phy_
27 fw_major, fw_minor, build_id, prov_id);
28 }
29
30 +static int aqr107_wait_processor_intensive_op(struct phy_device *phydev)
31 +{
32 + int val, err;
33 +
34 + /* The datasheet notes to wait at least 1ms after issuing a
35 + * processor intensive operation before checking.
36 + * We cannot use the 'sleep_before_read' parameter of read_poll_timeout
37 + * because that just determines the maximum time slept, not the minimum.
38 + */
39 + usleep_range(1000, 5000);
40 +
41 + err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
42 + VEND1_GLOBAL_GEN_STAT2, val,
43 + !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG),
44 + AQR107_OP_IN_PROG_SLEEP,
45 + AQR107_OP_IN_PROG_TIMEOUT, false);
46 + if (err) {
47 + phydev_err(phydev, "timeout: processor-intensive MDIO operation\n");
48 + return err;
49 + }
50 +
51 + return 0;
52 +}
53 +
54 static int aqr107_config_init(struct phy_device *phydev)
55 {
56 struct aqr107_priv *priv = phydev->priv;
57 @@ -498,6 +522,15 @@ static int aqr107_config_init(struct phy
58 if (!ret)
59 aqr107_chip_info(phydev);
60
61 + ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS,
62 + MDIO_PMD_TXDIS_GLOBAL);
63 + if (ret)
64 + return ret;
65 +
66 + ret = aqr107_wait_processor_intensive_op(phydev);
67 + if (ret)
68 + return ret;
69 +
70 ret = aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
71 if (ret)
72 return ret;
73 @@ -580,30 +613,6 @@ static void aqr107_link_change_notify(st
74 phydev_info(phydev, "Aquantia 1000Base-T2 mode active\n");
75 }
76
77 -static int aqr107_wait_processor_intensive_op(struct phy_device *phydev)
78 -{
79 - int val, err;
80 -
81 - /* The datasheet notes to wait at least 1ms after issuing a
82 - * processor intensive operation before checking.
83 - * We cannot use the 'sleep_before_read' parameter of read_poll_timeout
84 - * because that just determines the maximum time slept, not the minimum.
85 - */
86 - usleep_range(1000, 5000);
87 -
88 - err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
89 - VEND1_GLOBAL_GEN_STAT2, val,
90 - !(val & VEND1_GLOBAL_GEN_STAT2_OP_IN_PROG),
91 - AQR107_OP_IN_PROG_SLEEP,
92 - AQR107_OP_IN_PROG_TIMEOUT, false);
93 - if (err) {
94 - phydev_err(phydev, "timeout: processor-intensive MDIO operation\n");
95 - return err;
96 - }
97 -
98 - return 0;
99 -}
100 -
101 static int aqr107_get_rate_matching(struct phy_device *phydev,
102 phy_interface_t iface)
103 {