xref: /dpdk/drivers/net/hns3/hns3_ptp.c (revision 3ca3dcd6)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021-2021 Hisilicon Limited.
3  */
4 
5 #include <ethdev_pci.h>
6 #include <rte_io.h>
7 #include <rte_time.h>
8 
9 #include "hns3_ethdev.h"
10 #include "hns3_regs.h"
11 #include "hns3_logs.h"
12 
13 uint64_t hns3_timestamp_rx_dynflag;
14 int hns3_timestamp_dynfield_offset = -1;
15 
16 int
hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev * dev,struct rte_eth_conf * conf)17 hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
18 				    struct rte_eth_conf *conf)
19 {
20 	struct hns3_adapter *hns = dev->data->dev_private;
21 	struct hns3_hw *hw = &hns->hw;
22 	int ret;
23 
24 	if (!(conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP))
25 		return 0;
26 
27 	ret = rte_mbuf_dyn_rx_timestamp_register
28 			(&hns3_timestamp_dynfield_offset,
29 			 &hns3_timestamp_rx_dynflag);
30 	if (ret) {
31 		hns3_err(hw,
32 			"failed to register Rx timestamp field/flag");
33 		return ret;
34 	}
35 
36 	return 0;
37 }
38 
39 static int
hns3_ptp_int_en(struct hns3_hw * hw,bool en)40 hns3_ptp_int_en(struct hns3_hw *hw, bool en)
41 {
42 	struct hns3_ptp_int_cmd *req;
43 	struct hns3_cmd_desc desc;
44 	int ret;
45 
46 	req = (struct hns3_ptp_int_cmd *)desc.data;
47 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_PTP_INT_EN, false);
48 	req->int_en = en ? 1 : 0;
49 
50 	ret = hns3_cmd_send(hw, &desc, 1);
51 	if (ret)
52 		hns3_err(hw,
53 			"failed to %s ptp interrupt, ret = %d\n",
54 			en ? "enable" : "disable", ret);
55 
56 	return ret;
57 }
58 
59 int
hns3_ptp_init(struct hns3_hw * hw)60 hns3_ptp_init(struct hns3_hw *hw)
61 {
62 	int ret;
63 
64 	if (!hns3_dev_get_support(hw, PTP))
65 		return 0;
66 
67 	ret = hns3_ptp_int_en(hw, true);
68 	if (ret)
69 		return ret;
70 
71 	/* Start PTP timer */
72 	hns3_write_dev(hw, HNS3_CFG_TIME_CYC_EN, 1);
73 
74 	return 0;
75 }
76 
77 static int
hns3_timesync_configure(struct hns3_adapter * hns,bool en)78 hns3_timesync_configure(struct hns3_adapter *hns, bool en)
79 {
80 	struct hns3_ptp_mode_cfg_cmd *req;
81 	struct hns3_hw *hw = &hns->hw;
82 	struct hns3_pf *pf = &hns->pf;
83 	struct hns3_cmd_desc desc;
84 	int val;
85 	int ret;
86 
87 	hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_PTP_MODE, false);
88 
89 	req = (struct hns3_ptp_mode_cfg_cmd *)desc.data;
90 
91 	val = en ? 1 : 0;
92 	hns3_set_bit(req->enable, HNS3_PTP_ENABLE_B, val);
93 	hns3_set_bit(req->enable, HNS3_PTP_TX_ENABLE_B, val);
94 	hns3_set_bit(req->enable, HNS3_PTP_RX_ENABLE_B, val);
95 
96 	if (en) {
97 		hns3_set_field(req->ptp_type, HNS3_PTP_TYPE_M, HNS3_PTP_TYPE_S,
98 			       PTP_TYPE_L2_V2_TYPE);
99 		hns3_set_field(req->v2_message_type_1, HNS3_PTP_MESSAGE_TYPE_M,
100 			       HNS3_PTP_MESSAGE_TYPE_S, ALL_PTP_V2_TYPE);
101 	}
102 
103 	ret = hns3_cmd_send(hw, &desc, 1);
104 	if (ret) {
105 		hns3_err(hw, "configure PTP time failed, en = %d, ret = %d",
106 			 en, ret);
107 		return ret;
108 	}
109 
110 	pf->ptp_enable = en;
111 
112 	return 0;
113 }
114 
115 int
hns3_timesync_enable(struct rte_eth_dev * dev)116 hns3_timesync_enable(struct rte_eth_dev *dev)
117 {
118 	struct hns3_adapter *hns = dev->data->dev_private;
119 	struct hns3_hw *hw = &hns->hw;
120 	struct hns3_pf *pf = &hns->pf;
121 	int ret;
122 
123 	if (!hns3_dev_get_support(hw, PTP))
124 		return -ENOTSUP;
125 
126 	if (pf->ptp_enable)
127 		return 0;
128 	hns3_warn(hw, "note: please ensure Rx/Tx burst mode is simple or common when enabling PTP!");
129 
130 	rte_spinlock_lock(&hw->lock);
131 	ret = hns3_timesync_configure(hns, true);
132 	rte_spinlock_unlock(&hw->lock);
133 	return ret;
134 }
135 
136 int
hns3_timesync_disable(struct rte_eth_dev * dev)137 hns3_timesync_disable(struct rte_eth_dev *dev)
138 {
139 	struct hns3_adapter *hns = dev->data->dev_private;
140 	struct hns3_hw *hw = &hns->hw;
141 	struct hns3_pf *pf = &hns->pf;
142 	int ret;
143 
144 	if (!hns3_dev_get_support(hw, PTP))
145 		return -ENOTSUP;
146 
147 	if (!pf->ptp_enable)
148 		return 0;
149 
150 	rte_spinlock_lock(&hw->lock);
151 	ret = hns3_timesync_configure(hns, false);
152 	rte_spinlock_unlock(&hw->lock);
153 
154 	return ret;
155 }
156 
157 int
hns3_timesync_read_rx_timestamp(struct rte_eth_dev * dev,struct timespec * timestamp,uint32_t flags __rte_unused)158 hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
159 				struct timespec *timestamp,
160 				uint32_t flags __rte_unused)
161 {
162 #define TIME_RX_STAMP_NS_MASK 0x3FFFFFFF
163 	struct hns3_adapter *hns = dev->data->dev_private;
164 	struct hns3_hw *hw = &hns->hw;
165 	struct hns3_pf *pf = &hns->pf;
166 	uint64_t ns, sec;
167 
168 	if (!hns3_dev_get_support(hw, PTP))
169 		return -ENOTSUP;
170 
171 	ns = pf->rx_timestamp & TIME_RX_STAMP_NS_MASK;
172 	sec = upper_32_bits(pf->rx_timestamp);
173 
174 	ns += sec * NSEC_PER_SEC;
175 	*timestamp = rte_ns_to_timespec(ns);
176 
177 	return 0;
178 }
179 
180 int
hns3_timesync_read_tx_timestamp(struct rte_eth_dev * dev,struct timespec * timestamp)181 hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
182 				struct timespec *timestamp)
183 {
184 #define TIME_TX_STAMP_NS_MASK 0x3FFFFFFF
185 #define TIME_TX_STAMP_VALID   24
186 #define TIME_TX_STAMP_CNT_MASK 0x7
187 	struct hns3_adapter *hns = dev->data->dev_private;
188 	struct hns3_hw *hw = &hns->hw;
189 	uint64_t sec;
190 	uint64_t tmp;
191 	uint64_t ns;
192 	int ts_cnt;
193 
194 	if (!hns3_dev_get_support(hw, PTP))
195 		return -ENOTSUP;
196 
197 	ts_cnt = hns3_read_dev(hw, HNS3_TX_1588_BACK_TSP_CNT) &
198 			TIME_TX_STAMP_CNT_MASK;
199 	if (ts_cnt == 0)
200 		return -EINVAL;
201 
202 	ns = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_0) & TIME_TX_STAMP_NS_MASK;
203 	sec = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_1);
204 	tmp = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_2) & 0xFFFF;
205 	sec = (tmp << 32) | sec;
206 
207 	ns += sec * NSEC_PER_SEC;
208 
209 	*timestamp = rte_ns_to_timespec(ns);
210 
211 	/* Clear current timestamp hardware stores */
212 	hns3_read_dev(hw, HNS3_TX_1588_SEQID_BACK);
213 
214 	return 0;
215 }
216 
217 int
hns3_timesync_read_time(struct rte_eth_dev * dev,struct timespec * ts)218 hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
219 {
220 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
221 	uint64_t ns, sec;
222 
223 	if (!hns3_dev_get_support(hw, PTP))
224 		return -ENOTSUP;
225 
226 	sec = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_L);
227 	sec |= (uint64_t)(hns3_read_dev(hw, HNS3_CURR_TIME_OUT_H) & 0xFFFF)
228 		<< 32;
229 
230 	ns = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_NS);
231 	ns += sec * NSEC_PER_SEC;
232 	*ts = rte_ns_to_timespec(ns);
233 
234 	return 0;
235 }
236 
237 int
hns3_timesync_write_time(struct rte_eth_dev * dev,const struct timespec * ts)238 hns3_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
239 {
240 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
241 	uint64_t sec = ts->tv_sec;
242 	uint64_t ns = ts->tv_nsec;
243 
244 	if (!hns3_dev_get_support(hw, PTP))
245 		return -ENOTSUP;
246 
247 	/* Set the timecounters to a new value. */
248 	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_H, upper_32_bits(sec));
249 	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_M, lower_32_bits(sec));
250 	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_L, lower_32_bits(ns));
251 	hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_RDY, 1);
252 
253 	return 0;
254 }
255 
256 int
hns3_timesync_adjust_time(struct rte_eth_dev * dev,int64_t delta)257 hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
258 {
259 #define TIME_SYNC_L_MASK 0x7FFFFFFF
260 #define SYMBOL_BIT_OFFSET 31
261 	struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
262 	struct timespec cur_time;
263 	uint64_t ns;
264 
265 	if (!hns3_dev_get_support(hw, PTP))
266 		return -ENOTSUP;
267 
268 	(void)hns3_timesync_read_time(dev, &cur_time);
269 	ns = rte_timespec_to_ns((const struct timespec *)&cur_time);
270 	cur_time = rte_ns_to_timespec(ns + delta);
271 	(void)hns3_timesync_write_time(dev, (const struct timespec *)&cur_time);
272 
273 	return 0;
274 }
275 
276 int
hns3_restore_ptp(struct hns3_adapter * hns)277 hns3_restore_ptp(struct hns3_adapter *hns)
278 {
279 	struct hns3_pf *pf = &hns->pf;
280 	struct hns3_hw *hw = &hns->hw;
281 	bool en = pf->ptp_enable;
282 	int ret;
283 
284 	if (!hns3_dev_get_support(hw, PTP))
285 		return 0;
286 
287 	ret = hns3_timesync_configure(hns, en);
288 	if (ret)
289 		hns3_err(hw, "restore PTP enable state(%d) failed, ret = %d",
290 			 en, ret);
291 
292 	return ret;
293 }
294