forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
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,15 @@
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
+ if (!dp83822->fx_enabled)
251
+ misr_status |= DP83822_ANEG_COMPLETE_INT_EN |
252
+ DP83822_DUP_MODE_CHANGE_INT_EN |
253
+ DP83822_SPEED_CHANGED_INT_EN;
254
+
214255
215256 err = phy_write(phydev, MII_DP83822_MISR1, misr_status);
216257 if (err < 0)
....@@ -221,13 +262,14 @@
221262 return misr_status;
222263
223264 misr_status |= (DP83822_JABBER_DET_INT_EN |
224
- DP83822_WOL_PKT_INT_EN |
225265 DP83822_SLEEP_MODE_INT_EN |
226
- DP83822_MDI_XOVER_INT_EN |
227266 DP83822_LB_FIFO_INT_EN |
228267 DP83822_PAGE_RX_INT_EN |
229
- DP83822_ANEG_ERR_INT_EN |
230268 DP83822_EEE_ERROR_CHANGE_INT_EN);
269
+
270
+ if (!dp83822->fx_enabled)
271
+ misr_status |= DP83822_ANEG_ERR_INT_EN |
272
+ DP83822_WOL_PKT_INT_EN;
231273
232274 err = phy_write(phydev, MII_DP83822_MISR2, misr_status);
233275 if (err < 0)
....@@ -244,7 +286,7 @@
244286 if (err < 0)
245287 return err;
246288
247
- err = phy_write(phydev, MII_DP83822_MISR1, 0);
289
+ err = phy_write(phydev, MII_DP83822_MISR2, 0);
248290 if (err < 0)
249291 return err;
250292
....@@ -258,30 +300,237 @@
258300 return phy_write(phydev, MII_DP83822_PHYSCR, physcr_status);
259301 }
260302
303
+static int dp8382x_disable_wol(struct phy_device *phydev)
304
+{
305
+ return phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
306
+ DP83822_WOL_EN | DP83822_WOL_MAGIC_EN |
307
+ DP83822_WOL_SECURE_ON);
308
+}
309
+
310
+static int dp83822_read_status(struct phy_device *phydev)
311
+{
312
+ struct dp83822_private *dp83822 = phydev->priv;
313
+ int status = phy_read(phydev, MII_DP83822_PHYSTS);
314
+ int ctrl2;
315
+ int ret;
316
+
317
+ if (dp83822->fx_enabled) {
318
+ if (status & DP83822_PHYSTS_LINK) {
319
+ phydev->speed = SPEED_UNKNOWN;
320
+ phydev->duplex = DUPLEX_UNKNOWN;
321
+ } else {
322
+ ctrl2 = phy_read(phydev, MII_DP83822_CTRL_2);
323
+ if (ctrl2 < 0)
324
+ return ctrl2;
325
+
326
+ if (!(ctrl2 & DP83822_FX_ENABLE)) {
327
+ ret = phy_write(phydev, MII_DP83822_CTRL_2,
328
+ DP83822_FX_ENABLE | ctrl2);
329
+ if (ret < 0)
330
+ return ret;
331
+ }
332
+ }
333
+ }
334
+
335
+ ret = genphy_read_status(phydev);
336
+ if (ret)
337
+ return ret;
338
+
339
+ if (status < 0)
340
+ return status;
341
+
342
+ if (status & DP83822_PHYSTS_DUPLEX)
343
+ phydev->duplex = DUPLEX_FULL;
344
+ else
345
+ phydev->duplex = DUPLEX_HALF;
346
+
347
+ if (status & DP83822_PHYSTS_10)
348
+ phydev->speed = SPEED_10;
349
+ else
350
+ phydev->speed = SPEED_100;
351
+
352
+ return 0;
353
+}
354
+
261355 static int dp83822_config_init(struct phy_device *phydev)
262356 {
263
- int err;
264
- int value;
357
+ struct dp83822_private *dp83822 = phydev->priv;
358
+ struct device *dev = &phydev->mdio.dev;
359
+ int rgmii_delay;
360
+ s32 rx_int_delay;
361
+ s32 tx_int_delay;
362
+ int err = 0;
363
+ int bmcr;
265364
266
- err = genphy_config_init(phydev);
267
- if (err < 0)
268
- return err;
365
+ if (phy_interface_is_rgmii(phydev)) {
366
+ rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
367
+ true);
269368
270
- value = DP83822_WOL_MAGIC_EN | DP83822_WOL_SECURE_ON | DP83822_WOL_EN;
369
+ if (rx_int_delay <= 0)
370
+ rgmii_delay = 0;
371
+ else
372
+ rgmii_delay = DP83822_RX_CLK_SHIFT;
271373
272
- return phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG,
273
- value);
374
+ tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
375
+ false);
376
+ if (tx_int_delay <= 0)
377
+ rgmii_delay &= ~DP83822_TX_CLK_SHIFT;
378
+ else
379
+ rgmii_delay |= DP83822_TX_CLK_SHIFT;
380
+
381
+ if (rgmii_delay) {
382
+ err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
383
+ MII_DP83822_RCSR, rgmii_delay);
384
+ if (err)
385
+ return err;
386
+ }
387
+ }
388
+
389
+ if (dp83822->fx_enabled) {
390
+ err = phy_modify(phydev, MII_DP83822_CTRL_2,
391
+ DP83822_FX_ENABLE, 1);
392
+ if (err < 0)
393
+ return err;
394
+
395
+ /* Only allow advertising what this PHY supports */
396
+ linkmode_and(phydev->advertising, phydev->advertising,
397
+ phydev->supported);
398
+
399
+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
400
+ phydev->supported);
401
+ linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT,
402
+ phydev->advertising);
403
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
404
+ phydev->supported);
405
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
406
+ phydev->supported);
407
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT,
408
+ phydev->advertising);
409
+ linkmode_set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT,
410
+ phydev->advertising);
411
+
412
+ /* Auto neg is not supported in fiber mode */
413
+ bmcr = phy_read(phydev, MII_BMCR);
414
+ if (bmcr < 0)
415
+ return bmcr;
416
+
417
+ if (bmcr & BMCR_ANENABLE) {
418
+ err = phy_modify(phydev, MII_BMCR, BMCR_ANENABLE, 0);
419
+ if (err < 0)
420
+ return err;
421
+ }
422
+ phydev->autoneg = AUTONEG_DISABLE;
423
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
424
+ phydev->supported);
425
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
426
+ phydev->advertising);
427
+
428
+ /* Setup fiber advertisement */
429
+ err = phy_modify_changed(phydev, MII_ADVERTISE,
430
+ MII_DP83822_FIBER_ADVERTISE,
431
+ MII_DP83822_FIBER_ADVERTISE);
432
+
433
+ if (err < 0)
434
+ return err;
435
+
436
+ if (dp83822->fx_signal_det_low) {
437
+ err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
438
+ MII_DP83822_GENCFG,
439
+ DP83822_SIG_DET_LOW);
440
+ if (err)
441
+ return err;
442
+ }
443
+ }
444
+ return dp8382x_disable_wol(phydev);
445
+}
446
+
447
+static int dp8382x_config_init(struct phy_device *phydev)
448
+{
449
+ return dp8382x_disable_wol(phydev);
274450 }
275451
276452 static int dp83822_phy_reset(struct phy_device *phydev)
277453 {
278454 int err;
279455
280
- err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_HW_RESET);
456
+ err = phy_write(phydev, MII_DP83822_RESET_CTRL, DP83822_SW_RESET);
281457 if (err < 0)
282458 return err;
283459
284
- dp83822_config_init(phydev);
460
+ return phydev->drv->config_init(phydev);
461
+}
462
+
463
+#ifdef CONFIG_OF_MDIO
464
+static int dp83822_of_init(struct phy_device *phydev)
465
+{
466
+ struct dp83822_private *dp83822 = phydev->priv;
467
+ struct device *dev = &phydev->mdio.dev;
468
+
469
+ /* Signal detection for the PHY is only enabled if the FX_EN and the
470
+ * SD_EN pins are strapped. Signal detection can only enabled if FX_EN
471
+ * is strapped otherwise signal detection is disabled for the PHY.
472
+ */
473
+ if (dp83822->fx_enabled && dp83822->fx_sd_enable)
474
+ dp83822->fx_signal_det_low = device_property_present(dev,
475
+ "ti,link-loss-low");
476
+ if (!dp83822->fx_enabled)
477
+ dp83822->fx_enabled = device_property_present(dev,
478
+ "ti,fiber-mode");
479
+
480
+ return 0;
481
+}
482
+#else
483
+static int dp83822_of_init(struct phy_device *phydev)
484
+{
485
+ return 0;
486
+}
487
+#endif /* CONFIG_OF_MDIO */
488
+
489
+static int dp83822_read_straps(struct phy_device *phydev)
490
+{
491
+ struct dp83822_private *dp83822 = phydev->priv;
492
+ int fx_enabled, fx_sd_enable;
493
+ int val;
494
+
495
+ val = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_SOR1);
496
+ if (val < 0)
497
+ return val;
498
+
499
+ fx_enabled = (val & DP83822_COL_STRAP_MASK) >> DP83822_COL_SHIFT;
500
+ if (fx_enabled == DP83822_STRAP_MODE2 ||
501
+ fx_enabled == DP83822_STRAP_MODE3)
502
+ dp83822->fx_enabled = 1;
503
+
504
+ if (dp83822->fx_enabled) {
505
+ fx_sd_enable = (val & DP83822_RX_ER_STR_MASK) >> DP83822_RX_ER_SHIFT;
506
+ if (fx_sd_enable == DP83822_STRAP_MODE3 ||
507
+ fx_sd_enable == DP83822_STRAP_MODE4)
508
+ dp83822->fx_sd_enable = 1;
509
+ }
510
+
511
+ return 0;
512
+}
513
+
514
+static int dp83822_probe(struct phy_device *phydev)
515
+{
516
+ struct dp83822_private *dp83822;
517
+ int ret;
518
+
519
+ dp83822 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83822),
520
+ GFP_KERNEL);
521
+ if (!dp83822)
522
+ return -ENOMEM;
523
+
524
+ phydev->priv = dp83822;
525
+
526
+ ret = dp83822_read_straps(phydev);
527
+ if (ret)
528
+ return ret;
529
+
530
+ dp83822_of_init(phydev);
531
+
532
+ if (dp83822->fx_enabled)
533
+ phydev->port = PORT_FIBRE;
285534
286535 return 0;
287536 }
....@@ -312,31 +561,61 @@
312561 return 0;
313562 }
314563
564
+#define DP83822_PHY_DRIVER(_id, _name) \
565
+ { \
566
+ PHY_ID_MATCH_MODEL(_id), \
567
+ .name = (_name), \
568
+ /* PHY_BASIC_FEATURES */ \
569
+ .probe = dp83822_probe, \
570
+ .soft_reset = dp83822_phy_reset, \
571
+ .config_init = dp83822_config_init, \
572
+ .read_status = dp83822_read_status, \
573
+ .get_wol = dp83822_get_wol, \
574
+ .set_wol = dp83822_set_wol, \
575
+ .ack_interrupt = dp83822_ack_interrupt, \
576
+ .config_intr = dp83822_config_intr, \
577
+ .suspend = dp83822_suspend, \
578
+ .resume = dp83822_resume, \
579
+ }
580
+
581
+#define DP8382X_PHY_DRIVER(_id, _name) \
582
+ { \
583
+ PHY_ID_MATCH_MODEL(_id), \
584
+ .name = (_name), \
585
+ /* PHY_BASIC_FEATURES */ \
586
+ .soft_reset = dp83822_phy_reset, \
587
+ .config_init = dp8382x_config_init, \
588
+ .get_wol = dp83822_get_wol, \
589
+ .set_wol = dp83822_set_wol, \
590
+ .ack_interrupt = dp83822_ack_interrupt, \
591
+ .config_intr = dp83822_config_intr, \
592
+ .suspend = dp83822_suspend, \
593
+ .resume = dp83822_resume, \
594
+ }
595
+
315596 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
- },
597
+ DP83822_PHY_DRIVER(DP83822_PHY_ID, "TI DP83822"),
598
+ DP8382X_PHY_DRIVER(DP83825I_PHY_ID, "TI DP83825I"),
599
+ DP8382X_PHY_DRIVER(DP83826C_PHY_ID, "TI DP83826C"),
600
+ DP8382X_PHY_DRIVER(DP83826NC_PHY_ID, "TI DP83826NC"),
601
+ DP8382X_PHY_DRIVER(DP83825S_PHY_ID, "TI DP83825S"),
602
+ DP8382X_PHY_DRIVER(DP83825CM_PHY_ID, "TI DP83825M"),
603
+ DP8382X_PHY_DRIVER(DP83825CS_PHY_ID, "TI DP83825CS"),
331604 };
332605 module_phy_driver(dp83822_driver);
333606
334607 static struct mdio_device_id __maybe_unused dp83822_tbl[] = {
335608 { DP83822_PHY_ID, 0xfffffff0 },
609
+ { DP83825I_PHY_ID, 0xfffffff0 },
610
+ { DP83826C_PHY_ID, 0xfffffff0 },
611
+ { DP83826NC_PHY_ID, 0xfffffff0 },
612
+ { DP83825S_PHY_ID, 0xfffffff0 },
613
+ { DP83825CM_PHY_ID, 0xfffffff0 },
614
+ { DP83825CS_PHY_ID, 0xfffffff0 },
336615 { },
337616 };
338617 MODULE_DEVICE_TABLE(mdio, dp83822_tbl);
339618
340619 MODULE_DESCRIPTION("Texas Instruments DP83822 PHY driver");
341620 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
342
-MODULE_LICENSE("GPL");
621
+MODULE_LICENSE("GPL v2");