1// SPDX-License-Identifier: GPL-2.0
2/* Driver for the Texas Instruments DP83TG720 PHY
3 * Copyright (c) 2023 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
4 */
5#include <linux/bitfield.h>
6#include <linux/ethtool_netlink.h>
7#include <linux/jiffies.h>
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/phy.h>
11#include <linux/random.h>
12
13#include "open_alliance_helpers.h"
14
15/*
16 * DP83TG720S_POLL_ACTIVE_LINK - Polling interval in milliseconds when the link
17 * is active.
18 * DP83TG720S_POLL_NO_LINK_MIN - Minimum polling interval in milliseconds when
19 * the link is down.
20 * DP83TG720S_POLL_NO_LINK_MAX - Maximum polling interval in milliseconds when
21 * the link is down.
22 *
23 * These values are not documented or officially recommended by the vendor but
24 * were determined through empirical testing. They achieve a good balance in
25 * minimizing the number of reset retries while ensuring reliable link recovery
26 * within a reasonable timeframe.
27 */
28#define DP83TG720S_POLL_ACTIVE_LINK 1000
29#define DP83TG720S_POLL_NO_LINK_MIN 100
30#define DP83TG720S_POLL_NO_LINK_MAX 1000
31
32#define DP83TG720S_PHY_ID 0x2000a284
33
34/* MDIO_MMD_VEND2 registers */
35#define DP83TG720S_MII_REG_10 0x10
36#define DP83TG720S_STS_MII_INT BIT(7)
37#define DP83TG720S_LINK_STATUS BIT(0)
38
39/* TDR Configuration Register (0x1E) */
40#define DP83TG720S_TDR_CFG 0x1e
41/* 1b = TDR start, 0b = No TDR */
42#define DP83TG720S_TDR_START BIT(15)
43/* 1b = TDR auto on link down, 0b = Manual TDR start */
44#define DP83TG720S_CFG_TDR_AUTO_RUN BIT(14)
45/* 1b = TDR done, 0b = TDR in progress */
46#define DP83TG720S_TDR_DONE BIT(1)
47/* 1b = TDR fail, 0b = TDR success */
48#define DP83TG720S_TDR_FAIL BIT(0)
49
50#define DP83TG720S_PHY_RESET 0x1f
51#define DP83TG720S_HW_RESET BIT(15)
52
53#define DP83TG720S_LPS_CFG3 0x18c
54/* Power modes are documented as bit fields but used as values */
55/* Power Mode 0 is Normal mode */
56#define DP83TG720S_LPS_CFG3_PWR_MODE_0 BIT(0)
57
58/* Open Aliance 1000BaseT1 compatible HDD.TDR Fault Status Register */
59#define DP83TG720S_TDR_FAULT_STATUS 0x30f
60
61/* Register 0x0301: TDR Configuration 2 */
62#define DP83TG720S_TDR_CFG2 0x301
63
64/* Register 0x0303: TDR Configuration 3 */
65#define DP83TG720S_TDR_CFG3 0x303
66
67/* Register 0x0304: TDR Configuration 4 */
68#define DP83TG720S_TDR_CFG4 0x304
69
70/* Register 0x0405: Unknown Register */
71#define DP83TG720S_UNKNOWN_0405 0x405
72
73#define DP83TG720S_LINK_QUAL_3 0x547
74#define DP83TG720S_LINK_LOSS_CNT_MASK GENMASK(15, 10)
75
76/* Register 0x0576: TDR Master Link Down Control */
77#define DP83TG720S_TDR_MASTER_LINK_DOWN 0x576
78
79#define DP83TG720S_RGMII_DELAY_CTRL 0x602
80/* In RGMII mode, Enable or disable the internal delay for RXD */
81#define DP83TG720S_RGMII_RX_CLK_SEL BIT(1)
82/* In RGMII mode, Enable or disable the internal delay for TXD */
83#define DP83TG720S_RGMII_TX_CLK_SEL BIT(0)
84
85/*
86 * DP83TG720S_PKT_STAT_x registers correspond to similarly named registers
87 * in the datasheet (PKT_STAT_1 through PKT_STAT_6). These registers store
88 * 32-bit or 16-bit counters for TX and RX statistics and must be read in
89 * sequence to ensure the counters are cleared correctly.
90 *
91 * - DP83TG720S_PKT_STAT_1: Contains TX packet count bits [15:0].
92 * - DP83TG720S_PKT_STAT_2: Contains TX packet count bits [31:16].
93 * - DP83TG720S_PKT_STAT_3: Contains TX error packet count.
94 * - DP83TG720S_PKT_STAT_4: Contains RX packet count bits [15:0].
95 * - DP83TG720S_PKT_STAT_5: Contains RX packet count bits [31:16].
96 * - DP83TG720S_PKT_STAT_6: Contains RX error packet count.
97 *
98 * Keeping the register names as defined in the datasheet helps maintain
99 * clarity and alignment with the documentation.
100 */
101#define DP83TG720S_PKT_STAT_1 0x639
102#define DP83TG720S_PKT_STAT_2 0x63a
103#define DP83TG720S_PKT_STAT_3 0x63b
104#define DP83TG720S_PKT_STAT_4 0x63c
105#define DP83TG720S_PKT_STAT_5 0x63d
106#define DP83TG720S_PKT_STAT_6 0x63e
107
108/* Register 0x083F: Unknown Register */
109#define DP83TG720S_UNKNOWN_083F 0x83f
110
111#define DP83TG720S_SQI_REG_1 0x871
112#define DP83TG720S_SQI_OUT_WORST GENMASK(7, 5)
113#define DP83TG720S_SQI_OUT GENMASK(3, 1)
114
115#define DP83TG720_SQI_MAX 7
116
117struct dp83tg720_stats {
118 u64 link_loss_cnt;
119 u64 tx_pkt_cnt;
120 u64 tx_err_pkt_cnt;
121 u64 rx_pkt_cnt;
122 u64 rx_err_pkt_cnt;
123};
124
125struct dp83tg720_priv {
126 struct dp83tg720_stats stats;
127};
128
129/**
130 * dp83tg720_update_stats - Update the PHY statistics for the DP83TD510 PHY.
131 * @phydev: Pointer to the phy_device structure.
132 *
133 * The function reads the PHY statistics registers and updates the statistics
134 * structure.
135 *
136 * Returns: 0 on success or a negative error code on failure.
137 */
138static int dp83tg720_update_stats(struct phy_device *phydev)
139{
140 struct dp83tg720_priv *priv = phydev->priv;
141 u32 count;
142 int ret;
143
144 /* Read the link loss count */
145 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_LINK_QUAL_3);
146 if (ret < 0)
147 return ret;
148 /* link_loss_cnt */
149 count = FIELD_GET(DP83TG720S_LINK_LOSS_CNT_MASK, ret);
150 priv->stats.link_loss_cnt += count;
151
152 /* The DP83TG720S_PKT_STAT registers are divided into two groups:
153 * - Group 1 (TX stats): DP83TG720S_PKT_STAT_1 to DP83TG720S_PKT_STAT_3
154 * - Group 2 (RX stats): DP83TG720S_PKT_STAT_4 to DP83TG720S_PKT_STAT_6
155 *
156 * Registers in each group are cleared only after reading them in a
157 * plain sequence (e.g., 1, 2, 3 for Group 1 or 4, 5, 6 for Group 2).
158 * Any deviation from the sequence, such as reading 1, 2, 1, 2, 3, will
159 * prevent the group from being cleared. Additionally, the counters
160 * for a group are frozen as soon as the first register in that group
161 * is accessed.
162 */
163 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_1);
164 if (ret < 0)
165 return ret;
166 /* tx_pkt_cnt_15_0 */
167 count = ret;
168
169 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_2);
170 if (ret < 0)
171 return ret;
172 /* tx_pkt_cnt_31_16 */
173 count |= ret << 16;
174 priv->stats.tx_pkt_cnt += count;
175
176 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_3);
177 if (ret < 0)
178 return ret;
179 /* tx_err_pkt_cnt */
180 priv->stats.tx_err_pkt_cnt += ret;
181
182 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_4);
183 if (ret < 0)
184 return ret;
185 /* rx_pkt_cnt_15_0 */
186 count = ret;
187
188 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_5);
189 if (ret < 0)
190 return ret;
191 /* rx_pkt_cnt_31_16 */
192 count |= ret << 16;
193 priv->stats.rx_pkt_cnt += count;
194
195 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_PKT_STAT_6);
196 if (ret < 0)
197 return ret;
198 /* rx_err_pkt_cnt */
199 priv->stats.rx_err_pkt_cnt += ret;
200
201 return 0;
202}
203
204static void dp83tg720_get_link_stats(struct phy_device *phydev,
205 struct ethtool_link_ext_stats *link_stats)
206{
207 struct dp83tg720_priv *priv = phydev->priv;
208
209 link_stats->link_down_events = priv->stats.link_loss_cnt;
210}
211
212static void dp83tg720_get_phy_stats(struct phy_device *phydev,
213 struct ethtool_eth_phy_stats *eth_stats,
214 struct ethtool_phy_stats *stats)
215{
216 struct dp83tg720_priv *priv = phydev->priv;
217
218 stats->tx_packets = priv->stats.tx_pkt_cnt;
219 stats->tx_errors = priv->stats.tx_err_pkt_cnt;
220 stats->rx_packets = priv->stats.rx_pkt_cnt;
221 stats->rx_errors = priv->stats.rx_err_pkt_cnt;
222}
223
224/**
225 * dp83tg720_cable_test_start - Start the cable test for the DP83TG720 PHY.
226 * @phydev: Pointer to the phy_device structure.
227 *
228 * This sequence is based on the documented procedure for the DP83TG720 PHY.
229 *
230 * Returns: 0 on success, a negative error code on failure.
231 */
232static int dp83tg720_cable_test_start(struct phy_device *phydev)
233{
234 int ret;
235
236 /* Initialize the PHY to run the TDR test as described in the
237 * "DP83TG720S-Q1: Configuring for Open Alliance Specification
238 * Compliance (Rev. B)" application note.
239 * Most of the registers are not documented. Some of register names
240 * are guessed by comparing the register offsets with the DP83TD510E.
241 */
242
243 /* Force master link down */
244 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
245 DP83TG720S_TDR_MASTER_LINK_DOWN, val: 0x0400);
246 if (ret)
247 return ret;
248
249 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG2,
250 val: 0xa008);
251 if (ret)
252 return ret;
253
254 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG3,
255 val: 0x0928);
256 if (ret)
257 return ret;
258
259 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG4,
260 val: 0x0004);
261 if (ret)
262 return ret;
263
264 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_UNKNOWN_0405,
265 val: 0x6400);
266 if (ret)
267 return ret;
268
269 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_UNKNOWN_083F,
270 val: 0x3003);
271 if (ret)
272 return ret;
273
274 /* Start the TDR */
275 ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG,
276 DP83TG720S_TDR_START);
277 if (ret)
278 return ret;
279
280 return 0;
281}
282
283/**
284 * dp83tg720_cable_test_get_status - Get the status of the cable test for the
285 * DP83TG720 PHY.
286 * @phydev: Pointer to the phy_device structure.
287 * @finished: Pointer to a boolean that indicates whether the test is finished.
288 *
289 * The function sets the @finished flag to true if the test is complete.
290 *
291 * Returns: 0 on success or a negative error code on failure.
292 */
293static int dp83tg720_cable_test_get_status(struct phy_device *phydev,
294 bool *finished)
295{
296 int ret, stat;
297
298 *finished = false;
299
300 /* Read the TDR status */
301 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_TDR_CFG);
302 if (ret < 0)
303 return ret;
304
305 /* Check if the TDR test is done */
306 if (!(ret & DP83TG720S_TDR_DONE))
307 return 0;
308
309 /* Check for TDR test failure */
310 if (!(ret & DP83TG720S_TDR_FAIL)) {
311 int location;
312
313 /* Read fault status */
314 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
315 DP83TG720S_TDR_FAULT_STATUS);
316 if (ret < 0)
317 return ret;
318
319 /* Get fault type */
320 stat = oa_1000bt1_get_ethtool_cable_result_code(reg_value: ret);
321
322 /* Determine fault location */
323 location = oa_1000bt1_get_tdr_distance(reg_value: ret);
324 if (location > 0)
325 ethnl_cable_test_fault_length(phydev,
326 pair: ETHTOOL_A_CABLE_PAIR_A,
327 cm: location);
328 } else {
329 /* Active link partner or other issues */
330 stat = ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC;
331 }
332
333 *finished = true;
334
335 ethnl_cable_test_result(phydev, pair: ETHTOOL_A_CABLE_PAIR_A, result: stat);
336
337 /* save the current stats before resetting the PHY */
338 ret = dp83tg720_update_stats(phydev);
339 if (ret)
340 return ret;
341
342 return phy_init_hw(phydev);
343}
344
345static int dp83tg720_config_aneg(struct phy_device *phydev)
346{
347 int ret;
348
349 /* Autoneg is not supported and this PHY supports only one speed.
350 * We need to care only about master/slave configuration if it was
351 * changed by user.
352 */
353 ret = genphy_c45_pma_baset1_setup_master_slave(phydev);
354 if (ret)
355 return ret;
356
357 /* Re-read role configuration to make changes visible even if
358 * the link is in administrative down state.
359 */
360 return genphy_c45_pma_baset1_read_master_slave(phydev);
361}
362
363static int dp83tg720_read_status(struct phy_device *phydev)
364{
365 u16 phy_sts;
366 int ret;
367
368 phydev->pause = 0;
369 phydev->asym_pause = 0;
370
371 /* Most of Clause 45 registers are not present, so we can't use
372 * genphy_c45_read_status() here.
373 */
374 phy_sts = phy_read(phydev, DP83TG720S_MII_REG_10);
375 phydev->link = !!(phy_sts & DP83TG720S_LINK_STATUS);
376 if (!phydev->link) {
377 /* save the current stats before resetting the PHY */
378 ret = dp83tg720_update_stats(phydev);
379 if (ret)
380 return ret;
381
382 /* According to the "DP83TC81x, DP83TG72x Software
383 * Implementation Guide", the PHY needs to be reset after a
384 * link loss or if no link is created after at least 100ms.
385 *
386 * Currently we are polling with the PHY_STATE_TIME (1000ms)
387 * interval, which is still enough for not automotive use cases.
388 */
389 ret = phy_init_hw(phydev);
390 if (ret)
391 return ret;
392
393 /* Sleep 600ms for PHY stabilization post-reset.
394 * Empirically chosen value (not documented).
395 * Helps reduce reset bounces with link partners having similar
396 * issues.
397 */
398 msleep(msecs: 600);
399
400 /* After HW reset we need to restore master/slave configuration.
401 * genphy_c45_pma_baset1_read_master_slave() call will be done
402 * by the dp83tg720_config_aneg() function.
403 */
404 ret = dp83tg720_config_aneg(phydev);
405 if (ret)
406 return ret;
407
408 phydev->speed = SPEED_UNKNOWN;
409 phydev->duplex = DUPLEX_UNKNOWN;
410 } else {
411 /* PMA/PMD control 1 register (Register 1.0) is present, but it
412 * doesn't contain the link speed information.
413 * So genphy_c45_read_pma() can't be used here.
414 */
415 ret = genphy_c45_pma_baset1_read_master_slave(phydev);
416 if (ret)
417 return ret;
418
419 phydev->duplex = DUPLEX_FULL;
420 phydev->speed = SPEED_1000;
421 }
422
423 return 0;
424}
425
426static int dp83tg720_get_sqi(struct phy_device *phydev)
427{
428 int ret;
429
430 if (!phydev->link)
431 return 0;
432
433 ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_SQI_REG_1);
434 if (ret < 0)
435 return ret;
436
437 return FIELD_GET(DP83TG720S_SQI_OUT, ret);
438}
439
440static int dp83tg720_get_sqi_max(struct phy_device *phydev)
441{
442 return DP83TG720_SQI_MAX;
443}
444
445static int dp83tg720_config_rgmii_delay(struct phy_device *phydev)
446{
447 u16 rgmii_delay_mask;
448 u16 rgmii_delay = 0;
449
450 switch (phydev->interface) {
451 case PHY_INTERFACE_MODE_RGMII:
452 rgmii_delay = 0;
453 break;
454 case PHY_INTERFACE_MODE_RGMII_ID:
455 rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL |
456 DP83TG720S_RGMII_TX_CLK_SEL;
457 break;
458 case PHY_INTERFACE_MODE_RGMII_RXID:
459 rgmii_delay = DP83TG720S_RGMII_RX_CLK_SEL;
460 break;
461 case PHY_INTERFACE_MODE_RGMII_TXID:
462 rgmii_delay = DP83TG720S_RGMII_TX_CLK_SEL;
463 break;
464 default:
465 return 0;
466 }
467
468 rgmii_delay_mask = DP83TG720S_RGMII_RX_CLK_SEL |
469 DP83TG720S_RGMII_TX_CLK_SEL;
470
471 return phy_modify_mmd(phydev, MDIO_MMD_VEND2,
472 DP83TG720S_RGMII_DELAY_CTRL, mask: rgmii_delay_mask,
473 set: rgmii_delay);
474}
475
476static int dp83tg720_config_init(struct phy_device *phydev)
477{
478 int ret;
479
480 /* Software Restart is not enough to recover from a link failure.
481 * Using Hardware Reset instead.
482 */
483 ret = phy_write(phydev, DP83TG720S_PHY_RESET, DP83TG720S_HW_RESET);
484 if (ret)
485 return ret;
486
487 /* Wait until MDC can be used again.
488 * The wait value of one 1ms is documented in "DP83TG720S-Q1 1000BASE-T1
489 * Automotive Ethernet PHY with SGMII and RGMII" datasheet.
490 */
491 usleep_range(min: 1000, max: 2000);
492
493 if (phy_interface_is_rgmii(phydev)) {
494 ret = dp83tg720_config_rgmii_delay(phydev);
495 if (ret)
496 return ret;
497 }
498
499 /* In case the PHY is bootstrapped in managed mode, we need to
500 * wake it.
501 */
502 ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, DP83TG720S_LPS_CFG3,
503 DP83TG720S_LPS_CFG3_PWR_MODE_0);
504 if (ret)
505 return ret;
506
507 /* Make role configuration visible for ethtool on init and after
508 * rest.
509 */
510 return genphy_c45_pma_baset1_read_master_slave(phydev);
511}
512
513static int dp83tg720_probe(struct phy_device *phydev)
514{
515 struct device *dev = &phydev->mdio.dev;
516 struct dp83tg720_priv *priv;
517
518 priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL);
519 if (!priv)
520 return -ENOMEM;
521
522 phydev->priv = priv;
523
524 return 0;
525}
526
527/**
528 * dp83tg720_get_next_update_time - Determine the next update time for PHY
529 * state
530 * @phydev: Pointer to the phy_device structure
531 *
532 * This function addresses a limitation of the DP83TG720 PHY, which cannot
533 * reliably detect or report a stable link state. To recover from such
534 * scenarios, the PHY must be periodically reset when the link is down. However,
535 * if the link partner also runs Linux with the same driver, synchronized reset
536 * intervals can lead to a deadlock where the link never establishes due to
537 * simultaneous resets on both sides.
538 *
539 * To avoid this, the function implements randomized polling intervals when the
540 * link is down. It ensures that reset intervals are desynchronized by
541 * introducing a random delay between a configured minimum and maximum range.
542 * When the link is up, a fixed polling interval is used to minimize overhead.
543 *
544 * This mechanism guarantees that the link will reestablish within 10 seconds
545 * in the worst-case scenario.
546 *
547 * Return: Time (in jiffies) until the next update event for the PHY state
548 * machine.
549 */
550static unsigned int dp83tg720_get_next_update_time(struct phy_device *phydev)
551{
552 unsigned int next_time_jiffies;
553
554 if (phydev->link) {
555 /* When the link is up, use a fixed 1000ms interval
556 * (in jiffies)
557 */
558 next_time_jiffies =
559 msecs_to_jiffies(DP83TG720S_POLL_ACTIVE_LINK);
560 } else {
561 unsigned int min_jiffies, max_jiffies, rand_jiffies;
562
563 /* When the link is down, randomize interval between min/max
564 * (in jiffies)
565 */
566 min_jiffies = msecs_to_jiffies(DP83TG720S_POLL_NO_LINK_MIN);
567 max_jiffies = msecs_to_jiffies(DP83TG720S_POLL_NO_LINK_MAX);
568
569 rand_jiffies = min_jiffies +
570 get_random_u32_below(ceil: max_jiffies - min_jiffies + 1);
571 next_time_jiffies = rand_jiffies;
572 }
573
574 /* Ensure the polling time is at least one jiffy */
575 return max(next_time_jiffies, 1U);
576}
577
578static struct phy_driver dp83tg720_driver[] = {
579{
580 PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID),
581 .name = "TI DP83TG720S",
582
583 .flags = PHY_POLL_CABLE_TEST,
584 .probe = dp83tg720_probe,
585 .config_aneg = dp83tg720_config_aneg,
586 .read_status = dp83tg720_read_status,
587 .get_features = genphy_c45_pma_read_ext_abilities,
588 .config_init = dp83tg720_config_init,
589 .get_sqi = dp83tg720_get_sqi,
590 .get_sqi_max = dp83tg720_get_sqi_max,
591 .cable_test_start = dp83tg720_cable_test_start,
592 .cable_test_get_status = dp83tg720_cable_test_get_status,
593 .get_link_stats = dp83tg720_get_link_stats,
594 .get_phy_stats = dp83tg720_get_phy_stats,
595 .update_stats = dp83tg720_update_stats,
596 .get_next_update_time = dp83tg720_get_next_update_time,
597
598 .suspend = genphy_suspend,
599 .resume = genphy_resume,
600} };
601module_phy_driver(dp83tg720_driver);
602
603static const struct mdio_device_id __maybe_unused dp83tg720_tbl[] = {
604 { PHY_ID_MATCH_MODEL(DP83TG720S_PHY_ID) },
605 { }
606};
607MODULE_DEVICE_TABLE(mdio, dp83tg720_tbl);
608
609MODULE_DESCRIPTION("Texas Instruments DP83TG720S PHY driver");
610MODULE_AUTHOR("Oleksij Rempel <kernel@pengutronix.de>");
611MODULE_LICENSE("GPL");
612

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of linux/drivers/net/phy/dp83tg720.c