1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Netronome Systems, Inc. 3 * All rights reserved. 4 */ 5 6 #include <assert.h> 7 #include <stdint.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <stdlib.h> 11 #include <errno.h> 12 #include <sys/types.h> 13 14 #include <rte_byteorder.h> 15 16 #include "nfp_cpp.h" 17 #include "nfp_target.h" 18 #include "nfp6000/nfp6000.h" 19 #include "nfp6000/nfp_xpb.h" 20 #include "nfp_nffw.h" 21 22 #define NFP_PL_DEVICE_ID 0x00000004 23 #define NFP_PL_DEVICE_ID_MASK 0xff 24 25 #define NFP6000_ARM_GCSR_SOFTMODEL0 0x00400144 26 27 void 28 nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv) 29 { 30 cpp->priv = priv; 31 } 32 33 void * 34 nfp_cpp_priv(struct nfp_cpp *cpp) 35 { 36 return cpp->priv; 37 } 38 39 void 40 nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model) 41 { 42 cpp->model = model; 43 } 44 45 uint32_t 46 nfp_cpp_model(struct nfp_cpp *cpp) 47 { 48 if (!cpp) 49 return NFP_CPP_MODEL_INVALID; 50 51 if (cpp->model == 0) 52 cpp->model = __nfp_cpp_model_autodetect(cpp); 53 54 return cpp->model; 55 } 56 57 void 58 nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface) 59 { 60 cpp->interface = interface; 61 } 62 63 int 64 nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial) 65 { 66 *serial = cpp->serial; 67 return cpp->serial_len; 68 } 69 70 int 71 nfp_cpp_serial_set(struct nfp_cpp *cpp, const uint8_t *serial, 72 size_t serial_len) 73 { 74 if (cpp->serial_len) 75 free(cpp->serial); 76 77 cpp->serial = malloc(serial_len); 78 if (!cpp->serial) 79 return -1; 80 81 memcpy(cpp->serial, serial, serial_len); 82 cpp->serial_len = serial_len; 83 84 return 0; 85 } 86 87 uint16_t 88 nfp_cpp_interface(struct nfp_cpp *cpp) 89 { 90 if (!cpp) 91 return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0); 92 93 return cpp->interface; 94 } 95 96 void * 97 nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area) 98 { 99 return &cpp_area[1]; 100 } 101 102 struct nfp_cpp * 103 nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area) 104 { 105 return cpp_area->cpp; 106 } 107 108 const char * 109 nfp_cpp_area_name(struct nfp_cpp_area *cpp_area) 110 { 111 return cpp_area->name; 112 } 113 114 /* 115 * nfp_cpp_area_alloc - allocate a new CPP area 116 * @cpp: CPP handle 117 * @dest: CPP id 118 * @address: start address on CPP target 119 * @size: size of area in bytes 120 * 121 * Allocate and initialize a CPP area structure. The area must later 122 * be locked down with an 'acquire' before it can be safely accessed. 123 * 124 * NOTE: @address and @size must be 32-bit aligned values. 125 */ 126 struct nfp_cpp_area * 127 nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, uint32_t dest, 128 const char *name, unsigned long long address, 129 unsigned long size) 130 { 131 struct nfp_cpp_area *area; 132 uint64_t tmp64 = (uint64_t)address; 133 int tmp, err; 134 135 if (!cpp) 136 return NULL; 137 138 /* CPP bus uses only a 40-bit address */ 139 if ((address + size) > (1ULL << 40)) 140 return NFP_ERRPTR(EFAULT); 141 142 /* Remap from cpp_island to cpp_target */ 143 err = nfp_target_cpp(dest, tmp64, &dest, &tmp64, cpp->imb_cat_table); 144 if (err < 0) 145 return NULL; 146 147 address = (unsigned long long)tmp64; 148 149 if (!name) 150 name = ""; 151 152 area = calloc(1, sizeof(*area) + cpp->op->area_priv_size + 153 strlen(name) + 1); 154 if (!area) 155 return NULL; 156 157 area->cpp = cpp; 158 area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size; 159 memcpy(area->name, name, strlen(name) + 1); 160 161 /* 162 * Preserve errno around the call to area_init, since most 163 * implementations will blindly call nfp_target_action_width()for both 164 * read or write modes, and that will set errno to EINVAL. 165 */ 166 tmp = errno; 167 168 err = cpp->op->area_init(area, dest, address, size); 169 if (err < 0) { 170 free(area); 171 return NULL; 172 } 173 174 /* Restore errno */ 175 errno = tmp; 176 177 area->offset = address; 178 area->size = size; 179 180 return area; 181 } 182 183 struct nfp_cpp_area * 184 nfp_cpp_area_alloc(struct nfp_cpp *cpp, uint32_t dest, 185 unsigned long long address, unsigned long size) 186 { 187 return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size); 188 } 189 190 /* 191 * nfp_cpp_area_alloc_acquire - allocate a new CPP area and lock it down 192 * 193 * @cpp: CPP handle 194 * @dest: CPP id 195 * @address: start address on CPP target 196 * @size: size of area 197 * 198 * Allocate and initilizae a CPP area structure, and lock it down so 199 * that it can be accessed directly. 200 * 201 * NOTE: @address and @size must be 32-bit aligned values. 202 * 203 * NOTE: The area must also be 'released' when the structure is freed. 204 */ 205 struct nfp_cpp_area * 206 nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, uint32_t destination, 207 unsigned long long address, unsigned long size) 208 { 209 struct nfp_cpp_area *area; 210 211 area = nfp_cpp_area_alloc(cpp, destination, address, size); 212 if (!area) 213 return NULL; 214 215 if (nfp_cpp_area_acquire(area)) { 216 nfp_cpp_area_free(area); 217 return NULL; 218 } 219 220 return area; 221 } 222 223 /* 224 * nfp_cpp_area_free - free up the CPP area 225 * area: CPP area handle 226 * 227 * Frees up memory resources held by the CPP area. 228 */ 229 void 230 nfp_cpp_area_free(struct nfp_cpp_area *area) 231 { 232 if (area->cpp->op->area_cleanup) 233 area->cpp->op->area_cleanup(area); 234 free(area); 235 } 236 237 /* 238 * nfp_cpp_area_release_free - release CPP area and free it 239 * area: CPP area handle 240 * 241 * Releases CPP area and frees up memory resources held by the it. 242 */ 243 void 244 nfp_cpp_area_release_free(struct nfp_cpp_area *area) 245 { 246 nfp_cpp_area_release(area); 247 nfp_cpp_area_free(area); 248 } 249 250 /* 251 * nfp_cpp_area_acquire - lock down a CPP area for access 252 * @area: CPP area handle 253 * 254 * Locks down the CPP area for a potential long term activity. Area 255 * must always be locked down before being accessed. 256 */ 257 int 258 nfp_cpp_area_acquire(struct nfp_cpp_area *area) 259 { 260 if (area->cpp->op->area_acquire) { 261 int err = area->cpp->op->area_acquire(area); 262 263 if (err < 0) 264 return -1; 265 } 266 267 return 0; 268 } 269 270 /* 271 * nfp_cpp_area_release - release a locked down CPP area 272 * @area: CPP area handle 273 * 274 * Releases a previously locked down CPP area. 275 */ 276 void 277 nfp_cpp_area_release(struct nfp_cpp_area *area) 278 { 279 if (area->cpp->op->area_release) 280 area->cpp->op->area_release(area); 281 } 282 283 /* 284 * nfp_cpp_area_iomem() - get IOMEM region for CPP area 285 * 286 * @area: CPP area handle 287 * 288 * Returns an iomem pointer for use with readl()/writel() style operations. 289 * 290 * NOTE: Area must have been locked down with an 'acquire'. 291 * 292 * Return: pointer to the area, or NULL 293 */ 294 void * 295 nfp_cpp_area_iomem(struct nfp_cpp_area *area) 296 { 297 void *iomem = NULL; 298 299 if (area->cpp->op->area_iomem) 300 iomem = area->cpp->op->area_iomem(area); 301 302 return iomem; 303 } 304 305 /* 306 * nfp_cpp_area_read - read data from CPP area 307 * 308 * @area: CPP area handle 309 * @offset: offset into CPP area 310 * @kernel_vaddr: kernel address to put data into 311 * @length: number of bytes to read 312 * 313 * Read data from indicated CPP region. 314 * 315 * NOTE: @offset and @length must be 32-bit aligned values. 316 * 317 * NOTE: Area must have been locked down with an 'acquire'. 318 */ 319 int 320 nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset, 321 void *kernel_vaddr, size_t length) 322 { 323 if ((offset + length) > area->size) 324 return NFP_ERRNO(EFAULT); 325 326 return area->cpp->op->area_read(area, kernel_vaddr, offset, length); 327 } 328 329 /* 330 * nfp_cpp_area_write - write data to CPP area 331 * 332 * @area: CPP area handle 333 * @offset: offset into CPP area 334 * @kernel_vaddr: kernel address to read data from 335 * @length: number of bytes to write 336 * 337 * Write data to indicated CPP region. 338 * 339 * NOTE: @offset and @length must be 32-bit aligned values. 340 * 341 * NOTE: Area must have been locked down with an 'acquire'. 342 */ 343 int 344 nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset, 345 const void *kernel_vaddr, size_t length) 346 { 347 if ((offset + length) > area->size) 348 return NFP_ERRNO(EFAULT); 349 350 return area->cpp->op->area_write(area, kernel_vaddr, offset, length); 351 } 352 353 void * 354 nfp_cpp_area_mapped(struct nfp_cpp_area *area) 355 { 356 if (area->cpp->op->area_mapped) 357 return area->cpp->op->area_mapped(area); 358 return NULL; 359 } 360 361 /* 362 * nfp_cpp_area_check_range - check if address range fits in CPP area 363 * 364 * @area: CPP area handle 365 * @offset: offset into CPP area 366 * @length: size of address range in bytes 367 * 368 * Check if address range fits within CPP area. Return 0 if area fits 369 * or -1 on error. 370 */ 371 int 372 nfp_cpp_area_check_range(struct nfp_cpp_area *area, unsigned long long offset, 373 unsigned long length) 374 { 375 if (((offset + length) > area->size)) 376 return NFP_ERRNO(EFAULT); 377 378 return 0; 379 } 380 381 /* 382 * Return the correct CPP address, and fixup xpb_addr as needed, 383 * based upon NFP model. 384 */ 385 static uint32_t 386 nfp_xpb_to_cpp(struct nfp_cpp *cpp, uint32_t *xpb_addr) 387 { 388 uint32_t xpb; 389 int island; 390 391 if (!NFP_CPP_MODEL_IS_6000(cpp->model)) 392 return 0; 393 394 xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0); 395 396 /* 397 * Ensure that non-local XPB accesses go out through the 398 * global XPBM bus. 399 */ 400 island = ((*xpb_addr) >> 24) & 0x3f; 401 402 if (!island) 403 return xpb; 404 405 if (island == 1) { 406 /* 407 * Accesses to the ARM Island overlay uses Island 0 408 * Global Bit 409 */ 410 (*xpb_addr) &= ~0x7f000000; 411 if (*xpb_addr < 0x60000) 412 *xpb_addr |= (1 << 30); 413 else 414 /* And only non-ARM interfaces use island id = 1 */ 415 if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) != 416 NFP_CPP_INTERFACE_TYPE_ARM) 417 *xpb_addr |= (1 << 24); 418 } else { 419 (*xpb_addr) |= (1 << 30); 420 } 421 422 return xpb; 423 } 424 425 int 426 nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset, 427 uint32_t *value) 428 { 429 int sz; 430 uint32_t tmp = 0; 431 432 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp)); 433 *value = rte_le_to_cpu_32(tmp); 434 435 return (sz == sizeof(*value)) ? 0 : -1; 436 } 437 438 int 439 nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset, 440 uint32_t value) 441 { 442 int sz; 443 444 value = rte_cpu_to_le_32(value); 445 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value)); 446 return (sz == sizeof(value)) ? 0 : -1; 447 } 448 449 int 450 nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset, 451 uint64_t *value) 452 { 453 int sz; 454 uint64_t tmp = 0; 455 456 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp)); 457 *value = rte_le_to_cpu_64(tmp); 458 459 return (sz == sizeof(*value)) ? 0 : -1; 460 } 461 462 int 463 nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset, 464 uint64_t value) 465 { 466 int sz; 467 468 value = rte_cpu_to_le_64(value); 469 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value)); 470 471 return (sz == sizeof(value)) ? 0 : -1; 472 } 473 474 int 475 nfp_cpp_readl(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, 476 uint32_t *value) 477 { 478 int sz; 479 uint32_t tmp; 480 481 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp)); 482 *value = rte_le_to_cpu_32(tmp); 483 484 return (sz == sizeof(*value)) ? 0 : -1; 485 } 486 487 int 488 nfp_cpp_writel(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, 489 uint32_t value) 490 { 491 int sz; 492 493 value = rte_cpu_to_le_32(value); 494 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value)); 495 496 return (sz == sizeof(value)) ? 0 : -1; 497 } 498 499 int 500 nfp_cpp_readq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, 501 uint64_t *value) 502 { 503 int sz; 504 uint64_t tmp; 505 506 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp)); 507 *value = rte_le_to_cpu_64(tmp); 508 509 return (sz == sizeof(*value)) ? 0 : -1; 510 } 511 512 int 513 nfp_cpp_writeq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address, 514 uint64_t value) 515 { 516 int sz; 517 518 value = rte_cpu_to_le_64(value); 519 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value)); 520 521 return (sz == sizeof(value)) ? 0 : -1; 522 } 523 524 int 525 nfp_xpb_writel(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t value) 526 { 527 uint32_t cpp_dest; 528 529 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr); 530 531 return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value); 532 } 533 534 int 535 nfp_xpb_readl(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t *value) 536 { 537 uint32_t cpp_dest; 538 539 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr); 540 541 return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value); 542 } 543 544 static struct nfp_cpp * 545 nfp_cpp_alloc(const char *devname) 546 { 547 const struct nfp_cpp_operations *ops; 548 struct nfp_cpp *cpp; 549 int err; 550 551 ops = nfp_cpp_transport_operations(); 552 553 if (!ops || !ops->init) 554 return NFP_ERRPTR(EINVAL); 555 556 cpp = calloc(1, sizeof(*cpp)); 557 if (!cpp) 558 return NULL; 559 560 cpp->op = ops; 561 562 if (cpp->op->init) { 563 err = cpp->op->init(cpp, devname); 564 if (err < 0) { 565 free(cpp); 566 return NULL; 567 } 568 } 569 570 if (NFP_CPP_MODEL_IS_6000(nfp_cpp_model(cpp))) { 571 uint32_t xpbaddr; 572 size_t tgt; 573 574 for (tgt = 0; tgt < ARRAY_SIZE(cpp->imb_cat_table); tgt++) { 575 /* Hardcoded XPB IMB Base, island 0 */ 576 xpbaddr = 0x000a0000 + (tgt * 4); 577 err = nfp_xpb_readl(cpp, xpbaddr, 578 (uint32_t *)&cpp->imb_cat_table[tgt]); 579 if (err < 0) { 580 free(cpp); 581 return NULL; 582 } 583 } 584 } 585 586 return cpp; 587 } 588 589 /* 590 * nfp_cpp_free - free the CPP handle 591 * @cpp: CPP handle 592 */ 593 void 594 nfp_cpp_free(struct nfp_cpp *cpp) 595 { 596 if (cpp->op && cpp->op->free) 597 cpp->op->free(cpp); 598 599 if (cpp->serial_len) 600 free(cpp->serial); 601 602 free(cpp); 603 } 604 605 struct nfp_cpp * 606 nfp_cpp_from_device_name(const char *devname) 607 { 608 return nfp_cpp_alloc(devname); 609 } 610 611 /* 612 * Modify bits of a 32-bit value from the XPB bus 613 * 614 * @param cpp NFP CPP device handle 615 * @param xpb_tgt XPB target and address 616 * @param mask mask of bits to alter 617 * @param value value to modify 618 * 619 * @return 0 on success, or -1 on failure (and set errno accordingly). 620 */ 621 int 622 nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask, 623 uint32_t value) 624 { 625 int err; 626 uint32_t tmp; 627 628 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp); 629 if (err < 0) 630 return err; 631 632 tmp &= ~mask; 633 tmp |= (mask & value); 634 return nfp_xpb_writel(cpp, xpb_tgt, tmp); 635 } 636 637 /* 638 * Modify bits of a 32-bit value from the XPB bus 639 * 640 * @param cpp NFP CPP device handle 641 * @param xpb_tgt XPB target and address 642 * @param mask mask of bits to alter 643 * @param value value to monitor for 644 * @param timeout_us maximum number of us to wait (-1 for forever) 645 * 646 * @return >= 0 on success, or -1 on failure (and set errno accordingly). 647 */ 648 int 649 nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask, 650 uint32_t value, int timeout_us) 651 { 652 uint32_t tmp; 653 int err; 654 655 do { 656 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp); 657 if (err < 0) 658 goto exit; 659 660 if ((tmp & mask) == (value & mask)) { 661 if (timeout_us < 0) 662 timeout_us = 0; 663 break; 664 } 665 666 if (timeout_us < 0) 667 continue; 668 669 timeout_us -= 100; 670 usleep(100); 671 } while (timeout_us >= 0); 672 673 if (timeout_us < 0) 674 err = NFP_ERRNO(ETIMEDOUT); 675 else 676 err = timeout_us; 677 678 exit: 679 return err; 680 } 681 682 /* 683 * nfp_cpp_read - read from CPP target 684 * @cpp: CPP handle 685 * @destination: CPP id 686 * @address: offset into CPP target 687 * @kernel_vaddr: kernel buffer for result 688 * @length: number of bytes to read 689 */ 690 int 691 nfp_cpp_read(struct nfp_cpp *cpp, uint32_t destination, 692 unsigned long long address, void *kernel_vaddr, size_t length) 693 { 694 struct nfp_cpp_area *area; 695 int err; 696 697 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length); 698 if (!area) { 699 printf("Area allocation/acquire failed\n"); 700 return -1; 701 } 702 703 err = nfp_cpp_area_read(area, 0, kernel_vaddr, length); 704 705 nfp_cpp_area_release_free(area); 706 return err; 707 } 708 709 /* 710 * nfp_cpp_write - write to CPP target 711 * @cpp: CPP handle 712 * @destination: CPP id 713 * @address: offset into CPP target 714 * @kernel_vaddr: kernel buffer to read from 715 * @length: number of bytes to write 716 */ 717 int 718 nfp_cpp_write(struct nfp_cpp *cpp, uint32_t destination, 719 unsigned long long address, const void *kernel_vaddr, 720 size_t length) 721 { 722 struct nfp_cpp_area *area; 723 int err; 724 725 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length); 726 if (!area) 727 return -1; 728 729 err = nfp_cpp_area_write(area, 0, kernel_vaddr, length); 730 731 nfp_cpp_area_release_free(area); 732 return err; 733 } 734 735 /* 736 * nfp_cpp_area_fill - fill a CPP area with a value 737 * @area: CPP area 738 * @offset: offset into CPP area 739 * @value: value to fill with 740 * @length: length of area to fill 741 */ 742 int 743 nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset, 744 uint32_t value, size_t length) 745 { 746 int err; 747 size_t i; 748 uint64_t value64; 749 750 value = rte_cpu_to_le_32(value); 751 value64 = ((uint64_t)value << 32) | value; 752 753 if ((offset + length) > area->size) 754 return NFP_ERRNO(EINVAL); 755 756 if ((area->offset + offset) & 3) 757 return NFP_ERRNO(EINVAL); 758 759 if (((area->offset + offset) & 7) == 4 && length >= 4) { 760 err = nfp_cpp_area_write(area, offset, &value, sizeof(value)); 761 if (err < 0) 762 return err; 763 if (err != sizeof(value)) 764 return NFP_ERRNO(ENOSPC); 765 offset += sizeof(value); 766 length -= sizeof(value); 767 } 768 769 for (i = 0; (i + sizeof(value)) < length; i += sizeof(value64)) { 770 err = 771 nfp_cpp_area_write(area, offset + i, &value64, 772 sizeof(value64)); 773 if (err < 0) 774 return err; 775 if (err != sizeof(value64)) 776 return NFP_ERRNO(ENOSPC); 777 } 778 779 if ((i + sizeof(value)) <= length) { 780 err = 781 nfp_cpp_area_write(area, offset + i, &value, sizeof(value)); 782 if (err < 0) 783 return err; 784 if (err != sizeof(value)) 785 return NFP_ERRNO(ENOSPC); 786 i += sizeof(value); 787 } 788 789 return (int)i; 790 } 791 792 /* 793 * NOTE: This code should not use nfp_xpb_* functions, 794 * as those are model-specific 795 */ 796 uint32_t 797 __nfp_cpp_model_autodetect(struct nfp_cpp *cpp) 798 { 799 uint32_t arm_id = NFP_CPP_ID(NFP_CPP_TARGET_ARM, 0, 0); 800 uint32_t model = 0; 801 802 nfp_cpp_readl(cpp, arm_id, NFP6000_ARM_GCSR_SOFTMODEL0, &model); 803 804 if (NFP_CPP_MODEL_IS_6000(model)) { 805 uint32_t tmp; 806 807 nfp_cpp_model_set(cpp, model); 808 809 /* The PL's PluDeviceID revision code is authoratative */ 810 model &= ~0xff; 811 nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + 812 NFP_PL_DEVICE_ID, &tmp); 813 model |= (NFP_PL_DEVICE_ID_MASK & tmp) - 0x10; 814 } 815 816 return model; 817 } 818 819 /* 820 * nfp_cpp_map_area() - Helper function to map an area 821 * @cpp: NFP CPP handler 822 * @domain: CPP domain 823 * @target: CPP target 824 * @addr: CPP address 825 * @size: Size of the area 826 * @area: Area handle (output) 827 * 828 * Map an area of IOMEM access. To undo the effect of this function call 829 * @nfp_cpp_area_release_free(*area). 830 * 831 * Return: Pointer to memory mapped area or ERR_PTR 832 */ 833 uint8_t * 834 nfp_cpp_map_area(struct nfp_cpp *cpp, int domain, int target, uint64_t addr, 835 unsigned long size, struct nfp_cpp_area **area) 836 { 837 uint8_t *res; 838 uint32_t dest; 839 840 dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, domain); 841 842 *area = nfp_cpp_area_alloc_acquire(cpp, dest, addr, size); 843 if (!*area) 844 goto err_eio; 845 846 res = nfp_cpp_area_iomem(*area); 847 if (!res) 848 goto err_release_free; 849 850 return res; 851 852 err_release_free: 853 nfp_cpp_area_release_free(*area); 854 err_eio: 855 return NULL; 856 } 857