1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2019 Marvell International Ltd.
5 #include <ethdev_driver.h>
7 #include "otx2_ethdev.h"
9 #define PTP_FREQ_ADJUST (1 << 9)
11 /* Function to enable ptp config for VFs */
13 otx2_nix_ptp_enable_vf(struct rte_eth_dev *eth_dev)
15 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
17 if (otx2_nix_recalc_mtu(eth_dev))
18 otx2_err("Failed to set MTU size for ptp");
20 dev->scalar_ena = true;
21 dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
23 /* Setting up the function pointers as per new offload flags */
24 otx2_eth_set_rx_function(eth_dev);
25 otx2_eth_set_tx_function(eth_dev);
29 nix_eth_ptp_vf_burst(void *queue, struct rte_mbuf **mbufs, uint16_t pkts)
31 struct otx2_eth_rxq *rxq = queue;
32 struct rte_eth_dev *eth_dev;
37 eth_dev = rxq->eth_dev;
38 otx2_nix_ptp_enable_vf(eth_dev);
44 nix_read_raw_clock(struct otx2_eth_dev *dev, uint64_t *clock, uint64_t *tsc,
47 struct otx2_mbox *mbox = dev->mbox;
52 req = otx2_mbox_alloc_msg_ptp_op(mbox);
53 req->op = PTP_OP_GET_CLOCK;
55 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
68 /* This function calculates two parameters "clk_freq_mult" and
69 * "clk_delta" which is useful in deriving PTP HI clock from
70 * timestamp counter (tsc) value.
73 otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev *dev)
75 uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
78 /* Calculating the frequency at which PTP HI clock is running */
79 rc = nix_read_raw_clock(dev, &ticks_base, &tsc, false);
81 otx2_err("Failed to read the raw clock value: %d", rc);
87 rc = nix_read_raw_clock(dev, &ticks, &tsc, false);
89 otx2_err("Failed to read the raw clock value: %d", rc);
93 t_freq = (ticks - ticks_base) * 10;
95 /* Calculating the freq multiplier viz the ratio between the
96 * frequency at which PTP HI clock works and tsc clock runs
99 (double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
102 #ifdef RTE_ARM_EAL_RDTSC_USE_PMU
105 rc = nix_read_raw_clock(dev, &ticks, &tsc, val);
107 otx2_err("Failed to read the raw clock value: %d", rc);
111 /* Calculating delta between PTP HI clock and tsc */
112 dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
119 nix_start_timecounters(struct rte_eth_dev *eth_dev)
121 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
123 memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
124 memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
125 memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
127 dev->systime_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
128 dev->rx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
129 dev->tx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
133 nix_ptp_config(struct rte_eth_dev *eth_dev, int en)
135 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
136 struct otx2_mbox *mbox = dev->mbox;
137 uint8_t rc = -EINVAL;
139 if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev))
143 /* Enable time stamping of sent PTP packets. */
144 otx2_mbox_alloc_msg_nix_lf_ptp_tx_enable(mbox);
145 rc = otx2_mbox_process(mbox);
147 otx2_err("MBOX ptp tx conf enable failed: err %d", rc);
150 /* Enable time stamping of received PTP packets. */
151 otx2_mbox_alloc_msg_cgx_ptp_rx_enable(mbox);
153 /* Disable time stamping of sent PTP packets. */
154 otx2_mbox_alloc_msg_nix_lf_ptp_tx_disable(mbox);
155 rc = otx2_mbox_process(mbox);
157 otx2_err("MBOX ptp tx conf disable failed: err %d", rc);
160 /* Disable time stamping of received PTP packets. */
161 otx2_mbox_alloc_msg_cgx_ptp_rx_disable(mbox);
164 return otx2_mbox_process(mbox);
168 otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en)
170 struct otx2_eth_dev *otx2_dev = (struct otx2_eth_dev *)dev;
171 struct rte_eth_dev *eth_dev;
177 eth_dev = otx2_dev->eth_dev;
181 otx2_dev->ptp_en = ptp_en;
182 for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
183 struct otx2_eth_rxq *rxq = eth_dev->data->rx_queues[i];
184 rxq->mbuf_initializer =
185 otx2_nix_rxq_mbuf_setup(otx2_dev,
186 eth_dev->data->port_id);
188 if (otx2_dev_is_vf(otx2_dev) && !(otx2_dev_is_sdp(otx2_dev)) &&
189 !(otx2_dev_is_lbk(otx2_dev))) {
190 /* In case of VF, setting of MTU cant be done directly in this
191 * function as this is running as part of MBOX request(PF->VF)
192 * and MTU setting also requires MBOX message to be
195 eth_dev->rx_pkt_burst = nix_eth_ptp_vf_burst;
203 otx2_nix_timesync_enable(struct rte_eth_dev *eth_dev)
205 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
208 /* If we are VF/SDP/LBK, ptp cannot not be enabled */
209 if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev)) {
210 otx2_info("PTP cannot be enabled in case of VF/SDP/LBK");
214 if (otx2_ethdev_is_ptp_en(dev)) {
215 otx2_info("PTP mode is already enabled");
219 if (!(dev->rx_offload_flags & NIX_RX_OFFLOAD_PTYPE_F)) {
220 otx2_err("Ptype offload is disabled, it should be enabled");
224 if (dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_HIGIG) {
225 otx2_err("Both PTP and switch header enabled");
229 /* Allocating a iova address for tx tstamp */
230 const struct rte_memzone *ts;
231 ts = rte_eth_dma_zone_reserve(eth_dev, "otx2_ts",
232 0, OTX2_ALIGN, OTX2_ALIGN,
235 otx2_err("Failed to allocate mem for tx tstamp addr");
239 dev->tstamp.tx_tstamp_iova = ts->iova;
240 dev->tstamp.tx_tstamp = ts->addr;
242 rc = rte_mbuf_dyn_rx_timestamp_register(
243 &dev->tstamp.tstamp_dynfield_offset,
244 &dev->tstamp.rx_tstamp_dynflag);
246 otx2_err("Failed to register Rx timestamp field/flag");
250 /* System time should be already on by default */
251 nix_start_timecounters(eth_dev);
253 dev->rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
254 dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
255 dev->tx_offload_flags |= NIX_TX_OFFLOAD_TSTAMP_F;
257 rc = nix_ptp_config(eth_dev, 1);
259 for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
260 struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
261 otx2_nix_form_default_desc(txq);
264 /* Setting up the function pointers as per new offload flags */
265 otx2_eth_set_rx_function(eth_dev);
266 otx2_eth_set_tx_function(eth_dev);
269 rc = otx2_nix_recalc_mtu(eth_dev);
271 otx2_err("Failed to set MTU size for ptp");
277 otx2_nix_timesync_disable(struct rte_eth_dev *eth_dev)
279 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
282 if (!otx2_ethdev_is_ptp_en(dev)) {
283 otx2_nix_dbg("PTP mode is disabled");
287 if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev))
290 dev->rx_offloads &= ~DEV_RX_OFFLOAD_TIMESTAMP;
291 dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_TSTAMP_F;
292 dev->tx_offload_flags &= ~NIX_TX_OFFLOAD_TSTAMP_F;
294 rc = nix_ptp_config(eth_dev, 0);
296 for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
297 struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
298 otx2_nix_form_default_desc(txq);
301 /* Setting up the function pointers as per new offload flags */
302 otx2_eth_set_rx_function(eth_dev);
303 otx2_eth_set_tx_function(eth_dev);
306 rc = otx2_nix_recalc_mtu(eth_dev);
308 otx2_err("Failed to set MTU size for ptp");
314 otx2_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
315 struct timespec *timestamp,
316 uint32_t __rte_unused flags)
318 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
319 struct otx2_timesync_info *tstamp = &dev->tstamp;
322 if (!tstamp->rx_ready)
325 ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
326 *timestamp = rte_ns_to_timespec(ns);
327 tstamp->rx_ready = 0;
329 otx2_nix_dbg("rx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
330 (uint64_t)tstamp->rx_tstamp, (uint64_t)timestamp->tv_sec,
331 (uint64_t)timestamp->tv_nsec);
337 otx2_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
338 struct timespec *timestamp)
340 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
341 struct otx2_timesync_info *tstamp = &dev->tstamp;
344 if (*tstamp->tx_tstamp == 0)
347 ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
348 *timestamp = rte_ns_to_timespec(ns);
350 otx2_nix_dbg("tx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
351 *tstamp->tx_tstamp, (uint64_t)timestamp->tv_sec,
352 (uint64_t)timestamp->tv_nsec);
354 *tstamp->tx_tstamp = 0;
361 otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
363 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
364 struct otx2_mbox *mbox = dev->mbox;
369 /* Adjust the frequent to make tics increments in 10^9 tics per sec */
370 if (delta < PTP_FREQ_ADJUST && delta > -PTP_FREQ_ADJUST) {
371 req = otx2_mbox_alloc_msg_ptp_op(mbox);
372 req->op = PTP_OP_ADJFINE;
373 req->scaled_ppm = delta;
375 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
378 /* Since the frequency of PTP comp register is tuned, delta and
379 * freq mult calculation for deriving PTP_HI from timestamp
380 * counter should be done again.
382 rc = otx2_nix_raw_clock_tsc_conv(dev);
384 otx2_err("Failed to calculate delta and freq mult");
386 dev->systime_tc.nsec += delta;
387 dev->rx_tstamp_tc.nsec += delta;
388 dev->tx_tstamp_tc.nsec += delta;
394 otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
395 const struct timespec *ts)
397 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
400 ns = rte_timespec_to_ns(ts);
401 /* Set the time counters to a new value. */
402 dev->systime_tc.nsec = ns;
403 dev->rx_tstamp_tc.nsec = ns;
404 dev->tx_tstamp_tc.nsec = ns;
410 otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
412 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
413 struct otx2_mbox *mbox = dev->mbox;
419 req = otx2_mbox_alloc_msg_ptp_op(mbox);
420 req->op = PTP_OP_GET_CLOCK;
421 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
425 ns = rte_timecounter_update(&dev->systime_tc, rsp->clk);
426 *ts = rte_ns_to_timespec(ns);
428 otx2_nix_dbg("PTP time read: %"PRIu64" .%09"PRIu64"",
429 (uint64_t)ts->tv_sec, (uint64_t)ts->tv_nsec);
436 otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
438 struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
440 /* This API returns the raw PTP HI clock value. Since LFs doesn't
441 * have direct access to PTP registers and it requires mbox msg
442 * to AF for this value. In fastpath reading this value for every
443 * packet (which involes mbox call) becomes very expensive, hence
444 * we should be able to derive PTP HI clock value from tsc by
445 * using freq_mult and clk_delta calculated during configure stage.
447 *clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;