common/cnxk: support TIM device
[dpdk.git] / drivers / common / cnxk / roc_tim.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 static void
9 tim_err_desc(int rc)
10 {
11         switch (rc) {
12         case TIM_AF_NO_RINGS_LEFT:
13                 plt_err("Unable to allocate new TIM ring.");
14                 break;
15         case TIM_AF_INVALID_NPA_PF_FUNC:
16                 plt_err("Invalid NPA pf func.");
17                 break;
18         case TIM_AF_INVALID_SSO_PF_FUNC:
19                 plt_err("Invalid SSO pf func.");
20                 break;
21         case TIM_AF_RING_STILL_RUNNING:
22                 plt_err("Ring busy.");
23                 break;
24         case TIM_AF_LF_INVALID:
25                 plt_err("Invalid Ring id.");
26                 break;
27         case TIM_AF_CSIZE_NOT_ALIGNED:
28                 plt_err("Chunk size specified needs to be multiple of 16.");
29                 break;
30         case TIM_AF_CSIZE_TOO_SMALL:
31                 plt_err("Chunk size too small.");
32                 break;
33         case TIM_AF_CSIZE_TOO_BIG:
34                 plt_err("Chunk size too big.");
35                 break;
36         case TIM_AF_INTERVAL_TOO_SMALL:
37                 plt_err("Bucket traversal interval too small.");
38                 break;
39         case TIM_AF_INVALID_BIG_ENDIAN_VALUE:
40                 plt_err("Invalid Big endian value.");
41                 break;
42         case TIM_AF_INVALID_CLOCK_SOURCE:
43                 plt_err("Invalid Clock source specified.");
44                 break;
45         case TIM_AF_GPIO_CLK_SRC_NOT_ENABLED:
46                 plt_err("GPIO clock source not enabled.");
47                 break;
48         case TIM_AF_INVALID_BSIZE:
49                 plt_err("Invalid bucket size.");
50                 break;
51         case TIM_AF_INVALID_ENABLE_PERIODIC:
52                 plt_err("Invalid bucket size.");
53                 break;
54         case TIM_AF_INVALID_ENABLE_DONTFREE:
55                 plt_err("Invalid Don't free value.");
56                 break;
57         case TIM_AF_ENA_DONTFRE_NSET_PERIODIC:
58                 plt_err("Don't free bit not set when periodic is enabled.");
59                 break;
60         case TIM_AF_RING_ALREADY_DISABLED:
61                 plt_err("Ring already stopped");
62                 break;
63         default:
64                 plt_err("Unknown Error.");
65         }
66 }
67
68 int
69 roc_tim_lf_enable(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *start_tsc,
70                   uint32_t *cur_bkt)
71 {
72         struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
73         struct tim_enable_rsp *rsp;
74         struct tim_ring_req *req;
75         int rc = -ENOSPC;
76
77         req = mbox_alloc_msg_tim_enable_ring(dev->mbox);
78         if (req == NULL)
79                 return rc;
80         req->ring = ring_id;
81
82         rc = mbox_process_msg(dev->mbox, (void **)&rsp);
83         if (rc < 0) {
84                 tim_err_desc(rc);
85                 return rc;
86         }
87
88         if (cur_bkt)
89                 *cur_bkt = rsp->currentbucket;
90         if (start_tsc)
91                 *start_tsc = rsp->timestarted;
92
93         return 0;
94 }
95
96 int
97 roc_tim_lf_disable(struct roc_tim *roc_tim, uint8_t ring_id)
98 {
99         struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
100         struct tim_ring_req *req;
101         int rc = -ENOSPC;
102
103         req = mbox_alloc_msg_tim_disable_ring(dev->mbox);
104         if (req == NULL)
105                 return rc;
106         req->ring = ring_id;
107
108         rc = mbox_process(dev->mbox);
109         if (rc < 0) {
110                 tim_err_desc(rc);
111                 return rc;
112         }
113
114         return 0;
115 }
116
117 uintptr_t
118 roc_tim_lf_base_get(struct roc_tim *roc_tim, uint8_t ring_id)
119 {
120         struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
121
122         return dev->bar2 + (RVU_BLOCK_ADDR_TIM << 20 | ring_id << 12);
123 }
124
125 int
126 roc_tim_lf_config(struct roc_tim *roc_tim, uint8_t ring_id,
127                   enum roc_tim_clk_src clk_src, uint8_t ena_periodic,
128                   uint8_t ena_dfb, uint32_t bucket_sz, uint32_t chunk_sz,
129                   uint32_t interval)
130 {
131         struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
132         struct tim_config_req *req;
133         int rc = -ENOSPC;
134
135         req = mbox_alloc_msg_tim_config_ring(dev->mbox);
136         if (req == NULL)
137                 return rc;
138         req->ring = ring_id;
139         req->bigendian = false;
140         req->bucketsize = bucket_sz;
141         req->chunksize = chunk_sz;
142         req->clocksource = clk_src;
143         req->enableperiodic = ena_periodic;
144         req->enabledontfreebuffer = ena_dfb;
145         req->interval = interval;
146         req->gpioedge = TIM_GPIO_LTOH_TRANS;
147
148         rc = mbox_process(dev->mbox);
149         if (rc < 0) {
150                 tim_err_desc(rc);
151                 return rc;
152         }
153
154         return 0;
155 }
156
157 int
158 roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *clk)
159 {
160         struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
161         struct tim_lf_alloc_req *req;
162         struct tim_lf_alloc_rsp *rsp;
163         struct dev *dev = &sso->dev;
164         int rc = -ENOSPC;
165
166         req = mbox_alloc_msg_tim_lf_alloc(dev->mbox);
167         if (req == NULL)
168                 return rc;
169         req->npa_pf_func = idev_npa_pffunc_get();
170         req->sso_pf_func = idev_sso_pffunc_get();
171         req->ring = ring_id;
172
173         rc = mbox_process_msg(dev->mbox, (void **)&rsp);
174         if (rc < 0) {
175                 tim_err_desc(rc);
176                 return rc;
177         }
178
179         if (clk)
180                 *clk = rsp->tenns_clk;
181
182         return rc;
183 }
184
185 int
186 roc_tim_lf_free(struct roc_tim *roc_tim, uint8_t ring_id)
187 {
188         struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
189         struct dev *dev = &sso->dev;
190         struct tim_ring_req *req;
191         int rc = -ENOSPC;
192
193         req = mbox_alloc_msg_tim_lf_free(dev->mbox);
194         if (req == NULL)
195                 return rc;
196         req->ring = ring_id;
197
198         rc = mbox_process(dev->mbox);
199         if (rc < 0) {
200                 tim_err_desc(rc);
201                 return rc;
202         }
203
204         return 0;
205 }
206
207 int
208 roc_tim_init(struct roc_tim *roc_tim)
209 {
210         struct rsrc_attach_req *attach_req;
211         struct free_rsrcs_rsp *free_rsrc;
212         struct dev *dev;
213         uint16_t nb_lfs;
214         int rc;
215
216         if (roc_tim == NULL || roc_tim->roc_sso == NULL)
217                 return TIM_ERR_PARAM;
218
219         PLT_STATIC_ASSERT(sizeof(struct tim) <= TIM_MEM_SZ);
220         dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
221         nb_lfs = roc_tim->nb_lfs;
222         mbox_alloc_msg_free_rsrc_cnt(dev->mbox);
223         rc = mbox_process_msg(dev->mbox, (void *)&free_rsrc);
224         if (rc < 0) {
225                 plt_err("Unable to get free rsrc count.");
226                 return 0;
227         }
228
229         if (nb_lfs && (free_rsrc->tim < nb_lfs)) {
230                 plt_tim_dbg("Requested LFs : %d Available LFs : %d", nb_lfs,
231                             free_rsrc->tim);
232                 return 0;
233         }
234
235         attach_req = mbox_alloc_msg_attach_resources(dev->mbox);
236         if (attach_req == NULL)
237                 return -ENOSPC;
238         attach_req->modify = true;
239         attach_req->timlfs = nb_lfs ? nb_lfs : free_rsrc->tim;
240         nb_lfs = attach_req->timlfs;
241
242         rc = mbox_process(dev->mbox);
243         if (rc < 0) {
244                 plt_err("Unable to attach TIM LFs.");
245                 return 0;
246         }
247
248         return nb_lfs;
249 }
250
251 void
252 roc_tim_fini(struct roc_tim *roc_tim)
253 {
254         struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
255         struct rsrc_detach_req *detach_req;
256
257         detach_req = mbox_alloc_msg_detach_resources(dev->mbox);
258         PLT_ASSERT(detach_req);
259         detach_req->partial = true;
260         detach_req->timlfs = true;
261
262         mbox_process(dev->mbox);
263 }