xaui.c (25740B)
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 * XAUI Error monitoring features. 8 */ 9 10 #include <sal/core/libc.h> 11 #include <shared/alloc.h> 12 #include <sal/core/spl.h> 13 #include <sal/core/boot.h> 14 15 #include <soc/drv.h> 16 #include <soc/error.h> 17 #include <soc/cmic.h> 18 #include <soc/portmode.h> 19 #include <soc/ll.h> 20 #include <soc/xaui.h> 21 #include <soc/phyctrl.h> 22 #include <soc/debug.h> 23 #include <soc/esw/portctrl.h> 24 25 #ifdef BCM_XGS3_SWITCH_SUPPORT 26 27 /* 28 * Function: 29 * soc_xaui_err_sym_detect_set 30 * Description: 31 * Enable/Disable XAUI error symbol monitoring feature. 32 * Parameters: 33 * unit - Device number 34 * port - Port number 35 * enable - TRUE, enable |E| monitoring feature on the port. 36 * FALSE, disable |E| monitoring feature on the port. 37 * Return Value: 38 * SOC_E_NONE 39 * SOC_E_UNAVAIL - Functionality not available 40 */ 41 int 42 soc_xaui_err_sym_detect_set(int unit, soc_port_t port, int enable) 43 { 44 uint8 phy_addr; 45 uint16 octrl, rx_ctrl, rx_ctrl_1g, status; 46 47 if (SOC_USE_PORTCTRL(unit)) { 48 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 49 &phy_addr)); 50 } else { 51 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 52 } 53 /* Map RxAll Block */ 54 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 55 56 /* Read Rx Control 1G Register */ 57 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &rx_ctrl_1g)); 58 octrl = rx_ctrl_1g; 59 if (enable) { 60 /* 61 * Enable cgbad_tst, Emon_en, and cgbad_en 62 */ 63 rx_ctrl_1g |= 0x0680; 64 } else { 65 /* 66 * Disable cgbad_tst and Emon_en 67 */ 68 rx_ctrl_1g &= ~0x0600; 69 } 70 if (octrl != rx_ctrl_1g) { 71 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x19, 72 rx_ctrl_1g)); 73 } 74 75 /* Read Rx Control Register */ 76 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x11, &rx_ctrl)); 77 octrl = rx_ctrl; 78 if (enable) { 79 /* 80 * Enable SigDetected_en, SigDetRestart_en, and 81 * SigDetMonitor_en and map PRBS status register at 0x80F0. 82 */ 83 rx_ctrl |= 0x1c47; 84 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11, rx_ctrl)); 85 86 /* 87 * Clear the |E| count in PRBS status register (Clear-on-read) 88 */ 89 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &status)); 90 91 /* 92 * Restore original status register select mapping. 93 */ 94 rx_ctrl = octrl | 0x1c40; 95 if (rx_ctrl != octrl) { 96 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11, 97 rx_ctrl)); 98 } 99 100 } 101 /* 102 * SigDetected_en, SigDetRestart_en and SigDetMonitor_en are not disabled 103 * when disabling |E| monitoring because they are enabled by default. 104 * Just made sure to enable them when enabling |E| monitoring. 105 */ 106 107 /* Restore the block 0 mapping */ 108 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0)); 109 110 return SOC_E_NONE; 111 } 112 113 /* 114 * Function: 115 * soc_xaui_err_sym_detect_get 116 * Description: 117 * Get the status of XAUI error symbol monitoring feature. 118 * Parameters: 119 * unit - Device number 120 * port - Port number 121 * enable - (OUT) TRUE, port is enabled, FALSE port is disabled. 122 * Return Value: 123 * SOC_E_NONE 124 * SOC_E_UNAVAIL - Functionality not available 125 */ 126 int 127 soc_xaui_err_sym_detect_get(int unit, soc_port_t port, int *enable) 128 { 129 uint8 phy_addr; 130 uint16 rx_ctrl; 131 uint16 rx_ctrl_1g; 132 133 if (SOC_USE_PORTCTRL(unit)) { 134 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 135 &phy_addr)); 136 } else { 137 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 138 } 139 140 /* Map RxAll block */ 141 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 142 143 /* 144 * Read Rx Control register and mask 145 * SigDetected_en, SigDetRestart_en, and SigDetMonitor_en bits. 146 */ 147 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x11, &rx_ctrl)); 148 rx_ctrl &= 0x1c00; 149 150 /* 151 * Read Rx Control 1G register and mask 152 * cgbad_tst, Emon_en, and cgbad_en bits. 153 */ 154 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &rx_ctrl_1g)); 155 rx_ctrl_1g &= 0x0680; 156 157 if (rx_ctrl == 0x1c00 && rx_ctrl_1g == 0x680) { 158 *enable = 1; 159 } else { 160 *enable = 0; 161 } 162 163 /* Restore the block 0 mapping */ 164 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0)); 165 166 return SOC_E_NONE; 167 } 168 169 /* 170 * Function: 171 * soc_xaui_err_sym_count 172 * Description: 173 * Get the number of |E| symbol in XAUI lanes since last read. 174 * Parameters: 175 * unit - Device number 176 * port - Port number 177 * count - (OUT) Number of |E| error since last read. 178 * Return Value: 179 * SOC_E_NONE 180 * SOC_E_UNAVAIL - Functionality not available 181 * SOC_E_CONFIG - Error symbol detect feature is not enabled 182 */ 183 int 184 soc_xaui_err_sym_count(int unit, soc_port_t port, int *count) 185 { 186 uint8 phy_addr; 187 uint16 rx_ctrl, octrl; 188 uint16 rx_ctrl_1g; 189 uint16 rx_status; 190 191 if (SOC_USE_PORTCTRL(unit)) { 192 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 193 &phy_addr)); 194 } else { 195 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 196 } 197 /* 198 * Map Rx All register block 199 */ 200 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 201 202 /* 203 * Read Rx Control 1G and Rx Control register to check whether 204 * |E| monitoring is enabled. 205 */ 206 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &rx_ctrl_1g)); 207 rx_ctrl_1g &= 0x0680; 208 209 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x11, &rx_ctrl)); 210 octrl = rx_ctrl; 211 rx_ctrl &= 0x1c00; 212 213 if (rx_ctrl != 0x1c00 || rx_ctrl_1g != 0x0680) { 214 return SOC_E_CONFIG; 215 } 216 217 /* 218 * If |E| monitor is enabled, map PRPS status register at 0x00F0 219 */ 220 rx_ctrl = octrl | 0x0047; 221 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11, rx_ctrl)); 222 223 /* 224 * Read PRBS status and parse error count field. 225 * If sync_status indicates that symbol is not aligned to proper 226 * symbol boundry, error count is invalid. 227 */ 228 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &rx_status)); 229 if (rx_status & 0x8000) { 230 *count = rx_status & 0x3fff; 231 } else { 232 *count = 0; 233 } 234 235 /* 236 * Restore original status register mapping at 0x00F0 237 */ 238 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x11, octrl)); 239 240 /* 241 * Restore block 0 mapping. 242 */ 243 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0)); 244 245 return SOC_E_NONE; 246 } 247 248 /* 249 * Function: 250 * soc_xaui_txbert_enable 251 * Description: 252 * Enable Tx BERT in XAUI core. 253 * Parameters: 254 * unit - Device number 255 * port - Port number 256 * enable - Enable or disable Tx BERT 257 * Return Value: 258 * SOC_E_NONE 259 * SOC_E_PARAM - port does not have XAUI core. 260 * Note: 261 * This function clears the Tx counters before enabling 262 * Tx BERT. 263 */ 264 int 265 soc_xaui_txbert_enable(int unit, soc_port_t port, int enable) 266 { 267 uint8 phy_addr; 268 uint16 phy_reg; 269 uint16 blk_address; 270 271 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 272 return SOC_E_PARAM; 273 } 274 275 if (SOC_USE_PORTCTRL(unit)) { 276 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 277 &phy_addr)); 278 } else { 279 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 280 } 281 282 /* Save block address to restore at the end */ 283 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 284 285 /* Map Tx BERT Block */ 286 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0020)); 287 288 /* Configure Tx BERT */ 289 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &phy_reg)); 290 if (enable) { 291 /* Clear the Tx BERT counters */ 292 phy_reg |= 1 << 0; 293 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg)); 294 295 /* Run BERT */ 296 phy_reg |= 1 << 15; /* Enable Tx packet generator */ 297 phy_reg &= ~(1 << 0); 298 } else { 299 /* Disable packet generator */ 300 phy_reg &= ~(1 << 15); 301 } 302 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg)); 303 304 /* Restore block mapping */ 305 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 306 307 return SOC_E_NONE; 308 } 309 310 /* 311 * Function: 312 * soc_xaui_txbert_pkt_count_get 313 * Description: 314 * Read total transmitted packet. 315 * Parameters: 316 * unit - Device number 317 * port - Port number 318 * count - Number of packet transmitted 319 * Return Value: 320 * SOC_E_NONE 321 * SOC_E_PARAM - port does not have XAUI core. 322 * Note: 323 * The count is only 32 bit. The counter could overflow. 324 */ 325 int 326 soc_xaui_txbert_pkt_count_get(int unit, soc_port_t port, uint32 *count) 327 { 328 uint8 phy_addr; 329 uint16 pkt_cnt_hi, pkt_cnt_lo; 330 uint16 blk_address; 331 332 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 333 return SOC_E_PARAM; 334 } 335 336 if (SOC_USE_PORTCTRL(unit)) { 337 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 338 &phy_addr)); 339 } else { 340 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 341 } 342 343 /* Save block address to restore at the end */ 344 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 345 346 /* Map Tx BERT Block */ 347 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0020)); 348 349 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &pkt_cnt_lo)); 350 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1a, &pkt_cnt_hi)); 351 352 *count = (pkt_cnt_hi << 16) | pkt_cnt_lo; 353 354 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 355 356 return SOC_E_NONE; 357 } 358 359 /* 360 * Function: 361 * soc_xaui_txbert_byte_count_get 362 * Description: 363 * Read total transmitted byte. 364 * Parameters: 365 * unit - Device number 366 * port - Port number 367 * count - Number of byte transmitted 368 * Return Value: 369 * SOC_E_NONE 370 * SOC_E_PARAM - port does not have XAUI core. 371 * Note: 372 * The count is only 32 bit. The counter could overflow. 373 */ 374 int 375 soc_xaui_txbert_byte_count_get(int unit, soc_port_t port, uint32 *count) 376 { 377 uint8 phy_addr; 378 uint16 byte_cnt_hi, byte_cnt_lo; 379 uint16 blk_address; 380 381 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 382 return SOC_E_PARAM; 383 } 384 385 if (SOC_USE_PORTCTRL(unit)) { 386 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 387 &phy_addr)); 388 } else { 389 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 390 } 391 392 /* Save block address to restore at the end */ 393 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 394 395 /* Map Tx BERT Block */ 396 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0020)); 397 398 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &byte_cnt_lo)); 399 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x18, &byte_cnt_hi)); 400 401 *count = (byte_cnt_hi << 16) | byte_cnt_lo; 402 403 /* Restore original block address */ 404 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 405 406 return SOC_E_NONE; 407 } 408 409 /* 410 * Function: 411 * soc_xaui_rxbert_enable 412 * Description: 413 * Enable Rx BERT in XAUI core. 414 * Parameters: 415 * unit - Device number 416 * port - Port number 417 * enable - Enable or disable Rx BERT 418 * Return Value: 419 * SOC_E_NONE 420 * SOC_E_PARAM - port does not have XAUI core. 421 * Note: 422 * This function clears the Rx counters before enabling 423 * Rx BERT. 424 */ 425 int 426 soc_xaui_rxbert_enable(int unit, soc_port_t port, int enable) 427 { 428 uint8 phy_addr; 429 uint16 phy_reg; 430 uint16 blk_address; 431 432 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 433 return SOC_E_PARAM; 434 } 435 436 if (SOC_USE_PORTCTRL(unit)) { 437 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 438 &phy_addr)); 439 } else { 440 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 441 } 442 443 /* Save block address to restore at the end */ 444 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 445 446 /* Map Block 0 */ 447 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 448 449 if (enable) { 450 /* Turn off check end functions in xgmiiRcontrol */ 451 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg)); 452 phy_reg &= ~(1 << 10); 453 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x17, phy_reg)); 454 455 /* Enable pgen_en in xgxsControl */ 456 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &phy_reg)); 457 phy_reg |= 1 << 15; /* Enable pattern generator */ 458 phy_reg |= 1 << 14; /* Enable pattern comparator */ 459 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg)); 460 461 /* Map Rx BERT Block */ 462 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030)); 463 464 /* Clear the Rx BERT counters */ 465 phy_reg = 1 << 1; /* Clear Rx BERT error counters */ 466 phy_reg |= 1 << 0; /* Clear Rx BERT receive counters */ 467 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg)); 468 469 /* Enable packet monitor */ 470 phy_reg = 1 << 15; /* Enable Rx packet monitor */ 471 phy_reg |= 3 << 4; /* Get the source of Rx BERT from 472 * clock compensation 473 */ 474 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg)); 475 } else { 476 /* Turn on check end function */ 477 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg)); 478 phy_reg |= 1 << 10; 479 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x17, phy_reg)); 480 481 /* Disable pgen_en in xgxsControl */ 482 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x10, &phy_reg)); 483 phy_reg &= ~(1 << 15); /* Disable pattern generator */ 484 phy_reg &= ~(1 << 14); /* Disable pattern comparator */ 485 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg)); 486 487 /* Map Rx BERT Block */ 488 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030)); 489 490 /* Disable packet monitor */ 491 phy_reg &= ~(1 << 15); /* Disable Rx packet monitor */ 492 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x10, phy_reg)); 493 } 494 495 /* Restore original block address */ 496 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 497 498 return SOC_E_NONE; 499 } 500 501 /* 502 * Function: 503 * soc_xaui_rxbert_pkt_count_get 504 * Description: 505 * Read the number of packet received in BERT. 506 * Parameters: 507 * unit - Device number 508 * port - Port number 509 * count - Number of packet received. 510 * Return Value: 511 * SOC_E_NONE 512 * SOC_E_PARAM - port does not have XAUI core. 513 */ 514 int 515 soc_xaui_rxbert_pkt_count_get(int unit, soc_port_t port, 516 uint32 *count, int *prbs_lock) 517 { 518 uint8 phy_addr; 519 uint16 pkt_cnt_hi, pkt_cnt_lo; 520 uint16 blk_address, rx_status; 521 522 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 523 return SOC_E_PARAM; 524 } 525 526 if (SOC_USE_PORTCTRL(unit)) { 527 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 528 &phy_addr)); 529 } else { 530 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 531 } 532 533 /* Save block address to restore at the end */ 534 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 535 536 /* Map Rx BERT Block */ 537 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030)); 538 539 /* Get Rx Packet count */ 540 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x19, &pkt_cnt_lo)); 541 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1a, &pkt_cnt_hi)); 542 *count = (pkt_cnt_hi << 16) | pkt_cnt_lo; 543 544 /* Get PRBS Lock status */ 545 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &rx_status)); 546 *prbs_lock = (rx_status >> 15); 547 548 /* Restore original block address */ 549 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 550 551 return SOC_E_NONE; 552 } 553 554 /* 555 * Function: 556 * soc_xaui_rxbert_byte_count_get 557 * Description: 558 * Read the number of byte received in BERT. 559 * Parameters: 560 * unit - Device number 561 * port - Port number 562 * count - Number of byte received. 563 * Return Value: 564 * SOC_E_NONE 565 * SOC_E_PARAM - port does not have XAUI core. 566 */ 567 int 568 soc_xaui_rxbert_byte_count_get(int unit, soc_port_t port, 569 uint32 *count, int *prbs_lock) 570 { 571 uint8 phy_addr; 572 uint16 byte_cnt_hi, byte_cnt_lo; 573 uint16 blk_address, rx_status; 574 575 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 576 return SOC_E_PARAM; 577 } 578 579 if (SOC_USE_PORTCTRL(unit)) { 580 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 581 &phy_addr)); 582 } else { 583 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 584 } 585 586 /* Save block address to restore at the end */ 587 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 588 589 /* Map Rx BERT Block */ 590 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030)); 591 592 /* Get byte count */ 593 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &byte_cnt_lo)); 594 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x18, &byte_cnt_hi)); 595 *count = (byte_cnt_hi << 16) | byte_cnt_lo; 596 597 /* Get PRBS Lock status */ 598 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &rx_status)); 599 *prbs_lock = (rx_status >> 15); 600 601 /* Restore block address */ 602 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 603 604 return SOC_E_NONE; 605 } 606 607 /* 608 * Function: 609 * soc_xaui_rxbert_bit_err_count_get 610 * Description: 611 * Read the number of bit error received in BERT. 612 * Parameters: 613 * unit - Device number 614 * port - Port number 615 * count - Number of bit error received. 616 * Return Value: 617 * SOC_E_NONE 618 * SOC_E_PARAM - port does not have XAUI core. 619 */ 620 int 621 soc_xaui_rxbert_bit_err_count_get(int unit, soc_port_t port, 622 uint32 *count, int *prbs_lock) 623 { 624 uint8 phy_addr; 625 uint16 phy_reg; 626 uint16 blk_address; 627 628 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 629 return SOC_E_PARAM; 630 } 631 632 if (SOC_USE_PORTCTRL(unit)) { 633 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 634 &phy_addr)); 635 } else { 636 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 637 } 638 639 /* Save block mapping to restore at the end */ 640 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 641 642 /* Map Rx BERT Block */ 643 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030)); 644 645 /* Get bit error count */ 646 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1b, &phy_reg)); 647 *count = phy_reg; 648 649 /* Get PRBS Lock status */ 650 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &phy_reg)); 651 *prbs_lock = (phy_reg >> 15); 652 653 /* Restore original block mapping */ 654 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 655 656 return SOC_E_NONE; 657 } 658 659 /* 660 * Function: 661 * soc_xaui_rxbert_byte_err_count_get 662 * Description: 663 * Read the number of byte error received in BERT. 664 * Parameters: 665 * unit - Device number 666 * port - Port number 667 * count - Number of byte error received. 668 * Return Value: 669 * SOC_E_NONE 670 * SOC_E_PARAM - port does not have XAUI core. 671 */ 672 int 673 soc_xaui_rxbert_byte_err_count_get(int unit, soc_port_t port, 674 uint32 *count, int *prbs_lock) 675 { 676 uint8 phy_addr; 677 uint16 phy_reg; 678 uint16 blk_address; 679 680 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 681 return SOC_E_PARAM; 682 } 683 684 if (SOC_USE_PORTCTRL(unit)) { 685 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 686 &phy_addr)); 687 } else { 688 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 689 } 690 691 /* Save block mappping to restore at the end */ 692 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 693 694 /* Map Rx BERT Block */ 695 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030)); 696 697 /* Read byte error count */ 698 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1c, &phy_reg)); 699 *count = phy_reg; 700 701 /* Get PRBS Lock status */ 702 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &phy_reg)); 703 *prbs_lock = (phy_reg >> 15); 704 705 /* Restore original block mapping */ 706 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 707 708 return SOC_E_NONE; 709 } 710 711 /* 712 * Function: 713 * soc_xaui_rxbert_pkt_err_count_get 714 * Description: 715 * Read the number of packet error received in BERT. 716 * Parameters: 717 * unit - Device number 718 * port - Port number 719 * count - Number of packet error received. 720 * Return Value: 721 * SOC_E_NONE 722 * SOC_E_PARAM - port does not have XAUI core. 723 */ 724 int 725 soc_xaui_rxbert_pkt_err_count_get(int unit, soc_port_t port, 726 uint32 *count, int *prbs_lock) 727 { 728 uint8 phy_addr; 729 uint16 phy_reg; 730 uint16 blk_address; 731 732 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 733 return SOC_E_PARAM; 734 } 735 736 if (SOC_USE_PORTCTRL(unit)) { 737 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 738 &phy_addr)); 739 } else { 740 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 741 } 742 743 /* Save block address to restore at the end */ 744 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 745 746 /* Map Rx BERT Block */ 747 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x0030)); 748 749 /* Get packet error count */ 750 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1d, &phy_reg)); 751 *count = phy_reg; 752 753 /* Get PRBS Lock status */ 754 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1e, &phy_reg)); 755 *prbs_lock = (phy_reg >> 15); 756 757 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 758 759 return SOC_E_NONE; 760 } 761 762 int 763 soc_xaui_config_set(int unit, soc_port_t port, soc_xaui_config_t *config) 764 { 765 uint8 phy_addr; 766 uint16 phy_reg; 767 uint16 blk_address; 768 769 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 770 return SOC_E_PARAM; 771 } 772 773 if (SOC_USE_PORTCTRL(unit)) { 774 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 775 &phy_addr)); 776 } else { 777 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 778 } 779 780 /* Save block address to restore at the end */ 781 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 782 783 /* Map Tx All Block */ 784 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 785 786 /* Read Tx Driver Configuration*/ 787 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg)); 788 789 phy_reg &= ~(0xfff0); 790 phy_reg |= (_shr_bit_rev8(config->preemphasis) >> 4) << 12; 791 phy_reg |= (_shr_bit_rev8(config->idriver) >> 4) << 8; 792 phy_reg |= (_shr_bit_rev8(config->ipredriver) >> 4) << 4; 793 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x17, phy_reg)); 794 795 /* Map Rx All Block */ 796 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 797 798 /* Read Rx Eq Boost */ 799 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1c, &phy_reg)); 800 phy_reg &= ~(0x0007); 801 phy_reg |= config->equalizer_ctrl; 802 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1c, phy_reg)); 803 804 /* Restore block address */ 805 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 806 807 return SOC_E_NONE; 808 } 809 810 int 811 soc_xaui_config_get(int unit, soc_port_t port, soc_xaui_config_t *config) 812 { 813 uint8 phy_addr; 814 uint16 phy_reg; 815 uint16 blk_address; 816 817 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 818 return SOC_E_PARAM; 819 } 820 821 if (SOC_USE_PORTCTRL(unit)) { 822 SOC_IF_ERROR_RETURN(soc_esw_portctrl_port_to_phyaddr(unit, port, 823 &phy_addr)); 824 } else { 825 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 826 } 827 828 /* Save block address to restore at the end */ 829 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1f, &blk_address)); 830 831 /* Map Tx All Block */ 832 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 833 834 /* Read Tx Driver Configuration*/ 835 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x17, &phy_reg)); 836 837 config->preemphasis = (phy_reg & 0xf000) >> 12; 838 config->idriver = (phy_reg & 0x0f00) >> 8; 839 config->ipredriver = (phy_reg & 0x00f0) >> 4; 840 841 /* Map Rx All Block */ 842 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 843 844 /* Read Rx Eq Boost */ 845 SOC_IF_ERROR_RETURN(soc_miim_read(unit, phy_addr, 0x1c, &phy_reg)); 846 config->equalizer_ctrl = (phy_reg & 0x0007); 847 848 /* Restore block address */ 849 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x1f, blk_address)); 850 851 config->preemphasis = (_shr_bit_rev8(config->preemphasis) >> 4); 852 config->idriver = (_shr_bit_rev8(config->idriver) >> 4); 853 config->ipredriver = (_shr_bit_rev8(config->ipredriver) >> 4); 854 855 return SOC_E_NONE; 856 } 857 858 #endif /* BCM_XGS3_SWITCH */