1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Netronome Systems, Inc.
3  * All rights reserved.
4  */
5 
6 #ifndef NFP_TARGET_H
7 #define NFP_TARGET_H
8 
9 #include "nfp-common/nfp_resid.h"
10 #include "nfp-common/nfp_cppat.h"
11 #include "nfp-common/nfp_platform.h"
12 #include "nfp_cpp.h"
13 
14 #define P32 1
15 #define P64 2
16 
17 #define PUSHPULL(_pull, _push) (((_pull) << 4) | ((_push) << 0))
18 
19 #ifndef NFP_ERRNO
20 #include <errno.h>
21 #define NFP_ERRNO(x)    (errno = (x), -1)
22 #endif
23 
24 static inline int
pushpull_width(int pp)25 pushpull_width(int pp)
26 {
27 	pp &= 0xf;
28 
29 	if (pp == 0)
30 		return NFP_ERRNO(EINVAL);
31 	return (2 << pp);
32 }
33 
34 #define PUSH_WIDTH(_pushpull)      pushpull_width((_pushpull) >> 0)
35 #define PULL_WIDTH(_pushpull)      pushpull_width((_pushpull) >> 4)
36 
37 static inline int
target_rw(uint32_t cpp_id,int pp,int start,int len)38 target_rw(uint32_t cpp_id, int pp, int start, int len)
39 {
40 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
41 
42 	if (island && (island < start || island > (start + len)))
43 		return NFP_ERRNO(EINVAL);
44 
45 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
46 	case NFP_CPP_ID(0, 0, 0):
47 		return PUSHPULL(0, pp);
48 	case NFP_CPP_ID(0, 1, 0):
49 		return PUSHPULL(pp, 0);
50 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
51 		return PUSHPULL(pp, pp);
52 	default:
53 		return NFP_ERRNO(EINVAL);
54 	}
55 }
56 
57 static inline int
nfp6000_nbi_dma(uint32_t cpp_id)58 nfp6000_nbi_dma(uint32_t cpp_id)
59 {
60 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
61 	case NFP_CPP_ID(0, 0, 0): /* ReadNbiDma */
62 		return PUSHPULL(0, P64);
63 	case NFP_CPP_ID(0, 1, 0): /* WriteNbiDma */
64 		return PUSHPULL(P64, 0);
65 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
66 		return PUSHPULL(P64, P64);
67 	default:
68 		return NFP_ERRNO(EINVAL);
69 	}
70 }
71 
72 static inline int
nfp6000_nbi_stats(uint32_t cpp_id)73 nfp6000_nbi_stats(uint32_t cpp_id)
74 {
75 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
76 	case NFP_CPP_ID(0, 0, 0): /* ReadNbiStats */
77 		return PUSHPULL(0, P64);
78 	case NFP_CPP_ID(0, 1, 0): /* WriteNbiStats */
79 		return PUSHPULL(P64, 0);
80 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
81 		return PUSHPULL(P64, P64);
82 	default:
83 		return NFP_ERRNO(EINVAL);
84 	}
85 }
86 
87 static inline int
nfp6000_nbi_tm(uint32_t cpp_id)88 nfp6000_nbi_tm(uint32_t cpp_id)
89 {
90 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
91 	case NFP_CPP_ID(0, 0, 0): /* ReadNbiTM */
92 		return PUSHPULL(0, P64);
93 	case NFP_CPP_ID(0, 1, 0):  /* WriteNbiTM */
94 		return PUSHPULL(P64, 0);
95 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
96 		return PUSHPULL(P64, P64);
97 	default:
98 		return NFP_ERRNO(EINVAL);
99 	}
100 }
101 
102 static inline int
nfp6000_nbi_ppc(uint32_t cpp_id)103 nfp6000_nbi_ppc(uint32_t cpp_id)
104 {
105 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
106 	case NFP_CPP_ID(0, 0, 0): /* ReadNbiPreclassifier */
107 		return PUSHPULL(0, P64);
108 	case NFP_CPP_ID(0, 1, 0): /* WriteNbiPreclassifier */
109 		return PUSHPULL(P64, 0);
110 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0):
111 		return PUSHPULL(P64, P64);
112 	default:
113 		return NFP_ERRNO(EINVAL);
114 	}
115 }
116 
117 static inline int
nfp6000_nbi(uint32_t cpp_id,uint64_t address)118 nfp6000_nbi(uint32_t cpp_id, uint64_t address)
119 {
120 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
121 	uint64_t rel_addr = address & 0x3fFFFF;
122 
123 	if (island && (island < 8 || island > 9))
124 		return NFP_ERRNO(EINVAL);
125 
126 	if (rel_addr < (1 << 20))
127 		return nfp6000_nbi_dma(cpp_id);
128 	if (rel_addr < (2 << 20))
129 		return nfp6000_nbi_stats(cpp_id);
130 	if (rel_addr < (3 << 20))
131 		return nfp6000_nbi_tm(cpp_id);
132 	return nfp6000_nbi_ppc(cpp_id);
133 }
134 
135 /*
136  * This structure ONLY includes items that can be done with a read or write of
137  * 32-bit or 64-bit words. All others are not listed.
138  */
139 static inline int
nfp6000_mu_common(uint32_t cpp_id)140 nfp6000_mu_common(uint32_t cpp_id)
141 {
142 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
143 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 0): /* read_be/write_be */
144 		return PUSHPULL(P64, P64);
145 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 1): /* read_le/write_le */
146 		return PUSHPULL(P64, P64);
147 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 2): /* {read/write}_swap_be */
148 		return PUSHPULL(P64, P64);
149 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 3): /* {read/write}_swap_le */
150 		return PUSHPULL(P64, P64);
151 	case NFP_CPP_ID(0, 0, 0): /* read_be */
152 		return PUSHPULL(0, P64);
153 	case NFP_CPP_ID(0, 0, 1): /* read_le */
154 		return PUSHPULL(0, P64);
155 	case NFP_CPP_ID(0, 0, 2): /* read_swap_be */
156 		return PUSHPULL(0, P64);
157 	case NFP_CPP_ID(0, 0, 3): /* read_swap_le */
158 		return PUSHPULL(0, P64);
159 	case NFP_CPP_ID(0, 1, 0): /* write_be */
160 		return PUSHPULL(P64, 0);
161 	case NFP_CPP_ID(0, 1, 1): /* write_le */
162 		return PUSHPULL(P64, 0);
163 	case NFP_CPP_ID(0, 1, 2): /* write_swap_be */
164 		return PUSHPULL(P64, 0);
165 	case NFP_CPP_ID(0, 1, 3): /* write_swap_le */
166 		return PUSHPULL(P64, 0);
167 	case NFP_CPP_ID(0, 3, 0): /* atomic_read */
168 		return PUSHPULL(0, P32);
169 	case NFP_CPP_ID(0, 3, 2): /* mask_compare_write */
170 		return PUSHPULL(P32, 0);
171 	case NFP_CPP_ID(0, 4, 0): /* atomic_write */
172 		return PUSHPULL(P32, 0);
173 	case NFP_CPP_ID(0, 4, 2): /* atomic_write_imm */
174 		return PUSHPULL(0, 0);
175 	case NFP_CPP_ID(0, 4, 3): /* swap_imm */
176 		return PUSHPULL(0, P32);
177 	case NFP_CPP_ID(0, 5, 0): /* set */
178 		return PUSHPULL(P32, 0);
179 	case NFP_CPP_ID(0, 5, 3): /* test_set_imm */
180 		return PUSHPULL(0, P32);
181 	case NFP_CPP_ID(0, 6, 0): /* clr */
182 		return PUSHPULL(P32, 0);
183 	case NFP_CPP_ID(0, 6, 3): /* test_clr_imm */
184 		return PUSHPULL(0, P32);
185 	case NFP_CPP_ID(0, 7, 0): /* add */
186 		return PUSHPULL(P32, 0);
187 	case NFP_CPP_ID(0, 7, 3): /* test_add_imm */
188 		return PUSHPULL(0, P32);
189 	case NFP_CPP_ID(0, 8, 0): /* addsat */
190 		return PUSHPULL(P32, 0);
191 	case NFP_CPP_ID(0, 8, 3): /* test_subsat_imm */
192 		return PUSHPULL(0, P32);
193 	case NFP_CPP_ID(0, 9, 0): /* sub */
194 		return PUSHPULL(P32, 0);
195 	case NFP_CPP_ID(0, 9, 3): /* test_sub_imm */
196 		return PUSHPULL(0, P32);
197 	case NFP_CPP_ID(0, 10, 0): /* subsat */
198 		return PUSHPULL(P32, 0);
199 	case NFP_CPP_ID(0, 10, 3): /* test_subsat_imm */
200 		return PUSHPULL(0, P32);
201 	case NFP_CPP_ID(0, 13, 0): /* microq128_get */
202 		return PUSHPULL(0, P32);
203 	case NFP_CPP_ID(0, 13, 1): /* microq128_pop */
204 		return PUSHPULL(0, P32);
205 	case NFP_CPP_ID(0, 13, 2): /* microq128_put */
206 		return PUSHPULL(P32, 0);
207 	case NFP_CPP_ID(0, 15, 0): /* xor */
208 		return PUSHPULL(P32, 0);
209 	case NFP_CPP_ID(0, 15, 3): /* test_xor_imm */
210 		return PUSHPULL(0, P32);
211 	case NFP_CPP_ID(0, 28, 0): /* read32_be */
212 		return PUSHPULL(0, P32);
213 	case NFP_CPP_ID(0, 28, 1): /* read32_le */
214 		return PUSHPULL(0, P32);
215 	case NFP_CPP_ID(0, 28, 2): /* read32_swap_be */
216 		return PUSHPULL(0, P32);
217 	case NFP_CPP_ID(0, 28, 3): /* read32_swap_le */
218 		return PUSHPULL(0, P32);
219 	case NFP_CPP_ID(0, 31, 0): /* write32_be */
220 		return PUSHPULL(P32, 0);
221 	case NFP_CPP_ID(0, 31, 1): /* write32_le */
222 		return PUSHPULL(P32, 0);
223 	case NFP_CPP_ID(0, 31, 2): /* write32_swap_be */
224 		return PUSHPULL(P32, 0);
225 	case NFP_CPP_ID(0, 31, 3): /* write32_swap_le */
226 		return PUSHPULL(P32, 0);
227 	default:
228 		return NFP_ERRNO(EINVAL);
229 	}
230 }
231 
232 static inline int
nfp6000_mu_ctm(uint32_t cpp_id)233 nfp6000_mu_ctm(uint32_t cpp_id)
234 {
235 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
236 	case NFP_CPP_ID(0, 16, 1): /* packet_read_packet_status */
237 		return PUSHPULL(0, P32);
238 	default:
239 		return nfp6000_mu_common(cpp_id);
240 	}
241 }
242 
243 static inline int
nfp6000_mu_emu(uint32_t cpp_id)244 nfp6000_mu_emu(uint32_t cpp_id)
245 {
246 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
247 	case NFP_CPP_ID(0, 18, 0): /* read_queue */
248 		return PUSHPULL(0, P32);
249 	case NFP_CPP_ID(0, 18, 1): /* read_queue_ring */
250 		return PUSHPULL(0, P32);
251 	case NFP_CPP_ID(0, 18, 2): /* write_queue */
252 		return PUSHPULL(P32, 0);
253 	case NFP_CPP_ID(0, 18, 3): /* write_queue_ring */
254 		return PUSHPULL(P32, 0);
255 	case NFP_CPP_ID(0, 20, 2): /* journal */
256 		return PUSHPULL(P32, 0);
257 	case NFP_CPP_ID(0, 21, 0): /* get */
258 		return PUSHPULL(0, P32);
259 	case NFP_CPP_ID(0, 21, 1): /* get_eop */
260 		return PUSHPULL(0, P32);
261 	case NFP_CPP_ID(0, 21, 2): /* get_freely */
262 		return PUSHPULL(0, P32);
263 	case NFP_CPP_ID(0, 22, 0): /* pop */
264 		return PUSHPULL(0, P32);
265 	case NFP_CPP_ID(0, 22, 1): /* pop_eop */
266 		return PUSHPULL(0, P32);
267 	case NFP_CPP_ID(0, 22, 2): /* pop_freely */
268 		return PUSHPULL(0, P32);
269 	default:
270 		return nfp6000_mu_common(cpp_id);
271 	}
272 }
273 
274 static inline int
nfp6000_mu_imu(uint32_t cpp_id)275 nfp6000_mu_imu(uint32_t cpp_id)
276 {
277 	return nfp6000_mu_common(cpp_id);
278 }
279 
280 static inline int
nfp6000_mu(uint32_t cpp_id,uint64_t address)281 nfp6000_mu(uint32_t cpp_id, uint64_t address)
282 {
283 	int pp;
284 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
285 
286 	if (island == 0) {
287 		if (address < 0x2000000000ULL)
288 			pp = nfp6000_mu_ctm(cpp_id);
289 		else if (address < 0x8000000000ULL)
290 			pp = nfp6000_mu_emu(cpp_id);
291 		else if (address < 0x9800000000ULL)
292 			pp = nfp6000_mu_ctm(cpp_id);
293 		else if (address < 0x9C00000000ULL)
294 			pp = nfp6000_mu_emu(cpp_id);
295 		else if (address < 0xA000000000ULL)
296 			pp = nfp6000_mu_imu(cpp_id);
297 		else
298 			pp = nfp6000_mu_ctm(cpp_id);
299 	} else if (island >= 24 && island <= 27) {
300 		pp = nfp6000_mu_emu(cpp_id);
301 	} else if (island >= 28 && island <= 31) {
302 		pp = nfp6000_mu_imu(cpp_id);
303 	} else if (island == 1 ||
304 		   (island >= 4 && island <= 7) ||
305 		   (island >= 12 && island <= 13) ||
306 		   (island >= 32 && island <= 47) ||
307 		   (island >= 48 && island <= 51)) {
308 		pp = nfp6000_mu_ctm(cpp_id);
309 	} else {
310 		pp = NFP_ERRNO(EINVAL);
311 	}
312 
313 	return pp;
314 }
315 
316 static inline int
nfp6000_ila(uint32_t cpp_id)317 nfp6000_ila(uint32_t cpp_id)
318 {
319 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
320 
321 	if (island && (island < 48 || island > 51))
322 		return NFP_ERRNO(EINVAL);
323 
324 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
325 	case NFP_CPP_ID(0, 0, 1): /* read_check_error */
326 		return PUSHPULL(0, P32);
327 	case NFP_CPP_ID(0, 2, 0): /* read_int */
328 		return PUSHPULL(0, P32);
329 	case NFP_CPP_ID(0, 3, 0): /* write_int */
330 		return PUSHPULL(P32, 0);
331 	default:
332 		return target_rw(cpp_id, P32, 48, 4);
333 	}
334 }
335 
336 static inline int
nfp6000_pci(uint32_t cpp_id)337 nfp6000_pci(uint32_t cpp_id)
338 {
339 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
340 
341 	if (island && (island < 4 || island > 7))
342 		return NFP_ERRNO(EINVAL);
343 
344 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
345 	case NFP_CPP_ID(0, 2, 0):
346 		return PUSHPULL(0, P32);
347 	case NFP_CPP_ID(0, 3, 0):
348 		return PUSHPULL(P32, 0);
349 	default:
350 		return target_rw(cpp_id, P32, 4, 4);
351 	}
352 }
353 
354 static inline int
nfp6000_crypto(uint32_t cpp_id)355 nfp6000_crypto(uint32_t cpp_id)
356 {
357 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
358 
359 	if (island && (island < 12 || island > 15))
360 		return NFP_ERRNO(EINVAL);
361 
362 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
363 	case NFP_CPP_ID(0, 2, 0):
364 		return PUSHPULL(P64, 0);
365 	default:
366 		return target_rw(cpp_id, P64, 12, 4);
367 	}
368 }
369 
370 static inline int
nfp6000_cap_xpb(uint32_t cpp_id)371 nfp6000_cap_xpb(uint32_t cpp_id)
372 {
373 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
374 
375 	if (island && (island < 1 || island > 63))
376 		return NFP_ERRNO(EINVAL);
377 
378 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
379 	case NFP_CPP_ID(0, 0, 1): /* RingGet */
380 		return PUSHPULL(0, P32);
381 	case NFP_CPP_ID(0, 0, 2): /* Interthread Signal */
382 		return PUSHPULL(P32, 0);
383 	case NFP_CPP_ID(0, 1, 1): /* RingPut */
384 		return PUSHPULL(P32, 0);
385 	case NFP_CPP_ID(0, 1, 2): /* CTNNWr */
386 		return PUSHPULL(P32, 0);
387 	case NFP_CPP_ID(0, 2, 0): /* ReflectRd, signal none */
388 		return PUSHPULL(0, P32);
389 	case NFP_CPP_ID(0, 2, 1): /* ReflectRd, signal self */
390 		return PUSHPULL(0, P32);
391 	case NFP_CPP_ID(0, 2, 2): /* ReflectRd, signal remote */
392 		return PUSHPULL(0, P32);
393 	case NFP_CPP_ID(0, 2, 3): /* ReflectRd, signal both */
394 		return PUSHPULL(0, P32);
395 	case NFP_CPP_ID(0, 3, 0): /* ReflectWr, signal none */
396 		return PUSHPULL(P32, 0);
397 	case NFP_CPP_ID(0, 3, 1): /* ReflectWr, signal self */
398 		return PUSHPULL(P32, 0);
399 	case NFP_CPP_ID(0, 3, 2): /* ReflectWr, signal remote */
400 		return PUSHPULL(P32, 0);
401 	case NFP_CPP_ID(0, 3, 3): /* ReflectWr, signal both */
402 		return PUSHPULL(P32, 0);
403 	case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 1):
404 		return PUSHPULL(P32, P32);
405 	default:
406 		return target_rw(cpp_id, P32, 1, 63);
407 	}
408 }
409 
410 static inline int
nfp6000_cls(uint32_t cpp_id)411 nfp6000_cls(uint32_t cpp_id)
412 {
413 	int island = NFP_CPP_ID_ISLAND_of(cpp_id);
414 
415 	if (island && (island < 1 || island > 63))
416 		return NFP_ERRNO(EINVAL);
417 
418 	switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) {
419 	case NFP_CPP_ID(0, 0, 3): /* xor */
420 		return PUSHPULL(P32, 0);
421 	case NFP_CPP_ID(0, 2, 0): /* set */
422 		return PUSHPULL(P32, 0);
423 	case NFP_CPP_ID(0, 2, 1): /* clr */
424 		return PUSHPULL(P32, 0);
425 	case NFP_CPP_ID(0, 4, 0): /* add */
426 		return PUSHPULL(P32, 0);
427 	case NFP_CPP_ID(0, 4, 1): /* add64 */
428 		return PUSHPULL(P32, 0);
429 	case NFP_CPP_ID(0, 6, 0): /* sub */
430 		return PUSHPULL(P32, 0);
431 	case NFP_CPP_ID(0, 6, 1): /* sub64 */
432 		return PUSHPULL(P32, 0);
433 	case NFP_CPP_ID(0, 6, 2): /* subsat */
434 		return PUSHPULL(P32, 0);
435 	case NFP_CPP_ID(0, 8, 2): /* hash_mask */
436 		return PUSHPULL(P32, 0);
437 	case NFP_CPP_ID(0, 8, 3): /* hash_clear */
438 		return PUSHPULL(P32, 0);
439 	case NFP_CPP_ID(0, 9, 0): /* ring_get */
440 		return PUSHPULL(0, P32);
441 	case NFP_CPP_ID(0, 9, 1): /* ring_pop */
442 		return PUSHPULL(0, P32);
443 	case NFP_CPP_ID(0, 9, 2): /* ring_get_freely */
444 		return PUSHPULL(0, P32);
445 	case NFP_CPP_ID(0, 9, 3): /* ring_pop_freely */
446 		return PUSHPULL(0, P32);
447 	case NFP_CPP_ID(0, 10, 0): /* ring_put */
448 		return PUSHPULL(P32, 0);
449 	case NFP_CPP_ID(0, 10, 2): /* ring_journal */
450 		return PUSHPULL(P32, 0);
451 	case NFP_CPP_ID(0, 14, 0): /* reflect_write_sig_local */
452 		return PUSHPULL(P32, 0);
453 	case NFP_CPP_ID(0, 15, 1):  /* reflect_read_sig_local */
454 		return PUSHPULL(0, P32);
455 	case NFP_CPP_ID(0, 17, 2): /* statistic */
456 		return PUSHPULL(P32, 0);
457 	case NFP_CPP_ID(0, 24, 0): /* ring_read */
458 		return PUSHPULL(0, P32);
459 	case NFP_CPP_ID(0, 24, 1): /* ring_write */
460 		return PUSHPULL(P32, 0);
461 	case NFP_CPP_ID(0, 25, 0): /* ring_workq_add_thread */
462 		return PUSHPULL(0, P32);
463 	case NFP_CPP_ID(0, 25, 1): /* ring_workq_add_work */
464 		return PUSHPULL(P32, 0);
465 	default:
466 		return target_rw(cpp_id, P32, 0, 64);
467 	}
468 }
469 
470 static inline int
nfp6000_target_pushpull(uint32_t cpp_id,uint64_t address)471 nfp6000_target_pushpull(uint32_t cpp_id, uint64_t address)
472 {
473 	switch (NFP_CPP_ID_TARGET_of(cpp_id)) {
474 	case NFP6000_CPPTGT_NBI:
475 		return nfp6000_nbi(cpp_id, address);
476 	case NFP6000_CPPTGT_VQDR:
477 		return target_rw(cpp_id, P32, 24, 4);
478 	case NFP6000_CPPTGT_ILA:
479 		return nfp6000_ila(cpp_id);
480 	case NFP6000_CPPTGT_MU:
481 		return nfp6000_mu(cpp_id, address);
482 	case NFP6000_CPPTGT_PCIE:
483 		return nfp6000_pci(cpp_id);
484 	case NFP6000_CPPTGT_ARM:
485 		if (address < 0x10000)
486 			return target_rw(cpp_id, P64, 1, 1);
487 		else
488 			return target_rw(cpp_id, P32, 1, 1);
489 	case NFP6000_CPPTGT_CRYPTO:
490 		return nfp6000_crypto(cpp_id);
491 	case NFP6000_CPPTGT_CTXPB:
492 		return nfp6000_cap_xpb(cpp_id);
493 	case NFP6000_CPPTGT_CLS:
494 		return nfp6000_cls(cpp_id);
495 	case 0:
496 		return target_rw(cpp_id, P32, 4, 4);
497 	default:
498 		return NFP_ERRNO(EINVAL);
499 	}
500 }
501 
502 static inline int
nfp_target_pushpull_width(int pp,int write_not_read)503 nfp_target_pushpull_width(int pp, int write_not_read)
504 {
505 	if (pp < 0)
506 		return pp;
507 
508 	if (write_not_read)
509 		return PULL_WIDTH(pp);
510 	else
511 		return PUSH_WIDTH(pp);
512 }
513 
514 static inline int
nfp6000_target_action_width(uint32_t cpp_id,uint64_t address,int write_not_read)515 nfp6000_target_action_width(uint32_t cpp_id, uint64_t address,
516 			    int write_not_read)
517 {
518 	int pp;
519 
520 	pp = nfp6000_target_pushpull(cpp_id, address);
521 
522 	return nfp_target_pushpull_width(pp, write_not_read);
523 }
524 
525 static inline int
nfp_target_action_width(uint32_t model,uint32_t cpp_id,uint64_t address,int write_not_read)526 nfp_target_action_width(uint32_t model, uint32_t cpp_id, uint64_t address,
527 			int write_not_read)
528 {
529 	if (NFP_CPP_MODEL_IS_6000(model)) {
530 		return nfp6000_target_action_width(cpp_id, address,
531 						   write_not_read);
532 	} else {
533 		return NFP_ERRNO(EINVAL);
534 	}
535 }
536 
537 static inline 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)538 nfp_target_cpp(uint32_t cpp_island_id, uint64_t cpp_island_address,
539 	       uint32_t *cpp_target_id, uint64_t *cpp_target_address,
540 	       const uint32_t *imb_table)
541 {
542 	int err;
543 	int island = NFP_CPP_ID_ISLAND_of(cpp_island_id);
544 	int target = NFP_CPP_ID_TARGET_of(cpp_island_id);
545 	uint32_t imb;
546 
547 	if (target < 0 || target >= 16)
548 		return NFP_ERRNO(EINVAL);
549 
550 	if (island == 0) {
551 		/* Already translated */
552 		*cpp_target_id = cpp_island_id;
553 		*cpp_target_address = cpp_island_address;
554 		return 0;
555 	}
556 
557 	if (!imb_table) {
558 		/* CPP + Island only allowed on systems with IMB tables */
559 		return NFP_ERRNO(EINVAL);
560 	}
561 
562 	imb = imb_table[target];
563 
564 	*cpp_target_address = cpp_island_address;
565 	err = _nfp6000_cppat_addr_encode(cpp_target_address, island, target,
566 					 ((imb >> 13) & 7),
567 					 ((imb >> 12) & 1),
568 					 ((imb >> 6) & 0x3f),
569 					 ((imb >> 0) & 0x3f));
570 	if (err == 0) {
571 		*cpp_target_id =
572 		    NFP_CPP_ID(target, NFP_CPP_ID_ACTION_of(cpp_island_id),
573 			       NFP_CPP_ID_TOKEN_of(cpp_island_id));
574 	}
575 
576 	return err;
577 }
578 
579 #endif /* NFP_TARGET_H */
580