fc31796502123afa74c118499515e12ebc9f710d
[dpdk.git] / drivers / net / cnxk / cnxk_ptp.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "cnxk_ethdev.h"
6
7 /* This function calculates two parameters "clk_freq_mult" and
8  * "clk_delta" which is useful in deriving PTP HI clock from
9  * timestamp counter (tsc) value.
10  */
11 int
12 cnxk_nix_tsc_convert(struct cnxk_eth_dev *dev)
13 {
14         uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
15         struct roc_nix *nix = &dev->nix;
16         int rc, val;
17
18         /* Calculating the frequency at which PTP HI clock is running */
19         rc = roc_nix_ptp_clock_read(nix, &ticks_base, &tsc, false);
20         if (rc) {
21                 plt_err("Failed to read the raw clock value: %d", rc);
22                 goto fail;
23         }
24
25         rte_delay_ms(100);
26
27         rc = roc_nix_ptp_clock_read(nix, &ticks, &tsc, false);
28         if (rc) {
29                 plt_err("Failed to read the raw clock value: %d", rc);
30                 goto fail;
31         }
32
33         t_freq = (ticks - ticks_base) * 10;
34
35         /* Calculating the freq multiplier viz the ratio between the
36          * frequency at which PTP HI clock works and tsc clock runs
37          */
38         dev->clk_freq_mult =
39                 (double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
40
41         val = false;
42 #ifdef RTE_ARM_EAL_RDTSC_USE_PMU
43         val = true;
44 #endif
45         rc = roc_nix_ptp_clock_read(nix, &ticks, &tsc, val);
46         if (rc) {
47                 plt_err("Failed to read the raw clock value: %d", rc);
48                 goto fail;
49         }
50
51         /* Calculating delta between PTP HI clock and tsc */
52         dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
53
54 fail:
55         return rc;
56 }
57
58 int
59 cnxk_nix_timesync_enable(struct rte_eth_dev *eth_dev)
60 {
61         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
62         struct cnxk_timesync_info *tstamp = &dev->tstamp;
63         struct roc_nix *nix = &dev->nix;
64         const struct rte_memzone *ts;
65         int rc = 0;
66
67         /* If we are VF/SDP/LBK, ptp cannot not be enabled */
68         if (roc_nix_is_vf_or_sdp(nix) || roc_nix_is_lbk(nix)) {
69                 plt_err("PTP cannot be enabled for VF/SDP/LBK");
70                 return -EINVAL;
71         }
72
73         if (dev->ptp_en)
74                 return rc;
75
76         if (dev->ptype_disable) {
77                 plt_err("Ptype offload is disabled, it should be enabled");
78                 return -EINVAL;
79         }
80
81         if (dev->npc.switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
82                 plt_err("Both PTP and switch header cannot be enabled");
83                 return -EINVAL;
84         }
85
86         /* Allocating a iova address for tx tstamp */
87         ts = rte_eth_dma_zone_reserve(eth_dev, "cnxk_ts", 0, 128, 128, 0);
88         if (ts == NULL) {
89                 plt_err("Failed to allocate mem for tx tstamp addr");
90                 return -ENOMEM;
91         }
92
93         tstamp->tx_tstamp_iova = ts->iova;
94         tstamp->tx_tstamp = ts->addr;
95
96         rc = rte_mbuf_dyn_rx_timestamp_register(&tstamp->tstamp_dynfield_offset,
97                                                 &tstamp->rx_tstamp_dynflag);
98         if (rc) {
99                 plt_err("Failed to register Rx timestamp field/flag");
100                 goto error;
101         }
102
103         /* System time should be already on by default */
104         memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
105         memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
106         memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
107
108         dev->systime_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
109         dev->rx_tstamp_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
110         dev->tx_tstamp_tc.cc_mask = CNXK_CYCLECOUNTER_MASK;
111
112         dev->rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
113
114         rc = roc_nix_ptp_rx_ena_dis(nix, true);
115         if (!rc) {
116                 rc = roc_nix_ptp_tx_ena_dis(nix, true);
117                 if (rc) {
118                         roc_nix_ptp_rx_ena_dis(nix, false);
119                         goto error;
120                 }
121         }
122
123         rc = nix_recalc_mtu(eth_dev);
124         if (rc) {
125                 plt_err("Failed to set MTU size for ptp");
126                 goto error;
127         }
128
129         return rc;
130
131 error:
132         rte_eth_dma_zone_free(eth_dev, "cnxk_ts", 0);
133         dev->tstamp.tx_tstamp_iova = 0;
134         dev->tstamp.tx_tstamp = NULL;
135         return rc;
136 }
137
138 int
139 cnxk_nix_timesync_disable(struct rte_eth_dev *eth_dev)
140 {
141         struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
142         uint64_t rx_offloads = DEV_RX_OFFLOAD_TIMESTAMP;
143         struct roc_nix *nix = &dev->nix;
144         int rc = 0;
145
146         /* If we are VF/SDP/LBK, ptp cannot not be disabled */
147         if (roc_nix_is_vf_or_sdp(nix) || roc_nix_is_lbk(nix))
148                 return -EINVAL;
149
150         if (!dev->ptp_en)
151                 return rc;
152
153         dev->rx_offloads &= ~rx_offloads;
154
155         rc = roc_nix_ptp_rx_ena_dis(nix, false);
156         if (!rc) {
157                 rc = roc_nix_ptp_tx_ena_dis(nix, false);
158                 if (rc) {
159                         roc_nix_ptp_rx_ena_dis(nix, true);
160                         return rc;
161                 }
162         }
163
164         rc = nix_recalc_mtu(eth_dev);
165         if (rc)
166                 plt_err("Failed to set MTU size for ptp");
167
168         return rc;
169 }