blob: c4b7ac03cd3545d05c00ef7898bfc64b8ba13040 [file] [log] [blame]
Andrew Lunna2443fd2019-01-21 19:05:50 +01001// SPDX-License-Identifier: GPL-2.0+
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00002/*
3 * drivers/net/phy/at803x.c
4 *
Michael Walle96c36712019-11-06 23:36:16 +01005 * Driver for Qualcomm Atheros AR803x PHY
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00006 *
7 * Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00008 */
9
10#include <linux/phy.h>
11#include <linux/module.h>
12#include <linux/string.h>
13#include <linux/netdevice.h>
14#include <linux/etherdevice.h>
Michael Walle6cb75762020-05-13 22:38:07 +020015#include <linux/ethtool_netlink.h>
Daniel Mack13a56b42014-06-18 11:01:43 +020016#include <linux/of_gpio.h>
Michael Walle2f664822019-11-06 23:36:14 +010017#include <linux/bitfield.h>
Daniel Mack13a56b42014-06-18 11:01:43 +020018#include <linux/gpio/consumer.h>
Michael Walle2f664822019-11-06 23:36:14 +010019#include <linux/regulator/of_regulator.h>
20#include <linux/regulator/driver.h>
21#include <linux/regulator/consumer.h>
22#include <dt-bindings/net/qca-ar803x.h>
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000023
Oleksij Rempel7dce80c2020-07-19 10:05:30 +020024#define AT803X_SPECIFIC_FUNCTION_CONTROL 0x10
25#define AT803X_SFC_ASSERT_CRS BIT(11)
26#define AT803X_SFC_FORCE_LINK BIT(10)
27#define AT803X_SFC_MDI_CROSSOVER_MODE_M GENMASK(6, 5)
28#define AT803X_SFC_AUTOMATIC_CROSSOVER 0x3
29#define AT803X_SFC_MANUAL_MDIX 0x1
30#define AT803X_SFC_MANUAL_MDI 0x0
31#define AT803X_SFC_SQE_TEST BIT(2)
32#define AT803X_SFC_POLARITY_REVERSAL BIT(1)
33#define AT803X_SFC_DISABLE_JABBER BIT(0)
34
Russell King06d5f342019-10-04 17:06:14 +010035#define AT803X_SPECIFIC_STATUS 0x11
Luo Jie9540cdd2021-10-24 16:27:28 +080036#define AT803X_SS_SPEED_MASK GENMASK(15, 14)
37#define AT803X_SS_SPEED_1000 2
38#define AT803X_SS_SPEED_100 1
39#define AT803X_SS_SPEED_10 0
Russell King06d5f342019-10-04 17:06:14 +010040#define AT803X_SS_DUPLEX BIT(13)
41#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
42#define AT803X_SS_MDIX BIT(6)
43
Luo Jie79c7bc02021-10-24 16:27:30 +080044#define QCA808X_SS_SPEED_MASK GENMASK(9, 7)
45#define QCA808X_SS_SPEED_2500 4
46
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000047#define AT803X_INTR_ENABLE 0x12
Martin Blumenstingle6e4a552016-01-15 01:55:24 +010048#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
49#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
50#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13)
51#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12)
52#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11)
53#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10)
54#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5)
55#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1)
56#define AT803X_INTR_ENABLE_WOL BIT(0)
57
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000058#define AT803X_INTR_STATUS 0x13
Martin Blumenstingla46bd632016-01-15 01:55:23 +010059
Daniel Mack13a56b42014-06-18 11:01:43 +020060#define AT803X_SMART_SPEED 0x14
Michael Wallecde0f4f2020-04-28 23:15:02 +020061#define AT803X_SMART_SPEED_ENABLE BIT(5)
62#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2)
63#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1)
Michael Walle6cb75762020-05-13 22:38:07 +020064#define AT803X_CDT 0x16
65#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8)
66#define AT803X_CDT_ENABLE_TEST BIT(0)
67#define AT803X_CDT_STATUS 0x1c
68#define AT803X_CDT_STATUS_STAT_NORMAL 0
69#define AT803X_CDT_STATUS_STAT_SHORT 1
70#define AT803X_CDT_STATUS_STAT_OPEN 2
71#define AT803X_CDT_STATUS_STAT_FAIL 3
72#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8)
73#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0)
Daniel Mack13a56b42014-06-18 11:01:43 +020074#define AT803X_LED_CONTROL 0x18
Martin Blumenstingla46bd632016-01-15 01:55:23 +010075
Luo Jie7beecaf2021-10-24 16:27:27 +080076#define AT803X_PHY_MMD3_WOL_CTRL 0x8012
77#define AT803X_WOL_EN BIT(5)
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000078#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C
79#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B
80#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A
Zefir Kurtisif62265b2016-10-24 12:40:54 +020081#define AT803X_REG_CHIP_CONFIG 0x1f
82#define AT803X_BT_BX_REG_SEL 0x8000
Martin Blumenstingla46bd632016-01-15 01:55:23 +010083
Mugunthan V N1ca6d1b2013-06-03 20:10:06 +000084#define AT803X_DEBUG_ADDR 0x1D
85#define AT803X_DEBUG_DATA 0x1E
Martin Blumenstingla46bd632016-01-15 01:55:23 +010086
Zefir Kurtisif62265b2016-10-24 12:40:54 +020087#define AT803X_MODE_CFG_MASK 0x0F
88#define AT803X_MODE_CFG_SGMII 0x01
89
Ansuel Smithd0e13fd2021-05-14 23:00:14 +020090#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/
91#define AT803X_PSSR_MR_AN_COMPLETE 0x0200
Zefir Kurtisif62265b2016-10-24 12:40:54 +020092
Ansuel Smith67999552021-10-10 00:46:18 +020093#define AT803X_DEBUG_ANALOG_TEST_CTRL 0x00
Ansuel Smith1ca83112021-10-10 00:46:16 +020094#define QCA8327_DEBUG_MANU_CTRL_EN BIT(2)
95#define QCA8337_DEBUG_MANU_CTRL_EN GENMASK(3, 2)
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +010096#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15)
Martin Blumenstingla46bd632016-01-15 01:55:23 +010097
Ansuel Smith67999552021-10-10 00:46:18 +020098#define AT803X_DEBUG_SYSTEM_CTRL_MODE 0x05
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +010099#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000100
Ansuel Smithba3c01e2021-10-10 00:46:15 +0200101#define AT803X_DEBUG_REG_HIB_CTRL 0x0b
102#define AT803X_DEBUG_HIB_CTRL_SEL_RST_80U BIT(10)
103#define AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE BIT(13)
104
Ansuel Smith272833b2021-05-14 23:00:15 +0200105#define AT803X_DEBUG_REG_3C 0x3C
106
Ansuel Smith67999552021-10-10 00:46:18 +0200107#define AT803X_DEBUG_REG_GREEN 0x3D
Ansuel Smithba3c01e2021-10-10 00:46:15 +0200108#define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6)
Ansuel Smith272833b2021-05-14 23:00:15 +0200109
Michael Walle2f664822019-11-06 23:36:14 +0100110#define AT803X_DEBUG_REG_1F 0x1F
111#define AT803X_DEBUG_PLL_ON BIT(2)
112#define AT803X_DEBUG_RGMII_1V8 BIT(3)
113
Ansuel Smith272833b2021-05-14 23:00:15 +0200114#define MDIO_AZ_DEBUG 0x800D
115
Michael Walle2f664822019-11-06 23:36:14 +0100116/* AT803x supports either the XTAL input pad, an internal PLL or the
117 * DSP as clock reference for the clock output pad. The XTAL reference
118 * is only used for 25 MHz output, all other frequencies need the PLL.
119 * The DSP as a clock reference is used in synchronous ethernet
120 * applications.
121 *
122 * By default the PLL is only enabled if there is a link. Otherwise
123 * the PHY will go into low power state and disabled the PLL. You can
124 * set the PLL_ON bit (see debug register 0x1f) to keep the PLL always
125 * enabled.
126 */
127#define AT803X_MMD7_CLK25M 0x8016
128#define AT803X_CLK_OUT_MASK GENMASK(4, 2)
129#define AT803X_CLK_OUT_25MHZ_XTAL 0
130#define AT803X_CLK_OUT_25MHZ_DSP 1
131#define AT803X_CLK_OUT_50MHZ_PLL 2
132#define AT803X_CLK_OUT_50MHZ_DSP 3
133#define AT803X_CLK_OUT_62_5MHZ_PLL 4
134#define AT803X_CLK_OUT_62_5MHZ_DSP 5
135#define AT803X_CLK_OUT_125MHZ_PLL 6
136#define AT803X_CLK_OUT_125MHZ_DSP 7
137
Michael Walle428061f2019-11-06 23:36:15 +0100138/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask
139 * but doesn't support choosing between XTAL/PLL and DSP.
Michael Walle2f664822019-11-06 23:36:14 +0100140 */
141#define AT8035_CLK_OUT_MASK GENMASK(4, 3)
142
143#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7)
144#define AT803X_CLK_OUT_STRENGTH_FULL 0
145#define AT803X_CLK_OUT_STRENGTH_HALF 1
146#define AT803X_CLK_OUT_STRENGTH_QUARTER 2
147
Ansuel Smithd0e13fd2021-05-14 23:00:14 +0200148#define AT803X_DEFAULT_DOWNSHIFT 5
149#define AT803X_MIN_DOWNSHIFT 2
150#define AT803X_MAX_DOWNSHIFT 9
Michael Wallecde0f4f2020-04-28 23:15:02 +0200151
Russell King390b4ca2021-01-14 10:45:49 +0000152#define AT803X_MMD3_SMARTEEE_CTL1 0x805b
153#define AT803X_MMD3_SMARTEEE_CTL2 0x805c
154#define AT803X_MMD3_SMARTEEE_CTL3 0x805d
155#define AT803X_MMD3_SMARTEEE_CTL3_LPI_EN BIT(8)
156
Ansuel Smithd0e13fd2021-05-14 23:00:14 +0200157#define ATH9331_PHY_ID 0x004dd041
158#define ATH8030_PHY_ID 0x004dd076
159#define ATH8031_PHY_ID 0x004dd074
160#define ATH8032_PHY_ID 0x004dd023
161#define ATH8035_PHY_ID 0x004dd072
Michael Walle0465d8f2020-05-22 11:53:31 +0200162#define AT8030_PHY_ID_MASK 0xffffffef
Daniel Mackbd8ca172014-06-18 11:01:42 +0200163
Luo Jiedaf61732021-10-24 16:27:29 +0800164#define QCA8081_PHY_ID 0x004dd101
165
Ansuel Smithb4df02b2021-09-19 18:28:15 +0200166#define QCA8327_A_PHY_ID 0x004dd033
167#define QCA8327_B_PHY_ID 0x004dd034
Ansuel Smith272833b2021-05-14 23:00:15 +0200168#define QCA8337_PHY_ID 0x004dd036
David Bauerfada2ce2021-10-06 00:54:01 +0200169#define QCA9561_PHY_ID 0x004dd042
Ansuel Smith272833b2021-05-14 23:00:15 +0200170#define QCA8K_PHY_ID_MASK 0xffffffff
171
172#define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0)
173
Ansuel Smithd0e13fd2021-05-14 23:00:14 +0200174#define AT803X_PAGE_FIBER 0
175#define AT803X_PAGE_COPPER 1
176
177/* don't turn off internal PLL */
178#define AT803X_KEEP_PLL_ENABLED BIT(0)
179#define AT803X_DISABLE_SMARTEEE BIT(1)
David Bauerc329e5a2021-04-15 03:26:50 +0200180
Luo Jiedaf61732021-10-24 16:27:29 +0800181MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000182MODULE_AUTHOR("Matus Ujhelyi");
183MODULE_LICENSE("GPL");
184
Ansuel Smith272833b2021-05-14 23:00:15 +0200185enum stat_access_type {
186 PHY,
187 MMD
188};
189
190struct at803x_hw_stat {
191 const char *string;
192 u8 reg;
193 u32 mask;
194 enum stat_access_type access_type;
195};
196
197static struct at803x_hw_stat at803x_hw_stats[] = {
198 { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY},
199 { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY},
200 { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD},
201};
202
Michael Walle2f664822019-11-06 23:36:14 +0100203struct at803x_priv {
204 int flags;
Michael Walle2f664822019-11-06 23:36:14 +0100205 u16 clk_25m_reg;
206 u16 clk_25m_mask;
Russell King390b4ca2021-01-14 10:45:49 +0000207 u8 smarteee_lpi_tw_1g;
208 u8 smarteee_lpi_tw_100m;
Michael Walle2f664822019-11-06 23:36:14 +0100209 struct regulator_dev *vddio_rdev;
210 struct regulator_dev *vddh_rdev;
211 struct regulator *vddio;
Ansuel Smith272833b2021-05-14 23:00:15 +0200212 u64 stats[ARRAY_SIZE(at803x_hw_stats)];
Michael Walle2f664822019-11-06 23:36:14 +0100213};
214
Daniel Mack13a56b42014-06-18 11:01:43 +0200215struct at803x_context {
216 u16 bmcr;
217 u16 advertise;
218 u16 control1000;
219 u16 int_enable;
220 u16 smart_speed;
221 u16 led_control;
222};
223
Ansuel Smith272833b2021-05-14 23:00:15 +0200224static int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data)
225{
226 int ret;
227
228 ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
229 if (ret < 0)
230 return ret;
231
232 return phy_write(phydev, AT803X_DEBUG_DATA, data);
233}
234
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100235static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
236{
237 int ret;
238
239 ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
240 if (ret < 0)
241 return ret;
242
243 return phy_read(phydev, AT803X_DEBUG_DATA);
244}
245
246static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
247 u16 clear, u16 set)
248{
249 u16 val;
250 int ret;
251
252 ret = at803x_debug_reg_read(phydev, reg);
253 if (ret < 0)
254 return ret;
255
256 val = ret & 0xffff;
257 val &= ~clear;
258 val |= set;
259
260 return phy_write(phydev, AT803X_DEBUG_DATA, val);
261}
262
David Bauerc329e5a2021-04-15 03:26:50 +0200263static int at803x_write_page(struct phy_device *phydev, int page)
264{
265 int mask;
266 int set;
267
268 if (page == AT803X_PAGE_COPPER) {
269 set = AT803X_BT_BX_REG_SEL;
270 mask = 0;
271 } else {
272 set = 0;
273 mask = AT803X_BT_BX_REG_SEL;
274 }
275
276 return __phy_modify(phydev, AT803X_REG_CHIP_CONFIG, mask, set);
277}
278
279static int at803x_read_page(struct phy_device *phydev)
280{
281 int ccr = __phy_read(phydev, AT803X_REG_CHIP_CONFIG);
282
283 if (ccr < 0)
284 return ccr;
285
286 if (ccr & AT803X_BT_BX_REG_SEL)
287 return AT803X_PAGE_COPPER;
288
289 return AT803X_PAGE_FIBER;
290}
291
Vinod Koul6d4cd042019-02-21 15:53:15 +0530292static int at803x_enable_rx_delay(struct phy_device *phydev)
293{
Ansuel Smith67999552021-10-10 00:46:18 +0200294 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0,
Vinod Koul6d4cd042019-02-21 15:53:15 +0530295 AT803X_DEBUG_RX_CLK_DLY_EN);
296}
297
298static int at803x_enable_tx_delay(struct phy_device *phydev)
299{
Ansuel Smith67999552021-10-10 00:46:18 +0200300 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0,
Vinod Koul6d4cd042019-02-21 15:53:15 +0530301 AT803X_DEBUG_TX_CLK_DLY_EN);
302}
303
Vinod Koul43f2ebd2019-02-21 15:53:14 +0530304static int at803x_disable_rx_delay(struct phy_device *phydev)
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100305{
Ansuel Smith67999552021-10-10 00:46:18 +0200306 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
Vinod Koulcd28d1d2019-01-21 14:43:17 +0530307 AT803X_DEBUG_RX_CLK_DLY_EN, 0);
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100308}
309
Vinod Koul43f2ebd2019-02-21 15:53:14 +0530310static int at803x_disable_tx_delay(struct phy_device *phydev)
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100311{
Ansuel Smith67999552021-10-10 00:46:18 +0200312 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE,
Vinod Koulcd28d1d2019-01-21 14:43:17 +0530313 AT803X_DEBUG_TX_CLK_DLY_EN, 0);
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100314}
315
Daniel Mack13a56b42014-06-18 11:01:43 +0200316/* save relevant PHY registers to private copy */
317static void at803x_context_save(struct phy_device *phydev,
318 struct at803x_context *context)
319{
320 context->bmcr = phy_read(phydev, MII_BMCR);
321 context->advertise = phy_read(phydev, MII_ADVERTISE);
322 context->control1000 = phy_read(phydev, MII_CTRL1000);
323 context->int_enable = phy_read(phydev, AT803X_INTR_ENABLE);
324 context->smart_speed = phy_read(phydev, AT803X_SMART_SPEED);
325 context->led_control = phy_read(phydev, AT803X_LED_CONTROL);
326}
327
328/* restore relevant PHY registers from private copy */
329static void at803x_context_restore(struct phy_device *phydev,
330 const struct at803x_context *context)
331{
332 phy_write(phydev, MII_BMCR, context->bmcr);
333 phy_write(phydev, MII_ADVERTISE, context->advertise);
334 phy_write(phydev, MII_CTRL1000, context->control1000);
335 phy_write(phydev, AT803X_INTR_ENABLE, context->int_enable);
336 phy_write(phydev, AT803X_SMART_SPEED, context->smart_speed);
337 phy_write(phydev, AT803X_LED_CONTROL, context->led_control);
338}
339
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000340static int at803x_set_wol(struct phy_device *phydev,
341 struct ethtool_wolinfo *wol)
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000342{
343 struct net_device *ndev = phydev->attached_dev;
344 const u8 *mac;
Luo Jie7beecaf2021-10-24 16:27:27 +0800345 int ret, irq_enabled;
Luo Jiec0f0b562021-10-24 16:27:25 +0800346 unsigned int i;
347 const unsigned int offsets[] = {
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000348 AT803X_LOC_MAC_ADDR_32_47_OFFSET,
349 AT803X_LOC_MAC_ADDR_16_31_OFFSET,
350 AT803X_LOC_MAC_ADDR_0_15_OFFSET,
351 };
352
353 if (!ndev)
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000354 return -ENODEV;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000355
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000356 if (wol->wolopts & WAKE_MAGIC) {
357 mac = (const u8 *) ndev->dev_addr;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000358
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000359 if (!is_valid_ether_addr(mac))
Dan Murphyfc755682017-10-10 12:42:56 -0500360 return -EINVAL;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000361
Carlo Caione0e021392019-01-25 12:35:10 +0000362 for (i = 0; i < 3; i++)
Luo Jiec0f0b562021-10-24 16:27:25 +0800363 phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
Carlo Caione0e021392019-01-25 12:35:10 +0000364 mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000365
Luo Jie7beecaf2021-10-24 16:27:27 +0800366 /* Enable WOL function */
367 ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
368 0, AT803X_WOL_EN);
369 if (ret)
370 return ret;
371 /* Enable WOL interrupt */
Luo Jie2d4284e2021-10-24 16:27:26 +0800372 ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000373 if (ret)
374 return ret;
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000375 } else {
Luo Jie7beecaf2021-10-24 16:27:27 +0800376 /* Disable WoL function */
377 ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL,
378 AT803X_WOL_EN, 0);
379 if (ret)
380 return ret;
381 /* Disable WOL interrupt */
Luo Jie2d4284e2021-10-24 16:27:26 +0800382 ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000383 if (ret)
384 return ret;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000385 }
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000386
Luo Jie7beecaf2021-10-24 16:27:27 +0800387 /* Clear WOL status */
388 ret = phy_read(phydev, AT803X_INTR_STATUS);
389 if (ret < 0)
390 return ret;
391
392 /* Check if there are other interrupts except for WOL triggered when PHY is
393 * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can
394 * be passed up to the interrupt PIN.
395 */
396 irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
397 if (irq_enabled < 0)
398 return irq_enabled;
399
400 irq_enabled &= ~AT803X_INTR_ENABLE_WOL;
401 if (ret & irq_enabled && !phy_polling_mode(phydev))
402 phy_trigger_machine(phydev);
403
404 return 0;
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000405}
406
407static void at803x_get_wol(struct phy_device *phydev,
408 struct ethtool_wolinfo *wol)
409{
410 u32 value;
411
412 wol->supported = WAKE_MAGIC;
413 wol->wolopts = 0;
414
Luo Jie7beecaf2021-10-24 16:27:27 +0800415 value = phy_read_mmd(phydev, MDIO_MMD_PCS, AT803X_PHY_MMD3_WOL_CTRL);
416 if (value < 0)
417 return;
418
419 if (value & AT803X_WOL_EN)
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000420 wol->wolopts |= WAKE_MAGIC;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000421}
422
Ansuel Smith272833b2021-05-14 23:00:15 +0200423static int at803x_get_sset_count(struct phy_device *phydev)
424{
425 return ARRAY_SIZE(at803x_hw_stats);
426}
427
428static void at803x_get_strings(struct phy_device *phydev, u8 *data)
429{
430 int i;
431
432 for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++) {
433 strscpy(data + i * ETH_GSTRING_LEN,
434 at803x_hw_stats[i].string, ETH_GSTRING_LEN);
435 }
436}
437
438static u64 at803x_get_stat(struct phy_device *phydev, int i)
439{
440 struct at803x_hw_stat stat = at803x_hw_stats[i];
441 struct at803x_priv *priv = phydev->priv;
442 int val;
443 u64 ret;
444
445 if (stat.access_type == MMD)
446 val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg);
447 else
448 val = phy_read(phydev, stat.reg);
449
450 if (val < 0) {
451 ret = U64_MAX;
452 } else {
453 val = val & stat.mask;
454 priv->stats[i] += val;
455 ret = priv->stats[i];
456 }
457
458 return ret;
459}
460
461static void at803x_get_stats(struct phy_device *phydev,
462 struct ethtool_stats *stats, u64 *data)
463{
464 int i;
465
466 for (i = 0; i < ARRAY_SIZE(at803x_hw_stats); i++)
467 data[i] = at803x_get_stat(phydev, i);
468}
469
Daniel Mack6229ed12013-09-21 16:53:02 +0200470static int at803x_suspend(struct phy_device *phydev)
471{
472 int value;
473 int wol_enabled;
474
Daniel Mack6229ed12013-09-21 16:53:02 +0200475 value = phy_read(phydev, AT803X_INTR_ENABLE);
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100476 wol_enabled = value & AT803X_INTR_ENABLE_WOL;
Daniel Mack6229ed12013-09-21 16:53:02 +0200477
Daniel Mack6229ed12013-09-21 16:53:02 +0200478 if (wol_enabled)
Russell Kingfea23fb2018-01-02 10:58:58 +0000479 value = BMCR_ISOLATE;
Daniel Mack6229ed12013-09-21 16:53:02 +0200480 else
Russell Kingfea23fb2018-01-02 10:58:58 +0000481 value = BMCR_PDOWN;
Daniel Mack6229ed12013-09-21 16:53:02 +0200482
Russell Kingfea23fb2018-01-02 10:58:58 +0000483 phy_modify(phydev, MII_BMCR, 0, value);
Daniel Mack6229ed12013-09-21 16:53:02 +0200484
485 return 0;
486}
487
488static int at803x_resume(struct phy_device *phydev)
489{
Russell Kingf1028522018-01-05 16:07:10 +0000490 return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0);
Daniel Mack6229ed12013-09-21 16:53:02 +0200491}
492
Michael Walle2f664822019-11-06 23:36:14 +0100493static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
494 unsigned int selector)
495{
496 struct phy_device *phydev = rdev_get_drvdata(rdev);
497
498 if (selector)
499 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
500 0, AT803X_DEBUG_RGMII_1V8);
501 else
502 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
503 AT803X_DEBUG_RGMII_1V8, 0);
504}
505
506static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev)
507{
508 struct phy_device *phydev = rdev_get_drvdata(rdev);
509 int val;
510
511 val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F);
512 if (val < 0)
513 return val;
514
515 return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0;
516}
517
Rikard Falkeborn3faaf532020-08-27 00:56:06 +0200518static const struct regulator_ops vddio_regulator_ops = {
Michael Walle2f664822019-11-06 23:36:14 +0100519 .list_voltage = regulator_list_voltage_table,
520 .set_voltage_sel = at803x_rgmii_reg_set_voltage_sel,
521 .get_voltage_sel = at803x_rgmii_reg_get_voltage_sel,
522};
523
524static const unsigned int vddio_voltage_table[] = {
525 1500000,
526 1800000,
527};
528
529static const struct regulator_desc vddio_desc = {
530 .name = "vddio",
531 .of_match = of_match_ptr("vddio-regulator"),
532 .n_voltages = ARRAY_SIZE(vddio_voltage_table),
533 .volt_table = vddio_voltage_table,
534 .ops = &vddio_regulator_ops,
535 .type = REGULATOR_VOLTAGE,
536 .owner = THIS_MODULE,
537};
538
Rikard Falkeborn3faaf532020-08-27 00:56:06 +0200539static const struct regulator_ops vddh_regulator_ops = {
Michael Walle2f664822019-11-06 23:36:14 +0100540};
541
542static const struct regulator_desc vddh_desc = {
543 .name = "vddh",
544 .of_match = of_match_ptr("vddh-regulator"),
545 .n_voltages = 1,
546 .fixed_uV = 2500000,
547 .ops = &vddh_regulator_ops,
548 .type = REGULATOR_VOLTAGE,
549 .owner = THIS_MODULE,
550};
551
552static int at8031_register_regulators(struct phy_device *phydev)
553{
554 struct at803x_priv *priv = phydev->priv;
555 struct device *dev = &phydev->mdio.dev;
556 struct regulator_config config = { };
557
558 config.dev = dev;
559 config.driver_data = phydev;
560
561 priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config);
562 if (IS_ERR(priv->vddio_rdev)) {
563 phydev_err(phydev, "failed to register VDDIO regulator\n");
564 return PTR_ERR(priv->vddio_rdev);
565 }
566
567 priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config);
568 if (IS_ERR(priv->vddh_rdev)) {
569 phydev_err(phydev, "failed to register VDDH regulator\n");
570 return PTR_ERR(priv->vddh_rdev);
571 }
572
573 return 0;
574}
575
Michael Walle2f664822019-11-06 23:36:14 +0100576static int at803x_parse_dt(struct phy_device *phydev)
577{
578 struct device_node *node = phydev->mdio.dev.of_node;
579 struct at803x_priv *priv = phydev->priv;
Russell King390b4ca2021-01-14 10:45:49 +0000580 u32 freq, strength, tw;
Andrew Lunn3f2edd32020-07-07 03:49:33 +0200581 unsigned int sel;
Michael Walle2f664822019-11-06 23:36:14 +0100582 int ret;
583
584 if (!IS_ENABLED(CONFIG_OF_MDIO))
585 return 0;
586
Russell King390b4ca2021-01-14 10:45:49 +0000587 if (of_property_read_bool(node, "qca,disable-smarteee"))
588 priv->flags |= AT803X_DISABLE_SMARTEEE;
589
590 if (!of_property_read_u32(node, "qca,smarteee-tw-us-1g", &tw)) {
591 if (!tw || tw > 255) {
592 phydev_err(phydev, "invalid qca,smarteee-tw-us-1g\n");
593 return -EINVAL;
594 }
595 priv->smarteee_lpi_tw_1g = tw;
596 }
597
598 if (!of_property_read_u32(node, "qca,smarteee-tw-us-100m", &tw)) {
599 if (!tw || tw > 255) {
600 phydev_err(phydev, "invalid qca,smarteee-tw-us-100m\n");
601 return -EINVAL;
602 }
603 priv->smarteee_lpi_tw_100m = tw;
604 }
605
Michael Walle2f664822019-11-06 23:36:14 +0100606 ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq);
607 if (!ret) {
Michael Walle2f664822019-11-06 23:36:14 +0100608 switch (freq) {
609 case 25000000:
610 sel = AT803X_CLK_OUT_25MHZ_XTAL;
611 break;
612 case 50000000:
613 sel = AT803X_CLK_OUT_50MHZ_PLL;
614 break;
615 case 62500000:
616 sel = AT803X_CLK_OUT_62_5MHZ_PLL;
617 break;
618 case 125000000:
619 sel = AT803X_CLK_OUT_125MHZ_PLL;
620 break;
621 default:
622 phydev_err(phydev, "invalid qca,clk-out-frequency\n");
623 return -EINVAL;
624 }
625
Andrew Lunn3f2edd32020-07-07 03:49:33 +0200626 priv->clk_25m_reg |= FIELD_PREP(AT803X_CLK_OUT_MASK, sel);
627 priv->clk_25m_mask |= AT803X_CLK_OUT_MASK;
Michael Walle2f664822019-11-06 23:36:14 +0100628
629 /* Fixup for the AR8030/AR8035. This chip has another mask and
630 * doesn't support the DSP reference. Eg. the lowest bit of the
631 * mask. The upper two bits select the same frequencies. Mask
632 * the lowest bit here.
633 *
634 * Warning:
635 * There was no datasheet for the AR8030 available so this is
636 * just a guess. But the AR8035 is listed as pin compatible
637 * to the AR8030 so there might be a good chance it works on
638 * the AR8030 too.
639 */
Russell King8887ca52021-07-20 14:33:49 +0100640 if (phydev->drv->phy_id == ATH8030_PHY_ID ||
641 phydev->drv->phy_id == ATH8035_PHY_ID) {
Oleksij Rempelb1f4c202020-04-01 11:57:32 +0200642 priv->clk_25m_reg &= AT8035_CLK_OUT_MASK;
643 priv->clk_25m_mask &= AT8035_CLK_OUT_MASK;
Michael Walle2f664822019-11-06 23:36:14 +0100644 }
645 }
646
647 ret = of_property_read_u32(node, "qca,clk-out-strength", &strength);
648 if (!ret) {
649 priv->clk_25m_mask |= AT803X_CLK_OUT_STRENGTH_MASK;
650 switch (strength) {
651 case AR803X_STRENGTH_FULL:
652 priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_FULL;
653 break;
654 case AR803X_STRENGTH_HALF:
655 priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_HALF;
656 break;
657 case AR803X_STRENGTH_QUARTER:
658 priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_QUARTER;
659 break;
660 default:
661 phydev_err(phydev, "invalid qca,clk-out-strength\n");
662 return -EINVAL;
663 }
664 }
665
Michael Walle428061f2019-11-06 23:36:15 +0100666 /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping
667 * options.
668 */
Russell King8887ca52021-07-20 14:33:49 +0100669 if (phydev->drv->phy_id == ATH8031_PHY_ID) {
Michael Walle2f664822019-11-06 23:36:14 +0100670 if (of_property_read_bool(node, "qca,keep-pll-enabled"))
671 priv->flags |= AT803X_KEEP_PLL_ENABLED;
672
673 ret = at8031_register_regulators(phydev);
674 if (ret < 0)
675 return ret;
676
677 priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev,
678 "vddio");
679 if (IS_ERR(priv->vddio)) {
680 phydev_err(phydev, "failed to get VDDIO regulator\n");
681 return PTR_ERR(priv->vddio);
682 }
Michael Walle2f664822019-11-06 23:36:14 +0100683 }
684
685 return 0;
686}
687
688static int at803x_probe(struct phy_device *phydev)
689{
690 struct device *dev = &phydev->mdio.dev;
691 struct at803x_priv *priv;
David Bauerc329e5a2021-04-15 03:26:50 +0200692 int ret;
Michael Walle2f664822019-11-06 23:36:14 +0100693
694 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
695 if (!priv)
696 return -ENOMEM;
697
698 phydev->priv = priv;
699
David Bauerc329e5a2021-04-15 03:26:50 +0200700 ret = at803x_parse_dt(phydev);
701 if (ret)
702 return ret;
703
Michael Walle8f7e8762021-04-20 12:29:29 +0200704 if (priv->vddio) {
705 ret = regulator_enable(priv->vddio);
706 if (ret < 0)
707 return ret;
708 }
709
David Bauerc329e5a2021-04-15 03:26:50 +0200710 /* Some bootloaders leave the fiber page selected.
711 * Switch to the copper page, as otherwise we read
712 * the PHY capabilities from the fiber side.
713 */
Russell King8887ca52021-07-20 14:33:49 +0100714 if (phydev->drv->phy_id == ATH8031_PHY_ID) {
Michael Walle8f7e8762021-04-20 12:29:29 +0200715 phy_lock_mdio_bus(phydev);
716 ret = at803x_write_page(phydev, AT803X_PAGE_COPPER);
717 phy_unlock_mdio_bus(phydev);
718 if (ret)
719 goto err;
David Bauerc329e5a2021-04-15 03:26:50 +0200720 }
721
Michael Walle8f7e8762021-04-20 12:29:29 +0200722 return 0;
723
724err:
725 if (priv->vddio)
726 regulator_disable(priv->vddio);
727
David Bauerc329e5a2021-04-15 03:26:50 +0200728 return ret;
Michael Walle2f664822019-11-06 23:36:14 +0100729}
730
Michael Walle2318ca82020-01-30 18:54:02 +0100731static void at803x_remove(struct phy_device *phydev)
732{
733 struct at803x_priv *priv = phydev->priv;
734
735 if (priv->vddio)
736 regulator_disable(priv->vddio);
737}
738
David Bauerb8561502021-06-27 12:16:07 +0200739static int at803x_get_features(struct phy_device *phydev)
740{
741 int err;
742
743 err = genphy_read_abilities(phydev);
744 if (err)
745 return err;
746
Luo Jie765c22a2021-10-24 16:27:31 +0800747 if (phydev->drv->phy_id == QCA8081_PHY_ID) {
748 err = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_NG_EXTABLE);
749 if (err < 0)
750 return err;
751
752 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported,
753 err & MDIO_PMA_NG_EXTABLE_2_5GBT);
754 }
755
Vladimir Olteanf5621a02021-07-20 20:24:33 +0300756 if (phydev->drv->phy_id != ATH8031_PHY_ID)
David Bauerb8561502021-06-27 12:16:07 +0200757 return 0;
758
759 /* AR8031/AR8033 have different status registers
760 * for copper and fiber operation. However, the
761 * extended status register is the same for both
762 * operation modes.
763 *
764 * As a result of that, ESTATUS_1000_XFULL is set
765 * to 1 even when operating in copper TP mode.
766 *
767 * Remove this mode from the supported link modes,
768 * as this driver currently only supports copper
769 * operation.
770 */
771 linkmode_clear_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
772 phydev->supported);
773 return 0;
774}
775
Russell King390b4ca2021-01-14 10:45:49 +0000776static int at803x_smarteee_config(struct phy_device *phydev)
777{
778 struct at803x_priv *priv = phydev->priv;
779 u16 mask = 0, val = 0;
780 int ret;
781
782 if (priv->flags & AT803X_DISABLE_SMARTEEE)
783 return phy_modify_mmd(phydev, MDIO_MMD_PCS,
784 AT803X_MMD3_SMARTEEE_CTL3,
785 AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0);
786
787 if (priv->smarteee_lpi_tw_1g) {
788 mask |= 0xff00;
789 val |= priv->smarteee_lpi_tw_1g << 8;
790 }
791 if (priv->smarteee_lpi_tw_100m) {
792 mask |= 0x00ff;
793 val |= priv->smarteee_lpi_tw_100m;
794 }
795 if (!mask)
796 return 0;
797
798 ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL1,
799 mask, val);
800 if (ret)
801 return ret;
802
803 return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3,
804 AT803X_MMD3_SMARTEEE_CTL3_LPI_EN,
805 AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
806}
807
Michael Walle2f664822019-11-06 23:36:14 +0100808static int at803x_clk_out_config(struct phy_device *phydev)
809{
810 struct at803x_priv *priv = phydev->priv;
Michael Walle2f664822019-11-06 23:36:14 +0100811
812 if (!priv->clk_25m_mask)
813 return 0;
814
Russell Kinga45c1c12021-01-10 14:54:36 +0000815 return phy_modify_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M,
816 priv->clk_25m_mask, priv->clk_25m_reg);
Michael Walle2f664822019-11-06 23:36:14 +0100817}
818
819static int at8031_pll_config(struct phy_device *phydev)
820{
821 struct at803x_priv *priv = phydev->priv;
822
823 /* The default after hardware reset is PLL OFF. After a soft reset, the
824 * values are retained.
825 */
826 if (priv->flags & AT803X_KEEP_PLL_ENABLED)
827 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
828 0, AT803X_DEBUG_PLL_ON);
829 else
830 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
831 AT803X_DEBUG_PLL_ON, 0);
832}
833
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000834static int at803x_config_init(struct phy_device *phydev)
835{
Mugunthan V N1ca6d1b2013-06-03 20:10:06 +0000836 int ret;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000837
Vinod Koul6d4cd042019-02-21 15:53:15 +0530838 /* The RX and TX delay default is:
839 * after HW reset: RX delay enabled and TX delay disabled
840 * after SW reset: RX delay enabled, while TX delay retains the
841 * value before reset.
Vinod Koul6d4cd042019-02-21 15:53:15 +0530842 */
Vinod Koul6d4cd042019-02-21 15:53:15 +0530843 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
André Draszikbb0ce4c2019-08-09 12:20:25 +0100844 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
Vinod Koul6d4cd042019-02-21 15:53:15 +0530845 ret = at803x_enable_rx_delay(phydev);
André Draszikbb0ce4c2019-08-09 12:20:25 +0100846 else
847 ret = at803x_disable_rx_delay(phydev);
848 if (ret < 0)
849 return ret;
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100850
Vinod Koul6d4cd042019-02-21 15:53:15 +0530851 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
André Draszikbb0ce4c2019-08-09 12:20:25 +0100852 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
Vinod Koul6d4cd042019-02-21 15:53:15 +0530853 ret = at803x_enable_tx_delay(phydev);
André Draszikbb0ce4c2019-08-09 12:20:25 +0100854 else
855 ret = at803x_disable_tx_delay(phydev);
Michael Walle2f664822019-11-06 23:36:14 +0100856 if (ret < 0)
857 return ret;
Mugunthan V N1ca6d1b2013-06-03 20:10:06 +0000858
Russell King390b4ca2021-01-14 10:45:49 +0000859 ret = at803x_smarteee_config(phydev);
860 if (ret < 0)
861 return ret;
862
Michael Walle2f664822019-11-06 23:36:14 +0100863 ret = at803x_clk_out_config(phydev);
864 if (ret < 0)
865 return ret;
866
Russell King8887ca52021-07-20 14:33:49 +0100867 if (phydev->drv->phy_id == ATH8031_PHY_ID) {
Michael Walle2f664822019-11-06 23:36:14 +0100868 ret = at8031_pll_config(phydev);
869 if (ret < 0)
870 return ret;
871 }
872
Russell King3c51fa52021-01-12 22:59:43 +0000873 /* Ar803x extended next page bit is enabled by default. Cisco
874 * multigig switches read this bit and attempt to negotiate 10Gbps
875 * rates even if the next page bit is disabled. This is incorrect
876 * behaviour but we still need to accommodate it. XNP is only needed
877 * for 10Gbps support, so disable XNP.
878 */
879 return phy_modify(phydev, MII_ADVERTISE, MDIO_AN_CTRL1_XNP, 0);
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000880}
881
Zhao Qiang77a99392014-03-28 15:39:41 +0800882static int at803x_ack_interrupt(struct phy_device *phydev)
883{
884 int err;
885
Martin Blumenstingla46bd632016-01-15 01:55:23 +0100886 err = phy_read(phydev, AT803X_INTR_STATUS);
Zhao Qiang77a99392014-03-28 15:39:41 +0800887
888 return (err < 0) ? err : 0;
889}
890
891static int at803x_config_intr(struct phy_device *phydev)
892{
893 int err;
894 int value;
895
Martin Blumenstingla46bd632016-01-15 01:55:23 +0100896 value = phy_read(phydev, AT803X_INTR_ENABLE);
Zhao Qiang77a99392014-03-28 15:39:41 +0800897
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100898 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
Ioana Ciorneia3417882020-11-01 14:51:00 +0200899 /* Clear any pending interrupts */
900 err = at803x_ack_interrupt(phydev);
901 if (err)
902 return err;
903
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100904 value |= AT803X_INTR_ENABLE_AUTONEG_ERR;
905 value |= AT803X_INTR_ENABLE_SPEED_CHANGED;
906 value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
907 value |= AT803X_INTR_ENABLE_LINK_FAIL;
908 value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
909
910 err = phy_write(phydev, AT803X_INTR_ENABLE, value);
Ioana Ciorneia3417882020-11-01 14:51:00 +0200911 } else {
Martin Blumenstingla46bd632016-01-15 01:55:23 +0100912 err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
Ioana Ciorneia3417882020-11-01 14:51:00 +0200913 if (err)
914 return err;
915
916 /* Clear any pending interrupts */
917 err = at803x_ack_interrupt(phydev);
918 }
Zhao Qiang77a99392014-03-28 15:39:41 +0800919
920 return err;
921}
922
Ioana Ciornei29773092020-11-01 14:50:59 +0200923static irqreturn_t at803x_handle_interrupt(struct phy_device *phydev)
924{
925 int irq_status, int_enabled;
926
927 irq_status = phy_read(phydev, AT803X_INTR_STATUS);
928 if (irq_status < 0) {
929 phy_error(phydev);
930 return IRQ_NONE;
931 }
932
933 /* Read the current enabled interrupts */
934 int_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
935 if (int_enabled < 0) {
936 phy_error(phydev);
937 return IRQ_NONE;
938 }
939
940 /* See if this was one of our enabled interrupts */
941 if (!(irq_status & int_enabled))
942 return IRQ_NONE;
943
944 phy_trigger_machine(phydev);
945
946 return IRQ_HANDLED;
947}
948
Daniel Mack13a56b42014-06-18 11:01:43 +0200949static void at803x_link_change_notify(struct phy_device *phydev)
950{
Daniel Mack13a56b42014-06-18 11:01:43 +0200951 /*
952 * Conduct a hardware reset for AT8030 every time a link loss is
953 * signalled. This is necessary to circumvent a hardware bug that
954 * occurs when the cable is unplugged while TX packets are pending
955 * in the FIFO. In such cases, the FIFO enters an error mode it
956 * cannot recover from by software.
957 */
David Bauer6110ed22019-04-17 23:59:22 +0200958 if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) {
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100959 struct at803x_context context;
Daniel Mack13a56b42014-06-18 11:01:43 +0200960
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100961 at803x_context_save(phydev, &context);
Daniel Mack13a56b42014-06-18 11:01:43 +0200962
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100963 phy_device_reset(phydev, 1);
964 msleep(1);
965 phy_device_reset(phydev, 0);
966 msleep(1);
Daniel Mack13a56b42014-06-18 11:01:43 +0200967
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100968 at803x_context_restore(phydev, &context);
Daniel Mack13a56b42014-06-18 11:01:43 +0200969
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100970 phydev_dbg(phydev, "%s(): phy was reset\n", __func__);
Daniel Mack13a56b42014-06-18 11:01:43 +0200971 }
972}
973
Luo Jie79c7bc02021-10-24 16:27:30 +0800974static int at803x_read_specific_status(struct phy_device *phydev)
Russell King06d5f342019-10-04 17:06:14 +0100975{
Luo Jie79c7bc02021-10-24 16:27:30 +0800976 int ss;
Russell King06d5f342019-10-04 17:06:14 +0100977
978 /* Read the AT8035 PHY-Specific Status register, which indicates the
979 * speed and duplex that the PHY is actually using, irrespective of
980 * whether we are in autoneg mode or not.
981 */
982 ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
983 if (ss < 0)
984 return ss;
985
986 if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
Luo Jie79c7bc02021-10-24 16:27:30 +0800987 int sfc, speed;
Oleksij Rempel7dce80c2020-07-19 10:05:30 +0200988
989 sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
990 if (sfc < 0)
991 return sfc;
992
Luo Jie79c7bc02021-10-24 16:27:30 +0800993 /* qca8081 takes the different bits for speed value from at803x */
994 if (phydev->drv->phy_id == QCA8081_PHY_ID)
995 speed = FIELD_GET(QCA808X_SS_SPEED_MASK, ss);
996 else
997 speed = FIELD_GET(AT803X_SS_SPEED_MASK, ss);
998
999 switch (speed) {
Russell King06d5f342019-10-04 17:06:14 +01001000 case AT803X_SS_SPEED_10:
1001 phydev->speed = SPEED_10;
1002 break;
1003 case AT803X_SS_SPEED_100:
1004 phydev->speed = SPEED_100;
1005 break;
1006 case AT803X_SS_SPEED_1000:
1007 phydev->speed = SPEED_1000;
1008 break;
Luo Jie79c7bc02021-10-24 16:27:30 +08001009 case QCA808X_SS_SPEED_2500:
1010 phydev->speed = SPEED_2500;
1011 break;
Russell King06d5f342019-10-04 17:06:14 +01001012 }
1013 if (ss & AT803X_SS_DUPLEX)
1014 phydev->duplex = DUPLEX_FULL;
1015 else
1016 phydev->duplex = DUPLEX_HALF;
Oleksij Rempel7dce80c2020-07-19 10:05:30 +02001017
Russell King06d5f342019-10-04 17:06:14 +01001018 if (ss & AT803X_SS_MDIX)
1019 phydev->mdix = ETH_TP_MDI_X;
1020 else
1021 phydev->mdix = ETH_TP_MDI;
Oleksij Rempel7dce80c2020-07-19 10:05:30 +02001022
1023 switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) {
1024 case AT803X_SFC_MANUAL_MDI:
1025 phydev->mdix_ctrl = ETH_TP_MDI;
1026 break;
1027 case AT803X_SFC_MANUAL_MDIX:
1028 phydev->mdix_ctrl = ETH_TP_MDI_X;
1029 break;
1030 case AT803X_SFC_AUTOMATIC_CROSSOVER:
1031 phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
1032 break;
1033 }
Russell King06d5f342019-10-04 17:06:14 +01001034 }
1035
Luo Jie79c7bc02021-10-24 16:27:30 +08001036 return 0;
1037}
1038
1039static int at803x_read_status(struct phy_device *phydev)
1040{
1041 int err, old_link = phydev->link;
1042
1043 /* Update the link, but return if there was an error */
1044 err = genphy_update_link(phydev);
1045 if (err)
1046 return err;
1047
1048 /* why bother the PHY if nothing can have changed */
1049 if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
1050 return 0;
1051
1052 phydev->speed = SPEED_UNKNOWN;
1053 phydev->duplex = DUPLEX_UNKNOWN;
1054 phydev->pause = 0;
1055 phydev->asym_pause = 0;
1056
1057 err = genphy_read_lpa(phydev);
1058 if (err < 0)
1059 return err;
1060
1061 err = at803x_read_specific_status(phydev);
1062 if (err < 0)
1063 return err;
1064
Russell King06d5f342019-10-04 17:06:14 +01001065 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
1066 phy_resolve_aneg_pause(phydev);
1067
1068 return 0;
1069}
1070
Oleksij Rempel7dce80c2020-07-19 10:05:30 +02001071static int at803x_config_mdix(struct phy_device *phydev, u8 ctrl)
1072{
1073 u16 val;
1074
1075 switch (ctrl) {
1076 case ETH_TP_MDI:
1077 val = AT803X_SFC_MANUAL_MDI;
1078 break;
1079 case ETH_TP_MDI_X:
1080 val = AT803X_SFC_MANUAL_MDIX;
1081 break;
1082 case ETH_TP_MDI_AUTO:
1083 val = AT803X_SFC_AUTOMATIC_CROSSOVER;
1084 break;
1085 default:
1086 return 0;
1087 }
1088
1089 return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL,
1090 AT803X_SFC_MDI_CROSSOVER_MODE_M,
1091 FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val));
1092}
1093
1094static int at803x_config_aneg(struct phy_device *phydev)
1095{
1096 int ret;
1097
1098 ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
1099 if (ret < 0)
1100 return ret;
1101
1102 /* Changes of the midx bits are disruptive to the normal operation;
1103 * therefore any changes to these registers must be followed by a
1104 * software reset to take effect.
1105 */
1106 if (ret == 1) {
1107 ret = genphy_soft_reset(phydev);
1108 if (ret < 0)
1109 return ret;
1110 }
1111
1112 return genphy_config_aneg(phydev);
1113}
1114
Michael Wallecde0f4f2020-04-28 23:15:02 +02001115static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
1116{
1117 int val;
1118
1119 val = phy_read(phydev, AT803X_SMART_SPEED);
1120 if (val < 0)
1121 return val;
1122
1123 if (val & AT803X_SMART_SPEED_ENABLE)
1124 *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2;
1125 else
1126 *d = DOWNSHIFT_DEV_DISABLE;
1127
1128 return 0;
1129}
1130
1131static int at803x_set_downshift(struct phy_device *phydev, u8 cnt)
1132{
1133 u16 mask, set;
1134 int ret;
1135
1136 switch (cnt) {
1137 case DOWNSHIFT_DEV_DEFAULT_COUNT:
1138 cnt = AT803X_DEFAULT_DOWNSHIFT;
1139 fallthrough;
1140 case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT:
1141 set = AT803X_SMART_SPEED_ENABLE |
1142 AT803X_SMART_SPEED_BYPASS_TIMER |
1143 FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2);
1144 mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK;
1145 break;
1146 case DOWNSHIFT_DEV_DISABLE:
1147 set = 0;
1148 mask = AT803X_SMART_SPEED_ENABLE |
1149 AT803X_SMART_SPEED_BYPASS_TIMER;
1150 break;
1151 default:
1152 return -EINVAL;
1153 }
1154
1155 ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set);
1156
1157 /* After changing the smart speed settings, we need to perform a
1158 * software reset, use phy_init_hw() to make sure we set the
1159 * reapply any values which might got lost during software reset.
1160 */
1161 if (ret == 1)
1162 ret = phy_init_hw(phydev);
1163
1164 return ret;
1165}
1166
1167static int at803x_get_tunable(struct phy_device *phydev,
1168 struct ethtool_tunable *tuna, void *data)
1169{
1170 switch (tuna->id) {
1171 case ETHTOOL_PHY_DOWNSHIFT:
1172 return at803x_get_downshift(phydev, data);
1173 default:
1174 return -EOPNOTSUPP;
1175 }
1176}
1177
1178static int at803x_set_tunable(struct phy_device *phydev,
1179 struct ethtool_tunable *tuna, const void *data)
1180{
1181 switch (tuna->id) {
1182 case ETHTOOL_PHY_DOWNSHIFT:
1183 return at803x_set_downshift(phydev, *(const u8 *)data);
1184 default:
1185 return -EOPNOTSUPP;
1186 }
1187}
1188
Michael Walle6cb75762020-05-13 22:38:07 +02001189static int at803x_cable_test_result_trans(u16 status)
1190{
1191 switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) {
1192 case AT803X_CDT_STATUS_STAT_NORMAL:
1193 return ETHTOOL_A_CABLE_RESULT_CODE_OK;
1194 case AT803X_CDT_STATUS_STAT_SHORT:
1195 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
1196 case AT803X_CDT_STATUS_STAT_OPEN:
1197 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
1198 case AT803X_CDT_STATUS_STAT_FAIL:
1199 default:
1200 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
1201 }
1202}
1203
1204static bool at803x_cdt_test_failed(u16 status)
1205{
1206 return FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status) ==
1207 AT803X_CDT_STATUS_STAT_FAIL;
1208}
1209
1210static bool at803x_cdt_fault_length_valid(u16 status)
1211{
1212 switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) {
1213 case AT803X_CDT_STATUS_STAT_OPEN:
1214 case AT803X_CDT_STATUS_STAT_SHORT:
1215 return true;
1216 }
1217 return false;
1218}
1219
1220static int at803x_cdt_fault_length(u16 status)
1221{
1222 int dt;
1223
1224 /* According to the datasheet the distance to the fault is
1225 * DELTA_TIME * 0.824 meters.
1226 *
1227 * The author suspect the correct formula is:
1228 *
1229 * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2
1230 *
1231 * where c is the speed of light, VF is the velocity factor of
1232 * the twisted pair cable, 125MHz the counter frequency and
1233 * we need to divide by 2 because the hardware will measure the
1234 * round trip time to the fault and back to the PHY.
1235 *
1236 * With a VF of 0.69 we get the factor 0.824 mentioned in the
1237 * datasheet.
1238 */
1239 dt = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, status);
1240
1241 return (dt * 824) / 10;
1242}
1243
1244static int at803x_cdt_start(struct phy_device *phydev, int pair)
1245{
1246 u16 cdt;
1247
1248 cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) |
1249 AT803X_CDT_ENABLE_TEST;
1250
1251 return phy_write(phydev, AT803X_CDT, cdt);
1252}
1253
1254static int at803x_cdt_wait_for_completion(struct phy_device *phydev)
1255{
1256 int val, ret;
1257
1258 /* One test run takes about 25ms */
1259 ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
1260 !(val & AT803X_CDT_ENABLE_TEST),
1261 30000, 100000, true);
1262
1263 return ret < 0 ? ret : 0;
1264}
1265
1266static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair)
1267{
1268 static const int ethtool_pair[] = {
1269 ETHTOOL_A_CABLE_PAIR_A,
1270 ETHTOOL_A_CABLE_PAIR_B,
1271 ETHTOOL_A_CABLE_PAIR_C,
1272 ETHTOOL_A_CABLE_PAIR_D,
1273 };
1274 int ret, val;
1275
1276 ret = at803x_cdt_start(phydev, pair);
1277 if (ret)
1278 return ret;
1279
1280 ret = at803x_cdt_wait_for_completion(phydev);
1281 if (ret)
1282 return ret;
1283
1284 val = phy_read(phydev, AT803X_CDT_STATUS);
1285 if (val < 0)
1286 return val;
1287
1288 if (at803x_cdt_test_failed(val))
1289 return 0;
1290
1291 ethnl_cable_test_result(phydev, ethtool_pair[pair],
1292 at803x_cable_test_result_trans(val));
1293
1294 if (at803x_cdt_fault_length_valid(val))
1295 ethnl_cable_test_fault_length(phydev, ethtool_pair[pair],
1296 at803x_cdt_fault_length(val));
1297
1298 return 1;
1299}
1300
1301static int at803x_cable_test_get_status(struct phy_device *phydev,
1302 bool *finished)
1303{
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001304 unsigned long pair_mask;
Michael Walle6cb75762020-05-13 22:38:07 +02001305 int retries = 20;
1306 int pair, ret;
1307
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001308 if (phydev->phy_id == ATH9331_PHY_ID ||
David Bauerfada2ce2021-10-06 00:54:01 +02001309 phydev->phy_id == ATH8032_PHY_ID ||
1310 phydev->phy_id == QCA9561_PHY_ID)
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001311 pair_mask = 0x3;
1312 else
1313 pair_mask = 0xf;
1314
Michael Walle6cb75762020-05-13 22:38:07 +02001315 *finished = false;
1316
1317 /* According to the datasheet the CDT can be performed when
1318 * there is no link partner or when the link partner is
1319 * auto-negotiating. Starting the test will restart the AN
1320 * automatically. It seems that doing this repeatedly we will
1321 * get a slot where our link partner won't disturb our
1322 * measurement.
1323 */
1324 while (pair_mask && retries--) {
1325 for_each_set_bit(pair, &pair_mask, 4) {
1326 ret = at803x_cable_test_one_pair(phydev, pair);
1327 if (ret < 0)
1328 return ret;
1329 if (ret)
1330 clear_bit(pair, &pair_mask);
1331 }
1332 if (pair_mask)
1333 msleep(250);
1334 }
1335
1336 *finished = true;
1337
1338 return 0;
1339}
1340
1341static int at803x_cable_test_start(struct phy_device *phydev)
1342{
1343 /* Enable auto-negotiation, but advertise no capabilities, no link
1344 * will be established. A restart of the auto-negotiation is not
1345 * required, because the cable test will automatically break the link.
1346 */
1347 phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
1348 phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA);
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001349 if (phydev->phy_id != ATH9331_PHY_ID &&
David Bauerfada2ce2021-10-06 00:54:01 +02001350 phydev->phy_id != ATH8032_PHY_ID &&
1351 phydev->phy_id != QCA9561_PHY_ID)
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001352 phy_write(phydev, MII_CTRL1000, 0);
Michael Walle6cb75762020-05-13 22:38:07 +02001353
1354 /* we do all the (time consuming) work later */
1355 return 0;
1356}
1357
Ansuel Smith272833b2021-05-14 23:00:15 +02001358static int qca83xx_config_init(struct phy_device *phydev)
1359{
1360 u8 switch_revision;
1361
1362 switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK;
1363
1364 switch (switch_revision) {
1365 case 1:
1366 /* For 100M waveform */
Ansuel Smith67999552021-10-10 00:46:18 +02001367 at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea);
Ansuel Smith272833b2021-05-14 23:00:15 +02001368 /* Turn on Gigabit clock */
Ansuel Smith67999552021-10-10 00:46:18 +02001369 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0);
Ansuel Smith272833b2021-05-14 23:00:15 +02001370 break;
1371
1372 case 2:
1373 phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0);
1374 fallthrough;
1375 case 4:
1376 phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f);
Ansuel Smith67999552021-10-10 00:46:18 +02001377 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860);
1378 at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46);
Ansuel Smith272833b2021-05-14 23:00:15 +02001379 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000);
1380 break;
1381 }
1382
Ansuel Smith1ca83112021-10-10 00:46:16 +02001383 /* QCA8327 require DAC amplitude adjustment for 100m set to +6%.
1384 * Disable on init and enable only with 100m speed following
1385 * qca original source code.
1386 */
1387 if (phydev->drv->phy_id == QCA8327_A_PHY_ID ||
1388 phydev->drv->phy_id == QCA8327_B_PHY_ID)
Ansuel Smith67999552021-10-10 00:46:18 +02001389 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
Ansuel Smith1ca83112021-10-10 00:46:16 +02001390 QCA8327_DEBUG_MANU_CTRL_EN, 0);
1391
Ansuel Smith9d1c29b2021-10-10 00:46:17 +02001392 /* Following original QCA sourcecode set port to prefer master */
1393 phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER);
1394
Ansuel Smith272833b2021-05-14 23:00:15 +02001395 return 0;
1396}
1397
Ansuel Smith1ca83112021-10-10 00:46:16 +02001398static void qca83xx_link_change_notify(struct phy_device *phydev)
1399{
1400 /* QCA8337 doesn't require DAC Amplitude adjustement */
1401 if (phydev->drv->phy_id == QCA8337_PHY_ID)
1402 return;
1403
1404 /* Set DAC Amplitude adjustment to +6% for 100m on link running */
1405 if (phydev->state == PHY_RUNNING) {
1406 if (phydev->speed == SPEED_100)
Ansuel Smith67999552021-10-10 00:46:18 +02001407 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
Ansuel Smith1ca83112021-10-10 00:46:16 +02001408 QCA8327_DEBUG_MANU_CTRL_EN,
1409 QCA8327_DEBUG_MANU_CTRL_EN);
1410 } else {
1411 /* Reset DAC Amplitude adjustment */
Ansuel Smith67999552021-10-10 00:46:18 +02001412 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
Ansuel Smith1ca83112021-10-10 00:46:16 +02001413 QCA8327_DEBUG_MANU_CTRL_EN, 0);
1414 }
1415}
1416
Ansuel Smithba3c01e2021-10-10 00:46:15 +02001417static int qca83xx_resume(struct phy_device *phydev)
1418{
1419 int ret, val;
1420
1421 /* Skip reset if not suspended */
1422 if (!phydev->suspended)
1423 return 0;
1424
1425 /* Reinit the port, reset values set by suspend */
1426 qca83xx_config_init(phydev);
1427
1428 /* Reset the port on port resume */
1429 phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
1430
1431 /* On resume from suspend the switch execute a reset and
1432 * restart auto-negotiation. Wait for reset to complete.
1433 */
1434 ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
1435 50000, 600000, true);
1436 if (ret)
1437 return ret;
1438
1439 msleep(1);
1440
1441 return 0;
1442}
1443
1444static int qca83xx_suspend(struct phy_device *phydev)
1445{
1446 u16 mask = 0;
1447
1448 /* Only QCA8337 support actual suspend.
1449 * QCA8327 cause port unreliability when phy suspend
1450 * is set.
1451 */
1452 if (phydev->drv->phy_id == QCA8337_PHY_ID) {
1453 genphy_suspend(phydev);
1454 } else {
1455 mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX);
1456 phy_modify(phydev, MII_BMCR, mask, 0);
1457 }
1458
Ansuel Smith67999552021-10-10 00:46:18 +02001459 at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN,
Ansuel Smithba3c01e2021-10-10 00:46:15 +02001460 AT803X_DEBUG_GATE_CLK_IN1000, 0);
1461
1462 at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL,
1463 AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE |
1464 AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0);
1465
1466 return 0;
1467}
1468
Luo Jie79c7bc02021-10-24 16:27:30 +08001469static int qca808x_read_status(struct phy_device *phydev)
1470{
1471 int ret;
1472
1473 ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_STAT);
1474 if (ret < 0)
1475 return ret;
1476
1477 linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->lp_advertising,
1478 ret & MDIO_AN_10GBT_STAT_LP2_5G);
1479
1480 ret = genphy_read_status(phydev);
1481 if (ret)
1482 return ret;
1483
1484 ret = at803x_read_specific_status(phydev);
1485 if (ret < 0)
1486 return ret;
1487
1488 if (phydev->link && phydev->speed == SPEED_2500)
1489 phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
1490 else
1491 phydev->interface = PHY_INTERFACE_MODE_SMII;
1492
1493 return 0;
1494}
1495
Mugunthan V N317420a2013-06-03 20:10:04 +00001496static struct phy_driver at803x_driver[] = {
1497{
Michael Walle96c36712019-11-06 23:36:16 +01001498 /* Qualcomm Atheros AR8035 */
Michael Walle0465d8f2020-05-22 11:53:31 +02001499 PHY_ID_MATCH_EXACT(ATH8035_PHY_ID),
Michael Walle96c36712019-11-06 23:36:16 +01001500 .name = "Qualcomm Atheros AR8035",
Michael Walle6cb75762020-05-13 22:38:07 +02001501 .flags = PHY_POLL_CABLE_TEST,
Michael Walle2f664822019-11-06 23:36:14 +01001502 .probe = at803x_probe,
Michael Walle2318ca82020-01-30 18:54:02 +01001503 .remove = at803x_remove,
Oleksij Rempel7dce80c2020-07-19 10:05:30 +02001504 .config_aneg = at803x_config_aneg,
Daniel Mack13a56b42014-06-18 11:01:43 +02001505 .config_init = at803x_config_init,
Michael Wallecde0f4f2020-04-28 23:15:02 +02001506 .soft_reset = genphy_soft_reset,
Daniel Mack13a56b42014-06-18 11:01:43 +02001507 .set_wol = at803x_set_wol,
1508 .get_wol = at803x_get_wol,
1509 .suspend = at803x_suspend,
1510 .resume = at803x_resume,
Heiner Kallweitdcdecdc2019-04-12 20:47:03 +02001511 /* PHY_GBIT_FEATURES */
Russell King06d5f342019-10-04 17:06:14 +01001512 .read_status = at803x_read_status,
Måns Rullgård0eae5982015-11-12 17:40:20 +00001513 .config_intr = at803x_config_intr,
Ioana Ciornei29773092020-11-01 14:50:59 +02001514 .handle_interrupt = at803x_handle_interrupt,
Michael Wallecde0f4f2020-04-28 23:15:02 +02001515 .get_tunable = at803x_get_tunable,
1516 .set_tunable = at803x_set_tunable,
Michael Walle6cb75762020-05-13 22:38:07 +02001517 .cable_test_start = at803x_cable_test_start,
1518 .cable_test_get_status = at803x_cable_test_get_status,
Mugunthan V N317420a2013-06-03 20:10:04 +00001519}, {
Michael Walle96c36712019-11-06 23:36:16 +01001520 /* Qualcomm Atheros AR8030 */
Daniel Mack13a56b42014-06-18 11:01:43 +02001521 .phy_id = ATH8030_PHY_ID,
Michael Walle96c36712019-11-06 23:36:16 +01001522 .name = "Qualcomm Atheros AR8030",
Michael Walle0465d8f2020-05-22 11:53:31 +02001523 .phy_id_mask = AT8030_PHY_ID_MASK,
Michael Walle2f664822019-11-06 23:36:14 +01001524 .probe = at803x_probe,
Michael Walle2318ca82020-01-30 18:54:02 +01001525 .remove = at803x_remove,
Daniel Mack13a56b42014-06-18 11:01:43 +02001526 .config_init = at803x_config_init,
1527 .link_change_notify = at803x_link_change_notify,
1528 .set_wol = at803x_set_wol,
1529 .get_wol = at803x_get_wol,
1530 .suspend = at803x_suspend,
1531 .resume = at803x_resume,
Heiner Kallweitdcdecdc2019-04-12 20:47:03 +02001532 /* PHY_BASIC_FEATURES */
Måns Rullgård0eae5982015-11-12 17:40:20 +00001533 .config_intr = at803x_config_intr,
Ioana Ciornei29773092020-11-01 14:50:59 +02001534 .handle_interrupt = at803x_handle_interrupt,
Mugunthan V N05d7cce2013-06-03 20:10:07 +00001535}, {
Michael Walle96c36712019-11-06 23:36:16 +01001536 /* Qualcomm Atheros AR8031/AR8033 */
Michael Walle0465d8f2020-05-22 11:53:31 +02001537 PHY_ID_MATCH_EXACT(ATH8031_PHY_ID),
Michael Walle96c36712019-11-06 23:36:16 +01001538 .name = "Qualcomm Atheros AR8031/AR8033",
Michael Walle6cb75762020-05-13 22:38:07 +02001539 .flags = PHY_POLL_CABLE_TEST,
Michael Walle2f664822019-11-06 23:36:14 +01001540 .probe = at803x_probe,
Michael Walle2318ca82020-01-30 18:54:02 +01001541 .remove = at803x_remove,
Daniel Mack13a56b42014-06-18 11:01:43 +02001542 .config_init = at803x_config_init,
Michael Walle63477a52021-02-14 02:17:11 +01001543 .config_aneg = at803x_config_aneg,
Michael Wallecde0f4f2020-04-28 23:15:02 +02001544 .soft_reset = genphy_soft_reset,
Daniel Mack13a56b42014-06-18 11:01:43 +02001545 .set_wol = at803x_set_wol,
1546 .get_wol = at803x_get_wol,
1547 .suspend = at803x_suspend,
1548 .resume = at803x_resume,
David Bauerc329e5a2021-04-15 03:26:50 +02001549 .read_page = at803x_read_page,
1550 .write_page = at803x_write_page,
David Bauerb8561502021-06-27 12:16:07 +02001551 .get_features = at803x_get_features,
Russell King06d5f342019-10-04 17:06:14 +01001552 .read_status = at803x_read_status,
Daniel Mack13a56b42014-06-18 11:01:43 +02001553 .config_intr = &at803x_config_intr,
Ioana Ciornei29773092020-11-01 14:50:59 +02001554 .handle_interrupt = at803x_handle_interrupt,
Michael Wallecde0f4f2020-04-28 23:15:02 +02001555 .get_tunable = at803x_get_tunable,
1556 .set_tunable = at803x_set_tunable,
Michael Walle6cb75762020-05-13 22:38:07 +02001557 .cable_test_start = at803x_cable_test_start,
1558 .cable_test_get_status = at803x_cable_test_get_status,
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001559}, {
David Bauer58000912020-04-17 15:41:59 +02001560 /* Qualcomm Atheros AR8032 */
1561 PHY_ID_MATCH_EXACT(ATH8032_PHY_ID),
1562 .name = "Qualcomm Atheros AR8032",
1563 .probe = at803x_probe,
1564 .remove = at803x_remove,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001565 .flags = PHY_POLL_CABLE_TEST,
David Bauer58000912020-04-17 15:41:59 +02001566 .config_init = at803x_config_init,
1567 .link_change_notify = at803x_link_change_notify,
1568 .set_wol = at803x_set_wol,
1569 .get_wol = at803x_get_wol,
1570 .suspend = at803x_suspend,
1571 .resume = at803x_resume,
1572 /* PHY_BASIC_FEATURES */
David Bauer58000912020-04-17 15:41:59 +02001573 .config_intr = at803x_config_intr,
Ioana Ciornei29773092020-11-01 14:50:59 +02001574 .handle_interrupt = at803x_handle_interrupt,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001575 .cable_test_start = at803x_cable_test_start,
1576 .cable_test_get_status = at803x_cable_test_get_status,
David Bauer58000912020-04-17 15:41:59 +02001577}, {
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001578 /* ATHEROS AR9331 */
1579 PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
Michael Walle96c36712019-11-06 23:36:16 +01001580 .name = "Qualcomm Atheros AR9331 built-in PHY",
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001581 .suspend = at803x_suspend,
1582 .resume = at803x_resume,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001583 .flags = PHY_POLL_CABLE_TEST,
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001584 /* PHY_BASIC_FEATURES */
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001585 .config_intr = &at803x_config_intr,
Ioana Ciornei29773092020-11-01 14:50:59 +02001586 .handle_interrupt = at803x_handle_interrupt,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001587 .cable_test_start = at803x_cable_test_start,
1588 .cable_test_get_status = at803x_cable_test_get_status,
Oleksij Rempel7dce80c2020-07-19 10:05:30 +02001589 .read_status = at803x_read_status,
1590 .soft_reset = genphy_soft_reset,
1591 .config_aneg = at803x_config_aneg,
Ansuel Smith272833b2021-05-14 23:00:15 +02001592}, {
David Bauerfada2ce2021-10-06 00:54:01 +02001593 /* Qualcomm Atheros QCA9561 */
1594 PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
1595 .name = "Qualcomm Atheros QCA9561 built-in PHY",
1596 .suspend = at803x_suspend,
1597 .resume = at803x_resume,
1598 .flags = PHY_POLL_CABLE_TEST,
1599 /* PHY_BASIC_FEATURES */
1600 .config_intr = &at803x_config_intr,
1601 .handle_interrupt = at803x_handle_interrupt,
1602 .cable_test_start = at803x_cable_test_start,
1603 .cable_test_get_status = at803x_cable_test_get_status,
1604 .read_status = at803x_read_status,
1605 .soft_reset = genphy_soft_reset,
1606 .config_aneg = at803x_config_aneg,
1607}, {
Ansuel Smith272833b2021-05-14 23:00:15 +02001608 /* QCA8337 */
Ansuel Smithd44fd862021-09-19 18:28:17 +02001609 .phy_id = QCA8337_PHY_ID,
1610 .phy_id_mask = QCA8K_PHY_ID_MASK,
1611 .name = "Qualcomm Atheros 8337 internal PHY",
Ansuel Smith272833b2021-05-14 23:00:15 +02001612 /* PHY_GBIT_FEATURES */
Ansuel Smith1ca83112021-10-10 00:46:16 +02001613 .link_change_notify = qca83xx_link_change_notify,
Ansuel Smithd44fd862021-09-19 18:28:17 +02001614 .probe = at803x_probe,
1615 .flags = PHY_IS_INTERNAL,
1616 .config_init = qca83xx_config_init,
1617 .soft_reset = genphy_soft_reset,
1618 .get_sset_count = at803x_get_sset_count,
1619 .get_strings = at803x_get_strings,
1620 .get_stats = at803x_get_stats,
Ansuel Smithba3c01e2021-10-10 00:46:15 +02001621 .suspend = qca83xx_suspend,
1622 .resume = qca83xx_resume,
Ansuel Smith0ccf8512021-09-14 14:33:45 +02001623}, {
Ansuel Smithb4df02b2021-09-19 18:28:15 +02001624 /* QCA8327-A from switch QCA8327-AL1A */
Ansuel Smithd44fd862021-09-19 18:28:17 +02001625 .phy_id = QCA8327_A_PHY_ID,
1626 .phy_id_mask = QCA8K_PHY_ID_MASK,
1627 .name = "Qualcomm Atheros 8327-A internal PHY",
Ansuel Smithb4df02b2021-09-19 18:28:15 +02001628 /* PHY_GBIT_FEATURES */
Ansuel Smith1ca83112021-10-10 00:46:16 +02001629 .link_change_notify = qca83xx_link_change_notify,
Ansuel Smithd44fd862021-09-19 18:28:17 +02001630 .probe = at803x_probe,
1631 .flags = PHY_IS_INTERNAL,
1632 .config_init = qca83xx_config_init,
1633 .soft_reset = genphy_soft_reset,
1634 .get_sset_count = at803x_get_sset_count,
1635 .get_strings = at803x_get_strings,
1636 .get_stats = at803x_get_stats,
Ansuel Smithba3c01e2021-10-10 00:46:15 +02001637 .suspend = qca83xx_suspend,
1638 .resume = qca83xx_resume,
Ansuel Smithb4df02b2021-09-19 18:28:15 +02001639}, {
1640 /* QCA8327-B from switch QCA8327-BL1A */
Ansuel Smithd44fd862021-09-19 18:28:17 +02001641 .phy_id = QCA8327_B_PHY_ID,
1642 .phy_id_mask = QCA8K_PHY_ID_MASK,
1643 .name = "Qualcomm Atheros 8327-B internal PHY",
Ansuel Smith0ccf8512021-09-14 14:33:45 +02001644 /* PHY_GBIT_FEATURES */
Ansuel Smith1ca83112021-10-10 00:46:16 +02001645 .link_change_notify = qca83xx_link_change_notify,
Ansuel Smithd44fd862021-09-19 18:28:17 +02001646 .probe = at803x_probe,
1647 .flags = PHY_IS_INTERNAL,
1648 .config_init = qca83xx_config_init,
1649 .soft_reset = genphy_soft_reset,
1650 .get_sset_count = at803x_get_sset_count,
1651 .get_strings = at803x_get_strings,
1652 .get_stats = at803x_get_stats,
Ansuel Smithba3c01e2021-10-10 00:46:15 +02001653 .suspend = qca83xx_suspend,
1654 .resume = qca83xx_resume,
Luo Jiedaf61732021-10-24 16:27:29 +08001655}, {
1656 /* Qualcomm QCA8081 */
1657 PHY_ID_MATCH_EXACT(QCA8081_PHY_ID),
1658 .name = "Qualcomm QCA8081",
1659 .config_intr = at803x_config_intr,
1660 .handle_interrupt = at803x_handle_interrupt,
1661 .get_tunable = at803x_get_tunable,
1662 .set_tunable = at803x_set_tunable,
1663 .set_wol = at803x_set_wol,
1664 .get_wol = at803x_get_wol,
Luo Jie765c22a2021-10-24 16:27:31 +08001665 .get_features = at803x_get_features,
Luo Jiedaf61732021-10-24 16:27:29 +08001666 .suspend = genphy_suspend,
1667 .resume = genphy_resume,
Luo Jie79c7bc02021-10-24 16:27:30 +08001668 .read_status = qca808x_read_status,
Ansuel Smith272833b2021-05-14 23:00:15 +02001669}, };
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00001670
Johan Hovold50fd7152014-11-11 19:45:59 +01001671module_phy_driver(at803x_driver);
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00001672
1673static struct mdio_device_id __maybe_unused atheros_tbl[] = {
Michael Walle0465d8f2020-05-22 11:53:31 +02001674 { ATH8030_PHY_ID, AT8030_PHY_ID_MASK },
1675 { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) },
David Bauer58000912020-04-17 15:41:59 +02001676 { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) },
Michael Walle0465d8f2020-05-22 11:53:31 +02001677 { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) },
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001678 { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) },
Ansuel Smith0ccf8512021-09-14 14:33:45 +02001679 { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) },
Ansuel Smithb4df02b2021-09-19 18:28:15 +02001680 { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) },
1681 { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
David Bauerfada2ce2021-10-06 00:54:01 +02001682 { PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) },
Luo Jiedaf61732021-10-24 16:27:29 +08001683 { PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) },
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00001684 { }
1685};
1686
1687MODULE_DEVICE_TABLE(mdio, atheros_tbl);