Messages in this thread Patch in this message | | | From | Divya Koppera <> | Subject | [PATCH net-next] net: phy: micrel: Fix latency issues in LAN8814 PHY | Date | Tue, 5 Jul 2022 16:35:54 +0530 |
| |
Latency adjustments done for 1-step and 2-step from default latency register values to fix negative and high mean path delays.
Signed-off-by: Divya Koppera <Divya.Koppera@microchip.com> --- drivers/net/phy/micrel.c | 123 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 3 deletions(-)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index e78d0bf69bc3..3ae0b419298e 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -121,6 +121,26 @@ #define PTP_TIMESTAMP_EN_PDREQ_ BIT(2) #define PTP_TIMESTAMP_EN_PDRES_ BIT(3) +#define PTP_RX_LATENCY_1000 0x0224 +#define PTP_TX_LATENCY_1000 0x0225 + +#define PTP_RX_LATENCY_100 0x0222 +#define PTP_TX_LATENCY_100 0x0223 + +#define PTP_RX_LATENCY_10 0x0220 +#define PTP_TX_LATENCY_10 0x0221 + +#define PTP_LATENCY_1000_CRCTN_1S 0x000C +#define PTP_LATENCY_100_CRCTN_1S 0x028D +#define PTP_LATENCY_10_CRCTN_1S 0x01E + +#define PTP_RX_LATENCY_1000_CRCTN_2S 0x0048 +#define PTP_TX_LATENCY_1000_CRCTN_2S 0x0049 +#define PTP_RX_LATENCY_100_CRCTN_2S 0x0707 +#define PTP_TX_LATENCY_100_CRCTN_2S 0x0275 +#define PTP_RX_LATENCY_10_CRCTN_2S 0x17CE +#define PTP_TX_LATENCY_10_CRCTN_2S 0x17CE + #define PTP_TX_PARSE_L2_ADDR_EN 0x0284 #define PTP_RX_PARSE_L2_ADDR_EN 0x0244 @@ -284,6 +304,15 @@ struct lan8814_ptp_rx_ts { u16 seq_id; }; +struct kszphy_latencies { + u16 rx_10; + u16 tx_10; + u16 rx_100; + u16 tx_100; + u16 rx_1000; + u16 tx_1000; +}; + struct kszphy_ptp_priv { struct mii_timestamper mii_ts; struct phy_device *phydev; @@ -303,6 +332,7 @@ struct kszphy_ptp_priv { struct kszphy_priv { struct kszphy_ptp_priv ptp_priv; + struct kszphy_latencies latencies; const struct kszphy_type *type; int led_mode; u16 vct_ctrl1000; @@ -2087,16 +2117,82 @@ static void lan8814_flush_fifo(struct phy_device *phydev, bool egress) lanphy_read_page_reg(phydev, 5, PTP_TSU_INT_STS); } +static void lan8814_get_latency(struct phy_device *phydev) +{ + struct kszphy_priv *priv = phydev->priv; + struct kszphy_latencies *latencies = &priv->latencies; + + latencies->rx_1000 = lanphy_read_page_reg(phydev, 5, PTP_RX_LATENCY_1000); + latencies->rx_100 = lanphy_read_page_reg(phydev, 5, PTP_RX_LATENCY_100); + latencies->rx_10 = lanphy_read_page_reg(phydev, 5, PTP_RX_LATENCY_10); + latencies->tx_1000 = lanphy_read_page_reg(phydev, 5, PTP_TX_LATENCY_1000); + latencies->tx_100 = lanphy_read_page_reg(phydev, 5, PTP_TX_LATENCY_100); + latencies->tx_10 = lanphy_read_page_reg(phydev, 5, PTP_TX_LATENCY_10); +} + +static void lan8814_latency_config(struct phy_device *phydev, + struct kszphy_latencies *latencies) +{ + switch (phydev->speed) { + case SPEED_1000: + lanphy_write_page_reg(phydev, 5, PTP_RX_LATENCY_1000, + latencies->rx_1000); + lanphy_write_page_reg(phydev, 5, PTP_TX_LATENCY_1000, + latencies->tx_1000); + break; + case SPEED_100: + lanphy_write_page_reg(phydev, 5, PTP_RX_LATENCY_100, + latencies->rx_100); + lanphy_write_page_reg(phydev, 5, PTP_TX_LATENCY_100, + latencies->tx_100); + break; + case SPEED_10: + lanphy_write_page_reg(phydev, 5, PTP_RX_LATENCY_10, + latencies->rx_10); + lanphy_write_page_reg(phydev, 5, PTP_TX_LATENCY_10, + latencies->tx_10); + break; + default: + break; + } +} + +static void lan8814_latency_workaround(struct phy_device *phydev, + struct kszphy_latencies *latencies, bool onestep) +{ + struct kszphy_priv *priv = phydev->priv; + struct kszphy_latencies *priv_latencies = &priv->latencies; + + if (onestep) { + latencies->rx_10 = priv_latencies->rx_10 - PTP_LATENCY_10_CRCTN_1S; + latencies->rx_100 = priv_latencies->rx_100 - PTP_LATENCY_100_CRCTN_1S; + latencies->rx_1000 = priv_latencies->rx_1000 - PTP_LATENCY_1000_CRCTN_1S; + latencies->tx_10 = priv_latencies->tx_10 - PTP_LATENCY_10_CRCTN_1S; + latencies->tx_100 = priv_latencies->tx_100 - PTP_LATENCY_100_CRCTN_1S; + latencies->tx_1000 = priv_latencies->tx_1000 - PTP_LATENCY_1000_CRCTN_1S; + } else { + latencies->rx_10 = priv_latencies->rx_10 - PTP_RX_LATENCY_10_CRCTN_2S; + latencies->rx_100 = priv_latencies->rx_100 - PTP_RX_LATENCY_100_CRCTN_2S; + latencies->rx_1000 = priv_latencies->rx_1000 - PTP_RX_LATENCY_1000_CRCTN_2S; + latencies->tx_10 = priv_latencies->tx_10 - PTP_TX_LATENCY_10_CRCTN_2S; + latencies->tx_100 = priv_latencies->tx_100 - PTP_TX_LATENCY_100_CRCTN_2S; + latencies->tx_1000 = priv_latencies->tx_1000 - PTP_TX_LATENCY_1000_CRCTN_2S; + } +} + static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) { struct kszphy_ptp_priv *ptp_priv = container_of(mii_ts, struct kszphy_ptp_priv, mii_ts); struct phy_device *phydev = ptp_priv->phydev; struct lan8814_shared_priv *shared = phydev->shared->priv; + struct kszphy_priv *priv = phydev->priv; struct lan8814_ptp_rx_ts *rx_ts, *tmp; + struct kszphy_latencies latencies; struct hwtstamp_config config; int txcfg = 0, rxcfg = 0; int pkt_ts_enable; + u16 temp; if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) return -EFAULT; @@ -2146,9 +2242,21 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_TIMESTAMP_EN, pkt_ts_enable); lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_TIMESTAMP_EN, pkt_ts_enable); - if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) - lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, - PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_); + temp = lanphy_read_page_reg(phydev, 5, PTP_TX_MOD); + if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) { + temp |= PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_; + + lan8814_latency_workaround(phydev, &latencies, true); + lan8814_latency_config(phydev, &latencies); + } else if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ON) { + lan8814_latency_workaround(phydev, &latencies, false); + lan8814_latency_config(phydev, &latencies); + } else { + temp &= ~PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_; + + lan8814_latency_config(phydev, &priv->latencies); + } + lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD, temp); if (config.rx_filter != HWTSTAMP_FILTER_NONE) lan8814_config_ts_intr(ptp_priv->phydev, true); @@ -2676,6 +2784,13 @@ static int lan8804_config_init(struct phy_device *phydev) return 0; } +void lan8814_link_change_notify(struct phy_device *phydev) +{ + struct kszphy_priv *priv = phydev->priv; + + lan8814_latency_config(phydev, &priv->latencies); +} + static irqreturn_t lan8814_handle_interrupt(struct phy_device *phydev) { int irq_status, tsu_irq_status; @@ -2923,6 +3038,7 @@ static int lan8814_probe(struct phy_device *phydev) } lan8814_ptp_init(phydev); + lan8814_get_latency(phydev); return 0; } @@ -3117,6 +3233,7 @@ static struct phy_driver ksphy_driver[] = { .resume = kszphy_resume, .config_intr = lan8814_config_intr, .handle_interrupt = lan8814_handle_interrupt, + .link_change_notify = lan8814_link_change_notify, }, { .phy_id = PHY_ID_LAN8804, .phy_id_mask = MICREL_PHY_ID_MASK, -- 2.17.1
| |