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