blob: 97cbe593f0ea69f033fe0f0473abe75abfef110b [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
Russell King06d5f342019-10-04 17:06:14 +010024#define AT803X_SPECIFIC_STATUS 0x11
25#define AT803X_SS_SPEED_MASK (3 << 14)
26#define AT803X_SS_SPEED_1000 (2 << 14)
27#define AT803X_SS_SPEED_100 (1 << 14)
28#define AT803X_SS_SPEED_10 (0 << 14)
29#define AT803X_SS_DUPLEX BIT(13)
30#define AT803X_SS_SPEED_DUPLEX_RESOLVED BIT(11)
31#define AT803X_SS_MDIX BIT(6)
32
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000033#define AT803X_INTR_ENABLE 0x12
Martin Blumenstingle6e4a552016-01-15 01:55:24 +010034#define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
35#define AT803X_INTR_ENABLE_SPEED_CHANGED BIT(14)
36#define AT803X_INTR_ENABLE_DUPLEX_CHANGED BIT(13)
37#define AT803X_INTR_ENABLE_PAGE_RECEIVED BIT(12)
38#define AT803X_INTR_ENABLE_LINK_FAIL BIT(11)
39#define AT803X_INTR_ENABLE_LINK_SUCCESS BIT(10)
40#define AT803X_INTR_ENABLE_WIRESPEED_DOWNGRADE BIT(5)
41#define AT803X_INTR_ENABLE_POLARITY_CHANGED BIT(1)
42#define AT803X_INTR_ENABLE_WOL BIT(0)
43
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000044#define AT803X_INTR_STATUS 0x13
Martin Blumenstingla46bd632016-01-15 01:55:23 +010045
Daniel Mack13a56b42014-06-18 11:01:43 +020046#define AT803X_SMART_SPEED 0x14
Michael Wallecde0f4f2020-04-28 23:15:02 +020047#define AT803X_SMART_SPEED_ENABLE BIT(5)
48#define AT803X_SMART_SPEED_RETRY_LIMIT_MASK GENMASK(4, 2)
49#define AT803X_SMART_SPEED_BYPASS_TIMER BIT(1)
Michael Walle6cb75762020-05-13 22:38:07 +020050#define AT803X_CDT 0x16
51#define AT803X_CDT_MDI_PAIR_MASK GENMASK(9, 8)
52#define AT803X_CDT_ENABLE_TEST BIT(0)
53#define AT803X_CDT_STATUS 0x1c
54#define AT803X_CDT_STATUS_STAT_NORMAL 0
55#define AT803X_CDT_STATUS_STAT_SHORT 1
56#define AT803X_CDT_STATUS_STAT_OPEN 2
57#define AT803X_CDT_STATUS_STAT_FAIL 3
58#define AT803X_CDT_STATUS_STAT_MASK GENMASK(9, 8)
59#define AT803X_CDT_STATUS_DELTA_TIME_MASK GENMASK(7, 0)
Daniel Mack13a56b42014-06-18 11:01:43 +020060#define AT803X_LED_CONTROL 0x18
Martin Blumenstingla46bd632016-01-15 01:55:23 +010061
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000062#define AT803X_DEVICE_ADDR 0x03
63#define AT803X_LOC_MAC_ADDR_0_15_OFFSET 0x804C
64#define AT803X_LOC_MAC_ADDR_16_31_OFFSET 0x804B
65#define AT803X_LOC_MAC_ADDR_32_47_OFFSET 0x804A
Zefir Kurtisif62265b2016-10-24 12:40:54 +020066#define AT803X_REG_CHIP_CONFIG 0x1f
67#define AT803X_BT_BX_REG_SEL 0x8000
Martin Blumenstingla46bd632016-01-15 01:55:23 +010068
Mugunthan V N1ca6d1b2013-06-03 20:10:06 +000069#define AT803X_DEBUG_ADDR 0x1D
70#define AT803X_DEBUG_DATA 0x1E
Martin Blumenstingla46bd632016-01-15 01:55:23 +010071
Zefir Kurtisif62265b2016-10-24 12:40:54 +020072#define AT803X_MODE_CFG_MASK 0x0F
73#define AT803X_MODE_CFG_SGMII 0x01
74
75#define AT803X_PSSR 0x11 /*PHY-Specific Status Register*/
76#define AT803X_PSSR_MR_AN_COMPLETE 0x0200
77
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +010078#define AT803X_DEBUG_REG_0 0x00
79#define AT803X_DEBUG_RX_CLK_DLY_EN BIT(15)
Martin Blumenstingla46bd632016-01-15 01:55:23 +010080
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +010081#define AT803X_DEBUG_REG_5 0x05
82#define AT803X_DEBUG_TX_CLK_DLY_EN BIT(8)
Matus Ujhelyi0ca71112012-10-14 19:07:16 +000083
Michael Walle2f664822019-11-06 23:36:14 +010084#define AT803X_DEBUG_REG_1F 0x1F
85#define AT803X_DEBUG_PLL_ON BIT(2)
86#define AT803X_DEBUG_RGMII_1V8 BIT(3)
87
88/* AT803x supports either the XTAL input pad, an internal PLL or the
89 * DSP as clock reference for the clock output pad. The XTAL reference
90 * is only used for 25 MHz output, all other frequencies need the PLL.
91 * The DSP as a clock reference is used in synchronous ethernet
92 * applications.
93 *
94 * By default the PLL is only enabled if there is a link. Otherwise
95 * the PHY will go into low power state and disabled the PLL. You can
96 * set the PLL_ON bit (see debug register 0x1f) to keep the PLL always
97 * enabled.
98 */
99#define AT803X_MMD7_CLK25M 0x8016
100#define AT803X_CLK_OUT_MASK GENMASK(4, 2)
101#define AT803X_CLK_OUT_25MHZ_XTAL 0
102#define AT803X_CLK_OUT_25MHZ_DSP 1
103#define AT803X_CLK_OUT_50MHZ_PLL 2
104#define AT803X_CLK_OUT_50MHZ_DSP 3
105#define AT803X_CLK_OUT_62_5MHZ_PLL 4
106#define AT803X_CLK_OUT_62_5MHZ_DSP 5
107#define AT803X_CLK_OUT_125MHZ_PLL 6
108#define AT803X_CLK_OUT_125MHZ_DSP 7
109
Michael Walle428061f2019-11-06 23:36:15 +0100110/* The AR8035 has another mask which is compatible with the AR8031/AR8033 mask
111 * but doesn't support choosing between XTAL/PLL and DSP.
Michael Walle2f664822019-11-06 23:36:14 +0100112 */
113#define AT8035_CLK_OUT_MASK GENMASK(4, 3)
114
115#define AT803X_CLK_OUT_STRENGTH_MASK GENMASK(8, 7)
116#define AT803X_CLK_OUT_STRENGTH_FULL 0
117#define AT803X_CLK_OUT_STRENGTH_HALF 1
118#define AT803X_CLK_OUT_STRENGTH_QUARTER 2
119
Michael Wallecde0f4f2020-04-28 23:15:02 +0200120#define AT803X_DEFAULT_DOWNSHIFT 5
121#define AT803X_MIN_DOWNSHIFT 2
122#define AT803X_MAX_DOWNSHIFT 9
123
Oleksij Rempel7908d2c2019-10-03 10:21:12 +0200124#define ATH9331_PHY_ID 0x004dd041
Daniel Mackbd8ca172014-06-18 11:01:42 +0200125#define ATH8030_PHY_ID 0x004dd076
126#define ATH8031_PHY_ID 0x004dd074
David Bauer58000912020-04-17 15:41:59 +0200127#define ATH8032_PHY_ID 0x004dd023
Daniel Mackbd8ca172014-06-18 11:01:42 +0200128#define ATH8035_PHY_ID 0x004dd072
Michael Walle0465d8f2020-05-22 11:53:31 +0200129#define AT8030_PHY_ID_MASK 0xffffffef
Daniel Mackbd8ca172014-06-18 11:01:42 +0200130
Michael Walle96c36712019-11-06 23:36:16 +0100131MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver");
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000132MODULE_AUTHOR("Matus Ujhelyi");
133MODULE_LICENSE("GPL");
134
Michael Walle2f664822019-11-06 23:36:14 +0100135struct at803x_priv {
136 int flags;
137#define AT803X_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */
138 u16 clk_25m_reg;
139 u16 clk_25m_mask;
140 struct regulator_dev *vddio_rdev;
141 struct regulator_dev *vddh_rdev;
142 struct regulator *vddio;
143};
144
Daniel Mack13a56b42014-06-18 11:01:43 +0200145struct at803x_context {
146 u16 bmcr;
147 u16 advertise;
148 u16 control1000;
149 u16 int_enable;
150 u16 smart_speed;
151 u16 led_control;
152};
153
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100154static int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
155{
156 int ret;
157
158 ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
159 if (ret < 0)
160 return ret;
161
162 return phy_read(phydev, AT803X_DEBUG_DATA);
163}
164
165static int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
166 u16 clear, u16 set)
167{
168 u16 val;
169 int ret;
170
171 ret = at803x_debug_reg_read(phydev, reg);
172 if (ret < 0)
173 return ret;
174
175 val = ret & 0xffff;
176 val &= ~clear;
177 val |= set;
178
179 return phy_write(phydev, AT803X_DEBUG_DATA, val);
180}
181
Vinod Koul6d4cd042019-02-21 15:53:15 +0530182static int at803x_enable_rx_delay(struct phy_device *phydev)
183{
184 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0,
185 AT803X_DEBUG_RX_CLK_DLY_EN);
186}
187
188static int at803x_enable_tx_delay(struct phy_device *phydev)
189{
190 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0,
191 AT803X_DEBUG_TX_CLK_DLY_EN);
192}
193
Vinod Koul43f2ebd2019-02-21 15:53:14 +0530194static int at803x_disable_rx_delay(struct phy_device *phydev)
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100195{
Vinod Koulcd28d1d2019-01-21 14:43:17 +0530196 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
197 AT803X_DEBUG_RX_CLK_DLY_EN, 0);
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100198}
199
Vinod Koul43f2ebd2019-02-21 15:53:14 +0530200static int at803x_disable_tx_delay(struct phy_device *phydev)
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100201{
Vinod Koulcd28d1d2019-01-21 14:43:17 +0530202 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5,
203 AT803X_DEBUG_TX_CLK_DLY_EN, 0);
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100204}
205
Daniel Mack13a56b42014-06-18 11:01:43 +0200206/* save relevant PHY registers to private copy */
207static void at803x_context_save(struct phy_device *phydev,
208 struct at803x_context *context)
209{
210 context->bmcr = phy_read(phydev, MII_BMCR);
211 context->advertise = phy_read(phydev, MII_ADVERTISE);
212 context->control1000 = phy_read(phydev, MII_CTRL1000);
213 context->int_enable = phy_read(phydev, AT803X_INTR_ENABLE);
214 context->smart_speed = phy_read(phydev, AT803X_SMART_SPEED);
215 context->led_control = phy_read(phydev, AT803X_LED_CONTROL);
216}
217
218/* restore relevant PHY registers from private copy */
219static void at803x_context_restore(struct phy_device *phydev,
220 const struct at803x_context *context)
221{
222 phy_write(phydev, MII_BMCR, context->bmcr);
223 phy_write(phydev, MII_ADVERTISE, context->advertise);
224 phy_write(phydev, MII_CTRL1000, context->control1000);
225 phy_write(phydev, AT803X_INTR_ENABLE, context->int_enable);
226 phy_write(phydev, AT803X_SMART_SPEED, context->smart_speed);
227 phy_write(phydev, AT803X_LED_CONTROL, context->led_control);
228}
229
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000230static int at803x_set_wol(struct phy_device *phydev,
231 struct ethtool_wolinfo *wol)
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000232{
233 struct net_device *ndev = phydev->attached_dev;
234 const u8 *mac;
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000235 int ret;
236 u32 value;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000237 unsigned int i, offsets[] = {
238 AT803X_LOC_MAC_ADDR_32_47_OFFSET,
239 AT803X_LOC_MAC_ADDR_16_31_OFFSET,
240 AT803X_LOC_MAC_ADDR_0_15_OFFSET,
241 };
242
243 if (!ndev)
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000244 return -ENODEV;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000245
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000246 if (wol->wolopts & WAKE_MAGIC) {
247 mac = (const u8 *) ndev->dev_addr;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000248
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000249 if (!is_valid_ether_addr(mac))
Dan Murphyfc755682017-10-10 12:42:56 -0500250 return -EINVAL;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000251
Carlo Caione0e021392019-01-25 12:35:10 +0000252 for (i = 0; i < 3; i++)
253 phy_write_mmd(phydev, AT803X_DEVICE_ADDR, offsets[i],
254 mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000255
256 value = phy_read(phydev, AT803X_INTR_ENABLE);
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100257 value |= AT803X_INTR_ENABLE_WOL;
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000258 ret = phy_write(phydev, AT803X_INTR_ENABLE, value);
259 if (ret)
260 return ret;
261 value = phy_read(phydev, AT803X_INTR_STATUS);
262 } else {
263 value = phy_read(phydev, AT803X_INTR_ENABLE);
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100264 value &= (~AT803X_INTR_ENABLE_WOL);
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000265 ret = phy_write(phydev, AT803X_INTR_ENABLE, value);
266 if (ret)
267 return ret;
268 value = phy_read(phydev, AT803X_INTR_STATUS);
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000269 }
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000270
271 return ret;
272}
273
274static void at803x_get_wol(struct phy_device *phydev,
275 struct ethtool_wolinfo *wol)
276{
277 u32 value;
278
279 wol->supported = WAKE_MAGIC;
280 wol->wolopts = 0;
281
282 value = phy_read(phydev, AT803X_INTR_ENABLE);
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100283 if (value & AT803X_INTR_ENABLE_WOL)
Mugunthan V Nea13c9e2013-06-03 20:10:05 +0000284 wol->wolopts |= WAKE_MAGIC;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000285}
286
Daniel Mack6229ed12013-09-21 16:53:02 +0200287static int at803x_suspend(struct phy_device *phydev)
288{
289 int value;
290 int wol_enabled;
291
Daniel Mack6229ed12013-09-21 16:53:02 +0200292 value = phy_read(phydev, AT803X_INTR_ENABLE);
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100293 wol_enabled = value & AT803X_INTR_ENABLE_WOL;
Daniel Mack6229ed12013-09-21 16:53:02 +0200294
Daniel Mack6229ed12013-09-21 16:53:02 +0200295 if (wol_enabled)
Russell Kingfea23fb2018-01-02 10:58:58 +0000296 value = BMCR_ISOLATE;
Daniel Mack6229ed12013-09-21 16:53:02 +0200297 else
Russell Kingfea23fb2018-01-02 10:58:58 +0000298 value = BMCR_PDOWN;
Daniel Mack6229ed12013-09-21 16:53:02 +0200299
Russell Kingfea23fb2018-01-02 10:58:58 +0000300 phy_modify(phydev, MII_BMCR, 0, value);
Daniel Mack6229ed12013-09-21 16:53:02 +0200301
302 return 0;
303}
304
305static int at803x_resume(struct phy_device *phydev)
306{
Russell Kingf1028522018-01-05 16:07:10 +0000307 return phy_modify(phydev, MII_BMCR, BMCR_PDOWN | BMCR_ISOLATE, 0);
Daniel Mack6229ed12013-09-21 16:53:02 +0200308}
309
Michael Walle2f664822019-11-06 23:36:14 +0100310static int at803x_rgmii_reg_set_voltage_sel(struct regulator_dev *rdev,
311 unsigned int selector)
312{
313 struct phy_device *phydev = rdev_get_drvdata(rdev);
314
315 if (selector)
316 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
317 0, AT803X_DEBUG_RGMII_1V8);
318 else
319 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
320 AT803X_DEBUG_RGMII_1V8, 0);
321}
322
323static int at803x_rgmii_reg_get_voltage_sel(struct regulator_dev *rdev)
324{
325 struct phy_device *phydev = rdev_get_drvdata(rdev);
326 int val;
327
328 val = at803x_debug_reg_read(phydev, AT803X_DEBUG_REG_1F);
329 if (val < 0)
330 return val;
331
332 return (val & AT803X_DEBUG_RGMII_1V8) ? 1 : 0;
333}
334
335static struct regulator_ops vddio_regulator_ops = {
336 .list_voltage = regulator_list_voltage_table,
337 .set_voltage_sel = at803x_rgmii_reg_set_voltage_sel,
338 .get_voltage_sel = at803x_rgmii_reg_get_voltage_sel,
339};
340
341static const unsigned int vddio_voltage_table[] = {
342 1500000,
343 1800000,
344};
345
346static const struct regulator_desc vddio_desc = {
347 .name = "vddio",
348 .of_match = of_match_ptr("vddio-regulator"),
349 .n_voltages = ARRAY_SIZE(vddio_voltage_table),
350 .volt_table = vddio_voltage_table,
351 .ops = &vddio_regulator_ops,
352 .type = REGULATOR_VOLTAGE,
353 .owner = THIS_MODULE,
354};
355
356static struct regulator_ops vddh_regulator_ops = {
357};
358
359static const struct regulator_desc vddh_desc = {
360 .name = "vddh",
361 .of_match = of_match_ptr("vddh-regulator"),
362 .n_voltages = 1,
363 .fixed_uV = 2500000,
364 .ops = &vddh_regulator_ops,
365 .type = REGULATOR_VOLTAGE,
366 .owner = THIS_MODULE,
367};
368
369static int at8031_register_regulators(struct phy_device *phydev)
370{
371 struct at803x_priv *priv = phydev->priv;
372 struct device *dev = &phydev->mdio.dev;
373 struct regulator_config config = { };
374
375 config.dev = dev;
376 config.driver_data = phydev;
377
378 priv->vddio_rdev = devm_regulator_register(dev, &vddio_desc, &config);
379 if (IS_ERR(priv->vddio_rdev)) {
380 phydev_err(phydev, "failed to register VDDIO regulator\n");
381 return PTR_ERR(priv->vddio_rdev);
382 }
383
384 priv->vddh_rdev = devm_regulator_register(dev, &vddh_desc, &config);
385 if (IS_ERR(priv->vddh_rdev)) {
386 phydev_err(phydev, "failed to register VDDH regulator\n");
387 return PTR_ERR(priv->vddh_rdev);
388 }
389
390 return 0;
391}
392
393static bool at803x_match_phy_id(struct phy_device *phydev, u32 phy_id)
394{
395 return (phydev->phy_id & phydev->drv->phy_id_mask)
396 == (phy_id & phydev->drv->phy_id_mask);
397}
398
399static int at803x_parse_dt(struct phy_device *phydev)
400{
401 struct device_node *node = phydev->mdio.dev.of_node;
402 struct at803x_priv *priv = phydev->priv;
403 unsigned int sel, mask;
404 u32 freq, strength;
405 int ret;
406
407 if (!IS_ENABLED(CONFIG_OF_MDIO))
408 return 0;
409
410 ret = of_property_read_u32(node, "qca,clk-out-frequency", &freq);
411 if (!ret) {
412 mask = AT803X_CLK_OUT_MASK;
413 switch (freq) {
414 case 25000000:
415 sel = AT803X_CLK_OUT_25MHZ_XTAL;
416 break;
417 case 50000000:
418 sel = AT803X_CLK_OUT_50MHZ_PLL;
419 break;
420 case 62500000:
421 sel = AT803X_CLK_OUT_62_5MHZ_PLL;
422 break;
423 case 125000000:
424 sel = AT803X_CLK_OUT_125MHZ_PLL;
425 break;
426 default:
427 phydev_err(phydev, "invalid qca,clk-out-frequency\n");
428 return -EINVAL;
429 }
430
431 priv->clk_25m_reg |= FIELD_PREP(mask, sel);
432 priv->clk_25m_mask |= mask;
433
434 /* Fixup for the AR8030/AR8035. This chip has another mask and
435 * doesn't support the DSP reference. Eg. the lowest bit of the
436 * mask. The upper two bits select the same frequencies. Mask
437 * the lowest bit here.
438 *
439 * Warning:
440 * There was no datasheet for the AR8030 available so this is
441 * just a guess. But the AR8035 is listed as pin compatible
442 * to the AR8030 so there might be a good chance it works on
443 * the AR8030 too.
444 */
445 if (at803x_match_phy_id(phydev, ATH8030_PHY_ID) ||
446 at803x_match_phy_id(phydev, ATH8035_PHY_ID)) {
Oleksij Rempelb1f4c202020-04-01 11:57:32 +0200447 priv->clk_25m_reg &= AT8035_CLK_OUT_MASK;
448 priv->clk_25m_mask &= AT8035_CLK_OUT_MASK;
Michael Walle2f664822019-11-06 23:36:14 +0100449 }
450 }
451
452 ret = of_property_read_u32(node, "qca,clk-out-strength", &strength);
453 if (!ret) {
454 priv->clk_25m_mask |= AT803X_CLK_OUT_STRENGTH_MASK;
455 switch (strength) {
456 case AR803X_STRENGTH_FULL:
457 priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_FULL;
458 break;
459 case AR803X_STRENGTH_HALF:
460 priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_HALF;
461 break;
462 case AR803X_STRENGTH_QUARTER:
463 priv->clk_25m_reg |= AT803X_CLK_OUT_STRENGTH_QUARTER;
464 break;
465 default:
466 phydev_err(phydev, "invalid qca,clk-out-strength\n");
467 return -EINVAL;
468 }
469 }
470
Michael Walle428061f2019-11-06 23:36:15 +0100471 /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping
472 * options.
473 */
Michael Walle2f664822019-11-06 23:36:14 +0100474 if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) {
475 if (of_property_read_bool(node, "qca,keep-pll-enabled"))
476 priv->flags |= AT803X_KEEP_PLL_ENABLED;
477
478 ret = at8031_register_regulators(phydev);
479 if (ret < 0)
480 return ret;
481
482 priv->vddio = devm_regulator_get_optional(&phydev->mdio.dev,
483 "vddio");
484 if (IS_ERR(priv->vddio)) {
485 phydev_err(phydev, "failed to get VDDIO regulator\n");
486 return PTR_ERR(priv->vddio);
487 }
488
489 ret = regulator_enable(priv->vddio);
490 if (ret < 0)
491 return ret;
492 }
493
494 return 0;
495}
496
497static int at803x_probe(struct phy_device *phydev)
498{
499 struct device *dev = &phydev->mdio.dev;
500 struct at803x_priv *priv;
501
502 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
503 if (!priv)
504 return -ENOMEM;
505
506 phydev->priv = priv;
507
508 return at803x_parse_dt(phydev);
509}
510
Michael Walle2318ca82020-01-30 18:54:02 +0100511static void at803x_remove(struct phy_device *phydev)
512{
513 struct at803x_priv *priv = phydev->priv;
514
515 if (priv->vddio)
516 regulator_disable(priv->vddio);
517}
518
Michael Walle2f664822019-11-06 23:36:14 +0100519static int at803x_clk_out_config(struct phy_device *phydev)
520{
521 struct at803x_priv *priv = phydev->priv;
522 int val;
523
524 if (!priv->clk_25m_mask)
525 return 0;
526
527 val = phy_read_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M);
528 if (val < 0)
529 return val;
530
531 val &= ~priv->clk_25m_mask;
532 val |= priv->clk_25m_reg;
533
534 return phy_write_mmd(phydev, MDIO_MMD_AN, AT803X_MMD7_CLK25M, val);
535}
536
537static int at8031_pll_config(struct phy_device *phydev)
538{
539 struct at803x_priv *priv = phydev->priv;
540
541 /* The default after hardware reset is PLL OFF. After a soft reset, the
542 * values are retained.
543 */
544 if (priv->flags & AT803X_KEEP_PLL_ENABLED)
545 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
546 0, AT803X_DEBUG_PLL_ON);
547 else
548 return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_1F,
549 AT803X_DEBUG_PLL_ON, 0);
550}
551
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000552static int at803x_config_init(struct phy_device *phydev)
553{
Mugunthan V N1ca6d1b2013-06-03 20:10:06 +0000554 int ret;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000555
Vinod Koul6d4cd042019-02-21 15:53:15 +0530556 /* The RX and TX delay default is:
557 * after HW reset: RX delay enabled and TX delay disabled
558 * after SW reset: RX delay enabled, while TX delay retains the
559 * value before reset.
Vinod Koul6d4cd042019-02-21 15:53:15 +0530560 */
Vinod Koul6d4cd042019-02-21 15:53:15 +0530561 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
André Draszikbb0ce4c2019-08-09 12:20:25 +0100562 phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
Vinod Koul6d4cd042019-02-21 15:53:15 +0530563 ret = at803x_enable_rx_delay(phydev);
André Draszikbb0ce4c2019-08-09 12:20:25 +0100564 else
565 ret = at803x_disable_rx_delay(phydev);
566 if (ret < 0)
567 return ret;
Martin Blumenstingl2e5f9f22016-01-15 01:55:22 +0100568
Vinod Koul6d4cd042019-02-21 15:53:15 +0530569 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
André Draszikbb0ce4c2019-08-09 12:20:25 +0100570 phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
Vinod Koul6d4cd042019-02-21 15:53:15 +0530571 ret = at803x_enable_tx_delay(phydev);
André Draszikbb0ce4c2019-08-09 12:20:25 +0100572 else
573 ret = at803x_disable_tx_delay(phydev);
Michael Walle2f664822019-11-06 23:36:14 +0100574 if (ret < 0)
575 return ret;
Mugunthan V N1ca6d1b2013-06-03 20:10:06 +0000576
Michael Walle2f664822019-11-06 23:36:14 +0100577 ret = at803x_clk_out_config(phydev);
578 if (ret < 0)
579 return ret;
580
581 if (at803x_match_phy_id(phydev, ATH8031_PHY_ID)) {
582 ret = at8031_pll_config(phydev);
583 if (ret < 0)
584 return ret;
585 }
586
587 return 0;
Matus Ujhelyi0ca71112012-10-14 19:07:16 +0000588}
589
Zhao Qiang77a99392014-03-28 15:39:41 +0800590static int at803x_ack_interrupt(struct phy_device *phydev)
591{
592 int err;
593
Martin Blumenstingla46bd632016-01-15 01:55:23 +0100594 err = phy_read(phydev, AT803X_INTR_STATUS);
Zhao Qiang77a99392014-03-28 15:39:41 +0800595
596 return (err < 0) ? err : 0;
597}
598
599static int at803x_config_intr(struct phy_device *phydev)
600{
601 int err;
602 int value;
603
Martin Blumenstingla46bd632016-01-15 01:55:23 +0100604 value = phy_read(phydev, AT803X_INTR_ENABLE);
Zhao Qiang77a99392014-03-28 15:39:41 +0800605
Martin Blumenstingle6e4a552016-01-15 01:55:24 +0100606 if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
607 value |= AT803X_INTR_ENABLE_AUTONEG_ERR;
608 value |= AT803X_INTR_ENABLE_SPEED_CHANGED;
609 value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
610 value |= AT803X_INTR_ENABLE_LINK_FAIL;
611 value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
612
613 err = phy_write(phydev, AT803X_INTR_ENABLE, value);
614 }
Zhao Qiang77a99392014-03-28 15:39:41 +0800615 else
Martin Blumenstingla46bd632016-01-15 01:55:23 +0100616 err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
Zhao Qiang77a99392014-03-28 15:39:41 +0800617
618 return err;
619}
620
Daniel Mack13a56b42014-06-18 11:01:43 +0200621static void at803x_link_change_notify(struct phy_device *phydev)
622{
Daniel Mack13a56b42014-06-18 11:01:43 +0200623 /*
624 * Conduct a hardware reset for AT8030 every time a link loss is
625 * signalled. This is necessary to circumvent a hardware bug that
626 * occurs when the cable is unplugged while TX packets are pending
627 * in the FIFO. In such cases, the FIFO enters an error mode it
628 * cannot recover from by software.
629 */
David Bauer6110ed22019-04-17 23:59:22 +0200630 if (phydev->state == PHY_NOLINK && phydev->mdio.reset_gpio) {
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100631 struct at803x_context context;
Daniel Mack13a56b42014-06-18 11:01:43 +0200632
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100633 at803x_context_save(phydev, &context);
Daniel Mack13a56b42014-06-18 11:01:43 +0200634
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100635 phy_device_reset(phydev, 1);
636 msleep(1);
637 phy_device_reset(phydev, 0);
638 msleep(1);
Daniel Mack13a56b42014-06-18 11:01:43 +0200639
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100640 at803x_context_restore(phydev, &context);
Daniel Mack13a56b42014-06-18 11:01:43 +0200641
Heiner Kallweit5c5f6262019-03-19 19:56:51 +0100642 phydev_dbg(phydev, "%s(): phy was reset\n", __func__);
Daniel Mack13a56b42014-06-18 11:01:43 +0200643 }
644}
645
Zefir Kurtisif62265b2016-10-24 12:40:54 +0200646static int at803x_aneg_done(struct phy_device *phydev)
647{
648 int ccr;
649
650 int aneg_done = genphy_aneg_done(phydev);
651 if (aneg_done != BMSR_ANEGCOMPLETE)
652 return aneg_done;
653
654 /*
655 * in SGMII mode, if copper side autoneg is successful,
656 * also check SGMII side autoneg result
657 */
658 ccr = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
659 if ((ccr & AT803X_MODE_CFG_MASK) != AT803X_MODE_CFG_SGMII)
660 return aneg_done;
661
662 /* switch to SGMII/fiber page */
663 phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr & ~AT803X_BT_BX_REG_SEL);
664
665 /* check if the SGMII link is OK. */
666 if (!(phy_read(phydev, AT803X_PSSR) & AT803X_PSSR_MR_AN_COMPLETE)) {
Andrew Lunnab2a6052018-09-29 23:04:10 +0200667 phydev_warn(phydev, "803x_aneg_done: SGMII link is not ok\n");
Zefir Kurtisif62265b2016-10-24 12:40:54 +0200668 aneg_done = 0;
669 }
670 /* switch back to copper page */
671 phy_write(phydev, AT803X_REG_CHIP_CONFIG, ccr | AT803X_BT_BX_REG_SEL);
672
673 return aneg_done;
674}
675
Russell King06d5f342019-10-04 17:06:14 +0100676static int at803x_read_status(struct phy_device *phydev)
677{
678 int ss, err, old_link = phydev->link;
679
680 /* Update the link, but return if there was an error */
681 err = genphy_update_link(phydev);
682 if (err)
683 return err;
684
685 /* why bother the PHY if nothing can have changed */
686 if (phydev->autoneg == AUTONEG_ENABLE && old_link && phydev->link)
687 return 0;
688
689 phydev->speed = SPEED_UNKNOWN;
690 phydev->duplex = DUPLEX_UNKNOWN;
691 phydev->pause = 0;
692 phydev->asym_pause = 0;
693
694 err = genphy_read_lpa(phydev);
695 if (err < 0)
696 return err;
697
698 /* Read the AT8035 PHY-Specific Status register, which indicates the
699 * speed and duplex that the PHY is actually using, irrespective of
700 * whether we are in autoneg mode or not.
701 */
702 ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
703 if (ss < 0)
704 return ss;
705
706 if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
707 switch (ss & AT803X_SS_SPEED_MASK) {
708 case AT803X_SS_SPEED_10:
709 phydev->speed = SPEED_10;
710 break;
711 case AT803X_SS_SPEED_100:
712 phydev->speed = SPEED_100;
713 break;
714 case AT803X_SS_SPEED_1000:
715 phydev->speed = SPEED_1000;
716 break;
717 }
718 if (ss & AT803X_SS_DUPLEX)
719 phydev->duplex = DUPLEX_FULL;
720 else
721 phydev->duplex = DUPLEX_HALF;
722 if (ss & AT803X_SS_MDIX)
723 phydev->mdix = ETH_TP_MDI_X;
724 else
725 phydev->mdix = ETH_TP_MDI;
726 }
727
728 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete)
729 phy_resolve_aneg_pause(phydev);
730
731 return 0;
732}
733
Michael Wallecde0f4f2020-04-28 23:15:02 +0200734static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
735{
736 int val;
737
738 val = phy_read(phydev, AT803X_SMART_SPEED);
739 if (val < 0)
740 return val;
741
742 if (val & AT803X_SMART_SPEED_ENABLE)
743 *d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2;
744 else
745 *d = DOWNSHIFT_DEV_DISABLE;
746
747 return 0;
748}
749
750static int at803x_set_downshift(struct phy_device *phydev, u8 cnt)
751{
752 u16 mask, set;
753 int ret;
754
755 switch (cnt) {
756 case DOWNSHIFT_DEV_DEFAULT_COUNT:
757 cnt = AT803X_DEFAULT_DOWNSHIFT;
758 fallthrough;
759 case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT:
760 set = AT803X_SMART_SPEED_ENABLE |
761 AT803X_SMART_SPEED_BYPASS_TIMER |
762 FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2);
763 mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK;
764 break;
765 case DOWNSHIFT_DEV_DISABLE:
766 set = 0;
767 mask = AT803X_SMART_SPEED_ENABLE |
768 AT803X_SMART_SPEED_BYPASS_TIMER;
769 break;
770 default:
771 return -EINVAL;
772 }
773
774 ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set);
775
776 /* After changing the smart speed settings, we need to perform a
777 * software reset, use phy_init_hw() to make sure we set the
778 * reapply any values which might got lost during software reset.
779 */
780 if (ret == 1)
781 ret = phy_init_hw(phydev);
782
783 return ret;
784}
785
786static int at803x_get_tunable(struct phy_device *phydev,
787 struct ethtool_tunable *tuna, void *data)
788{
789 switch (tuna->id) {
790 case ETHTOOL_PHY_DOWNSHIFT:
791 return at803x_get_downshift(phydev, data);
792 default:
793 return -EOPNOTSUPP;
794 }
795}
796
797static int at803x_set_tunable(struct phy_device *phydev,
798 struct ethtool_tunable *tuna, const void *data)
799{
800 switch (tuna->id) {
801 case ETHTOOL_PHY_DOWNSHIFT:
802 return at803x_set_downshift(phydev, *(const u8 *)data);
803 default:
804 return -EOPNOTSUPP;
805 }
806}
807
Michael Walle6cb75762020-05-13 22:38:07 +0200808static int at803x_cable_test_result_trans(u16 status)
809{
810 switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) {
811 case AT803X_CDT_STATUS_STAT_NORMAL:
812 return ETHTOOL_A_CABLE_RESULT_CODE_OK;
813 case AT803X_CDT_STATUS_STAT_SHORT:
814 return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
815 case AT803X_CDT_STATUS_STAT_OPEN:
816 return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
817 case AT803X_CDT_STATUS_STAT_FAIL:
818 default:
819 return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
820 }
821}
822
823static bool at803x_cdt_test_failed(u16 status)
824{
825 return FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status) ==
826 AT803X_CDT_STATUS_STAT_FAIL;
827}
828
829static bool at803x_cdt_fault_length_valid(u16 status)
830{
831 switch (FIELD_GET(AT803X_CDT_STATUS_STAT_MASK, status)) {
832 case AT803X_CDT_STATUS_STAT_OPEN:
833 case AT803X_CDT_STATUS_STAT_SHORT:
834 return true;
835 }
836 return false;
837}
838
839static int at803x_cdt_fault_length(u16 status)
840{
841 int dt;
842
843 /* According to the datasheet the distance to the fault is
844 * DELTA_TIME * 0.824 meters.
845 *
846 * The author suspect the correct formula is:
847 *
848 * fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2
849 *
850 * where c is the speed of light, VF is the velocity factor of
851 * the twisted pair cable, 125MHz the counter frequency and
852 * we need to divide by 2 because the hardware will measure the
853 * round trip time to the fault and back to the PHY.
854 *
855 * With a VF of 0.69 we get the factor 0.824 mentioned in the
856 * datasheet.
857 */
858 dt = FIELD_GET(AT803X_CDT_STATUS_DELTA_TIME_MASK, status);
859
860 return (dt * 824) / 10;
861}
862
863static int at803x_cdt_start(struct phy_device *phydev, int pair)
864{
865 u16 cdt;
866
867 cdt = FIELD_PREP(AT803X_CDT_MDI_PAIR_MASK, pair) |
868 AT803X_CDT_ENABLE_TEST;
869
870 return phy_write(phydev, AT803X_CDT, cdt);
871}
872
873static int at803x_cdt_wait_for_completion(struct phy_device *phydev)
874{
875 int val, ret;
876
877 /* One test run takes about 25ms */
878 ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
879 !(val & AT803X_CDT_ENABLE_TEST),
880 30000, 100000, true);
881
882 return ret < 0 ? ret : 0;
883}
884
885static int at803x_cable_test_one_pair(struct phy_device *phydev, int pair)
886{
887 static const int ethtool_pair[] = {
888 ETHTOOL_A_CABLE_PAIR_A,
889 ETHTOOL_A_CABLE_PAIR_B,
890 ETHTOOL_A_CABLE_PAIR_C,
891 ETHTOOL_A_CABLE_PAIR_D,
892 };
893 int ret, val;
894
895 ret = at803x_cdt_start(phydev, pair);
896 if (ret)
897 return ret;
898
899 ret = at803x_cdt_wait_for_completion(phydev);
900 if (ret)
901 return ret;
902
903 val = phy_read(phydev, AT803X_CDT_STATUS);
904 if (val < 0)
905 return val;
906
907 if (at803x_cdt_test_failed(val))
908 return 0;
909
910 ethnl_cable_test_result(phydev, ethtool_pair[pair],
911 at803x_cable_test_result_trans(val));
912
913 if (at803x_cdt_fault_length_valid(val))
914 ethnl_cable_test_fault_length(phydev, ethtool_pair[pair],
915 at803x_cdt_fault_length(val));
916
917 return 1;
918}
919
920static int at803x_cable_test_get_status(struct phy_device *phydev,
921 bool *finished)
922{
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +0200923 unsigned long pair_mask;
Michael Walle6cb75762020-05-13 22:38:07 +0200924 int retries = 20;
925 int pair, ret;
926
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +0200927 if (phydev->phy_id == ATH9331_PHY_ID ||
928 phydev->phy_id == ATH8032_PHY_ID)
929 pair_mask = 0x3;
930 else
931 pair_mask = 0xf;
932
Michael Walle6cb75762020-05-13 22:38:07 +0200933 *finished = false;
934
935 /* According to the datasheet the CDT can be performed when
936 * there is no link partner or when the link partner is
937 * auto-negotiating. Starting the test will restart the AN
938 * automatically. It seems that doing this repeatedly we will
939 * get a slot where our link partner won't disturb our
940 * measurement.
941 */
942 while (pair_mask && retries--) {
943 for_each_set_bit(pair, &pair_mask, 4) {
944 ret = at803x_cable_test_one_pair(phydev, pair);
945 if (ret < 0)
946 return ret;
947 if (ret)
948 clear_bit(pair, &pair_mask);
949 }
950 if (pair_mask)
951 msleep(250);
952 }
953
954 *finished = true;
955
956 return 0;
957}
958
959static int at803x_cable_test_start(struct phy_device *phydev)
960{
961 /* Enable auto-negotiation, but advertise no capabilities, no link
962 * will be established. A restart of the auto-negotiation is not
963 * required, because the cable test will automatically break the link.
964 */
965 phy_write(phydev, MII_BMCR, BMCR_ANENABLE);
966 phy_write(phydev, MII_ADVERTISE, ADVERTISE_CSMA);
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +0200967 if (phydev->phy_id != ATH9331_PHY_ID &&
968 phydev->phy_id != ATH8032_PHY_ID)
969 phy_write(phydev, MII_CTRL1000, 0);
Michael Walle6cb75762020-05-13 22:38:07 +0200970
971 /* we do all the (time consuming) work later */
972 return 0;
973}
974
Mugunthan V N317420a2013-06-03 20:10:04 +0000975static struct phy_driver at803x_driver[] = {
976{
Michael Walle96c36712019-11-06 23:36:16 +0100977 /* Qualcomm Atheros AR8035 */
Michael Walle0465d8f2020-05-22 11:53:31 +0200978 PHY_ID_MATCH_EXACT(ATH8035_PHY_ID),
Michael Walle96c36712019-11-06 23:36:16 +0100979 .name = "Qualcomm Atheros AR8035",
Michael Walle6cb75762020-05-13 22:38:07 +0200980 .flags = PHY_POLL_CABLE_TEST,
Michael Walle2f664822019-11-06 23:36:14 +0100981 .probe = at803x_probe,
Michael Walle2318ca82020-01-30 18:54:02 +0100982 .remove = at803x_remove,
Daniel Mack13a56b42014-06-18 11:01:43 +0200983 .config_init = at803x_config_init,
Michael Wallecde0f4f2020-04-28 23:15:02 +0200984 .soft_reset = genphy_soft_reset,
Daniel Mack13a56b42014-06-18 11:01:43 +0200985 .set_wol = at803x_set_wol,
986 .get_wol = at803x_get_wol,
987 .suspend = at803x_suspend,
988 .resume = at803x_resume,
Heiner Kallweitdcdecdc2019-04-12 20:47:03 +0200989 /* PHY_GBIT_FEATURES */
Russell King06d5f342019-10-04 17:06:14 +0100990 .read_status = at803x_read_status,
Måns Rullgård0eae5982015-11-12 17:40:20 +0000991 .ack_interrupt = at803x_ack_interrupt,
992 .config_intr = at803x_config_intr,
Michael Wallecde0f4f2020-04-28 23:15:02 +0200993 .get_tunable = at803x_get_tunable,
994 .set_tunable = at803x_set_tunable,
Michael Walle6cb75762020-05-13 22:38:07 +0200995 .cable_test_start = at803x_cable_test_start,
996 .cable_test_get_status = at803x_cable_test_get_status,
Mugunthan V N317420a2013-06-03 20:10:04 +0000997}, {
Michael Walle96c36712019-11-06 23:36:16 +0100998 /* Qualcomm Atheros AR8030 */
Daniel Mack13a56b42014-06-18 11:01:43 +0200999 .phy_id = ATH8030_PHY_ID,
Michael Walle96c36712019-11-06 23:36:16 +01001000 .name = "Qualcomm Atheros AR8030",
Michael Walle0465d8f2020-05-22 11:53:31 +02001001 .phy_id_mask = AT8030_PHY_ID_MASK,
Michael Walle2f664822019-11-06 23:36:14 +01001002 .probe = at803x_probe,
Michael Walle2318ca82020-01-30 18:54:02 +01001003 .remove = at803x_remove,
Daniel Mack13a56b42014-06-18 11:01:43 +02001004 .config_init = at803x_config_init,
1005 .link_change_notify = at803x_link_change_notify,
1006 .set_wol = at803x_set_wol,
1007 .get_wol = at803x_get_wol,
1008 .suspend = at803x_suspend,
1009 .resume = at803x_resume,
Heiner Kallweitdcdecdc2019-04-12 20:47:03 +02001010 /* PHY_BASIC_FEATURES */
Måns Rullgård0eae5982015-11-12 17:40:20 +00001011 .ack_interrupt = at803x_ack_interrupt,
1012 .config_intr = at803x_config_intr,
Mugunthan V N05d7cce2013-06-03 20:10:07 +00001013}, {
Michael Walle96c36712019-11-06 23:36:16 +01001014 /* Qualcomm Atheros AR8031/AR8033 */
Michael Walle0465d8f2020-05-22 11:53:31 +02001015 PHY_ID_MATCH_EXACT(ATH8031_PHY_ID),
Michael Walle96c36712019-11-06 23:36:16 +01001016 .name = "Qualcomm Atheros AR8031/AR8033",
Michael Walle6cb75762020-05-13 22:38:07 +02001017 .flags = PHY_POLL_CABLE_TEST,
Michael Walle2f664822019-11-06 23:36:14 +01001018 .probe = at803x_probe,
Michael Walle2318ca82020-01-30 18:54:02 +01001019 .remove = at803x_remove,
Daniel Mack13a56b42014-06-18 11:01:43 +02001020 .config_init = at803x_config_init,
Michael Wallecde0f4f2020-04-28 23:15:02 +02001021 .soft_reset = genphy_soft_reset,
Daniel Mack13a56b42014-06-18 11:01:43 +02001022 .set_wol = at803x_set_wol,
1023 .get_wol = at803x_get_wol,
1024 .suspend = at803x_suspend,
1025 .resume = at803x_resume,
Heiner Kallweitdcdecdc2019-04-12 20:47:03 +02001026 /* PHY_GBIT_FEATURES */
Russell King06d5f342019-10-04 17:06:14 +01001027 .read_status = at803x_read_status,
Zefir Kurtisif62265b2016-10-24 12:40:54 +02001028 .aneg_done = at803x_aneg_done,
Daniel Mack13a56b42014-06-18 11:01:43 +02001029 .ack_interrupt = &at803x_ack_interrupt,
1030 .config_intr = &at803x_config_intr,
Michael Wallecde0f4f2020-04-28 23:15:02 +02001031 .get_tunable = at803x_get_tunable,
1032 .set_tunable = at803x_set_tunable,
Michael Walle6cb75762020-05-13 22:38:07 +02001033 .cable_test_start = at803x_cable_test_start,
1034 .cable_test_get_status = at803x_cable_test_get_status,
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001035}, {
David Bauer58000912020-04-17 15:41:59 +02001036 /* Qualcomm Atheros AR8032 */
1037 PHY_ID_MATCH_EXACT(ATH8032_PHY_ID),
1038 .name = "Qualcomm Atheros AR8032",
1039 .probe = at803x_probe,
1040 .remove = at803x_remove,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001041 .flags = PHY_POLL_CABLE_TEST,
David Bauer58000912020-04-17 15:41:59 +02001042 .config_init = at803x_config_init,
1043 .link_change_notify = at803x_link_change_notify,
1044 .set_wol = at803x_set_wol,
1045 .get_wol = at803x_get_wol,
1046 .suspend = at803x_suspend,
1047 .resume = at803x_resume,
1048 /* PHY_BASIC_FEATURES */
1049 .ack_interrupt = at803x_ack_interrupt,
1050 .config_intr = at803x_config_intr,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001051 .cable_test_start = at803x_cable_test_start,
1052 .cable_test_get_status = at803x_cable_test_get_status,
David Bauer58000912020-04-17 15:41:59 +02001053}, {
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001054 /* ATHEROS AR9331 */
1055 PHY_ID_MATCH_EXACT(ATH9331_PHY_ID),
Michael Walle96c36712019-11-06 23:36:16 +01001056 .name = "Qualcomm Atheros AR9331 built-in PHY",
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001057 .suspend = at803x_suspend,
1058 .resume = at803x_resume,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001059 .flags = PHY_POLL_CABLE_TEST,
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001060 /* PHY_BASIC_FEATURES */
1061 .ack_interrupt = &at803x_ack_interrupt,
1062 .config_intr = &at803x_config_intr,
Oleksij Rempeldc0f3ed2020-05-27 07:08:43 +02001063 .cable_test_start = at803x_cable_test_start,
1064 .cable_test_get_status = at803x_cable_test_get_status,
Mugunthan V N317420a2013-06-03 20:10:04 +00001065} };
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00001066
Johan Hovold50fd7152014-11-11 19:45:59 +01001067module_phy_driver(at803x_driver);
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00001068
1069static struct mdio_device_id __maybe_unused atheros_tbl[] = {
Michael Walle0465d8f2020-05-22 11:53:31 +02001070 { ATH8030_PHY_ID, AT8030_PHY_ID_MASK },
1071 { PHY_ID_MATCH_EXACT(ATH8031_PHY_ID) },
David Bauer58000912020-04-17 15:41:59 +02001072 { PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) },
Michael Walle0465d8f2020-05-22 11:53:31 +02001073 { PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) },
Oleksij Rempel7908d2c2019-10-03 10:21:12 +02001074 { PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) },
Matus Ujhelyi0ca71112012-10-14 19:07:16 +00001075 { }
1076};
1077
1078MODULE_DEVICE_TABLE(mdio, atheros_tbl);