phy8750.c (61509B)
1 2 /* 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * File: phy8750.c 9 * Purpose: Phys Driver support for Broadcom 8750 Serial 10Gig 10 * transceiver :XFI system side and SFI Line interface. 11 * Note: 12 */ 13 14 #include <sal/types.h> 15 #include <shared/bsl.h> 16 #include <soc/drv.h> 17 #include <soc/debug.h> 18 #include <soc/error.h> 19 #include <soc/phyreg.h> 20 21 #include <soc/phy.h> 22 #include <soc/phy/phyctrl.h> 23 #include <soc/phy/drv.h> 24 25 #include "phydefs.h" /* Must include before other phy related includes */ 26 27 #if defined(INCLUDE_PHY_8750) 28 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 29 #include "phyident.h" 30 #include "phyreg.h" 31 #include "phynull.h" 32 #include "phyxehg.h" 33 #include "phy8750.h" 34 /* 35 * SPI-ROM Program related defs 36 */ 37 #define SPI_CTRL_1_L 0xC000 38 #define SPI_CTRL_1_H 0xC002 39 #define SPI_CTRL_2_L 0xC400 40 #define SPI_CTRL_2_H 0xC402 41 #define SPI_TXFIFO 0xD000 42 #define SPI_RXFIFO 0xD400 43 #define WR_CPU_CTRL_REGS 0x11 44 #define RD_CPU_CTRL_REGS 0xEE 45 #define WR_CPU_CTRL_FIFO 0x66 46 47 /* 48 * SPI Controller Commands(Messages). 49 */ 50 #define MSGTYPE_HWR 0x40 51 #define MSGTYPE_HRD 0x80 52 #define WRSR_OPCODE 0x01 53 #define WR_OPCODE 0x02 54 #define WRDI_OPCODE 0x04 55 #define RDSR_OPCODE 0x05 56 #define WREN_OPCODE 0x06 57 #define WR_BLOCK_SIZE 0x40 58 #define TOTAL_WR_BYTE 0x4000 59 60 #define WR_TIMEOUT 1000000 61 62 /* typedefs */ 63 typedef struct { 64 int rx_los; 65 int rx_los_invert; 66 int mod_abs; 67 int mod_abs_invert; 68 } PHY8750_DEV_DESC_t; 69 70 /* device field macros */ 71 #define RX_LOS(_pc) (((PHY8750_DEV_DESC_t *)((_pc) + 1))->rx_los) 72 #define RX_LOS_INVERT(_pc) (((PHY8750_DEV_DESC_t *)((_pc) + 1))->rx_los_invert) 73 #define MOD_ABS(_pc) (((PHY8750_DEV_DESC_t *)((_pc) + 1))->mod_abs) 74 #define MOD_ABS_INVERT(_pc) (((PHY8750_DEV_DESC_t *)((_pc) + 1))->mod_abs_invert) 75 76 static int write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, 77 uint16 *rddata); 78 79 80 STATIC int _phy8754_mdio_firmware_download(int unit, int port, int offset, uint8 *array,int datalen); 81 STATIC int phy_8750_speed_get(int, soc_port_t, int *); 82 83 extern unsigned char phy8754_ucode_bin[]; 84 extern unsigned int phy8754_ucode_bin_len; 85 86 87 STATIC int 88 _phy8750_optical_sig_cfg(int unit, int port) 89 { 90 uint16 mask16; 91 uint16 data16; 92 phy_ctrl_t *pc; 93 94 pc = EXT_PHY_SW_STATE(unit, port); 95 96 mask16 = PHY8750_RXLOS_OVERRIDE_MASK | 97 PHY8750_MOD_ABS_OVERRIDE_MASK; 98 data16 = 0; 99 /* default: override RX_LOS signalling */ 100 if (!RX_LOS(pc)) { 101 data16 |= PHY8750_RXLOS_OVERRIDE_MASK; 102 } 103 /* default: override MOD_ABS signalling */ 104 if (!MOD_ABS(pc)) { 105 data16 |= PHY8750_MOD_ABS_OVERRIDE_MASK; 106 } 107 108 SOC_IF_ERROR_RETURN 109 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit,pc, 110 PHY8750_PMAD_OPTICAL_CFG_REG, data16,mask16)); 111 112 mask16 = PHY8750_RXLOS_LVL_MASK | PHY8750_MOD_ABS_LVL_MASK; 113 data16 = 0; 114 /* default: RX_LOS level high */ 115 if (!RX_LOS_INVERT(pc)) { 116 data16 |= PHY8750_RXLOS_LVL_MASK; 117 } 118 /* default: MOD_ABS level high */ 119 if (!MOD_ABS_INVERT(pc)) { 120 data16 |= PHY8750_MOD_ABS_LVL_MASK; 121 } 122 SOC_IF_ERROR_RETURN 123 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit,pc, 124 PHY8750_PMAD_OPTICAL_SIG_LVL_REG, 125 data16, mask16)); 126 return SOC_E_NONE; 127 } 128 129 STATIC int 130 _phy8754_rom_load(int unit, int port, phy_ctrl_t *pc) 131 { 132 133 uint8 phy_id, i; 134 135 SOC_IF_ERROR_RETURN 136 (_phy8750_optical_sig_cfg(unit,port)); 137 138 phy_id = pc->phy_id; 139 /* configure all four ports */ 140 for (i = 0; i < 4; i++) { 141 pc->phy_id = (phy_id | 0x3) & ~i; /* Port 3, 2, 1 and 0 */ 142 143 /* Disable all port's SPI. bits 3:0 is GPIO port = input. 144 * SPI control and debug port pin is multiplexed 145 */ 146 SOC_IF_ERROR_RETURN 147 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x000F)); 148 149 /* bits 3:2 is Mode control for SPI/Debug/GPIO pins */ 150 SOC_IF_ERROR_RETURN 151 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x000C)); 152 153 /* Set bit SPI Download (15), SER Boot (14) And SPI Port Enable (0): 154 * enable SPI bus arbitor. 155 */ 156 SOC_IF_ERROR_RETURN 157 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0xC0F1)); 158 159 } 160 /* restore the original phy_id */ 161 pc->phy_id = phy_id; 162 163 /* place the port's uC in reset state */ 164 SOC_IF_ERROR_RETURN 165 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x018F)); 166 167 SOC_IF_ERROR_RETURN 168 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x0000)); 169 SOC_IF_ERROR_RETURN 170 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x0000)); 171 SOC_IF_ERROR_RETURN 172 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x0188)); 173 174 sal_usleep(100000); /* Sleep for at least 80ms */ 175 176 SOC_IF_ERROR_RETURN 177 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x000F)); 178 SOC_IF_ERROR_RETURN 179 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x000C)); 180 181 return SOC_E_NONE; 182 } 183 184 STATIC int 185 _phy8750_rom_load(int unit, int port, phy_ctrl_t *pc) 186 { 187 uint16 data = 0; 188 189 /* Read Chip IDs */ 190 SOC_IF_ERROR_RETURN 191 (READ_PHY8750_PMA_PMD_CHIPIDr(unit, pc, &data)); 192 if (data == 0x8754) { 193 SOC_IF_ERROR_RETURN 194 (_phy8754_rom_load(unit, port, pc)); 195 } else { 196 SOC_IF_ERROR_RETURN( 197 READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xc848, &data)); 198 data |= 0xc000; /* Set SER boot and download via SPI */ 199 SOC_IF_ERROR_RETURN( 200 WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xc848, data)); 201 202 /* Reset */; 203 SOC_IF_ERROR_RETURN( 204 MODIFY_PHY8750_PMA_PMD_CTRLr(unit, pc, 0x8000, 0x8000)); 205 } 206 207 /* Wait for atleast 100ms for code to download via SPI port*/ 208 sal_usleep(200000); 209 210 return SOC_E_NONE; 211 } 212 213 214 215 STATIC int 216 _phy8750_adjust_xfi_tx_preemphasis(int unit, int port, phy_ctrl_t *pc) 217 { 218 219 SOC_IF_ERROR_RETURN( 220 PHY8750_XFI(unit, pc)); 221 222 SOC_IF_ERROR_RETURN( 223 WRITE_PHY8750_XFI_PMA_PMD_REG(unit, pc, 0xc90b, 0xb000)); 224 225 SOC_IF_ERROR_RETURN( 226 WRITE_PHY8750_XFI_PMA_PMD_REG(unit, pc, 0xc90c, 0x1052)); 227 228 SOC_IF_ERROR_RETURN( 229 WRITE_PHY8750_XFI_PMA_PMD_REG(unit, pc, 0xc900, 0xec91)); 230 231 SOC_IF_ERROR_RETURN( 232 PHY8750_MMF(unit, pc)); 233 234 return SOC_E_NONE; 235 } 236 237 /* Function: 238 * phy_8750_init 239 * Purpose: 240 * Initialize 8750 phys 241 * Parameters: 242 * unit - StrataSwitch unit #. 243 * port - StrataSwitch port #. 244 * Returns: 245 * SOC_E_NONE 246 */ 247 248 STATIC int 249 phy_8750_init(int unit, soc_port_t port) 250 { 251 soc_timeout_t to; 252 int rv = SOC_E_NONE; 253 uint16 data16,ucode_ver; 254 phy_ctrl_t *pc; 255 uint32 phy_ext_rom_boot, phy_long_xfi; 256 uint16 chip_id = 0xffff, chip_rev = 0xffff; 257 258 pc = EXT_PHY_SW_STATE(unit, port); 259 260 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45); 261 262 263 /* Read Chip IDs */ 264 SOC_IF_ERROR_RETURN 265 (READ_PHY8750_PMA_PMD_CHIPIDr(unit, pc, &chip_id)); 266 /* Read Chip Revision */ 267 SOC_IF_ERROR_RETURN 268 (READ_PHY8750_PMA_PMD_CHIPREVr(unit, pc, &chip_rev)); 269 chip_rev &= 0x000f; 270 271 272 /* Support BCM8750, BCM8752 and BCM8754 PHYs */ 273 if ((chip_id != 0x8750) && (chip_id != 0x8752) && (chip_id != 0x8754)) { 274 LOG_CLI((BSL_META_U(unit, 275 "Unsupported PHY: Chip Id = %x\n"), chip_id)); 276 return SOC_E_FAIL; 277 } 278 279 if (chip_id == 0x8754) { 280 /* These two register writes allow the device boots and stays executing from 281 * the internal ROM after the PMA/PMD MII_CTRL_RESET. Otherwise it will load 282 * the content from SPI-ROM to RAM and executes from the RAM. In case the 283 * SPI-ROM has not been programmed with any firmware, the uController will 284 * not work properly. 285 */ 286 SOC_IF_ERROR_RETURN 287 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0, (1 << 14) |(1 << 13))); 288 SOC_IF_ERROR_RETURN 289 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xca85, 0, 1 )); 290 } 291 292 /* Reset the device */ 293 SOC_IF_ERROR_RETURN 294 (MODIFY_PHY8750_PMA_PMD_CTRLr(unit, pc, 295 MII_CTRL_RESET, MII_CTRL_RESET)); 296 SOC_IF_ERROR_RETURN 297 (MODIFY_PHY8750_PCS_CTRLr(unit, pc, 298 MII_CTRL_RESET, MII_CTRL_RESET)); 299 300 /* Wait for device to come out of reset */ 301 soc_timeout_init(&to, 10000, 0); 302 while (!soc_timeout_check(&to)) { 303 rv = READ_PHY8750_PMA_PMD_CTRLr(unit, pc, &data16); 304 if (((data16 & MII_CTRL_RESET) == 0) || 305 SOC_FAILURE(rv)) { 306 break; 307 } 308 } 309 if (((data16 & MII_CTRL_RESET) != 0) || SOC_FAILURE(rv)) { 310 LOG_WARN(BSL_LS_SOC_PHY, 311 (BSL_META_U(unit, 312 "PHY8750/8726 reset failed: u=%d p=%d\n"), 313 unit, port)); 314 return SOC_E_FAIL; 315 } 316 317 /* check optical signaling configuration */ 318 RX_LOS(pc) = soc_property_port_get(unit, port,spn_PHY_RX_LOS, 0); 319 MOD_ABS(pc) = soc_property_port_get(unit, port,spn_PHY_MOD_ABS, 0); 320 RX_LOS_INVERT(pc) = soc_property_port_get(unit, port,spn_PHY_RX_LOS_INVERT, 0); 321 MOD_ABS_INVERT(pc) = soc_property_port_get(unit, port,spn_PHY_MOD_ABS_INVERT, 0); 322 323 phy_ext_rom_boot = soc_property_port_get(unit, port, 324 spn_PHY_EXT_ROM_BOOT, 1); 325 if (phy_ext_rom_boot) { 326 SOC_IF_ERROR_RETURN 327 (_phy8750_rom_load(unit, port, pc)); 328 } else { 329 /* MDIO loading */ 330 if (chip_id == 0x8754) { 331 SOC_IF_ERROR_RETURN 332 (_phy8754_mdio_firmware_download(unit, port, 0,phy8754_ucode_bin, 333 phy8754_ucode_bin_len)); 334 SOC_IF_ERROR_RETURN 335 (_phy8750_optical_sig_cfg(unit,port)); 336 } 337 } 338 339 /* read the microcode revision */ 340 SOC_IF_ERROR_RETURN 341 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &ucode_ver)); 342 343 /* If microcode revision > 0x0301, then check the completion of 344 * the SPI-ROM load. 345 */ 346 if (ucode_ver >= 0x0301) { 347 rv = READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16); 348 if (data16 != 0x600D || SOC_FAILURE(rv)) { 349 LOG_WARN(BSL_LS_SOC_PHY, 350 (BSL_META_U(unit, 351 "8750: p=%d SPI-ROM load: Bad Checksum (0x%x)\n"), 352 port, data16)); 353 /* let it continue in case a blank SPI-ROM or allow other ports to 354 * initialize. Internal ROM code always show checksum as zero. 355 */ 356 } 357 } else { 358 LOG_WARN(BSL_LS_SOC_PHY, 359 (BSL_META_U(unit, 360 "8750: p=%d SPI-ROM load: Invalid Ucode version (0x%x)\n"), 361 port, ucode_ver)); 362 /* let it continue to allow other ports to initialize */ 363 } 364 365 LOG_INFO(BSL_LS_SOC_PHY, 366 (BSL_META_U(unit, 367 "8750: u=%d port%d rom code ver: 0x%x: init.\n"), 368 unit, port, ucode_ver)); 369 370 /* By default XFI cannot drive long distance cables. TX premphasis needs 371 * to be adjusted if long cables are used on the XFI side 372 */ 373 phy_long_xfi = soc_property_port_get(unit, port, 374 spn_PHY_LONG_XFI, 1); 375 if (phy_long_xfi) { 376 SOC_IF_ERROR_RETURN( 377 _phy8750_adjust_xfi_tx_preemphasis(unit, port, pc)); 378 } 379 380 /* Disable SyncE */ 381 SOC_IF_ERROR_RETURN( 382 PHY8750_MMF(unit, pc)); 383 SOC_IF_ERROR_RETURN( 384 MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xc840, 0x0000, 0xffff)); 385 SOC_IF_ERROR_RETURN( 386 MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xcd17, 0x0000, 0xffff)); 387 SOC_IF_ERROR_RETURN( 388 PHY8750_XFI(unit, pc)); 389 SOC_IF_ERROR_RETURN( 390 MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xcd17, 0x0000, 0xffff)); 391 SOC_IF_ERROR_RETURN( 392 PHY8750_MMF(unit, pc)); 393 SOC_IF_ERROR_RETURN( 394 MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 395 PHY8750_PMAD_OPTICAL_CFG_REG, (1U<<12), ((1U<<12) | (1U<<4)))); 396 397 LOG_CLI((BSL_META_U(unit, 398 "BCM%x (Rev. %d): u=%d port%d rom code ver. 0x%x\n"), 399 chip_id, chip_rev, unit, port, ucode_ver)); 400 401 return SOC_E_NONE; 402 } 403 404 /* 405 * Function: 406 * phy_8750_an_get 407 * Purpose: 408 * Get the current auto-negotiation status (enabled/busy) 409 * Parameters: 410 * unit - StrataSwitch unit #. 411 * port - StrataSwitch port #. 412 * an - (OUT) if true, auto-negotiation is enabled. 413 * an_done - (OUT) if true, auto-negotiation is complete. This 414 * value is undefined if an == false. 415 * Returns: 416 * SOC_E_XXX 417 */ 418 419 STATIC int 420 phy_8750_an_get(int unit, soc_port_t port, int *an, int *an_done) 421 { 422 phy_ctrl_t *pc; 423 uint16 an_status; 424 425 pc = EXT_PHY_SW_STATE(unit, port); 426 SOC_IF_ERROR_RETURN 427 (READ_PHY8750_MMF_AN_REG(unit, pc, 0xFFE0, &an_status)); 428 *an = (an_status & PHY8750_AN_ENABLE)? TRUE: FALSE; 429 430 SOC_IF_ERROR_RETURN 431 (READ_PHY8750_MMF_AN_REG(unit, pc, 0xFFE1, &an_status)); 432 *an_done = (an_status & PHY8750_AN_DONE)? TRUE: FALSE; 433 434 return SOC_E_NONE; 435 } 436 437 /* 438 * Function: 439 * phy_8750_an_set 440 * Purpose: 441 * Enable or disabled auto-negotiation on the specified port. 442 * Parameters: 443 * unit - StrataSwitch unit #. 444 * port - StrataSwitch port #. 445 * an - Boolean, if true, auto-negotiation is enabled 446 * (and/or restarted). If false, autonegotiation is disabled. 447 * Returns: 448 * SOC_E_XXX 449 */ 450 STATIC int 451 phy_8750_an_set(int unit, soc_port_t port, int an) 452 { 453 phy_ctrl_t *pc; 454 phy_ctrl_t *int_pc; 455 456 int_pc = INT_PHY_SW_STATE(unit, port); 457 if (NULL != int_pc) { 458 SOC_IF_ERROR_RETURN( 459 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an)); 460 } 461 462 pc = EXT_PHY_SW_STATE(unit, port); 463 464 LOG_INFO(BSL_LS_SOC_PHY, 465 (BSL_META_U(unit, 466 "phy_8750_an_set: u=%d p=%d an=%d\n"), 467 unit, port, an)); 468 469 if (an) { 470 /* Clear Forced Speed selections in Miscellaneous 2 Register */ 471 SOC_IF_ERROR_RETURN 472 (WRITE_PHY8750_MMF_AN_REG(unit, pc, 0x8309, 0x0000)); 473 /* Enable Clause 37 AN */ 474 SOC_IF_ERROR_RETURN 475 (WRITE_PHY8750_MMF_AN_REG(unit, pc, 0xFFE0, 0x1300)); 476 } else { 477 /* disable Clause 37 AN */ 478 SOC_IF_ERROR_RETURN 479 (WRITE_PHY8750_MMF_AN_REG(unit, pc, 0xFFE0, 0)); 480 SOC_IF_ERROR_RETURN 481 (WRITE_PHY8750_MMF_AN_REG(unit, pc, 0x8309, 0x0020)); 482 } 483 484 return SOC_E_NONE; 485 } 486 487 /* 488 * Function: 489 * phy_8750_ability_advert_get 490 * Purpose: 491 * Get the current advertisement for auto-negotiation. 492 * Parameters: 493 * unit - StrataSwitch unit #. 494 * port - StrataSwitch port #. 495 * mode - (OUT) Port mode mask indicating supported options/speeds. 496 * Returns: 497 * SOC_E_XXX 498 * Notes: 499 * The advertisement is retrieved for the ACTIVE medium. 500 * No synchronization performed at this level. 501 */ 502 503 STATIC int 504 phy_8750_ability_advert_get(int unit, soc_port_t port, 505 soc_port_ability_t *ability) 506 { 507 uint16 an_adv; 508 soc_port_mode_t mode; 509 phy_ctrl_t *pc; 510 511 if (NULL == ability) { 512 return (SOC_E_PARAM); 513 } 514 pc = EXT_PHY_SW_STATE(unit, port); 515 516 SOC_IF_ERROR_RETURN 517 (READ_PHY8750_MMF_AN_REG(unit, pc, 0xFFE0, &an_adv)); 518 519 mode = 0; 520 mode |= (an_adv & 0x1000) ? SOC_PA_SPEED_1000MB : 0; 521 522 /* check Full Duplex advertisement on Clause 37 */ 523 SOC_IF_ERROR_RETURN 524 (READ_PHY8750_MMF_AN_REG(unit, pc, 0xFFE4, &an_adv)); 525 mode |= (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0; 526 527 ability->speed_full_duplex = mode; 528 ability->pause = 0; 529 530 switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) { 531 case MII_ANA_C37_PAUSE: 532 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 533 break; 534 case MII_ANA_C37_ASYM_PAUSE: 535 ability->pause = SOC_PA_PAUSE_TX; 536 break; 537 case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE: 538 ability->pause = SOC_PA_PAUSE_RX; 539 break; 540 } 541 542 LOG_INFO(BSL_LS_SOC_PHY, 543 (BSL_META_U(unit, 544 "phy_8750_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 545 unit, port, ability->speed_full_duplex, ability->pause)); 546 return SOC_E_NONE; 547 } 548 549 /* 550 * Function: 551 * phy_8750_ability_remote_get 552 * Purpose: 553 * Get the device's complete abilities. 554 * Parameters: 555 * unit - StrataSwitch unit #. 556 * port - StrataSwitch port #. 557 * ability - return device's abilities. 558 * Returns: 559 * SOC_E_XXX 560 */ 561 562 STATIC int 563 phy_8750_ability_remote_get(int unit, soc_port_t port, 564 soc_port_ability_t *ability) 565 { 566 phy_ctrl_t *pc; 567 uint16 lp_abil; 568 569 pc = EXT_PHY_SW_STATE(unit, port); 570 571 if (NULL == ability) { 572 return SOC_E_PARAM; 573 } 574 575 SOC_IF_ERROR_RETURN 576 (READ_PHY8750_MMF_AN_REG(unit, pc, 0xFFE5, &lp_abil)); 577 ability->speed_full_duplex = (lp_abil & MII_ANA_C37_FD) ? 578 SOC_PA_SPEED_1000MB : 0; 579 580 ability->pause = 0; 581 switch (lp_abil & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) { 582 case MII_ANP_C37_PAUSE: 583 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 584 break; 585 case MII_ANP_C37_ASYM_PAUSE: 586 ability->pause = SOC_PA_PAUSE_TX; 587 break; 588 case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE: 589 ability->pause = SOC_PA_PAUSE_RX; 590 break; 591 } 592 593 SOC_IF_ERROR_RETURN 594 (READ_PHY8750_MMF_AN_REG(unit, pc, PHY8750_AN_STATUS_REG, &lp_abil)); 595 ability->flags = (lp_abil & 0x1) ? SOC_PA_AUTONEG : 0; 596 597 LOG_INFO(BSL_LS_SOC_PHY, 598 (BSL_META_U(unit, 599 "phy_8750_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 600 unit, port, ability->speed_full_duplex, ability->pause)); 601 602 return (SOC_E_NONE); 603 } 604 605 /* 606 * Function: 607 * phy_8750_ability_advert_set 608 * Purpose: 609 * Set the current advertisement for auto-negotiation. 610 * Parameters: 611 * unit - StrataSwitch unit #. 612 * port - StrataSwitch port #. 613 * mode - Port mode mask indicating supported options/speeds. 614 * Returns: 615 * SOC_E_XXX 616 * Notes: 617 * The advertisement is set only for the ACTIVE medium. 618 * No synchronization performed at this level. 619 */ 620 621 STATIC int 622 phy_8750_ability_advert_set(int unit, soc_port_t port, 623 soc_port_ability_t *ability) 624 { 625 uint16 an_adv; 626 phy_ctrl_t *pc; 627 628 if (NULL == ability) { 629 return (SOC_E_PARAM); 630 } 631 632 pc = EXT_PHY_SW_STATE(unit, port); 633 /* 634 * Set advertised duplex (only FD supported). 635 */ 636 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 637 MII_ANA_C37_FD : 0; 638 639 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 640 case SOC_PA_PAUSE_TX: 641 an_adv |= MII_ANA_C37_ASYM_PAUSE; 642 break; 643 case SOC_PA_PAUSE_RX: 644 an_adv |= MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE; 645 break; 646 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 647 an_adv |= MII_ANA_C37_PAUSE; 648 break; 649 } 650 651 /* write Clause37 advertisement */ 652 SOC_IF_ERROR_RETURN 653 (MODIFY_PHY8750_MMF_AN_REG(unit, pc, 0xFFE4, an_adv, 654 MII_ANA_C37_ASYM_PAUSE | 655 MII_ANA_C37_PAUSE | 656 MII_ANA_C37_FD | 657 MII_ANA_C37_HD )); 658 659 /*Set on the XFI side as well */ 660 PHY8750_XFI(unit, pc); 661 /* write Clause37 advertisement */ 662 SOC_IF_ERROR_RETURN 663 (MODIFY_PHY8750_XFI_AN_REG(unit, pc, 0xFFE4, an_adv, 664 MII_ANA_C37_ASYM_PAUSE | 665 MII_ANA_C37_PAUSE | 666 MII_ANA_C37_FD | 667 MII_ANA_C37_HD )); 668 PHY8750_MMF(unit, pc); 669 670 LOG_INFO(BSL_LS_SOC_PHY, 671 (BSL_META_U(unit, 672 "phy_8750_ability_advert_set: u=%d p=%d pause=0x%08x adv_reg1=0x%04x\n"), 673 unit, port, ability->pause, an_adv)); 674 return SOC_E_NONE; 675 } 676 677 /* 678 * Function: 679 * phy_8750_ability_local_get 680 * Purpose: 681 * Get the device's complete abilities. 682 * Parameters: 683 * unit - StrataSwitch unit #. 684 * port - StrataSwitch port #. 685 * ability - return device's abilities. 686 * Returns: 687 * SOC_E_XXX 688 */ 689 690 STATIC int 691 phy_8750_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 692 { 693 phy_ctrl_t *pc; 694 pc = EXT_PHY_SW_STATE(unit, port); 695 696 LOG_INFO(BSL_LS_SOC_PHY, 697 (BSL_META_U(unit, 698 "phy_8750_ability_local_get: u=%d p=%d\n"), 699 unit, port)); 700 701 if (NULL == ability) { 702 return SOC_E_PARAM; 703 } 704 705 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 706 ability->speed_full_duplex = SOC_PA_SPEED_1000MB; 707 708 switch(pc->speed_max) { 709 case 10000: 710 default: 711 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 712 break; 713 } 714 715 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 716 ability->interface = SOC_PA_INTF_XGMII; 717 ability->medium = SOC_PA_MEDIUM_FIBER; 718 ability->loopback = SOC_PA_LB_PHY; 719 720 LOG_INFO(BSL_LS_SOC_PHY, 721 (BSL_META_U(unit, 722 "phy_8750_ability_local_get: u=%d p=%d speed=0x%x\n"), 723 unit, port, ability->speed_full_duplex)); 724 725 return (SOC_E_NONE); 726 } 727 728 /* 729 * Function: 730 * phy_8750_link_get 731 * Purpose: 732 * Get layer2 connection status. 733 * Parameters: 734 * unit - StrataSwitch unit #. 735 * port - StrataSwitch port #. 736 * link - address of memory to store link up/down state. 737 * Returns: 738 * SOC_E_NONE 739 */ 740 741 STATIC int 742 phy_8750_link_get(int unit, soc_port_t port, int *link) 743 { 744 uint16 pma_mii_stat, pcs_mii_stat, link_stat; 745 phy_ctrl_t *pc; 746 int cur_speed = 0; 747 int an = 0,an_done = 0; 748 uint16 speed_val; 749 750 if (link == NULL) { 751 return SOC_E_NONE; 752 } 753 754 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 755 *link = FALSE; 756 return SOC_E_NONE; 757 } 758 759 pc = EXT_PHY_SW_STATE(unit, port); 760 761 phy_8750_an_get(unit,port,&an,&an_done); 762 763 /* return link false if in the middle of autoneg */ 764 if (an == TRUE && an_done == FALSE) { 765 *link = FALSE; 766 return SOC_E_NONE; 767 } 768 769 /* AN only supports 1G */ 770 if (!an) { 771 SOC_IF_ERROR_RETURN 772 (READ_PHY8750_MMF_PMA_PMD_REG(unit,pc, PHY8750_PMAD_CTRL2_REG, 773 &speed_val)); 774 if ((speed_val & PHY8750_PMAD_CTRL2r_PMA_TYPE_MASK) != 775 PHY8750_PMAD_CTRL2r_PMA_TYPE_1G_KX) { 776 cur_speed = 10000; 777 } else { 778 cur_speed = 1000; 779 } 780 } else { 781 cur_speed = 1000; 782 } 783 784 if (cur_speed == 10000) { /* check all 3 device's link status if 10G */ 785 786 /* Receive Link status */ 787 SOC_IF_ERROR_RETURN 788 (READ_PHY8750_PCS_STATr(unit, pc, &pcs_mii_stat)); 789 790 SOC_IF_ERROR_RETURN 791 (READ_PHY8750_PMA_PMD_STATr(unit, pc, &pma_mii_stat)); 792 793 /* MMF link status */ 794 link_stat = pma_mii_stat & pcs_mii_stat; 795 *link = (link_stat & MII_STAT_LA) ? TRUE : FALSE; 796 797 } else { 798 SOC_IF_ERROR_RETURN 799 (READ_PHY8750_MMF_AN_REG(unit, pc, 0xffe1, 800 &link_stat)); 801 *link = (link_stat & MII_STAT_LA) ? TRUE : FALSE; 802 } 803 804 LOG_VERBOSE(BSL_LS_SOC_PHY, 805 (BSL_META_U(unit, 806 "phy_8750_link_get: u=%d port%d: link:%s\n"), 807 unit, port, *link ? "Up": "Down")); 808 809 return SOC_E_NONE; 810 } 811 812 /* 813 * Function: 814 * phy_8750_enable_set 815 * Purpose: 816 * Enable/Disable phy 817 * Parameters: 818 * unit - StrataSwitch unit #. 819 * port - StrataSwitch port #. 820 * enable - on/off state to set 821 * Returns: 822 * SOC_E_NONE 823 */ 824 825 STATIC int 826 phy_8750_enable_set(int unit, soc_port_t port, int enable) 827 { 828 uint16 data; /* Holder for new value to write to PHY reg */ 829 uint16 mask; /* Holder for bit mask to update in PHY reg */ 830 phy_ctrl_t *pc; 831 832 pc = EXT_PHY_SW_STATE(unit, port); 833 834 data = 0; 835 mask = 1 << 0; /* Global PMD transmit disable */ 836 if (enable) { 837 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 838 } else { 839 data = 1 << 0; /* Global PMD transmit disable */ 840 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 841 } 842 843 SOC_IF_ERROR_RETURN 844 (MODIFY_PHY8750_PMA_PMD_TX_DISABLEr(unit, pc, data, mask)); 845 846 data = mask = 1 << 11; /* Disable clock for low power*/ 847 if (enable) { 848 data = 0; 849 } 850 SOC_IF_ERROR_RETURN 851 (MODIFY_PHY8750_PMA_PMD_CTRLr(unit, pc, data, mask)); 852 853 return (SOC_E_NONE); 854 } 855 856 /* 857 * Function: 858 * phy_8750_lb_set 859 * Purpose: 860 * Put 8750 in PHY PMA/PMD loopback 861 * Parameters: 862 * unit - StrataSwitch unit #. 863 * port - StrataSwitch port #. 864 * enable - binary value for on/off (1/0) 865 * Returns: 866 * SOC_E_NONE 867 */ 868 869 STATIC int 870 phy_8750_lb_set(int unit, soc_port_t port, int enable) 871 { 872 phy_ctrl_t *pc; 873 uint16 tmp; 874 875 pc = EXT_PHY_SW_STATE(unit, port); 876 877 tmp = enable ? PHY8750_MII_CTRL_PMA_LOOPBACK : 0; 878 879 SOC_IF_ERROR_RETURN 880 (MODIFY_PHY8750_PMA_PMD_CTRLr(unit, pc, 881 tmp, PHY8750_MII_CTRL_PMA_LOOPBACK)); 882 return SOC_E_NONE; 883 } 884 885 /* 886 * Function: 887 * phy_8750_lb_get 888 * Purpose: 889 * Get 8750 PHY loopback state 890 * Parameters: 891 * unit - StrataSwitch unit #. 892 * port - StrataSwitch port #. 893 * enable - address of location to store binary value for on/off (1/0) 894 * Returns: 895 * SOC_E_NONE 896 */ 897 898 STATIC int 899 phy_8750_lb_get(int unit, soc_port_t port, int *enable) 900 { 901 uint16 tmp; 902 phy_ctrl_t *pc; 903 904 pc = EXT_PHY_SW_STATE(unit, port); 905 906 SOC_IF_ERROR_RETURN 907 (READ_PHY8750_PMA_PMD_CTRLr(unit, pc, &tmp)); 908 *enable = (tmp & PHY8750_MII_CTRL_PMA_LOOPBACK) ? TRUE : FALSE; 909 910 LOG_INFO(BSL_LS_SOC_PHY, 911 (BSL_META_U(unit, 912 "phy_8750_lb_get: u=%d port%d: loopback:%s\n"), 913 unit, port, *enable ? "Enabled": "Disabled")); 914 915 return SOC_E_NONE; 916 } 917 918 STATIC int 919 _phy_8750_control_tx_driver_set(int unit, soc_port_t port, 920 soc_phy_control_t type, uint32 value) 921 { 922 uint16 data; /* Temporary holder of reg value to be written */ 923 uint16 mask; /* Bit mask of reg value to be updated */ 924 phy_ctrl_t *pc; /* PHY software state */ 925 926 pc = EXT_PHY_SW_STATE(unit, port); 927 928 /* Dozen SerDes */ 929 switch(type) { 930 case SOC_PHY_CONTROL_PREEMPHASIS: 931 data = (uint16)(value & 0xf); 932 data = data << 12; 933 mask = 0xf000; 934 break; 935 case SOC_PHY_CONTROL_DRIVER_CURRENT: 936 data = (uint16)(value & 0xf); 937 data = data << 8; 938 mask = 0x0f00; 939 break; 940 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 941 data = (uint16)(value & 0xf); 942 data = data << 4; 943 mask = 0x00f0; 944 break; 945 default: 946 /* should never get here */ 947 return SOC_E_PARAM; 948 } 949 SOC_IF_ERROR_RETURN 950 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xca05, data, mask)); 951 952 return SOC_E_NONE; 953 } 954 955 STATIC int 956 _phy_8750_control_tx_driver_get(int unit, soc_port_t port, 957 soc_phy_control_t type, uint32 *value) 958 { 959 uint16 data16; /* Temporary holder of a reg value */ 960 phy_ctrl_t *pc; /* PHY software state */ 961 962 pc = EXT_PHY_SW_STATE(unit, port); 963 964 data16 = 0; 965 SOC_IF_ERROR_RETURN 966 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xca05, &data16)); 967 switch(type) { 968 case SOC_PHY_CONTROL_PREEMPHASIS: 969 *value = (data16 & 0xf000) >> 12; 970 break; 971 case SOC_PHY_CONTROL_DRIVER_CURRENT: 972 *value = (data16 & 0x0f00) >> 8; 973 break; 974 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 975 *value = (data16 & 0x00f0) >> 4; 976 break; 977 default: 978 /* should never get here */ 979 return SOC_E_PARAM; 980 } 981 982 return SOC_E_NONE; 983 } 984 985 /* 986 * Function: 987 * phy_8750_control_set 988 * Purpose: 989 * Configure PHY device specific control fucntion. 990 * Parameters: 991 * unit - StrataSwitch unit #. 992 * port - StrataSwitch port #. 993 * type - Control to update 994 * value - New setting for the control 995 * Returns: 996 * SOC_E_NONE 997 */ 998 STATIC int 999 phy_8750_control_set(int unit, soc_port_t port, 1000 soc_phy_control_t type, uint32 value) 1001 { 1002 int rv; 1003 1004 PHY_CONTROL_TYPE_CHECK(type); 1005 1006 rv = SOC_E_UNAVAIL; 1007 switch(type) { 1008 case SOC_PHY_CONTROL_PREEMPHASIS: 1009 /* fall through */ 1010 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1011 /* fall through */ 1012 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 1013 rv = _phy_8750_control_tx_driver_set(unit, port, type, value); 1014 break; 1015 default: 1016 rv = SOC_E_UNAVAIL; 1017 break; 1018 } 1019 return rv; 1020 } 1021 /* 1022 * Function: 1023 * phy_8750_control_get 1024 * Purpose: 1025 * Get current control settign of the PHY. 1026 * Parameters: 1027 * unit - StrataSwitch unit #. 1028 * port - StrataSwitch port #. 1029 * type - Control to update 1030 * value - (OUT)Current setting for the control 1031 * Returns: 1032 * SOC_E_NONE 1033 */ 1034 STATIC int 1035 phy_8750_control_get(int unit, soc_port_t port, 1036 soc_phy_control_t type, uint32 *value) 1037 { 1038 int rv; 1039 1040 PHY_CONTROL_TYPE_CHECK(type); 1041 1042 rv = SOC_E_UNAVAIL; 1043 switch(type) { 1044 case SOC_PHY_CONTROL_PREEMPHASIS: 1045 /* fall through */ 1046 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1047 /* fall through */ 1048 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 1049 rv = _phy_8750_control_tx_driver_get(unit, port, type, value); 1050 break; 1051 default: 1052 rv = SOC_E_UNAVAIL; 1053 break; 1054 } 1055 1056 return rv; 1057 } 1058 1059 /* 1060 * Function: 1061 * phy_8750_speed_set 1062 * Purpose: 1063 * Set PHY speed 1064 * Parameters: 1065 * unit - StrataSwitch unit #. 1066 * port - StrataSwitch port #. 1067 * speed - link speed in Mbps 1068 * Returns: 1069 * SOC_E_NONE 1070 */ 1071 1072 STATIC int 1073 phy_8750_speed_set(int unit, soc_port_t port, int speed) 1074 { 1075 phy_ctrl_t *pc; 1076 phy_ctrl_t *int_pc; 1077 int rv = SOC_E_NONE; 1078 1079 1080 LOG_INFO(BSL_LS_SOC_PHY, 1081 (BSL_META_U(unit, 1082 "phy_8750_speed_set: u=%d p=%d speed=%d\n"), 1083 unit, port,speed)); 1084 1085 if (!(speed == 10000 || speed == 1000)) { 1086 return SOC_E_PARAM; 1087 } 1088 1089 pc = EXT_PHY_SW_STATE(unit, port); 1090 1091 if (speed == 10000) { 1092 SOC_IF_ERROR_RETURN 1093 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit,pc, PHY8750_PMAD_CTRL_REG, 1094 MII_CTRL_SS_LSB, 1095 MII_CTRL_SS_LSB)); 1096 SOC_IF_ERROR_RETURN 1097 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit,pc, PHY8750_PMAD_CTRL2_REG, 1098 PHY8750_PMAD_CTRL2r_PMA_TYPE_10G_LRM, 1099 PHY8750_PMAD_CTRL2r_PMA_TYPE_MASK)); 1100 1101 SOC_IF_ERROR_RETURN 1102 (WRITE_PHY8750_MMF_AN_REG(unit, pc, PHY8750_AN_CTRL_REG, 1103 PHY8750_AN_ENABLE | 1104 PHY8750_AN_RESTART)); 1105 sal_usleep(40000); 1106 SOC_IF_ERROR_RETURN 1107 (WRITE_PHY8750_MMF_AN_REG(unit,pc, PHY8750_AN_CTRL_REG, 0x0)); 1108 1109 } else { 1110 SOC_IF_ERROR_RETURN 1111 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit,pc, PHY8750_PMAD_CTRL2_REG, 1112 PHY8750_PMAD_CTRL2r_PMA_TYPE_1G_KX, 1113 PHY8750_PMAD_CTRL2r_PMA_TYPE_MASK)); 1114 SOC_IF_ERROR_RETURN 1115 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit,pc, MII_CTRL_REG, 1116 0, MII_CTRL_SS_LSB)); 1117 1118 } 1119 /* need to set the internal phy's speed accordingly */ 1120 1121 int_pc = INT_PHY_SW_STATE(unit, port); 1122 if (NULL != int_pc) { 1123 rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed); 1124 } 1125 return rv; 1126 } 1127 1128 /* 1129 * Function: 1130 * phy_8750_speed_get 1131 * Purpose: 1132 * Get PHY speed 1133 * Parameters: 1134 * unit - StrataSwitch unit #. 1135 * port - StrataSwitch port #. 1136 * speed - current link speed in Mbps 1137 * Returns: 1138 * SOC_E_NONE 1139 */ 1140 1141 STATIC int 1142 phy_8750_speed_get(int unit, soc_port_t port, int *speed) 1143 { 1144 phy_ctrl_t *pc; 1145 uint16 speed_val; 1146 int an = 0; 1147 int an_done = 0; 1148 1149 pc = EXT_PHY_SW_STATE(unit, port); 1150 1151 phy_8750_an_get(unit,port,&an,&an_done); 1152 1153 *speed = 0; 1154 if (an) { /* autoneg is enabled */ 1155 if (an_done) { 1156 *speed = 1000; /* can only do 1G autoneg */ 1157 } 1158 } else { /* autoneg is not enabled, forced speed */ 1159 SOC_IF_ERROR_RETURN 1160 (READ_PHY8750_MMF_PMA_PMD_REG(unit,pc, PHY8750_PMAD_CTRL2_REG, &speed_val)); 1161 if ((speed_val & PHY8750_PMAD_CTRL2r_PMA_TYPE_MASK) == 1162 PHY8750_PMAD_CTRL2r_PMA_TYPE_1G_KX) { 1163 *speed = 1000; 1164 } else { 1165 *speed = 10000; 1166 } 1167 } 1168 return SOC_E_NONE; 1169 } 1170 1171 /* 1172 * Function: 1173 * _phy8754_mdio_firmware_download 1174 * Purpose: 1175 * write the given firmware to the internal RAM 1176 * Parameters: 1177 * unit - StrataSwitch unit #. 1178 * port - StrataSwitch port #. 1179 * offset - offset to the data stream 1180 * array - the given data 1181 * datalen- the data length 1182 * Returns: 1183 * SOC_E_NONE 1184 */ 1185 1186 STATIC int 1187 _phy8754_mdio_firmware_download(int unit, int port, int offset, uint8 *array,int datalen) 1188 { 1189 int j; 1190 phy_ctrl_t *pc; 1191 uint16 data16; 1192 uint16 mask16; 1193 1194 if (array == NULL) { 1195 return SOC_E_PARAM; 1196 } 1197 1198 pc = EXT_PHY_SW_STATE(unit, port); 1199 1200 /* Programme SPA Control Register to Boot from MDIO 1201 * bit 15, 0 MDIO for serial boot. bit 14, 1 serial boot 1202 */ 1203 mask16 = (1 << 14) | (1 << 15); 1204 data16 = 1 << 14; 1205 SOC_IF_ERROR_RETURN 1206 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, PHY8750_PMAD_SPA_CTRL_REG, 1207 data16,mask16)); 1208 1209 /* Reset, to download code from MDIO */ 1210 SOC_IF_ERROR_RETURN 1211 (READ_PHY8750_PMA_PMD_CTRLr(unit, pc, &data16)); 1212 1213 data16 |= 0x8000; 1214 1215 SOC_IF_ERROR_RETURN 1216 (WRITE_PHY8750_PMA_PMD_CTRLr(unit, pc, data16)); 1217 1218 sal_usleep(3000); /* Wait for 3ms */ 1219 1220 /* Write Starting Address, where the Code will reside in SRAM */ 1221 data16 = 0xC000; 1222 SOC_IF_ERROR_RETURN 1223 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 1224 PHY8750_PMAD_M8051_MSGIN_REG, data16)); 1225 sal_udelay(20); /* Wait for 15us */ 1226 1227 /* Write SPI SRAM Count Size */ 1228 data16 = (datalen)/2; 1229 SOC_IF_ERROR_RETURN 1230 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 1231 PHY8750_PMAD_M8051_MSGIN_REG, data16)); 1232 sal_udelay(20); /* Wait for 15us */ 1233 1234 /* Fill in the SPI RAM */ 1235 for (j = 0; j < datalen/2; j++) { 1236 data16 = (array[2*j] << 8) | array[2*j+1]; 1237 SOC_IF_ERROR_RETURN 1238 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 1239 PHY8750_PMAD_M8051_MSGIN_REG, data16)); 1240 1241 /* Make sure the word is read by the Micro */ 1242 sal_udelay(20); /* Wait for 15us */ 1243 } 1244 1245 /* Read Hand-Shake message (Done) from Micro */ 1246 SOC_IF_ERROR_RETURN 1247 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 1248 PHY8750_PMAD_M8051_MSGOUT_REG, &data16)); 1249 1250 if (data16 != 0x4321) { 1251 /* Download failure */ 1252 LOG_CLI((BSL_META_U(unit, 1253 "_phy8754_mdio_firmware_download fail,p=%d done msg 0x%x\n"), 1254 port,data16)); 1255 return SOC_E_FAIL; 1256 } 1257 1258 /* Clear LASI status */ 1259 SOC_IF_ERROR_RETURN 1260 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 1261 PHY8750_PMAD_RX_ALARM_STAT_REG, &data16)); 1262 1263 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 1264 sal_udelay(400); /* Wait for 300us */ 1265 1266 /* read message out reg */ 1267 SOC_IF_ERROR_RETURN 1268 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 1269 PHY8750_PMAD_M8051_MSGOUT_REG, &data16)); 1270 1271 LOG_INFO(BSL_LS_SOC_PHY, 1272 (BSL_META_U(unit, 1273 "_phy8754_mdio_firmware_download: p=%d msgout 0x%x\n"), 1274 port,data16)); 1275 1276 /* clear LASI */ 1277 SOC_IF_ERROR_RETURN 1278 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 1279 PHY8750_PMAD_RX_ALARM_STAT_REG, &data16)); 1280 1281 SOC_IF_ERROR_RETURN 1282 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16)); 1283 1284 /* check if checksum is correct */ 1285 if (data16 != 0x600D) { 1286 /* Bad CHECKSUM */ 1287 LOG_CLI((BSL_META_U(unit, 1288 "_phy8754_mdio_firmware_download, bad cksum: " 1289 "p=%d, cksum=0x%x\n"), 1290 port, data16)); 1291 return SOC_E_FAIL; 1292 } 1293 1294 return SOC_E_NONE; 1295 } 1296 1297 /* 1298 * Function: * phy_8750_rom_wait 1299 * 1300 * Purpose: 1301 * Wait for data to be written to the SPI-ROM. 1302 * Input: 1303 * unit, port 1304 */ 1305 STATIC int 1306 phy_8750_rom_wait(int unit, int port) 1307 { 1308 uint16 rd_data; 1309 uint16 wr_data; 1310 int count; 1311 phy_ctrl_t *pc; 1312 soc_timeout_t to; 1313 int SPI_READY; 1314 1315 pc = EXT_PHY_SW_STATE(unit, port); 1316 1317 rd_data = 0; 1318 soc_timeout_init(&to, WR_TIMEOUT, 0); 1319 do { 1320 /* Write SPI Control Register Read Command. */ 1321 count = 1; 1322 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 1323 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1324 wr_data = SPI_CTRL_1_L; 1325 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1326 if (rd_data & 0x0100) { 1327 break; 1328 } 1329 } while (!soc_timeout_check(&to)); 1330 if (!(rd_data & 0x0100)) { 1331 LOG_ERROR(BSL_LS_SOC_PHY, 1332 (BSL_META_U(unit, 1333 "phy_8750_rom_program: u = %d p = %d " 1334 "timeout 1\n"), unit, port)); 1335 return SOC_E_TIMEOUT; 1336 } 1337 1338 SPI_READY = 1; 1339 while (SPI_READY == 1) { 1340 /* Set-up SPI Controller To Receive SPI EEPROM Status. */ 1341 count = 1; 1342 wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count); 1343 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1344 wr_data = SPI_CTRL_2_H; 1345 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1346 wr_data = 0x0100; 1347 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1348 /* Fill-up SPI Transmit Fifo To check SPI Status. */ 1349 count = 2; 1350 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1351 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1352 /* Write Tx Fifo Register Address. */ 1353 wr_data = SPI_TXFIFO; 1354 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1355 1356 /* Write SPI Tx Fifo Control Word-1. */ 1357 wr_data = ((1 * 0x0100) | MSGTYPE_HRD); 1358 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1359 /* Write SPI Tx Fifo Control Word-2. */ 1360 wr_data = RDSR_OPCODE; 1361 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1362 /* Write SPI Control Register Write Command. */ 1363 count = 2; 1364 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1365 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1366 /* Write SPI Control -1 Register Address. */ 1367 wr_data = SPI_CTRL_1_L; 1368 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1369 /* Write SPI Control -1 Register Word-1. */ 1370 wr_data = 0x0101; 1371 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1372 /* Write SPI Control -1 Register Word-2. */ 1373 wr_data = 0x0100; 1374 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1375 /* Write SPI Control Register Write Command. */ 1376 count = 1; 1377 wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count); 1378 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1379 /* Write SPI Control -1 Register Address. */ 1380 wr_data = SPI_CTRL_1_H; 1381 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1382 /* Write SPI Control -1 Register Word-2. */ 1383 wr_data = 0x0103; 1384 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1385 /* Wait For 64 bytes To be written. */ 1386 rd_data = 0x0000; 1387 soc_timeout_init(&to, WR_TIMEOUT, 0); 1388 do { 1389 count = 1; 1390 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 1391 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1392 wr_data = SPI_CTRL_1_L; 1393 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1394 if (rd_data & 0x0100) { 1395 break; 1396 } 1397 } while (!soc_timeout_check(&to)); 1398 if (!(rd_data & 0x0100)) { 1399 LOG_ERROR(BSL_LS_SOC_PHY, 1400 (BSL_META_U(unit, 1401 "phy_8750_rom_program: u = %d p = %d " 1402 "timeout 2\n"), unit, port)); 1403 return SOC_E_TIMEOUT; 1404 } 1405 /* Write SPI Control Register Read Command. */ 1406 count = 1; 1407 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 1408 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1409 /* Write SPI Control -1 Register Address. */ 1410 wr_data = SPI_RXFIFO; 1411 1412 SOC_IF_ERROR_RETURN 1413 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wr_data)); 1414 SOC_IF_ERROR_RETURN 1415 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data)); 1416 1417 /* Clear LASI Message Out Status. */ 1418 SOC_IF_ERROR_RETURN 1419 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9003, &wr_data)); 1420 1421 if ((rd_data & 0x1) == 0) { 1422 SPI_READY = 0; 1423 } 1424 } /* SPI_READY */ 1425 return SOC_E_NONE; 1426 } 1427 1428 1429 /* 1430 * Function: 1431 * phy_8750_rom_write_enable_set 1432 * 1433 * Purpose: 1434 * Enable disable protection on SPI_EEPROM 1435 * 1436 * Input: 1437 * unit 1438 * port 1439 * enable 1440 * Output: 1441 * SOC_E_xxx 1442 * 1443 * Notes: 1444 * 25AA256 256Kbit Serial EEPROM 1445 * STATUS Register 1446 * +------------------------------------------+ 1447 * | WPEN | x | x | x | BP1 | BP0 | WEL | WIP | 1448 * +------------------------------------------+ 1449 * BP1 BP0 : Protected Blocks 1450 * 0 0 : Protect None 1451 * 1 1 : Protect All 1452 * 1453 * WEL : Write Latch Enable 1454 * 0 : Do not allow writes 1455 * 1 : Allow writes 1456 */ 1457 1458 STATIC int 1459 phy_8750_rom_write_enable_set(int unit, int port, int enable) 1460 { 1461 uint16 rd_data; 1462 uint16 wr_data; 1463 uint8 wrsr_data; 1464 int count; 1465 phy_ctrl_t *pc; 1466 1467 pc = EXT_PHY_SW_STATE(unit, port); 1468 1469 /* 1470 * Write SPI Control Register Write Command. 1471 */ 1472 count = 2; 1473 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1474 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1475 1476 /* 1477 * Write SPI Control -2 Register Address. 1478 */ 1479 wr_data = SPI_CTRL_2_L; 1480 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1481 1482 /* 1483 * Write SPI Control -2 Register Word-1. 1484 */ 1485 wr_data = 0x8200; 1486 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1487 1488 /* 1489 * Write SPI Control -2 Register Word-2. 1490 */ 1491 wr_data = 0x0100; 1492 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1493 1494 /* 1495 * Fill-up SPI Transmit Fifo With SPI EEPROM Messages. 1496 * Write SPI Control Register Write Command. 1497 */ 1498 count = 4; 1499 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1500 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1501 1502 /* 1503 * Write Tx Fifo Register Address. 1504 */ 1505 wr_data = SPI_TXFIFO; 1506 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1507 1508 /* 1509 * Write SPI Tx Fifo Control Word-1. 1510 */ 1511 wr_data = ((1 * 0x0100) | MSGTYPE_HWR); 1512 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1513 1514 /* 1515 * Write SPI Tx Fifo Control Word-2. 1516 */ 1517 wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE); 1518 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1519 1520 /* 1521 * Write SPI Tx Fifo Control Word-3. 1522 */ 1523 wr_data = ((WRSR_OPCODE * 0x100) | (0x2)); 1524 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1525 1526 /* 1527 * Write SPI Tx Fifo Control Word-4. 1528 */ 1529 wrsr_data = enable ? 0x2 : 0xc; 1530 wr_data = ((wrsr_data * 0x0100) | wrsr_data); 1531 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1532 1533 /* 1534 * Write SPI Control Register Write Command. 1535 */ 1536 count = 2; 1537 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1538 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1539 1540 /* 1541 * Write SPI Control -1 Register Address. 1542 */ 1543 wr_data = SPI_CTRL_1_L; 1544 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1545 1546 /* 1547 * Write SPI Control -1 Register Word-1. 1548 */ 1549 wr_data = 0x0101; 1550 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1551 1552 /* 1553 * Write SPI Control -1 Register Word-2. 1554 */ 1555 wr_data = 0x0003; 1556 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1557 1558 /* 1559 * Wait For WRSR Command To be written. 1560 */ 1561 SOC_IF_ERROR_RETURN(phy_8750_rom_wait(unit, port)); 1562 1563 return SOC_E_NONE; 1564 } 1565 1566 /* 1567 * Function: 1568 * phy_8750_firmware_set 1569 * Purpose: 1570 * program the given firmware into the SPI-ROM 1571 * Parameters: 1572 * unit - StrataSwitch unit #. 1573 * port - StrataSwitch port #. 1574 * offset - offset to the data stream 1575 * array - the given data 1576 * datalen- the data length 1577 * Returns: 1578 * SOC_E_NONE 1579 */ 1580 1581 STATIC int 1582 phy_8750_firmware_set(int unit, int port, int offset, uint8 *array,int datalen) 1583 { 1584 1585 uint16 rd_data; 1586 uint16 wr_data; 1587 int j; 1588 int i = 0; 1589 int count; 1590 uint8 spi_values[WR_BLOCK_SIZE]; 1591 uint8 phy_id; 1592 uint16 chip_id; 1593 phy_ctrl_t *pc; 1594 1595 pc = EXT_PHY_SW_STATE(unit, port); 1596 phy_id = pc->phy_id; 1597 1598 /* Read Chip IDs */ 1599 SOC_IF_ERROR_RETURN 1600 (READ_PHY8750_PMA_PMD_CHIPIDr(unit, pc, &chip_id)); 1601 if (chip_id == 0x8754) { 1602 /* 1603 * Place all Micros in reset, GEN_CTRL 1604 * CAVEAT: 1605 * To eliminate the interference with SPI Programming process 1606 * it is required to reset the MicroController in adjacent odd port. 1607 * i.e. if you are programming channel-0(2) of the 8754 then you need 1608 * to reset the microcontroller of channel-1(3). 1609 * The instruction below reset all channels in 8754. 1610 */ 1611 phy_id = pc->phy_id; 1612 for (i = 0; i < 4; i++) { 1613 pc->phy_id = (phy_id & (~3)) + i; /* Port 3, 2, 1 and 0 */ 1614 SOC_IF_ERROR_RETURN 1615 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x018f)); 1616 } 1617 pc->phy_id = phy_id; /* restore original phy_id */ 1618 1619 /* 1620 * Disable all port's SPI 1621 * CAVEAT: 1622 * Always disable all ports associated with the 1623 * SPI you are programming. 1624 */ 1625 /* 1626 * Write to register 0x1.C843 bits 3:0 to 4'b1111 1627 */ 1628 phy_id = pc->phy_id; 1629 for (i = 0; i < 4; i++) { 1630 pc->phy_id = (phy_id & (~3)) + i; /* Port 3, 2, 1 and 0 */ 1631 SOC_IF_ERROR_RETURN 1632 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x000f)); 1633 } 1634 pc->phy_id = phy_id; /* restore original phy_id */ 1635 1636 /* 1637 * Write to register 0x1.C840 bits 3:2 to 2'b11. 1638 */ 1639 phy_id = pc->phy_id; 1640 for (i = 0; i < 4; i++) { 1641 pc->phy_id = (phy_id & (~3)) + i; /* Port 3, 2, 1 and 0 */ 1642 SOC_IF_ERROR_RETURN 1643 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x000c)); 1644 } 1645 pc->phy_id = phy_id; 1646 1647 /* 1648 * Enable SPI for Port0 1649 */ 1650 SOC_IF_ERROR_RETURN 1651 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x0000)); 1652 SOC_IF_ERROR_RETURN 1653 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x0000)); 1654 /* 1655 * Remove M8051 resets for port 0. 1656 * and wait for Micro to complete Init. 1657 */ 1658 SOC_IF_ERROR_RETURN 1659 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x0188)); 1660 sal_usleep(10000); 1661 1662 /* 1663 * Set bit 0 (spa enable) in C848 for master channel. 1664 */ 1665 phy_id = pc->phy_id; 1666 for (i = 0; i < 4; i++) { 1667 pc->phy_id = (phy_id & (~3)) + i; /* Port 3, 2, 1 and 0 */ 1668 SOC_IF_ERROR_RETURN 1669 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0x80f9)); 1670 } 1671 pc->phy_id = phy_id; 1672 } 1673 1674 /* 1675 * Enable SPI ROM access in SPI control 1676 */ 1677 if (chip_id == 0x8754) { 1678 SOC_IF_ERROR_RETURN 1679 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0xc0fd)); 1680 } else { 1681 SOC_IF_ERROR_RETURN 1682 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0x80fd)); 1683 } 1684 1685 /* 1686 * ser_boot pin HIGH 1687 */ 1688 SOC_IF_ERROR_RETURN 1689 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA85, 0x1, 0x1)); 1690 /* 1691 * Read LASI Status registers To clear initial Failure status. 1692 */ 1693 SOC_IF_ERROR_RETURN 1694 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data)); 1695 SOC_IF_ERROR_RETURN 1696 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9004, &rd_data)); 1697 SOC_IF_ERROR_RETURN 1698 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9005, &rd_data)); 1699 1700 /* 1701 * Enable the LASI For Message out. 1702 */ 1703 SOC_IF_ERROR_RETURN 1704 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9000, 0x0004)); 1705 /* 1706 * 0x9002, bit 2 Is Rx Alarm enabled For LASI. 1707 */ 1708 SOC_IF_ERROR_RETURN 1709 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9002, 0x0004)); 1710 /* 1711 * Read Any Residual Message out register. 1712 */ 1713 SOC_IF_ERROR_RETURN 1714 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data)); 1715 /* 1716 * Clear LASI Message Out Status. 1717 */ 1718 SOC_IF_ERROR_RETURN 1719 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data)); 1720 1721 /* set SPI-ROM write enable */ 1722 SOC_IF_ERROR_RETURN(phy_8750_rom_write_enable_set(unit, port, 1)); 1723 1724 LOG_INFO(BSL_LS_SOC_PHY, 1725 (BSL_META_U(unit, 1726 "init0: u=%d p=%d\n"), 1727 unit, port)); 1728 1729 for (j = 0; j < datalen; j += WR_BLOCK_SIZE) { 1730 /* 1731 * Setup SPI Controller. 1732 */ 1733 count = 2; 1734 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1735 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1736 1737 /* Write SPI Control -2 Register Address.*/ 1738 wr_data = SPI_CTRL_2_L; 1739 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1740 1741 /* Write SPI Control -2 Register Word-1. */ 1742 wr_data = 0x8200; 1743 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1744 1745 /* Write SPI Control -2 Register Word-2. */ 1746 wr_data = 0x0100; 1747 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1748 1749 /* Fill-up SPI Transmit Fifo. 1750 * Write SPI Control Register Write Command. 1751 */ 1752 count = 4 + (WR_BLOCK_SIZE / 2); 1753 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1754 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1755 1756 /* Write Tx Fifo Register Address. */ 1757 wr_data = SPI_TXFIFO; 1758 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1759 1760 /* Write SPI Tx Fifo Control Word-1. */ 1761 wr_data = ((1 * 0x0100) | MSGTYPE_HWR); 1762 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1763 1764 /* Write SPI Tx Fifo Control Word-2. */ 1765 wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE); 1766 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1767 1768 /* Write SPI Tx Fifo Control Word-3. */ 1769 wr_data = ((WR_OPCODE * 0x0100) | (0x3 + WR_BLOCK_SIZE)); 1770 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1771 1772 /* Write SPI Tx Fifo Control Word-4. */ 1773 wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100)); 1774 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1775 1776 LOG_INFO(BSL_LS_SOC_PHY, 1777 (BSL_META_U(unit, 1778 "loop: u=%d p=%d,inxj: %d,inxi:%d\n"), 1779 unit, port,j,i)); 1780 1781 if (datalen < (j + WR_BLOCK_SIZE)) { /* last block */ 1782 sal_memset(spi_values,0,WR_BLOCK_SIZE); 1783 sal_memcpy(spi_values,&array[j],datalen - j); 1784 1785 for (i = 0; i < WR_BLOCK_SIZE; i += 2) { 1786 /* Write SPI Tx Fifo Data Word-4. */ 1787 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]); 1788 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data)); 1789 } 1790 } else { 1791 for (i = 0; i < WR_BLOCK_SIZE; i += 2) { 1792 /* Write SPI Tx Fifo Data Word-4. */ 1793 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]); 1794 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data)); 1795 } 1796 } 1797 1798 /* 1799 * Set-up SPI Controller To Transmit. 1800 * Write SPI Control Register Write Command. 1801 */ 1802 count = 2; 1803 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1804 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1805 1806 wr_data = SPI_CTRL_1_L; 1807 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1808 1809 /* Write SPI Control -1 Register Word-1. */ 1810 wr_data = 0x0501; 1811 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1812 1813 /* Write SPI Control -1 Register Word-2. */ 1814 wr_data = 0x0003; 1815 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1816 1817 /* Wait For 64 bytes To be written. */ 1818 SOC_IF_ERROR_RETURN(phy_8750_rom_wait(unit,port)); 1819 1820 } /* SPI_WRITE */ 1821 1822 /* clear SPI-ROM write enable */ 1823 SOC_IF_ERROR_RETURN(phy_8750_rom_write_enable_set(unit, port, 0)); 1824 1825 /* Disable SPI EEPROM. */ 1826 count = 2; 1827 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1828 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1829 1830 /* Write SPI Control -2 Register Address. */ 1831 wr_data = SPI_CTRL_2_L; 1832 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1833 1834 /* Write SPI Control -2 Register Word-1. */ 1835 wr_data = 0x8200; 1836 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1837 1838 /* Write SPI Control -2 Register Word-2. */ 1839 wr_data = 0x0100; 1840 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1841 1842 1843 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */ 1844 count = 2; 1845 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1846 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1847 1848 /* Write Tx Fifo Register Address. */ 1849 wr_data = SPI_TXFIFO; 1850 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1851 1852 /* Write SPI Tx Fifo Control Word-1. */ 1853 wr_data = ((0x1*0x0100) | MSGTYPE_HWR); 1854 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1855 1856 /* Write SPI Tx Fifo Control Word-2. */ 1857 wr_data = WRDI_OPCODE; 1858 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1859 1860 /* Write SPI Control Register Write Command. */ 1861 count = 2; 1862 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 1863 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1864 1865 /* Write SPI Control -1 Register Address. */ 1866 wr_data = SPI_CTRL_1_L; 1867 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1868 1869 /* Write SPI Control -1 Register Word-1. */ 1870 wr_data = 0x0101; 1871 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1872 1873 /* Write SPI Control -1 Register Word-2. */ 1874 wr_data = 0x0003; 1875 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 1876 1877 /* 1878 * ser_boot pin LOW 1879 */ 1880 SOC_IF_ERROR_RETURN 1881 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA85, 0x0, 0x1)); 1882 /* 1883 * Disable SPI ROM access in SPI control 1884 */ 1885 SOC_IF_ERROR_RETURN 1886 (MODIFY_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0xc0fd, 0xffff)); 1887 1888 LOG_INFO(BSL_LS_SOC_PHY, 1889 (BSL_META_U(unit, 1890 "phy_8750_rom_program: u=%d p=%d done\n"), unit, port)); 1891 1892 return SOC_E_NONE; 1893 } 1894 1895 static int 1896 write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata) 1897 { 1898 1899 uint16 tmp_data = 0; 1900 soc_timeout_t to; 1901 1902 SOC_IF_ERROR_RETURN 1903 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data)); 1904 SOC_IF_ERROR_RETURN 1905 (WRITE_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wrdata)); 1906 1907 soc_timeout_init(&to, WR_TIMEOUT, 0); 1908 do { 1909 SOC_IF_ERROR_RETURN 1910 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9005, &tmp_data)); 1911 if (tmp_data & 0x4) 1912 break; 1913 } while (!soc_timeout_check(&to)); 1914 if (!(tmp_data & 0x4)) { 1915 LOG_ERROR(BSL_LS_SOC_PHY, 1916 (BSL_META_U(unit, 1917 "write_message failed: wrdata %04x\n"), wrdata)); 1918 return SOC_E_FAIL; 1919 } 1920 1921 SOC_IF_ERROR_RETURN 1922 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data)); 1923 *rddata = tmp_data; 1924 SOC_IF_ERROR_RETURN 1925 (READ_PHY8750_MMF_PMA_PMD_REG(unit, pc, 0x9003, &tmp_data)); 1926 1927 return SOC_E_NONE; 1928 } 1929 /* 1930 * Function: 1931 * phy_8750_probe 1932 * Purpose: 1933 * Complement the generic phy probe routine to identify this phy when its 1934 * phy id0 and id1 is same as some other phy's. 1935 * Parameters: 1936 * unit - StrataSwitch unit #. 1937 * pc - phy ctrl descriptor. 1938 * Returns: 1939 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 1940 */ 1941 STATIC int 1942 phy_8750_probe(int unit, phy_ctrl_t *pc) 1943 { 1944 pc->size = sizeof(PHY8750_DEV_DESC_t); 1945 return SOC_E_NONE; 1946 } 1947 1948 1949 /* 1950 * Variable: 1951 * phy_8750_drv 1952 * Purpose: 1953 * Phy Driver for 10G XFI to SFI PHY. 1954 */ 1955 1956 phy_driver_t phy_8750drv_xe = { 1957 "8750 10-Gigabit PHY Driver", 1958 phy_8750_init, /* Init */ 1959 phy_null_reset, /* Reset (dummy) */ 1960 phy_8750_link_get, /* Link get */ 1961 phy_8750_enable_set, /* Enable set */ 1962 phy_null_enable_get, /* Enable get */ 1963 phy_null_set, /* Duplex set */ 1964 phy_null_one_get, /* Duplex get */ 1965 phy_8750_speed_set, /* Speed set */ 1966 phy_8750_speed_get, /* Speed get */ 1967 phy_null_set, /* Master set */ 1968 phy_null_zero_get, /* Master get */ 1969 phy_8750_an_set, /* ANA set */ 1970 phy_8750_an_get, /* ANA get */ 1971 NULL, /* Local Advert set */ 1972 NULL, /* Local Advert get */ 1973 phy_null_mode_get, /* Remote Advert get */ 1974 phy_8750_lb_set, /* PHY loopback set */ 1975 phy_8750_lb_get, /* PHY loopback set */ 1976 phy_null_interface_set, /* IO Interface set */ 1977 phy_xehg_interface_get, /* IO Interface get */ 1978 NULL, /* PHY abilities mask */ 1979 NULL, 1980 NULL, 1981 phy_null_mdix_set, 1982 phy_null_mdix_get, 1983 phy_null_mdix_status_get, 1984 NULL, 1985 NULL, 1986 phy_null_medium_get, 1987 NULL, /* phy_cable_diag */ 1988 NULL, /* phy_link_change */ 1989 phy_8750_control_set, /* phy_control_set */ 1990 phy_8750_control_get, /* phy_control_get */ 1991 NULL, /* phy_reg_read */ 1992 NULL, /* phy_reg_write */ 1993 NULL, /* phy_reg_modify */ 1994 NULL, /* phy_notify */ 1995 phy_8750_probe, /* pd_probe */ 1996 phy_8750_ability_advert_set, /* pd_ability_advert_set */ 1997 phy_8750_ability_advert_get, /* pd_ability_advert_get */ 1998 phy_8750_ability_remote_get, /* pd_ability_remote_get */ 1999 phy_8750_ability_local_get, /* pd_ability_local_get */ 2000 phy_8750_firmware_set /* pd_firmware_set */ 2001 }; 2002 2003 #else /* INCLUDE_PHY_8750 */ 2004 int _phy_8750_not_empty; 2005 #endif /* INCLUDE_PHY_8750 */ 2006