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, int driver_lock_needed) 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 cpp->driver_lock_needed = driver_lock_needed; 562 563 if (cpp->op->init) { 564 err = cpp->op->init(cpp, devname); 565 if (err < 0) { 566 free(cpp); 567 return NULL; 568 } 569 } 570 571 if (NFP_CPP_MODEL_IS_6000(nfp_cpp_model(cpp))) { 572 uint32_t xpbaddr; 573 size_t tgt; 574 575 for (tgt = 0; tgt < ARRAY_SIZE(cpp->imb_cat_table); tgt++) { 576 /* Hardcoded XPB IMB Base, island 0 */ 577 xpbaddr = 0x000a0000 + (tgt * 4); 578 err = nfp_xpb_readl(cpp, xpbaddr, 579 (uint32_t *)&cpp->imb_cat_table[tgt]); 580 if (err < 0) { 581 free(cpp); 582 return NULL; 583 } 584 } 585 } 586 587 return cpp; 588 } 589 590 /* 591 * nfp_cpp_free - free the CPP handle 592 * @cpp: CPP handle 593 */ 594 void 595 nfp_cpp_free(struct nfp_cpp *cpp) 596 { 597 if (cpp->op && cpp->op->free) 598 cpp->op->free(cpp); 599 600 if (cpp->serial_len) 601 free(cpp->serial); 602 603 free(cpp); 604 } 605 606 struct nfp_cpp * 607 nfp_cpp_from_device_name(const char *devname, int driver_lock_needed) 608 { 609 return nfp_cpp_alloc(devname, driver_lock_needed); 610 } 611 612 /* 613 * Modify bits of a 32-bit value from the XPB bus 614 * 615 * @param cpp NFP CPP device handle 616 * @param xpb_tgt XPB target and address 617 * @param mask mask of bits to alter 618 * @param value value to modify 619 * 620 * @return 0 on success, or -1 on failure (and set errno accordingly). 621 */ 622 int 623 nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask, 624 uint32_t value) 625 { 626 int err; 627 uint32_t tmp; 628 629 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp); 630 if (err < 0) 631 return err; 632 633 tmp &= ~mask; 634 tmp |= (mask & value); 635 return nfp_xpb_writel(cpp, xpb_tgt, tmp); 636 } 637 638 /* 639 * Modify bits of a 32-bit value from the XPB bus 640 * 641 * @param cpp NFP CPP device handle 642 * @param xpb_tgt XPB target and address 643 * @param mask mask of bits to alter 644 * @param value value to monitor for 645 * @param timeout_us maximum number of us to wait (-1 for forever) 646 * 647 * @return >= 0 on success, or -1 on failure (and set errno accordingly). 648 */ 649 int 650 nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask, 651 uint32_t value, int timeout_us) 652 { 653 uint32_t tmp; 654 int err; 655 656 do { 657 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp); 658 if (err < 0) 659 goto exit; 660 661 if ((tmp & mask) == (value & mask)) { 662 if (timeout_us < 0) 663 timeout_us = 0; 664 break; 665 } 666 667 if (timeout_us < 0) 668 continue; 669 670 timeout_us -= 100; 671 usleep(100); 672 } while (timeout_us >= 0); 673 674 if (timeout_us < 0) 675 err = NFP_ERRNO(ETIMEDOUT); 676 else 677 err = timeout_us; 678 679 exit: 680 return err; 681 } 682 683 /* 684 * nfp_cpp_read - read from CPP target 685 * @cpp: CPP handle 686 * @destination: CPP id 687 * @address: offset into CPP target 688 * @kernel_vaddr: kernel buffer for result 689 * @length: number of bytes to read 690 */ 691 int 692 nfp_cpp_read(struct nfp_cpp *cpp, uint32_t destination, 693 unsigned long long address, void *kernel_vaddr, size_t length) 694 { 695 struct nfp_cpp_area *area; 696 int err; 697 698 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length); 699 if (!area) { 700 printf("Area allocation/acquire failed\n"); 701 return -1; 702 } 703 704 err = nfp_cpp_area_read(area, 0, kernel_vaddr, length); 705 706 nfp_cpp_area_release_free(area); 707 return err; 708 } 709 710 /* 711 * nfp_cpp_write - write to CPP target 712 * @cpp: CPP handle 713 * @destination: CPP id 714 * @address: offset into CPP target 715 * @kernel_vaddr: kernel buffer to read from 716 * @length: number of bytes to write 717 */ 718 int 719 nfp_cpp_write(struct nfp_cpp *cpp, uint32_t destination, 720 unsigned long long address, const void *kernel_vaddr, 721 size_t length) 722 { 723 struct nfp_cpp_area *area; 724 int err; 725 726 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length); 727 if (!area) 728 return -1; 729 730 err = nfp_cpp_area_write(area, 0, kernel_vaddr, length); 731 732 nfp_cpp_area_release_free(area); 733 return err; 734 } 735 736 /* 737 * nfp_cpp_area_fill - fill a CPP area with a value 738 * @area: CPP area 739 * @offset: offset into CPP area 740 * @value: value to fill with 741 * @length: length of area to fill 742 */ 743 int 744 nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset, 745 uint32_t value, size_t length) 746 { 747 int err; 748 size_t i; 749 uint64_t value64; 750 751 value = rte_cpu_to_le_32(value); 752 value64 = ((uint64_t)value << 32) | value; 753 754 if ((offset + length) > area->size) 755 return NFP_ERRNO(EINVAL); 756 757 if ((area->offset + offset) & 3) 758 return NFP_ERRNO(EINVAL); 759 760 if (((area->offset + offset) & 7) == 4 && length >= 4) { 761 err = nfp_cpp_area_write(area, offset, &value, sizeof(value)); 762 if (err < 0) 763 return err; 764 if (err != sizeof(value)) 765 return NFP_ERRNO(ENOSPC); 766 offset += sizeof(value); 767 length -= sizeof(value); 768 } 769 770 for (i = 0; (i + sizeof(value)) < length; i += sizeof(value64)) { 771 err = 772 nfp_cpp_area_write(area, offset + i, &value64, 773 sizeof(value64)); 774 if (err < 0) 775 return err; 776 if (err != sizeof(value64)) 777 return NFP_ERRNO(ENOSPC); 778 } 779 780 if ((i + sizeof(value)) <= length) { 781 err = 782 nfp_cpp_area_write(area, offset + i, &value, sizeof(value)); 783 if (err < 0) 784 return err; 785 if (err != sizeof(value)) 786 return NFP_ERRNO(ENOSPC); 787 i += sizeof(value); 788 } 789 790 return (int)i; 791 } 792 793 /* 794 * NOTE: This code should not use nfp_xpb_* functions, 795 * as those are model-specific 796 */ 797 uint32_t 798 __nfp_cpp_model_autodetect(struct nfp_cpp *cpp) 799 { 800 uint32_t arm_id = NFP_CPP_ID(NFP_CPP_TARGET_ARM, 0, 0); 801 uint32_t model = 0; 802 803 nfp_cpp_readl(cpp, arm_id, NFP6000_ARM_GCSR_SOFTMODEL0, &model); 804 805 if (NFP_CPP_MODEL_IS_6000(model)) { 806 uint32_t tmp; 807 808 nfp_cpp_model_set(cpp, model); 809 810 /* The PL's PluDeviceID revision code is authoratative */ 811 model &= ~0xff; 812 nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + 813 NFP_PL_DEVICE_ID, &tmp); 814 model |= (NFP_PL_DEVICE_ID_MASK & tmp) - 0x10; 815 } 816 817 return model; 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) 845 goto err_eio; 846 847 res = nfp_cpp_area_iomem(*area); 848 if (!res) 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