xgs.c (17842B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: xgs.c 8 * Purpose: Simple XGS board programming support library 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <sal/core/alloc.h> 14 #include <sal/core/libc.h> 15 #include <bcm/error.h> 16 #include <bcm/stack.h> 17 #include <board/board.h> 18 #if defined(INCLUDE_LIB_STKTASK) 19 #include <appl/stktask/topo_brd.h> 20 #endif 21 #if defined(INCLUDE_LIB_DISCOVER) 22 #include <appl/discover/disc.h> 23 #endif 24 #include <board/manager.h> 25 #include <board/stack.h> 26 #include <board/xgs.h> 27 #include <board_int/support.h> 28 29 #ifndef MAX_DESCRIPTION 30 #define MAX_DESCRIPTION 80 31 #endif 32 33 #define UNIT0 0 34 35 STATIC int 36 _board_xgs_modid_get(board_driver_t *driver, char *name, int *modid); 37 STATIC int 38 _board_xgs_modid_set(board_driver_t *driver, char *name, int modid); 39 STATIC int 40 _board_xgs_num_modid_get(board_driver_t *driver, 41 char *name, int *num_modid); 42 43 #define PRIVATE(field) \ 44 (((board_xgs_data_t *)(driver->user_data))->field) 45 46 board_attribute_t board_xgs_attrib[] = { 47 { 48 BOARD_ATTRIBUTE_MODID, 49 _board_xgs_modid_get, 50 _board_xgs_modid_set, 51 }, 52 { 53 BOARD_ATTRIBUTE_NUM_MODID, 54 _board_xgs_num_modid_get, 55 NULL 56 } 57 }; 58 59 60 61 /* 62 * Function: 63 * _board_xgs_modid_get 64 * Purpose: 65 * Get board modid 66 * Parameters: 67 * driver - (IN) current driver 68 * name - (IN) attribute name (ignored) 69 * modid - (OUT) modid 70 * Returns: 71 * BCM_E_NONE - success 72 * BCM_E_XXX - failed 73 */ 74 STATIC int 75 _board_xgs_modid_get(board_driver_t *driver, char *name, int *modid) 76 { 77 if (!modid) { 78 return BCM_E_PARAM; 79 } 80 81 *modid = PRIVATE(device[UNIT0].modid); 82 83 return BCM_E_NONE; 84 } 85 86 /* 87 * Function: 88 * _adjust_modid 89 * Purpose: 90 * If the given modid does not match the mask constraint, 91 * adjust it so it does 92 * Parameters: 93 * device - (IN) device data 94 * modid - (INOUT) modid 95 * Returns: 96 * BCM_E_NONE - success 97 * BCM_E_XXX - failed 98 */ 99 STATIC int 100 _adjust_modid(board_xgs_device_data_t *device, int *modid) 101 { 102 if ((device->modid_mask & *modid) != *modid) { 103 *modid = (device->modid_mask & *modid) + device->num_modid; 104 } 105 device->modid = *modid; 106 107 return BCM_E_NONE; 108 } 109 110 /* 111 * Function: 112 * _board_xgs_modid_set 113 * Purpose: 114 * Set the board modid 115 * Parameters: 116 * driver - (IN) current driver 117 * name - (IN) attribute name (ignored) 118 * modid - (IN) modid 119 * Returns: 120 * BCM_E_NONE - success 121 * BCM_E_XXX - failed 122 */ 123 STATIC int 124 _board_xgs_modid_set(board_driver_t *driver, char *name, int modid) 125 { 126 int unit; 127 int current_modid; 128 129 current_modid = modid; 130 131 for (unit=0; unit < PRIVATE(num_device); unit++) { 132 _adjust_modid(&PRIVATE(device[unit]), ¤t_modid); 133 BCM_IF_ERROR_RETURN(bcm_stk_my_modid_set(unit, current_modid)); 134 PRIVATE(device[unit].modid) = current_modid; 135 current_modid += PRIVATE(device[unit].num_modid); 136 } 137 138 return BCM_E_NONE; 139 } 140 141 /* 142 * Function: 143 * _board_xgs_num_modid_get 144 * Purpose: 145 * Get the number of modids required by this board 146 * Parameters: 147 * driver - (IN) current driver (ignored) 148 * name - (IN) attribute name (ignored) 149 * modid - (OUT) modid 150 * Returns: 151 * BCM_E_NONE - success 152 * BCM_E_XXX - failed 153 */ 154 STATIC int 155 _board_xgs_num_modid_get(board_driver_t *driver, 156 char *name, int *num_modid) 157 { 158 int unit; 159 int nm; 160 161 if (!num_modid) { 162 return BCM_E_PARAM; 163 } 164 165 nm = 0; 166 167 for (unit=0; unit < PRIVATE(num_device); unit++) { 168 nm += PRIVATE(device[unit].num_modid); 169 } 170 171 *num_modid = nm; 172 173 return BCM_E_NONE; 174 } 175 176 #if defined(INCLUDE_LIB_CPUDB) 177 178 /* 179 * Function: 180 * _board_xgs_stack_init 181 * Purpose: 182 * Initialize cpudb and required stacking subsystems 183 * Parameters: 184 * driver - (IN) current driver 185 * db_ref - (OUT) stack CPUDB 186 * Returns: 187 * BCM_E_NONE - success 188 * BCM_E_XXX - failed 189 */ 190 STATIC int 191 _board_xgs_stack_init(board_driver_t *driver, cpudb_ref_t db_ref) 192 { 193 BCM_IF_ERROR_RETURN(board_cpudb_get(driver, db_ref)); 194 #if defined(INCLUDE_LIB_DISCOVER) 195 disc_ttl_max_set(2); 196 #endif 197 return BCM_E_NONE; 198 } 199 200 /* 201 * Function: 202 * _board_xgs_stack 203 * Purpose: 204 * Manage stktask callbacks 205 * Parameters: 206 * op - (IN) current driver 207 * db_ref - (IN/OUT) stack CPUDB 208 * topo_cpu - (IN) stack TOPO_CPU (ignored) 209 * user_data - (IN) user data 210 * Returns: 211 * BCM_E_NONE - success 212 * BCM_E_XXX - failed 213 */ 214 STATIC int 215 _board_xgs_stack(topo_board_control_t op, 216 cpudb_ref_t db_ref, 217 topo_cpu_t *topo_cpu, 218 void *user_data) 219 { 220 int rv = BCM_E_PARAM; 221 board_driver_t *driver = (board_driver_t *)user_data; 222 223 switch (op) { 224 case topoBoardInit: 225 rv = _board_xgs_stack_init(driver, db_ref); 226 break; 227 228 case topoBoardProgram: 229 rv = board_stack_program(db_ref, 0); 230 break; 231 232 default: 233 break; 234 235 } 236 237 return rv; 238 } 239 #endif 240 241 /* 242 * Function: 243 * board_xgs_description 244 * Purpose: 245 * Return the board description string 246 * Parameters: 247 * driver - (IN) current driver 248 * Returns: 249 * BCM_E_NONE - success 250 * BCM_E_XXX - failed 251 */ 252 char * 253 board_xgs_description(board_driver_t *driver) 254 { 255 return PRIVATE(description); 256 } 257 258 /* 259 * Function: 260 * board_xgs_probe 261 * Purpose: 262 * Test if board devices are appropriate for this board. 263 * Parameters: 264 * driver - (IN) board driver 265 * num - (IN) number of devices; length of info array 266 * info - (IN) array of bcm_info_t 267 * Returns: 268 * BCM_E_NONE - success 269 * BCM_E_XXX - failed 270 */ 271 int 272 board_xgs_probe(board_driver_t *driver, int num, bcm_info_t *info) 273 { 274 int i,j,idx,rv,match; 275 276 rv = BCM_E_FAIL; 277 278 if (num == PRIVATE(num_device)) { 279 280 /* The number of supported devices needs to be modulo the number 281 of devices on the board. */ 282 if (PRIVATE(num_supported_device) % PRIVATE(num_device)) { 283 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 284 (BSL_META("%s: devtab not modulo numdev\n"), 285 driver->name)); 286 return BCM_E_CONFIG; 287 } 288 for (i=0; i<PRIVATE(num_supported_device); i+=PRIVATE(num_device)) { 289 match=0; 290 291 /* Test successive num_device entries for a match */ 292 for (j=0; j<PRIVATE(num_device); j++) { 293 idx = i+j; 294 if ((PRIVATE(supported_device[idx]) == 295 BOARD_DRIVER_ANY_DEVICE) || 296 (PRIVATE(supported_device[idx]) == info[j].device)) { 297 match++; 298 } else { 299 /* No match, try next set of devices */ 300 break; 301 } 302 } 303 if (match == PRIVATE(num_device)) { 304 /* Found something */ 305 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 306 (BSL_META("%s: units match\n"), 307 driver->name)); 308 rv = BCM_E_NONE; 309 break; 310 } 311 } 312 } 313 314 return rv; 315 } 316 317 /* 318 * Function: 319 * _board_xgs_banner 320 * Purpose: 321 * Setup the board description string 322 * Parameters: 323 * driver - (IN) board driver 324 * Returns: 325 * BCM_E_NONE - success 326 * BCM_E_XXX - failed 327 */ 328 STATIC int 329 _board_xgs_banner(board_driver_t *driver) 330 { 331 if (PRIVATE(description) == NULL) { 332 PRIVATE(description) = sal_alloc(MAX_DESCRIPTION, driver->name); 333 if (PRIVATE(description) == NULL) { 334 return BCM_E_MEMORY; 335 } 336 } 337 338 sal_sprintf(PRIVATE(description), "%s board driver", driver->name); 339 340 return BCM_E_NONE; 341 } 342 343 /* 344 * Function: 345 * _board_xgs_add_internal_connections 346 * Purpose: 347 * Add internal connections to probed stackable ports to 348 * construct a merged connection list for this board 349 * Parameters: 350 * driver - (IN) board driver 351 * count - (IN) number of connections 352 * conn - (IN) connection list 353 * Returns: 354 * BCM_E_NONE - success 355 * BCM_E_XXX - failed 356 * Notes: 357 * gports are not conveniently orderable, so merge with brute force 358 */ 359 STATIC int 360 _board_xgs_add_internal_connections(board_driver_t *driver, 361 int *count, board_connection_t *conn) 362 { 363 int i,j,replace,end,d_idx; 364 bcm_gport_t i_port; 365 board_connection_t *internal = PRIVATE(internal_connection); 366 367 end = *count; 368 for (i=0; i<PRIVATE(num_internal_connection); i++) { 369 370 replace = -1; 371 d_idx = -1; 372 for (j=0; j<end; j++) { 373 374 i_port = BCM_GPORT_TYPE_NONE; 375 376 /* If either internal port matches the current connection 377 list .from port, copy the 'other' internal port to the 378 connection list .to entry, and prepare to remove the 379 other internal port from the connection list. This 380 should always be found after the current connection 381 list position. */ 382 if (conn[j].from == internal[i].from) { 383 i_port = internal[i].to; 384 } else if (conn[j].from == internal[i].to) { 385 i_port = internal[i].from; 386 } 387 388 if (i_port != BCM_GPORT_TYPE_NONE) { 389 if (replace < 0) { 390 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 391 (BSL_META("Adding internal connection %d to conn %d\n"), 392 i, j)); 393 /* if internal_connection.from matches conn.from */ 394 conn[j].to = i_port; 395 replace = i; 396 } else { 397 /* one side of internal matched, delete other side */ 398 d_idx = j; 399 break; 400 } 401 } 402 } 403 404 if (d_idx >= 0) { 405 /* move up entries over deleted entry */ 406 for (j=d_idx; j<end; j++) { 407 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 408 (BSL_META("Copying %d to %d\n"), 409 j+1, j)); 410 conn[j] = conn[j+1]; 411 } 412 end -= 1; 413 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 414 (BSL_META("Delete, end now %d\n"), 415 end)); 416 } else if (replace < 0) { 417 /* add the internal entry to the end of the list */ 418 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 419 (BSL_META("Copying internal %d to %d\n"), 420 i, end)); 421 sal_memcpy(&conn[end], &internal[i], sizeof(conn[end])); 422 end += 1; 423 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 424 (BSL_META("Add internal, end now %d\n"), 425 end)); 426 } 427 } 428 429 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 430 (BSL_META("Board: %d internal, %d stack connections\n"), 431 PRIVATE(num_internal_connection), 432 end - PRIVATE(num_internal_connection))); 433 434 *count = end; 435 return BCM_E_NONE; 436 } 437 438 439 440 /* 441 * Function: 442 * _board_xgs_initialize_connections 443 * Purpose: 444 * Create connections for board based on requested and probed data 445 * Parameters: 446 * driver - (IN) board driver 447 * Returns: 448 * BCM_E_NONE - success 449 * BCM_E_XXX - failed 450 */ 451 STATIC int 452 _board_xgs_initialize_connections(board_driver_t *driver) 453 { 454 board_connection_t *conn; 455 int count; 456 int rv = BCM_E_FAIL; 457 458 /* create connection array with the largest possible length */ 459 460 count = PRIVATE(num_device) * BCM_PBMP_PORT_MAX; 461 conn = sal_alloc(count * sizeof(*conn), driver->name); 462 463 if (conn) { 464 sal_memset(conn, 0, count * sizeof(*conn)); 465 rv = board_connection_stack_ports(count, conn, &count); 466 if (BCM_SUCCESS(rv)) { 467 /* Go though the internal connection list */ 468 rv = _board_xgs_add_internal_connections(driver, &count, conn); 469 } else { 470 sal_free(conn); 471 } 472 } else { 473 rv = BCM_E_MEMORY; 474 } 475 476 if (BCM_SUCCESS(rv)) { 477 /* Add connection list to driver structure */ 478 driver->connection = conn; 479 driver->num_connection = count; 480 } 481 return rv; 482 } 483 484 /* 485 * Function: 486 * _board_xgs_initialize 487 * Purpose: 488 * Initialize driver data 489 * Parameters: 490 * driver - (IN) board driver 491 * Returns: 492 * BCM_E_NONE - success 493 * BCM_E_XXX - failed 494 */ 495 STATIC int 496 _board_xgs_initialize(board_driver_t *driver) 497 { 498 BCM_IF_ERROR_RETURN 499 (board_connection_add_internal_stack_ports 500 (PRIVATE(num_internal_connection), 501 PRIVATE(internal_connection))); 502 BCM_IF_ERROR_RETURN(_board_xgs_initialize_connections(driver)); 503 BCM_IF_ERROR_RETURN(board_connection_setup()); 504 return BCM_E_NONE; 505 506 } 507 508 /* 509 * Function: 510 * _board_xgs_cold_boot 511 * Purpose: 512 * Cold boot device 513 * Parameters: 514 * driver - (IN) board driver 515 * unit - (IN) BCM device number 516 * Returns: 517 * BCM_E_NONE - success 518 * BCM_E_XXX - failed 519 */ 520 STATIC int 521 _board_xgs_cold_boot(board_driver_t *driver, int unit) 522 { 523 BCM_IF_ERROR_RETURN(board_device_init(unit)); 524 BCM_IF_ERROR_RETURN(board_port_init(unit)); 525 526 /* I2C devices are only on unit 0 */ 527 if (unit == UNIT0) { 528 #if defined(INCLUDE_I2C) 529 BCM_IF_ERROR_RETURN(board_i2c_device_init(unit)); 530 #endif 531 532 } 533 534 BCM_IF_ERROR_RETURN(bcm_info_get(unit, &PRIVATE(device[unit].info))); 535 536 BCM_IF_ERROR_RETURN 537 (bcm_stk_modid_count(unit, &PRIVATE(device[unit].num_modid))); 538 539 PRIVATE(device[unit].modid_mask) = 540 ~(PRIVATE(device[unit].num_modid) - 1); 541 542 return BCM_E_NONE; 543 } 544 545 /* 546 547 */ 548 /* 549 * Function: 550 * _board_xgs_init_modid 551 * Purpose: 552 * Initialize modid on all devices 553 * Parameters: 554 * driver - (IN) board driver 555 * Returns: 556 * BCM_E_NONE - success 557 * BCM_E_XXX - failed 558 */ 559 STATIC int 560 _board_xgs_init_modid(board_driver_t *driver) 561 { 562 int unit, modid, rv = BCM_E_NONE; 563 564 for (unit=0; unit<PRIVATE(num_device); unit++) { 565 rv = bcm_stk_my_modid_get(unit, &modid); 566 if (BCM_SUCCESS(rv)) { 567 rv = _board_xgs_modid_set(driver, NULL, modid); 568 } else if (rv != BCM_E_UNAVAIL) { 569 break; /* if the error is not UNAVAIL, 570 something bad is happening */ 571 } 572 } 573 574 return rv; 575 } 576 577 /* 578 * Function: 579 * _board_xgs_warm_boot 580 * Purpose: 581 * Warm Boot device 582 * Parameters: 583 * driver - (IN) board driver 584 * unit - (IN) BCM device number 585 * Returns: 586 * BCM_E_NONE - success 587 * BCM_E_XXX - failed 588 */ 589 STATIC int 590 _board_xgs_warm_boot(board_driver_t *driver, int unit) 591 { 592 return BCM_E_UNAVAIL; 593 } 594 595 /* 596 * Function: 597 * _board_xgs_clear 598 * Purpose: 599 * Clear device 600 * Parameters: 601 * driver - (IN) board driver 602 * unit - (IN) BCM device number 603 * Returns: 604 * BCM_E_NONE - success 605 * BCM_E_XXX - failed 606 */ 607 STATIC int 608 _board_xgs_clear(board_driver_t *driver, int unit) 609 { 610 return BCM_E_UNAVAIL; 611 } 612 613 614 /* 615 * Function: 616 * board_xgs_start 617 * Purpose: 618 * XGS Board driver start function 619 * Parameters: 620 * driver - (IN) board driver 621 * flags - (IN) start flags 622 * Returns: 623 * BCM_E_NONE - success 624 * BCM_E_XXX - failed 625 */ 626 int 627 board_xgs_start(board_driver_t *driver, uint32 flags) 628 { 629 int unit; 630 631 /* allocate device instance data */ 632 if (PRIVATE(device) == NULL) { 633 PRIVATE(device) = sal_alloc 634 (sizeof(PRIVATE(device[UNIT0])) * (PRIVATE(num_device)), 635 driver->name); 636 if (PRIVATE(device) == NULL) { 637 return BCM_E_MEMORY; 638 } 639 } 640 641 /* install attributes */ 642 driver->attribute = board_xgs_attrib; 643 driver->num_attribute = COUNTOF(board_xgs_attrib); 644 645 /* init all the units */ 646 for (unit=0; unit<PRIVATE(num_device); unit++) { 647 if (flags & BOARD_START_F_WARM_BOOT) { 648 BCM_IF_ERROR_RETURN(_board_xgs_warm_boot(driver, unit)); 649 } else if (flags & BOARD_START_F_CLEAR) { 650 BCM_IF_ERROR_RETURN(_board_xgs_clear(driver, unit)); 651 } else { 652 BCM_IF_ERROR_RETURN(_board_xgs_cold_boot(driver, unit)); 653 } 654 } 655 656 BCM_IF_ERROR_RETURN(_board_xgs_init_modid(driver)); 657 658 /* Hook into stacking */ 659 #if defined(INCLUDE_LIB_STKTASK) && defined(INCLUDE_LIB_CPUDB) 660 BCM_IF_ERROR_RETURN 661 (topo_board_register(_board_xgs_stack, (void *)driver)); 662 #endif 663 BCM_IF_ERROR_RETURN(_board_xgs_initialize(driver)); 664 BCM_IF_ERROR_RETURN(_board_xgs_banner(driver)); 665 666 LOG_VERBOSE(BSL_LS_BOARD_COMMON, 667 (BSL_META_U(unit, 668 "%s\n"), 669 PRIVATE(description))); 670 671 return BCM_E_NONE; 672 } 673 674 /* 675 * Function: 676 * board_xgs_stop 677 * Purpose: 678 * XGS Board driver stop function 679 * Parameters: 680 * driver - (IN) board driver 681 * Returns: 682 * BCM_E_NONE - success 683 * BCM_E_XXX - failed 684 */ 685 int 686 board_xgs_stop(board_driver_t *driver) 687 { 688 board_xgs_device_data_t *dev; 689 char *str; 690 int unit; 691 692 /* deinit all the units */ 693 for (unit=0; unit<PRIVATE(num_device); unit++) { 694 BCM_IF_ERROR_RETURN(board_port_deinit(unit)); 695 BCM_IF_ERROR_RETURN(board_device_deinit(unit)); 696 } 697 698 /* Reset dynamic data */ 699 driver->num_connection = 0; 700 if (driver->connection) { 701 sal_free(driver->connection); 702 driver->connection = NULL; 703 } 704 705 dev = PRIVATE(device); 706 PRIVATE(device) = NULL; 707 sal_free(dev); 708 709 str = PRIVATE(description); 710 PRIVATE(description) = NULL; 711 sal_free(str); 712 713 return BCM_E_NONE; 714 } 715 716