138b539d9SMin Hu (Connor) /* SPDX-License-Identifier: BSD-3-Clause 238b539d9SMin Hu (Connor) * Copyright(c) 2021-2021 Hisilicon Limited. 338b539d9SMin Hu (Connor) */ 438b539d9SMin Hu (Connor) 538b539d9SMin Hu (Connor) #include <ethdev_pci.h> 638b539d9SMin Hu (Connor) #include <rte_io.h> 738b539d9SMin Hu (Connor) #include <rte_time.h> 838b539d9SMin Hu (Connor) 938b539d9SMin Hu (Connor) #include "hns3_ethdev.h" 1078399874SHuisong Li #include "hns3_ptp.h" 1138b539d9SMin Hu (Connor) #include "hns3_logs.h" 1238b539d9SMin Hu (Connor) 1338b539d9SMin Hu (Connor) uint64_t hns3_timestamp_rx_dynflag; 1438b539d9SMin Hu (Connor) int hns3_timestamp_dynfield_offset = -1; 1538b539d9SMin Hu (Connor) 1638b539d9SMin Hu (Connor) int 1738b539d9SMin Hu (Connor) hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev, 1838b539d9SMin Hu (Connor) struct rte_eth_conf *conf) 1938b539d9SMin Hu (Connor) { 2038b539d9SMin Hu (Connor) struct hns3_adapter *hns = dev->data->dev_private; 2138b539d9SMin Hu (Connor) struct hns3_hw *hw = &hns->hw; 2238b539d9SMin Hu (Connor) int ret; 2338b539d9SMin Hu (Connor) 24295968d1SFerruh Yigit if (!(conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP)) 2538b539d9SMin Hu (Connor) return 0; 2638b539d9SMin Hu (Connor) 2738b539d9SMin Hu (Connor) ret = rte_mbuf_dyn_rx_timestamp_register 2838b539d9SMin Hu (Connor) (&hns3_timestamp_dynfield_offset, 2938b539d9SMin Hu (Connor) &hns3_timestamp_rx_dynflag); 3038b539d9SMin Hu (Connor) if (ret) { 3138b539d9SMin Hu (Connor) hns3_err(hw, 3238b539d9SMin Hu (Connor) "failed to register Rx timestamp field/flag"); 3338b539d9SMin Hu (Connor) return ret; 3438b539d9SMin Hu (Connor) } 3538b539d9SMin Hu (Connor) 3638b539d9SMin Hu (Connor) return 0; 3738b539d9SMin Hu (Connor) } 3838b539d9SMin Hu (Connor) 3938b539d9SMin Hu (Connor) static int 4038b539d9SMin Hu (Connor) hns3_ptp_int_en(struct hns3_hw *hw, bool en) 4138b539d9SMin Hu (Connor) { 4238b539d9SMin Hu (Connor) struct hns3_ptp_int_cmd *req; 4338b539d9SMin Hu (Connor) struct hns3_cmd_desc desc; 4438b539d9SMin Hu (Connor) int ret; 4538b539d9SMin Hu (Connor) 4638b539d9SMin Hu (Connor) req = (struct hns3_ptp_int_cmd *)desc.data; 4738b539d9SMin Hu (Connor) hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_PTP_INT_EN, false); 4838b539d9SMin Hu (Connor) req->int_en = en ? 1 : 0; 4938b539d9SMin Hu (Connor) 5038b539d9SMin Hu (Connor) ret = hns3_cmd_send(hw, &desc, 1); 5138b539d9SMin Hu (Connor) if (ret) 5238b539d9SMin Hu (Connor) hns3_err(hw, 53*f665790aSDavid Marchand "failed to %s ptp interrupt, ret = %d", 5438b539d9SMin Hu (Connor) en ? "enable" : "disable", ret); 5538b539d9SMin Hu (Connor) 5638b539d9SMin Hu (Connor) return ret; 5738b539d9SMin Hu (Connor) } 5838b539d9SMin Hu (Connor) 59f901c570SHuisong Li static void 60f901c570SHuisong Li hns3_ptp_timesync_write_time(struct hns3_hw *hw, const struct timespec *ts) 61f901c570SHuisong Li { 62f901c570SHuisong Li uint64_t sec = ts->tv_sec; 63f901c570SHuisong Li uint64_t ns = ts->tv_nsec; 64f901c570SHuisong Li 65f901c570SHuisong Li /* Set the timecounters to a new value. */ 66f901c570SHuisong Li hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_H, upper_32_bits(sec)); 67f901c570SHuisong Li hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_M, lower_32_bits(sec)); 68f901c570SHuisong Li hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_L, lower_32_bits(ns)); 69f901c570SHuisong Li hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_RDY, 1); 70f901c570SHuisong Li } 71f901c570SHuisong Li 7238b539d9SMin Hu (Connor) int 7338b539d9SMin Hu (Connor) hns3_ptp_init(struct hns3_hw *hw) 7438b539d9SMin Hu (Connor) { 75f901c570SHuisong Li struct timespec sys_time; 7638b539d9SMin Hu (Connor) int ret; 7738b539d9SMin Hu (Connor) 78efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 7938b539d9SMin Hu (Connor) return 0; 8038b539d9SMin Hu (Connor) 8138b539d9SMin Hu (Connor) ret = hns3_ptp_int_en(hw, true); 8238b539d9SMin Hu (Connor) if (ret) 8338b539d9SMin Hu (Connor) return ret; 8438b539d9SMin Hu (Connor) 8538b539d9SMin Hu (Connor) /* Start PTP timer */ 8638b539d9SMin Hu (Connor) hns3_write_dev(hw, HNS3_CFG_TIME_CYC_EN, 1); 8738b539d9SMin Hu (Connor) 88f901c570SHuisong Li /* Initializing the RTC. */ 89f901c570SHuisong Li clock_gettime(CLOCK_REALTIME, &sys_time); 90f901c570SHuisong Li hns3_ptp_timesync_write_time(hw, &sys_time); 91f901c570SHuisong Li 9238b539d9SMin Hu (Connor) return 0; 9338b539d9SMin Hu (Connor) } 9438b539d9SMin Hu (Connor) 9538b539d9SMin Hu (Connor) static int 9638b539d9SMin Hu (Connor) hns3_timesync_configure(struct hns3_adapter *hns, bool en) 9738b539d9SMin Hu (Connor) { 9838b539d9SMin Hu (Connor) struct hns3_ptp_mode_cfg_cmd *req; 9938b539d9SMin Hu (Connor) struct hns3_hw *hw = &hns->hw; 10038b539d9SMin Hu (Connor) struct hns3_pf *pf = &hns->pf; 10138b539d9SMin Hu (Connor) struct hns3_cmd_desc desc; 102b902301eSMin Hu (Connor) uint32_t val; 10338b539d9SMin Hu (Connor) int ret; 10438b539d9SMin Hu (Connor) 10538b539d9SMin Hu (Connor) hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_PTP_MODE, false); 10638b539d9SMin Hu (Connor) 10738b539d9SMin Hu (Connor) req = (struct hns3_ptp_mode_cfg_cmd *)desc.data; 10838b539d9SMin Hu (Connor) 10938b539d9SMin Hu (Connor) val = en ? 1 : 0; 11038b539d9SMin Hu (Connor) hns3_set_bit(req->enable, HNS3_PTP_ENABLE_B, val); 11138b539d9SMin Hu (Connor) hns3_set_bit(req->enable, HNS3_PTP_TX_ENABLE_B, val); 11238b539d9SMin Hu (Connor) hns3_set_bit(req->enable, HNS3_PTP_RX_ENABLE_B, val); 11338b539d9SMin Hu (Connor) 11438b539d9SMin Hu (Connor) if (en) { 11538b539d9SMin Hu (Connor) hns3_set_field(req->ptp_type, HNS3_PTP_TYPE_M, HNS3_PTP_TYPE_S, 11638b539d9SMin Hu (Connor) PTP_TYPE_L2_V2_TYPE); 11738b539d9SMin Hu (Connor) hns3_set_field(req->v2_message_type_1, HNS3_PTP_MESSAGE_TYPE_M, 11838b539d9SMin Hu (Connor) HNS3_PTP_MESSAGE_TYPE_S, ALL_PTP_V2_TYPE); 11938b539d9SMin Hu (Connor) } 12038b539d9SMin Hu (Connor) 12138b539d9SMin Hu (Connor) ret = hns3_cmd_send(hw, &desc, 1); 12238b539d9SMin Hu (Connor) if (ret) { 12338b539d9SMin Hu (Connor) hns3_err(hw, "configure PTP time failed, en = %d, ret = %d", 12438b539d9SMin Hu (Connor) en, ret); 12538b539d9SMin Hu (Connor) return ret; 12638b539d9SMin Hu (Connor) } 12738b539d9SMin Hu (Connor) 12838b539d9SMin Hu (Connor) pf->ptp_enable = en; 12938b539d9SMin Hu (Connor) 13038b539d9SMin Hu (Connor) return 0; 13138b539d9SMin Hu (Connor) } 13238b539d9SMin Hu (Connor) 13338b539d9SMin Hu (Connor) int 13438b539d9SMin Hu (Connor) hns3_timesync_enable(struct rte_eth_dev *dev) 13538b539d9SMin Hu (Connor) { 13638b539d9SMin Hu (Connor) struct hns3_adapter *hns = dev->data->dev_private; 13738b539d9SMin Hu (Connor) struct hns3_hw *hw = &hns->hw; 13838b539d9SMin Hu (Connor) struct hns3_pf *pf = &hns->pf; 13938b539d9SMin Hu (Connor) int ret; 14038b539d9SMin Hu (Connor) 141efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 14238b539d9SMin Hu (Connor) return -ENOTSUP; 14338b539d9SMin Hu (Connor) 14438b539d9SMin Hu (Connor) if (pf->ptp_enable) 14538b539d9SMin Hu (Connor) return 0; 14638b539d9SMin Hu (Connor) 14738b539d9SMin Hu (Connor) rte_spinlock_lock(&hw->lock); 14838b539d9SMin Hu (Connor) ret = hns3_timesync_configure(hns, true); 14938b539d9SMin Hu (Connor) rte_spinlock_unlock(&hw->lock); 15038b539d9SMin Hu (Connor) return ret; 15138b539d9SMin Hu (Connor) } 15238b539d9SMin Hu (Connor) 15338b539d9SMin Hu (Connor) int 15438b539d9SMin Hu (Connor) hns3_timesync_disable(struct rte_eth_dev *dev) 15538b539d9SMin Hu (Connor) { 15638b539d9SMin Hu (Connor) struct hns3_adapter *hns = dev->data->dev_private; 15738b539d9SMin Hu (Connor) struct hns3_hw *hw = &hns->hw; 15838b539d9SMin Hu (Connor) struct hns3_pf *pf = &hns->pf; 15938b539d9SMin Hu (Connor) int ret; 16038b539d9SMin Hu (Connor) 161efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 16238b539d9SMin Hu (Connor) return -ENOTSUP; 16338b539d9SMin Hu (Connor) 16438b539d9SMin Hu (Connor) if (!pf->ptp_enable) 16538b539d9SMin Hu (Connor) return 0; 16638b539d9SMin Hu (Connor) 16738b539d9SMin Hu (Connor) rte_spinlock_lock(&hw->lock); 16838b539d9SMin Hu (Connor) ret = hns3_timesync_configure(hns, false); 16938b539d9SMin Hu (Connor) rte_spinlock_unlock(&hw->lock); 17038b539d9SMin Hu (Connor) 17138b539d9SMin Hu (Connor) return ret; 17238b539d9SMin Hu (Connor) } 17338b539d9SMin Hu (Connor) 17438b539d9SMin Hu (Connor) int 17538b539d9SMin Hu (Connor) hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev, 17638b539d9SMin Hu (Connor) struct timespec *timestamp, 17738b539d9SMin Hu (Connor) uint32_t flags __rte_unused) 17838b539d9SMin Hu (Connor) { 17938b539d9SMin Hu (Connor) #define TIME_RX_STAMP_NS_MASK 0x3FFFFFFF 18038b539d9SMin Hu (Connor) struct hns3_adapter *hns = dev->data->dev_private; 18138b539d9SMin Hu (Connor) struct hns3_hw *hw = &hns->hw; 18238b539d9SMin Hu (Connor) struct hns3_pf *pf = &hns->pf; 18338b539d9SMin Hu (Connor) uint64_t ns, sec; 18438b539d9SMin Hu (Connor) 185efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 18638b539d9SMin Hu (Connor) return -ENOTSUP; 18738b539d9SMin Hu (Connor) 18838b539d9SMin Hu (Connor) ns = pf->rx_timestamp & TIME_RX_STAMP_NS_MASK; 18938b539d9SMin Hu (Connor) sec = upper_32_bits(pf->rx_timestamp); 19038b539d9SMin Hu (Connor) 19138b539d9SMin Hu (Connor) ns += sec * NSEC_PER_SEC; 19238b539d9SMin Hu (Connor) *timestamp = rte_ns_to_timespec(ns); 19338b539d9SMin Hu (Connor) 19438b539d9SMin Hu (Connor) return 0; 19538b539d9SMin Hu (Connor) } 19638b539d9SMin Hu (Connor) 19738b539d9SMin Hu (Connor) int 19838b539d9SMin Hu (Connor) hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev, 19938b539d9SMin Hu (Connor) struct timespec *timestamp) 20038b539d9SMin Hu (Connor) { 20138b539d9SMin Hu (Connor) #define TIME_TX_STAMP_NS_MASK 0x3FFFFFFF 20238b539d9SMin Hu (Connor) #define TIME_TX_STAMP_VALID 24 20338b539d9SMin Hu (Connor) #define TIME_TX_STAMP_CNT_MASK 0x7 20438b539d9SMin Hu (Connor) struct hns3_adapter *hns = dev->data->dev_private; 20538b539d9SMin Hu (Connor) struct hns3_hw *hw = &hns->hw; 20638b539d9SMin Hu (Connor) uint64_t sec; 20738b539d9SMin Hu (Connor) uint64_t tmp; 20838b539d9SMin Hu (Connor) uint64_t ns; 20938b539d9SMin Hu (Connor) int ts_cnt; 21038b539d9SMin Hu (Connor) 211efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 21238b539d9SMin Hu (Connor) return -ENOTSUP; 21338b539d9SMin Hu (Connor) 21438b539d9SMin Hu (Connor) ts_cnt = hns3_read_dev(hw, HNS3_TX_1588_BACK_TSP_CNT) & 21538b539d9SMin Hu (Connor) TIME_TX_STAMP_CNT_MASK; 21638b539d9SMin Hu (Connor) if (ts_cnt == 0) 21738b539d9SMin Hu (Connor) return -EINVAL; 21838b539d9SMin Hu (Connor) 21938b539d9SMin Hu (Connor) ns = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_0) & TIME_TX_STAMP_NS_MASK; 22038b539d9SMin Hu (Connor) sec = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_1); 22138b539d9SMin Hu (Connor) tmp = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_2) & 0xFFFF; 22238b539d9SMin Hu (Connor) sec = (tmp << 32) | sec; 22338b539d9SMin Hu (Connor) 22438b539d9SMin Hu (Connor) ns += sec * NSEC_PER_SEC; 22538b539d9SMin Hu (Connor) 22638b539d9SMin Hu (Connor) *timestamp = rte_ns_to_timespec(ns); 22738b539d9SMin Hu (Connor) 22838b539d9SMin Hu (Connor) /* Clear current timestamp hardware stores */ 22938b539d9SMin Hu (Connor) hns3_read_dev(hw, HNS3_TX_1588_SEQID_BACK); 23038b539d9SMin Hu (Connor) 23138b539d9SMin Hu (Connor) return 0; 23238b539d9SMin Hu (Connor) } 23338b539d9SMin Hu (Connor) 23438b539d9SMin Hu (Connor) int 23538b539d9SMin Hu (Connor) hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts) 23638b539d9SMin Hu (Connor) { 2376170abd5SHuisong Li #define HNS3_PTP_SEC_H_OFFSET 32 2386170abd5SHuisong Li #define HNS3_PTP_SEC_H_MASK 0xFFFF 2396170abd5SHuisong Li 24038b539d9SMin Hu (Connor) struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); 2416170abd5SHuisong Li uint32_t sec_hi, sec_lo; 24238b539d9SMin Hu (Connor) uint64_t ns, sec; 24338b539d9SMin Hu (Connor) 244efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 24538b539d9SMin Hu (Connor) return -ENOTSUP; 24638b539d9SMin Hu (Connor) 24738b539d9SMin Hu (Connor) ns = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_NS); 2486170abd5SHuisong Li sec_hi = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_H) & HNS3_PTP_SEC_H_MASK; 2496170abd5SHuisong Li sec_lo = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_L); 2506170abd5SHuisong Li sec = ((uint64_t)sec_hi << HNS3_PTP_SEC_H_OFFSET) | sec_lo; 2516170abd5SHuisong Li 25238b539d9SMin Hu (Connor) ns += sec * NSEC_PER_SEC; 25338b539d9SMin Hu (Connor) *ts = rte_ns_to_timespec(ns); 25438b539d9SMin Hu (Connor) 25538b539d9SMin Hu (Connor) return 0; 25638b539d9SMin Hu (Connor) } 25738b539d9SMin Hu (Connor) 25838b539d9SMin Hu (Connor) int 25938b539d9SMin Hu (Connor) hns3_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts) 26038b539d9SMin Hu (Connor) { 26138b539d9SMin Hu (Connor) struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); 26238b539d9SMin Hu (Connor) 263efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 26438b539d9SMin Hu (Connor) return -ENOTSUP; 26538b539d9SMin Hu (Connor) 266f901c570SHuisong Li hns3_ptp_timesync_write_time(hw, ts); 26738b539d9SMin Hu (Connor) 26838b539d9SMin Hu (Connor) return 0; 26938b539d9SMin Hu (Connor) } 27038b539d9SMin Hu (Connor) 27138b539d9SMin Hu (Connor) int 27238b539d9SMin Hu (Connor) hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) 27338b539d9SMin Hu (Connor) { 27438b539d9SMin Hu (Connor) #define TIME_SYNC_L_MASK 0x7FFFFFFF 27538b539d9SMin Hu (Connor) #define SYMBOL_BIT_OFFSET 31 27638b539d9SMin Hu (Connor) struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); 27738b539d9SMin Hu (Connor) struct timespec cur_time; 27838b539d9SMin Hu (Connor) uint64_t ns; 27938b539d9SMin Hu (Connor) 280efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 28138b539d9SMin Hu (Connor) return -ENOTSUP; 28238b539d9SMin Hu (Connor) 28338b539d9SMin Hu (Connor) (void)hns3_timesync_read_time(dev, &cur_time); 28438b539d9SMin Hu (Connor) ns = rte_timespec_to_ns((const struct timespec *)&cur_time); 28538b539d9SMin Hu (Connor) cur_time = rte_ns_to_timespec(ns + delta); 28638b539d9SMin Hu (Connor) (void)hns3_timesync_write_time(dev, (const struct timespec *)&cur_time); 28738b539d9SMin Hu (Connor) 28838b539d9SMin Hu (Connor) return 0; 28938b539d9SMin Hu (Connor) } 29038b539d9SMin Hu (Connor) 29138b539d9SMin Hu (Connor) int 29238b539d9SMin Hu (Connor) hns3_restore_ptp(struct hns3_adapter *hns) 29338b539d9SMin Hu (Connor) { 29438b539d9SMin Hu (Connor) struct hns3_pf *pf = &hns->pf; 29538b539d9SMin Hu (Connor) struct hns3_hw *hw = &hns->hw; 29638b539d9SMin Hu (Connor) bool en = pf->ptp_enable; 29738b539d9SMin Hu (Connor) int ret; 29838b539d9SMin Hu (Connor) 299efcaa81eSChengchang Tang if (!hns3_dev_get_support(hw, PTP)) 30038b539d9SMin Hu (Connor) return 0; 30138b539d9SMin Hu (Connor) 30238b539d9SMin Hu (Connor) ret = hns3_timesync_configure(hns, en); 30338b539d9SMin Hu (Connor) if (ret) 30438b539d9SMin Hu (Connor) hns3_err(hw, "restore PTP enable state(%d) failed, ret = %d", 30538b539d9SMin Hu (Connor) en, ret); 30638b539d9SMin Hu (Connor) 30738b539d9SMin Hu (Connor) return ret; 30838b539d9SMin Hu (Connor) } 309bfd20b33SHuisong Li 310bfd20b33SHuisong Li void 311bfd20b33SHuisong Li hns3_ptp_uninit(struct hns3_hw *hw) 312bfd20b33SHuisong Li { 313bfd20b33SHuisong Li struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); 314bfd20b33SHuisong Li int ret; 315bfd20b33SHuisong Li 316bfd20b33SHuisong Li if (!hns3_dev_get_support(hw, PTP)) 317bfd20b33SHuisong Li return; 318bfd20b33SHuisong Li 319bfd20b33SHuisong Li ret = hns3_ptp_int_en(hw, false); 320bfd20b33SHuisong Li if (ret != 0) 321bfd20b33SHuisong Li hns3_err(hw, "disable PTP interrupt failed, ret = %d.", ret); 322bfd20b33SHuisong Li 323bfd20b33SHuisong Li ret = hns3_timesync_configure(hns, false); 324bfd20b33SHuisong Li if (ret != 0) 325bfd20b33SHuisong Li hns3_err(hw, "disable timesync failed, ret = %d.", ret); 326bfd20b33SHuisong Li } 327