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