0186c629a2ef889bc1bae19a22db60155791ec6e
[dpdk.git] / drivers / net / octeontx2 / otx2_ptp.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_ethdev_driver.h>
6
7 #include "otx2_ethdev.h"
8
9 #define PTP_FREQ_ADJUST (1 << 9)
10
11 static void
12 nix_start_timecounters(struct rte_eth_dev *eth_dev)
13 {
14         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
15
16         memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
17         memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
18         memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
19
20         dev->systime_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
21         dev->rx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
22         dev->tx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
23 }
24
25 static int
26 nix_ptp_config(struct rte_eth_dev *eth_dev, int en)
27 {
28         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
29         struct otx2_mbox *mbox = dev->mbox;
30         uint8_t rc = 0;
31
32         if (otx2_dev_is_vf(dev))
33                 return rc;
34
35         if (en) {
36                 /* Enable time stamping of sent PTP packets. */
37                 otx2_mbox_alloc_msg_nix_lf_ptp_tx_enable(mbox);
38                 rc = otx2_mbox_process(mbox);
39                 if (rc) {
40                         otx2_err("MBOX ptp tx conf enable failed: err %d", rc);
41                         return rc;
42                 }
43                 /* Enable time stamping of received PTP packets. */
44                 otx2_mbox_alloc_msg_cgx_ptp_rx_enable(mbox);
45         } else {
46                 /* Disable time stamping of sent PTP packets. */
47                 otx2_mbox_alloc_msg_nix_lf_ptp_tx_disable(mbox);
48                 rc = otx2_mbox_process(mbox);
49                 if (rc) {
50                         otx2_err("MBOX ptp tx conf disable failed: err %d", rc);
51                         return rc;
52                 }
53                 /* Disable time stamping of received PTP packets. */
54                 otx2_mbox_alloc_msg_cgx_ptp_rx_disable(mbox);
55         }
56
57         return otx2_mbox_process(mbox);
58 }
59
60 int
61 otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en)
62 {
63         struct otx2_eth_dev *otx2_dev = (struct otx2_eth_dev *)dev;
64         struct rte_eth_dev *eth_dev = otx2_dev->eth_dev;
65         int i;
66
67         otx2_dev->ptp_en = ptp_en;
68         for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
69                 struct otx2_eth_rxq *rxq = eth_dev->data->rx_queues[i];
70                 rxq->mbuf_initializer =
71                         otx2_nix_rxq_mbuf_setup(otx2_dev,
72                                                 eth_dev->data->port_id);
73         }
74         return 0;
75 }
76
77 int
78 otx2_nix_timesync_enable(struct rte_eth_dev *eth_dev)
79 {
80         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
81         int i, rc = 0;
82
83         if (otx2_ethdev_is_ptp_en(dev)) {
84                 otx2_info("PTP mode is already enabled ");
85                 return -EINVAL;
86         }
87
88         /* If we are VF, no further action can be taken */
89         if (otx2_dev_is_vf(dev))
90                 return -EINVAL;
91
92         if (!(dev->rx_offload_flags & NIX_RX_OFFLOAD_PTYPE_F)) {
93                 otx2_err("Ptype offload is disabled, it should be enabled");
94                 return -EINVAL;
95         }
96
97         /* Allocating a iova address for tx tstamp */
98         const struct rte_memzone *ts;
99         ts = rte_eth_dma_zone_reserve(eth_dev, "otx2_ts",
100                                       0, OTX2_ALIGN, OTX2_ALIGN,
101                                       dev->node);
102         if (ts == NULL)
103                 otx2_err("Failed to allocate mem for tx tstamp addr");
104
105         dev->tstamp.tx_tstamp_iova = ts->iova;
106         dev->tstamp.tx_tstamp = ts->addr;
107
108         /* System time should be already on by default */
109         nix_start_timecounters(eth_dev);
110
111         dev->rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
112         dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
113         dev->tx_offload_flags |= NIX_TX_OFFLOAD_TSTAMP_F;
114
115         rc = nix_ptp_config(eth_dev, 1);
116         if (!rc) {
117                 for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
118                         struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
119                         otx2_nix_form_default_desc(txq);
120                 }
121
122                 /* Setting up the function pointers as per new offload flags */
123                 otx2_eth_set_rx_function(eth_dev);
124                 otx2_eth_set_tx_function(eth_dev);
125         }
126         return rc;
127 }
128
129 int
130 otx2_nix_timesync_disable(struct rte_eth_dev *eth_dev)
131 {
132         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
133         int i, rc = 0;
134
135         if (!otx2_ethdev_is_ptp_en(dev)) {
136                 otx2_nix_dbg("PTP mode is disabled");
137                 return -EINVAL;
138         }
139
140         /* If we are VF, nothing else can be done */
141         if (otx2_dev_is_vf(dev))
142                 return -EINVAL;
143
144         dev->rx_offloads &= ~DEV_RX_OFFLOAD_TIMESTAMP;
145         dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_TSTAMP_F;
146         dev->tx_offload_flags &= ~NIX_TX_OFFLOAD_TSTAMP_F;
147
148         rc = nix_ptp_config(eth_dev, 0);
149         if (!rc) {
150                 for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
151                         struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
152                         otx2_nix_form_default_desc(txq);
153                 }
154
155                 /* Setting up the function pointers as per new offload flags */
156                 otx2_eth_set_rx_function(eth_dev);
157                 otx2_eth_set_tx_function(eth_dev);
158         }
159         return rc;
160 }
161
162 int
163 otx2_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
164                                     struct timespec *timestamp,
165                                     uint32_t __rte_unused flags)
166 {
167         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
168         struct otx2_timesync_info *tstamp = &dev->tstamp;
169         uint64_t ns;
170
171         if (!tstamp->rx_ready)
172                 return -EINVAL;
173
174         ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
175         *timestamp = rte_ns_to_timespec(ns);
176         tstamp->rx_ready = 0;
177
178         otx2_nix_dbg("rx timestamp: %llu sec: %lu nsec %lu",
179                      (unsigned long long)tstamp->rx_tstamp, timestamp->tv_sec,
180                      timestamp->tv_nsec);
181
182         return 0;
183 }
184
185 int
186 otx2_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
187                                     struct timespec *timestamp)
188 {
189         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
190         struct otx2_timesync_info *tstamp = &dev->tstamp;
191         uint64_t ns;
192
193         if (*tstamp->tx_tstamp == 0)
194                 return -EINVAL;
195
196         ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
197         *timestamp = rte_ns_to_timespec(ns);
198
199         otx2_nix_dbg("tx timestamp: %llu sec: %lu nsec %lu",
200                      *(unsigned long long *)tstamp->tx_tstamp,
201                      timestamp->tv_sec, timestamp->tv_nsec);
202
203         *tstamp->tx_tstamp = 0;
204         rte_wmb();
205
206         return 0;
207 }
208
209 int
210 otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
211 {
212         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
213         struct otx2_mbox *mbox = dev->mbox;
214         struct ptp_req *req;
215         struct ptp_rsp *rsp;
216         int rc;
217
218         /* Adjust the frequent to make tics increments in 10^9 tics per sec */
219         if (delta < PTP_FREQ_ADJUST && delta > -PTP_FREQ_ADJUST) {
220                 req = otx2_mbox_alloc_msg_ptp_op(mbox);
221                 req->op = PTP_OP_ADJFINE;
222                 req->scaled_ppm = delta;
223
224                 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
225                 if (rc)
226                         return rc;
227         }
228         dev->systime_tc.nsec += delta;
229         dev->rx_tstamp_tc.nsec += delta;
230         dev->tx_tstamp_tc.nsec += delta;
231
232         return 0;
233 }
234
235 int
236 otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
237                              const struct timespec *ts)
238 {
239         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
240         uint64_t ns;
241
242         ns = rte_timespec_to_ns(ts);
243         /* Set the time counters to a new value. */
244         dev->systime_tc.nsec = ns;
245         dev->rx_tstamp_tc.nsec = ns;
246         dev->tx_tstamp_tc.nsec = ns;
247
248         return 0;
249 }
250
251 int
252 otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
253 {
254         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
255         struct otx2_mbox *mbox = dev->mbox;
256         struct ptp_req *req;
257         struct ptp_rsp *rsp;
258         uint64_t ns;
259         int rc;
260
261         req = otx2_mbox_alloc_msg_ptp_op(mbox);
262         req->op = PTP_OP_GET_CLOCK;
263         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
264         if (rc)
265                 return rc;
266
267         ns = rte_timecounter_update(&dev->systime_tc, rsp->clk);
268         *ts = rte_ns_to_timespec(ns);
269
270         otx2_nix_dbg("PTP time read: %ld.%09ld", ts->tv_sec, ts->tv_nsec);
271
272         return 0;
273 }