New upstream version 18.08
[deb_dpdk.git] / drivers / net / nfp / nfpcore / nfp_target.h
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
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
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
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
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
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
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
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
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
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
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
275 nfp6000_mu_imu(uint32_t cpp_id)
276 {
277         return nfp6000_mu_common(cpp_id);
278 }
279
280 static inline int
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
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
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
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
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
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
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
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
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
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
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 */