raw/octeontx2_ep: add device configuration
[dpdk.git] / drivers / raw / octeontx2_ep / otx2_ep_vf.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_common.h>
6 #include <rte_rawdev.h>
7 #include <rte_rawdev_pmd.h>
8
9 #include "otx2_common.h"
10 #include "otx2_ep_rawdev.h"
11 #include "otx2_ep_vf.h"
12
13 static int
14 sdp_vf_reset_iq(struct sdp_device *sdpvf, int q_no)
15 {
16         uint64_t loop = SDP_VF_BUSY_LOOP_COUNT;
17         volatile uint64_t d64 = 0ull;
18
19         /* There is no RST for a ring.
20          * Clear all registers one by one after disabling the ring
21          */
22
23         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
24         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_INSTR_BADDR(q_no));
25         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_INSTR_RSIZE(q_no));
26
27         d64 = 0xFFFFFFFF; /* ~0ull */
28         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_INSTR_DBELL(q_no));
29         d64 = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_INSTR_DBELL(q_no));
30
31         while ((d64 != 0) && loop--) {
32                 otx2_write64(d64, sdpvf->hw_addr +
33                              SDP_VF_R_IN_INSTR_DBELL(q_no));
34
35                 rte_delay_ms(1);
36
37                 d64 = otx2_read64(sdpvf->hw_addr +
38                                   SDP_VF_R_IN_INSTR_DBELL(q_no));
39         }
40
41         loop = SDP_VF_BUSY_LOOP_COUNT;
42         d64 = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_CNTS(q_no));
43         while ((d64 != 0) && loop--) {
44                 otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_CNTS(q_no));
45
46                 rte_delay_ms(1);
47
48                 d64 = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_CNTS(q_no));
49         }
50
51         d64 = 0ull;
52         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_INT_LEVELS(q_no));
53         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_PKT_CNT(q_no));
54         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_IN_BYTE_CNT(q_no));
55
56         return 0;
57 }
58
59 static int
60 sdp_vf_reset_oq(struct sdp_device *sdpvf, int q_no)
61 {
62         uint64_t loop = SDP_VF_BUSY_LOOP_COUNT;
63         volatile uint64_t d64 = 0ull;
64
65         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
66
67         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_SLIST_BADDR(q_no));
68
69         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_SLIST_RSIZE(q_no));
70
71         d64 = 0xFFFFFFFF;
72         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_SLIST_DBELL(q_no));
73         d64 = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_SLIST_DBELL(q_no));
74
75         while ((d64 != 0) && loop--) {
76                 otx2_write64(d64, sdpvf->hw_addr +
77                              SDP_VF_R_OUT_SLIST_DBELL(q_no));
78
79                 rte_delay_ms(1);
80
81                 d64 = otx2_read64(sdpvf->hw_addr +
82                                   SDP_VF_R_OUT_SLIST_DBELL(q_no));
83         }
84
85         loop = SDP_VF_BUSY_LOOP_COUNT;
86         d64 = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_CNTS(q_no));
87         while ((d64 != 0) && (loop--)) {
88                 otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_CNTS(q_no));
89
90                 rte_delay_ms(1);
91
92                 d64 = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_CNTS(q_no));
93         }
94
95         d64 = 0ull;
96         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_INT_LEVELS(q_no));
97         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_PKT_CNT(q_no));
98         otx2_write64(d64, sdpvf->hw_addr + SDP_VF_R_OUT_BYTE_CNT(q_no));
99
100         return 0;
101 }
102
103 static void
104 sdp_vf_setup_global_iq_reg(struct sdp_device *sdpvf, int q_no)
105 {
106         volatile uint64_t reg_val = 0ull;
107
108         /* Select ES, RO, NS, RDSIZE,DPTR Fomat#0 for IQs
109          * IS_64B is by default enabled.
110          */
111         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
112
113         reg_val |= SDP_VF_R_IN_CTL_RDSIZE;
114         reg_val |= SDP_VF_R_IN_CTL_IS_64B;
115         reg_val |= SDP_VF_R_IN_CTL_ESR;
116
117         otx2_write64(reg_val, sdpvf->hw_addr + SDP_VF_R_IN_CONTROL(q_no));
118
119 }
120
121 static void
122 sdp_vf_setup_global_oq_reg(struct sdp_device *sdpvf, int q_no)
123 {
124         volatile uint64_t reg_val = 0ull;
125
126         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
127
128         reg_val |= (SDP_VF_R_OUT_CTL_IMODE);
129
130         reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_P);
131         reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_P);
132         reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_I);
133         reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_I);
134         reg_val &= ~(SDP_VF_R_OUT_CTL_ES_I);
135         reg_val &= ~(SDP_VF_R_OUT_CTL_ROR_D);
136         reg_val &= ~(SDP_VF_R_OUT_CTL_NSR_D);
137         reg_val &= ~(SDP_VF_R_OUT_CTL_ES_D);
138
139         /* INFO/DATA ptr swap is required  */
140         reg_val |= (SDP_VF_R_OUT_CTL_ES_P);
141
142         otx2_write64(reg_val, sdpvf->hw_addr + SDP_VF_R_OUT_CONTROL(q_no));
143
144 }
145
146 static int
147 sdp_vf_reset_input_queues(struct sdp_device *sdpvf)
148 {
149         uint32_t q_no = 0;
150
151         otx2_sdp_dbg("%s :", __func__);
152
153         for (q_no = 0; q_no < sdpvf->sriov_info.rings_per_vf; q_no++)
154                 sdp_vf_reset_iq(sdpvf, q_no);
155
156         return 0;
157 }
158
159 static int
160 sdp_vf_reset_output_queues(struct sdp_device *sdpvf)
161 {
162         uint64_t q_no = 0ull;
163
164         otx2_sdp_dbg(" %s :", __func__);
165
166         for (q_no = 0; q_no < sdpvf->sriov_info.rings_per_vf; q_no++)
167                 sdp_vf_reset_oq(sdpvf, q_no);
168
169         return 0;
170 }
171
172 static void
173 sdp_vf_setup_global_input_regs(struct sdp_device *sdpvf)
174 {
175         uint64_t q_no = 0ull;
176
177         sdp_vf_reset_input_queues(sdpvf);
178
179         for (q_no = 0; q_no < (sdpvf->sriov_info.rings_per_vf); q_no++)
180                 sdp_vf_setup_global_iq_reg(sdpvf, q_no);
181 }
182
183 static void
184 sdp_vf_setup_global_output_regs(struct sdp_device *sdpvf)
185 {
186         uint32_t q_no;
187
188         sdp_vf_reset_output_queues(sdpvf);
189
190         for (q_no = 0; q_no < (sdpvf->sriov_info.rings_per_vf); q_no++)
191                 sdp_vf_setup_global_oq_reg(sdpvf, q_no);
192
193 }
194
195 static int
196 sdp_vf_setup_device_regs(struct sdp_device *sdpvf)
197 {
198         sdp_vf_setup_global_input_regs(sdpvf);
199         sdp_vf_setup_global_output_regs(sdpvf);
200
201         return 0;
202 }
203
204 static void
205 sdp_vf_setup_iq_regs(struct sdp_device *sdpvf, uint32_t iq_no)
206 {
207         struct sdp_instr_queue *iq = sdpvf->instr_queue[iq_no];
208         volatile uint64_t reg_val = 0ull;
209
210         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_CONTROL(iq_no));
211
212         /* Wait till IDLE to set to 1, not supposed to configure BADDR
213          * as long as IDLE is 0
214          */
215         if (!(reg_val & SDP_VF_R_IN_CTL_IDLE)) {
216                 do {
217                         reg_val = otx2_read64(sdpvf->hw_addr +
218                                               SDP_VF_R_IN_CONTROL(iq_no));
219                 } while (!(reg_val & SDP_VF_R_IN_CTL_IDLE));
220         }
221
222         /* Write the start of the input queue's ring and its size  */
223         otx2_write64(iq->base_addr_dma, sdpvf->hw_addr +
224                      SDP_VF_R_IN_INSTR_BADDR(iq_no));
225         otx2_write64(iq->nb_desc, sdpvf->hw_addr +
226                      SDP_VF_R_IN_INSTR_RSIZE(iq_no));
227
228         /* Remember the doorbell & instruction count register addr
229          * for this queue
230          */
231         iq->doorbell_reg = (uint8_t *) sdpvf->hw_addr +
232                            SDP_VF_R_IN_INSTR_DBELL(iq_no);
233         iq->inst_cnt_reg = (uint8_t *) sdpvf->hw_addr +
234                            SDP_VF_R_IN_CNTS(iq_no);
235
236         otx2_sdp_dbg("InstQ[%d]:dbell reg @ 0x%p instcnt_reg @ 0x%p",
237                      iq_no, iq->doorbell_reg, iq->inst_cnt_reg);
238
239         /* Store the current instrn counter(used in flush_iq calculation) */
240         iq->reset_instr_cnt = rte_read32(iq->inst_cnt_reg);
241
242         /* IN INTR_THRESHOLD is set to max(FFFFFFFF) which disable the IN INTR
243          * to raise
244          */
245         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_INT_LEVELS(iq_no));
246         reg_val = 0xffffffff;
247
248         otx2_write64(reg_val, sdpvf->hw_addr + SDP_VF_R_IN_INT_LEVELS(iq_no));
249
250 }
251
252 static void
253 sdp_vf_setup_oq_regs(struct sdp_device *sdpvf, uint32_t oq_no)
254 {
255         volatile uint64_t reg_val = 0ull;
256         uint64_t oq_ctl = 0ull;
257
258         struct sdp_droq *droq = sdpvf->droq[oq_no];
259
260         /* Wait on IDLE to set to 1, supposed to configure BADDR
261          * as log as IDLE is 0
262          */
263         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
264
265         while (!(reg_val & SDP_VF_R_OUT_CTL_IDLE)) {
266                 reg_val = otx2_read64(sdpvf->hw_addr +
267                                       SDP_VF_R_OUT_CONTROL(oq_no));
268         }
269
270         otx2_write64(droq->desc_ring_dma, sdpvf->hw_addr +
271                      SDP_VF_R_OUT_SLIST_BADDR(oq_no));
272         otx2_write64(droq->nb_desc, sdpvf->hw_addr +
273                      SDP_VF_R_OUT_SLIST_RSIZE(oq_no));
274
275         oq_ctl = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
276
277         /* Clear the ISIZE and BSIZE (22-0) */
278         oq_ctl &= ~(0x7fffffull);
279
280         /* Populate the BSIZE (15-0) */
281         oq_ctl |= (droq->buffer_size & 0xffff);
282
283         /* Populate ISIZE(22-16) */
284         oq_ctl |= ((SDP_RH_SIZE << 16) & 0x7fffff);
285         otx2_write64(oq_ctl, sdpvf->hw_addr + SDP_VF_R_OUT_CONTROL(oq_no));
286
287         /* Mapped address of the pkt_sent and pkts_credit regs */
288         droq->pkts_sent_reg = (uint8_t *) sdpvf->hw_addr +
289                               SDP_VF_R_OUT_CNTS(oq_no);
290         droq->pkts_credit_reg = (uint8_t *) sdpvf->hw_addr +
291                                 SDP_VF_R_OUT_SLIST_DBELL(oq_no);
292
293         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_INT_LEVELS(oq_no));
294
295         /* Clear PKT_CNT register */
296         rte_write64(0xFFFFFFFFF, (uint8_t *)sdpvf->hw_addr +
297                     SDP_VF_R_OUT_PKT_CNT(oq_no));
298
299         /* Clear the OQ doorbell  */
300         rte_write32(0xFFFFFFFF, droq->pkts_credit_reg);
301         while ((rte_read32(droq->pkts_credit_reg) != 0ull)) {
302                 rte_write32(0xFFFFFFFF, droq->pkts_credit_reg);
303                 rte_delay_ms(1);
304         }
305         otx2_sdp_dbg("SDP_R[%d]_credit:%x", oq_no,
306                      rte_read32(droq->pkts_credit_reg));
307
308         /* Clear the OQ_OUT_CNTS doorbell  */
309         reg_val = rte_read32(droq->pkts_sent_reg);
310         rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
311
312         otx2_sdp_dbg("SDP_R[%d]_sent: %x", oq_no,
313                      rte_read32(droq->pkts_sent_reg));
314
315         while (((rte_read32(droq->pkts_sent_reg)) != 0ull)) {
316                 reg_val = rte_read32(droq->pkts_sent_reg);
317                 rte_write32((uint32_t)reg_val, droq->pkts_sent_reg);
318                 rte_delay_ms(1);
319         }
320
321 }
322
323 static void
324 sdp_vf_enable_iq(struct sdp_device *sdpvf, uint32_t q_no)
325 {
326         volatile uint64_t reg_val = 0ull;
327         uint64_t loop = SDP_VF_BUSY_LOOP_COUNT;
328
329         /* Resetting doorbells during IQ enabling also to handle abrupt
330          * guest reboot. IQ reset does not clear the doorbells.
331          */
332         otx2_write64(0xFFFFFFFF, sdpvf->hw_addr +
333                      SDP_VF_R_IN_INSTR_DBELL(q_no));
334
335         while (((otx2_read64(sdpvf->hw_addr +
336                  SDP_VF_R_IN_INSTR_DBELL(q_no))) != 0ull) && loop--) {
337
338                 rte_delay_ms(1);
339         }
340
341         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
342         reg_val |= 0x1ull;
343
344         otx2_write64(reg_val, sdpvf->hw_addr + SDP_VF_R_IN_ENABLE(q_no));
345
346         otx2_info("IQ[%d] enable done", q_no);
347
348 }
349
350 static void
351 sdp_vf_enable_oq(struct sdp_device *sdpvf, uint32_t q_no)
352 {
353         volatile uint64_t reg_val = 0ull;
354
355         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
356         reg_val |= 0x1ull;
357         otx2_write64(reg_val, sdpvf->hw_addr + SDP_VF_R_OUT_ENABLE(q_no));
358
359         otx2_info("OQ[%d] enable done", q_no);
360 }
361
362 static void
363 sdp_vf_enable_io_queues(struct sdp_device *sdpvf)
364 {
365         uint32_t q_no = 0;
366
367         for (q_no = 0; q_no < sdpvf->num_iqs; q_no++)
368                 sdp_vf_enable_iq(sdpvf, q_no);
369
370         for (q_no = 0; q_no < sdpvf->num_oqs; q_no++)
371                 sdp_vf_enable_oq(sdpvf, q_no);
372 }
373
374 int
375 sdp_vf_setup_device(struct sdp_device *sdpvf)
376 {
377         uint64_t reg_val = 0ull;
378
379         /* If application doesn't provide its conf, use driver default conf */
380         if (sdpvf->conf == NULL) {
381                 sdpvf->conf = sdp_get_defconf(sdpvf);
382                 if (sdpvf->conf == NULL) {
383                         otx2_err("SDP VF default config not found");
384                         return -ENOMEM;
385                 }
386                 otx2_info("Default config is used");
387         }
388
389         /* Get IOQs (RPVF] count */
390         reg_val = otx2_read64(sdpvf->hw_addr + SDP_VF_R_IN_CONTROL(0));
391
392         sdpvf->sriov_info.rings_per_vf = ((reg_val >> SDP_VF_R_IN_CTL_RPVF_POS)
393                                           & SDP_VF_R_IN_CTL_RPVF_MASK);
394
395         otx2_info("SDP RPVF: %d", sdpvf->sriov_info.rings_per_vf);
396
397         sdpvf->fn_list.setup_iq_regs       = sdp_vf_setup_iq_regs;
398         sdpvf->fn_list.setup_oq_regs       = sdp_vf_setup_oq_regs;
399         sdpvf->fn_list.setup_device_regs   = sdp_vf_setup_device_regs;
400         sdpvf->fn_list.enable_io_queues    = sdp_vf_enable_io_queues;
401         sdpvf->fn_list.enable_iq           = sdp_vf_enable_iq;
402         sdpvf->fn_list.enable_oq           = sdp_vf_enable_oq;
403
404
405         return 0;
406
407 }