Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2022 Corigine, Inc.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "nfp_target.h"
7 : :
8 : : #include "nfp_cpp.h"
9 : : #include "nfp6000/nfp6000.h"
10 : :
11 : : #define P32 1
12 : : #define P64 2
13 : :
14 : : /*
15 : : * All magic NFP-6xxx IMB 'mode' numbers here are from:
16 : : * Databook (1 August 2013)
17 : : * - System Overview and Connectivity
18 : : * -- Internal Connectivity
19 : : * --- Distributed Switch Fabric - Command Push/Pull (DSF-CPP) Bus
20 : : * ---- CPP addressing
21 : : * ----- Table 3.6. CPP Address Translation Mode Commands
22 : : */
23 : : #define NFP6000_MU_LOCALITY_DIRECT 2
24 : :
25 : : static int
26 : : target_rw(uint32_t cpp_id,
27 : : int pp,
28 : : int start,
29 : : int len)
30 : : {
31 : : uint8_t island;
32 : :
33 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
34 [ # # # # : 0 : if (island != 0 && (island < start || island > (start + len)))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
35 : : return -EINVAL;
36 : :
37 [ # # # # : 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
38 : : case NFP_CPP_ID(0, 0, 0):
39 : : return PUSHPULL(0, pp);
40 : 0 : case NFP_CPP_ID(0, 1, 0):
41 : 0 : return PUSHPULL(pp, 0);
42 : 0 : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
43 : 0 : return PUSHPULL(pp, pp);
44 : 0 : default:
45 : 0 : return -EINVAL;
46 : : }
47 : : }
48 : :
49 : : static int
50 : : nfp6000_nbi_dma(uint32_t cpp_id)
51 : : {
52 [ # # # # ]: 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
53 : : case NFP_CPP_ID(0, 0, 0): /* Read NBI DMA */
54 : : return PUSHPULL(0, P64);
55 : 0 : case NFP_CPP_ID(0, 1, 0): /* Write NBI DMA */
56 : 0 : return PUSHPULL(P64, 0);
57 : 0 : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
58 : 0 : return PUSHPULL(P64, P64);
59 : 0 : default:
60 : 0 : return -EINVAL;
61 : : }
62 : : }
63 : :
64 : : static int
65 : : nfp6000_nbi_stats(uint32_t cpp_id)
66 : : {
67 [ # # # # ]: 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
68 : : case NFP_CPP_ID(0, 0, 0): /* Read NBI Stats */
69 : : return PUSHPULL(0, P32);
70 : 0 : case NFP_CPP_ID(0, 1, 0): /* Write NBI Stats */
71 : 0 : return PUSHPULL(P32, 0);
72 : 0 : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
73 : 0 : return PUSHPULL(P32, P32);
74 : 0 : default:
75 : 0 : return -EINVAL;
76 : : }
77 : : }
78 : :
79 : : static int
80 : : nfp6000_nbi_tm(uint32_t cpp_id)
81 : : {
82 [ # # # # ]: 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
83 : : case NFP_CPP_ID(0, 0, 0): /* Read NBI TM */
84 : : return PUSHPULL(0, P64);
85 : 0 : case NFP_CPP_ID(0, 1, 0): /* Write NBI TM */
86 : 0 : return PUSHPULL(P64, 0);
87 : 0 : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
88 : 0 : return PUSHPULL(P64, P64);
89 : 0 : default:
90 : 0 : return -EINVAL;
91 : : }
92 : : }
93 : :
94 : : static int
95 : : nfp6000_nbi_ppc(uint32_t cpp_id)
96 : : {
97 [ # # # # ]: 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
98 : : case NFP_CPP_ID(0, 0, 0): /* Read NBI Preclassifier */
99 : : return PUSHPULL(0, P64);
100 : 0 : case NFP_CPP_ID(0, 1, 0): /* Write NBI Preclassifier */
101 : 0 : return PUSHPULL(P64, 0);
102 : 0 : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
103 : 0 : return PUSHPULL(P64, P64);
104 : 0 : default:
105 : 0 : return -EINVAL;
106 : : }
107 : : }
108 : :
109 : : static int
110 [ # # ]: 0 : nfp6000_nbi(uint32_t cpp_id,
111 : : uint64_t address)
112 : : {
113 : : uint8_t island;
114 : : uint64_t rel_addr;
115 : :
116 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
117 [ # # ]: 0 : if (island != 8 && island != 9)
118 : : return -EINVAL;
119 : :
120 : 0 : rel_addr = address & 0x3FFFFF;
121 [ # # ]: 0 : if (rel_addr < (1 << 20)) /* [0x000000, 0x100000) */
122 : 0 : return nfp6000_nbi_dma(cpp_id);
123 [ # # ]: 0 : else if (rel_addr < (2 << 20)) /* [0x100000, 0x200000) */
124 : 0 : return nfp6000_nbi_stats(cpp_id);
125 [ # # ]: 0 : else if (rel_addr < (3 << 20)) /* [0x200000, 0x300000) */
126 : 0 : return nfp6000_nbi_tm(cpp_id);
127 : : else /* [0x300000, 0x400000) */
128 : 0 : return nfp6000_nbi_ppc(cpp_id);
129 : : }
130 : :
131 : : /*
132 : : * This structure ONLY includes items that can be done with a read or write of
133 : : * 32-bit or 64-bit words. All others are not listed.
134 : : */
135 : : static int
136 : 0 : nfp6000_mu_common(uint32_t cpp_id)
137 : : {
138 [ # # # # : 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
139 : : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0): /* read_be/write_be */
140 : : return PUSHPULL(P64, P64);
141 : : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 1): /* read_le/write_le */
142 : : return PUSHPULL(P64, P64);
143 : : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 2): /* read_swap_be/write_swap_be */
144 : : return PUSHPULL(P64, P64);
145 : : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 3): /* read_swap_le/write_swap_le */
146 : : return PUSHPULL(P64, P64);
147 : 0 : case NFP_CPP_ID(0, 0, 0): /* read_be */
148 : 0 : return PUSHPULL(0, P64);
149 : 0 : case NFP_CPP_ID(0, 0, 1): /* read_le */
150 : 0 : return PUSHPULL(0, P64);
151 : 0 : case NFP_CPP_ID(0, 0, 2): /* read_swap_be */
152 : 0 : return PUSHPULL(0, P64);
153 : 0 : case NFP_CPP_ID(0, 0, 3): /* read_swap_le */
154 : 0 : return PUSHPULL(0, P64);
155 : 0 : case NFP_CPP_ID(0, 1, 0): /* write_be */
156 : 0 : return PUSHPULL(P64, 0);
157 : 0 : case NFP_CPP_ID(0, 1, 1): /* write_le */
158 : 0 : return PUSHPULL(P64, 0);
159 : 0 : case NFP_CPP_ID(0, 1, 2): /* write_swap_be */
160 : 0 : return PUSHPULL(P64, 0);
161 : 0 : case NFP_CPP_ID(0, 1, 3): /* write_swap_le */
162 : 0 : return PUSHPULL(P64, 0);
163 : 0 : case NFP_CPP_ID(0, 3, 0): /* atomic_read */
164 : 0 : return PUSHPULL(0, P32);
165 : 0 : case NFP_CPP_ID(0, 3, 2): /* mask_compare_write */
166 : 0 : return PUSHPULL(P32, 0);
167 : 0 : case NFP_CPP_ID(0, 4, 0): /* atomic_write */
168 : 0 : return PUSHPULL(P32, 0);
169 : 0 : case NFP_CPP_ID(0, 4, 2): /* atomic_write_imm */
170 : 0 : return PUSHPULL(0, 0);
171 : 0 : case NFP_CPP_ID(0, 4, 3): /* swap_imm */
172 : 0 : return PUSHPULL(0, P32);
173 : 0 : case NFP_CPP_ID(0, 5, 0): /* set */
174 : 0 : return PUSHPULL(P32, 0);
175 : 0 : case NFP_CPP_ID(0, 5, 3): /* test_set_imm */
176 : 0 : return PUSHPULL(0, P32);
177 : 0 : case NFP_CPP_ID(0, 6, 0): /* clr */
178 : 0 : return PUSHPULL(P32, 0);
179 : 0 : case NFP_CPP_ID(0, 6, 3): /* test_clr_imm */
180 : 0 : return PUSHPULL(0, P32);
181 : 0 : case NFP_CPP_ID(0, 7, 0): /* add */
182 : 0 : return PUSHPULL(P32, 0);
183 : 0 : case NFP_CPP_ID(0, 7, 3): /* test_add_imm */
184 : 0 : return PUSHPULL(0, P32);
185 : 0 : case NFP_CPP_ID(0, 8, 0): /* addsat */
186 : 0 : return PUSHPULL(P32, 0);
187 : 0 : case NFP_CPP_ID(0, 8, 3): /* test_subsat_imm */
188 : 0 : return PUSHPULL(0, P32);
189 : 0 : case NFP_CPP_ID(0, 9, 0): /* sub */
190 : 0 : return PUSHPULL(P32, 0);
191 : 0 : case NFP_CPP_ID(0, 9, 3): /* test_sub_imm */
192 : 0 : return PUSHPULL(0, P32);
193 : 0 : case NFP_CPP_ID(0, 10, 0): /* subsat */
194 : 0 : return PUSHPULL(P32, 0);
195 : 0 : case NFP_CPP_ID(0, 10, 3): /* test_subsat_imm */
196 : 0 : return PUSHPULL(0, P32);
197 : 0 : case NFP_CPP_ID(0, 13, 0): /* microq128_get */
198 : 0 : return PUSHPULL(0, P32);
199 : 0 : case NFP_CPP_ID(0, 13, 1): /* microq128_pop */
200 : 0 : return PUSHPULL(0, P32);
201 : 0 : case NFP_CPP_ID(0, 13, 2): /* microq128_put */
202 : 0 : return PUSHPULL(P32, 0);
203 : 0 : case NFP_CPP_ID(0, 15, 0): /* xor */
204 : 0 : return PUSHPULL(P32, 0);
205 : 0 : case NFP_CPP_ID(0, 15, 3): /* test_xor_imm */
206 : 0 : return PUSHPULL(0, P32);
207 : 0 : case NFP_CPP_ID(0, 28, 0): /* read32_be */
208 : 0 : return PUSHPULL(0, P32);
209 : 0 : case NFP_CPP_ID(0, 28, 1): /* read32_le */
210 : 0 : return PUSHPULL(0, P32);
211 : 0 : case NFP_CPP_ID(0, 28, 2): /* read32_swap_be */
212 : 0 : return PUSHPULL(0, P32);
213 : 0 : case NFP_CPP_ID(0, 28, 3): /* read32_swap_le */
214 : 0 : return PUSHPULL(0, P32);
215 : 0 : case NFP_CPP_ID(0, 31, 0): /* write32_be */
216 : 0 : return PUSHPULL(P32, 0);
217 : 0 : case NFP_CPP_ID(0, 31, 1): /* write32_le */
218 : 0 : return PUSHPULL(P32, 0);
219 : 0 : case NFP_CPP_ID(0, 31, 2): /* write32_swap_be */
220 : 0 : return PUSHPULL(P32, 0);
221 : 0 : case NFP_CPP_ID(0, 31, 3): /* write32_swap_le */
222 : 0 : return PUSHPULL(P32, 0);
223 : 0 : default:
224 : 0 : return -EINVAL;
225 : : }
226 : : }
227 : :
228 : : static int
229 : 0 : nfp6000_mu_ctm(uint32_t cpp_id)
230 : : {
231 [ # # # # : 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
# # # #
# ]
232 : : case NFP_CPP_ID(0, 16, 1): /* packet_read_packet_status */
233 : : return PUSHPULL(0, P32);
234 : : case NFP_CPP_ID(0, 17, 1): /* packet_credit_get */
235 : : return PUSHPULL(0, P32);
236 : 0 : case NFP_CPP_ID(0, 17, 3): /* packet_add_thread */
237 : 0 : return PUSHPULL(0, P64);
238 : 0 : case NFP_CPP_ID(0, 18, 2): /* packet_free_and_return_pointer */
239 : 0 : return PUSHPULL(0, P64);
240 : 0 : case NFP_CPP_ID(0, 18, 3): /* packet_return_pointer */
241 : 0 : return PUSHPULL(0, P64);
242 : 0 : case NFP_CPP_ID(0, 21, 0): /* pe_dma_to_memory_indirect */
243 : 0 : return PUSHPULL(0, P64);
244 : 0 : case NFP_CPP_ID(0, 21, 1): /* pe_dma_to_memory_indirect_swap */
245 : 0 : return PUSHPULL(0, P64);
246 : 0 : case NFP_CPP_ID(0, 21, 2): /* pe_dma_to_memory_indirect_free */
247 : 0 : return PUSHPULL(0, P64);
248 : 0 : case NFP_CPP_ID(0, 21, 3): /* pe_dma_to_memory_indirect_free_swap */
249 : 0 : return PUSHPULL(0, P64);
250 : 0 : default:
251 : 0 : return nfp6000_mu_common(cpp_id);
252 : : }
253 : : }
254 : :
255 : : static int
256 : 0 : nfp6000_mu_emu(uint32_t cpp_id)
257 : : {
258 [ # # # # : 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
# ]
259 : : case NFP_CPP_ID(0, 18, 0): /* read_queue */
260 : : return PUSHPULL(0, P32);
261 : : case NFP_CPP_ID(0, 18, 1): /* read_queue_ring */
262 : : return PUSHPULL(0, P32);
263 : 0 : case NFP_CPP_ID(0, 18, 2): /* write_queue */
264 : 0 : return PUSHPULL(P32, 0);
265 : 0 : case NFP_CPP_ID(0, 18, 3): /* write_queue_ring */
266 : 0 : return PUSHPULL(P32, 0);
267 : 0 : case NFP_CPP_ID(0, 20, 2): /* journal */
268 : 0 : return PUSHPULL(P32, 0);
269 : : case NFP_CPP_ID(0, 21, 0): /* get */
270 : : return PUSHPULL(0, P32);
271 : : case NFP_CPP_ID(0, 21, 1): /* get_eop */
272 : : return PUSHPULL(0, P32);
273 : : case NFP_CPP_ID(0, 21, 2): /* get_freely */
274 : : return PUSHPULL(0, P32);
275 : : case NFP_CPP_ID(0, 22, 0): /* pop */
276 : : return PUSHPULL(0, P32);
277 : : case NFP_CPP_ID(0, 22, 1): /* pop_eop */
278 : : return PUSHPULL(0, P32);
279 : : case NFP_CPP_ID(0, 22, 2): /* pop_freely */
280 : : return PUSHPULL(0, P32);
281 : 0 : default:
282 : 0 : return nfp6000_mu_common(cpp_id);
283 : : }
284 : : }
285 : :
286 : : static int
287 : : nfp6000_mu_imu(uint32_t cpp_id)
288 : : {
289 : 0 : return nfp6000_mu_common(cpp_id);
290 : : }
291 : :
292 : : static int
293 [ # # ]: 0 : nfp6000_mu(uint32_t cpp_id,
294 : : uint64_t address)
295 : : {
296 : : int pp;
297 : : uint8_t island;
298 : :
299 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
300 [ # # ]: 0 : if (island == 0) {
301 [ # # ]: 0 : if (address < 0x2000000000ULL)
302 : 0 : pp = nfp6000_mu_ctm(cpp_id);
303 [ # # ]: 0 : else if (address < 0x8000000000ULL)
304 : 0 : pp = nfp6000_mu_emu(cpp_id);
305 [ # # ]: 0 : else if (address < 0x9800000000ULL)
306 : 0 : pp = nfp6000_mu_ctm(cpp_id);
307 [ # # ]: 0 : else if (address < 0x9C00000000ULL)
308 : 0 : pp = nfp6000_mu_emu(cpp_id);
309 [ # # ]: 0 : else if (address < 0xA000000000ULL)
310 : : pp = nfp6000_mu_imu(cpp_id);
311 : : else
312 : 0 : pp = nfp6000_mu_ctm(cpp_id);
313 [ # # # # ]: 0 : } else if (island >= 24 && island <= 27) {
314 : 0 : pp = nfp6000_mu_emu(cpp_id);
315 : : } else if (island >= 28 && island <= 31) {
316 : : pp = nfp6000_mu_imu(cpp_id);
317 : : } else if (island == 1 ||
318 : : (island >= 4 && island <= 7) ||
319 : : (island >= 12 && island <= 13) ||
320 : : (island >= 32 && island <= 51)) {
321 : 0 : pp = nfp6000_mu_ctm(cpp_id);
322 : : } else {
323 : : pp = -EINVAL;
324 : : }
325 : :
326 : 0 : return pp;
327 : : }
328 : :
329 : : static int
330 [ # # ]: 0 : nfp6000_ila(uint32_t cpp_id)
331 : : {
332 : : uint8_t island;
333 : :
334 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
335 [ # # ]: 0 : if (island != 0 && (island < 48 || island > 51))
336 : : return -EINVAL;
337 : :
338 [ # # # ]: 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
339 : : case NFP_CPP_ID(0, 0, 1): /* read_check_error */
340 : : return PUSHPULL(0, P32);
341 : : case NFP_CPP_ID(0, 2, 0): /* read_int */
342 : : return PUSHPULL(0, P32);
343 : 0 : case NFP_CPP_ID(0, 3, 0): /* write_int */
344 : 0 : return PUSHPULL(P32, 0);
345 : : default:
346 : : return target_rw(cpp_id, P32, 48, 4);
347 : : }
348 : : }
349 : :
350 : : static int
351 [ # # ]: 0 : nfp6000_pci(uint32_t cpp_id)
352 : : {
353 : : uint8_t island;
354 : :
355 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
356 [ # # ]: 0 : if (island != 0 && (island < 4 || island > 7))
357 : : return -EINVAL;
358 : :
359 [ # # # ]: 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
360 : : case NFP_CPP_ID(0, 2, 0):
361 : : return PUSHPULL(0, P32);
362 : 0 : case NFP_CPP_ID(0, 3, 0):
363 : 0 : return PUSHPULL(P32, 0);
364 : : default:
365 : : return target_rw(cpp_id, P32, 4, 4);
366 : : }
367 : : }
368 : :
369 : : static int
370 [ # # ]: 0 : nfp6000_crypto(uint32_t cpp_id)
371 : : {
372 : : uint8_t island;
373 : :
374 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
375 [ # # ]: 0 : if (island != 0 && (island < 12 || island > 15))
376 : : return -EINVAL;
377 : :
378 [ # # ]: 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
379 : : case NFP_CPP_ID(0, 2, 0):
380 : : return PUSHPULL(P64, 0);
381 : : default:
382 : : return target_rw(cpp_id, P64, 12, 4);
383 : : }
384 : : }
385 : :
386 : : static int
387 [ # # ]: 0 : nfp6000_cap_xpb(uint32_t cpp_id)
388 : : {
389 : : uint8_t island;
390 : :
391 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
392 [ # # ]: 0 : if (island > 63)
393 : : return -EINVAL;
394 : :
395 [ # # # # : 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
# # # # #
# ]
396 : : case NFP_CPP_ID(0, 0, 1): /* RingGet */
397 : : return PUSHPULL(0, P32);
398 : 0 : case NFP_CPP_ID(0, 0, 2): /* Interthread Signal */
399 : 0 : return PUSHPULL(P32, 0);
400 : 0 : case NFP_CPP_ID(0, 1, 1): /* RingPut */
401 : 0 : return PUSHPULL(P32, 0);
402 : 0 : case NFP_CPP_ID(0, 1, 2): /* CTNNWr */
403 : 0 : return PUSHPULL(P32, 0);
404 : : case NFP_CPP_ID(0, 2, 0): /* ReflectRd, signal none */
405 : : return PUSHPULL(0, P32);
406 : : case NFP_CPP_ID(0, 2, 1): /* ReflectRd, signal self */
407 : : return PUSHPULL(0, P32);
408 : : case NFP_CPP_ID(0, 2, 2): /* ReflectRd, signal remote */
409 : : return PUSHPULL(0, P32);
410 : : case NFP_CPP_ID(0, 2, 3): /* ReflectRd, signal both */
411 : : return PUSHPULL(0, P32);
412 : 0 : case NFP_CPP_ID(0, 3, 0): /* ReflectWr, signal none */
413 : 0 : return PUSHPULL(P32, 0);
414 : 0 : case NFP_CPP_ID(0, 3, 1): /* ReflectWr, signal self */
415 : 0 : return PUSHPULL(P32, 0);
416 : 0 : case NFP_CPP_ID(0, 3, 2): /* ReflectWr, signal remote */
417 : 0 : return PUSHPULL(P32, 0);
418 : 0 : case NFP_CPP_ID(0, 3, 3): /* ReflectWr, signal both */
419 : 0 : return PUSHPULL(P32, 0);
420 : 0 : case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 1):
421 : 0 : return PUSHPULL(P32, P32);
422 : : default:
423 : : return target_rw(cpp_id, P32, 1, 63);
424 : : }
425 : : }
426 : :
427 : : static int
428 [ # # ]: 0 : nfp6000_cls(uint32_t cpp_id)
429 : : {
430 : : uint8_t island;
431 : :
432 : : island = NFP_CPP_ID_ISLAND_of(cpp_id);
433 [ # # ]: 0 : if (island > 63)
434 : : return -EINVAL;
435 : :
436 [ # # # # : 0 : switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
# # # #
# ]
437 : : case NFP_CPP_ID(0, 0, 3): /* xor */
438 : : return PUSHPULL(P32, 0);
439 : : case NFP_CPP_ID(0, 2, 0): /* set */
440 : : return PUSHPULL(P32, 0);
441 : : case NFP_CPP_ID(0, 2, 1): /* clr */
442 : : return PUSHPULL(P32, 0);
443 : : case NFP_CPP_ID(0, 4, 0): /* add */
444 : : return PUSHPULL(P32, 0);
445 : : case NFP_CPP_ID(0, 4, 1): /* add64 */
446 : : return PUSHPULL(P32, 0);
447 : : case NFP_CPP_ID(0, 6, 0): /* sub */
448 : : return PUSHPULL(P32, 0);
449 : : case NFP_CPP_ID(0, 6, 1): /* sub64 */
450 : : return PUSHPULL(P32, 0);
451 : : case NFP_CPP_ID(0, 6, 2): /* subsat */
452 : : return PUSHPULL(P32, 0);
453 : : case NFP_CPP_ID(0, 8, 2): /* hash_mask */
454 : : return PUSHPULL(P32, 0);
455 : : case NFP_CPP_ID(0, 8, 3): /* hash_clear */
456 : : return PUSHPULL(P32, 0);
457 : 0 : case NFP_CPP_ID(0, 9, 0): /* ring_get */
458 : 0 : return PUSHPULL(0, P32);
459 : 0 : case NFP_CPP_ID(0, 9, 1): /* ring_pop */
460 : 0 : return PUSHPULL(0, P32);
461 : 0 : case NFP_CPP_ID(0, 9, 2): /* ring_get_freely */
462 : 0 : return PUSHPULL(0, P32);
463 : 0 : case NFP_CPP_ID(0, 9, 3): /* ring_pop_freely */
464 : 0 : return PUSHPULL(0, P32);
465 : : case NFP_CPP_ID(0, 10, 0): /* ring_put */
466 : : return PUSHPULL(P32, 0);
467 : : case NFP_CPP_ID(0, 10, 2): /* ring_journal */
468 : : return PUSHPULL(P32, 0);
469 : : case NFP_CPP_ID(0, 14, 0): /* reflect_write_sig_local */
470 : : return PUSHPULL(P32, 0);
471 : 0 : case NFP_CPP_ID(0, 15, 1): /* reflect_read_sig_local */
472 : 0 : return PUSHPULL(0, P32);
473 : : case NFP_CPP_ID(0, 17, 2): /* statistic */
474 : : return PUSHPULL(P32, 0);
475 : 0 : case NFP_CPP_ID(0, 24, 0): /* ring_read */
476 : 0 : return PUSHPULL(0, P32);
477 : : case NFP_CPP_ID(0, 24, 1): /* ring_write */
478 : : return PUSHPULL(P32, 0);
479 : 0 : case NFP_CPP_ID(0, 25, 0): /* ring_workq_add_thread */
480 : 0 : return PUSHPULL(0, P32);
481 : : case NFP_CPP_ID(0, 25, 1): /* ring_workq_add_work */
482 : : return PUSHPULL(P32, 0);
483 : : default:
484 : : return target_rw(cpp_id, P32, 0, 64);
485 : : }
486 : : }
487 : :
488 : : int
489 [ # # # # : 0 : nfp_target_pushpull(uint32_t cpp_id,
# # # # #
# # ]
490 : : uint64_t address)
491 : : {
492 [ # # # # : 0 : switch (NFP_CPP_ID_TARGET_of(cpp_id)) {
# # # # #
# # ]
493 : 0 : case NFP_CPP_TARGET_NBI:
494 : 0 : return nfp6000_nbi(cpp_id, address);
495 : : case NFP_CPP_TARGET_QDR:
496 : : return target_rw(cpp_id, P32, 24, 4);
497 : 0 : case NFP_CPP_TARGET_ILA:
498 : 0 : return nfp6000_ila(cpp_id);
499 : 0 : case NFP_CPP_TARGET_MU:
500 : 0 : return nfp6000_mu(cpp_id, address);
501 : 0 : case NFP_CPP_TARGET_PCIE:
502 : 0 : return nfp6000_pci(cpp_id);
503 : 0 : case NFP_CPP_TARGET_ARM:
504 [ # # ]: 0 : if (address < 0x10000)
505 : 0 : return target_rw(cpp_id, P64, 1, 1);
506 : : else
507 : 0 : return target_rw(cpp_id, P32, 1, 1);
508 : 0 : case NFP_CPP_TARGET_CRYPTO:
509 : 0 : return nfp6000_crypto(cpp_id);
510 : 0 : case NFP_CPP_TARGET_CT_XPB:
511 : 0 : return nfp6000_cap_xpb(cpp_id);
512 : 0 : case NFP_CPP_TARGET_CLS:
513 : 0 : return nfp6000_cls(cpp_id);
514 : : case NFP_CPP_TARGET_INVALID:
515 : : return target_rw(cpp_id, P32, 4, 4);
516 : : default:
517 : : return -EINVAL;
518 : : }
519 : : }
520 : :
521 : : static uint64_t
522 : : nfp_mask64(int msb,
523 : : int lsb)
524 : : {
525 : : int width;
526 : :
527 [ # # ]: 0 : if (msb < 0 || lsb < 0)
528 : : return 0;
529 : :
530 : 0 : width = msb - lsb + 1;
531 [ # # ]: 0 : if (width <= 0)
532 : : return 0;
533 : :
534 [ # # ]: 0 : if (width == 64)
535 : : return ~(uint64_t)0;
536 : :
537 [ # # ]: 0 : if ((lsb + width) > 64)
538 : : return 0;
539 : :
540 : 0 : return (RTE_BIT64(width) - 1) << lsb;
541 : : }
542 : :
543 : : static int
544 : 0 : nfp_decode_basic(uint64_t addr,
545 : : int *dest_island,
546 : : int cpp_tgt,
547 : : int mode,
548 : : int addr40,
549 : : int isld1,
550 : : int isld0)
551 : : {
552 : : int iid_lsb;
553 : : int idx_lsb;
554 : :
555 : : /* This function doesn't handle MU or CTXBP */
556 [ # # ]: 0 : if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB)
557 : : return -EINVAL;
558 : :
559 [ # # # # : 0 : switch (mode) {
# ]
560 : 0 : case 0:
561 : : /*
562 : : * For VQDR, in this mode for 32-bit addressing it would be
563 : : * islands 0, 16, 32 and 48 depending on channel and upper
564 : : * address bits. Since those are not all valid islands, most
565 : : * decode cases would result in bad island IDs, but we do them
566 : : * anyway since this is decoding an address that is already
567 : : * assumed to be used as-is to get to sram.
568 : : */
569 [ # # ]: 0 : iid_lsb = (addr40) ? 34 : 26;
570 : 0 : *dest_island = (int)(addr >> iid_lsb) & 0x3F;
571 : :
572 : 0 : return 0;
573 : 0 : case 1:
574 : : /*
575 : : * For VQDR 32-bit, this would decode as:
576 : : * Channel 0: island#0
577 : : * Channel 1: island#0
578 : : * Channel 2: island#1
579 : : * Channel 3: island#1
580 : : *
581 : : * That would be valid as long as both islands have VQDR.
582 : : * Let's allow this.
583 : : */
584 [ # # ]: 0 : idx_lsb = (addr40) ? 39 : 31;
585 [ # # ]: 0 : if ((addr & nfp_mask64(idx_lsb, idx_lsb)) != 0)
586 : 0 : *dest_island = isld1;
587 : : else
588 : 0 : *dest_island = isld0;
589 : :
590 : : return 0;
591 : 0 : case 2:
592 : : /*
593 : : * For VQDR 32-bit:
594 : : * Channel 0: (island#0 | 0)
595 : : * Channel 1: (island#0 | 1)
596 : : * Channel 2: (island#1 | 0)
597 : : * Channel 3: (island#1 | 1)
598 : : *
599 : : * Make sure we compare against isldN values by clearing the
600 : : * LSB. This is what the silicon does.
601 : : */
602 : 0 : isld0 &= ~1;
603 : 0 : isld1 &= ~1;
604 : :
605 [ # # ]: 0 : idx_lsb = (addr40) ? 39 : 31;
606 : 0 : iid_lsb = idx_lsb - 1;
607 : :
608 [ # # ]: 0 : if ((addr & nfp_mask64(idx_lsb, idx_lsb)) != 0)
609 : 0 : *dest_island = isld1 | (int)((addr >> iid_lsb) & 1);
610 : : else
611 : 0 : *dest_island = isld0 | (int)((addr >> iid_lsb) & 1);
612 : :
613 : : return 0;
614 : 0 : case 3:
615 : : /*
616 : : * In this mode the data address starts to affect the island ID
617 : : * so rather not allow it. In some really specific case one
618 : : * could use this to send the upper half of the VQDR channel to
619 : : * another MU, but this is getting very specific. However, as
620 : : * above for mode 0, this is the decoder and the caller should
621 : : * validate the resulting IID. This blindly does what the
622 : : * silicon would do.
623 : : */
624 : 0 : isld0 &= ~3;
625 : 0 : isld1 &= ~3;
626 : :
627 [ # # ]: 0 : idx_lsb = (addr40) ? 39 : 31;
628 : 0 : iid_lsb = idx_lsb - 2;
629 : :
630 [ # # ]: 0 : if ((addr & nfp_mask64(idx_lsb, idx_lsb)) != 0)
631 : 0 : *dest_island = isld1 | (int)((addr >> iid_lsb) & 3);
632 : : else
633 : 0 : *dest_island = isld0 | (int)((addr >> iid_lsb) & 3);
634 : :
635 : : return 0;
636 : : default:
637 : : return -EINVAL;
638 : : }
639 : : }
640 : :
641 : : static int
642 : : nfp_encode_basic_qdr(uint64_t addr,
643 : : int dest_island,
644 : : int cpp_tgt,
645 : : int mode,
646 : : int addr40,
647 : : int isld1,
648 : : int isld0)
649 : : {
650 : : int v;
651 : : int ret;
652 : :
653 : : /* Full Island ID and channel bits overlap? */
654 : 0 : ret = nfp_decode_basic(addr, &v, cpp_tgt, mode, addr40, isld1, isld0);
655 [ # # # # : 0 : if (ret != 0)
# # # # ]
656 : : return ret;
657 : :
658 : : /* The current address won't go where expected? */
659 [ # # # # : 0 : if (dest_island != -1 && dest_island != v)
# # # # ]
660 : 0 : return -EINVAL;
661 : :
662 : : /* If dest_island was -1, we don't care where it goes. */
663 : : return 0;
664 : : }
665 : :
666 : : /*
667 : : * Try each option, take first one that fits.
668 : : * Not sure if we would want to do some smarter
669 : : * searching and prefer 0 or non-0 island IDs.
670 : : */
671 : : static int
672 : 0 : nfp_encode_basic_search(uint64_t *addr,
673 : : int dest_island,
674 : : int *isld,
675 : : int iid_lsb,
676 : : int idx_lsb,
677 : : int v_max)
678 : : {
679 : : int i;
680 : : int v;
681 : :
682 [ # # ]: 0 : for (i = 0; i < 2; i++)
683 [ # # ]: 0 : for (v = 0; v < v_max; v++) {
684 [ # # ]: 0 : if (dest_island != (isld[i] | v))
685 : : continue;
686 : :
687 : 0 : *addr &= ~nfp_mask64(idx_lsb, iid_lsb);
688 : 0 : *addr |= ((uint64_t)i << idx_lsb);
689 : 0 : *addr |= ((uint64_t)v << iid_lsb);
690 : 0 : return 0;
691 : : }
692 : :
693 : : return -ENODEV;
694 : : }
695 : :
696 : : /*
697 : : * For VQDR, we may not modify the Channel bits, which might overlap
698 : : * with the Index bit. When it does, we need to ensure that isld0 == isld1.
699 : : */
700 : : static int
701 : 0 : nfp_encode_basic(uint64_t *addr,
702 : : int dest_island,
703 : : int cpp_tgt,
704 : : int mode,
705 : : int addr40,
706 : : int isld1,
707 : : int isld0)
708 : : {
709 : : int iid_lsb;
710 : : int idx_lsb;
711 : : int isld[2];
712 : : uint64_t value;
713 : :
714 : 0 : isld[0] = isld0;
715 : 0 : isld[1] = isld1;
716 : :
717 : : /* This function doesn't handle MU or CTXBP */
718 [ # # ]: 0 : if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB)
719 : : return -EINVAL;
720 : :
721 [ # # # # : 0 : switch (mode) {
# ]
722 : 0 : case 0:
723 [ # # ]: 0 : if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) {
724 : : /*
725 : : * In this specific mode we'd rather not modify the
726 : : * address but we can verify if the existing contents
727 : : * will point to a valid island.
728 : : */
729 : 0 : return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
730 : : mode, addr40, isld1, isld0);
731 : : }
732 : :
733 [ # # ]: 0 : iid_lsb = (addr40) ? 34 : 26;
734 : :
735 : : /* <39:34> or <31:26> */
736 : : value = nfp_mask64((iid_lsb + 5), iid_lsb);
737 : 0 : *addr &= ~value;
738 : 0 : *addr |= (((uint64_t)dest_island) << iid_lsb) & value;
739 : 0 : return 0;
740 : 0 : case 1:
741 [ # # ]: 0 : if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) {
742 : 0 : return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
743 : : mode, addr40, isld1, isld0);
744 : : }
745 : :
746 [ # # ]: 0 : idx_lsb = (addr40) ? 39 : 31;
747 [ # # ]: 0 : if (dest_island == isld0) {
748 : : /* Only need to clear the Index bit */
749 : 0 : *addr &= ~nfp_mask64(idx_lsb, idx_lsb);
750 : 0 : return 0;
751 : : }
752 : :
753 [ # # ]: 0 : if (dest_island == isld1) {
754 : : /* Only need to set the Index bit */
755 : 0 : *addr |= (UINT64_C(1) << idx_lsb);
756 : 0 : return 0;
757 : : }
758 : :
759 : : return -ENODEV;
760 : 0 : case 2:
761 [ # # ]: 0 : if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) {
762 : : /* iid<0> = addr<30> = channel<0> */
763 : : /* channel<1> = addr<31> = Index */
764 : 0 : return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
765 : : mode, addr40, isld1, isld0);
766 : : }
767 : :
768 : : /*
769 : : * Make sure we compare against isldN values by clearing the
770 : : * LSB. This is what the silicon does.
771 : : */
772 : 0 : isld[0] &= ~1;
773 : 0 : isld[1] &= ~1;
774 : :
775 [ # # ]: 0 : idx_lsb = (addr40) ? 39 : 31;
776 : 0 : iid_lsb = idx_lsb - 1;
777 : :
778 : 0 : return nfp_encode_basic_search(addr, dest_island, isld,
779 : : iid_lsb, idx_lsb, 2);
780 : 0 : case 3:
781 [ # # ]: 0 : if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) {
782 : : /*
783 : : * iid<0> = addr<29> = data
784 : : * iid<1> = addr<30> = channel<0>
785 : : * channel<1> = addr<31> = Index
786 : : */
787 : 0 : return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island,
788 : : mode, addr40, isld1, isld0);
789 : : }
790 : :
791 : 0 : isld[0] &= ~3;
792 : 0 : isld[1] &= ~3;
793 : :
794 [ # # ]: 0 : idx_lsb = (addr40) ? 39 : 31;
795 : 0 : iid_lsb = idx_lsb - 2;
796 : :
797 : 0 : return nfp_encode_basic_search(addr, dest_island, isld,
798 : : iid_lsb, idx_lsb, 4);
799 : : default:
800 : : return -EINVAL;
801 : : }
802 : : }
803 : :
804 : : static int
805 : 0 : nfp_encode_mu(uint64_t *addr,
806 : : int dest_island,
807 : : int mode,
808 : : int addr40,
809 : : int isld1,
810 : : int isld0)
811 : : {
812 : : int da;
813 : : int iid_lsb;
814 : : int idx_lsb;
815 : : int isld[2];
816 : : uint64_t value;
817 : : int locality_lsb;
818 : :
819 : 0 : isld[0] = isld0;
820 [ # # ]: 0 : isld[1] = isld1;
821 : :
822 : : locality_lsb = nfp_cppat_mu_locality_lsb(mode, addr40);
823 : : if (locality_lsb < 0)
824 : : return -EINVAL;
825 : :
826 [ # # ]: 0 : if (((*addr >> locality_lsb) & 3) == NFP6000_MU_LOCALITY_DIRECT)
827 : : da = 1;
828 : : else
829 : : da = 0;
830 : :
831 [ # # # # ]: 0 : switch (mode) {
832 : 0 : case 0:
833 [ # # ]: 0 : iid_lsb = (addr40 != 0) ? 32 : 24;
834 : : value = nfp_mask64((iid_lsb + 5), iid_lsb);
835 : 0 : *addr &= ~value;
836 : 0 : *addr |= (((uint64_t)dest_island) << iid_lsb) & value;
837 : 0 : return 0;
838 : 0 : case 1:
839 [ # # ]: 0 : if (da == 1) {
840 [ # # ]: 0 : iid_lsb = (addr40 != 0) ? 32 : 24;
841 : : value = nfp_mask64((iid_lsb + 5), iid_lsb);
842 : 0 : *addr &= ~value;
843 : 0 : *addr |= (((uint64_t)dest_island) << iid_lsb) & value;
844 : 0 : return 0;
845 : : }
846 : :
847 [ # # ]: 0 : idx_lsb = (addr40 != 0) ? 37 : 29;
848 [ # # ]: 0 : if (dest_island == isld0) {
849 : 0 : *addr &= ~nfp_mask64(idx_lsb, idx_lsb);
850 : 0 : return 0;
851 : : }
852 : :
853 [ # # ]: 0 : if (dest_island == isld1) {
854 : 0 : *addr |= (UINT64_C(1) << idx_lsb);
855 : 0 : return 0;
856 : : }
857 : :
858 : : return -ENODEV;
859 : 0 : case 2:
860 [ # # ]: 0 : if (da == 1) {
861 [ # # ]: 0 : iid_lsb = (addr40 != 0) ? 32 : 24;
862 : : value = nfp_mask64((iid_lsb + 5), iid_lsb);
863 : 0 : *addr &= ~value;
864 : 0 : *addr |= (((uint64_t)dest_island) << iid_lsb) & value;
865 : 0 : return 0;
866 : : }
867 : :
868 : : /*
869 : : * Make sure we compare against isldN values by clearing the
870 : : * LSB. This is what the silicon does.
871 : : */
872 : 0 : isld[0] &= ~1;
873 : 0 : isld[1] &= ~1;
874 : :
875 [ # # ]: 0 : idx_lsb = (addr40 != 0) ? 37 : 29;
876 : 0 : iid_lsb = idx_lsb - 1;
877 : :
878 : 0 : return nfp_encode_basic_search(addr, dest_island, isld,
879 : : iid_lsb, idx_lsb, 2);
880 : 0 : case 3:
881 : : /*
882 : : * Only the EMU will use 40 bit addressing. Silently set the
883 : : * direct locality bit for everyone else. The SDK toolchain
884 : : * uses dest_island <= 0 to test for atypical address encodings
885 : : * to support access to local-island CTM with a 32-but address
886 : : * (high-locality is effectively ignored and just used for
887 : : * routing to island #0).
888 : : */
889 [ # # ]: 0 : if (dest_island > 0 && (dest_island < 24 || dest_island > 26)) {
890 : 0 : *addr |= ((uint64_t)NFP6000_MU_LOCALITY_DIRECT)
891 : 0 : << locality_lsb;
892 : : da = 1;
893 : : }
894 : :
895 [ # # ]: 0 : if (da == 1) {
896 [ # # ]: 0 : iid_lsb = (addr40 != 0) ? 32 : 24;
897 : : value = nfp_mask64((iid_lsb + 5), iid_lsb);
898 : 0 : *addr &= ~value;
899 : 0 : *addr |= (((uint64_t)dest_island) << iid_lsb) & value;
900 : 0 : return 0;
901 : : }
902 : :
903 : 0 : isld[0] &= ~3;
904 : 0 : isld[1] &= ~3;
905 : :
906 [ # # ]: 0 : idx_lsb = (addr40 != 0) ? 37 : 29;
907 : 0 : iid_lsb = idx_lsb - 2;
908 : :
909 : 0 : return nfp_encode_basic_search(addr, dest_island, isld,
910 : : iid_lsb, idx_lsb, 4);
911 : : default:
912 : : return -EINVAL;
913 : : }
914 : : }
915 : :
916 : : static int
917 : 0 : nfp_cppat_addr_encode(uint64_t *addr,
918 : : int dest_island,
919 : : int cpp_tgt,
920 : : int mode,
921 : : int addr40,
922 : : int isld1,
923 : : int isld0)
924 : : {
925 : : uint64_t value;
926 : :
927 [ # # # # ]: 0 : switch (cpp_tgt) {
928 : 0 : case NFP_CPP_TARGET_NBI:
929 : : case NFP_CPP_TARGET_QDR:
930 : : case NFP_CPP_TARGET_ILA:
931 : : case NFP_CPP_TARGET_PCIE:
932 : : case NFP_CPP_TARGET_ARM:
933 : : case NFP_CPP_TARGET_CRYPTO:
934 : : case NFP_CPP_TARGET_CLS:
935 : 0 : return nfp_encode_basic(addr, dest_island, cpp_tgt, mode,
936 : : addr40, isld1, isld0);
937 : 0 : case NFP_CPP_TARGET_MU:
938 : 0 : return nfp_encode_mu(addr, dest_island, mode, addr40,
939 : : isld1, isld0);
940 : 0 : case NFP_CPP_TARGET_CT_XPB:
941 [ # # ]: 0 : if (mode != 1 || addr40 != 0)
942 : : return -EINVAL;
943 : :
944 : : value = nfp_mask64(29, 24);
945 : 0 : *addr &= ~value;
946 : 0 : *addr |= (((uint64_t)dest_island) << 24) & value;
947 : 0 : return 0;
948 : : default:
949 : : return -EINVAL;
950 : : }
951 : : }
952 : :
953 : : int
954 [ # # ]: 0 : nfp_target_cpp(uint32_t cpp_island_id,
955 : : uint64_t cpp_island_address,
956 : : uint32_t *cpp_target_id,
957 : : uint64_t *cpp_target_address,
958 : : const uint32_t *imb_table)
959 : : {
960 : : int err;
961 : : uint32_t imb;
962 : : uint8_t island;
963 : : uint8_t target;
964 : :
965 : : target = NFP_CPP_ID_TARGET_of(cpp_island_id);
966 [ # # ]: 0 : if (target >= 16)
967 : : return -EINVAL;
968 : :
969 : : island = NFP_CPP_ID_ISLAND_of(cpp_island_id);
970 [ # # ]: 0 : if (island == 0) {
971 : : /* Already translated */
972 : 0 : *cpp_target_id = cpp_island_id;
973 : 0 : *cpp_target_address = cpp_island_address;
974 : 0 : return 0;
975 : : }
976 : :
977 : : /* CPP + Island only allowed on systems with IMB tables */
978 [ # # ]: 0 : if (imb_table == NULL)
979 : : return -EINVAL;
980 : :
981 : 0 : imb = imb_table[target];
982 : :
983 : 0 : *cpp_target_address = cpp_island_address;
984 : 0 : err = nfp_cppat_addr_encode(cpp_target_address, island, target,
985 : 0 : ((imb >> 13) & 7), ((imb >> 12) & 1),
986 : 0 : ((imb >> 6) & 0x3f), ((imb >> 0) & 0x3f));
987 [ # # ]: 0 : if (err != 0)
988 : : return err;
989 : :
990 : 0 : *cpp_target_id = NFP_CPP_ID(target,
991 : : NFP_CPP_ID_ACTION_of(cpp_island_id),
992 : : NFP_CPP_ID_TOKEN_of(cpp_island_id));
993 : :
994 : 0 : return 0;
995 : : }
|