hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/net/phy/marvell.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * drivers/net/phy/marvell.c
34 *
....@@ -8,12 +9,6 @@
89 * Copyright (c) 2004 Freescale Semiconductor, Inc.
910 *
1011 * Copyright (c) 2013 Michael Stapelberg <michael@stapelberg.de>
11
- *
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
- *
1712 */
1813 #include <linux/kernel.h>
1914 #include <linux/string.h>
....@@ -32,8 +27,10 @@
3227 #include <linux/module.h>
3328 #include <linux/mii.h>
3429 #include <linux/ethtool.h>
30
+#include <linux/ethtool_netlink.h>
3531 #include <linux/phy.h>
3632 #include <linux/marvell_phy.h>
33
+#include <linux/bitfield.h>
3734 #include <linux/of.h>
3835
3936 #include <linux/io.h>
....@@ -45,7 +42,9 @@
4542 #define MII_MARVELL_FIBER_PAGE 0x01
4643 #define MII_MARVELL_MSCR_PAGE 0x02
4744 #define MII_MARVELL_LED_PAGE 0x03
45
+#define MII_MARVELL_VCT5_PAGE 0x05
4846 #define MII_MARVELL_MISC_TEST_PAGE 0x06
47
+#define MII_MARVELL_VCT7_PAGE 0x07
4948 #define MII_MARVELL_WOL_PAGE 0x11
5049
5150 #define MII_M1011_IEVENT 0x13
....@@ -57,16 +56,22 @@
5756
5857 #define MII_M1011_PHY_SCR 0x10
5958 #define MII_M1011_PHY_SCR_DOWNSHIFT_EN BIT(11)
60
-#define MII_M1011_PHY_SCR_DOWNSHIFT_SHIFT 12
61
-#define MII_M1011_PHY_SRC_DOWNSHIFT_MASK 0x7800
59
+#define MII_M1011_PHY_SCR_DOWNSHIFT_MASK GENMASK(14, 12)
60
+#define MII_M1011_PHY_SCR_DOWNSHIFT_MAX 8
6261 #define MII_M1011_PHY_SCR_MDI (0x0 << 5)
6362 #define MII_M1011_PHY_SCR_MDI_X (0x1 << 5)
6463 #define MII_M1011_PHY_SCR_AUTO_CROSS (0x3 << 5)
64
+
65
+#define MII_M1011_PHY_SSR 0x11
66
+#define MII_M1011_PHY_SSR_DOWNSHIFT BIT(5)
6567
6668 #define MII_M1111_PHY_LED_CONTROL 0x18
6769 #define MII_M1111_PHY_LED_DIRECT 0x4100
6870 #define MII_M1111_PHY_LED_COMBINE 0x411c
6971 #define MII_M1111_PHY_EXT_CR 0x14
72
+#define MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK GENMASK(11, 9)
73
+#define MII_M1111_PHY_EXT_CR_DOWNSHIFT_MAX 8
74
+#define MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN BIT(8)
7075 #define MII_M1111_RGMII_RX_DELAY BIT(7)
7176 #define MII_M1111_RGMII_TX_DELAY BIT(1)
7277 #define MII_M1111_PHY_EXT_SR 0x1b
....@@ -95,6 +100,14 @@
95100
96101 #define MII_88E1510_TEMP_SENSOR 0x1b
97102 #define MII_88E1510_TEMP_SENSOR_MASK 0xff
103
+
104
+#define MII_88E1540_COPPER_CTRL3 0x1a
105
+#define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK GENMASK(11, 10)
106
+#define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_00MS 0
107
+#define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_10MS 1
108
+#define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_20MS 2
109
+#define MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_40MS 3
110
+#define MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN BIT(9)
98111
99112 #define MII_88E6390_MISC_TEST 0x1b
100113 #define MII_88E6390_MISC_TEST_SAMPLE_1S 0
....@@ -133,6 +146,7 @@
133146 #define MII_PHY_LED_CTRL 16
134147 #define MII_88E1121_PHY_LED_DEF 0x0030
135148 #define MII_88E1510_PHY_LED_DEF 0x1177
149
+#define MII_88E1510_PHY_LED0_LINK_LED1_ACTIVE 0x1040
136150
137151 #define MII_M1011_PHY_STATUS 0x11
138152 #define MII_M1011_PHY_STATUS_1000 0x8000
....@@ -151,19 +165,93 @@
151165 #define MII_88E1510_GEN_CTRL_REG_1_MODE_SGMII 0x1 /* SGMII to copper */
152166 #define MII_88E1510_GEN_CTRL_REG_1_RESET 0x8000 /* Soft reset */
153167
154
-#define LPA_FIBER_1000HALF 0x40
155
-#define LPA_FIBER_1000FULL 0x20
168
+#define MII_VCT5_TX_RX_MDI0_COUPLING 0x10
169
+#define MII_VCT5_TX_RX_MDI1_COUPLING 0x11
170
+#define MII_VCT5_TX_RX_MDI2_COUPLING 0x12
171
+#define MII_VCT5_TX_RX_MDI3_COUPLING 0x13
172
+#define MII_VCT5_TX_RX_AMPLITUDE_MASK 0x7f00
173
+#define MII_VCT5_TX_RX_AMPLITUDE_SHIFT 8
174
+#define MII_VCT5_TX_RX_COUPLING_POSITIVE_REFLECTION BIT(15)
175
+
176
+#define MII_VCT5_CTRL 0x17
177
+#define MII_VCT5_CTRL_ENABLE BIT(15)
178
+#define MII_VCT5_CTRL_COMPLETE BIT(14)
179
+#define MII_VCT5_CTRL_TX_SAME_CHANNEL (0x0 << 11)
180
+#define MII_VCT5_CTRL_TX0_CHANNEL (0x4 << 11)
181
+#define MII_VCT5_CTRL_TX1_CHANNEL (0x5 << 11)
182
+#define MII_VCT5_CTRL_TX2_CHANNEL (0x6 << 11)
183
+#define MII_VCT5_CTRL_TX3_CHANNEL (0x7 << 11)
184
+#define MII_VCT5_CTRL_SAMPLES_2 (0x0 << 8)
185
+#define MII_VCT5_CTRL_SAMPLES_4 (0x1 << 8)
186
+#define MII_VCT5_CTRL_SAMPLES_8 (0x2 << 8)
187
+#define MII_VCT5_CTRL_SAMPLES_16 (0x3 << 8)
188
+#define MII_VCT5_CTRL_SAMPLES_32 (0x4 << 8)
189
+#define MII_VCT5_CTRL_SAMPLES_64 (0x5 << 8)
190
+#define MII_VCT5_CTRL_SAMPLES_128 (0x6 << 8)
191
+#define MII_VCT5_CTRL_SAMPLES_DEFAULT (0x6 << 8)
192
+#define MII_VCT5_CTRL_SAMPLES_256 (0x7 << 8)
193
+#define MII_VCT5_CTRL_SAMPLES_SHIFT 8
194
+#define MII_VCT5_CTRL_MODE_MAXIMUM_PEEK (0x0 << 6)
195
+#define MII_VCT5_CTRL_MODE_FIRST_LAST_PEEK (0x1 << 6)
196
+#define MII_VCT5_CTRL_MODE_OFFSET (0x2 << 6)
197
+#define MII_VCT5_CTRL_SAMPLE_POINT (0x3 << 6)
198
+#define MII_VCT5_CTRL_PEEK_HYST_DEFAULT 3
199
+
200
+#define MII_VCT5_SAMPLE_POINT_DISTANCE 0x18
201
+#define MII_VCT5_SAMPLE_POINT_DISTANCE_MAX 511
202
+#define MII_VCT5_TX_PULSE_CTRL 0x1c
203
+#define MII_VCT5_TX_PULSE_CTRL_DONT_WAIT_LINK_DOWN BIT(12)
204
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_128nS (0x0 << 10)
205
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_96nS (0x1 << 10)
206
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_64nS (0x2 << 10)
207
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_32nS (0x3 << 10)
208
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_SHIFT 10
209
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_1000mV (0x0 << 8)
210
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_750mV (0x1 << 8)
211
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_500mV (0x2 << 8)
212
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_250mV (0x3 << 8)
213
+#define MII_VCT5_TX_PULSE_CTRL_PULSE_AMPLITUDE_SHIFT 8
214
+#define MII_VCT5_TX_PULSE_CTRL_MAX_AMP BIT(7)
215
+#define MII_VCT5_TX_PULSE_CTRL_GT_140m_46_86mV (0x6 << 0)
216
+
217
+/* For TDR measurements less than 11 meters, a short pulse should be
218
+ * used.
219
+ */
220
+#define TDR_SHORT_CABLE_LENGTH 11
221
+
222
+#define MII_VCT7_PAIR_0_DISTANCE 0x10
223
+#define MII_VCT7_PAIR_1_DISTANCE 0x11
224
+#define MII_VCT7_PAIR_2_DISTANCE 0x12
225
+#define MII_VCT7_PAIR_3_DISTANCE 0x13
226
+
227
+#define MII_VCT7_RESULTS 0x14
228
+#define MII_VCT7_RESULTS_PAIR3_MASK 0xf000
229
+#define MII_VCT7_RESULTS_PAIR2_MASK 0x0f00
230
+#define MII_VCT7_RESULTS_PAIR1_MASK 0x00f0
231
+#define MII_VCT7_RESULTS_PAIR0_MASK 0x000f
232
+#define MII_VCT7_RESULTS_PAIR3_SHIFT 12
233
+#define MII_VCT7_RESULTS_PAIR2_SHIFT 8
234
+#define MII_VCT7_RESULTS_PAIR1_SHIFT 4
235
+#define MII_VCT7_RESULTS_PAIR0_SHIFT 0
236
+#define MII_VCT7_RESULTS_INVALID 0
237
+#define MII_VCT7_RESULTS_OK 1
238
+#define MII_VCT7_RESULTS_OPEN 2
239
+#define MII_VCT7_RESULTS_SAME_SHORT 3
240
+#define MII_VCT7_RESULTS_CROSS_SHORT 4
241
+#define MII_VCT7_RESULTS_BUSY 9
242
+
243
+#define MII_VCT7_CTRL 0x15
244
+#define MII_VCT7_CTRL_RUN_NOW BIT(15)
245
+#define MII_VCT7_CTRL_RUN_ANEG BIT(14)
246
+#define MII_VCT7_CTRL_DISABLE_CROSS BIT(13)
247
+#define MII_VCT7_CTRL_RUN_AFTER_BREAK_LINK BIT(12)
248
+#define MII_VCT7_CTRL_IN_PROGRESS BIT(11)
249
+#define MII_VCT7_CTRL_METERS BIT(10)
250
+#define MII_VCT7_CTRL_CENTIMETERS 0
156251
157252 #define LPA_PAUSE_FIBER 0x180
158253 #define LPA_PAUSE_ASYM_FIBER 0x100
159254
160
-#define ADVERTISE_FIBER_1000HALF 0x40
161
-#define ADVERTISE_FIBER_1000FULL 0x20
162
-
163
-#define ADVERTISE_PAUSE_FIBER 0x180
164
-#define ADVERTISE_PAUSE_ASYM_FIBER 0x100
165
-
166
-#define REGISTER_LINK_STATUS 0x400
167255 #define NB_FIBER_STATS 1
168256
169257 MODULE_DESCRIPTION("Marvell PHY driver");
....@@ -187,6 +275,11 @@
187275 u64 stats[ARRAY_SIZE(marvell_hw_stats)];
188276 char *hwmon_name;
189277 struct device *hwmon_dev;
278
+ bool cable_test_tdr;
279
+ u32 first;
280
+ u32 last;
281
+ u32 step;
282
+ s8 pair;
190283 };
191284
192285 static int marvell_read_page(struct phy_device *phydev)
....@@ -265,33 +358,19 @@
265358 return err;
266359 }
267360
268
- return 0;
269
-}
270
-
271
-static int marvell_set_downshift(struct phy_device *phydev, bool enable,
272
- u8 retries)
273
-{
274
- int reg;
275
-
276
- reg = phy_read(phydev, MII_M1011_PHY_SCR);
277
- if (reg < 0)
278
- return reg;
279
-
280
- reg &= MII_M1011_PHY_SRC_DOWNSHIFT_MASK;
281
- reg |= ((retries - 1) << MII_M1011_PHY_SCR_DOWNSHIFT_SHIFT);
282
- if (enable)
283
- reg |= MII_M1011_PHY_SCR_DOWNSHIFT_EN;
284
-
285
- return phy_write(phydev, MII_M1011_PHY_SCR, reg);
361
+ return val != reg;
286362 }
287363
288364 static int marvell_config_aneg(struct phy_device *phydev)
289365 {
366
+ int changed = 0;
290367 int err;
291368
292369 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
293370 if (err < 0)
294371 return err;
372
+
373
+ changed = err;
295374
296375 err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
297376 MII_M1111_PHY_LED_DIRECT);
....@@ -302,7 +381,7 @@
302381 if (err < 0)
303382 return err;
304383
305
- if (phydev->autoneg != AUTONEG_ENABLE) {
384
+ if (phydev->autoneg != AUTONEG_ENABLE || changed) {
306385 /* A write to speed/duplex bits (that is performed by
307386 * genphy_config_aneg() call above) must be followed by
308387 * a software reset. Otherwise, the write has no effect.
....@@ -350,43 +429,7 @@
350429 return marvell_config_aneg(phydev);
351430 }
352431
353
-static int m88e1111_config_aneg(struct phy_device *phydev)
354
-{
355
- int err;
356
-
357
- /* The Marvell PHY has an errata which requires
358
- * that certain registers get written in order
359
- * to restart autonegotiation
360
- */
361
- err = genphy_soft_reset(phydev);
362
-
363
- err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
364
- if (err < 0)
365
- return err;
366
-
367
- err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL,
368
- MII_M1111_PHY_LED_DIRECT);
369
- if (err < 0)
370
- return err;
371
-
372
- err = genphy_config_aneg(phydev);
373
- if (err < 0)
374
- return err;
375
-
376
- if (phydev->autoneg != AUTONEG_ENABLE) {
377
- /* A write to speed/duplex bits (that is performed by
378
- * genphy_config_aneg() call above) must be followed by
379
- * a software reset. Otherwise, the write has no effect.
380
- */
381
- err = genphy_soft_reset(phydev);
382
- if (err < 0)
383
- return err;
384
- }
385
-
386
- return 0;
387
-}
388
-
389
-#ifdef CONFIG_OF_MDIO
432
+#if IS_ENABLED(CONFIG_OF_MDIO)
390433 /* Set and/or override some configuration registers based on the
391434 * marvell,reg-init property stored in the of_node for the phydev.
392435 *
....@@ -472,13 +515,14 @@
472515 else
473516 mscr = 0;
474517
475
- return phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
476
- MII_88E1121_PHY_MSCR_REG,
477
- MII_88E1121_PHY_MSCR_DELAY_MASK, mscr);
518
+ return phy_modify_paged_changed(phydev, MII_MARVELL_MSCR_PAGE,
519
+ MII_88E1121_PHY_MSCR_REG,
520
+ MII_88E1121_PHY_MSCR_DELAY_MASK, mscr);
478521 }
479522
480523 static int m88e1121_config_aneg(struct phy_device *phydev)
481524 {
525
+ int changed = 0;
482526 int err = 0;
483527
484528 if (phy_interface_is_rgmii(phydev)) {
....@@ -487,15 +531,28 @@
487531 return err;
488532 }
489533
490
- err = genphy_soft_reset(phydev);
491
- if (err < 0)
492
- return err;
534
+ changed = err;
493535
494536 err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
495537 if (err < 0)
496538 return err;
497539
498
- return genphy_config_aneg(phydev);
540
+ changed |= err;
541
+
542
+ err = genphy_config_aneg(phydev);
543
+ if (err < 0)
544
+ return err;
545
+
546
+ if (phydev->autoneg != AUTONEG_ENABLE || changed) {
547
+ /* A software reset is used to ensure a "commit" of the
548
+ * changes is done.
549
+ */
550
+ err = genphy_soft_reset(phydev);
551
+ if (err < 0)
552
+ return err;
553
+ }
554
+
555
+ return 0;
499556 }
500557
501558 static int m88e1318_config_aneg(struct phy_device *phydev)
....@@ -512,27 +569,27 @@
512569 }
513570
514571 /**
515
- * ethtool_adv_to_fiber_adv_t
516
- * @ethadv: the ethtool advertisement settings
572
+ * linkmode_adv_to_fiber_adv_t
573
+ * @advertise: the linkmode advertisement settings
517574 *
518
- * A small helper function that translates ethtool advertisement
519
- * settings to phy autonegotiation advertisements for the
520
- * MII_ADV register for fiber link.
575
+ * A small helper function that translates linkmode advertisement
576
+ * settings to phy autonegotiation advertisements for the MII_ADV
577
+ * register for fiber link.
521578 */
522
-static inline u32 ethtool_adv_to_fiber_adv_t(u32 ethadv)
579
+static inline u32 linkmode_adv_to_fiber_adv_t(unsigned long *advertise)
523580 {
524581 u32 result = 0;
525582
526
- if (ethadv & ADVERTISED_1000baseT_Half)
527
- result |= ADVERTISE_FIBER_1000HALF;
528
- if (ethadv & ADVERTISED_1000baseT_Full)
529
- result |= ADVERTISE_FIBER_1000FULL;
583
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, advertise))
584
+ result |= ADVERTISE_1000XHALF;
585
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertise))
586
+ result |= ADVERTISE_1000XFULL;
530587
531
- if ((ethadv & ADVERTISE_PAUSE_ASYM) && (ethadv & ADVERTISE_PAUSE_CAP))
532
- result |= LPA_PAUSE_ASYM_FIBER;
533
- else if (ethadv & ADVERTISE_PAUSE_CAP)
534
- result |= (ADVERTISE_PAUSE_FIBER
535
- & (~ADVERTISE_PAUSE_ASYM_FIBER));
588
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertise) &&
589
+ linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertise))
590
+ result |= ADVERTISE_1000XPSE_ASYM;
591
+ else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertise))
592
+ result |= ADVERTISE_1000XPAUSE;
536593
537594 return result;
538595 }
....@@ -550,54 +607,28 @@
550607 {
551608 int changed = 0;
552609 int err;
553
- int adv, oldadv;
554
- u32 advertise;
610
+ u16 adv;
555611
556612 if (phydev->autoneg != AUTONEG_ENABLE)
557613 return genphy_setup_forced(phydev);
558614
559615 /* Only allow advertising what this PHY supports */
560
- phydev->advertising &= phydev->supported;
561
- advertise = phydev->advertising;
616
+ linkmode_and(phydev->advertising, phydev->advertising,
617
+ phydev->supported);
618
+
619
+ adv = linkmode_adv_to_fiber_adv_t(phydev->advertising);
562620
563621 /* Setup fiber advertisement */
564
- adv = phy_read(phydev, MII_ADVERTISE);
565
- if (adv < 0)
566
- return adv;
567
-
568
- oldadv = adv;
569
- adv &= ~(ADVERTISE_FIBER_1000HALF | ADVERTISE_FIBER_1000FULL
570
- | LPA_PAUSE_FIBER);
571
- adv |= ethtool_adv_to_fiber_adv_t(advertise);
572
-
573
- if (adv != oldadv) {
574
- err = phy_write(phydev, MII_ADVERTISE, adv);
575
- if (err < 0)
576
- return err;
577
-
622
+ err = phy_modify_changed(phydev, MII_ADVERTISE,
623
+ ADVERTISE_1000XHALF | ADVERTISE_1000XFULL |
624
+ ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM,
625
+ adv);
626
+ if (err < 0)
627
+ return err;
628
+ if (err > 0)
578629 changed = 1;
579
- }
580630
581
- if (changed == 0) {
582
- /* Advertisement hasn't changed, but maybe aneg was never on to
583
- * begin with? Or maybe phy was isolated?
584
- */
585
- int ctl = phy_read(phydev, MII_BMCR);
586
-
587
- if (ctl < 0)
588
- return ctl;
589
-
590
- if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
591
- changed = 1; /* do restart aneg */
592
- }
593
-
594
- /* Only restart aneg if we are advertising something different
595
- * than we were before.
596
- */
597
- if (changed > 0)
598
- changed = genphy_restart_aneg(phydev);
599
-
600
- return changed;
631
+ return genphy_check_and_restart_aneg(phydev, changed);
601632 }
602633
603634 static int m88e1510_config_aneg(struct phy_device *phydev)
....@@ -650,7 +681,10 @@
650681 * LED[2] .. Blink, Activity
651682 */
652683 case MARVELL_PHY_FAMILY_ID(MARVELL_PHY_ID_88E1510):
653
- def_config = MII_88E1510_PHY_LED_DEF;
684
+ if (phydev->dev_flags & MARVELL_PHY_LED0_LINK_LED1_ACTIVE)
685
+ def_config = MII_88E1510_PHY_LED0_LINK_LED1_ACTIVE;
686
+ else
687
+ def_config = MII_88E1510_PHY_LED_DEF;
654688 break;
655689 default:
656690 return;
....@@ -659,7 +693,7 @@
659693 err = phy_write_paged(phydev, MII_MARVELL_LED_PAGE, MII_PHY_LED_CTRL,
660694 def_config);
661695 if (err < 0)
662
- pr_warn("Fail to config marvell phy LED.\n");
696
+ phydev_warn(phydev, "Fail to config marvell phy LED.\n");
663697 }
664698
665699 static int marvell_config_init(struct phy_device *phydev)
....@@ -669,41 +703,6 @@
669703
670704 /* Set registers from marvell,reg-init DT property */
671705 return marvell_of_reg_init(phydev);
672
-}
673
-
674
-static int m88e1116r_config_init(struct phy_device *phydev)
675
-{
676
- int err;
677
-
678
- err = genphy_soft_reset(phydev);
679
- if (err < 0)
680
- return err;
681
-
682
- msleep(500);
683
-
684
- err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
685
- if (err < 0)
686
- return err;
687
-
688
- err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
689
- if (err < 0)
690
- return err;
691
-
692
- err = marvell_set_downshift(phydev, true, 8);
693
- if (err < 0)
694
- return err;
695
-
696
- if (phy_interface_is_rgmii(phydev)) {
697
- err = m88e1121_config_aneg_rgmii_delays(phydev);
698
- if (err < 0)
699
- return err;
700
- }
701
-
702
- err = genphy_soft_reset(phydev);
703
- if (err < 0)
704
- return err;
705
-
706
- return marvell_config_init(phydev);
707706 }
708707
709708 static int m88e3016_config_init(struct phy_device *phydev)
....@@ -844,6 +843,169 @@
844843 return err;
845844
846845 return genphy_soft_reset(phydev);
846
+}
847
+
848
+static int m88e1111_get_downshift(struct phy_device *phydev, u8 *data)
849
+{
850
+ int val, cnt, enable;
851
+
852
+ val = phy_read(phydev, MII_M1111_PHY_EXT_CR);
853
+ if (val < 0)
854
+ return val;
855
+
856
+ enable = FIELD_GET(MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN, val);
857
+ cnt = FIELD_GET(MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK, val) + 1;
858
+
859
+ *data = enable ? cnt : DOWNSHIFT_DEV_DISABLE;
860
+
861
+ return 0;
862
+}
863
+
864
+static int m88e1111_set_downshift(struct phy_device *phydev, u8 cnt)
865
+{
866
+ int val, err;
867
+
868
+ if (cnt > MII_M1111_PHY_EXT_CR_DOWNSHIFT_MAX)
869
+ return -E2BIG;
870
+
871
+ if (!cnt) {
872
+ err = phy_clear_bits(phydev, MII_M1111_PHY_EXT_CR,
873
+ MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN);
874
+ } else {
875
+ val = MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN;
876
+ val |= FIELD_PREP(MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK, cnt - 1);
877
+
878
+ err = phy_modify(phydev, MII_M1111_PHY_EXT_CR,
879
+ MII_M1111_PHY_EXT_CR_DOWNSHIFT_EN |
880
+ MII_M1111_PHY_EXT_CR_DOWNSHIFT_MASK,
881
+ val);
882
+ }
883
+
884
+ if (err < 0)
885
+ return err;
886
+
887
+ return genphy_soft_reset(phydev);
888
+}
889
+
890
+static int m88e1111_get_tunable(struct phy_device *phydev,
891
+ struct ethtool_tunable *tuna, void *data)
892
+{
893
+ switch (tuna->id) {
894
+ case ETHTOOL_PHY_DOWNSHIFT:
895
+ return m88e1111_get_downshift(phydev, data);
896
+ default:
897
+ return -EOPNOTSUPP;
898
+ }
899
+}
900
+
901
+static int m88e1111_set_tunable(struct phy_device *phydev,
902
+ struct ethtool_tunable *tuna, const void *data)
903
+{
904
+ switch (tuna->id) {
905
+ case ETHTOOL_PHY_DOWNSHIFT:
906
+ return m88e1111_set_downshift(phydev, *(const u8 *)data);
907
+ default:
908
+ return -EOPNOTSUPP;
909
+ }
910
+}
911
+
912
+static int m88e1011_get_downshift(struct phy_device *phydev, u8 *data)
913
+{
914
+ int val, cnt, enable;
915
+
916
+ val = phy_read(phydev, MII_M1011_PHY_SCR);
917
+ if (val < 0)
918
+ return val;
919
+
920
+ enable = FIELD_GET(MII_M1011_PHY_SCR_DOWNSHIFT_EN, val);
921
+ cnt = FIELD_GET(MII_M1011_PHY_SCR_DOWNSHIFT_MASK, val) + 1;
922
+
923
+ *data = enable ? cnt : DOWNSHIFT_DEV_DISABLE;
924
+
925
+ return 0;
926
+}
927
+
928
+static int m88e1011_set_downshift(struct phy_device *phydev, u8 cnt)
929
+{
930
+ int val, err;
931
+
932
+ if (cnt > MII_M1011_PHY_SCR_DOWNSHIFT_MAX)
933
+ return -E2BIG;
934
+
935
+ if (!cnt) {
936
+ err = phy_clear_bits(phydev, MII_M1011_PHY_SCR,
937
+ MII_M1011_PHY_SCR_DOWNSHIFT_EN);
938
+ } else {
939
+ val = MII_M1011_PHY_SCR_DOWNSHIFT_EN;
940
+ val |= FIELD_PREP(MII_M1011_PHY_SCR_DOWNSHIFT_MASK, cnt - 1);
941
+
942
+ err = phy_modify(phydev, MII_M1011_PHY_SCR,
943
+ MII_M1011_PHY_SCR_DOWNSHIFT_EN |
944
+ MII_M1011_PHY_SCR_DOWNSHIFT_MASK,
945
+ val);
946
+ }
947
+
948
+ if (err < 0)
949
+ return err;
950
+
951
+ return genphy_soft_reset(phydev);
952
+}
953
+
954
+static int m88e1011_get_tunable(struct phy_device *phydev,
955
+ struct ethtool_tunable *tuna, void *data)
956
+{
957
+ switch (tuna->id) {
958
+ case ETHTOOL_PHY_DOWNSHIFT:
959
+ return m88e1011_get_downshift(phydev, data);
960
+ default:
961
+ return -EOPNOTSUPP;
962
+ }
963
+}
964
+
965
+static int m88e1011_set_tunable(struct phy_device *phydev,
966
+ struct ethtool_tunable *tuna, const void *data)
967
+{
968
+ switch (tuna->id) {
969
+ case ETHTOOL_PHY_DOWNSHIFT:
970
+ return m88e1011_set_downshift(phydev, *(const u8 *)data);
971
+ default:
972
+ return -EOPNOTSUPP;
973
+ }
974
+}
975
+
976
+static int m88e1116r_config_init(struct phy_device *phydev)
977
+{
978
+ int err;
979
+
980
+ err = genphy_soft_reset(phydev);
981
+ if (err < 0)
982
+ return err;
983
+
984
+ msleep(500);
985
+
986
+ err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
987
+ if (err < 0)
988
+ return err;
989
+
990
+ err = marvell_set_polarity(phydev, phydev->mdix_ctrl);
991
+ if (err < 0)
992
+ return err;
993
+
994
+ err = m88e1011_set_downshift(phydev, 8);
995
+ if (err < 0)
996
+ return err;
997
+
998
+ if (phy_interface_is_rgmii(phydev)) {
999
+ err = m88e1121_config_aneg_rgmii_delays(phydev);
1000
+ if (err < 0)
1001
+ return err;
1002
+ }
1003
+
1004
+ err = genphy_soft_reset(phydev);
1005
+ if (err < 0)
1006
+ return err;
1007
+
1008
+ return marvell_config_init(phydev);
8471009 }
8481010
8491011 static int m88e1318_config_init(struct phy_device *phydev)
....@@ -1056,6 +1218,105 @@
10561218 return 0;
10571219 }
10581220
1221
+static int m88e1540_get_fld(struct phy_device *phydev, u8 *msecs)
1222
+{
1223
+ int val;
1224
+
1225
+ val = phy_read(phydev, MII_88E1540_COPPER_CTRL3);
1226
+ if (val < 0)
1227
+ return val;
1228
+
1229
+ if (!(val & MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN)) {
1230
+ *msecs = ETHTOOL_PHY_FAST_LINK_DOWN_OFF;
1231
+ return 0;
1232
+ }
1233
+
1234
+ val = FIELD_GET(MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK, val);
1235
+
1236
+ switch (val) {
1237
+ case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_00MS:
1238
+ *msecs = 0;
1239
+ break;
1240
+ case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_10MS:
1241
+ *msecs = 10;
1242
+ break;
1243
+ case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_20MS:
1244
+ *msecs = 20;
1245
+ break;
1246
+ case MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_40MS:
1247
+ *msecs = 40;
1248
+ break;
1249
+ default:
1250
+ return -EINVAL;
1251
+ }
1252
+
1253
+ return 0;
1254
+}
1255
+
1256
+static int m88e1540_set_fld(struct phy_device *phydev, const u8 *msecs)
1257
+{
1258
+ struct ethtool_eee eee;
1259
+ int val, ret;
1260
+
1261
+ if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
1262
+ return phy_clear_bits(phydev, MII_88E1540_COPPER_CTRL3,
1263
+ MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN);
1264
+
1265
+ /* According to the Marvell data sheet EEE must be disabled for
1266
+ * Fast Link Down detection to work properly
1267
+ */
1268
+ ret = phy_ethtool_get_eee(phydev, &eee);
1269
+ if (!ret && eee.eee_enabled) {
1270
+ phydev_warn(phydev, "Fast Link Down detection requires EEE to be disabled!\n");
1271
+ return -EBUSY;
1272
+ }
1273
+
1274
+ if (*msecs <= 5)
1275
+ val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_00MS;
1276
+ else if (*msecs <= 15)
1277
+ val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_10MS;
1278
+ else if (*msecs <= 30)
1279
+ val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_20MS;
1280
+ else
1281
+ val = MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_40MS;
1282
+
1283
+ val = FIELD_PREP(MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK, val);
1284
+
1285
+ ret = phy_modify(phydev, MII_88E1540_COPPER_CTRL3,
1286
+ MII_88E1540_COPPER_CTRL3_LINK_DOWN_DELAY_MASK, val);
1287
+ if (ret)
1288
+ return ret;
1289
+
1290
+ return phy_set_bits(phydev, MII_88E1540_COPPER_CTRL3,
1291
+ MII_88E1540_COPPER_CTRL3_FAST_LINK_DOWN);
1292
+}
1293
+
1294
+static int m88e1540_get_tunable(struct phy_device *phydev,
1295
+ struct ethtool_tunable *tuna, void *data)
1296
+{
1297
+ switch (tuna->id) {
1298
+ case ETHTOOL_PHY_FAST_LINK_DOWN:
1299
+ return m88e1540_get_fld(phydev, data);
1300
+ case ETHTOOL_PHY_DOWNSHIFT:
1301
+ return m88e1011_get_downshift(phydev, data);
1302
+ default:
1303
+ return -EOPNOTSUPP;
1304
+ }
1305
+}
1306
+
1307
+static int m88e1540_set_tunable(struct phy_device *phydev,
1308
+ struct ethtool_tunable *tuna, const void *data)
1309
+{
1310
+ switch (tuna->id) {
1311
+ case ETHTOOL_PHY_FAST_LINK_DOWN:
1312
+ return m88e1540_set_fld(phydev, data);
1313
+ case ETHTOOL_PHY_DOWNSHIFT:
1314
+ return m88e1011_set_downshift(phydev, *(const u8 *)data);
1315
+ default:
1316
+ return -EOPNOTSUPP;
1317
+ }
1318
+}
1319
+
10591320 /* The VOD can be out of specification on link up. Poke an
10601321 * undocumented register, in an undocumented page, with a magic value
10611322 * to fix this.
....@@ -1090,83 +1351,40 @@
10901351 }
10911352
10921353 /**
1093
- * fiber_lpa_to_ethtool_lpa_t
1354
+ * fiber_lpa_mod_linkmode_lpa_t
1355
+ * @advertising: the linkmode advertisement settings
10941356 * @lpa: value of the MII_LPA register for fiber link
10951357 *
1096
- * A small helper function that translates MII_LPA
1097
- * bits to ethtool LP advertisement settings.
1358
+ * A small helper function that translates MII_LPA bits to linkmode LP
1359
+ * advertisement settings. Other bits in advertising are left
1360
+ * unchanged.
10981361 */
1099
-static u32 fiber_lpa_to_ethtool_lpa_t(u32 lpa)
1362
+static void fiber_lpa_mod_linkmode_lpa_t(unsigned long *advertising, u32 lpa)
11001363 {
1101
- u32 result = 0;
1364
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
1365
+ advertising, lpa & LPA_1000XHALF);
11021366
1103
- if (lpa & LPA_FIBER_1000HALF)
1104
- result |= ADVERTISED_1000baseT_Half;
1105
- if (lpa & LPA_FIBER_1000FULL)
1106
- result |= ADVERTISED_1000baseT_Full;
1107
-
1108
- return result;
1109
-}
1110
-
1111
-/**
1112
- * marvell_update_link - update link status in real time in @phydev
1113
- * @phydev: target phy_device struct
1114
- *
1115
- * Description: Update the value in phydev->link to reflect the
1116
- * current link value.
1117
- */
1118
-static int marvell_update_link(struct phy_device *phydev, int fiber)
1119
-{
1120
- int status;
1121
-
1122
- /* Use the generic register for copper link, or specific
1123
- * register for fiber case
1124
- */
1125
- if (fiber) {
1126
- status = phy_read(phydev, MII_M1011_PHY_STATUS);
1127
- if (status < 0)
1128
- return status;
1129
-
1130
- if ((status & REGISTER_LINK_STATUS) == 0)
1131
- phydev->link = 0;
1132
- else
1133
- phydev->link = 1;
1134
- } else {
1135
- return genphy_update_link(phydev);
1136
- }
1137
-
1138
- return 0;
1367
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
1368
+ advertising, lpa & LPA_1000XFULL);
11391369 }
11401370
11411371 static int marvell_read_status_page_an(struct phy_device *phydev,
1142
- int fiber)
1372
+ int fiber, int status)
11431373 {
1144
- int status;
11451374 int lpa;
1146
- int lpagb;
1375
+ int err;
11471376
1148
- status = phy_read(phydev, MII_M1011_PHY_STATUS);
1149
- if (status < 0)
1150
- return status;
1151
-
1152
- lpa = phy_read(phydev, MII_LPA);
1153
- if (lpa < 0)
1154
- return lpa;
1155
-
1156
- lpagb = phy_read(phydev, MII_STAT1000);
1157
- if (lpagb < 0)
1158
- return lpagb;
1377
+ if (!(status & MII_M1011_PHY_STATUS_RESOLVED)) {
1378
+ phydev->link = 0;
1379
+ return 0;
1380
+ }
11591381
11601382 if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
11611383 phydev->duplex = DUPLEX_FULL;
11621384 else
11631385 phydev->duplex = DUPLEX_HALF;
11641386
1165
- status = status & MII_M1011_PHY_STATUS_SPD_MASK;
1166
- phydev->pause = 0;
1167
- phydev->asym_pause = 0;
1168
-
1169
- switch (status) {
1387
+ switch (status & MII_M1011_PHY_STATUS_SPD_MASK) {
11701388 case MII_M1011_PHY_STATUS_1000:
11711389 phydev->speed = SPEED_1000;
11721390 break;
....@@ -1181,17 +1399,18 @@
11811399 }
11821400
11831401 if (!fiber) {
1184
- phydev->lp_advertising =
1185
- mii_stat1000_to_ethtool_lpa_t(lpagb) |
1186
- mii_lpa_to_ethtool_lpa_t(lpa);
1402
+ err = genphy_read_lpa(phydev);
1403
+ if (err < 0)
1404
+ return err;
11871405
1188
- if (phydev->duplex == DUPLEX_FULL) {
1189
- phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
1190
- phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
1191
- }
1406
+ phy_resolve_aneg_pause(phydev);
11921407 } else {
1408
+ lpa = phy_read(phydev, MII_LPA);
1409
+ if (lpa < 0)
1410
+ return lpa;
1411
+
11931412 /* The fiber link is only 1000M capable */
1194
- phydev->lp_advertising = fiber_lpa_to_ethtool_lpa_t(lpa);
1413
+ fiber_lpa_mod_linkmode_lpa_t(phydev->lp_advertising, lpa);
11951414
11961415 if (phydev->duplex == DUPLEX_FULL) {
11971416 if (!(lpa & LPA_PAUSE_FIBER)) {
....@@ -1206,31 +1425,6 @@
12061425 }
12071426 }
12081427 }
1209
- return 0;
1210
-}
1211
-
1212
-static int marvell_read_status_page_fixed(struct phy_device *phydev)
1213
-{
1214
- int bmcr = phy_read(phydev, MII_BMCR);
1215
-
1216
- if (bmcr < 0)
1217
- return bmcr;
1218
-
1219
- if (bmcr & BMCR_FULLDPLX)
1220
- phydev->duplex = DUPLEX_FULL;
1221
- else
1222
- phydev->duplex = DUPLEX_HALF;
1223
-
1224
- if (bmcr & BMCR_SPEED1000)
1225
- phydev->speed = SPEED_1000;
1226
- else if (bmcr & BMCR_SPEED100)
1227
- phydev->speed = SPEED_100;
1228
- else
1229
- phydev->speed = SPEED_10;
1230
-
1231
- phydev->pause = 0;
1232
- phydev->asym_pause = 0;
1233
- phydev->lp_advertising = 0;
12341428
12351429 return 0;
12361430 }
....@@ -1245,25 +1439,41 @@
12451439 */
12461440 static int marvell_read_status_page(struct phy_device *phydev, int page)
12471441 {
1442
+ int status;
12481443 int fiber;
12491444 int err;
12501445
1251
- /* Detect and update the link, but return if there
1252
- * was an error
1446
+ status = phy_read(phydev, MII_M1011_PHY_STATUS);
1447
+ if (status < 0)
1448
+ return status;
1449
+
1450
+ /* Use the generic register for copper link status,
1451
+ * and the PHY status register for fiber link status.
12531452 */
1453
+ if (page == MII_MARVELL_FIBER_PAGE) {
1454
+ phydev->link = !!(status & MII_M1011_PHY_STATUS_LINK);
1455
+ } else {
1456
+ err = genphy_update_link(phydev);
1457
+ if (err)
1458
+ return err;
1459
+ }
1460
+
12541461 if (page == MII_MARVELL_FIBER_PAGE)
12551462 fiber = 1;
12561463 else
12571464 fiber = 0;
12581465
1259
- err = marvell_update_link(phydev, fiber);
1260
- if (err)
1261
- return err;
1466
+ linkmode_zero(phydev->lp_advertising);
1467
+ phydev->pause = 0;
1468
+ phydev->asym_pause = 0;
1469
+ phydev->speed = SPEED_UNKNOWN;
1470
+ phydev->duplex = DUPLEX_UNKNOWN;
1471
+ phydev->port = fiber ? PORT_FIBRE : PORT_TP;
12621472
12631473 if (phydev->autoneg == AUTONEG_ENABLE)
1264
- err = marvell_read_status_page_an(phydev, fiber);
1474
+ err = marvell_read_status_page_an(phydev, fiber, status);
12651475 else
1266
- err = marvell_read_status_page_fixed(phydev);
1476
+ err = genphy_read_status_fixed(phydev);
12671477
12681478 return err;
12691479 }
....@@ -1282,7 +1492,8 @@
12821492 int err;
12831493
12841494 /* Check the fiber mode first */
1285
- if (phydev->supported & SUPPORTED_FIBRE &&
1495
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1496
+ phydev->supported) &&
12861497 phydev->interface != PHY_INTERFACE_MODE_SGMII) {
12871498 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
12881499 if (err < 0)
....@@ -1325,7 +1536,8 @@
13251536 int err;
13261537
13271538 /* Suspend the fiber mode first */
1328
- if (!(phydev->supported & SUPPORTED_FIBRE)) {
1539
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1540
+ phydev->supported)) {
13291541 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
13301542 if (err < 0)
13311543 goto error;
....@@ -1359,7 +1571,8 @@
13591571 int err;
13601572
13611573 /* Resume the fiber mode first */
1362
- if (!(phydev->supported & SUPPORTED_FIBRE)) {
1574
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1575
+ phydev->supported)) {
13631576 err = marvell_set_page(phydev, MII_MARVELL_FIBER_PAGE);
13641577 if (err < 0)
13651578 goto error;
....@@ -1405,21 +1618,15 @@
14051618 static void m88e1318_get_wol(struct phy_device *phydev,
14061619 struct ethtool_wolinfo *wol)
14071620 {
1408
- int oldpage, ret = 0;
1621
+ int ret;
14091622
14101623 wol->supported = WAKE_MAGIC;
14111624 wol->wolopts = 0;
14121625
1413
- oldpage = phy_select_page(phydev, MII_MARVELL_WOL_PAGE);
1414
- if (oldpage < 0)
1415
- goto error;
1416
-
1417
- ret = __phy_read(phydev, MII_88E1318S_PHY_WOL_CTRL);
1418
- if (ret & MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
1626
+ ret = phy_read_paged(phydev, MII_MARVELL_WOL_PAGE,
1627
+ MII_88E1318S_PHY_WOL_CTRL);
1628
+ if (ret >= 0 && ret & MII_88E1318S_PHY_WOL_CTRL_MAGIC_PACKET_MATCH_ENABLE)
14191629 wol->wolopts |= WAKE_MAGIC;
1420
-
1421
-error:
1422
- phy_restore_page(phydev, oldpage, ret);
14231630 }
14241631
14251632 static int m88e1318_set_wol(struct phy_device *phydev,
....@@ -1510,7 +1717,8 @@
15101717
15111718 static int marvell_get_sset_count(struct phy_device *phydev)
15121719 {
1513
- if (phydev->supported & SUPPORTED_FIBRE)
1720
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
1721
+ phydev->supported))
15141722 return ARRAY_SIZE(marvell_hw_stats);
15151723 else
15161724 return ARRAY_SIZE(marvell_hw_stats) - NB_FIBER_STATS;
....@@ -1554,6 +1762,382 @@
15541762
15551763 for (i = 0; i < count; i++)
15561764 data[i] = marvell_get_stat(phydev, i);
1765
+}
1766
+
1767
+static int marvell_vct5_wait_complete(struct phy_device *phydev)
1768
+{
1769
+ int i;
1770
+ int val;
1771
+
1772
+ for (i = 0; i < 32; i++) {
1773
+ val = __phy_read(phydev, MII_VCT5_CTRL);
1774
+ if (val < 0)
1775
+ return val;
1776
+
1777
+ if (val & MII_VCT5_CTRL_COMPLETE)
1778
+ return 0;
1779
+ }
1780
+
1781
+ phydev_err(phydev, "Timeout while waiting for cable test to finish\n");
1782
+ return -ETIMEDOUT;
1783
+}
1784
+
1785
+static int marvell_vct5_amplitude(struct phy_device *phydev, int pair)
1786
+{
1787
+ int amplitude;
1788
+ int val;
1789
+ int reg;
1790
+
1791
+ reg = MII_VCT5_TX_RX_MDI0_COUPLING + pair;
1792
+ val = __phy_read(phydev, reg);
1793
+
1794
+ if (val < 0)
1795
+ return 0;
1796
+
1797
+ amplitude = (val & MII_VCT5_TX_RX_AMPLITUDE_MASK) >>
1798
+ MII_VCT5_TX_RX_AMPLITUDE_SHIFT;
1799
+
1800
+ if (!(val & MII_VCT5_TX_RX_COUPLING_POSITIVE_REFLECTION))
1801
+ amplitude = -amplitude;
1802
+
1803
+ return 1000 * amplitude / 128;
1804
+}
1805
+
1806
+static u32 marvell_vct5_distance2cm(int distance)
1807
+{
1808
+ return distance * 805 / 10;
1809
+}
1810
+
1811
+static u32 marvell_vct5_cm2distance(int cm)
1812
+{
1813
+ return cm * 10 / 805;
1814
+}
1815
+
1816
+static int marvell_vct5_amplitude_distance(struct phy_device *phydev,
1817
+ int distance, int pair)
1818
+{
1819
+ u16 reg;
1820
+ int err;
1821
+ int mV;
1822
+ int i;
1823
+
1824
+ err = __phy_write(phydev, MII_VCT5_SAMPLE_POINT_DISTANCE,
1825
+ distance);
1826
+ if (err)
1827
+ return err;
1828
+
1829
+ reg = MII_VCT5_CTRL_ENABLE |
1830
+ MII_VCT5_CTRL_TX_SAME_CHANNEL |
1831
+ MII_VCT5_CTRL_SAMPLES_DEFAULT |
1832
+ MII_VCT5_CTRL_SAMPLE_POINT |
1833
+ MII_VCT5_CTRL_PEEK_HYST_DEFAULT;
1834
+ err = __phy_write(phydev, MII_VCT5_CTRL, reg);
1835
+ if (err)
1836
+ return err;
1837
+
1838
+ err = marvell_vct5_wait_complete(phydev);
1839
+ if (err)
1840
+ return err;
1841
+
1842
+ for (i = 0; i < 4; i++) {
1843
+ if (pair != PHY_PAIR_ALL && i != pair)
1844
+ continue;
1845
+
1846
+ mV = marvell_vct5_amplitude(phydev, i);
1847
+ ethnl_cable_test_amplitude(phydev, i, mV);
1848
+ }
1849
+
1850
+ return 0;
1851
+}
1852
+
1853
+static int marvell_vct5_amplitude_graph(struct phy_device *phydev)
1854
+{
1855
+ struct marvell_priv *priv = phydev->priv;
1856
+ int distance;
1857
+ u16 width;
1858
+ int page;
1859
+ int err;
1860
+ u16 reg;
1861
+
1862
+ if (priv->first <= TDR_SHORT_CABLE_LENGTH)
1863
+ width = MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_32nS;
1864
+ else
1865
+ width = MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_128nS;
1866
+
1867
+ reg = MII_VCT5_TX_PULSE_CTRL_GT_140m_46_86mV |
1868
+ MII_VCT5_TX_PULSE_CTRL_DONT_WAIT_LINK_DOWN |
1869
+ MII_VCT5_TX_PULSE_CTRL_MAX_AMP | width;
1870
+
1871
+ err = phy_write_paged(phydev, MII_MARVELL_VCT5_PAGE,
1872
+ MII_VCT5_TX_PULSE_CTRL, reg);
1873
+ if (err)
1874
+ return err;
1875
+
1876
+ /* Reading the TDR data is very MDIO heavy. We need to optimize
1877
+ * access to keep the time to a minimum. So lock the bus once,
1878
+ * and don't release it until complete. We can then avoid having
1879
+ * to change the page for every access, greatly speeding things
1880
+ * up.
1881
+ */
1882
+ page = phy_select_page(phydev, MII_MARVELL_VCT5_PAGE);
1883
+ if (page < 0)
1884
+ goto restore_page;
1885
+
1886
+ for (distance = priv->first;
1887
+ distance <= priv->last;
1888
+ distance += priv->step) {
1889
+ err = marvell_vct5_amplitude_distance(phydev, distance,
1890
+ priv->pair);
1891
+ if (err)
1892
+ goto restore_page;
1893
+
1894
+ if (distance > TDR_SHORT_CABLE_LENGTH &&
1895
+ width == MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_32nS) {
1896
+ width = MII_VCT5_TX_PULSE_CTRL_PULSE_WIDTH_128nS;
1897
+ reg = MII_VCT5_TX_PULSE_CTRL_GT_140m_46_86mV |
1898
+ MII_VCT5_TX_PULSE_CTRL_DONT_WAIT_LINK_DOWN |
1899
+ MII_VCT5_TX_PULSE_CTRL_MAX_AMP | width;
1900
+ err = __phy_write(phydev, MII_VCT5_TX_PULSE_CTRL, reg);
1901
+ if (err)
1902
+ goto restore_page;
1903
+ }
1904
+ }
1905
+
1906
+restore_page:
1907
+ return phy_restore_page(phydev, page, err);
1908
+}
1909
+
1910
+static int marvell_cable_test_start_common(struct phy_device *phydev)
1911
+{
1912
+ int bmcr, bmsr, ret;
1913
+
1914
+ /* If auto-negotiation is enabled, but not complete, the cable
1915
+ * test never completes. So disable auto-neg.
1916
+ */
1917
+ bmcr = phy_read(phydev, MII_BMCR);
1918
+ if (bmcr < 0)
1919
+ return bmcr;
1920
+
1921
+ bmsr = phy_read(phydev, MII_BMSR);
1922
+
1923
+ if (bmsr < 0)
1924
+ return bmsr;
1925
+
1926
+ if (bmcr & BMCR_ANENABLE) {
1927
+ ret = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
1928
+ if (ret < 0)
1929
+ return ret;
1930
+ ret = genphy_soft_reset(phydev);
1931
+ if (ret < 0)
1932
+ return ret;
1933
+ }
1934
+
1935
+ /* If the link is up, allow it some time to go down */
1936
+ if (bmsr & BMSR_LSTATUS)
1937
+ msleep(1500);
1938
+
1939
+ return 0;
1940
+}
1941
+
1942
+static int marvell_vct7_cable_test_start(struct phy_device *phydev)
1943
+{
1944
+ struct marvell_priv *priv = phydev->priv;
1945
+ int ret;
1946
+
1947
+ ret = marvell_cable_test_start_common(phydev);
1948
+ if (ret)
1949
+ return ret;
1950
+
1951
+ priv->cable_test_tdr = false;
1952
+
1953
+ /* Reset the VCT5 API control to defaults, otherwise
1954
+ * VCT7 does not work correctly.
1955
+ */
1956
+ ret = phy_write_paged(phydev, MII_MARVELL_VCT5_PAGE,
1957
+ MII_VCT5_CTRL,
1958
+ MII_VCT5_CTRL_TX_SAME_CHANNEL |
1959
+ MII_VCT5_CTRL_SAMPLES_DEFAULT |
1960
+ MII_VCT5_CTRL_MODE_MAXIMUM_PEEK |
1961
+ MII_VCT5_CTRL_PEEK_HYST_DEFAULT);
1962
+ if (ret)
1963
+ return ret;
1964
+
1965
+ ret = phy_write_paged(phydev, MII_MARVELL_VCT5_PAGE,
1966
+ MII_VCT5_SAMPLE_POINT_DISTANCE, 0);
1967
+ if (ret)
1968
+ return ret;
1969
+
1970
+ return phy_write_paged(phydev, MII_MARVELL_VCT7_PAGE,
1971
+ MII_VCT7_CTRL,
1972
+ MII_VCT7_CTRL_RUN_NOW |
1973
+ MII_VCT7_CTRL_CENTIMETERS);
1974
+}
1975
+
1976
+static int marvell_vct5_cable_test_tdr_start(struct phy_device *phydev,
1977
+ const struct phy_tdr_config *cfg)
1978
+{
1979
+ struct marvell_priv *priv = phydev->priv;
1980
+ int ret;
1981
+
1982
+ priv->cable_test_tdr = true;
1983
+ priv->first = marvell_vct5_cm2distance(cfg->first);
1984
+ priv->last = marvell_vct5_cm2distance(cfg->last);
1985
+ priv->step = marvell_vct5_cm2distance(cfg->step);
1986
+ priv->pair = cfg->pair;
1987
+
1988
+ if (priv->first > MII_VCT5_SAMPLE_POINT_DISTANCE_MAX)
1989
+ return -EINVAL;
1990
+
1991
+ if (priv->last > MII_VCT5_SAMPLE_POINT_DISTANCE_MAX)
1992
+ return -EINVAL;
1993
+
1994
+ /* Disable VCT7 */
1995
+ ret = phy_write_paged(phydev, MII_MARVELL_VCT7_PAGE,
1996
+ MII_VCT7_CTRL, 0);
1997
+ if (ret)
1998
+ return ret;
1999
+
2000
+ ret = marvell_cable_test_start_common(phydev);
2001
+ if (ret)
2002
+ return ret;
2003
+
2004
+ ret = ethnl_cable_test_pulse(phydev, 1000);
2005
+ if (ret)
2006
+ return ret;
2007
+
2008
+ return ethnl_cable_test_step(phydev,
2009
+ marvell_vct5_distance2cm(priv->first),
2010
+ marvell_vct5_distance2cm(priv->last),
2011
+ marvell_vct5_distance2cm(priv->step));
2012
+}
2013
+
2014
+static int marvell_vct7_distance_to_length(int distance, bool meter)
2015
+{
2016
+ if (meter)
2017
+ distance *= 100;
2018
+
2019
+ return distance;
2020
+}
2021
+
2022
+static bool marvell_vct7_distance_valid(int result)
2023
+{
2024
+ switch (result) {
2025
+ case MII_VCT7_RESULTS_OPEN:
2026
+ case MII_VCT7_RESULTS_SAME_SHORT:
2027
+ case MII_VCT7_RESULTS_CROSS_SHORT:
2028
+ return true;
2029
+ }
2030
+ return false;
2031
+}
2032
+
2033
+static int marvell_vct7_report_length(struct phy_device *phydev,
2034
+ int pair, bool meter)
2035
+{
2036
+ int length;
2037
+ int ret;
2038
+
2039
+ ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE,
2040
+ MII_VCT7_PAIR_0_DISTANCE + pair);
2041
+ if (ret < 0)
2042
+ return ret;
2043
+
2044
+ length = marvell_vct7_distance_to_length(ret, meter);
2045
+
2046
+ ethnl_cable_test_fault_length(phydev, pair, length);
2047
+
2048
+ return 0;
2049
+}
2050
+
2051
+static int marvell_vct7_cable_test_report_trans(int result)
2052
+{
2053
+ switch (result) {
2054
+ case MII_VCT7_RESULTS_OK:
2055
+ return ETHTOOL_A_CABLE_RESULT_CODE_OK;
2056
+ case MII_VCT7_RESULTS_OPEN:
2057
+ return ETHTOOL_A_CABLE_RESULT_CODE_OPEN;
2058
+ case MII_VCT7_RESULTS_SAME_SHORT:
2059
+ return ETHTOOL_A_CABLE_RESULT_CODE_SAME_SHORT;
2060
+ case MII_VCT7_RESULTS_CROSS_SHORT:
2061
+ return ETHTOOL_A_CABLE_RESULT_CODE_CROSS_SHORT;
2062
+ default:
2063
+ return ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
2064
+ }
2065
+}
2066
+
2067
+static int marvell_vct7_cable_test_report(struct phy_device *phydev)
2068
+{
2069
+ int pair0, pair1, pair2, pair3;
2070
+ bool meter;
2071
+ int ret;
2072
+
2073
+ ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE,
2074
+ MII_VCT7_RESULTS);
2075
+ if (ret < 0)
2076
+ return ret;
2077
+
2078
+ pair3 = (ret & MII_VCT7_RESULTS_PAIR3_MASK) >>
2079
+ MII_VCT7_RESULTS_PAIR3_SHIFT;
2080
+ pair2 = (ret & MII_VCT7_RESULTS_PAIR2_MASK) >>
2081
+ MII_VCT7_RESULTS_PAIR2_SHIFT;
2082
+ pair1 = (ret & MII_VCT7_RESULTS_PAIR1_MASK) >>
2083
+ MII_VCT7_RESULTS_PAIR1_SHIFT;
2084
+ pair0 = (ret & MII_VCT7_RESULTS_PAIR0_MASK) >>
2085
+ MII_VCT7_RESULTS_PAIR0_SHIFT;
2086
+
2087
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_A,
2088
+ marvell_vct7_cable_test_report_trans(pair0));
2089
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_B,
2090
+ marvell_vct7_cable_test_report_trans(pair1));
2091
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_C,
2092
+ marvell_vct7_cable_test_report_trans(pair2));
2093
+ ethnl_cable_test_result(phydev, ETHTOOL_A_CABLE_PAIR_D,
2094
+ marvell_vct7_cable_test_report_trans(pair3));
2095
+
2096
+ ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE, MII_VCT7_CTRL);
2097
+ if (ret < 0)
2098
+ return ret;
2099
+
2100
+ meter = ret & MII_VCT7_CTRL_METERS;
2101
+
2102
+ if (marvell_vct7_distance_valid(pair0))
2103
+ marvell_vct7_report_length(phydev, 0, meter);
2104
+ if (marvell_vct7_distance_valid(pair1))
2105
+ marvell_vct7_report_length(phydev, 1, meter);
2106
+ if (marvell_vct7_distance_valid(pair2))
2107
+ marvell_vct7_report_length(phydev, 2, meter);
2108
+ if (marvell_vct7_distance_valid(pair3))
2109
+ marvell_vct7_report_length(phydev, 3, meter);
2110
+
2111
+ return 0;
2112
+}
2113
+
2114
+static int marvell_vct7_cable_test_get_status(struct phy_device *phydev,
2115
+ bool *finished)
2116
+{
2117
+ struct marvell_priv *priv = phydev->priv;
2118
+ int ret;
2119
+
2120
+ if (priv->cable_test_tdr) {
2121
+ ret = marvell_vct5_amplitude_graph(phydev);
2122
+ *finished = true;
2123
+ return ret;
2124
+ }
2125
+
2126
+ *finished = false;
2127
+
2128
+ ret = phy_read_paged(phydev, MII_MARVELL_VCT7_PAGE,
2129
+ MII_VCT7_CTRL);
2130
+
2131
+ if (ret < 0)
2132
+ return ret;
2133
+
2134
+ if (!(ret & MII_VCT7_CTRL_IN_PROGRESS)) {
2135
+ *finished = true;
2136
+
2137
+ return marvell_vct7_cable_test_report(phydev);
2138
+ }
2139
+
2140
+ return 0;
15572141 }
15582142
15592143 #ifdef CONFIG_HWMON
....@@ -2053,15 +2637,14 @@
20532637 .phy_id = MARVELL_PHY_ID_88E1101,
20542638 .phy_id_mask = MARVELL_PHY_ID_MASK,
20552639 .name = "Marvell 88E1101",
2056
- .features = PHY_GBIT_FEATURES,
2057
- .flags = PHY_HAS_INTERRUPT,
2640
+ /* PHY_GBIT_FEATURES */
20582641 .probe = marvell_probe,
2059
- .config_init = &marvell_config_init,
2060
- .config_aneg = &m88e1101_config_aneg,
2061
- .ack_interrupt = &marvell_ack_interrupt,
2062
- .config_intr = &marvell_config_intr,
2063
- .resume = &genphy_resume,
2064
- .suspend = &genphy_suspend,
2642
+ .config_init = marvell_config_init,
2643
+ .config_aneg = m88e1101_config_aneg,
2644
+ .ack_interrupt = marvell_ack_interrupt,
2645
+ .config_intr = marvell_config_intr,
2646
+ .resume = genphy_resume,
2647
+ .suspend = genphy_suspend,
20652648 .read_page = marvell_read_page,
20662649 .write_page = marvell_write_page,
20672650 .get_sset_count = marvell_get_sset_count,
....@@ -2072,54 +2655,55 @@
20722655 .phy_id = MARVELL_PHY_ID_88E1112,
20732656 .phy_id_mask = MARVELL_PHY_ID_MASK,
20742657 .name = "Marvell 88E1112",
2075
- .features = PHY_GBIT_FEATURES,
2076
- .flags = PHY_HAS_INTERRUPT,
2658
+ /* PHY_GBIT_FEATURES */
20772659 .probe = marvell_probe,
2078
- .config_init = &m88e1111_config_init,
2079
- .config_aneg = &marvell_config_aneg,
2080
- .ack_interrupt = &marvell_ack_interrupt,
2081
- .config_intr = &marvell_config_intr,
2082
- .resume = &genphy_resume,
2083
- .suspend = &genphy_suspend,
2660
+ .config_init = m88e1111_config_init,
2661
+ .config_aneg = marvell_config_aneg,
2662
+ .ack_interrupt = marvell_ack_interrupt,
2663
+ .config_intr = marvell_config_intr,
2664
+ .resume = genphy_resume,
2665
+ .suspend = genphy_suspend,
20842666 .read_page = marvell_read_page,
20852667 .write_page = marvell_write_page,
20862668 .get_sset_count = marvell_get_sset_count,
20872669 .get_strings = marvell_get_strings,
20882670 .get_stats = marvell_get_stats,
2671
+ .get_tunable = m88e1011_get_tunable,
2672
+ .set_tunable = m88e1011_set_tunable,
20892673 },
20902674 {
20912675 .phy_id = MARVELL_PHY_ID_88E1111,
20922676 .phy_id_mask = MARVELL_PHY_ID_MASK,
20932677 .name = "Marvell 88E1111",
2094
- .features = PHY_GBIT_FEATURES,
2095
- .flags = PHY_HAS_INTERRUPT,
2678
+ /* PHY_GBIT_FEATURES */
20962679 .probe = marvell_probe,
2097
- .config_init = &m88e1111_config_init,
2098
- .config_aneg = &m88e1111_config_aneg,
2099
- .read_status = &marvell_read_status,
2100
- .ack_interrupt = &marvell_ack_interrupt,
2101
- .config_intr = &marvell_config_intr,
2102
- .resume = &genphy_resume,
2103
- .suspend = &genphy_suspend,
2680
+ .config_init = m88e1111_config_init,
2681
+ .config_aneg = marvell_config_aneg,
2682
+ .read_status = marvell_read_status,
2683
+ .ack_interrupt = marvell_ack_interrupt,
2684
+ .config_intr = marvell_config_intr,
2685
+ .resume = genphy_resume,
2686
+ .suspend = genphy_suspend,
21042687 .read_page = marvell_read_page,
21052688 .write_page = marvell_write_page,
21062689 .get_sset_count = marvell_get_sset_count,
21072690 .get_strings = marvell_get_strings,
21082691 .get_stats = marvell_get_stats,
2692
+ .get_tunable = m88e1111_get_tunable,
2693
+ .set_tunable = m88e1111_set_tunable,
21092694 },
21102695 {
21112696 .phy_id = MARVELL_PHY_ID_88E1118,
21122697 .phy_id_mask = MARVELL_PHY_ID_MASK,
21132698 .name = "Marvell 88E1118",
2114
- .features = PHY_GBIT_FEATURES,
2115
- .flags = PHY_HAS_INTERRUPT,
2699
+ /* PHY_GBIT_FEATURES */
21162700 .probe = marvell_probe,
2117
- .config_init = &m88e1118_config_init,
2118
- .config_aneg = &m88e1118_config_aneg,
2119
- .ack_interrupt = &marvell_ack_interrupt,
2120
- .config_intr = &marvell_config_intr,
2121
- .resume = &genphy_resume,
2122
- .suspend = &genphy_suspend,
2701
+ .config_init = m88e1118_config_init,
2702
+ .config_aneg = m88e1118_config_aneg,
2703
+ .ack_interrupt = marvell_ack_interrupt,
2704
+ .config_intr = marvell_config_intr,
2705
+ .resume = genphy_resume,
2706
+ .suspend = genphy_suspend,
21232707 .read_page = marvell_read_page,
21242708 .write_page = marvell_write_page,
21252709 .get_sset_count = marvell_get_sset_count,
....@@ -2130,40 +2714,40 @@
21302714 .phy_id = MARVELL_PHY_ID_88E1121R,
21312715 .phy_id_mask = MARVELL_PHY_ID_MASK,
21322716 .name = "Marvell 88E1121R",
2133
- .features = PHY_GBIT_FEATURES,
2134
- .flags = PHY_HAS_INTERRUPT,
2135
- .probe = &m88e1121_probe,
2136
- .config_init = &marvell_config_init,
2137
- .config_aneg = &m88e1121_config_aneg,
2138
- .read_status = &marvell_read_status,
2139
- .ack_interrupt = &marvell_ack_interrupt,
2140
- .config_intr = &marvell_config_intr,
2141
- .did_interrupt = &m88e1121_did_interrupt,
2142
- .resume = &genphy_resume,
2143
- .suspend = &genphy_suspend,
2717
+ /* PHY_GBIT_FEATURES */
2718
+ .probe = m88e1121_probe,
2719
+ .config_init = marvell_config_init,
2720
+ .config_aneg = m88e1121_config_aneg,
2721
+ .read_status = marvell_read_status,
2722
+ .ack_interrupt = marvell_ack_interrupt,
2723
+ .config_intr = marvell_config_intr,
2724
+ .did_interrupt = m88e1121_did_interrupt,
2725
+ .resume = genphy_resume,
2726
+ .suspend = genphy_suspend,
21442727 .read_page = marvell_read_page,
21452728 .write_page = marvell_write_page,
21462729 .get_sset_count = marvell_get_sset_count,
21472730 .get_strings = marvell_get_strings,
21482731 .get_stats = marvell_get_stats,
2732
+ .get_tunable = m88e1011_get_tunable,
2733
+ .set_tunable = m88e1011_set_tunable,
21492734 },
21502735 {
21512736 .phy_id = MARVELL_PHY_ID_88E1318S,
21522737 .phy_id_mask = MARVELL_PHY_ID_MASK,
21532738 .name = "Marvell 88E1318S",
2154
- .features = PHY_GBIT_FEATURES,
2155
- .flags = PHY_HAS_INTERRUPT,
2739
+ /* PHY_GBIT_FEATURES */
21562740 .probe = marvell_probe,
2157
- .config_init = &m88e1318_config_init,
2158
- .config_aneg = &m88e1318_config_aneg,
2159
- .read_status = &marvell_read_status,
2160
- .ack_interrupt = &marvell_ack_interrupt,
2161
- .config_intr = &marvell_config_intr,
2162
- .did_interrupt = &m88e1121_did_interrupt,
2163
- .get_wol = &m88e1318_get_wol,
2164
- .set_wol = &m88e1318_set_wol,
2165
- .resume = &genphy_resume,
2166
- .suspend = &genphy_suspend,
2741
+ .config_init = m88e1318_config_init,
2742
+ .config_aneg = m88e1318_config_aneg,
2743
+ .read_status = marvell_read_status,
2744
+ .ack_interrupt = marvell_ack_interrupt,
2745
+ .config_intr = marvell_config_intr,
2746
+ .did_interrupt = m88e1121_did_interrupt,
2747
+ .get_wol = m88e1318_get_wol,
2748
+ .set_wol = m88e1318_set_wol,
2749
+ .resume = genphy_resume,
2750
+ .suspend = genphy_suspend,
21672751 .read_page = marvell_read_page,
21682752 .write_page = marvell_write_page,
21692753 .get_sset_count = marvell_get_sset_count,
....@@ -2174,35 +2758,35 @@
21742758 .phy_id = MARVELL_PHY_ID_88E1145,
21752759 .phy_id_mask = MARVELL_PHY_ID_MASK,
21762760 .name = "Marvell 88E1145",
2177
- .features = PHY_GBIT_FEATURES,
2178
- .flags = PHY_HAS_INTERRUPT,
2761
+ /* PHY_GBIT_FEATURES */
21792762 .probe = marvell_probe,
2180
- .config_init = &m88e1145_config_init,
2181
- .config_aneg = &m88e1101_config_aneg,
2182
- .read_status = &genphy_read_status,
2183
- .ack_interrupt = &marvell_ack_interrupt,
2184
- .config_intr = &marvell_config_intr,
2185
- .resume = &genphy_resume,
2186
- .suspend = &genphy_suspend,
2763
+ .config_init = m88e1145_config_init,
2764
+ .config_aneg = m88e1101_config_aneg,
2765
+ .read_status = genphy_read_status,
2766
+ .ack_interrupt = marvell_ack_interrupt,
2767
+ .config_intr = marvell_config_intr,
2768
+ .resume = genphy_resume,
2769
+ .suspend = genphy_suspend,
21872770 .read_page = marvell_read_page,
21882771 .write_page = marvell_write_page,
21892772 .get_sset_count = marvell_get_sset_count,
21902773 .get_strings = marvell_get_strings,
21912774 .get_stats = marvell_get_stats,
2775
+ .get_tunable = m88e1111_get_tunable,
2776
+ .set_tunable = m88e1111_set_tunable,
21922777 },
21932778 {
21942779 .phy_id = MARVELL_PHY_ID_88E1149R,
21952780 .phy_id_mask = MARVELL_PHY_ID_MASK,
21962781 .name = "Marvell 88E1149R",
2197
- .features = PHY_GBIT_FEATURES,
2198
- .flags = PHY_HAS_INTERRUPT,
2782
+ /* PHY_GBIT_FEATURES */
21992783 .probe = marvell_probe,
2200
- .config_init = &m88e1149_config_init,
2201
- .config_aneg = &m88e1118_config_aneg,
2202
- .ack_interrupt = &marvell_ack_interrupt,
2203
- .config_intr = &marvell_config_intr,
2204
- .resume = &genphy_resume,
2205
- .suspend = &genphy_suspend,
2784
+ .config_init = m88e1149_config_init,
2785
+ .config_aneg = m88e1118_config_aneg,
2786
+ .ack_interrupt = marvell_ack_interrupt,
2787
+ .config_intr = marvell_config_intr,
2788
+ .resume = genphy_resume,
2789
+ .suspend = genphy_suspend,
22062790 .read_page = marvell_read_page,
22072791 .write_page = marvell_write_page,
22082792 .get_sset_count = marvell_get_sset_count,
....@@ -2213,15 +2797,14 @@
22132797 .phy_id = MARVELL_PHY_ID_88E1240,
22142798 .phy_id_mask = MARVELL_PHY_ID_MASK,
22152799 .name = "Marvell 88E1240",
2216
- .features = PHY_GBIT_FEATURES,
2217
- .flags = PHY_HAS_INTERRUPT,
2800
+ /* PHY_GBIT_FEATURES */
22182801 .probe = marvell_probe,
2219
- .config_init = &m88e1111_config_init,
2220
- .config_aneg = &marvell_config_aneg,
2221
- .ack_interrupt = &marvell_ack_interrupt,
2222
- .config_intr = &marvell_config_intr,
2223
- .resume = &genphy_resume,
2224
- .suspend = &genphy_suspend,
2802
+ .config_init = m88e1111_config_init,
2803
+ .config_aneg = marvell_config_aneg,
2804
+ .ack_interrupt = marvell_ack_interrupt,
2805
+ .config_intr = marvell_config_intr,
2806
+ .resume = genphy_resume,
2807
+ .suspend = genphy_suspend,
22252808 .read_page = marvell_read_page,
22262809 .write_page = marvell_write_page,
22272810 .get_sset_count = marvell_get_sset_count,
....@@ -2232,101 +2815,116 @@
22322815 .phy_id = MARVELL_PHY_ID_88E1116R,
22332816 .phy_id_mask = MARVELL_PHY_ID_MASK,
22342817 .name = "Marvell 88E1116R",
2235
- .features = PHY_GBIT_FEATURES,
2236
- .flags = PHY_HAS_INTERRUPT,
2818
+ /* PHY_GBIT_FEATURES */
22372819 .probe = marvell_probe,
2238
- .config_init = &m88e1116r_config_init,
2239
- .ack_interrupt = &marvell_ack_interrupt,
2240
- .config_intr = &marvell_config_intr,
2241
- .resume = &genphy_resume,
2242
- .suspend = &genphy_suspend,
2820
+ .config_init = m88e1116r_config_init,
2821
+ .ack_interrupt = marvell_ack_interrupt,
2822
+ .config_intr = marvell_config_intr,
2823
+ .resume = genphy_resume,
2824
+ .suspend = genphy_suspend,
22432825 .read_page = marvell_read_page,
22442826 .write_page = marvell_write_page,
22452827 .get_sset_count = marvell_get_sset_count,
22462828 .get_strings = marvell_get_strings,
22472829 .get_stats = marvell_get_stats,
2830
+ .get_tunable = m88e1011_get_tunable,
2831
+ .set_tunable = m88e1011_set_tunable,
22482832 },
22492833 {
22502834 .phy_id = MARVELL_PHY_ID_88E1510,
22512835 .phy_id_mask = MARVELL_PHY_ID_MASK,
22522836 .name = "Marvell 88E1510",
2253
- .features = PHY_GBIT_FEATURES | SUPPORTED_FIBRE,
2254
- .flags = PHY_HAS_INTERRUPT,
2255
- .probe = &m88e1510_probe,
2256
- .config_init = &m88e1510_config_init,
2257
- .config_aneg = &m88e1510_config_aneg,
2258
- .read_status = &marvell_read_status,
2259
- .ack_interrupt = &marvell_ack_interrupt,
2260
- .config_intr = &marvell_config_intr,
2261
- .did_interrupt = &m88e1121_did_interrupt,
2262
- .get_wol = &m88e1318_get_wol,
2263
- .set_wol = &m88e1318_set_wol,
2264
- .resume = &marvell_resume,
2265
- .suspend = &marvell_suspend,
2837
+ .features = PHY_GBIT_FIBRE_FEATURES,
2838
+ .flags = PHY_POLL_CABLE_TEST,
2839
+ .probe = m88e1510_probe,
2840
+ .config_init = m88e1510_config_init,
2841
+ .config_aneg = m88e1510_config_aneg,
2842
+ .read_status = marvell_read_status,
2843
+ .ack_interrupt = marvell_ack_interrupt,
2844
+ .config_intr = marvell_config_intr,
2845
+ .did_interrupt = m88e1121_did_interrupt,
2846
+ .get_wol = m88e1318_get_wol,
2847
+ .set_wol = m88e1318_set_wol,
2848
+ .resume = marvell_resume,
2849
+ .suspend = marvell_suspend,
22662850 .read_page = marvell_read_page,
22672851 .write_page = marvell_write_page,
22682852 .get_sset_count = marvell_get_sset_count,
22692853 .get_strings = marvell_get_strings,
22702854 .get_stats = marvell_get_stats,
22712855 .set_loopback = genphy_loopback,
2856
+ .get_tunable = m88e1011_get_tunable,
2857
+ .set_tunable = m88e1011_set_tunable,
2858
+ .cable_test_start = marvell_vct7_cable_test_start,
2859
+ .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
2860
+ .cable_test_get_status = marvell_vct7_cable_test_get_status,
22722861 },
22732862 {
22742863 .phy_id = MARVELL_PHY_ID_88E1540,
22752864 .phy_id_mask = MARVELL_PHY_ID_MASK,
22762865 .name = "Marvell 88E1540",
2277
- .features = PHY_GBIT_FEATURES,
2278
- .flags = PHY_HAS_INTERRUPT,
2866
+ /* PHY_GBIT_FEATURES */
2867
+ .flags = PHY_POLL_CABLE_TEST,
22792868 .probe = m88e1510_probe,
2280
- .config_init = &marvell_config_init,
2281
- .config_aneg = &m88e1510_config_aneg,
2282
- .read_status = &marvell_read_status,
2283
- .ack_interrupt = &marvell_ack_interrupt,
2284
- .config_intr = &marvell_config_intr,
2285
- .did_interrupt = &m88e1121_did_interrupt,
2286
- .resume = &genphy_resume,
2287
- .suspend = &genphy_suspend,
2869
+ .config_init = marvell_config_init,
2870
+ .config_aneg = m88e1510_config_aneg,
2871
+ .read_status = marvell_read_status,
2872
+ .ack_interrupt = marvell_ack_interrupt,
2873
+ .config_intr = marvell_config_intr,
2874
+ .did_interrupt = m88e1121_did_interrupt,
2875
+ .resume = genphy_resume,
2876
+ .suspend = genphy_suspend,
22882877 .read_page = marvell_read_page,
22892878 .write_page = marvell_write_page,
22902879 .get_sset_count = marvell_get_sset_count,
22912880 .get_strings = marvell_get_strings,
22922881 .get_stats = marvell_get_stats,
2882
+ .get_tunable = m88e1540_get_tunable,
2883
+ .set_tunable = m88e1540_set_tunable,
2884
+ .cable_test_start = marvell_vct7_cable_test_start,
2885
+ .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
2886
+ .cable_test_get_status = marvell_vct7_cable_test_get_status,
22932887 },
22942888 {
22952889 .phy_id = MARVELL_PHY_ID_88E1545,
22962890 .phy_id_mask = MARVELL_PHY_ID_MASK,
22972891 .name = "Marvell 88E1545",
22982892 .probe = m88e1510_probe,
2299
- .features = PHY_GBIT_FEATURES,
2300
- .flags = PHY_HAS_INTERRUPT,
2301
- .config_init = &marvell_config_init,
2302
- .config_aneg = &m88e1510_config_aneg,
2303
- .read_status = &marvell_read_status,
2304
- .ack_interrupt = &marvell_ack_interrupt,
2305
- .config_intr = &marvell_config_intr,
2306
- .did_interrupt = &m88e1121_did_interrupt,
2307
- .resume = &genphy_resume,
2308
- .suspend = &genphy_suspend,
2893
+ /* PHY_GBIT_FEATURES */
2894
+ .flags = PHY_POLL_CABLE_TEST,
2895
+ .config_init = marvell_config_init,
2896
+ .config_aneg = m88e1510_config_aneg,
2897
+ .read_status = marvell_read_status,
2898
+ .ack_interrupt = marvell_ack_interrupt,
2899
+ .config_intr = marvell_config_intr,
2900
+ .did_interrupt = m88e1121_did_interrupt,
2901
+ .resume = genphy_resume,
2902
+ .suspend = genphy_suspend,
23092903 .read_page = marvell_read_page,
23102904 .write_page = marvell_write_page,
23112905 .get_sset_count = marvell_get_sset_count,
23122906 .get_strings = marvell_get_strings,
23132907 .get_stats = marvell_get_stats,
2908
+ .get_tunable = m88e1540_get_tunable,
2909
+ .set_tunable = m88e1540_set_tunable,
2910
+ .cable_test_start = marvell_vct7_cable_test_start,
2911
+ .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
2912
+ .cable_test_get_status = marvell_vct7_cable_test_get_status,
23142913 },
23152914 {
23162915 .phy_id = MARVELL_PHY_ID_88E3016,
23172916 .phy_id_mask = MARVELL_PHY_ID_MASK,
23182917 .name = "Marvell 88E3016",
2319
- .features = PHY_BASIC_FEATURES,
2320
- .flags = PHY_HAS_INTERRUPT,
2918
+ /* PHY_BASIC_FEATURES */
23212919 .probe = marvell_probe,
2322
- .config_init = &m88e3016_config_init,
2323
- .aneg_done = &marvell_aneg_done,
2324
- .read_status = &marvell_read_status,
2325
- .ack_interrupt = &marvell_ack_interrupt,
2326
- .config_intr = &marvell_config_intr,
2327
- .did_interrupt = &m88e1121_did_interrupt,
2328
- .resume = &genphy_resume,
2329
- .suspend = &genphy_suspend,
2920
+ .config_init = m88e3016_config_init,
2921
+ .aneg_done = marvell_aneg_done,
2922
+ .read_status = marvell_read_status,
2923
+ .ack_interrupt = marvell_ack_interrupt,
2924
+ .config_intr = marvell_config_intr,
2925
+ .did_interrupt = m88e1121_did_interrupt,
2926
+ .resume = genphy_resume,
2927
+ .suspend = genphy_suspend,
23302928 .read_page = marvell_read_page,
23312929 .write_page = marvell_write_page,
23322930 .get_sset_count = marvell_get_sset_count,
....@@ -2337,43 +2935,97 @@
23372935 .phy_id = MARVELL_PHY_ID_88E6341_FAMILY,
23382936 .phy_id_mask = MARVELL_PHY_ID_MASK,
23392937 .name = "Marvell 88E6341 Family",
2340
- .features = PHY_GBIT_FEATURES,
2341
- .flags = PHY_HAS_INTERRUPT,
2938
+ /* PHY_GBIT_FEATURES */
2939
+ .flags = PHY_POLL_CABLE_TEST,
23422940 .probe = m88e1510_probe,
2343
- .config_init = &marvell_config_init,
2344
- .config_aneg = &m88e6390_config_aneg,
2345
- .read_status = &marvell_read_status,
2346
- .ack_interrupt = &marvell_ack_interrupt,
2347
- .config_intr = &marvell_config_intr,
2348
- .did_interrupt = &m88e1121_did_interrupt,
2349
- .resume = &genphy_resume,
2350
- .suspend = &genphy_suspend,
2941
+ .config_init = marvell_config_init,
2942
+ .config_aneg = m88e6390_config_aneg,
2943
+ .read_status = marvell_read_status,
2944
+ .ack_interrupt = marvell_ack_interrupt,
2945
+ .config_intr = marvell_config_intr,
2946
+ .did_interrupt = m88e1121_did_interrupt,
2947
+ .resume = genphy_resume,
2948
+ .suspend = genphy_suspend,
23512949 .read_page = marvell_read_page,
23522950 .write_page = marvell_write_page,
23532951 .get_sset_count = marvell_get_sset_count,
23542952 .get_strings = marvell_get_strings,
23552953 .get_stats = marvell_get_stats,
2954
+ .get_tunable = m88e1540_get_tunable,
2955
+ .set_tunable = m88e1540_set_tunable,
2956
+ .cable_test_start = marvell_vct7_cable_test_start,
2957
+ .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
2958
+ .cable_test_get_status = marvell_vct7_cable_test_get_status,
23562959 },
23572960 {
23582961 .phy_id = MARVELL_PHY_ID_88E6390_FAMILY,
23592962 .phy_id_mask = MARVELL_PHY_ID_MASK,
23602963 .name = "Marvell 88E6390 Family",
2361
- .features = PHY_GBIT_FEATURES,
2362
- .flags = PHY_HAS_INTERRUPT,
2964
+ /* PHY_GBIT_FEATURES */
2965
+ .flags = PHY_POLL_CABLE_TEST,
23632966 .probe = m88e6390_probe,
2364
- .config_init = &marvell_config_init,
2365
- .config_aneg = &m88e6390_config_aneg,
2366
- .read_status = &marvell_read_status,
2367
- .ack_interrupt = &marvell_ack_interrupt,
2368
- .config_intr = &marvell_config_intr,
2369
- .did_interrupt = &m88e1121_did_interrupt,
2370
- .resume = &genphy_resume,
2371
- .suspend = &genphy_suspend,
2967
+ .config_init = marvell_config_init,
2968
+ .config_aneg = m88e6390_config_aneg,
2969
+ .read_status = marvell_read_status,
2970
+ .ack_interrupt = marvell_ack_interrupt,
2971
+ .config_intr = marvell_config_intr,
2972
+ .did_interrupt = m88e1121_did_interrupt,
2973
+ .resume = genphy_resume,
2974
+ .suspend = genphy_suspend,
23722975 .read_page = marvell_read_page,
23732976 .write_page = marvell_write_page,
23742977 .get_sset_count = marvell_get_sset_count,
23752978 .get_strings = marvell_get_strings,
23762979 .get_stats = marvell_get_stats,
2980
+ .get_tunable = m88e1540_get_tunable,
2981
+ .set_tunable = m88e1540_set_tunable,
2982
+ .cable_test_start = marvell_vct7_cable_test_start,
2983
+ .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start,
2984
+ .cable_test_get_status = marvell_vct7_cable_test_get_status,
2985
+ },
2986
+ {
2987
+ .phy_id = MARVELL_PHY_ID_88E1340S,
2988
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
2989
+ .name = "Marvell 88E1340S",
2990
+ .probe = m88e1510_probe,
2991
+ /* PHY_GBIT_FEATURES */
2992
+ .config_init = marvell_config_init,
2993
+ .config_aneg = m88e1510_config_aneg,
2994
+ .read_status = marvell_read_status,
2995
+ .ack_interrupt = marvell_ack_interrupt,
2996
+ .config_intr = marvell_config_intr,
2997
+ .did_interrupt = m88e1121_did_interrupt,
2998
+ .resume = genphy_resume,
2999
+ .suspend = genphy_suspend,
3000
+ .read_page = marvell_read_page,
3001
+ .write_page = marvell_write_page,
3002
+ .get_sset_count = marvell_get_sset_count,
3003
+ .get_strings = marvell_get_strings,
3004
+ .get_stats = marvell_get_stats,
3005
+ .get_tunable = m88e1540_get_tunable,
3006
+ .set_tunable = m88e1540_set_tunable,
3007
+ },
3008
+ {
3009
+ .phy_id = MARVELL_PHY_ID_88E1548P,
3010
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
3011
+ .name = "Marvell 88E1548P",
3012
+ .probe = m88e1510_probe,
3013
+ .features = PHY_GBIT_FIBRE_FEATURES,
3014
+ .config_init = marvell_config_init,
3015
+ .config_aneg = m88e1510_config_aneg,
3016
+ .read_status = marvell_read_status,
3017
+ .ack_interrupt = marvell_ack_interrupt,
3018
+ .config_intr = marvell_config_intr,
3019
+ .did_interrupt = m88e1121_did_interrupt,
3020
+ .resume = genphy_resume,
3021
+ .suspend = genphy_suspend,
3022
+ .read_page = marvell_read_page,
3023
+ .write_page = marvell_write_page,
3024
+ .get_sset_count = marvell_get_sset_count,
3025
+ .get_strings = marvell_get_strings,
3026
+ .get_stats = marvell_get_stats,
3027
+ .get_tunable = m88e1540_get_tunable,
3028
+ .set_tunable = m88e1540_set_tunable,
23773029 },
23783030 };
23793031
....@@ -2396,6 +3048,8 @@
23963048 { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK },
23973049 { MARVELL_PHY_ID_88E6341_FAMILY, MARVELL_PHY_ID_MASK },
23983050 { MARVELL_PHY_ID_88E6390_FAMILY, MARVELL_PHY_ID_MASK },
3051
+ { MARVELL_PHY_ID_88E1340S, MARVELL_PHY_ID_MASK },
3052
+ { MARVELL_PHY_ID_88E1548P, MARVELL_PHY_ID_MASK },
23993053 { }
24003054 };
24013055