1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2021 Marvell.
5 #include "cnxk_ethdev.h"
8 cnxk_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
10 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
12 /* This API returns the raw PTP HI clock value. Since LFs do not
13 * have direct access to PTP registers and it requires mbox msg
14 * to AF for this value. In fastpath reading this value for every
15 * packet (which involes mbox call) becomes very expensive, hence
16 * we should be able to derive PTP HI clock value from tsc by
17 * using freq_mult and clk_delta calculated during configure stage.
19 *clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;
24 /* This function calculates two parameters "clk_freq_mult" and
25 * "clk_delta" which is useful in deriving PTP HI clock from
26 * timestamp counter (tsc) value.
29 cnxk_nix_tsc_convert(struct cnxk_eth_dev *dev)
31 uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
32 struct roc_nix *nix = &dev->nix;
35 /* Calculating the frequency at which PTP HI clock is running */
36 rc = roc_nix_ptp_clock_read(nix, &ticks_base, &tsc, false);
38 plt_err("Failed to read the raw clock value: %d", rc);
44 rc = roc_nix_ptp_clock_read(nix, &ticks, &tsc, false);
46 plt_err("Failed to read the raw clock value: %d", rc);
50 t_freq = (ticks - ticks_base) * 10;
52 /* Calculating the freq multiplier viz the ratio between the
53 * frequency at which PTP HI clock works and tsc clock runs
56 (double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
59 #ifdef RTE_ARM_EAL_RDTSC_USE_PMU
62 rc = roc_nix_ptp_clock_read(nix, &ticks, &tsc, val);
64 plt_err("Failed to read the raw clock value: %d", rc);
68 /* Calculating delta between PTP HI clock and tsc */
69 dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
76 cnxk_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
78 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
79 struct roc_nix *nix = &dev->nix;
83 rc = roc_nix_ptp_clock_read(nix, &clock, NULL, false);
87 ns = rte_timecounter_update(&dev->systime_tc, clock);
88 *ts = rte_ns_to_timespec(ns);
93 cnxk_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
94 const struct timespec *ts)
96 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
99 ns = rte_timespec_to_ns(ts);
100 /* Set the time counters to a new value. */
101 dev->systime_tc.nsec = ns;
102 dev->rx_tstamp_tc.nsec = ns;
103 dev->tx_tstamp_tc.nsec = ns;
109 cnxk_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
111 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
112 struct roc_nix *nix = &dev->nix;
115 /* Adjust the frequent to make tics increments in 10^9 tics per sec */
116 if (delta < ROC_NIX_PTP_FREQ_ADJUST &&
117 delta > -ROC_NIX_PTP_FREQ_ADJUST) {
118 rc = roc_nix_ptp_sync_time_adjust(nix, delta);
122 /* Since the frequency of PTP comp register is tuned, delta and
123 * freq mult calculation for deriving PTP_HI from timestamp
124 * counter should be done again.
126 rc = cnxk_nix_tsc_convert(dev);
128 plt_err("Failed to calculate delta and freq mult");
131 dev->systime_tc.nsec += delta;
132 dev->rx_tstamp_tc.nsec += delta;
133 dev->tx_tstamp_tc.nsec += delta;
139 cnxk_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
140 struct timespec *timestamp, uint32_t flags)
142 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
143 struct cnxk_timesync_info *tstamp = &dev->tstamp;
148 if (!tstamp->rx_ready)
151 ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
152 *timestamp = rte_ns_to_timespec(ns);
153 tstamp->rx_ready = 0;
158 cnxk_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
159 struct timespec *timestamp)
161 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
162 struct cnxk_timesync_info *tstamp = &dev->tstamp;
165 if (*tstamp->tx_tstamp == 0)
168 ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
169 *timestamp = rte_ns_to_timespec(ns);
170 *tstamp->tx_tstamp = 0;
177 cnxk_nix_timesync_enable(struct rte_eth_dev *eth_dev)
179 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
180 struct cnxk_timesync_info *tstamp = &dev->tstamp;
181 struct roc_nix *nix = &dev->nix;
182 const struct rte_memzone *ts;
185 /* If we are VF/SDP/LBK, ptp cannot not be enabled */
186 if (roc_nix_is_vf_or_sdp(nix) || roc_nix_is_lbk(nix)) {
187 plt_err("PTP cannot be enabled for VF/SDP/LBK");
194 if (dev->ptype_disable) {
195 plt_err("Ptype offload is disabled, it should be enabled");
199 if (dev->npc.switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
200 plt_err("Both PTP and switch header cannot be enabled");
204 /* Allocating a iova address for tx tstamp */
205 ts = rte_eth_dma_zone_reserve(eth_dev, "cnxk_ts", 0, 128, 128, 0);
207 plt_err("Failed to allocate mem for tx tstamp addr");
211 tstamp->tx_tstamp_iova = ts->iova;
212 tstamp->tx_tstamp = ts->addr;
214 rc = rte_mbuf_dyn_rx_timestamp_register(&tstamp->tstamp_dynfield_offset,
215 &tstamp->rx_tstamp_dynflag);
217 plt_err("Failed to register Rx timestamp field/flag");
221 /* System time should be already on by default */
222 memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
223 memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
224 memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
226 dev->systime_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
227 dev->rx_tstamp_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
228 dev->tx_tstamp_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
230 dev->rx_offloads |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
232 rc = roc_nix_ptp_rx_ena_dis(nix, true);
234 rc = roc_nix_ptp_tx_ena_dis(nix, true);
236 roc_nix_ptp_rx_ena_dis(nix, false);
241 rc = nix_recalc_mtu(eth_dev);
243 plt_err("Failed to set MTU size for ptp");
250 rte_eth_dma_zone_free(eth_dev, "cnxk_ts", 0);
251 dev->tstamp.tx_tstamp_iova = 0;
252 dev->tstamp.tx_tstamp = NULL;
257 cnxk_nix_timesync_disable(struct rte_eth_dev *eth_dev)
259 struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
260 uint64_t rx_offloads = RTE_ETH_RX_OFFLOAD_TIMESTAMP;
261 struct roc_nix *nix = &dev->nix;
264 /* If we are VF/SDP/LBK, ptp cannot not be disabled */
265 if (roc_nix_is_vf_or_sdp(nix) || roc_nix_is_lbk(nix))
271 dev->rx_offloads &= ~rx_offloads;
273 rc = roc_nix_ptp_rx_ena_dis(nix, false);
275 rc = roc_nix_ptp_tx_ena_dis(nix, false);
277 roc_nix_ptp_rx_ena_dis(nix, true);
282 rc = nix_recalc_mtu(eth_dev);
284 plt_err("Failed to set MTU size for ptp");