+
+int
+otx2_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
+ struct timespec *timestamp,
+ uint32_t __rte_unused flags)
+{
+ struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+ struct otx2_timesync_info *tstamp = &dev->tstamp;
+ uint64_t ns;
+
+ if (!tstamp->rx_ready)
+ return -EINVAL;
+
+ ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
+ *timestamp = rte_ns_to_timespec(ns);
+ tstamp->rx_ready = 0;
+
+ otx2_nix_dbg("rx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
+ (uint64_t)tstamp->rx_tstamp, (uint64_t)timestamp->tv_sec,
+ (uint64_t)timestamp->tv_nsec);
+
+ return 0;
+}
+
+int
+otx2_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
+ struct timespec *timestamp)
+{
+ struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+ struct otx2_timesync_info *tstamp = &dev->tstamp;
+ uint64_t ns;
+
+ if (*tstamp->tx_tstamp == 0)
+ return -EINVAL;
+
+ ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
+ *timestamp = rte_ns_to_timespec(ns);
+
+ otx2_nix_dbg("tx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
+ *tstamp->tx_tstamp, (uint64_t)timestamp->tv_sec,
+ (uint64_t)timestamp->tv_nsec);
+
+ *tstamp->tx_tstamp = 0;
+ rte_wmb();
+
+ return 0;
+}
+
+int
+otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
+{
+ struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+ struct otx2_mbox *mbox = dev->mbox;
+ struct ptp_req *req;
+ struct ptp_rsp *rsp;
+ int rc;
+
+ /* Adjust the frequent to make tics increments in 10^9 tics per sec */
+ if (delta < PTP_FREQ_ADJUST && delta > -PTP_FREQ_ADJUST) {
+ req = otx2_mbox_alloc_msg_ptp_op(mbox);
+ req->op = PTP_OP_ADJFINE;
+ req->scaled_ppm = delta;
+
+ rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ return rc;
+ /* Since the frequency of PTP comp register is tuned, delta and
+ * freq mult calculation for deriving PTP_HI from timestamp
+ * counter should be done again.
+ */
+ rc = otx2_nix_raw_clock_tsc_conv(dev);
+ if (rc)
+ otx2_err("Failed to calculate delta and freq mult");
+ }
+ dev->systime_tc.nsec += delta;
+ dev->rx_tstamp_tc.nsec += delta;
+ dev->tx_tstamp_tc.nsec += delta;
+
+ return 0;
+}
+
+int
+otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
+ const struct timespec *ts)
+{
+ struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+ uint64_t ns;
+
+ ns = rte_timespec_to_ns(ts);
+ /* Set the time counters to a new value. */
+ dev->systime_tc.nsec = ns;
+ dev->rx_tstamp_tc.nsec = ns;
+ dev->tx_tstamp_tc.nsec = ns;
+
+ return 0;
+}
+
+int
+otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
+{
+ struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+ struct otx2_mbox *mbox = dev->mbox;
+ struct ptp_req *req;
+ struct ptp_rsp *rsp;
+ uint64_t ns;
+ int rc;
+
+ req = otx2_mbox_alloc_msg_ptp_op(mbox);
+ req->op = PTP_OP_GET_CLOCK;
+ rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
+ if (rc)
+ return rc;
+
+ ns = rte_timecounter_update(&dev->systime_tc, rsp->clk);
+ *ts = rte_ns_to_timespec(ns);
+
+ otx2_nix_dbg("PTP time read: %"PRIu64" .%09"PRIu64"",
+ (uint64_t)ts->tv_sec, (uint64_t)ts->tv_nsec);
+
+ return 0;
+}
+
+
+int
+otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
+{
+ struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
+
+ /* This API returns the raw PTP HI clock value. Since LFs doesn't
+ * have direct access to PTP registers and it requires mbox msg
+ * to AF for this value. In fastpath reading this value for every
+ * packet (which involes mbox call) becomes very expensive, hence
+ * we should be able to derive PTP HI clock value from tsc by
+ * using freq_mult and clk_delta calculated during configure stage.
+ */
+ *clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;
+
+ return 0;
+}