c1655ce71e74dbe8f668d574725f920e66776b91
[openwrt/staging/wigyori.git] /
1 From a2e1ba275eae96a8171deb19e9c7c2f5978fee7b Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Fri, 4 Oct 2024 17:18:16 +0100
4 Subject: [PATCH] net: phy: aquantia: allow forcing order of MDI pairs
5
6 Despite supporting Auto MDI-X, it looks like Aquantia only supports
7 swapping pair (1,2) with pair (3,6) like it used to be for MDI-X on
8 100MBit/s networks.
9
10 When all 4 pairs are in use (for 1000MBit/s or faster) the link does not
11 come up with pair order is not configured correctly, either using
12 MDI_CFG pin or using the "PMA Receive Reserved Vendor Provisioning 1"
13 register.
14
15 Normally, the order of MDI pairs being either ABCD or DCBA is configured
16 by pulling the MDI_CFG pin.
17
18 However, some hardware designs require overriding the value configured
19 by that bootstrap pin. The PHY allows doing that by setting a bit in
20 "PMA Receive Reserved Vendor Provisioning 1" register which allows
21 ignoring the state of the MDI_CFG pin and another bit configuring
22 whether the order of MDI pairs should be normal (ABCD) or reverse
23 (DCBA). Pair polarity is not affected and remains identical in both
24 settings.
25
26 Introduce property "marvell,mdi-cfg-order" which allows forcing either
27 normal or reverse order of the MDI pairs from DT.
28
29 If the property isn't present, the behavior is unchanged and MDI pair
30 order configuration is untouched (ie. either the result of MDI_CFG pin
31 pull-up/pull-down, or pair order override already configured by the
32 bootloader before Linux is started).
33
34 Forcing normal pair order is required on the Adtran SDG-8733A Wi-Fi 7
35 residential gateway.
36
37 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
38 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
39 Link: https://patch.msgid.link/9ed760ff87d5fc456f31e407ead548bbb754497d.1728058550.git.daniel@makrotopia.org
40 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
41 ---
42 drivers/net/phy/aquantia/aquantia_main.c | 33 ++++++++++++++++++++++++
43 1 file changed, 33 insertions(+)
44
45 --- a/drivers/net/phy/aquantia/aquantia_main.c
46 +++ b/drivers/net/phy/aquantia/aquantia_main.c
47 @@ -11,6 +11,7 @@
48 #include <linux/module.h>
49 #include <linux/delay.h>
50 #include <linux/bitfield.h>
51 +#include <linux/of.h>
52 #include <linux/phy.h>
53
54 #include "aquantia.h"
55 @@ -70,6 +71,11 @@
56 #define MDIO_AN_TX_VEND_INT_MASK2 0xd401
57 #define MDIO_AN_TX_VEND_INT_MASK2_LINK BIT(0)
58
59 +#define PMAPMD_RSVD_VEND_PROV 0xe400
60 +#define PMAPMD_RSVD_VEND_PROV_MDI_CONF GENMASK(1, 0)
61 +#define PMAPMD_RSVD_VEND_PROV_MDI_REVERSE BIT(0)
62 +#define PMAPMD_RSVD_VEND_PROV_MDI_FORCE BIT(1)
63 +
64 #define MDIO_AN_RX_LP_STAT1 0xe820
65 #define MDIO_AN_RX_LP_STAT1_1000BASET_FULL BIT(15)
66 #define MDIO_AN_RX_LP_STAT1_1000BASET_HALF BIT(14)
67 @@ -497,6 +503,29 @@ static int aqr107_wait_processor_intensi
68 return 0;
69 }
70
71 +static int aqr107_config_mdi(struct phy_device *phydev)
72 +{
73 + struct device_node *np = phydev->mdio.dev.of_node;
74 + u32 mdi_conf;
75 + int ret;
76 +
77 + ret = of_property_read_u32(np, "marvell,mdi-cfg-order", &mdi_conf);
78 +
79 + /* Do nothing in case property "marvell,mdi-cfg-order" is not present */
80 + if (ret == -ENOENT)
81 + return 0;
82 +
83 + if (ret)
84 + return ret;
85 +
86 + if (mdi_conf & ~PMAPMD_RSVD_VEND_PROV_MDI_REVERSE)
87 + return -EINVAL;
88 +
89 + return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_RSVD_VEND_PROV,
90 + PMAPMD_RSVD_VEND_PROV_MDI_CONF,
91 + mdi_conf | PMAPMD_RSVD_VEND_PROV_MDI_FORCE);
92 +}
93 +
94 static int aqr107_config_init(struct phy_device *phydev)
95 {
96 struct aqr107_priv *priv = phydev->priv;
97 @@ -535,6 +564,10 @@ static int aqr107_config_init(struct phy
98 if (ret)
99 return ret;
100
101 + ret = aqr107_config_mdi(phydev);
102 + if (ret)
103 + return ret;
104 +
105 /* Restore LED polarity state after reset */
106 for_each_set_bit(led_active_low, &priv->leds_active_low, AQR_MAX_LEDS) {
107 ret = aqr_phy_led_active_low_set(phydev, led_active_low, true);