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