phy54680.c (152199B)
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: phy54680.c 8 * Purpose: PHY driver for BCM54680 9 */ 10 #include <sal/types.h> 11 #include <sal/core/spl.h> 12 #include <shared/bsl.h> 13 #include <soc/drv.h> 14 #include <soc/debug.h> 15 #include <soc/error.h> 16 #include <soc/phyreg.h> 17 18 #include <soc/phy.h> 19 #include <soc/phy/phyctrl.h> 20 #include <soc/phy/drv.h> 21 22 #include "phydefs.h" /* Must include before other phy related includes */ 23 24 #if defined(INCLUDE_PHY_54680) || defined(INCLUDE_PHY_54680E) || defined(INCLUDE_PHY_52681E) 25 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 26 27 #include "phyident.h" 28 #include "phyreg.h" 29 #include "phyfege.h" 30 #include "phynull.h" 31 #include "phy54680.h" 32 33 #define PHY_IS_BCM54680(_pc) (PHY_MODEL_CHECK((_pc), \ 34 PHY_BCM54680_OUI, \ 35 PHY_BCM54680_MODEL)) 36 37 #define PHY_IS_BCM54680_A0(_pc) (PHY_MODEL_CHECK((_pc), \ 38 PHY_BCM54680_OUI, \ 39 PHY_BCM54680_MODEL) \ 40 && ((_pc)->phy_rev == 0x0 )) 41 42 #define PHY_BCM54680_A0_ID0 PHY_ID0(PHY_BCM54680_OUI,PHY_BCM54680_MODEL,0) 43 #define PHY_BCM54680_A0_ID1 PHY_ID1(PHY_BCM54680_OUI,PHY_BCM54680_MODEL,0) 44 45 #define PHY_IS_BCM54880E(_pc) (PHY_MODEL_CHECK((_pc), \ 46 PHY_BCM54880E_OUI, \ 47 PHY_BCM54880E_MODEL)) 48 49 #define PHY_IS_BCM54880E_A0(_pc) (PHY_MODEL_CHECK((_pc), \ 50 PHY_BCM54880E_OUI, \ 51 PHY_BCM54880E_MODEL) \ 52 && ((_pc)->phy_rev == 0x0 )) 53 54 #define PHY_IS_BCM54880E_A1(_pc) (PHY_MODEL_CHECK((_pc), \ 55 PHY_BCM54880E_OUI, \ 56 PHY_BCM54880E_MODEL) \ 57 && ((_pc)->phy_rev == 0x1)) 58 59 #define PHY_IS_BCM54880E_A0A1(_pc) (PHY_MODEL_CHECK((_pc), \ 60 PHY_BCM54880E_OUI, \ 61 PHY_BCM54880E_MODEL) \ 62 && (((_pc)->phy_rev & 0xe) == 0x0)) 63 64 #define PHY_IS_BCM54680E(_pc) (PHY_MODEL_CHECK((_pc), \ 65 PHY_BCM54680E_OUI, \ 66 PHY_BCM54680E_MODEL) \ 67 && (((_pc)->phy_rev & 0x8) == 0x8)) 68 69 #define PHY_IS_BCM54680E_A0(_pc) (PHY_MODEL_CHECK((_pc), \ 70 PHY_BCM54680E_OUI, \ 71 PHY_BCM54680E_MODEL) \ 72 && ((_pc)->phy_rev == 0x8)) 73 74 #define PHY_IS_BCM54680E_A1(_pc) (PHY_MODEL_CHECK((_pc), \ 75 PHY_BCM54680E_OUI, \ 76 PHY_BCM54680E_MODEL) \ 77 && ((_pc)->phy_rev == 0x9)) 78 79 #define PHY_IS_BCM54680E_A0A1(_pc) (PHY_MODEL_CHECK((_pc), \ 80 PHY_BCM54680E_OUI, \ 81 PHY_BCM54680E_MODEL) \ 82 && (((_pc)->phy_rev & 0xe) == 0x8)) 83 84 #define PHY_IS_BCM52681E(_pc) (PHY_MODEL_CHECK((_pc), \ 85 PHY_BCM52681E_OUI, \ 86 PHY_BCM52681E_MODEL) \ 87 && (((_pc)->phy_rev & 0x8) == 0x8)) 88 89 #define SOC_IF_ERROR_BREAK(op, __rv__) \ 90 if (((__rv__) = (op)) < 0) { \ 91 break; \ 92 } 93 94 #ifndef DISABLE_CLK125 95 #define DISABLE_CLK125 0 96 #endif 97 98 #ifndef AUTO_MDIX_WHEN_AN_DIS 99 #define AUTO_MDIX_WHEN_AN_DIS 0 100 #endif 101 102 #define ECD_ENABLE 0 103 104 #define DISABLE_TEST_PORT 1 105 /* #define A0_AUTO_FILL_PORT_INDEX 1 */ 106 107 STATIC int 108 phy_54680_speed_set(int unit, soc_port_t port, int speed); 109 STATIC int 110 phy_54680_duplex_set(int unit, soc_port_t port, int duplex); 111 STATIC int 112 phy_54680_master_set(int unit, soc_port_t port, int master); 113 STATIC int 114 phy_54680_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability); 115 STATIC int 116 phy_54680_autoneg_set(int unit, soc_port_t port, int autoneg); 117 STATIC int 118 phy_54680_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode); 119 STATIC int 120 phy_54680_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability); 121 122 STATIC int 123 phy_54680_control_set(int unit, soc_port_t port, 124 soc_phy_control_t type, uint32 value); 125 126 extern int 127 phy_ecd_cable_diag_init(int unit, soc_port_t port); 128 129 extern int 130 phy_ecd_cable_diag(int unit, soc_port_t port, 131 soc_port_cable_diag_t *status); 132 133 134 135 136 /* 137 * Function: 138 * _phy_54680e_cl45_reg_read 139 * Purpose: 140 * Read Clause 45 Register using Clause 22 register access 141 * Parameters: 142 * unit - StrataSwitch unit #. 143 * pc - Phy control 144 * flags - Flags 145 * dev_addr - Clause 45 Device 146 * reg_addr - Register Address to read 147 * val - Value Read 148 * Returns: 149 * SOC_E_XXX 150 */ 151 152 STATIC int 153 _phy_54680e_cl45_reg_read(int unit, phy_ctrl_t *pc, uint32 flags, 154 uint8 dev_addr, uint16 reg_addr, uint16 *val) 155 { 156 157 /* Write Device Address to register 0x0D (Set Function field to Address)*/ 158 SOC_IF_ERROR_RETURN 159 (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, (dev_addr & 0x001f))); 160 161 /* Select the register by writing to register address to register 0x0E */ 162 SOC_IF_ERROR_RETURN 163 (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0E, reg_addr)); 164 165 /* Write Device Address to register 0x0D (Set Function field to Data)*/ 166 SOC_IF_ERROR_RETURN 167 (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, 168 ((0x4000) | (dev_addr & 0x001f)))); 169 170 /* Read register 0x0E to get the value */ 171 SOC_IF_ERROR_RETURN 172 (PHY54680_REG_READ(unit, pc, flags, 0x00, 0x0E, val)); 173 174 return SOC_E_NONE; 175 } 176 177 /* 178 * Function: 179 * _phy_54680e_cl45_reg_write 180 * Purpose: 181 * Write Clause 45 Register content using Clause 22 register access 182 * Parameters: 183 * unit - StrataSwitch unit #. 184 * pc - Phy control 185 * flags - Flags 186 * dev_addr - Clause 45 Device 187 * reg_addr - Register Address to read 188 * val - Value to be written 189 * Returns: 190 * SOC_E_XXX 191 */ 192 193 STATIC int 194 _phy_54680e_cl45_reg_write(int unit, phy_ctrl_t *pc, uint32 flags, 195 uint8 dev_addr, uint16 reg_addr, uint16 val) 196 { 197 198 /* Write Device Address to register 0x0D (Set Function field to Address)*/ 199 SOC_IF_ERROR_RETURN 200 (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, (dev_addr & 0x001f))); 201 202 /* Select the register by writing to register address to register 0x0E */ 203 SOC_IF_ERROR_RETURN 204 (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0E, reg_addr)); 205 206 /* Write Device Address to register 0x0D (Set Function field to Data)*/ 207 SOC_IF_ERROR_RETURN 208 (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0D, 209 ((0x4000) | (dev_addr & 0x001f)))); 210 211 /* Write register 0x0E to write the value */ 212 SOC_IF_ERROR_RETURN 213 (PHY54680_REG_WRITE(unit, pc, flags, 0x00, 0x0E, val)); 214 215 return SOC_E_NONE; 216 } 217 218 /* 219 * Function: 220 * _phy_54680e_cl45_reg_modify 221 * Purpose: 222 * Modify Clause 45 Register contents using Clause 22 register access 223 * Parameters: 224 * unit - StrataSwitch unit #. 225 * pc - Phy control 226 * flags - Flags 227 * reg_bank - Register bank 228 * dev_addr - Clause 45 Device 229 * reg_addr - Register Address to read 230 * val - Value 231 * mask - Mask for modifying the contents of the register 232 * Returns: 233 * SOC_E_XXX 234 */ 235 236 STATIC int 237 _phy_54680e_cl45_reg_modify(int unit, phy_ctrl_t *pc, uint32 flags, 238 uint8 dev_addr, uint16 reg_addr, uint16 val, 239 uint16 mask) 240 { 241 242 uint16 value = 0; 243 244 SOC_IF_ERROR_RETURN 245 (PHY54680E_CL45_REG_READ(unit, pc, flags, dev_addr, reg_addr, &value)); 246 247 value = (val & mask) | (value & ~mask); 248 249 SOC_IF_ERROR_RETURN 250 (PHY54680E_CL45_REG_WRITE(unit, pc, flags, dev_addr, reg_addr, value)); 251 252 return SOC_E_NONE; 253 } 254 255 /* 256 * Function: 257 * _phy_54680e_blk_top_lvl_reg_read 258 * Purpose: 259 * New mechanism to Read Top Level Registers for EEE and 1588. 260 * Parameters: 261 * unit - StrataSwitch unit #. 262 * pc - Phy control 263 * flags - Flags 264 * reg_offset - Register Address to read 265 * val - Value Read 266 * Returns: 267 * SOC_E_XXX 268 */ 269 270 STATIC int 271 _phy_54680e_blk_top_lvl_reg_read(int unit, phy_ctrl_t *pc, uint32 flags, 272 uint16 reg_offset, uint16 *val) 273 { 274 275 /* Write register 0x17 with the top level reg offset to read (handled in PHY54680_REG_READ) */ 276 /* Read register 0x15 to get the value */ 277 SOC_IF_ERROR_RETURN 278 (PHY54680_REG_READ(unit, pc, flags, (0x0D00|(reg_offset & 0xff)), 0x15, val)); 279 280 return SOC_E_NONE; 281 } 282 283 /* 284 * Function: 285 * _phy_54680e_blk_top_lvl_reg_write 286 * Purpose: 287 * New mechanism to Write Top Level Registers for EEE and 1588 288 * Parameters: 289 * unit - StrataSwitch unit #. 290 * pc - Phy control 291 * flags - Flags 292 * reg_offset - Register Address to read 293 * val - Value to be written 294 * Returns: 295 * SOC_E_XXX 296 */ 297 298 STATIC int 299 _phy_54680e_blk_top_lvl_reg_write(int unit, phy_ctrl_t *pc, uint32 flags, 300 uint16 reg_offset, uint16 val) 301 { 302 303 /* Write register 0x17 with the top level reg offset to write (handled in PHY54680_REG_WRITE) */ 304 /* Write register 0x15 the value to write to the top level register offset */ 305 SOC_IF_ERROR_RETURN 306 (PHY54680_REG_WRITE(unit, pc, flags, (0x0D00|(reg_offset & 0xff)), 0x15, val)); 307 308 return SOC_E_NONE; 309 } 310 311 /* 312 * Function: 313 * _phy_54680e_blk_top_lvl_reg_modify 314 * Purpose: 315 * Modify Clause 45 Register contents using Clause 22 register access 316 * Parameters: 317 * unit - StrataSwitch unit #. 318 * pc - Phy control 319 * flags - Flags 320 * reg_bank - Register bank 321 * dev_addr - Clause 45 Device 322 * reg_addr - Register Address to read 323 * val - Value 324 * mask - Mask for modifying the contents of the register 325 * Returns: 326 * SOC_E_XXX 327 */ 328 329 STATIC int 330 _phy_54680e_blk_top_lvl_reg_modify(int unit, phy_ctrl_t *pc, uint32 flags, 331 uint16 reg_offset, uint16 val, uint16 mask) 332 { 333 334 uint16 value = 0; 335 336 /* Write register 0x17 with the top level reg offset to read */ 337 SOC_IF_ERROR_RETURN 338 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, flags, 339 reg_offset, &value)); 340 value = (val & mask) | (value & ~mask); 341 342 /* Write register 0x17 with the top level reg offset to read */ 343 SOC_IF_ERROR_RETURN 344 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, flags, 345 reg_offset, value)); 346 347 return SOC_E_NONE; 348 } 349 350 /* 351 * Function: 352 * phy_54680_toplvl_reg_read 353 * Purpose: 354 * Read a top level register from a supporting chip 355 * Parameters: 356 * unit - SOC Unit #. 357 * port - Port number. 358 * flags - 359 * reg_offset - Offset to the reg 360 * data - Pointer to data returned 361 * Returns: 362 * SOC_E_XXX 363 */ 364 int 365 phy_54680_toplvl_reg_read(int unit, soc_port_t port, int flags, uint8 reg_offset, uint16 *data) 366 { 367 phy_ctrl_t *pc; 368 uint16 reg_data, status; 369 int rv = SOC_E_NONE; 370 371 LOG_VERBOSE(BSL_LS_SOC_PHY, 372 (BSL_META_U(unit, 373 "entered phy_54680_toplvl_reg_read: " 374 "unit %d, port %d, flags %x reg_offset %u\n"), 375 unit, port, flags, reg_offset)); 376 377 pc = EXT_PHY_SW_STATE(unit, port); 378 379 /* Write Reg address to Port 5's (offset=4) register 0x1C, shadow 0x0B */ 380 /* Status READ from Port 3's (offset=2) register 0x15 */ 381 382 /* Write Reg offset to Port 5's register 0x1C, shadow 0x0B */ 383 reg_data = (0xAC00 | reg_offset); 384 INT_MCU_LOCK(unit); 385 pc->phy_id = PHY54680_SLICE_ADDR(pc, 4); 386 rv = pc->write(unit, pc->phy_id, 0x1c, reg_data); 387 if (SOC_FAILURE(rv)) { 388 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 389 INT_MCU_UNLOCK(unit); 390 return rv; 391 } 392 393 pc->phy_id = PHY54680_SLICE_ADDR(pc, 2); 394 /* Read data from Top level MII Status register(0x15h) */ 395 rv = pc->write(unit, pc->phy_id, 0x17, 0x8F0B); 396 if (SOC_FAILURE(rv)) { 397 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 398 INT_MCU_UNLOCK(unit); 399 return rv; 400 } 401 rv = pc->read(unit, pc->phy_id, 0x15, &status); 402 INT_MCU_UNLOCK(unit); 403 if (SOC_FAILURE(rv)) { 404 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 405 return rv; 406 } 407 408 *data = (status & 0xff); 409 410 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 411 412 return SOC_E_NONE; 413 } 414 415 /* 416 * Function: 417 * phy_54680_toplvl_reg_write 418 * Purpose: 419 * Write to a top level register from a supporting chip 420 * Parameters: 421 * unit - SOC Unit #. 422 * port - Port number. 423 * flags - 424 * reg_offset - Offset to the reg 425 * data - Data to be written 426 * Returns: 427 * SOC_E_XXX 428 */ 429 int 430 phy_54680_toplvl_reg_write(int unit, soc_port_t port, int flags, uint8 reg_offset, uint16 data) 431 { 432 phy_ctrl_t *pc; 433 uint16 reg_data; 434 #ifdef BROADCOM_DEBUG 435 uint16 status; 436 #endif 437 int rv = SOC_E_NONE; 438 439 LOG_VERBOSE(BSL_LS_SOC_PHY, 440 (BSL_META_U(unit, 441 "entered phy_54680_toplvl_reg_write: " 442 "unit %d, port %d, flags %x reg_offset %u, data %u\n"), 443 unit, port, flags, reg_offset, data)); 444 445 pc = EXT_PHY_SW_STATE(unit, port); 446 447 /* Write Reg address to Port 5's register 0x1C, shadow 0x0B */ 448 /* Write data to Port 6's register 0x1C, shadow 0x0c */ 449 /* Status READ from Port 3's register 0x15 */ 450 451 /* Write Data to port6 (offset = 5), register 0x1C, shadow 0x0c */ 452 INT_MCU_LOCK(unit); 453 pc->phy_id = PHY54680_SLICE_ADDR(pc, 5); 454 reg_data = (0xB000 | (data & 0xff)); 455 rv = pc->write(unit, pc->phy_id, 0x1c, reg_data); 456 if (SOC_FAILURE(rv)) { 457 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 458 INT_MCU_UNLOCK(unit); 459 return rv; 460 } 461 462 pc->phy_id = PHY54680_SLICE_ADDR(pc, 4); 463 /* Write Reg address to Port 5's (offset = 4) register 0x1C, shadow 0x0B */ 464 /* Enable Write ( Port 5's register 0x1C, shadow 0x0B) Bit 7 = 1 */ 465 reg_data = (0xAC80 | reg_offset); 466 rv = pc->write(unit, pc->phy_id, 0x1c, reg_data); 467 if (SOC_FAILURE(rv)) { 468 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 469 INT_MCU_UNLOCK(unit); 470 return rv; 471 } 472 473 /* Disable Write ( Port 5's register 0x1C, shadow 0x0B) Bit 7 = 0 */ 474 reg_data = (0xAC00 | reg_offset); 475 rv = pc->write(unit, pc->phy_id, 0x1c, reg_data); 476 if (SOC_FAILURE(rv)) { 477 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 478 INT_MCU_UNLOCK(unit); 479 return rv; 480 } 481 482 #ifdef BROADCOM_DEBUG 483 pc->phy_id = PHY54680_SLICE_ADDR(pc, 2); 484 /* Read data from Top level MII Status register(0x15h) */ 485 rv = pc->write(unit, pc->phy_id, 0x17, 0x8F0B); 486 if (SOC_FAILURE(rv)) { 487 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 488 INT_MCU_UNLOCK(unit); 489 return rv; 490 } 491 rv = pc->read(unit, pc->phy_id, 0x15, &status); 492 493 if (SOC_FAILURE(rv)) { 494 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 495 return rv; 496 } 497 #endif 498 499 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 500 INT_MCU_UNLOCK(unit); 501 502 return SOC_E_NONE; 503 } 504 505 /* 506 * Function: 507 * phy_54680_medium_status 508 * Purpose: 509 * Indicate the current active medium 510 * Parameters: 511 * unit - StrataSwitch unit #. 512 * port - StrataSwitch port #. 513 * medium - (OUT) One of: 514 * SOC_PORT_MEDIUM_COPPER 515 * SOC_PORT_MEDIUM_FIBER 516 * Returns: 517 * SOC_E_NONE. 518 */ 519 STATIC int 520 phy_54680_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 521 { 522 523 *medium = SOC_PORT_MEDIUM_COPPER; 524 525 return SOC_E_NONE; 526 527 } 528 529 /* 530 * Function: 531 * phy_54680_medium_config_set 532 * Purpose: 533 * Set the operating parameters that are automatically selected 534 * when medium switches type. 535 * Parameters: 536 * unit - StrataSwitch unit # 537 * port - Port number 538 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 539 * cfg - Operating parameters 540 * Returns: 541 * SOC_E_XXX 542 */ 543 STATIC int 544 phy_54680_medium_config_set(int unit, soc_port_t port, 545 soc_port_medium_t medium, 546 soc_phy_config_t *cfg) 547 { 548 COMPILER_REFERENCE(medium); 549 550 SOC_IF_ERROR_RETURN 551 (phy_54680_speed_set(unit, port, cfg->force_speed)); 552 SOC_IF_ERROR_RETURN 553 (phy_54680_duplex_set(unit, port, cfg->force_duplex)); 554 SOC_IF_ERROR_RETURN 555 (phy_54680_master_set(unit, port, cfg->master)); 556 SOC_IF_ERROR_RETURN 557 (phy_54680_ability_advert_set(unit, port, &cfg->advert_ability)); 558 SOC_IF_ERROR_RETURN 559 (phy_54680_autoneg_set(unit, port, cfg->autoneg_enable)); 560 SOC_IF_ERROR_RETURN 561 (phy_54680_mdix_set(unit, port, cfg->mdix)); 562 563 return SOC_E_NONE; 564 } 565 566 /* 567 * Function: 568 * phy_54680_medium_config_get 569 * Purpose: 570 * Get the operating parameters that are automatically selected 571 * when medium switches type. 572 * Parameters: 573 * unit - StrataSwitch unit # 574 * port - Port number 575 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 576 * cfg - (OUT) Operating parameters 577 * Returns: 578 * SOC_E_XXX 579 */ 580 581 STATIC int 582 phy_54680_medium_config_get(int unit, soc_port_t port, 583 soc_port_medium_t medium, 584 soc_phy_config_t *cfg) 585 { 586 phy_ctrl_t *pc; 587 588 COMPILER_REFERENCE(medium); 589 590 pc = EXT_PHY_SW_STATE(unit, port); 591 592 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 593 594 return SOC_E_NONE; 595 } 596 597 598 599 600 601 STATIC int 602 _phy_54680_mdi_pair_set(int unit, soc_port_t port, uint32 mdi_pair_map) 603 { 604 phy_ctrl_t *pc; 605 uint16 reg_val; 606 pc = EXT_PHY_SW_STATE(unit, port); 607 608 if (mdi_pair_map) { 609 /* 610 * lane 0 (bit0~1), lane 1 (bit2~3), lane 2 (bit4~5), lane 3 (bit6~7) 611 * Enable swap (bit 8) 612 */ 613 reg_val = ((mdi_pair_map & (0x3<<12)) >> 6) | 614 ((mdi_pair_map & (0x3<<8)) >> 4) | 615 ((mdi_pair_map & (0x3<<4)) >> 2) | 616 (mdi_pair_map & 0x3); 617 reg_val |= 0x100; /* Enable */ 618 SOC_IF_ERROR_RETURN( 619 WRITE_PHY_REG(unit, pc, 0x17, 0x0f09)); 620 SOC_IF_ERROR_RETURN( 621 WRITE_PHY_REG(unit, pc, 0x15, reg_val)); 622 } 623 624 LOG_INFO(BSL_LS_SOC_PORT, 625 (BSL_META_U(unit, 626 "_phy_54680_mdi_pair_set port %d\n"), port)); 627 628 return SOC_E_NONE; 629 } 630 631 632 /* 633 * Function: 634 * _phy_54680_reset_setup 635 * Purpose: 636 * Function to reset the PHY and set up initial operating registers. 637 * Parameters: 638 * unit - StrataSwitch unit #. 639 * port - StrataSwitch port #. 640 * Returns: 641 * SOC_E_XXX 642 */ 643 644 STATIC int 645 _phy_54680_reset_setup(int unit, soc_port_t port) 646 { 647 phy_ctrl_t *pc; 648 uint16 tmp; 649 uint16 phy_addr; 650 soc_port_t primary_port; 651 uint16 id0, id1; 652 int index; 653 uint32 phy_mdi_pair_map; 654 655 pc = EXT_PHY_SW_STATE(unit, port); 656 657 if (PHY_IS_BCM52681E(pc)) { 658 SOC_IF_ERROR_RETURN(phy_fe_init(unit, port)); 659 660 SOC_IF_ERROR_RETURN 661 (MODIFY_PHY54680_MII_GB_CTRLr(unit, pc, 0, MII_GB_CTRL_ADV_1000HD | MII_GB_CTRL_ADV_1000FD)); 662 } else { 663 SOC_IF_ERROR_RETURN(phy_ge_init(unit, port)); 664 } 665 666 if ( soc_phy_primary_and_offset_get(unit, port, &primary_port, &index) 667 == SOC_E_NONE ) { 668 /* determine the order of logical ports on a PHY chip */ 669 if ( index & 0x80 ) { 670 PHY54680_FLAGS(pc) |= ( PHY54680_PHYA_REV); /* reverse order */ 671 } else { 672 PHY54680_FLAGS(pc) &= (~PHY54680_PHYA_REV); /* normal order */ 673 } 674 } else { 675 /* config variable 'phy_port_primary_and_offset' not specified *\ 676 |* Assign default values in a 4-alignment basis : *| 677 |* e.g. port = 2 3 4 5 6 7 8 9 *| 678 |* index = 0 1 2 3 0 1 2 3 *| 679 \* primary_port = 2 2 2 2 6 6 6 6 */ 680 index = pc->phy_id & ( PHY54680_DEV_PHY_SLICE_MASK); 681 primary_port = ((port - index) <= 0) ? 0 : (port - index); 682 PHY54680_FLAGS(pc) &= (~PHY54680_PHYA_REV); /* normal order */ 683 LOG_WARN(BSL_LS_SOC_PHY, 684 (BSL_META_U(unit, 685 "Config property 'phy_port_primary_and_offset' " 686 "not set for unit %d, port %d. " 687 "Default to slice=0x%x, base=0x%x\n"), 688 unit, port, index, primary_port)); 689 } 690 691 /* keep the original MDIO address. Set slice ID & base PHY address */ 692 /* Do not change the order to the following four lines */ 693 index &= ~0x80; /* clear reverse bit (PHYA_REV) */ 694 PHY54680_DEV_PHY_ID_ORIG(pc) = pc->phy_id; 695 PHY54680_DEV_PHY_SLICE(pc) = index; 696 PHY54680_DEV_SET_BASE_ADDR(pc); /* phy address of port 0 of this chip */ 697 698 SOC_IF_ERROR_RETURN 699 (phy_54680_control_set( unit, port, SOC_PHY_CONTROL_PORT_PRIMARY, 700 primary_port)); 701 SOC_IF_ERROR_RETURN 702 (phy_54680_control_set( unit, port, SOC_PHY_CONTROL_PORT_OFFSET, 703 index )); 704 705 #ifdef DISABLE_TEST_PORT 706 if (PHY_IS_BCM54680_A0(pc)) { 707 /* Disable test port */ 708 709 phy_addr = pc->phy_id + 1; 710 711 SOC_IF_ERROR_RETURN 712 (pc->read(unit, phy_addr, MII_PHY_ID0_REG, &id0)); 713 714 SOC_IF_ERROR_RETURN 715 (pc->read(unit, phy_addr, MII_PHY_ID1_REG, &id1)); 716 717 if ( ( id0 != PHY_BCM54680_A0_ID0 ) || ( id1 != PHY_BCM54680_A0_ID1 ) ) { 718 719 720 SOC_IF_ERROR_RETURN 721 (pc->write(unit, phy_addr, 0x1f, 0xffd0)); 722 723 SOC_IF_ERROR_RETURN 724 (pc->write(unit, phy_addr, 0x1e, 0x001f)); 725 726 SOC_IF_ERROR_RETURN 727 (pc->write(unit, phy_addr, 0x1f, 0x8000)); 728 729 SOC_IF_ERROR_RETURN 730 (pc->write(unit, phy_addr, 0x1d, 0x4002)); 731 732 SOC_IF_ERROR_RETURN 733 (pc->write(unit, phy_addr, 0x00, MII_CTRL_RESET)); 734 735 #ifdef A0_AUTO_FILL_PORT_INDEX 736 { 737 int i; 738 739 for (i = 0; i < 8; i++) { 740 SOC_IF_ERROR_RETURN 741 (phy_54680_control_set( unit, port - i, SOC_PHY_CONTROL_PORT_PRIMARY, port - 7 )); 742 SOC_IF_ERROR_RETURN 743 (phy_54680_control_set( unit, port - i, SOC_PHY_CONTROL_PORT_OFFSET, 7 - i )); 744 } 745 } 746 #endif 747 } 748 } 749 #endif 750 /* Disable super-isolate */ 751 SOC_IF_ERROR_RETURN 752 (MODIFY_PHY54680_MII_POWER_CTRLr(unit, pc, 0x0, 1U<<5)); 753 754 /* remove power down */ 755 if (pc->copper.enable) { 756 tmp = PHY_DISABLED_MODE(unit, port) ? MII_CTRL_PD : 0; 757 } else { 758 tmp = MII_CTRL_PD; 759 } 760 SOC_IF_ERROR_RETURN 761 (MODIFY_PHY54680_MII_CTRLr(unit, pc, tmp, MII_CTRL_PD)); 762 763 if (PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc)) { 764 SOC_IF_ERROR_RETURN 765 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x4f, (1U << 12), (1U << 12))); 766 767 SOC_IF_ERROR_RETURN 768 (MODIFY_PHY54680_MODE_CTRLr(unit, pc, 0x00, 0x06)); 769 770 SOC_IF_ERROR_RETURN 771 (MODIFY_PHY54680_SGMII_SLAVEr(unit, pc, 0x02, 0x02)); 772 773 SOC_IF_ERROR_RETURN 774 (MODIFY_PHY54680_EXT_SERDES_CTRLr(unit, pc, 0x00, 0x01)); 775 776 if (!PHY_IS_BCM52681E(pc)) { 777 SOC_IF_ERROR_RETURN 778 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0F7F,0x15, 0x7, 0x7)); /* exp 7f */ 779 } 780 781 } 782 783 #if DISABLE_CLK125 784 /* Reduce EMI emissions by disabling the CLK125 pin if not used */ 785 SOC_IF_ERROR_RETURN 786 (MODIFY_PHY54680_SPARE_CTRL_3r(unit, pc, 0, 1)); 787 #endif 788 789 /* Get Requested LED selectors (defaults are hardware defaults) */ 790 pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 791 pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1); 792 pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3); 793 pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6); 794 pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8); 795 pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0); 796 797 /* Configure Extended Control Register */ 798 /* Enable LEDs to indicate traffic status */ 799 SOC_IF_ERROR_RETURN 800 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0x0020, 0x0020)); 801 802 #if AUTO_MDIX_WHEN_AN_DIS 803 /* Enable Auto-MDIX When autoneg disabled */ 804 SOC_IF_ERROR_RETURN 805 (MODIFY_PHY54680_MII_MISC_CTRLr(unit, pc, 0x0200, 0x0200)); 806 #endif 807 808 /* Enable extended packet length (4.5k through 25k) */ 809 SOC_IF_ERROR_RETURN 810 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x4000, 0x4000)); 811 812 SOC_IF_ERROR_RETURN 813 (MODIFY_PHY54680_MISC_1000X_CTRL2r(unit, pc, 0x0001, 0x0001)); 814 815 SOC_IF_ERROR_RETURN 816 (MODIFY_PHY54680_AUX_CTRLr(unit, pc, 0x0002, 0x0002)); 817 818 /* Configure LED selectors */ 819 tmp = ((pc->ledmode[1] & 0xf) << 4) | (pc->ledmode[0] & 0xf); 820 SOC_IF_ERROR_RETURN 821 (WRITE_PHY54680_LED_SELECTOR_1r(unit, pc, tmp)); 822 823 tmp = ((pc->ledmode[3] & 0xf) << 4) | (pc->ledmode[2] & 0xf); 824 SOC_IF_ERROR_RETURN 825 (WRITE_PHY54680_LED_SELECTOR_2r(unit, pc, tmp)); 826 827 tmp = (pc->ledctrl & 0x3ff); 828 SOC_IF_ERROR_RETURN 829 (WRITE_PHY54680_LED_CTRLr(unit, pc, tmp)); 830 831 SOC_IF_ERROR_RETURN 832 (WRITE_PHY54680_EXP_LED_SELECTORr(unit, pc, pc->ledselect)); 833 834 /* 835 * Configure Auxiliary control register to turn off 836 * carrier extension. The Intel 7131 NIC does not accept carrier 837 * extension and gets CRC errors. 838 */ 839 /* Disable carrier extension */ 840 SOC_IF_ERROR_RETURN 841 (MODIFY_PHY54680_AUX_CTRLr(unit, pc, 0x0040, 0x0040)); 842 843 /* BCM54880E is EEE capable */ 844 if (PHY_IS_BCM54680E(pc) || PHY_IS_BCM54880E(pc)) { 845 if (pc->phy_rev == 0x1) { /* rev A1 */ 846 SOC_IF_ERROR_RETURN 847 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00)); 848 SOC_IF_ERROR_RETURN( 849 WRITE_PHY_REG(unit, pc, 0x17, 0x0ffe)); 850 SOC_IF_ERROR_RETURN( 851 WRITE_PHY_REG(unit, pc, 0x15, 0x0100)); 852 SOC_IF_ERROR_RETURN( 853 WRITE_PHY_REG(unit, pc, 0x17, 0x2022)); 854 SOC_IF_ERROR_RETURN( 855 WRITE_PHY_REG(unit, pc, 0x15, 0x01f0)); 856 SOC_IF_ERROR_RETURN( 857 WRITE_PHY_REG(unit, pc, 0x17, 0x4021)); 858 SOC_IF_ERROR_RETURN( 859 WRITE_PHY_REG(unit, pc, 0x15, 0x0887)); 860 SOC_IF_ERROR_RETURN( 861 WRITE_PHY_REG(unit, pc, 0x17, 0x2021)); 862 SOC_IF_ERROR_RETURN( 863 WRITE_PHY_REG(unit, pc, 0x15, 0x8983)); 864 SOC_IF_ERROR_RETURN 865 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00)); 866 } 867 SOC_IF_ERROR_RETURN 868 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7, 869 0x0000, 0x0003)); 870 PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE); 871 } 872 873 /* BCM52681E is EEE capable */ 874 if (PHY_IS_BCM52681E(pc)) { 875 SOC_IF_ERROR_RETURN 876 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7, 877 0x0000, 0x0003)); 878 SOC_IF_ERROR_RETURN 879 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0F7F,0x15, 0x0, 0x7)); /* exp 7f */ 880 PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE); 881 } 882 883 if (PHY_IS_BCM54680(pc)) { 884 SOC_IF_ERROR_RETURN 885 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00)); 886 SOC_IF_ERROR_RETURN( 887 WRITE_PHY_REG(unit, pc, 0x17, 0x000e)); 888 SOC_IF_ERROR_RETURN( 889 WRITE_PHY_REG(unit, pc, 0x15, 0x0752)); 890 SOC_IF_ERROR_RETURN( 891 WRITE_PHY_REG(unit, pc, 0x17, 0x000f)); 892 SOC_IF_ERROR_RETURN( 893 WRITE_PHY_REG(unit, pc, 0x15, 0xe04e)); 894 SOC_IF_ERROR_RETURN 895 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00)); 896 } 897 898 #if defined(BCM_53314) 899 if (PHY_IS_BCM53324(pc)) { 900 /* BCM53324 internal GPHY is EEE capable */ 901 PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE); 902 } 903 #endif /* BCM_53314 */ 904 905 906 907 908 /* Check config for MDI PAIR */ 909 phy_mdi_pair_map = soc_property_port_get(unit, port, 910 spn_PHY_MDI_PAIR_MAP, 0); 911 if (phy_mdi_pair_map) { 912 SOC_IF_ERROR_RETURN( 913 _phy_54680_mdi_pair_set(unit, port, phy_mdi_pair_map)); 914 } 915 916 if (ECD_ENABLE && ((((PHY_IS_BCM54880E(pc)) || (PHY_IS_BCM54680E(pc))) && ((pc->phy_rev & 0x7) > 0x2)) || 917 ((PHY_IS_BCM54680(pc)) && ((pc->phy_rev & 0xf) > 0x1)))) { 918 SOC_IF_ERROR_RETURN( 919 phy_ecd_cable_diag_init(unit, port)); 920 } 921 922 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 923 return SOC_E_NONE; 924 } 925 926 /* 100BASE-TX initialization change for EEE and autogreen mode */ 927 SOC_IF_ERROR_RETURN 928 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00)); 929 SOC_IF_ERROR_RETURN( 930 WRITE_PHY_REG(unit, pc, 0x17, 0x4022)); 931 SOC_IF_ERROR_RETURN( 932 WRITE_PHY_REG(unit, pc, 0x15, 0x017b)); 933 SOC_IF_ERROR_RETURN 934 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00)); 935 936 return SOC_E_NONE; 937 } 938 939 940 /* 941 * Function: 942 * phy_54680_init 943 * Purpose: 944 * Init function for 54680 PHY. 945 * Parameters: 946 * unit - StrataSwitch unit #. 947 * port - StrataSwitch port #. 948 * Returns: 949 * SOC_E_XXX 950 */ 951 STATIC int 952 phy_54680_init(int unit, soc_port_t port) 953 { 954 phy_ctrl_t *pc; 955 956 pc = EXT_PHY_SW_STATE(unit, port); 957 958 pc->automedium = FALSE; 959 pc->fiber_detect = FALSE; 960 pc->fiber.enable = FALSE; 961 962 pc->copper.enable = TRUE; 963 pc->copper.preferred = TRUE; 964 pc->copper.autoneg_enable = TRUE; 965 if (PHY_IS_BCM52681E(pc)) { 966 pc->copper.force_speed = 100; 967 } else { 968 pc->copper.force_speed = 1000; 969 } 970 pc->copper.force_duplex = TRUE; 971 pc->copper.master = SOC_PORT_MS_AUTO; 972 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 973 974 975 /* Initially configure for the preferred medium. */ 976 977 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 978 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 979 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 980 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 981 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE); 982 983 SOC_IF_ERROR_RETURN 984 (_phy_54680_reset_setup(unit, port)); 985 986 /* Advertise all possible by default */ 987 SOC_IF_ERROR_RETURN 988 (phy_54680_ability_local_get(unit, port, &pc->copper.advert_ability)); 989 990 SOC_IF_ERROR_RETURN 991 (phy_54680_medium_config_set(unit, port, 0, &pc->copper)); 992 993 return SOC_E_NONE; 994 995 } 996 997 /* 998 * Function: 999 * phy_54680_enable_set 1000 * Purpose: 1001 * Enable or disable the physical interface. 1002 * Parameters: 1003 * unit - StrataSwitch unit #. 1004 * port - StrataSwitch port #. 1005 * enable - Boolean, true = enable PHY, false = disable. 1006 * Returns: 1007 * SOC_E_XXX 1008 */ 1009 1010 STATIC int 1011 phy_54680_enable_set(int unit, soc_port_t port, int enable) 1012 { 1013 phy_ctrl_t *pc; 1014 soc_timeout_t to; 1015 uint16 power_down, mii_stat; 1016 1017 pc = EXT_PHY_SW_STATE(unit, port); 1018 1019 power_down = (enable) ? 0 : MII_CTRL_PD; 1020 1021 SOC_IF_ERROR_RETURN 1022 (MODIFY_PHY54680_MII_CTRLr(unit, pc, power_down, MII_CTRL_PD)); 1023 1024 if (!enable) { 1025 if ((PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) && 1026 (((pc->phy_rev & 0x4) == 0x0) || /* A0,A1,B0,B1 */ 1027 (PHY_IS_BCM53324(pc) && pc->phy_rev == 0x0))) { 1028 soc_timeout_init(&to, 2000000, 0); 1029 do { 1030 SOC_IF_ERROR_RETURN 1031 (READ_PHY54680_MII_STATr(unit, pc, &mii_stat)); 1032 1033 if (soc_timeout_check(&to)) { 1034 LOG_WARN(BSL_LS_SOC_PHY, 1035 (BSL_META_U(unit, 1036 "phy54680.c: link didn't go down after power down: u=%d p=%d\n"), 1037 unit, port)); 1038 break; 1039 } 1040 } while(mii_stat & MII_STAT_LA); 1041 } 1042 } 1043 1044 SOC_IF_ERROR_RETURN 1045 (phy_fe_ge_enable_set(unit, port, enable)); 1046 1047 return SOC_E_NONE; 1048 1049 } 1050 1051 /* 1052 * Function: 1053 * phy_54680_enable_get 1054 * Purpose: 1055 * Enable or disable the physical interface for a 54680 device. 1056 * Parameters: 1057 * unit - StrataSwitch unit #. 1058 * port - StrataSwitch port #. 1059 * enable - (OUT) Boolean, true = enable PHY, false = disable. 1060 * Returns: 1061 * SOC_E_XXX 1062 */ 1063 1064 STATIC int 1065 phy_54680_enable_get(int unit, soc_port_t port, int *enable) 1066 { 1067 SOC_IF_ERROR_RETURN 1068 (phy_fe_ge_enable_get(unit, port, enable)); 1069 1070 return SOC_E_NONE; 1071 } 1072 1073 1074 /* 1075 * Function: 1076 * phy_54680_link_get 1077 * Purpose: 1078 * Determine the current link up/down status for a 54680 device. 1079 * Parameters: 1080 * unit - StrataSwitch unit #. 1081 * port - StrataSwitch port #. 1082 * link - (OUT) Boolean, true indicates link established. 1083 * Returns: 1084 * SOC_E_XXX 1085 * Notes: 1086 * If using automedium, also switches the mode. 1087 */ 1088 1089 STATIC int 1090 phy_54680_link_get(int unit, soc_port_t port, int *link) 1091 { 1092 1093 SOC_IF_ERROR_RETURN 1094 (phy_fe_ge_link_get(unit, port, link)); 1095 1096 return SOC_E_NONE; 1097 } 1098 1099 /* 1100 * Function: 1101 * phy_54680_duplex_set 1102 * Purpose: 1103 * Set the current duplex mode (forced). 1104 * Parameters: 1105 * unit - StrataSwitch unit #. 1106 * port - StrataSwitch port #. 1107 * duplex - Boolean, true indicates full duplex, false indicates half. 1108 * Returns: 1109 * SOC_E_XXX 1110 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 1111 * Notes: 1112 * The duplex is set only for the ACTIVE medium. 1113 * No synchronization performed at this level. 1114 * Autonegotiation is not manipulated. 1115 */ 1116 1117 STATIC int 1118 phy_54680_duplex_set(int unit, soc_port_t port, int duplex) 1119 { 1120 phy_ctrl_t *pc; 1121 1122 pc = EXT_PHY_SW_STATE(unit, port); 1123 1124 SOC_IF_ERROR_RETURN 1125 (phy_fe_ge_duplex_set(unit, port, duplex)); 1126 1127 pc->copper.force_duplex = duplex; 1128 1129 return SOC_E_NONE; 1130 } 1131 1132 /* 1133 * Function: 1134 * phy_54680_duplex_get 1135 * Purpose: 1136 * Get the current operating duplex mode. If autoneg is enabled, 1137 * then operating mode is returned, otherwise forced mode is returned. 1138 * Parameters: 1139 * unit - StrataSwitch unit #. 1140 * port - StrataSwitch port #. 1141 * duplex - (OUT) Boolean, true indicates full duplex, false 1142 * indicates half. 1143 * Returns: 1144 * SOC_E_XXX 1145 * Notes: 1146 * The duplex is retrieved for the ACTIVE medium. 1147 * No synchronization performed at this level. Autonegotiation is 1148 * not manipulated. 1149 */ 1150 1151 STATIC int 1152 phy_54680_duplex_get(int unit, soc_port_t port, int *duplex) 1153 { 1154 SOC_IF_ERROR_RETURN 1155 (phy_fe_ge_duplex_get(unit, port, duplex)); 1156 1157 return SOC_E_NONE; 1158 } 1159 1160 /* 1161 * Function: 1162 * phy_54680_speed_set 1163 * Purpose: 1164 * Set the current operating speed (forced). 1165 * Parameters: 1166 * unit - StrataSwitch unit #. 1167 * port - StrataSwitch port #. 1168 * speed - Requested speed. 1169 * Returns: 1170 * SOC_E_XXX 1171 * Notes: 1172 * The speed is set only for the ACTIVE medium. 1173 */ 1174 1175 STATIC int 1176 phy_54680_speed_set(int unit, soc_port_t port, int speed) 1177 { 1178 SOC_IF_ERROR_RETURN 1179 (phy_fe_ge_speed_set(unit, port, speed)); 1180 1181 return SOC_E_NONE; 1182 } 1183 1184 /* 1185 * Function: 1186 * phy_54680_speed_get 1187 * Purpose: 1188 * Get the current operating speed for a 54680 device. 1189 * Parameters: 1190 * unit - StrataSwitch unit #. 1191 * port - StrataSwitch port #. 1192 * duplex - (OUT) Boolean, true indicates full duplex, false 1193 * indicates half. 1194 * Returns: 1195 * SOC_E_XXX 1196 * Notes: 1197 * The speed is retrieved for the ACTIVE medium. 1198 */ 1199 1200 STATIC int 1201 phy_54680_speed_get(int unit, soc_port_t port, int *speed) 1202 { 1203 SOC_IF_ERROR_RETURN 1204 (phy_fe_ge_speed_get(unit, port, speed)); 1205 1206 return SOC_E_NONE; 1207 } 1208 1209 /* 1210 * Function: 1211 * phy_54680_master_set 1212 * Purpose: 1213 * Set the current master mode 1214 * Parameters: 1215 * unit - StrataSwitch unit #. 1216 * port - StrataSwitch port #. 1217 * master - SOC_PORT_MS_* 1218 * Returns: 1219 * SOC_E_XXX 1220 * Notes: 1221 * The master mode is set only for the ACTIVE medium. 1222 */ 1223 1224 STATIC int 1225 phy_54680_master_set(int unit, soc_port_t port, int master) 1226 { 1227 phy_ctrl_t *pc; 1228 1229 pc = EXT_PHY_SW_STATE(unit, port); 1230 1231 SOC_IF_ERROR_RETURN 1232 (phy_fe_ge_master_set(unit, port, master)); 1233 1234 pc->copper.master = master; 1235 1236 return SOC_E_NONE; 1237 } 1238 1239 /* 1240 * Function: 1241 * phy_54680_master_get 1242 * Purpose: 1243 * Get the current master mode for a 54680 device. 1244 * Parameters: 1245 * unit - StrataSwitch unit #. 1246 * port - StrataSwitch port #. 1247 * master - (OUT) SOC_PORT_MS_* 1248 * Returns: 1249 * SOC_E_XXX 1250 * Notes: 1251 * The master mode is retrieved for the ACTIVE medium. 1252 */ 1253 1254 STATIC int 1255 phy_54680_master_get(int unit, soc_port_t port, int *master) 1256 { 1257 SOC_IF_ERROR_RETURN 1258 (phy_fe_ge_master_get(unit, port, master)); 1259 1260 return SOC_E_NONE; 1261 } 1262 1263 /* 1264 * Function: 1265 * phy_54680_autoneg_set 1266 * Purpose: 1267 * Enable or disable auto-negotiation on the specified port. 1268 * Parameters: 1269 * unit - StrataSwitch unit #. 1270 * port - StrataSwitch port #. 1271 * autoneg - Boolean, if true, auto-negotiation is enabled 1272 * (and/or restarted). If false, autonegotiation is disabled. 1273 * Returns: 1274 * SOC_E_XXX 1275 * Notes: 1276 * The autoneg mode is set only for the ACTIVE medium. 1277 */ 1278 1279 STATIC int 1280 phy_54680_autoneg_set(int unit, soc_port_t port, int autoneg) 1281 { 1282 int rv; 1283 phy_ctrl_t *pc; 1284 1285 pc = EXT_PHY_SW_STATE(unit, port); 1286 rv = SOC_E_NONE; 1287 1288 /* Set auto-neg on PHY */ 1289 rv = phy_fe_ge_an_set(unit, port, autoneg); 1290 if (SOC_SUCCESS(rv)) { 1291 pc->copper.autoneg_enable = autoneg ? 1 : 0; 1292 } 1293 1294 return SOC_E_NONE; 1295 } 1296 1297 /* 1298 * Function: 1299 * phy_54680_autoneg_get 1300 * Purpose: 1301 * Get the current auto-negotiation status (enabled/busy). 1302 * Parameters: 1303 * unit - StrataSwitch unit #. 1304 * port - StrataSwitch port #. 1305 * autoneg - (OUT) if true, auto-negotiation is enabled. 1306 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 1307 * value is undefined if autoneg == FALSE. 1308 * Returns: 1309 * SOC_E_XXX 1310 * Notes: 1311 * The autoneg mode is retrieved for the ACTIVE medium. 1312 */ 1313 1314 STATIC int 1315 phy_54680_autoneg_get(int unit, soc_port_t port, 1316 int *autoneg, int *autoneg_done) 1317 { 1318 1319 SOC_IF_ERROR_RETURN 1320 (phy_fe_ge_an_get(unit, port, autoneg, autoneg_done)); 1321 1322 return SOC_E_NONE; 1323 } 1324 1325 /* 1326 * Function: 1327 * phy_54680_ability_advert_set 1328 * Purpose: 1329 * Set the current advertisement for auto-negotiation. 1330 * Parameters: 1331 * unit - StrataSwitch unit #. 1332 * port - StrataSwitch port #. 1333 * ability - Port ability indicating supported options/speeds. 1334 * Returns: 1335 * SOC_E_XXX 1336 */ 1337 1338 STATIC int 1339 phy_54680_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability) 1340 { 1341 phy_ctrl_t *pc; 1342 uint16 eee_ability = 0; 1343 1344 if (NULL == ability) { 1345 return (SOC_E_PARAM); 1346 } 1347 1348 pc = EXT_PHY_SW_STATE(unit, port); 1349 1350 SOC_IF_ERROR_RETURN 1351 (phy_fe_ge_ability_advert_set(unit, port, ability)); 1352 1353 /* EEE settings */ 1354 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 1355 eee_ability = 0; 1356 if (ability->eee & SOC_PA_EEE_1GB_BASET) { 1357 eee_ability |= 0x4; 1358 } 1359 if (ability->eee & SOC_PA_EEE_100MB_BASETX) { 1360 eee_ability |= 0x2; 1361 } 1362 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) { 1363 SOC_IF_ERROR_RETURN 1364 (MODIFY_PHY54680_EEE_ADVr(unit, pc, eee_ability, 0x0006)); 1365 } else { 1366 SOC_IF_ERROR_RETURN 1367 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0000, 0x0006)); 1368 } 1369 } 1370 1371 return SOC_E_NONE; 1372 1373 } 1374 1375 /* 1376 * Function: 1377 * phy_54680_ability_advert_get 1378 * Purpose: 1379 * Get the current advertisement for auto-negotiation. 1380 * Parameters: 1381 * unit - StrataSwitch unit #. 1382 * port - StrataSwitch port #. 1383 * ability - Port ability indicating supported options/speeds. 1384 * Returns: 1385 * SOC_E_XXX 1386 * Notes: 1387 * The advertisement is retrieved for the ACTIVE medium. 1388 * No synchronization performed at this level. 1389 */ 1390 1391 STATIC int 1392 phy_54680_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1393 { 1394 phy_ctrl_t *pc; 1395 uint16 eee_ability = 0; 1396 1397 if (NULL == ability) { 1398 return (SOC_E_PARAM); 1399 } 1400 1401 pc = EXT_PHY_SW_STATE(unit, port); 1402 1403 SOC_IF_ERROR_RETURN 1404 (phy_fe_ge_ability_advert_get(unit, port, ability)); 1405 1406 /* EEE settings */ 1407 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 1408 SOC_IF_ERROR_RETURN 1409 (READ_PHY54680_EEE_ADVr(unit, pc, &eee_ability)); 1410 if (eee_ability & 0x04) { 1411 ability->eee |= SOC_PA_EEE_1GB_BASET; 1412 } 1413 if (eee_ability & 0x02) { 1414 ability->eee |= SOC_PA_EEE_100MB_BASETX; 1415 } 1416 } 1417 1418 return SOC_E_NONE; 1419 } 1420 1421 /* 1422 * Function: 1423 * phy_54680_ability_remote_get 1424 * Purpose: 1425 * Get partners current advertisement for auto-negotiation. 1426 * Parameters: 1427 * unit - StrataSwitch unit #. 1428 * port - StrataSwitch port #. 1429 * ability - Port ability indicating supported options/speeds. 1430 * Returns: 1431 * SOC_E_XXX 1432 * Notes: 1433 * The remote advertisement is retrieved for the ACTIVE medium. 1434 * No synchronization performed at this level. If Autonegotiation is 1435 * disabled or in progress, this routine will return an error. 1436 */ 1437 1438 STATIC int 1439 phy_54680_ability_remote_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1440 { 1441 phy_ctrl_t *pc; 1442 uint16 eee_resolution; 1443 1444 if (NULL == ability) { 1445 return (SOC_E_PARAM); 1446 } 1447 1448 pc = EXT_PHY_SW_STATE(unit, port); 1449 1450 SOC_IF_ERROR_RETURN 1451 (phy_fe_ge_ability_remote_get(unit, port, ability)); 1452 1453 /* EEE settings */ 1454 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 1455 SOC_IF_ERROR_RETURN 1456 (READ_PHY54680_EEE_RESOLUTION_STATr(unit, pc, &eee_resolution)); 1457 if (eee_resolution & 0x04) { 1458 ability->eee |= SOC_PA_EEE_1GB_BASET; 1459 } 1460 if (eee_resolution & 0x02) { 1461 ability->eee |= SOC_PA_EEE_100MB_BASETX; 1462 } 1463 } 1464 1465 return SOC_E_NONE; 1466 } 1467 1468 /* 1469 * Function: 1470 * phy_54680_ability_local_get 1471 * Purpose: 1472 * Get the device's complete abilities. 1473 * Parameters: 1474 * unit - StrataSwitch unit #. 1475 * port - StrataSwitch port #. 1476 * ability - return device's abilities. 1477 * Returns: 1478 * SOC_E_XXX 1479 */ 1480 1481 STATIC int 1482 phy_54680_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1483 { 1484 phy_ctrl_t *pc; 1485 1486 pc = EXT_PHY_SW_STATE(unit, port); 1487 1488 1489 if (NULL == ability) { 1490 return SOC_E_PARAM; 1491 } 1492 1493 ability->speed_half_duplex = SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB; 1494 ability->speed_full_duplex = SOC_PA_SPEED_1000MB |SOC_PA_SPEED_100MB | 1495 SOC_PA_SPEED_10MB; 1496 1497 1498 if (PHY_IS_BCM54880E_A0(pc)) { /* 880E A0 has a bug, 10Mbs doesn't work */ 1499 ability->speed_half_duplex = SOC_PA_SPEED_100MB; 1500 ability->speed_full_duplex = SOC_PA_SPEED_1000MB |SOC_PA_SPEED_100MB; 1501 } 1502 1503 if (PHY_IS_BCM52681E(pc)) { 1504 ability->speed_half_duplex = SOC_PA_SPEED_100MB |SOC_PA_SPEED_10MB; 1505 ability->speed_full_duplex = SOC_PA_SPEED_100MB |SOC_PA_SPEED_10MB; 1506 } 1507 1508 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 1509 ability->interface = SOC_PA_INTF_SGMII; 1510 if (PHY_IS_BCM53324(pc)) { 1511 /* No SGMII interface */ 1512 ability->interface = SOC_PA_INTF_GMII; 1513 } 1514 ability->medium = SOC_PA_MEDIUM_COPPER; 1515 ability->loopback = SOC_PA_LB_PHY; 1516 ability->flags = SOC_PA_AUTONEG; 1517 1518 /* EEE settings */ 1519 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 1520 if (PHY_IS_BCM52681E(pc)) { 1521 ability->eee = SOC_PA_EEE_100MB_BASETX; 1522 } else { 1523 ability->eee = SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX; 1524 } 1525 } 1526 1527 return SOC_E_NONE; 1528 } 1529 1530 1531 /* 1532 * Function: 1533 * phy_54680_lb_set 1534 * Purpose: 1535 * Set the local PHY loopback mode. 1536 * Parameters: 1537 * unit - StrataSwitch unit #. 1538 * port - StrataSwitch port #. 1539 * loopback - Boolean: true = enable loopback, false = disable. 1540 * Returns: 1541 * SOC_E_XXX 1542 * Notes: 1543 * The loopback mode is set only for the ACTIVE medium. 1544 * No synchronization performed at this level. 1545 */ 1546 1547 STATIC int 1548 phy_54680_lb_set(int unit, soc_port_t port, int enable) 1549 { 1550 phy_ctrl_t *pc; 1551 int link = FALSE; 1552 1553 pc = EXT_PHY_SW_STATE(unit, port); 1554 1555 if ( PHY_IS_BCM53324(pc) || PHY_IS_BCM52681E(pc) ) { 1556 /* No SGMII interface */ 1557 1558 /* 1559 * Force link state machine into pass state. 1560 * Thus the PHY is forced to show link up without the link partner. 1561 * This is WA for no link-up issue about forcing 10/100 Mbps 1562 * in PHY loopback. 1563 */ 1564 if( PHY_IS_BCM53324(pc) ) { 1565 if( enable ) { 1566 /* Force LSM to pass state */ 1567 SOC_IF_ERROR_RETURN 1568 (MODIFY_PHY54680_TEST1r(unit, pc, (1U << 12), (1U << 12))); 1569 } else { 1570 /* Normal LSM operation */ 1571 SOC_IF_ERROR_RETURN 1572 (MODIFY_PHY54680_TEST1r(unit, pc, 0, (1U << 12))); 1573 } 1574 } 1575 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 1576 if ( enable ) { 1577 SOC_IF_ERROR_RETURN( 1578 PHY_LINKUP_EVT(pc->pd, unit, port)); 1579 } else { 1580 SOC_IF_ERROR_RETURN( 1581 phy_54680_link_get(unit, port, &link)); 1582 if ( link == TRUE ) { 1583 SOC_IF_ERROR_RETURN( 1584 PHY_LINKUP_EVT(pc->pd, unit, port)); 1585 } else { 1586 SOC_IF_ERROR_RETURN( 1587 PHY_LINKDN_EVT(pc->pd, unit, port)); 1588 } 1589 } 1590 } 1591 } else { 1592 1593 /* devices with SGMII interface */ 1594 if ( enable ) { 1595 /* SGMII loopback with RX/TX on MDI suppressed */ 1596 SOC_IF_ERROR_RETURN 1597 (WRITE_PHY54680_EXP_SGMII_LINESIDE_LOOPBACK_CTRLr(unit, pc, 1598 (1U << 2) | (1U << 1) | (1U << 0))); 1599 /* Force LSM to pass state */ 1600 SOC_IF_ERROR_RETURN 1601 (MODIFY_PHY54680_TEST1r(unit, pc, (1U << 12), (1U << 12))); 1602 /* Disable TX */ 1603 SOC_IF_ERROR_RETURN 1604 (MODIFY_PHY54680_MII_ECRr(unit, pc, (1U << 13), (1U << 13))); 1605 1606 } else { 1607 /* no SGMII loopback */ 1608 SOC_IF_ERROR_RETURN 1609 (WRITE_PHY54680_EXP_SGMII_LINESIDE_LOOPBACK_CTRLr(unit, pc, 1610 0x0)); 1611 /* Normal LSM operation */ 1612 SOC_IF_ERROR_RETURN 1613 (MODIFY_PHY54680_TEST1r(unit, pc, 0, (1U << 12))); 1614 /* Enable TX */ 1615 SOC_IF_ERROR_RETURN 1616 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0, (1U << 13))); 1617 } 1618 } 1619 1620 /* MII Control Register, Reg.0x0 bit[14] internal loopback */ 1621 SOC_IF_ERROR_RETURN 1622 (phy_fe_ge_lb_set(unit, port, enable)); 1623 1624 return SOC_E_NONE; 1625 } 1626 1627 /* 1628 * Function: 1629 * phy_54680_lb_get 1630 * Purpose: 1631 * Get the local PHY loopback mode. 1632 * Parameters: 1633 * unit - StrataSwitch unit #. 1634 * port - StrataSwitch port #. 1635 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 1636 * Returns: 1637 * SOC_E_XXX 1638 * Notes: 1639 * The loopback mode is retrieved for the ACTIVE medium. 1640 */ 1641 1642 STATIC int 1643 phy_54680_lb_get(int unit, soc_port_t port, int *enable) 1644 { 1645 phy_ctrl_t *pc; 1646 uint16 temp; 1647 1648 pc = EXT_PHY_SW_STATE(unit, port); 1649 1650 if ( PHY_IS_BCM53324(pc) || PHY_IS_BCM52681E(pc) ) { 1651 /* No SGMII interface */ 1652 SOC_IF_ERROR_RETURN(phy_fe_ge_lb_get(unit, port, enable)); 1653 return SOC_E_NONE; 1654 } 1655 1656 SOC_IF_ERROR_RETURN 1657 (READ_PHY54680_EXP_SGMII_LINESIDE_LOOPBACK_CTRLr(unit, pc, &temp)); 1658 *enable = (temp & (1U << 2)) ? TRUE : FALSE; 1659 1660 return SOC_E_NONE; 1661 } 1662 1663 /* 1664 * Function: 1665 * phy_54680_interface_set 1666 * Purpose: 1667 * Set the current operating mode of the internal PHY. 1668 * (Pertaining to the MAC/PHY interface, not the line interface). 1669 * Parameters: 1670 * unit - StrataSwitch unit #. 1671 * port - StrataSwitch port #. 1672 * pif - one of SOC_PORT_IF_* 1673 * Returns: 1674 * SOC_E_XXX 1675 */ 1676 1677 STATIC int 1678 phy_54680_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1679 { 1680 COMPILER_REFERENCE(unit); 1681 COMPILER_REFERENCE(port); 1682 COMPILER_REFERENCE(pif); 1683 1684 return SOC_E_NONE; 1685 1686 } 1687 1688 /* 1689 * Function: 1690 * phy_54680_interface_get 1691 * Purpose: 1692 * Get the current operating mode of the internal PHY. 1693 * (Pertaining to the MAC/PHY interface, not the line interface). 1694 * Parameters: 1695 * unit - StrataSwitch unit #. 1696 * port - StrataSwitch port #. 1697 * pif - (OUT) one of SOC_PORT_IF_* 1698 * Returns: 1699 * SOC_E_XXX 1700 */ 1701 1702 STATIC int 1703 phy_54680_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1704 { 1705 #if defined(BCM_53314) 1706 phy_ctrl_t *pc; 1707 1708 pc = EXT_PHY_SW_STATE(unit, port); 1709 1710 if(PHY_IS_BCM53324(pc)) { 1711 *pif = SOC_PORT_IF_GMII; 1712 } else 1713 #endif /* BCM_53314 */ 1714 { 1715 *pif = SOC_PORT_IF_SGMII; 1716 } 1717 1718 return(SOC_E_NONE); 1719 } 1720 1721 /* 1722 * Function: 1723 * phy_54680_mdix_set 1724 * Description: 1725 * Set the Auto-MDIX mode of a port/PHY 1726 * Parameters: 1727 * unit - Device number 1728 * port - Port number 1729 * mode - One of: 1730 * SOC_PORT_MDIX_AUTO 1731 * Enable auto-MDIX when autonegotiation is enabled 1732 * SOC_PORT_MDIX_FORCE_AUTO 1733 * Enable auto-MDIX always 1734 * SOC_PORT_MDIX_NORMAL 1735 * Disable auto-MDIX 1736 * SOC_PORT_MDIX_XOVER 1737 * Disable auto-MDIX, and swap cable pairs 1738 * Return Value: 1739 * SOC_E_XXX 1740 */ 1741 STATIC int 1742 phy_54680_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode) 1743 { 1744 phy_ctrl_t *pc; 1745 int speed; 1746 1747 pc = EXT_PHY_SW_STATE(unit, port); 1748 1749 switch (mode) { 1750 case SOC_PORT_MDIX_AUTO: 1751 /* Clear bit 14 for automatic MDI crossover */ 1752 SOC_IF_ERROR_RETURN 1753 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0, 0x4000)); 1754 1755 /* 1756 * Write the result in the register 0x18, shadow copy 7 1757 */ 1758 /* Clear bit 9 to disable forced auto MDI xover */ 1759 SOC_IF_ERROR_RETURN 1760 (MODIFY_PHY54680_MII_MISC_CTRLr(unit, pc, 0, 0x0200)); 1761 break; 1762 1763 case SOC_PORT_MDIX_FORCE_AUTO: 1764 /* Clear bit 14 for automatic MDI crossover */ 1765 SOC_IF_ERROR_RETURN 1766 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0, 0x4000)); 1767 1768 /* 1769 * Write the result in the register 0x18, shadow copy 7 1770 */ 1771 /* Set bit 9 to force automatic MDI crossover */ 1772 SOC_IF_ERROR_RETURN 1773 (MODIFY_PHY54680_MII_MISC_CTRLr(unit, pc, 0x0200, 0x0200)); 1774 break; 1775 1776 case SOC_PORT_MDIX_NORMAL: 1777 SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed)); 1778 if (speed == 0 || speed == 10 || speed == 100) { 1779 /* Set bit 14 for manual MDI crossover */ 1780 SOC_IF_ERROR_RETURN 1781 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0x4000, 0x4000)); 1782 1783 SOC_IF_ERROR_RETURN 1784 (WRITE_PHY54680_TEST1r(unit, pc, 0)); 1785 } else { 1786 return SOC_E_UNAVAIL; 1787 } 1788 break; 1789 1790 case SOC_PORT_MDIX_XOVER: 1791 SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed)); 1792 if (speed == 0 || speed == 10 || speed == 100) { 1793 /* Set bit 14 for manual MDI crossover */ 1794 SOC_IF_ERROR_RETURN 1795 (MODIFY_PHY54680_MII_ECRr(unit, pc, 0x4000, 0x4000)); 1796 1797 SOC_IF_ERROR_RETURN 1798 (WRITE_PHY54680_TEST1r(unit, pc, 0x0080)); 1799 } else { 1800 return SOC_E_UNAVAIL; 1801 } 1802 break; 1803 1804 default: 1805 return SOC_E_PARAM; 1806 } 1807 1808 pc->copper.mdix = mode; 1809 return SOC_E_NONE; 1810 1811 } 1812 1813 #if defined(BCM_WARM_BOOT_SUPPORT) 1814 /* 1815 * Function: 1816 * phy_54680_mdix_wb_update 1817 * Description: 1818 * Read the hw, derive the mode and update the mdix mode in sw structure 1819 * during wb. 1820 * Parameters: 1821 * unit - (IN) Device number 1822 * port - (IN) Port number 1823 * mode - (OUT) :One of: 1824 * SOC_PORT_MDIX_AUTO 1825 * Enable auto-MDIX when autonegotiation is enabled 1826 * SOC_PORT_MDIX_FORCE_AUTO 1827 * Enable auto-MDIX always 1828 * SOC_PORT_MDIX_NORMAL 1829 * Disable auto-MDIX 1830 * SOC_PORT_MDIX_XOVER 1831 * Disable auto-MDIX, and swap cable pairs 1832 * Return Value: 1833 * SOC_E_XXX 1834 */ 1835 STATIC int 1836 phy_54680_mdix_wb_update(int unit, soc_port_t port) 1837 { 1838 phy_ctrl_t *pc; 1839 int speed; 1840 int mode = 0; 1841 uint16 val = 0; 1842 1843 pc = EXT_PHY_SW_STATE(unit, port); 1844 1845 /* Check bit 14 for automatic MDI crossover */ 1846 SOC_IF_ERROR_RETURN (READ_PHY54680_MII_ECRr(unit, pc, &val)); 1847 if(val & 0x4000) { 1848 SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed)); 1849 if (speed == 0 || speed == 10 || speed == 100) { 1850 SOC_IF_ERROR_RETURN (READ_PHY54680_TEST1r(unit, pc, &val)); 1851 if (0 == val) { 1852 mode = SOC_PORT_MDIX_NORMAL; 1853 } else if (0x80 == val) { 1854 mode = SOC_PORT_MDIX_XOVER; 1855 } else { 1856 return SOC_E_UNAVAIL; 1857 } 1858 } else { 1859 return SOC_E_UNAVAIL; 1860 } 1861 } else { 1862 /* Check bit 9 forced auto MDI xover */ 1863 SOC_IF_ERROR_RETURN (READ_PHY54680_MII_MISC_CTRLr(unit, pc,&val)); 1864 if (val & 0x200) { 1865 /* bit 9 Set, forced auto MDI xover */ 1866 mode = SOC_PORT_MDIX_FORCE_AUTO; 1867 } else { 1868 /* bit 9 Clear, forced auto MDI xover */ 1869 mode = SOC_PORT_MDIX_AUTO; 1870 } 1871 } 1872 pc->copper.mdix = mode; 1873 1874 return SOC_E_NONE; 1875 } 1876 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */ 1877 1878 1879 /* 1880 * Function: 1881 * phy_54680_mdix_get 1882 * Description: 1883 * Get the Auto-MDIX mode of a port/PHY 1884 * Parameters: 1885 * unit - Device number 1886 * port - Port number 1887 * mode - (Out) One of: 1888 * SOC_PORT_MDIX_AUTO 1889 * Enable auto-MDIX when autonegotiation is enabled 1890 * SOC_PORT_MDIX_FORCE_AUTO 1891 * Enable auto-MDIX always 1892 * SOC_PORT_MDIX_NORMAL 1893 * Disable auto-MDIX 1894 * SOC_PORT_MDIX_XOVER 1895 * Disable auto-MDIX, and swap cable pairs 1896 * Return Value: 1897 * SOC_E_XXX 1898 */ 1899 STATIC int 1900 phy_54680_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode) 1901 { 1902 phy_ctrl_t *pc; 1903 int speed; 1904 1905 pc = EXT_PHY_SW_STATE(unit, port); 1906 1907 #if defined(BCM_WARM_BOOT_SUPPORT) 1908 if (SOC_WARM_BOOT(unit)) { 1909 return phy_54680_mdix_wb_update(unit, port); 1910 } 1911 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */ 1912 1913 SOC_IF_ERROR_RETURN(phy_54680_speed_get(unit, port, &speed)); 1914 if (speed == 1000) { 1915 *mode = SOC_PORT_MDIX_AUTO; 1916 } else { 1917 *mode = pc->copper.mdix; 1918 } 1919 1920 return SOC_E_NONE; 1921 } 1922 1923 /* 1924 * Function: 1925 * phy_54680_mdix_status_get 1926 * Description: 1927 * Get the current MDIX status on a port/PHY 1928 * Parameters: 1929 * unit - Device number 1930 * port - Port number 1931 * status - (OUT) One of: 1932 * SOC_PORT_MDIX_STATUS_NORMAL 1933 * Straight connection 1934 * SOC_PORT_MDIX_STATUS_XOVER 1935 * Crossover has been performed 1936 * Return Value: 1937 * SOC_E_XXX 1938 */ 1939 STATIC int 1940 phy_54680_mdix_status_get(int unit, soc_port_t port, 1941 soc_port_mdix_status_t *status) 1942 { 1943 phy_ctrl_t *pc; 1944 uint16 tmp; 1945 1946 pc = EXT_PHY_SW_STATE(unit, port); 1947 1948 SOC_IF_ERROR_RETURN 1949 (READ_PHY54680_MII_ESRr(unit, pc, &tmp)); 1950 if (tmp & 0x2000) { 1951 *status = SOC_PORT_MDIX_STATUS_XOVER; 1952 } else { 1953 *status = SOC_PORT_MDIX_STATUS_NORMAL; 1954 } 1955 1956 return SOC_E_NONE; 1957 } 1958 1959 STATIC int 1960 _phy_54680_power_mode_set (int unit, soc_port_t port, int mode) 1961 { 1962 phy_ctrl_t *pc; 1963 1964 pc = EXT_PHY_SW_STATE(unit, port); 1965 1966 if (pc->power_mode == mode) { 1967 return SOC_E_NONE; 1968 } 1969 1970 if (mode == SOC_PHY_CONTROL_POWER_LOW) { 1971 /* enable dsp clock */ 1972 SOC_IF_ERROR_RETURN 1973 (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0c00,0x0c00)); 1974 1975 /* enable low power 136 */ 1976 SOC_IF_ERROR_RETURN 1977 (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,0x80,0x80)); 1978 1979 /* reduce tx bias current to -20% */ 1980 SOC_IF_ERROR_RETURN 1981 (WRITE_PHY_REG(unit, pc, 0x17, 0x0f75)); 1982 SOC_IF_ERROR_RETURN 1983 (WRITE_PHY_REG(unit, pc, 0x15, 0x1555)); 1984 1985 /* disable dsp clock */ 1986 SOC_IF_ERROR_RETURN 1987 (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0400,0x0c00)); 1988 1989 } else if (mode == SOC_PHY_CONTROL_POWER_FULL) { 1990 1991 /* back to normal mode */ 1992 /* enable dsp clock */ 1993 SOC_IF_ERROR_RETURN 1994 (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0c00,0x0c00)); 1995 1996 /* disable low power 136 */ 1997 SOC_IF_ERROR_RETURN 1998 (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc,0x00,0x80)); 1999 2000 /* set tx bias current to nominal */ 2001 SOC_IF_ERROR_RETURN 2002 (WRITE_PHY_REG(unit, pc, 0x17, 0x0f75)); 2003 SOC_IF_ERROR_RETURN 2004 (WRITE_PHY_REG(unit, pc, 0x15, 0x0)); 2005 2006 /* disable dsp clock */ 2007 SOC_IF_ERROR_RETURN 2008 (MODIFY_PHY54680_MII_AUX_CTRLr(unit,pc,0x0400,0x0c00)); 2009 2010 /* disable the auto power mode */ 2011 SOC_IF_ERROR_RETURN 2012 (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc, 2013 0, 2014 PHY_54680_AUTO_PWRDWN_EN)); 2015 } else if (mode == SOC_PHY_CONTROL_POWER_AUTO) { 2016 SOC_IF_ERROR_RETURN 2017 (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc, 2018 PHY_54680_AUTO_PWRDWN_EN, 2019 PHY_54680_AUTO_PWRDWN_EN)); 2020 } else if (mode == SOC_PHY_CONTROL_POWER_AUTO_DISABLE) { 2021 /* 2022 Power mode added(SDK-30895). Requirement is to disable Auto Power Down 2023 without changing Tx bias current 2024 */ 2025 SOC_IF_ERROR_RETURN 2026 (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc, 2027 0, 2028 PHY_54680_AUTO_PWRDWN_EN)); 2029 2030 } 2031 2032 pc->power_mode = mode; 2033 2034 return SOC_E_NONE; 2035 } 2036 2037 /* 2038 * Function: 2039 * _phy_54680_eee_enable 2040 * Purpose: 2041 * Enable or disable EEE (Native) 2042 * Parameters: 2043 * unit - StrataSwitch unit #. 2044 * port - StrataSwitch port #. 2045 * enable - Enable Native EEE 2046 * Returns: 2047 * SOC_E_NONE 2048 */ 2049 STATIC int 2050 _phy_54680_eee_enable(int unit, soc_port_t port, int enable) 2051 { 2052 phy_ctrl_t *pc; 2053 2054 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2055 return SOC_E_FAIL; 2056 } 2057 pc = EXT_PHY_SW_STATE(unit, port); 2058 2059 if (enable == 1) { 2060 if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) { 2061 SOC_IF_ERROR_RETURN 2062 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00)); 2063 2064 SOC_IF_ERROR_RETURN( 2065 WRITE_PHY_REG(unit, pc, 0x17, 0x0ffe)); 2066 SOC_IF_ERROR_RETURN( 2067 WRITE_PHY_REG(unit, pc, 0x15, 0x0100)); 2068 2069 SOC_IF_ERROR_RETURN( 2070 WRITE_PHY_REG(unit, pc, 0x17, 0x0fff)); 2071 SOC_IF_ERROR_RETURN( 2072 WRITE_PHY_REG(unit, pc, 0x15, 0x4000)); 2073 2074 SOC_IF_ERROR_RETURN( 2075 WRITE_PHY_REG(unit, pc, 0x17, 0x2022)); 2076 SOC_IF_ERROR_RETURN( 2077 WRITE_PHY_REG(unit, pc, 0x15, 0x01f1)); 2078 2079 SOC_IF_ERROR_RETURN( 2080 WRITE_PHY_REG(unit, pc, 0x17, 0x4021)); 2081 SOC_IF_ERROR_RETURN( 2082 WRITE_PHY_REG(unit, pc, 0x15, 0x0887)); 2083 2084 SOC_IF_ERROR_RETURN( 2085 WRITE_PHY_REG(unit, pc, 0x17, 0x2021)); 2086 SOC_IF_ERROR_RETURN( 2087 WRITE_PHY_REG(unit, pc, 0x15, 0x8983)); 2088 2089 SOC_IF_ERROR_RETURN( 2090 WRITE_PHY_REG(unit, pc, 0x17, 0x0021)); 2091 SOC_IF_ERROR_RETURN( 2092 WRITE_PHY_REG(unit, pc, 0x15, 0x4600)); 2093 2094 SOC_IF_ERROR_RETURN( 2095 WRITE_PHY_REG(unit, pc, 0x17, 0x0e40)); 2096 SOC_IF_ERROR_RETURN( 2097 WRITE_PHY_REG(unit, pc, 0x15, 0x0000)); 2098 2099 SOC_IF_ERROR_RETURN 2100 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00)); 2101 2102 SOC_IF_ERROR_RETURN 2103 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0xc000, 0xc000)); 2104 SOC_IF_ERROR_RETURN 2105 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0xf300, 0xf300)); 2106 } else { 2107 SOC_IF_ERROR_RETURN 2108 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0xc000, 0xc000)); /* 7.803d */ 2109 } 2110 if (PHY_IS_BCM52681E(pc)) { 2111 SOC_IF_ERROR_RETURN 2112 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0002, 0x0006)); 2113 pc->copper.advert_ability.eee |= SOC_PA_EEE_100MB_BASETX; 2114 2115 } else { 2116 SOC_IF_ERROR_RETURN 2117 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0006, 0x0006)); 2118 pc->copper.advert_ability.eee |= (SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2119 } 2120 2121 /* no support of AutogrEEEn */ 2122 SOC_IF_ERROR_RETURN 2123 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x1, 0x1)); /* exp af */ 2124 } else { /* enable != 1 */ 2125 if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) { 2126 SOC_IF_ERROR_RETURN 2127 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0x0000, 0xc000)); 2128 SOC_IF_ERROR_RETURN 2129 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0x0000, 0xf300)); 2130 } else { 2131 SOC_IF_ERROR_RETURN 2132 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0x0000, 0xc000)); /* 7.803d */ 2133 } 2134 SOC_IF_ERROR_RETURN 2135 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0000, 0x0006)); 2136 pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2137 2138 /* no support of AutogrEEEn */ 2139 SOC_IF_ERROR_RETURN 2140 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 0x1)); /* exp af */ 2141 } 2142 2143 return SOC_E_NONE; 2144 } 2145 2146 /* 2147 * Function: 2148 * _phy_54680_eee_auto_enable 2149 * Purpose: 2150 * Enable or disable EEE (Native) 2151 * Parameters: 2152 * unit - StrataSwitch unit #. 2153 * port - StrataSwitch port #. 2154 * enable - Enable Native EEE 2155 * Returns: 2156 * SOC_E_NONE 2157 */ 2158 STATIC int 2159 _phy_54680_eee_auto_enable(int unit, soc_port_t port, int enable) 2160 { 2161 phy_ctrl_t *pc; 2162 2163 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2164 return SOC_E_FAIL; 2165 } 2166 pc = EXT_PHY_SW_STATE(unit, port); 2167 2168 if (enable == 1) { 2169 if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) { 2170 SOC_IF_ERROR_RETURN 2171 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0c00, 0x0c00)); 2172 2173 SOC_IF_ERROR_RETURN( 2174 WRITE_PHY_REG(unit, pc, 0x17, 0x0ffe)); 2175 SOC_IF_ERROR_RETURN( 2176 WRITE_PHY_REG(unit, pc, 0x15, 0x0900)); 2177 2178 SOC_IF_ERROR_RETURN( 2179 WRITE_PHY_REG(unit, pc, 0x17, 0x0fff)); 2180 SOC_IF_ERROR_RETURN( 2181 WRITE_PHY_REG(unit, pc, 0x15, 0x4000)); 2182 2183 SOC_IF_ERROR_RETURN( 2184 WRITE_PHY_REG(unit, pc, 0x17, 0x2022)); 2185 SOC_IF_ERROR_RETURN( 2186 WRITE_PHY_REG(unit, pc, 0x15, 0x01f1)); 2187 2188 SOC_IF_ERROR_RETURN( 2189 WRITE_PHY_REG(unit, pc, 0x17, 0x2021)); 2190 SOC_IF_ERROR_RETURN( 2191 WRITE_PHY_REG(unit, pc, 0x15, 0x8983)); 2192 2193 SOC_IF_ERROR_RETURN( 2194 WRITE_PHY_REG(unit, pc, 0x17, 0x4021)); 2195 SOC_IF_ERROR_RETURN( 2196 WRITE_PHY_REG(unit, pc, 0x15, 0x0887)); 2197 2198 SOC_IF_ERROR_RETURN( 2199 WRITE_PHY_REG(unit, pc, 0x17, 0x0021)); 2200 SOC_IF_ERROR_RETURN( 2201 WRITE_PHY_REG(unit, pc, 0x15, 0x4600)); 2202 2203 SOC_IF_ERROR_RETURN 2204 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0x0400, 0x0c00)); 2205 2206 SOC_IF_ERROR_RETURN 2207 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0xc000, 0xc000)); 2208 2209 SOC_IF_ERROR_RETURN 2210 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0x1300, 0x1300)); 2211 2212 } else { 2213 SOC_IF_ERROR_RETURN 2214 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0xc000, 0xc000)); /* 7.803d */ 2215 } 2216 if (PHY_IS_BCM52681E(pc)) { 2217 SOC_IF_ERROR_RETURN 2218 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0002, 0x0006)); 2219 pc->copper.advert_ability.eee |= SOC_PA_EEE_100MB_BASETX; 2220 } else { 2221 SOC_IF_ERROR_RETURN 2222 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0006, 0x0006)); 2223 pc->copper.advert_ability.eee |= (SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2224 } 2225 2226 SOC_IF_ERROR_RETURN 2227 (MODIFY_PHY54680_MODE_CTRLr(unit, pc, 0x00, 0x06)); 2228 2229 SOC_IF_ERROR_RETURN 2230 (MODIFY_PHY54680_SGMII_SLAVEr(unit, pc, 0x02, 0x02)); 2231 2232 if (!PHY_IS_BCM52681E(pc)) { 2233 SOC_IF_ERROR_RETURN 2234 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0F7F,0x15, 0x7, 0x7)); /* exp 7f */ 2235 } 2236 2237 SOC_IF_ERROR_RETURN 2238 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x1, 0x1)); /* exp af */ 2239 2240 SOC_IF_ERROR_RETURN 2241 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7, 0x0001, 0x0003)); 2242 2243 } else { /* enable != 1 */ 2244 SOC_IF_ERROR_RETURN 2245 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 0x3)); /* exp af */ 2246 SOC_IF_ERROR_RETURN 2247 (MODIFY_PHY54680_EEE_ADVr(unit, pc, 0x0000, 0x0006)); 2248 pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2249 2250 if (PHY_IS_BCM54680E_A0A1(pc) || PHY_IS_BCM54880E_A0A1(pc)) { 2251 SOC_IF_ERROR_RETURN 2252 (MODIFY_PHY54680_EEE_TEST_CTRL_Br(unit, pc, 0x0000, 0xc000)); /* 7.8031 */ 2253 SOC_IF_ERROR_RETURN 2254 (MODIFY_PHY54680_EEE_TEST_CTRL_Ar(unit, pc, 0x0000, 0xf300)); /* 7.8030 2 ops */ 2255 } else { 2256 SOC_IF_ERROR_RETURN 2257 (MODIFY_PHY54680_EEE_803Dr(unit, pc, 0x0000, 0xc000)); /* 7.803d */ 2258 } 2259 } 2260 2261 return SOC_E_NONE; 2262 } 2263 2264 /* 2265 * Function: 2266 * phy_54680_control_set 2267 * Purpose: 2268 * Configure PHY device specific control fucntion. 2269 * Parameters: 2270 * unit - StrataSwitch unit #. 2271 * port - StrataSwitch port #. 2272 * type - Control to update 2273 * value - New setting for the control 2274 * Returns: 2275 * SOC_E_NONE 2276 */ 2277 STATIC int 2278 phy_54680_control_set(int unit, soc_port_t port, 2279 soc_phy_control_t type, uint32 value) 2280 { 2281 int rv; 2282 phy_ctrl_t *pc; 2283 uint16 data; 2284 soc_port_t primary; 2285 int offset, saved_autoneg; 2286 2287 PHY_CONTROL_TYPE_CHECK(type); 2288 2289 pc = EXT_PHY_SW_STATE(unit, port); 2290 rv = SOC_E_NONE; 2291 2292 switch(type) { 2293 case SOC_PHY_CONTROL_POWER: 2294 rv = _phy_54680_power_mode_set(unit,port,value); 2295 break; 2296 2297 case SOC_PHY_CONTROL_DLL_POWER_AUTO: 2298 /* 2299 Deep Green Mode Control(PHY-401) - to enable/diable DLL Auto Power Down 2300 */ 2301 if(1 == value) { /* enable */ 2302 SOC_IF_ERROR_RETURN 2303 (MODIFY_PHY54680_SPARE_CTRL_3r(unit, pc, 2304 0, 2305 PHY_54680_SPARE_CTRL3_REG_DLL_AUTO_PWR_DOWN)); 2306 2307 } else if(0 == value){ /* disable */ 2308 SOC_IF_ERROR_RETURN 2309 (MODIFY_PHY54680_SPARE_CTRL_3r(unit, pc, 2310 PHY_54680_SPARE_CTRL3_REG_DLL_AUTO_PWR_DOWN, 2311 PHY_54680_SPARE_CTRL3_REG_DLL_AUTO_PWR_DOWN)); 2312 } else { 2313 rv = SOC_E_PARAM; 2314 } 2315 break; 2316 2317 case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME: 2318 if (value <= PHY_54680_AUTO_PWRDWN_WAKEUP_MAX) { 2319 2320 /* at least one unit */ 2321 if (value < PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT) { 2322 value = PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT; 2323 } 2324 } else { /* anything more then max, set to the max */ 2325 value = PHY_54680_AUTO_PWRDWN_WAKEUP_MAX; 2326 } 2327 SOC_IF_ERROR_RETURN 2328 (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc, 2329 value/PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT, 2330 PHY_54680_AUTO_PWRDWN_WAKEUP_MASK)); 2331 break; 2332 2333 case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME: 2334 /* sleep time configuration is either 2.7s or 5.4 s, default is 2.7s */ 2335 if (value < PHY_54680_AUTO_PWRDWN_SLEEP_MAX) { 2336 data = 0; /* anything less than 5.4s, default to 2.7s */ 2337 } else { 2338 data = PHY_54680_AUTO_PWRDWN_SLEEP_MASK; 2339 } 2340 SOC_IF_ERROR_RETURN 2341 (MODIFY_PHY54680_AUTO_POWER_DOWNr(unit,pc, 2342 data, 2343 PHY_54680_AUTO_PWRDWN_SLEEP_MASK)); 2344 break; 2345 2346 case SOC_PHY_CONTROL_PORT_PRIMARY: 2347 SOC_IF_ERROR_RETURN 2348 (soc_phyctrl_primary_set(unit, port, (soc_port_t)value)); 2349 break; 2350 2351 case SOC_PHY_CONTROL_PORT_OFFSET: 2352 SOC_IF_ERROR_RETURN 2353 (soc_phyctrl_offset_set(unit, port, (int)value)); 2354 break; 2355 2356 case SOC_PHY_CONTROL_CLOCK_ENABLE: 2357 SOC_IF_ERROR_RETURN 2358 (soc_phyctrl_primary_get(unit, port, &primary)); 2359 SOC_IF_ERROR_RETURN 2360 (soc_phyctrl_offset_get(unit, port, &offset)); 2361 SOC_IF_ERROR_RETURN 2362 (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data)); 2363 if ( value ) { 2364 SOC_IF_ERROR_RETURN 2365 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 2366 ( data & 0xf0 ) | ( offset & 0x7 ))); 2367 } else { 2368 SOC_IF_ERROR_RETURN 2369 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 2370 ( data & 0xf0 ) | 0x8 )); 2371 } 2372 break; 2373 2374 case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE: 2375 SOC_IF_ERROR_RETURN 2376 (soc_phyctrl_primary_get(unit, port, &primary)); 2377 SOC_IF_ERROR_RETURN 2378 (soc_phyctrl_offset_get(unit, port, &offset)); 2379 SOC_IF_ERROR_RETURN 2380 (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data)); 2381 if ( value ) { 2382 SOC_IF_ERROR_RETURN 2383 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 2384 ( data & 0x0f ) | (( offset & 0x7 )<<4 ))); 2385 } else { 2386 SOC_IF_ERROR_RETURN 2387 (phy_54680_toplvl_reg_write(unit, port, primary, 0x0, 2388 ( data & 0x0f ) | (0x8<<4) )); 2389 } 2390 break; 2391 2392 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 2393 /* Not supported for 10/100/1000BASE-T interfaces */ 2394 rv = SOC_E_UNAVAIL; 2395 break; 2396 2397 case SOC_PHY_CONTROL_EEE: 2398 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2399 rv = SOC_E_UNAVAIL; 2400 } 2401 2402 if (value == 1) { 2403 /* didn't support Auto EEE */ 2404 if ((!PHY_IS_BCM53324(pc))) { 2405 /* Disable Auto EEE */ 2406 SOC_IF_ERROR_RETURN 2407 (_phy_54680_eee_auto_enable(unit, port, 0)); 2408 } 2409 /* Enable Native EEE */ 2410 SOC_IF_ERROR_RETURN 2411 (_phy_54680_eee_enable(unit, port, 1)); 2412 saved_autoneg = pc->copper.autoneg_enable; 2413 /* Initiate AN */ 2414 SOC_IF_ERROR_RETURN 2415 (phy_54680_autoneg_set(unit, port, 1)); 2416 pc->copper.autoneg_enable = saved_autoneg; 2417 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 2418 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE); 2419 } else { 2420 SOC_IF_ERROR_RETURN 2421 (_phy_54680_eee_enable(unit, port, 0)); 2422 /* Initiate AN if administratively enabled */ 2423 SOC_IF_ERROR_RETURN 2424 (phy_54680_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0)); 2425 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 2426 2427 } 2428 2429 2430 break; 2431 2432 case SOC_PHY_CONTROL_EEE_AUTO: 2433 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2434 rv = SOC_E_UNAVAIL; 2435 } 2436 if (PHY_IS_BCM53324(pc)) { 2437 rv = SOC_E_UNAVAIL; 2438 } 2439 if (value == 1) { 2440 /* Disable Native EEE */ 2441 SOC_IF_ERROR_RETURN 2442 (_phy_54680_eee_enable(unit, port, 0)); 2443 /* Enable Auto EEE */ 2444 SOC_IF_ERROR_RETURN 2445 (_phy_54680_eee_auto_enable(unit, port, 1)); 2446 saved_autoneg = pc->copper.autoneg_enable; 2447 /* Initiate AN */ 2448 SOC_IF_ERROR_RETURN 2449 (phy_54680_autoneg_set(unit, port, 1)); 2450 pc->copper.autoneg_enable = saved_autoneg; 2451 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 2452 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_MODE); 2453 } else { 2454 /* Disable Auto EEE */ 2455 SOC_IF_ERROR_RETURN 2456 (_phy_54680_eee_auto_enable(unit, port, 0)); 2457 /* Initiate AN if administratively enabled */ 2458 SOC_IF_ERROR_RETURN 2459 (phy_54680_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0)); 2460 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 2461 } 2462 2463 break; 2464 2465 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 2466 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2467 rv = SOC_E_UNAVAIL; 2468 } 2469 2470 if (value > 7) { /* Values needs to between 0 to 7 (inclusive) */ 2471 rv = SOC_E_CONFIG; 2472 } 2473 2474 SOC_IF_ERROR_RETURN 2475 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7, 2476 value<<8, 0x0700)); 2477 /* Setting GPHY core, MII buffer register as well */ 2478 SOC_IF_ERROR_RETURN 2479 (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 2480 value<<8, 0x0700)); 2481 break; 2482 2483 2484 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 2485 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2486 rv = SOC_E_UNAVAIL; 2487 } 2488 /* Fixed latency can have only 0 or 1 value */ 2489 if ((value != FALSE) && (value != TRUE)) { 2490 return SOC_E_PARAM; 2491 } 2492 if (value == FALSE) { 2493 /* Sets Variable Latency */ 2494 SOC_IF_ERROR_RETURN 2495 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7, 2496 0x0004, 0x0004)); 2497 /* Setting GPHY core, MII buffer register as well */ 2498 SOC_IF_ERROR_RETURN 2499 (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 2500 0x0004, 0x0004)); 2501 } else { 2502 /* Sets Fixed Latency */ 2503 SOC_IF_ERROR_RETURN 2504 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 7, 2505 0x0000, 0x0004)); 2506 /* Setting GPHY core, MII buffer register as well */ 2507 SOC_IF_ERROR_RETURN 2508 (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 2509 0x0000, 0x0004)); 2510 } 2511 break; 2512 2513 2514 case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT: 2515 /* Buffer limit modification is not allowed */ 2516 2517 case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME: 2518 case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME: 2519 case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME: 2520 case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME: 2521 case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME: 2522 case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME: 2523 case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME: 2524 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2525 rv = SOC_E_UNAVAIL; 2526 } 2527 2528 /* Time modification not allowed, IEEE EEE spec constants */ 2529 rv = SOC_E_UNAVAIL; 2530 break; 2531 2532 case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR: 2533 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2534 rv = SOC_E_UNAVAIL; 2535 } 2536 2537 if (value == 1) { 2538 /* Clearing the stats: Enable clear on Read */ 2539 SOC_IF_ERROR_RETURN 2540 (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 2541 0x1000, 0x1000)); 2542 2543 /* Read all the stats to clear */ 2544 SOC_IF_ERROR_RETURN 2545 (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data)); 2546 SOC_IF_ERROR_RETURN 2547 (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data)); 2548 SOC_IF_ERROR_RETURN 2549 (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data)); 2550 SOC_IF_ERROR_RETURN 2551 (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data)); 2552 SOC_IF_ERROR_RETURN 2553 (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data)); 2554 SOC_IF_ERROR_RETURN 2555 (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data)); 2556 SOC_IF_ERROR_RETURN 2557 (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data)); 2558 SOC_IF_ERROR_RETURN 2559 (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data)); 2560 2561 /* Disable Clear on Read */ 2562 SOC_IF_ERROR_RETURN 2563 (MODIFY_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, 2564 0x0000, 0x1000)); 2565 } 2566 break; 2567 2568 case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL: 2569 if (value) { 2570 int saved_autoneg, saved_speed; 2571 2572 saved_autoneg = pc->copper.autoneg_enable; 2573 SOC_IF_ERROR_RETURN 2574 (phy_54680_autoneg_set(unit, port, 0)); 2575 pc->copper.autoneg_enable = saved_autoneg; 2576 2577 saved_speed = pc->copper.force_speed; 2578 SOC_IF_ERROR_RETURN 2579 (phy_54680_speed_set(unit, port, 1000)); 2580 pc->copper.force_speed = saved_speed; 2581 2582 SOC_IF_ERROR_RETURN 2583 (MODIFY_PHY54680_MII_GB_CTRLr(unit, pc, (1U << 12 | 1U << 11), (1U << 12 | 1U << 11))); 2584 SOC_IF_ERROR_RETURN 2585 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, (1U << 15 | 1U << 10), (1U << 15 | 1U << 10))); 2586 } else { 2587 SOC_IF_ERROR_RETURN 2588 (MODIFY_PHY54680_MII_GB_CTRLr(unit, pc, 0, (1U << 12 | 1U << 11))); 2589 SOC_IF_ERROR_RETURN 2590 (MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0, (1U << 15 | 1U << 10))); 2591 SOC_IF_ERROR_RETURN 2592 (phy_54680_speed_set(unit, port, pc->copper.force_speed)); 2593 SOC_IF_ERROR_RETURN 2594 (phy_54680_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0)); 2595 } 2596 break; 2597 2598 default: 2599 rv = SOC_E_UNAVAIL; 2600 break; 2601 } 2602 return rv; 2603 } 2604 2605 /* 2606 * Function: 2607 * phy_54680_control_get 2608 * Purpose: 2609 * Get current control settign of the PHY. 2610 * Parameters: 2611 * unit - StrataSwitch unit #. 2612 * port - StrataSwitch port #. 2613 * type - Control to update 2614 * value - (OUT)Current setting for the control 2615 * Returns: 2616 * SOC_E_NONE 2617 */ 2618 STATIC int 2619 phy_54680_control_get(int unit, soc_port_t port, 2620 soc_phy_control_t type, uint32 *value) 2621 { 2622 int rv; 2623 phy_ctrl_t *pc; 2624 uint16 data; 2625 uint32 temp; 2626 soc_port_t primary; 2627 int offset; 2628 2629 PHY_CONTROL_TYPE_CHECK(type); 2630 2631 pc = EXT_PHY_SW_STATE(unit, port); 2632 rv = SOC_E_NONE; 2633 2634 switch(type) { 2635 case SOC_PHY_CONTROL_POWER: 2636 *value = pc->power_mode; 2637 break; 2638 2639 case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME: 2640 SOC_IF_ERROR_RETURN 2641 (READ_PHY54680_AUTO_POWER_DOWNr(unit,pc, &data)); 2642 2643 if (data & PHY_54680_AUTO_PWRDWN_SLEEP_MASK) { 2644 *value = PHY_54680_AUTO_PWRDWN_SLEEP_MAX; 2645 } else { 2646 *value = 2700; 2647 } 2648 break; 2649 2650 case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME: 2651 SOC_IF_ERROR_RETURN 2652 (READ_PHY54680_AUTO_POWER_DOWNr(unit,pc, &data)); 2653 2654 data &= PHY_54680_AUTO_PWRDWN_WAKEUP_MASK; 2655 *value = data * PHY_54680_AUTO_PWRDWN_WAKEUP_UNIT; 2656 break; 2657 2658 case SOC_PHY_CONTROL_PORT_PRIMARY: 2659 SOC_IF_ERROR_RETURN 2660 (soc_phyctrl_primary_get(unit, port, &primary)); 2661 *value = (uint32) primary; 2662 break; 2663 2664 case SOC_PHY_CONTROL_PORT_OFFSET: 2665 SOC_IF_ERROR_RETURN 2666 (soc_phyctrl_offset_get(unit, port, &offset)); 2667 *value = (uint32) offset; 2668 break; 2669 2670 case SOC_PHY_CONTROL_CLOCK_ENABLE: 2671 SOC_IF_ERROR_RETURN 2672 (soc_phyctrl_primary_get(unit, port, &primary)); 2673 SOC_IF_ERROR_RETURN 2674 (soc_phyctrl_offset_get(unit, port, &offset)); 2675 if (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data) == SOC_E_NONE) { 2676 if (( data & 0x8 ) || (( data & 0x7 ) != offset)) { 2677 *value = FALSE; 2678 } else { 2679 *value = TRUE; 2680 } 2681 } 2682 break; 2683 2684 case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE: 2685 SOC_IF_ERROR_RETURN 2686 (soc_phyctrl_primary_get(unit, port, &primary)); 2687 SOC_IF_ERROR_RETURN 2688 (soc_phyctrl_offset_get(unit, port, &offset)); 2689 if (phy_54680_toplvl_reg_read(unit, port, primary, 0x0, &data) == SOC_E_NONE) { 2690 if (( data & (0x8<<4) ) || (( data & (0x7<<4) ) != (offset<<4) )) { 2691 *value = FALSE; 2692 } else { 2693 *value = TRUE; 2694 } 2695 } 2696 break; 2697 2698 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 2699 /* Not supported for 10/100/1000BASE-T interfaces */ 2700 rv = SOC_E_UNAVAIL; 2701 break; 2702 2703 case SOC_PHY_CONTROL_EEE: 2704 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2705 rv = SOC_E_UNAVAIL; 2706 } 2707 *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 2708 !PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0; 2709 break; 2710 2711 case SOC_PHY_CONTROL_EEE_AUTO: 2712 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2713 rv = SOC_E_UNAVAIL; 2714 } 2715 if (PHY_IS_BCM53324(pc)) { 2716 rv = SOC_E_UNAVAIL; 2717 } 2718 *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 2719 PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0; 2720 break; 2721 2722 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 2723 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2724 rv = SOC_E_UNAVAIL; 2725 } 2726 SOC_IF_ERROR_RETURN 2727 (READ_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, &data)); 2728 *value = ((data & 0x0004) == 0); 2729 break; 2730 2731 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 2732 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2733 rv = SOC_E_UNAVAIL; 2734 } 2735 SOC_IF_ERROR_RETURN 2736 (READ_PHY54680_EXP_MII_BUF_CNTL_STAT1r(unit, pc, &data)); 2737 *value = ((data & 0x0700) >> 8); 2738 break; 2739 2740 case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS: 2741 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2742 rv = SOC_E_UNAVAIL; 2743 } 2744 if (PHY_IS_BCM53324(pc)) { 2745 /* Internal GPHY didn't support */ 2746 rv = SOC_E_UNAVAIL; 2747 return rv; 2748 } 2749 SOC_IF_ERROR_RETURN 2750 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */ 2751 SOC_IF_ERROR_RETURN 2752 (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data)); 2753 temp = data; 2754 SOC_IF_ERROR_RETURN 2755 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */ 2756 SOC_IF_ERROR_RETURN 2757 (READ_PHY54680_EXP_EEE_TX_EVENTSr(unit, pc, &data)); 2758 temp |= (data << 16); 2759 *value = temp; 2760 break; 2761 2762 case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION: 2763 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2764 rv = SOC_E_UNAVAIL; 2765 } 2766 if (PHY_IS_BCM53324(pc)) { 2767 /* Internal GPHY didn't support */ 2768 rv = SOC_E_UNAVAIL; 2769 return rv; 2770 } 2771 SOC_IF_ERROR_RETURN 2772 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */ 2773 SOC_IF_ERROR_RETURN 2774 (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data)); 2775 temp = data; 2776 SOC_IF_ERROR_RETURN 2777 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */ 2778 SOC_IF_ERROR_RETURN 2779 (READ_PHY54680_EXP_EEE_TX_DURATIONr(unit, pc, &data)); 2780 temp |= (data << 16); 2781 *value = temp; 2782 break; 2783 2784 case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS: 2785 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2786 rv = SOC_E_UNAVAIL; 2787 } 2788 SOC_IF_ERROR_RETURN 2789 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */ 2790 SOC_IF_ERROR_RETURN 2791 (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data)); 2792 temp = data; 2793 SOC_IF_ERROR_RETURN 2794 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */ 2795 SOC_IF_ERROR_RETURN 2796 (READ_PHY54680_EXP_EEE_RX_EVENTSr(unit, pc, &data)); 2797 temp |= (data << 16); 2798 *value = temp; 2799 break; 2800 2801 case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION: 2802 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 2803 rv = SOC_E_UNAVAIL; 2804 } 2805 SOC_IF_ERROR_RETURN 2806 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 0x0, 1U<<14)); /* exp af */ 2807 SOC_IF_ERROR_RETURN 2808 (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data)); 2809 temp = data; 2810 SOC_IF_ERROR_RETURN 2811 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FAF,0x15, 1U<<14, 1U<<14)); /* exp af */ 2812 SOC_IF_ERROR_RETURN 2813 (READ_PHY54680_EXP_EEE_RX_DURATIONr(unit, pc, &data)); 2814 temp |= (data << 16); 2815 *value = temp; 2816 break; 2817 2818 case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL: 2819 SOC_IF_ERROR_RETURN 2820 (READ_PHY54680_MII_AUX_CTRLr(unit, pc, &data)); 2821 *value = data & (1U<<15) ? 1 : 0; 2822 break; 2823 2824 default: 2825 rv = SOC_E_UNAVAIL; 2826 break; 2827 } 2828 return rv; 2829 } 2830 2831 /* 2832 * Function: 2833 * phy_54680_cable_diag 2834 * Purpose: 2835 * Run 546x cable diagnostics 2836 * Parameters: 2837 * unit - device number 2838 * port - port number 2839 * status - (OUT) cable diagnotic status structure 2840 * Returns: 2841 * SOC_E_XXX 2842 */ 2843 STATIC int 2844 phy_54680_cable_diag(int unit, soc_port_t port, 2845 soc_port_cable_diag_t *status) 2846 { 2847 int rv, rv2, i; 2848 phy_ctrl_t *pc; 2849 2850 extern int phy_5464_cable_diag_sw(int, soc_port_t , 2851 soc_port_cable_diag_t *); 2852 2853 pc = EXT_PHY_SW_STATE(unit, port); 2854 2855 if (status == NULL) { 2856 return SOC_E_PARAM; 2857 } 2858 2859 status->state = SOC_PORT_CABLE_STATE_OK; 2860 status->npairs = 4; 2861 status->fuzz_len = 0; 2862 for (i = 0; i < 4; i++) { 2863 status->pair_state[i] = SOC_PORT_CABLE_STATE_OK; 2864 } 2865 2866 MIIM_LOCK(unit); /* this locks out linkscan, essentially */ 2867 rv = phy_5464_cable_diag_sw(unit,port, status); 2868 MIIM_UNLOCK(unit); 2869 rv2 = 0; 2870 if (rv <= 0) { /* don't reset if > 0 -- link was up */ 2871 rv2 = _phy_54680_reset_setup(unit, port); 2872 if (SOC_SUCCESS(rv2)) { 2873 rv2 = phy_54680_medium_config_set(unit, port, SOC_PORT_MEDIUM_COPPER, &pc->copper); 2874 } 2875 } 2876 if (rv >= 0 && rv2 < 0) { 2877 return rv2; 2878 } 2879 return rv; 2880 } 2881 2882 /* 2883 * Function: 2884 * phy_54680_probe 2885 * Purpose: 2886 * Complement the generic phy probe routine to identify this phy when its 2887 * phy id0 and id1 is same as some other phy's. 2888 * Parameters: 2889 * unit - StrataSwitch unit #. 2890 * pc - phy ctrl descriptor. 2891 * Returns: 2892 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 2893 */ 2894 STATIC int 2895 phy_54680_probe(int unit, phy_ctrl_t *pc) 2896 { 2897 uint16 id0, id1; 2898 int rv = SOC_E_NOT_FOUND; 2899 2900 if (READ_PHY54680_MII_PHY_ID0r(unit, pc, &id0) < 0) { 2901 return rv; 2902 } 2903 if (READ_PHY54680_MII_PHY_ID1r(unit, pc, &id1) < 0) { 2904 return rv; 2905 } 2906 2907 switch (PHY_MODEL(id0, id1)) { 2908 2909 case PHY_BCM54680_MODEL: 2910 case PHY_BCM54880E_MODEL: 2911 case PHY_BCM53324_MODEL: 2912 rv = SOC_E_NONE; 2913 break; 2914 2915 case PHY_BCM54680E_MODEL: 2916 if (id1 & 0x8) { 2917 rv = SOC_E_NONE; 2918 } 2919 break; 2920 2921 case PHY_BCM52681E_MODEL: 2922 if (id1 & 0x8) { 2923 rv = SOC_E_NONE; 2924 } 2925 break; 2926 2927 default: 2928 break; 2929 2930 } 2931 pc->size = sizeof(PHY54680_DEV_DESC_t); 2932 2933 return rv; 2934 } 2935 2936 2937 STATIC int 2938 phy_54680_link_up(int unit, soc_port_t port) 2939 { 2940 phy_ctrl_t *pc; 2941 int speed; 2942 uint16 phy_auto, value; 2943 uint32 rev_b_cfg = 0; 2944 uint32 rev_a_cfg = 0; 2945 2946 2947 pc = EXT_PHY_SW_STATE(unit, port); 2948 2949 SOC_IF_ERROR_RETURN 2950 (phy_54680_speed_get(unit, port, &speed)); 2951 2952 if (speed == 100) { 2953 SOC_IF_ERROR_RETURN( 2954 READ_PHY_REG(unit, pc, 0x11, &value)); 2955 if(value & (1U << 13)) { 2956 SOC_IF_ERROR_RETURN 2957 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 0x0<<10, 0x3<<10)); /* exp reg f5 */ 2958 } else { 2959 SOC_IF_ERROR_RETURN 2960 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 0x1<<10, 0x3<<10)); /* exp reg f5 */ 2961 } 2962 } 2963 2964 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) { /*non EEE */ 2965 /* do nothing */ 2966 rev_a_cfg = rev_b_cfg = 0; 2967 } else 2968 if (PHY_IS_BCM53324(pc)) { 2969 /* Check if rev Bx configuration is required for integrated PHY */ 2970 if ((PHY_IS_BCM53324(pc) && pc->phy_rev == 0x0)) { 2971 rev_b_cfg = 1; 2972 } 2973 } else { 2974 if ((pc->phy_rev & 0x6) == 0x2) { 2975 rev_b_cfg = 1; 2976 } else if ((pc->phy_rev & 0x6) == 0x0) { 2977 rev_a_cfg = 1; 2978 } 2979 } 2980 if (rev_b_cfg) { 2981 /* revs B0 and B1 of supported PHYs */ 2982 sal_usleep(10000); 2983 SOC_IF_ERROR_RETURN( 2984 READ_PHY54680_AUTO_POWER_DOWNr(unit, pc, &phy_auto)); 2985 if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) { 2986 /* Disable PHY Auto Power-Down mode */ 2987 SOC_IF_ERROR_RETURN( 2988 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc, 2989 0, PHY_54680_AUTO_PWRDWN_EN)); 2990 } 2991 SOC_IF_ERROR_RETURN( 2992 MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, (1U << 11), (1U << 11))); 2993 SOC_IF_ERROR_RETURN( 2994 WRITE_PHY_REG(unit, pc, 0x17, 0x001a)); 2995 SOC_IF_ERROR_RETURN( 2996 WRITE_PHY_REG(unit, pc, 0x15, 0x0003)); 2997 SOC_IF_ERROR_RETURN( 2998 MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0, (1U << 11))); 2999 if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) { 3000 /* Enable PHY Auto Power-Down mode */ 3001 SOC_IF_ERROR_RETURN( 3002 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc, 3003 PHY_54680_AUTO_PWRDWN_EN, PHY_54680_AUTO_PWRDWN_EN)); 3004 } 3005 } 3006 if (rev_a_cfg) { 3007 /* revs A0 and A1 of supported PHYs */ 3008 uint32 eee_auto; 3009 3010 SOC_IF_ERROR_RETURN 3011 (phy_54680_control_get(unit, port, 3012 SOC_PHY_CONTROL_EEE_AUTO, &eee_auto)); 3013 if ((speed == 100) && (eee_auto == 1)) { 3014 SOC_IF_ERROR_RETURN( 3015 WRITE_PHY_REG(unit, pc, 0x17, 0x0d10)); 3016 SOC_IF_ERROR_RETURN( 3017 WRITE_PHY_REG(unit, pc, 0x15, 0x00ff)); 3018 3019 } else { 3020 SOC_IF_ERROR_RETURN( 3021 WRITE_PHY_REG(unit, pc, 0x17, 0x0d10)); 3022 SOC_IF_ERROR_RETURN( 3023 WRITE_PHY_REG(unit, pc, 0x15, 0x0000)); 3024 } 3025 } 3026 3027 /* Notify interface to internal PHY */ 3028 SOC_IF_ERROR_RETURN 3029 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII)); 3030 3031 /* Situation observed with Saber devices XGXS16g1l+BCM54640E 3032 Linkscan is not updating speed for internal phy xgxs16g1l. 3033 It was observed that when speed is set to 100M the int phy 3034 is still set to 1G and traffic does not flow through untill 3035 int phy speed is also update to 100M. This applies to other 3036 speeds as well. 3037 Explicitly send speed notify to int phy from ext phy. 3038 */ 3039 SOC_IF_ERROR_RETURN 3040 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed)); 3041 3042 3043 return SOC_E_NONE; 3044 } 3045 3046 STATIC int 3047 phy_54680_link_down(int unit, soc_port_t port) 3048 { 3049 phy_ctrl_t *pc; 3050 uint16 phy_auto; 3051 uint32 rev_b_cfg = 0; 3052 3053 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED)) { /*non EEE */ 3054 return SOC_E_NONE; 3055 } 3056 3057 pc = EXT_PHY_SW_STATE(unit, port); 3058 3059 if (PHY_IS_BCM53324(pc)) { 3060 /* Check if rev Bx configuration is required for integrated PHY */ 3061 if ((PHY_IS_BCM53324(pc) && pc->phy_rev == 0x0)) { 3062 rev_b_cfg = 1; 3063 } 3064 } else { 3065 if ((pc->phy_rev & 0x6) == 0x2) { 3066 rev_b_cfg = 1; 3067 } 3068 } 3069 3070 if (rev_b_cfg) { 3071 /* revs B0 and B1 of supported PHYs */ 3072 SOC_IF_ERROR_RETURN( 3073 READ_PHY54680_AUTO_POWER_DOWNr(unit, pc, &phy_auto)); 3074 if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) { 3075 /* Disable PHY Auto Power-Down mode */ 3076 SOC_IF_ERROR_RETURN( 3077 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc, 3078 0, PHY_54680_AUTO_PWRDWN_EN)); 3079 } 3080 SOC_IF_ERROR_RETURN( 3081 MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, (1U << 11), (1U << 11))); 3082 SOC_IF_ERROR_RETURN( 3083 WRITE_PHY_REG(unit, pc, 0x17, 0x001a)); 3084 SOC_IF_ERROR_RETURN( 3085 WRITE_PHY_REG(unit, pc, 0x15, 0x0007)); 3086 SOC_IF_ERROR_RETURN( 3087 MODIFY_PHY54680_MII_AUX_CTRLr(unit, pc, 0, (1U << 11))); 3088 if ((phy_auto & PHY_54680_AUTO_PWRDWN_EN) != 0) { 3089 /* Enable PHY Auto Power-Down mode */ 3090 SOC_IF_ERROR_RETURN( 3091 MODIFY_PHY54680_AUTO_POWER_DOWNr(unit, pc, 3092 PHY_54680_AUTO_PWRDWN_EN, PHY_54680_AUTO_PWRDWN_EN)); 3093 } 3094 } 3095 3096 return SOC_E_NONE; 3097 } 3098 3099 STATIC int 3100 phy54680_cable_diag_dispatch(int unit, soc_port_t port, 3101 soc_port_cable_diag_t *status) 3102 { 3103 phy_ctrl_t *pc; 3104 3105 pc = EXT_PHY_SW_STATE(unit, port); 3106 3107 if (ECD_ENABLE && ((((PHY_IS_BCM54880E(pc)) || (PHY_IS_BCM54680E(pc))) && ((pc->phy_rev & 0x7) > 0x2)) || 3108 ((PHY_IS_BCM54680(pc)) && ((pc->phy_rev & 0xf) > 0x1)))) { 3109 SOC_IF_ERROR_RETURN( 3110 phy_ecd_cable_diag(unit, port, status)); 3111 SOC_IF_ERROR_RETURN( 3112 _phy_54680_reset_setup(unit, port)); 3113 } else { 3114 SOC_IF_ERROR_RETURN( 3115 phy_54680_cable_diag(unit, port, status)); 3116 } 3117 3118 return SOC_E_NONE; 3119 } 3120 3121 void _phy_54680e_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode, 3122 int offset, uint16 *value) 3123 { 3124 3125 switch (mode) { 3126 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE: 3127 *value |= (0x0 << offset); 3128 break; 3129 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD: 3130 *value |= (0x1 << offset); 3131 break; 3132 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN: 3133 *value |= (0x2 << offset); 3134 break; 3135 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP: 3136 *value |= (0x3 << offset); 3137 break; 3138 default: 3139 break; 3140 } 3141 3142 } 3143 3144 void _phy_54680e_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode, 3145 int offset, uint16 *value) 3146 { 3147 3148 switch (mode) { 3149 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE: 3150 *value |= (0x0 << offset); 3151 break; 3152 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD: 3153 *value |= (0x1 << offset); 3154 break; 3155 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP: 3156 *value |= (0x2 << offset); 3157 break; 3158 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME: 3159 *value |= (0x3 << offset); 3160 break; 3161 default: 3162 break; 3163 } 3164 3165 } 3166 3167 void _phy_54680e_decode_egress_message_mode(uint16 value, int offset, 3168 soc_port_phy_timesync_event_message_egress_mode_t *mode) 3169 { 3170 3171 switch ((value >> offset) & 0x3) { 3172 case 0x0: 3173 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE; 3174 break; 3175 case 0x1: 3176 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD; 3177 break; 3178 case 0x2: 3179 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN; 3180 break; 3181 case 0x3: 3182 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP; 3183 break; 3184 } 3185 3186 } 3187 3188 void _phy_54680e_decode_ingress_message_mode(uint16 value, int offset, 3189 soc_port_phy_timesync_event_message_ingress_mode_t *mode) 3190 { 3191 3192 switch ((value >> offset) & 0x3) { 3193 case 0x0: 3194 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE; 3195 break; 3196 case 0x1: 3197 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD; 3198 break; 3199 case 0x2: 3200 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP; 3201 break; 3202 case 0x3: 3203 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME; 3204 break; 3205 } 3206 3207 } 3208 3209 void _phy_54680e_encode_gmode(soc_port_phy_timesync_global_mode_t mode, 3210 uint16 *value) 3211 { 3212 3213 switch (mode) { 3214 case SOC_PORT_PHY_TIMESYNC_MODE_FREE: 3215 *value = 0x1; 3216 break; 3217 case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN: 3218 *value = 0x2; 3219 break; 3220 case SOC_PORT_PHY_TIMESYNC_MODE_CPU: 3221 *value = 0x3; 3222 break; 3223 default: 3224 break; 3225 } 3226 3227 } 3228 3229 void _phy_54680e_decode_gmode(uint16 value, 3230 soc_port_phy_timesync_global_mode_t *mode) 3231 { 3232 3233 switch (value & 0x3) { 3234 case 0x1: 3235 *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 3236 break; 3237 case 0x2: 3238 *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN; 3239 break; 3240 case 0x3: 3241 *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU; 3242 break; 3243 default: 3244 break; 3245 } 3246 3247 } 3248 3249 void _phy_54680e_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode, 3250 uint16 *value) 3251 { 3252 3253 switch (mode) { 3254 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0: 3255 *value = 1U << 0; 3256 break; 3257 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1: 3258 *value = 1U << 1; 3259 break; 3260 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT: 3261 *value = 1U << 2; 3262 break; 3263 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU: 3264 *value = 1U << 3; 3265 break; 3266 default: 3267 break; 3268 } 3269 3270 } 3271 3272 void _phy_54680e_decode_framesync_mode(uint16 value, 3273 soc_port_phy_timesync_framesync_mode_t *mode) 3274 { 3275 3276 switch (value & 0xf) { 3277 case 1U << 0: 3278 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0; 3279 break; 3280 case 1U << 1: 3281 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1; 3282 break; 3283 case 1U << 2: 3284 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT; 3285 break; 3286 case 1U << 3: 3287 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU; 3288 break; 3289 default: 3290 break; 3291 } 3292 3293 } 3294 3295 void _phy_54680e_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode, 3296 uint16 *value) 3297 { 3298 3299 switch (mode) { 3300 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE: 3301 *value = 0x0; 3302 break; 3303 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME: 3304 *value = 0x1; 3305 break; 3306 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN: 3307 *value = 0x2; 3308 break; 3309 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC: 3310 *value = 0x3; 3311 break; 3312 default: 3313 break; 3314 } 3315 3316 } 3317 3318 void _phy_54680e_decode_syncout_mode(uint16 value, 3319 soc_port_phy_timesync_syncout_mode_t *mode) 3320 { 3321 3322 switch (value & 0x3) { 3323 case 0x0: 3324 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 3325 break; 3326 case 0x1: 3327 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME; 3328 break; 3329 case 0x2: 3330 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN; 3331 break; 3332 case 0x3: 3333 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC; 3334 break; 3335 } 3336 3337 } 3338 3339 3340 STATIC int 3341 phy_54680_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf) 3342 { 3343 phy_ctrl_t *pc; 3344 int offset, rv = SOC_E_NONE; 3345 uint16 rx_control_reg = 0, tx_control_reg = 0, rx_crc_control_reg = 0, 3346 en_control_reg = 0, tx_capture_en_reg = 0, rx_capture_en_reg = 0, 3347 nse_nco_6 = 0, nse_nco_2c = 0, value, mask, 3348 gmode = 0, framesync_mode = 0, syncout_mode = 0, 3349 pulse_1_length, pulse_2_length, length_threshold, event_offset; 3350 uint32 interval; 3351 3352 pc = EXT_PHY_SW_STATE(unit, port); 3353 3354 if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) { 3355 return SOC_E_UNAVAIL; 3356 } 3357 3358 offset = PHY54680_DEV_PHY_SLICE(pc); 3359 3360 do { 3361 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 3362 3363 if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) { 3364 en_control_reg |= ((1U << (offset + 8)) | (1U << offset)); 3365 nse_nco_6 |= (1U << 12); /* NSE init */ 3366 SOC_IF_ERROR_BREAK 3367 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 1U<<0, 1U<<0), rv); /* exp reg f5 */ 3368 } else { 3369 SOC_IF_ERROR_BREAK 3370 (PHY54680_REG_MODIFY(unit, pc, 0x00, 0x0FF5,0x15, 0, 1U<<0), rv); /* exp reg f5 */ 3371 } 3372 3373 /* pc->phy_id = PHY54680_SLICE_ADDR(pc, 0); */ 3374 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 3375 3376 SOC_IF_ERROR_BREAK 3377 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x10, en_control_reg, 3378 ((1U << (offset + 8)) | (1U << offset))), rv); 3379 3380 SOC_IF_ERROR_BREAK 3381 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x10, &en_control_reg), rv); 3382 3383 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) { 3384 tx_capture_en_reg |= (1U << offset); 3385 rx_capture_en_reg |= (1U << (offset + 8)); 3386 } 3387 3388 SOC_IF_ERROR_BREAK 3389 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x12, tx_capture_en_reg, 3390 (1U << offset)), rv); 3391 3392 SOC_IF_ERROR_BREAK 3393 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x13, rx_capture_en_reg, 3394 (1U << (offset + 8))), rv); 3395 3396 if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) { 3397 nse_nco_6 |= (1U << 13); 3398 } 3399 3400 SOC_IF_ERROR_BREAK 3401 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x4f, nse_nco_6, 3402 (1U << 13)), rv); 3403 3404 if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) { 3405 rx_crc_control_reg |= (1U << 3); 3406 } 3407 3408 SOC_IF_ERROR_BREAK 3409 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x34, rx_crc_control_reg), rv); 3410 3411 if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) { 3412 rx_control_reg |= (1U << 3); 3413 tx_control_reg |= (1U << 3); 3414 } 3415 3416 if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) { 3417 rx_control_reg |= (1U << 2); 3418 tx_control_reg |= (1U << 2); 3419 } 3420 3421 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) { 3422 rx_control_reg |= (1U << 1); 3423 tx_control_reg |= (1U << 1); 3424 } 3425 3426 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) { 3427 rx_control_reg |= (1U << 0); 3428 tx_control_reg |= (1U << 0); 3429 } 3430 3431 SOC_IF_ERROR_BREAK 3432 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x32, tx_control_reg), rv); 3433 3434 SOC_IF_ERROR_BREAK 3435 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x33, rx_control_reg), rv); 3436 3437 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 3438 nse_nco_2c &= (uint16) ~(1U << 14); 3439 } else { 3440 nse_nco_2c |= (1U << 14); 3441 } 3442 3443 SOC_IF_ERROR_BREAK 3444 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x47, nse_nco_2c, 3445 (1U << 14)), rv); 3446 } 3447 3448 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 3449 /* VLAN TAG register */ 3450 SOC_IF_ERROR_BREAK 3451 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x35, conf->itpid), rv); 3452 } 3453 3454 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 3455 /* OUTER VLAN TAG register */ 3456 SOC_IF_ERROR_BREAK 3457 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x36, conf->otpid), rv); 3458 } 3459 3460 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 3461 /* INNER VLAN TAG register */ 3462 SOC_IF_ERROR_BREAK 3463 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x52, conf->otpid2), rv); 3464 } 3465 3466 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 3467 SOC_IF_ERROR_BREAK 3468 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4b, conf->ts_divider & 0xfff), rv); 3469 } 3470 3471 3472 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 3473 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 3474 SOC_IF_ERROR_BREAK 3475 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x6f, conf->rx_link_delay & 0xffff), rv); 3476 SOC_IF_ERROR_BREAK 3477 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x70, (conf->rx_link_delay >> 16) & 0xffff), rv); 3478 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 3479 } 3480 3481 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 3482 SOC_IF_ERROR_BREAK 3483 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x25, (uint16)(conf->original_timecode.nanoseconds & 0xffff)), rv); 3484 3485 SOC_IF_ERROR_BREAK 3486 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x26, (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff)), rv); 3487 3488 SOC_IF_ERROR_BREAK 3489 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x27, (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff)), rv); 3490 3491 SOC_IF_ERROR_BREAK 3492 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x28, (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff)), rv); 3493 3494 SOC_IF_ERROR_BREAK 3495 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x29, (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff)), rv); 3496 3497 } 3498 mask = 0; 3499 3500 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 3501 _phy_54680e_encode_gmode(conf->gmode,&gmode); 3502 mask |= (0x3 << 14); 3503 } 3504 3505 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 3506 _phy_54680e_encode_framesync_mode(conf->framesync.mode, &framesync_mode); 3507 mask |= (0xf << 2) | (0x1 << 11); 3508 3509 /* Divide by 8 */ 3510 length_threshold = conf->framesync.length_threshold >> 3; 3511 event_offset = conf->framesync.event_offset >> 3; 3512 3513 SOC_IF_ERROR_BREAK 3514 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x51, length_threshold), rv); 3515 SOC_IF_ERROR_BREAK 3516 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x50, event_offset), rv); 3517 } 3518 3519 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 3520 _phy_54680e_encode_syncout_mode(conf->syncout.mode, &syncout_mode); 3521 mask |= (0x3 << 0); 3522 3523 /* Divide by 8 */ 3524 interval = conf->syncout.interval >> 3; 3525 pulse_1_length = conf->syncout.pulse_1_length >> 3; 3526 pulse_2_length = conf->syncout.pulse_2_length >> 3; 3527 3528 SOC_IF_ERROR_BREAK 3529 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x48, interval & 0xffff), rv); 3530 SOC_IF_ERROR_BREAK 3531 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x49, 3532 ((pulse_2_length & 0x3) << 14) | ((interval >> 16) & 0x3fff)), rv); 3533 SOC_IF_ERROR_BREAK 3534 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4a, 3535 ((pulse_1_length & 0x1ff) << 7) | ((pulse_2_length >> 2) & 0x7f)), rv); 3536 3537 SOC_IF_ERROR_BREAK 3538 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4e, 3539 (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xffff)), rv); 3540 SOC_IF_ERROR_BREAK 3541 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4d, 3542 (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff)), rv); 3543 SOC_IF_ERROR_BREAK 3544 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4c, 3545 (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff)), rv); 3546 } 3547 3548 SOC_IF_ERROR_BREAK 3549 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x4f, (gmode << 14) | 3550 ((framesync_mode & 0x2) ? (1U << 11) : (1U << 6)) | /* if bits 1 or 2 are set, turn off syncout */ 3551 (framesync_mode << 2) | (syncout_mode << 0), mask), rv); 3552 3553 /* tx_timestamp_offset */ 3554 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 3555 SOC_IF_ERROR_BREAK 3556 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x15 + offset, (uint16)(conf->tx_timestamp_offset & 0xffff)), rv); 3557 3558 if (offset < 4 ) { 3559 SOC_IF_ERROR_BREAK 3560 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x63, 3561 ((conf->tx_timestamp_offset & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv); 3562 } else { 3563 uint16 offset1 = offset - 4; 3564 SOC_IF_ERROR_BREAK 3565 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x64, 3566 ((conf->tx_timestamp_offset & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv); 3567 } 3568 } 3569 3570 /* rx_timestamp_offset */ 3571 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 3572 SOC_IF_ERROR_BREAK 3573 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x1d + offset, (uint16)(conf->rx_timestamp_offset & 0xffff)), rv); 3574 3575 if (offset < 4 ) { 3576 SOC_IF_ERROR_BREAK 3577 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x65, 3578 ((conf->rx_timestamp_offset & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv); 3579 } else { 3580 uint16 offset1 = offset - 4; 3581 SOC_IF_ERROR_BREAK 3582 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x66, 3583 ((conf->rx_timestamp_offset & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv); 3584 } 3585 } 3586 3587 value = 0; 3588 mask = 0; 3589 3590 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 3591 _phy_54680e_encode_egress_message_mode(conf->tx_sync_mode, 0, &value); 3592 mask |= 0x3 << 0; 3593 } 3594 3595 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 3596 _phy_54680e_encode_egress_message_mode(conf->tx_delay_request_mode, 2, &value); 3597 mask |= 0x3 << 2; 3598 } 3599 3600 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 3601 _phy_54680e_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4, &value); 3602 mask |= 0x3 << 4; 3603 } 3604 3605 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 3606 _phy_54680e_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6, &value); 3607 mask |= 0x3 << 6; 3608 } 3609 3610 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 3611 3612 SOC_IF_ERROR_BREAK 3613 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x11, value, mask), rv); 3614 3615 value = 0; 3616 mask = 0; 3617 3618 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 3619 _phy_54680e_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value); 3620 mask |= 0x3 << 0; 3621 } 3622 3623 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 3624 _phy_54680e_encode_ingress_message_mode(conf->rx_delay_request_mode, 2, &value); 3625 mask |= 0x3 << 2; 3626 } 3627 3628 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 3629 _phy_54680e_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4, &value); 3630 mask |= 0x3 << 4; 3631 } 3632 3633 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 3634 _phy_54680e_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6, &value); 3635 mask |= 0x3 << 6; 3636 } 3637 3638 3639 SOC_IF_ERROR_BREAK 3640 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x12, value << 8, mask << 8), rv); 3641 3642 /* pc->phy_id = PHY54680_SLICE_ADDR(pc, 0); */ 3643 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 3644 3645 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 3646 /* Initial ref phase [15:0] */ 3647 SOC_IF_ERROR_BREAK 3648 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x38, (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff)), rv); 3649 3650 /* Initial ref phase [31:16] */ 3651 SOC_IF_ERROR_BREAK 3652 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x39, (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff)), rv); 3653 3654 /* Initial ref phase [47:32] */ 3655 SOC_IF_ERROR_BREAK 3656 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3a, (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff)), rv); 3657 } 3658 3659 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 3660 /* Ref phase delta [15:0] */ 3661 SOC_IF_ERROR_BREAK 3662 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3b, (uint16)(conf->phy_1588_dpll_ref_phase_delta & 0xffff)), rv); 3663 3664 /* Ref phase delta [31:16] */ 3665 SOC_IF_ERROR_BREAK 3666 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3c, (uint16)((conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff)), rv); 3667 } 3668 3669 /* DPLL K1 & K2 */ 3670 mask = 0; 3671 3672 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 3673 mask |= 0xff << 8; 3674 } 3675 3676 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 3677 mask |= 0xff; 3678 } 3679 SOC_IF_ERROR_BREAK 3680 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x3d, (conf->phy_1588_dpll_k1 & 0xff)<<8 | (conf->phy_1588_dpll_k2 & 0xff), mask ), rv); 3681 3682 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 3683 /* DPLL K3 */ 3684 SOC_IF_ERROR_BREAK 3685 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3e, conf->phy_1588_dpll_k3 & 0xff), rv); 3686 } 3687 3688 3689 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER) { 3690 /* Initial loop filter[15:0] */ 3691 SOC_IF_ERROR_BREAK 3692 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x3f, (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) & 0xffff)), rv); 3693 3694 /* Initial loop filter[31:16] */ 3695 SOC_IF_ERROR_BREAK 3696 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x40, (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff)), rv); 3697 3698 /* Initial loop filter[47:32] */ 3699 SOC_IF_ERROR_BREAK 3700 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x41, (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) & 0xffff)), rv); 3701 3702 /* Initial loop filter[63:48] */ 3703 SOC_IF_ERROR_BREAK 3704 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x42, (uint16)((COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff)), rv); 3705 } 3706 3707 } while(0); 3708 3709 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 3710 3711 return SOC_E_NONE; 3712 } 3713 3714 STATIC int 3715 phy_54680_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf) 3716 { 3717 phy_ctrl_t *pc; 3718 int offset, rv = SOC_E_NONE; 3719 uint16 tx_control_reg = 0, rx_crc_control_reg = 0, 3720 en_control_reg = 0, tx_capture_en_reg = 0, 3721 nse_nco_6 = 0, nse_nco_2c = 0, temp1, temp2, temp3, temp4, value; 3722 soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 3723 soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE; 3724 soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 3725 3726 pc = EXT_PHY_SW_STATE(unit, port); 3727 3728 if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) { 3729 return SOC_E_UNAVAIL; 3730 } 3731 3732 conf->flags = 0; 3733 3734 offset = PHY54680_DEV_PHY_SLICE(pc); 3735 3736 do { 3737 /* pc->phy_id = PHY54680_SLICE_ADDR(pc, 0); */ 3738 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 3739 3740 SOC_IF_ERROR_BREAK 3741 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4f, &nse_nco_6), rv); 3742 3743 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 3744 SOC_IF_ERROR_BREAK 3745 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x10, &en_control_reg), rv); 3746 3747 if (en_control_reg & (1U << offset)) { 3748 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE; 3749 } 3750 3751 SOC_IF_ERROR_BREAK 3752 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x12, &tx_capture_en_reg), rv); 3753 3754 if (tx_capture_en_reg & (1U << offset)) { 3755 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 3756 } 3757 3758 /* 3759 SOC_IF_ERROR_BREAK 3760 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4f, &nse_nco_6), rv); 3761 */ 3762 3763 if (nse_nco_6 & (1U << 13)) { 3764 conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE; 3765 } 3766 3767 SOC_IF_ERROR_BREAK 3768 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x34, &rx_crc_control_reg), rv); 3769 3770 if (rx_crc_control_reg & (1U << 3)) { 3771 conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE; 3772 } 3773 3774 SOC_IF_ERROR_BREAK 3775 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x32, &tx_control_reg), rv); 3776 3777 if (tx_control_reg & (1U << 3)) { 3778 conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE; 3779 } 3780 3781 if (tx_control_reg & (1U << 2)) { 3782 conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE; 3783 } 3784 3785 if (tx_control_reg & (1U << 1)) { 3786 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE; 3787 } 3788 3789 if (tx_control_reg & (1U << 0)) { 3790 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE; 3791 } 3792 3793 SOC_IF_ERROR_BREAK 3794 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x47, &nse_nco_2c), rv); 3795 3796 if (!(nse_nco_2c & (1U << 14))) { 3797 conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 3798 } 3799 } 3800 3801 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 3802 _phy_54680e_decode_gmode((nse_nco_6 >> 14),&gmode); 3803 conf->gmode = gmode; 3804 } 3805 3806 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 3807 _phy_54680e_decode_framesync_mode((nse_nco_6 >> 2), &framesync_mode); 3808 conf->framesync.mode = framesync_mode; 3809 SOC_IF_ERROR_BREAK 3810 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x51, &temp1), rv); 3811 SOC_IF_ERROR_BREAK 3812 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x50, &temp2), rv); 3813 3814 /* Multiply by 8 */ 3815 conf->framesync.length_threshold = temp1 << 3; 3816 conf->framesync.event_offset = temp2 << 3; 3817 } 3818 3819 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 3820 _phy_54680e_decode_syncout_mode((nse_nco_6 >> 0), &syncout_mode); 3821 conf->syncout.mode = syncout_mode; 3822 3823 SOC_IF_ERROR_BREAK 3824 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x48, &temp1), rv); 3825 SOC_IF_ERROR_BREAK 3826 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x49, &temp2), rv); 3827 SOC_IF_ERROR_BREAK 3828 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4a, &temp3), rv); 3829 3830 /* Multiply by 8 */ 3831 conf->syncout.pulse_1_length = ((temp3 >> 7) & 0x1ff) << 3; 3832 conf->syncout.pulse_2_length = (((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3)) << 3; 3833 conf->syncout.interval = (((temp2 & 0x3fff) << 16) | temp1) << 3; 3834 3835 SOC_IF_ERROR_BREAK 3836 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4e, &temp1), rv); 3837 SOC_IF_ERROR_BREAK 3838 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4d, &temp2), rv); 3839 SOC_IF_ERROR_BREAK 3840 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4c, &temp3), rv); 3841 3842 COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 3843 } 3844 3845 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 3846 SOC_IF_ERROR_BREAK 3847 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x35, &conf->itpid), rv); 3848 } 3849 3850 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 3851 SOC_IF_ERROR_BREAK 3852 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x36, &conf->otpid), rv); 3853 } 3854 3855 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 3856 SOC_IF_ERROR_BREAK 3857 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x52, &conf->otpid2), rv); 3858 } 3859 3860 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 3861 SOC_IF_ERROR_BREAK 3862 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4b, &conf->ts_divider), rv); 3863 } 3864 3865 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 3866 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 3867 3868 SOC_IF_ERROR_BREAK 3869 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x6f, &temp1), rv); 3870 SOC_IF_ERROR_BREAK 3871 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x70, &temp2), rv); 3872 3873 conf->rx_link_delay = ((uint32)temp2 << 16) | temp1; 3874 3875 /* pc->phy_id = PHY54680_SLICE_ADDR(pc, 0); */ 3876 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 3877 } 3878 3879 3880 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 3881 SOC_IF_ERROR_BREAK 3882 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x25, &temp1), rv); 3883 3884 SOC_IF_ERROR_BREAK 3885 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x26, &temp2), rv); 3886 3887 conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1; 3888 3889 SOC_IF_ERROR_BREAK 3890 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x27, &temp1), rv); 3891 3892 SOC_IF_ERROR_BREAK 3893 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x28, &temp2), rv); 3894 3895 SOC_IF_ERROR_BREAK 3896 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x29, &temp3), rv); 3897 3898 /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((uint32)temp2 << 16) | temp1; */ 3899 3900 COMPILER_64_SET(conf->original_timecode.seconds, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 3901 } 3902 3903 /* tx_timestamp_offset */ 3904 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 3905 uint32 temp32; 3906 3907 SOC_IF_ERROR_BREAK 3908 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x15 + offset, &temp1), rv); 3909 if (offset < 4 ) { 3910 SOC_IF_ERROR_BREAK 3911 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x63, &temp2), rv); 3912 temp32 = (temp2 & (0xf << (offset << 2))) << ((4 - offset) << 2); 3913 } else { 3914 uint16 offset1 = offset - 4; 3915 SOC_IF_ERROR_BREAK 3916 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x64, &temp2), rv); 3917 temp32 = (temp2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2); 3918 } 3919 conf->tx_timestamp_offset = temp32 | temp1; 3920 } 3921 3922 /* rx_timestamp_offset */ 3923 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 3924 uint32 temp32; 3925 3926 SOC_IF_ERROR_BREAK 3927 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x1d + offset, &temp1), rv); 3928 if (offset < 4 ) { 3929 SOC_IF_ERROR_BREAK 3930 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x65, &temp2), rv); 3931 temp32 = (temp2 & (0xf << (offset << 2))) << ((4 - offset) << 2); 3932 } else { 3933 uint16 offset1 = offset - 4; 3934 SOC_IF_ERROR_BREAK 3935 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x66, &temp2), rv); 3936 temp32 = (temp2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2); 3937 } 3938 conf->rx_timestamp_offset = temp32 | temp1; 3939 } 3940 3941 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 3942 3943 SOC_IF_ERROR_BREAK 3944 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x11, &value), rv); 3945 3946 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 3947 _phy_54680e_decode_egress_message_mode(value, 0, &conf->tx_sync_mode); 3948 } 3949 3950 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 3951 _phy_54680e_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode); 3952 } 3953 3954 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 3955 _phy_54680e_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode); 3956 } 3957 3958 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 3959 _phy_54680e_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode); 3960 } 3961 3962 SOC_IF_ERROR_BREAK 3963 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x12, &value), rv); 3964 3965 value >>= 8; 3966 3967 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 3968 _phy_54680e_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode); 3969 } 3970 3971 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 3972 _phy_54680e_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode); 3973 } 3974 3975 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 3976 _phy_54680e_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode); 3977 } 3978 3979 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 3980 _phy_54680e_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode); 3981 } 3982 3983 /* pc->phy_id = PHY54680_SLICE_ADDR(pc, 0); */ 3984 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 3985 3986 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 3987 /* Initial ref phase [15:0] */ 3988 SOC_IF_ERROR_BREAK 3989 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x38, &temp1), rv); 3990 3991 /* Initial ref phase [31:16] */ 3992 SOC_IF_ERROR_BREAK 3993 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x39, &temp2), rv); 3994 3995 /* Initial ref phase [47:32] */ 3996 SOC_IF_ERROR_BREAK 3997 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3a, &temp3), rv); 3998 3999 COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 4000 } 4001 4002 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 4003 /* Ref phase delta [15:0] */ 4004 SOC_IF_ERROR_BREAK 4005 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3b, &temp1), rv); 4006 4007 /* Ref phase delta [31:16] */ 4008 SOC_IF_ERROR_BREAK 4009 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3c, &temp2), rv); 4010 4011 conf->phy_1588_dpll_ref_phase_delta = (temp2 << 16) | temp1; 4012 } 4013 4014 /* DPLL K1 & K2 */ 4015 SOC_IF_ERROR_BREAK 4016 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3d, &temp1 ), rv); 4017 4018 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 4019 conf->phy_1588_dpll_k1 = (temp1 >> 8 ) & 0xff; 4020 } 4021 4022 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 4023 conf->phy_1588_dpll_k2 = temp1 & 0xff; 4024 } 4025 4026 /* DPLL K3 */ 4027 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 4028 SOC_IF_ERROR_BREAK 4029 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3e, &temp1), rv); 4030 conf->phy_1588_dpll_k3 = temp1 & 0xff; 4031 } 4032 4033 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER) { 4034 /* Initial loop filter[15:0] */ 4035 SOC_IF_ERROR_BREAK 4036 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x3f, &temp1), rv); 4037 4038 /* Initial loop filter[31:16] */ 4039 SOC_IF_ERROR_BREAK 4040 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x40, &temp2), rv); 4041 4042 /* Initial loop filter[47:32] */ 4043 SOC_IF_ERROR_BREAK 4044 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x41, &temp3), rv); 4045 4046 /* Initial loop filter[63:48] */ 4047 SOC_IF_ERROR_BREAK 4048 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x42, &temp4), rv); 4049 4050 COMPILER_64_SET(conf->phy_1588_dpll_loop_filter, (((uint32)temp4<<16)|((uint32)temp3)), (((uint32)temp2<<16)|((uint32)temp1))); 4051 } 4052 } while(0); 4053 4054 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 4055 4056 return SOC_E_NONE; 4057 } 4058 4059 STATIC int 4060 phy_54680_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 value) 4061 { 4062 phy_ctrl_t *pc; 4063 uint16 temp1, temp2; 4064 uint32 value0; 4065 int offset, rv = SOC_E_NONE; 4066 4067 pc = EXT_PHY_SW_STATE(unit, port); 4068 4069 if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) { 4070 return SOC_E_UNAVAIL; 4071 } 4072 4073 offset = PHY54680_DEV_PHY_SLICE(pc); 4074 4075 do { 4076 /* pc->phy_id = PHY54680_SLICE_ADDR(pc, 0); */ 4077 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 4078 4079 switch (type) { 4080 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 4081 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 4082 return SOC_E_FAIL; 4083 4084 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 4085 SOC_IF_ERROR_BREAK 4086 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x44, (uint16)COMPILER_64_LO(value)), rv); 4087 break; 4088 4089 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 4090 SOC_IF_ERROR_BREAK 4091 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x4f, &temp1), rv); 4092 temp2 = ((temp1 | (0x3 << 14) | (0x1 << 12)) & ~(0xf << 2)) | (0x1 << 5); 4093 SOC_IF_ERROR_BREAK 4094 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4f, temp2), rv); 4095 sal_udelay(1); 4096 temp2 &= ~((0x1 << 5) | (0x1 << 12)); 4097 SOC_IF_ERROR_BREAK 4098 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4f, temp2), rv); 4099 sal_udelay(1); 4100 SOC_IF_ERROR_BREAK 4101 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x4f, temp1), rv); 4102 4103 break; 4104 4105 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 4106 COMPILER_64_SHR(value, 4); 4107 SOC_IF_ERROR_BREAK 4108 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x45, (uint16)(COMPILER_64_LO(value) & 0xffff)), rv); 4109 SOC_IF_ERROR_BREAK 4110 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x46, (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff)), rv); 4111 SOC_IF_ERROR_BREAK 4112 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x47, (uint16)(COMPILER_64_HI(value) & 0xfff), 0xfff), rv); 4113 break; 4114 4115 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 4116 temp1 = 0; 4117 temp2 = 0; 4118 4119 value0 = COMPILER_64_LO(value); 4120 4121 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_LOAD) { 4122 temp1 |= 1U << 11; 4123 } 4124 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) { 4125 temp2 |= 1U << 11; 4126 } 4127 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) { 4128 temp1 |= 1U << 10; 4129 } 4130 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) { 4131 temp2 |= 1U << 10; 4132 } 4133 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) { 4134 temp1 |= 1U << 9; 4135 } 4136 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) { 4137 temp2 |= 1U << 9; 4138 } 4139 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) { 4140 temp1 |= 1U << 8; 4141 } 4142 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) { 4143 temp2 |= 1U << 8; 4144 } 4145 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) { 4146 temp1 |= 1U << 7; 4147 } 4148 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) { 4149 temp2 |= 1U << 7; 4150 } 4151 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) { 4152 temp1 |= 1U << 6; 4153 } 4154 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) { 4155 temp2 |= 1U << 6; 4156 } 4157 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) { 4158 temp1 |= 1U << 5; 4159 } 4160 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) { 4161 temp2 |= 1U << 5; 4162 } 4163 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) { 4164 temp1 |= 1U << 4; 4165 } 4166 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) { 4167 temp2 |= 1U << 4; 4168 } 4169 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) { 4170 temp1 |= 1U << 3; 4171 } 4172 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) { 4173 temp2 |= 1U << 3; 4174 } 4175 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) { 4176 temp1 |= 1U << 2; 4177 } 4178 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) { 4179 temp2 |= 1U << 2; 4180 } 4181 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) { 4182 temp1 |= 1U << 1; 4183 } 4184 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) { 4185 temp2 |= 1U << 1; 4186 } 4187 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) { 4188 temp1 |= 1U << 0; 4189 } 4190 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) { 4191 temp2 |= 1U << 0; 4192 } 4193 SOC_IF_ERROR_BREAK 4194 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x2e, temp1), rv); 4195 SOC_IF_ERROR_BREAK 4196 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x2f, temp2), rv); 4197 break; 4198 4199 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 4200 temp1 = 0; 4201 4202 value0 = COMPILER_64_LO(value); 4203 4204 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) { 4205 temp1 |= 1U << 1; 4206 } 4207 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) { 4208 temp1 |= 1U << 0; 4209 } 4210 SOC_IF_ERROR_BREAK 4211 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x30, temp1), rv); 4212 break; 4213 4214 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 4215 value0 = COMPILER_64_LO(value); 4216 4217 /* tx_timestamp_offset */ 4218 SOC_IF_ERROR_BREAK 4219 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x15 + offset, (uint16)(value0 & 0xffff)), rv); 4220 4221 if (offset < 4 ) { 4222 SOC_IF_ERROR_BREAK 4223 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x63, 4224 ((value0 & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv); 4225 } else { 4226 uint16 offset1 = offset - 4; 4227 SOC_IF_ERROR_BREAK 4228 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x64, 4229 ((value0 & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv); 4230 } 4231 break; 4232 4233 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 4234 value0 = COMPILER_64_LO(value); 4235 4236 /* rx_timestamp_offset */ 4237 SOC_IF_ERROR_BREAK 4238 (_phy_54680e_blk_top_lvl_reg_write(unit, pc, 0, 0x1d + offset, (uint16)(value0 & 0xffff)), rv); 4239 4240 if (offset < 4 ) { 4241 SOC_IF_ERROR_BREAK 4242 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x65, 4243 ((value0 & 0xf0000) >> ((4 - offset) << 2)), 0xf << (offset << 2)), rv); 4244 } else { 4245 uint16 offset1 = offset - 4; 4246 SOC_IF_ERROR_BREAK 4247 (_phy_54680e_blk_top_lvl_reg_modify(unit, pc, 0, 0x66, 4248 ((value0 & 0xf0000) >> ((4 - offset1) << 2)), 0xf << (offset1 << 2)), rv); 4249 } 4250 break; 4251 4252 4253 default: 4254 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 4255 return SOC_E_FAIL; 4256 } 4257 } while(0); 4258 4259 pc->phy_id = PHY54680_DEV_PHY_ID_ORIG(pc); 4260 4261 return SOC_E_NONE; 4262 } 4263 4264 STATIC int 4265 phy_54680_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 *value) 4266 { 4267 phy_ctrl_t *pc; 4268 uint16 value0; 4269 uint16 value1; 4270 uint16 value2; 4271 uint32 temp32; 4272 int offset, rv = SOC_E_NONE; 4273 4274 pc = EXT_PHY_SW_STATE(unit, port); 4275 4276 if ((!(PHY_IS_BCM54880E(pc) || PHY_IS_BCM52681E(pc))) || PHY_IS_BCM54880E_A0A1(pc)) { 4277 return SOC_E_UNAVAIL; 4278 } 4279 4280 offset = PHY54680_DEV_PHY_SLICE(pc); 4281 4282 do { 4283 /* pc->phy_id = PHY54680_SLICE_ADDR(pc, 0); */ 4284 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 4285 4286 switch (type) { 4287 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 4288 SOC_IF_ERROR_BREAK 4289 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x1), rv); 4290 4291 SOC_IF_ERROR_BREAK 4292 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x56, &value0), rv); 4293 SOC_IF_ERROR_BREAK 4294 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x57, &value1), rv); 4295 SOC_IF_ERROR_BREAK 4296 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x58, &value2), rv); 4297 4298 SOC_IF_ERROR_BREAK 4299 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x2), rv); 4300 SOC_IF_ERROR_BREAK 4301 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x0), rv); 4302 4303 COMPILER_64_SET((*value), ((uint32)value2), (((uint32)value1<<16)|((uint32)value0))); 4304 4305 /* *value = (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 4306 break; 4307 4308 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 4309 SOC_IF_ERROR_BREAK 4310 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x4), rv); 4311 4312 SOC_IF_ERROR_BREAK 4313 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x53, &value0), rv); 4314 SOC_IF_ERROR_BREAK 4315 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x54, &value1), rv); 4316 SOC_IF_ERROR_BREAK 4317 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x55, &value2), rv); 4318 4319 SOC_IF_ERROR_BREAK 4320 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x8), rv); 4321 SOC_IF_ERROR_BREAK 4322 (WRITE_PHY54680_EXP_READ_START_END_CTRLr(unit, pc, 0x0), rv); 4323 4324 COMPILER_64_SET((*value), ((uint32)value2), (((uint32)value1<<16)|((uint32)value0))); 4325 4326 /* *value = (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 4327 break; 4328 4329 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 4330 SOC_IF_ERROR_BREAK 4331 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x44, &value0), rv); 4332 /* *value = value0; */ 4333 COMPILER_64_SET((*value), 0, (uint32)value0); 4334 break; 4335 4336 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 4337 SOC_IF_ERROR_BREAK 4338 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x45, &value0), rv); 4339 SOC_IF_ERROR_BREAK 4340 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x46, &value1), rv); 4341 SOC_IF_ERROR_BREAK 4342 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x47, &value2), rv); 4343 4344 COMPILER_64_SET((*value), (value2 & 0x0fff), ((uint32)value1 << 16) | value0 ); 4345 COMPILER_64_SHL((*value), 4); 4346 break; 4347 4348 4349 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 4350 SOC_IF_ERROR_BREAK 4351 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x2e, &value1), rv); 4352 SOC_IF_ERROR_BREAK 4353 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x2f, &value2), rv); 4354 value0 = 0; 4355 if (value1 & (1U << 11)) { 4356 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_LOAD; 4357 } 4358 if (value2 & (1U << 11)) { 4359 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD; 4360 } 4361 if (value1 & (1U << 10)) { 4362 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD; 4363 } 4364 if (value2 & (1U << 10)) { 4365 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD; 4366 } 4367 if (value1 & (1U << 9)) { 4368 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD; 4369 } 4370 if (value2 & (1U << 9)) { 4371 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD; 4372 } 4373 if (value1 & (1U << 8)) { 4374 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD; 4375 } 4376 if (value1 & (1U << 8)) { 4377 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD; 4378 } 4379 if (value1 & (1U << 7)) { 4380 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD; 4381 } 4382 if (value1 & (1U << 7)) { 4383 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD; 4384 } 4385 if (value1 & (1U << 6)) { 4386 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD; 4387 } 4388 if (value2 & (1U << 6)) { 4389 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD; 4390 } 4391 if (value1 & (1U << 5)) { 4392 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD; 4393 } 4394 if (value2 & (1U << 5)) { 4395 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD; 4396 } 4397 if (value1 & (1U << 4)) { 4398 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD; 4399 } 4400 if (value2 & (1U << 4)) { 4401 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD; 4402 } 4403 if (value1 & (1U << 3)) { 4404 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD; 4405 } 4406 if (value2 & (1U << 3)) { 4407 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD; 4408 } 4409 if (value1 & (1U << 2)) { 4410 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD; 4411 } 4412 if (value2 & (1U << 2)) { 4413 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD; 4414 } 4415 if (value1 & (1U << 1)) { 4416 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD; 4417 } 4418 if (value2 & (1U << 1)) { 4419 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD; 4420 } 4421 if (value1 & (1U << 0)) { 4422 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD; 4423 } 4424 if (value2 & (1U << 0)) { 4425 value0 |= (uint16) SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD; 4426 } 4427 COMPILER_64_SET((*value), 0, (uint32)value0); 4428 break; 4429 4430 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 4431 SOC_IF_ERROR_BREAK 4432 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x31, &value1), rv); 4433 value0 = 0; 4434 if (value1 & (1U << 1)) { 4435 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT; 4436 } 4437 if (value1 & (1U << 0)) { 4438 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT; 4439 } 4440 COMPILER_64_SET((*value), 0, (uint32)value0); 4441 break; 4442 4443 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 4444 SOC_IF_ERROR_BREAK 4445 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x30, &value1), rv); 4446 value0 = 0; 4447 if (value1 & (1U << 1)) { 4448 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK; 4449 } 4450 if (value1 & (1U << 0)) { 4451 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK; 4452 } 4453 COMPILER_64_SET((*value), 0, (uint32)value0); 4454 break; 4455 4456 4457 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 4458 /* tx_timestamp_offset */ 4459 SOC_IF_ERROR_BREAK 4460 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x15 + offset, &value1), rv); 4461 if (offset < 4 ) { 4462 SOC_IF_ERROR_BREAK 4463 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x63, &value2), rv); 4464 temp32 = (value2 & (0xf << (offset << 2))) << ((4 - offset) << 2); 4465 } else { 4466 uint16 offset1 = offset - 4; 4467 SOC_IF_ERROR_BREAK 4468 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x64, &value2), rv); 4469 temp32 = (value2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2); 4470 } 4471 /* *value = temp32 | value1; */ 4472 COMPILER_64_SET((*value), 0, (uint32)(temp32 | value1)); 4473 break; 4474 4475 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 4476 /* rx_timestamp_offset */ 4477 SOC_IF_ERROR_BREAK 4478 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x1d + offset, &value1), rv); 4479 if (offset < 4 ) { 4480 SOC_IF_ERROR_BREAK 4481 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x65, &value2), rv); 4482 temp32 = (value2 & (0xf << (offset << 2))) << ((4 - offset) << 2); 4483 } else { 4484 uint16 offset1 = offset - 4; 4485 SOC_IF_ERROR_BREAK 4486 (_phy_54680e_blk_top_lvl_reg_read(unit, pc, 0, 0x66, &value2), rv); 4487 temp32 = (value2 & (0xf << (offset1 << 2))) << ((4 - offset1) << 2); 4488 } 4489 /* *value = temp32 | value1; */ 4490 COMPILER_64_SET((*value), 0, (uint32)(temp32 | value1)); 4491 break; 4492 4493 default: 4494 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 4495 return SOC_E_FAIL; 4496 } 4497 } while(0); 4498 4499 pc->phy_id = PHY54680_DEV_PHY_ID_BASE(pc); 4500 4501 return SOC_E_NONE; 4502 } 4503 4504 /* 4505 * Variable: phy_54680drv_ge 4506 * Purpose: PHY driver for 54680 4507 */ 4508 4509 phy_driver_t phy_54680drv_ge = { 4510 "54680 Gigabit PHY Driver", 4511 phy_54680_init, 4512 phy_fe_ge_reset, 4513 phy_54680_link_get, 4514 phy_54680_enable_set, 4515 phy_54680_enable_get, 4516 phy_54680_duplex_set, 4517 phy_54680_duplex_get, 4518 phy_54680_speed_set, 4519 phy_54680_speed_get, 4520 phy_54680_master_set, 4521 phy_54680_master_get, 4522 phy_54680_autoneg_set, 4523 phy_54680_autoneg_get, 4524 NULL, 4525 NULL, 4526 NULL, 4527 phy_54680_lb_set, 4528 phy_54680_lb_get, 4529 phy_54680_interface_set, 4530 phy_54680_interface_get, 4531 NULL, /* Deprecated */ 4532 phy_54680_link_up, /* Link up event */ 4533 phy_54680_link_down, 4534 phy_54680_mdix_set, 4535 phy_54680_mdix_get, 4536 phy_54680_mdix_status_get, 4537 phy_54680_medium_config_set, 4538 phy_54680_medium_config_get, 4539 phy_54680_medium_status, 4540 phy54680_cable_diag_dispatch, 4541 NULL, /* phy_link_change */ 4542 phy_54680_control_set, /* phy_control_set */ 4543 phy_54680_control_get, /* phy_control_get */ 4544 phy_ge_reg_read, 4545 phy_ge_reg_write, 4546 phy_ge_reg_modify, 4547 NULL, /* Phy notify event */ 4548 phy_54680_probe, /* pd_probe */ 4549 phy_54680_ability_advert_set,/* pd_ability_advert_set */ 4550 phy_54680_ability_advert_get,/* pd_ability_advert_get */ 4551 phy_54680_ability_remote_get,/* pd_ability_remote_get */ 4552 phy_54680_ability_local_get, /* pd_ability_local_get */ 4553 NULL, /* pd_firmware_set */ 4554 phy_54680_timesync_config_set, 4555 phy_54680_timesync_config_get, 4556 phy_54680_timesync_control_set, 4557 phy_54680_timesync_control_get 4558 }; 4559 4560 #else /* INCLUDE_PHY_54680_ESW */ 4561 int _phy_54680_not_empty; 4562 #endif /* INCLUDE_PHY_54680_ESW */ 4563