hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
kernel/drivers/net/phy/marvell10g.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * Marvell 10G 88x3310 PHY driver
34 *
....@@ -22,11 +23,18 @@
2223 * link takes priority and the other port is completely locked out.
2324 */
2425 #include <linux/ctype.h>
26
+#include <linux/delay.h>
2527 #include <linux/hwmon.h>
2628 #include <linux/marvell_phy.h>
2729 #include <linux/phy.h>
30
+#include <linux/sfp.h>
31
+
32
+#define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe
33
+#define MV_PHY_ALASKA_NBT_QUIRK_REV (MARVELL_PHY_ID_88X3310 | 0xa)
2834
2935 enum {
36
+ MV_PMA_FW_VER0 = 0xc011,
37
+ MV_PMA_FW_VER1 = 0xc012,
3038 MV_PMA_BOOT = 0xc050,
3139 MV_PMA_BOOT_FATAL = BIT(0),
3240
....@@ -34,10 +42,32 @@
3442 MV_PCS_BASE_R = 0x1000,
3543 MV_PCS_1000BASEX = 0x2000,
3644
37
- MV_PCS_PAIRSWAP = 0x8182,
38
- MV_PCS_PAIRSWAP_MASK = 0x0003,
39
- MV_PCS_PAIRSWAP_AB = 0x0002,
40
- MV_PCS_PAIRSWAP_NONE = 0x0003,
45
+ MV_PCS_CSCR1 = 0x8000,
46
+ MV_PCS_CSCR1_ED_MASK = 0x0300,
47
+ MV_PCS_CSCR1_ED_OFF = 0x0000,
48
+ MV_PCS_CSCR1_ED_RX = 0x0200,
49
+ MV_PCS_CSCR1_ED_NLP = 0x0300,
50
+ MV_PCS_CSCR1_MDIX_MASK = 0x0060,
51
+ MV_PCS_CSCR1_MDIX_MDI = 0x0000,
52
+ MV_PCS_CSCR1_MDIX_MDIX = 0x0020,
53
+ MV_PCS_CSCR1_MDIX_AUTO = 0x0060,
54
+
55
+ MV_PCS_CSSR1 = 0x8008,
56
+ MV_PCS_CSSR1_SPD1_MASK = 0xc000,
57
+ MV_PCS_CSSR1_SPD1_SPD2 = 0xc000,
58
+ MV_PCS_CSSR1_SPD1_1000 = 0x8000,
59
+ MV_PCS_CSSR1_SPD1_100 = 0x4000,
60
+ MV_PCS_CSSR1_SPD1_10 = 0x0000,
61
+ MV_PCS_CSSR1_DUPLEX_FULL= BIT(13),
62
+ MV_PCS_CSSR1_RESOLVED = BIT(11),
63
+ MV_PCS_CSSR1_MDIX = BIT(6),
64
+ MV_PCS_CSSR1_SPD2_MASK = 0x000c,
65
+ MV_PCS_CSSR1_SPD2_5000 = 0x0008,
66
+ MV_PCS_CSSR1_SPD2_2500 = 0x0004,
67
+ MV_PCS_CSSR1_SPD2_10000 = 0x0000,
68
+
69
+ /* Temperature read register (88E2110 only) */
70
+ MV_PCS_TEMP = 0x8042,
4171
4272 /* These registers appear at 0x800X and 0xa00X - the 0xa00X control
4373 * registers appear to set themselves to the 0x800X when AN is
....@@ -47,6 +77,12 @@
4777 MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */
4878
4979 /* Vendor2 MMD registers */
80
+ MV_V2_PORT_CTRL = 0xf001,
81
+ MV_V2_PORT_CTRL_SWRST = BIT(15),
82
+ MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
83
+ MV_V2_PORT_MAC_TYPE_MASK = 0x7,
84
+ MV_V2_PORT_MAC_TYPE_RATE_MATCH = 0x6,
85
+ /* Temperature control/read registers (88X3310 only) */
5086 MV_V2_TEMP_CTRL = 0xf08a,
5187 MV_V2_TEMP_CTRL_MASK = 0xc000,
5288 MV_V2_TEMP_CTRL_SAMPLE = 0x0000,
....@@ -56,27 +92,12 @@
5692 };
5793
5894 struct mv3310_priv {
95
+ u32 firmware_ver;
96
+ bool rate_match;
97
+
5998 struct device *hwmon_dev;
6099 char *hwmon_name;
61100 };
62
-
63
-static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
64
- u16 mask, u16 bits)
65
-{
66
- int old, val, ret;
67
-
68
- old = phy_read_mmd(phydev, devad, reg);
69
- if (old < 0)
70
- return old;
71
-
72
- val = (old & ~mask) | (bits & mask);
73
- if (val == old)
74
- return 0;
75
-
76
- ret = phy_write_mmd(phydev, devad, reg, val);
77
-
78
- return ret < 0 ? ret : 1;
79
-}
80101
81102 #ifdef CONFIG_HWMON
82103 static umode_t mv3310_hwmon_is_visible(const void *data,
....@@ -88,6 +109,24 @@
88109 if (type == hwmon_temp && attr == hwmon_temp_input)
89110 return 0444;
90111 return 0;
112
+}
113
+
114
+static int mv3310_hwmon_read_temp_reg(struct phy_device *phydev)
115
+{
116
+ return phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
117
+}
118
+
119
+static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev)
120
+{
121
+ return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP);
122
+}
123
+
124
+static int mv10g_hwmon_read_temp_reg(struct phy_device *phydev)
125
+{
126
+ if (phydev->drv->phy_id == MARVELL_PHY_ID_88X3310)
127
+ return mv3310_hwmon_read_temp_reg(phydev);
128
+ else /* MARVELL_PHY_ID_88E2110 */
129
+ return mv2110_hwmon_read_temp_reg(phydev);
91130 }
92131
93132 static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
....@@ -102,7 +141,7 @@
102141 }
103142
104143 if (type == hwmon_temp && attr == hwmon_temp_input) {
105
- temp = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
144
+ temp = mv10g_hwmon_read_temp_reg(phydev);
106145 if (temp < 0)
107146 return temp;
108147
....@@ -155,23 +194,18 @@
155194 u16 val;
156195 int ret;
157196
197
+ if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310)
198
+ return 0;
199
+
158200 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
159201 MV_V2_TEMP_UNKNOWN);
160202 if (ret < 0)
161203 return ret;
162204
163205 val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
164
- ret = mv3310_modify(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
165
- MV_V2_TEMP_CTRL_MASK, val);
166206
167
- return ret < 0 ? ret : 0;
168
-}
169
-
170
-static void mv3310_hwmon_disable(void *data)
171
-{
172
- struct phy_device *phydev = data;
173
-
174
- mv3310_hwmon_config(phydev, false);
207
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
208
+ MV_V2_TEMP_CTRL_MASK, val);
175209 }
176210
177211 static int mv3310_hwmon_probe(struct phy_device *phydev)
....@@ -197,10 +231,6 @@
197231 if (ret)
198232 return ret;
199233
200
- ret = devm_add_action_or_reset(dev, mv3310_hwmon_disable, phydev);
201
- if (ret)
202
- return ret;
203
-
204234 priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
205235 priv->hwmon_name, phydev,
206236 &mv3310_hwmon_chip_info, NULL);
....@@ -218,6 +248,118 @@
218248 return 0;
219249 }
220250 #endif
251
+
252
+static int mv3310_power_down(struct phy_device *phydev)
253
+{
254
+ return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
255
+ MV_V2_PORT_CTRL_PWRDOWN);
256
+}
257
+
258
+static int mv3310_power_up(struct phy_device *phydev)
259
+{
260
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
261
+ int ret;
262
+
263
+ ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
264
+ MV_V2_PORT_CTRL_PWRDOWN);
265
+
266
+ if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
267
+ priv->firmware_ver < 0x00030000)
268
+ return ret;
269
+
270
+ return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
271
+ MV_V2_PORT_CTRL_SWRST);
272
+}
273
+
274
+static int mv3310_reset(struct phy_device *phydev, u32 unit)
275
+{
276
+ int val, err;
277
+
278
+ err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
279
+ MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
280
+ if (err < 0)
281
+ return err;
282
+
283
+ return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
284
+ unit + MDIO_CTRL1, val,
285
+ !(val & MDIO_CTRL1_RESET),
286
+ 5000, 100000, true);
287
+}
288
+
289
+static int mv3310_get_edpd(struct phy_device *phydev, u16 *edpd)
290
+{
291
+ int val;
292
+
293
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1);
294
+ if (val < 0)
295
+ return val;
296
+
297
+ switch (val & MV_PCS_CSCR1_ED_MASK) {
298
+ case MV_PCS_CSCR1_ED_NLP:
299
+ *edpd = 1000;
300
+ break;
301
+ case MV_PCS_CSCR1_ED_RX:
302
+ *edpd = ETHTOOL_PHY_EDPD_NO_TX;
303
+ break;
304
+ default:
305
+ *edpd = ETHTOOL_PHY_EDPD_DISABLE;
306
+ break;
307
+ }
308
+ return 0;
309
+}
310
+
311
+static int mv3310_set_edpd(struct phy_device *phydev, u16 edpd)
312
+{
313
+ u16 val;
314
+ int err;
315
+
316
+ switch (edpd) {
317
+ case 1000:
318
+ case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
319
+ val = MV_PCS_CSCR1_ED_NLP;
320
+ break;
321
+
322
+ case ETHTOOL_PHY_EDPD_NO_TX:
323
+ val = MV_PCS_CSCR1_ED_RX;
324
+ break;
325
+
326
+ case ETHTOOL_PHY_EDPD_DISABLE:
327
+ val = MV_PCS_CSCR1_ED_OFF;
328
+ break;
329
+
330
+ default:
331
+ return -EINVAL;
332
+ }
333
+
334
+ err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
335
+ MV_PCS_CSCR1_ED_MASK, val);
336
+ if (err > 0)
337
+ err = mv3310_reset(phydev, MV_PCS_BASE_T);
338
+
339
+ return err;
340
+}
341
+
342
+static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
343
+{
344
+ struct phy_device *phydev = upstream;
345
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
346
+ phy_interface_t iface;
347
+
348
+ sfp_parse_support(phydev->sfp_bus, id, support);
349
+ iface = sfp_select_interface(phydev->sfp_bus, support);
350
+
351
+ if (iface != PHY_INTERFACE_MODE_10GBASER) {
352
+ dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
353
+ return -EINVAL;
354
+ }
355
+ return 0;
356
+}
357
+
358
+static const struct sfp_upstream_ops mv3310_sfp_ops = {
359
+ .attach = phy_sfp_attach,
360
+ .detach = phy_sfp_detach,
361
+ .module_insert = mv3310_sfp_insert,
362
+};
221363
222364 static int mv3310_probe(struct phy_device *phydev)
223365 {
....@@ -245,172 +387,187 @@
245387
246388 dev_set_drvdata(&phydev->mdio.dev, priv);
247389
390
+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
391
+ if (ret < 0)
392
+ return ret;
393
+
394
+ priv->firmware_ver = ret << 16;
395
+
396
+ ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
397
+ if (ret < 0)
398
+ return ret;
399
+
400
+ priv->firmware_ver |= ret;
401
+
402
+ phydev_info(phydev, "Firmware version %u.%u.%u.%u\n",
403
+ priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
404
+ (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
405
+
406
+ /* Powering down the port when not in use saves about 600mW */
407
+ ret = mv3310_power_down(phydev);
408
+ if (ret)
409
+ return ret;
410
+
248411 ret = mv3310_hwmon_probe(phydev);
249412 if (ret)
250413 return ret;
251414
252
- return 0;
415
+ return phy_sfp_probe(phydev, &mv3310_sfp_ops);
416
+}
417
+
418
+static void mv3310_remove(struct phy_device *phydev)
419
+{
420
+ mv3310_hwmon_config(phydev, false);
253421 }
254422
255423 static int mv3310_suspend(struct phy_device *phydev)
256424 {
257
- return 0;
425
+ return mv3310_power_down(phydev);
258426 }
259427
260428 static int mv3310_resume(struct phy_device *phydev)
261429 {
430
+ int ret;
431
+
432
+ ret = mv3310_power_up(phydev);
433
+ if (ret)
434
+ return ret;
435
+
262436 return mv3310_hwmon_config(phydev, true);
437
+}
438
+
439
+/* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010
440
+ * don't set bit 14 in PMA Extended Abilities (1.11), although they do
441
+ * support 2.5GBASET and 5GBASET. For these models, we can still read their
442
+ * 2.5G/5G extended abilities register (1.21). We detect these models based on
443
+ * the PMA device identifier, with a mask matching models known to have this
444
+ * issue
445
+ */
446
+static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
447
+{
448
+ if (!(phydev->c45_ids.devices_in_package & MDIO_DEVS_PMAPMD))
449
+ return false;
450
+
451
+ /* Only some revisions of the 88X3310 family PMA seem to be impacted */
452
+ return (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
453
+ MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
263454 }
264455
265456 static int mv3310_config_init(struct phy_device *phydev)
266457 {
267
- __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
268
- u32 mask;
458
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
459
+ int err;
269460 int val;
270461
271462 /* Check that the PHY interface type is compatible */
272463 if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
464
+ phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
273465 phydev->interface != PHY_INTERFACE_MODE_XAUI &&
274466 phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
275
- phydev->interface != PHY_INTERFACE_MODE_10GKR)
467
+ phydev->interface != PHY_INTERFACE_MODE_10GBASER)
276468 return -ENODEV;
277469
278
- __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
279
- __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
470
+ phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
280471
281
- if (phydev->c45_ids.devices_in_package & MDIO_DEVS_AN) {
282
- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
283
- if (val < 0)
284
- return val;
472
+ /* Power up so reset works */
473
+ err = mv3310_power_up(phydev);
474
+ if (err)
475
+ return err;
285476
286
- if (val & MDIO_AN_STAT1_ABLE)
287
- __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
288
- }
289
-
290
- val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_STAT2);
477
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
291478 if (val < 0)
292479 return val;
480
+ priv->rate_match = ((val & MV_V2_PORT_MAC_TYPE_MASK) ==
481
+ MV_V2_PORT_MAC_TYPE_RATE_MATCH);
293482
294
- /* Ethtool does not support the WAN mode bits */
295
- if (val & (MDIO_PMA_STAT2_10GBSR | MDIO_PMA_STAT2_10GBLR |
296
- MDIO_PMA_STAT2_10GBER | MDIO_PMA_STAT2_10GBLX4 |
297
- MDIO_PMA_STAT2_10GBSW | MDIO_PMA_STAT2_10GBLW |
298
- MDIO_PMA_STAT2_10GBEW))
299
- __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
300
- if (val & MDIO_PMA_STAT2_10GBSR)
301
- __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
302
- if (val & MDIO_PMA_STAT2_10GBLR)
303
- __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
304
- if (val & MDIO_PMA_STAT2_10GBER)
305
- __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
483
+ /* Enable EDPD mode - saving 600mW */
484
+ return mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS);
485
+}
306486
307
- if (val & MDIO_PMA_STAT2_EXTABLE) {
308
- val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_EXTABLE);
487
+static int mv3310_get_features(struct phy_device *phydev)
488
+{
489
+ int ret, val;
490
+
491
+ ret = genphy_c45_pma_read_abilities(phydev);
492
+ if (ret)
493
+ return ret;
494
+
495
+ if (mv3310_has_pma_ngbaset_quirk(phydev)) {
496
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
497
+ MDIO_PMA_NG_EXTABLE);
309498 if (val < 0)
310499 return val;
311500
312
- if (val & (MDIO_PMA_EXTABLE_10GBT | MDIO_PMA_EXTABLE_1000BT |
313
- MDIO_PMA_EXTABLE_100BTX | MDIO_PMA_EXTABLE_10BT))
314
- __set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
315
- if (val & MDIO_PMA_EXTABLE_10GBLRM)
316
- __set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
317
- if (val & (MDIO_PMA_EXTABLE_10GBKX4 | MDIO_PMA_EXTABLE_10GBKR |
318
- MDIO_PMA_EXTABLE_1000BKX))
319
- __set_bit(ETHTOOL_LINK_MODE_Backplane_BIT, supported);
320
- if (val & MDIO_PMA_EXTABLE_10GBLRM)
321
- __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
322
- supported);
323
- if (val & MDIO_PMA_EXTABLE_10GBT)
324
- __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
325
- supported);
326
- if (val & MDIO_PMA_EXTABLE_10GBKX4)
327
- __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
328
- supported);
329
- if (val & MDIO_PMA_EXTABLE_10GBKR)
330
- __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
331
- supported);
332
- if (val & MDIO_PMA_EXTABLE_1000BT)
333
- __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
334
- supported);
335
- if (val & MDIO_PMA_EXTABLE_1000BKX)
336
- __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
337
- supported);
338
- if (val & MDIO_PMA_EXTABLE_100BTX) {
339
- __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
340
- supported);
341
- __set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
342
- supported);
343
- }
344
- if (val & MDIO_PMA_EXTABLE_10BT) {
345
- __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
346
- supported);
347
- __set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
348
- supported);
349
- }
501
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
502
+ phydev->supported,
503
+ val & MDIO_PMA_NG_EXTABLE_2_5GBT);
504
+
505
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
506
+ phydev->supported,
507
+ val & MDIO_PMA_NG_EXTABLE_5GBT);
350508 }
351509
352
- if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
353
- dev_warn(&phydev->mdio.dev,
354
- "PHY supports (%*pb) more modes than phylib supports, some modes not supported.\n",
355
- __ETHTOOL_LINK_MODE_MASK_NBITS, supported);
356
-
357
- phydev->supported &= mask;
358
- phydev->advertising &= phydev->supported;
359
-
360510 return 0;
511
+}
512
+
513
+static int mv3310_config_mdix(struct phy_device *phydev)
514
+{
515
+ u16 val;
516
+ int err;
517
+
518
+ switch (phydev->mdix_ctrl) {
519
+ case ETH_TP_MDI_AUTO:
520
+ val = MV_PCS_CSCR1_MDIX_AUTO;
521
+ break;
522
+ case ETH_TP_MDI_X:
523
+ val = MV_PCS_CSCR1_MDIX_MDIX;
524
+ break;
525
+ case ETH_TP_MDI:
526
+ val = MV_PCS_CSCR1_MDIX_MDI;
527
+ break;
528
+ default:
529
+ return -EINVAL;
530
+ }
531
+
532
+ err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
533
+ MV_PCS_CSCR1_MDIX_MASK, val);
534
+ if (err > 0)
535
+ err = mv3310_reset(phydev, MV_PCS_BASE_T);
536
+
537
+ return err;
361538 }
362539
363540 static int mv3310_config_aneg(struct phy_device *phydev)
364541 {
365542 bool changed = false;
366
- u32 advertising;
543
+ u16 reg;
367544 int ret;
368545
369
- /* We don't support manual MDI control */
370
- phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
546
+ ret = mv3310_config_mdix(phydev);
547
+ if (ret < 0)
548
+ return ret;
371549
372
- if (phydev->autoneg == AUTONEG_DISABLE) {
373
- ret = genphy_c45_pma_setup_forced(phydev);
374
- if (ret < 0)
375
- return ret;
550
+ if (phydev->autoneg == AUTONEG_DISABLE)
551
+ return genphy_c45_pma_setup_forced(phydev);
376552
377
- return genphy_c45_an_disable_aneg(phydev);
378
- }
379
-
380
- phydev->advertising &= phydev->supported;
381
- advertising = phydev->advertising;
382
-
383
- ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
384
- ADVERTISE_ALL | ADVERTISE_100BASE4 |
385
- ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM,
386
- ethtool_adv_to_mii_adv_t(advertising));
553
+ ret = genphy_c45_an_config_aneg(phydev);
387554 if (ret < 0)
388555 return ret;
389556 if (ret > 0)
390557 changed = true;
391558
392
- ret = mv3310_modify(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
393
- ADVERTISE_1000FULL | ADVERTISE_1000HALF,
394
- ethtool_adv_to_mii_ctrl1000_t(advertising));
559
+ /* Clause 45 has no standardized support for 1000BaseT, therefore
560
+ * use vendor registers for this mode.
561
+ */
562
+ reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
563
+ ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
564
+ ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
395565 if (ret < 0)
396566 return ret;
397567 if (ret > 0)
398568 changed = true;
399569
400
- /* 10G control register */
401
- ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
402
- MDIO_AN_10GBT_CTRL_ADV10G,
403
- advertising & ADVERTISED_10000baseT_Full ?
404
- MDIO_AN_10GBT_CTRL_ADV10G : 0);
405
- if (ret < 0)
406
- return ret;
407
- if (ret > 0)
408
- changed = true;
409
-
410
- if (changed)
411
- ret = genphy_c45_restart_aneg(phydev);
412
-
413
- return ret;
570
+ return genphy_c45_check_and_restart_aneg(phydev, changed);
414571 }
415572
416573 static int mv3310_aneg_done(struct phy_device *phydev)
....@@ -429,70 +586,114 @@
429586
430587 static void mv3310_update_interface(struct phy_device *phydev)
431588 {
589
+ struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
590
+
591
+ /* In "XFI with Rate Matching" mode the PHY interface is fixed at
592
+ * 10Gb. The PHY adapts the rate to actual wire speed with help of
593
+ * internal 16KB buffer.
594
+ */
595
+ if (priv->rate_match) {
596
+ phydev->interface = PHY_INTERFACE_MODE_10GBASER;
597
+ return;
598
+ }
599
+
432600 if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
433
- phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
601
+ phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
602
+ phydev->interface == PHY_INTERFACE_MODE_10GBASER) &&
603
+ phydev->link) {
434604 /* The PHY automatically switches its serdes interface (and
435
- * active PHYXS instance) between Cisco SGMII and 10GBase-KR
436
- * modes according to the speed. Florian suggests setting
437
- * phydev->interface to communicate this to the MAC. Only do
438
- * this if we are already in either SGMII or 10GBase-KR mode.
605
+ * active PHYXS instance) between Cisco SGMII, 10GBase-R and
606
+ * 2500BaseX modes according to the speed. Florian suggests
607
+ * setting phydev->interface to communicate this to the MAC.
608
+ * Only do this if we are already in one of the above modes.
439609 */
440
- if (phydev->speed == SPEED_10000)
441
- phydev->interface = PHY_INTERFACE_MODE_10GKR;
442
- else if (phydev->speed >= SPEED_10 &&
443
- phydev->speed < SPEED_10000)
610
+ switch (phydev->speed) {
611
+ case SPEED_10000:
612
+ phydev->interface = PHY_INTERFACE_MODE_10GBASER;
613
+ break;
614
+ case SPEED_2500:
615
+ phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
616
+ break;
617
+ case SPEED_1000:
618
+ case SPEED_100:
619
+ case SPEED_10:
444620 phydev->interface = PHY_INTERFACE_MODE_SGMII;
621
+ break;
622
+ default:
623
+ break;
624
+ }
445625 }
446626 }
447627
448628 /* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
449
-static int mv3310_read_10gbr_status(struct phy_device *phydev)
629
+static int mv3310_read_status_10gbaser(struct phy_device *phydev)
450630 {
451631 phydev->link = 1;
452632 phydev->speed = SPEED_10000;
453633 phydev->duplex = DUPLEX_FULL;
454
-
455
- mv3310_update_interface(phydev);
634
+ phydev->port = PORT_FIBRE;
456635
457636 return 0;
458637 }
459638
460
-static int mv3310_read_status(struct phy_device *phydev)
639
+static int mv3310_read_status_copper(struct phy_device *phydev)
461640 {
462
- u32 mmd_mask = phydev->c45_ids.devices_in_package;
463
- int val;
641
+ int cssr1, speed, val;
464642
465
- /* The vendor devads do not report link status. Avoid the PHYXS
466
- * instance as there are three, and its status depends on the MAC
467
- * being appropriately configured for the negotiated speed.
468
- */
469
- mmd_mask &= ~(BIT(MDIO_MMD_VEND1) | BIT(MDIO_MMD_VEND2) |
470
- BIT(MDIO_MMD_PHYXS));
471
-
472
- phydev->speed = SPEED_UNKNOWN;
473
- phydev->duplex = DUPLEX_UNKNOWN;
474
- phydev->lp_advertising = 0;
475
- phydev->link = 0;
476
- phydev->pause = 0;
477
- phydev->asym_pause = 0;
478
- phydev->mdix = 0;
479
-
480
- val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
643
+ val = genphy_c45_read_link(phydev);
481644 if (val < 0)
482645 return val;
483
-
484
- if (val & MDIO_STAT1_LSTATUS)
485
- return mv3310_read_10gbr_status(phydev);
486
-
487
- val = genphy_c45_read_link(phydev, mmd_mask);
488
- if (val < 0)
489
- return val;
490
-
491
- phydev->link = val > 0 ? 1 : 0;
492646
493647 val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
494648 if (val < 0)
495649 return val;
650
+
651
+ cssr1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSSR1);
652
+ if (cssr1 < 0)
653
+ return cssr1;
654
+
655
+ /* If the link settings are not resolved, mark the link down */
656
+ if (!(cssr1 & MV_PCS_CSSR1_RESOLVED)) {
657
+ phydev->link = 0;
658
+ return 0;
659
+ }
660
+
661
+ /* Read the copper link settings */
662
+ speed = cssr1 & MV_PCS_CSSR1_SPD1_MASK;
663
+ if (speed == MV_PCS_CSSR1_SPD1_SPD2)
664
+ speed |= cssr1 & MV_PCS_CSSR1_SPD2_MASK;
665
+
666
+ switch (speed) {
667
+ case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_10000:
668
+ phydev->speed = SPEED_10000;
669
+ break;
670
+
671
+ case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_5000:
672
+ phydev->speed = SPEED_5000;
673
+ break;
674
+
675
+ case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_2500:
676
+ phydev->speed = SPEED_2500;
677
+ break;
678
+
679
+ case MV_PCS_CSSR1_SPD1_1000:
680
+ phydev->speed = SPEED_1000;
681
+ break;
682
+
683
+ case MV_PCS_CSSR1_SPD1_100:
684
+ phydev->speed = SPEED_100;
685
+ break;
686
+
687
+ case MV_PCS_CSSR1_SPD1_10:
688
+ phydev->speed = SPEED_10;
689
+ break;
690
+ }
691
+
692
+ phydev->duplex = cssr1 & MV_PCS_CSSR1_DUPLEX_FULL ?
693
+ DUPLEX_FULL : DUPLEX_HALF;
694
+ phydev->port = PORT_TP;
695
+ phydev->mdix = cssr1 & MV_PCS_CSSR1_MDIX ?
696
+ ETH_TP_MDI_X : ETH_TP_MDI;
496697
497698 if (val & MDIO_AN_STAT1_COMPLETE) {
498699 val = genphy_c45_read_lpa(phydev);
....@@ -504,61 +705,72 @@
504705 if (val < 0)
505706 return val;
506707
507
- phydev->lp_advertising |= mii_stat1000_to_ethtool_lpa_t(val);
708
+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
508709
509
- if (phydev->autoneg == AUTONEG_ENABLE)
510
- phy_resolve_aneg_linkmode(phydev);
710
+ /* Update the pause status */
711
+ phy_resolve_aneg_pause(phydev);
511712 }
512
-
513
- if (phydev->autoneg != AUTONEG_ENABLE) {
514
- val = genphy_c45_read_pma(phydev);
515
- if (val < 0)
516
- return val;
517
- }
518
-
519
- if (phydev->speed == SPEED_10000) {
520
- val = genphy_c45_read_mdix(phydev);
521
- if (val < 0)
522
- return val;
523
- } else {
524
- val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PAIRSWAP);
525
- if (val < 0)
526
- return val;
527
-
528
- switch (val & MV_PCS_PAIRSWAP_MASK) {
529
- case MV_PCS_PAIRSWAP_AB:
530
- phydev->mdix = ETH_TP_MDI_X;
531
- break;
532
- case MV_PCS_PAIRSWAP_NONE:
533
- phydev->mdix = ETH_TP_MDI;
534
- break;
535
- default:
536
- phydev->mdix = ETH_TP_MDI_INVALID;
537
- break;
538
- }
539
- }
540
-
541
- mv3310_update_interface(phydev);
542713
543714 return 0;
544715 }
545716
717
+static int mv3310_read_status(struct phy_device *phydev)
718
+{
719
+ int err, val;
720
+
721
+ phydev->speed = SPEED_UNKNOWN;
722
+ phydev->duplex = DUPLEX_UNKNOWN;
723
+ linkmode_zero(phydev->lp_advertising);
724
+ phydev->link = 0;
725
+ phydev->pause = 0;
726
+ phydev->asym_pause = 0;
727
+ phydev->mdix = ETH_TP_MDI_INVALID;
728
+
729
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
730
+ if (val < 0)
731
+ return val;
732
+
733
+ if (val & MDIO_STAT1_LSTATUS)
734
+ err = mv3310_read_status_10gbaser(phydev);
735
+ else
736
+ err = mv3310_read_status_copper(phydev);
737
+ if (err < 0)
738
+ return err;
739
+
740
+ if (phydev->link)
741
+ mv3310_update_interface(phydev);
742
+
743
+ return 0;
744
+}
745
+
746
+static int mv3310_get_tunable(struct phy_device *phydev,
747
+ struct ethtool_tunable *tuna, void *data)
748
+{
749
+ switch (tuna->id) {
750
+ case ETHTOOL_PHY_EDPD:
751
+ return mv3310_get_edpd(phydev, data);
752
+ default:
753
+ return -EOPNOTSUPP;
754
+ }
755
+}
756
+
757
+static int mv3310_set_tunable(struct phy_device *phydev,
758
+ struct ethtool_tunable *tuna, const void *data)
759
+{
760
+ switch (tuna->id) {
761
+ case ETHTOOL_PHY_EDPD:
762
+ return mv3310_set_edpd(phydev, *(u16 *)data);
763
+ default:
764
+ return -EOPNOTSUPP;
765
+ }
766
+}
767
+
546768 static struct phy_driver mv3310_drivers[] = {
547769 {
548
- .phy_id = 0x002b09aa,
770
+ .phy_id = MARVELL_PHY_ID_88X3310,
549771 .phy_id_mask = MARVELL_PHY_ID_MASK,
550772 .name = "mv88x3310",
551
- .features = SUPPORTED_10baseT_Full |
552
- SUPPORTED_10baseT_Half |
553
- SUPPORTED_100baseT_Full |
554
- SUPPORTED_100baseT_Half |
555
- SUPPORTED_1000baseT_Full |
556
- SUPPORTED_Autoneg |
557
- SUPPORTED_TP |
558
- SUPPORTED_FIBRE |
559
- SUPPORTED_10000baseT_Full |
560
- SUPPORTED_Backplane,
561
- .soft_reset = gen10g_no_soft_reset,
773
+ .get_features = mv3310_get_features,
562774 .config_init = mv3310_config_init,
563775 .probe = mv3310_probe,
564776 .suspend = mv3310_suspend,
....@@ -566,13 +778,32 @@
566778 .config_aneg = mv3310_config_aneg,
567779 .aneg_done = mv3310_aneg_done,
568780 .read_status = mv3310_read_status,
781
+ .get_tunable = mv3310_get_tunable,
782
+ .set_tunable = mv3310_set_tunable,
783
+ .remove = mv3310_remove,
784
+ },
785
+ {
786
+ .phy_id = MARVELL_PHY_ID_88E2110,
787
+ .phy_id_mask = MARVELL_PHY_ID_MASK,
788
+ .name = "mv88x2110",
789
+ .probe = mv3310_probe,
790
+ .suspend = mv3310_suspend,
791
+ .resume = mv3310_resume,
792
+ .config_init = mv3310_config_init,
793
+ .config_aneg = mv3310_config_aneg,
794
+ .aneg_done = mv3310_aneg_done,
795
+ .read_status = mv3310_read_status,
796
+ .get_tunable = mv3310_get_tunable,
797
+ .set_tunable = mv3310_set_tunable,
798
+ .remove = mv3310_remove,
569799 },
570800 };
571801
572802 module_phy_driver(mv3310_drivers);
573803
574804 static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
575
- { 0x002b09aa, MARVELL_PHY_ID_MASK },
805
+ { MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },
806
+ { MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
576807 { },
577808 };
578809 MODULE_DEVICE_TABLE(mdio, mv3310_tbl);