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