kernel: 5.15: update Aquantia PHY driver to v6.1 code
[openwrt/openwrt.git] / target / linux / generic / backport-5.15 / 778-v5.18-01-net-phy-at803x-add-fiber-support.patch
1 From 3265f421887847db9ae2c01a00645e33608556d8 Mon Sep 17 00:00:00 2001
2 From: Robert Hancock <robert.hancock@calian.com>
3 Date: Tue, 25 Jan 2022 10:54:09 -0600
4 Subject: [PATCH] net: phy: at803x: add fiber support
5
6 Previously this driver always forced the copper page to be selected,
7 however for AR8031 in 100Base-FX or 1000Base-X modes, the fiber page
8 needs to be selected. Set the appropriate mode based on the hardware
9 mode_cfg strap selection.
10
11 Enable the appropriate interrupt bits to detect fiber-side link up
12 or down events.
13
14 Update config_aneg and read_status methods to use the appropriate
15 Clause 37 calls when fiber mode is in use.
16
17 Signed-off-by: Robert Hancock <robert.hancock@calian.com>
18 Signed-off-by: David S. Miller <davem@davemloft.net>
19 ---
20 drivers/net/phy/at803x.c | 76 +++++++++++++++++++++++++++++++++++-----
21 1 file changed, 67 insertions(+), 9 deletions(-)
22
23 --- a/drivers/net/phy/at803x.c
24 +++ b/drivers/net/phy/at803x.c
25 @@ -48,6 +48,8 @@
26 #define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12)
27 #define AT803X_INTR_ENABLE_LINK_FAIL BIT(11)
28 #define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10)
29 +#define AT803X_INTR_ENABLE_LINK_FAIL_BX BIT(8)
30 +#define AT803X_INTR_ENABLE_LINK_SUCCESS_BX BIT(7)
31 #define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5)
32 #define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1)
33 #define AT803X_INTR_ENABLE_WOL BIT(0)
34 @@ -82,6 +84,17 @@
35
36 #define AT803X_MODE_CFG_MASK 0x0F
37 #define AT803X_MODE_CFG_SGMII 0x01
38 +#define AT803X_MODE_CFG_BASET_RGMII 0x00
39 +#define AT803X_MODE_CFG_BASET_SGMII 0x01
40 +#define AT803X_MODE_CFG_BX1000_RGMII_50OHM 0x02
41 +#define AT803X_MODE_CFG_BX1000_RGMII_75OHM 0x03
42 +#define AT803X_MODE_CFG_BX1000_CONV_50OHM 0x04
43 +#define AT803X_MODE_CFG_BX1000_CONV_75OHM 0x05
44 +#define AT803X_MODE_CFG_FX100_RGMII_50OHM 0x06
45 +#define AT803X_MODE_CFG_FX100_CONV_50OHM 0x07
46 +#define AT803X_MODE_CFG_RGMII_AUTO_MDET 0x0B
47 +#define AT803X_MODE_CFG_FX100_RGMII_75OHM 0x0E
48 +#define AT803X_MODE_CFG_FX100_CONV_75OHM 0x0F
49
50 #define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/
51 #define AT803X_PSSR_MR_AN_COMPLETE 0x0200
52 @@ -199,6 +212,8 @@ struct at803x_priv {
53 u16 clk_25m_mask;
54 u8 smarteee_lpi_tw_1g;
55 u8 smarteee_lpi_tw_100m;
56 + bool is_fiber;
57 + bool is_1000basex;
58 struct regulator_dev *vddio_rdev;
59 struct regulator_dev *vddh_rdev;
60 struct regulator *vddio;
61 @@ -674,7 +689,33 @@ static int at803x_probe(struct phy_devic
62 return ret;
63 }
64
65 + if (phydev->drv->phy_id == ATH8031_PHY_ID) {
66 + int ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
67 + int mode_cfg;
68 +
69 + if (ccr < 0)
70 + goto err;
71 + mode_cfg = ccr & AT803X_MODE_CFG_MASK;
72 +
73 + switch (mode_cfg) {
74 + case AT803X_MODE_CFG_BX1000_RGMII_50OHM:
75 + case AT803X_MODE_CFG_BX1000_RGMII_75OHM:
76 + priv->is_1000basex = true;
77 + fallthrough;
78 + case AT803X_MODE_CFG_FX100_RGMII_50OHM:
79 + case AT803X_MODE_CFG_FX100_RGMII_75OHM:
80 + priv->is_fiber = true;
81 + break;
82 + }
83 + }
84 +
85 return 0;
86 +
87 +err:
88 + if (priv->vddio)
89 + regulator_disable(priv->vddio);
90 +
91 + return ret;
92 }
93
94 static void at803x_remove(struct phy_device *phydev)
95 @@ -687,6 +728,7 @@ static void at803x_remove(struct phy_dev
96
97 static int at803x_get_features(struct phy_device *phydev)
98 {
99 + struct at803x_priv *priv = phydev->priv;
100 int err;
101
102 err = genphy_read_abilities(phydev);
103 @@ -704,12 +746,13 @@ static int at803x_get_features(struct ph
104 * As a result of that, ESTATUS_1000_XFULL is set
105 * to 1 even when operating in copper TP mode.
106 *
107 - * Remove this mode from the supported link modes,
108 - * as this driver currently only supports copper
109 - * operation.
110 + * Remove this mode from the supported link modes
111 + * when not operating in 1000BaseX mode.
112 */
113 - linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
114 - phydev->supported);
115 + if (!priv->is_1000basex)
116 + linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
117 + phydev->supported);
118 +
119 return 0;
120 }
121
122 @@ -773,15 +816,18 @@ static int at8031_pll_config(struct phy_
123
124 static int at803x_config_init(struct phy_device *phydev)
125 {
126 + struct at803x_priv *priv = phydev->priv;
127 int ret;
128
129 if (phydev->drv->phy_id == ATH8031_PHY_ID) {
130 /* Some bootloaders leave the fiber page selected.
131 - * Switch to the copper page, as otherwise we read
132 - * the PHY capabilities from the fiber side.
133 + * Switch to the appropriate page (fiber or copper), as otherwise we
134 + * read the PHY capabilities from the wrong page.
135 */
136 phy_lock_mdio_bus(phydev);
137 - ret = at803x_write_page(phydev, AT803X_PAGE_COPPER);
138 + ret = at803x_write_page(phydev,
139 + priv->is_fiber ? AT803X_PAGE_FIBER :
140 + AT803X_PAGE_COPPER);
141 phy_unlock_mdio_bus(phydev);
142 if (ret)
143 return ret;
144 @@ -840,6 +886,7 @@ static int at803x_ack_interrupt(struct p
145
146 static int at803x_config_intr(struct phy_device *phydev)
147 {
148 + struct at803x_priv *priv = phydev->priv;
149 int err;
150 int value;
151
152 @@ -856,6 +903,10 @@ static int at803x_config_intr(struct phy
153 value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
154 value |= AT803X_INTR_ENABLE_LINK_FAIL;
155 value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
156 + if (priv->is_fiber) {
157 + value |= AT803X_INTR_ENABLE_LINK_FAIL_BX;
158 + value |= AT803X_INTR_ENABLE_LINK_SUCCESS_BX;
159 + }
160
161 err = phy_write(phydev, AT803X_INTR_ENABLE, value);
162 } else {
163 @@ -923,8 +974,12 @@ static void at803x_link_change_notify(st
164
165 static int at803x_read_status(struct phy_device *phydev)
166 {
167 + struct at803x_priv *priv = phydev->priv;
168 int ss, err, old_link = phydev->link;
169
170 + if (priv->is_1000basex)
171 + return genphy_c37_read_status(phydev);
172 +
173 /* Update the link, but return if there was an error */
174 err = genphy_update_link(phydev);
175 if (err)
176 @@ -1023,6 +1078,7 @@ static int at803x_config_mdix(struct phy
177
178 static int at803x_config_aneg(struct phy_device *phydev)
179 {
180 + struct at803x_priv *priv = phydev->priv;
181 int ret;
182
183 ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
184 @@ -1039,6 +1095,9 @@ static int at803x_config_aneg(struct phy
185 return ret;
186 }
187
188 + if (priv->is_1000basex)
189 + return genphy_c37_config_aneg(phydev);
190 +
191 return genphy_config_aneg(phydev);
192 }
193