forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-09 95099d4622f8cb224d94e314c7a8e0df60b13f87
kernel/drivers/net/phy/dp83867.c
....@@ -1,16 +1,7 @@
1
-/*
2
- * Driver for the Texas Instruments DP83867 PHY
1
+// SPDX-License-Identifier: GPL-2.0
2
+/* Driver for the Texas Instruments DP83867 PHY
33 *
44 * Copyright (C) 2015 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>
....@@ -19,6 +10,10 @@
1910 #include <linux/module.h>
2011 #include <linux/of.h>
2112 #include <linux/phy.h>
13
+#include <linux/delay.h>
14
+#include <linux/netdevice.h>
15
+#include <linux/etherdevice.h>
16
+#include <linux/bitfield.h>
2217
2318 #include <dt-bindings/net/ti-dp83867.h>
2419
....@@ -26,13 +21,16 @@
2621 #define DP83867_DEVADDR 0x1f
2722
2823 #define MII_DP83867_PHYCTRL 0x10
24
+#define MII_DP83867_PHYSTS 0x11
2925 #define MII_DP83867_MICR 0x12
3026 #define MII_DP83867_ISR 0x13
31
-#define DP83867_CTRL 0x1f
27
+#define DP83867_CFG2 0x14
3228 #define DP83867_CFG3 0x1e
29
+#define DP83867_CTRL 0x1f
3330
3431 /* Extended Registers */
35
-#define DP83867_CFG4 0x0031
32
+#define DP83867_FLD_THR_CFG 0x002e
33
+#define DP83867_CFG4 0x0031
3634 #define DP83867_CFG4_SGMII_ANEG_MASK (BIT(5) | BIT(6))
3735 #define DP83867_CFG4_SGMII_ANEG_TIMER_11MS (3 << 5)
3836 #define DP83867_CFG4_SGMII_ANEG_TIMER_800US (2 << 5)
....@@ -41,16 +39,22 @@
4139
4240 #define DP83867_RGMIICTL 0x0032
4341 #define DP83867_STRAP_STS1 0x006E
42
+#define DP83867_STRAP_STS2 0x006f
4443 #define DP83867_RGMIIDCTL 0x0086
44
+#define DP83867_RXFCFG 0x0134
45
+#define DP83867_RXFPMD1 0x0136
46
+#define DP83867_RXFPMD2 0x0137
47
+#define DP83867_RXFPMD3 0x0138
48
+#define DP83867_RXFSOP1 0x0139
49
+#define DP83867_RXFSOP2 0x013A
50
+#define DP83867_RXFSOP3 0x013B
4551 #define DP83867_IO_MUX_CFG 0x0170
52
+#define DP83867_SGMIICTL 0x00D3
4653 #define DP83867_10M_SGMII_CFG 0x016F
4754 #define DP83867_10M_SGMII_RATE_ADAPT_MASK BIT(7)
4855
4956 #define DP83867_SW_RESET BIT(15)
5057 #define DP83867_SW_RESTART BIT(14)
51
-
52
-/* PHYCTRL bits */
53
-#define MII_DP83867_PHYCTRL_FORCE_LINK_GOOD BIT(10)
5458
5559 /* MICR Interrupt bits */
5660 #define MII_DP83867_MICR_AN_ERR_INT_EN BIT(15)
....@@ -70,24 +74,70 @@
7074 #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1)
7175 #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0)
7276
77
+/* SGMIICTL bits */
78
+#define DP83867_SGMII_TYPE BIT(14)
79
+
80
+/* RXFCFG bits*/
81
+#define DP83867_WOL_MAGIC_EN BIT(0)
82
+#define DP83867_WOL_BCAST_EN BIT(2)
83
+#define DP83867_WOL_UCAST_EN BIT(4)
84
+#define DP83867_WOL_SEC_EN BIT(5)
85
+#define DP83867_WOL_ENH_MAC BIT(7)
86
+
7387 /* STRAP_STS1 bits */
7488 #define DP83867_STRAP_STS1_RESERVED BIT(11)
7589
90
+/* STRAP_STS2 bits */
91
+#define DP83867_STRAP_STS2_CLK_SKEW_TX_MASK GENMASK(6, 4)
92
+#define DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT 4
93
+#define DP83867_STRAP_STS2_CLK_SKEW_RX_MASK GENMASK(2, 0)
94
+#define DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT 0
95
+#define DP83867_STRAP_STS2_CLK_SKEW_NONE BIT(2)
96
+#define DP83867_STRAP_STS2_STRAP_FLD BIT(10)
97
+
7698 /* PHY CTRL bits */
77
-#define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14
78
-#define DP83867_PHYCR_FIFO_DEPTH_MASK (3 << 14)
99
+#define DP83867_PHYCR_TX_FIFO_DEPTH_SHIFT 14
100
+#define DP83867_PHYCR_RX_FIFO_DEPTH_SHIFT 12
101
+#define DP83867_PHYCR_FIFO_DEPTH_MAX 0x03
102
+#define DP83867_PHYCR_TX_FIFO_DEPTH_MASK GENMASK(15, 14)
103
+#define DP83867_PHYCR_RX_FIFO_DEPTH_MASK GENMASK(13, 12)
79104 #define DP83867_PHYCR_RESERVED_MASK BIT(11)
105
+#define DP83867_PHYCR_FORCE_LINK_GOOD BIT(10)
80106
81107 /* RGMIIDCTL bits */
108
+#define DP83867_RGMII_TX_CLK_DELAY_MAX 0xf
82109 #define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4
110
+#define DP83867_RGMII_TX_CLK_DELAY_INV (DP83867_RGMII_TX_CLK_DELAY_MAX + 1)
111
+#define DP83867_RGMII_RX_CLK_DELAY_MAX 0xf
112
+#define DP83867_RGMII_RX_CLK_DELAY_SHIFT 0
113
+#define DP83867_RGMII_RX_CLK_DELAY_INV (DP83867_RGMII_RX_CLK_DELAY_MAX + 1)
83114
84115 /* IO_MUX_CFG bits */
85
-#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL 0x1f
86
-
116
+#define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MASK 0x1f
87117 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX 0x0
88118 #define DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN 0x1f
119
+#define DP83867_IO_MUX_CFG_CLK_O_DISABLE BIT(6)
89120 #define DP83867_IO_MUX_CFG_CLK_O_SEL_MASK (0x1f << 8)
90121 #define DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT 8
122
+
123
+/* PHY STS bits */
124
+#define DP83867_PHYSTS_1000 BIT(15)
125
+#define DP83867_PHYSTS_100 BIT(14)
126
+#define DP83867_PHYSTS_DUPLEX BIT(13)
127
+#define DP83867_PHYSTS_LINK BIT(10)
128
+
129
+/* CFG2 bits */
130
+#define DP83867_DOWNSHIFT_EN (BIT(8) | BIT(9))
131
+#define DP83867_DOWNSHIFT_ATTEMPT_MASK (BIT(10) | BIT(11))
132
+#define DP83867_DOWNSHIFT_1_COUNT_VAL 0
133
+#define DP83867_DOWNSHIFT_2_COUNT_VAL 1
134
+#define DP83867_DOWNSHIFT_4_COUNT_VAL 2
135
+#define DP83867_DOWNSHIFT_8_COUNT_VAL 3
136
+#define DP83867_DOWNSHIFT_1_COUNT 1
137
+#define DP83867_DOWNSHIFT_2_COUNT 2
138
+#define DP83867_DOWNSHIFT_4_COUNT 4
139
+#define DP83867_DOWNSHIFT_8_COUNT 8
140
+#define DP83867_SGMII_AUTONEG_EN BIT(7)
91141
92142 /* CFG3 bits */
93143 #define DP83867_CFG3_INT_OE BIT(7)
....@@ -96,6 +146,9 @@
96146 /* CFG4 bits */
97147 #define DP83867_CFG4_PORT_MIRROR_EN BIT(0)
98148
149
+/* FLD_THR_CFG */
150
+#define DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK 0x7
151
+
99152 enum {
100153 DP83867_PORT_MIRROING_KEEP,
101154 DP83867_PORT_MIRROING_EN,
....@@ -103,13 +156,16 @@
103156 };
104157
105158 struct dp83867_private {
106
- int rx_id_delay;
107
- int tx_id_delay;
108
- int fifo_depth;
159
+ u32 rx_id_delay;
160
+ u32 tx_id_delay;
161
+ u32 tx_fifo_depth;
162
+ u32 rx_fifo_depth;
109163 int io_impedance;
110164 int port_mirroring;
111165 bool rxctrl_strap_quirk;
112
- int clk_output_sel;
166
+ bool set_clk_output;
167
+ u32 clk_output_sel;
168
+ bool sgmii_ref_clk_en;
113169 };
114170
115171 static int dp83867_ack_interrupt(struct phy_device *phydev)
....@@ -120,6 +176,115 @@
120176 return err;
121177
122178 return 0;
179
+}
180
+
181
+static int dp83867_set_wol(struct phy_device *phydev,
182
+ struct ethtool_wolinfo *wol)
183
+{
184
+ struct net_device *ndev = phydev->attached_dev;
185
+ u16 val_rxcfg, val_micr;
186
+ u8 *mac;
187
+
188
+ val_rxcfg = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
189
+ val_micr = phy_read(phydev, MII_DP83867_MICR);
190
+
191
+ if (wol->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_UCAST |
192
+ WAKE_BCAST)) {
193
+ val_rxcfg |= DP83867_WOL_ENH_MAC;
194
+ val_micr |= MII_DP83867_MICR_WOL_INT_EN;
195
+
196
+ if (wol->wolopts & WAKE_MAGIC) {
197
+ mac = (u8 *)ndev->dev_addr;
198
+
199
+ if (!is_valid_ether_addr(mac))
200
+ return -EINVAL;
201
+
202
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD1,
203
+ (mac[1] << 8 | mac[0]));
204
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD2,
205
+ (mac[3] << 8 | mac[2]));
206
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFPMD3,
207
+ (mac[5] << 8 | mac[4]));
208
+
209
+ val_rxcfg |= DP83867_WOL_MAGIC_EN;
210
+ } else {
211
+ val_rxcfg &= ~DP83867_WOL_MAGIC_EN;
212
+ }
213
+
214
+ if (wol->wolopts & WAKE_MAGICSECURE) {
215
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP1,
216
+ (wol->sopass[1] << 8) | wol->sopass[0]);
217
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP2,
218
+ (wol->sopass[3] << 8) | wol->sopass[2]);
219
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFSOP3,
220
+ (wol->sopass[5] << 8) | wol->sopass[4]);
221
+
222
+ val_rxcfg |= DP83867_WOL_SEC_EN;
223
+ } else {
224
+ val_rxcfg &= ~DP83867_WOL_SEC_EN;
225
+ }
226
+
227
+ if (wol->wolopts & WAKE_UCAST)
228
+ val_rxcfg |= DP83867_WOL_UCAST_EN;
229
+ else
230
+ val_rxcfg &= ~DP83867_WOL_UCAST_EN;
231
+
232
+ if (wol->wolopts & WAKE_BCAST)
233
+ val_rxcfg |= DP83867_WOL_BCAST_EN;
234
+ else
235
+ val_rxcfg &= ~DP83867_WOL_BCAST_EN;
236
+ } else {
237
+ val_rxcfg &= ~DP83867_WOL_ENH_MAC;
238
+ val_micr &= ~MII_DP83867_MICR_WOL_INT_EN;
239
+ }
240
+
241
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG, val_rxcfg);
242
+ phy_write(phydev, MII_DP83867_MICR, val_micr);
243
+
244
+ return 0;
245
+}
246
+
247
+static void dp83867_get_wol(struct phy_device *phydev,
248
+ struct ethtool_wolinfo *wol)
249
+{
250
+ u16 value, sopass_val;
251
+
252
+ wol->supported = (WAKE_UCAST | WAKE_BCAST | WAKE_MAGIC |
253
+ WAKE_MAGICSECURE);
254
+ wol->wolopts = 0;
255
+
256
+ value = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RXFCFG);
257
+
258
+ if (value & DP83867_WOL_UCAST_EN)
259
+ wol->wolopts |= WAKE_UCAST;
260
+
261
+ if (value & DP83867_WOL_BCAST_EN)
262
+ wol->wolopts |= WAKE_BCAST;
263
+
264
+ if (value & DP83867_WOL_MAGIC_EN)
265
+ wol->wolopts |= WAKE_MAGIC;
266
+
267
+ if (value & DP83867_WOL_SEC_EN) {
268
+ sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
269
+ DP83867_RXFSOP1);
270
+ wol->sopass[0] = (sopass_val & 0xff);
271
+ wol->sopass[1] = (sopass_val >> 8);
272
+
273
+ sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
274
+ DP83867_RXFSOP2);
275
+ wol->sopass[2] = (sopass_val & 0xff);
276
+ wol->sopass[3] = (sopass_val >> 8);
277
+
278
+ sopass_val = phy_read_mmd(phydev, DP83867_DEVADDR,
279
+ DP83867_RXFSOP3);
280
+ wol->sopass[4] = (sopass_val & 0xff);
281
+ wol->sopass[5] = (sopass_val >> 8);
282
+
283
+ wol->wolopts |= WAKE_MAGICSECURE;
284
+ }
285
+
286
+ if (!(value & DP83867_WOL_ENH_MAC))
287
+ wol->wolopts = 0;
123288 }
124289
125290 static int dp83867_config_intr(struct phy_device *phydev)
....@@ -146,25 +311,183 @@
146311 return phy_write(phydev, MII_DP83867_MICR, micr_status);
147312 }
148313
149
-static int dp83867_config_port_mirroring(struct phy_device *phydev)
314
+static int dp83867_read_status(struct phy_device *phydev)
150315 {
151
- struct dp83867_private *dp83867 =
152
- (struct dp83867_private *)phydev->priv;
153
- u16 val;
316
+ int status = phy_read(phydev, MII_DP83867_PHYSTS);
317
+ int ret;
154318
155
- val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
319
+ ret = genphy_read_status(phydev);
320
+ if (ret)
321
+ return ret;
156322
157
- if (dp83867->port_mirroring == DP83867_PORT_MIRROING_EN)
158
- val |= DP83867_CFG4_PORT_MIRROR_EN;
323
+ if (status < 0)
324
+ return status;
325
+
326
+ if (status & DP83867_PHYSTS_DUPLEX)
327
+ phydev->duplex = DUPLEX_FULL;
159328 else
160
- val &= ~DP83867_CFG4_PORT_MIRROR_EN;
329
+ phydev->duplex = DUPLEX_HALF;
161330
162
- phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
331
+ if (status & DP83867_PHYSTS_1000)
332
+ phydev->speed = SPEED_1000;
333
+ else if (status & DP83867_PHYSTS_100)
334
+ phydev->speed = SPEED_100;
335
+ else
336
+ phydev->speed = SPEED_10;
163337
164338 return 0;
165339 }
166340
167
-#ifdef CONFIG_OF_MDIO
341
+static int dp83867_get_downshift(struct phy_device *phydev, u8 *data)
342
+{
343
+ int val, cnt, enable, count;
344
+
345
+ val = phy_read(phydev, DP83867_CFG2);
346
+ if (val < 0)
347
+ return val;
348
+
349
+ enable = FIELD_GET(DP83867_DOWNSHIFT_EN, val);
350
+ cnt = FIELD_GET(DP83867_DOWNSHIFT_ATTEMPT_MASK, val);
351
+
352
+ switch (cnt) {
353
+ case DP83867_DOWNSHIFT_1_COUNT_VAL:
354
+ count = DP83867_DOWNSHIFT_1_COUNT;
355
+ break;
356
+ case DP83867_DOWNSHIFT_2_COUNT_VAL:
357
+ count = DP83867_DOWNSHIFT_2_COUNT;
358
+ break;
359
+ case DP83867_DOWNSHIFT_4_COUNT_VAL:
360
+ count = DP83867_DOWNSHIFT_4_COUNT;
361
+ break;
362
+ case DP83867_DOWNSHIFT_8_COUNT_VAL:
363
+ count = DP83867_DOWNSHIFT_8_COUNT;
364
+ break;
365
+ default:
366
+ return -EINVAL;
367
+ }
368
+
369
+ *data = enable ? count : DOWNSHIFT_DEV_DISABLE;
370
+
371
+ return 0;
372
+}
373
+
374
+static int dp83867_set_downshift(struct phy_device *phydev, u8 cnt)
375
+{
376
+ int val, count;
377
+
378
+ if (cnt > DP83867_DOWNSHIFT_8_COUNT)
379
+ return -E2BIG;
380
+
381
+ if (!cnt)
382
+ return phy_clear_bits(phydev, DP83867_CFG2,
383
+ DP83867_DOWNSHIFT_EN);
384
+
385
+ switch (cnt) {
386
+ case DP83867_DOWNSHIFT_1_COUNT:
387
+ count = DP83867_DOWNSHIFT_1_COUNT_VAL;
388
+ break;
389
+ case DP83867_DOWNSHIFT_2_COUNT:
390
+ count = DP83867_DOWNSHIFT_2_COUNT_VAL;
391
+ break;
392
+ case DP83867_DOWNSHIFT_4_COUNT:
393
+ count = DP83867_DOWNSHIFT_4_COUNT_VAL;
394
+ break;
395
+ case DP83867_DOWNSHIFT_8_COUNT:
396
+ count = DP83867_DOWNSHIFT_8_COUNT_VAL;
397
+ break;
398
+ default:
399
+ phydev_err(phydev,
400
+ "Downshift count must be 1, 2, 4 or 8\n");
401
+ return -EINVAL;
402
+ }
403
+
404
+ val = DP83867_DOWNSHIFT_EN;
405
+ val |= FIELD_PREP(DP83867_DOWNSHIFT_ATTEMPT_MASK, count);
406
+
407
+ return phy_modify(phydev, DP83867_CFG2,
408
+ DP83867_DOWNSHIFT_EN | DP83867_DOWNSHIFT_ATTEMPT_MASK,
409
+ val);
410
+}
411
+
412
+static int dp83867_get_tunable(struct phy_device *phydev,
413
+ struct ethtool_tunable *tuna, void *data)
414
+{
415
+ switch (tuna->id) {
416
+ case ETHTOOL_PHY_DOWNSHIFT:
417
+ return dp83867_get_downshift(phydev, data);
418
+ default:
419
+ return -EOPNOTSUPP;
420
+ }
421
+}
422
+
423
+static int dp83867_set_tunable(struct phy_device *phydev,
424
+ struct ethtool_tunable *tuna, const void *data)
425
+{
426
+ switch (tuna->id) {
427
+ case ETHTOOL_PHY_DOWNSHIFT:
428
+ return dp83867_set_downshift(phydev, *(const u8 *)data);
429
+ default:
430
+ return -EOPNOTSUPP;
431
+ }
432
+}
433
+
434
+static int dp83867_config_port_mirroring(struct phy_device *phydev)
435
+{
436
+ struct dp83867_private *dp83867 =
437
+ (struct dp83867_private *)phydev->priv;
438
+
439
+ if (dp83867->port_mirroring == DP83867_PORT_MIRROING_EN)
440
+ phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
441
+ DP83867_CFG4_PORT_MIRROR_EN);
442
+ else
443
+ phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
444
+ DP83867_CFG4_PORT_MIRROR_EN);
445
+ return 0;
446
+}
447
+
448
+static int dp83867_verify_rgmii_cfg(struct phy_device *phydev)
449
+{
450
+ struct dp83867_private *dp83867 = phydev->priv;
451
+
452
+ /* Existing behavior was to use default pin strapping delay in rgmii
453
+ * mode, but rgmii should have meant no delay. Warn existing users.
454
+ */
455
+ if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
456
+ const u16 val = phy_read_mmd(phydev, DP83867_DEVADDR,
457
+ DP83867_STRAP_STS2);
458
+ const u16 txskew = (val & DP83867_STRAP_STS2_CLK_SKEW_TX_MASK) >>
459
+ DP83867_STRAP_STS2_CLK_SKEW_TX_SHIFT;
460
+ const u16 rxskew = (val & DP83867_STRAP_STS2_CLK_SKEW_RX_MASK) >>
461
+ DP83867_STRAP_STS2_CLK_SKEW_RX_SHIFT;
462
+
463
+ if (txskew != DP83867_STRAP_STS2_CLK_SKEW_NONE ||
464
+ rxskew != DP83867_STRAP_STS2_CLK_SKEW_NONE)
465
+ phydev_warn(phydev,
466
+ "PHY has delays via pin strapping, but phy-mode = 'rgmii'\n"
467
+ "Should be 'rgmii-id' to use internal delays txskew:%x rxskew:%x\n",
468
+ txskew, rxskew);
469
+ }
470
+
471
+ /* RX delay *must* be specified if internal delay of RX is used. */
472
+ if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
473
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) &&
474
+ dp83867->rx_id_delay == DP83867_RGMII_RX_CLK_DELAY_INV) {
475
+ phydev_err(phydev, "ti,rx-internal-delay must be specified\n");
476
+ return -EINVAL;
477
+ }
478
+
479
+ /* TX delay *must* be specified if internal delay of TX is used. */
480
+ if ((phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
481
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) &&
482
+ dp83867->tx_id_delay == DP83867_RGMII_TX_CLK_DELAY_INV) {
483
+ phydev_err(phydev, "ti,tx-internal-delay must be specified\n");
484
+ return -EINVAL;
485
+ }
486
+
487
+ return 0;
488
+}
489
+
490
+#if IS_ENABLED(CONFIG_OF_MDIO)
168491 static int dp83867_of_init(struct phy_device *phydev)
169492 {
170493 struct dp83867_private *dp83867 = phydev->priv;
....@@ -175,38 +498,55 @@
175498 if (!of_node)
176499 return -ENODEV;
177500
178
- dp83867->io_impedance = -EINVAL;
179
-
180501 /* Optional configuration */
181502 ret = of_property_read_u32(of_node, "ti,clk-output-sel",
182503 &dp83867->clk_output_sel);
183
- if (ret || dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK)
184
- /* Keep the default value if ti,clk-output-sel is not set
185
- * or too high
504
+ /* If not set, keep default */
505
+ if (!ret) {
506
+ dp83867->set_clk_output = true;
507
+ /* Valid values are 0 to DP83867_CLK_O_SEL_REF_CLK or
508
+ * DP83867_CLK_O_SEL_OFF.
186509 */
187
- dp83867->clk_output_sel = DP83867_CLK_O_SEL_REF_CLK;
510
+ if (dp83867->clk_output_sel > DP83867_CLK_O_SEL_REF_CLK &&
511
+ dp83867->clk_output_sel != DP83867_CLK_O_SEL_OFF) {
512
+ phydev_err(phydev, "ti,clk-output-sel value %u out of range\n",
513
+ dp83867->clk_output_sel);
514
+ return -EINVAL;
515
+ }
516
+ }
188517
189518 if (of_property_read_bool(of_node, "ti,max-output-impedance"))
190519 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
191520 else if (of_property_read_bool(of_node, "ti,min-output-impedance"))
192521 dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MIN;
522
+ else
523
+ dp83867->io_impedance = -1; /* leave at default */
193524
194525 dp83867->rxctrl_strap_quirk = of_property_read_bool(of_node,
195
- "ti,dp83867-rxctrl-strap-quirk");
526
+ "ti,dp83867-rxctrl-strap-quirk");
196527
528
+ dp83867->sgmii_ref_clk_en = of_property_read_bool(of_node,
529
+ "ti,sgmii-ref-clock-output-enable");
530
+
531
+ dp83867->rx_id_delay = DP83867_RGMII_RX_CLK_DELAY_INV;
197532 ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
198533 &dp83867->rx_id_delay);
199
- if (ret &&
200
- (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
201
- phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
202
- return ret;
534
+ if (!ret && dp83867->rx_id_delay > DP83867_RGMII_RX_CLK_DELAY_MAX) {
535
+ phydev_err(phydev,
536
+ "ti,rx-internal-delay value of %u out of range\n",
537
+ dp83867->rx_id_delay);
538
+ return -EINVAL;
539
+ }
203540
541
+ dp83867->tx_id_delay = DP83867_RGMII_TX_CLK_DELAY_INV;
204542 ret = of_property_read_u32(of_node, "ti,tx-internal-delay",
205543 &dp83867->tx_id_delay);
206
- if (ret &&
207
- (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
208
- phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID))
209
- return ret;
544
+ if (!ret && dp83867->tx_id_delay > DP83867_RGMII_TX_CLK_DELAY_MAX) {
545
+ phydev_err(phydev,
546
+ "ti,tx-internal-delay value of %u out of range\n",
547
+ dp83867->tx_id_delay);
548
+ return -EINVAL;
549
+ }
210550
211551 if (of_property_read_bool(of_node, "enet-phy-lane-swap"))
212552 dp83867->port_mirroring = DP83867_PORT_MIRROING_EN;
....@@ -214,8 +554,34 @@
214554 if (of_property_read_bool(of_node, "enet-phy-lane-no-swap"))
215555 dp83867->port_mirroring = DP83867_PORT_MIRROING_DIS;
216556
217
- return of_property_read_u32(of_node, "ti,fifo-depth",
218
- &dp83867->fifo_depth);
557
+ ret = of_property_read_u32(of_node, "ti,fifo-depth",
558
+ &dp83867->tx_fifo_depth);
559
+ if (ret) {
560
+ ret = of_property_read_u32(of_node, "tx-fifo-depth",
561
+ &dp83867->tx_fifo_depth);
562
+ if (ret)
563
+ dp83867->tx_fifo_depth =
564
+ DP83867_PHYCR_FIFO_DEPTH_4_B_NIB;
565
+ }
566
+
567
+ if (dp83867->tx_fifo_depth > DP83867_PHYCR_FIFO_DEPTH_MAX) {
568
+ phydev_err(phydev, "tx-fifo-depth value %u out of range\n",
569
+ dp83867->tx_fifo_depth);
570
+ return -EINVAL;
571
+ }
572
+
573
+ ret = of_property_read_u32(of_node, "rx-fifo-depth",
574
+ &dp83867->rx_fifo_depth);
575
+ if (ret)
576
+ dp83867->rx_fifo_depth = DP83867_PHYCR_FIFO_DEPTH_4_B_NIB;
577
+
578
+ if (dp83867->rx_fifo_depth > DP83867_PHYCR_FIFO_DEPTH_MAX) {
579
+ phydev_err(phydev, "rx-fifo-depth value %u out of range\n",
580
+ dp83867->rx_fifo_depth);
581
+ return -EINVAL;
582
+ }
583
+
584
+ return 0;
219585 }
220586 #else
221587 static int dp83867_of_init(struct phy_device *phydev)
....@@ -224,39 +590,80 @@
224590 }
225591 #endif /* CONFIG_OF_MDIO */
226592
227
-static int dp83867_config_init(struct phy_device *phydev)
593
+static int dp83867_probe(struct phy_device *phydev)
228594 {
229595 struct dp83867_private *dp83867;
596
+
597
+ dp83867 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83867),
598
+ GFP_KERNEL);
599
+ if (!dp83867)
600
+ return -ENOMEM;
601
+
602
+ phydev->priv = dp83867;
603
+
604
+ return dp83867_of_init(phydev);
605
+}
606
+
607
+static int dp83867_config_init(struct phy_device *phydev)
608
+{
609
+ struct dp83867_private *dp83867 = phydev->priv;
230610 int ret, val, bs;
231611 u16 delay;
232612
233
- if (!phydev->priv) {
234
- dp83867 = devm_kzalloc(&phydev->mdio.dev, sizeof(*dp83867),
235
- GFP_KERNEL);
236
- if (!dp83867)
237
- return -ENOMEM;
613
+ /* Force speed optimization for the PHY even if it strapped */
614
+ ret = phy_modify(phydev, DP83867_CFG2, DP83867_DOWNSHIFT_EN,
615
+ DP83867_DOWNSHIFT_EN);
616
+ if (ret)
617
+ return ret;
238618
239
- phydev->priv = dp83867;
240
- ret = dp83867_of_init(phydev);
241
- if (ret)
242
- return ret;
243
- } else {
244
- dp83867 = (struct dp83867_private *)phydev->priv;
245
- }
619
+ ret = dp83867_verify_rgmii_cfg(phydev);
620
+ if (ret)
621
+ return ret;
246622
247623 /* RX_DV/RX_CTRL strapped in mode 1 or mode 2 workaround */
248
- if (dp83867->rxctrl_strap_quirk) {
249
- val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
250
- val &= ~BIT(7);
251
- phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
624
+ if (dp83867->rxctrl_strap_quirk)
625
+ phy_clear_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
626
+ BIT(7));
627
+
628
+ bs = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_STRAP_STS2);
629
+ if (bs & DP83867_STRAP_STS2_STRAP_FLD) {
630
+ /* When using strap to enable FLD, the ENERGY_LOST_FLD_THR will
631
+ * be set to 0x2. This may causes the PHY link to be unstable -
632
+ * the default value 0x1 need to be restored.
633
+ */
634
+ ret = phy_modify_mmd(phydev, DP83867_DEVADDR,
635
+ DP83867_FLD_THR_CFG,
636
+ DP83867_FLD_THR_CFG_ENERGY_LOST_THR_MASK,
637
+ 0x1);
638
+ if (ret)
639
+ return ret;
640
+ }
641
+
642
+ if (phy_interface_is_rgmii(phydev) ||
643
+ phydev->interface == PHY_INTERFACE_MODE_SGMII) {
644
+ val = phy_read(phydev, MII_DP83867_PHYCTRL);
645
+ if (val < 0)
646
+ return val;
647
+
648
+ val &= ~DP83867_PHYCR_TX_FIFO_DEPTH_MASK;
649
+ val |= (dp83867->tx_fifo_depth <<
650
+ DP83867_PHYCR_TX_FIFO_DEPTH_SHIFT);
651
+
652
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
653
+ val &= ~DP83867_PHYCR_RX_FIFO_DEPTH_MASK;
654
+ val |= (dp83867->rx_fifo_depth <<
655
+ DP83867_PHYCR_RX_FIFO_DEPTH_SHIFT);
656
+ }
657
+
658
+ ret = phy_write(phydev, MII_DP83867_PHYCTRL, val);
659
+ if (ret)
660
+ return ret;
252661 }
253662
254663 if (phy_interface_is_rgmii(phydev)) {
255664 val = phy_read(phydev, MII_DP83867_PHYCTRL);
256665 if (val < 0)
257666 return val;
258
- val &= ~DP83867_PHYCR_FIFO_DEPTH_MASK;
259
- val |= (dp83867->fifo_depth << DP83867_PHYCR_FIFO_DEPTH_SHIFT);
260667
261668 /* The code below checks if "port mirroring" N/A MODE4 has been
262669 * enabled during power on bootstrap.
....@@ -276,9 +683,16 @@
276683 if (ret)
277684 return ret;
278685
279
- /* Set up RGMII delays */
686
+ /* If rgmii mode with no internal delay is selected, we do NOT use
687
+ * aligned mode as one might expect. Instead we use the PHY's default
688
+ * based on pin strapping. And the "mode 0" default is to *use*
689
+ * internal delay with a value of 7 (2.00 ns).
690
+ *
691
+ * Set up RGMII delays
692
+ */
280693 val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL);
281694
695
+ val &= ~(DP83867_RGMII_TX_CLK_DELAY_EN | DP83867_RGMII_RX_CLK_DELAY_EN);
282696 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
283697 val |= (DP83867_RGMII_TX_CLK_DELAY_EN | DP83867_RGMII_RX_CLK_DELAY_EN);
284698
....@@ -290,24 +704,22 @@
290704
291705 phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIICTL, val);
292706
293
- delay = (dp83867->rx_id_delay |
294
- (dp83867->tx_id_delay << DP83867_RGMII_TX_CLK_DELAY_SHIFT));
707
+ delay = 0;
708
+ if (dp83867->rx_id_delay != DP83867_RGMII_RX_CLK_DELAY_INV)
709
+ delay |= dp83867->rx_id_delay;
710
+ if (dp83867->tx_id_delay != DP83867_RGMII_TX_CLK_DELAY_INV)
711
+ delay |= dp83867->tx_id_delay <<
712
+ DP83867_RGMII_TX_CLK_DELAY_SHIFT;
295713
296714 phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_RGMIIDCTL,
297715 delay);
298
-
299
- if (dp83867->io_impedance >= 0) {
300
- val = phy_read_mmd(phydev, DP83867_DEVADDR,
301
- DP83867_IO_MUX_CFG);
302
-
303
- val &= ~DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
304
- val |= dp83867->io_impedance &
305
- DP83867_IO_MUX_CFG_IO_IMPEDANCE_CTRL;
306
-
307
- phy_write_mmd(phydev, DP83867_DEVADDR,
308
- DP83867_IO_MUX_CFG, val);
309
- }
310716 }
717
+
718
+ /* If specified, set io impedance */
719
+ if (dp83867->io_impedance >= 0)
720
+ phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG,
721
+ DP83867_IO_MUX_CFG_IO_IMPEDANCE_MASK,
722
+ dp83867->io_impedance);
311723
312724 if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
313725 /* For support SPEED_10 in SGMII mode
....@@ -316,12 +728,10 @@
316728 * does not affect SPEED_100 and
317729 * SPEED_1000.
318730 */
319
- val = phy_read_mmd(phydev, DP83867_DEVADDR,
320
- DP83867_10M_SGMII_CFG);
321
- val &= ~DP83867_10M_SGMII_RATE_ADAPT_MASK;
322
- ret = phy_write_mmd(phydev, DP83867_DEVADDR,
323
- DP83867_10M_SGMII_CFG, val);
324
-
731
+ ret = phy_modify_mmd(phydev, DP83867_DEVADDR,
732
+ DP83867_10M_SGMII_CFG,
733
+ DP83867_10M_SGMII_RATE_ADAPT_MASK,
734
+ 0);
325735 if (ret)
326736 return ret;
327737
....@@ -329,13 +739,32 @@
329739 * are 01). That is not enough to finalize autoneg on some
330740 * devices. Increase this timer duration to maximum 16ms.
331741 */
332
- val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4);
333
- val &= ~DP83867_CFG4_SGMII_ANEG_MASK;
334
- val |= DP83867_CFG4_SGMII_ANEG_TIMER_16MS;
335
- ret = phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4, val);
742
+ ret = phy_modify_mmd(phydev, DP83867_DEVADDR,
743
+ DP83867_CFG4,
744
+ DP83867_CFG4_SGMII_ANEG_MASK,
745
+ DP83867_CFG4_SGMII_ANEG_TIMER_16MS);
336746
337747 if (ret)
338748 return ret;
749
+
750
+ val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL);
751
+ /* SGMII type is set to 4-wire mode by default.
752
+ * If we place appropriate property in dts (see above)
753
+ * switch on 6-wire mode.
754
+ */
755
+ if (dp83867->sgmii_ref_clk_en)
756
+ val |= DP83867_SGMII_TYPE;
757
+ else
758
+ val &= ~DP83867_SGMII_TYPE;
759
+ phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_SGMIICTL, val);
760
+
761
+ /* This is a SW workaround for link instability if RX_CTRL is
762
+ * not strapped to mode 3 or 4 in HW. This is required for SGMII
763
+ * in addition to clearing bit 7, handled above.
764
+ */
765
+ if (dp83867->rxctrl_strap_quirk)
766
+ phy_set_bits_mmd(phydev, DP83867_DEVADDR, DP83867_CFG4,
767
+ BIT(8));
339768 }
340769
341770 val = phy_read(phydev, DP83867_CFG3);
....@@ -350,28 +779,19 @@
350779 dp83867_config_port_mirroring(phydev);
351780
352781 /* Clock output selection if muxing property is set */
353
- if (dp83867->clk_output_sel != DP83867_CLK_O_SEL_REF_CLK) {
354
- val = phy_read_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG);
355
- val &= ~DP83867_IO_MUX_CFG_CLK_O_SEL_MASK;
356
- val |= (dp83867->clk_output_sel << DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT);
357
- phy_write_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG, val);
358
- }
782
+ if (dp83867->set_clk_output) {
783
+ u16 mask = DP83867_IO_MUX_CFG_CLK_O_DISABLE;
359784
360
- /* Check if the PHY is an internal testing mode.
361
- * This mode can cause connection problems.
362
- */
363
- val = phy_read_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR);
364
- if (val & BIT(7)) {
365
- val &= ~BIT(7);
366
- phy_write_mmd_indirect(phydev, DP83867_CFG4, DP83867_DEVADDR,
367
- val);
368
- }
785
+ if (dp83867->clk_output_sel == DP83867_CLK_O_SEL_OFF) {
786
+ val = DP83867_IO_MUX_CFG_CLK_O_DISABLE;
787
+ } else {
788
+ mask |= DP83867_IO_MUX_CFG_CLK_O_SEL_MASK;
789
+ val = dp83867->clk_output_sel <<
790
+ DP83867_IO_MUX_CFG_CLK_O_SEL_SHIFT;
791
+ }
369792
370
- /* Disable FORCE_LINK_GOOD */
371
- val = phy_read(phydev, MII_DP83867_PHYCTRL);
372
- if (val & MII_DP83867_PHYCTRL_FORCE_LINK_GOOD) {
373
- val &= ~(MII_DP83867_PHYCTRL_FORCE_LINK_GOOD);
374
- phy_write(phydev, MII_DP83867_PHYCTRL, val);
793
+ phy_modify_mmd(phydev, DP83867_DEVADDR, DP83867_IO_MUX_CFG,
794
+ mask, val);
375795 }
376796
377797 return 0;
....@@ -381,11 +801,40 @@
381801 {
382802 int err;
383803
384
- err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET);
804
+ err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART);
385805 if (err < 0)
386806 return err;
387807
388
- return dp83867_config_init(phydev);
808
+ usleep_range(10, 20);
809
+
810
+ return phy_modify(phydev, MII_DP83867_PHYCTRL,
811
+ DP83867_PHYCR_FORCE_LINK_GOOD, 0);
812
+}
813
+
814
+static void dp83867_link_change_notify(struct phy_device *phydev)
815
+{
816
+ /* There is a limitation in DP83867 PHY device where SGMII AN is
817
+ * only triggered once after the device is booted up. Even after the
818
+ * PHY TPI is down and up again, SGMII AN is not triggered and
819
+ * hence no new in-band message from PHY to MAC side SGMII.
820
+ * This could cause an issue during power up, when PHY is up prior
821
+ * to MAC. At this condition, once MAC side SGMII is up, MAC side
822
+ * SGMII wouldn`t receive new in-band message from TI PHY with
823
+ * correct link status, speed and duplex info.
824
+ * Thus, implemented a SW solution here to retrigger SGMII Auto-Neg
825
+ * whenever there is a link change.
826
+ */
827
+ if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
828
+ int val = 0;
829
+
830
+ val = phy_clear_bits(phydev, DP83867_CFG2,
831
+ DP83867_SGMII_AUTONEG_EN);
832
+ if (val < 0)
833
+ return;
834
+
835
+ phy_set_bits(phydev, DP83867_CFG2,
836
+ DP83867_SGMII_AUTONEG_EN);
837
+ }
389838 }
390839
391840 static struct phy_driver dp83867_driver[] = {
....@@ -393,11 +842,18 @@
393842 .phy_id = DP83867_PHY_ID,
394843 .phy_id_mask = 0xfffffff0,
395844 .name = "TI DP83867",
396
- .features = PHY_GBIT_FEATURES,
397
- .flags = PHY_HAS_INTERRUPT,
845
+ /* PHY_GBIT_FEATURES */
398846
847
+ .probe = dp83867_probe,
399848 .config_init = dp83867_config_init,
400849 .soft_reset = dp83867_phy_reset,
850
+
851
+ .read_status = dp83867_read_status,
852
+ .get_tunable = dp83867_get_tunable,
853
+ .set_tunable = dp83867_set_tunable,
854
+
855
+ .get_wol = dp83867_get_wol,
856
+ .set_wol = dp83867_set_wol,
401857
402858 /* IRQ related */
403859 .ack_interrupt = dp83867_ack_interrupt,
....@@ -405,6 +861,8 @@
405861
406862 .suspend = genphy_suspend,
407863 .resume = genphy_resume,
864
+
865
+ .link_change_notify = dp83867_link_change_notify,
408866 },
409867 };
410868 module_phy_driver(dp83867_driver);
....@@ -418,4 +876,4 @@
418876
419877 MODULE_DESCRIPTION("Texas Instruments DP83867 PHY driver");
420878 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com");
421
-MODULE_LICENSE("GPL");
879
+MODULE_LICENSE("GPL v2");