<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);" class="elementToProof">
<span style="font-family: Calibri, sans-serif; font-size: 11pt; color: rgb(0, 0, 0);">----Original Message-----</span><span style="font-size: 11pt;"><br>
From: Hore, Soumyadeep <soumyadeep.hore@intel.com><br>
Sent: 15 February 2026 01:19 AM<br>
To: dev@dpdk.org; Richardson, Bruce <bruce.richardson@intel.com><br>
Cc: Kumar, Rajesh3 <rajesh3.kumar@intel.com>; Singh, Aman Deep <aman.deep.singh@intel.com>; Subbarao, Manoj Kumar <manoj.kumar.subbarao@intel.com><br>
Subject: [PATCH v6 2/4] net/idpf: add PTP virtchnl2 support<br>
<br>
Add a new file - idpf_ptp - to handle PTP virtchnl messages.<br>
Keep the registers addresses in the PTP struct.<br>
<br>
Signed-off-by: Soumyadeep Hore <soumyadeep.hore@intel.com><br>
---<br>
 drivers/net/intel/idpf/idpf_common_device.h   |   4 +<br>
 drivers/net/intel/idpf/idpf_common_virtchnl.c |  31 +-<br>
 drivers/net/intel/idpf/idpf_ptp.c             | 504 ++++++++++++++++++<br>
 drivers/net/intel/idpf/idpf_ptp.h             | 130 +++++<br>
 drivers/net/intel/idpf/meson.build            |   1 +<br>
 5 files changed, 668 insertions(+), 2 deletions(-)  create mode 100644 drivers/net/intel/idpf/idpf_ptp.c  create mode 100644 drivers/net/intel/idpf/idpf_ptp.h<br>
<br>
diff --git a/drivers/net/intel/idpf/idpf_common_device.h b/drivers/net/intel/idpf/idpf_common_device.h<br>
index 31915a03d4..e45795c18b 100644<br>
--- a/drivers/net/intel/idpf/idpf_common_device.h<br>
+++ b/drivers/net/intel/idpf/idpf_common_device.h<br>
@@ -103,6 +103,7 @@ struct idpf_adapter {<br>
 <br>
         /* For timestamp */<br>
         uint64_t time_hw;<br>
+       struct idpf_ptp *ptp;<br>
 <br>
         enum idpf_rx_func_type rx_func_type;<br>
         enum idpf_tx_func_type tx_func_type;<br>
@@ -173,6 +174,9 @@ struct idpf_vport {<br>
         /* Event from ipf */<br>
         bool link_up;<br>
         uint32_t link_speed;<br>
+<br>
+       /* For PTP */<br>
+       struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;<br>
 };<br>
 <br>
 /* Message type read in virtual channel from PF */ diff --git a/drivers/net/intel/idpf/idpf_common_virtchnl.c b/drivers/net/intel/idpf/idpf_common_virtchnl.c<br>
index e927d7415a..f8c487c537 100644<br>
--- a/drivers/net/intel/idpf/idpf_common_virtchnl.c<br>
+++ b/drivers/net/intel/idpf/idpf_common_virtchnl.c<br>
@@ -4,6 +4,7 @@<br>
 <br>
 #include "idpf_common_virtchnl.h"<br>
 #include "idpf_common_logs.h"<br>
+#include "idpf_ptp.h"<br>
 <br>
 #include <eal_export.h><br>
 <br>
@@ -38,6 +39,24 @@ idpf_vc_clean(struct idpf_adapter *adapter)<br>
         return 0;<br>
 }<br>
 <br>
+       /* Helper to detect PTP-related mailbox messages */ static inline bool<br>
+idpf_mb_msg_is_ptp(uint32_t op) {<br>
+       switch (op) {<br>
+       case VIRTCHNL2_OP_PTP_GET_VPORT_TX_TSTAMP:<br>
+       case VIRTCHNL2_OP_PTP_GET_DEV_CLK_TIME:<br>
+       case VIRTCHNL2_OP_PTP_GET_CROSS_TIME:<br>
+       case VIRTCHNL2_OP_PTP_SET_DEV_CLK_TIME:<br>
+       case VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_FINE:<br>
+       case VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_TIME:<br>
+       case VIRTCHNL2_OP_PTP_GET_VPORT_TX_TSTAMP_CAPS:<br>
+               return true;<br>
+       default:<br>
+               return false;<br>
+       }<br>
+}<br>
+<br>
 static int<br>
 idpf_send_vc_msg(struct idpf_adapter *adapter, uint32_t op,<br>
                  uint16_t msg_size, uint8_t *msg)<br>
@@ -71,8 +90,16 @@ idpf_send_vc_msg(struct idpf_adapter *adapter, uint32_t op,<br>
 <br>
         memcpy(dma_mem->va, msg, msg_size);<br>
 <br>
-       ctlq_msg->opcode = idpf_mbq_opc_send_msg_to_pf;<br>
-       ctlq_msg->func_id = 0;<br>
+       if (adapter->ptp != NULL &&<br>
+           idpf_mb_msg_is_ptp(op) &&<br>
+           adapter->ptp->secondary_mbx.valid) {<br>
+               ctlq_msg->opcode = idpf_mbq_opc_send_msg_to_peer_drv;<br>
+               ctlq_msg->func_id = adapter->ptp->secondary_mbx.peer_mbx_q_id;<br>
+               ctlq_msg->host_id = adapter->ptp->secondary_mbx.peer_id;<br>
+       } else {<br>
+               ctlq_msg->opcode = idpf_mbq_opc_send_msg_to_pf;<br>
+               ctlq_msg->func_id = 0;<br>
+       }<br>
         ctlq_msg->data_len = msg_size;<br>
         ctlq_msg->cookie.mbx.chnl_opcode = op;<br>
         ctlq_msg->cookie.mbx.chnl_retval = VIRTCHNL_STATUS_SUCCESS; diff --git a/drivers/net/intel/idpf/idpf_ptp.c b/drivers/net/intel/idpf/idpf_ptp.c<br>
new file mode 100644<br>
index 0000000000..aefd1309f7<br>
--- /dev/null<br>
+++ b/drivers/net/intel/idpf/idpf_ptp.c<br>
@@ -0,0 +1,504 @@<br>
+/* SPDX-License-Identifier: BSD-3-Clause<br>
+ * Copyright(c) 2025 Intel Corporation<br>
+ */<br>
+<br>
+#include "idpf_ptp.h"<br>
+#include "idpf_common_virtchnl.h"<br>
+#include "base/virtchnl2.h"<br>
+<br>
+static enum idpf_ptp_access<br>
+idpf_ptp_get_access(const struct idpf_adapter *adapter, uint32_t direct,<br>
+                   uint32_t mailbox)<br>
+{<br>
+       if (adapter->ptp->caps & direct)<br>
+               return IDPF_PTP_DIRECT;<br>
+       else if (adapter->ptp->caps & mailbox)<br>
+               return IDPF_PTP_MAILBOX;<br>
+       else<br>
+               return IDPF_PTP_NONE;<br>
+}<br>
+<br>
+#define IDPF_PTP_ACCESS(adapter, cap) \<br>
+       ((uint8_t)idpf_ptp_get_access((adapter), (cap), (cap##_MB)))<br>
+<br>
+static void<br>
+idpf_ptp_get_features_access(const struct idpf_adapter *adapter) {<br>
+       struct idpf_ptp *ptp = adapter->ptp;<br>
+<br>
+       ptp->get_dev_clk_time_access =<br>
+               IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME);<br>
+       ptp->get_cross_tstamp_access =<br>
+               IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_GET_CROSS_TIME);<br>
+       ptp->set_dev_clk_time_access =<br>
+               IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME);<br>
+       ptp->adj_dev_clk_time_access =<br>
+               IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK);<br>
+       ptp->tx_tstamp_access =<br>
+               IDPF_PTP_ACCESS(adapter, VIRTCHNL2_CAP_PTP_TX_TSTAMPS); }<br>
+<br>
+int<br>
+idpf_ptp_get_caps(struct idpf_adapter *adapter) {<br>
+       struct virtchnl2_ptp_cross_time_reg_offsets cross_tstamp_offsets;<br>
+       struct virtchnl2_ptp_clk_adj_reg_offsets clk_adj_offsets;<br>
+       struct virtchnl2_ptp_get_caps send_ptp_caps_msg = {0};<br>
+       struct virtchnl2_ptp_clk_reg_offsets clock_offsets;<br>
+       struct virtchnl2_ptp_get_caps *recv_ptp_caps_msg;<br>
+       struct idpf_cmd_info args = {0};<br>
+       struct idpf_ptp_secondary_mbx *scnd_mbx;<br>
+       struct idpf_ptp *ptp = adapter->ptp;<br>
+       struct idpf_hw *hw = &adapter->hw;<br>
+       enum idpf_ptp_access access_type;<br>
+       int err;<br>
+       uint32_t temp_offset;<br>
+<br>
+       send_ptp_caps_msg.caps = CPU_TO_LE32(VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME |<br>
+               VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME_MB |<br>
+               VIRTCHNL2_CAP_PTP_GET_CROSS_TIME |<br>
+               VIRTCHNL2_CAP_PTP_GET_CROSS_TIME_MB |<br>
+               VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME |<br>
+               VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME_MB |<br>
+               VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK |<br>
+               VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK_MB |<br>
+               VIRTCHNL2_CAP_PTP_TX_TSTAMPS |<br>
+               VIRTCHNL2_CAP_PTP_TX_TSTAMPS_MB);<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_GET_CAPS;<br>
+       args.in_args = (uint8_t *)&send_ptp_caps_msg;<br>
+       args.in_args_size = sizeof(send_ptp_caps_msg);<br>
+       args.out_buffer = adapter->mbx_resp;<br>
+       args.out_size = sizeof(*recv_ptp_caps_msg);<br>
+<br>
+       err = idpf_vc_cmd_execute(adapter, &args);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       recv_ptp_caps_msg = (struct virtchnl2_ptp_get_caps *)args.out_buffer;<br>
+       ptp->caps = LE32_TO_CPU(recv_ptp_caps_msg->caps);<br>
+       ptp->base_incval = LE64_TO_CPU(recv_ptp_caps_msg->base_incval);<br>
+       ptp->max_adj = LE32_TO_CPU(recv_ptp_caps_msg->max_adj);<br>
+<br>
+       scnd_mbx = &ptp->secondary_mbx;<br>
+       scnd_mbx->peer_mbx_q_id = LE16_TO_CPU(recv_ptp_caps_msg->peer_mbx_q_id);<br>
+       scnd_mbx->valid = scnd_mbx->peer_mbx_q_id != 0xffff;<br>
+       if (scnd_mbx->valid)<br>
+               scnd_mbx->peer_id = recv_ptp_caps_msg->peer_id;<br>
+<br>
+       idpf_ptp_get_features_access(adapter);<br>
+<br>
+       access_type = (enum idpf_ptp_access)ptp->get_dev_clk_time_access;<br>
+       if (access_type == IDPF_PTP_DIRECT) {<br>
+               clock_offsets = recv_ptp_caps_msg->clk_offsets;<br>
+<br>
+               temp_offset = LE32_TO_CPU(clock_offsets.dev_clk_ns_l);<br>
+               ptp->dev_clk_regs.dev_clk_ns_l = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clock_offsets.dev_clk_ns_h);<br>
+               ptp->dev_clk_regs.dev_clk_ns_h = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clock_offsets.phy_clk_ns_l);<br>
+               ptp->dev_clk_regs.phy_clk_ns_l = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clock_offsets.phy_clk_ns_h);<br>
+               ptp->dev_clk_regs.phy_clk_ns_h = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clock_offsets.cmd_sync_trigger);<br>
+               ptp->dev_clk_regs.cmd_sync = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+       }<br>
+<br>
+       access_type = (enum idpf_ptp_access)ptp->get_cross_tstamp_access;<br>
+       if (access_type == IDPF_PTP_DIRECT) {<br>
+               cross_tstamp_offsets = recv_ptp_caps_msg->cross_time_offsets;<br>
+<br>
+               temp_offset = LE32_TO_CPU(cross_tstamp_offsets.sys_time_ns_l);<br>
+               ptp->dev_clk_regs.sys_time_ns_l = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(cross_tstamp_offsets.sys_time_ns_h);<br>
+               ptp->dev_clk_regs.sys_time_ns_h = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(cross_tstamp_offsets.cmd_sync_trigger);<br>
+               ptp->dev_clk_regs.cmd_sync = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+       }<br>
+<br>
+       access_type = (enum idpf_ptp_access)ptp->adj_dev_clk_time_access;<br>
+       if (access_type == IDPF_PTP_DIRECT) {<br>
+               clk_adj_offsets = recv_ptp_caps_msg->clk_adj_offsets;<br>
+<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_cmd_type);<br>
+               ptp->dev_clk_regs.cmd = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_incval_l);<br>
+               ptp->dev_clk_regs.incval_l = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_incval_h);<br>
+               ptp->dev_clk_regs.incval_h = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_shadj_l);<br>
+               ptp->dev_clk_regs.shadj_l = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.dev_clk_shadj_h);<br>
+               ptp->dev_clk_regs.shadj_h = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_cmd_type);<br>
+               ptp->dev_clk_regs.phy_cmd = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_incval_l);<br>
+               ptp->dev_clk_regs.phy_incval_l = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_incval_h);<br>
+               ptp->dev_clk_regs.phy_incval_h = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_shadj_l);<br>
+               ptp->dev_clk_regs.phy_shadj_l = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+               temp_offset = LE32_TO_CPU(clk_adj_offsets.phy_clk_shadj_h);<br>
+               ptp->dev_clk_regs.phy_shadj_h = IDPF_PCI_REG_ADDR(hw, temp_offset);<br>
+       }<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+static void<br>
+idpf_ptp_enable_shtime(struct idpf_adapter *adapter) {<br>
+       uint32_t shtime_enable, exec_cmd;<br>
+<br>
+       shtime_enable = adapter->ptp->cmd.shtime_enable_mask;<br>
+       exec_cmd = adapter->ptp->cmd.exec_cmd_mask;<br>
+<br>
+       IDPF_PCI_REG_WRITE(adapter->ptp->dev_clk_regs.cmd_sync, shtime_enable);<br>
+       IDPF_PCI_REG_WRITE(adapter->ptp->dev_clk_regs.cmd_sync,<br>
+                         exec_cmd | shtime_enable);<br>
+}<br>
+<br>
+int<br>
+idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,<br>
+                         struct idpf_ptp_dev_timers *dev_clk_time) {<br>
+       struct virtchnl2_ptp_get_dev_clk_time get_dev_clk_time_msg = {0};<br>
+       struct idpf_cmd_info args = {0};<br>
+       int err;<br>
+       uint64_t dev_time;<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_GET_DEV_CLK_TIME;<br>
+       args.in_args = (uint8_t *)&get_dev_clk_time_msg;<br>
+       args.in_args_size = sizeof(get_dev_clk_time_msg);<br>
+       args.out_buffer = adapter->mbx_resp;<br>
+       args.out_size = sizeof(get_dev_clk_time_msg);<br>
+<br>
+       err = idpf_vc_cmd_execute(adapter, &args);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       get_dev_clk_time_msg =<br>
+               *(struct virtchnl2_ptp_get_dev_clk_time *)args.out_buffer;<br>
+       dev_time = LE64_TO_CPU(get_dev_clk_time_msg.dev_time_ns);<br>
+       dev_clk_time->dev_clk_time_ns = dev_time;<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+int<br>
+idpf_ptp_get_cross_time(struct idpf_adapter *adapter,<br>
+                        struct idpf_ptp_dev_timers *cross_time) {<br>
+       struct virtchnl2_ptp_get_cross_time cross_time_msg = {0};<br>
+       struct idpf_cmd_info args = {0};<br>
+       int err;<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_GET_CROSS_TIME;<br>
+       args.in_args = (uint8_t *)&cross_time_msg;<br>
+       args.in_args_size = sizeof(cross_time_msg);<br>
+       args.out_buffer = adapter->mbx_resp;<br>
+       args.out_size = sizeof(cross_time_msg);<br>
+<br>
+       err = idpf_vc_cmd_execute(adapter, &args);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       cross_time_msg =<br>
+               *(struct virtchnl2_ptp_get_cross_time *)args.out_buffer;<br>
+       cross_time->dev_clk_time_ns = LE64_TO_CPU(cross_time_msg.dev_time_ns);<br>
+       cross_time->sys_time_ns = LE64_TO_CPU(cross_time_msg.sys_time_ns);<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+int<br>
+idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, uint64_t time)<br>
+{<br>
+       struct virtchnl2_ptp_set_dev_clk_time set_dev_clk_time_msg = {0};<br>
+       struct idpf_cmd_info args = {0};<br>
+       int err;<br>
+<br>
+       set_dev_clk_time_msg.dev_time_ns = CPU_TO_LE64(time);<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_SET_DEV_CLK_TIME;<br>
+       args.in_args = (uint8_t *)&set_dev_clk_time_msg;<br>
+       args.in_args_size = sizeof(set_dev_clk_time_msg);<br>
+       args.out_buffer = adapter->mbx_resp;<br>
+       args.out_size = sizeof(set_dev_clk_time_msg);<br>
+<br>
+       err = idpf_vc_cmd_execute(adapter, &args);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+int<br>
+idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, int64_t delta)<br>
+{<br>
+       struct virtchnl2_ptp_adj_dev_clk_time adj_dev_clk_time_msg = {0};<br>
+       struct idpf_cmd_info args = {0};<br>
+       int err;<br>
+<br>
+       adj_dev_clk_time_msg.delta = CPU_TO_LE64(delta);<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_TIME;<br>
+       args.in_args = (uint8_t *)&adj_dev_clk_time_msg;<br>
+       args.in_args_size = sizeof(adj_dev_clk_time_msg);<br>
+       args.out_buffer = adapter->mbx_resp;<br>
+       args.out_size = sizeof(adj_dev_clk_time_msg);<br>
+<br>
+       err = idpf_vc_cmd_execute(adapter, &args);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+int<br>
+idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, uint64_t<br>
+incval) {<br>
+       struct virtchnl2_ptp_adj_dev_clk_fine adj_dev_clk_fine_msg = {0};<br>
+       struct idpf_cmd_info args = {0};<br>
+       int err;<br>
+<br>
+       adj_dev_clk_fine_msg.incval = CPU_TO_LE64(incval);<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_FINE;<br>
+       args.in_args = (uint8_t *)&adj_dev_clk_fine_msg;<br>
+       args.in_args_size = sizeof(adj_dev_clk_fine_msg);<br>
+       args.out_buffer = adapter->mbx_resp;<br>
+       args.out_size = sizeof(adj_dev_clk_fine_msg);<br>
+<br>
+       err = idpf_vc_cmd_execute(adapter, &args);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+int<br>
+idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport) {<br>
+       struct virtchnl2_ptp_get_vport_tx_tstamp_caps send_tx_tstamp_caps = {0};<br>
+       struct virtchnl2_ptp_get_vport_tx_tstamp_caps *rcv_tx_tstamp_caps;<br>
+       struct virtchnl2_ptp_tx_tstamp_latch_caps tx_tstamp_latch_caps;<br>
+       enum idpf_ptp_access tstamp_access, get_dev_clk_access;<br>
+       struct idpf_ptp_vport_tx_tstamp_caps *tstamp_caps;<br>
+       struct idpf_ptp *ptp = vport->adapter->ptp;<br>
+       struct idpf_cmd_info args = {0};<br>
+       int err;<br>
+       uint16_t num_latches, i;<br>
Instead of using i, Can we use something like latch_itr ?<br>
+       uint32_t size;<br>
+<br>
+       if (ptp == NULL)<br>
+               return -EOPNOTSUPP;<br>
+<br>
+       tstamp_access = (enum idpf_ptp_access)ptp->tx_tstamp_access;<br>
+       get_dev_clk_access = (enum idpf_ptp_access)ptp->get_dev_clk_time_access;<br>
+       if (tstamp_access == IDPF_PTP_NONE ||<br>
+           get_dev_clk_access == IDPF_PTP_NONE)<br>
+               return -EOPNOTSUPP;<br>
+<br>
+       send_tx_tstamp_caps.vport_id = CPU_TO_LE32(vport->vport_id);<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_GET_VPORT_TX_TSTAMP_CAPS;<br>
+       args.in_args = (uint8_t *)&send_tx_tstamp_caps;<br>
+       args.in_args_size = sizeof(send_tx_tstamp_caps);<br>
+       args.out_size = IDPF_CTLQ_MAX_BUF_LEN;<br>
+       args.out_buffer = vport->adapter->mbx_resp;<br>
+<br>
+       err = idpf_vc_cmd_execute(vport->adapter, &args);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       rcv_tx_tstamp_caps =<br>
+               (struct virtchnl2_ptp_get_vport_tx_tstamp_caps *)args.out_buffer;<br>
+       num_latches = LE16_TO_CPU(rcv_tx_tstamp_caps->num_latches);<br>
+       size = sizeof(struct idpf_ptp_vport_tx_tstamp_caps) +<br>
+               sizeof(struct idpf_ptp_tx_tstamp) * num_latches;<br>
+       tstamp_caps = rte_zmalloc(NULL, size, 0);<br>
+       if (tstamp_caps == NULL)<br>
+               return -ENOMEM;<br>
+<br>
+       tstamp_caps->access = true;<br>
+       tstamp_caps->num_entries = num_latches;<br>
+       tstamp_caps->tstamp_ns_lo_bit = rcv_tx_tstamp_caps->tstamp_ns_lo_bit;<br>
+<br>
+       for (i = 0; i < tstamp_caps->num_entries; i++) {<br>
+               __le32 offset_l, offset_h;<br>
+<br>
+               tx_tstamp_latch_caps = rcv_tx_tstamp_caps->tstamp_latches[i];<br>
+<br>
+               if (tstamp_access == IDPF_PTP_DIRECT) {<br>
+                       offset_l = tx_tstamp_latch_caps.tx_latch_reg_offset_l;<br>
+                       offset_h = tx_tstamp_latch_caps.tx_latch_reg_offset_h;<br>
+                       tstamp_caps->tx_tstamp[i].tx_latch_reg_offset_l =<br>
+                               LE32_TO_CPU(offset_l);<br>
+                       tstamp_caps->tx_tstamp[i].tx_latch_reg_offset_h =<br>
+                               LE32_TO_CPU(offset_h);<br>
+               }<br>
+               tstamp_caps->tx_tstamp[i].idx = tx_tstamp_latch_caps.index;<br>
+       }<br>
+<br>
+       tstamp_caps->latched_idx = -1;<br>
+       vport->tx_tstamp_caps = tstamp_caps;<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+static int<br>
+idpf_ptp_get_tstamp_value(struct idpf_vport *vport,<br>
+                        struct virtchnl2_ptp_tx_tstamp_latch *tstamp_latch,<br>
+                        struct idpf_ptp_tx_tstamp *tx_tstamp) {<br>
+       struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;<br>
+       uint8_t tstamp_ns_lo_bit;<br>
+<br>
+       tx_tstamp_caps = vport->tx_tstamp_caps;<br>
+       tstamp_ns_lo_bit = tx_tstamp_caps->tstamp_ns_lo_bit;<br>
+<br>
+       tx_tstamp->tstamp = LE64_TO_CPU(tstamp_latch->tstamp);<br>
+       tx_tstamp->tstamp >>= tstamp_ns_lo_bit;<br>
+<br>
+       return 0;<br>
+}<br>
+<br>
+int<br>
+idpf_ptp_get_tx_tstamp(struct idpf_vport *vport) {<br>
+       struct virtchnl2_ptp_get_vport_tx_tstamp_latches *send_tx_tstamp_msg;<br>
+       struct virtchnl2_ptp_get_vport_tx_tstamp_latches *recv_tx_tstamp_msg;<br>
+       struct idpf_ptp_vport_tx_tstamp_caps *tx_tstamp_caps;<br>
+       struct virtchnl2_ptp_tx_tstamp_latch tstamp_latch;<br>
+       struct idpf_ptp_tx_tstamp *ptp_tx_tstamp;<br>
+       struct idpf_cmd_info args = {0};<br>
+       int size, msg_size;<br>
+       uint32_t vport_id;<br>
+       uint16_t num_latches, id;<br>
Instead of using id, Can we use something like latch_itr ?</span></div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 11pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 11pt; color: rgb(0, 0, 0);" class="elementToProof">
I am keeping it uniform and cheanging it to idx across the code as followed in previous developments</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 11pt; color: rgb(0, 0, 0);" class="elementToProof">
<br>
+       int err;<br>
+<br>
+       tx_tstamp_caps = vport->tx_tstamp_caps;<br>
+       ptp_tx_tstamp = tx_tstamp_caps->tx_tstamp;<br>
+<br>
+       size = sizeof(struct virtchnl2_ptp_get_vport_tx_tstamp_latches) +<br>
+               sizeof(struct virtchnl2_ptp_tx_tstamp_latch) *<br>
+               tx_tstamp_caps->num_entries;<br>
+       send_tx_tstamp_msg = rte_zmalloc(NULL, size, 0);<br>
+       if (send_tx_tstamp_msg == NULL)<br>
+               return -ENOMEM;<br>
+<br>
+       for (id = 0; id < tx_tstamp_caps->num_entries; id++, ptp_tx_tstamp++)<br>
+               send_tx_tstamp_msg->tstamp_latches[id].index = ptp_tx_tstamp->idx;<br>
+       send_tx_tstamp_msg->get_devtime_with_txtstmp = 1;<br>
+<br>
+       msg_size = sizeof(struct virtchnl2_ptp_get_vport_tx_tstamp_latches) +<br>
+               sizeof(struct virtchnl2_ptp_tx_tstamp_latch) * id;<br>
+       send_tx_tstamp_msg->vport_id = CPU_TO_LE32(vport->vport_id);<br>
+       send_tx_tstamp_msg->num_latches = CPU_TO_LE16(id);<br>
+<br>
+       args.ops = VIRTCHNL2_OP_PTP_GET_VPORT_TX_TSTAMP;<br>
+       args.in_args = (uint8_t *)send_tx_tstamp_msg;<br>
+       args.in_args_size = msg_size;<br>
+       args.out_size = msg_size;<br>
+       args.out_buffer = vport->adapter->mbx_resp;<br>
+<br>
+       err = idpf_vc_cmd_execute(vport->adapter, &args);<br>
+       rte_free(send_tx_tstamp_msg);<br>
+       if (err < 0)<br>
+               return err;<br>
+<br>
+       recv_tx_tstamp_msg =<br>
+               (struct virtchnl2_ptp_get_vport_tx_tstamp_latches *)args.out_buffer;<br>
+       vport_id = LE32_TO_CPU(recv_tx_tstamp_msg->vport_id);<br>
+       if (vport->vport_id != vport_id)<br>
+               return -EINVAL;<br>
+<br>
+       num_latches = LE16_TO_CPU(recv_tx_tstamp_msg->num_latches);<br>
+<br>
+       ptp_tx_tstamp = tx_tstamp_caps->tx_tstamp;<br>
+       for (id = 0; id < num_latches; id++, ptp_tx_tstamp++) {<br>
+               tstamp_latch = recv_tx_tstamp_msg->tstamp_latches[id];<br>
+<br>
+               if (!tstamp_latch.valid)<br>
+                       continue;<br>
+<br>
+               err = idpf_ptp_get_tstamp_value(vport, &tstamp_latch,<br>
+                                               ptp_tx_tstamp);<br>
+               if (err == 0) {<br>
+                       tx_tstamp_caps->latched_idx = id;<br>
+                       vport->adapter->time_hw = recv_tx_tstamp_msg->device_time;<br>
+               }<br>
+               break;<br>
+       }<br>
+<br>
+       return err;<br>
+}<br>
+<br>
+/**<br>
+ * idpf_ptp_read_src_clk_reg_direct - Read directly the main timer<br>
+value<br>
+ * @adapter: Driver specific private structure<br>
+ * @src_clk: Returned main timer value in nanoseconds unit<br>
+ *<br>
+ * Return: 0 on success, -errno otherwise.<br>
+ */<br>
+static int<br>
+idpf_ptp_read_src_clk_reg_direct(struct idpf_adapter *adapter, uint64_t<br>
+*src_clk) {<br>
+       struct idpf_ptp *ptp = adapter->ptp;<br>
+       uint32_t hi, lo;<br>
+<br>
+       idpf_ptp_enable_shtime(adapter);<br>
+<br>
+       lo = IDPF_PCI_REG(ptp->dev_clk_regs.dev_clk_ns_l);<br>
+       hi = IDPF_PCI_REG(ptp->dev_clk_regs.dev_clk_ns_h);<br>
+<br>
+       *src_clk = ((uint64_t)hi << 32) | lo;<br>
+       return 0;<br>
+}<br>
+<br>
+/**<br>
+ * idpf_ptp_read_src_clk_reg_mailbox - Read the main timer value<br>
+through mailbox<br>
+ * @adapter: Driver specific private structure<br>
+ * @src_clk: Returned main timer value in nanoseconds unit<br>
+ *<br>
+ * Return: 0 on success, -errno otherwise.<br>
+ */<br>
+static int<br>
+idpf_ptp_read_src_clk_reg_mailbox(struct idpf_adapter *adapter,<br>
+                                           uint64_t *src_clk)<br>
+{<br>
+       struct idpf_ptp_dev_timers clk_time;<br>
+       int err;<br>
+<br>
+       err = idpf_ptp_get_dev_clk_time(adapter, &clk_time);<br>
+       if (err)<br>
+               return err;<br>
+<br>
+       *src_clk = clk_time.dev_clk_time_ns;<br>
+       return 0;<br>
+}<br>
+<br>
+/**<br>
+ * idpf_ptp_read_src_clk_reg - Read the main timer value<br>
+ * @adapter: Driver specific private structure<br>
+ * @src_clk: Returned main timer value in nanoseconds unit<br>
+ *<br>
+ * Return: 0 on success, -errno otherwise.<br>
+ */<br>
+int<br>
+idpf_ptp_read_src_clk_reg(struct idpf_adapter *adapter, uint64_t<br>
+*src_clk) {<br>
+       if (adapter->ptp == NULL)<br>
+               return -EINVAL;<br>
+<br>
+       switch ((enum idpf_ptp_access)adapter->ptp->get_dev_clk_time_access) {<br>
+       case IDPF_PTP_MAILBOX:<br>
+               return idpf_ptp_read_src_clk_reg_mailbox(adapter, src_clk);<br>
+       case IDPF_PTP_DIRECT:<br>
+               return idpf_ptp_read_src_clk_reg_direct(adapter, src_clk);<br>
+       default:<br>
+               return -EOPNOTSUPP;<br>
+       }<br>
+}<br>
diff --git a/drivers/net/intel/idpf/idpf_ptp.h b/drivers/net/intel/idpf/idpf_ptp.h<br>
new file mode 100644<br>
index 0000000000..0c901440fb<br>
--- /dev/null<br>
+++ b/drivers/net/intel/idpf/idpf_ptp.h<br>
@@ -0,0 +1,130 @@<br>
+/* SPDX-License-Identifier: BSD-3-Clause<br>
+ * Copyright(c) 2025 Intel Corporation<br>
+ */<br>
+<br>
+#ifndef _IDPF_PTP_H_<br>
+#define _IDPF_PTP_H_<br>
+<br>
+#include "base/idpf_osdep.h"<br>
+#include <rte_time.h><br>
+#include "idpf_common_device.h"<br>
+<br>
+struct idpf_ptp_cmd {<br>
+       uint32_t exec_cmd_mask;<br>
+       uint32_t shtime_enable_mask;<br>
+};<br>
+<br>
+struct idpf_ptp_dev_clk_regs {<br>
+       volatile uint32_t *dev_clk_ns_l;<br>
+       volatile uint32_t *dev_clk_ns_h;<br>
+       volatile uint32_t *phy_clk_ns_l;<br>
+       volatile uint32_t *phy_clk_ns_h;<br>
+       volatile uint32_t *sys_time_ns_l;<br>
+       volatile uint32_t *sys_time_ns_h;<br>
+       volatile uint32_t *incval_l;<br>
+       volatile uint32_t *incval_h;<br>
+       volatile uint32_t *shadj_l;<br>
+       volatile uint32_t *shadj_h;<br>
+       volatile uint32_t *phy_incval_l;<br>
+       volatile uint32_t *phy_incval_h;<br>
+       volatile uint32_t *phy_shadj_l;<br>
+       volatile uint32_t *phy_shadj_h;<br>
+       volatile uint32_t *cmd;<br>
+       volatile uint32_t *phy_cmd;<br>
+       volatile uint32_t *cmd_sync;<br>
+};<br>
+<br>
+enum idpf_ptp_access {<br>
+       IDPF_PTP_NONE = 0,<br>
+       IDPF_PTP_DIRECT,<br>
+       IDPF_PTP_MAILBOX,<br>
+};<br>
+<br>
+struct idpf_ptp_secondary_mbx {<br>
+       uint16_t peer_mbx_q_id;<br>
+       uint16_t peer_id;<br>
+       bool valid:1;<br>
+};<br>
+<br>
+enum idpf_ptp_tx_tstamp_state {<br>
+       IDPF_PTP_FREE,<br>
+       IDPF_PTP_REQUEST,<br>
+       IDPF_PTP_READ_VALUE,<br>
+};<br>
+<br>
+struct idpf_ptp_tx_tstamp {<br>
+       uint64_t tstamp;<br>
+       uint32_t tx_latch_reg_offset_l;<br>
+       uint32_t tx_latch_reg_offset_h;<br>
+       uint32_t idx;<br>
+};<br>
+<br>
+struct idpf_ptp_vport_tx_tstamp_caps {<br>
+       uint32_t vport_id;<br>
+       uint16_t num_entries;<br>
+       uint16_t tstamp_ns_lo_bit;<br>
+       uint16_t latched_idx;<br>
+       bool access:1;<br>
+       struct idpf_ptp_tx_tstamp tx_tstamp[]; };<br>
+<br>
+struct idpf_ptp {<br>
+       uint64_t base_incval;<br>
+       uint64_t max_adj;<br>
+       struct idpf_ptp_cmd cmd;<br>
+       struct idpf_ptp_dev_clk_regs dev_clk_regs;<br>
+       uint32_t caps;<br>
+       uint8_t get_dev_clk_time_access:2;<br>
+       uint8_t get_cross_tstamp_access:2;<br>
+       uint8_t set_dev_clk_time_access:2;<br>
+       uint8_t adj_dev_clk_time_access:2;<br>
+       uint8_t tx_tstamp_access:2;<br>
+       uint8_t rsv:6;<br>
+       struct idpf_ptp_secondary_mbx secondary_mbx; };<br>
+<br>
+struct idpf_ptp_dev_timers {<br>
+       uint64_t sys_time_ns;<br>
+       uint64_t dev_clk_time_ns;<br>
+};<br>
+<br>
+int idpf_ptp_get_caps(struct idpf_adapter *adapter); int<br>
+idpf_ptp_read_src_clk_reg(struct idpf_adapter *adapter, uint64_t<br>
+*src_clk); int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,<br>
+                            struct idpf_ptp_dev_timers *dev_clk_time); int<br>
+idpf_ptp_get_cross_time(struct idpf_adapter *adapter,<br>
+                           struct idpf_ptp_dev_timers *cross_time); int<br>
+idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, uint64_t time);<br>
+int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, uint64_t<br>
+incval); int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter,<br>
+int64_t delta); int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport<br>
+*vport); int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport);<br>
+<br>
+static inline uint64_t<br>
+idpf_tstamp_convert_32b_64b(struct idpf_adapter *ad, uint32_t flag,<br>
+                           bool is_rx, uint32_t in_timestamp) {<br>
+       const uint64_t mask = 0xFFFFFFFFULL;<br>
+       uint32_t phc_time_lo, delta;<br>
+       uint64_t ns;<br>
+<br>
+       if (flag != 0)<br>
+               idpf_ptp_read_src_clk_reg(ad, &ad->time_hw);<br>
+<br>
+       phc_time_lo = (uint32_t)(ad->time_hw);<br>
+       delta = in_timestamp - phc_time_lo;<br>
+<br>
+       if (delta > mask / 2) {<br>
+               delta = phc_time_lo - in_timestamp;<br>
+               ns = ad->time_hw - delta;<br>
+       } else {<br>
+               if (is_rx)<br>
+                       ns = ad->time_hw - delta;<br>
+               else<br>
+                       ns = ad->time_hw + delta;<br>
+       }<br>
+<br>
+       return ns;<br>
+}<br>
+<br>
+#endif /* _IDPF_PTP_H_ */<br>
diff --git a/drivers/net/intel/idpf/meson.build b/drivers/net/intel/idpf/meson.build<br>
index a805d02ea2..740c1a5985 100644<br>
--- a/drivers/net/intel/idpf/meson.build<br>
+++ b/drivers/net/intel/idpf/meson.build<br>
@@ -17,6 +17,7 @@ sources += files(<br>
         'idpf_common_virtchnl.c',<br>
 <br>
         'idpf_ethdev.c',<br>
+        'idpf_ptp.c',<br>
         'idpf_rxtx.c',<br>
 )<br>
 <br>
--<br>
2.47.1<br>
<br>
</div>
</body>
</html>