1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2015-2017 Landon Fuller <landonf@landonf.org> 5 * Copyright (c) 2017 The FreeBSD Foundation 6 * All rights reserved. 7 * 8 * Portions of this software were developed by Landon Fuller 9 * under sponsorship from the FreeBSD Foundation. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 19 * redistribution must be conditioned upon including a substantially 20 * similar Disclaimer requirement for further binary redistribution. 21 * 22 * NO WARRANTY 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 26 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 27 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 28 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 31 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 33 * THE POSSIBILITY OF SUCH DAMAGES. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/bus.h> 38 #include <sys/kernel.h> 39 #include <sys/limits.h> 40 #include <sys/systm.h> 41 42 #include <machine/bus.h> 43 #include <machine/resource.h> 44 45 #include <dev/bhnd/bhnd_eromvar.h> 46 47 #include "bcma_eromreg.h" 48 #include "bcma_eromvar.h" 49 50 /* 51 * BCMA Enumeration ROM (EROM) Table 52 * 53 * Provides auto-discovery of BCMA cores on Broadcom's HND SoC. 54 * 55 * The EROM core address can be found at BCMA_CC_EROM_ADDR within the 56 * ChipCommon registers. The table itself is comprised of 32-bit 57 * type-tagged entries, organized into an array of variable-length 58 * core descriptor records. 59 * 60 * The final core descriptor is followed by a 32-bit BCMA_EROM_TABLE_EOF (0xF) 61 * marker. 62 */ 63 64 static const char *bcma_erom_entry_type_name (uint8_t entry); 65 66 static int bcma_erom_read32(struct bcma_erom *erom, 67 uint32_t *entry); 68 static int bcma_erom_skip32(struct bcma_erom *erom); 69 70 static int bcma_erom_skip_core(struct bcma_erom *erom); 71 static int bcma_erom_skip_mport(struct bcma_erom *erom); 72 static int bcma_erom_skip_sport_region(struct bcma_erom *erom); 73 74 static int bcma_erom_seek_next(struct bcma_erom *erom, 75 uint8_t etype); 76 static int bcma_erom_region_to_port_type(struct bcma_erom *erom, 77 uint8_t region_type, bhnd_port_type *port_type); 78 79 static int bcma_erom_peek32(struct bcma_erom *erom, 80 uint32_t *entry); 81 82 static bus_size_t bcma_erom_tell(struct bcma_erom *erom); 83 static void bcma_erom_seek(struct bcma_erom *erom, 84 bus_size_t offset); 85 static void bcma_erom_reset(struct bcma_erom *erom); 86 87 static int bcma_erom_seek_matching_core(struct bcma_erom *sc, 88 const struct bhnd_core_match *desc, 89 struct bhnd_core_info *core); 90 91 static int bcma_erom_parse_core(struct bcma_erom *erom, 92 struct bcma_erom_core *core); 93 94 static int bcma_erom_parse_mport(struct bcma_erom *erom, 95 struct bcma_erom_mport *mport); 96 97 static int bcma_erom_parse_sport_region(struct bcma_erom *erom, 98 struct bcma_erom_sport_region *region); 99 100 static void bcma_erom_to_core_info(const struct bcma_erom_core *core, 101 u_int core_idx, int core_unit, 102 struct bhnd_core_info *info); 103 104 /** 105 * BCMA EROM per-instance state. 106 */ 107 struct bcma_erom { 108 struct bhnd_erom obj; 109 device_t dev; /**< parent device, or NULL if none. */ 110 struct bhnd_erom_io *eio; /**< bus I/O callbacks */ 111 bhnd_size_t offset; /**< current read offset */ 112 }; 113 114 #define EROM_LOG(erom, fmt, ...) do { \ 115 printf("%s erom[0x%llx]: " fmt, __FUNCTION__, \ 116 (unsigned long long)(erom->offset), ##__VA_ARGS__); \ 117 } while(0) 118 119 /** Return the type name for an EROM entry */ 120 static const char * 121 bcma_erom_entry_type_name (uint8_t entry) 122 { 123 switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) { 124 case BCMA_EROM_ENTRY_TYPE_CORE: 125 return "core"; 126 case BCMA_EROM_ENTRY_TYPE_MPORT: 127 return "mport"; 128 case BCMA_EROM_ENTRY_TYPE_REGION: 129 return "region"; 130 default: 131 return "unknown"; 132 } 133 } 134 135 /* BCMA implementation of BHND_EROM_INIT() */ 136 static int 137 bcma_erom_init(bhnd_erom_t *erom, const struct bhnd_chipid *cid, 138 struct bhnd_erom_io *eio) 139 { 140 struct bcma_erom *sc; 141 bhnd_addr_t table_addr; 142 int error; 143 144 sc = (struct bcma_erom *)erom; 145 sc->eio = eio; 146 sc->offset = 0; 147 148 /* Determine erom table address */ 149 if (BHND_ADDR_MAX - BCMA_EROM_TABLE_START < cid->enum_addr) 150 return (ENXIO); /* would overflow */ 151 152 table_addr = cid->enum_addr + BCMA_EROM_TABLE_START; 153 154 /* Try to map the erom table */ 155 error = bhnd_erom_io_map(sc->eio, table_addr, BCMA_EROM_TABLE_SIZE); 156 if (error) 157 return (error); 158 159 return (0); 160 } 161 162 /* BCMA implementation of BHND_EROM_PROBE() */ 163 static int 164 bcma_erom_probe(bhnd_erom_class_t *cls, struct bhnd_erom_io *eio, 165 const struct bhnd_chipid *hint, struct bhnd_chipid *cid) 166 { 167 int error; 168 169 /* Hints aren't supported; all BCMA devices have a ChipCommon 170 * core */ 171 if (hint != NULL) 172 return (EINVAL); 173 174 /* Read and parse chip identification */ 175 if ((error = bhnd_erom_read_chipid(eio, cid))) 176 return (error); 177 178 /* Verify chip type */ 179 switch (cid->chip_type) { 180 case BHND_CHIPTYPE_BCMA: 181 return (BUS_PROBE_DEFAULT); 182 183 case BHND_CHIPTYPE_BCMA_ALT: 184 case BHND_CHIPTYPE_UBUS: 185 return (BUS_PROBE_GENERIC); 186 187 default: 188 return (ENXIO); 189 } 190 } 191 192 static void 193 bcma_erom_fini(bhnd_erom_t *erom) 194 { 195 struct bcma_erom *sc = (struct bcma_erom *)erom; 196 197 bhnd_erom_io_fini(sc->eio); 198 } 199 200 static int 201 bcma_erom_lookup_core(bhnd_erom_t *erom, const struct bhnd_core_match *desc, 202 struct bhnd_core_info *core) 203 { 204 struct bcma_erom *sc = (struct bcma_erom *)erom; 205 206 /* Search for the first matching core */ 207 return (bcma_erom_seek_matching_core(sc, desc, core)); 208 } 209 210 static int 211 bcma_erom_lookup_core_addr(bhnd_erom_t *erom, const struct bhnd_core_match *desc, 212 bhnd_port_type port_type, u_int port_num, u_int region_num, 213 struct bhnd_core_info *core, bhnd_addr_t *addr, bhnd_size_t *size) 214 { 215 struct bcma_erom *sc; 216 struct bcma_erom_core ec; 217 uint32_t entry; 218 uint8_t region_port, region_type; 219 bool found; 220 int error; 221 222 sc = (struct bcma_erom *)erom; 223 224 /* Seek to the first matching core and provide the core info 225 * to the caller */ 226 if ((error = bcma_erom_seek_matching_core(sc, desc, core))) 227 return (error); 228 229 if ((error = bcma_erom_parse_core(sc, &ec))) 230 return (error); 231 232 /* Skip master ports */ 233 for (u_long i = 0; i < ec.num_mport; i++) { 234 if ((error = bcma_erom_skip_mport(sc))) 235 return (error); 236 } 237 238 /* Seek to the region block for the given port type */ 239 found = false; 240 while (1) { 241 bhnd_port_type p_type; 242 uint8_t r_type; 243 244 if ((error = bcma_erom_peek32(sc, &entry))) 245 return (error); 246 247 if (!BCMA_EROM_ENTRY_IS(entry, REGION)) 248 return (ENOENT); 249 250 /* Expected region type? */ 251 r_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); 252 error = bcma_erom_region_to_port_type(sc, r_type, &p_type); 253 if (error) 254 return (error); 255 256 if (p_type == port_type) { 257 found = true; 258 break; 259 } 260 261 /* Skip to next entry */ 262 if ((error = bcma_erom_skip_sport_region(sc))) 263 return (error); 264 } 265 266 if (!found) 267 return (ENOENT); 268 269 /* Found the appropriate port type block; now find the region records 270 * for the given port number */ 271 found = false; 272 for (u_int i = 0; i <= port_num; i++) { 273 bhnd_port_type p_type; 274 275 if ((error = bcma_erom_peek32(sc, &entry))) 276 return (error); 277 278 if (!BCMA_EROM_ENTRY_IS(entry, REGION)) 279 return (ENOENT); 280 281 /* Fetch the type/port of the first region entry */ 282 region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); 283 region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); 284 285 /* Have we found the region entries for the desired port? */ 286 if (i == port_num) { 287 error = bcma_erom_region_to_port_type(sc, region_type, 288 &p_type); 289 if (error) 290 return (error); 291 292 if (p_type == port_type) 293 found = true; 294 295 break; 296 } 297 298 /* Otherwise, seek to next block of region records */ 299 while (1) { 300 uint8_t next_type, next_port; 301 302 if ((error = bcma_erom_skip_sport_region(sc))) 303 return (error); 304 305 if ((error = bcma_erom_peek32(sc, &entry))) 306 return (error); 307 308 if (!BCMA_EROM_ENTRY_IS(entry, REGION)) 309 return (ENOENT); 310 311 next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); 312 next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); 313 314 if (next_type != region_type || 315 next_port != region_port) 316 break; 317 } 318 } 319 320 if (!found) 321 return (ENOENT); 322 323 /* Finally, search for the requested region number */ 324 for (u_int i = 0; i <= region_num; i++) { 325 struct bcma_erom_sport_region region; 326 uint8_t next_port, next_type; 327 328 if ((error = bcma_erom_peek32(sc, &entry))) 329 return (error); 330 331 if (!BCMA_EROM_ENTRY_IS(entry, REGION)) 332 return (ENOENT); 333 334 /* Check for the end of the region block */ 335 next_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); 336 next_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); 337 338 if (next_type != region_type || 339 next_port != region_port) 340 break; 341 342 /* Parse the region */ 343 if ((error = bcma_erom_parse_sport_region(sc, ®ion))) 344 return (error); 345 346 /* Is this our target region_num? */ 347 if (i == region_num) { 348 /* Found */ 349 *addr = region.base_addr; 350 *size = region.size; 351 return (0); 352 } 353 } 354 355 /* Not found */ 356 return (ENOENT); 357 }; 358 359 static int 360 bcma_erom_get_core_table(bhnd_erom_t *erom, struct bhnd_core_info **cores, 361 u_int *num_cores) 362 { 363 struct bcma_erom *sc; 364 struct bhnd_core_info *buffer; 365 bus_size_t initial_offset; 366 u_int count; 367 int error; 368 369 sc = (struct bcma_erom *)erom; 370 371 buffer = NULL; 372 initial_offset = bcma_erom_tell(sc); 373 374 /* Determine the core count */ 375 bcma_erom_reset(sc); 376 for (count = 0, error = 0; !error; count++) { 377 struct bcma_erom_core core; 378 379 /* Seek to the first readable core entry */ 380 error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); 381 if (error == ENOENT) 382 break; 383 else if (error) 384 goto cleanup; 385 386 /* Read past the core descriptor */ 387 if ((error = bcma_erom_parse_core(sc, &core))) 388 goto cleanup; 389 } 390 391 /* Allocate our output buffer */ 392 buffer = mallocarray(count, sizeof(struct bhnd_core_info), M_BHND, 393 M_NOWAIT); 394 if (buffer == NULL) { 395 error = ENOMEM; 396 goto cleanup; 397 } 398 399 /* Parse all core descriptors */ 400 bcma_erom_reset(sc); 401 for (u_int i = 0; i < count; i++) { 402 struct bcma_erom_core core; 403 int unit; 404 405 /* Parse the core */ 406 error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); 407 if (error) 408 goto cleanup; 409 410 error = bcma_erom_parse_core(sc, &core); 411 if (error) 412 goto cleanup; 413 414 /* Determine the unit number */ 415 unit = 0; 416 for (u_int j = 0; j < i; j++) { 417 if (buffer[i].vendor == buffer[j].vendor && 418 buffer[i].device == buffer[j].device) 419 unit++; 420 } 421 422 /* Convert to a bhnd info record */ 423 bcma_erom_to_core_info(&core, i, unit, &buffer[i]); 424 } 425 426 cleanup: 427 if (!error) { 428 *cores = buffer; 429 *num_cores = count; 430 } else { 431 if (buffer != NULL) 432 free(buffer, M_BHND); 433 } 434 435 /* Restore the initial position */ 436 bcma_erom_seek(sc, initial_offset); 437 return (error); 438 } 439 440 static void 441 bcma_erom_free_core_table(bhnd_erom_t *erom, struct bhnd_core_info *cores) 442 { 443 free(cores, M_BHND); 444 } 445 446 /** 447 * Return the current read position. 448 */ 449 static bus_size_t 450 bcma_erom_tell(struct bcma_erom *erom) 451 { 452 return (erom->offset); 453 } 454 455 /** 456 * Seek to an absolute read position. 457 */ 458 static void 459 bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset) 460 { 461 erom->offset = offset; 462 } 463 464 /** 465 * Read a 32-bit entry value from the EROM table without advancing the 466 * read position. 467 * 468 * @param erom EROM read state. 469 * @param entry Will contain the read result on success. 470 * @retval 0 success 471 * @retval ENOENT The end of the EROM table was reached. 472 * @retval non-zero The read could not be completed. 473 */ 474 static int 475 bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry) 476 { 477 if (erom->offset >= (BCMA_EROM_TABLE_SIZE - sizeof(uint32_t))) { 478 EROM_LOG(erom, "BCMA EROM table missing terminating EOF\n"); 479 return (EINVAL); 480 } 481 482 *entry = bhnd_erom_io_read(erom->eio, erom->offset, 4); 483 return (0); 484 } 485 486 /** 487 * Read a 32-bit entry value from the EROM table. 488 * 489 * @param erom EROM read state. 490 * @param entry Will contain the read result on success. 491 * @retval 0 success 492 * @retval ENOENT The end of the EROM table was reached. 493 * @retval non-zero The read could not be completed. 494 */ 495 static int 496 bcma_erom_read32(struct bcma_erom *erom, uint32_t *entry) 497 { 498 int error; 499 500 if ((error = bcma_erom_peek32(erom, entry)) == 0) 501 erom->offset += 4; 502 503 return (error); 504 } 505 506 /** 507 * Read and discard 32-bit entry value from the EROM table. 508 * 509 * @param erom EROM read state. 510 * @retval 0 success 511 * @retval ENOENT The end of the EROM table was reached. 512 * @retval non-zero The read could not be completed. 513 */ 514 static int 515 bcma_erom_skip32(struct bcma_erom *erom) 516 { 517 uint32_t entry; 518 519 return bcma_erom_read32(erom, &entry); 520 } 521 522 /** 523 * Read and discard a core descriptor from the EROM table. 524 * 525 * @param erom EROM read state. 526 * @retval 0 success 527 * @retval ENOENT The end of the EROM table was reached. 528 * @retval non-zero The read could not be completed. 529 */ 530 static int 531 bcma_erom_skip_core(struct bcma_erom *erom) 532 { 533 struct bcma_erom_core core; 534 return (bcma_erom_parse_core(erom, &core)); 535 } 536 537 /** 538 * Read and discard a master port descriptor from the EROM table. 539 * 540 * @param erom EROM read state. 541 * @retval 0 success 542 * @retval ENOENT The end of the EROM table was reached. 543 * @retval non-zero The read could not be completed. 544 */ 545 static int 546 bcma_erom_skip_mport(struct bcma_erom *erom) 547 { 548 struct bcma_erom_mport mp; 549 return (bcma_erom_parse_mport(erom, &mp)); 550 } 551 552 /** 553 * Read and discard a port region descriptor from the EROM table. 554 * 555 * @param erom EROM read state. 556 * @retval 0 success 557 * @retval ENOENT The end of the EROM table was reached. 558 * @retval non-zero The read could not be completed. 559 */ 560 static int 561 bcma_erom_skip_sport_region(struct bcma_erom *erom) 562 { 563 struct bcma_erom_sport_region r; 564 return (bcma_erom_parse_sport_region(erom, &r)); 565 } 566 567 /** 568 * Seek to the next entry matching the given EROM entry type. 569 * 570 * @param erom EROM read state. 571 * @param etype One of BCMA_EROM_ENTRY_TYPE_CORE, 572 * BCMA_EROM_ENTRY_TYPE_MPORT, or BCMA_EROM_ENTRY_TYPE_REGION. 573 * @retval 0 success 574 * @retval ENOENT The end of the EROM table was reached. 575 * @retval non-zero Reading or parsing the descriptor failed. 576 */ 577 static int 578 bcma_erom_seek_next(struct bcma_erom *erom, uint8_t etype) 579 { 580 uint32_t entry; 581 int error; 582 583 /* Iterate until we hit an entry matching the requested type. */ 584 while (!(error = bcma_erom_peek32(erom, &entry))) { 585 /* Handle EOF */ 586 if (entry == BCMA_EROM_TABLE_EOF) 587 return (ENOENT); 588 589 /* Invalid entry */ 590 if (!BCMA_EROM_GET_ATTR(entry, ENTRY_ISVALID)) 591 return (EINVAL); 592 593 /* Entry type matches? */ 594 if (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE) == etype) 595 return (0); 596 597 /* Skip non-matching entry types. */ 598 switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) { 599 case BCMA_EROM_ENTRY_TYPE_CORE: 600 if ((error = bcma_erom_skip_core(erom))) 601 return (error); 602 603 break; 604 605 case BCMA_EROM_ENTRY_TYPE_MPORT: 606 if ((error = bcma_erom_skip_mport(erom))) 607 return (error); 608 609 break; 610 611 case BCMA_EROM_ENTRY_TYPE_REGION: 612 if ((error = bcma_erom_skip_sport_region(erom))) 613 return (error); 614 break; 615 616 default: 617 /* Unknown entry type! */ 618 return (EINVAL); 619 } 620 } 621 622 return (error); 623 } 624 625 /** 626 * Return the read position to the start of the EROM table. 627 * 628 * @param erom EROM read state. 629 */ 630 static void 631 bcma_erom_reset(struct bcma_erom *erom) 632 { 633 erom->offset = 0; 634 } 635 636 /** 637 * Seek to the first core entry matching @p desc. 638 * 639 * @param erom EROM read state. 640 * @param desc The core match descriptor. 641 * @param[out] core On success, the matching core info. If the core info 642 * is not desired, a NULL pointer may be provided. 643 * @retval 0 success 644 * @retval ENOENT The end of the EROM table was reached before @p index was 645 * found. 646 * @retval non-zero Reading or parsing failed. 647 */ 648 static int 649 bcma_erom_seek_matching_core(struct bcma_erom *sc, 650 const struct bhnd_core_match *desc, struct bhnd_core_info *core) 651 { 652 struct bhnd_core_match imatch; 653 bus_size_t core_offset, next_offset; 654 int error; 655 656 /* Seek to table start. */ 657 bcma_erom_reset(sc); 658 659 /* We can't determine a core's unit number during the initial scan. */ 660 imatch = *desc; 661 imatch.m.match.core_unit = 0; 662 663 /* Locate the first matching core */ 664 for (u_int i = 0; i < UINT_MAX; i++) { 665 struct bcma_erom_core ec; 666 struct bhnd_core_info ci; 667 668 /* Seek to the next core */ 669 error = bcma_erom_seek_next(sc, BCMA_EROM_ENTRY_TYPE_CORE); 670 if (error) 671 return (error); 672 673 /* Save the core offset */ 674 core_offset = bcma_erom_tell(sc); 675 676 /* Parse the core */ 677 if ((error = bcma_erom_parse_core(sc, &ec))) 678 return (error); 679 680 bcma_erom_to_core_info(&ec, i, 0, &ci); 681 682 /* Check for initial match */ 683 if (!bhnd_core_matches(&ci, &imatch)) 684 continue; 685 686 /* Re-scan preceding cores to determine the unit number. */ 687 next_offset = bcma_erom_tell(sc); 688 bcma_erom_reset(sc); 689 for (u_int j = 0; j < i; j++) { 690 /* Parse the core */ 691 error = bcma_erom_seek_next(sc, 692 BCMA_EROM_ENTRY_TYPE_CORE); 693 if (error) 694 return (error); 695 696 if ((error = bcma_erom_parse_core(sc, &ec))) 697 return (error); 698 699 /* Bump the unit number? */ 700 if (ec.vendor == ci.vendor && ec.device == ci.device) 701 ci.unit++; 702 } 703 704 /* Check for full match against now-valid unit number */ 705 if (!bhnd_core_matches(&ci, desc)) { 706 /* Reposition to allow reading the next core */ 707 bcma_erom_seek(sc, next_offset); 708 continue; 709 } 710 711 /* Found; seek to the core's initial offset and provide 712 * the core info to the caller */ 713 bcma_erom_seek(sc, core_offset); 714 if (core != NULL) 715 *core = ci; 716 717 return (0); 718 } 719 720 /* Not found, or a parse error occurred */ 721 return (error); 722 } 723 724 /** 725 * Read the next core descriptor from the EROM table. 726 * 727 * @param erom EROM read state. 728 * @param[out] core On success, will be populated with the parsed core 729 * descriptor data. 730 * @retval 0 success 731 * @retval ENOENT The end of the EROM table was reached. 732 * @retval non-zero Reading or parsing the core descriptor failed. 733 */ 734 static int 735 bcma_erom_parse_core(struct bcma_erom *erom, struct bcma_erom_core *core) 736 { 737 uint32_t entry; 738 int error; 739 740 /* Parse CoreDescA */ 741 if ((error = bcma_erom_read32(erom, &entry))) 742 return (error); 743 744 /* Handle EOF */ 745 if (entry == BCMA_EROM_TABLE_EOF) 746 return (ENOENT); 747 748 if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { 749 EROM_LOG(erom, "Unexpected EROM entry 0x%x (type=%s)\n", 750 entry, bcma_erom_entry_type_name(entry)); 751 752 return (EINVAL); 753 } 754 755 core->vendor = BCMA_EROM_GET_ATTR(entry, COREA_DESIGNER); 756 core->device = BCMA_EROM_GET_ATTR(entry, COREA_ID); 757 758 /* Parse CoreDescB */ 759 if ((error = bcma_erom_read32(erom, &entry))) 760 return (error); 761 762 if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { 763 return (EINVAL); 764 } 765 766 core->rev = BCMA_EROM_GET_ATTR(entry, COREB_REV); 767 core->num_mport = BCMA_EROM_GET_ATTR(entry, COREB_NUM_MP); 768 core->num_dport = BCMA_EROM_GET_ATTR(entry, COREB_NUM_DP); 769 core->num_mwrap = BCMA_EROM_GET_ATTR(entry, COREB_NUM_WMP); 770 core->num_swrap = BCMA_EROM_GET_ATTR(entry, COREB_NUM_WSP); 771 772 return (0); 773 } 774 775 /** 776 * Read the next master port descriptor from the EROM table. 777 * 778 * @param erom EROM read state. 779 * @param[out] mport On success, will be populated with the parsed 780 * descriptor data. 781 * @retval 0 success 782 * @retval non-zero Reading or parsing the descriptor failed. 783 */ 784 static int 785 bcma_erom_parse_mport(struct bcma_erom *erom, struct bcma_erom_mport *mport) 786 { 787 uint32_t entry; 788 int error; 789 790 /* Parse the master port descriptor */ 791 if ((error = bcma_erom_read32(erom, &entry))) 792 return (error); 793 794 if (!BCMA_EROM_ENTRY_IS(entry, MPORT)) 795 return (EINVAL); 796 797 mport->port_vid = BCMA_EROM_GET_ATTR(entry, MPORT_ID); 798 mport->port_num = BCMA_EROM_GET_ATTR(entry, MPORT_NUM); 799 800 return (0); 801 } 802 803 /** 804 * Read the next slave port region descriptor from the EROM table. 805 * 806 * @param erom EROM read state. 807 * @param[out] mport On success, will be populated with the parsed 808 * descriptor data. 809 * @retval 0 success 810 * @retval ENOENT The end of the region descriptor table was reached. 811 * @retval non-zero Reading or parsing the descriptor failed. 812 */ 813 static int 814 bcma_erom_parse_sport_region(struct bcma_erom *erom, 815 struct bcma_erom_sport_region *region) 816 { 817 uint32_t entry; 818 uint8_t size_type; 819 int error; 820 821 /* Peek at the region descriptor */ 822 if (bcma_erom_peek32(erom, &entry)) 823 return (EINVAL); 824 825 /* A non-region entry signals the end of the region table */ 826 if (!BCMA_EROM_ENTRY_IS(entry, REGION)) { 827 return (ENOENT); 828 } else { 829 bcma_erom_skip32(erom); 830 } 831 832 region->base_addr = BCMA_EROM_GET_ATTR(entry, REGION_BASE); 833 region->region_type = BCMA_EROM_GET_ATTR(entry, REGION_TYPE); 834 region->region_port = BCMA_EROM_GET_ATTR(entry, REGION_PORT); 835 size_type = BCMA_EROM_GET_ATTR(entry, REGION_SIZE); 836 837 /* If region address is 64-bit, fetch the high bits. */ 838 if (BCMA_EROM_GET_ATTR(entry, REGION_64BIT)) { 839 if ((error = bcma_erom_read32(erom, &entry))) 840 return (error); 841 842 region->base_addr |= ((bhnd_addr_t) entry << 32); 843 } 844 845 /* Parse the region size; it's either encoded as the binary logarithm 846 * of the number of 4K pages (i.e. log2 n), or its encoded as a 847 * 32-bit/64-bit literal value directly following the current entry. */ 848 if (size_type == BCMA_EROM_REGION_SIZE_OTHER) { 849 if ((error = bcma_erom_read32(erom, &entry))) 850 return (error); 851 852 region->size = BCMA_EROM_GET_ATTR(entry, RSIZE_VAL); 853 854 if (BCMA_EROM_GET_ATTR(entry, RSIZE_64BIT)) { 855 if ((error = bcma_erom_read32(erom, &entry))) 856 return (error); 857 region->size |= ((bhnd_size_t) entry << 32); 858 } 859 } else { 860 region->size = BCMA_EROM_REGION_SIZE_BASE << size_type; 861 } 862 863 /* Verify that addr+size does not overflow. */ 864 if (region->size != 0 && 865 BHND_ADDR_MAX - (region->size - 1) < region->base_addr) 866 { 867 EROM_LOG(erom, "%s%u: invalid address map %llx:%llx\n", 868 bcma_erom_entry_type_name(region->region_type), 869 region->region_port, 870 (unsigned long long) region->base_addr, 871 (unsigned long long) region->size); 872 873 return (EINVAL); 874 } 875 876 return (0); 877 } 878 879 /** 880 * Convert a bcma_erom_core record to its bhnd_core_info representation. 881 * 882 * @param core EROM core record to convert. 883 * @param core_idx The core index of @p core. 884 * @param core_unit The core unit of @p core. 885 * @param[out] info The populated bhnd_core_info representation. 886 */ 887 static void 888 bcma_erom_to_core_info(const struct bcma_erom_core *core, u_int core_idx, 889 int core_unit, struct bhnd_core_info *info) 890 { 891 info->vendor = core->vendor; 892 info->device = core->device; 893 info->hwrev = core->rev; 894 info->core_idx = core_idx; 895 info->unit = core_unit; 896 } 897 898 /** 899 * Map an EROM region type to its corresponding port type. 900 * 901 * @param region_type Region type value. 902 * @param[out] port_type On success, the corresponding port type. 903 */ 904 static int 905 bcma_erom_region_to_port_type(struct bcma_erom *erom, uint8_t region_type, 906 bhnd_port_type *port_type) 907 { 908 switch (region_type) { 909 case BCMA_EROM_REGION_TYPE_DEVICE: 910 *port_type = BHND_PORT_DEVICE; 911 return (0); 912 case BCMA_EROM_REGION_TYPE_BRIDGE: 913 *port_type = BHND_PORT_BRIDGE; 914 return (0); 915 case BCMA_EROM_REGION_TYPE_MWRAP: 916 case BCMA_EROM_REGION_TYPE_SWRAP: 917 *port_type = BHND_PORT_AGENT; 918 return (0); 919 default: 920 EROM_LOG(erom, "unsupported region type %hhx\n", 921 region_type); 922 return (EINVAL); 923 } 924 } 925 926 /** 927 * Register all MMIO region descriptors for the given slave port. 928 * 929 * @param erom EROM read state. 930 * @param corecfg Core info to be populated with the scanned port regions. 931 * @param port_num Port index for which regions will be parsed. 932 * @param region_type The region type to be parsed. 933 * @param[out] offset The offset at which to perform parsing. On success, this 934 * will be updated to point to the next EROM table entry. 935 */ 936 static int 937 bcma_erom_corecfg_fill_port_regions(struct bcma_erom *erom, 938 struct bcma_corecfg *corecfg, bcma_pid_t port_num, 939 uint8_t region_type) 940 { 941 struct bcma_sport *sport; 942 struct bcma_sport_list *sports; 943 bus_size_t entry_offset; 944 int error; 945 bhnd_port_type port_type; 946 947 error = 0; 948 949 /* Determine the port type for this region type. */ 950 error = bcma_erom_region_to_port_type(erom, region_type, &port_type); 951 if (error) 952 return (error); 953 954 /* Fetch the list to be populated */ 955 sports = bcma_corecfg_get_port_list(corecfg, port_type); 956 957 /* Allocate a new port descriptor */ 958 sport = bcma_alloc_sport(port_num, port_type); 959 if (sport == NULL) 960 return (ENOMEM); 961 962 /* Read all address regions defined for this port */ 963 for (bcma_rmid_t region_num = 0;; region_num++) { 964 struct bcma_map *map; 965 struct bcma_erom_sport_region spr; 966 967 /* No valid port definition should come anywhere near 968 * BCMA_RMID_MAX. */ 969 if (region_num == BCMA_RMID_MAX) { 970 EROM_LOG(erom, "core%u %s%u: region count reached " 971 "upper limit of %u\n", 972 corecfg->core_info.core_idx, 973 bhnd_port_type_name(port_type), 974 port_num, BCMA_RMID_MAX); 975 976 error = EINVAL; 977 goto cleanup; 978 } 979 980 /* Parse the next region entry. */ 981 entry_offset = bcma_erom_tell(erom); 982 error = bcma_erom_parse_sport_region(erom, &spr); 983 if (error && error != ENOENT) { 984 EROM_LOG(erom, "core%u %s%u.%u: invalid slave port " 985 "address region\n", 986 corecfg->core_info.core_idx, 987 bhnd_port_type_name(port_type), 988 port_num, region_num); 989 goto cleanup; 990 } 991 992 /* ENOENT signals no further region entries */ 993 if (error == ENOENT) { 994 /* No further entries */ 995 error = 0; 996 break; 997 } 998 999 /* A region or type mismatch also signals no further region 1000 * entries */ 1001 if (spr.region_port != port_num || 1002 spr.region_type != region_type) 1003 { 1004 /* We don't want to consume this entry */ 1005 bcma_erom_seek(erom, entry_offset); 1006 1007 error = 0; 1008 goto cleanup; 1009 } 1010 1011 /* 1012 * Create the map entry. 1013 */ 1014 map = malloc(sizeof(struct bcma_map), M_BHND, M_NOWAIT); 1015 if (map == NULL) { 1016 error = ENOMEM; 1017 goto cleanup; 1018 } 1019 1020 map->m_region_num = region_num; 1021 map->m_base = spr.base_addr; 1022 map->m_size = spr.size; 1023 map->m_rid = -1; 1024 1025 /* Add the region map to the port */ 1026 STAILQ_INSERT_TAIL(&sport->sp_maps, map, m_link); 1027 sport->sp_num_maps++; 1028 } 1029 1030 cleanup: 1031 /* Append the new port descriptor on success, or deallocate the 1032 * partially parsed descriptor on failure. */ 1033 if (error == 0) { 1034 STAILQ_INSERT_TAIL(sports, sport, sp_link); 1035 } else if (sport != NULL) { 1036 bcma_free_sport(sport); 1037 } 1038 1039 return error; 1040 } 1041 1042 /** 1043 * Parse the next core entry from the EROM table and produce a bcma_corecfg 1044 * to be owned by the caller. 1045 * 1046 * @param erom A bcma EROM instance. 1047 * @param[out] result On success, the core's device info. The caller inherits 1048 * ownership of this allocation. 1049 * 1050 * @return If successful, returns 0. If the end of the EROM table is hit, 1051 * ENOENT will be returned. On error, returns a non-zero error value. 1052 */ 1053 int 1054 bcma_erom_next_corecfg(struct bcma_erom *erom, struct bcma_corecfg **result) 1055 { 1056 struct bcma_corecfg *cfg; 1057 struct bcma_erom_core core; 1058 uint8_t first_region_type; 1059 bus_size_t initial_offset; 1060 u_int core_index; 1061 int core_unit; 1062 int error; 1063 1064 cfg = NULL; 1065 initial_offset = bcma_erom_tell(erom); 1066 1067 /* Parse the next core entry */ 1068 if ((error = bcma_erom_parse_core(erom, &core))) 1069 return (error); 1070 1071 /* Determine the core's index and unit numbers */ 1072 bcma_erom_reset(erom); 1073 core_unit = 0; 1074 core_index = 0; 1075 for (; bcma_erom_tell(erom) != initial_offset; core_index++) { 1076 struct bcma_erom_core prev_core; 1077 1078 /* Parse next core */ 1079 error = bcma_erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); 1080 if (error) 1081 return (error); 1082 1083 if ((error = bcma_erom_parse_core(erom, &prev_core))) 1084 return (error); 1085 1086 /* Is earlier unit? */ 1087 if (core.vendor == prev_core.vendor && 1088 core.device == prev_core.device) 1089 { 1090 core_unit++; 1091 } 1092 1093 /* Seek to next core */ 1094 error = bcma_erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE); 1095 if (error) 1096 return (error); 1097 } 1098 1099 /* We already parsed the core descriptor */ 1100 if ((error = bcma_erom_skip_core(erom))) 1101 return (error); 1102 1103 /* Allocate our corecfg */ 1104 cfg = bcma_alloc_corecfg(core_index, core_unit, core.vendor, 1105 core.device, core.rev); 1106 if (cfg == NULL) 1107 return (ENOMEM); 1108 1109 /* These are 5-bit values in the EROM table, and should never be able 1110 * to overflow BCMA_PID_MAX. */ 1111 KASSERT(core.num_mport <= BCMA_PID_MAX, ("unsupported mport count")); 1112 KASSERT(core.num_dport <= BCMA_PID_MAX, ("unsupported dport count")); 1113 KASSERT(core.num_mwrap + core.num_swrap <= BCMA_PID_MAX, 1114 ("unsupported wport count")); 1115 1116 if (bootverbose) { 1117 EROM_LOG(erom, 1118 "core%u: %s %s (cid=%hx, rev=%hu, unit=%d)\n", 1119 core_index, 1120 bhnd_vendor_name(core.vendor), 1121 bhnd_find_core_name(core.vendor, core.device), 1122 core.device, core.rev, core_unit); 1123 } 1124 1125 cfg->num_master_ports = core.num_mport; 1126 cfg->num_dev_ports = 0; /* determined below */ 1127 cfg->num_bridge_ports = 0; /* determined blow */ 1128 cfg->num_wrapper_ports = core.num_mwrap + core.num_swrap; 1129 1130 /* Parse Master Port Descriptors */ 1131 for (uint8_t i = 0; i < core.num_mport; i++) { 1132 struct bcma_mport *mport; 1133 struct bcma_erom_mport mpd; 1134 1135 /* Parse the master port descriptor */ 1136 error = bcma_erom_parse_mport(erom, &mpd); 1137 if (error) 1138 goto failed; 1139 1140 /* Initialize a new bus mport structure */ 1141 mport = malloc(sizeof(struct bcma_mport), M_BHND, M_NOWAIT); 1142 if (mport == NULL) { 1143 error = ENOMEM; 1144 goto failed; 1145 } 1146 1147 mport->mp_vid = mpd.port_vid; 1148 mport->mp_num = mpd.port_num; 1149 1150 /* Update dinfo */ 1151 STAILQ_INSERT_TAIL(&cfg->master_ports, mport, mp_link); 1152 } 1153 1154 /* 1155 * Determine whether this is a bridge device; if so, we can 1156 * expect the first sequence of address region descriptors to 1157 * be of EROM_REGION_TYPE_BRIDGE instead of 1158 * BCMA_EROM_REGION_TYPE_DEVICE. 1159 * 1160 * It's unclear whether this is the correct mechanism by which we 1161 * should detect/handle bridge devices, but this approach matches 1162 * that of (some of) Broadcom's published drivers. 1163 */ 1164 if (core.num_dport > 0) { 1165 uint32_t entry; 1166 1167 if ((error = bcma_erom_peek32(erom, &entry))) 1168 goto failed; 1169 1170 if (BCMA_EROM_ENTRY_IS(entry, REGION) && 1171 BCMA_EROM_GET_ATTR(entry, REGION_TYPE) == BCMA_EROM_REGION_TYPE_BRIDGE) 1172 { 1173 first_region_type = BCMA_EROM_REGION_TYPE_BRIDGE; 1174 cfg->num_dev_ports = 0; 1175 cfg->num_bridge_ports = core.num_dport; 1176 } else { 1177 first_region_type = BCMA_EROM_REGION_TYPE_DEVICE; 1178 cfg->num_dev_ports = core.num_dport; 1179 cfg->num_bridge_ports = 0; 1180 } 1181 } 1182 1183 /* Device/bridge port descriptors */ 1184 for (uint8_t sp_num = 0; sp_num < core.num_dport; sp_num++) { 1185 error = bcma_erom_corecfg_fill_port_regions(erom, cfg, sp_num, 1186 first_region_type); 1187 1188 if (error) 1189 goto failed; 1190 } 1191 1192 /* Wrapper (aka device management) descriptors (for master ports). */ 1193 for (uint8_t sp_num = 0; sp_num < core.num_mwrap; sp_num++) { 1194 error = bcma_erom_corecfg_fill_port_regions(erom, cfg, sp_num, 1195 BCMA_EROM_REGION_TYPE_MWRAP); 1196 1197 if (error) 1198 goto failed; 1199 } 1200 1201 /* Wrapper (aka device management) descriptors (for slave ports). */ 1202 for (uint8_t i = 0; i < core.num_swrap; i++) { 1203 /* Slave wrapper ports are not numbered distinctly from master 1204 * wrapper ports. */ 1205 1206 /* 1207 * Broadcom DDR1/DDR2 Memory Controller 1208 * (cid=82e, rev=1, unit=0, d/mw/sw = 2/0/1 ) -> 1209 * bhnd0: erom[0xdc]: core6 agent0.0: mismatch got: 0x1 (0x2) 1210 * 1211 * ARM BP135 AMBA3 AXI to APB Bridge 1212 * (cid=135, rev=0, unit=0, d/mw/sw = 1/0/1 ) -> 1213 * bhnd0: erom[0x124]: core9 agent1.0: mismatch got: 0x0 (0x2) 1214 * 1215 * core.num_mwrap 1216 * ===> 1217 * (core.num_mwrap > 0) ? 1218 * core.num_mwrap : 1219 * ((core.vendor == BHND_MFGID_BCM) ? 1 : 0) 1220 */ 1221 uint8_t sp_num; 1222 sp_num = (core.num_mwrap > 0) ? 1223 core.num_mwrap : 1224 ((core.vendor == BHND_MFGID_BCM) ? 1 : 0) + i; 1225 error = bcma_erom_corecfg_fill_port_regions(erom, cfg, sp_num, 1226 BCMA_EROM_REGION_TYPE_SWRAP); 1227 1228 if (error) 1229 goto failed; 1230 } 1231 1232 /* 1233 * Seek to the next core entry (if any), skipping any dangling/invalid 1234 * region entries. 1235 * 1236 * On the BCM4706, the EROM entry for the memory controller core 1237 * (0x4bf/0x52E) contains a dangling/unused slave wrapper port region 1238 * descriptor. 1239 */ 1240 if ((error = bcma_erom_seek_next(erom, BCMA_EROM_ENTRY_TYPE_CORE))) { 1241 if (error != ENOENT) 1242 goto failed; 1243 } 1244 1245 *result = cfg; 1246 return (0); 1247 1248 failed: 1249 if (cfg != NULL) 1250 bcma_free_corecfg(cfg); 1251 1252 return error; 1253 } 1254 1255 static int 1256 bcma_erom_dump(bhnd_erom_t *erom) 1257 { 1258 struct bcma_erom *sc; 1259 uint32_t entry; 1260 int error; 1261 1262 sc = (struct bcma_erom *)erom; 1263 1264 bcma_erom_reset(sc); 1265 1266 while (!(error = bcma_erom_read32(sc, &entry))) { 1267 /* Handle EOF */ 1268 if (entry == BCMA_EROM_TABLE_EOF) { 1269 EROM_LOG(sc, "EOF\n"); 1270 return (0); 1271 } 1272 1273 /* Invalid entry */ 1274 if (!BCMA_EROM_GET_ATTR(entry, ENTRY_ISVALID)) { 1275 EROM_LOG(sc, "invalid EROM entry %#x\n", entry); 1276 return (EINVAL); 1277 } 1278 1279 switch (BCMA_EROM_GET_ATTR(entry, ENTRY_TYPE)) { 1280 case BCMA_EROM_ENTRY_TYPE_CORE: { 1281 /* CoreDescA */ 1282 EROM_LOG(sc, "coreA (0x%x)\n", entry); 1283 EROM_LOG(sc, "\tdesigner:\t0x%x\n", 1284 BCMA_EROM_GET_ATTR(entry, COREA_DESIGNER)); 1285 EROM_LOG(sc, "\tid:\t\t0x%x\n", 1286 BCMA_EROM_GET_ATTR(entry, COREA_ID)); 1287 EROM_LOG(sc, "\tclass:\t\t0x%x\n", 1288 BCMA_EROM_GET_ATTR(entry, COREA_CLASS)); 1289 1290 /* CoreDescB */ 1291 if ((error = bcma_erom_read32(sc, &entry))) { 1292 EROM_LOG(sc, "error reading CoreDescB: %d\n", 1293 error); 1294 return (error); 1295 } 1296 1297 if (!BCMA_EROM_ENTRY_IS(entry, CORE)) { 1298 EROM_LOG(sc, "invalid core descriptor; found " 1299 "unexpected entry %#x (type=%s)\n", 1300 entry, bcma_erom_entry_type_name(entry)); 1301 return (EINVAL); 1302 } 1303 1304 EROM_LOG(sc, "coreB (0x%x)\n", entry); 1305 EROM_LOG(sc, "\trev:\t0x%x\n", 1306 BCMA_EROM_GET_ATTR(entry, COREB_REV)); 1307 EROM_LOG(sc, "\tnummp:\t0x%x\n", 1308 BCMA_EROM_GET_ATTR(entry, COREB_NUM_MP)); 1309 EROM_LOG(sc, "\tnumdp:\t0x%x\n", 1310 BCMA_EROM_GET_ATTR(entry, COREB_NUM_DP)); 1311 EROM_LOG(sc, "\tnumwmp:\t0x%x\n", 1312 BCMA_EROM_GET_ATTR(entry, COREB_NUM_WMP)); 1313 EROM_LOG(sc, "\tnumwsp:\t0x%x\n", 1314 BCMA_EROM_GET_ATTR(entry, COREB_NUM_WMP)); 1315 1316 break; 1317 } 1318 case BCMA_EROM_ENTRY_TYPE_MPORT: 1319 EROM_LOG(sc, "\tmport 0x%x\n", entry); 1320 EROM_LOG(sc, "\t\tport:\t0x%x\n", 1321 BCMA_EROM_GET_ATTR(entry, MPORT_NUM)); 1322 EROM_LOG(sc, "\t\tid:\t\t0x%x\n", 1323 BCMA_EROM_GET_ATTR(entry, MPORT_ID)); 1324 break; 1325 1326 case BCMA_EROM_ENTRY_TYPE_REGION: { 1327 bool addr64; 1328 uint8_t size_type; 1329 1330 addr64 = (BCMA_EROM_GET_ATTR(entry, REGION_64BIT) != 0); 1331 size_type = BCMA_EROM_GET_ATTR(entry, REGION_SIZE); 1332 1333 EROM_LOG(sc, "\tregion 0x%x:\n", entry); 1334 EROM_LOG(sc, "\t\t%s:\t0x%x\n", 1335 addr64 ? "baselo" : "base", 1336 BCMA_EROM_GET_ATTR(entry, REGION_BASE)); 1337 EROM_LOG(sc, "\t\tport:\t0x%x\n", 1338 BCMA_EROM_GET_ATTR(entry, REGION_PORT)); 1339 EROM_LOG(sc, "\t\ttype:\t0x%x\n", 1340 BCMA_EROM_GET_ATTR(entry, REGION_TYPE)); 1341 EROM_LOG(sc, "\t\tsztype:\t0x%hhx\n", size_type); 1342 1343 /* Read the base address high bits */ 1344 if (addr64) { 1345 if ((error = bcma_erom_read32(sc, &entry))) { 1346 EROM_LOG(sc, "error reading region " 1347 "base address high bits %d\n", 1348 error); 1349 return (error); 1350 } 1351 1352 EROM_LOG(sc, "\t\tbasehi:\t0x%x\n", entry); 1353 } 1354 1355 /* Read extended size descriptor */ 1356 if (size_type == BCMA_EROM_REGION_SIZE_OTHER) { 1357 bool size64; 1358 1359 if ((error = bcma_erom_read32(sc, &entry))) { 1360 EROM_LOG(sc, "error reading region " 1361 "size descriptor %d\n", 1362 error); 1363 return (error); 1364 } 1365 1366 if (BCMA_EROM_GET_ATTR(entry, RSIZE_64BIT)) 1367 size64 = true; 1368 else 1369 size64 = false; 1370 1371 EROM_LOG(sc, "\t\t%s:\t0x%x\n", 1372 size64 ? "sizelo" : "size", 1373 BCMA_EROM_GET_ATTR(entry, RSIZE_VAL)); 1374 1375 if (size64) { 1376 error = bcma_erom_read32(sc, &entry); 1377 if (error) { 1378 EROM_LOG(sc, "error reading " 1379 "region size high bits: " 1380 "%d\n", error); 1381 return (error); 1382 } 1383 1384 EROM_LOG(sc, "\t\tsizehi:\t0x%x\n", 1385 entry); 1386 } 1387 } 1388 break; 1389 } 1390 1391 default: 1392 EROM_LOG(sc, "unknown EROM entry 0x%x (type=%s)\n", 1393 entry, bcma_erom_entry_type_name(entry)); 1394 return (EINVAL); 1395 } 1396 } 1397 1398 if (error == ENOENT) 1399 EROM_LOG(sc, "BCMA EROM table missing terminating EOF\n"); 1400 else if (error) 1401 EROM_LOG(sc, "EROM read failed: %d\n", error); 1402 1403 return (error); 1404 } 1405 1406 static kobj_method_t bcma_erom_methods[] = { 1407 KOBJMETHOD(bhnd_erom_probe, bcma_erom_probe), 1408 KOBJMETHOD(bhnd_erom_init, bcma_erom_init), 1409 KOBJMETHOD(bhnd_erom_fini, bcma_erom_fini), 1410 KOBJMETHOD(bhnd_erom_get_core_table, bcma_erom_get_core_table), 1411 KOBJMETHOD(bhnd_erom_free_core_table, bcma_erom_free_core_table), 1412 KOBJMETHOD(bhnd_erom_lookup_core, bcma_erom_lookup_core), 1413 KOBJMETHOD(bhnd_erom_lookup_core_addr, bcma_erom_lookup_core_addr), 1414 KOBJMETHOD(bhnd_erom_dump, bcma_erom_dump), 1415 1416 KOBJMETHOD_END 1417 }; 1418 1419 BHND_EROM_DEFINE_CLASS(bcma_erom, bcma_erom_parser, bcma_erom_methods, sizeof(struct bcma_erom)); 1420