hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/net/phy/dp83822.c
....@@ -1,16 +1,7 @@
1
-/*
2
- * Driver for the Texas Instruments DP83822 PHY
1
+// SPDX-License-Identifier: GPL-2.0
2
+/* Driver for the Texas Instruments DP83822, DP83825 and DP83826 PHYs.
33 *
44 * Copyright (C) 2017 Texas Instruments Inc.
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
145 */
156
167 #include <linux/ethtool.h>
....@@ -23,15 +14,39 @@
2314 #include <linux/netdevice.h>
2415
2516 #define DP83822_PHY_ID 0x2000a240
17
+#define DP83825S_PHY_ID 0x2000a140
18
+#define DP83825I_PHY_ID 0x2000a150
19
+#define DP83825CM_PHY_ID 0x2000a160
20
+#define DP83825CS_PHY_ID 0x2000a170
21
+#define DP83826C_PHY_ID 0x2000a130
22
+#define DP83826NC_PHY_ID 0x2000a110
23
+
2624 #define DP83822_DEVADDR 0x1f
2725
26
+#define MII_DP83822_CTRL_2 0x0a
27
+#define MII_DP83822_PHYSTS 0x10
2828 #define MII_DP83822_PHYSCR 0x11
2929 #define MII_DP83822_MISR1 0x12
3030 #define MII_DP83822_MISR2 0x13
31
+#define MII_DP83822_FCSCR 0x14
32
+#define MII_DP83822_RCSR 0x17
3133 #define MII_DP83822_RESET_CTRL 0x1f
34
+#define MII_DP83822_GENCFG 0x465
35
+#define MII_DP83822_SOR1 0x467
36
+
37
+/* GENCFG */
38
+#define DP83822_SIG_DET_LOW BIT(0)
39
+
40
+/* Control Register 2 bits */
41
+#define DP83822_FX_ENABLE BIT(14)
3242
3343 #define DP83822_HW_RESET BIT(15)
3444 #define DP83822_SW_RESET BIT(14)
45
+
46
+/* PHY STS bits */
47
+#define DP83822_PHYSTS_DUPLEX BIT(2)
48
+#define DP83822_PHYSTS_10 BIT(1)
49
+#define DP83822_PHYSTS_LINK BIT(0)
3550
3651 /* PHYSCR Register Fields */
3752 #define DP83822_PHYSCR_INT_OE BIT(0) /* Interrupt Output Enable */
....@@ -78,6 +93,31 @@
7893 #define DP83822_WOL_EN BIT(7)
7994 #define DP83822_WOL_INDICATION_SEL BIT(8)
8095 #define DP83822_WOL_CLR_INDICATION BIT(11)
96
+
97
+/* RSCR bits */
98
+#define DP83822_RX_CLK_SHIFT BIT(12)
99
+#define DP83822_TX_CLK_SHIFT BIT(11)
100
+
101
+/* SOR1 mode */
102
+#define DP83822_STRAP_MODE1 0
103
+#define DP83822_STRAP_MODE2 BIT(0)
104
+#define DP83822_STRAP_MODE3 BIT(1)
105
+#define DP83822_STRAP_MODE4 GENMASK(1, 0)
106
+
107
+#define DP83822_COL_STRAP_MASK GENMASK(11, 10)
108
+#define DP83822_COL_SHIFT 10
109
+#define DP83822_RX_ER_STR_MASK GENMASK(9, 8)
110
+#define DP83822_RX_ER_SHIFT 8
111
+
112
+#define MII_DP83822_FIBER_ADVERTISE (ADVERTISED_TP | ADVERTISED_MII | \
113
+ ADVERTISED_FIBRE | \
114
+ ADVERTISED_Pause | ADVERTISED_Asym_Pause)
115
+
116
+struct dp83822_private {
117
+ bool fx_signal_det_low;
118
+ int fx_enabled;
119
+ u16 fx_sd_enable;
120
+};
81121
82122 static int dp83822_ack_interrupt(struct phy_device *phydev)
83123 {
....@@ -139,19 +179,18 @@
139179 value &= ~DP83822_WOL_SECURE_ON;
140180 }
141181
142
- value |= (DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |
143
- DP83822_WOL_CLR_INDICATION);
144
- phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
145
- value);
146
- } else {
147
- value = phy_read_mmd(phydev, DP83822_DEVADDR,
148
- MII_DP83822_WOL_CFG);
149
- value &= ~DP83822_WOL_EN;
150
- phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
151
- value);
152
- }
182
+ /* Clear any pending WoL interrupt */
183
+ phy_read(phydev, MII_DP83822_MISR2);
153184
154
- return 0;
185
+ value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |
186
+ DP83822_WOL_CLR_INDICATION;
187
+
188
+ return phy_write_mmd(phydev, DP83822_DEVADDR,
189
+ MII_DP83822_WOL_CFG, value);
190
+ } else {
191
+ return phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
192
+ MII_DP83822_WOL_CFG, DP83822_WOL_EN);
193
+ }
155194 }
156195
157196 static void dp83822_get_wol(struct phy_device *phydev,
....@@ -194,6 +233,7 @@
194233
195234 static int dp83822_config_intr(struct phy_device *phydev)
196235 {
236
+ struct dp83822_private *dp83822 = phydev->priv;
197237 int misr_status;
198238 int physcr_status;
199239 int err;
....@@ -203,14 +243,16 @@
203243 if (misr_status < 0)
204244 return misr_status;
205245
206
- misr_status |= (DP83822_RX_ERR_HF_INT_EN |
207
- DP83822_FALSE_CARRIER_HF_INT_EN |
208
- DP83822_ANEG_COMPLETE_INT_EN |
209
- DP83822_DUP_MODE_CHANGE_INT_EN |
210
- DP83822_SPEED_CHANGED_INT_EN |
211
- DP83822_LINK_STAT_INT_EN |
246
+ misr_status |= (DP83822_LINK_STAT_INT_EN |
212247 DP83822_ENERGY_DET_INT_EN |
213248 DP83822_LINK_QUAL_INT_EN);
249
+
250
+ /* Private data pointer is NULL on DP83825/26 */
251
+ if (!dp83822 || !dp83822->fx_enabled)
252
+ misr_status |= DP83822_ANEG_COMPLETE_INT_EN |
253
+ DP83822_DUP_MODE_CHANGE_INT_EN |
254
+ DP83822_SPEED_CHANGED_INT_EN;
255
+
214256
215257 err = phy_write(phydev, MII_DP83822_MISR1, misr_status);
216258 if (err < 0)
....@@ -221,13 +263,15 @@
221263 return misr_status;
222264
223265 misr_status |= (DP83822_JABBER_DET_INT_EN |
224
- DP83822_WOL_PKT_INT_EN |
225266 DP83822_SLEEP_MODE_INT_EN |
226
- DP83822_MDI_XOVER_INT_EN |
227267 DP83822_LB_FIFO_INT_EN |
228268 DP83822_PAGE_RX_INT_EN |
229
- DP83822_ANEG_ERR_INT_EN |
230269 DP83822_EEE_ERROR_CHANGE_INT_EN);
270
+
271
+ /* Private data pointer is NULL on DP83825/26 */
272
+ if (!dp83822 || !dp83822->fx_enabled)
273
+ misr_status |= DP83822_ANEG_ERR_INT_EN |
274
+ DP83822_WOL_PKT_INT_EN;
231275
232276 err = phy_write(phydev, MII_DP83822_MISR2, misr_status);
233277 if (err < 0)
....@@ -244,7 +288,7 @@
244288 if (err < 0)
245289 return err;
246290
247
- err = phy_write(phydev, MII_DP83822_MISR1, 0);
291
+ err = phy_write(phydev, MII_DP83822_MISR2, 0);
248292 if (err < 0)
249293 return err;
250294
....@@ -258,30 +302,237 @@
258302 return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status);
259303 }
260304
305
+static int dp8382x_disable_wol(struct phy_device *phydev)
306
+{
307
+ return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
308
+ DP83822_WOL_EN | DP83822_WOL_MAGIC_EN |
309
+ DP83822_WOL_SECURE_ON);
310
+}
311
+
312
+static int dp83822_read_status(struct phy_device *phydev)
313
+{
314
+ struct dp83822_private *dp83822 = phydev->priv;
315
+ int status = phy_read(phydev, MII_DP83822_PHYSTS);
316
+ int ctrl2;
317
+ int ret;
318
+
319
+ if (dp83822->fx_enabled) {
320
+ if (status & DP83822_PHYSTS_LINK) {
321
+ phydev->speed = SPEED_UNKNOWN;
322
+ phydev->duplex = DUPLEX_UNKNOWN;
323
+ } else {
324
+ ctrl2 = phy_read(phydev, MII_DP83822_CTRL_2);
325
+ if (ctrl2 < 0)
326
+ return ctrl2;
327
+
328
+ if (!(ctrl2 & DP83822_FX_ENABLE)) {
329
+ ret = phy_write(phydev, MII_DP83822_CTRL_2,
330
+ DP83822_FX_ENABLE | ctrl2);
331
+ if (ret < 0)
332
+ return ret;
333
+ }
334
+ }
335
+ }
336
+
337
+ ret = genphy_read_status(phydev);
338
+ if (ret)
339
+ return ret;
340
+
341
+ if (status < 0)
342
+ return status;
343
+
344
+ if (status & DP83822_PHYSTS_DUPLEX)
345
+ phydev->duplex = DUPLEX_FULL;
346
+ else
347
+ phydev->duplex = DUPLEX_HALF;
348
+
349
+ if (status & DP83822_PHYSTS_10)
350
+ phydev->speed = SPEED_10;
351
+ else
352
+ phydev->speed = SPEED_100;
353
+
354
+ return 0;
355
+}
356
+
261357 static int dp83822_config_init(struct phy_device *phydev)
262358 {
263
- int err;
264
- int value;
359
+ struct dp83822_private *dp83822 = phydev->priv;
360
+ struct device *dev = &phydev->mdio.dev;
361
+ int rgmii_delay;
362
+ s32 rx_int_delay;
363
+ s32 tx_int_delay;
364
+ int err = 0;
365
+ int bmcr;
265366
266
- err = genphy_config_init(phydev);
267
- if (err < 0)
268
- return err;
367
+ if (phy_interface_is_rgmii(phydev)) {
368
+ rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
369
+ true);
269370
270
- value = DP83822_WOL_MAGIC_EN | DP83822_WOL_SECURE_ON | DP83822_WOL_EN;
371
+ if (rx_int_delay <= 0)
372
+ rgmii_delay = 0;
373
+ else
374
+ rgmii_delay = DP83822_RX_CLK_SHIFT;
271375
272
- return phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
273
- value);
376
+ tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
377
+ false);
378
+ if (tx_int_delay <= 0)
379
+ rgmii_delay &= ~DP83822_TX_CLK_SHIFT;
380
+ else
381
+ rgmii_delay |= DP83822_TX_CLK_SHIFT;
382
+
383
+ if (rgmii_delay) {
384
+ err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
385
+ MII_DP83822_RCSR, rgmii_delay);
386
+ if (err)
387
+ return err;
388
+ }
389
+ }
390
+
391
+ if (dp83822->fx_enabled) {
392
+ err = phy_modify(phydev, MII_DP83822_CTRL_2,
393
+ DP83822_FX_ENABLE, 1);
394
+ if (err < 0)
395
+ return err;
396
+
397
+ /* Only allow advertising what this PHY supports */
398
+ linkmode_and(phydev->advertising, phydev->advertising,
399
+ phydev->supported);
400
+
401
+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
402
+ phydev->supported);
403
+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
404
+ phydev->advertising);
405
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
406
+ phydev->supported);
407
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
408
+ phydev->supported);
409
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
410
+ phydev->advertising);
411
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
412
+ phydev->advertising);
413
+
414
+ /* Auto neg is not supported in fiber mode */
415
+ bmcr = phy_read(phydev, MII_BMCR);
416
+ if (bmcr < 0)
417
+ return bmcr;
418
+
419
+ if (bmcr & BMCR_ANENABLE) {
420
+ err = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
421
+ if (err < 0)
422
+ return err;
423
+ }
424
+ phydev->autoneg = AUTONEG_DISABLE;
425
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
426
+ phydev->supported);
427
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
428
+ phydev->advertising);
429
+
430
+ /* Setup fiber advertisement */
431
+ err = phy_modify_changed(phydev, MII_ADVERTISE,
432
+ MII_DP83822_FIBER_ADVERTISE,
433
+ MII_DP83822_FIBER_ADVERTISE);
434
+
435
+ if (err < 0)
436
+ return err;
437
+
438
+ if (dp83822->fx_signal_det_low) {
439
+ err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
440
+ MII_DP83822_GENCFG,
441
+ DP83822_SIG_DET_LOW);
442
+ if (err)
443
+ return err;
444
+ }
445
+ }
446
+ return dp8382x_disable_wol(phydev);
447
+}
448
+
449
+static int dp8382x_config_init(struct phy_device *phydev)
450
+{
451
+ return dp8382x_disable_wol(phydev);
274452 }
275453
276454 static int dp83822_phy_reset(struct phy_device *phydev)
277455 {
278456 int err;
279457
280
- err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_HW_RESET);
458
+ err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_SW_RESET);
281459 if (err < 0)
282460 return err;
283461
284
- dp83822_config_init(phydev);
462
+ return phydev->drv->config_init(phydev);
463
+}
464
+
465
+#ifdef CONFIG_OF_MDIO
466
+static int dp83822_of_init(struct phy_device *phydev)
467
+{
468
+ struct dp83822_private *dp83822 = phydev->priv;
469
+ struct device *dev = &phydev->mdio.dev;
470
+
471
+ /* Signal detection for the PHY is only enabled if the FX_EN and the
472
+ * SD_EN pins are strapped. Signal detection can only enabled if FX_EN
473
+ * is strapped otherwise signal detection is disabled for the PHY.
474
+ */
475
+ if (dp83822->fx_enabled && dp83822->fx_sd_enable)
476
+ dp83822->fx_signal_det_low = device_property_present(dev,
477
+ "ti,link-loss-low");
478
+ if (!dp83822->fx_enabled)
479
+ dp83822->fx_enabled = device_property_present(dev,
480
+ "ti,fiber-mode");
481
+
482
+ return 0;
483
+}
484
+#else
485
+static int dp83822_of_init(struct phy_device *phydev)
486
+{
487
+ return 0;
488
+}
489
+#endif /* CONFIG_OF_MDIO */
490
+
491
+static int dp83822_read_straps(struct phy_device *phydev)
492
+{
493
+ struct dp83822_private *dp83822 = phydev->priv;
494
+ int fx_enabled, fx_sd_enable;
495
+ int val;
496
+
497
+ val = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_SOR1);
498
+ if (val < 0)
499
+ return val;
500
+
501
+ fx_enabled = (val & DP83822_COL_STRAP_MASK) >> DP83822_COL_SHIFT;
502
+ if (fx_enabled == DP83822_STRAP_MODE2 ||
503
+ fx_enabled == DP83822_STRAP_MODE3)
504
+ dp83822->fx_enabled = 1;
505
+
506
+ if (dp83822->fx_enabled) {
507
+ fx_sd_enable = (val & DP83822_RX_ER_STR_MASK) >> DP83822_RX_ER_SHIFT;
508
+ if (fx_sd_enable == DP83822_STRAP_MODE3 ||
509
+ fx_sd_enable == DP83822_STRAP_MODE4)
510
+ dp83822->fx_sd_enable = 1;
511
+ }
512
+
513
+ return 0;
514
+}
515
+
516
+static int dp83822_probe(struct phy_device *phydev)
517
+{
518
+ struct dp83822_private *dp83822;
519
+ int ret;
520
+
521
+ dp83822 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83822),
522
+ GFP_KERNEL);
523
+ if (!dp83822)
524
+ return -ENOMEM;
525
+
526
+ phydev->priv = dp83822;
527
+
528
+ ret = dp83822_read_straps(phydev);
529
+ if (ret)
530
+ return ret;
531
+
532
+ dp83822_of_init(phydev);
533
+
534
+ if (dp83822->fx_enabled)
535
+ phydev->port = PORT_FIBRE;
285536
286537 return 0;
287538 }
....@@ -312,31 +563,61 @@
312563 return 0;
313564 }
314565
566
+#define DP83822_PHY_DRIVER(_id, _name) \
567
+ { \
568
+ PHY_ID_MATCH_MODEL(_id), \
569
+ .name = (_name), \
570
+ /* PHY_BASIC_FEATURES */ \
571
+ .probe = dp83822_probe, \
572
+ .soft_reset = dp83822_phy_reset, \
573
+ .config_init = dp83822_config_init, \
574
+ .read_status = dp83822_read_status, \
575
+ .get_wol = dp83822_get_wol, \
576
+ .set_wol = dp83822_set_wol, \
577
+ .ack_interrupt = dp83822_ack_interrupt, \
578
+ .config_intr = dp83822_config_intr, \
579
+ .suspend = dp83822_suspend, \
580
+ .resume = dp83822_resume, \
581
+ }
582
+
583
+#define DP8382X_PHY_DRIVER(_id, _name) \
584
+ { \
585
+ PHY_ID_MATCH_MODEL(_id), \
586
+ .name = (_name), \
587
+ /* PHY_BASIC_FEATURES */ \
588
+ .soft_reset = dp83822_phy_reset, \
589
+ .config_init = dp8382x_config_init, \
590
+ .get_wol = dp83822_get_wol, \
591
+ .set_wol = dp83822_set_wol, \
592
+ .ack_interrupt = dp83822_ack_interrupt, \
593
+ .config_intr = dp83822_config_intr, \
594
+ .suspend = dp83822_suspend, \
595
+ .resume = dp83822_resume, \
596
+ }
597
+
315598 static struct phy_driver dp83822_driver[] = {
316
- {
317
- .phy_id = DP83822_PHY_ID,
318
- .phy_id_mask = 0xfffffff0,
319
- .name = "TI DP83822",
320
- .features = PHY_BASIC_FEATURES,
321
- .flags = PHY_HAS_INTERRUPT,
322
- .config_init = dp83822_config_init,
323
- .soft_reset = dp83822_phy_reset,
324
- .get_wol = dp83822_get_wol,
325
- .set_wol = dp83822_set_wol,
326
- .ack_interrupt = dp83822_ack_interrupt,
327
- .config_intr = dp83822_config_intr,
328
- .suspend = dp83822_suspend,
329
- .resume = dp83822_resume,
330
- },
599
+ DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"),
600
+ DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"),
601
+ DP8382X_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"),
602
+ DP8382X_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"),
603
+ DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"),
604
+ DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"),
605
+ DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"),
331606 };
332607 module_phy_driver(dp83822_driver);
333608
334609 static struct mdio_device_id __maybe_unused dp83822_tbl[] = {
335610 { DP83822_PHY_ID, 0xfffffff0 },
611
+ { DP83825I_PHY_ID, 0xfffffff0 },
612
+ { DP83826C_PHY_ID, 0xfffffff0 },
613
+ { DP83826NC_PHY_ID, 0xfffffff0 },
614
+ { DP83825S_PHY_ID, 0xfffffff0 },
615
+ { DP83825CM_PHY_ID, 0xfffffff0 },
616
+ { DP83825CS_PHY_ID, 0xfffffff0 },
336617 { },
337618 };
338619 MODULE_DEVICE_TABLE(mdio, dp83822_tbl);
339620
340621 MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver");
341622 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
342
-MODULE_LICENSE("GPL");
623
+MODULE_LICENSE("GPL v2");