diff --git a/doc/guides/nics/features/hns3.ini b/doc/guides/nics/features/hns3.ini
index 3988be4..502bfe7 100644
--- a/doc/guides/nics/features/hns3.ini
+++ b/doc/guides/nics/features/hns3.ini
@@ -43,6 +43,8 @@ Stats per queue      = Y
 FW version           = Y
 Registers dump       = Y
 Module EEPROM dump   = Y
+Timesync             = Y
+Timestamp offload    = Y
 Multiprocess aware   = Y
 Linux                = Y
 ARMv8                = Y
diff --git a/doc/guides/nics/hns3.rst b/doc/guides/nics/hns3.rst
index ccd2f6f..3366562 100644
--- a/doc/guides/nics/hns3.rst
+++ b/doc/guides/nics/hns3.rst
@@ -37,6 +37,7 @@ Features of the HNS3 PMD are:
 - MTU update
 - NUMA support
 - Generic flow API
+- IEEE1588/802.1AS timestamping
 
 Prerequisites
 -------------
diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h
index e704d0c..abc853b 100644
--- a/drivers/net/hns3/hns3_cmd.h
+++ b/drivers/net/hns3/hns3_cmd.h
@@ -123,6 +123,12 @@ enum hns3_opcode_type {
 	HNS3_OPC_CLEAR_MAC_TNL_INT      = 0x0312,
 	HNS3_OPC_CONFIG_FEC_MODE        = 0x031A,
 
+#ifdef RTE_LIBRTE_IEEE1588
+	/* PTP command */
+	HNS3_OPC_PTP_INT_EN             = 0x0501,
+	HNS3_OPC_CFG_PTP_MODE           = 0x0507,
+#endif
+
 	/* PFC/Pause commands */
 	HNS3_OPC_CFG_MAC_PAUSE_EN       = 0x0701,
 	HNS3_OPC_CFG_PFC_PAUSE_EN       = 0x0702,
@@ -969,6 +975,33 @@ struct hns3_query_ssu_cmd {
 	uint32_t oq_drop_cnt;
 	uint32_t rev1[2];
 };
+#ifdef RTE_LIBRTE_IEEE1588
+#define HNS3_PTP_ENABLE_B               0
+#define HNS3_PTP_TX_ENABLE_B            1
+#define HNS3_PTP_RX_ENABLE_B            2
+
+#define HNS3_PTP_TYPE_S                 0
+#define HNS3_PTP_TYPE_M                (0x3 << HNS3_PTP_TYPE_S)
+
+#define ALL_PTP_V2_TYPE                 0xF
+#define HNS3_PTP_MESSAGE_TYPE_S         0
+#define HNS3_PTP_MESSAGE_TYPE_M        (0xF << HNS3_PTP_MESSAGE_TYPE_S)
+
+#define PTP_TYPE_L2_V2_TYPE             0
+
+struct hns3_ptp_mode_cfg_cmd {
+	uint8_t enable;
+	uint8_t ptp_type;
+	uint8_t v2_message_type_1;
+	uint8_t v2_message_type_0;
+	uint8_t rsv[20];
+};
+
+struct hns3_ptp_int_cmd {
+	uint8_t int_en;
+	uint8_t rsvd[23];
+};
+#endif
 
 #define HNS3_MAX_TQP_NUM_HIP08_PF	64
 #define HNS3_DEFAULT_TX_BUF		0x4000    /* 16k  bytes */
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
index b985447..11b9065 100644
--- a/drivers/net/hns3/hns3_ethdev.c
+++ b/drivers/net/hns3/hns3_ethdev.c
@@ -58,6 +58,10 @@ enum hns3_evt_cause {
 	HNS3_VECTOR0_EVENT_RST,
 	HNS3_VECTOR0_EVENT_MBX,
 	HNS3_VECTOR0_EVENT_ERR,
+
+#ifdef RTE_LIBRTE_IEEE1588
+	HNS3_VECTOR0_EVENT_PTP,
+#endif
 	HNS3_VECTOR0_EVENT_OTHER,
 };
 
@@ -202,6 +206,14 @@ hns3_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval)
 		goto out;
 	}
 
+#ifdef RTE_LIBRTE_IEEE1588
+	/* Check for vector0 1588 event source */
+	if (BIT(HNS3_VECTOR0_1588_INT_B) & vector0_int_stats) {
+		val = BIT(HNS3_VECTOR0_1588_INT_B);
+		ret = HNS3_VECTOR0_EVENT_PTP;
+		goto out;
+	}
+#endif
 	/* check for vector0 msix event source */
 	if (vector0_int_stats & HNS3_VECTOR0_REG_MSIX_MASK ||
 	    hw_err_src_reg & HNS3_RAS_REG_NFE_MASK) {
@@ -227,10 +239,22 @@ hns3_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval)
 	return ret;
 }
 
+static bool
+hns3_is_1588_event_type(uint32_t event_type)
+{
+#ifdef RTE_LIBRTE_IEEE1588
+	return (event_type == HNS3_VECTOR0_EVENT_PTP);
+#else
+	RTE_SET_USED(event_type);
+	return false;
+#endif
+}
+
 static void
 hns3_clear_event_cause(struct hns3_hw *hw, uint32_t event_type, uint32_t regclr)
 {
-	if (event_type == HNS3_VECTOR0_EVENT_RST)
+	if (event_type == HNS3_VECTOR0_EVENT_RST ||
+	    hns3_is_1588_event_type(event_type))
 		hns3_write_dev(hw, HNS3_MISC_RESET_STS_REG, regclr);
 	else if (event_type == HNS3_VECTOR0_EVENT_MBX)
 		hns3_write_dev(hw, HNS3_VECTOR0_CMDQ_SRC_REG, regclr);
@@ -253,6 +277,11 @@ hns3_clear_all_event_cause(struct hns3_hw *hw)
 			       BIT(HNS3_VECTOR0_GLOBALRESET_INT_B) |
 			       BIT(HNS3_VECTOR0_CORERESET_INT_B));
 	hns3_clear_event_cause(hw, HNS3_VECTOR0_EVENT_MBX, 0);
+
+#ifdef RTE_LIBRTE_IEEE1588
+	hns3_clear_event_cause(hw, HNS3_VECTOR0_EVENT_PTP,
+				BIT(HNS3_VECTOR0_1588_INT_B));
+#endif
 }
 
 static void
@@ -2467,6 +2496,11 @@ hns3_dev_configure(struct rte_eth_dev *dev)
 	if (ret)
 		goto cfg_err;
 
+#ifdef RTE_LIBRTE_IEEE1588
+	ret = hns3_mbuf_dyn_rx_timestamp_register(dev, conf);
+	if (ret)
+		goto cfg_err;
+#endif
 	ret = hns3_dev_configure_vlan(dev);
 	if (ret)
 		goto cfg_err;
@@ -2640,6 +2674,9 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info)
 		info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP |
 				 RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP;
 
+	if (hns3_dev_ptp_supported(hw))
+		info->rx_offload_capa |= DEV_RX_OFFLOAD_TIMESTAMP;
+
 	info->rx_desc_lim = (struct rte_eth_desc_lim) {
 		.nb_max = HNS3_MAX_RING_DESC,
 		.nb_min = HNS3_MIN_RING_DESC,
@@ -4933,6 +4970,11 @@ hns3_init_pf(struct rte_eth_dev *eth_dev)
 		goto err_intr_callback_register;
 	}
 
+#ifdef RTE_LIBRTE_IEEE1588
+	ret = hns3_ptp_init(hw);
+	if (ret)
+		goto err_get_config;
+#endif
 	/* Enable interrupt */
 	rte_intr_enable(&pci_dev->intr_handle);
 	hns3_pf_enable_irq0(hw);
@@ -5950,6 +5992,12 @@ hns3_restore_conf(struct hns3_adapter *hns)
 	if (ret)
 		goto err_promisc;
 
+#ifdef RTE_LIBRTE_IEEE1588
+	ret = hns3_restore_ptp(hns);
+	if (ret)
+		goto err_promisc;
+#endif
+
 	ret = hns3_restore_rx_interrupt(hw);
 	if (ret)
 		goto err_promisc;
@@ -6654,6 +6702,15 @@ static const struct eth_dev_ops hns3_eth_dev_ops = {
 	.fec_set                = hns3_fec_set,
 	.tm_ops_get             = hns3_tm_ops_get,
 	.tx_done_cleanup        = hns3_tx_done_cleanup,
+#ifdef RTE_LIBRTE_IEEE1588
+	.timesync_enable            = hns3_timesync_enable,
+	.timesync_disable           = hns3_timesync_disable,
+	.timesync_read_rx_timestamp = hns3_timesync_read_rx_timestamp,
+	.timesync_read_tx_timestamp = hns3_timesync_read_tx_timestamp,
+	.timesync_adjust_time       = hns3_timesync_adjust_time,
+	.timesync_read_time         = hns3_timesync_read_time,
+	.timesync_write_time        = hns3_timesync_write_time,
+#endif
 };
 
 static const struct hns3_reset_ops hns3_reset_ops = {
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
index f69e2d8..4ce192c 100644
--- a/drivers/net/hns3/hns3_ethdev.h
+++ b/drivers/net/hns3/hns3_ethdev.h
@@ -731,6 +731,13 @@ struct hns3_pf {
 	bool support_sfp_query;
 	uint32_t fec_mode; /* current FEC mode for ethdev */
 
+#ifdef RTE_LIBRTE_IEEE1588
+	bool ptp_enable;
+
+	/* Stores timestamp of last received packet on dev */
+	uint64_t rx_timestamp;
+#endif
+
 	struct hns3_vtag_cfg vtag_config;
 	LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list;
 
@@ -982,6 +989,24 @@ void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
 			  uint32_t link_speed, uint8_t link_duplex);
 void hns3_parse_devargs(struct rte_eth_dev *dev);
 
+#ifdef RTE_LIBRTE_IEEE1588
+int hns3_restore_ptp(struct hns3_adapter *hns);
+int hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
+				    struct rte_eth_conf *conf);
+int hns3_ptp_init(struct hns3_hw *hw);
+int hns3_timesync_enable(struct rte_eth_dev *dev);
+int hns3_timesync_disable(struct rte_eth_dev *dev);
+int hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
+				struct timespec *timestamp,
+				uint32_t flags __rte_unused);
+int hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
+				struct timespec *timestamp);
+int hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts);
+int hns3_timesync_write_time(struct rte_eth_dev *dev,
+			const struct timespec *ts);
+int hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta);
+#endif
+
 static inline bool
 is_reset_pending(struct hns3_adapter *hns)
 {
diff --git a/drivers/net/hns3/hns3_ptp.c b/drivers/net/hns3/hns3_ptp.c
new file mode 100644
index 0000000..d7e18c1
--- /dev/null
+++ b/drivers/net/hns3/hns3_ptp.c
@@ -0,0 +1,294 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021-2021 Hisilicon Limited.
+ */
+
+#include <ethdev_pci.h>
+#include <rte_io.h>
+#include <rte_time.h>
+
+#include "hns3_ethdev.h"
+#include "hns3_regs.h"
+#include "hns3_logs.h"
+
+#ifdef RTE_LIBRTE_IEEE1588
+uint64_t hns3_timestamp_rx_dynflag;
+int hns3_timestamp_dynfield_offset = -1;
+
+int
+hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
+				    struct rte_eth_conf *conf)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	int ret;
+
+	if (!(conf->rxmode.offloads & DEV_RX_OFFLOAD_TIMESTAMP))
+		return 0;
+
+	ret = rte_mbuf_dyn_rx_timestamp_register
+			(&hns3_timestamp_dynfield_offset,
+			 &hns3_timestamp_rx_dynflag);
+	if (ret) {
+		hns3_err(hw,
+			"failed to register Rx timestamp field/flag");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+hns3_ptp_int_en(struct hns3_hw *hw, bool en)
+{
+	struct hns3_ptp_int_cmd *req;
+	struct hns3_cmd_desc desc;
+	int ret;
+
+	req = (struct hns3_ptp_int_cmd *)desc.data;
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_PTP_INT_EN, false);
+	req->int_en = en ? 1 : 0;
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret)
+		hns3_err(hw,
+			"failed to %s ptp interrupt, ret = %d\n",
+			en ? "enable" : "disable", ret);
+
+	return ret;
+}
+
+int
+hns3_ptp_init(struct hns3_hw *hw)
+{
+	int ret;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return 0;
+
+	ret = hns3_ptp_int_en(hw, true);
+	if (ret)
+		return ret;
+
+	/* Start PTP timer */
+	hns3_write_dev(hw, HNS3_CFG_TIME_CYC_EN, 1);
+
+	return 0;
+}
+
+static int
+hns3_timesync_configure(struct hns3_adapter *hns, bool en)
+{
+	struct hns3_ptp_mode_cfg_cmd *req;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_pf *pf = &hns->pf;
+	struct hns3_cmd_desc desc;
+	int val;
+	int ret;
+
+	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_PTP_MODE, false);
+
+	req = (struct hns3_ptp_mode_cfg_cmd *)desc.data;
+
+	val = en ? 1 : 0;
+	hns3_set_bit(req->enable, HNS3_PTP_ENABLE_B, val);
+	hns3_set_bit(req->enable, HNS3_PTP_TX_ENABLE_B, val);
+	hns3_set_bit(req->enable, HNS3_PTP_RX_ENABLE_B, val);
+
+	if (en) {
+		hns3_set_field(req->ptp_type, HNS3_PTP_TYPE_M, HNS3_PTP_TYPE_S,
+			       PTP_TYPE_L2_V2_TYPE);
+		hns3_set_field(req->v2_message_type_1, HNS3_PTP_MESSAGE_TYPE_M,
+			       HNS3_PTP_MESSAGE_TYPE_S, ALL_PTP_V2_TYPE);
+	}
+
+	ret = hns3_cmd_send(hw, &desc, 1);
+	if (ret) {
+		hns3_err(hw, "configure PTP time failed, en = %d, ret = %d",
+			 en, ret);
+		return ret;
+	}
+
+	pf->ptp_enable = en;
+
+	return 0;
+}
+
+int
+hns3_timesync_enable(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+
+	if (pf->ptp_enable)
+		return 0;
+
+	rte_spinlock_lock(&hw->lock);
+	ret = hns3_timesync_configure(hns, true);
+	rte_spinlock_unlock(&hw->lock);
+	return ret;
+}
+
+int
+hns3_timesync_disable(struct rte_eth_dev *dev)
+{
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_pf *pf = &hns->pf;
+	int ret;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+
+	if (!pf->ptp_enable)
+		return 0;
+
+	rte_spinlock_lock(&hw->lock);
+	ret = hns3_timesync_configure(hns, false);
+	rte_spinlock_unlock(&hw->lock);
+
+	return ret;
+}
+
+int
+hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
+				struct timespec *timestamp,
+				uint32_t flags __rte_unused)
+{
+#define TIME_RX_STAMP_NS_MASK 0x3FFFFFFF
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	struct hns3_pf *pf = &hns->pf;
+	uint64_t ns, sec;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+
+	ns = pf->rx_timestamp & TIME_RX_STAMP_NS_MASK;
+	sec = upper_32_bits(pf->rx_timestamp);
+
+	ns += sec * NSEC_PER_SEC;
+	*timestamp = rte_ns_to_timespec(ns);
+
+	return 0;
+}
+
+int
+hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
+				struct timespec *timestamp)
+{
+#define TIME_TX_STAMP_NS_MASK 0x3FFFFFFF
+#define TIME_TX_STAMP_VALID   24
+#define TIME_TX_STAMP_CNT_MASK 0x7
+	struct hns3_adapter *hns = dev->data->dev_private;
+	struct hns3_hw *hw = &hns->hw;
+	uint64_t sec;
+	uint64_t tmp;
+	uint64_t ns;
+	int ts_cnt;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+
+	ts_cnt = hns3_read_dev(hw, HNS3_TX_1588_BACK_TSP_CNT) &
+			TIME_TX_STAMP_CNT_MASK;
+	if (ts_cnt == 0)
+		return -EINVAL;
+
+	ns = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_0) & TIME_TX_STAMP_NS_MASK;
+	sec = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_1);
+	tmp = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_2) & 0xFFFF;
+	sec = (tmp << 32) | sec;
+
+	ns += sec * NSEC_PER_SEC;
+
+	*timestamp = rte_ns_to_timespec(ns);
+
+	/* Clear current timestamp hardware stores */
+	hns3_read_dev(hw, HNS3_TX_1588_SEQID_BACK);
+
+	return 0;
+}
+
+int
+hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint64_t ns, sec;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+
+	sec = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_L);
+	sec |= (uint64_t)(hns3_read_dev(hw, HNS3_CURR_TIME_OUT_H) & 0xFFFF)
+		<< 32;
+
+	ns = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_NS);
+	ns += sec * NSEC_PER_SEC;
+	*ts = rte_ns_to_timespec(ns);
+
+	return 0;
+}
+
+int
+hns3_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
+{
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	uint64_t sec = ts->tv_sec;
+	uint64_t ns = ts->tv_nsec;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+
+	/* Set the timecounters to a new value. */
+	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_H, upper_32_bits(sec));
+	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_M, lower_32_bits(sec));
+	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_L, lower_32_bits(ns));
+	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_RDY, 1);
+
+	return 0;
+}
+
+int
+hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
+{
+#define TIME_SYNC_L_MASK 0x7FFFFFFF
+#define SYMBOL_BIT_OFFSET 31
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct timespec cur_time;
+	uint64_t ns;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+
+	(void)hns3_timesync_read_time(dev, &cur_time);
+	ns = rte_timespec_to_ns((const struct timespec *)&cur_time);
+	cur_time = rte_ns_to_timespec(ns + delta);
+	(void)hns3_timesync_write_time(dev, (const struct timespec *)&cur_time);
+
+	return 0;
+}
+
+int
+hns3_restore_ptp(struct hns3_adapter *hns)
+{
+	struct hns3_pf *pf = &hns->pf;
+	struct hns3_hw *hw = &hns->hw;
+	bool en = pf->ptp_enable;
+	int ret;
+
+	if (!hns3_dev_ptp_supported(hw))
+		return 0;
+
+	ret = hns3_timesync_configure(hns, en);
+	if (ret)
+		hns3_err(hw, "restore PTP enable state(%d) failed, ret = %d",
+			 en, ret);
+
+	return ret;
+}
+#endif
diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h
index e141fe1..58a20ca 100644
--- a/drivers/net/hns3/hns3_regs.h
+++ b/drivers/net/hns3/hns3_regs.h
@@ -121,6 +121,31 @@
 #define HNS3_TQP_INTR_RL_DEFAULT		0
 #define HNS3_TQP_INTR_QL_DEFAULT		0
 
+#ifdef RTE_LIBRTE_IEEE1588
+/* Register bit for 1588 event */
+#define HNS3_VECTOR0_1588_INT_B	                0
+
+#define HNS3_PTP_BASE_ADDRESS			0x29000
+
+#define HNS3_TX_1588_SEQID_BACK			(HNS3_PTP_BASE_ADDRESS + 0x0)
+#define HNS3_TX_1588_TSP_BACK_0			(HNS3_PTP_BASE_ADDRESS + 0x4)
+#define HNS3_TX_1588_TSP_BACK_1			(HNS3_PTP_BASE_ADDRESS + 0x8)
+#define HNS3_TX_1588_TSP_BACK_2			(HNS3_PTP_BASE_ADDRESS + 0xc)
+
+#define HNS3_TX_1588_BACK_TSP_CNT		(HNS3_PTP_BASE_ADDRESS + 0x30)
+
+#define HNS3_CFG_TIME_SYNC_H			(HNS3_PTP_BASE_ADDRESS + 0x50)
+#define HNS3_CFG_TIME_SYNC_M			(HNS3_PTP_BASE_ADDRESS + 0x54)
+#define HNS3_CFG_TIME_SYNC_L			(HNS3_PTP_BASE_ADDRESS + 0x58)
+#define HNS3_CFG_TIME_SYNC_RDY			(HNS3_PTP_BASE_ADDRESS + 0x5c)
+
+#define HNS3_CFG_TIME_CYC_EN			(HNS3_PTP_BASE_ADDRESS + 0x70)
+
+#define HNS3_CURR_TIME_OUT_H			(HNS3_PTP_BASE_ADDRESS + 0x74)
+#define HNS3_CURR_TIME_OUT_L			(HNS3_PTP_BASE_ADDRESS + 0x78)
+#define HNS3_CURR_TIME_OUT_NS			(HNS3_PTP_BASE_ADDRESS + 0x7c)
+#endif
+
 /* gl_usec convert to hardware count, as writing each 1 represents 2us */
 #define HNS3_GL_USEC_TO_REG(gl_usec)		((gl_usec) >> 1)
 /* rl_usec convert to hardware count, as writing each 1 represents 4us */
diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index feeb702..ceed302 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -2275,6 +2275,25 @@ hns3_rx_alloc_buffer(struct hns3_rx_queue *rxq)
 		return rte_mbuf_raw_alloc(rxq->mb_pool);
 }
 
+#ifdef RTE_LIBRTE_IEEE1588
+static inline void
+hns3_rx_ptp_timestamp_handle(struct hns3_rx_queue *rxq, struct rte_mbuf *mbuf,
+		  volatile struct hns3_desc *rxd)
+{
+	struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(rxq->hns);
+	uint64_t timestamp = rte_le_to_cpu_64(rxd->timestamp);
+
+	mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST;
+	if (hns3_timestamp_rx_dynflag > 0) {
+		*RTE_MBUF_DYNFIELD(mbuf, hns3_timestamp_dynfield_offset,
+			rte_mbuf_timestamp_t *) = timestamp;
+		mbuf->ol_flags |= hns3_timestamp_rx_dynflag;
+	}
+
+	pf->rx_timestamp = timestamp;
+}
+#endif
+
 uint16_t
 hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 {
@@ -2334,8 +2353,13 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		}
 
 		rxm = rxe->mbuf;
+		rxm->ol_flags = 0;
 		rxe->mbuf = nmb;
 
+#ifdef RTE_LIBRTE_IEEE1588
+		if (unlikely(bd_base_info & BIT(HNS3_RXD_TS_VLD_B)))
+			hns3_rx_ptp_timestamp_handle(rxq, rxm, rxdp);
+#endif
 		dma_addr = rte_mbuf_data_iova_default(nmb);
 		rxdp->addr = rte_cpu_to_le_64(dma_addr);
 		rxdp->rx.bd_base_info = 0;
@@ -2346,7 +2370,7 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		rxm->data_len = rxm->pkt_len;
 		rxm->port = rxq->port_id;
 		rxm->hash.rss = rte_le_to_cpu_32(rxd.rx.rss_hash);
-		rxm->ol_flags = PKT_RX_RSS_HASH;
+		rxm->ol_flags |= PKT_RX_RSS_HASH;
 		if (unlikely(bd_base_info & BIT(HNS3_RXD_LUM_B))) {
 			rxm->hash.fdir.hi =
 				rte_le_to_cpu_16(rxd.rx.fd_id);
@@ -2365,6 +2389,11 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 		rxm->packet_type = hns3_rx_calc_ptype(rxq, l234_info, ol_info);
 
+#ifdef RTE_LIBRTE_IEEE1588
+		if (rxm->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC)
+			rxm->ol_flags |= PKT_RX_IEEE1588_PTP;
+#endif
+
 		if (likely(bd_base_info & BIT(HNS3_RXD_L3L4P_B)))
 			hns3_rx_set_cksum_flag(rxm, rxm->packet_type,
 					       cksum_err);
@@ -2952,7 +2981,7 @@ hns3_fill_per_desc(struct hns3_desc *desc, struct rte_mbuf *rxm)
 {
 	desc->addr = rte_mbuf_data_iova(rxm);
 	desc->tx.send_size = rte_cpu_to_le_16(rte_pktmbuf_data_len(rxm));
-	desc->tx.tp_fe_sc_vld_ra_ri = rte_cpu_to_le_16(BIT(HNS3_TXD_VLD_B));
+	desc->tx.tp_fe_sc_vld_ra_ri |= rte_cpu_to_le_16(BIT(HNS3_TXD_VLD_B));
 }
 
 static void
@@ -3000,6 +3029,12 @@ hns3_fill_first_desc(struct hns3_tx_queue *txq, struct hns3_desc *desc,
 					rte_cpu_to_le_32(BIT(HNS3_TXD_VLAN_B));
 		desc->tx.vlan_tag = rte_cpu_to_le_16(rxm->vlan_tci);
 	}
+
+#ifdef RTE_LIBRTE_IEEE1588
+	if (ol_flags & PKT_TX_IEEE1588_TMST)
+		desc->tx.tp_fe_sc_vld_ra_ri |=
+				rte_cpu_to_le_16(BIT(HNS3_TXD_TSYN_B));
+#endif
 }
 
 static inline int
@@ -3991,10 +4026,23 @@ hns3_tx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id,
 	return 0;
 }
 
+static bool
+hns3_tx_check_simple_support(struct rte_eth_dev *dev)
+{
+	uint64_t offloads = dev->data->dev_conf.txmode.offloads;
+
+#ifdef RTE_LIBRTE_IEEE1588
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	if (hns3_dev_ptp_supported(hw))
+		return false;
+#endif
+
+	return (offloads == (offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE));
+}
+
 static eth_tx_burst_t
 hns3_get_tx_function(struct rte_eth_dev *dev, eth_tx_prep_t *prep)
 {
-	uint64_t offloads = dev->data->dev_conf.txmode.offloads;
 	struct hns3_adapter *hns = dev->data->dev_private;
 	bool vec_allowed, sve_allowed, simple_allowed;
 
@@ -4002,7 +4050,7 @@ hns3_get_tx_function(struct rte_eth_dev *dev, eth_tx_prep_t *prep)
 		      hns3_tx_check_vec_support(dev) == 0;
 	sve_allowed = vec_allowed && hns3_check_sve_support();
 	simple_allowed = hns->tx_simple_allowed &&
-			 offloads == (offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE);
+			 hns3_tx_check_simple_support(dev);
 
 	*prep = NULL;
 
diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h
index f9b3048..74e5407 100644
--- a/drivers/net/hns3/hns3_rxtx.h
+++ b/drivers/net/hns3/hns3_rxtx.h
@@ -106,6 +106,8 @@
 #define HNS3_RXD_L3L4P_B			11
 #define HNS3_RXD_TSIND_S			12
 #define HNS3_RXD_TSIND_M			(0x7 << HNS3_RXD_TSIND_S)
+
+#define HNS3_RXD_TS_VLD_B			14
 #define HNS3_RXD_LKBK_B				15
 #define HNS3_RXD_GRO_SIZE_S			16
 #define HNS3_RXD_GRO_SIZE_M			(0x3fff << HNS3_RXD_GRO_SIZE_S)
@@ -200,6 +202,11 @@ enum hns3_pkt_tun_type {
 struct hns3_desc {
 	union {
 		uint64_t addr;
+
+#ifdef RTE_LIBRTE_IEEE1588
+		uint64_t timestamp;
+#endif
+
 		struct {
 			uint32_t addr0;
 			uint32_t addr1;
@@ -518,6 +525,11 @@ enum hns3_cksum_status {
 	HNS3_OUTER_L4_CKSUM_ERR = 8
 };
 
+#ifdef RTE_LIBRTE_IEEE1588
+extern uint64_t hns3_timestamp_rx_dynflag;
+extern int hns3_timestamp_dynfield_offset;
+#endif
+
 static inline int
 hns3_handle_bdinfo(struct hns3_rx_queue *rxq, struct rte_mbuf *rxm,
 		   uint32_t bd_base_info, uint32_t l234_info,
diff --git a/drivers/net/hns3/hns3_rxtx_vec.c b/drivers/net/hns3/hns3_rxtx_vec.c
index 2bc4372..4584d8a 100644
--- a/drivers/net/hns3/hns3_rxtx_vec.c
+++ b/drivers/net/hns3/hns3_rxtx_vec.c
@@ -18,6 +18,12 @@ hns3_tx_check_vec_support(struct rte_eth_dev *dev)
 {
 	struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
 
+#ifdef RTE_LIBRTE_IEEE1588
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	if (hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+#endif
+
 	/* Only support DEV_TX_OFFLOAD_MBUF_FAST_FREE */
 	if (txmode->offloads != DEV_TX_OFFLOAD_MBUF_FAST_FREE)
 		return -ENOTSUP;
@@ -167,7 +173,6 @@ hns3_rxq_vec_setup(struct hns3_rx_queue *rxq)
 	memset(rxq->offset_table, 0, sizeof(rxq->offset_table));
 }
 
-#ifndef RTE_LIBRTE_IEEE1588
 static int
 hns3_rxq_vec_check(struct hns3_rx_queue *rxq, void *arg)
 {
@@ -183,17 +188,21 @@ hns3_rxq_vec_check(struct hns3_rx_queue *rxq, void *arg)
 	RTE_SET_USED(arg);
 	return 0;
 }
-#endif
 
 int
 hns3_rx_check_vec_support(struct rte_eth_dev *dev)
 {
-#ifndef RTE_LIBRTE_IEEE1588
 	struct rte_fdir_conf *fconf = &dev->data->dev_conf.fdir_conf;
 	struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
 	uint64_t offloads_mask = DEV_RX_OFFLOAD_TCP_LRO |
 				 DEV_RX_OFFLOAD_VLAN;
 
+#ifdef RTE_LIBRTE_IEEE1588
+	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	if (hns3_dev_ptp_supported(hw))
+		return -ENOTSUP;
+#endif
+
 	if (dev->data->scattered_rx)
 		return -ENOTSUP;
 
@@ -207,8 +216,4 @@ hns3_rx_check_vec_support(struct rte_eth_dev *dev)
 		return -ENOTSUP;
 
 	return 0;
-#else
-	RTE_SET_USED(dev);
-	return -ENOTSUP;
-#endif
 }
diff --git a/drivers/net/hns3/meson.build b/drivers/net/hns3/meson.build
index f6aac69..6d78c33 100644
--- a/drivers/net/hns3/meson.build
+++ b/drivers/net/hns3/meson.build
@@ -26,7 +26,8 @@ sources = files('hns3_cmd.c',
 	'hns3_rxtx.c',
 	'hns3_stats.c',
 	'hns3_mp.c',
-	'hns3_tm.c')
+	'hns3_tm.c',
+	'hns3_ptp.c')
 
 deps += ['hash']
 
