Lines Matching +full:no +full:- +full:comparator +full:- +full:bypass

1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 * Driver for Microsemi VSC85xx PHYs - timestamping and PHC support
27 /* phydev->bus->mdio_lock should be locked when using this function */
30 struct vsc8531_private *priv = phydev->priv; in phy_ts_base_write()
32 WARN_ON_ONCE(!mutex_is_locked(&phydev->mdio.bus->mdio_lock)); in phy_ts_base_write()
33 return __mdiobus_write(phydev->mdio.bus, priv->ts_base_addr, regnum, in phy_ts_base_write()
37 /* phydev->bus->mdio_lock should be locked when using this function */
40 struct vsc8531_private *priv = phydev->priv; in phy_ts_base_read()
42 WARN_ON_ONCE(!mutex_is_locked(&phydev->mdio.bus->mdio_lock)); in phy_ts_base_read()
43 return __mdiobus_read(phydev->mdio.bus, priv->ts_base_addr, regnum); in phy_ts_base_read()
66 struct vsc8531_private *priv = phydev->priv; in vsc85xx_ts_read_csr()
67 bool base_port = phydev->mdio.addr == priv->ts_base_addr; in vsc85xx_ts_read_csr()
110 struct vsc8531_private *priv = phydev->priv; in vsc85xx_ts_write_csr()
111 bool base_port = phydev->mdio.addr == priv->ts_base_addr; in vsc85xx_ts_write_csr()
112 u32 reg, bypass, cnt = 0, lower = val & 0xffff, upper = val >> 16; in vsc85xx_ts_write_csr() local
136 bypass = phy_ts_base_read(phydev, MSCC_PHY_BYPASS_CONTROL); in vsc85xx_ts_write_csr()
156 phy_ts_base_write(phydev, MSCC_PHY_BYPASS_CONTROL, bypass); in vsc85xx_ts_write_csr()
164 #define PTP_HEADER_BYTE_8_31(x) (31 - (x))
165 #define MAC_ADDRESS_BYTE(x) ((x) + (35 - ETH_ALEN + 1))
173 for (i = 1; i >= 0; i--) in vsc85xx_ts_fsb_init()
183 for (i = ETH_ALEN - 1; i >= 0; i--) in vsc85xx_ts_fsb_init()
193 for (pos = i * 5 + 4; pos >= i * 5; pos--) in vsc85xx_ts_fsb_init()
251 /* No need to set latencies of packets if the PHY is not connected */ in vsc85xx_ts_set_latencies()
252 if (!phydev->link) in vsc85xx_ts_set_latencies()
256 STALL_EGR_LATENCY(phydev->speed)); in vsc85xx_ts_set_latencies()
258 switch (phydev->speed) { in vsc85xx_ts_set_latencies()
366 if (iphdr->version != 4 || iphdr->protocol != IPPROTO_UDP) in get_ptp_header_l4()
378 if (ethhdr->h_proto == htons(ETH_P_1588)) in get_ptp_header_tx()
382 if (ethhdr->h_proto != htons(ETH_P_IP)) in get_ptp_header_tx()
398 return (struct vsc85xx_ptphdr *)skb->data; in get_ptp_header_rx()
400 iphdr = (struct iphdr *)skb->data; in get_ptp_header_rx()
401 udphdr = (struct udphdr *)(skb->data + iphdr->ihl * 4); in get_ptp_header_rx()
413 return -EOPNOTSUPP; in get_sig()
415 sig[0] = (__force u16)ptphdr->seq_id >> 8; in get_sig()
416 sig[1] = (__force u16)ptphdr->seq_id & GENMASK(7, 0); in get_sig()
417 sig[2] = ptphdr->domain; in get_sig()
418 sig[3] = ptphdr->tsmt & GENMASK(3, 0); in get_sig()
420 memcpy(&sig[4], ethhdr->h_dest, ETH_ALEN); in get_sig()
424 sig[i] = ptphdr->tsmt & GENMASK(3, 0); in get_sig()
441 reg = vsc85xx_ts_read_csr(ptp->phydev, PROCESSOR, in vsc85xx_dequeue_skb()
451 reg = vsc85xx_ts_read_csr(ptp->phydev, PROCESSOR, in vsc85xx_dequeue_skb()
459 len = skb_queue_len_lockless(&ptp->tx_queue); in vsc85xx_dequeue_skb()
463 while (len--) { in vsc85xx_dequeue_skb()
464 skb = skb_dequeue(&ptp->tx_queue); in vsc85xx_dequeue_skb()
489 skb_queue_tail(&ptp->tx_queue, skb); in vsc85xx_dequeue_skb()
501 reg = vsc85xx_ts_read_csr(ptp->phydev, PROCESSOR, in vsc85xx_get_tx_ts()
508 struct vsc8531_private *vsc8531 = phydev->priv; in vsc85xx_ptp_cmp_init()
509 bool base = phydev->mdio.addr == vsc8531->ts_base_addr; in vsc85xx_ptp_cmp_init()
542 struct vsc8531_private *vsc8531 = phydev->priv; in vsc85xx_eth_cmp1_init()
543 bool base = phydev->mdio.addr == vsc8531->ts_base_addr; in vsc85xx_eth_cmp1_init()
574 struct vsc8531_private *vsc8531 = phydev->priv; in vsc85xx_ip_cmp1_init()
575 bool base = phydev->mdio.addr == vsc8531->ts_base_addr; in vsc85xx_ip_cmp1_init()
614 struct phy_device *phydev = ptp->phydev; in vsc85xx_adjfine()
615 struct vsc8531_private *priv = phydev->priv; in vsc85xx_adjfine()
629 mutex_lock(&priv->phc_lock); in vsc85xx_adjfine()
640 mutex_unlock(&priv->phc_lock); in vsc85xx_adjfine()
648 struct phy_device *phydev = ptp->phydev; in __vsc85xx_gettime()
649 struct vsc8531_private *priv = phydev->priv; in __vsc85xx_gettime()
662 mutex_lock(&shared->gpio_lock); in __vsc85xx_gettime()
663 gpiod_set_value(priv->load_save, 1); in __vsc85xx_gettime()
668 ts->tv_sec = ((time64_t)val) << 32; in __vsc85xx_gettime()
672 ts->tv_sec += val; in __vsc85xx_gettime()
674 ts->tv_nsec = vsc85xx_ts_read_csr(phydev, PROCESSOR, in __vsc85xx_gettime()
677 gpiod_set_value(priv->load_save, 0); in __vsc85xx_gettime()
678 mutex_unlock(&shared->gpio_lock); in __vsc85xx_gettime()
686 struct phy_device *phydev = ptp->phydev; in vsc85xx_gettime()
687 struct vsc8531_private *priv = phydev->priv; in vsc85xx_gettime()
689 mutex_lock(&priv->phc_lock); in vsc85xx_gettime()
691 mutex_unlock(&priv->phc_lock); in vsc85xx_gettime()
700 struct phy_device *phydev = ptp->phydev; in __vsc85xx_settime()
701 struct vsc8531_private *priv = phydev->priv; in __vsc85xx_settime()
708 PTP_LTC_LOAD_SEC_MSB(ts->tv_sec)); in __vsc85xx_settime()
710 PTP_LTC_LOAD_SEC_LSB(ts->tv_sec)); in __vsc85xx_settime()
712 PTP_LTC_LOAD_NS(ts->tv_nsec)); in __vsc85xx_settime()
721 mutex_lock(&shared->gpio_lock); in __vsc85xx_settime()
722 gpiod_set_value(priv->load_save, 1); in __vsc85xx_settime()
727 gpiod_set_value(priv->load_save, 0); in __vsc85xx_settime()
728 mutex_unlock(&shared->gpio_lock); in __vsc85xx_settime()
737 struct phy_device *phydev = ptp->phydev; in vsc85xx_settime()
738 struct vsc8531_private *priv = phydev->priv; in vsc85xx_settime()
740 mutex_lock(&priv->phc_lock); in vsc85xx_settime()
742 mutex_unlock(&priv->phc_lock); in vsc85xx_settime()
750 struct phy_device *phydev = ptp->phydev; in vsc85xx_adjtime()
751 struct vsc8531_private *priv = phydev->priv; in vsc85xx_adjtime()
759 mutex_lock(&priv->phc_lock); in vsc85xx_adjtime()
766 mutex_unlock(&priv->phc_lock); in vsc85xx_adjtime()
771 mutex_lock(&priv->phc_lock); in vsc85xx_adjtime()
778 mutex_unlock(&priv->phc_lock); in vsc85xx_adjtime()
815 /* Check non-zero reserved field */ in vsc85xx_ts_ptp_action_flow()
837 /* no rewrite */ in vsc85xx_ts_ptp_action_flow()
865 /* no need to know Sync t when sending in one_step */ in vsc85xx_ptp_conf()
887 struct vsc8531_private *vsc8531 = phydev->priv; in vsc85xx_eth1_conf()
890 if (vsc8531->ptp->rx_filter == HWTSTAMP_FILTER_PTP_V2_L2_EVENT) { in vsc85xx_eth1_conf()
968 struct vsc8531_private *vsc8531 = phydev->priv; in vsc85xx_ts_engine_init()
969 bool ptp_l4, base = phydev->mdio.addr == vsc8531->ts_base_addr; in vsc85xx_ts_engine_init()
973 ptp_l4 = vsc8531->ptp->rx_filter == HWTSTAMP_FILTER_PTP_V2_L4_EVENT; in vsc85xx_ts_engine_init()
983 if (vsc8531->ptp->rx_filter == HWTSTAMP_FILTER_PTP_V2_L2_EVENT) { in vsc85xx_ts_engine_init()
1003 vsc8531->ptp->rx_filter != HWTSTAMP_FILTER_NONE); in vsc85xx_ts_engine_init()
1005 ptp_l4 && vsc8531->ptp->rx_filter != HWTSTAMP_FILTER_NONE); in vsc85xx_ts_engine_init()
1007 vsc8531->ptp->rx_filter != HWTSTAMP_FILTER_NONE); in vsc85xx_ts_engine_init()
1010 vsc8531->ptp->tx_type != HWTSTAMP_TX_OFF); in vsc85xx_ts_engine_init()
1012 ptp_l4 && vsc8531->ptp->tx_type != HWTSTAMP_TX_OFF); in vsc85xx_ts_engine_init()
1014 vsc8531->ptp->tx_type != HWTSTAMP_TX_OFF); in vsc85xx_ts_engine_init()
1017 if (vsc8531->ptp->tx_type != HWTSTAMP_TX_OFF) in vsc85xx_ts_engine_init()
1021 if (vsc8531->ptp->rx_filter != HWTSTAMP_FILTER_NONE) in vsc85xx_ts_engine_init()
1032 struct vsc8531_private *priv = phydev->priv; in vsc85xx_link_change_notify()
1034 mutex_lock(&priv->ts_lock); in vsc85xx_link_change_notify()
1036 mutex_unlock(&priv->ts_lock); in vsc85xx_link_change_notify()
1060 struct phy_device *phydev = vsc8531->ptp->phydev; in vsc85xx_hwtstamp()
1064 switch (cfg->tx_type) { in vsc85xx_hwtstamp()
1071 skb_queue_purge(&vsc8531->ptp->tx_queue); in vsc85xx_hwtstamp()
1074 return -ERANGE; in vsc85xx_hwtstamp()
1077 vsc8531->ptp->tx_type = cfg->tx_type; in vsc85xx_hwtstamp()
1079 switch (cfg->rx_filter) { in vsc85xx_hwtstamp()
1083 /* ETH->IP->UDP->PTP */ in vsc85xx_hwtstamp()
1086 /* ETH->PTP */ in vsc85xx_hwtstamp()
1089 return -ERANGE; in vsc85xx_hwtstamp()
1092 vsc8531->ptp->rx_filter = cfg->rx_filter; in vsc85xx_hwtstamp()
1094 mutex_lock(&vsc8531->ts_lock); in vsc85xx_hwtstamp()
1108 /* Bypass egress or ingress blocks if timestamping isn't used */ in vsc85xx_hwtstamp()
1111 if (vsc8531->ptp->tx_type == HWTSTAMP_TX_OFF) in vsc85xx_hwtstamp()
1113 if (vsc8531->ptp->rx_filter == HWTSTAMP_FILTER_NONE) in vsc85xx_hwtstamp()
1122 /* Re-enable predictors now */ in vsc85xx_hwtstamp()
1134 vsc8531->ptp->configured = 1; in vsc85xx_hwtstamp()
1135 mutex_unlock(&vsc8531->ts_lock); in vsc85xx_hwtstamp()
1146 info->phc_index = ptp_clock_index(vsc8531->ptp->ptp_clock); in vsc85xx_ts_info()
1147 info->so_timestamping = in vsc85xx_ts_info()
1151 info->tx_types = in vsc85xx_ts_info()
1155 info->rx_filters = in vsc85xx_ts_info()
1169 if (!vsc8531->ptp->configured) in vsc85xx_txtstamp()
1172 if (vsc8531->ptp->tx_type == HWTSTAMP_TX_OFF) in vsc85xx_txtstamp()
1175 if (vsc8531->ptp->tx_type == HWTSTAMP_TX_ONESTEP_SYNC) in vsc85xx_txtstamp()
1179 skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; in vsc85xx_txtstamp()
1181 skb_queue_tail(&vsc8531->ptp->tx_queue, skb); in vsc85xx_txtstamp()
1196 if (!vsc8531->ptp->configured) in vsc85xx_rxtstamp()
1199 if (vsc8531->ptp->rx_filter == HWTSTAMP_FILTER_NONE || in vsc85xx_rxtstamp()
1203 ptphdr = get_ptp_header_rx(skb, vsc8531->ptp->rx_filter); in vsc85xx_rxtstamp()
1207 ns = ntohl(ptphdr->rsrvd2); in vsc85xx_rxtstamp()
1209 VSC8531_SKB_CB(skb)->ns = ns; in vsc85xx_rxtstamp()
1210 skb_queue_tail(&vsc8531->rx_skbs_list, skb); in vsc85xx_rxtstamp()
1212 ptp_schedule_worker(vsc8531->ptp->ptp_clock, 0); in vsc85xx_rxtstamp()
1221 struct phy_device *phydev = ptp->phydev; in vsc85xx_do_aux_work()
1222 struct vsc8531_private *priv = phydev->priv; in vsc85xx_do_aux_work()
1229 spin_lock_irqsave(&priv->rx_skbs_list.lock, flags); in vsc85xx_do_aux_work()
1230 skb_queue_splice_tail_init(&priv->rx_skbs_list, &received); in vsc85xx_do_aux_work()
1231 spin_unlock_irqrestore(&priv->rx_skbs_list.lock, flags); in vsc85xx_do_aux_work()
1238 if (ts.tv_nsec < VSC8531_SKB_CB(rx_skb)->ns) in vsc85xx_do_aux_work()
1239 ts.tv_sec--; in vsc85xx_do_aux_work()
1241 shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, in vsc85xx_do_aux_work()
1242 VSC8531_SKB_CB(rx_skb)->ns); in vsc85xx_do_aux_work()
1246 return -1; in vsc85xx_do_aux_work()
1267 struct vsc8531_private *vsc8531 = phydev->priv; in vsc8584_base_priv()
1269 if (vsc8531->ts_base_addr != phydev->mdio.addr) { in vsc8584_base_priv()
1272 dev = phydev->mdio.bus->mdio_map[vsc8531->ts_base_addr]; in vsc8584_base_priv()
1275 return phydev->priv; in vsc8584_base_priv()
1285 return vsc8531->input_clk_init; in vsc8584_is_1588_input_clk_configured()
1292 vsc8531->input_clk_init = true; in vsc8584_set_input_clk_configured()
1362 /* Enable n-phase sampler for Viper Rev-B */ in __vsc8584_init_ptp()
1500 * - The Ethernet comparator. in __vsc8584_init_ptp()
1501 * - The IP comparator. in __vsc8584_init_ptp()
1502 * - The PTP comparator. in __vsc8584_init_ptp()
1518 struct vsc8531_private *priv = phydev->priv; in vsc8584_config_ts_intr()
1520 mutex_lock(&priv->ts_lock); in vsc8584_config_ts_intr()
1523 mutex_unlock(&priv->ts_lock); in vsc8584_config_ts_intr()
1528 switch (phydev->phy_id & phydev->drv->phy_id_mask) { in vsc8584_ptp_init()
1542 struct vsc8531_private *vsc8531 = phydev->priv; in vsc8584_ptp_deinit()
1544 if (vsc8531->ptp->ptp_clock) { in vsc8584_ptp_deinit()
1545 ptp_clock_unregister(vsc8531->ptp->ptp_clock); in vsc8584_ptp_deinit()
1546 skb_queue_purge(&vsc8531->rx_skbs_list); in vsc8584_ptp_deinit()
1547 skb_queue_purge(&vsc8531->ptp->tx_queue); in vsc8584_ptp_deinit()
1553 struct vsc8531_private *priv = phydev->priv; in vsc8584_handle_ts_interrupt()
1556 mutex_lock(&priv->ts_lock); in vsc8584_handle_ts_interrupt()
1564 mutex_unlock(&priv->ts_lock); in vsc8584_handle_ts_interrupt()
1569 vsc85xx_get_tx_ts(priv->ptp); in vsc8584_handle_ts_interrupt()
1571 skb_queue_purge(&priv->ptp->tx_queue); in vsc8584_handle_ts_interrupt()
1575 mutex_unlock(&priv->ts_lock); in vsc8584_handle_ts_interrupt()
1581 struct vsc8531_private *vsc8531 = phydev->priv; in vsc8584_ptp_probe()
1583 vsc8531->ptp = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531->ptp), in vsc8584_ptp_probe()
1585 if (!vsc8531->ptp) in vsc8584_ptp_probe()
1586 return -ENOMEM; in vsc8584_ptp_probe()
1588 mutex_init(&vsc8531->phc_lock); in vsc8584_ptp_probe()
1589 mutex_init(&vsc8531->ts_lock); in vsc8584_ptp_probe()
1590 skb_queue_head_init(&vsc8531->rx_skbs_list); in vsc8584_ptp_probe()
1591 skb_queue_head_init(&vsc8531->ptp->tx_queue); in vsc8584_ptp_probe()
1598 vsc8531->load_save = devm_gpiod_get_optional(&phydev->mdio.dev, "load-save", in vsc8584_ptp_probe()
1601 if (IS_ERR(vsc8531->load_save)) { in vsc8584_ptp_probe()
1602 phydev_err(phydev, "Can't get load-save GPIO (%ld)\n", in vsc8584_ptp_probe()
1603 PTR_ERR(vsc8531->load_save)); in vsc8584_ptp_probe()
1604 return PTR_ERR(vsc8531->load_save); in vsc8584_ptp_probe()
1608 phydev->default_timestamp = true; in vsc8584_ptp_probe()
1610 vsc8531->ptp->phydev = phydev; in vsc8584_ptp_probe()
1612 vsc8531->mii_ts.rxtstamp = vsc85xx_rxtstamp; in vsc8584_ptp_probe()
1613 vsc8531->mii_ts.txtstamp = vsc85xx_txtstamp; in vsc8584_ptp_probe()
1614 vsc8531->mii_ts.hwtstamp = vsc85xx_hwtstamp; in vsc8584_ptp_probe()
1615 vsc8531->mii_ts.ts_info = vsc85xx_ts_info; in vsc8584_ptp_probe()
1616 phydev->mii_ts = &vsc8531->mii_ts; in vsc8584_ptp_probe()
1618 memcpy(&vsc8531->ptp->caps, &vsc85xx_clk_caps, sizeof(vsc85xx_clk_caps)); in vsc8584_ptp_probe()
1619 vsc8531->ptp->ptp_clock = ptp_clock_register(&vsc8531->ptp->caps, in vsc8584_ptp_probe()
1620 &phydev->mdio.dev); in vsc8584_ptp_probe()
1621 return PTR_ERR_OR_ZERO(vsc8531->ptp->ptp_clock); in vsc8584_ptp_probe()
1629 mutex_init(&shared->gpio_lock); in vsc8584_ptp_probe_once()