defconfig: exynos9610: Re-add dropped Wi-Fi AP options lost
[GitHub/LineageOS/android_kernel_motorola_exynos9610.git] / drivers / net / phy / marvell.c
CommitLineData
00db8189
AF
1/*
2 * drivers/net/phy/marvell.c
3 *
4 * Driver for Marvell PHYs
5 *
6 * Author: Andy Fleming
7 *
8 * Copyright (c) 2004 Freescale Semiconductor, Inc.
9 *
3871c387
MS
10 * Copyright (c) 2013 Michael Stapelberg <michael@stapelberg.de>
11 *
00db8189
AF
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 */
00db8189 18#include <linux/kernel.h>
00db8189 19#include <linux/string.h>
0b04680f 20#include <linux/ctype.h>
00db8189
AF
21#include <linux/errno.h>
22#include <linux/unistd.h>
0b04680f 23#include <linux/hwmon.h>
00db8189
AF
24#include <linux/interrupt.h>
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/netdevice.h>
28#include <linux/etherdevice.h>
29#include <linux/skbuff.h>
30#include <linux/spinlock.h>
31#include <linux/mm.h>
32#include <linux/module.h>
00db8189
AF
33#include <linux/mii.h>
34#include <linux/ethtool.h>
35#include <linux/phy.h>
2f495c39 36#include <linux/marvell_phy.h>
cf41a51d 37#include <linux/of.h>
00db8189 38
eea3b201 39#include <linux/io.h>
00db8189 40#include <asm/irq.h>
eea3b201 41#include <linux/uaccess.h>
00db8189 42
27d916d6 43#define MII_MARVELL_PHY_PAGE 22
52295666
AL
44#define MII_MARVELL_COPPER_PAGE 0x00
45#define MII_MARVELL_FIBER_PAGE 0x01
46#define MII_MARVELL_MSCR_PAGE 0x02
47#define MII_MARVELL_LED_PAGE 0x03
48#define MII_MARVELL_MISC_TEST_PAGE 0x06
49#define MII_MARVELL_WOL_PAGE 0x11
27d916d6 50
00db8189
AF
51#define MII_M1011_IEVENT 0x13
52#define MII_M1011_IEVENT_CLEAR 0x0000
53
54#define MII_M1011_IMASK 0x12
55#define MII_M1011_IMASK_INIT 0x6400
56#define MII_M1011_IMASK_CLEAR 0x0000
57
fecd5e91
AL
58#define MII_M1011_PHY_SCR 0x10
59#define MII_M1011_PHY_SCR_DOWNSHIFT_EN BIT(11)
60#define MII_M1011_PHY_SCR_DOWNSHIFT_SHIFT 12
6ef05eb7 61#define MII_M1011_PHY_SRC_DOWNSHIFT_MASK 0x7800
fecd5e91
AL
62#define MII_M1011_PHY_SCR_MDI (0x0 << 5)
63#define MII_M1011_PHY_SCR_MDI_X (0x1 << 5)
64#define MII_M1011_PHY_SCR_AUTO_CROSS (0x3 << 5)
76884679 65
76884679
AF
66#define MII_M1111_PHY_LED_CONTROL 0x18
67#define MII_M1111_PHY_LED_DIRECT 0x4100
68#define MII_M1111_PHY_LED_COMBINE 0x411c
895ee682 69#define MII_M1111_PHY_EXT_CR 0x14
61111598
AL
70#define MII_M1111_RGMII_RX_DELAY BIT(7)
71#define MII_M1111_RGMII_TX_DELAY BIT(1)
895ee682 72#define MII_M1111_PHY_EXT_SR 0x1b
be937f1f
AS
73
74#define MII_M1111_HWCFG_MODE_MASK 0xf
be937f1f 75#define MII_M1111_HWCFG_MODE_FIBER_RGMII 0x3
4117b5be 76#define MII_M1111_HWCFG_MODE_SGMII_NO_CLK 0x4
865b813a 77#define MII_M1111_HWCFG_MODE_RTBI 0x7
5f8cbc13 78#define MII_M1111_HWCFG_MODE_COPPER_RTBI 0x9
865b813a
AL
79#define MII_M1111_HWCFG_MODE_COPPER_RGMII 0xb
80#define MII_M1111_HWCFG_FIBER_COPPER_RES BIT(13)
81#define MII_M1111_HWCFG_FIBER_COPPER_AUTO BIT(15)
be937f1f 82
c477d044
CC
83#define MII_88E1121_PHY_MSCR_REG 21
84#define MII_88E1121_PHY_MSCR_RX_DELAY BIT(5)
85#define MII_88E1121_PHY_MSCR_TX_DELAY BIT(4)
5987feb3 86#define MII_88E1121_PHY_MSCR_DELAY_MASK (~(BIT(5) | BIT(4)))
c477d044 87
0b04680f
AL
88#define MII_88E1121_MISC_TEST 0x1a
89#define MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK 0x1f00
90#define MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT 8
91#define MII_88E1510_MISC_TEST_TEMP_IRQ_EN BIT(7)
92#define MII_88E1510_MISC_TEST_TEMP_IRQ BIT(6)
93#define MII_88E1121_MISC_TEST_TEMP_SENSOR_EN BIT(5)
94#define MII_88E1121_MISC_TEST_TEMP_MASK 0x1f
95
96#define MII_88E1510_TEMP_SENSOR 0x1b
97#define MII_88E1510_TEMP_SENSOR_MASK 0xff
98
337ac9d5
CC
99#define MII_88E1318S_PHY_MSCR1_REG 16
100#define MII_88E1318S_PHY_MSCR1_PAD_ODD BIT(6)
3ff1c259 101
3871c387 102/* Copper Specific Interrupt Enable Register */
8cf8b87b 103#define MII_88E1318S_PHY_CSIER 0x12
3871c387 104/* WOL Event Interrupt Enable */
8cf8b87b 105#define MII_88E1318S_PHY_CSIER_WOL_EIE BIT(7)
3871c387
MS
106
107/* LED Timer Control Register */
8cf8b87b
AL
108#define MII_88E1318S_PHY_LED_TCR 0x12
109#define MII_88E1318S_PHY_LED_TCR_FORCE_INT BIT(15)
110#define MII_88E1318S_PHY_LED_TCR_INTn_ENABLE BIT(7)
111#define MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW BIT(11)
3871c387
MS
112
113/* Magic Packet MAC address registers */
8cf8b87b
AL
114#define MII_88E1318S_PHY_MAGIC_PACKET_WORD2 0x17
115#define MII_88E1318S_PHY_MAGIC_PACKET_WORD1 0x18
116#define MII_88E1318S_PHY_MAGIC_PACKET_WORD0 0x19
3871c387 117
8cf8b87b
AL
118#define MII_88E1318S_PHY_WOL_CTRL 0x10
119#define MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS BIT(12)
120#define MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE BIT(14)
3871c387 121
140bc929 122#define MII_88E1121_PHY_LED_CTRL 16
140bc929 123#define MII_88E1121_PHY_LED_DEF 0x0030
140bc929 124
be937f1f
AS
125#define MII_M1011_PHY_STATUS 0x11
126#define MII_M1011_PHY_STATUS_1000 0x8000
127#define MII_M1011_PHY_STATUS_100 0x4000
128#define MII_M1011_PHY_STATUS_SPD_MASK 0xc000
129#define MII_M1011_PHY_STATUS_FULLDUPLEX 0x2000
130#define MII_M1011_PHY_STATUS_RESOLVED 0x0800
131#define MII_M1011_PHY_STATUS_LINK 0x0400
132
6b358aed
SH
133#define MII_88E3016_PHY_SPEC_CTRL 0x10
134#define MII_88E3016_DISABLE_SCRAMBLER 0x0200
135#define MII_88E3016_AUTO_MDIX_CROSSOVER 0x0030
76884679 136
930b37ee
SR
137#define MII_88E1510_GEN_CTRL_REG_1 0x14
138#define MII_88E1510_GEN_CTRL_REG_1_MODE_MASK 0x7
139#define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1 /* SGMII to copper */
140#define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */
141
6cfb3bcc
CAC
142#define LPA_FIBER_1000HALF 0x40
143#define LPA_FIBER_1000FULL 0x20
144
8cf8b87b 145#define LPA_PAUSE_FIBER 0x180
6cfb3bcc
CAC
146#define LPA_PAUSE_ASYM_FIBER 0x100
147
148#define ADVERTISE_FIBER_1000HALF 0x40
149#define ADVERTISE_FIBER_1000FULL 0x20
150
151#define ADVERTISE_PAUSE_FIBER 0x180
152#define ADVERTISE_PAUSE_ASYM_FIBER 0x100
153
154#define REGISTER_LINK_STATUS 0x400
2170fef7 155#define NB_FIBER_STATS 1
6cfb3bcc 156
00db8189
AF
157MODULE_DESCRIPTION("Marvell PHY driver");
158MODULE_AUTHOR("Andy Fleming");
159MODULE_LICENSE("GPL");
160
d2fa47d9
AL
161struct marvell_hw_stat {
162 const char *string;
163 u8 page;
164 u8 reg;
165 u8 bits;
166};
167
168static struct marvell_hw_stat marvell_hw_stats[] = {
2170fef7 169 { "phy_receive_errors_copper", 0, 21, 16},
d2fa47d9 170 { "phy_idle_errors", 0, 10, 8 },
2170fef7 171 { "phy_receive_errors_fiber", 1, 21, 16},
d2fa47d9
AL
172};
173
174struct marvell_priv {
175 u64 stats[ARRAY_SIZE(marvell_hw_stats)];
0b04680f
AL
176 char *hwmon_name;
177 struct device *hwmon_dev;
d2fa47d9
AL
178};
179
6427bb2d
AL
180static int marvell_get_page(struct phy_device *phydev)
181{
182 return phy_read(phydev, MII_MARVELL_PHY_PAGE);
183}
184
185static int marvell_set_page(struct phy_device *phydev, int page)
186{
187 return phy_write(phydev, MII_MARVELL_PHY_PAGE, page);
188}
189
53798328
AL
190static int marvell_get_set_page(struct phy_device *phydev, int page)
191{
192 int oldpage = marvell_get_page(phydev);
193
194 if (oldpage < 0)
195 return oldpage;
196
197 if (page != oldpage)
198 return marvell_set_page(phydev, page);
199
200 return 0;
201}
202
00db8189
AF
203static int marvell_ack_interrupt(struct phy_device *phydev)
204{
205 int err;
206
207 /* Clear the interrupts by reading the reg */
208 err = phy_read(phydev, MII_M1011_IEVENT);
209
210 if (err < 0)
211 return err;
212
213 return 0;
214}
215
216static int marvell_config_intr(struct phy_device *phydev)
217{
218 int err;
219
76884679 220 if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
23beb38f
AL
221 err = phy_write(phydev, MII_M1011_IMASK,
222 MII_M1011_IMASK_INIT);
00db8189 223 else
23beb38f
AL
224 err = phy_write(phydev, MII_M1011_IMASK,
225 MII_M1011_IMASK_CLEAR);
00db8189
AF
226
227 return err;
228}
229
239aa55b
DT
230static int marvell_set_polarity(struct phy_device *phydev, int polarity)
231{
232 int reg;
233 int err;
234 int val;
235
236 /* get the current settings */
237 reg = phy_read(phydev, MII_M1011_PHY_SCR);
238 if (reg < 0)
239 return reg;
240
241 val = reg;
242 val &= ~MII_M1011_PHY_SCR_AUTO_CROSS;
243 switch (polarity) {
244 case ETH_TP_MDI:
245 val |= MII_M1011_PHY_SCR_MDI;
246 break;
247 case ETH_TP_MDI_X:
248 val |= MII_M1011_PHY_SCR_MDI_X;
249 break;
250 case ETH_TP_MDI_AUTO:
251 case ETH_TP_MDI_INVALID:
252 default:
253 val |= MII_M1011_PHY_SCR_AUTO_CROSS;
254 break;
255 }
256
257 if (val != reg) {
258 /* Set the new polarity value in the register */
259 err = phy_write(phydev, MII_M1011_PHY_SCR, val);
260 if (err)
261 return err;
262 }
263
264 return 0;
265}
266
6ef05eb7
AL
267static int marvell_set_downshift(struct phy_device *phydev, bool enable,
268 u8 retries)
269{
270 int reg;
271
272 reg = phy_read(phydev, MII_M1011_PHY_SCR);
273 if (reg < 0)
274 return reg;
275
276 reg &= MII_M1011_PHY_SRC_DOWNSHIFT_MASK;
277 reg |= ((retries - 1) << MII_M1011_PHY_SCR_DOWNSHIFT_SHIFT);
278 if (enable)
279 reg |= MII_M1011_PHY_SCR_DOWNSHIFT_EN;
280
281 return phy_write(phydev, MII_M1011_PHY_SCR, reg);
282}
283
00db8189
AF
284static int marvell_config_aneg(struct phy_device *phydev)
285{
286 int err;
287
4e26c5c3 288 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
76884679
AF
289 if (err < 0)
290 return err;
291
292 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
293 MII_M1111_PHY_LED_DIRECT);
294 if (err < 0)
295 return err;
00db8189
AF
296
297 err = genphy_config_aneg(phydev);
8ff44985
AV
298 if (err < 0)
299 return err;
00db8189 300
8ff44985 301 if (phydev->autoneg != AUTONEG_ENABLE) {
0c3439bc 302 /* A write to speed/duplex bits (that is performed by
8ff44985
AV
303 * genphy_config_aneg() call above) must be followed by
304 * a software reset. Otherwise, the write has no effect.
305 */
34386344 306 err = genphy_soft_reset(phydev);
8ff44985
AV
307 if (err < 0)
308 return err;
309 }
310
311 return 0;
00db8189
AF
312}
313
f2899788
AL
314static int m88e1101_config_aneg(struct phy_device *phydev)
315{
316 int err;
317
318 /* This Marvell PHY has an errata which requires
319 * that certain registers get written in order
320 * to restart autonegotiation
321 */
34386344 322 err = genphy_soft_reset(phydev);
f2899788
AL
323 if (err < 0)
324 return err;
325
326 err = phy_write(phydev, 0x1d, 0x1f);
327 if (err < 0)
328 return err;
329
330 err = phy_write(phydev, 0x1e, 0x200c);
331 if (err < 0)
332 return err;
333
334 err = phy_write(phydev, 0x1d, 0x5);
335 if (err < 0)
336 return err;
337
338 err = phy_write(phydev, 0x1e, 0);
339 if (err < 0)
340 return err;
341
342 err = phy_write(phydev, 0x1e, 0x100);
343 if (err < 0)
344 return err;
345
346 return marvell_config_aneg(phydev);
347}
348
3ec0a0f1
HK
349static int m88e1111_config_aneg(struct phy_device *phydev)
350{
351 int err;
352
353 /* The Marvell PHY has an errata which requires
354 * that certain registers get written in order
355 * to restart autonegotiation
356 */
34386344 357 err = genphy_soft_reset(phydev);
3ec0a0f1 358
4e26c5c3 359 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
3ec0a0f1
HK
360 if (err < 0)
361 return err;
362
363 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
364 MII_M1111_PHY_LED_DIRECT);
365 if (err < 0)
366 return err;
367
368 err = genphy_config_aneg(phydev);
369 if (err < 0)
370 return err;
371
372 if (phydev->autoneg != AUTONEG_ENABLE) {
3ec0a0f1
HK
373 /* A write to speed/duplex bits (that is performed by
374 * genphy_config_aneg() call above) must be followed by
375 * a software reset. Otherwise, the write has no effect.
376 */
34386344 377 err = genphy_soft_reset(phydev);
3ec0a0f1
HK
378 if (err < 0)
379 return err;
380 }
381
382 return 0;
383}
384
cf41a51d 385#ifdef CONFIG_OF_MDIO
0c3439bc 386/* Set and/or override some configuration registers based on the
cf41a51d
DD
387 * marvell,reg-init property stored in the of_node for the phydev.
388 *
389 * marvell,reg-init = <reg-page reg mask value>,...;
390 *
391 * There may be one or more sets of <reg-page reg mask value>:
392 *
393 * reg-page: which register bank to use.
394 * reg: the register.
395 * mask: if non-zero, ANDed with existing register value.
396 * value: ORed with the masked value and written to the regiser.
397 *
398 */
399static int marvell_of_reg_init(struct phy_device *phydev)
400{
401 const __be32 *paddr;
b5718b5a 402 int len, i, saved_page, current_page, ret;
cf41a51d 403
e5a03bfd 404 if (!phydev->mdio.dev.of_node)
cf41a51d
DD
405 return 0;
406
e5a03bfd
AL
407 paddr = of_get_property(phydev->mdio.dev.of_node,
408 "marvell,reg-init", &len);
cf41a51d
DD
409 if (!paddr || len < (4 * sizeof(*paddr)))
410 return 0;
411
6427bb2d 412 saved_page = marvell_get_page(phydev);
cf41a51d
DD
413 if (saved_page < 0)
414 return saved_page;
cf41a51d
DD
415 current_page = saved_page;
416
417 ret = 0;
418 len /= sizeof(*paddr);
419 for (i = 0; i < len - 3; i += 4) {
6427bb2d 420 u16 page = be32_to_cpup(paddr + i);
cf41a51d
DD
421 u16 reg = be32_to_cpup(paddr + i + 1);
422 u16 mask = be32_to_cpup(paddr + i + 2);
423 u16 val_bits = be32_to_cpup(paddr + i + 3);
424 int val;
425
6427bb2d
AL
426 if (page != current_page) {
427 current_page = page;
428 ret = marvell_set_page(phydev, page);
cf41a51d
DD
429 if (ret < 0)
430 goto err;
431 }
432
433 val = 0;
434 if (mask) {
435 val = phy_read(phydev, reg);
436 if (val < 0) {
437 ret = val;
438 goto err;
439 }
440 val &= mask;
441 }
442 val |= val_bits;
443
444 ret = phy_write(phydev, reg, val);
445 if (ret < 0)
446 goto err;
cf41a51d
DD
447 }
448err:
b5718b5a 449 if (current_page != saved_page) {
6427bb2d 450 i = marvell_set_page(phydev, saved_page);
cf41a51d
DD
451 if (ret == 0)
452 ret = i;
453 }
454 return ret;
455}
456#else
457static int marvell_of_reg_init(struct phy_device *phydev)
458{
459 return 0;
460}
461#endif /* CONFIG_OF_MDIO */
462
864dc729 463static int m88e1121_config_aneg_rgmii_delays(struct phy_device *phydev)
140bc929 464{
c477d044
CC
465 int err, oldpage, mscr;
466
52295666 467 oldpage = marvell_get_set_page(phydev, MII_MARVELL_MSCR_PAGE);
53798328
AL
468 if (oldpage < 0)
469 return oldpage;
be8c6480 470
864dc729
AL
471 mscr = phy_read(phydev, MII_88E1121_PHY_MSCR_REG);
472 if (mscr < 0) {
473 err = mscr;
474 goto out;
be8c6480 475 }
c477d044 476
864dc729
AL
477 mscr &= MII_88E1121_PHY_MSCR_DELAY_MASK;
478
479 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
480 mscr |= (MII_88E1121_PHY_MSCR_RX_DELAY |
481 MII_88E1121_PHY_MSCR_TX_DELAY);
482 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
483 mscr |= MII_88E1121_PHY_MSCR_RX_DELAY;
484 else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
485 mscr |= MII_88E1121_PHY_MSCR_TX_DELAY;
486
487 err = phy_write(phydev, MII_88E1121_PHY_MSCR_REG, mscr);
488
489out:
6427bb2d 490 marvell_set_page(phydev, oldpage);
140bc929 491
864dc729
AL
492 return err;
493}
494
495static int m88e1121_config_aneg(struct phy_device *phydev)
496{
497 int err = 0;
498
499 if (phy_interface_is_rgmii(phydev)) {
500 err = m88e1121_config_aneg_rgmii_delays(phydev);
501 if (err)
502 return err;
503 }
504
34386344 505 err = genphy_soft_reset(phydev);
140bc929
SP
506 if (err < 0)
507 return err;
508
fecd5e91 509 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
140bc929
SP
510 if (err < 0)
511 return err;
512
fdecf36f 513 return genphy_config_aneg(phydev);
140bc929
SP
514}
515
337ac9d5 516static int m88e1318_config_aneg(struct phy_device *phydev)
3ff1c259
CC
517{
518 int err, oldpage, mscr;
519
52295666 520 oldpage = marvell_get_set_page(phydev, MII_MARVELL_MSCR_PAGE);
53798328
AL
521 if (oldpage < 0)
522 return oldpage;
3ff1c259 523
337ac9d5
CC
524 mscr = phy_read(phydev, MII_88E1318S_PHY_MSCR1_REG);
525 mscr |= MII_88E1318S_PHY_MSCR1_PAD_ODD;
3ff1c259 526
337ac9d5 527 err = phy_write(phydev, MII_88E1318S_PHY_MSCR1_REG, mscr);
3ff1c259
CC
528 if (err < 0)
529 return err;
530
6427bb2d 531 err = marvell_set_page(phydev, oldpage);
3ff1c259
CC
532 if (err < 0)
533 return err;
534
535 return m88e1121_config_aneg(phydev);
536}
537
78301ebe
CAC
538/**
539 * ethtool_adv_to_fiber_adv_t
540 * @ethadv: the ethtool advertisement settings
541 *
542 * A small helper function that translates ethtool advertisement
543 * settings to phy autonegotiation advertisements for the
544 * MII_ADV register for fiber link.
545 */
546static inline u32 ethtool_adv_to_fiber_adv_t(u32 ethadv)
547{
548 u32 result = 0;
549
550 if (ethadv & ADVERTISED_1000baseT_Half)
551 result |= ADVERTISE_FIBER_1000HALF;
552 if (ethadv & ADVERTISED_1000baseT_Full)
553 result |= ADVERTISE_FIBER_1000FULL;
554
555 if ((ethadv & ADVERTISE_PAUSE_ASYM) && (ethadv & ADVERTISE_PAUSE_CAP))
556 result |= LPA_PAUSE_ASYM_FIBER;
557 else if (ethadv & ADVERTISE_PAUSE_CAP)
558 result |= (ADVERTISE_PAUSE_FIBER
559 & (~ADVERTISE_PAUSE_ASYM_FIBER));
560
561 return result;
562}
563
564/**
565 * marvell_config_aneg_fiber - restart auto-negotiation or write BMCR
566 * @phydev: target phy_device struct
567 *
568 * Description: If auto-negotiation is enabled, we configure the
569 * advertising, and then restart auto-negotiation. If it is not
570 * enabled, then we write the BMCR. Adapted for fiber link in
571 * some Marvell's devices.
572 */
573static int marvell_config_aneg_fiber(struct phy_device *phydev)
574{
575 int changed = 0;
576 int err;
577 int adv, oldadv;
578 u32 advertise;
579
580 if (phydev->autoneg != AUTONEG_ENABLE)
581 return genphy_setup_forced(phydev);
582
583 /* Only allow advertising what this PHY supports */
584 phydev->advertising &= phydev->supported;
585 advertise = phydev->advertising;
586
587 /* Setup fiber advertisement */
588 adv = phy_read(phydev, MII_ADVERTISE);
589 if (adv < 0)
590 return adv;
591
592 oldadv = adv;
593 adv &= ~(ADVERTISE_FIBER_1000HALF | ADVERTISE_FIBER_1000FULL
594 | LPA_PAUSE_FIBER);
595 adv |= ethtool_adv_to_fiber_adv_t(advertise);
596
597 if (adv != oldadv) {
598 err = phy_write(phydev, MII_ADVERTISE, adv);
599 if (err < 0)
600 return err;
601
602 changed = 1;
603 }
604
605 if (changed == 0) {
606 /* Advertisement hasn't changed, but maybe aneg was never on to
8cf8b87b 607 * begin with? Or maybe phy was isolated?
78301ebe
CAC
608 */
609 int ctl = phy_read(phydev, MII_BMCR);
610
611 if (ctl < 0)
612 return ctl;
613
614 if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
615 changed = 1; /* do restart aneg */
616 }
617
618 /* Only restart aneg if we are advertising something different
619 * than we were before.
620 */
621 if (changed > 0)
622 changed = genphy_restart_aneg(phydev);
623
624 return changed;
625}
626
10e24caa
MS
627static int m88e1510_config_aneg(struct phy_device *phydev)
628{
629 int err;
630
52295666 631 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
78301ebe
CAC
632 if (err < 0)
633 goto error;
634
635 /* Configure the copper link first */
10e24caa
MS
636 err = m88e1318_config_aneg(phydev);
637 if (err < 0)
78301ebe 638 goto error;
10e24caa 639
78301ebe 640 /* Then the fiber link */
52295666 641 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
78301ebe
CAC
642 if (err < 0)
643 goto error;
644
645 err = marvell_config_aneg_fiber(phydev);
646 if (err < 0)
647 goto error;
648
52295666 649 return marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
78301ebe
CAC
650
651error:
52295666 652 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
78301ebe 653 return err;
79be1a1c
CG
654}
655
656static int marvell_config_init(struct phy_device *phydev)
657{
658 /* Set registers from marvell,reg-init DT property */
10e24caa
MS
659 return marvell_of_reg_init(phydev);
660}
661
3da09a51
MS
662static int m88e1116r_config_init(struct phy_device *phydev)
663{
3da09a51
MS
664 int err;
665
34386344 666 err = genphy_soft_reset(phydev);
3da09a51
MS
667 if (err < 0)
668 return err;
669
670 mdelay(500);
671
52295666 672 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
3da09a51
MS
673 if (err < 0)
674 return err;
675
fecd5e91
AL
676 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
677 if (err < 0)
678 return err;
679
6ef05eb7 680 err = marvell_set_downshift(phydev, true, 8);
3da09a51
MS
681 if (err < 0)
682 return err;
683
14fc0aba
AL
684 if (phy_interface_is_rgmii(phydev)) {
685 err = m88e1121_config_aneg_rgmii_delays(phydev);
686 if (err < 0)
687 return err;
688 }
3da09a51 689
34386344 690 err = genphy_soft_reset(phydev);
3da09a51
MS
691 if (err < 0)
692 return err;
693
79be1a1c 694 return marvell_config_init(phydev);
3da09a51
MS
695}
696
6b358aed
SH
697static int m88e3016_config_init(struct phy_device *phydev)
698{
699 int reg;
700
701 /* Enable Scrambler and Auto-Crossover */
702 reg = phy_read(phydev, MII_88E3016_PHY_SPEC_CTRL);
703 if (reg < 0)
704 return reg;
705
706 reg &= ~MII_88E3016_DISABLE_SCRAMBLER;
707 reg |= MII_88E3016_AUTO_MDIX_CROSSOVER;
708
709 reg = phy_write(phydev, MII_88E3016_PHY_SPEC_CTRL, reg);
710 if (reg < 0)
711 return reg;
712
79be1a1c 713 return marvell_config_init(phydev);
6b358aed
SH
714}
715
865b813a
AL
716static int m88e1111_config_init_hwcfg_mode(struct phy_device *phydev,
717 u16 mode,
718 int fibre_copper_auto)
719{
720 int temp;
721
722 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
723 if (temp < 0)
724 return temp;
725
726 temp &= ~(MII_M1111_HWCFG_MODE_MASK |
727 MII_M1111_HWCFG_FIBER_COPPER_AUTO |
728 MII_M1111_HWCFG_FIBER_COPPER_RES);
729 temp |= mode;
730
731 if (fibre_copper_auto)
732 temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
733
734 return phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
735}
736
61111598 737static int m88e1111_config_init_rgmii_delays(struct phy_device *phydev)
895ee682 738{
be937f1f 739 int temp;
be937f1f 740
e1dde8dc
AL
741 temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
742 if (temp < 0)
743 return temp;
895ee682 744
e1dde8dc 745 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
61111598 746 temp |= (MII_M1111_RGMII_RX_DELAY | MII_M1111_RGMII_TX_DELAY);
e1dde8dc 747 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
61111598
AL
748 temp &= ~MII_M1111_RGMII_TX_DELAY;
749 temp |= MII_M1111_RGMII_RX_DELAY;
e1dde8dc 750 } else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
61111598
AL
751 temp &= ~MII_M1111_RGMII_RX_DELAY;
752 temp |= MII_M1111_RGMII_TX_DELAY;
e1dde8dc 753 }
895ee682 754
61111598
AL
755 return phy_write(phydev, MII_M1111_PHY_EXT_CR, temp);
756}
757
758static int m88e1111_config_init_rgmii(struct phy_device *phydev)
759{
760 int temp;
761 int err;
762
763 err = m88e1111_config_init_rgmii_delays(phydev);
e1dde8dc
AL
764 if (err < 0)
765 return err;
9daf5a76 766
e1dde8dc
AL
767 temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
768 if (temp < 0)
769 return temp;
895ee682 770
e1dde8dc 771 temp &= ~(MII_M1111_HWCFG_MODE_MASK);
be937f1f 772
e1dde8dc
AL
773 if (temp & MII_M1111_HWCFG_FIBER_COPPER_RES)
774 temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
775 else
776 temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
895ee682 777
e1dde8dc
AL
778 return phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
779}
895ee682 780
e1dde8dc
AL
781static int m88e1111_config_init_sgmii(struct phy_device *phydev)
782{
783 int err;
4117b5be 784
865b813a
AL
785 err = m88e1111_config_init_hwcfg_mode(
786 phydev,
787 MII_M1111_HWCFG_MODE_SGMII_NO_CLK,
788 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
e1dde8dc
AL
789 if (err < 0)
790 return err;
07151bc9 791
e1dde8dc 792 /* make sure copper is selected */
52295666 793 return marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
e1dde8dc 794}
5f8cbc13 795
e1dde8dc
AL
796static int m88e1111_config_init_rtbi(struct phy_device *phydev)
797{
61111598 798 int err;
e1dde8dc 799
61111598
AL
800 err = m88e1111_config_init_rgmii_delays(phydev);
801 if (err)
e1dde8dc
AL
802 return err;
803
865b813a
AL
804 err = m88e1111_config_init_hwcfg_mode(
805 phydev,
806 MII_M1111_HWCFG_MODE_RTBI,
807 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
e1dde8dc
AL
808 if (err < 0)
809 return err;
810
811 /* soft reset */
34386344 812 err = genphy_soft_reset(phydev);
e1dde8dc
AL
813 if (err < 0)
814 return err;
815
865b813a
AL
816 return m88e1111_config_init_hwcfg_mode(
817 phydev,
818 MII_M1111_HWCFG_MODE_RTBI,
819 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
e1dde8dc
AL
820}
821
822static int m88e1111_config_init(struct phy_device *phydev)
823{
824 int err;
825
826 if (phy_interface_is_rgmii(phydev)) {
827 err = m88e1111_config_init_rgmii(phydev);
828 if (err)
5f8cbc13 829 return err;
e1dde8dc 830 }
5f8cbc13 831
e1dde8dc
AL
832 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
833 err = m88e1111_config_init_sgmii(phydev);
5f8cbc13
LYB
834 if (err < 0)
835 return err;
e1dde8dc 836 }
5f8cbc13 837
e1dde8dc
AL
838 if (phydev->interface == PHY_INTERFACE_MODE_RTBI) {
839 err = m88e1111_config_init_rtbi(phydev);
5f8cbc13
LYB
840 if (err < 0)
841 return err;
842 }
843
cf41a51d
DD
844 err = marvell_of_reg_init(phydev);
845 if (err < 0)
846 return err;
5f8cbc13 847
34386344 848 return genphy_soft_reset(phydev);
895ee682
KP
849}
850
fdecf36f
CG
851static int m88e1121_config_init(struct phy_device *phydev)
852{
853 int err, oldpage;
854
52295666 855 oldpage = marvell_get_set_page(phydev, MII_MARVELL_LED_PAGE);
53798328
AL
856 if (oldpage < 0)
857 return oldpage;
fdecf36f
CG
858
859 /* Default PHY LED config: LED[0] .. Link, LED[1] .. Activity */
860 err = phy_write(phydev, MII_88E1121_PHY_LED_CTRL,
861 MII_88E1121_PHY_LED_DEF);
862 if (err < 0)
863 return err;
864
6427bb2d 865 marvell_set_page(phydev, oldpage);
fdecf36f
CG
866
867 /* Set marvell,reg-init configuration from device tree */
868 return marvell_config_init(phydev);
869}
870
407353ec
CG
871static int m88e1510_config_init(struct phy_device *phydev)
872{
873 int err;
874 int temp;
875
876 /* SGMII-to-Copper mode initialization */
877 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
878 /* Select page 18 */
6427bb2d 879 err = marvell_set_page(phydev, 18);
407353ec
CG
880 if (err < 0)
881 return err;
882
883 /* In reg 20, write MODE[2:0] = 0x1 (SGMII to Copper) */
884 temp = phy_read(phydev, MII_88E1510_GEN_CTRL_REG_1);
885 temp &= ~MII_88E1510_GEN_CTRL_REG_1_MODE_MASK;
886 temp |= MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII;
887 err = phy_write(phydev, MII_88E1510_GEN_CTRL_REG_1, temp);
888 if (err < 0)
889 return err;
890
891 /* PHY reset is necessary after changing MODE[2:0] */
892 temp |= MII_88E1510_GEN_CTRL_REG_1_RESET;
893 err = phy_write(phydev, MII_88E1510_GEN_CTRL_REG_1, temp);
894 if (err < 0)
895 return err;
896
897 /* Reset page selection */
52295666 898 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
407353ec
CG
899 if (err < 0)
900 return err;
901 }
902
fdecf36f 903 return m88e1121_config_init(phydev);
407353ec
CG
904}
905
605f196e
RM
906static int m88e1118_config_aneg(struct phy_device *phydev)
907{
908 int err;
909
34386344 910 err = genphy_soft_reset(phydev);
605f196e
RM
911 if (err < 0)
912 return err;
913
fecd5e91 914 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
605f196e
RM
915 if (err < 0)
916 return err;
917
918 err = genphy_config_aneg(phydev);
919 return 0;
920}
921
922static int m88e1118_config_init(struct phy_device *phydev)
923{
924 int err;
925
926 /* Change address */
52295666 927 err = marvell_set_page(phydev, MII_MARVELL_MSCR_PAGE);
605f196e
RM
928 if (err < 0)
929 return err;
930
931 /* Enable 1000 Mbit */
932 err = phy_write(phydev, 0x15, 0x1070);
933 if (err < 0)
934 return err;
935
936 /* Change address */
52295666 937 err = marvell_set_page(phydev, MII_MARVELL_LED_PAGE);
605f196e
RM
938 if (err < 0)
939 return err;
940
941 /* Adjust LED Control */
2f495c39
BH
942 if (phydev->dev_flags & MARVELL_PHY_M1118_DNS323_LEDS)
943 err = phy_write(phydev, 0x10, 0x1100);
944 else
945 err = phy_write(phydev, 0x10, 0x021e);
605f196e
RM
946 if (err < 0)
947 return err;
948
cf41a51d
DD
949 err = marvell_of_reg_init(phydev);
950 if (err < 0)
951 return err;
952
605f196e 953 /* Reset address */
52295666 954 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
605f196e
RM
955 if (err < 0)
956 return err;
957
34386344 958 return genphy_soft_reset(phydev);
605f196e
RM
959}
960
90600732
DD
961static int m88e1149_config_init(struct phy_device *phydev)
962{
963 int err;
964
965 /* Change address */
52295666 966 err = marvell_set_page(phydev, MII_MARVELL_MSCR_PAGE);
90600732
DD
967 if (err < 0)
968 return err;
969
970 /* Enable 1000 Mbit */
971 err = phy_write(phydev, 0x15, 0x1048);
972 if (err < 0)
973 return err;
974
cf41a51d
DD
975 err = marvell_of_reg_init(phydev);
976 if (err < 0)
977 return err;
978
90600732 979 /* Reset address */
52295666 980 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
90600732
DD
981 if (err < 0)
982 return err;
983
34386344 984 return genphy_soft_reset(phydev);
90600732
DD
985}
986
e1dde8dc
AL
987static int m88e1145_config_init_rgmii(struct phy_device *phydev)
988{
61111598 989 int temp;
e1dde8dc 990 int err;
e1dde8dc 991
61111598 992 err = m88e1111_config_init_rgmii_delays(phydev);
e1dde8dc
AL
993 if (err < 0)
994 return err;
995
996 if (phydev->dev_flags & MARVELL_PHY_M1145_FLAGS_RESISTANCE) {
997 err = phy_write(phydev, 0x1d, 0x0012);
998 if (err < 0)
999 return err;
1000
1001 temp = phy_read(phydev, 0x1e);
1002 if (temp < 0)
1003 return temp;
1004
1005 temp &= 0xf03f;
1006 temp |= 2 << 9; /* 36 ohm */
1007 temp |= 2 << 6; /* 39 ohm */
1008
1009 err = phy_write(phydev, 0x1e, temp);
1010 if (err < 0)
1011 return err;
1012
1013 err = phy_write(phydev, 0x1d, 0x3);
1014 if (err < 0)
1015 return err;
1016
1017 err = phy_write(phydev, 0x1e, 0x8000);
1018 }
1019 return err;
1020}
1021
1022static int m88e1145_config_init_sgmii(struct phy_device *phydev)
1023{
865b813a
AL
1024 return m88e1111_config_init_hwcfg_mode(
1025 phydev, MII_M1111_HWCFG_MODE_SGMII_NO_CLK,
1026 MII_M1111_HWCFG_FIBER_COPPER_AUTO);
e1dde8dc
AL
1027}
1028
76884679
AF
1029static int m88e1145_config_init(struct phy_device *phydev)
1030{
1031 int err;
1032
1033 /* Take care of errata E0 & E1 */
1034 err = phy_write(phydev, 0x1d, 0x001b);
1035 if (err < 0)
1036 return err;
1037
1038 err = phy_write(phydev, 0x1e, 0x418f);
1039 if (err < 0)
1040 return err;
1041
1042 err = phy_write(phydev, 0x1d, 0x0016);
1043 if (err < 0)
1044 return err;
1045
1046 err = phy_write(phydev, 0x1e, 0xa2da);
1047 if (err < 0)
1048 return err;
1049
895ee682 1050 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) {
e1dde8dc 1051 err = m88e1145_config_init_rgmii(phydev);
76884679
AF
1052 if (err < 0)
1053 return err;
76884679
AF
1054 }
1055
b0224175 1056 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
e1dde8dc 1057 err = m88e1145_config_init_sgmii(phydev);
b0224175
VND
1058 if (err < 0)
1059 return err;
1060 }
1061
cf41a51d
DD
1062 err = marvell_of_reg_init(phydev);
1063 if (err < 0)
1064 return err;
1065
76884679
AF
1066 return 0;
1067}
00db8189 1068
6cfb3bcc
CAC
1069/**
1070 * fiber_lpa_to_ethtool_lpa_t
1071 * @lpa: value of the MII_LPA register for fiber link
1072 *
1073 * A small helper function that translates MII_LPA
1074 * bits to ethtool LP advertisement settings.
1075 */
1076static u32 fiber_lpa_to_ethtool_lpa_t(u32 lpa)
1077{
1078 u32 result = 0;
1079
1080 if (lpa & LPA_FIBER_1000HALF)
1081 result |= ADVERTISED_1000baseT_Half;
1082 if (lpa & LPA_FIBER_1000FULL)
1083 result |= ADVERTISED_1000baseT_Full;
1084
1085 return result;
1086}
1087
1088/**
1089 * marvell_update_link - update link status in real time in @phydev
1090 * @phydev: target phy_device struct
1091 *
1092 * Description: Update the value in phydev->link to reflect the
1093 * current link value.
1094 */
1095static int marvell_update_link(struct phy_device *phydev, int fiber)
1096{
1097 int status;
1098
1099 /* Use the generic register for copper link, or specific
0c3439bc
AL
1100 * register for fiber case
1101 */
6cfb3bcc
CAC
1102 if (fiber) {
1103 status = phy_read(phydev, MII_M1011_PHY_STATUS);
1104 if (status < 0)
1105 return status;
1106
1107 if ((status & REGISTER_LINK_STATUS) == 0)
1108 phydev->link = 0;
1109 else
1110 phydev->link = 1;
1111 } else {
1112 return genphy_update_link(phydev);
1113 }
1114
1115 return 0;
1116}
1117
e1dde8dc
AL
1118static int marvell_read_status_page_an(struct phy_device *phydev,
1119 int fiber)
1120{
1121 int status;
1122 int lpa;
1123 int lpagb;
e1dde8dc
AL
1124
1125 status = phy_read(phydev, MII_M1011_PHY_STATUS);
1126 if (status < 0)
1127 return status;
1128
1129 lpa = phy_read(phydev, MII_LPA);
1130 if (lpa < 0)
1131 return lpa;
1132
1133 lpagb = phy_read(phydev, MII_STAT1000);
1134 if (lpagb < 0)
1135 return lpagb;
1136
e1dde8dc
AL
1137 if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
1138 phydev->duplex = DUPLEX_FULL;
1139 else
1140 phydev->duplex = DUPLEX_HALF;
1141
1142 status = status & MII_M1011_PHY_STATUS_SPD_MASK;
1143 phydev->pause = 0;
1144 phydev->asym_pause = 0;
1145
1146 switch (status) {
1147 case MII_M1011_PHY_STATUS_1000:
1148 phydev->speed = SPEED_1000;
1149 break;
1150
1151 case MII_M1011_PHY_STATUS_100:
1152 phydev->speed = SPEED_100;
1153 break;
1154
1155 default:
1156 phydev->speed = SPEED_10;
1157 break;
1158 }
1159
1160 if (!fiber) {
1161 phydev->lp_advertising =
1162 mii_stat1000_to_ethtool_lpa_t(lpagb) |
1163 mii_lpa_to_ethtool_lpa_t(lpa);
1164
1165 if (phydev->duplex == DUPLEX_FULL) {
1166 phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
1167 phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
1168 }
1169 } else {
1170 /* The fiber link is only 1000M capable */
1171 phydev->lp_advertising = fiber_lpa_to_ethtool_lpa_t(lpa);
1172
1173 if (phydev->duplex == DUPLEX_FULL) {
1174 if (!(lpa & LPA_PAUSE_FIBER)) {
1175 phydev->pause = 0;
1176 phydev->asym_pause = 0;
1177 } else if ((lpa & LPA_PAUSE_ASYM_FIBER)) {
1178 phydev->pause = 1;
1179 phydev->asym_pause = 1;
1180 } else {
1181 phydev->pause = 1;
1182 phydev->asym_pause = 0;
1183 }
1184 }
1185 }
1186 return 0;
1187}
1188
1189static int marvell_read_status_page_fixed(struct phy_device *phydev)
1190{
1191 int bmcr = phy_read(phydev, MII_BMCR);
1192
1193 if (bmcr < 0)
1194 return bmcr;
1195
1196 if (bmcr & BMCR_FULLDPLX)
1197 phydev->duplex = DUPLEX_FULL;
1198 else
1199 phydev->duplex = DUPLEX_HALF;
1200
1201 if (bmcr & BMCR_SPEED1000)
1202 phydev->speed = SPEED_1000;
1203 else if (bmcr & BMCR_SPEED100)
1204 phydev->speed = SPEED_100;
1205 else
1206 phydev->speed = SPEED_10;
1207
1208 phydev->pause = 0;
1209 phydev->asym_pause = 0;
1210 phydev->lp_advertising = 0;
1211
1212 return 0;
1213}
1214
6cfb3bcc 1215/* marvell_read_status_page
be937f1f 1216 *
f0c88f9c 1217 * Description:
be937f1f
AS
1218 * Check the link, then figure out the current state
1219 * by comparing what we advertise with what the link partner
1220 * advertises. Start by checking the gigabit possibilities,
1221 * then move on to 10/100.
1222 */
6cfb3bcc 1223static int marvell_read_status_page(struct phy_device *phydev, int page)
be937f1f 1224{
6cfb3bcc 1225 int fiber;
e1dde8dc 1226 int err;
be937f1f 1227
6cfb3bcc 1228 /* Detect and update the link, but return if there
0c3439bc
AL
1229 * was an error
1230 */
52295666 1231 if (page == MII_MARVELL_FIBER_PAGE)
6cfb3bcc
CAC
1232 fiber = 1;
1233 else
1234 fiber = 0;
1235
1236 err = marvell_update_link(phydev, fiber);
be937f1f
AS
1237 if (err)
1238 return err;
1239
e1dde8dc
AL
1240 if (phydev->autoneg == AUTONEG_ENABLE)
1241 err = marvell_read_status_page_an(phydev, fiber);
1242 else
1243 err = marvell_read_status_page_fixed(phydev);
be937f1f 1244
e1dde8dc 1245 return err;
be937f1f
AS
1246}
1247
6cfb3bcc
CAC
1248/* marvell_read_status
1249 *
1250 * Some Marvell's phys have two modes: fiber and copper.
1251 * Both need status checked.
1252 * Description:
1253 * First, check the fiber link and status.
1254 * If the fiber link is down, check the copper link and status which
1255 * will be the default value if both link are down.
1256 */
1257static int marvell_read_status(struct phy_device *phydev)
1258{
1259 int err;
1260
1261 /* Check the fiber mode first */
a13c0652
RK
1262 if (phydev->supported & SUPPORTED_FIBRE &&
1263 phydev->interface != PHY_INTERFACE_MODE_SGMII) {
52295666 1264 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
6cfb3bcc
CAC
1265 if (err < 0)
1266 goto error;
1267
52295666 1268 err = marvell_read_status_page(phydev, MII_MARVELL_FIBER_PAGE);
6cfb3bcc
CAC
1269 if (err < 0)
1270 goto error;
1271
0c3439bc
AL
1272 /* If the fiber link is up, it is the selected and
1273 * used link. In this case, we need to stay in the
1274 * fiber page. Please to be careful about that, avoid
1275 * to restore Copper page in other functions which
1276 * could break the behaviour for some fiber phy like
1277 * 88E1512.
1278 */
6cfb3bcc
CAC
1279 if (phydev->link)
1280 return 0;
1281
1282 /* If fiber link is down, check and save copper mode state */
52295666 1283 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
6cfb3bcc
CAC
1284 if (err < 0)
1285 goto error;
1286 }
1287
52295666 1288 return marvell_read_status_page(phydev, MII_MARVELL_COPPER_PAGE);
6cfb3bcc
CAC
1289
1290error:
52295666 1291 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
6cfb3bcc
CAC
1292 return err;
1293}
3758be3d
CAC
1294
1295/* marvell_suspend
1296 *
1297 * Some Marvell's phys have two modes: fiber and copper.
1298 * Both need to be suspended
1299 */
1300static int marvell_suspend(struct phy_device *phydev)
1301{
1302 int err;
1303
1304 /* Suspend the fiber mode first */
1305 if (!(phydev->supported & SUPPORTED_FIBRE)) {
52295666 1306 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
3758be3d
CAC
1307 if (err < 0)
1308 goto error;
1309
1310 /* With the page set, use the generic suspend */
1311 err = genphy_suspend(phydev);
1312 if (err < 0)
1313 goto error;
1314
1315 /* Then, the copper link */
52295666 1316 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
3758be3d
CAC
1317 if (err < 0)
1318 goto error;
1319 }
1320
1321 /* With the page set, use the generic suspend */
1322 return genphy_suspend(phydev);
1323
1324error:
52295666 1325 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
3758be3d
CAC
1326 return err;
1327}
1328
1329/* marvell_resume
1330 *
1331 * Some Marvell's phys have two modes: fiber and copper.
1332 * Both need to be resumed
1333 */
1334static int marvell_resume(struct phy_device *phydev)
1335{
1336 int err;
1337
1338 /* Resume the fiber mode first */
1339 if (!(phydev->supported & SUPPORTED_FIBRE)) {
52295666 1340 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
3758be3d
CAC
1341 if (err < 0)
1342 goto error;
1343
1344 /* With the page set, use the generic resume */
1345 err = genphy_resume(phydev);
1346 if (err < 0)
1347 goto error;
1348
1349 /* Then, the copper link */
52295666 1350 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
3758be3d
CAC
1351 if (err < 0)
1352 goto error;
1353 }
1354
1355 /* With the page set, use the generic resume */
1356 return genphy_resume(phydev);
1357
1358error:
52295666 1359 marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
3758be3d
CAC
1360 return err;
1361}
1362
6b358aed
SH
1363static int marvell_aneg_done(struct phy_device *phydev)
1364{
1365 int retval = phy_read(phydev, MII_M1011_PHY_STATUS);
e69d9ed4 1366
6b358aed
SH
1367 return (retval < 0) ? retval : (retval & MII_M1011_PHY_STATUS_RESOLVED);
1368}
1369
dcd07be3
AG
1370static int m88e1121_did_interrupt(struct phy_device *phydev)
1371{
1372 int imask;
1373
1374 imask = phy_read(phydev, MII_M1011_IEVENT);
1375
1376 if (imask & MII_M1011_IMASK_INIT)
1377 return 1;
1378
1379 return 0;
1380}
1381
23beb38f
AL
1382static void m88e1318_get_wol(struct phy_device *phydev,
1383 struct ethtool_wolinfo *wol)
3871c387
MS
1384{
1385 wol->supported = WAKE_MAGIC;
1386 wol->wolopts = 0;
1387
52295666 1388 if (marvell_set_page(phydev, MII_MARVELL_WOL_PAGE) < 0)
3871c387
MS
1389 return;
1390
1391 if (phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL) &
1392 MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
1393 wol->wolopts |= WAKE_MAGIC;
1394
52295666 1395 if (marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE) < 0)
3871c387
MS
1396 return;
1397}
1398
23beb38f
AL
1399static int m88e1318_set_wol(struct phy_device *phydev,
1400 struct ethtool_wolinfo *wol)
3871c387
MS
1401{
1402 int err, oldpage, temp;
1403
6427bb2d 1404 oldpage = marvell_get_page(phydev);
3871c387
MS
1405
1406 if (wol->wolopts & WAKE_MAGIC) {
1407 /* Explicitly switch to page 0x00, just to be sure */
52295666 1408 err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
3871c387
MS
1409 if (err < 0)
1410 return err;
1411
9148e21d
JH
1412 /* If WOL event happened once, the LED[2] interrupt pin
1413 * will not be cleared unless we reading the interrupt status
1414 * register. If interrupts are in use, the normal interrupt
1415 * handling will clear the WOL event. Clear the WOL event
1416 * before enabling it if !phy_interrupt_is_valid()
1417 */
1418 if (!phy_interrupt_is_valid(phydev))
1419 phy_read(phydev, MII_M1011_IEVENT);
1420
3871c387
MS
1421 /* Enable the WOL interrupt */
1422 temp = phy_read(phydev, MII_88E1318S_PHY_CSIER);
1423 temp |= MII_88E1318S_PHY_CSIER_WOL_EIE;
1424 err = phy_write(phydev, MII_88E1318S_PHY_CSIER, temp);
1425 if (err < 0)
1426 return err;
1427
52295666 1428 err = marvell_set_page(phydev, MII_MARVELL_LED_PAGE);
3871c387
MS
1429 if (err < 0)
1430 return err;
1431
1432 /* Setup LED[2] as interrupt pin (active low) */
1433 temp = phy_read(phydev, MII_88E1318S_PHY_LED_TCR);
1434 temp &= ~MII_88E1318S_PHY_LED_TCR_FORCE_INT;
1435 temp |= MII_88E1318S_PHY_LED_TCR_INTn_ENABLE;
1436 temp |= MII_88E1318S_PHY_LED_TCR_INT_ACTIVE_LOW;
1437 err = phy_write(phydev, MII_88E1318S_PHY_LED_TCR, temp);
1438 if (err < 0)
1439 return err;
1440
52295666 1441 err = marvell_set_page(phydev, MII_MARVELL_WOL_PAGE);
3871c387
MS
1442 if (err < 0)
1443 return err;
1444
1445 /* Store the device address for the magic packet */
1446 err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD2,
1447 ((phydev->attached_dev->dev_addr[5] << 8) |
1448 phydev->attached_dev->dev_addr[4]));
1449 if (err < 0)
1450 return err;
1451 err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD1,
1452 ((phydev->attached_dev->dev_addr[3] << 8) |
1453 phydev->attached_dev->dev_addr[2]));
1454 if (err < 0)
1455 return err;
1456 err = phy_write(phydev, MII_88E1318S_PHY_MAGIC_PACKET_WORD0,
1457 ((phydev->attached_dev->dev_addr[1] << 8) |
1458 phydev->attached_dev->dev_addr[0]));
1459 if (err < 0)
1460 return err;
1461
1462 /* Clear WOL status and enable magic packet matching */
1463 temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
1464 temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
1465 temp |= MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
1466 err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
1467 if (err < 0)
1468 return err;
1469 } else {
52295666 1470 err = marvell_set_page(phydev, MII_MARVELL_WOL_PAGE);
3871c387
MS
1471 if (err < 0)
1472 return err;
1473
1474 /* Clear WOL status and disable magic packet matching */
1475 temp = phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
1476 temp |= MII_88E1318S_PHY_WOL_CTRL_CLEAR_WOL_STATUS;
1477 temp &= ~MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE;
1478 err = phy_write(phydev, MII_88E1318S_PHY_WOL_CTRL, temp);
1479 if (err < 0)
1480 return err;
1481 }
1482
6427bb2d 1483 err = marvell_set_page(phydev, oldpage);
3871c387
MS
1484 if (err < 0)
1485 return err;
1486
1487 return 0;
1488}
1489
d2fa47d9
AL
1490static int marvell_get_sset_count(struct phy_device *phydev)
1491{
2170fef7
CAC
1492 if (phydev->supported & SUPPORTED_FIBRE)
1493 return ARRAY_SIZE(marvell_hw_stats);
1494 else
1495 return ARRAY_SIZE(marvell_hw_stats) - NB_FIBER_STATS;
d2fa47d9
AL
1496}
1497
1498static void marvell_get_strings(struct phy_device *phydev, u8 *data)
1499{
1500 int i;
1501
1502 for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++) {
1503 memcpy(data + i * ETH_GSTRING_LEN,
1504 marvell_hw_stats[i].string, ETH_GSTRING_LEN);
1505 }
1506}
1507
1508#ifndef UINT64_MAX
8cf8b87b 1509#define UINT64_MAX (u64)(~((u64)0))
d2fa47d9
AL
1510#endif
1511static u64 marvell_get_stat(struct phy_device *phydev, int i)
1512{
1513 struct marvell_hw_stat stat = marvell_hw_stats[i];
1514 struct marvell_priv *priv = phydev->priv;
53798328 1515 int oldpage, val;
321b4d4b 1516 u64 ret;
d2fa47d9 1517
53798328
AL
1518 oldpage = marvell_get_set_page(phydev, stat.page);
1519 if (oldpage < 0)
d2fa47d9
AL
1520 return UINT64_MAX;
1521
1522 val = phy_read(phydev, stat.reg);
1523 if (val < 0) {
321b4d4b 1524 ret = UINT64_MAX;
d2fa47d9
AL
1525 } else {
1526 val = val & ((1 << stat.bits) - 1);
1527 priv->stats[i] += val;
321b4d4b 1528 ret = priv->stats[i];
d2fa47d9
AL
1529 }
1530
6427bb2d 1531 marvell_set_page(phydev, oldpage);
d2fa47d9 1532
321b4d4b 1533 return ret;
d2fa47d9
AL
1534}
1535
1536static void marvell_get_stats(struct phy_device *phydev,
1537 struct ethtool_stats *stats, u64 *data)
1538{
1539 int i;
1540
1541 for (i = 0; i < ARRAY_SIZE(marvell_hw_stats); i++)
1542 data[i] = marvell_get_stat(phydev, i);
1543}
1544
0b04680f
AL
1545#ifdef CONFIG_HWMON
1546static int m88e1121_get_temp(struct phy_device *phydev, long *temp)
1547{
975b388c 1548 int oldpage;
0b04680f
AL
1549 int ret;
1550 int val;
1551
1552 *temp = 0;
1553
1554 mutex_lock(&phydev->lock);
1555
52295666 1556 oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
975b388c
AL
1557 if (oldpage < 0) {
1558 mutex_unlock(&phydev->lock);
1559 return oldpage;
1560 }
1561
0b04680f
AL
1562 /* Enable temperature sensor */
1563 ret = phy_read(phydev, MII_88E1121_MISC_TEST);
1564 if (ret < 0)
1565 goto error;
1566
1567 ret = phy_write(phydev, MII_88E1121_MISC_TEST,
1568 ret | MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
1569 if (ret < 0)
1570 goto error;
1571
1572 /* Wait for temperature to stabilize */
1573 usleep_range(10000, 12000);
1574
1575 val = phy_read(phydev, MII_88E1121_MISC_TEST);
1576 if (val < 0) {
1577 ret = val;
1578 goto error;
1579 }
1580
1581 /* Disable temperature sensor */
1582 ret = phy_write(phydev, MII_88E1121_MISC_TEST,
1583 ret & ~MII_88E1121_MISC_TEST_TEMP_SENSOR_EN);
1584 if (ret < 0)
1585 goto error;
1586
1587 *temp = ((val & MII_88E1121_MISC_TEST_TEMP_MASK) - 5) * 5000;
1588
1589error:
975b388c 1590 marvell_set_page(phydev, oldpage);
0b04680f
AL
1591 mutex_unlock(&phydev->lock);
1592
1593 return ret;
1594}
1595
1596static int m88e1121_hwmon_read(struct device *dev,
1597 enum hwmon_sensor_types type,
1598 u32 attr, int channel, long *temp)
1599{
1600 struct phy_device *phydev = dev_get_drvdata(dev);
1601 int err;
1602
1603 switch (attr) {
1604 case hwmon_temp_input:
1605 err = m88e1121_get_temp(phydev, temp);
1606 break;
1607 default:
1608 return -EOPNOTSUPP;
1609 }
1610
1611 return err;
1612}
1613
1614static umode_t m88e1121_hwmon_is_visible(const void *data,
1615 enum hwmon_sensor_types type,
1616 u32 attr, int channel)
1617{
1618 if (type != hwmon_temp)
1619 return 0;
1620
1621 switch (attr) {
1622 case hwmon_temp_input:
1623 return 0444;
1624 default:
1625 return 0;
1626 }
1627}
1628
1629static u32 m88e1121_hwmon_chip_config[] = {
1630 HWMON_C_REGISTER_TZ,
1631 0
1632};
1633
1634static const struct hwmon_channel_info m88e1121_hwmon_chip = {
1635 .type = hwmon_chip,
1636 .config = m88e1121_hwmon_chip_config,
1637};
1638
1639static u32 m88e1121_hwmon_temp_config[] = {
1640 HWMON_T_INPUT,
1641 0
1642};
1643
1644static const struct hwmon_channel_info m88e1121_hwmon_temp = {
1645 .type = hwmon_temp,
1646 .config = m88e1121_hwmon_temp_config,
1647};
1648
1649static const struct hwmon_channel_info *m88e1121_hwmon_info[] = {
1650 &m88e1121_hwmon_chip,
1651 &m88e1121_hwmon_temp,
1652 NULL
1653};
1654
1655static const struct hwmon_ops m88e1121_hwmon_hwmon_ops = {
1656 .is_visible = m88e1121_hwmon_is_visible,
1657 .read = m88e1121_hwmon_read,
1658};
1659
1660static const struct hwmon_chip_info m88e1121_hwmon_chip_info = {
1661 .ops = &m88e1121_hwmon_hwmon_ops,
1662 .info = m88e1121_hwmon_info,
1663};
1664
1665static int m88e1510_get_temp(struct phy_device *phydev, long *temp)
1666{
975b388c 1667 int oldpage;
0b04680f
AL
1668 int ret;
1669
1670 *temp = 0;
1671
1672 mutex_lock(&phydev->lock);
1673
52295666 1674 oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
975b388c
AL
1675 if (oldpage < 0) {
1676 mutex_unlock(&phydev->lock);
1677 return oldpage;
1678 }
1679
0b04680f
AL
1680 ret = phy_read(phydev, MII_88E1510_TEMP_SENSOR);
1681 if (ret < 0)
1682 goto error;
1683
1684 *temp = ((ret & MII_88E1510_TEMP_SENSOR_MASK) - 25) * 1000;
1685
1686error:
975b388c 1687 marvell_set_page(phydev, oldpage);
0b04680f
AL
1688 mutex_unlock(&phydev->lock);
1689
1690 return ret;
1691}
1692
f0a45816 1693static int m88e1510_get_temp_critical(struct phy_device *phydev, long *temp)
0b04680f 1694{
975b388c 1695 int oldpage;
0b04680f
AL
1696 int ret;
1697
1698 *temp = 0;
1699
1700 mutex_lock(&phydev->lock);
53798328 1701
52295666 1702 oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
975b388c
AL
1703 if (oldpage < 0) {
1704 mutex_unlock(&phydev->lock);
1705 return oldpage;
1706 }
0b04680f 1707
0b04680f
AL
1708 ret = phy_read(phydev, MII_88E1121_MISC_TEST);
1709 if (ret < 0)
1710 goto error;
1711
1712 *temp = (((ret & MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK) >>
1713 MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT) * 5) - 25;
1714 /* convert to mC */
1715 *temp *= 1000;
1716
1717error:
975b388c 1718 marvell_set_page(phydev, oldpage);
0b04680f
AL
1719 mutex_unlock(&phydev->lock);
1720
1721 return ret;
1722}
1723
f0a45816 1724static int m88e1510_set_temp_critical(struct phy_device *phydev, long temp)
0b04680f 1725{
975b388c 1726 int oldpage;
0b04680f
AL
1727 int ret;
1728
1729 mutex_lock(&phydev->lock);
1730
52295666 1731 oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
975b388c
AL
1732 if (oldpage < 0) {
1733 mutex_unlock(&phydev->lock);
1734 return oldpage;
1735 }
1736
0b04680f
AL
1737 ret = phy_read(phydev, MII_88E1121_MISC_TEST);
1738 if (ret < 0)
1739 goto error;
1740
1741 temp = temp / 1000;
1742 temp = clamp_val(DIV_ROUND_CLOSEST(temp, 5) + 5, 0, 0x1f);
1743 ret = phy_write(phydev, MII_88E1121_MISC_TEST,
1744 (ret & ~MII_88E1510_MISC_TEST_TEMP_THRESHOLD_MASK) |
1745 (temp << MII_88E1510_MISC_TEST_TEMP_THRESHOLD_SHIFT));
1746
1747error:
975b388c 1748 marvell_set_page(phydev, oldpage);
0b04680f
AL
1749 mutex_unlock(&phydev->lock);
1750
1751 return ret;
1752}
1753
f0a45816 1754static int m88e1510_get_temp_alarm(struct phy_device *phydev, long *alarm)
0b04680f 1755{
975b388c 1756 int oldpage;
0b04680f
AL
1757 int ret;
1758
1759 *alarm = false;
1760
1761 mutex_lock(&phydev->lock);
1762
52295666 1763 oldpage = marvell_get_set_page(phydev, MII_MARVELL_MISC_TEST_PAGE);
975b388c
AL
1764 if (oldpage < 0) {
1765 mutex_unlock(&phydev->lock);
1766 return oldpage;
1767 }
1768
0b04680f
AL
1769 ret = phy_read(phydev, MII_88E1121_MISC_TEST);
1770 if (ret < 0)
1771 goto error;
1772 *alarm = !!(ret & MII_88E1510_MISC_TEST_TEMP_IRQ);
1773
1774error:
975b388c 1775 marvell_set_page(phydev, oldpage);
0b04680f
AL
1776 mutex_unlock(&phydev->lock);
1777
1778 return ret;
1779}
1780
1781static int m88e1510_hwmon_read(struct device *dev,
1782 enum hwmon_sensor_types type,
1783 u32 attr, int channel, long *temp)
1784{
1785 struct phy_device *phydev = dev_get_drvdata(dev);
1786 int err;
1787
1788 switch (attr) {
1789 case hwmon_temp_input:
1790 err = m88e1510_get_temp(phydev, temp);
1791 break;
1792 case hwmon_temp_crit:
1793 err = m88e1510_get_temp_critical(phydev, temp);
1794 break;
1795 case hwmon_temp_max_alarm:
1796 err = m88e1510_get_temp_alarm(phydev, temp);
1797 break;
1798 default:
1799 return -EOPNOTSUPP;
1800 }
1801
1802 return err;
1803}
1804
1805static int m88e1510_hwmon_write(struct device *dev,
1806 enum hwmon_sensor_types type,
1807 u32 attr, int channel, long temp)
1808{
1809 struct phy_device *phydev = dev_get_drvdata(dev);
1810 int err;
1811
1812 switch (attr) {
1813 case hwmon_temp_crit:
1814 err = m88e1510_set_temp_critical(phydev, temp);
1815 break;
1816 default:
1817 return -EOPNOTSUPP;
1818 }
1819 return err;
1820}
1821
1822static umode_t m88e1510_hwmon_is_visible(const void *data,
1823 enum hwmon_sensor_types type,
1824 u32 attr, int channel)
1825{
1826 if (type != hwmon_temp)
1827 return 0;
1828
1829 switch (attr) {
1830 case hwmon_temp_input:
1831 case hwmon_temp_max_alarm:
1832 return 0444;
1833 case hwmon_temp_crit:
1834 return 0644;
1835 default:
1836 return 0;
1837 }
1838}
1839
1840static u32 m88e1510_hwmon_temp_config[] = {
1841 HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_MAX_ALARM,
1842 0
1843};
1844
1845static const struct hwmon_channel_info m88e1510_hwmon_temp = {
1846 .type = hwmon_temp,
1847 .config = m88e1510_hwmon_temp_config,
1848};
1849
1850static const struct hwmon_channel_info *m88e1510_hwmon_info[] = {
1851 &m88e1121_hwmon_chip,
1852 &m88e1510_hwmon_temp,
1853 NULL
1854};
1855
1856static const struct hwmon_ops m88e1510_hwmon_hwmon_ops = {
1857 .is_visible = m88e1510_hwmon_is_visible,
1858 .read = m88e1510_hwmon_read,
1859 .write = m88e1510_hwmon_write,
1860};
1861
1862static const struct hwmon_chip_info m88e1510_hwmon_chip_info = {
1863 .ops = &m88e1510_hwmon_hwmon_ops,
1864 .info = m88e1510_hwmon_info,
1865};
1866
1867static int marvell_hwmon_name(struct phy_device *phydev)
1868{
1869 struct marvell_priv *priv = phydev->priv;
1870 struct device *dev = &phydev->mdio.dev;
1871 const char *devname = dev_name(dev);
1872 size_t len = strlen(devname);
1873 int i, j;
1874
1875 priv->hwmon_name = devm_kzalloc(dev, len, GFP_KERNEL);
1876 if (!priv->hwmon_name)
1877 return -ENOMEM;
1878
1879 for (i = j = 0; i < len && devname[i]; i++) {
1880 if (isalnum(devname[i]))
1881 priv->hwmon_name[j++] = devname[i];
1882 }
1883
1884 return 0;
1885}
1886
1887static int marvell_hwmon_probe(struct phy_device *phydev,
1888 const struct hwmon_chip_info *chip)
1889{
1890 struct marvell_priv *priv = phydev->priv;
1891 struct device *dev = &phydev->mdio.dev;
1892 int err;
1893
1894 err = marvell_hwmon_name(phydev);
1895 if (err)
1896 return err;
1897
1898 priv->hwmon_dev = devm_hwmon_device_register_with_info(
1899 dev, priv->hwmon_name, phydev, chip, NULL);
1900
1901 return PTR_ERR_OR_ZERO(priv->hwmon_dev);
1902}
1903
1904static int m88e1121_hwmon_probe(struct phy_device *phydev)
1905{
1906 return marvell_hwmon_probe(phydev, &m88e1121_hwmon_chip_info);
1907}
1908
1909static int m88e1510_hwmon_probe(struct phy_device *phydev)
1910{
1911 return marvell_hwmon_probe(phydev, &m88e1510_hwmon_chip_info);
1912}
1913#else
1914static int m88e1121_hwmon_probe(struct phy_device *phydev)
1915{
1916 return 0;
1917}
1918
1919static int m88e1510_hwmon_probe(struct phy_device *phydev)
1920{
1921 return 0;
1922}
1923#endif
1924
d2fa47d9
AL
1925static int marvell_probe(struct phy_device *phydev)
1926{
1927 struct marvell_priv *priv;
1928
e5a03bfd 1929 priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
d2fa47d9
AL
1930 if (!priv)
1931 return -ENOMEM;
1932
1933 phydev->priv = priv;
1934
1935 return 0;
1936}
1937
0b04680f
AL
1938static int m88e1121_probe(struct phy_device *phydev)
1939{
1940 int err;
1941
1942 err = marvell_probe(phydev);
1943 if (err)
1944 return err;
1945
1946 return m88e1121_hwmon_probe(phydev);
1947}
1948
1949static int m88e1510_probe(struct phy_device *phydev)
1950{
1951 int err;
1952
1953 err = marvell_probe(phydev);
1954 if (err)
1955 return err;
1956
1957 return m88e1510_hwmon_probe(phydev);
1958}
1959
e5479239
OJ
1960static struct phy_driver marvell_drivers[] = {
1961 {
2f495c39
BH
1962 .phy_id = MARVELL_PHY_ID_88E1101,
1963 .phy_id_mask = MARVELL_PHY_ID_MASK,
e5479239
OJ
1964 .name = "Marvell 88E1101",
1965 .features = PHY_GBIT_FEATURES,
1966 .flags = PHY_HAS_INTERRUPT,
18702414 1967 .probe = marvell_probe,
79be1a1c 1968 .config_init = &marvell_config_init,
f2899788 1969 .config_aneg = &m88e1101_config_aneg,
e5479239
OJ
1970 .read_status = &genphy_read_status,
1971 .ack_interrupt = &marvell_ack_interrupt,
1972 .config_intr = &marvell_config_intr,
0898b448
SH
1973 .resume = &genphy_resume,
1974 .suspend = &genphy_suspend,
d2fa47d9
AL
1975 .get_sset_count = marvell_get_sset_count,
1976 .get_strings = marvell_get_strings,
1977 .get_stats = marvell_get_stats,
e5479239 1978 },
85cfb534 1979 {
2f495c39
BH
1980 .phy_id = MARVELL_PHY_ID_88E1112,
1981 .phy_id_mask = MARVELL_PHY_ID_MASK,
85cfb534
OJ
1982 .name = "Marvell 88E1112",
1983 .features = PHY_GBIT_FEATURES,
1984 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 1985 .probe = marvell_probe,
85cfb534
OJ
1986 .config_init = &m88e1111_config_init,
1987 .config_aneg = &marvell_config_aneg,
1988 .read_status = &genphy_read_status,
1989 .ack_interrupt = &marvell_ack_interrupt,
1990 .config_intr = &marvell_config_intr,
0898b448
SH
1991 .resume = &genphy_resume,
1992 .suspend = &genphy_suspend,
d2fa47d9
AL
1993 .get_sset_count = marvell_get_sset_count,
1994 .get_strings = marvell_get_strings,
1995 .get_stats = marvell_get_stats,
85cfb534 1996 },
e5479239 1997 {
2f495c39
BH
1998 .phy_id = MARVELL_PHY_ID_88E1111,
1999 .phy_id_mask = MARVELL_PHY_ID_MASK,
e5479239
OJ
2000 .name = "Marvell 88E1111",
2001 .features = PHY_GBIT_FEATURES,
2002 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2003 .probe = marvell_probe,
e5479239 2004 .config_init = &m88e1111_config_init,
3ec0a0f1 2005 .config_aneg = &m88e1111_config_aneg,
be937f1f 2006 .read_status = &marvell_read_status,
e5479239
OJ
2007 .ack_interrupt = &marvell_ack_interrupt,
2008 .config_intr = &marvell_config_intr,
0898b448
SH
2009 .resume = &genphy_resume,
2010 .suspend = &genphy_suspend,
d2fa47d9
AL
2011 .get_sset_count = marvell_get_sset_count,
2012 .get_strings = marvell_get_strings,
2013 .get_stats = marvell_get_stats,
e5479239 2014 },
605f196e 2015 {
2f495c39
BH
2016 .phy_id = MARVELL_PHY_ID_88E1118,
2017 .phy_id_mask = MARVELL_PHY_ID_MASK,
605f196e
RM
2018 .name = "Marvell 88E1118",
2019 .features = PHY_GBIT_FEATURES,
2020 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2021 .probe = marvell_probe,
605f196e
RM
2022 .config_init = &m88e1118_config_init,
2023 .config_aneg = &m88e1118_config_aneg,
2024 .read_status = &genphy_read_status,
2025 .ack_interrupt = &marvell_ack_interrupt,
2026 .config_intr = &marvell_config_intr,
0898b448
SH
2027 .resume = &genphy_resume,
2028 .suspend = &genphy_suspend,
d2fa47d9
AL
2029 .get_sset_count = marvell_get_sset_count,
2030 .get_strings = marvell_get_strings,
2031 .get_stats = marvell_get_stats,
605f196e 2032 },
140bc929 2033 {
2f495c39
BH
2034 .phy_id = MARVELL_PHY_ID_88E1121R,
2035 .phy_id_mask = MARVELL_PHY_ID_MASK,
140bc929
SP
2036 .name = "Marvell 88E1121R",
2037 .features = PHY_GBIT_FEATURES,
2038 .flags = PHY_HAS_INTERRUPT,
18702414 2039 .probe = &m88e1121_probe,
fdecf36f 2040 .config_init = &m88e1121_config_init,
140bc929
SP
2041 .config_aneg = &m88e1121_config_aneg,
2042 .read_status = &marvell_read_status,
2043 .ack_interrupt = &marvell_ack_interrupt,
2044 .config_intr = &marvell_config_intr,
dcd07be3 2045 .did_interrupt = &m88e1121_did_interrupt,
0898b448
SH
2046 .resume = &genphy_resume,
2047 .suspend = &genphy_suspend,
d2fa47d9
AL
2048 .get_sset_count = marvell_get_sset_count,
2049 .get_strings = marvell_get_strings,
2050 .get_stats = marvell_get_stats,
140bc929 2051 },
3ff1c259 2052 {
337ac9d5 2053 .phy_id = MARVELL_PHY_ID_88E1318S,
6ba74014 2054 .phy_id_mask = MARVELL_PHY_ID_MASK,
337ac9d5 2055 .name = "Marvell 88E1318S",
3ff1c259
CC
2056 .features = PHY_GBIT_FEATURES,
2057 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2058 .probe = marvell_probe,
fdecf36f 2059 .config_init = &m88e1121_config_init,
337ac9d5 2060 .config_aneg = &m88e1318_config_aneg,
3ff1c259
CC
2061 .read_status = &marvell_read_status,
2062 .ack_interrupt = &marvell_ack_interrupt,
2063 .config_intr = &marvell_config_intr,
2064 .did_interrupt = &m88e1121_did_interrupt,
3871c387
MS
2065 .get_wol = &m88e1318_get_wol,
2066 .set_wol = &m88e1318_set_wol,
0898b448
SH
2067 .resume = &genphy_resume,
2068 .suspend = &genphy_suspend,
d2fa47d9
AL
2069 .get_sset_count = marvell_get_sset_count,
2070 .get_strings = marvell_get_strings,
2071 .get_stats = marvell_get_stats,
3ff1c259 2072 },
e5479239 2073 {
2f495c39
BH
2074 .phy_id = MARVELL_PHY_ID_88E1145,
2075 .phy_id_mask = MARVELL_PHY_ID_MASK,
e5479239
OJ
2076 .name = "Marvell 88E1145",
2077 .features = PHY_GBIT_FEATURES,
2078 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2079 .probe = marvell_probe,
e5479239 2080 .config_init = &m88e1145_config_init,
5e255d68 2081 .config_aneg = &m88e1101_config_aneg,
e5479239
OJ
2082 .read_status = &genphy_read_status,
2083 .ack_interrupt = &marvell_ack_interrupt,
2084 .config_intr = &marvell_config_intr,
0898b448
SH
2085 .resume = &genphy_resume,
2086 .suspend = &genphy_suspend,
d2fa47d9
AL
2087 .get_sset_count = marvell_get_sset_count,
2088 .get_strings = marvell_get_strings,
2089 .get_stats = marvell_get_stats,
ac8c635a 2090 },
90600732
DD
2091 {
2092 .phy_id = MARVELL_PHY_ID_88E1149R,
2093 .phy_id_mask = MARVELL_PHY_ID_MASK,
2094 .name = "Marvell 88E1149R",
2095 .features = PHY_GBIT_FEATURES,
2096 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2097 .probe = marvell_probe,
90600732
DD
2098 .config_init = &m88e1149_config_init,
2099 .config_aneg = &m88e1118_config_aneg,
2100 .read_status = &genphy_read_status,
2101 .ack_interrupt = &marvell_ack_interrupt,
2102 .config_intr = &marvell_config_intr,
0898b448
SH
2103 .resume = &genphy_resume,
2104 .suspend = &genphy_suspend,
d2fa47d9
AL
2105 .get_sset_count = marvell_get_sset_count,
2106 .get_strings = marvell_get_strings,
2107 .get_stats = marvell_get_stats,
90600732 2108 },
ac8c635a 2109 {
2f495c39
BH
2110 .phy_id = MARVELL_PHY_ID_88E1240,
2111 .phy_id_mask = MARVELL_PHY_ID_MASK,
ac8c635a
OJ
2112 .name = "Marvell 88E1240",
2113 .features = PHY_GBIT_FEATURES,
2114 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2115 .probe = marvell_probe,
ac8c635a
OJ
2116 .config_init = &m88e1111_config_init,
2117 .config_aneg = &marvell_config_aneg,
2118 .read_status = &genphy_read_status,
2119 .ack_interrupt = &marvell_ack_interrupt,
2120 .config_intr = &marvell_config_intr,
0898b448
SH
2121 .resume = &genphy_resume,
2122 .suspend = &genphy_suspend,
d2fa47d9
AL
2123 .get_sset_count = marvell_get_sset_count,
2124 .get_strings = marvell_get_strings,
2125 .get_stats = marvell_get_stats,
ac8c635a 2126 },
3da09a51
MS
2127 {
2128 .phy_id = MARVELL_PHY_ID_88E1116R,
2129 .phy_id_mask = MARVELL_PHY_ID_MASK,
2130 .name = "Marvell 88E1116R",
2131 .features = PHY_GBIT_FEATURES,
2132 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2133 .probe = marvell_probe,
3da09a51
MS
2134 .config_init = &m88e1116r_config_init,
2135 .config_aneg = &genphy_config_aneg,
2136 .read_status = &genphy_read_status,
2137 .ack_interrupt = &marvell_ack_interrupt,
2138 .config_intr = &marvell_config_intr,
0898b448
SH
2139 .resume = &genphy_resume,
2140 .suspend = &genphy_suspend,
d2fa47d9
AL
2141 .get_sset_count = marvell_get_sset_count,
2142 .get_strings = marvell_get_strings,
2143 .get_stats = marvell_get_stats,
3da09a51 2144 },
10e24caa
MS
2145 {
2146 .phy_id = MARVELL_PHY_ID_88E1510,
2147 .phy_id_mask = MARVELL_PHY_ID_MASK,
2148 .name = "Marvell 88E1510",
6cfb3bcc 2149 .features = PHY_GBIT_FEATURES | SUPPORTED_FIBRE,
18702414 2150 .flags = PHY_HAS_INTERRUPT,
0b04680f 2151 .probe = &m88e1510_probe,
930b37ee 2152 .config_init = &m88e1510_config_init,
10e24caa
MS
2153 .config_aneg = &m88e1510_config_aneg,
2154 .read_status = &marvell_read_status,
2155 .ack_interrupt = &marvell_ack_interrupt,
2156 .config_intr = &marvell_config_intr,
2157 .did_interrupt = &m88e1121_did_interrupt,
f39aac7e
JH
2158 .get_wol = &m88e1318_get_wol,
2159 .set_wol = &m88e1318_set_wol,
3758be3d
CAC
2160 .resume = &marvell_resume,
2161 .suspend = &marvell_suspend,
d2fa47d9
AL
2162 .get_sset_count = marvell_get_sset_count,
2163 .get_strings = marvell_get_strings,
2164 .get_stats = marvell_get_stats,
f0f9b4ed 2165 .set_loopback = genphy_loopback,
10e24caa 2166 },
819ec8e1
AL
2167 {
2168 .phy_id = MARVELL_PHY_ID_88E1540,
2169 .phy_id_mask = MARVELL_PHY_ID_MASK,
2170 .name = "Marvell 88E1540",
2171 .features = PHY_GBIT_FEATURES,
2172 .flags = PHY_HAS_INTERRUPT,
18702414 2173 .probe = m88e1510_probe,
79be1a1c 2174 .config_init = &marvell_config_init,
819ec8e1
AL
2175 .config_aneg = &m88e1510_config_aneg,
2176 .read_status = &marvell_read_status,
2177 .ack_interrupt = &marvell_ack_interrupt,
2178 .config_intr = &marvell_config_intr,
2179 .did_interrupt = &m88e1121_did_interrupt,
2180 .resume = &genphy_resume,
2181 .suspend = &genphy_suspend,
d2fa47d9
AL
2182 .get_sset_count = marvell_get_sset_count,
2183 .get_strings = marvell_get_strings,
2184 .get_stats = marvell_get_stats,
819ec8e1 2185 },
60f06fde
AL
2186 {
2187 .phy_id = MARVELL_PHY_ID_88E1545,
2188 .phy_id_mask = MARVELL_PHY_ID_MASK,
2189 .name = "Marvell 88E1545",
2190 .probe = m88e1510_probe,
60f06fde
AL
2191 .features = PHY_GBIT_FEATURES,
2192 .flags = PHY_HAS_INTERRUPT,
2193 .config_init = &marvell_config_init,
2194 .config_aneg = &m88e1510_config_aneg,
2195 .read_status = &marvell_read_status,
2196 .ack_interrupt = &marvell_ack_interrupt,
2197 .config_intr = &marvell_config_intr,
2198 .did_interrupt = &m88e1121_did_interrupt,
2199 .resume = &genphy_resume,
2200 .suspend = &genphy_suspend,
2201 .get_sset_count = marvell_get_sset_count,
2202 .get_strings = marvell_get_strings,
2203 .get_stats = marvell_get_stats,
2204 },
6b358aed
SH
2205 {
2206 .phy_id = MARVELL_PHY_ID_88E3016,
2207 .phy_id_mask = MARVELL_PHY_ID_MASK,
2208 .name = "Marvell 88E3016",
2209 .features = PHY_BASIC_FEATURES,
2210 .flags = PHY_HAS_INTERRUPT,
d2fa47d9 2211 .probe = marvell_probe,
6b358aed
SH
2212 .config_aneg = &genphy_config_aneg,
2213 .config_init = &m88e3016_config_init,
2214 .aneg_done = &marvell_aneg_done,
2215 .read_status = &marvell_read_status,
2216 .ack_interrupt = &marvell_ack_interrupt,
2217 .config_intr = &marvell_config_intr,
2218 .did_interrupt = &m88e1121_did_interrupt,
2219 .resume = &genphy_resume,
2220 .suspend = &genphy_suspend,
d2fa47d9
AL
2221 .get_sset_count = marvell_get_sset_count,
2222 .get_strings = marvell_get_strings,
2223 .get_stats = marvell_get_stats,
6b358aed 2224 },
e4cf8a38
AL
2225 {
2226 .phy_id = MARVELL_PHY_ID_88E6390,
2227 .phy_id_mask = MARVELL_PHY_ID_MASK,
2228 .name = "Marvell 88E6390",
2229 .features = PHY_GBIT_FEATURES,
2230 .flags = PHY_HAS_INTERRUPT,
2231 .probe = m88e1510_probe,
2232 .config_init = &marvell_config_init,
2233 .config_aneg = &m88e1510_config_aneg,
2234 .read_status = &marvell_read_status,
2235 .ack_interrupt = &marvell_ack_interrupt,
2236 .config_intr = &marvell_config_intr,
2237 .did_interrupt = &m88e1121_did_interrupt,
2238 .resume = &genphy_resume,
2239 .suspend = &genphy_suspend,
2240 .get_sset_count = marvell_get_sset_count,
2241 .get_strings = marvell_get_strings,
2242 .get_stats = marvell_get_stats,
2243 },
00db8189
AF
2244};
2245
50fd7150 2246module_phy_driver(marvell_drivers);
4e4f10f6 2247
cf93c945 2248static struct mdio_device_id __maybe_unused marvell_tbl[] = {
f5e1cabf
MS
2249 { MARVELL_PHY_ID_88E1101, MARVELL_PHY_ID_MASK },
2250 { MARVELL_PHY_ID_88E1112, MARVELL_PHY_ID_MASK },
2251 { MARVELL_PHY_ID_88E1111, MARVELL_PHY_ID_MASK },
2252 { MARVELL_PHY_ID_88E1118, MARVELL_PHY_ID_MASK },
2253 { MARVELL_PHY_ID_88E1121R, MARVELL_PHY_ID_MASK },
2254 { MARVELL_PHY_ID_88E1145, MARVELL_PHY_ID_MASK },
2255 { MARVELL_PHY_ID_88E1149R, MARVELL_PHY_ID_MASK },
2256 { MARVELL_PHY_ID_88E1240, MARVELL_PHY_ID_MASK },
2257 { MARVELL_PHY_ID_88E1318S, MARVELL_PHY_ID_MASK },
3da09a51 2258 { MARVELL_PHY_ID_88E1116R, MARVELL_PHY_ID_MASK },
10e24caa 2259 { MARVELL_PHY_ID_88E1510, MARVELL_PHY_ID_MASK },
819ec8e1 2260 { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK },
60f06fde 2261 { MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK },
6b358aed 2262 { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
e4cf8a38 2263 { MARVELL_PHY_ID_88E6390, MARVELL_PHY_ID_MASK },
4e4f10f6
DW
2264 { }
2265};
2266
2267MODULE_DEVICE_TABLE(mdio, marvell_tbl);