1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2022 Corigine, Inc. 3 * All rights reserved. 4 */ 5 6 #include "nfp_target.h" 7 8 #include "nfp_cpp.h" 9 #include "nfp6000/nfp6000.h" 10 11 #define P32 1 12 #define P64 2 13 14 /* 15 * All magic NFP-6xxx IMB 'mode' numbers here are from: 16 * Databook (1 August 2013) 17 * - System Overview and Connectivity 18 * -- Internal Connectivity 19 * --- Distributed Switch Fabric - Command Push/Pull (DSF-CPP) Bus 20 * ---- CPP addressing 21 * ----- Table 3.6. CPP Address Translation Mode Commands 22 */ 23 #define NFP6000_MU_LOCALITY_DIRECT 2 24 25 static int 26 target_rw(uint32_t cpp_id, 27 int pp, 28 int start, 29 int len) 30 { 31 uint8_t island; 32 33 island = NFP_CPP_ID_ISLAND_of(cpp_id); 34 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 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 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 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 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 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 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 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 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, 2): /* journal */ 268 return PUSHPULL(P32, 0); 269 case NFP_CPP_ID(0, 21, 0): /* get */ 270 return PUSHPULL(0, P32); 271 case NFP_CPP_ID(0, 21, 1): /* get_eop */ 272 return PUSHPULL(0, P32); 273 case NFP_CPP_ID(0, 21, 2): /* get_freely */ 274 return PUSHPULL(0, P32); 275 case NFP_CPP_ID(0, 22, 0): /* pop */ 276 return PUSHPULL(0, P32); 277 case NFP_CPP_ID(0, 22, 1): /* pop_eop */ 278 return PUSHPULL(0, P32); 279 case NFP_CPP_ID(0, 22, 2): /* pop_freely */ 280 return PUSHPULL(0, P32); 281 default: 282 return nfp6000_mu_common(cpp_id); 283 } 284 } 285 286 static int 287 nfp6000_mu_imu(uint32_t cpp_id) 288 { 289 return nfp6000_mu_common(cpp_id); 290 } 291 292 static int 293 nfp6000_mu(uint32_t cpp_id, 294 uint64_t address) 295 { 296 int pp; 297 uint8_t island; 298 299 island = NFP_CPP_ID_ISLAND_of(cpp_id); 300 if (island == 0) { 301 if (address < 0x2000000000ULL) 302 pp = nfp6000_mu_ctm(cpp_id); 303 else if (address < 0x8000000000ULL) 304 pp = nfp6000_mu_emu(cpp_id); 305 else if (address < 0x9800000000ULL) 306 pp = nfp6000_mu_ctm(cpp_id); 307 else if (address < 0x9C00000000ULL) 308 pp = nfp6000_mu_emu(cpp_id); 309 else if (address < 0xA000000000ULL) 310 pp = nfp6000_mu_imu(cpp_id); 311 else 312 pp = nfp6000_mu_ctm(cpp_id); 313 } else if (island >= 24 && island <= 27) { 314 pp = nfp6000_mu_emu(cpp_id); 315 } else if (island >= 28 && island <= 31) { 316 pp = nfp6000_mu_imu(cpp_id); 317 } else if (island == 1 || 318 (island >= 4 && island <= 7) || 319 (island >= 12 && island <= 13) || 320 (island >= 32 && island <= 51)) { 321 pp = nfp6000_mu_ctm(cpp_id); 322 } else { 323 pp = -EINVAL; 324 } 325 326 return pp; 327 } 328 329 static int 330 nfp6000_ila(uint32_t cpp_id) 331 { 332 uint8_t island; 333 334 island = NFP_CPP_ID_ISLAND_of(cpp_id); 335 if (island != 0 && (island < 48 || island > 51)) 336 return -EINVAL; 337 338 switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) { 339 case NFP_CPP_ID(0, 0, 1): /* read_check_error */ 340 return PUSHPULL(0, P32); 341 case NFP_CPP_ID(0, 2, 0): /* read_int */ 342 return PUSHPULL(0, P32); 343 case NFP_CPP_ID(0, 3, 0): /* write_int */ 344 return PUSHPULL(P32, 0); 345 default: 346 return target_rw(cpp_id, P32, 48, 4); 347 } 348 } 349 350 static int 351 nfp6000_pci(uint32_t cpp_id) 352 { 353 uint8_t island; 354 355 island = NFP_CPP_ID_ISLAND_of(cpp_id); 356 if (island != 0 && (island < 4 || island > 7)) 357 return -EINVAL; 358 359 switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) { 360 case NFP_CPP_ID(0, 2, 0): 361 return PUSHPULL(0, P32); 362 case NFP_CPP_ID(0, 3, 0): 363 return PUSHPULL(P32, 0); 364 default: 365 return target_rw(cpp_id, P32, 4, 4); 366 } 367 } 368 369 static int 370 nfp6000_crypto(uint32_t cpp_id) 371 { 372 uint8_t island; 373 374 island = NFP_CPP_ID_ISLAND_of(cpp_id); 375 if (island != 0 && (island < 12 || island > 15)) 376 return -EINVAL; 377 378 switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) { 379 case NFP_CPP_ID(0, 2, 0): 380 return PUSHPULL(P64, 0); 381 default: 382 return target_rw(cpp_id, P64, 12, 4); 383 } 384 } 385 386 static int 387 nfp6000_cap_xpb(uint32_t cpp_id) 388 { 389 uint8_t island; 390 391 island = NFP_CPP_ID_ISLAND_of(cpp_id); 392 if (island > 63) 393 return -EINVAL; 394 395 switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) { 396 case NFP_CPP_ID(0, 0, 1): /* RingGet */ 397 return PUSHPULL(0, P32); 398 case NFP_CPP_ID(0, 0, 2): /* Interthread Signal */ 399 return PUSHPULL(P32, 0); 400 case NFP_CPP_ID(0, 1, 1): /* RingPut */ 401 return PUSHPULL(P32, 0); 402 case NFP_CPP_ID(0, 1, 2): /* CTNNWr */ 403 return PUSHPULL(P32, 0); 404 case NFP_CPP_ID(0, 2, 0): /* ReflectRd, signal none */ 405 return PUSHPULL(0, P32); 406 case NFP_CPP_ID(0, 2, 1): /* ReflectRd, signal self */ 407 return PUSHPULL(0, P32); 408 case NFP_CPP_ID(0, 2, 2): /* ReflectRd, signal remote */ 409 return PUSHPULL(0, P32); 410 case NFP_CPP_ID(0, 2, 3): /* ReflectRd, signal both */ 411 return PUSHPULL(0, P32); 412 case NFP_CPP_ID(0, 3, 0): /* ReflectWr, signal none */ 413 return PUSHPULL(P32, 0); 414 case NFP_CPP_ID(0, 3, 1): /* ReflectWr, signal self */ 415 return PUSHPULL(P32, 0); 416 case NFP_CPP_ID(0, 3, 2): /* ReflectWr, signal remote */ 417 return PUSHPULL(P32, 0); 418 case NFP_CPP_ID(0, 3, 3): /* ReflectWr, signal both */ 419 return PUSHPULL(P32, 0); 420 case NFP_CPP_ID(0, NFP_CPP_ACTION_RW, 1): 421 return PUSHPULL(P32, P32); 422 default: 423 return target_rw(cpp_id, P32, 1, 63); 424 } 425 } 426 427 static int 428 nfp6000_cls(uint32_t cpp_id) 429 { 430 uint8_t island; 431 432 island = NFP_CPP_ID_ISLAND_of(cpp_id); 433 if (island > 63) 434 return -EINVAL; 435 436 switch (cpp_id & NFP_CPP_ID(0, ~0, ~0)) { 437 case NFP_CPP_ID(0, 0, 3): /* xor */ 438 return PUSHPULL(P32, 0); 439 case NFP_CPP_ID(0, 2, 0): /* set */ 440 return PUSHPULL(P32, 0); 441 case NFP_CPP_ID(0, 2, 1): /* clr */ 442 return PUSHPULL(P32, 0); 443 case NFP_CPP_ID(0, 4, 0): /* add */ 444 return PUSHPULL(P32, 0); 445 case NFP_CPP_ID(0, 4, 1): /* add64 */ 446 return PUSHPULL(P32, 0); 447 case NFP_CPP_ID(0, 6, 0): /* sub */ 448 return PUSHPULL(P32, 0); 449 case NFP_CPP_ID(0, 6, 1): /* sub64 */ 450 return PUSHPULL(P32, 0); 451 case NFP_CPP_ID(0, 6, 2): /* subsat */ 452 return PUSHPULL(P32, 0); 453 case NFP_CPP_ID(0, 8, 2): /* hash_mask */ 454 return PUSHPULL(P32, 0); 455 case NFP_CPP_ID(0, 8, 3): /* hash_clear */ 456 return PUSHPULL(P32, 0); 457 case NFP_CPP_ID(0, 9, 0): /* ring_get */ 458 return PUSHPULL(0, P32); 459 case NFP_CPP_ID(0, 9, 1): /* ring_pop */ 460 return PUSHPULL(0, P32); 461 case NFP_CPP_ID(0, 9, 2): /* ring_get_freely */ 462 return PUSHPULL(0, P32); 463 case NFP_CPP_ID(0, 9, 3): /* ring_pop_freely */ 464 return PUSHPULL(0, P32); 465 case NFP_CPP_ID(0, 10, 0): /* ring_put */ 466 return PUSHPULL(P32, 0); 467 case NFP_CPP_ID(0, 10, 2): /* ring_journal */ 468 return PUSHPULL(P32, 0); 469 case NFP_CPP_ID(0, 14, 0): /* reflect_write_sig_local */ 470 return PUSHPULL(P32, 0); 471 case NFP_CPP_ID(0, 15, 1): /* reflect_read_sig_local */ 472 return PUSHPULL(0, P32); 473 case NFP_CPP_ID(0, 17, 2): /* statistic */ 474 return PUSHPULL(P32, 0); 475 case NFP_CPP_ID(0, 24, 0): /* ring_read */ 476 return PUSHPULL(0, P32); 477 case NFP_CPP_ID(0, 24, 1): /* ring_write */ 478 return PUSHPULL(P32, 0); 479 case NFP_CPP_ID(0, 25, 0): /* ring_workq_add_thread */ 480 return PUSHPULL(0, P32); 481 case NFP_CPP_ID(0, 25, 1): /* ring_workq_add_work */ 482 return PUSHPULL(P32, 0); 483 default: 484 return target_rw(cpp_id, P32, 0, 64); 485 } 486 } 487 488 int 489 nfp_target_pushpull(uint32_t cpp_id, 490 uint64_t address) 491 { 492 switch (NFP_CPP_ID_TARGET_of(cpp_id)) { 493 case NFP_CPP_TARGET_NBI: 494 return nfp6000_nbi(cpp_id, address); 495 case NFP_CPP_TARGET_QDR: 496 return target_rw(cpp_id, P32, 24, 4); 497 case NFP_CPP_TARGET_ILA: 498 return nfp6000_ila(cpp_id); 499 case NFP_CPP_TARGET_MU: 500 return nfp6000_mu(cpp_id, address); 501 case NFP_CPP_TARGET_PCIE: 502 return nfp6000_pci(cpp_id); 503 case NFP_CPP_TARGET_ARM: 504 if (address < 0x10000) 505 return target_rw(cpp_id, P64, 1, 1); 506 else 507 return target_rw(cpp_id, P32, 1, 1); 508 case NFP_CPP_TARGET_CRYPTO: 509 return nfp6000_crypto(cpp_id); 510 case NFP_CPP_TARGET_CT_XPB: 511 return nfp6000_cap_xpb(cpp_id); 512 case NFP_CPP_TARGET_CLS: 513 return nfp6000_cls(cpp_id); 514 case NFP_CPP_TARGET_INVALID: 515 return target_rw(cpp_id, P32, 4, 4); 516 default: 517 return -EINVAL; 518 } 519 } 520 521 static uint64_t 522 nfp_mask64(int msb, 523 int lsb) 524 { 525 int width; 526 527 if (msb < 0 || lsb < 0) 528 return 0; 529 530 width = msb - lsb + 1; 531 if (width <= 0) 532 return 0; 533 534 if (width == 64) 535 return ~(uint64_t)0; 536 537 if ((lsb + width) > 64) 538 return 0; 539 540 return (RTE_BIT64(width) - 1) << lsb; 541 } 542 543 static int 544 nfp_decode_basic(uint64_t addr, 545 int *dest_island, 546 int cpp_tgt, 547 int mode, 548 int addr40, 549 int isld1, 550 int isld0) 551 { 552 int iid_lsb; 553 int idx_lsb; 554 555 /* This function doesn't handle MU or CTXBP */ 556 if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB) 557 return -EINVAL; 558 559 switch (mode) { 560 case 0: 561 /* 562 * For VQDR, in this mode for 32-bit addressing it would be 563 * islands 0, 16, 32 and 48 depending on channel and upper 564 * address bits. Since those are not all valid islands, most 565 * decode cases would result in bad island IDs, but we do them 566 * anyway since this is decoding an address that is already 567 * assumed to be used as-is to get to sram. 568 */ 569 iid_lsb = (addr40) ? 34 : 26; 570 *dest_island = (int)(addr >> iid_lsb) & 0x3F; 571 572 return 0; 573 case 1: 574 /* 575 * For VQDR 32-bit, this would decode as: 576 * Channel 0: island#0 577 * Channel 1: island#0 578 * Channel 2: island#1 579 * Channel 3: island#1 580 * 581 * That would be valid as long as both islands have VQDR. 582 * Let's allow this. 583 */ 584 idx_lsb = (addr40) ? 39 : 31; 585 if ((addr & nfp_mask64(idx_lsb, idx_lsb)) != 0) 586 *dest_island = isld1; 587 else 588 *dest_island = isld0; 589 590 return 0; 591 case 2: 592 /* 593 * For VQDR 32-bit: 594 * Channel 0: (island#0 | 0) 595 * Channel 1: (island#0 | 1) 596 * Channel 2: (island#1 | 0) 597 * Channel 3: (island#1 | 1) 598 * 599 * Make sure we compare against isldN values by clearing the 600 * LSB. This is what the silicon does. 601 */ 602 isld0 &= ~1; 603 isld1 &= ~1; 604 605 idx_lsb = (addr40) ? 39 : 31; 606 iid_lsb = idx_lsb - 1; 607 608 if ((addr & nfp_mask64(idx_lsb, idx_lsb)) != 0) 609 *dest_island = isld1 | (int)((addr >> iid_lsb) & 1); 610 else 611 *dest_island = isld0 | (int)((addr >> iid_lsb) & 1); 612 613 return 0; 614 case 3: 615 /* 616 * In this mode the data address starts to affect the island ID 617 * so rather not allow it. In some really specific case one 618 * could use this to send the upper half of the VQDR channel to 619 * another MU, but this is getting very specific. However, as 620 * above for mode 0, this is the decoder and the caller should 621 * validate the resulting IID. This blindly does what the 622 * silicon would do. 623 */ 624 isld0 &= ~3; 625 isld1 &= ~3; 626 627 idx_lsb = (addr40) ? 39 : 31; 628 iid_lsb = idx_lsb - 2; 629 630 if ((addr & nfp_mask64(idx_lsb, idx_lsb)) != 0) 631 *dest_island = isld1 | (int)((addr >> iid_lsb) & 3); 632 else 633 *dest_island = isld0 | (int)((addr >> iid_lsb) & 3); 634 635 return 0; 636 default: 637 return -EINVAL; 638 } 639 } 640 641 static int 642 nfp_encode_basic_qdr(uint64_t addr, 643 int dest_island, 644 int cpp_tgt, 645 int mode, 646 int addr40, 647 int isld1, 648 int isld0) 649 { 650 int v; 651 int ret; 652 653 /* Full Island ID and channel bits overlap? */ 654 ret = nfp_decode_basic(addr, &v, cpp_tgt, mode, addr40, isld1, isld0); 655 if (ret != 0) 656 return ret; 657 658 /* The current address won't go where expected? */ 659 if (dest_island != -1 && dest_island != v) 660 return -EINVAL; 661 662 /* If dest_island was -1, we don't care where it goes. */ 663 return 0; 664 } 665 666 /* 667 * Try each option, take first one that fits. 668 * Not sure if we would want to do some smarter 669 * searching and prefer 0 or non-0 island IDs. 670 */ 671 static int 672 nfp_encode_basic_search(uint64_t *addr, 673 int dest_island, 674 int *isld, 675 int iid_lsb, 676 int idx_lsb, 677 int v_max) 678 { 679 int i; 680 int v; 681 682 for (i = 0; i < 2; i++) 683 for (v = 0; v < v_max; v++) { 684 if (dest_island != (isld[i] | v)) 685 continue; 686 687 *addr &= ~nfp_mask64(idx_lsb, iid_lsb); 688 *addr |= ((uint64_t)i << idx_lsb); 689 *addr |= ((uint64_t)v << iid_lsb); 690 return 0; 691 } 692 693 return -ENODEV; 694 } 695 696 /* 697 * For VQDR, we may not modify the Channel bits, which might overlap 698 * with the Index bit. When it does, we need to ensure that isld0 == isld1. 699 */ 700 static int 701 nfp_encode_basic(uint64_t *addr, 702 int dest_island, 703 int cpp_tgt, 704 int mode, 705 int addr40, 706 int isld1, 707 int isld0) 708 { 709 int iid_lsb; 710 int idx_lsb; 711 int isld[2]; 712 uint64_t value; 713 714 isld[0] = isld0; 715 isld[1] = isld1; 716 717 /* This function doesn't handle MU or CTXBP */ 718 if (cpp_tgt == NFP_CPP_TARGET_MU || cpp_tgt == NFP_CPP_TARGET_CT_XPB) 719 return -EINVAL; 720 721 switch (mode) { 722 case 0: 723 if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) { 724 /* 725 * In this specific mode we'd rather not modify the 726 * address but we can verify if the existing contents 727 * will point to a valid island. 728 */ 729 return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island, 730 mode, addr40, isld1, isld0); 731 } 732 733 iid_lsb = (addr40) ? 34 : 26; 734 735 /* <39:34> or <31:26> */ 736 value = nfp_mask64((iid_lsb + 5), iid_lsb); 737 *addr &= ~value; 738 *addr |= (((uint64_t)dest_island) << iid_lsb) & value; 739 return 0; 740 case 1: 741 if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) { 742 return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island, 743 mode, addr40, isld1, isld0); 744 } 745 746 idx_lsb = (addr40) ? 39 : 31; 747 if (dest_island == isld0) { 748 /* Only need to clear the Index bit */ 749 *addr &= ~nfp_mask64(idx_lsb, idx_lsb); 750 return 0; 751 } 752 753 if (dest_island == isld1) { 754 /* Only need to set the Index bit */ 755 *addr |= (UINT64_C(1) << idx_lsb); 756 return 0; 757 } 758 759 return -ENODEV; 760 case 2: 761 if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) { 762 /* iid<0> = addr<30> = channel<0> */ 763 /* channel<1> = addr<31> = Index */ 764 return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island, 765 mode, addr40, isld1, isld0); 766 } 767 768 /* 769 * Make sure we compare against isldN values by clearing the 770 * LSB. This is what the silicon does. 771 */ 772 isld[0] &= ~1; 773 isld[1] &= ~1; 774 775 idx_lsb = (addr40) ? 39 : 31; 776 iid_lsb = idx_lsb - 1; 777 778 return nfp_encode_basic_search(addr, dest_island, isld, 779 iid_lsb, idx_lsb, 2); 780 case 3: 781 if (cpp_tgt == NFP_CPP_TARGET_QDR && addr40 == 0) { 782 /* 783 * iid<0> = addr<29> = data 784 * iid<1> = addr<30> = channel<0> 785 * channel<1> = addr<31> = Index 786 */ 787 return nfp_encode_basic_qdr(*addr, cpp_tgt, dest_island, 788 mode, addr40, isld1, isld0); 789 } 790 791 isld[0] &= ~3; 792 isld[1] &= ~3; 793 794 idx_lsb = (addr40) ? 39 : 31; 795 iid_lsb = idx_lsb - 2; 796 797 return nfp_encode_basic_search(addr, dest_island, isld, 798 iid_lsb, idx_lsb, 4); 799 default: 800 return -EINVAL; 801 } 802 } 803 804 static int 805 nfp_encode_mu(uint64_t *addr, 806 int dest_island, 807 int mode, 808 int addr40, 809 int isld1, 810 int isld0) 811 { 812 int da; 813 int iid_lsb; 814 int idx_lsb; 815 int isld[2]; 816 uint64_t value; 817 int locality_lsb; 818 819 isld[0] = isld0; 820 isld[1] = isld1; 821 822 locality_lsb = nfp_cppat_mu_locality_lsb(mode, addr40); 823 if (locality_lsb < 0) 824 return -EINVAL; 825 826 if (((*addr >> locality_lsb) & 3) == NFP6000_MU_LOCALITY_DIRECT) 827 da = 1; 828 else 829 da = 0; 830 831 switch (mode) { 832 case 0: 833 iid_lsb = (addr40 != 0) ? 32 : 24; 834 value = nfp_mask64((iid_lsb + 5), iid_lsb); 835 *addr &= ~value; 836 *addr |= (((uint64_t)dest_island) << iid_lsb) & value; 837 return 0; 838 case 1: 839 if (da == 1) { 840 iid_lsb = (addr40 != 0) ? 32 : 24; 841 value = nfp_mask64((iid_lsb + 5), iid_lsb); 842 *addr &= ~value; 843 *addr |= (((uint64_t)dest_island) << iid_lsb) & value; 844 return 0; 845 } 846 847 idx_lsb = (addr40 != 0) ? 37 : 29; 848 if (dest_island == isld0) { 849 *addr &= ~nfp_mask64(idx_lsb, idx_lsb); 850 return 0; 851 } 852 853 if (dest_island == isld1) { 854 *addr |= (UINT64_C(1) << idx_lsb); 855 return 0; 856 } 857 858 return -ENODEV; 859 case 2: 860 if (da == 1) { 861 iid_lsb = (addr40 != 0) ? 32 : 24; 862 value = nfp_mask64((iid_lsb + 5), iid_lsb); 863 *addr &= ~value; 864 *addr |= (((uint64_t)dest_island) << iid_lsb) & value; 865 return 0; 866 } 867 868 /* 869 * Make sure we compare against isldN values by clearing the 870 * LSB. This is what the silicon does. 871 */ 872 isld[0] &= ~1; 873 isld[1] &= ~1; 874 875 idx_lsb = (addr40 != 0) ? 37 : 29; 876 iid_lsb = idx_lsb - 1; 877 878 return nfp_encode_basic_search(addr, dest_island, isld, 879 iid_lsb, idx_lsb, 2); 880 case 3: 881 /* 882 * Only the EMU will use 40 bit addressing. Silently set the 883 * direct locality bit for everyone else. The SDK toolchain 884 * uses dest_island <= 0 to test for atypical address encodings 885 * to support access to local-island CTM with a 32-but address 886 * (high-locality is effectively ignored and just used for 887 * routing to island #0). 888 */ 889 if (dest_island > 0 && (dest_island < 24 || dest_island > 26)) { 890 *addr |= ((uint64_t)NFP6000_MU_LOCALITY_DIRECT) 891 << locality_lsb; 892 da = 1; 893 } 894 895 if (da == 1) { 896 iid_lsb = (addr40 != 0) ? 32 : 24; 897 value = nfp_mask64((iid_lsb + 5), iid_lsb); 898 *addr &= ~value; 899 *addr |= (((uint64_t)dest_island) << iid_lsb) & value; 900 return 0; 901 } 902 903 isld[0] &= ~3; 904 isld[1] &= ~3; 905 906 idx_lsb = (addr40 != 0) ? 37 : 29; 907 iid_lsb = idx_lsb - 2; 908 909 return nfp_encode_basic_search(addr, dest_island, isld, 910 iid_lsb, idx_lsb, 4); 911 default: 912 return -EINVAL; 913 } 914 } 915 916 static int 917 nfp_cppat_addr_encode(uint64_t *addr, 918 int dest_island, 919 int cpp_tgt, 920 int mode, 921 int addr40, 922 int isld1, 923 int isld0) 924 { 925 uint64_t value; 926 927 switch (cpp_tgt) { 928 case NFP_CPP_TARGET_NBI: 929 case NFP_CPP_TARGET_QDR: 930 case NFP_CPP_TARGET_ILA: 931 case NFP_CPP_TARGET_PCIE: 932 case NFP_CPP_TARGET_ARM: 933 case NFP_CPP_TARGET_CRYPTO: 934 case NFP_CPP_TARGET_CLS: 935 return nfp_encode_basic(addr, dest_island, cpp_tgt, mode, 936 addr40, isld1, isld0); 937 case NFP_CPP_TARGET_MU: 938 return nfp_encode_mu(addr, dest_island, mode, addr40, 939 isld1, isld0); 940 case NFP_CPP_TARGET_CT_XPB: 941 if (mode != 1 || addr40 != 0) 942 return -EINVAL; 943 944 value = nfp_mask64(29, 24); 945 *addr &= ~value; 946 *addr |= (((uint64_t)dest_island) << 24) & value; 947 return 0; 948 default: 949 return -EINVAL; 950 } 951 } 952 953 int 954 nfp_target_cpp(uint32_t cpp_island_id, 955 uint64_t cpp_island_address, 956 uint32_t *cpp_target_id, 957 uint64_t *cpp_target_address, 958 const uint32_t *imb_table) 959 { 960 int err; 961 uint32_t imb; 962 uint8_t island; 963 uint8_t target; 964 965 target = NFP_CPP_ID_TARGET_of(cpp_island_id); 966 if (target >= 16) 967 return -EINVAL; 968 969 island = NFP_CPP_ID_ISLAND_of(cpp_island_id); 970 if (island == 0) { 971 /* Already translated */ 972 *cpp_target_id = cpp_island_id; 973 *cpp_target_address = cpp_island_address; 974 return 0; 975 } 976 977 /* CPP + Island only allowed on systems with IMB tables */ 978 if (imb_table == NULL) 979 return -EINVAL; 980 981 imb = imb_table[target]; 982 983 *cpp_target_address = cpp_island_address; 984 err = nfp_cppat_addr_encode(cpp_target_address, island, target, 985 ((imb >> 13) & 7), ((imb >> 12) & 1), 986 ((imb >> 6) & 0x3f), ((imb >> 0) & 0x3f)); 987 if (err != 0) 988 return err; 989 990 *cpp_target_id = NFP_CPP_ID(target, 991 NFP_CPP_ID_ACTION_of(cpp_island_id), 992 NFP_CPP_ID_TOKEN_of(cpp_island_id)); 993 994 return 0; 995 } 996