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