Lines Matching +full:phy +full:- +full:reset +full:- +full:post +full:- +full:delay

1 // SPDX-License-Identifier: GPL-2.0
2 /* Driver for the Texas Instruments DP83TG720 PHY
10 #include <linux/phy.h>
16 * DP83TG720 PHY Limitations and Workarounds
18 * The DP83TG720 1000BASE-T1 PHY has several limitations that require
19 * software-side mitigations. These workarounds are implemented throughout
23 * 1. Unreliable Link Detection and Synchronized Reset Deadlock
24 * ------------------------------------------------------------
25 * After a link loss or during link establishment, the DP83TG720 PHY may fail
27 * errata sheet for the DP83TG720 PHY documents this behavior.
34 * However, in point-to-point setups where both link partners use the same
35 * driver (e.g. Linux on both sides), a synchronized reset pattern may emerge.
36 * This leads to a deadlock, where both PHYs reset at the same time and
37 * continuously miss each other during auto-negotiation.
39 * To address this, the reset procedure includes two components:
41 * - A **fixed minimum delay of 1ms** after a hardware reset. The datasheet
42 * "DP83TG720S-Q1 1000BASE-T1 Automotive Ethernet PHY with SGMII and RGMII"
43 * specifies this as the "Post reset stabilization-time prior to MDC preamble
44 * for register access" (T6.2), ensuring the PHY is ready for MDIO
47 * - An **additional asymmetric delay**, empirically chosen based on
50 * the link is re-established within a few cycles.
53 * - dp83tg720_soft_reset()
54 * - dp83tg720_get_next_update_time()
56 * 2. Polling-Based Link Detection and IRQ Support
57 * -----------------------------------------------
58 * Due to the PHY-specific limitation described in section 1, link-up events
60 * polling is required to detect transitions from link-down to link-up.
62 * While link-down events *can* be detected via IRQs on this PHY, this driver
67 * - When the link is up: slow polling (e.g. 1s).
68 * - When the link just went down: fast polling for a short time.
69 * - When the link stays down: fallback to slow polling.
71 * This design balances responsiveness and CPU usage. It sacrifices fast link-up
77 * DP83TG720S_POLL_ACTIVE_LINK - Polling interval in milliseconds when the link
79 * DP83TG720S_POLL_NO_LINK - Polling interval in milliseconds when the
81 * DP83TG720S_FAST_POLL_DURATION_MS - Timeout in milliseconds for no-link
84 * DP83TG720S_POLL_SLOW - Slow polling interval when there is no
86 * DP83TG720S_RESET_DELAY_MS_MASTER - Delay after a reset before attempting
87 * to establish a link again for master phy.
88 * DP83TG720S_RESET_DELAY_MS_SLAVE - Delay after a reset before attempting
89 * to establish a link again for slave phy.
93 * minimizing the number of reset retries while ensuring reliable link recovery
151 /* In RGMII mode, Enable or disable the internal delay for RXD */
153 /* In RGMII mode, Enable or disable the internal delay for TXD */
159 * 32-bit or 16-bit counters for TX and RX statistics and must be read in
162 * - DP83TG720S_PKT_STAT_1: Contains TX packet count bits [15:0].
163 * - DP83TG720S_PKT_STAT_2: Contains TX packet count bits [31:16].
164 * - DP83TG720S_PKT_STAT_3: Contains TX error packet count.
165 * - DP83TG720S_PKT_STAT_4: Contains RX packet count bits [15:0].
166 * - DP83TG720S_PKT_STAT_5: Contains RX packet count bits [31:16].
167 * - DP83TG720S_PKT_STAT_6: Contains RX error packet count.
202 * dp83tg720_update_stats - Update the PHY statistics for the DP83TD510 PHY.
205 * The function reads the PHY statistics registers and updates the statistics
212 struct dp83tg720_priv *priv = phydev->priv; in dp83tg720_update_stats()
222 priv->stats.link_loss_cnt += count; in dp83tg720_update_stats()
225 * - Group 1 (TX stats): DP83TG720S_PKT_STAT_1 to DP83TG720S_PKT_STAT_3 in dp83tg720_update_stats()
226 * - Group 2 (RX stats): DP83TG720S_PKT_STAT_4 to DP83TG720S_PKT_STAT_6 in dp83tg720_update_stats()
246 priv->stats.tx_pkt_cnt += count; in dp83tg720_update_stats()
252 priv->stats.tx_err_pkt_cnt += ret; in dp83tg720_update_stats()
265 priv->stats.rx_pkt_cnt += count; in dp83tg720_update_stats()
271 priv->stats.rx_err_pkt_cnt += ret; in dp83tg720_update_stats()
284 /* Include mandatory MDC-access delay (1ms) + extra asymmetric delay to in dp83tg720_soft_reset()
285 * avoid synchronized reset deadlock. See section 1 in the top-of-file in dp83tg720_soft_reset()
288 if (phydev->master_slave_state == MASTER_SLAVE_STATE_SLAVE) in dp83tg720_soft_reset()
299 struct dp83tg720_priv *priv = phydev->priv; in dp83tg720_get_link_stats()
301 link_stats->link_down_events = priv->stats.link_loss_cnt; in dp83tg720_get_link_stats()
308 struct dp83tg720_priv *priv = phydev->priv; in dp83tg720_get_phy_stats()
310 stats->tx_packets = priv->stats.tx_pkt_cnt; in dp83tg720_get_phy_stats()
311 stats->tx_errors = priv->stats.tx_err_pkt_cnt; in dp83tg720_get_phy_stats()
312 stats->rx_packets = priv->stats.rx_pkt_cnt; in dp83tg720_get_phy_stats()
313 stats->rx_errors = priv->stats.rx_err_pkt_cnt; in dp83tg720_get_phy_stats()
317 * dp83tg720_cable_test_start - Start the cable test for the DP83TG720 PHY.
320 * This sequence is based on the documented procedure for the DP83TG720 PHY.
328 /* Initialize the PHY to run the TDR test as described in the in dp83tg720_cable_test_start()
329 * "DP83TG720S-Q1: Configuring for Open Alliance Specification in dp83tg720_cable_test_start()
376 * dp83tg720_cable_test_get_status - Get the status of the cable test for the
377 * DP83TG720 PHY.
429 /* save the current stats before resetting the PHY */ in dp83tg720_cable_test_get_status()
441 /* Autoneg is not supported and this PHY supports only one speed. in dp83tg720_config_aneg()
449 /* Re-read role configuration to make changes visible even if in dp83tg720_config_aneg()
460 phydev->pause = 0; in dp83tg720_read_status()
461 phydev->asym_pause = 0; in dp83tg720_read_status()
467 phydev->link = !!(phy_sts & DP83TG720S_LINK_STATUS); in dp83tg720_read_status()
468 if (!phydev->link) { in dp83tg720_read_status()
469 /* save the current stats before resetting the PHY */ in dp83tg720_read_status()
475 * Implementation Guide", the PHY needs to be reset after a in dp83tg720_read_status()
482 /* After HW reset we need to restore master/slave configuration. in dp83tg720_read_status()
490 phydev->speed = SPEED_UNKNOWN; in dp83tg720_read_status()
491 phydev->duplex = DUPLEX_UNKNOWN; in dp83tg720_read_status()
501 phydev->duplex = DUPLEX_FULL; in dp83tg720_read_status()
502 phydev->speed = SPEED_1000; in dp83tg720_read_status()
512 if (!phydev->link) in dp83tg720_get_sqi()
532 switch (phydev->interface) { in dp83tg720_config_rgmii_delay()
562 /* Reset the PHY to recover from a link failure */ in dp83tg720_config_init()
573 /* In case the PHY is bootstrapped in managed mode, we need to in dp83tg720_config_init()
589 struct device *dev = &phydev->mdio.dev; in dp83tg720_probe()
594 return -ENOMEM; in dp83tg720_probe()
596 phydev->priv = priv; in dp83tg720_probe()
602 * dp83tg720_get_next_update_time - Return next polling interval for PHY state
606 * downtime duration. See the "2. Polling-Based Link Detection and IRQ Support"
613 struct dp83tg720_priv *priv = phydev->priv; in dp83tg720_get_next_update_time()
616 if (phydev->link) { in dp83tg720_get_next_update_time()
617 priv->last_link_down_jiffies = 0; in dp83tg720_get_next_update_time()
625 if (!priv->last_link_down_jiffies) in dp83tg720_get_next_update_time()
626 priv->last_link_down_jiffies = now; in dp83tg720_get_next_update_time()
628 if (time_before(now, priv->last_link_down_jiffies + in dp83tg720_get_next_update_time()
676 MODULE_DESCRIPTION("Texas Instruments DP83TG720S PHY driver");