net/octeontx2: add remaining PTP operations
[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         return rc;
123 }
124
125 int
126 otx2_nix_timesync_disable(struct rte_eth_dev *eth_dev)
127 {
128         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
129         int i, rc = 0;
130
131         if (!otx2_ethdev_is_ptp_en(dev)) {
132                 otx2_nix_dbg("PTP mode is disabled");
133                 return -EINVAL;
134         }
135
136         /* If we are VF, nothing else can be done */
137         if (otx2_dev_is_vf(dev))
138                 return -EINVAL;
139
140         dev->rx_offloads &= ~DEV_RX_OFFLOAD_TIMESTAMP;
141         dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_TSTAMP_F;
142         dev->tx_offload_flags &= ~NIX_TX_OFFLOAD_TSTAMP_F;
143
144         rc = nix_ptp_config(eth_dev, 0);
145         if (!rc) {
146                 for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
147                         struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
148                         otx2_nix_form_default_desc(txq);
149                 }
150         }
151         return rc;
152 }
153
154 int
155 otx2_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
156                                     struct timespec *timestamp,
157                                     uint32_t __rte_unused flags)
158 {
159         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
160         struct otx2_timesync_info *tstamp = &dev->tstamp;
161         uint64_t ns;
162
163         if (!tstamp->rx_ready)
164                 return -EINVAL;
165
166         ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
167         *timestamp = rte_ns_to_timespec(ns);
168         tstamp->rx_ready = 0;
169
170         otx2_nix_dbg("rx timestamp: %llu sec: %lu nsec %lu",
171                      (unsigned long long)tstamp->rx_tstamp, timestamp->tv_sec,
172                      timestamp->tv_nsec);
173
174         return 0;
175 }
176
177 int
178 otx2_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
179                                     struct timespec *timestamp)
180 {
181         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
182         struct otx2_timesync_info *tstamp = &dev->tstamp;
183         uint64_t ns;
184
185         if (*tstamp->tx_tstamp == 0)
186                 return -EINVAL;
187
188         ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
189         *timestamp = rte_ns_to_timespec(ns);
190
191         otx2_nix_dbg("tx timestamp: %llu sec: %lu nsec %lu",
192                      *(unsigned long long *)tstamp->tx_tstamp,
193                      timestamp->tv_sec, timestamp->tv_nsec);
194
195         *tstamp->tx_tstamp = 0;
196         rte_wmb();
197
198         return 0;
199 }
200
201 int
202 otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
203 {
204         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
205         struct otx2_mbox *mbox = dev->mbox;
206         struct ptp_req *req;
207         struct ptp_rsp *rsp;
208         int rc;
209
210         /* Adjust the frequent to make tics increments in 10^9 tics per sec */
211         if (delta < PTP_FREQ_ADJUST && delta > -PTP_FREQ_ADJUST) {
212                 req = otx2_mbox_alloc_msg_ptp_op(mbox);
213                 req->op = PTP_OP_ADJFINE;
214                 req->scaled_ppm = delta;
215
216                 rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
217                 if (rc)
218                         return rc;
219         }
220         dev->systime_tc.nsec += delta;
221         dev->rx_tstamp_tc.nsec += delta;
222         dev->tx_tstamp_tc.nsec += delta;
223
224         return 0;
225 }
226
227 int
228 otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
229                              const struct timespec *ts)
230 {
231         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
232         uint64_t ns;
233
234         ns = rte_timespec_to_ns(ts);
235         /* Set the time counters to a new value. */
236         dev->systime_tc.nsec = ns;
237         dev->rx_tstamp_tc.nsec = ns;
238         dev->tx_tstamp_tc.nsec = ns;
239
240         return 0;
241 }
242
243 int
244 otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
245 {
246         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
247         struct otx2_mbox *mbox = dev->mbox;
248         struct ptp_req *req;
249         struct ptp_rsp *rsp;
250         uint64_t ns;
251         int rc;
252
253         req = otx2_mbox_alloc_msg_ptp_op(mbox);
254         req->op = PTP_OP_GET_CLOCK;
255         rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
256         if (rc)
257                 return rc;
258
259         ns = rte_timecounter_update(&dev->systime_tc, rsp->clk);
260         *ts = rte_ns_to_timespec(ns);
261
262         otx2_nix_dbg("PTP time read: %ld.%09ld", ts->tv_sec, ts->tv_nsec);
263
264         return 0;
265 }