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