phy84756_fcmap.c (463541B)
1 2 3 /* 4 * 5 * 6 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 7 * 8 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 9 * 10 * File: phy84756.c 11 * Purpose: SDK PHY driver for BCM84756 (FCMAP) 12 * 13 * Supported BCM546X Family of PHY devices: 14 * 15 * Device Ports Media MAC Interface 16 * 84756 4 4 10G SFP+ XFI 17 * 84757 4 4 10G SFP+/8(4/2) FC XFI 18 * 84759 4 4 10G SFP+ XFI 19 * 20 * OUI Model Revision 21 * BCM84756 18-C0-86 100111 00xx 22 * BCM84757 18-C0-86 100111 10xx 23 * BCM84759 18-C0-86 100111 01xx 24 * 25 * 26 * Workarounds: 27 * 28 * References: 29 * 30 * Notes: 31 */ 32 33 34 #include <sal/types.h> 35 #include <sal/core/spl.h> 36 #include <shared/bsl.h> 37 #include <soc/drv.h> 38 #include <soc/debug.h> 39 #include <soc/error.h> 40 #include <soc/phyreg.h> 41 42 #include <soc/phy.h> 43 #include <soc/phy/phyctrl.h> 44 #include <soc/phy/drv.h> 45 46 #include "phydefs.h" /* Must include before other phy related includes */ 47 48 49 50 #if defined(INCLUDE_FCMAP) || defined(INCLUDE_MACSEC) 51 #if defined(INCLUDE_PHY_84756) 52 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 53 #include "phyident.h" 54 #include "phyreg.h" 55 #include "phynull.h" 56 #include "phyfege.h" 57 #include "phyxehg.h" 58 59 #if defined(INCLUDE_FCMAP) 60 #include <soc/fcmapphy.h> 61 #endif 62 #if defined(INCLUDE_MACSEC) 63 #include <soc/macsecphy.h> 64 #endif 65 #include "phy_mac_ctrl.h" 66 #include "phy_xmac.h" 67 #include "phy84756_fcmap_int.h" 68 #include "phy84756_fcmap.h" 69 #include "phy84756_i2c.h" 70 #if defined(INCLUDE_FCMAP) 71 #include <bfcmap_int.h> 72 #include <bfcmap_io.h> 73 #endif 74 75 #define ADVERT_ALL_COPPER \ 76 (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \ 77 SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB) 78 79 #define ADVERT_ALL_FIBER \ 80 (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 81 82 #define ADVERT_ALL_10GFIBER \ 83 (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 84 85 #define PHY84756_REG_READ(_unit, _phy_ctrl, _addr, _val) \ 86 READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val)) 87 88 #define PHY84756_REG_WRITE(_unit, _phy_ctrl, _addr, _val) \ 89 WRITE_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val)) 90 91 #define READ_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 92 PHY84756_REG_READ((_unit), (_phy_ctrl), \ 93 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 94 95 #define WRITE_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 96 PHY84756_REG_WRITE((_unit), (_phy_ctrl), \ 97 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 98 99 100 #define BFCMAP_PHY84756_LINE_MAC_PORT(p) (p) 101 #define BFCMAP_PHY84756_SWITCH_MAC_PORT(p) ((p) + 1) 102 103 #define PHY84756_XFI(unit,_pc)\ 104 BFCMAP_PHY84756_IO_MDIO_WRITE((_pc), BLMI_IO_CL45_ADDRESS(1, 0xffff), 0x1) 105 106 #define PHY84756_MMF(unit,_pc)\ 107 BFCMAP_PHY84756_IO_MDIO_WRITE((_pc), BLMI_IO_CL45_ADDRESS(1, 0xffff), 0x0) 108 109 110 /* 40G support macros */ 111 #undef _PHY_CALL 112 #define _PHY_CALL(_pd, _pf, _pa) \ 113 ((_pd)->_pf == 0 ? SOC_E_UNAVAIL : (_pd)->_pf _pa) 114 115 extern phy_driver_t phy_84741drv_xe; 116 #define PHY84756_40G (&phy_84741drv_xe) 117 #define PHY84756_SINGLE_PORT_MODE(_pc) \ 118 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4) 119 #define PHY84756_IS_8474X(_pc) ((_pc)->size > sizeof(phy84756_map_t)) 120 #define PHY84756_CALL_IF_SINGLE_PORT(_u, _p, _func) \ 121 do { \ 122 int _rv; \ 123 phy_ctrl_t *_pc = EXT_PHY_SW_STATE((_u), (_p)); \ 124 if (PHY84756_IS_8474X(_pc) && \ 125 PHY84756_SINGLE_PORT_MODE(_pc)) { \ 126 _rv = (_func); \ 127 return _rv; \ 128 } \ 129 } while (0) 130 131 #define PHY84756_CALL_IF_8474X(_u, _p, _func) \ 132 do { \ 133 phy_ctrl_t *_pc = EXT_PHY_SW_STATE((_u), (_p)); \ 134 int _sav; \ 135 if (PHY84756_IS_8474X(_pc)) {\ 136 _sav = PHYCTRL_INIT_STATE(_pc);\ 137 SOC_IF_ERROR_RETURN(_func); \ 138 if (PHY84756_SINGLE_PORT_MODE(_pc)) { \ 139 return SOC_E_NONE; \ 140 }\ 141 PHYCTRL_INIT_STATE_SET(_pc, _sav);\ 142 } \ 143 } while (0) 144 145 #define PHY84756_PMAD_CHIP_MODE_MASK 0x3 146 #define PHY84756_PMAD_DAC_MODE_MASK (1 << 3) 147 #define PHY84756_PMAD_BKPLANE_MODE_MASK (1 << 2) 148 #define PHY84756_PMAD_DAC_MODE 0x8 149 #define PHY84756_PMAD_MODE_40G 0x1 150 #define NUM_LANES 4 151 STATIC int 152 _phy_84741_squelch_enable(int unit, soc_port_t port, int intf, int enable, int force); 153 STATIC int 154 _phy_84741_single_to_quad_mode(int unit,soc_port_t port, phy_ctrl_t *pc); 155 156 STATIC int 157 phy_84756_macsec_enable(int unit, int lport, int enable); 158 159 /* 160 * PHY Map structure for mapping mac drivers 161 */ 162 typedef struct phy84756_map_s { 163 bfcmap_phy84756_intf_t line_mode; /* configured line mode */ 164 phy_mac_ctrl_t *unimac; 165 phy_mac_ctrl_t *xmac; 166 int phy_ext_rom_boot; 167 int fcmap_enable; 168 int macsec_enable; 169 int macsec_support; 170 int fiber_force_speed; 171 int skip_fw_download; 172 int chip_rev_id; 173 uint8 *firmware; 174 int firmware_len; 175 }phy84756_map_t; 176 177 /* 178 * PHY MDIO Address, Device Address and Device Port Mapping table 179 */ 180 #define PHY84756_PHY_INFO(_pc) \ 181 ((phy84756_map_t *)(((char *)((_pc) + 1))+(_pc)->size-sizeof(phy84756_map_t))) 182 183 #define PHY_EXT_ROM_BOOT(_pc) ((PHY84756_PHY_INFO(_pc))->phy_ext_rom_boot) 184 #define FCMAP_ENABLE(_pc) ((PHY84756_PHY_INFO(_pc))->fcmap_enable) 185 #define MACSEC_ENABLE(_pc) ((PHY84756_PHY_INFO(_pc))->macsec_enable) 186 #define MACSEC_SUPPORT(_pc) ((PHY84756_PHY_INFO(_pc))->macsec_support) 187 188 #define FIBER_FORCE_SPEED(_pc) ((PHY84756_PHY_INFO(_pc))->fiber_force_speed) 189 #define SKIP_EDC_FW_DOWNLOAD(_pc) ((PHY84756_PHY_INFO(_pc))->skip_fw_download) 190 #define FIRMWARE(_pc) ((PHY84756_PHY_INFO(_pc))->firmware) 191 #define FIRMWARE_LEN(_pc) ((PHY84756_PHY_INFO(_pc))->firmware_len) 192 #define CHIP_REV_ID(_pc) ((PHY84756_PHY_INFO(_pc))->chip_rev_id) 193 194 #define CHIP_IS_A0(_pc) (CHIP_REV_ID(_pc) == 0xa0a0) 195 #define CHIP_IS_B0(_pc) (CHIP_REV_ID(_pc) == 0xb0b0) 196 #define CHIP_IS_C0(_pc) (CHIP_REV_ID(_pc) == 0xc0c0 || CHIP_REV_ID(_pc) == 0xc1c1 || CHIP_REV_ID(_pc) == 0xc2c2) 197 /*#define CHIP_IS_C0(_pc) \ 198 ((PHY_REV((_pc)->phy_id0, (_pc)->phy_id1) & 0xe) == 0xa ) 199 */ 200 201 /* OUI from ID0 and ID1 registers contents */ 202 #define BFCMAP_PHY84756_PHY_OUI(id0, id1) \ 203 bfcmap_phy84756_bit_rev_by_byte_word32((buint32_t)(id0) << 6 | \ 204 ((id1) >> 10 & 0x3f)) 205 206 /* PHY model from ID0 and ID1 register Contents */ 207 #define BFCMAP_PHY84756_PHY_MODEL(id0, id1) ((id1) >> 4 & 0x3f) 208 209 /* PHY revision from ID0 and ID1 register Contents */ 210 #define BFCMAP_PHY84756_PHY_REV(id0, id1) ((id1) & 0xf) 211 212 #define PHY84756_EDC_MODE_MASK 0xff 213 /* PRBS */ 214 #define PHY84756_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS 0x0135 215 #define PHY84756_40G_PRBS31 (1 << 7) 216 #define PHY84756_40G_PRBS9 (1 << 6) 217 #define PHY84756_40G_PRBS_TX_ENABLE (1 << 3) 218 #define PHY84756_40G_PRBS_RX_ENABLE (1 << 0) 219 #define PHY84756_40G_PRBS_ENABLE (PHY84756_40G_PRBS_RX_ENABLE | \ 220 PHY84756_40G_PRBS_TX_ENABLE) 221 222 #define PHY84756_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0 0x0140 223 #define PHY84756_USER_PRBS_CONTROL_0_REGISTER 0xCD14 224 #define PHY84756_USER_PRBS_TX_INVERT (1 << 4) 225 #define PHY84756_USER_PRBS_RX_INVERT (1 << 15) 226 #define PHY84756_USER_PRBS_INVERT (1 << 4 | 1 << 15) 227 #define PHY84756_USER_PRBS_ENABLE (1 << 7) 228 #define PHY84756_USER_PRBS_TYPE_MASK (0x7) 229 #define PHY84756_USER_PRBS_TYPE_MASK_1G (0x3) 230 231 #define PHY84756_USER_PRBS_STATUS_0_REGISTER 0xCD15 232 #define PHY84756_GENSIG_8071_REGISTER 0xCD16 233 #define PHY84756_RESET_CONTROL_REGISTER 0xCD17 234 235 /* Speed/Val Map */ 236 #define SP_MAP(_s,_v)\ 237 ((_s) == 1000 ? ((_v) - (((_v) >= 3) ? 3 : 1)) : (_v)) 238 239 /* Disable Comma Detect and CL36 */ 240 #define PHY84756_1G_PRBS_XGXS_CTRL 0x2c2e 241 #define PHY84756_1G_PRBS_LANE_CTRL2 0xff00 242 #define PHY84756_1G_PRBS_LANE_CTRL0 0x0011 243 #define PHY84756_1G_USER_PRBS_TX_INVERT (1 << 2) 244 245 /* preemphasis control */ 246 #define PHY84756_PREEMPH_CTRL_FORCE_SHFT 15 247 #define PHY84756_PREEMPH_GET_FORCE(_val) \ 248 (((_val) >> PHY84756_PREEMPH_CTRL_FORCE_SHFT) & 1) 249 #define PHY84756_PREEMPH_CTRL_POST_TAP_SHFT 10 250 #define PHY84756_PREEMPH_GET_POST_TAP(_val) \ 251 (((_val) >> PHY84756_PREEMPH_CTRL_POST_TAP_SHFT) & 0x1f) 252 #define PHY84756_PREEMPH_CTRL_MAIN_TAP_SHFT 4 253 #define PHY84756_PREEMPH_GET_MAIN_TAP(_val) \ 254 (((_val) >> PHY84756_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f) 255 #define PHY84756_PREEMPH_REG_FORCE_MASK (1 << 15) 256 #define PHY84756_PREEMPH_REG_POST_TAP_SHFT 4 257 #define PHY84756_PREEMPH_REG_POST_TAP_MASK (0xf << PHY84756_PREEMPH_REG_POST_TAP_SHFT) 258 #define PHY84756_PREEMPH_REG_MAIN_TAP_SHFT 11 259 #define PHY84756_PREEMPH_REG_MAIN_TAP_MASK (0x1f << PHY84756_PREEMPH_REG_MAIN_TAP_SHFT) 260 #define PHY84756_PREEMPH_REG_TX_PWRDN_MASK (0x1 << 10) 261 #define PHY84756_PDET_MASK (1 << 0) 262 /* 263 * Function: 264 * bfcmap_bit_rev_by_byte_word32 265 * Purpose: 266 * Reverse the bits in each byte of a 32 bit long 267 * Parameters: 268 * n - 32bit input 269 * Notes: 270 */ 271 STATIC buint32_t 272 bfcmap_phy84756_bit_rev_by_byte_word32(buint32_t n) 273 { 274 n = (((n & 0xaaaaaaaa) >> 1) | ((n & 0x55555555) << 1)); 275 n = (((n & 0xcccccccc) >> 2) | ((n & 0x33333333) << 2)); 276 n = (((n & 0xf0f0f0f0) >> 4) | ((n & 0x0f0f0f0f) << 4)); 277 return n; 278 } 279 280 /* Structure used to communicate with the event handler */ 281 typedef struct _phy84756_fcmap_event_callback_data_s{ 282 int unit; 283 soc_port_t port; 284 int link; 285 }_phy84756_fcmap_event_callback_data_t; 286 287 STATIC int phy_84756_fcmap_init(int unit, soc_port_t port); 288 STATIC int phy_84756_fcmap_link_get(int unit, soc_port_t port, int *link); 289 STATIC int phy_84756_fcmap_linkfault_get(int unit, soc_port_t port, int *fault); 290 STATIC int phy_84756_fcmap_enable_set(int unit, soc_port_t port, int enable); 291 STATIC int phy_84756_fcmap_duplex_set(int unit, soc_port_t port, int duplex); 292 STATIC int phy_84756_fcmap_duplex_get(int unit, soc_port_t port, int *duplex); 293 STATIC int phy_84756_fcmap_speed_set(int unit, soc_port_t port, int speed); 294 STATIC int phy_84756_fcmap_speed_get(int unit, soc_port_t port, int *speed); 295 STATIC int phy_84756_fcmap_an_set(int unit, soc_port_t port, int autoneg); 296 STATIC int phy_84756_fcmap_an_get(int unit, soc_port_t port, 297 int *autoneg, int *autoneg_done); 298 STATIC int phy_84756_fcmap_lb_set(int unit, soc_port_t port, int enable); 299 STATIC int phy_84756_fcmap_lb_get(int unit, soc_port_t port, int *enable); 300 STATIC int phy_84756_fcmap_ability_advert_set(int unit, soc_port_t port, 301 soc_port_ability_t *ability); 302 STATIC int phy_84756_fcmap_ability_advert_get(int unit, soc_port_t port, 303 soc_port_ability_t *ability); 304 STATIC int phy_84756_fcmap_ability_remote_get(int unit, soc_port_t port, 305 soc_port_ability_t *ability); 306 STATIC int phy_84756_fcmap_ability_local_get(int unit, soc_port_t port, 307 soc_port_ability_t *ability); 308 STATIC int phy_84756_fcmap_firmware_set(int unit, int port, int offset, 309 uint8 *data, int len); 310 STATIC int phy_84756_fcmap_control_set(int unit, soc_port_t port, 311 soc_phy_control_t type, uint32 value); 312 STATIC int phy_84756_fcmap_control_get(int unit, soc_port_t port, 313 soc_phy_control_t type, uint32 *value); 314 STATIC int phy_84756_fcmap_linkup(int unit, soc_port_t port); 315 316 STATIC int phy_84756_fcmap_reg_read(int unit, soc_port_t port, uint32 flags, 317 uint32 phy_reg_addr, uint32 *phy_data); 318 319 STATIC int phy_84756_fcmap_reg_write(int unit, soc_port_t port, uint32 flags, 320 uint32 phy_reg_addr, uint32 phy_data); 321 STATIC int 322 phy_84756_fcmap_squelch_enable(int unit, soc_port_t port, int intf, int enable, int force); 323 STATIC int 324 _bfcmap_phy84756_system_sgmii_init(phy_ctrl_t *pc, int dev_port); 325 STATIC int 326 _bfcmap_phy84756_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port, int duplex); 327 STATIC int 328 _bfcmap_phy84756_system_sgmii_sync(phy_ctrl_t *pc, int dev_port); 329 330 extern buint8_t bcm84756_fw[]; 331 extern buint32_t bcm84756_fw_length; 332 extern buint8_t bcm84756_b0_fw[]; 333 extern buint32_t bcm84756_b0_fw_length; 334 335 /* 336 * Function: 337 * _phy84756_system_xfi_speed_set 338 * Purpose: 339 * To set system side SGMII speed 340 * Parameters: 341 * phy_id - PHY's device address 342 * speed - Speed to set 343 * 100000 = 10Gbps 344 * Returns: 345 */ 346 static int 347 _phy84756_system_xfi_speed_set(phy_ctrl_t *pc, int dev_port, int speed) 348 { 349 if (speed != 10000) { 350 return SOC_E_CONFIG; 351 } 352 /* Disable Clause 37 Autoneg */ 353 SOC_IF_ERROR_RETURN( 354 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0, 355 BFCMAP_PHY84756_AN_MII_CTRL_AE)); 356 /* Force Speed in PDM */ 357 SOC_IF_ERROR_RETURN( 358 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 359 BFCMAP_PHY84756_PMD_CTRL_SS_10000, 360 BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK)); 361 return SOC_E_NONE; 362 } 363 364 /* 365 * Function: 366 * _phy_84756_fcmap_medium_config_update 367 * Purpose: 368 * Update the PHY with config parameters 369 * Parameters: 370 * unit - StrataSwitch unit #. 371 * port - StrataSwitch port #. 372 * cfg - Config structure. 373 * Returns: 374 * SOC_E_XXX 375 */ 376 377 STATIC int 378 _phy_84756_fcmap_medium_config_update(int unit, soc_port_t port, 379 soc_phy_config_t *cfg) 380 { 381 382 SOC_IF_ERROR_RETURN 383 (phy_84756_fcmap_speed_set(unit, port, cfg->force_speed)); 384 SOC_IF_ERROR_RETURN 385 (phy_84756_fcmap_duplex_set(unit, port, cfg->force_duplex)); 386 SOC_IF_ERROR_RETURN 387 (phy_84756_fcmap_ability_advert_set(unit, port, &cfg->advert_ability)); 388 SOC_IF_ERROR_RETURN 389 (phy_84756_fcmap_an_set(unit, port, cfg->autoneg_enable)); 390 391 return SOC_E_NONE; 392 } 393 394 STATIC int 395 _phy_84756_fcmap_firmware_is_downloaded(int unit, soc_port_t port) 396 { 397 int rv = 0; 398 uint16 data16; 399 phy_ctrl_t *pc; 400 401 pc = EXT_PHY_SW_STATE(unit, port); 402 403 if (soc_property_port_get(unit, port,spn_PHY_FORCE_FIRMWARE_LOAD, TRUE)) { 404 return 0; 405 } 406 407 /* 408 * To determine whether the firmware has been downloaded, it must 409 * pass the following: 410 * 1. firmware is in RAM: 1.c848.13==1 411 * 2. expected checksum: 1.ca1c==600d 412 * 3. version is non-zero: 1.ca1a!=0 413 */ 414 415 /* 1. Firmware download status */ 416 rv = BFCMAP_RD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, &data16); 417 if (rv != SOC_E_NONE) { 418 return 0; 419 } 420 if (PHY_EXT_ROM_BOOT(pc)) { 421 if ((data16 & 0xa000) != 0xa000) { 422 return 0; 423 } 424 } else if ((data16 & 0x6000) != 0x6000) { 425 return 0; 426 } 427 LOG_INFO(BSL_LS_SOC_PHY, 428 (BSL_META_U(unit, 429 "84756 FW download status=%x: u=%d p=%d\n"), data16, unit, port)); 430 431 /* 2. Expected checksum */ 432 rv = BFCMAP_RD_PHY84756_LN_DEV1_CHECKSUMr(pc, &data16); 433 if ((rv != SOC_E_NONE) || (data16 != BFCMAP_PHY84756_FW_CHECKSUM)) { 434 return 0; 435 } 436 LOG_INFO(BSL_LS_SOC_PHY, 437 (BSL_META_U(unit, 438 "84756 FW checksum=%x: u=%d p=%d\n"), data16, unit, port)); 439 440 /* 3. non-zero version */ 441 rv = BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &data16); 442 if ((rv != SOC_E_NONE) || (data16 == 0)) { 443 return 0; 444 } 445 LOG_INFO(BSL_LS_SOC_PHY, 446 (BSL_META_U(unit, 447 "84756 FW version=%x: u=%d p=%d\n"), data16, unit, port)); 448 449 return 1; 450 } 451 452 /* Function: 453 * phy_84756_fcmap_init 454 * Purpose: 455 * Initialize 84756 phys 456 * Parameters: 457 * unit - StrataSwitch unit #. 458 * port - StrataSwitch port #. 459 * Returns: 460 * SOC_E_NONE 461 */ 462 463 /* 464 * ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP = 1: always download FC uCode at power-up 465 * ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP = 0: Download FC uCode at power-up only if at least one of the ports in the same mdio bus is FC enabled 466 */ 467 #define ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP 0 468 469 STATIC int 470 phy_84756_fcmap_init(int unit, soc_port_t port) 471 { 472 phy_ctrl_t *pc; 473 int rv = SOC_E_NONE; 474 buint16_t data; 475 476 pc = EXT_PHY_SW_STATE(unit, port); 477 478 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT || 479 PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1 ) { 480 int mmi_mdio_addr; 481 482 LOG_INFO(BSL_LS_SOC_PHY, 483 (BSL_META_U(unit, 484 "phy_84756_fcmap_init PASS1: u=%d p=%d\n"),unit, port)); 485 486 sal_memset(PHY84756_PHY_INFO(pc), 0, sizeof(phy84756_map_t)); 487 488 489 490 FCMAP_ENABLE(pc) = soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0); 491 492 MACSEC_ENABLE(pc) = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0); 493 494 /* Save chip rev */ 495 SOC_IF_ERROR_RETURN( 496 BFCMAP_RD_PHY84756_LN_DEV1_CHIP_REVr(pc, &data)); 497 CHIP_REV_ID(pc) = data; 498 499 if (CHIP_IS_A0(pc)) { 500 /* this firmware is used by A0 */ 501 FIRMWARE(pc) = bcm84756_fw; 502 FIRMWARE_LEN(pc) = bcm84756_fw_length; 503 } else { 504 /* this firmware is used by B0 and C0 */ 505 FIRMWARE(pc) = bcm84756_b0_fw; 506 FIRMWARE_LEN(pc) = bcm84756_b0_fw_length; 507 } 508 509 MACSEC_SUPPORT(pc) = 0; 510 511 #if defined(INCLUDE_FCMAP) 512 if (!FCMAP_ENABLE(pc)) { 513 /* Call 40G Init */ 514 PHY84756_CALL_IF_8474X(unit,port, 515 PHY_INIT(PHY84756_40G, unit, port)); 516 } 517 #else 518 /* Call 40G Init */ 519 PHY84756_CALL_IF_8474X(unit,port, 520 PHY_INIT(PHY84756_40G, unit, port)); 521 #endif 522 523 #if defined(INCLUDE_FCMAP) 524 if (FCMAP_ENABLE(pc)) { 525 pc->fcmap_enable = FCMAP_ENABLE(pc); 526 pc->fcmap_dev_port = 0; 527 mmi_mdio_addr = pc->phy_id; 528 529 pc->fcmap_uc_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 530 pc->fcmap_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1); 531 532 rv = bfcmap_phy84756_phy_mac_driver_attach(pc, 533 pc->fcmap_dev_addr, 534 pc->fcmap_dev_port, 535 blmi_io_mmi1_cl45); 536 if(rv != SOC_E_NONE) { 537 LOG_WARN(BSL_LS_SOC_PHY, 538 (BSL_META_U(unit, 539 "phy_84756_fcmap_init: bfcmap_phy_mac_driver_attach " 540 "returned error for u=%d p=%d\n"), unit, port)); 541 return SOC_E_FAIL; 542 } 543 } 544 #endif /* INCLUDE_FCMAP */ 545 546 #if defined(INCLUDE_MACSEC) 547 MACSEC_SUPPORT(pc) = 1; 548 if (MACSEC_ENABLE(pc)) { 549 pc->macsec_enable = MACSEC_ENABLE(pc); 550 pc->macsec_dev_port = soc_property_port_get(unit, port, 551 spn_MACSEC_PORT_INDEX, -1); 552 553 /* Base PHY ID is used to access MACSEC core */ 554 mmi_mdio_addr = soc_property_port_get(unit, port, 555 spn_MACSEC_DEV_ADDR, -1); 556 if (mmi_mdio_addr < 0) { 557 LOG_WARN(BSL_LS_SOC_PHY, 558 (BSL_META_U(unit, 559 "phy_84756_macsec_init: " 560 "MACSEC_DEV_ADDR property " 561 "not configured for u=%d p=%d\n"), unit, port)); 562 return SOC_E_CONFIG; 563 } 564 565 pc->macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1); 566 567 rv = bfcmap_phy84756_phy_mac_driver_attach(pc, 568 pc->macsec_dev_addr, 569 pc->macsec_dev_port, 570 blmi_io_mmi1_cl45); 571 572 if(rv != SOC_E_NONE) { 573 LOG_WARN(BSL_LS_SOC_PHY, 574 (BSL_META_U(unit, 575 "phy_84756_macsec_init: bfcmap_phy_mac_driver_attach " 576 "returned error for u=%d p=%d\n"), unit, port)); 577 return SOC_E_FAIL; 578 } 579 } 580 #endif /* INCLUDE_MACSEC */ 581 582 /* If 1G link detected set speed */ 583 SOC_IF_ERROR_RETURN 584 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xC820, &data)); 585 if (data & 0x1) { 586 FIBER_FORCE_SPEED(pc) = 1000; 587 } else { 588 FIBER_FORCE_SPEED(pc) = 10000; 589 } 590 591 /* By default select ethernet chip mode */ 592 SOC_IF_ERROR_RETURN( 593 BFCMAP_RD_PHY84756_LN_DEV1_CHIP_MODEr(pc, &data)); 594 data &= ~0x3; 595 SOC_IF_ERROR_RETURN( 596 BFCMAP_WR_PHY84756_LN_DEV1_CHIP_MODEr(pc, data)); 597 598 PHY_EXT_ROM_BOOT(pc) = soc_property_port_get(unit, port, 599 spn_PHY_EXT_ROM_BOOT, 1); 600 601 SKIP_EDC_FW_DOWNLOAD(pc) = _phy_84756_fcmap_firmware_is_downloaded(unit, port); 602 603 pc->flags &= ~(PHYCTRL_MDIO_BCST | PHYCTRL_MDIO_BCST2); 604 605 if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) { 606 if (!PHY_EXT_ROM_BOOT(pc) && !SKIP_EDC_FW_DOWNLOAD(pc)) { 607 pc->flags |= PHYCTRL_MDIO_BCST; 608 } 609 #if defined(INCLUDE_FCMAP) 610 #if ALWAYS_DOWNLOAD_FC_UCODE_AT_POWERUP 611 /* Always download FC uCode in advance */ 612 pc->flags |= PHYCTRL_MDIO_BCST2; 613 #else 614 if (FCMAP_ENABLE(pc)) { 615 pc->flags |= PHYCTRL_MDIO_BCST2; 616 } 617 #endif 618 #endif 619 if (PHY84756_IS_8474X(pc)) { 620 /* pc->dev_name already set */ 621 } else 622 if (CHIP_IS_A0(pc)) { 623 pc->dev_name = "BCM84756_A0"; 624 } else { 625 if (CHIP_IS_B0(pc)) { 626 pc->dev_name = "BCM84756_B0"; 627 } else { 628 pc->dev_name = "BCM84756_C0"; 629 } 630 } 631 } 632 633 /* reset */ 634 SOC_IF_ERROR_RETURN( 635 bfcmap_phy84756_reset(pc)); 636 637 if ( PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT ) { 638 /* indicate second pass of init is needed */ 639 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_PASS2); 640 641 return SOC_E_NONE; 642 } 643 644 } 645 646 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 647 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 648 int line_mode; 649 int fiber_preferred; 650 #if defined(INCLUDE_FCMAP) 651 phy_ctrl_t *int_pc; 652 #endif /* INCLUDE_FCMAP */ 653 654 LOG_INFO(BSL_LS_SOC_PHY, 655 (BSL_META_U(unit, 656 "phy_84756_fcmap_init PASS2: u=%d p=%d\n"),unit, port)); 657 658 #if defined(INCLUDE_FCMAP) 659 if (!FCMAP_ENABLE(pc)) { 660 /* Call 40G Init */ 661 PHY84756_CALL_IF_8474X(unit,port, 662 PHY_INIT(PHY84756_40G, unit, port)); 663 } 664 #else 665 /* Call 40G Init */ 666 PHY84756_CALL_IF_8474X(unit,port, 667 PHY_INIT(PHY84756_40G, unit, port)); 668 #endif 669 670 /* Preferred mode: 671 * phy_fiber_pref = 1 ; Port is in SFI mode in 10G Default 672 * when speed is changed to 1G, its 1000X 673 * phy_fiber_pref = 0; Port is in SGMII mode, allows only 1G/100M/10M 674 */ 675 fiber_preferred = 676 soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1); 677 678 /* Initially configure for the preferred medium. */ 679 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 680 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 681 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 682 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 683 684 if (fiber_preferred) { 685 if (FIBER_FORCE_SPEED(pc) == 10000) { 686 line_mode = BFCMAP_PHY84756_INTF_SFI; 687 } else { 688 line_mode = BFCMAP_PHY84756_INTF_1000X; 689 } 690 pc->copper.enable = FALSE; 691 pc->fiber.enable = TRUE; 692 pc->interface = SOC_PORT_IF_XFI; 693 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 694 } else { 695 pc->interface = SOC_PORT_IF_SGMII; 696 line_mode = BFCMAP_PHY84756_INTF_SGMII; 697 pc->copper.enable = TRUE; 698 pc->fiber.enable = FALSE; 699 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 700 } 701 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45); 702 703 pc->copper.preferred = !fiber_preferred; 704 pc->copper.autoneg_enable = TRUE; 705 pc->copper.autoneg_advert = ADVERT_ALL_COPPER; 706 pc->copper.force_speed = 1000; 707 pc->copper.force_duplex = TRUE; 708 pc->copper.master = SOC_PORT_MS_AUTO; 709 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 710 711 pc->fiber.preferred = TRUE; 712 pc->fiber.autoneg_enable = FALSE; 713 pc->fiber.autoneg_advert = ADVERT_ALL_FIBER; 714 pc->fiber.force_speed = FIBER_FORCE_SPEED(pc); 715 pc->fiber.force_duplex = TRUE; 716 pc->fiber.master = SOC_PORT_MS_NONE; 717 pc->fiber.mdix = SOC_PORT_MDIX_NORMAL; 718 719 720 SOC_IF_ERROR_RETURN( 721 bfcmap_phy84756_no_reset_setup(pc, 722 line_mode, 723 PHY_EXT_ROM_BOOT(pc))); 724 725 /* Get Requested LED selectors (defaults are hardware defaults) */ 726 pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 727 pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1); 728 pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3); 729 pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6); 730 pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8); 731 pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0); 732 733 734 if (line_mode != BFCMAP_PHY84756_INTF_SGMII) 735 { 736 SOC_IF_ERROR_RETURN 737 (_phy_84756_fcmap_medium_config_update(unit, port, 738 PHY_COPPER_MODE(unit, port) ? 739 &pc->copper : 740 &pc->fiber)); 741 } 742 743 #if defined(INCLUDE_FCMAP) 744 if (FCMAP_ENABLE(pc)) { 745 if (CHIP_IS_C0(pc)) { 746 rv = soc_fcmapphy_init(unit, port, pc, 747 BFCMAP_CORE_BCM84756_C0, bfcmap_io_mmi1_cl45); 748 } 749 else { 750 rv = soc_fcmapphy_init(unit, port, pc, 751 BFCMAP_CORE_BCM84756, bfcmap_io_mmi1_cl45); 752 } 753 if (!SOC_SUCCESS(rv)) { 754 LOG_ERROR(BSL_LS_SOC_PHY, 755 (BSL_META_U(unit, 756 "soc_fcmapphy_init: FCMAP init for" 757 " u=%d p=%d FAILED "), unit, port)); 758 } else { 759 LOG_INFO(BSL_LS_SOC_PHY, 760 (BSL_META_U(unit, 761 "soc_fcmapphy_init: FCMAP init for" 762 " u=%d p=%d SUCCESS "), unit, port)); 763 } 764 765 /* Internal serdes speed should be set to 10G in FC Mode */ 766 int_pc = INT_PHY_SW_STATE(unit, port); 767 if (NULL != int_pc) { 768 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 769 PHY_SPEED_SET(int_pc->pd, unit, port, 10000); 770 } 771 } 772 #endif 773 #if defined(INCLUDE_MACSEC) 774 if (MACSEC_ENABLE(pc)) { 775 if (CHIP_IS_C0(pc)) { 776 rv = soc_macsecphy_init(unit, port, pc, 777 BMACSEC_CORE_BCM84756_C0, bmacsec_io_mmi1_cl45); 778 } else { 779 rv = soc_macsecphy_init(unit, port, pc, 780 BMACSEC_CORE_BCM84756, bmacsec_io_mmi1_cl45); 781 } 782 if (!SOC_SUCCESS(rv)) { 783 LOG_ERROR(BSL_LS_SOC_PHY, 784 (BSL_META_U(unit, 785 "soc_macsec_init: MACSEC init for" 786 " u=%d p=%d FAILED "), unit, port)); 787 } else { 788 LOG_INFO(BSL_LS_SOC_PHY, 789 (BSL_META_U(unit, 790 "soc_macsec_init: MACSEC init for" 791 " u=%d p=%d SUCCESS "), unit, port)); 792 } 793 } 794 #endif 795 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT); 796 } 797 798 if (soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 0)) { 799 if(!PHY84756_SINGLE_PORT_MODE(pc)) { 800 /* put device in repeat mode. Single port is already in repeat mode */ 801 SOC_IF_ERROR_RETURN 802 (WRITE_PHY84756_PMA_PMD_REG(unit, pc, 0xc806, 0x6)); 803 PHY_FLAGS_SET(unit, port, PHY_FLAGS_REPEATER); 804 } 805 } 806 return SOC_E_NONE; 807 } 808 809 /* 810 * Function: 811 * phy_84756_fcmap_link_get 812 * Purpose: 813 * Get layer2 connection status. 814 * Parameters: 815 * unit - StrataSwitch unit #. 816 * port - StrataSwitch port #. 817 * link - address of memory to store link up/down state. 818 * Returns: 819 * SOC_E_NONE 820 */ 821 822 STATIC int 823 phy_84756_fcmap_link_get(int unit, soc_port_t port, int *link) 824 { 825 phy_ctrl_t *pc; 826 int rv = SOC_E_NONE; 827 bfcmap_phy84756_intf_t bfcmap_mode; 828 int bfcmap_link; 829 phy_ctrl_t *int_pc; 830 buint16_t repeater_mode; 831 832 int_pc = INT_PHY_SW_STATE(unit, port); 833 pc = EXT_PHY_SW_STATE(unit, port); 834 *link = FALSE; /* Default return */ 835 836 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 837 return SOC_E_NONE; 838 } 839 840 /* 40G link get */ 841 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 842 PHY_LINK_GET(PHY84756_40G, unit, port, link)); 843 844 #if defined(INCLUDE_FCMAP) 845 if (pc->fcmap_enable) { 846 rv = bfcmap_phy84756_link_get(pc, &bfcmap_link); 847 if (!SOC_SUCCESS(rv)) { 848 return SOC_E_FAIL; 849 } 850 *link = bfcmap_link ? TRUE : FALSE; 851 return SOC_E_NONE; 852 } 853 #endif 854 855 rv = bfcmap_phy84756_line_intf_get(pc, 0, &bfcmap_mode); 856 if (!SOC_SUCCESS(rv)) { 857 return SOC_E_FAIL; 858 } 859 860 if (bfcmap_mode == BFCMAP_PHY84756_INTF_SGMII) { 861 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 862 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 863 } else { 864 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 865 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 866 } 867 868 rv = bfcmap_phy84756_link_get(pc, &bfcmap_link); 869 if (!SOC_SUCCESS(rv)) { 870 return SOC_E_FAIL; 871 } 872 873 if (bfcmap_link) { 874 *link = TRUE; 875 } else { 876 *link = FALSE; 877 } 878 LOG_VERBOSE(BSL_LS_SOC_PHY, 879 (BSL_META_U(unit, 880 "phy_84756_fcmap_link_get: u=%d p=%d link=%d\n"), 881 unit, port, 882 *link)); 883 884 SOC_IF_ERROR_RETURN 885 (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode)); 886 887 if ((repeater_mode & 0x6) == 0x6) { 888 if (NULL != int_pc) { 889 SOC_IF_ERROR_RETURN( 890 PHY_LINK_GET(int_pc->pd, unit, port, link)); 891 } 892 } 893 return SOC_E_NONE; 894 } 895 896 897 /* 898 * Function: 899 * phy_84756_fcmap_linkfault_get 900 * Purpose: 901 * Get layer2 connection status. 902 * Parameters: 903 * unit - StrataSwitch unit #. 904 * port - StrataSwitch port #. 905 * fault - address of memory to store link fault state. 906 * Returns: 907 * SOC_E_NONE 908 */ 909 910 STATIC int 911 phy_84756_fcmap_linkfault_get(int unit, soc_port_t port, int *fault) 912 { 913 #if defined(INCLUDE_FCMAP) 914 phy_ctrl_t *pc; 915 916 pc = EXT_PHY_SW_STATE(unit, port); 917 #endif 918 919 *fault = FALSE; /* Default return */ 920 921 #if defined(INCLUDE_FCMAP) 922 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 923 return SOC_E_NONE; 924 } 925 926 if (pc->fcmap_enable) { 927 int rv = SOC_E_NONE; 928 929 rv = bfcmap_phy84756_linkfault_get(pc, fault); 930 if (!SOC_SUCCESS(rv)) { 931 return SOC_E_FAIL; 932 } 933 } 934 #endif 935 936 LOG_VERBOSE(BSL_LS_SOC_PHY, 937 (BSL_META_U(unit, 938 "phy_84756_fcmap_linkfault_get: u=%d p=%d linkfault=%d\n"), 939 unit, port, 940 *fault)); 941 return SOC_E_NONE; 942 } 943 944 945 /* 946 * Function: 947 * phy_84756_fcmap_enable_set 948 * Purpose: 949 * Enable or disable the physical interface. 950 * Parameters: 951 * unit - StrataSwitch unit #. 952 * port - StrataSwitch port #. 953 * enable - Boolean, true = enable PHY, false = disable. 954 * Returns: 955 * SOC_E_XXX 956 */ 957 958 STATIC int 959 phy_84756_fcmap_enable_set(int unit, soc_port_t port, int enable) 960 { 961 phy_ctrl_t *pc; 962 buint16_t power; 963 buint16_t data, tx_ctrl; 964 965 pc = EXT_PHY_SW_STATE(unit, port); 966 967 if (enable) { 968 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 969 } else { 970 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 971 } 972 973 /* 40G en set */ 974 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 975 PHY_ENABLE_SET(PHY84756_40G, unit, port, enable)); 976 977 if (enable) { 978 /* c8e4[4] indicates the TX active state, 0 means TX active, 1 means inactive. 979 * This state = TxOnOff pin XOR c800[7] when c8e4[12]=0. 980 * The default value of c800[7] is 1. 981 * If user straps the TxOnOff to 0, 982 * then the Tx won't be enabled until this function is called. 983 * Toggle 0xc800[7] to enable the Tx when c8e4[4]=1. 984 */ 985 SOC_IF_ERROR_RETURN 986 (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc8e4, &data)); 987 988 SOC_IF_ERROR_RETURN 989 (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc800, &tx_ctrl)); 990 991 tx_ctrl &= (1 << 7); 992 if (data & (1 << 4)) { 993 SOC_IF_ERROR_RETURN 994 (BFCMAP_PHY84756_REG_MOD(pc, 00, 0x1, 0xc800, 995 tx_ctrl? 0:(1 << 7), (1 << 7))); 996 } 997 } 998 else { 999 #if defined(INCLUDE_FCMAP) || defined(INCLUDE_MACSEC) 1000 /* If macsec or fcmap is enabled, remain TX active to make sure xmac is accessible */ 1001 if (FCMAP_ENABLE(pc) || MACSEC_ENABLE(pc)) 1002 goto xxx; 1003 #endif 1004 /* Toggle 0xc800[7] to set TX inactive if it is currently active */ 1005 SOC_IF_ERROR_RETURN 1006 (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc8e4, &data)); 1007 1008 SOC_IF_ERROR_RETURN 1009 (BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc800, &tx_ctrl)); 1010 1011 tx_ctrl &= (1 << 7); 1012 if ((data & (1 << 4)) == 0) { 1013 SOC_IF_ERROR_RETURN 1014 (BFCMAP_PHY84756_REG_MOD(pc, 00, 0x1, 0xc800, 1015 tx_ctrl? 0:(1 << 7), (1 << 7))); 1016 } 1017 } 1018 1019 xxx: 1020 #if defined(INCLUDE_FCMAP) 1021 if (FCMAP_ENABLE(pc)) { 1022 int p; 1023 int rv = SOC_E_NONE; 1024 1025 /* Issue a enable request to the FC firmware */ 1026 p = SOC_FCMAP_PORTID(unit, port); 1027 if (enable) { 1028 rv = bfcmap_port_link_enable(p); 1029 } else { 1030 rv = bfcmap_port_shutdown(p); 1031 } 1032 if (rv != BFCMAP_E_NONE) { 1033 LOG_INFO(BSL_LS_SOC_PHY, 1034 (BSL_META_U(unit, 1035 "phy_84756_fcmap_enable_set: Failed u=%d p=%d enable=%d rv=%d\n"), 1036 unit, port, enable, rv)); 1037 return SOC_E_FAIL; 1038 } 1039 LOG_INFO(BSL_LS_SOC_PHY, 1040 (BSL_META_U(unit, 1041 "phy_84756_fcmap_enable_set: Success u=%d p=%d enable=%d rv=%d\n"), 1042 unit, port, enable, rv)); 1043 return SOC_E_NONE; 1044 } 1045 #endif 1046 1047 1048 /* set 1.9.0 to control OPTXENB pin connected to module */ 1049 power = (enable) ? 0 : 0x0001 ; 1050 SOC_IF_ERROR_RETURN( 1051 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, power, 0x0001)); 1052 1053 1054 LOG_INFO(BSL_LS_SOC_PHY, 1055 (BSL_META_U(unit, 1056 "phy_84756_fcmap_enable_set: " 1057 "Power %s fiber medium\n"), (enable) ? "up" : "down")); 1058 1059 return SOC_E_NONE; 1060 } 1061 1062 /* 1063 * Function: 1064 * phy_84756_fcmap_duplex_set 1065 * Purpose: 1066 * Set the current duplex mode 1067 * Parameters: 1068 * unit - StrataSwitch unit #. 1069 * port - StrataSwitch port #. 1070 * duplex - Boolean, true indicates full duplex, false indicates half. 1071 * Returns: 1072 * SOC_E_NONE 1073 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 1074 * Notes: 1075 */ 1076 STATIC int 1077 phy_84756_fcmap_duplex_set(int unit, soc_port_t port, int duplex_in) 1078 { 1079 int rv = SOC_E_NONE ; 1080 phy_ctrl_t *pc; 1081 bfcmap_phy84756_duplex_t duplex; 1082 buint16_t mii_ctrl; 1083 bfcmap_phy84756_intf_t line_mode; 1084 1085 pc = EXT_PHY_SW_STATE(unit, port); 1086 1087 /* 40G duplex set */ 1088 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1089 PHY_DUPLEX_SET(PHY84756_40G, unit, port, duplex_in)); 1090 1091 #if defined(INCLUDE_FCMAP) 1092 if (pc->fcmap_enable) { 1093 return SOC_E_NONE; 1094 } 1095 #endif 1096 1097 if (duplex_in) { 1098 duplex = BFCMAP_PHY84756_FULL_DUPLEX; 1099 } else { 1100 duplex = BFCMAP_PHY84756_HALF_DUPLEX; 1101 } 1102 1103 SOC_IF_ERROR_RETURN( 1104 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 1105 1106 if ((line_mode == BFCMAP_PHY84756_INTF_1000X ) || 1107 (line_mode == BFCMAP_PHY84756_INTF_SFI )) { 1108 1109 if (duplex == BFCMAP_PHY84756_FULL_DUPLEX) { 1110 rv = SOC_E_NONE; 1111 goto exit; 1112 } else { 1113 rv = SOC_E_UNAVAIL; 1114 goto exit; 1115 } 1116 } 1117 SOC_IF_ERROR_RETURN( 1118 BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &mii_ctrl)); 1119 1120 if (duplex == BFCMAP_PHY84756_FULL_DUPLEX) { 1121 mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_FD; 1122 } else { 1123 mii_ctrl &= ~BFCMAP_PHY84756_AN_MII_CTRL_FD; 1124 } 1125 SOC_IF_ERROR_RETURN( 1126 BFCMAP_WR_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, mii_ctrl)); 1127 1128 exit: 1129 if(SOC_SUCCESS(rv)) { 1130 pc->copper.force_duplex = duplex_in; 1131 } 1132 1133 1134 LOG_INFO(BSL_LS_SOC_PHY, 1135 (BSL_META_U(unit, 1136 "phy_84756_fcmap_duplex_set: u=%d p=%d d=%d rv=%d\n"), 1137 unit, port, duplex, rv)); 1138 return rv; 1139 } 1140 1141 /* 1142 * Function: 1143 * phy_84756_fcmap_duplex_get 1144 * Purpose: 1145 * Get the current operating duplex mode. If autoneg is enabled, 1146 * then operating mode is returned, otherwise forced mode is returned. 1147 * Parameters: 1148 * unit - StrataSwitch unit #. 1149 * port - StrataSwitch port #. 1150 * duplex - (OUT) Boolean, true indicates full duplex, false 1151 * indicates half. 1152 * Returns: 1153 * SOC_E_NONE 1154 * Notes: 1155 * The duplex is retrieved for the ACTIVE medium. 1156 * No synchronization performed at this level. Autonegotiation is 1157 * not manipulated. 1158 */ 1159 1160 STATIC int 1161 phy_84756_fcmap_duplex_get(int unit, soc_port_t port, int *duplex) 1162 { 1163 1164 phy_ctrl_t *pc; 1165 buint16_t status; 1166 bfcmap_phy84756_intf_t line_mode; 1167 1168 pc = EXT_PHY_SW_STATE(unit, port); 1169 1170 /* 40G duplex get */ 1171 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1172 PHY_DUPLEX_GET(PHY84756_40G, unit, port, duplex)); 1173 1174 #if defined(INCLUDE_FCMAP) 1175 if (pc->fcmap_enable) { 1176 *duplex = TRUE; 1177 return SOC_E_NONE; 1178 } 1179 #endif 1180 1181 SOC_IF_ERROR_RETURN( 1182 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 1183 1184 if ((line_mode == BFCMAP_PHY84756_INTF_1000X ) || 1185 (line_mode == BFCMAP_PHY84756_INTF_SFI )) { 1186 *duplex = TRUE; 1187 } else { 1188 SOC_IF_ERROR_RETURN( 1189 BFCMAP_RD_PHY84756_LN_DEV7_AN_BASE1000X_STAT1r(pc, &status)); 1190 if (status & (1U << 2)) { 1191 *duplex = TRUE; 1192 } else { 1193 *duplex = FALSE; 1194 } 1195 } 1196 1197 LOG_INFO(BSL_LS_SOC_PHY, 1198 (BSL_META_U(unit, 1199 "phy_84756_fcmap_duplex_get: u=%d p=%d d=%d \n"), 1200 unit, port, *duplex)); 1201 return SOC_E_NONE; 1202 } 1203 1204 1205 /* 1206 * Function: 1207 * phy_84756_fcmap_speed_set 1208 * Purpose: 1209 * Set PHY speed 1210 * Parameters: 1211 * unit - StrataSwitch unit #. 1212 * port - StrataSwitch port #. 1213 * speed - link speed in Mbps 1214 * Returns: 1215 * SOC_E_NONE 1216 */ 1217 STATIC int 1218 phy_84756_fcmap_speed_set(int unit, soc_port_t port, int speed) 1219 { 1220 phy_ctrl_t *pc; 1221 phy_ctrl_t *int_pc; 1222 int rv; 1223 1224 pc = EXT_PHY_SW_STATE(unit, port); 1225 int_pc = INT_PHY_SW_STATE(unit, port); 1226 rv = SOC_E_NONE; 1227 1228 /* 40G speed set */ 1229 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1230 PHY_SPEED_SET(PHY84756_40G, unit, port, speed)); 1231 1232 #if defined(INCLUDE_FCMAP) 1233 if (pc->fcmap_enable) { 1234 if (NULL != int_pc) { 1235 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 1236 PHY_SPEED_SET(int_pc->pd, unit, port, 10000); 1237 } 1238 return SOC_E_NONE; 1239 } 1240 #endif 1241 1242 if (speed > 10000) { 1243 return SOC_E_UNAVAIL; 1244 } 1245 1246 if(PHY_FIBER_MODE(unit, port)) { 1247 if (speed < 1000) { 1248 return SOC_E_UNAVAIL; 1249 } 1250 } 1251 1252 rv = bfcmap_phy84756_speed_set(pc, speed); 1253 if(SOC_SUCCESS(rv)) { 1254 if (NULL != int_pc) { 1255 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 1256 PHY_SPEED_SET(int_pc->pd, unit, port, speed); 1257 } 1258 if(PHY_COPPER_MODE(unit, port)) { 1259 pc->copper.force_speed = speed; 1260 } else { 1261 if(PHY_FIBER_MODE(unit, port)) { 1262 pc->fiber.force_speed = speed; 1263 } 1264 } 1265 } 1266 LOG_INFO(BSL_LS_SOC_PHY, 1267 (BSL_META_U(unit, 1268 "phy_84756_fcmap_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"), 1269 unit, port, speed, PHY_FIBER_MODE(unit, port), rv)); 1270 1271 return rv; 1272 } 1273 1274 /* 1275 * Function: 1276 * phy_84756_fcmap_speed_get 1277 * Purpose: 1278 * Get the current operating speed for a 84756 device. 1279 * Parameters: 1280 * unit - StrataSwitch unit #. 1281 * port - StrataSwitch port #. 1282 * speed - (OUT) Speed of the phy 1283 * Returns: 1284 * SOC_E_NONE 1285 * Notes: 1286 * The speed is retrieved for the ACTIVE medium. 1287 */ 1288 1289 STATIC int 1290 phy_84756_fcmap_speed_get(int unit, soc_port_t port, int *speed) 1291 { 1292 int rv = SOC_E_NONE; 1293 phy_ctrl_t *pc; 1294 buint16_t data = 0; 1295 #if defined(INCLUDE_FCMAP) 1296 buint16_t fval = 0; 1297 #endif 1298 bfcmap_phy84756_intf_t line_mode; 1299 phy_ctrl_t *int_pc; 1300 buint16_t repeater_mode; 1301 1302 int_pc = INT_PHY_SW_STATE(unit, port); 1303 1304 if (speed == NULL) { 1305 return SOC_E_PARAM; 1306 } 1307 1308 pc = EXT_PHY_SW_STATE(unit, port); 1309 1310 /* 40G speed set */ 1311 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1312 PHY_SPEED_GET(PHY84756_40G, unit, port, speed)); 1313 1314 1315 #if defined(INCLUDE_FCMAP) 1316 if (pc->fcmap_enable) { 1317 BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x50, &fval); 1318 *speed = 0; 1319 if (fval == 0x1a) { /* Link up event */ 1320 BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x52, &fval); 1321 switch (fval) { 1322 case 8: 1323 *speed = 8000; 1324 break; 1325 case 4: 1326 *speed = 4000; 1327 break; 1328 case 2: 1329 *speed = 2000; 1330 break; 1331 default: 1332 *speed = 0; 1333 break; 1334 } 1335 } 1336 } else 1337 #endif 1338 { 1339 SOC_IF_ERROR_RETURN( 1340 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 1341 1342 if (line_mode == BFCMAP_PHY84756_INTF_SFI) { 1343 *speed = 10000; 1344 return SOC_E_NONE; 1345 } 1346 if (line_mode == BFCMAP_PHY84756_INTF_1000X) { 1347 *speed = 1000; 1348 return SOC_E_NONE; 1349 } 1350 SOC_IF_ERROR_RETURN( 1351 BFCMAP_RD_PHY84756_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &data)); 1352 switch(data & BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_MASK) { 1353 case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_10M: 1354 *speed = 10; 1355 break; 1356 case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_100M: 1357 *speed = 100; 1358 break; 1359 case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_1G: 1360 *speed = 1000; 1361 break; 1362 case BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_10G: 1363 *speed = 10000; 1364 break; 1365 default : 1366 *speed = 0; 1367 break; 1368 } 1369 } 1370 1371 if(!SOC_SUCCESS(rv)) { 1372 LOG_WARN(BSL_LS_SOC_PHY, 1373 (BSL_META_U(unit, 1374 "phy_84756_fcmap_speed_get: u=%d p=%d invalid speed\n"), 1375 unit, port)); 1376 } else { 1377 LOG_INFO(BSL_LS_SOC_PHY, 1378 (BSL_META_U(unit, 1379 "phy_84756_fcmap_speed_get: u=%d p=%d speed=%d"), 1380 unit, port, *speed)); 1381 } 1382 1383 SOC_IF_ERROR_RETURN 1384 (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode)); 1385 1386 if ((repeater_mode & 0x6) == 0x6) { 1387 if (NULL != int_pc) { 1388 SOC_IF_ERROR_RETURN 1389 (PHY_SPEED_GET(int_pc->pd, unit, port, speed)); 1390 } 1391 } 1392 return rv; 1393 } 1394 1395 /* 1396 * Function: 1397 * phy_84756_fcmap_an_set 1398 * Purpose: 1399 * Enable or disable auto-negotiation on the specified port. 1400 * Parameters: 1401 * unit - StrataSwitch unit #. 1402 * port - StrataSwitch port #. 1403 * autoneg - Boolean, if true, auto-negotiation is enabled 1404 * (and/or restarted). If false, autonegotiation is disabled. 1405 * Returns: 1406 * SOC_E_XXX 1407 * Notes: 1408 * The autoneg mode is set only for the ACTIVE medium. 1409 */ 1410 1411 STATIC int 1412 phy_84756_fcmap_an_set(int unit, soc_port_t port, int autoneg) 1413 { 1414 int rv; 1415 phy_ctrl_t *pc; 1416 buint16_t data = 0; 1417 bfcmap_phy84756_intf_t line_mode; 1418 phy_ctrl_t *int_pc; 1419 buint16_t repeater_mode; 1420 1421 int_pc = INT_PHY_SW_STATE(unit, port); 1422 pc = EXT_PHY_SW_STATE(unit, port); 1423 rv = SOC_E_NONE; 1424 1425 /* 40G an set */ 1426 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1427 PHY_AUTO_NEGOTIATE_SET(PHY84756_40G, unit, port, autoneg)); 1428 1429 #if defined(INCLUDE_FCMAP) 1430 if (pc->fcmap_enable) { 1431 return SOC_E_NONE; 1432 } 1433 #endif 1434 1435 SOC_IF_ERROR_RETURN( 1436 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 1437 1438 if (line_mode == BFCMAP_PHY84756_INTF_SFI ) { 1439 /* force speed ie an=f */ 1440 autoneg = 0 ; 1441 } 1442 1443 /* 1444 * Autoneg 1445 * enabled disabled 1446 * 1.0000=2040 1.0000=0040 1447 * 7.8309=0010 7.8309=0030 1448 * 7.FFE0=1100 7.FFE0=0100 1449 */ 1450 1451 if (line_mode != BFCMAP_PHY84756_INTF_SFI ) { 1452 SOC_IF_ERROR_RETURN( 1453 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, autoneg ? 0x2040 : 0x0040, 0x2040)); 1454 } 1455 1456 SOC_IF_ERROR_RETURN( 1457 BFCMAP_MOD_PHY84756_LN_DEV7_AN_MSIC2r(pc, autoneg ? 0x10 : 0x30, 0x30)); 1458 1459 SOC_IF_ERROR_RETURN( 1460 BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &data)); 1461 if (autoneg) { 1462 data |= (BFCMAP_PHY84756_AN_MII_CTRL_AE | 1463 BFCMAP_PHY84756_AN_MII_CTRL_FD | 1464 BFCMAP_PHY84756_AN_MII_CTRL_RAN); 1465 } else { 1466 data &= ~(BFCMAP_PHY84756_AN_MII_CTRL_AE | 1467 BFCMAP_PHY84756_AN_MII_CTRL_RAN); 1468 data |= BFCMAP_PHY84756_AN_MII_CTRL_FD; 1469 } 1470 SOC_IF_ERROR_RETURN( 1471 BFCMAP_WR_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, data)); 1472 1473 if(SOC_SUCCESS(rv)) { 1474 if(PHY_COPPER_MODE(unit, port)) { 1475 pc->copper.autoneg_enable = autoneg ? TRUE : FALSE; 1476 } else { 1477 if(PHY_FIBER_MODE(unit, port)) { 1478 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE; 1479 } 1480 } 1481 } 1482 1483 LOG_INFO(BSL_LS_SOC_PHY, 1484 (BSL_META_U(unit, 1485 "phy_84756_fcmap_an_set: u=%d p=%d autoneg=%d rv=%d\n"), 1486 unit, port, autoneg, rv)); 1487 1488 SOC_IF_ERROR_RETURN(BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode)); 1489 1490 if(NULL != int_pc) { 1491 /* if in passthru mode, enable autoneg on internal serdes */ 1492 if((repeater_mode & 0x6) == 0x6) { 1493 SOC_IF_ERROR_RETURN( 1494 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, autoneg)); 1495 } else { 1496 SOC_IF_ERROR_RETURN( 1497 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, FALSE)); 1498 } 1499 } 1500 1501 if((autoneg == 0) && !PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1502 SOC_IF_ERROR_RETURN( 1503 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, 1, 0x0001)); 1504 sal_usleep(50000); 1505 SOC_IF_ERROR_RETURN( 1506 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, 0, 0x0001)); 1507 } 1508 1509 return rv; 1510 } 1511 1512 /* 1513 * Function: 1514 * phy_84756_fcmap_an_get 1515 * Purpose: 1516 * Get the current auto-negotiation status (enabled/busy). 1517 * Parameters: 1518 * unit - StrataSwitch unit #. 1519 * port - StrataSwitch port #. 1520 * autoneg - (OUT) if true, auto-negotiation is enabled. 1521 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 1522 * value is undefined if autoneg == FALSE. 1523 * Returns: 1524 * SOC_E_XXX 1525 * Notes: 1526 * The autoneg mode is retrieved for the ACTIVE medium. 1527 */ 1528 1529 STATIC int 1530 phy_84756_fcmap_an_get(int unit, soc_port_t port, 1531 int *autoneg, int *autoneg_done) 1532 { 1533 int rv; 1534 phy_ctrl_t *pc; 1535 buint16_t an_mii_ctrl = 0; 1536 bfcmap_phy84756_intf_t line_mode; 1537 1538 pc = EXT_PHY_SW_STATE(unit, port); 1539 1540 rv = SOC_E_NONE; 1541 *autoneg = FALSE; 1542 *autoneg_done = FALSE; 1543 1544 /* 40G an get */ 1545 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1546 PHY_AUTO_NEGOTIATE_GET(PHY84756_40G, unit, port,autoneg,autoneg_done)); 1547 1548 #if defined(INCLUDE_FCMAP) 1549 if (pc->fcmap_enable) { 1550 int bfcmap_link; 1551 *autoneg = TRUE; /* Always in Autoneg */ 1552 rv = bfcmap_phy84756_link_get(pc, &bfcmap_link); 1553 if (!SOC_SUCCESS(rv)) { 1554 return SOC_E_FAIL; 1555 } 1556 *autoneg_done = bfcmap_link ? TRUE : FALSE; 1557 return SOC_E_NONE; 1558 } 1559 #endif 1560 SOC_IF_ERROR_RETURN( 1561 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 1562 1563 if (line_mode == BFCMAP_PHY84756_INTF_SFI ) { 1564 *autoneg = FALSE; 1565 *autoneg_done = FALSE; 1566 } else { 1567 SOC_IF_ERROR_RETURN( 1568 BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &an_mii_ctrl)); 1569 *autoneg = (an_mii_ctrl & BFCMAP_PHY84756_AN_MII_CTRL_AE) ? 1 : 0; 1570 *autoneg_done = 1571 (pc->mii_stat & BFCMAP_PHY84756_AN_MII_STAT_AN_DONE) ? 1 : 0; 1572 } 1573 1574 return rv; 1575 } 1576 1577 /* 1578 * Function: 1579 * phy_84756_fcmap_lb_set 1580 * Purpose: 1581 * Set the local PHY loopback mode. 1582 * Parameters: 1583 * unit - StrataSwitch unit #. 1584 * port - StrataSwitch port #. 1585 * loopback - Boolean: true = enable loopback, false = disable. 1586 * Returns: 1587 * SOC_E_XXX 1588 * Notes: 1589 * The loopback mode is set only for the ACTIVE medium. 1590 * No synchronization performed at this level. 1591 */ 1592 1593 STATIC int 1594 phy_84756_fcmap_lb_set(int unit, soc_port_t port, int enable) 1595 { 1596 int rv; 1597 phy_ctrl_t *pc; 1598 buint16_t data = 0; 1599 bfcmap_phy84756_intf_t line_mode; 1600 int intf_tx; 1601 int intf_rx; 1602 1603 1604 pc = EXT_PHY_SW_STATE(unit, port); 1605 rv = SOC_E_NONE; 1606 1607 /* 40G lb set */ 1608 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1609 PHY_LOOPBACK_SET(PHY84756_40G, unit, port, enable)); 1610 1611 1612 intf_tx = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? 1613 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 1614 1615 intf_rx = ( intf_tx == PHY_DIAG_INTF_LINE ) ? 1616 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 1617 1618 /* TX Enable(Disable) Squelch(FORCE) when we Enable(Disable) loopback */ 1619 SOC_IF_ERROR_RETURN 1620 (phy_84756_fcmap_squelch_enable(unit, port, 1621 intf_tx, enable ? TRUE : FALSE, enable ? TRUE : FALSE )); 1622 1623 /* RX Disable(Enable) Squelch when we Enable(Disable) loopback */ 1624 SOC_IF_ERROR_RETURN 1625 (phy_84756_fcmap_squelch_enable(unit, port, 1626 intf_rx, enable ? FALSE : TRUE, FALSE)); 1627 1628 SOC_IF_ERROR_RETURN( 1629 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 1630 1631 if (line_mode == BFCMAP_PHY84756_INTF_SFI) { 1632 SOC_IF_ERROR_RETURN( 1633 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &data)); 1634 data &= ~(1); 1635 data |= (enable) ? 1 : 0x0000; 1636 SOC_IF_ERROR_RETURN( 1637 BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, data)); 1638 } else { 1639 SOC_IF_ERROR_RETURN( 1640 BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &data)); 1641 data &= ~BFCMAP_PHY84756_AN_MII_CTRL_LE; 1642 data |= (enable) ? BFCMAP_PHY84756_AN_MII_CTRL_LE : 0; 1643 SOC_IF_ERROR_RETURN( 1644 BFCMAP_WR_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, data)); 1645 } 1646 if (rv == SOC_E_NONE) { 1647 /* wait for link up when loopback is enabled */ 1648 1649 if (enable) { 1650 sal_usleep(2000000); 1651 } 1652 } 1653 LOG_INFO(BSL_LS_SOC_PHY, 1654 (BSL_META_U(unit, 1655 "phy_84756_fcmap_lb_set: u=%d p=%d en=%d rv=%d\n"), 1656 unit, port, enable, rv)); 1657 1658 return rv; 1659 } 1660 1661 /* 1662 * Function: 1663 * phy_84756_fcmap_lb_get 1664 * Purpose: 1665 * Get the local PHY loopback mode. 1666 * Parameters: 1667 * unit - StrataSwitch unit #. 1668 * port - StrataSwitch port #. 1669 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 1670 * Returns: 1671 * SOC_E_XXX 1672 * Notes: 1673 * The loopback mode is retrieved for the ACTIVE medium. 1674 */ 1675 1676 STATIC int 1677 phy_84756_fcmap_lb_get(int unit, soc_port_t port, int *enable) 1678 { 1679 int rv; 1680 phy_ctrl_t *pc; 1681 buint16_t data = 0; 1682 bfcmap_phy84756_intf_t line_mode; 1683 1684 pc = EXT_PHY_SW_STATE(unit, port); 1685 rv = SOC_E_NONE; 1686 1687 /* 40G lb get */ 1688 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1689 PHY_LOOPBACK_GET(PHY84756_40G, unit, port, enable)); 1690 1691 1692 SOC_IF_ERROR_RETURN( 1693 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 1694 1695 if (line_mode == BFCMAP_PHY84756_INTF_SFI) { 1696 SOC_IF_ERROR_RETURN( 1697 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &data)); 1698 /* ctrl != 0xffff check is to handle removable PHY daughter cards */ 1699 *enable = ((data != 0xffff) && (data & 1)) ? 1 : 0; 1700 } else { 1701 SOC_IF_ERROR_RETURN( 1702 BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, &data)); 1703 /* ctrl != 0xffff check is to handle removable PHY daughter cards */ 1704 *enable = ((data != 0xffff) && 1705 (data & BFCMAP_PHY84756_AN_MII_CTRL_LE)) ? 1 : 0; 1706 } 1707 1708 return rv; 1709 } 1710 1711 1712 /* 1713 * Function: 1714 * phy_84756_fcmap_ability_advert_set 1715 * Purpose: 1716 * Set the current advertisement for auto-negotiation. 1717 * Parameters: 1718 * unit - StrataSwitch unit #. 1719 * port - StrataSwitch port #. 1720 * mode - Port mode mask indicating supported options/speeds. 1721 * Returns: 1722 * SOC_E_XXX 1723 * Notes: 1724 * The advertisement is set only for the ACTIVE medium. 1725 * No synchronization performed at this level. 1726 */ 1727 STATIC int 1728 phy_84756_fcmap_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability) 1729 { 1730 int rv; 1731 phy_ctrl_t *pc; 1732 bfcmap_phy84756_port_ability_t local_ability; 1733 phy_ctrl_t *int_pc; 1734 buint16_t repeater_mode; 1735 1736 int_pc = INT_PHY_SW_STATE(unit, port); 1737 pc = EXT_PHY_SW_STATE(unit, port); 1738 1739 1740 if (NULL == ability) { 1741 return (SOC_E_PARAM); 1742 } 1743 1744 /* 40G advert Set */ 1745 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1746 PHY_ABILITY_ADVERT_SET(PHY84756_40G, unit, port, ability)); 1747 1748 #if defined(INCLUDE_FCMAP) 1749 if (pc->fcmap_enable) { 1750 return SOC_E_NONE; 1751 } 1752 #endif 1753 1754 if (PHY_COPPER_MODE(unit, port)) { 1755 pc->copper.advert_ability = *ability; 1756 } else { 1757 pc->fiber.advert_ability = *ability; 1758 } 1759 1760 local_ability = 0; 1761 1762 if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1763 local_ability |= BFCMAP_PHY84756_PA_1000MB_FD; 1764 } 1765 if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) { 1766 local_ability |= BFCMAP_PHY84756_PA_10000MB_FD; 1767 } 1768 1769 if(ability->pause & SOC_PA_PAUSE_TX) { 1770 local_ability |= BFCMAP_PHY84756_PA_PAUSE_TX; 1771 } 1772 if(ability->pause & SOC_PA_PAUSE_RX) { 1773 local_ability |= BFCMAP_PHY84756_PA_PAUSE_RX; 1774 } 1775 if(ability->pause & SOC_PA_PAUSE_ASYMM) { 1776 local_ability |= BFCMAP_PHY84756_PA_PAUSE_ASYMM; 1777 } 1778 1779 if(ability->loopback & SOC_PA_LB_NONE) { 1780 local_ability |= BFCMAP_PHY84756_PA_LB_NONE; 1781 } 1782 if(ability->loopback & SOC_PA_LB_PHY) { 1783 local_ability |= BFCMAP_PHY84756_PA_LB_PHY; 1784 } 1785 if(ability->flags & SOC_PA_AUTONEG) { 1786 local_ability |= BFCMAP_PHY84756_PA_AN; 1787 } 1788 1789 rv = bfcmap_phy84756_ability_advert_set(pc, local_ability); 1790 1791 SOC_IF_ERROR_RETURN 1792 (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode)); 1793 1794 if ((repeater_mode & 0x6) == 0x6) { 1795 if (NULL != int_pc) { 1796 SOC_IF_ERROR_RETURN( 1797 PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, ability)); 1798 } 1799 } 1800 1801 return rv; 1802 } 1803 1804 /* 1805 * Function: 1806 * phy_84756_fcmap_ability_advert_get 1807 * Purpose: 1808 * Get the current advertisement for auto-negotiation. 1809 * Parameters: 1810 * unit - StrataSwitch unit #. 1811 * port - StrataSwitch port #. 1812 * mode - (OUT) Port mode mask indicating supported options/speeds. 1813 * Returns: 1814 * SOC_E_XXX 1815 * Notes: 1816 * The advertisement is retrieved for the ACTIVE medium. 1817 * No synchronization performed at this level. 1818 */ 1819 STATIC int 1820 phy_84756_fcmap_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1821 { 1822 phy_ctrl_t *pc; 1823 int rv; 1824 bfcmap_phy84756_port_ability_t local_ability; 1825 phy_ctrl_t *int_pc; 1826 buint16_t repeater_mode; 1827 1828 int_pc = INT_PHY_SW_STATE(unit, port); 1829 1830 1831 if (NULL == ability) { 1832 return (SOC_E_PARAM); 1833 } 1834 1835 /* 40G advert Get */ 1836 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1837 PHY_ABILITY_ADVERT_GET(PHY84756_40G, unit, port, ability)); 1838 1839 1840 pc = EXT_PHY_SW_STATE(unit, port); 1841 #if defined(INCLUDE_FCMAP) 1842 if (pc->fcmap_enable) { 1843 ability->pause |= SOC_PA_PAUSE_TX; 1844 ability->pause |= SOC_PA_PAUSE_RX; 1845 return SOC_E_NONE; 1846 } 1847 #endif 1848 1849 local_ability = 0; 1850 1851 rv = bfcmap_phy84756_ability_advert_get(pc, &local_ability); 1852 if (rv != SOC_E_NONE) { 1853 return SOC_E_FAIL; 1854 } 1855 1856 if(local_ability & BFCMAP_PHY84756_PA_1000MB_FD) { 1857 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1858 } 1859 if(local_ability & BFCMAP_PHY84756_PA_10000MB_FD) { 1860 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1861 } 1862 1863 if(local_ability & BFCMAP_PHY84756_PA_PAUSE_TX) { 1864 ability->pause |= SOC_PA_PAUSE_TX; 1865 } 1866 if(local_ability & BFCMAP_PHY84756_PA_PAUSE_RX) { 1867 ability->pause |= SOC_PA_PAUSE_RX; 1868 } 1869 if(local_ability & BFCMAP_PHY84756_PA_PAUSE_ASYMM) { 1870 ability->pause |= SOC_PA_PAUSE_ASYMM; 1871 } 1872 1873 if(local_ability & BFCMAP_PHY84756_PA_LB_NONE) { 1874 ability->loopback |= SOC_PA_LB_NONE; 1875 } 1876 if(local_ability & BFCMAP_PHY84756_PA_LB_PHY) { 1877 ability->loopback |= SOC_PA_LB_PHY; 1878 } 1879 if(local_ability & BFCMAP_PHY84756_PA_AN) { 1880 ability->flags = SOC_PA_AUTONEG; 1881 } 1882 1883 SOC_IF_ERROR_RETURN 1884 (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode)); 1885 1886 if ((repeater_mode & 0x6) == 0x6) { 1887 if (NULL != int_pc) { 1888 SOC_IF_ERROR_RETURN( 1889 PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, ability)); 1890 } 1891 } 1892 1893 return SOC_E_NONE; 1894 } 1895 1896 /* 1897 * Function: 1898 * phy_84756_fcmap_ability_remote_get 1899 * Purpose: 1900 * Get the current remote advertisement for auto-negotiation. 1901 * Parameters: 1902 * unit - StrataSwitch unit #. 1903 * port - StrataSwitch port #. 1904 * mode - (OUT) Port mode mask indicating supported options/speeds. 1905 * Returns: 1906 * SOC_E_XXX 1907 * Notes: 1908 * The advertisement is retrieved for the ACTIVE medium. 1909 * No synchronization performed at this level. 1910 */ 1911 STATIC int 1912 phy_84756_fcmap_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1913 { 1914 phy_ctrl_t *pc; 1915 int rv; 1916 bfcmap_phy84756_port_ability_t remote_ability; 1917 phy_ctrl_t *int_pc; 1918 buint16_t repeater_mode; 1919 1920 int_pc = INT_PHY_SW_STATE(unit, port); 1921 1922 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1923 return SOC_E_NONE; 1924 } 1925 1926 if (NULL == ability) { 1927 return (SOC_E_PARAM); 1928 } 1929 1930 /* 40G ability Get */ 1931 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 1932 PHY_ABILITY_REMOTE_GET(PHY84756_40G, unit, port, ability)); 1933 1934 pc = EXT_PHY_SW_STATE(unit, port); 1935 #if defined(INCLUDE_FCMAP) 1936 if (pc->fcmap_enable) { 1937 ability->pause |= SOC_PA_PAUSE_TX; 1938 ability->pause |= SOC_PA_PAUSE_RX; 1939 return SOC_E_NONE; 1940 } 1941 #endif 1942 1943 remote_ability = 0; 1944 1945 rv = bfcmap_phy84756_remote_ability_advert_get(pc, 1946 &remote_ability); 1947 if (rv != SOC_E_NONE) { 1948 return SOC_E_FAIL; 1949 } 1950 1951 if(remote_ability & BFCMAP_PHY84756_PA_1000MB_FD) { 1952 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1953 } 1954 if(remote_ability & BFCMAP_PHY84756_PA_10000MB_FD) { 1955 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1956 } 1957 1958 if(remote_ability & BFCMAP_PHY84756_PA_PAUSE_TX) { 1959 ability->pause |= SOC_PA_PAUSE_TX; 1960 } 1961 if(remote_ability & BFCMAP_PHY84756_PA_PAUSE_RX) { 1962 ability->pause |= SOC_PA_PAUSE_RX; 1963 } 1964 if(remote_ability & BFCMAP_PHY84756_PA_PAUSE_ASYMM) { 1965 ability->pause |= SOC_PA_PAUSE_ASYMM; 1966 } 1967 1968 if(remote_ability & BFCMAP_PHY84756_PA_LB_NONE) { 1969 ability->loopback |= SOC_PA_LB_NONE; 1970 } 1971 if(remote_ability & BFCMAP_PHY84756_PA_LB_PHY) { 1972 ability->loopback |= SOC_PA_LB_PHY; 1973 } 1974 if(remote_ability & BFCMAP_PHY84756_PA_AN) { 1975 ability->flags = SOC_PA_AUTONEG; 1976 } 1977 1978 SOC_IF_ERROR_RETURN 1979 (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode)); 1980 1981 if ((repeater_mode & 0x6) == 0x6) { 1982 if (NULL != int_pc) { 1983 SOC_IF_ERROR_RETURN( 1984 PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability)); 1985 } 1986 } 1987 1988 return SOC_E_NONE; 1989 } 1990 1991 1992 1993 /* 1994 * Function: 1995 * phy_84756_fcmap_ability_local_get 1996 * Purpose: 1997 * Get local abilities 1998 * Parameters: 1999 * unit - StrataSwitch unit #. 2000 * port - StrataSwitch port #. 2001 * mode - (OUT) Port mode mask indicating supported options/speeds. 2002 * Returns: 2003 * SOC_E_NONE 2004 * Notes: 2005 * The ability is retrieved only for the ACTIVE medium. 2006 */ 2007 2008 STATIC int 2009 phy_84756_fcmap_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 2010 { 2011 int rv = SOC_E_NONE; 2012 phy_ctrl_t *pc; 2013 bfcmap_phy84756_port_ability_t local_ability = 0; 2014 phy_ctrl_t *int_pc; 2015 buint16_t repeater_mode; 2016 2017 int_pc = INT_PHY_SW_STATE(unit, port); 2018 2019 if (NULL == ability) { 2020 return SOC_E_PARAM; 2021 } 2022 2023 /* 40G ability Get */ 2024 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 2025 PHY_ABILITY_LOCAL_GET(PHY84756_40G, unit, port, ability)); 2026 2027 pc = EXT_PHY_SW_STATE(unit, port); 2028 #if defined(INCLUDE_FCMAP) 2029 if (pc->fcmap_enable) { 2030 ability->pause |= SOC_PA_PAUSE_TX; 2031 ability->pause |= SOC_PA_PAUSE_RX; 2032 return SOC_E_NONE; 2033 } 2034 #endif 2035 2036 rv = bfcmap_phy84756_ability_local_get(pc, &local_ability); 2037 if (rv != SOC_E_NONE) { 2038 return SOC_E_FAIL; 2039 } 2040 2041 if(local_ability & BFCMAP_PHY84756_PA_1000MB_FD) { 2042 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 2043 } 2044 if(local_ability & BFCMAP_PHY84756_PA_10000MB_FD) { 2045 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 2046 } 2047 2048 if(local_ability & BFCMAP_PHY84756_PA_PAUSE_TX) { 2049 ability->pause |= SOC_PA_PAUSE_TX; 2050 } 2051 if(local_ability & BFCMAP_PHY84756_PA_PAUSE_RX) { 2052 ability->pause |= SOC_PA_PAUSE_RX; 2053 } 2054 if(local_ability & BFCMAP_PHY84756_PA_PAUSE_ASYMM) { 2055 ability->pause |= SOC_PA_PAUSE_ASYMM; 2056 } 2057 if(local_ability & BFCMAP_PHY84756_PA_LB_NONE) { 2058 ability->loopback |= SOC_PA_LB_NONE; 2059 } 2060 if(local_ability & BFCMAP_PHY84756_PA_LB_PHY) { 2061 ability->loopback |= SOC_PA_LB_PHY; 2062 } 2063 if(local_ability & BFCMAP_PHY84756_PA_AN) { 2064 ability->flags = SOC_PA_AUTONEG; 2065 } 2066 2067 SOC_IF_ERROR_RETURN 2068 (BFCMAP_PHY84756_REG_RD(pc, 0x0, 0x1, 0xc806, &repeater_mode)); 2069 2070 if ((repeater_mode & 0x6) == 0x6) { 2071 if (NULL != int_pc) { 2072 SOC_IF_ERROR_RETURN( 2073 PHY_ABILITY_LOCAL_GET(int_pc->pd, unit, port, ability)); 2074 } 2075 } 2076 2077 return SOC_E_NONE; 2078 } 2079 2080 #if defined(INCLUDE_FCMAP) 2081 extern int 2082 bfcmap84756_a0_firmware_download(bfcmap_dev_addr_t dev_addr, int broadcast, int enable); 2083 #endif 2084 2085 STATIC int 2086 _phy84756_init_ucode_bcst(int unit, int port, uint32 cmd) 2087 { 2088 uint16 data16; 2089 uint16 mask16; 2090 int j, bcst_edc_fw; 2091 uint16 phy_id; 2092 int i; 2093 uint16 chip_mode; 2094 int num_lanes; 2095 uint16 num_words; 2096 uint8 *fw_ptr; 2097 int fw_length; 2098 phy_ctrl_t *pc; 2099 #if defined(INCLUDE_FCMAP) 2100 static int fc_extra_delay = 0; 2101 int bcst_fc_fw; 2102 #endif 2103 pc = EXT_PHY_SW_STATE(unit, port); 2104 num_lanes = PHY84756_SINGLE_PORT_MODE(pc) ? 4 : 1; 2105 2106 bcst_edc_fw = pc->flags & PHYCTRL_MDIO_BCST; 2107 #if defined(INCLUDE_FCMAP) 2108 bcst_fc_fw = pc->flags & PHYCTRL_MDIO_BCST2; 2109 #endif 2110 2111 #ifdef BCM_WARM_BOOT_SUPPORT 2112 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 2113 return SOC_E_NONE; 2114 } 2115 #endif 2116 2117 if (cmd == PHYCTRL_UCODE_BCST_SETUP) { 2118 SOC_IF_ERROR_RETURN( 2119 BFCMAP_RD_PHY84756_LN_DEV1_CHIP_MODEr(pc, &chip_mode)); 2120 2121 LOG_INFO(BSL_LS_SOC_PHY, 2122 (BSL_META_U(unit, 2123 "PHY84756 BCST start: u=%d p=%d\n"), unit, port)); 2124 2125 /* check the current chip mode, switch to quad if in single port mode */ 2126 if ((chip_mode & PHY84756_PMAD_CHIP_MODE_MASK) == PHY84756_PMAD_MODE_40G) { 2127 LOG_INFO(BSL_LS_SOC_PHY, 2128 (BSL_META_U(unit, 2129 "PHY84741 BCST mode switch: u=%d p=%d\n"), unit, port)); 2130 SOC_IF_ERROR_RETURN( 2131 _phy_84741_single_to_quad_mode(unit,port,NULL)); 2132 } 2133 2134 /* program the bcst register. do 4 lanes for single port configuration */ 2135 phy_id = pc->phy_id; 2136 /* configure all four ports */ 2137 for (i = 0; i < num_lanes; i++) { 2138 if (num_lanes > 1) { 2139 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 2140 } 2141 SOC_IF_ERROR_RETURN 2142 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff)); 2143 } 2144 /* restore the original phy_id */ 2145 pc->phy_id = phy_id; 2146 return SOC_E_NONE; 2147 } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) { 2148 if (bcst_edc_fw) { 2149 LOG_INFO(BSL_LS_SOC_PHY, 2150 (BSL_META_U(unit, 2151 "PHY84756 BCST1: u=%d p=%d\n"), unit, port)); 2152 /* clear SPA ctrl reg bit 15 and bit 13. 2153 * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM 2154 * bit 13, 0 clear download done status, 1 skip download 2155 */ 2156 mask16 = (1 << 13) | (1 << 15); 2157 data16 = 0; 2158 2159 SOC_IF_ERROR_RETURN 2160 (BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, data16, mask16)); 2161 2162 /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */ 2163 mask16 = 1 << 14; 2164 data16 = mask16; 2165 2166 SOC_IF_ERROR_RETURN 2167 (BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, data16, mask16)); 2168 2169 /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */ 2170 mask16 = 1 << 3; 2171 data16 = mask16; 2172 2173 SOC_IF_ERROR_RETURN 2174 (BFCMAP_MOD_PHY84756_LN_DEV1_MISC_CNTL2r(pc, data16, mask16)); 2175 2176 /* apply bcst Reset to start download code from MDIO */ 2177 SOC_IF_ERROR_RETURN 2178 (BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, 0x8000)); 2179 } 2180 return SOC_E_NONE; 2181 } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) { 2182 LOG_INFO(BSL_LS_SOC_PHY, 2183 (BSL_META_U(unit, 2184 "PHY84756 BCST2: u=%d p=%d\n"), unit, port)); 2185 2186 /* reset clears bcst register */ 2187 /* restore bcst register after reset */ 2188 2189 phy_id = pc->phy_id; 2190 /* configure all four ports */ 2191 for (i = 0; i < num_lanes; i++) { 2192 if (num_lanes > 1) { 2193 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 2194 } 2195 SOC_IF_ERROR_RETURN 2196 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8fe, 0xffff)); 2197 } 2198 /* restore the original phy_id */ 2199 pc->phy_id = phy_id; 2200 return SOC_E_NONE; 2201 } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) { 2202 if (bcst_edc_fw) { 2203 2204 LOG_INFO(BSL_LS_SOC_PHY, 2205 (BSL_META_U(unit, 2206 "firmware_bcst,device name %s: u=%d p=%d\n"), 2207 pc->dev_name? pc->dev_name: "NULL", unit, port)); 2208 2209 2210 fw_ptr = FIRMWARE(pc); 2211 fw_length = FIRMWARE_LEN(pc); 2212 2213 /* wait for 2ms for M8051 start and 5ms to initialize the RAM */ 2214 sal_usleep(10000); /* Wait for 10ms */ 2215 2216 /* Write Starting Address, where the Code will reside in SRAM */ 2217 data16 = 0x8000; 2218 SOC_IF_ERROR_RETURN 2219 (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, data16)); 2220 2221 /* make sure address word is read by the micro */ 2222 sal_udelay(10); /* Wait for 10us */ 2223 2224 /* Write SPI SRAM Count Size */ 2225 data16 = (fw_length)/2; 2226 SOC_IF_ERROR_RETURN 2227 (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, data16)); 2228 2229 /* make sure read by the micro */ 2230 sal_udelay(10); /* Wait for 10us */ 2231 2232 /* Fill in the SRAM */ 2233 num_words = (fw_length - 1); 2234 for (j = 0; j < num_words; j+=2) { 2235 /* Make sure the word is read by the Micro */ 2236 sal_udelay(10); 2237 2238 data16 = (fw_ptr[j] << 8) | fw_ptr[j+1]; 2239 2240 SOC_IF_ERROR_RETURN 2241 (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, data16)); 2242 } 2243 2244 } 2245 return SOC_E_NONE; 2246 } else if (cmd == PHYCTRL_UCODE_BCST_LOAD2) { 2247 #if defined(INCLUDE_FCMAP) 2248 if (bcst_fc_fw) 2249 { 2250 LOG_INFO(BSL_LS_SOC_PHY, 2251 (BSL_META_U(unit, 2252 "uc_firmware_bcst,device name %s: u=%d p=%d\n"), 2253 pc->dev_name? pc->dev_name: "NULL", unit, port)); 2254 /* reset clears macsec enable */ 2255 /* restore macsec enable after reset */ 2256 SOC_IF_ERROR_RETURN 2257 (BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, 0)); 2258 sal_udelay(100); /* Wait for 100us */ 2259 2260 /* Send to UC Firmware Download data */ 2261 bfcmap84756_a0_firmware_download(SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1), 1, 0); 2262 sal_udelay(100000); 2263 fc_extra_delay = 1; 2264 2265 /* Power down MACSEC to reduce power consumption */ 2266 SOC_IF_ERROR_RETURN( 2267 BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, 2268 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE | 2269 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC | 2270 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC)); 2271 } 2272 #endif 2273 return SOC_E_NONE; 2274 } else if (cmd == PHYCTRL_UCODE_BCST_END) { 2275 LOG_INFO(BSL_LS_SOC_PHY, 2276 (BSL_META_U(unit, 2277 "PHY84756 BCST end: u=%d p=%d\n"), unit, port)); 2278 2279 /* make sure last code word is read by the micro */ 2280 sal_udelay(20); 2281 2282 phy_id = pc->phy_id; 2283 for (i = 0; i < num_lanes; i++) { 2284 if (num_lanes > 1) { 2285 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 2286 } 2287 2288 /* first disable bcst mode */ 2289 SOC_IF_ERROR_RETURN 2290 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8fe, 0x0)); 2291 2292 if (bcst_edc_fw) { 2293 /* Read Hand-Shake message (Done) from Micro */ 2294 SOC_IF_ERROR_RETURN 2295 (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &data16)); 2296 2297 /* Download done message */ 2298 LOG_INFO(BSL_LS_SOC_PHY, 2299 (BSL_META_U(unit, 2300 "u=%d p=%d MDIO firmware download done message: 0x%x\n"), 2301 unit, port,data16)); 2302 2303 /* Clear LASI status */ 2304 SOC_IF_ERROR_RETURN 2305 (BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARM_STATr(pc, &data16)); 2306 2307 } 2308 2309 } 2310 /* restore the original phy_id */ 2311 pc->phy_id = phy_id; 2312 2313 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 2314 sal_udelay(100); /* Wait for 100 usecs */ 2315 2316 phy_id = pc->phy_id; 2317 for (i = 0; i < num_lanes; i++) { 2318 if (num_lanes > 1) { 2319 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 2320 } 2321 if (bcst_edc_fw) { 2322 SOC_IF_ERROR_RETURN 2323 (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &data16)); 2324 2325 2326 /* read Rev-ID */ 2327 /* Need to check if checksum is correct */ 2328 SOC_IF_ERROR_RETURN 2329 (BFCMAP_RD_PHY84756_LN_DEV1_CHECKSUMr(pc, &data16)); 2330 2331 if (data16 != 0x600D) { 2332 /* Bad CHECKSUM */ 2333 LOG_CLI((BSL_META_U(unit, 2334 "firmware_bcst downlad failure: port %d " 2335 "Incorrect Checksum %x\n"), port,data16)); 2336 return SOC_E_FAIL; 2337 } 2338 2339 /* read Rev-ID */ 2340 SOC_IF_ERROR_RETURN 2341 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &data16)); 2342 LOG_INFO(BSL_LS_SOC_PHY, 2343 (BSL_META_U(unit, 2344 "BCM84756 u=%d p=%d: MDIO broadcast download, EDC firmware version=%x\n"), 2345 unit, port, data16)); 2346 } 2347 } 2348 /* restore the original phy_id */ 2349 pc->phy_id = phy_id; 2350 2351 #if defined(INCLUDE_FCMAP) 2352 if (bcst_fc_fw) 2353 { 2354 LOG_INFO(BSL_LS_SOC_PHY, 2355 (BSL_META_U(unit, 2356 "BCM84756 u=%d p=%d: FC firmware MDIO broadcast download\n"), 2357 unit, port)); 2358 if (fc_extra_delay) 2359 { 2360 sal_udelay(100000); /* per mdio bus: wait 100 msec for bcast disable to become effective */ 2361 fc_extra_delay = 0; 2362 } 2363 } 2364 #endif 2365 return SOC_E_NONE; 2366 } else { 2367 LOG_WARN(BSL_LS_SOC_PHY, 2368 (BSL_META_U(unit, 2369 "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"), 2370 unit, port,cmd)); 2371 } 2372 2373 return SOC_E_FAIL; 2374 } 2375 2376 /* 2377 * Function: 2378 * phy_84756_firmware_set 2379 * Purpose: 2380 * program the given firmware into the SPI-ROM 2381 * Parameters: 2382 * unit - StrataSwitch unit #. 2383 * port - StrataSwitch port #. 2384 * offset - offset to the data stream 2385 * array - the given data 2386 * datalen- the data length 2387 * Returns: 2388 * SOC_E_NONE 2389 */ 2390 2391 STATIC int 2392 phy_84756_fcmap_firmware_set(int unit, int port, int offset, uint8 *data,int len) 2393 { 2394 int rv; 2395 phy_ctrl_t *pc; 2396 2397 pc = EXT_PHY_SW_STATE(unit, port); 2398 2399 if (PHY84756_IS_8474X(pc) && (data != NULL)) { 2400 if (PHY84756_SINGLE_PORT_MODE(pc)) { 2401 LOG_WARN(BSL_LS_SOC_PHY, 2402 (BSL_META_U(unit, 2403 "u=%d p=%d Firmware set not supported in 40G mode\n"), 2404 unit, port)); 2405 return SOC_E_FAIL; 2406 } 2407 } 2408 2409 /* overload this function a littl bit if data == NULL 2410 * special handling for init. uCode broadcast. Internal use only 2411 */ 2412 if (data == NULL) { 2413 return _phy84756_init_ucode_bcst(unit,port,(uint32)offset); 2414 } 2415 2416 rv = bfcmap_phy84756_spi_firmware_update(pc, data, len); 2417 if (rv != SOC_E_NONE) { 2418 LOG_WARN(BSL_LS_SOC_PHY, 2419 (BSL_META_U(unit, 2420 "PHY84756 firmware upgrade possibly failed:" 2421 "u=%d p=%d\n"), unit, port)); 2422 return (SOC_E_FAIL); 2423 } 2424 LOG_INFO(BSL_LS_SOC_PHY, 2425 (BSL_META_U(unit, 2426 "PHY84756 firmware upgrade successful:" 2427 "u=%d p=%d\n"), unit, port)); 2428 2429 return SOC_E_NONE; 2430 } 2431 2432 /* 2433 * Function: 2434 * phy_84756_fcmap_medium_status 2435 * Purpose: 2436 * Indicate the current active medium 2437 * Parameters: 2438 * unit - StrataSwitch unit #. 2439 * port - StrataSwitch port #. 2440 * medium - (OUT) One of: 2441 * SOC_PORT_MEDIUM_COPPER 2442 * SOC_PORT_MEDIUM_XAUI 2443 * Returns: 2444 * SOC_E_NONE 2445 */ 2446 2447 STATIC int 2448 phy_84756_fcmap_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 2449 { 2450 COMPILER_REFERENCE(unit); 2451 COMPILER_REFERENCE(port); 2452 2453 *medium = SOC_PORT_MEDIUM_FIBER; 2454 2455 return SOC_E_NONE; 2456 } 2457 2458 STATIC int 2459 _phy_84756_control_tx_driver_set(int unit, soc_port_t port, 2460 soc_phy_control_t type, uint32 value) 2461 { 2462 uint16 data; /* Temporary holder of reg value to be written */ 2463 uint16 mask; /* Bit mask of reg value to be updated */ 2464 uint16 post_tap; 2465 uint16 main_tap; 2466 phy_ctrl_t *pc; /* PHY software state */ 2467 uint16 reg; 2468 int interface; 2469 2470 pc = EXT_PHY_SW_STATE(unit, port); 2471 interface = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)? 2472 PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE; 2473 2474 switch(type) { 2475 case SOC_PHY_CONTROL_DRIVER_CURRENT: 2476 /* fall through */ 2477 data = (uint16)(value & 0xf); 2478 data = data << 12; 2479 mask = 0xf000; 2480 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 2481 SOC_IF_ERROR_RETURN 2482 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, data, mask)); 2483 break; 2484 2485 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 2486 /* fall through */ 2487 data = (uint16)(value & 0xf); 2488 data = data << 8; 2489 mask = 0x0f00; 2490 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 2491 SOC_IF_ERROR_RETURN 2492 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, data, mask)); 2493 break; 2494 case SOC_PHY_CONTROL_PREEMPHASIS: 2495 /* The value format: 2496 * bit 15: 1 enable forced preemphasis ctrl, 0 auto config 2497 * bit 14:10: post_tap value 2498 * bit 09:04: main tap value 2499 * 2500 * set 1.CA05[15] = 0, 1.CA02[15:11] for main_tap and 1.CA05[7:4] for post tap. 2501 * main tap control is in the register field 0xCA02[15:11]. 2502 * If a wrong value is written to the same register, field 0xCA02[9:7], 2503 * it may DAMAGE the device. User must avoid writing to 0xCA02[9:7] 2504 */ 2505 /* Register bit15, 0 force preemphasis, 1 auto config, 1.CA05 */ 2506 post_tap = PHY84756_PREEMPH_GET_FORCE(value)? 0: 2507 PHY84756_PREEMPH_REG_FORCE_MASK; 2508 2509 /* add post tap value */ 2510 post_tap |= PHY84756_PREEMPH_GET_POST_TAP(value) << 2511 PHY84756_PREEMPH_REG_POST_TAP_SHFT; 2512 2513 /* main tap in 1.CA02 */ 2514 main_tap = PHY84756_PREEMPH_GET_MAIN_TAP(value) << 2515 PHY84756_PREEMPH_REG_MAIN_TAP_SHFT; 2516 2517 2518 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca05; 2519 SOC_IF_ERROR_RETURN 2520 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, 2521 post_tap, PHY84756_PREEMPH_REG_POST_TAP_MASK | 2522 PHY84756_PREEMPH_REG_FORCE_MASK)); 2523 2524 /* always clear tx_pwrdn bit. The read/modify/write may accidently 2525 * set the bit 0xCA02[10]. Because the CA02[10] read value is: 2526 * CA02[10]_read_value = CA02[10] OR Digital_State_Machine 2527 * The problem will occur when the Digital_State_Machine output is 1 2528 * at the time of reading this register. 2529 */ 2530 2531 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90b : 0xca02; 2532 SOC_IF_ERROR_RETURN 2533 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, reg, 2534 main_tap, 2535 PHY84756_PREEMPH_REG_MAIN_TAP_MASK | 2536 PHY84756_PREEMPH_REG_TX_PWRDN_MASK)); 2537 break; 2538 2539 default: 2540 /* should never get here */ 2541 return SOC_E_PARAM; 2542 } 2543 return SOC_E_NONE; 2544 } 2545 2546 STATIC int 2547 _phy_84756_control_tx_driver_get(int unit, soc_port_t port, 2548 soc_phy_control_t type, uint32 *value) 2549 { 2550 uint16 data16; /* Temporary holder of a reg value */ 2551 uint16 main_tap; 2552 uint16 post_tap; 2553 phy_ctrl_t *pc; /* PHY software state */ 2554 uint16 reg; 2555 int interface; 2556 2557 pc = EXT_PHY_SW_STATE(unit, port); 2558 interface = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)? 2559 PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE; 2560 2561 data16 = 0; 2562 switch(type) { 2563 case SOC_PHY_CONTROL_PREEMPHASIS: 2564 /* 1.CA05[15] = 0, set 1.CA02[15:11] for main_tap and 2565 * 1.CA05[7:4] for postcursor 2566 */ 2567 2568 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90b : 0xca02; 2569 SOC_IF_ERROR_RETURN 2570 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &main_tap)); 2571 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca05; 2572 SOC_IF_ERROR_RETURN 2573 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &post_tap)); 2574 2575 /* bit15 force flag, 14:10 post_tap, 09:04 main tap */ 2576 *value = (post_tap & PHY84756_PREEMPH_REG_FORCE_MASK)? 0: 2577 (1 << PHY84756_PREEMPH_CTRL_FORCE_SHFT); 2578 *value |= ((post_tap & PHY84756_PREEMPH_REG_POST_TAP_MASK) >> 2579 PHY84756_PREEMPH_REG_POST_TAP_SHFT) << 2580 PHY84756_PREEMPH_CTRL_POST_TAP_SHFT; 2581 *value |= ((main_tap & PHY84756_PREEMPH_REG_MAIN_TAP_MASK) >> 2582 PHY84756_PREEMPH_REG_MAIN_TAP_SHFT) << 2583 PHY84756_PREEMPH_CTRL_MAIN_TAP_SHFT; 2584 2585 break; 2586 2587 case SOC_PHY_CONTROL_DRIVER_CURRENT: 2588 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 2589 SOC_IF_ERROR_RETURN 2590 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &data16)); 2591 *value = (data16 & 0xf000) >> 12; 2592 break; 2593 2594 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 2595 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 2596 SOC_IF_ERROR_RETURN 2597 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, reg, &data16)); 2598 *value = (data16 & 0x0f00) >> 8; 2599 break; 2600 2601 default: 2602 /* should never get here */ 2603 return SOC_E_PARAM; 2604 } 2605 2606 return SOC_E_NONE; 2607 } 2608 2609 STATIC int 2610 _phy_84756_control_edc_mode_set(int unit, soc_port_t port, uint32 value) 2611 { 2612 uint16 data16; 2613 uint16 mask16; 2614 phy_ctrl_t *pc; /* PHY software state */ 2615 2616 pc = EXT_PHY_SW_STATE(unit, port); 2617 2618 2619 /* EDC mode programming sequence*/ 2620 mask16 = 1 << 9; 2621 2622 /* induce LOS condition: toggle register bit 0xc800.9 */ 2623 SOC_IF_ERROR_RETURN 2624 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 2625 0xc800,&data16)); 2626 2627 /* only change toggled bit 9 */ 2628 SOC_IF_ERROR_RETURN 2629 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 2630 0xc800,~data16,mask16)); 2631 2632 /* program EDC mode */ 2633 SOC_IF_ERROR_RETURN 2634 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A,(uint16)value, 2635 PHY84756_EDC_MODE_MASK)); 2636 2637 /* remove LOS condition: restore back original value of bit 0xc800.9 */ 2638 SOC_IF_ERROR_RETURN 2639 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 2640 0xc800,data16,mask16)); 2641 2642 return SOC_E_NONE; 2643 } 2644 2645 2646 STATIC int 2647 _phy_84756_control_prbs_tx_invert_data_set(int unit, soc_port_t port, int invert) 2648 { 2649 phy_ctrl_t *pc; /* PHY software state */ 2650 uint16 data16; 2651 int speed=0; 2652 2653 pc = EXT_PHY_SW_STATE(unit, port); 2654 2655 SOC_IF_ERROR_RETURN( 2656 phy_84756_fcmap_speed_get(unit, port, &speed)); 2657 2658 if (speed == 1000) { 2659 /* tx inversion */ 2660 data16 = invert? PHY84756_1G_USER_PRBS_TX_INVERT: 0; 2661 2662 2663 SOC_IF_ERROR_RETURN 2664 (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc, 2665 data16, 2666 PHY84756_1G_USER_PRBS_TX_INVERT)); 2667 } else { 2668 /* tx inversion */ 2669 data16 = invert? PHY84756_USER_PRBS_TX_INVERT: 0; 2670 2671 SOC_IF_ERROR_RETURN 2672 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 2673 PHY84756_USER_PRBS_CONTROL_0_REGISTER, data16, 2674 PHY84756_USER_PRBS_TX_INVERT)); 2675 } 2676 return SOC_E_NONE; 2677 } 2678 2679 STATIC int 2680 _phy_84756_control_prbs_rx_invert_data_set(int unit, soc_port_t port, int invert) 2681 { 2682 phy_ctrl_t *pc; /* PHY software state */ 2683 uint16 data16; 2684 uint16 mask16; 2685 2686 pc = EXT_PHY_SW_STATE(unit, port); 2687 2688 /* rx inversion */ 2689 data16 = invert? PHY84756_USER_PRBS_RX_INVERT: 0; 2690 mask16 = PHY84756_USER_PRBS_RX_INVERT; 2691 SOC_IF_ERROR_RETURN 2692 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 2693 PHY84756_USER_PRBS_CONTROL_0_REGISTER, data16, 2694 mask16)); 2695 return SOC_E_NONE; 2696 } 2697 2698 STATIC int 2699 _phy_84756_control_prbs_polynomial_set(int unit, soc_port_t port,int poly_ctrl, 2700 int tx) /* tx or rx */ 2701 { 2702 phy_ctrl_t *pc; /* PHY software state */ 2703 uint16 data16; 2704 uint16 mask16; 2705 int speed=0; 2706 2707 /* 2708 * poly_ctrl: 2709 * 0x0 = prbs7 2710 * 0x1 = prbs15 2711 * 0x2 = prbs23 2712 * 0x3 = prbs31 2713 */ 2714 pc = EXT_PHY_SW_STATE(unit, port); 2715 2716 /* 001 : prbs7 2717 010 : prbs9 2718 011 : prbs11 2719 100 : prbs15 2720 101 : prbs23 2721 110 : prbs31 2722 */ 2723 2724 SOC_IF_ERROR_RETURN( 2725 phy_84756_fcmap_speed_get(unit, port, &speed)); 2726 2727 if (poly_ctrl == 0) { 2728 data16 = SP_MAP(speed,1); 2729 } else if (poly_ctrl == 1) { 2730 data16 = SP_MAP(speed,4); 2731 } else if (poly_ctrl == 2) { 2732 data16 = SP_MAP(speed,5); 2733 } else if (poly_ctrl == 3) { 2734 data16 = SP_MAP(speed,6); 2735 } else { 2736 return SOC_E_PARAM; 2737 } 2738 2739 if(speed == 1000) { 2740 mask16 = PHY84756_USER_PRBS_TYPE_MASK_1G; 2741 } else { 2742 mask16 = PHY84756_USER_PRBS_TYPE_MASK; 2743 /* default is tx */ 2744 if (!tx) { /* rx */ 2745 data16 = data16 << 12; 2746 mask16 = mask16 << 12; 2747 } 2748 } 2749 2750 if(speed == 1000) { 2751 SOC_IF_ERROR_RETURN 2752 (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc, 2753 data16, mask16)); 2754 /* Enable PRBS Checker 7.80B1.[2:0]=111 */ 2755 SOC_IF_ERROR_RETURN 2756 (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_LOCK_ERR(pc, 0x7, 0x7)); 2757 2758 } else { 2759 /* both tx/rx types */ 2760 SOC_IF_ERROR_RETURN 2761 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 2762 PHY84756_USER_PRBS_CONTROL_0_REGISTER, 2763 data16, mask16)); 2764 } 2765 2766 return SOC_E_NONE; 2767 } 2768 STATIC int 2769 _phy_84756_control_prbs_enable_set(int unit, soc_port_t port, int enable) 2770 { 2771 phy_ctrl_t *pc; /* PHY software state */ 2772 int repeater_mode; 2773 uint16 data16; 2774 int speed = 0; 2775 2776 pc = EXT_PHY_SW_STATE(unit, port); 2777 2778 SOC_IF_ERROR_RETURN( 2779 phy_84756_fcmap_speed_get(unit, port, &speed)); 2780 2781 if(speed == 1000) { 2782 /* disable Comma Detect and CL36 for 1G PRBS */ 2783 SOC_IF_ERROR_RETURN( 2784 BFCMAP_WR_PHY84756_XFI_DEV7_XGXS_CTRL(pc, 0x2c22)); 2785 SOC_IF_ERROR_RETURN( 2786 BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL2(pc, 0)); 2787 SOC_IF_ERROR_RETURN( 2788 BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL0(pc, 0)); 2789 } 2790 2791 SOC_IF_ERROR_RETURN 2792 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc81d, &data16)); 2793 2794 repeater_mode = ((data16 & 0x6) == 0x6)? TRUE: FALSE; 2795 if (repeater_mode) { 2796 /* Enable retimer prbs clocks inside SFI */ 2797 SOC_IF_ERROR_RETURN 2798 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 2799 PHY84756_GENSIG_8071_REGISTER, 2800 enable?0x3:0,0x3)); 2801 2802 /* Enable the retimer datapath */ 2803 SOC_IF_ERROR_RETURN 2804 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 0xcd58, 2805 enable?0x2:0,0x3)); 2806 } 2807 /* clear PRBS control if disabled */ 2808 if (!enable) { 2809 if (speed == 1000) { 2810 2811 SOC_IF_ERROR_RETURN 2812 (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc, 2813 0, PHY84756_40G_PRBS_TX_ENABLE)); 2814 /* Set 7.8015, 7.8017, 7.8000 to original values */ 2815 SOC_IF_ERROR_RETURN( 2816 BFCMAP_WR_PHY84756_XFI_DEV7_XGXS_CTRL(pc, PHY84756_1G_PRBS_XGXS_CTRL)); 2817 SOC_IF_ERROR_RETURN( 2818 BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL2(pc, PHY84756_1G_PRBS_LANE_CTRL2)); 2819 SOC_IF_ERROR_RETURN( 2820 BFCMAP_WR_PHY84756_XFI_DEV7_LANE_CTRL0(pc, PHY84756_1G_PRBS_LANE_CTRL0)); 2821 2822 } else { 2823 SOC_IF_ERROR_RETURN 2824 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 2825 PHY84756_USER_PRBS_CONTROL_0_REGISTER, 0, 2826 PHY84756_USER_PRBS_TYPE_MASK | 2827 PHY84756_USER_PRBS_TYPE_MASK << 12)); /* rx type*/ 2828 } 2829 } 2830 2831 /* program the PRBS enable */ 2832 2833 if (speed == 1000) { 2834 SOC_IF_ERROR_RETURN 2835 (BFCMAP_MOD_PHY84756_XFI_DEV7_PRBS_GEN( pc, 2836 enable? PHY84756_40G_PRBS_TX_ENABLE: 0 , PHY84756_40G_PRBS_TX_ENABLE)); 2837 } else { 2838 SOC_IF_ERROR_RETURN 2839 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr( pc, 2840 PHY84756_USER_PRBS_CONTROL_0_REGISTER, 2841 enable? PHY84756_USER_PRBS_ENABLE: 0,PHY84756_USER_PRBS_ENABLE)); 2842 } 2843 2844 return SOC_E_NONE; 2845 } 2846 2847 STATIC int 2848 _phy_84756_control_pdet_set(int unit, soc_port_t port, uint32 enable) 2849 { 2850 uint16 mask; 2851 uint16 data; 2852 phy_ctrl_t *pc; /* PHY software state */ 2853 2854 mask = PHY84756_PDET_MASK; 2855 data = enable ? mask : 0; 2856 2857 pc = EXT_PHY_SW_STATE(unit, port); 2858 2859 SOC_IF_ERROR_RETURN( 2860 BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL2r(pc, data, mask)); 2861 2862 return SOC_E_NONE; 2863 } 2864 2865 STATIC int 2866 _phy_84756_control_prbs_enable_get(int unit, soc_port_t port, uint32 *value) 2867 { 2868 uint16 data16; 2869 phy_ctrl_t *pc; /* PHY software state */ 2870 int speed =0; 2871 2872 pc = EXT_PHY_SW_STATE(unit, port); 2873 2874 SOC_IF_ERROR_RETURN( 2875 phy_84756_fcmap_speed_get(unit, port, &speed)); 2876 2877 if(speed == 1000) { 2878 SOC_IF_ERROR_RETURN 2879 (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_GEN( pc, 2880 &data16)); 2881 } else { 2882 2883 SOC_IF_ERROR_RETURN 2884 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 2885 PHY84756_USER_PRBS_CONTROL_0_REGISTER, &data16)); 2886 } 2887 2888 if ( ((speed == 1000) && (data16 & PHY84756_40G_PRBS_TX_ENABLE)) ) { 2889 *value = TRUE; 2890 } else if ( (speed != 1000) && (data16 & PHY84756_USER_PRBS_ENABLE) ) { 2891 *value = TRUE; 2892 } else { 2893 *value = FALSE; 2894 } 2895 2896 return SOC_E_NONE; 2897 } 2898 STATIC int 2899 _phy_84756_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value) 2900 { 2901 phy_ctrl_t *pc; /* PHY software state */ 2902 uint16 poly_ctrl; 2903 int speed =0; 2904 2905 pc = EXT_PHY_SW_STATE(unit, port); 2906 SOC_IF_ERROR_RETURN( 2907 phy_84756_fcmap_speed_get(unit, port, &speed)); 2908 2909 if(speed == 1000) { 2910 SOC_IF_ERROR_RETURN 2911 (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_GEN( pc, 2912 &poly_ctrl)); 2913 poly_ctrl &= PHY84756_USER_PRBS_TYPE_MASK_1G; 2914 } else { 2915 2916 SOC_IF_ERROR_RETURN 2917 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 2918 PHY84756_USER_PRBS_CONTROL_0_REGISTER, &poly_ctrl)); 2919 poly_ctrl &= PHY84756_USER_PRBS_TYPE_MASK; 2920 } 2921 2922 if (poly_ctrl == SP_MAP(speed,1)) { 2923 * value = 0; 2924 } else if (poly_ctrl == SP_MAP(speed,4)) { 2925 *value = 1; 2926 } else if (poly_ctrl == SP_MAP(speed,5)) { 2927 *value = 2; 2928 } else if (poly_ctrl == SP_MAP(speed,6)) { 2929 *value = 3; 2930 } else { 2931 *value = poly_ctrl; 2932 } 2933 2934 return SOC_E_NONE; 2935 } 2936 2937 STATIC int 2938 _phy_84756_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value) 2939 { 2940 phy_ctrl_t *pc; /* PHY software state */ 2941 uint16 data16; 2942 int speed=0; 2943 2944 pc = EXT_PHY_SW_STATE(unit, port); 2945 2946 SOC_IF_ERROR_RETURN( 2947 phy_84756_fcmap_speed_get(unit, port, &speed)); 2948 2949 if (speed == 1000) { 2950 2951 SOC_IF_ERROR_RETURN 2952 (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_GEN( pc, &data16)); 2953 2954 if (data16 & PHY84756_1G_USER_PRBS_TX_INVERT) { 2955 *value = TRUE; 2956 } else { 2957 *value = FALSE; 2958 } 2959 2960 } else { 2961 2962 SOC_IF_ERROR_RETURN 2963 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 2964 PHY84756_USER_PRBS_CONTROL_0_REGISTER, &data16)); 2965 if (data16 & PHY84756_USER_PRBS_TX_INVERT) { 2966 *value = TRUE; 2967 } else { 2968 *value = FALSE; 2969 } 2970 } 2971 return SOC_E_NONE; 2972 } 2973 2974 STATIC int 2975 _phy_84756_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value) 2976 { 2977 phy_ctrl_t *pc; /* PHY software state */ 2978 uint16 data16; 2979 int speed = 0; 2980 2981 pc = EXT_PHY_SW_STATE(unit, port); 2982 2983 *value = 0; 2984 2985 SOC_IF_ERROR_RETURN( 2986 phy_84756_fcmap_speed_get(unit, port, &speed)); 2987 2988 if(speed == 1000) { 2989 SOC_IF_ERROR_RETURN 2990 (BFCMAP_RD_PHY84756_XFI_DEV7_PRBS_CHK(pc, &data16)); 2991 } else { 2992 SOC_IF_ERROR_RETURN 2993 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr( pc, 2994 PHY84756_USER_PRBS_STATUS_0_REGISTER, &data16)); 2995 } 2996 2997 if (data16 == 0x8000) { /* PRBS lock and error free */ 2998 *value = 0; 2999 } else if (!(data16 & 0x8000)) { 3000 *value = -1; 3001 } else { 3002 *value = data16 & 0x7fff; 3003 } 3004 3005 return SOC_E_NONE; 3006 } 3007 3008 STATIC int 3009 _phy_84756_control_edc_mode_get(int unit, soc_port_t port, uint32 *value) 3010 { 3011 uint16 data16; 3012 phy_ctrl_t *pc; /* PHY software state */ 3013 3014 pc = EXT_PHY_SW_STATE(unit, port); 3015 3016 /* get EDC mode */ 3017 SOC_IF_ERROR_RETURN 3018 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A,&data16)); 3019 3020 *value = data16 & PHY84756_EDC_MODE_MASK; 3021 3022 return SOC_E_NONE; 3023 } 3024 3025 STATIC char * 3026 _phy_84756_mode_name_get(int unit, soc_port_t port) 3027 { 3028 phy_ctrl_t *pc; 3029 3030 pc = EXT_PHY_SW_STATE(unit, port); 3031 if (FCMAP_ENABLE(pc)) { 3032 return "FC"; 3033 } else if (MACSEC_ENABLE(pc)) { 3034 return "MACSEC"; 3035 } 3036 return "ETHERNET"; 3037 } 3038 3039 STATIC int 3040 _phy_84756_firmware_info_dump(int unit, soc_port_t port) 3041 { 3042 uint16 sts; 3043 uint16 version; 3044 uint16 cksum; 3045 phy_ctrl_t *pc; 3046 3047 pc = EXT_PHY_SW_STATE(unit, port); 3048 3049 SOC_IF_ERROR_RETURN 3050 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &version)); 3051 SOC_IF_ERROR_RETURN 3052 (BFCMAP_RD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, &sts)); 3053 SOC_IF_ERROR_RETURN 3054 (BFCMAP_RD_PHY84756_LN_DEV1_CHECKSUMr(pc, &cksum)); 3055 3056 LOG_CLI((BSL_META_U(unit, 3057 " Firmware: version=%04x, download status=%04x, " 3058 "checksum=%04x\n"), 3059 version, sts, cksum)); 3060 3061 return SOC_E_NONE; 3062 } 3063 3064 STATIC int 3065 _phy_84756_control_dump(int unit, soc_port_t port) 3066 { 3067 phy_ctrl_t *pc; 3068 uint16 chip_rev_id; 3069 3070 pc = EXT_PHY_SW_STATE(unit, port); 3071 3072 SOC_IF_ERROR_RETURN 3073 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xC801, &chip_rev_id)); 3074 3075 LOG_CLI((BSL_META_U(unit, 3076 "Port %d: chiprev=%04x, mode=%s, MACSEC support=%s\n"), 3077 port, chip_rev_id, _phy_84756_mode_name_get(unit, port), 3078 MACSEC_SUPPORT(pc) ? "yes" : "no")); 3079 LOG_CLI((BSL_META_U(unit, 3080 "size=%d sof=%d \n"), 3081 pc->size, (int) sizeof(phy84756_map_t) )); 3082 3083 SOC_IF_ERROR_RETURN(_phy_84756_firmware_info_dump(unit, port)); 3084 return SOC_E_NONE; 3085 } 3086 3087 STATIC int 3088 _phy_84756_control_pdet_get(int unit, soc_port_t port, uint32 *value) 3089 { 3090 uint16 data16; 3091 phy_ctrl_t *pc; /* PHY software state */ 3092 3093 pc = EXT_PHY_SW_STATE(unit, port); 3094 3095 SOC_IF_ERROR_RETURN( 3096 BFCMAP_RD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL2r(pc, &data16)); 3097 3098 if ((data16 & PHY84756_PDET_MASK) == PHY84756_PDET_MASK) { 3099 *value = 1; 3100 } else { 3101 *value = 0; 3102 } 3103 3104 return SOC_E_NONE; 3105 } 3106 3107 3108 /* 3109 * Function: 3110 * phy_84756_control_set 3111 * Purpose: 3112 * Configure PHY device specific control fucntion. 3113 * Parameters: 3114 * unit - StrataSwitch unit #. 3115 * port - StrataSwitch port #. 3116 * type - Control to update 3117 * value - New setting for the control 3118 * Returns: 3119 * SOC_E_NONE 3120 */ 3121 STATIC int 3122 _phy_84756_control_set(int unit, soc_port_t port, int intf,int lane, 3123 soc_phy_control_t type, uint32 value) 3124 { 3125 phy_ctrl_t *pc; /* PHY software state */ 3126 int rv; 3127 3128 pc = EXT_PHY_SW_STATE(unit, port); 3129 3130 PHY_CONTROL_TYPE_CHECK(type); 3131 3132 rv = SOC_E_UNAVAIL; 3133 if (intf == PHY_DIAG_INTF_SYS) { 3134 /* if is targeted to the system side */ 3135 SOC_IF_ERROR_RETURN 3136 (PHY84756_XFI(unit,pc)); 3137 } 3138 switch(type) { 3139 case SOC_PHY_CONTROL_PREEMPHASIS: 3140 /* fall through */ 3141 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3142 /* fall through */ 3143 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3144 /* fall through */ 3145 rv = _phy_84756_control_tx_driver_set(unit, port, type, value); 3146 break; 3147 3148 case SOC_PHY_CONTROL_EDC_MODE: 3149 rv = _phy_84756_control_edc_mode_set(unit,port,value); 3150 break; 3151 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 3152 /* on line side, rx poly type is auto-detected. On system side, 3153 * need to enable the rx type as well. 3154 */ 3155 rv = _phy_84756_control_prbs_polynomial_set(unit, port, value, TRUE); 3156 if (intf == PHY_DIAG_INTF_SYS) { 3157 rv = _phy_84756_control_prbs_polynomial_set(unit, port,value,FALSE); 3158 } 3159 break; 3160 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 3161 /* on line side, rx invertion is auto-detected. On system side, 3162 * need to enable the rx as well. 3163 */ 3164 rv = _phy_84756_control_prbs_tx_invert_data_set(unit, port, value); 3165 if (intf == PHY_DIAG_INTF_SYS) { 3166 rv = _phy_84756_control_prbs_rx_invert_data_set(unit, port, value); 3167 } 3168 break; 3169 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 3170 /* fall through */ 3171 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 3172 /* tx/rx is enabled at the same time. no seperate control */ 3173 rv = _phy_84756_control_prbs_enable_set(unit, port, value); 3174 break; 3175 case SOC_PHY_CONTROL_DUMP: 3176 _phy_84756_control_dump(unit, port); 3177 break; 3178 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 3179 rv = _phy_84756_control_pdet_set(unit, port, value); 3180 break; 3181 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 3182 rv = phy_84756_fcmap_squelch_enable(unit, port, intf, value, FALSE); 3183 break; 3184 case SOC_PHY_CONTROL_MACSEC_ENABLE: 3185 phy_84756_macsec_enable(unit, port, value); 3186 break; 3187 default: 3188 rv = SOC_E_UNAVAIL; 3189 break; 3190 } 3191 if (intf == PHY_DIAG_INTF_SYS) { 3192 /* if it is targeted to the system side, switch back */ 3193 SOC_IF_ERROR_RETURN 3194 (PHY84756_MMF(unit,pc)); 3195 } 3196 return rv; 3197 } 3198 3199 /* 3200 * Function: 3201 * phy_84756_fcmap_control_set 3202 * Purpose: 3203 * Configure PHY device specific control fucntion. 3204 * Parameters: 3205 * unit - StrataSwitch unit #. 3206 * port - StrataSwitch port #. 3207 * type - Control to update 3208 * value - New setting for the control 3209 * Returns: 3210 * SOC_E_NONE 3211 */ 3212 STATIC int 3213 phy_84756_fcmap_control_set(int unit, soc_port_t port, 3214 soc_phy_control_t type, uint32 value) 3215 { 3216 int intf; 3217 phy_ctrl_t *pc; /* PHY software state */ 3218 3219 pc = EXT_PHY_SW_STATE(unit, port); 3220 3221 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)? 3222 PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE; 3223 3224 /* 40G control Set */ 3225 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 3226 PHY_CONTROL_SET(PHY84756_40G, unit, port, type, value)); 3227 3228 if (PHY84756_IS_8474X(pc)) { 3229 switch(type) { 3230 case SOC_PHY_CONTROL_EDC_MODE: 3231 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 3232 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 3233 SOC_IF_ERROR_RETURN( 3234 PHY_CONTROL_SET(PHY84756_40G, unit, port, type, value)); 3235 return SOC_E_NONE; 3236 default: 3237 break; 3238 } 3239 } 3240 3241 SOC_IF_ERROR_RETURN 3242 (_phy_84756_control_set(unit, port, intf, 3243 PHY_DIAG_LN_DFLT, type, value)); 3244 return SOC_E_NONE; 3245 } 3246 3247 /* 3248 * Function: 3249 * phy_84756_control_get 3250 * Purpose: 3251 * Get current control settign of the PHY. 3252 * Parameters: 3253 * unit - StrataSwitch unit #. 3254 * port - StrataSwitch port #. 3255 * type - Control to update 3256 * value - (OUT)Current setting for the control 3257 * Returns: 3258 * SOC_E_NONE 3259 */ 3260 STATIC int 3261 _phy_84756_control_get(int unit, soc_port_t port, int intf,int lane, 3262 soc_phy_control_t type, uint32 *value) 3263 { 3264 phy_ctrl_t *pc; /* PHY software state */ 3265 int rv; 3266 3267 pc = EXT_PHY_SW_STATE(unit, port); 3268 3269 PHY_CONTROL_TYPE_CHECK(type); 3270 3271 if (intf == PHY_DIAG_INTF_SYS) { 3272 /* targeted to the system side */ 3273 SOC_IF_ERROR_RETURN 3274 (PHY84756_XFI(unit,pc)); 3275 } 3276 rv = SOC_E_UNAVAIL; 3277 switch(type) { 3278 case SOC_PHY_CONTROL_PREEMPHASIS: 3279 /* fall through */ 3280 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3281 /* fall through */ 3282 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3283 /* fall through */ 3284 rv = _phy_84756_control_tx_driver_get(unit, port, type, value); 3285 break; 3286 3287 case SOC_PHY_CONTROL_EDC_MODE: 3288 rv = _phy_84756_control_edc_mode_get(unit,port,value); 3289 break; 3290 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 3291 rv = _phy_84756_control_prbs_polynomial_get(unit, port, value); 3292 break; 3293 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 3294 rv = _phy_84756_control_prbs_tx_invert_data_get(unit, port, value); 3295 break; 3296 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 3297 /* fall through */ 3298 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 3299 rv = _phy_84756_control_prbs_enable_get(unit, port, value); 3300 break; 3301 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 3302 rv = _phy_84756_control_prbs_rx_status_get(unit, port, value); 3303 break; 3304 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 3305 rv = _phy_84756_control_pdet_get(unit, port, value); 3306 break; 3307 default: 3308 rv = SOC_E_UNAVAIL; 3309 break; 3310 } 3311 3312 if (intf == PHY_DIAG_INTF_SYS) { 3313 /* if it is targeted to the system side, switch back */ 3314 SOC_IF_ERROR_RETURN 3315 (PHY84756_MMF(unit,pc)); 3316 } 3317 return rv; 3318 } 3319 /* 3320 * Function: 3321 * phy_84756_fcmap_control_get 3322 * Purpose: 3323 * Get current control settign of the PHY. 3324 * Parameters: 3325 * unit - StrataSwitch unit #. 3326 * port - StrataSwitch port #. 3327 * type - Control to update 3328 * value - (OUT)Current setting for the control 3329 * Returns: 3330 * SOC_E_NONE 3331 */ 3332 STATIC int 3333 phy_84756_fcmap_control_get(int unit, soc_port_t port, 3334 soc_phy_control_t type, uint32 *value) 3335 { 3336 int intf; 3337 phy_ctrl_t *pc; /* PHY software state */ 3338 3339 pc = EXT_PHY_SW_STATE(unit, port); 3340 3341 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL)? 3342 PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE; 3343 3344 /* 40G control get */ 3345 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 3346 PHY_CONTROL_GET(PHY84756_40G, unit, port, type, value)); 3347 3348 3349 if (PHY84756_IS_8474X(pc)) { 3350 switch(type) { 3351 case SOC_PHY_CONTROL_EDC_MODE: 3352 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 3353 SOC_IF_ERROR_RETURN( 3354 PHY_CONTROL_GET(PHY84756_40G, unit, port, type, value)); 3355 return SOC_E_NONE; 3356 default: 3357 break; 3358 } 3359 } 3360 3361 SOC_IF_ERROR_RETURN 3362 (_phy_84756_control_get(unit, port, intf, 3363 PHY_DIAG_LN_DFLT, type, value)); 3364 return SOC_E_NONE; 3365 } 3366 3367 STATIC int 3368 phy_84756_diag_ctrl( 3369 int unit, /* unit */ 3370 soc_port_t port, /* port */ 3371 uint32 inst, /* the specific device block the control action directs to */ 3372 int op_type, /* operation types: read,write or command sequence */ 3373 int op_cmd, /* command code */ 3374 void *arg) /* command argument */ 3375 { 3376 int lane; 3377 int intf; 3378 3379 LOG_INFO(BSL_LS_SOC_PHY, 3380 (BSL_META_U(unit, 3381 "phy_84756_diag_ctrl: u=%d p=%d ctrl=0x%x\n"), 3382 unit, port,op_cmd)); 3383 3384 /* 40G reg read */ 3385 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 3386 PHY_DIAG_CTRL(PHY84756_40G, unit, port, inst, op_type, op_cmd, arg)); 3387 3388 lane = PHY_DIAG_INST_LN(inst); 3389 intf = PHY_DIAG_INST_INTF(inst); 3390 if (intf == PHY_DIAG_INTF_DFLT) { 3391 intf = PHY_DIAG_INTF_LINE; 3392 } 3393 3394 if (op_type == PHY_DIAG_CTRL_GET) { 3395 SOC_IF_ERROR_RETURN 3396 (_phy_84756_control_get(unit, port, intf, lane, 3397 op_cmd,(uint32 *)arg)); 3398 } else if (op_type == PHY_DIAG_CTRL_SET) { 3399 SOC_IF_ERROR_RETURN 3400 (_phy_84756_control_set(unit, port, intf, lane, 3401 op_cmd, PTR_TO_INT(arg))); 3402 } 3403 return SOC_E_NONE; 3404 } 3405 3406 /* 3407 * Function: 3408 * phy_84756_fcmap_linkup 3409 * Purpose: 3410 * Link up handler 3411 * Parameters: 3412 * unit - StrataSwitch unit #. 3413 * port - StrataSwitch port #. 3414 * Returns: 3415 * SOC_E_NONE 3416 */ 3417 STATIC int 3418 phy_84756_fcmap_linkup(int unit, soc_port_t port) 3419 { 3420 3421 /* After link up configure the system side to operate at 10G */ 3422 phy_ctrl_t *pc; 3423 #if defined(INCLUDE_FCMAP) 3424 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 3425 #endif 3426 bfcmap_phy84756_intf_t line_mode; 3427 3428 pc = EXT_PHY_SW_STATE(unit, port); 3429 3430 /* 40G linkup evt */ 3431 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 3432 PHY_LINKUP_EVT(PHY84756_40G, unit, port)); 3433 3434 #if defined(INCLUDE_FCMAP) 3435 if (pc->fcmap_enable) { 3436 if (NULL != int_pc) { 3437 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 3438 PHY_SPEED_SET(int_pc->pd, unit, port, 10000); 3439 } 3440 /* XFI System Side Speed to 10G */ 3441 SOC_IF_ERROR_RETURN( 3442 _phy84756_system_xfi_speed_set(pc, 0, 10000)); 3443 3444 /* Notify 10G speed */ 3445 SOC_IF_ERROR_RETURN 3446 (soc_phyctrl_notify(unit, port, phyEventSpeed, 10000)); 3447 3448 } else 3449 #endif 3450 { 3451 SOC_IF_ERROR_RETURN( 3452 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 3453 3454 if (line_mode == BFCMAP_PHY84756_INTF_SGMII) { 3455 SOC_IF_ERROR_RETURN( 3456 _bfcmap_phy84756_system_sgmii_sync(pc, 0)); 3457 } 3458 } 3459 3460 return SOC_E_NONE; 3461 } 3462 3463 /* 3464 * Function: 3465 * phy_84756_fcmap_interface_set 3466 * Purpose: 3467 * Get interface on a given port. 3468 * Parameters: 3469 * unit - StrataSwitch unit #. 3470 * port - StrataSwitch port #. 3471 * pif - Interface. 3472 * Returns: 3473 * SOC_E_NONE 3474 */ 3475 STATIC int 3476 phy_84756_fcmap_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 3477 { 3478 3479 /* 40G INTF set */ 3480 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 3481 PHY_INTERFACE_SET(PHY84756_40G, unit, port, pif)); 3482 3483 SOC_IF_ERROR_RETURN( 3484 phy_null_interface_set(unit, port, pif)); 3485 3486 return SOC_E_NONE; 3487 } 3488 3489 /* 3490 * Function: 3491 * phy_84756_fcmap_interface_get 3492 * Purpose: 3493 * Get interface on a given port. 3494 * Parameters: 3495 * unit - StrataSwitch unit #. 3496 * port - StrataSwitch port #. 3497 * pif - Interface. 3498 * Returns: 3499 * SOC_E_NONE 3500 */ 3501 STATIC int 3502 phy_84756_fcmap_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 3503 { 3504 int speed = 0; 3505 3506 /* 40G INTF get */ 3507 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 3508 PHY_INTERFACE_GET(PHY84756_40G, unit, port, pif)); 3509 3510 SOC_IF_ERROR_RETURN( 3511 phy_84756_fcmap_speed_get(unit, port, &speed)); 3512 3513 *pif = (speed > 0 && speed <= 1000) ? SOC_PORT_IF_SGMII : SOC_PORT_IF_XFI; 3514 return SOC_E_NONE; 3515 } 3516 3517 /* 3518 * Function: 3519 * phy_84756_precondition_before_probe 3520 * Purpose: 3521 * When the device is in 40G, ie. after a power reset, and the 10G 3522 * port being probed does not have the 40G address in PRTAD, the 3523 * device will not respond until the port that has the 40G address 3524 * is probed. To avoid not programming ports correctly, make 3525 * sure the device is in quad (4x10G) PMD mode when the SDK port is 10G. 3526 * Parameters: 3527 * unit - StrataSwitch unit #. 3528 * pc - phy ctrl descriptor. 3529 * Returns: 3530 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 3531 */ 3532 3533 STATIC int 3534 phy_84756_precondition_before_probe(int unit, phy_ctrl_t *pc) 3535 { 3536 int ids; 3537 int rv = SOC_E_NOT_FOUND; 3538 uint16 id0, id1; 3539 uint16 saved_phy_id; 3540 3541 /* Not required when the port is single PMD */ 3542 if (PHY84756_SINGLE_PORT_MODE(pc)) { 3543 LOG_INFO(BSL_LS_SOC_PHY, 3544 (BSL_META_U(unit, 3545 "PMD must not be called when in single PMD\n"))); 3546 return rv; 3547 } 3548 3549 saved_phy_id = pc->phy_id; 3550 3551 /* Look for first address that responds */ 3552 for (ids = 0; ids < 4; ids++) { 3553 3554 pc->phy_id = (saved_phy_id & ~0x3) + ids; 3555 LOG_INFO(BSL_LS_SOC_PHY, 3556 (BSL_META_U(unit, 3557 "Try device with address %x\n"), pc->phy_id)); 3558 3559 /* 3560 * Make sure the device has the correct dev IDs 3561 * Note that this is being called either because the soc probe found 3562 * the ids or there was an id override. In the later case, the device 3563 * might not have the 84756 ids so this PMD setup will not be supported 3564 */ 3565 id0 = 0; 3566 BFCMAP_RD_PHY84756_SYS_DEV1_PMD_ID0r(pc, &id0); 3567 if (id0 != 0x600d) { 3568 continue; 3569 } 3570 id1 = 0; 3571 BFCMAP_RD_PHY84756_SYS_DEV1_PMD_ID1r(pc, &id1); 3572 if ((id1 & 0xffff) != 0x8675) { 3573 continue; 3574 } 3575 SOC_IF_ERROR_RETURN( 3576 _phy_84741_single_to_quad_mode(unit, pc->port, pc)); 3577 /* Found the address that responds and the device now is in 4x10G */ 3578 rv = SOC_E_NONE; 3579 break; 3580 } 3581 3582 pc->phy_id = saved_phy_id; 3583 3584 return rv; 3585 } 3586 3587 /* 3588 * Function: 3589 * phy_84756_fcmap_probe 3590 * Purpose: 3591 * Complement the generic phy probe routine to identify this phy when its 3592 * phy id0 and id1 is same as some other phy's. 3593 * Parameters: 3594 * unit - StrataSwitch unit #. 3595 * pc - phy ctrl descriptor. 3596 * Returns: 3597 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 3598 */ 3599 STATIC int 3600 phy_84756_fcmap_probe(int unit, phy_ctrl_t *pc) 3601 { 3602 3603 3604 pc->size = -1 ; 3605 PHY_PROBE(PHY84756_40G, unit, pc); 3606 3607 /* Support 40G only for 84741/84744 */ 3608 if (PHY84756_SINGLE_PORT_MODE(pc) && pc->size == 0) { 3609 return SOC_E_NOT_FOUND; 3610 } 3611 3612 3613 #ifdef INCLUDE_MACSEC 3614 /* Use of Standalone MACSEC driver is selected by fcmap_enable=0xff */ 3615 if (0xff != soc_property_port_get(unit, pc->port, spn_FCMAP_ENABLE, 0)) { 3616 LOG_CLI((BSL_META_U(unit, 3617 "u=%d p=%d Using SDK PHY driver for BCM84756/7/9\n"), 3618 unit, pc->port)); 3619 pc->size += sizeof(phy84756_map_t); 3620 return SOC_E_NONE; 3621 } 3622 return SOC_E_NOT_FOUND; 3623 #else 3624 pc->size += sizeof(phy84756_map_t); 3625 LOG_INFO(BSL_LS_SOC_PHY, 3626 (BSL_META_U(unit, 3627 "u=%d p=%d Using SDK PHY driver for BCM84756/7/9 (no MACSEC support)\n"), 3628 unit, pc->port)); 3629 return SOC_E_NONE; 3630 #endif 3631 } 3632 3633 /* 3634 * Function: 3635 * _phy84756_phy_get_dev_addr 3636 * Purpose: 3637 * For a given PHY Device address retrive Device port 3638 * Parameters: 3639 * phy_dev_addr - PHY Device Address 3640 * fcmap_dev_addr - MACSEC core Device Address 3641 * dev_port - (OUT)Port number 3642 * Notes: 3643 */ 3644 STATIC int 3645 _phy84756_phy_get_dev_addr(phy_ctrl_t *pc, 3646 blmi_dev_addr_t *fcmap_dev_addr, int *dev_port) 3647 { 3648 if (dev_port) { 3649 #if defined(INCLUDE_MACSEC) 3650 if (pc->macsec_enable) { 3651 *dev_port = pc->macsec_dev_port; 3652 } else 3653 #endif 3654 #if defined(INCLUDE_FCMAP) 3655 if (pc->fcmap_enable) { 3656 *dev_port = pc->fcmap_dev_port; 3657 } else 3658 #endif 3659 { 3660 #if defined(INCLUDE_FCMAP) 3661 *dev_port = pc->fcmap_dev_port; 3662 #endif 3663 #if defined(INCLUDE_MACSEC) 3664 *dev_port = pc->macsec_dev_port; 3665 #endif 3666 } 3667 } 3668 if (fcmap_dev_addr) { 3669 #if defined(INCLUDE_MACSEC) 3670 if (pc->macsec_enable) { 3671 *fcmap_dev_addr = pc->macsec_dev_addr; 3672 } else 3673 #endif 3674 #if defined(INCLUDE_FCMAP) 3675 if (pc->fcmap_enable) { 3676 *fcmap_dev_addr = pc->fcmap_dev_addr; 3677 } else 3678 #endif 3679 { 3680 #if defined(INCLUDE_FCMAP) 3681 *fcmap_dev_addr = pc->fcmap_dev_addr; 3682 #endif 3683 #if defined(INCLUDE_MACSEC) 3684 *fcmap_dev_addr = pc->macsec_dev_addr; 3685 #endif 3686 } 3687 } 3688 return SOC_E_NONE; 3689 } 3690 3691 /* 3692 * Function: 3693 * _phy84756_get_model_rev 3694 * Purpose: 3695 * Get OUI, Model and Revision of the PHY 3696 * Parameters: 3697 * phy_dev_addr - PHY Device Address 3698 * oui - (OUT) Organization Unique Identifier 3699 * model - (OUT)Device Model number` 3700 * rev - (OUT)Device Revision number 3701 * Notes: 3702 */ 3703 int 3704 _phy84756_get_model_rev(phy_ctrl_t *pc, 3705 int *oui, int *model, int *rev) 3706 { 3707 buint16_t id0, id1; 3708 3709 SOC_IF_ERROR_RETURN 3710 (BFCMAP_RD_PHY84756_LN_DEV1_PMD_ID0r(pc, &id0)); 3711 3712 SOC_IF_ERROR_RETURN 3713 (BFCMAP_RD_PHY84756_LN_DEV1_PMD_ID1r(pc, &id1)); 3714 3715 *oui = BFCMAP_PHY84756_PHY_OUI(id0, id1); 3716 *model = BFCMAP_PHY84756_PHY_MODEL(id0, id1); 3717 *rev = BFCMAP_PHY84756_PHY_REV(id0, id1); 3718 3719 return SOC_E_NONE; 3720 } 3721 3722 3723 3724 /* 3725 * Function: 3726 * bfcmap_phy84756_firmware_spi_download 3727 * Purpose: 3728 * Download firmware via SPI 3729 * - Check if firmware download is complete 3730 * - Check if the checksum is good 3731 * Parameters: 3732 * phy_id - PHY Device Address 3733 * Returns: 3734 */ 3735 /* STATIC int */ 3736 int 3737 bfcmap_phy84756_firmware_spi_download(phy_ctrl_t *pc) 3738 { 3739 buint16_t data = 0; 3740 int i; 3741 3742 LOG_INFO(BSL_LS_SOC_PHY, 3743 (BSL_META_U(pc->unit, 3744 "PHY84756: SPI-ROM firmware download start: u=%d p=%d\n"), 3745 pc->unit, pc->port)); 3746 3747 /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */ 3748 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 3749 SOC_IF_ERROR_RETURN( 3750 BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc848, 3751 (1 << 15)|(1 << 14), 3752 ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 2)))); 3753 3754 /* apply software reset to download code from SPI-ROM */ 3755 /* Reset the PHY **/ 3756 SOC_IF_ERROR_RETURN( 3757 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 3758 BFCMAP_PHY84756_PMD_CTRL_RESET, BFCMAP_PHY84756_PMD_CTRL_RESET)); 3759 3760 for (i = 0; i < 5; i++) { 3761 sal_usleep(100000); 3762 SOC_IF_ERROR_RETURN( 3763 BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc848, &data)); 3764 if (data & 0x2000) { /* Check for download complete */ 3765 /* Need to check if checksum is correct */ 3766 SOC_IF_ERROR_RETURN( 3767 BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xca1c, &data)); 3768 if (data == 0x600D) { 3769 break; 3770 } 3771 } 3772 } 3773 if (i >= 5) { /* Bad CHECKSUM */ 3774 LOG_CLI((BSL_META_U(pc->unit, 3775 "SPI-Download Firmware download failure:" 3776 "Incorrect Checksum %x\n"), data)); 3777 return SOC_E_FAIL; 3778 } 3779 3780 SOC_IF_ERROR_RETURN( 3781 BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xca1a, &data)); 3782 3783 LOG_CLI((BSL_META_U(pc->unit, 3784 "BCM84756: SPI-ROM download complete: version: 0x%x\n"), data)); 3785 3786 return SOC_E_NONE; 3787 } 3788 3789 3790 /* 3791 * Function: 3792 * bfcmap_phy84756_phy_mac_driver_attach 3793 * Purpose: 3794 * Add Mapping of PHY device address, Device port 3795 * Parameters: 3796 * phy_dev_addr - PHY Device Address 3797 * dev_port - Port number 3798 * Notes: 3799 */ 3800 int 3801 bfcmap_phy84756_phy_mac_driver_attach(phy_ctrl_t *pc, 3802 blmi_dev_addr_t fcmap_dev_addr, 3803 int dev_port, blmi_dev_io_f mmi_cbf) 3804 { 3805 phy84756_map_t *phy84756_map; 3806 uint32 mac_config_flag = 0; 3807 3808 /* Delete the mapping if already present */ 3809 (void)bfcmap_phy84756_phy_mac_driver_detach(pc); 3810 3811 phy84756_map = PHY84756_PHY_INFO(pc); 3812 3813 if (phy84756_map == NULL) { 3814 return SOC_E_RESOURCE; 3815 } 3816 3817 /* Alloc unimac driver and attach */ 3818 phy84756_map->unimac = 3819 phy_mac_driver_attach(fcmap_dev_addr, 3820 PHY_MAC_CORE_UNIMAC, mmi_cbf); 3821 if (!phy84756_map->unimac) { 3822 bfcmap_phy84756_phy_mac_driver_detach(pc); 3823 return SOC_E_INTERNAL; 3824 } 3825 3826 phy84756_map->xmac = 3827 phy_mac_driver_attach(fcmap_dev_addr, 3828 PHY_MAC_CORE_XMAC, mmi_cbf); 3829 if (!phy84756_map->xmac) { 3830 bfcmap_phy84756_phy_mac_driver_detach(pc); 3831 return SOC_E_INTERNAL; 3832 } 3833 3834 3835 if (CHIP_IS_C0(pc)) { 3836 mac_config_flag |= PHY_MAC_CTRL_FLAG_XMAC_V2; 3837 } 3838 3839 if(mac_config_flag) { 3840 phy_mac_driver_config(phy84756_map->xmac, 3841 PHY_MAC_CORE_XMAC, 3842 mac_config_flag); 3843 } 3844 3845 return SOC_E_NONE; 3846 } 3847 3848 3849 3850 /* 3851 * Function: 3852 * bfcmap_phy84756_phy_mac_driver_detach 3853 * Purpose: 3854 * Delete Mapping of PHY device address and Device port 3855 * Parameters: 3856 * phy_dev_addr - PHY Device Address 3857 * Notes: 3858 */ 3859 int 3860 bfcmap_phy84756_phy_mac_driver_detach(phy_ctrl_t *pc) 3861 { 3862 phy84756_map_t *this; 3863 int rv = SOC_E_NONE; 3864 3865 this = PHY84756_PHY_INFO(pc); 3866 if (this->unimac) { 3867 phy_mac_driver_detach(this->unimac); 3868 this->unimac = NULL; 3869 } 3870 if (this->xmac) { 3871 phy_mac_driver_detach(this->xmac); 3872 this->xmac = NULL; 3873 } 3874 return rv; 3875 } 3876 3877 3878 /* 3879 * Function: 3880 * bfcmap_phy84756_line_intf_get 3881 * Purpose: 3882 * Determine the Line side Interface 3883 * Parameters: 3884 * phy_id - PHY's device address 3885 * dev_port - Channel number 3886 * mode - (OUT) Line Port mode status 3887 * Returns: 3888 */ 3889 int 3890 bfcmap_phy84756_line_intf_get(phy_ctrl_t *pc, int dev_port, 3891 bfcmap_phy84756_intf_t *mode) 3892 { 3893 3894 phy84756_map_t *phy_info; 3895 3896 if (mode == NULL) { 3897 return SOC_E_PARAM; 3898 } 3899 3900 phy_info = PHY84756_PHY_INFO(pc); 3901 3902 *mode = phy_info->line_mode; 3903 return SOC_E_NONE; 3904 } 3905 3906 3907 3908 /* 3909 * Function: 3910 * bfcmap_phy84756_line_mode_set 3911 * Purpose: 3912 * Set the Line side mode 3913 * Parameters: 3914 * phy_id - PHY's device address 3915 * dev_port - Channel number 3916 * mode - Desired mode (SGMII/1000x/SFI) 3917 * Returns: 3918 */ 3919 int 3920 bfcmap_phy84756_line_mode_set(phy_ctrl_t *pc, int dev_port, 3921 bfcmap_phy84756_intf_t mode) 3922 { 3923 3924 int rv = SOC_E_NONE; 3925 phy84756_map_t *phy_info; 3926 3927 phy_info = PHY84756_PHY_INFO(pc); 3928 3929 /* Disable Autodetect */ 3930 SOC_IF_ERROR_RETURN( 3931 BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 0, 3932 BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_AUTODETECT_EN)); 3933 switch (mode) { 3934 3935 case BFCMAP_PHY84756_INTF_SGMII : 3936 3937 SOC_IF_ERROR_RETURN( 3938 BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0x8300, 0x0184)); 3939 SOC_IF_ERROR_RETURN( 3940 BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0x8308, 0x0000)); 3941 SOC_IF_ERROR_RETURN( 3942 BFCMAP_PHY84756_REG_MOD(pc, 0x00, 0x0007, 0x8309, 0x6000, 0x6020)); 3943 SOC_IF_ERROR_RETURN( 3944 BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0x835c, 0x0801)); 3945 SOC_IF_ERROR_RETURN( 3946 BFCMAP_PHY84756_REG_WR(pc, 0x00, 0x0007, 0xffe0, 0x1140)); 3947 3948 break; 3949 3950 case BFCMAP_PHY84756_INTF_1000X : 3951 SOC_IF_ERROR_RETURN( 3952 BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 1, 3953 BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE)); 3954 break; 3955 3956 case BFCMAP_PHY84756_INTF_SFI : 3957 SOC_IF_ERROR_RETURN( 3958 BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 1, 3959 BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE)); 3960 /* Set PMA type */ 3961 SOC_IF_ERROR_RETURN( 3962 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRL2r(pc, 0x8, 0x003f)); 3963 break; 3964 3965 case BFCMAP_PHY84756_INTF_XFI : 3966 default : 3967 rv = SOC_E_PARAM; 3968 break; 3969 3970 } 3971 3972 if (SOC_SUCCESS(rv)) { 3973 phy_info->line_mode = mode; 3974 } 3975 return rv; 3976 } 3977 3978 3979 /* 3980 * Function: 3981 * bfcmap_phy84756_sys_intf_get 3982 * Purpose: 3983 * Determine the System side Interface 3984 * Parameters: 3985 * phy_id - PHY's device address 3986 * dev_port - Channel number 3987 * mode - (OUT) System side mode status 3988 * Returns: 3989 */ 3990 int 3991 bfcmap_phy84756_sys_intf_get(phy_ctrl_t *pc, int dev_port, 3992 bfcmap_phy84756_intf_t *mode) 3993 { 3994 3995 phy84756_map_t *phy_info; 3996 3997 if (mode == NULL) { 3998 return SOC_E_PARAM; 3999 } 4000 4001 phy_info = PHY84756_PHY_INFO(pc); 4002 4003 /* System will always follow line side interface */ 4004 *mode = phy_info->line_mode; 4005 4006 return SOC_E_NONE; 4007 } 4008 4009 4010 4011 /* 4012 * Function: 4013 * bfcmap_phy84756_sys_mode_set 4014 * Purpose: 4015 * Set the system side mode 4016 * Parameters: 4017 * phy_id - PHY's device address 4018 * dev_port - Channel number 4019 * mode - Desired mode (SGMII/1000x/XFI) 4020 * Returns: 4021 */ 4022 int 4023 bfcmap_phy84756_sys_mode_set(phy_ctrl_t *pc, int dev_port, 4024 bfcmap_phy84756_intf_t mode) 4025 { 4026 int rv = SOC_E_NONE; 4027 4028 /* Disable Autodetect */ 4029 SOC_IF_ERROR_RETURN( 4030 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 0, 4031 BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_AUTODETECT_EN)); 4032 switch (mode) { 4033 case BFCMAP_PHY84756_INTF_SGMII : 4034 SOC_IF_ERROR_RETURN( 4035 _bfcmap_phy84756_system_sgmii_init(pc, dev_port)); 4036 break; 4037 4038 case BFCMAP_PHY84756_INTF_1000X : 4039 SOC_IF_ERROR_RETURN( 4040 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 1, 4041 BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE)); 4042 break; 4043 case BFCMAP_PHY84756_INTF_XFI : 4044 break; 4045 4046 case BFCMAP_PHY84756_INTF_XAUI : 4047 SOC_IF_ERROR_RETURN( 4048 BFCMAP_MOD_PHY84756_XGXS_DEV7_AN_BASE1000X_CTRL1r(pc, 1, 4049 BFCMAP_PHY84756_AN_BASE1000X_CTRL1r_FIBER_MODE)); 4050 /* Set PMA type */ 4051 SOC_IF_ERROR_RETURN( 4052 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRL2r(pc, 0x8, 4053 0x000f)); 4054 break; 4055 case BFCMAP_PHY84756_INTF_SFI : 4056 default : 4057 rv = SOC_E_PARAM; 4058 break; 4059 } 4060 4061 return rv; 4062 } 4063 4064 4065 #if defined(INCLUDE_FCMAP) || defined(INCLUDE_MACSEC) 4066 #define BIT_MASK_07 (1U << 7) 4067 4068 STATIC int 4069 bfcmap_phy84756_macsec_enable(phy_ctrl_t *pc) 4070 { 4071 buint16_t data; 4072 4073 SOC_IF_ERROR_RETURN( BFCMAP_WR_PHY84756_SGMII_DEV1_MACSEC_BYPASS_CTRLr(pc, 0x0000) ); 4074 4075 /* Set to TX active to make macsec registers (xmac) accessible */ 4076 SOC_IF_ERROR_RETURN( BFCMAP_PHY84756_REG_RD(pc, 0x00, 0x01, 0xc8e4, &data) ); 4077 /* check if TX inactive */ 4078 if ( data & 0x0010 ) { 4079 /* disable OPTXENB until the port is explicitly enabled */ 4080 SOC_IF_ERROR_RETURN( 4081 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_XMIT_DISABLEr(pc, 1, 0x0001) ); 4082 4083 /* Toggle 1.0xc800.7 to become TX active */ 4084 SOC_IF_ERROR_RETURN( BFCMAP_PHY84756_REG_RD(pc, 00, 0x1, 0xc800, &data) ); 4085 data ^= BIT_MASK_07; /* toggle bit[7] */ 4086 SOC_IF_ERROR_RETURN( BFCMAP_PHY84756_REG_WR(pc, 00, 0x1, 0xc800, data) ); 4087 } 4088 4089 return SOC_E_PARAM; 4090 } 4091 #endif 4092 4093 /* 4094 * Function: 4095 * bfcmap_phy84756_no_reset_setup 4096 * Purpose: 4097 * Initialize the PHY without reset. 4098 * Parameters: 4099 * phy_dev_addr - PHY Device Address 4100 * line_mode - Line side Mode (SGMII/1000X/SFI). 4101 * fcmap_enable - Fibre Channel enabled or disabled. 4102 * Notes: 4103 */ 4104 int 4105 bfcmap_phy84756_no_reset_setup(phy_ctrl_t *pc, int line_mode, 4106 int phy_ext_boot) 4107 { 4108 int dev_port; 4109 int port; 4110 phy84756_map_t *phy_info; 4111 #ifdef INCLUDE_FCMAP 4112 buint16_t val = 0xDEAD; 4113 #endif 4114 buint16_t data; 4115 4116 if (_phy84756_phy_get_dev_addr(pc, NULL, 4117 &dev_port) != SOC_E_NONE) { 4118 return SOC_E_CONFIG; 4119 } 4120 4121 phy_info = PHY84756_PHY_INFO(pc); 4122 4123 if ((line_mode != BFCMAP_PHY84756_INTF_SGMII) && 4124 (line_mode != BFCMAP_PHY84756_INTF_1000X) && 4125 (line_mode != BFCMAP_PHY84756_INTF_SFI)) { 4126 return SOC_E_CONFIG; 4127 } 4128 4129 /* Enable Power - PMA/PMD, PCS, AN */ 4130 SOC_IF_ERROR_RETURN( 4131 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 0, 4132 BFCMAP_PHY84756_PMD_CTRL_PD)); 4133 SOC_IF_ERROR_RETURN( 4134 BFCMAP_MOD_PHY84756_LN_DEV3_PCS_CTRLr(pc, 0, 4135 BFCMAP_PHY84756_PCS_PCS_CTRL_PD)); 4136 SOC_IF_ERROR_RETURN( 4137 BFCMAP_MOD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, 0, 4138 BFCMAP_PHY84756_AN_MII_CTRL_PD)); 4139 if (phy_ext_boot) { 4140 if (!PHY84756_IS_8474X(pc) && (!SKIP_EDC_FW_DOWNLOAD(pc))) { 4141 /* Download firmware via SPI */ 4142 SOC_IF_ERROR_RETURN(bfcmap_phy84756_firmware_spi_download(pc)); 4143 } 4144 } else if (!(pc->flags & PHYCTRL_MDIO_BCST) && (!SKIP_EDC_FW_DOWNLOAD(pc))) { 4145 /* MDIO based firmware download to RAM */ 4146 SOC_IF_ERROR_RETURN( 4147 bfcmap_phy84756_mdio_firmware_download(pc, 4148 FIRMWARE(pc), FIRMWARE_LEN(pc))); 4149 } 4150 4151 if ((!soc_property_port_get(pc->unit, pc->port, spn_FCMAP_ENABLE, 0)) && 4152 (!soc_property_port_get(pc->unit, pc->port, spn_MACSEC_ENABLE, 0))) { 4153 /* Set Line mode */ 4154 SOC_IF_ERROR_RETURN( 4155 bfcmap_phy84756_line_mode_set(pc, 0, line_mode)); 4156 4157 /* Disable MACSEC */ 4158 SOC_IF_ERROR_RETURN( 4159 BFCMAP_RD_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, &data)); 4160 4161 data &= ~(BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE | 4162 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC | 4163 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC | 4164 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_RESET_MACSEC); 4165 4166 data |= BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE; 4167 /* Power down MACSEC to reduce power consumption */ 4168 data |= BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC; 4169 data |= BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC; 4170 4171 SOC_IF_ERROR_RETURN( 4172 BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, data)); 4173 4174 /* System side mode */ 4175 if (line_mode == BFCMAP_PHY84756_INTF_SFI) { 4176 phy_info->line_mode = BFCMAP_PHY84756_INTF_SFI; 4177 SOC_IF_ERROR_RETURN( 4178 bfcmap_phy84756_sys_mode_set(pc, 0, 4179 BFCMAP_PHY84756_INTF_XFI)); 4180 /* Force Speed to 10G */ 4181 SOC_IF_ERROR_RETURN( 4182 _phy84756_system_xfi_speed_set(pc, 0, 10000)); 4183 SOC_IF_ERROR_RETURN( 4184 bfcmap_phy84756_speed_set(pc, 10000)); 4185 } else { 4186 if (line_mode == BFCMAP_PHY84756_INTF_1000X) { 4187 phy_info->line_mode = BFCMAP_PHY84756_INTF_1000X; 4188 SOC_IF_ERROR_RETURN( 4189 bfcmap_phy84756_sys_mode_set(pc, 0, 4190 BFCMAP_PHY84756_INTF_1000X)); 4191 /* Force Speed to 1G */ 4192 SOC_IF_ERROR_RETURN( 4193 bfcmap_phy84756_speed_set(pc, 1000)); 4194 } else { /* SGMII MODE */ 4195 phy_info->line_mode = BFCMAP_PHY84756_INTF_SGMII; 4196 SOC_IF_ERROR_RETURN( 4197 bfcmap_phy84756_sys_mode_set(pc, 0, 4198 BFCMAP_PHY84756_INTF_SGMII)); 4199 } 4200 } 4201 } else { 4202 if (soc_property_port_get(pc->unit, pc->port, spn_FCMAP_ENABLE, 0)) { 4203 #ifdef INCLUDE_FCMAP 4204 /* FCMAP enable */ 4205 sal_usleep(10000); 4206 /* Enable FC */ 4207 SOC_IF_ERROR_RETURN( 4208 BFCMAP_RD_PHY84756_LN_DEV1_CHIP_MODEr(pc, &data)); 4209 data &= ~0x3; 4210 data |= 0x2; 4211 SOC_IF_ERROR_RETURN( 4212 BFCMAP_WR_PHY84756_LN_DEV1_CHIP_MODEr(pc, data)); 4213 4214 sal_usleep(100000); /* need 100ms delay */ 4215 4216 /* Enable MACSEC */ 4217 SOC_IF_ERROR_RETURN( bfcmap_phy84756_macsec_enable(pc) ); 4218 4219 SOC_IF_ERROR_RETURN( 4220 BFCMAP_PHY84756_REG_WR(pc, 0, 1, 0xcd58, 0x300)); 4221 sal_usleep(30); 4222 SOC_IF_ERROR_RETURN( 4223 BFCMAP_PHY84756_REG_WR(pc, 0, 1, 0xcd53, 0)); 4224 4225 SOC_IF_ERROR_RETURN( 4226 BFCMAP_PHY84756_REG_RD(pc, 0, 1, 0xcd53, &val)); 4227 4228 /* Set Line mode */ 4229 SOC_IF_ERROR_RETURN( 4230 bfcmap_phy84756_line_mode_set(pc, 0, 4231 BFCMAP_PHY84756_INTF_SFI)); 4232 4233 /* System side mode */ 4234 SOC_IF_ERROR_RETURN( 4235 bfcmap_phy84756_sys_mode_set(pc, 0, 4236 BFCMAP_PHY84756_INTF_XFI)); 4237 /* Force Speed to 10G */ 4238 SOC_IF_ERROR_RETURN( 4239 _phy84756_system_xfi_speed_set(pc, 0, 10000)); 4240 4241 4242 /* Initialize the switch side XMAC */ 4243 port = BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port); 4244 SOC_IF_ERROR_RETURN( 4245 phy_xmac_mac_fcmap_init(phy_info->xmac, port)); 4246 #endif 4247 4248 } else { 4249 if (soc_property_port_get(pc->unit, pc->port, spn_MACSEC_ENABLE, 0)) { 4250 #ifdef INCLUDE_MACSEC 4251 /* Set Line mode */ 4252 SOC_IF_ERROR_RETURN( 4253 bfcmap_phy84756_line_mode_set(pc, 0, line_mode)); 4254 4255 /* System side mode */ 4256 if (line_mode == BFCMAP_PHY84756_INTF_SFI) { 4257 phy_info->line_mode = BFCMAP_PHY84756_INTF_SFI; 4258 SOC_IF_ERROR_RETURN( 4259 bfcmap_phy84756_sys_mode_set(pc, 0, 4260 BFCMAP_PHY84756_INTF_XFI)); 4261 /* Force Speed to 10G */ 4262 SOC_IF_ERROR_RETURN( 4263 _phy84756_system_xfi_speed_set(pc, 0, 10000)); 4264 SOC_IF_ERROR_RETURN( 4265 bfcmap_phy84756_speed_set(pc, 10000)); 4266 } else { 4267 if (line_mode == BFCMAP_PHY84756_INTF_1000X) { 4268 phy_info->line_mode = BFCMAP_PHY84756_INTF_1000X; 4269 SOC_IF_ERROR_RETURN( 4270 bfcmap_phy84756_sys_mode_set(pc, 0, 4271 BFCMAP_PHY84756_INTF_1000X)); 4272 /* Force Speed to 1G */ 4273 SOC_IF_ERROR_RETURN( 4274 bfcmap_phy84756_speed_set(pc, 1000)); 4275 } else { /* SGMII MODE */ 4276 phy_info->line_mode = BFCMAP_PHY84756_INTF_SGMII; 4277 SOC_IF_ERROR_RETURN( 4278 bfcmap_phy84756_sys_mode_set(pc, 0, 4279 BFCMAP_PHY84756_INTF_SGMII)); 4280 } 4281 } 4282 4283 /* Enable MACSEC */ 4284 SOC_IF_ERROR_RETURN( bfcmap_phy84756_macsec_enable(pc) ); 4285 4286 /* 4287 * Set defaults to Line and Swithc side MAC 4288 * MTU = 0x3fff 4289 * IPG = 12Bytes 4290 * Auto Config Mode Enabled 4291 */ 4292 /* Initialize the Line side MAC */ 4293 port = BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port); 4294 SOC_IF_ERROR_RETURN( 4295 BMACSEC_MAC_INIT(phy_info->xmac, port)); 4296 4297 /* Initialize the Line side MAC */ 4298 port = BFCMAP_PHY84756_LINE_MAC_PORT(dev_port); 4299 SOC_IF_ERROR_RETURN( 4300 BMACSEC_MAC_INIT(phy_info->xmac, port)); 4301 4302 /* Initialize the Line side MAC */ 4303 port = BFCMAP_PHY84756_LINE_MAC_PORT(dev_port); 4304 SOC_IF_ERROR_RETURN( 4305 BMACSEC_MAC_INIT(phy_info->unimac, port)); 4306 4307 /* Initialize the Line side MAC */ 4308 port = BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port); 4309 SOC_IF_ERROR_RETURN( 4310 BMACSEC_MAC_INIT(phy_info->unimac, port)); 4311 #endif 4312 } 4313 } 4314 } 4315 return SOC_E_NONE; 4316 } 4317 4318 STATIC int 4319 phy_84756_fcmap_xmac_rx_enable_set(int unit, int port, int side, int enable) 4320 { 4321 phy_ctrl_t *pc; 4322 phy84756_map_t *phy_info; 4323 4324 pc = EXT_PHY_SW_STATE(unit, port); 4325 phy_info = PHY84756_PHY_INFO(pc); 4326 return BMACSEC_MAC_RX_ENABLE_SET(phy_info->xmac, side, enable); 4327 } 4328 4329 STATIC int 4330 phy_84756_fcmap_rx_enable_set(int unit, soc_port_t port, int side, int enable) 4331 { 4332 return phy_84756_fcmap_xmac_rx_enable_set(unit, port, side, enable); 4333 } 4334 4335 STATIC int 4336 phy_84756_macsec_enable(int unit, int lport, int enable) 4337 { 4338 phy_ctrl_t *pc; 4339 phy84756_map_t *phy_info; 4340 buint16_t data = 0; 4341 int dev_port = 0; 4342 4343 EXT_PHY_INIT_CHECK(unit, lport); 4344 pc = EXT_PHY_SW_STATE(unit, lport); 4345 if ( _phy84756_phy_get_dev_addr(pc, NULL, &dev_port) != SOC_E_NONE ) { 4346 return SOC_E_CONFIG; 4347 } 4348 phy_info = PHY84756_PHY_INFO(pc); 4349 4350 if ( enable ) { /* Enable MACSEC */ 4351 SOC_IF_ERROR_RETURN( 4352 BFCMAP_WR_PHY84756_SGMII_DEV1_MACSEC_BYPASS_CTRLr(pc, 0x8000) ); 4353 sal_udelay(5); /* Wait for 5 us */ 4354 SOC_IF_ERROR_RETURN( 4355 BFCMAP_WR_PHY84756_SGMII_DEV1_MACSEC_BYPASS_CTRLr(pc, 0x0000) ); 4356 4357 /* Set defaults to Line and Swithc side MAC *\ 4358 \* MTU = 0x3fff , IPG = 12Bytes , Auto Config Mode Enabled */ 4359 4360 /* Initialize the System side XMAC */ 4361 SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->xmac , 4362 BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port)) ); 4363 /* Initialize the Line side XMAC */ 4364 SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->xmac , 4365 BFCMAP_PHY84756_LINE_MAC_PORT( dev_port)) ); 4366 4367 /* Initialize the Line side UNIMAC */ 4368 SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->unimac, 4369 BFCMAP_PHY84756_LINE_MAC_PORT( dev_port)) ); 4370 /* Initialize the System side UNIMAC */ 4371 SOC_IF_ERROR_RETURN( BMACSEC_MAC_INIT(phy_info->unimac, 4372 BFCMAP_PHY84756_SWITCH_MAC_PORT(dev_port)) ); 4373 #if defined(INCLUDE_MACSEC) 4374 SOC_IF_ERROR_RETURN( 4375 soc_macsecphy_init(unit, lport, pc, 4376 (CHIP_IS_C0(pc)) ? BMACSEC_CORE_BCM84756_C0 4377 : BMACSEC_CORE_BCM84756, 4378 bmacsec_io_mmi1_cl45) ); 4379 #endif 4380 } else { /* disable MACSEC */ 4381 SOC_IF_ERROR_RETURN( 4382 BFCMAP_RD_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, &data) ); 4383 data &= ~BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_RESET_MACSEC; 4384 /* Power down MACSEC to reduce power consumption */ 4385 data |= (BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_BYPASS_MODE | 4386 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_ENABLE_PWRDN_MACSEC | 4387 BFCMAP_PHY84756_LN_DEV1_MACSEC_CTRL_UDSW_PWRDW_MACSEC); 4388 SOC_IF_ERROR_RETURN( 4389 BFCMAP_WR_PHY84756_LN_DEV1_MACSEC_BYPASS_CTLRr(pc, data) ); 4390 } 4391 4392 return SOC_E_NONE; 4393 } 4394 4395 4396 4397 /* 4398 * Function: 4399 * bfcmap_phy84756_reset 4400 * Purpose: 4401 * Reset the PHY. 4402 * Parameters: 4403 * phy_id - PHY Device Address of the PHY to reset 4404 */ 4405 int 4406 bfcmap_phy84756_reset(phy_ctrl_t *pc) 4407 { 4408 buint16_t ctrl = 0; 4409 buint16_t tmp = 0; 4410 4411 4412 /* Reset the PHY **/ 4413 SOC_IF_ERROR_RETURN( 4414 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &ctrl)); 4415 4416 SOC_IF_ERROR_RETURN( 4417 BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, 4418 (ctrl | BFCMAP_PHY84756_PMD_CTRL_RESET))); 4419 /* Needs minimum of 5us to complete the reset */ 4420 sal_usleep(30); 4421 4422 SOC_IF_ERROR_RETURN( 4423 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRLr(pc, &tmp)); 4424 4425 if ((tmp & BFCMAP_PHY84756_PMD_CTRL_RESET) != 0) { 4426 SOC_IF_ERROR_RETURN 4427 (BFCMAP_WR_PHY84756_LN_DEV1_PMD_CTRLr(pc, ctrl)); 4428 return SOC_E_FAIL; 4429 } 4430 4431 return SOC_E_NONE; 4432 } 4433 4434 4435 /* 4436 * Function: 4437 * bfcmap_phy84756_speed_set 4438 * Purpose: 4439 * To set the PHY's speed 4440 * Parameters: 4441 * phy_id - PHY's device address 4442 * speed - Speed to set 4443 * 10 = 10Mbps 4444 * 100 = 100Mbps 4445 * 1000 = 1000Mbps 4446 * Returns: 4447 */ 4448 int 4449 bfcmap_phy84756_speed_set(phy_ctrl_t *pc, int speed) 4450 { 4451 int value = 0; 4452 bfcmap_phy84756_intf_t line_mode; 4453 4454 if ((speed != 10) && (speed != 100) && 4455 (speed != 1000) && (speed != 10000)) { 4456 return SOC_E_NONE; 4457 } 4458 4459 SOC_IF_ERROR_RETURN( 4460 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 4461 4462 switch (line_mode) { 4463 case BFCMAP_PHY84756_INTF_SFI: 4464 case BFCMAP_PHY84756_INTF_1000X: 4465 /* Disable Clause 37 Autoneg */ 4466 SOC_IF_ERROR_RETURN( 4467 BFCMAP_MOD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, 0x0000, 4468 0x3040)); 4469 SOC_IF_ERROR_RETURN( 4470 BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 1, 4471 1)); 4472 SOC_IF_ERROR_RETURN( 4473 BFCMAP_MOD_PHY84756_LN_DEV7_AN_MSIC2r(pc, 0x2020, 4474 0x2020)); 4475 /* Disable Clause 37 Autoneg */ 4476 SOC_IF_ERROR_RETURN( 4477 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0x0000, 4478 0x3040)); 4479 SOC_IF_ERROR_RETURN( 4480 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 1, 4481 1)); 4482 if (speed == 10000) { 4483 4484 /* Set Line mode */ 4485 SOC_IF_ERROR_RETURN( 4486 bfcmap_phy84756_line_mode_set(pc, 0, 4487 BFCMAP_PHY84756_INTF_SFI)); 4488 4489 /* Set System side to match Line side */ 4490 SOC_IF_ERROR_RETURN( 4491 bfcmap_phy84756_sys_mode_set(pc, 0, 4492 BFCMAP_PHY84756_INTF_XFI)); 4493 /* Force Speed in PMD */ 4494 SOC_IF_ERROR_RETURN( 4495 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 4496 BFCMAP_PHY84756_PMD_CTRL_SS_10000, 4497 BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK)); 4498 /* Select 10G-LRM PMA */ 4499 SOC_IF_ERROR_RETURN( 4500 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRL2r(pc, 4501 BFCMAP_PHY84756_PMD_CTRL2_PMA_10GLRMPMD_TYPE, 4502 BFCMAP_PHY84756_PMD_CTRL2_PMA_SELECT_MASK)); 4503 /* Select 10G-LRM PMA */ 4504 SOC_IF_ERROR_RETURN( 4505 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRL2r(pc, 4506 BFCMAP_PHY84756_PMD_CTRL2_PMA_10GLRMPMD_TYPE, 4507 BFCMAP_PHY84756_PMD_CTRL2_PMA_SELECT_MASK)); 4508 4509 /* Force Speed in PMD */ 4510 SOC_IF_ERROR_RETURN( 4511 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 4512 BFCMAP_PHY84756_PMD_CTRL_SS_10000, 4513 BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK)); 4514 } else { 4515 if (speed == 1000) { 4516 /* Set Line mode */ 4517 SOC_IF_ERROR_RETURN( 4518 bfcmap_phy84756_line_mode_set(pc, 0, 4519 BFCMAP_PHY84756_INTF_1000X)); 4520 /* Set System side to match Line side */ 4521 SOC_IF_ERROR_RETURN( 4522 bfcmap_phy84756_sys_mode_set(pc, 0, 4523 BFCMAP_PHY84756_INTF_1000X)); 4524 /* Force Speed in PMD */ 4525 SOC_IF_ERROR_RETURN( 4526 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 4527 BFCMAP_PHY84756_PMD_CTRL_SS_1000, 4528 BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK)); 4529 4530 /* Force Speed in PMD */ 4531 SOC_IF_ERROR_RETURN( 4532 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 4533 BFCMAP_PHY84756_PMD_CTRL_SS_1000, 4534 BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK)); 4535 } else { 4536 return SOC_E_CONFIG; 4537 } 4538 } 4539 break; 4540 4541 case BFCMAP_PHY84756_INTF_SGMII: 4542 if (speed > 1000) { 4543 return SOC_E_CONFIG; 4544 } 4545 /* Disable Clause 37 Autoneg */ 4546 SOC_IF_ERROR_RETURN( 4547 BFCMAP_MOD_PHY84756_LN_DEV7_AN_MII_CTRLr(pc, 0x0000, 4548 0x3040)); 4549 SOC_IF_ERROR_RETURN( 4550 BFCMAP_MOD_PHY84756_LN_DEV7_AN_BASE1000X_CTRL1r(pc, 0, 4551 1)); 4552 SOC_IF_ERROR_RETURN( 4553 BFCMAP_MOD_PHY84756_LN_DEV7_AN_MSIC2r(pc, 0x2020, 4554 0x2020)); 4555 if (speed == 1000) { 4556 value = BFCMAP_PHY84756_PMD_CTRL_SS_1000; 4557 } 4558 if (speed == 100) { 4559 value = BFCMAP_PHY84756_PMD_CTRL_SS_100; 4560 } 4561 if (speed == 100) { 4562 value = BFCMAP_PHY84756_PMD_CTRL_SS_10; 4563 } 4564 /* Force Speed in PMD */ 4565 SOC_IF_ERROR_RETURN( 4566 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 4567 value, 4568 BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK)); 4569 4570 /* Set System side to match Line side */ 4571 SOC_IF_ERROR_RETURN( 4572 bfcmap_phy84756_sys_mode_set(pc, 0, 4573 BFCMAP_PHY84756_INTF_SGMII)); 4574 /* Disable Clause 37 Autoneg */ 4575 SOC_IF_ERROR_RETURN( 4576 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0x0000, 4577 0x3040)); 4578 SOC_IF_ERROR_RETURN( 4579 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 0, 4580 1)); 4581 SOC_IF_ERROR_RETURN( 4582 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MISC2r(pc, 0x2020, 4583 0x2020)); 4584 /* Force Speed in PMD */ 4585 SOC_IF_ERROR_RETURN( 4586 BFCMAP_MOD_PHY84756_SYS_DEV1_PMD_CTRLr(pc, 4587 value, 4588 BFCMAP_PHY84756_PMD_CTRL_10GSS_MASK)); 4589 break; 4590 default: 4591 return SOC_E_CONFIG; 4592 } 4593 4594 return SOC_E_NONE; 4595 } 4596 4597 4598 /* 4599 * Function: 4600 * bfcmap_phy84756_link_get 4601 * Purpose: 4602 * Determine the current link up/down status for a 84756 device. 4603 * Parameters: 4604 * phy_id - PHY Device Address 4605 * link - (OUT) 4606 * 1 = Indicates Link is established 4607 * 0 = No Link. 4608 * Returns: 4609 */ 4610 int 4611 bfcmap_phy84756_link_get(phy_ctrl_t *pc, int *link) 4612 { 4613 4614 buint16_t data = 0, pma_mii_stat = 0, pcs_mii_stat = 0,status=0; 4615 int speed=0; 4616 uint32 pdet_ena=0; 4617 #if defined(INCLUDE_FCMAP) 4618 buint16_t fval = 0; 4619 #endif 4620 int an, an_done; 4621 bfcmap_phy84756_intf_t line_mode; 4622 4623 /* Read AN MII STAT once per link get period */ 4624 SOC_IF_ERROR_RETURN( 4625 BFCMAP_RD_PHY84756_LN_DEV7_AN_MII_STATr(pc, &pc->mii_stat)); 4626 4627 #if defined(INCLUDE_FCMAP) 4628 if (pc->fcmap_enable) { 4629 BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x50, &fval); 4630 if (fval == 0x1a) { 4631 *link = 1; 4632 } else { 4633 *link = 0; 4634 } 4635 return SOC_E_NONE; 4636 } 4637 #endif 4638 4639 *link = 0; 4640 if (pc->mii_stat == 0xffff) { 4641 /* status == 0xffff check is to handle removable PHY daughter cards */ 4642 return SOC_E_NONE; 4643 } 4644 4645 SOC_IF_ERROR_RETURN( 4646 phy_84756_fcmap_an_get(pc->unit, pc->port, &an, &an_done)); 4647 4648 if (an && (an_done == 0)) { 4649 /* Auto neg in progess, return no link */ 4650 *link = 0; 4651 SOC_IF_ERROR_RETURN( 4652 phy_84756_fcmap_speed_get(pc->unit, pc->port, &speed)); 4653 if(speed == 1000) { 4654 SOC_IF_ERROR_RETURN( 4655 _phy_84756_control_pdet_get(pc->unit, pc->port, &pdet_ena)); 4656 SOC_IF_ERROR_RETURN( 4657 BFCMAP_RD_PHY84756_LN_DEV7_AN_BASE1000X_STAT1r(pc, &status)); 4658 status = (status & (0x1 << 1)) >> 1; 4659 if (pdet_ena == 1 && status == 1) { 4660 *link = 1; 4661 } 4662 } 4663 return SOC_E_NONE; 4664 } 4665 4666 4667 SOC_IF_ERROR_RETURN( 4668 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 4669 4670 switch (line_mode) { 4671 case BFCMAP_PHY84756_INTF_SFI: 4672 SOC_IF_ERROR_RETURN( 4673 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRL2r(pc, &data)); 4674 4675 SOC_IF_ERROR_RETURN( 4676 BFCMAP_RD_PHY84756_LN_DEV1_PMD_CTRL2r(pc, &data)); 4677 4678 SOC_IF_ERROR_RETURN( 4679 BFCMAP_RD_PHY84756_LN_DEV1_PMD_STATr(pc, &pma_mii_stat)); 4680 4681 SOC_IF_ERROR_RETURN( 4682 BFCMAP_RD_PHY84756_LN_DEV3_PCS_STATr(pc, &pcs_mii_stat)); 4683 4684 *link = pma_mii_stat & pcs_mii_stat & BFCMAP_PHY84756_PMD_STAT_RX_LINK_STATUS; 4685 4686 break; 4687 4688 case BFCMAP_PHY84756_INTF_1000X: 4689 case BFCMAP_PHY84756_INTF_SGMII: 4690 /* sgmii should have AN enabled to declare link up */ 4691 if ((line_mode == BFCMAP_PHY84756_INTF_SGMII) && (an == 0)) { 4692 *link = 0; 4693 break; 4694 } 4695 if (!(pc->mii_stat & BFCMAP_PHY84756_AN_MII_STAT_LINK_STATUS)) { 4696 /* In transition, no link */ 4697 *link = 0; 4698 break; 4699 } 4700 SOC_IF_ERROR_RETURN( 4701 BFCMAP_RD_PHY84756_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &data)); 4702 if ((data & 0x8080) == 0x8080) { 4703 /* System side and line side rx signal detect OK */ 4704 if (data & 0x1700) { /* system side link up */ 4705 if (data & 0x0017) { /* line side line up */ 4706 *link = 1; 4707 } 4708 } 4709 } 4710 break; 4711 4712 default: 4713 break; 4714 } 4715 return SOC_E_NONE; 4716 } 4717 4718 4719 /* 4720 * Function: 4721 * bfcmap_phy84756_linkfault_get 4722 * Purpose: 4723 * Determine the current link fault status for a 84757 device. 4724 * Parameters: 4725 * phy_id - PHY Device Address 4726 * fault - (OUT) 4727 * 1 = Indicates fault has triggered 4728 * 0 = No link fault. 4729 * Returns: 4730 */ 4731 int 4732 bfcmap_phy84756_linkfault_get(phy_ctrl_t *pc, int *fault) 4733 { 4734 4735 #if defined(INCLUDE_FCMAP) 4736 buint16_t fval = 0; 4737 4738 if (pc->fcmap_enable) { 4739 BFCMAP_PHY84756_REG_RD(pc, 0, 0x1e, 0x54, &fval); 4740 if (fval == 0x1) { 4741 /* clear the sticky fault */ 4742 BFCMAP_PHY84756_REG_WR(pc, 0, 0x1e, 0x54, 0); 4743 *fault = 1; 4744 } else { 4745 *fault = 0; 4746 } 4747 return SOC_E_NONE; 4748 } 4749 #endif 4750 *fault = 0; 4751 return SOC_E_NONE; 4752 } 4753 4754 4755 4756 4757 /* 4758 * Function: 4759 * bfcmap_phy84756_ability_advert_set 4760 * Purpose: 4761 * Set the current advertisement for auto-negotiation. 4762 * Parameters: 4763 * phy_id - PHY Device Address 4764 * ability - Ability indicating supported options/speeds. 4765 * For Speed & Duplex: 4766 * BFCMAP_PM_10MB_HD = 10Mb, Half Duplex 4767 * BFCMAP_PM_10MB_FD = 10Mb, Full Duplex 4768 * BFCMAP_PM_100MB_HD = 100Mb, Half Duplex 4769 * BFCMAP_PM_100MB_FD = 100Mb, Full Duplex 4770 * BFCMAP_PM_1000MB_HD = 1000Mb, Half Duplex 4771 * BFCMAP_PM_1000MB_FD = 1000Mb, Full Duplex 4772 * BFCMAP_PM_PAUSE_TX = TX Pause 4773 * BFCMAP_PM_PAUSE_RX = RX Pause 4774 * BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause 4775 * Returns: 4776 */ 4777 4778 int 4779 bfcmap_phy84756_ability_advert_set(phy_ctrl_t *pc, 4780 bfcmap_phy84756_port_ability_t ability) 4781 { 4782 buint16_t data = 0; 4783 bfcmap_phy84756_intf_t line_mode; 4784 4785 SOC_IF_ERROR_RETURN( 4786 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 4787 4788 if (line_mode == BFCMAP_PHY84756_INTF_1000X) { 4789 /* Always advertise 1000X full duplex */ 4790 data = BFCMAP_PHY84756_DEV7_1000X_ANA_C37_FD; 4791 if ((ability & BFCMAP_PHY84756_PA_PAUSE) == 4792 BFCMAP_PHY84756_PA_PAUSE) { 4793 data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE; 4794 } else { 4795 if (ability & BFCMAP_PHY84756_PA_PAUSE_TX) { 4796 data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE; 4797 } else { 4798 if (ability & BFCMAP_PHY84756_PA_PAUSE_RX) { 4799 data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE; 4800 data |= BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE; 4801 } 4802 } 4803 } 4804 SOC_IF_ERROR_RETURN( 4805 BFCMAP_WR_PHY84756_LN_DEV7_AN_ANAr(pc, data)); 4806 4807 } 4808 if (line_mode == BFCMAP_PHY84756_INTF_SGMII) { 4809 4810 4811 } else { 4812 /* No Autoneg in SFI mode */ 4813 /* return SOC_E_UNAVAIL; */ 4814 } 4815 return SOC_E_NONE; 4816 } 4817 4818 4819 /* 4820 * Function: 4821 * bfcmap_phy84756_ability_advert_get 4822 * Purpose: 4823 * Get the current advertisement for auto-negotiation. 4824 * Parameters: 4825 * phy_id - PHY Device Address 4826 * ability - (OUT) Port ability mask indicating supported options/speeds. 4827 * For Speed & Duplex: 4828 * BFCMAP_PM_10MB_HD = 10Mb, Half Duplex 4829 * BFCMAP_PM_10MB_FD = 10Mb, Full Duplex 4830 * BFCMAP_PM_100MB_HD = 100Mb, Half Duplex 4831 * BFCMAP_PM_100MB_FD = 100Mb, Full Duplex 4832 * BFCMAP_PM_1000MB_HD = 1000Mb, Half Duplex 4833 * BFCMAP_PM_1000MB_FD = 1000Mb, Full Duplex 4834 * BFCMAP_PM_PAUSE_TX = TX Pause 4835 * BFCMAP_PM_PAUSE_RX = RX Pause 4836 * BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause 4837 * Returns: 4838 */ 4839 4840 int 4841 bfcmap_phy84756_ability_advert_get(phy_ctrl_t *pc, 4842 bfcmap_phy84756_port_ability_t *ability) 4843 { 4844 buint16_t data = 0; 4845 bfcmap_phy84756_intf_t line_mode; 4846 4847 if (ability == NULL) { 4848 return SOC_E_PARAM; 4849 } 4850 4851 SOC_IF_ERROR_RETURN( 4852 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 4853 4854 if (line_mode == BFCMAP_PHY84756_INTF_1000X) { 4855 SOC_IF_ERROR_RETURN( 4856 BFCMAP_RD_PHY84756_LN_DEV7_AN_ANAr(pc, &data)); 4857 4858 *ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_FD) ? 4859 BFCMAP_PHY84756_PA_1000MB_FD : 0; 4860 *ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_HD) ? 4861 BFCMAP_PHY84756_PA_1000MB_HD : 0; 4862 switch (data & (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 4863 BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE)) { 4864 case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE: 4865 *ability |= BFCMAP_PHY84756_PA_PAUSE; 4866 break; 4867 case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE: 4868 *ability |= BFCMAP_PHY84756_PA_PAUSE_TX; 4869 break; 4870 case (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 4871 BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE): 4872 *ability |= BFCMAP_PHY84756_PA_PAUSE_RX; 4873 break; 4874 } 4875 } else { 4876 if (line_mode == BFCMAP_PHY84756_INTF_SGMII) { 4877 *ability = BFCMAP_PHY84756_PA_SPEED_ALL | 4878 BFCMAP_PHY84756_PA_AN | 4879 BFCMAP_PHY84756_PA_PAUSE | 4880 BFCMAP_PHY84756_PA_PAUSE_ASYMM; 4881 4882 } else { 4883 /* No Autoneg in SFI mode */ 4884 *ability = BFCMAP_PHY84756_PA_10000MB_FD | 4885 BFCMAP_PHY84756_PA_PAUSE; 4886 } 4887 } 4888 return SOC_E_NONE; 4889 } 4890 4891 4892 /* 4893 * Function: 4894 * bfcmap_phy84756_remote_ability_advert_get 4895 * Purpose: 4896 * Get partners current advertisement for auto-negotiation. 4897 * Parameters: 4898 * phy_id - PHY Device Address 4899 * remote_ability - (OUT) Port ability mask indicating supported options/speeds. 4900 * For Speed & Duplex: 4901 * BFCMAP_PM_10MB_HD = 10Mb, Half Duplex 4902 * BFCMAP_PM_10MB_FD = 10Mb, Full Duplex 4903 * BFCMAP_PM_100MB_HD = 100Mb, Half Duplex 4904 * BFCMAP_PM_100MB_FD = 100Mb, Full Duplex 4905 * BFCMAP_PM_1000MB_HD = 1000Mb, Half Duplex 4906 * BFCMAP_PM_1000MB_FD = 1000Mb, Full Duplex 4907 * BFCMAP_PM_PAUSE_TX = TX Pause 4908 * BFCMAP_PM_PAUSE_RX = RX Pause 4909 * BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause 4910 * Returns: 4911 */ 4912 4913 int 4914 bfcmap_phy84756_remote_ability_advert_get(phy_ctrl_t *pc, 4915 bfcmap_phy84756_port_ability_t *remote_ability) 4916 { 4917 buint16_t data = 0; 4918 bfcmap_phy84756_intf_t line_mode; 4919 4920 if (remote_ability == NULL) { 4921 return SOC_E_PARAM; 4922 } 4923 4924 SOC_IF_ERROR_RETURN( 4925 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 4926 4927 if (line_mode == BFCMAP_PHY84756_INTF_1000X) { 4928 SOC_IF_ERROR_RETURN( 4929 BFCMAP_RD_PHY84756_LN_DEV7_AN_ANPr(pc, &data)); 4930 4931 *remote_ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_FD) ? 4932 BFCMAP_PHY84756_PA_1000MB_FD : 0; 4933 *remote_ability |= (data & BFCMAP_PHY84756_DEV7_1000X_ANA_C37_HD) ? 4934 BFCMAP_PHY84756_PA_1000MB_HD : 0; 4935 switch (data & (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 4936 BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE)) { 4937 case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE: 4938 *remote_ability |= BFCMAP_PHY84756_PA_PAUSE; 4939 break; 4940 case BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE: 4941 *remote_ability |= BFCMAP_PHY84756_PA_PAUSE_TX; 4942 break; 4943 case (BFCMAP_PHY84756_DEV7_1000X_ANA_C37_PAUSE | 4944 BFCMAP_PHY84756_DEV7_1000X_ANA_C37_ASYM_PAUSE): 4945 *remote_ability |= BFCMAP_PHY84756_PA_PAUSE_RX; 4946 break; 4947 } 4948 } else if (line_mode == BFCMAP_PHY84756_INTF_SGMII) { 4949 4950 4951 } else { 4952 /* No Autoneg in SFI mode */ 4953 return SOC_E_UNAVAIL; 4954 } 4955 return SOC_E_NONE; 4956 } 4957 4958 4959 /* 4960 * Function: 4961 * bfcmap_phy84756_ability_local_get 4962 * Purpose: 4963 * Get the PHY abilities 4964 * Parameters: 4965 * phy_id - PHY Device Address 4966 * mode - Mask indicating supported options/speeds. 4967 * For Speed & Duplex: 4968 * BFCMAP_PM_10MB_HD = 10Mb, Half Duplex 4969 * BFCMAP_PM_10MB_FD = 10Mb, Full Duplex 4970 * BFCMAP_PM_100MB_HD = 100Mb, Half Duplex 4971 * BFCMAP_PM_100MB_FD = 100Mb, Full Duplex 4972 * BFCMAP_PM_1000MB_HD = 1000Mb, Half Duplex 4973 * BFCMAP_PM_1000MB_FD = 1000Mb, Full Duplex 4974 * BFCMAP_PM_PAUSE_TX = TX Pause 4975 * BFCMAP_PM_PAUSE_RX = RX Pause 4976 * BFCMAP_PM_PAUSE_ASYMM = Asymmetric Pause 4977 * BFCMAP_PM_SGMII = SGMIII Supported 4978 * BFCMAP_PM_XSGMII = XSGMIII Supported 4979 * Returns: 4980 */ 4981 int 4982 bfcmap_phy84756_ability_local_get(phy_ctrl_t *pc, 4983 bfcmap_phy84756_port_ability_t *ability) 4984 { 4985 bfcmap_phy84756_intf_t line_mode; 4986 4987 if (ability == NULL) { 4988 return SOC_E_PARAM; 4989 } 4990 4991 SOC_IF_ERROR_RETURN( 4992 bfcmap_phy84756_line_intf_get(pc, 0, &line_mode)); 4993 4994 *ability = BFCMAP_PHY84756_PA_LB_PHY | BFCMAP_PHY84756_PA_PAUSE; 4995 *ability |= BFCMAP_PHY84756_PA_SGMII; 4996 4997 if (line_mode == BFCMAP_PHY84756_INTF_SGMII) { 4998 *ability |= BFCMAP_PHY84756_PA_AN; 4999 *ability |= BFCMAP_PHY84756_PA_SPEED_ALL; 5000 5001 } else { 5002 *ability |= BFCMAP_PHY84756_PA_XSGMII; 5003 *ability |= BFCMAP_PHY84756_PA_10000MB_FD; 5004 *ability |= BFCMAP_PHY84756_PA_1000MB_FD; 5005 } 5006 5007 return(SOC_E_NONE); 5008 } 5009 5010 STATIC int 5011 _bfcmap_phy84756_system_sgmii_speed_set(phy_ctrl_t *pc, int dev_port, int speed) 5012 { 5013 buint16_t mii_ctrl = 0; 5014 5015 if (speed == 0) { 5016 return SOC_E_NONE; 5017 } 5018 5019 { 5020 SOC_IF_ERROR_RETURN( 5021 BFCMAP_RD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, &mii_ctrl)); 5022 5023 mii_ctrl &= ~(BFCMAP_PHY84756_SGMII_MII_CTRL_SS_MASK); 5024 switch(speed) { 5025 case 10: 5026 mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_SS_10; 5027 break; 5028 case 100: 5029 mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_SS_100; 5030 break; 5031 case 1000: 5032 mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_SS_1000; 5033 break; 5034 default: 5035 return SOC_E_CONFIG; 5036 } 5037 SOC_IF_ERROR_RETURN( 5038 BFCMAP_WR_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, mii_ctrl)); 5039 } 5040 return SOC_E_NONE; 5041 } 5042 5043 STATIC int 5044 _bfcmap_phy84756_system_sgmii_duplex_set(phy_ctrl_t *pc, int dev_port, 5045 int duplex) 5046 { 5047 buint16_t mii_ctrl; 5048 5049 { 5050 SOC_IF_ERROR_RETURN( 5051 BFCMAP_RD_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, &mii_ctrl)); 5052 5053 if ( duplex ) { 5054 mii_ctrl |= BFCMAP_PHY84756_AN_MII_CTRL_FD; 5055 } else { 5056 mii_ctrl &= ~BFCMAP_PHY84756_AN_MII_CTRL_FD; 5057 } 5058 SOC_IF_ERROR_RETURN( 5059 BFCMAP_WR_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, mii_ctrl)); 5060 } 5061 5062 return SOC_E_NONE; 5063 } 5064 5065 STATIC int 5066 _bfcmap_phy84756_system_sgmii_init(phy_ctrl_t *pc, int dev_port) 5067 { 5068 SOC_IF_ERROR_RETURN( 5069 BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x0000, 0x2000)); 5070 5071 SOC_IF_ERROR_RETURN( 5072 BFCMAP_WR_PHY84756_XFI_DEV7_AN_BASE1000X_CTRL1r(pc, 0x01a0)); 5073 5074 SOC_IF_ERROR_RETURN( 5075 BFCMAP_MOD_PHY84756_XFI_DEV7_AN_MISC2r(pc, 0x6000, 0x6020)); 5076 5077 SOC_IF_ERROR_RETURN( 5078 BFCMAP_PHY84756_REG_WR(pc, 0x01, 0x0007, 0x835c, 0x0001)); 5079 5080 SOC_IF_ERROR_RETURN( 5081 BFCMAP_WR_PHY84756_XFI_DEV7_AN_MII_CTRLr(pc, 0x0140)); 5082 5083 SOC_IF_ERROR_RETURN( 5084 BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x2000, 0x2000)); 5085 5086 return SOC_E_NONE; 5087 } 5088 5089 STATIC int 5090 _bfcmap_phy84756_system_sgmii_sync(phy_ctrl_t *pc, int dev_port) 5091 { 5092 int speed; 5093 int duplex; 5094 5095 SOC_IF_ERROR_RETURN( 5096 phy_84756_fcmap_speed_get(pc->unit, pc->port, &speed)); 5097 5098 SOC_IF_ERROR_RETURN( 5099 phy_84756_fcmap_duplex_get(pc->unit, pc->port, &duplex)); 5100 5101 SOC_IF_ERROR_RETURN( 5102 BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x0000, 0x2000)); 5103 5104 SOC_IF_ERROR_RETURN( 5105 _bfcmap_phy84756_system_sgmii_speed_set(pc, dev_port, speed)); 5106 5107 SOC_IF_ERROR_RETURN( 5108 _bfcmap_phy84756_system_sgmii_duplex_set(pc, dev_port, duplex)); 5109 5110 SOC_IF_ERROR_RETURN( 5111 BFCMAP_PHY84756_REG_MOD(pc, 0x01, 0x0007, 0x8000, 0x2000, 0x2000)); 5112 5113 SOC_IF_ERROR_RETURN( /* Notify Switch of Speed */ 5114 soc_phyctrl_notify(pc->unit, pc->port, phyEventSpeed, speed)); 5115 5116 return SOC_E_NONE; 5117 } 5118 5119 /* 5120 * Function: 5121 * bfcmap_phy84756_mdio_firmware_download 5122 * Purpose: 5123 * Download new firmware via MDIO. 5124 * Parameters: 5125 * phy_id - PHY Device Address 5126 * new_fw - Pointer to new firmware 5127 * fw_length - Length of the firmware 5128 * Returns: 5129 */ 5130 int 5131 bfcmap_phy84756_mdio_firmware_download(phy_ctrl_t *pc, 5132 buint8_t *new_fw, buint32_t fw_length) 5133 { 5134 5135 buint16_t data16; 5136 int j; 5137 buint16_t num_words; 5138 5139 /* 0xc848[15]=0, MDIO downloading to RAM, 0xc848[14]=1, serial boot */ 5140 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 5141 SOC_IF_ERROR_RETURN( 5142 BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc848, 5143 (0 << 15)|(1 << 14), 5144 (1 << 15)|(1 << 14)|((1 << 13) | (1 << 2)))); 5145 5146 /* Reset, to download code from MDIO */ 5147 SOC_IF_ERROR_RETURN( 5148 BFCMAP_MOD_PHY84756_LN_DEV1_PMD_CTRLr(pc, 5149 BFCMAP_PHY84756_PMD_CTRL_RESET, BFCMAP_PHY84756_PMD_CTRL_RESET)); 5150 5151 sal_usleep(50000); 5152 5153 /* Write Starting Address, where the Code will reside in SRAM */ 5154 data16 = 0x8000; 5155 SOC_IF_ERROR_RETURN 5156 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, BFCMAP_PHY84756_PMAD_M8051_MSGIN_REG, data16)); 5157 5158 /* make sure address word is read by the micro */ 5159 sal_usleep(10); /* Wait for 10us */ 5160 5161 /* Write SPI SRAM Count Size */ 5162 data16 = (fw_length)/2; 5163 SOC_IF_ERROR_RETURN 5164 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, BFCMAP_PHY84756_PMAD_M8051_MSGIN_REG, data16)); 5165 5166 /* make sure read by the micro */ 5167 sal_usleep(10); /* Wait for 10us */ 5168 5169 /* Fill in the SRAM */ 5170 num_words = (fw_length - 1); 5171 for (j = 0; j < num_words; j+=2) { 5172 /* Make sure the word is read by the Micro */ 5173 sal_usleep(10); 5174 5175 data16 = (new_fw[j] << 8) | new_fw[j+1]; 5176 SOC_IF_ERROR_RETURN 5177 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, BFCMAP_PHY84756_PMAD_M8051_MSGIN_REG, 5178 data16)); 5179 } 5180 5181 /* make sure last code word is read by the micro */ 5182 sal_usleep(20); 5183 5184 /* Read Hand-Shake message (Done) from Micro */ 5185 SOC_IF_ERROR_RETURN 5186 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc,BFCMAP_PHY84756_PMAD_M8051_MSGOUT_REG, &data16)); 5187 5188 if (data16 != 0x4321 ) { 5189 /* Download done message */ 5190 LOG_CLI((BSL_META_U(pc->unit, 5191 "MDIO firmware download failed. Message: 0x%x\n"), data16)); 5192 } 5193 5194 /* Clear LASI status */ 5195 SOC_IF_ERROR_RETURN 5196 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0x9003, &data16)); 5197 5198 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 5199 sal_usleep(100); /* Wait for 100 usecs */ 5200 5201 SOC_IF_ERROR_RETURN 5202 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc,BFCMAP_PHY84756_PMAD_M8051_MSGOUT_REG, &data16)); 5203 5204 /* Need to check if checksum is correct */ 5205 SOC_IF_ERROR_RETURN 5206 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1C, &data16)); 5207 5208 if (data16 != 0x600D) { 5209 /* Bad CHECKSUM */ 5210 LOG_CLI((BSL_META_U(pc->unit, 5211 "MDIO Firmware downlad failure:" 5212 "Incorrect Checksum %x\n"), data16)); 5213 return SOC_E_FAIL; 5214 } 5215 5216 /* read Rev-ID */ 5217 SOC_IF_ERROR_RETURN 5218 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xCA1A, &data16)); 5219 LOG_INFO(BSL_LS_SOC_PHY, 5220 (BSL_META_U(pc->unit, 5221 "MDIO Firmware download completed. Version : 0x%x\n"), data16)); 5222 5223 return SOC_E_NONE; 5224 } 5225 5226 /* 5227 * Function: 5228 * _phy_84756_phy_84756_write_message 5229 * 5230 * Purpose: 5231 * Write into Message In and Read from MSG Out register. 5232 * Input: 5233 * phy_id 5234 * wrdata 5235 * rddata 5236 */ 5237 5238 STATIC int 5239 _phy_84756_write_message(phy_ctrl_t *pc, buint16_t wrdata, buint16_t *rddata) 5240 { 5241 buint16_t tmp_data = 0; 5242 int iter = 0; 5243 5244 SOC_IF_ERROR_RETURN 5245 (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data)); 5246 SOC_IF_ERROR_RETURN 5247 (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, wrdata)); 5248 5249 do { 5250 SOC_IF_ERROR_RETURN 5251 (BFCMAP_RD_PHY84756_LN_DEV1_LASI_STATr(pc, &tmp_data)); 5252 5253 if (tmp_data & 0x4) { 5254 break; 5255 } 5256 sal_usleep(BFCMAP_WR_TIMEOUT); 5257 iter++; 5258 } while (iter < BFCMAP_WR_ITERATIONS); 5259 5260 if (!(tmp_data & 0x4)) { 5261 LOG_CLI((BSL_META_U(pc->unit, 5262 "write message failed due to timeout\n"))); 5263 return SOC_E_FAIL; 5264 } 5265 5266 SOC_IF_ERROR_RETURN 5267 (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &tmp_data)); 5268 5269 *rddata = tmp_data; 5270 SOC_IF_ERROR_RETURN 5271 (BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARMr(pc, &tmp_data)); 5272 5273 return SOC_E_NONE; 5274 } 5275 5276 5277 /* 5278 * Function: 5279 * _phy_84756_rom_wait 5280 * 5281 * Purpose: 5282 * Wait for data to be written to the SPI-ROM. 5283 * Input: 5284 * phy_id 5285 */ 5286 5287 STATIC int 5288 _phy_84756_rom_wait(phy_ctrl_t *pc) 5289 { 5290 buint16_t rd_data = 0, wr_data; 5291 int count; 5292 int SPI_READY; 5293 int iter = 0; 5294 5295 do { 5296 count = 1; 5297 wr_data = ((BFCMAP_RD_CPU_CTRL_REGS * 0x0100) | count); 5298 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5299 wr_data = BFCMAP_SPI_CTRL_1_L; 5300 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5301 if (rd_data & 0x0100) { 5302 break; 5303 } 5304 sal_usleep(BFCMAP_WR_TIMEOUT); 5305 iter++; 5306 } while (iter < BFCMAP_WR_ITERATIONS); 5307 5308 if (!(rd_data & 0x0100)) { 5309 LOG_CLI((BSL_META_U(pc->unit, 5310 "_phy_84756_rom_wait: write timeout\n"))); 5311 return SOC_E_TIMEOUT; 5312 } 5313 5314 SPI_READY = 1; 5315 while (SPI_READY == 1) { 5316 /* Set-up SPI Controller To Receive SPI EEPROM Status. */ 5317 count = 1; 5318 wr_data = ((BFCMAP_WR_CPU_CTRL_REGS * 0x0100) | count); 5319 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5320 wr_data = BFCMAP_SPI_CTRL_2_H; 5321 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5322 wr_data = 0x0100; 5323 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5324 /* Fill-up SPI Transmit Fifo To check SPI Status. */ 5325 count = 2; 5326 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5327 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5328 /* Write Tx Fifo Register Address. */ 5329 wr_data = BFCMAP_SPI_TXFIFO; 5330 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5331 5332 /* Write SPI Tx Fifo Control Word-1. */ 5333 wr_data = ((1 * 0x0100) | BFCMAP_MSGTYPE_HRD); 5334 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5335 /* Write SPI Tx Fifo Control Word-2. */ 5336 wr_data = BFCMAP_RDSR_OPCODE; 5337 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5338 /* Write SPI Control Register Write Command. */ 5339 count = 2; 5340 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5341 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5342 /* Write SPI Control -1 Register Address. */ 5343 wr_data = BFCMAP_SPI_CTRL_1_L; 5344 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5345 /* Write SPI Control -1 Register Word-1. */ 5346 wr_data = 0x0101; 5347 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5348 /* Write SPI Control -1 Register Word-2. */ 5349 wr_data = 0x0100; 5350 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5351 /* Write SPI Control Register Write Command. */ 5352 count = 1; 5353 wr_data = ((BFCMAP_WR_CPU_CTRL_REGS * 0x0100) | count); 5354 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5355 /* Write SPI Control -1 Register Address. */ 5356 wr_data = BFCMAP_SPI_CTRL_1_H; 5357 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5358 /* Write SPI Control -1 Register Word-2. */ 5359 wr_data = 0x0103; 5360 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5361 /* Wait For 64 bytes To be written. */ 5362 rd_data = 0x0000; 5363 5364 do { 5365 count = 1; 5366 wr_data = ((BFCMAP_RD_CPU_CTRL_REGS * 0x0100) | count); 5367 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5368 wr_data = BFCMAP_SPI_CTRL_1_L; 5369 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5370 if (rd_data & 0x0100) { 5371 break; 5372 } 5373 sal_usleep(BFCMAP_WR_TIMEOUT); 5374 iter ++; 5375 } while (iter < BFCMAP_WR_ITERATIONS); 5376 5377 if (!(rd_data & 0x0100)) { 5378 LOG_CLI((BSL_META_U(pc->unit, 5379 "_phy_84756_rom_program:timeout 2\n"))); 5380 return SOC_E_TIMEOUT; 5381 } 5382 /* Write SPI Control Register Read Command. */ 5383 count = 1; 5384 wr_data = ((BFCMAP_RD_CPU_CTRL_REGS * 0x0100) | count); 5385 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5386 /* Write SPI Control -1 Register Address. */ 5387 wr_data = BFCMAP_SPI_RXFIFO; 5388 5389 SOC_IF_ERROR_RETURN 5390 (BFCMAP_WR_PHY84756_LN_DEV1_M8501_MSGINr(pc, wr_data)); 5391 SOC_IF_ERROR_RETURN 5392 (BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &rd_data)); 5393 5394 /* Clear LASI Message Out Status. */ 5395 SOC_IF_ERROR_RETURN 5396 (BFCMAP_RD_PHY84756_LN_DEV1_LASI_STATr(pc, &wr_data)); 5397 5398 if ((rd_data & 0x1) == 0) { 5399 SPI_READY = 0; 5400 } 5401 } /* SPI_READY */ 5402 return SOC_E_NONE; 5403 } 5404 5405 5406 /* 5407 * Function: 5408 * _phy_84756_rom_write_enable_set 5409 * 5410 * Purpose: 5411 * Enable disable protection on SPI_EEPROM 5412 * 5413 * Input: 5414 * phy_id 5415 * Output: 5416 * SOC_E_xxx 5417 * 5418 * Notes: 5419 * 25AA256 256Kbit Serial EEPROM 5420 * STATUS Register 5421 * +------------------------------------------+ 5422 * | WPEN | x | x | x | BP1 | BP0 | WEL | WIP | 5423 * +------------------------------------------+ 5424 * BP1 BP0 : Protected Blocks 5425 * 0 0 : Protect None 5426 * 1 1 : Protect All 5427 * 5428 * WEL : Write Latch Enable 5429 * 0 : Do not allow writes 5430 * 1 : Allow writes 5431 */ 5432 STATIC int 5433 _phy_84756_rom_write_enable_set(phy_ctrl_t *pc, int enable) 5434 { 5435 buint16_t rd_data, wr_data; 5436 buint8_t wrsr_data; 5437 int count; 5438 5439 /* 5440 * Write SPI Control Register Write Command. 5441 */ 5442 count = 2; 5443 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5444 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5445 5446 /* 5447 * Write SPI Control -2 Register Address. 5448 */ 5449 wr_data = BFCMAP_SPI_CTRL_2_L; 5450 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5451 5452 /* 5453 * Write SPI Control -2 Register Word-1. 5454 */ 5455 wr_data = 0x8200; 5456 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5457 5458 /* 5459 * Write SPI Control -2 Register Word-2. 5460 */ 5461 wr_data = 0x0100; 5462 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5463 5464 /* 5465 * Fill-up SPI Transmit Fifo With SPI EEPROM Messages. 5466 * Write SPI Control Register Write Command. 5467 */ 5468 count = 4; 5469 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5470 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5471 5472 /* 5473 * Write Tx Fifo Register Address. 5474 */ 5475 wr_data = BFCMAP_SPI_TXFIFO; 5476 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5477 5478 /* 5479 * Write SPI Tx Fifo Control Word-1. 5480 */ 5481 wr_data = ((1 * 0x0100) | BFCMAP_MSGTYPE_HWR); 5482 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5483 5484 /* 5485 * Write SPI Tx Fifo Control Word-2. 5486 */ 5487 wr_data = ((BFCMAP_MSGTYPE_HWR * 0x0100) | BFCMAP_WREN_OPCODE); 5488 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5489 5490 /* 5491 * Write SPI Tx Fifo Control Word-3. 5492 */ 5493 wr_data = ((BFCMAP_WRSR_OPCODE * 0x100) | (0x2)); 5494 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5495 5496 /* 5497 * Write SPI Tx Fifo Control Word-4. 5498 */ 5499 wrsr_data = enable ? 0x2 : 0xc; 5500 wr_data = ((wrsr_data * 0x0100) | wrsr_data); 5501 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5502 5503 /* 5504 * Write SPI Control Register Write Command. 5505 */ 5506 count = 2; 5507 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5508 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5509 5510 /* 5511 * Write SPI Control -1 Register Address. 5512 */ 5513 wr_data = BFCMAP_SPI_CTRL_1_L; 5514 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5515 5516 /* 5517 * Write SPI Control -1 Register Word-1. 5518 */ 5519 wr_data = 0x0101; 5520 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5521 5522 /* 5523 * Write SPI Control -1 Register Word-2. 5524 */ 5525 wr_data = 0x0003; 5526 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5527 5528 /* 5529 * Wait For WRSR Command To be written. 5530 */ 5531 SOC_IF_ERROR_RETURN(_phy_84756_rom_wait(pc)); 5532 5533 return SOC_E_NONE; 5534 } 5535 5536 /* 5537 * Function: 5538 * bfcmap_phy84756_spi_firmware_update 5539 * Purpose: 5540 * Update the firmware in SPI ROM 5541 * Parameters: 5542 * phy_id - PHY Device Address 5543 * new_fw - Pointer to new firmware 5544 * fw_length - Length of the firmware 5545 * Returns: 5546 */ 5547 int 5548 bfcmap_phy84756_spi_firmware_update(phy_ctrl_t *pc, 5549 buint8_t *array, buint32_t datalen) 5550 { 5551 5552 buint16_t data = 0; 5553 int dev_port, j; 5554 buint16_t rd_data, wr_data; 5555 buint8_t spi_values[BFCMAP_WR_BLOCK_SIZE]; 5556 int count, i = 0; 5557 5558 5559 if (array == NULL) { 5560 return SOC_E_PARAM; 5561 } 5562 5563 if (_phy84756_phy_get_dev_addr(pc, NULL, &dev_port) != SOC_E_NONE) { 5564 return SOC_E_CONFIG; 5565 } 5566 5567 /* Set Bit 2 and Bit 0 in SPI Control */ 5568 SOC_IF_ERROR_RETURN( 5569 BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, 0x80FD, 0xffff)); 5570 5571 /* ser_boot pin high */ 5572 SOC_IF_ERROR_RETURN( 5573 BFCMAP_MOD_PHY84756_LN_DEV1_MISC_CNTL2r(pc, 0x1, 0x1)); 5574 5575 /* Read LASI Status */ 5576 SOC_IF_ERROR_RETURN( 5577 BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARM_STATr(pc, &data)); 5578 SOC_IF_ERROR_RETURN( 5579 BFCMAP_RD_PHY84756_LN_DEV1_TX_ALARM_STATr(pc, &data)); 5580 SOC_IF_ERROR_RETURN( 5581 BFCMAP_RD_PHY84756_LN_DEV1_LASI_STATr(pc, &data)); 5582 5583 /* Enable LASI for Message Out */ 5584 SOC_IF_ERROR_RETURN( 5585 BFCMAP_MOD_PHY84756_LN_DEV1_RX_ALARM_CNTLr(pc, 0x4, 0x4)); 5586 5587 /* Enable RX Alarm in LASI */ 5588 SOC_IF_ERROR_RETURN( 5589 BFCMAP_MOD_PHY84756_LN_DEV1_LASI_CNTLr(pc, 0x4, 0x4)); 5590 5591 /* Read any residual Message out register */ 5592 SOC_IF_ERROR_RETURN( 5593 BFCMAP_RD_PHY84756_LN_DEV1_M8501_MSGOUTr(pc, &data)); 5594 5595 /* Clear LASI Message OUT status */ 5596 SOC_IF_ERROR_RETURN( 5597 BFCMAP_RD_PHY84756_LN_DEV1_RX_ALARM_STATr(pc, &data)); 5598 5599 /* Set SPI-ROM write enable */ 5600 SOC_IF_ERROR_RETURN( 5601 _phy_84756_rom_write_enable_set(pc, 1)); 5602 5603 5604 for (j = 0; j < datalen; j +=BFCMAP_WR_BLOCK_SIZE) { 5605 /* Setup SPI Controller */ 5606 count = 2; 5607 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5608 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5609 5610 /* Write SPI Control -2 Register Address.*/ 5611 wr_data = BFCMAP_SPI_CTRL_2_L; 5612 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5613 5614 /* Write SPI Control -2 Register Word-1. */ 5615 wr_data = 0x8200; 5616 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5617 5618 /* Write SPI Control -2 Register Word-2. */ 5619 wr_data = 0x0100; 5620 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5621 5622 /* Fill-up SPI Transmit Fifo. 5623 * Write SPI Control Register Write Command. 5624 */ 5625 count = 4 + (BFCMAP_WR_BLOCK_SIZE / 2); 5626 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5627 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5628 5629 /* Write Tx Fifo Register Address. */ 5630 wr_data = BFCMAP_SPI_TXFIFO; 5631 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5632 5633 /* Write SPI Tx Fifo Control Word-1. */ 5634 wr_data = ((1 * 0x0100) | BFCMAP_MSGTYPE_HWR); 5635 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5636 5637 /* Write SPI Tx Fifo Control Word-2. */ 5638 wr_data = ((BFCMAP_MSGTYPE_HWR * 0x0100) | BFCMAP_WREN_OPCODE); 5639 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5640 5641 /* Write SPI Tx Fifo Control Word-3. */ 5642 wr_data = ((BFCMAP_WR_OPCODE * 0x0100) | (0x3 + BFCMAP_WR_BLOCK_SIZE)); 5643 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5644 5645 /* Write SPI Tx Fifo Control Word-4. */ 5646 wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100)); 5647 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5648 5649 if (datalen < (j + BFCMAP_WR_BLOCK_SIZE)) { /* last block */ 5650 sal_memset(spi_values,0,BFCMAP_WR_BLOCK_SIZE); 5651 sal_memcpy(spi_values,&array[j],datalen - j); 5652 5653 for (i = 0; i < BFCMAP_WR_BLOCK_SIZE; i += 2) { 5654 /* Write SPI Tx Fifo Data Word-4. */ 5655 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]); 5656 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5657 } 5658 } else { 5659 for (i = 0; i < BFCMAP_WR_BLOCK_SIZE; i += 2) { 5660 /* Write SPI Tx Fifo Data Word-4. */ 5661 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]); 5662 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5663 } 5664 } 5665 5666 /* 5667 * Set-up SPI Controller To Transmit. 5668 * Write SPI Control Register Write Command. 5669 */ 5670 count = 2; 5671 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5672 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5673 5674 wr_data = BFCMAP_SPI_CTRL_1_L; 5675 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5676 5677 /* Write SPI Control -1 Register Word-1. */ 5678 wr_data = 0x0501; 5679 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5680 5681 /* Write SPI Control -1 Register Word-2. */ 5682 wr_data = 0x0003; 5683 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5684 5685 /* Wait For 64 bytes To be written. */ 5686 SOC_IF_ERROR_RETURN(_phy_84756_rom_wait(pc)); 5687 } 5688 5689 /* Clear SPI-ROM write enable */ 5690 SOC_IF_ERROR_RETURN( 5691 _phy_84756_rom_write_enable_set(pc, 0)); 5692 5693 /* Disable SPI EEPROM. */ 5694 count = 2; 5695 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5696 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5697 5698 /* Write SPI Control -2 Register Address. */ 5699 wr_data = BFCMAP_SPI_CTRL_2_L; 5700 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5701 5702 /* Write SPI Control -2 Register Word-1. */ 5703 wr_data = 0x8200; 5704 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5705 5706 /* Write SPI Control -2 Register Word-2. */ 5707 wr_data = 0x0100; 5708 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5709 5710 5711 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */ 5712 count = 2; 5713 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5714 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5715 5716 /* Write Tx Fifo Register Address. */ 5717 wr_data = BFCMAP_SPI_TXFIFO; 5718 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5719 5720 /* Write SPI Tx Fifo Control Word-1. */ 5721 wr_data = ((0x1*0x0100) | BFCMAP_MSGTYPE_HWR); 5722 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5723 5724 /* Write SPI Tx Fifo Control Word-2. */ 5725 wr_data = BFCMAP_WRDI_OPCODE; 5726 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5727 5728 /* Write SPI Control Register Write Command. */ 5729 count = 2; 5730 wr_data = ((BFCMAP_WR_CPU_CTRL_FIFO * 0x0100) | count); 5731 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5732 5733 /* Write SPI Control -1 Register Address. */ 5734 wr_data = BFCMAP_SPI_CTRL_1_L; 5735 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5736 5737 /* Write SPI Control -1 Register Word-1. */ 5738 wr_data = 0x0101; 5739 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5740 5741 /* Write SPI Control -1 Register Word-2. */ 5742 wr_data = 0x0003; 5743 SOC_IF_ERROR_RETURN(_phy_84756_write_message(pc, wr_data, &rd_data)); 5744 5745 /* ser_boot pin LOW */ 5746 SOC_IF_ERROR_RETURN( 5747 BFCMAP_MOD_PHY84756_LN_DEV1_MISC_CNTL2r(pc, 0x0, 0x1)); 5748 5749 /* Disable Bit 2 and Bit 0 in SPI Control */ 5750 SOC_IF_ERROR_RETURN( 5751 BFCMAP_MOD_PHY84756_LN_DEV1_SPI_CTRL_STATr(pc, 0xc0F9, 0xffff)); 5752 5753 return SOC_E_NONE; 5754 } 5755 5756 5757 5758 void _phy_84756_fcmap_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode, 5759 int offset, buint16_t *value) 5760 { 5761 5762 switch (mode) { 5763 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE: 5764 *value |= (0x0 << offset); 5765 break; 5766 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD: 5767 *value |= (0x1 << offset); 5768 break; 5769 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN: 5770 *value |= (0x2 << offset); 5771 break; 5772 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP: 5773 *value |= (0x3 << offset); 5774 break; 5775 default: 5776 break; 5777 } 5778 5779 } 5780 5781 void _phy_84756_fcmap_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode, 5782 int offset, buint16_t *value) 5783 { 5784 5785 switch (mode) { 5786 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE: 5787 *value |= (0x0 << offset); 5788 break; 5789 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD: 5790 *value |= (0x1 << offset); 5791 break; 5792 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP: 5793 *value |= (0x2 << offset); 5794 break; 5795 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME: 5796 *value |= (0x3 << offset); 5797 break; 5798 default: 5799 break; 5800 } 5801 5802 } 5803 5804 void _phy_84756_fcmap_decode_egress_message_mode(buint16_t value, int offset, 5805 soc_port_phy_timesync_event_message_egress_mode_t *mode) 5806 { 5807 5808 switch ((value >> offset) & 0x3) { 5809 case 0x0: 5810 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE; 5811 break; 5812 case 0x1: 5813 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD; 5814 break; 5815 case 0x2: 5816 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN; 5817 break; 5818 case 0x3: 5819 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP; 5820 break; 5821 default: 5822 break; 5823 } 5824 5825 } 5826 5827 void _phy_84756_fcmap_decode_ingress_message_mode(buint16_t value, int offset, 5828 soc_port_phy_timesync_event_message_ingress_mode_t *mode) 5829 { 5830 5831 switch ((value >> offset) & 0x3) { 5832 case 0x0: 5833 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE; 5834 break; 5835 case 0x1: 5836 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD; 5837 break; 5838 case 0x2: 5839 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP; 5840 break; 5841 case 0x3: 5842 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME; 5843 break; 5844 default: 5845 break; 5846 } 5847 5848 } 5849 5850 void _phy_84756_fcmap_encode_gmode(soc_port_phy_timesync_global_mode_t mode, 5851 buint16_t *value) 5852 { 5853 5854 switch (mode) { 5855 case SOC_PORT_PHY_TIMESYNC_MODE_FREE: 5856 *value = 0x1; 5857 break; 5858 case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN: 5859 *value = 0x2; 5860 break; 5861 case SOC_PORT_PHY_TIMESYNC_MODE_CPU: 5862 *value = 0x3; 5863 break; 5864 default: 5865 break; 5866 } 5867 5868 } 5869 5870 void _phy_84756_fcmap_decode_gmode(buint16_t value, 5871 soc_port_phy_timesync_global_mode_t *mode) 5872 { 5873 5874 switch (value & 0x3) { 5875 case 0x1: 5876 *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 5877 break; 5878 case 0x2: 5879 *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN; 5880 break; 5881 case 0x3: 5882 *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU; 5883 break; 5884 default: 5885 break; 5886 } 5887 5888 } 5889 5890 5891 void _phy_84756_fcmap_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode, 5892 buint16_t *value) 5893 { 5894 5895 switch (mode) { 5896 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0: 5897 *value = 1U << 0; 5898 break; 5899 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1: 5900 *value = 1U << 1; 5901 break; 5902 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT: 5903 *value = 1U << 2; 5904 break; 5905 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU: 5906 *value = 1U << 3; 5907 break; 5908 default: 5909 break; 5910 } 5911 5912 } 5913 5914 void _phy_84756_fcmap_decode_framesync_mode(buint16_t value, 5915 soc_port_phy_timesync_framesync_mode_t *mode) 5916 { 5917 5918 switch (value & 0xf) { 5919 case 1U << 0: 5920 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0; 5921 break; 5922 case 1U << 1: 5923 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1; 5924 break; 5925 case 1U << 2: 5926 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT; 5927 break; 5928 case 1U << 3: 5929 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU; 5930 break; 5931 default: 5932 break; 5933 } 5934 5935 } 5936 5937 void _phy_84756_fcmap_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode, 5938 buint16_t *value) 5939 { 5940 5941 switch (mode) { 5942 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE: 5943 *value = 0x0; 5944 break; 5945 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME: 5946 *value = 0x1; 5947 break; 5948 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN: 5949 *value = 0x2; 5950 break; 5951 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC: 5952 *value = 0x3; 5953 break; 5954 default: 5955 break; 5956 } 5957 5958 } 5959 5960 void _phy_84756_fcmap_decode_syncout_mode(buint16_t value, 5961 soc_port_phy_timesync_syncout_mode_t *mode) 5962 { 5963 5964 switch (value & 0x3) { 5965 case 0x0: 5966 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 5967 break; 5968 case 0x1: 5969 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME; 5970 break; 5971 case 0x2: 5972 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN; 5973 break; 5974 case 0x3: 5975 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC; 5976 break; 5977 default: 5978 break; 5979 } 5980 5981 } 5982 5983 5984 int 5985 phy_84756_fcmap_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf) 5986 { 5987 buint16_t rx_control_reg = 0, tx_control_reg = 0, rx_tx_control_reg = 0, 5988 en_control_reg = 0, capture_en_reg = 0, 5989 nse_sc_8 = 0, nse_nco_3 = 0, value, mpls_control_reg = 0, temp = 0, 5990 gmode = 0, framesync_mode = 0, syncout_mode = 0, mask = 0; 5991 int i; 5992 phy_ctrl_t *pc; 5993 5994 pc = EXT_PHY_SW_STATE(unit, port); 5995 5996 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 5997 5998 if (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) { 5999 SOC_IF_ERROR_RETURN 6000 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc600, 0x8000)); 6001 SOC_IF_ERROR_RETURN 6002 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc8f0, 0x0000)); 6003 SOC_IF_ERROR_RETURN 6004 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xcd58, 0x0300)); 6005 SOC_IF_ERROR_RETURN 6006 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xcd53, 0x0000)); 6007 en_control_reg |= 3U; 6008 nse_sc_8 |= (1U << 12); 6009 } 6010 6011 /* slice enable control reg */ 6012 SOC_IF_ERROR_RETURN 6013 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc600, en_control_reg, 6014 3U)); 6015 6016 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) { 6017 capture_en_reg |= 3U; 6018 } 6019 6020 /* TXRX SOP TS CAPTURE ENABLE reg */ 6021 SOC_IF_ERROR_RETURN 6022 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc607, capture_en_reg, 3U)); 6023 6024 if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) { 6025 nse_sc_8 |= (1U << 13); 6026 } 6027 6028 /* NSE SC 8 register */ 6029 SOC_IF_ERROR_RETURN 6030 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, nse_sc_8, 6031 (1U << 12)| (1U << 13))); 6032 6033 if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) { 6034 rx_tx_control_reg |= (1U << 3); 6035 } 6036 6037 /* RX TX CONTROL register */ 6038 SOC_IF_ERROR_RETURN 6039 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc61c, rx_tx_control_reg, (1U << 3))); 6040 6041 if (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) { 6042 rx_control_reg |= (1U << 3); 6043 tx_control_reg |= (1U << 3); 6044 } 6045 6046 if (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) { 6047 rx_control_reg |= (1U << 2); 6048 tx_control_reg |= (1U << 2); 6049 } 6050 6051 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE) { 6052 rx_control_reg |= (1U << 1); 6053 tx_control_reg |= (1U << 1); 6054 } 6055 6056 if (conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE) { 6057 rx_control_reg |= (1U << 0); 6058 tx_control_reg |= (1U << 0); 6059 } 6060 6061 /* TX CONTROL register */ 6062 SOC_IF_ERROR_RETURN 6063 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc618, tx_control_reg)); 6064 6065 /* RX CONTROL register */ 6066 SOC_IF_ERROR_RETURN 6067 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61a, rx_control_reg)); 6068 6069 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 6070 nse_nco_3 &= ~(1U << 14); 6071 } else { 6072 nse_nco_3 |= (1U << 14); 6073 } 6074 6075 /* NSE NCO 3 register */ 6076 SOC_IF_ERROR_RETURN 6077 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, nse_nco_3, 6078 (1U << 14))); 6079 } 6080 6081 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 6082 /* VLAN TAG register */ 6083 SOC_IF_ERROR_RETURN 6084 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61d, conf->itpid)); 6085 } 6086 6087 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 6088 /* OUTER VLAN TAG register */ 6089 SOC_IF_ERROR_RETURN 6090 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61e, conf->otpid)); 6091 } 6092 6093 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 6094 /* INNER VLAN TAG register */ 6095 SOC_IF_ERROR_RETURN 6096 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc61f, conf->otpid2)); 6097 } 6098 6099 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 6100 SOC_IF_ERROR_RETURN 6101 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc636, conf->ts_divider & 0xfff)); 6102 } 6103 6104 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 6105 SOC_IF_ERROR_RETURN 6106 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc605, conf->rx_link_delay & 0xffff)); 6107 SOC_IF_ERROR_RETURN 6108 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc606, (conf->rx_link_delay >> 16) & 0xffff)); 6109 } 6110 6111 6112 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 6113 6114 /* TIME CODE 5 register */ 6115 SOC_IF_ERROR_RETURN 6116 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc610, (buint16_t)(conf->original_timecode.nanoseconds & 0xffff))); 6117 6118 /* TIME CODE 4 register */ 6119 SOC_IF_ERROR_RETURN 6120 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60f, (buint16_t)((conf->original_timecode.nanoseconds >> 16) & 0xffff))); 6121 6122 /* TIME CODE 3 register */ 6123 SOC_IF_ERROR_RETURN 6124 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60e, (buint16_t)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff))); 6125 6126 /* TIME CODE 2 register */ 6127 SOC_IF_ERROR_RETURN 6128 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60d, (buint16_t)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff))); 6129 6130 /* TIME CODE 1 register */ 6131 SOC_IF_ERROR_RETURN 6132 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60c, (buint16_t)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff))); 6133 } 6134 6135 mask = 0; 6136 6137 /* NSE SC 8 register */ 6138 6139 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 6140 _phy_84756_fcmap_encode_gmode(conf->gmode,&gmode); 6141 mask |= (0x3 << 14); 6142 } 6143 6144 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 6145 _phy_84756_fcmap_encode_framesync_mode(conf->framesync.mode, &framesync_mode); 6146 mask |= (0xf << 2); 6147 SOC_IF_ERROR_RETURN 6148 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63c, conf->framesync.length_threshold)); 6149 SOC_IF_ERROR_RETURN 6150 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63b, conf->framesync.event_offset)); 6151 } 6152 6153 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 6154 _phy_84756_fcmap_encode_syncout_mode(conf->syncout.mode, &syncout_mode); 6155 mask |= (0x3 << 0); 6156 6157 SOC_IF_ERROR_RETURN 6158 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc635, conf->syncout.interval & 0xffff)); 6159 SOC_IF_ERROR_RETURN 6160 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc634, 6161 ((conf->syncout.pulse_1_length & 0x3) << 14) | ((conf->syncout.interval >> 16) & 0x3fff))); 6162 SOC_IF_ERROR_RETURN 6163 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc633, 6164 ((conf->syncout.pulse_2_length & 0x1ff) << 7) | ((conf->syncout.pulse_1_length >> 2) & 0x7f))); 6165 6166 SOC_IF_ERROR_RETURN 6167 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc639, 6168 (buint16_t)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xfff0))); 6169 SOC_IF_ERROR_RETURN 6170 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc638, 6171 (buint16_t)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff))); 6172 SOC_IF_ERROR_RETURN 6173 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc637, 6174 (buint16_t)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff))); 6175 } 6176 6177 SOC_IF_ERROR_RETURN 6178 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, (gmode << 14) | (framesync_mode << 2) | (syncout_mode << 0), 6179 mask)); 6180 6181 mask = 0; 6182 6183 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 6184 /* RX TS OFFSET register */ 6185 SOC_IF_ERROR_RETURN 6186 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, (buint16_t)(conf->rx_timestamp_offset & 0xffff))); 6187 mask |= 0xf000; 6188 } 6189 6190 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 6191 mask |= 0x0fff; 6192 } 6193 6194 /* TXRX TS OFFSET register */ 6195 SOC_IF_ERROR_RETURN 6196 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, (buint16_t)(((conf->rx_timestamp_offset & 0xf0000) >> 4) | 6197 (conf->tx_timestamp_offset & 0xfff)), mask)); 6198 value = 0; 6199 mask = 0; 6200 6201 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 6202 _phy_84756_fcmap_encode_egress_message_mode(conf->tx_sync_mode, 0, &value); 6203 mask = 0x3 << 0; 6204 } 6205 6206 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 6207 _phy_84756_fcmap_encode_egress_message_mode(conf->tx_delay_request_mode, 2, &value); 6208 mask = 0x3 << 2; 6209 } 6210 6211 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 6212 _phy_84756_fcmap_encode_egress_message_mode(conf->tx_pdelay_request_mode, 4, &value); 6213 mask = 0x3 << 4; 6214 } 6215 6216 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 6217 _phy_84756_fcmap_encode_egress_message_mode(conf->tx_pdelay_response_mode, 6, &value); 6218 mask = 0x3 << 6; 6219 } 6220 6221 /* TX EVENT MESSAGE MODE SEL register */ 6222 SOC_IF_ERROR_RETURN 6223 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc601, value, 0x00ff)); 6224 6225 value = 0; 6226 mask = 0; 6227 6228 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 6229 _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value); 6230 mask = 0x3 << 0; 6231 } 6232 6233 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 6234 _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_delay_request_mode, 2, &value); 6235 mask = 0x3 << 2; 6236 } 6237 6238 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 6239 _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 4, &value); 6240 mask = 0x3 << 4; 6241 } 6242 6243 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 6244 _phy_84756_fcmap_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6, &value); 6245 mask = 0x3 << 6; 6246 } 6247 6248 /* RX EVENT MESSAGE MODE SEL register */ 6249 SOC_IF_ERROR_RETURN 6250 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc603, value, 0x00ff)); 6251 6252 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 6253 6254 /* Initial ref phase [15:0] */ 6255 SOC_IF_ERROR_RETURN 6256 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc623, (buint16_t)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff))); 6257 6258 /* Initial ref phase [31:16] */ 6259 SOC_IF_ERROR_RETURN 6260 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc622, (buint16_t)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff))); 6261 6262 /* Initial ref phase [47:32] */ 6263 SOC_IF_ERROR_RETURN 6264 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc621, (buint16_t)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff))); 6265 } 6266 6267 6268 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 6269 SOC_IF_ERROR_RETURN 6270 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc625, conf->phy_1588_dpll_ref_phase_delta & 0xffff)); 6271 SOC_IF_ERROR_RETURN 6272 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc624, (conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff)); 6273 } 6274 6275 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 6276 /* DPLL K1 */ 6277 SOC_IF_ERROR_RETURN 6278 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc626, conf->phy_1588_dpll_k1 & 0xff)); 6279 } 6280 6281 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 6282 /* DPLL K2 */ 6283 SOC_IF_ERROR_RETURN 6284 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc627, conf->phy_1588_dpll_k2 & 0xff)); 6285 } 6286 6287 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 6288 /* DPLL K3 */ 6289 SOC_IF_ERROR_RETURN 6290 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc628, conf->phy_1588_dpll_k3 & 0xff)); 6291 } 6292 6293 6294 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 6295 6296 /* MPLS controls */ 6297 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE) { 6298 mpls_control_reg |= (1U << 7) | (1U << 3); 6299 } 6300 6301 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE) { 6302 mpls_control_reg |= (1U << 6) | (1U << 2); 6303 } 6304 6305 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE) { 6306 mpls_control_reg |= (1U << 4); 6307 } 6308 6309 if (conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) { 6310 mpls_control_reg |= (1U << 5) | (1U << 1); 6311 } 6312 6313 SOC_IF_ERROR_RETURN 6314 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc651, mpls_control_reg, 6315 (1U << 7) | (1U << 3)| (1U << 6) | (1U << 2) | (1U << 4) | (1U << 5) | (1U << 1))); 6316 6317 /* special label [19:16] */ 6318 SOC_IF_ERROR_RETURN 6319 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc653, (buint16_t)((conf->mpls_control.special_label >> 16 ) & 0xf))); 6320 6321 /* special label [15:0] */ 6322 SOC_IF_ERROR_RETURN 6323 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc652, (buint16_t)(conf->mpls_control.special_label & 0xffff))); 6324 6325 for (i = 0; i < 10; i++ ) { 6326 SOC_IF_ERROR_RETURN 6327 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc654 + i, (buint16_t)(conf->mpls_control.labels[i].value & 0xffff))); 6328 SOC_IF_ERROR_RETURN 6329 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc661 + i, (buint16_t)(conf->mpls_control.labels[i].mask & 0xffff))); 6330 } 6331 6332 SOC_IF_ERROR_RETURN 6333 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc65e, (buint16_t)( 6334 ((conf->mpls_control.labels[3].value >> 4) & 0xf000) | 6335 ((conf->mpls_control.labels[2].value >> 8) & 0x0f00) | 6336 ((conf->mpls_control.labels[1].value >> 12) & 0x00f0) | 6337 ((conf->mpls_control.labels[0].value >> 16) & 0x000f)))); 6338 6339 SOC_IF_ERROR_RETURN 6340 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc65f, (buint16_t)( 6341 ((conf->mpls_control.labels[7].value >> 4) & 0xf000) | 6342 ((conf->mpls_control.labels[6].value >> 8) & 0x0f00) | 6343 ((conf->mpls_control.labels[5].value >> 12) & 0x00f0) | 6344 ((conf->mpls_control.labels[4].value >> 16) & 0x000f)))); 6345 6346 SOC_IF_ERROR_RETURN 6347 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc660, (buint16_t)( 6348 ((conf->mpls_control.labels[9].value >> 12) & 0x00f0) | 6349 ((conf->mpls_control.labels[8].value >> 16) & 0x000f)))); 6350 6351 SOC_IF_ERROR_RETURN 6352 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66b, (buint16_t)( 6353 ((conf->mpls_control.labels[3].mask >> 4) & 0xf000) | 6354 ((conf->mpls_control.labels[2].mask >> 8) & 0x0f00) | 6355 ((conf->mpls_control.labels[1].mask >> 12) & 0x00f0) | 6356 ((conf->mpls_control.labels[0].mask >> 16) & 0x000f)))); 6357 6358 SOC_IF_ERROR_RETURN 6359 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66c, (buint16_t)( 6360 ((conf->mpls_control.labels[7].mask >> 4) & 0xf000) | 6361 ((conf->mpls_control.labels[6].mask >> 8) & 0x0f00) | 6362 ((conf->mpls_control.labels[5].mask >> 12) & 0x00f0) | 6363 ((conf->mpls_control.labels[4].mask >> 16) & 0x000f)))); 6364 6365 SOC_IF_ERROR_RETURN 6366 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66d, (buint16_t)( 6367 ((conf->mpls_control.labels[9].mask >> 12) & 0x00f0) | 6368 ((conf->mpls_control.labels[8].mask >> 16) & 0x000f)))); 6369 6370 /* label flags */ 6371 temp = 0; 6372 for (i = 0; i < 8; i++ ) { 6373 temp |= conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT ? (0x2 << (i<<1)) : 0; 6374 temp |= (conf->mpls_control.labels[i].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i<<1)) : 0; 6375 } 6376 6377 SOC_IF_ERROR_RETURN 6378 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66e, temp)); 6379 6380 temp = 0; 6381 for (i = 0; i < 2; i++ ) { 6382 temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT) ? (0x2 << (i<<1)) : 0; 6383 temp |= (conf->mpls_control.labels[i + 8].flags & SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN) ? (0x1 << (i<<1)) : 0; 6384 } 6385 6386 SOC_IF_ERROR_RETURN 6387 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc66f, temp)); 6388 } 6389 6390 6391 return SOC_E_NONE; 6392 } 6393 6394 int 6395 phy_84756_fcmap_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *conf) 6396 { 6397 buint16_t rx_tx_control_reg = 0, tx_control_reg = 0, 6398 en_control_reg = 0, capture_en_reg = 0, 6399 nse_sc_8 = 0, nse_nco_3 = 0, temp1, temp2, temp3, value, mpls_control_reg; 6400 soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 6401 soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE; 6402 soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 6403 int i; 6404 phy_ctrl_t *pc; 6405 6406 pc = EXT_PHY_SW_STATE(unit, port); 6407 6408 conf->flags = 0; 6409 6410 /* NSE SC 8 register */ 6411 SOC_IF_ERROR_RETURN 6412 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8)); 6413 6414 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 6415 /* SLICE ENABLE CONTROL register */ 6416 SOC_IF_ERROR_RETURN 6417 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc600, &en_control_reg)); 6418 6419 if (en_control_reg & 1U) { 6420 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE; 6421 } 6422 6423 /* TXRX SOP TS CAPTURE ENABLE reg */ 6424 SOC_IF_ERROR_RETURN 6425 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc607, &capture_en_reg)); 6426 6427 if (capture_en_reg & 1U) { 6428 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 6429 } 6430 6431 /* NSE SC 8 register */ 6432 /* SOC_IF_ERROR_RETURN 6433 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, &nse_sc_8)); 6434 */ 6435 6436 if (nse_sc_8 & (1U << 13)) { 6437 conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE; 6438 } 6439 6440 /* RX TX CONTROL register */ 6441 SOC_IF_ERROR_RETURN 6442 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61c, &rx_tx_control_reg)); 6443 6444 if (rx_tx_control_reg & (1U << 3)) { 6445 conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE; 6446 } 6447 6448 /* TX CONTROL register */ 6449 SOC_IF_ERROR_RETURN 6450 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc618, &tx_control_reg)); 6451 6452 if (tx_control_reg & (1U << 3)) { 6453 conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE; 6454 } 6455 6456 if (tx_control_reg & (1U << 2)) { 6457 conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE; 6458 } 6459 6460 if (tx_control_reg & (1U << 1)) { 6461 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE; 6462 } 6463 6464 if (tx_control_reg & (1U << 0)) { 6465 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE; 6466 } 6467 6468 SOC_IF_ERROR_RETURN 6469 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, &nse_nco_3)); 6470 6471 if (!(nse_nco_3 & (1U << 14))) { 6472 conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 6473 } 6474 } 6475 6476 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 6477 _phy_84756_fcmap_decode_gmode((nse_sc_8 >> 14),&gmode); 6478 conf->gmode = gmode; 6479 } 6480 6481 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 6482 _phy_84756_fcmap_decode_framesync_mode((nse_sc_8 >> 2), &framesync_mode); 6483 conf->framesync.mode = framesync_mode; 6484 SOC_IF_ERROR_RETURN 6485 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63c, &temp1)); 6486 SOC_IF_ERROR_RETURN 6487 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63b, &temp2)); 6488 conf->framesync.length_threshold = temp1; 6489 conf->framesync.event_offset = temp2; 6490 } 6491 6492 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 6493 _phy_84756_fcmap_decode_syncout_mode((nse_sc_8 >> 2), &syncout_mode); 6494 conf->syncout.mode = syncout_mode; 6495 6496 SOC_IF_ERROR_RETURN 6497 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc635, &temp1)); 6498 SOC_IF_ERROR_RETURN 6499 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc634, &temp2)); 6500 SOC_IF_ERROR_RETURN 6501 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc633, &temp3)); 6502 6503 conf->syncout.pulse_1_length = ((temp3 & 0x7f) << 2) | ((temp2 >> 14) & 0x3); 6504 conf->syncout.pulse_2_length = (temp3 >> 7) & 0x1ff; 6505 conf->syncout.interval = ((temp2 & 0x3fff) << 16) | temp1; 6506 6507 SOC_IF_ERROR_RETURN 6508 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc639, &temp1)); 6509 SOC_IF_ERROR_RETURN 6510 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc638, &temp2)); 6511 SOC_IF_ERROR_RETURN 6512 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc637, &temp3)); 6513 6514 COMPILER_64_SET(conf->syncout.syncout_ts, ((buint32_t)temp3), (((buint32_t)temp2<<16)|((buint32_t)temp1))); 6515 } 6516 6517 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 6518 /* VLAN TAG register */ 6519 SOC_IF_ERROR_RETURN 6520 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61d, &conf->itpid)); 6521 } 6522 6523 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 6524 /* OUTER VLAN TAG register */ 6525 SOC_IF_ERROR_RETURN 6526 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61e, &conf->otpid)); 6527 } 6528 6529 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 6530 /* INNER VLAN TAG register */ 6531 SOC_IF_ERROR_RETURN 6532 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc61f, &conf->otpid2)); 6533 } 6534 6535 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 6536 SOC_IF_ERROR_RETURN 6537 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc636, &conf->ts_divider)); 6538 conf->ts_divider &= 0xfff; 6539 } 6540 6541 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 6542 SOC_IF_ERROR_RETURN 6543 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc605, &temp1)); 6544 SOC_IF_ERROR_RETURN 6545 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc606, &temp2)); 6546 6547 conf->rx_link_delay = ((buint32_t)temp2 << 16) | temp1; 6548 } 6549 6550 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 6551 /* TIME CODE 5 register */ 6552 SOC_IF_ERROR_RETURN 6553 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc610, &temp1)); 6554 6555 /* TIME CODE 4 register */ 6556 SOC_IF_ERROR_RETURN 6557 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60f, &temp2)); 6558 6559 conf->original_timecode.nanoseconds = ((buint32_t)temp2 << 16) | temp1; 6560 6561 /* TIME CODE 3 register */ 6562 SOC_IF_ERROR_RETURN 6563 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60e, &temp1)); 6564 6565 /* TIME CODE 2 register */ 6566 SOC_IF_ERROR_RETURN 6567 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60d, &temp2)); 6568 6569 /* TIME CODE 1 register */ 6570 SOC_IF_ERROR_RETURN 6571 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60c, &temp3)); 6572 6573 /* conf->original_timecode.seconds = ((uint64)temp3 << 32) | ((buint32_t)temp2 << 16) | temp1; */ 6574 6575 COMPILER_64_SET(conf->original_timecode.seconds, ((buint32_t)temp3), (((buint32_t)temp2<<16)|((buint32_t)temp1))); 6576 } 6577 6578 /* TXRX TS OFFSET register */ 6579 SOC_IF_ERROR_RETURN 6580 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, &temp1)); 6581 6582 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 6583 /* RX TS OFFSET register */ 6584 SOC_IF_ERROR_RETURN 6585 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, &temp2)); 6586 conf->rx_timestamp_offset = (((buint32_t)(temp1 & 0xf000)) << 4) | temp2; 6587 } 6588 6589 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 6590 conf->tx_timestamp_offset = temp1 & 0xfff; 6591 } 6592 6593 /* TX EVENT MESSAGE MODE SEL register */ 6594 SOC_IF_ERROR_RETURN 6595 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc601, &value)); 6596 6597 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 6598 _phy_84756_fcmap_decode_egress_message_mode(value, 0, &conf->tx_sync_mode); 6599 } 6600 6601 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 6602 _phy_84756_fcmap_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode); 6603 } 6604 6605 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 6606 _phy_84756_fcmap_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode); 6607 } 6608 6609 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 6610 _phy_84756_fcmap_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode); 6611 } 6612 6613 /* RX EVENT MESSAGE MODE SEL register */ 6614 SOC_IF_ERROR_RETURN 6615 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc603, &value)); 6616 6617 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 6618 _phy_84756_fcmap_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode); 6619 } 6620 6621 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 6622 _phy_84756_fcmap_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode); 6623 } 6624 6625 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 6626 _phy_84756_fcmap_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode); 6627 } 6628 6629 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 6630 _phy_84756_fcmap_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode); 6631 } 6632 6633 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 6634 /* Initial ref phase [15:0] */ 6635 SOC_IF_ERROR_RETURN 6636 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc623, &temp1)); 6637 6638 /* Initial ref phase [31:16] */ 6639 SOC_IF_ERROR_RETURN 6640 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc622, &temp2)); 6641 6642 /* Initial ref phase [47:32] */ 6643 SOC_IF_ERROR_RETURN 6644 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc621, &temp3)); 6645 6646 /* conf->phy_1588_dpll_phase_initial = ((uint64)temp3 << 32) | ((buint32_t)temp2 << 16) | temp1; */ 6647 6648 COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((buint32_t)temp3), (((buint32_t)temp2<<16)|((buint32_t)temp1))); 6649 } 6650 6651 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 6652 SOC_IF_ERROR_RETURN 6653 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc625, &temp1)); 6654 SOC_IF_ERROR_RETURN 6655 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc624, &temp2)); 6656 6657 conf->phy_1588_dpll_ref_phase_delta = ((buint32_t)temp2 << 16) | temp1; 6658 } 6659 6660 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 6661 /* DPLL K1 */ 6662 SOC_IF_ERROR_RETURN 6663 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc626, &conf->phy_1588_dpll_k1)); 6664 conf->phy_1588_dpll_k1 &= 0xff; 6665 } 6666 6667 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 6668 /* DPLL K2 */ 6669 SOC_IF_ERROR_RETURN 6670 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc627, &conf->phy_1588_dpll_k2)); 6671 conf->phy_1588_dpll_k2 &= 0xff; 6672 } 6673 6674 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 6675 /* DPLL K3 */ 6676 SOC_IF_ERROR_RETURN 6677 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc628, &conf->phy_1588_dpll_k3)); 6678 conf->phy_1588_dpll_k3 &= 0xff; 6679 } 6680 6681 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 6682 SOC_IF_ERROR_RETURN 6683 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc651, &mpls_control_reg)); 6684 6685 conf->mpls_control.flags = 0; 6686 6687 if (mpls_control_reg & (1U << 7)) { 6688 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE; 6689 } 6690 6691 if (mpls_control_reg & (1U << 6)) { 6692 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE; 6693 } 6694 6695 if (mpls_control_reg & (1U << 4)) { 6696 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE; 6697 } 6698 6699 if (mpls_control_reg & (1U << 5)) { 6700 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE; 6701 } 6702 6703 /* special label [19:16] */ 6704 SOC_IF_ERROR_RETURN 6705 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc653, &temp2)); 6706 6707 /* special label [15:0] */ 6708 SOC_IF_ERROR_RETURN 6709 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc652, &temp1)); 6710 6711 conf->mpls_control.special_label = ((buint32_t)(temp2 & 0x0f) << 16) | temp1; 6712 6713 6714 for (i = 0; i < 10; i++ ) { 6715 6716 SOC_IF_ERROR_RETURN 6717 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc654 + i, &temp1)); 6718 conf->mpls_control.labels[i].value = temp1; 6719 6720 SOC_IF_ERROR_RETURN 6721 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc661 + i, &temp1)); 6722 conf->mpls_control.labels[i].mask = temp1; 6723 } 6724 6725 /* now get [19:16] of labels */ 6726 SOC_IF_ERROR_RETURN 6727 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc65e, &temp1)); 6728 6729 conf->mpls_control.labels[0].value |= ((buint32_t)(temp1 & 0x000f) << 16); 6730 conf->mpls_control.labels[1].value |= ((buint32_t)(temp1 & 0x00f0) << 12); 6731 conf->mpls_control.labels[2].value |= ((buint32_t)(temp1 & 0x0f00) << 8); 6732 conf->mpls_control.labels[3].value |= ((buint32_t)(temp1 & 0xf000) << 4); 6733 6734 6735 SOC_IF_ERROR_RETURN 6736 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc65f, &temp1)); 6737 6738 conf->mpls_control.labels[4].value |= ((buint32_t)(temp1 & 0x000f) << 16); 6739 conf->mpls_control.labels[5].value |= ((buint32_t)(temp1 & 0x00f0) << 12); 6740 conf->mpls_control.labels[6].value |= ((buint32_t)(temp1 & 0x0f00) << 8); 6741 conf->mpls_control.labels[7].value |= ((buint32_t)(temp1 & 0xf000) << 4); 6742 6743 6744 SOC_IF_ERROR_RETURN 6745 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc660, &temp1)); 6746 6747 conf->mpls_control.labels[8].value |= ((buint32_t)(temp1 & 0x000f) << 16); 6748 conf->mpls_control.labels[9].value |= ((buint32_t)(temp1 & 0x00f0) << 12); 6749 6750 /* now get [19:16] of masks */ 6751 SOC_IF_ERROR_RETURN 6752 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66b, &temp1)); 6753 6754 conf->mpls_control.labels[0].mask |= ((buint32_t)(temp1 & 0x000f) << 16); 6755 conf->mpls_control.labels[1].mask |= ((buint32_t)(temp1 & 0x00f0) << 12); 6756 conf->mpls_control.labels[2].mask |= ((buint32_t)(temp1 & 0x0f00) << 8); 6757 conf->mpls_control.labels[3].mask |= ((buint32_t)(temp1 & 0xf000) << 4); 6758 6759 6760 SOC_IF_ERROR_RETURN 6761 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66c, &temp1)); 6762 6763 conf->mpls_control.labels[4].mask |= ((buint32_t)(temp1 & 0x000f) << 16); 6764 conf->mpls_control.labels[5].mask |= ((buint32_t)(temp1 & 0x00f0) << 12); 6765 conf->mpls_control.labels[6].mask |= ((buint32_t)(temp1 & 0x0f00) << 8); 6766 conf->mpls_control.labels[7].mask |= ((buint32_t)(temp1 & 0xf000) << 4); 6767 6768 6769 SOC_IF_ERROR_RETURN 6770 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66d, &temp1)); 6771 6772 conf->mpls_control.labels[8].mask |= ((buint32_t)(temp1 & 0x000f) << 16); 6773 conf->mpls_control.labels[9].mask |= ((buint32_t)(temp1 & 0x00f0) << 12); 6774 6775 6776 /* label flags */ 6777 SOC_IF_ERROR_RETURN 6778 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66e, &temp1)); 6779 for (i = 0; i < 8; i++ ) { 6780 conf->mpls_control.labels[i].flags |= temp1 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0; 6781 conf->mpls_control.labels[i].flags |= temp1 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0; 6782 } 6783 SOC_IF_ERROR_RETURN 6784 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc66f, &temp2)); 6785 for (i = 0; i < 2; i++ ) { 6786 conf->mpls_control.labels[i + 8].flags |= temp2 & (0x2 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_OUT : 0; 6787 conf->mpls_control.labels[i + 8].flags |= temp2 & (0x1 << (i<<1)) ? SOC_PORT_PHY_TIMESYNC_MPLS_LABEL_IN : 0; 6788 } 6789 6790 } 6791 return SOC_E_NONE; 6792 } 6793 6794 int 6795 phy_84756_fcmap_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 value) 6796 { 6797 buint16_t temp1, temp2; 6798 buint32_t value0; 6799 phy_ctrl_t *pc; 6800 6801 pc = EXT_PHY_SW_STATE(unit, port); 6802 6803 switch (type) { 6804 6805 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 6806 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 6807 return SOC_E_FAIL; 6808 6809 6810 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 6811 SOC_IF_ERROR_RETURN 6812 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc62f, (buint16_t)(COMPILER_64_LO(value) & 0xffff))); 6813 SOC_IF_ERROR_RETURN 6814 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc62e, (buint16_t)((COMPILER_64_LO(value) >> 16) & 0xffff))); 6815 break; 6816 6817 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 6818 6819 SOC_IF_ERROR_RETURN 6820 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, &temp1)); 6821 temp2 = ((temp1 | (0x3 << 14) | (0x1 << 12)) & ~(0xf << 2)) | (0x1 << 5); 6822 SOC_IF_ERROR_RETURN 6823 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, temp2)); 6824 sal_usleep(1); 6825 temp2 &= ~((0x1 << 5) | (0x1 << 12)); 6826 SOC_IF_ERROR_RETURN 6827 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, temp2)); 6828 sal_usleep(1); 6829 SOC_IF_ERROR_RETURN 6830 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63a, temp1)); 6831 break; 6832 6833 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 6834 SOC_IF_ERROR_RETURN 6835 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc632, (buint16_t)(COMPILER_64_LO(value) & 0xffff))); 6836 SOC_IF_ERROR_RETURN 6837 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc631, (buint16_t)((COMPILER_64_LO(value) >> 16) & 0xffff))); 6838 SOC_IF_ERROR_RETURN 6839 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, (buint16_t)COMPILER_64_HI(value), 0x0fff)); 6840 break; 6841 6842 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 6843 temp1 = 0; 6844 temp2 = 0; 6845 6846 value0 = COMPILER_64_LO(value); 6847 6848 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_LOAD) { 6849 temp1 |= 1U << 11; 6850 } 6851 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) { 6852 temp2 |= 1U << 11; 6853 } 6854 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) { 6855 temp1 |= 1U << 10; 6856 } 6857 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) { 6858 temp2 |= 1U << 10; 6859 } 6860 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) { 6861 temp1 |= 1U << 9; 6862 } 6863 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) { 6864 temp2 |= 1U << 9; 6865 } 6866 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) { 6867 temp1 |= 1U << 8; 6868 } 6869 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) { 6870 temp2 |= 1U << 8; 6871 } 6872 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) { 6873 temp1 |= 1U << 7; 6874 } 6875 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) { 6876 temp2 |= 1U << 7; 6877 } 6878 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) { 6879 temp1 |= 1U << 6; 6880 } 6881 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) { 6882 temp2 |= 1U << 6; 6883 } 6884 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) { 6885 temp1 |= 1U << 5; 6886 } 6887 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) { 6888 temp2 |= 1U << 5; 6889 } 6890 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) { 6891 temp1 |= 1U << 4; 6892 } 6893 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) { 6894 temp2 |= 1U << 4; 6895 } 6896 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) { 6897 temp1 |= 1U << 3; 6898 } 6899 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) { 6900 temp2 |= 1U << 3; 6901 } 6902 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) { 6903 temp1 |= 1U << 2; 6904 } 6905 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) { 6906 temp2 |= 1U << 2; 6907 } 6908 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) { 6909 temp1 |= 1U << 1; 6910 } 6911 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) { 6912 temp2 |= 1U << 1; 6913 } 6914 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) { 6915 temp1 |= 1U << 0; 6916 } 6917 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) { 6918 temp2 |= 1U << 0; 6919 } 6920 SOC_IF_ERROR_RETURN 6921 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc614, temp1)); 6922 SOC_IF_ERROR_RETURN 6923 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc615, temp2)); 6924 6925 break; 6926 6927 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 6928 temp1 = 0; 6929 6930 value0 = COMPILER_64_LO(value); 6931 6932 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) { 6933 temp1 |= 1U << 1; 6934 } 6935 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) { 6936 temp1 |= 1U << 0; 6937 } 6938 SOC_IF_ERROR_RETURN 6939 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc617, temp1)); 6940 break; 6941 6942 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 6943 temp1 = 0; 6944 6945 value0 = COMPILER_64_LO(value); 6946 6947 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) { 6948 temp1 |= 1U << 1; 6949 } 6950 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) { 6951 temp1 |= 1U << 0; 6952 } 6953 SOC_IF_ERROR_RETURN 6954 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc616, temp1)); 6955 break; 6956 6957 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 6958 value0 = COMPILER_64_LO(value); 6959 6960 SOC_IF_ERROR_RETURN 6961 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, (buint16_t)(value0 & 0x0fff), 0x0fff)); 6962 break; 6963 6964 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 6965 value0 = COMPILER_64_LO(value); 6966 6967 SOC_IF_ERROR_RETURN 6968 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, (buint16_t)(value0 & 0xffff))); 6969 SOC_IF_ERROR_RETURN 6970 (BFCMAP_MOD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, (buint16_t)((value0 >> 4) & 0xf000), 0xf000)); 6971 break; 6972 6973 default: 6974 return SOC_E_NONE; 6975 break; 6976 } 6977 6978 return SOC_E_NONE; 6979 } 6980 6981 int 6982 phy_84756_fcmap_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t type, uint64 *value) 6983 { 6984 buint16_t value0 = 0; 6985 buint16_t value1 = 0; 6986 buint16_t value2 = 0; 6987 buint16_t value3 = 0; 6988 phy_ctrl_t *pc; 6989 6990 pc = EXT_PHY_SW_STATE(unit, port); 6991 6992 switch (type) { 6993 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 6994 6995 SOC_IF_ERROR_RETURN 6996 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x4)); 6997 6998 SOC_IF_ERROR_RETURN 6999 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc647, &value0)); 7000 SOC_IF_ERROR_RETURN 7001 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc646, &value1)); 7002 SOC_IF_ERROR_RETURN 7003 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc645, &value2)); 7004 7005 SOC_IF_ERROR_RETURN 7006 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x8)); 7007 SOC_IF_ERROR_RETURN 7008 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x0)); 7009 7010 /* *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 7011 COMPILER_64_SET((*value), (((buint32_t)value3<<16)|((buint32_t)value2)), (((buint32_t)value1<<16)|((buint32_t)value0))); 7012 break; 7013 7014 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 7015 7016 SOC_IF_ERROR_RETURN 7017 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x1)); 7018 7019 SOC_IF_ERROR_RETURN 7020 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc640, &value0)); 7021 SOC_IF_ERROR_RETURN 7022 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63f, &value1)); 7023 SOC_IF_ERROR_RETURN 7024 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc63e, &value2)); 7025 7026 SOC_IF_ERROR_RETURN 7027 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x2)); 7028 SOC_IF_ERROR_RETURN 7029 (BFCMAP_WR_PHY84756_LN_DEV1_PMDr(pc, 0xc63d, 0x0)); 7030 7031 /* *value = (((uint64)value3) << 48) | (((uint64)value2) << 32) | (((uint64)value1) << 16) | ((uint64)value0); */ 7032 COMPILER_64_SET((*value), (((buint32_t)value3<<16)|((buint32_t)value2)), (((buint32_t)value1<<16)|((buint32_t)value0))); 7033 break; 7034 7035 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 7036 SOC_IF_ERROR_RETURN 7037 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc62f, &value0)); 7038 SOC_IF_ERROR_RETURN 7039 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc62e, &value1)); 7040 COMPILER_64_SET((*value), (buint32_t)value1, (buint32_t)value0); 7041 break; 7042 7043 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 7044 SOC_IF_ERROR_RETURN 7045 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc632, &value0)); 7046 SOC_IF_ERROR_RETURN 7047 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc631, &value1)); 7048 SOC_IF_ERROR_RETURN 7049 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc630, &value2)); 7050 7051 COMPILER_64_SET((*value), ((buint32_t)(value2 & 0x0fff)), (((buint32_t)value1<<16)|((buint32_t)value0))); 7052 break; 7053 7054 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 7055 7056 SOC_IF_ERROR_RETURN 7057 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0x2e, &value1)); 7058 SOC_IF_ERROR_RETURN 7059 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0x2f, &value2)); 7060 7061 value0 = 0; 7062 7063 if (value1 & (1U << 11)) { 7064 value0 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD; 7065 } 7066 if (value2 & (1U << 11)) { 7067 value0 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD; 7068 } 7069 if (value1 & (1U << 10)) { 7070 value0 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD; 7071 } 7072 if (value2 & (1U << 10)) { 7073 value0 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD; 7074 } 7075 if (value1 & (1U << 9)) { 7076 value0 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD; 7077 } 7078 if (value2 & (1U << 9)) { 7079 value0 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD; 7080 } 7081 if (value1 & (1U << 8)) { 7082 value0 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD; 7083 } 7084 if (value1 & (1U << 8)) { 7085 value0 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD; 7086 } 7087 if (value1 & (1U << 7)) { 7088 value0 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD; 7089 } 7090 if (value1 & (1U << 7)) { 7091 value0 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD; 7092 } 7093 if (value1 & (1U << 6)) { 7094 value0 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD; 7095 } 7096 if (value2 & (1U << 6)) { 7097 value0 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD; 7098 } 7099 if (value1 & (1U << 5)) { 7100 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD; 7101 } 7102 if (value2 & (1U << 5)) { 7103 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD; 7104 } 7105 if (value1 & (1U << 4)) { 7106 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD; 7107 } 7108 if (value2 & (1U << 4)) { 7109 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD; 7110 } 7111 if (value1 & (1U << 3)) { 7112 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD; 7113 } 7114 if (value2 & (1U << 3)) { 7115 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD; 7116 } 7117 if (value1 & (1U << 2)) { 7118 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD; 7119 } 7120 if (value2 & (1U << 2)) { 7121 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD; 7122 } 7123 if (value1 & (1U << 1)) { 7124 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD; 7125 } 7126 if (value2 & (1U << 1)) { 7127 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD; 7128 } 7129 if (value1 & (1U << 0)) { 7130 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD; 7131 } 7132 if (value2 & (1U << 0)) { 7133 value0 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD; 7134 } 7135 COMPILER_64_SET((*value), 0, (buint32_t)value0); 7136 7137 break; 7138 7139 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 7140 SOC_IF_ERROR_RETURN 7141 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc617, &value1)); 7142 7143 value0 = 0; 7144 7145 if (value1 & (1U << 1)) { 7146 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT; 7147 } 7148 if (value1 & (1U << 0)) { 7149 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT; 7150 } 7151 COMPILER_64_SET((*value), 0, (buint32_t)value0); 7152 7153 break; 7154 7155 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 7156 SOC_IF_ERROR_RETURN 7157 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc616, &value1)); 7158 7159 value0 = 0; 7160 7161 if (value1 & (1U << 1)) { 7162 value0 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK; 7163 } 7164 if (value1 & (1U << 0)) { 7165 value0 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK; 7166 } 7167 COMPILER_64_SET((*value), 0, (buint32_t)value0); 7168 7169 break; 7170 7171 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 7172 SOC_IF_ERROR_RETURN 7173 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, &value0)); 7174 7175 COMPILER_64_SET((*value), 0, (buint32_t)(value0 & 0x0fff)); 7176 break; 7177 7178 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 7179 SOC_IF_ERROR_RETURN 7180 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60b, &value0)); 7181 7182 SOC_IF_ERROR_RETURN 7183 (BFCMAP_RD_PHY84756_LN_DEV1_PMDr(pc, 0xc60a, &value1)); 7184 7185 COMPILER_64_SET((*value), 0, (buint32_t)(((((buint32_t)value1) << 4) & 0xf0000) | value0)); 7186 break; 7187 7188 default: 7189 return SOC_E_FAIL; 7190 } 7191 7192 return SOC_E_NONE; 7193 } 7194 7195 int 7196 bfcmap_phy84756_reg_read(phy_ctrl_t * pc, buint32_t flags, buint8_t reg_bank, 7197 buint16_t reg_addr, buint16_t *data) 7198 { 7199 int rv; 7200 buint16_t reg_data, xpmd_reg_sel = 0xffff; 7201 buint32_t cl45_reg_addr; 7202 7203 7204 rv = SOC_E_NONE; 7205 7206 if (flags & BFCMAP_PHY84756_SYS_SIDE) { 7207 /* Select System side registers */ 7208 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel); 7209 reg_data = 0x01; 7210 SOC_IF_ERROR_RETURN( 7211 BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 7212 7213 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr); 7214 rv = BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, data); 7215 7216 /* De-Select System side registers */ 7217 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel); 7218 reg_data = 0x0; 7219 SOC_IF_ERROR_RETURN( 7220 BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 7221 7222 } else { 7223 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr); 7224 rv = BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, data); 7225 } 7226 7227 return rv; 7228 } 7229 7230 int 7231 bfcmap_phy84756_reg_write(phy_ctrl_t * pc, buint32_t flags, buint8_t reg_bank, 7232 buint16_t reg_addr, buint16_t data) 7233 { 7234 int rv; 7235 buint16_t reg_data, xpmd_reg_sel = 0xffff; 7236 buint32_t cl45_reg_addr; 7237 7238 rv = SOC_E_NONE; 7239 7240 if (flags & BFCMAP_PHY84756_SYS_SIDE) { 7241 /* Select System side registers */ 7242 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel); 7243 reg_data = 0x01; 7244 SOC_IF_ERROR_RETURN( 7245 BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 7246 7247 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr); 7248 rv = BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, data); 7249 7250 /* De-Select System side registers */ 7251 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel); 7252 reg_data = 0x00; 7253 SOC_IF_ERROR_RETURN( 7254 BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 7255 } else { 7256 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr); 7257 rv = BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, data); 7258 } 7259 7260 return rv; 7261 } 7262 7263 7264 int 7265 bfcmap_phy84756_reg_modify(phy_ctrl_t * pc, buint32_t flags, buint8_t reg_bank, 7266 buint16_t reg_addr, buint16_t data, buint16_t mask) 7267 { 7268 buint16_t tmp, otmp, reg_data; 7269 buint32_t cl45_reg_addr = 0; 7270 buint16_t xpmd_reg_sel = 0xffff; 7271 7272 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 7273 if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) { 7274 return SOC_E_NONE; 7275 } 7276 #endif /* BCM_WARM_BOOT_SUPPORT */ 7277 7278 7279 if (flags & BFCMAP_PHY84756_SYS_SIDE) { 7280 /* Select System side registers */ 7281 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel); 7282 reg_data = 0x01; 7283 SOC_IF_ERROR_RETURN( 7284 BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, reg_data)); 7285 7286 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr); 7287 7288 SOC_IF_ERROR_RETURN 7289 (BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, &tmp)); 7290 7291 reg_data = data & mask; /* Mask off other bits */ 7292 otmp = tmp; 7293 tmp &= ~(mask); 7294 tmp |= reg_data; 7295 7296 if (otmp != tmp) { 7297 SOC_IF_ERROR_RETURN 7298 (BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp)); 7299 } 7300 7301 /* De-Select System side registers */ 7302 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(1, xpmd_reg_sel); 7303 data = 0x00; 7304 SOC_IF_ERROR_RETURN( 7305 BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, data)); 7306 7307 } else { 7308 cl45_reg_addr = BLMI_IO_CL45_ADDRESS(reg_bank, reg_addr); 7309 7310 SOC_IF_ERROR_RETURN 7311 (BFCMAP_PHY84756_IO_MDIO_READ(pc, cl45_reg_addr, &tmp)); 7312 7313 reg_data = data & mask; /* Mask off other bits */ 7314 otmp = tmp; 7315 tmp &= ~(mask); 7316 tmp |= reg_data; 7317 7318 if (otmp != tmp) { 7319 SOC_IF_ERROR_RETURN 7320 (BFCMAP_PHY84756_IO_MDIO_WRITE(pc, cl45_reg_addr, tmp)); 7321 } 7322 } 7323 return SOC_E_NONE; 7324 } 7325 7326 7327 7328 STATIC int 7329 phy_84756_fcmap_reg_read(int unit, soc_port_t port, uint32 flags, 7330 uint32 phy_reg_addr, uint32 *phy_data) 7331 { 7332 uint16 data16; 7333 uint16 regdata; 7334 phy_ctrl_t *pc; /* PHY software state */ 7335 int rv = SOC_E_NONE; 7336 int rd_cnt; 7337 7338 pc = EXT_PHY_SW_STATE(unit, port); 7339 7340 /* 40G reg read */ 7341 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 7342 PHY_REG_READ(PHY84756_40G, unit, port, flags, phy_reg_addr, phy_data)); 7343 7344 rd_cnt = 1; 7345 7346 if (flags & SOC_PHY_I2C_DATA8) { 7347 7348 SOC_IF_ERROR_RETURN 7349 (phy_84756_i2cdev_read(pc, 7350 SOC_PHY_I2C_DEVAD(phy_reg_addr), 7351 SOC_PHY_I2C_REGAD(phy_reg_addr), 7352 rd_cnt, 7353 (uint8 *)&data16)); 7354 *phy_data = *((uint8 *)&data16); 7355 7356 } else if (flags & SOC_PHY_I2C_DATA16) { 7357 /* This operation is generally targeted to access 16-bit device, 7358 * such as PHY IC inside the SFP. However there is no 16-bit 7359 * scratch register space on the device. Use 1.800e 7360 * for this operation. 7361 */ 7362 SOC_IF_ERROR_RETURN 7363 (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 7364 ®data)); 7365 7366 rv = _phy_84756_bsc_rw(pc, 7367 SOC_PHY_I2C_DEVAD(phy_reg_addr), 7368 PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_READ,PHY84756_I2C_16BIT), 7369 SOC_PHY_I2C_REGAD(phy_reg_addr),1, 7370 (void *)&data16,PHY84756_I2C_TEMP_RAM); 7371 7372 *phy_data = data16; 7373 7374 /* restore the ram register value */ 7375 SOC_IF_ERROR_RETURN 7376 (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 7377 regdata)); 7378 } else { 7379 SOC_IF_ERROR_RETURN 7380 (READ_PHY_REG(unit, pc, phy_reg_addr, &data16)); 7381 *phy_data = data16; 7382 } 7383 7384 return rv; 7385 7386 } 7387 7388 7389 7390 STATIC int 7391 phy_84756_fcmap_reg_write(int unit, soc_port_t port, uint32 flags, 7392 uint32 phy_reg_addr, uint32 phy_data) 7393 { 7394 uint8 data8[4]; 7395 uint16 data16[2]; 7396 uint16 regdata[2]; 7397 phy_ctrl_t *pc; /* PHY software state */ 7398 int rv = SOC_E_NONE; 7399 int wr_cnt; 7400 7401 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 7402 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 7403 return SOC_E_NONE; 7404 } 7405 #endif /* BCM_WARM_BOOT_SUPPORT */ 7406 7407 pc = EXT_PHY_SW_STATE(unit, port); 7408 7409 /* 40G reg write */ 7410 PHY84756_CALL_IF_SINGLE_PORT(unit, port, 7411 PHY_REG_WRITE(PHY84756_40G, unit, port, flags, phy_reg_addr, phy_data)); 7412 7413 7414 wr_cnt = 1; 7415 7416 if (flags & SOC_PHY_I2C_DATA8) { 7417 data8[0] = (uint8)phy_data; 7418 SOC_IF_ERROR_RETURN 7419 (phy_84756_i2cdev_write(pc, 7420 SOC_PHY_I2C_DEVAD(phy_reg_addr), 7421 SOC_PHY_I2C_REGAD(phy_reg_addr), 7422 wr_cnt, 7423 data8)); 7424 } else if (flags & SOC_PHY_I2C_DATA16) { 7425 7426 /* This operation is generally targeted to access 16-bit device, 7427 * such as PHY IC inside the SFP. However there is no 16-bit 7428 * scratch register space on the device. Use 1.800e 7429 * for this operation. 7430 */ 7431 /* save the temp ram register */ 7432 SOC_IF_ERROR_RETURN 7433 (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 7434 ®data[0])); 7435 data16[0] = phy_data; 7436 rv = _phy_84756_bsc_rw(pc, 7437 SOC_PHY_I2C_DEVAD(phy_reg_addr), 7438 PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_WRITE,PHY84756_I2C_16BIT), 7439 SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt, 7440 (void *)data16,PHY84756_I2C_TEMP_RAM); 7441 7442 /* restore the ram register value */ 7443 SOC_IF_ERROR_RETURN 7444 (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 7445 regdata[0])); 7446 } else { 7447 SOC_IF_ERROR_RETURN 7448 (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16)phy_data)); 7449 } 7450 return rv; 7451 } 7452 7453 STATIC int 7454 phy_84756_fcmap_squelch_enable(int unit, soc_port_t port, int intf, int enable, int force) 7455 { 7456 phy_ctrl_t *pc; 7457 int ix = 0; 7458 uint16 data16 = 0, mask16 = 0; 7459 uint16 speed_val = 0; 7460 7461 pc = EXT_PHY_SW_STATE(unit, port); 7462 7463 if (PHY84756_SINGLE_PORT_MODE(pc)) { 7464 mask16 = (1 << 4) | (1 << 6) | (1 << 11); 7465 data16 = enable ? mask16 : 0; 7466 7467 for (ix = 0; ix < NUM_LANES; ix++) { 7468 if (intf == PHY_DIAG_INTF_SYS) { 7469 SOC_IF_ERROR_RETURN(PHY84756_MMF(unit, pc)); 7470 SOC_IF_ERROR_RETURN 7471 (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, ix)); 7472 SOC_IF_ERROR_RETURN(PHY84756_XFI(unit, pc)); 7473 SOC_IF_ERROR_RETURN 7474 (BFCMAP_PHY84756_REG_MOD(pc, 0x1, 0x1, 0xcd18, data16, mask16)); 7475 } else { 7476 SOC_IF_ERROR_RETURN 7477 (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, ix)); 7478 SOC_IF_ERROR_RETURN 7479 (BFCMAP_PHY84756_REG_MOD(pc, 0x0, 0x1, 0xcd18, data16, mask16)); 7480 } 7481 } 7482 7483 if (intf == PHY_DIAG_INTF_SYS) { 7484 SOC_IF_ERROR_RETURN(PHY84756_MMF(unit, pc)); 7485 SOC_IF_ERROR_RETURN 7486 (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, 0)); 7487 SOC_IF_ERROR_RETURN(PHY84756_XFI(unit, pc)); 7488 } else { 7489 SOC_IF_ERROR_RETURN 7490 (BFCMAP_PHY84756_REG_WR(pc, 0x0, 0x1, 0xc702, 0)); 7491 } 7492 } else { 7493 SOC_IF_ERROR_RETURN 7494 (BFCMAP_RD_PHY84756_LN_DEV1_SPEED_LINK_DETECT_STATr(pc, &speed_val)); 7495 7496 if ((speed_val & BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_MASK) == 7497 BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_1G) { 7498 mask16 = (1 << 3) | (1 << 5); 7499 data16 = enable ? mask16 : 0; 7500 } 7501 7502 if ((speed_val & BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_MASK) == 7503 BFCMAP_PHY84756_PMD_SPEED_LD_STATr_LN_PDM_SPEED_10G) { 7504 mask16 = (1 << 4) | (1 << 5); 7505 data16 = enable ? mask16 : 0; 7506 } 7507 if (intf == PHY_DIAG_INTF_SYS) { 7508 SOC_IF_ERROR_RETURN 7509 (BFCMAP_PHY84756_REG_MOD(pc, 0x1, 0x1, 0xcd18, data16, mask16)); 7510 SOC_IF_ERROR_RETURN 7511 (BFCMAP_PHY84756_REG_MOD(pc, 0x1, 0x1, 0xcd16, 7512 force ? (1 << 3) : 0, 7513 (1 << 3))); 7514 } else { 7515 SOC_IF_ERROR_RETURN 7516 (BFCMAP_PHY84756_REG_MOD(pc, 0x0, 0x1, 0xcd18, data16, mask16)); 7517 SOC_IF_ERROR_RETURN 7518 (BFCMAP_PHY84756_REG_MOD(pc, 0x0, 0x1, 0xcd16, 7519 force ? (1 << 3) : 0, 7520 (1 << 3))); 7521 } 7522 } 7523 return SOC_E_NONE; 7524 } 7525 7526 /* 7527 * Callout interface to phy_84741_i2cdev_read(); 7528 * TBD: Extend to handle max_size > PHY84740_BSC_XFER_MAX. 7529 */ 7530 7531 STATIC int 7532 phy_84756_multi_get(int unit, soc_port_t port, uint32 flags, 7533 uint32 dev_addr, uint32 offset, int max_size, uint8 *data, int *actual_size) 7534 { 7535 7536 SOC_IF_ERROR_RETURN 7537 (PHY_MULTI_GET(PHY84756_40G, unit, port, flags, 7538 dev_addr, offset, max_size, data, actual_size)); 7539 7540 return SOC_E_NONE; 7541 } 7542 7543 /* 7544 * Variable: 7545 * phy_84756_fcmap_drv 7546 * Purpose: 7547 * Phy Driver for BCM84756 FCMAP PHY 7548 */ 7549 phy_driver_t phy_84756drv_fcmap_xe = { 7550 "84756 1G/10-Gigabit PHY-FCMAP Driver", 7551 phy_84756_fcmap_init, /* Init */ 7552 phy_null_reset, /* Reset */ 7553 phy_84756_fcmap_link_get, /* Link get */ 7554 phy_84756_fcmap_enable_set, /* Enable set */ 7555 phy_null_enable_get, /* Enable get */ 7556 phy_84756_fcmap_duplex_set, /* Duplex set */ 7557 phy_84756_fcmap_duplex_get, /* Duplex get */ 7558 phy_84756_fcmap_speed_set, /* Speed set */ 7559 phy_84756_fcmap_speed_get, /* Speed get */ 7560 phy_null_set, /* Master set */ 7561 phy_null_zero_get, /* Master get */ 7562 phy_84756_fcmap_an_set, /* ANA set */ 7563 phy_84756_fcmap_an_get, /* ANA get */ 7564 NULL, /* Local Advert set, deprecated */ 7565 NULL, /* Local Advert get, deprecated */ 7566 NULL, /* Remote Advert get, deprecated */ 7567 phy_84756_fcmap_lb_set, /* PHY loopback set */ 7568 phy_84756_fcmap_lb_get, /* PHY loopback set */ 7569 phy_84756_fcmap_interface_set, /* IO Interface set */ 7570 phy_84756_fcmap_interface_get, /* IO Interface get */ 7571 NULL, /* pd_ability, deprecated */ 7572 phy_84756_fcmap_linkup, 7573 NULL, 7574 phy_null_mdix_set, /* phy_84756_fcmap_mdix_set */ 7575 phy_null_mdix_get, /* phy_84756_fcmap_mdix_get */ 7576 phy_null_mdix_status_get, /* phy_84756_fcmap_mdix_status_get */ 7577 NULL, /* medium config setting set */ 7578 NULL, /* medium config setting get */ 7579 phy_84756_fcmap_medium_status, /* active medium */ 7580 NULL, /* phy_cable_diag */ 7581 NULL, /* phy_link_change */ 7582 phy_84756_fcmap_control_set, /* phy_control_set */ 7583 phy_84756_fcmap_control_get, /* phy_control_get */ 7584 phy_84756_fcmap_reg_read, /* phy_reg_read */ 7585 phy_84756_fcmap_reg_write, /* phy_reg_write */ 7586 NULL, /* phy_reg_modify */ 7587 NULL, /* phy_notify */ 7588 phy_84756_fcmap_probe, /* pd_probe */ 7589 phy_84756_fcmap_ability_advert_set, /* pd_ability_advert_set */ 7590 phy_84756_fcmap_ability_advert_get, /* pd_ability_advert_get */ 7591 phy_84756_fcmap_ability_remote_get, /* pd_ability_remote_get */ 7592 phy_84756_fcmap_ability_local_get, /* pd_ability_local_get */ 7593 phy_84756_fcmap_firmware_set, 7594 phy_84756_fcmap_timesync_config_set, 7595 phy_84756_fcmap_timesync_config_get, 7596 phy_84756_fcmap_timesync_control_set, 7597 phy_84756_fcmap_timesync_control_get, 7598 phy_84756_diag_ctrl, /* .pd_diag_ctrl */ 7599 NULL, /* pd_lane_control_set */ 7600 NULL, /* pd_lane_control_get */ 7601 NULL, /* pd_lane_reg_read */ 7602 NULL, /* pd_lane_reg_write */ 7603 NULL, /* pd_oam_config_set */ 7604 NULL, /* pd_oam_config_get */ 7605 NULL, /* pd_oam_control_set */ 7606 NULL, /* pd_oam_control_get */ 7607 NULL, /* pd_timesync_enhanced_capture_get */ 7608 phy_84756_multi_get, /* pd_multi_get */ 7609 phy_84756_precondition_before_probe, /* pd_precondition_before_probe */ 7610 phy_84756_fcmap_linkfault_get /* LinkFault get */ 7611 }; 7612 7613 7614 /* 7615 * 7616 * $Copyright: (c) 2005 Broadcom Corp. 7617 * All Rights Reserved.$ 7618 * 7619 * File: phy84740.c 7620 * Purpose: Phys Driver support for Broadcom 84740 40Gig 7621 * transceiver :XLAUI system side and PPI Line interface. 7622 * Note: 7623 */ 7624 7625 #include <sal/types.h> 7626 7627 #include <soc/drv.h> 7628 #include <soc/debug.h> 7629 #include <soc/error.h> 7630 #include <soc/phyreg.h> 7631 7632 #include <soc/phy.h> 7633 #include <soc/phy/phyctrl.h> 7634 #include <soc/phy/drv.h> 7635 7636 #include "phydefs.h" /* Must include before other phy related includes */ 7637 7638 #if defined(INCLUDE_PHY_84756) 7639 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 7640 #include "phyident.h" 7641 #include "phyreg.h" 7642 #include "phynull.h" 7643 #include "phyxehg.h" 7644 #include "phy84740.h" 7645 /* 7646 * SPI-ROM Program related defs 7647 */ 7648 #define SPI_CTRL_1_L 0xC000 7649 #define SPI_CTRL_1_H 0xC002 7650 #define SPI_CTRL_2_L 0xC400 7651 #define SPI_CTRL_2_H 0xC402 7652 #define SPI_TXFIFO 0xD000 7653 #define SPI_RXFIFO 0xD400 7654 #define WR_CPU_CTRL_REGS 0x11 7655 #define RD_CPU_CTRL_REGS 0xEE 7656 #define WR_CPU_CTRL_FIFO 0x66 7657 7658 /* 7659 * SPI Controller Commands(Messages). 7660 */ 7661 #define MSGTYPE_HWR 0x40 7662 #define MSGTYPE_HRD 0x80 7663 #define WRSR_OPCODE 0x01 7664 #define WR_OPCODE 0x02 7665 #define WRDI_OPCODE 0x04 7666 #define RDSR_OPCODE 0x05 7667 #define WREN_OPCODE 0x06 7668 #define WR_BLOCK_SIZE 0x40 7669 #define TOTAL_WR_BYTE 0x4000 7670 7671 #define WR_TIMEOUT 1000000 7672 7673 /* CL73 autoneg */ 7674 #define AN_ADVERT_40GCR4 (1 << 9) 7675 #define AN_ADVERT_40GKR4 (1 << 8) 7676 #define AN_ADVERT_10GKR (1 << 7) 7677 #define AN_ADVERT_1GKX (1 << 5) 7678 7679 /* PRBS */ 7680 #define PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS 0x0135 7681 #define PHY84740_40G_PRBS31 (1 << 7) 7682 #define PHY84740_40G_PRBS9 (1 << 6) 7683 #define PHY84740_40G_PRBS_TX_ENABLE (1 << 3) 7684 #define PHY84740_40G_PRBS_RX_ENABLE (1 << 0) 7685 #define PHY84740_40G_PRBS_ENABLE (PHY84740_40G_PRBS_RX_ENABLE | \ 7686 PHY84740_40G_PRBS_TX_ENABLE) 7687 7688 #define PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0 0x0140 7689 #define PHY84740_USER_PRBS_CONTROL_0_REGISTER 0xCD14 7690 #define PHY84740_USER_PRBS_TX_INVERT (1 << 4) 7691 #define PHY84740_USER_PRBS_RX_INVERT (1 << 15) 7692 #define PHY84740_USER_PRBS_INVERT (1 << 4 | 1 << 15) 7693 #define PHY84740_USER_PRBS_ENABLE (1 << 7) 7694 #define PHY84740_USER_PRBS_TYPE_MASK (0x7) 7695 7696 #define PHY84740_USER_PRBS_STATUS_0_REGISTER 0xCD15 7697 #define PHY84740_GENSIG_8071_REGISTER 0xCD16 7698 #define PHY84740_RESET_CONTROL_REGISTER 0xCD17 7699 7700 /* Module auto detect status */ 7701 #define PHY84740_MOD_AUTO_DETECT_STS_REG 0xc82b 7702 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE (1 << 15) 7703 #define PHY84740_MOD_AUTO_DETECT_STS_SFP_EN (1 << 10) 7704 #define PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL (1 << 9) 7705 #define PHY84740_MOD_AUTO_DETECT_STS_NOT_RES (1 << 0) 7706 7707 /* Optical config */ 7708 #define PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE (1 << 3) 7709 7710 /* General purpose register */ 7711 #define PHY84740_PMAD_GEN_PURPOSE_REG 0xc710 7712 #define PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN (1 << 2) 7713 7714 /* Polarity config */ 7715 #define POL_CONFIG_LANE_WIDTH 0x4 7716 #define POL_CONFIG_LANE_MASK(_ln) (0xf << ((_ln) * POL_CONFIG_LANE_WIDTH)) 7717 #define POL_CONFIG_ALL_LANES 1 7718 /* 7719 * When a port is being flexed between 40G->10G, 7720 * the polarity config syntax can be in 7721 * 40G syntax for first lane, so there is a need to parse 7722 * both 10G and 40G polarity config syntax in 10G. 7723 */ 7724 #define PHY84740_LN(_pc) ((_pc)->phy_id & 0x3) 7725 #define PHY84740_POL_MASK(_pc) POL_CONFIG_LANE_MASK(PHY84740_LN(_pc)) 7726 #define PHY84740_10G_POL_CFG_GET(_pc, _pol) \ 7727 (((_pol) == POL_CONFIG_ALL_LANES) || \ 7728 (((_pol) & PHY84740_POL_MASK(_pc)) == PHY84740_POL_MASK(_pc))) 7729 7730 7731 /* I2C related defines */ 7732 #define PHY84740_BSC_XFER_MAX 0x1F9 7733 #define PHY84740_BSC_WR_MAX 16 7734 #define PHY84740_WRITE_START_ADDR 0x8007 7735 #define PHY84740_READ_START_ADDR 0x8007 7736 #define PHY84740_WR_FREQ_400KHZ 0x0100 7737 #define PHY84740_2W_STAT 0x000C 7738 #define PHY84740_2W_STAT_IDLE 0x0000 7739 #define PHY84740_2W_STAT_COMPLETE 0x0004 7740 #define PHY84740_2W_STAT_IN_PRG 0x0008 7741 #define PHY84740_2W_STAT_FAIL 0x000C 7742 #define PHY84740_BSC_WRITE_OP 0x22 7743 #define PHY84740_BSC_READ_OP 0x2 7744 #define PHY84740_I2CDEV_WRITE 0x1 7745 #define PHY84740_I2CDEV_READ 0x0 7746 #define PHY84740_I2C_8BIT 0 7747 #define PHY84740_I2C_16BIT 1 7748 #define PHY84740_I2C_TEMP_RAM 0xE 7749 #define PHY84740_I2C_OP_TYPE(access_type,data_type) \ 7750 ((access_type) | ((data_type) << 8)) 7751 #define PHY84740_I2C_ACCESS_TYPE(op_type) ((op_type) & 0xff) 7752 #define PHY84740_I2C_DATA_TYPE(op_type) (((op_type) >> 8) & 0xff) 7753 7754 /* preemphasis control */ 7755 #define PHY84740_PREEMPH_CTRL_FORCE_SHFT 15 7756 #define PHY84740_PREEMPH_GET_FORCE(_val) \ 7757 (((_val) >> PHY84740_PREEMPH_CTRL_FORCE_SHFT) & 1) 7758 #define PHY84740_PREEMPH_CTRL_POST_TAP_SHFT 10 7759 #define PHY84740_PREEMPH_GET_POST_TAP(_val) \ 7760 (((_val) >> PHY84740_PREEMPH_CTRL_POST_TAP_SHFT) & 0x1f) 7761 #define PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT 0 7762 #define PHY84740_PREEMPH_GET_PRE_TAP(_val) \ 7763 (((_val) >> PHY84740_PREEMPH_CTRL_PRE_TAP_SHFT) & 0xf) 7764 #define PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT 4 7765 #define PHY84740_PREEMPH_GET_MAIN_TAP(_val) \ 7766 (((_val) >> PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f) 7767 #define PHY84740_PREEMPH_REG_FORCE_MASK (1 << 8) 7768 #define PHY84740_PREEMPH_REG_POST_TAP_SHFT 4 7769 #define PHY84740_PREEMPH_REG_POST_TAP_MASK (0xf << PHY84740_PREEMPH_REG_POST_TAP_SHFT) 7770 #define PHY84740_PREEMPH_REG_PRE_TAP_SHFT 0 7771 #define PHY84740_PREEMPH_REG_PRE_TAP_MASK (0x7 << PHY84740_PREEMPH_REG_PRE_TAP_SHFT) 7772 #define PHY84740_PREEMPH_REG_MAIN_TAP_SHFT 11 7773 #define PHY84740_PREEMPH_REG_MAIN_TAP_MASK (0x1f << PHY84740_PREEMPH_REG_MAIN_TAP_SHFT) 7774 #define PHY84740_PREEMPH_REG_TX_PWRDN_MASK (0x1 << 10) 7775 7776 /* Misc. */ 7777 #define PHY84740_UCODE_DEVID_ADDR 0x7FF9 7778 7779 #define PHY84740_SINGLE_PORT_MODE(_pc) \ 7780 (SOC_INFO((_pc)->unit).port_num_lanes[(_pc)->port] >= 4) 7781 #define PHY84740_EDC_MODE_MASK 0xff 7782 #define PHY84740_ID_84740 0x84740 7783 #define PHY84740_ID_84064 0x84064 7784 #define PHY84740_ID_84754 0x84754 7785 #define PHY84740_ID_84753 0x84753 7786 #define PHY84740_ID_84752 0x84752 7787 7788 /* Other variants */ 7789 #define PHY84740_ID_84780 0x84780 7790 #define PHY84740_ID_84784 0x84784 7791 #define PHY84740_ID_84758 0x84758 7792 #define PHY84740_ID_84164 0x84164 7793 #define PHY84740_ID_84168 0x84168 7794 #define PHY84740_ID_84741 0x84741 7795 #define PHY84740_ID_84744 0x84744 7796 7797 #define PHY84740_IS_QUADRA(devid)\ 7798 ((devid) == PHY84740_ID_84780 ||\ 7799 (devid) == PHY84740_ID_84784 ||\ 7800 (devid) == PHY84740_ID_84758 ||\ 7801 (devid) == PHY84740_ID_84164 ||\ 7802 (devid) == PHY84740_ID_84168 ) 7803 7804 #define PHY84740_IS_MONTREAL(devid)\ 7805 ((devid) == PHY84740_ID_84741 ||\ 7806 (devid) == PHY84740_ID_84744 ) 7807 7808 7809 /* typedefs */ 7810 typedef struct { 7811 int rx_los; 7812 int rx_los_invert; 7813 int mod_abs; 7814 int mod_abs_invert; 7815 int p2l_map[NUM_LANES]; /* index: physical lane, array element: logical lane */ 7816 int pcs_repeater; 7817 int reverse_mode; 7818 int mod_auto_detect; 7819 int mod_auto_detect_msg; 7820 int software_rx_los; 7821 int fcmap_passthrough; 7822 int single_lpmode; 7823 int skip_fw_dload; 7824 } PHY84740_DEV_DESC_t; 7825 7826 /* device field macros */ 7827 #define RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los) 7828 #define RX_LOS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->rx_los_invert) 7829 #define MOD_ABS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs) 7830 #define MOD_ABS_INVERT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_abs_invert) 7831 #define P2L_MAP(_pc,_ix) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->p2l_map[(_ix)]) 7832 #define PCS_REPEATER(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->pcs_repeater) 7833 #define REVERSE_MODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->reverse_mode) 7834 #define MOD_AUTO_DETECT(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect) 7835 #define MOD_AUTO_DETECT_MSG(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->mod_auto_detect_msg) 7836 #define SOFTWARE_RX_LOS(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->software_rx_los) 7837 #define FCMAP_PASSTHROUGH(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->fcmap_passthrough) 7838 #define SINGLE_LPMODE(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->single_lpmode) 7839 #define SKIP_FW_DLOAD(_pc) (((PHY84740_DEV_DESC_t *)((_pc) + 1))->skip_fw_dload) 7840 7841 #define PHY84740_FCS_ERROR_WAR 7842 7843 /* callback to deliever the firmware by application 7844 * return value: TRUE successfully delivered 7845 * FALSE fail to deliver 7846 * 7847 * Example: 7848 * 7849 * int user_firmware_send (int unit,int port,int flag,unsigned char **data,int *len) 7850 * { 7851 * *data = phy84740_ucode_bin; 7852 * *len = phy84740_ucode_bin_len; 7853 * return TRUE; 7854 * } 7855 * Then initialize the function pointer before the BCM port initialization: 7856 * phy_84741_uc_firmware_hook = user_firmware_send; 7857 */ 7858 int (*phy_84741_uc_firmware_hook)( 7859 int unit, /* switch number */ 7860 int port, /* port number */ 7861 int flag, /* any information need to ba passed. Not used for now*/ 7862 unsigned char **addr, /* starting address of delivered firmware */ 7863 int *len /* length of the firmware */ 7864 ) = NULL; 7865 7866 static int write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, 7867 uint16 *rddata); 7868 7869 7870 STATIC int phy_84741_speed_get(int, soc_port_t, int *); 7871 STATIC int 7872 _phy_84741_firmware_to_rom(int unit, int port, int offset, uint8 *array,int datalen); 7873 STATIC int 7874 _phy84741_mdio_lane_firmware_download(int unit, int port, phy_ctrl_t *pc, 7875 uint8 *new_fw, uint32 fw_length); 7876 7877 extern unsigned char phy84740_ucode_bin[]; 7878 extern unsigned int phy84740_ucode_bin_len; 7879 extern unsigned char phy84754_ucode_bin[]; 7880 extern unsigned int phy84754_ucode_bin_len; 7881 extern unsigned char phy84753_ucode_bin[]; 7882 extern unsigned int phy84753_ucode_bin_len; 7883 extern unsigned char phy84064_ucode_bin[]; 7884 extern unsigned int phy84064_ucode_bin_len; 7885 extern unsigned char phy84752_ucode_bin[]; 7886 extern unsigned int phy84752_ucode_bin_len; 7887 extern unsigned char phy84758_ucode_bin[]; 7888 extern unsigned int phy84758_ucode_bin_len; 7889 extern unsigned char phy84780_ucode_bin[]; 7890 extern unsigned int phy84780_ucode_bin_len; 7891 extern unsigned char phy84784_ucode_bin[]; 7892 extern unsigned int phy84784_ucode_bin_len; 7893 7894 static char *dev_name_84740 = "BCM84740"; 7895 static char *dev_name_84752 = "BCM84752"; 7896 static char *dev_name_84753 = "BCM84753"; 7897 static char *dev_name_84754 = "BCM84754"; 7898 static char *dev_name_84064 = "BCM84064"; 7899 static char *dev_name_84784 = "BCM84784"; 7900 7901 static char *dev_name_84741 = "BCM84741"; 7902 static char *dev_name_84744 = "BCM84744"; 7903 7904 STATIC int 7905 _phy_84741_config_devid(int unit,soc_port_t port,phy_ctrl_t *pc, uint32 *devid) 7906 { 7907 uint16 data16; 7908 7909 if (soc_property_port_get(unit, port,spn_PHY_84740, FALSE)) { 7910 *devid = PHY84740_ID_84740; 7911 } else if (soc_property_port_get(unit, port,spn_PHY_84752, FALSE)) { 7912 *devid = PHY84740_ID_84752; 7913 } else if (soc_property_port_get(unit, port,spn_PHY_84753, FALSE)) { 7914 *devid = PHY84740_ID_84753; 7915 } else if (soc_property_port_get(unit, port,spn_PHY_84754, FALSE)) { 7916 *devid = PHY84740_ID_84754; 7917 } else if (soc_property_port_get(unit, port,spn_PHY_84064, FALSE)) { 7918 *devid = PHY84740_ID_84064; 7919 } else { 7920 7921 /* read Other chip id */ 7922 SOC_IF_ERROR_RETURN 7923 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc802, &data16)); 7924 7925 if (PHY84740_IS_QUADRA(0x80000 | data16)) { 7926 *devid = 0x80000 | data16; 7927 } else if (PHY84740_IS_MONTREAL(0x80000 | data16)) { 7928 *devid = 0x80000 | data16; 7929 } else { 7930 *devid = 0; 7931 } 7932 } 7933 return SOC_E_NONE; 7934 } 7935 7936 STATIC int 7937 _phy_84741_single_to_quad_mode(int unit,soc_port_t port, phy_ctrl_t *pc) 7938 { 7939 int ix; 7940 uint16 saved_phy_addr; 7941 uint16 mask16; 7942 uint16 data16; 7943 uint32 devid; 7944 7945 if (pc == NULL) { 7946 pc = EXT_PHY_SW_STATE(unit, port); 7947 } 7948 7949 /* probe routine should block any invalid devids. 7950 * devids should be always valid here 7951 */ 7952 SOC_IF_ERROR_RETURN( 7953 _phy_84741_config_devid(pc->unit,pc->port, pc, &devid)); 7954 7955 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK; 7956 if (devid == PHY84740_ID_84064) { 7957 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 7958 } else { 7959 data16 = 0; 7960 } 7961 7962 /* config DAC mode/backplane mode first. This is a bcst register in single mode */ 7963 SOC_IF_ERROR_RETURN( 7964 MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 7965 data16, mask16)); 7966 7967 /* then configure quad chip mode */ 7968 SOC_IF_ERROR_RETURN( 7969 MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 7970 0, PHY84740_PMAD_CHIP_MODE_MASK)); 7971 7972 /* once this mode register is configured with quad mode, each lane is 7973 * accessable by the lane specific MDIO address 7974 */ 7975 saved_phy_addr = pc->phy_id; 7976 /* Reset all 4 lanes. Only after reset, the mode is actually switched */ 7977 for (ix = 0; ix < 4; ix++) { 7978 pc->phy_id = (saved_phy_addr & (~0x3)) + ix; 7979 SOC_IF_ERROR_RETURN 7980 (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc, 7981 MII_CTRL_RESET, MII_CTRL_RESET)); 7982 } 7983 pc->phy_id = saved_phy_addr; 7984 7985 return SOC_E_NONE; 7986 } 7987 7988 STATIC int 7989 _phy_84741_quad_to_single_mode(int unit,soc_port_t port) 7990 { 7991 int ix; 7992 uint16 saved_phy_addr; 7993 phy_ctrl_t *pc; 7994 uint16 mask16; 7995 uint16 data16; 7996 uint32 devid; 7997 7998 pc = EXT_PHY_SW_STATE(unit, port); 7999 8000 SOC_IF_ERROR_RETURN( 8001 _phy_84741_config_devid(pc->unit,pc->port, pc, &devid)); 8002 8003 saved_phy_addr = pc->phy_id; 8004 /* configure all four lanes to bcst mode */ 8005 for (ix = 0; ix < 4; ix++) { 8006 pc->phy_id = (saved_phy_addr & (~0x3)) + ix; 8007 SOC_IF_ERROR_RETURN 8008 (WRITE_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, 8009 PHY84740_PMAD_BCST_REG, 0xffff)); 8010 } 8011 pc->phy_id = saved_phy_addr; 8012 8013 /* then configure single mode */ 8014 SOC_IF_ERROR_RETURN( 8015 MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 8016 PHY84740_PMAD_MODE_40G, PHY84740_PMAD_CHIP_MODE_MASK)); 8017 8018 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK; 8019 if (devid == PHY84740_ID_84064) { 8020 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 8021 } else { 8022 data16 = 0; 8023 } 8024 8025 /* config DAC mode and backplane mode for LR4/SR4 */ 8026 SOC_IF_ERROR_RETURN( 8027 MODIFY_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 8028 data16, mask16)); 8029 8030 /* do a soft reset to switch to the configured mode 8031 * The reset should also clear the bcst register configuration 8032 */ 8033 SOC_IF_ERROR_RETURN 8034 (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc, 8035 MII_CTRL_RESET, MII_CTRL_RESET)); 8036 8037 return SOC_E_NONE; 8038 } 8039 STATIC int 8040 _phy84741_mdio_firmware_download(int unit, int port, phy_ctrl_t *pc, 8041 uint8 *new_fw, uint32 fw_length) 8042 { 8043 uint16 data16; 8044 uint16 mask16; 8045 int lane; 8046 int rv = SOC_E_NONE; 8047 8048 if (new_fw == NULL || fw_length == 0) { 8049 LOG_WARN(BSL_LS_SOC_PHY, 8050 (BSL_META_U(unit, 8051 "u=%d p=%d MDIO firmware download: invalid firmware\n"), 8052 unit, port)); 8053 return SOC_E_NONE; 8054 } 8055 8056 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8057 /* point to lane 0 */ 8058 SOC_IF_ERROR_RETURN 8059 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 8060 0)); 8061 } 8062 8063 /* clear SPA ctrl reg bit 15 and bit 13. 8064 * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM 8065 * bit 13, 0 clear download done status, 1 skip download 8066 */ 8067 mask16 = (1 << 13) | (1 << 15); 8068 data16 = 0; 8069 SOC_IF_ERROR_RETURN 8070 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 8071 data16,mask16)); 8072 8073 /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */ 8074 mask16 = 1 << 14; 8075 data16 = mask16; 8076 SOC_IF_ERROR_RETURN 8077 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 8078 data16,mask16)); 8079 8080 /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */ 8081 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8082 for (lane = 0; lane < NUM_LANES; lane++) { 8083 SOC_IF_ERROR_RETURN 8084 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane)); 8085 mask16 = 1 << 3; 8086 data16 = mask16; 8087 SOC_IF_ERROR_RETURN 8088 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, 8089 data16,mask16)); 8090 } 8091 } else { 8092 mask16 = 1 << 3; 8093 data16 = mask16; 8094 SOC_IF_ERROR_RETURN 8095 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, 8096 data16,mask16)); 8097 } 8098 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8099 /* apply bcst Reset to start download code from MDIO */ 8100 SOC_IF_ERROR_RETURN 8101 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 8102 } 8103 SOC_IF_ERROR_RETURN 8104 (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000)); 8105 8106 /* wait for 2ms for M8051 start and 5ms to initialize the RAM */ 8107 sal_usleep(10000); /* Wait for 10ms */ 8108 8109 8110 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8111 for (lane = 0; lane < NUM_LANES; lane++) { 8112 SOC_IF_ERROR_RETURN 8113 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, lane)); 8114 /* download the firmware to the specific lane */ 8115 rv = _phy84741_mdio_lane_firmware_download(unit,port,pc,new_fw,fw_length); 8116 } 8117 8118 /* point back to lane0 */ 8119 SOC_IF_ERROR_RETURN 8120 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 8121 } else { 8122 SOC_IF_ERROR_RETURN 8123 (_phy84741_mdio_lane_firmware_download(unit,port,pc,new_fw,fw_length)); 8124 } 8125 return rv; 8126 } 8127 8128 STATIC int 8129 _phy84741_mdio_lane_firmware_download(int unit, int port, phy_ctrl_t *pc, 8130 uint8 *new_fw, uint32 fw_length) 8131 8132 { 8133 uint16 data16; 8134 int j; 8135 uint16 num_words; 8136 8137 8138 /* Write Starting Address, where the Code will reside in SRAM */ 8139 data16 = 0x8000; 8140 SOC_IF_ERROR_RETURN 8141 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 8142 8143 /* make sure address word is read by the micro */ 8144 sal_udelay(10); /* Wait for 10us */ 8145 8146 /* Write SPI SRAM Count Size */ 8147 data16 = (fw_length)/2; 8148 SOC_IF_ERROR_RETURN 8149 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 8150 8151 /* make sure read by the micro */ 8152 sal_udelay(10); /* Wait for 10us */ 8153 8154 /* Fill in the SRAM */ 8155 num_words = (fw_length - 1); 8156 for (j = 0; j < num_words; j+=2) { 8157 /* Make sure the word is read by the Micro */ 8158 sal_udelay(10); 8159 8160 data16 = (new_fw[j] << 8) | new_fw[j+1]; 8161 SOC_IF_ERROR_RETURN 8162 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, 8163 data16)); 8164 } 8165 8166 /* make sure last code word is read by the micro */ 8167 sal_udelay(20); 8168 8169 /* Read Hand-Shake message (Done) from Micro */ 8170 SOC_IF_ERROR_RETURN 8171 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_M8051_MSGOUT_REG, &data16)); 8172 8173 /* Download done message */ 8174 LOG_INFO(BSL_LS_SOC_PHY, 8175 (BSL_META_U(unit, 8176 "u=%d p=%d MDIO firmware download done message: 0x%x\n"), 8177 unit, port,data16)); 8178 8179 /* Clear LASI status */ 8180 SOC_IF_ERROR_RETURN 8181 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 8182 8183 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 8184 sal_udelay(100); /* Wait for 100 usecs */ 8185 8186 SOC_IF_ERROR_RETURN 8187 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_M8051_MSGOUT_REG, &data16)); 8188 8189 /* Need to check if checksum is correct */ 8190 SOC_IF_ERROR_RETURN 8191 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16)); 8192 8193 if (data16 != 0x600D) { 8194 /* Bad CHECKSUM */ 8195 LOG_CLI((BSL_META_U(unit, 8196 "MDIO Firmware downlad failure:" 8197 "Incorrect Checksum %x\n"), data16)); 8198 return SOC_E_FAIL; 8199 } 8200 8201 /* read Rev-ID */ 8202 SOC_IF_ERROR_RETURN 8203 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16)); 8204 LOG_INFO(BSL_LS_SOC_PHY, 8205 (BSL_META_U(unit, 8206 "u=%d p=%d MDIO Firmware download revID: 0x%x\n"), 8207 unit, port,data16)); 8208 8209 return SOC_E_NONE; 8210 } 8211 8212 STATIC int 8213 _phy84741_rom_firmware_download(int unit, int port, phy_ctrl_t *pc) 8214 { 8215 int lane; 8216 uint16 data16; 8217 uint16 mask16; 8218 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8219 for (lane = 3; lane >= 0; lane--) { 8220 SOC_IF_ERROR_RETURN 8221 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8222 PHY84740_PMAD_AER_ADDR_REG, lane)); 8223 8224 /* 0xca85[3]=1, 32K download */ 8225 mask16 = (1 << 3); 8226 data16 = mask16; 8227 SOC_IF_ERROR_RETURN 8228 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA85, data16,mask16)); 8229 } 8230 8231 /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */ 8232 mask16 = (1 << 15) | (1 << 14); 8233 data16 = mask16; 8234 8235 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 8236 mask16 |= (1 << 13) | (1 << 2); 8237 SOC_IF_ERROR_RETURN 8238 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16)); 8239 8240 /* apply software reset to download code from SPI-ROM */ 8241 SOC_IF_ERROR_RETURN 8242 (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, MII_CTRL_RESET)); 8243 8244 for (lane = 0; lane < NUM_LANES; lane++) { 8245 SOC_IF_ERROR_RETURN 8246 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8247 PHY84740_PMAD_AER_ADDR_REG, lane)); 8248 /* wait for at least 50ms */ 8249 sal_usleep(100000); 8250 SOC_IF_ERROR_RETURN 8251 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 8252 LOG_INFO(BSL_LS_SOC_PHY, 8253 (BSL_META_U(unit, 8254 "u=%d p=%d lane%d SPI-ROM download done msg 0x%x\n"), 8255 unit, port,lane,data16)); 8256 SOC_IF_ERROR_RETURN 8257 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16)); 8258 SOC_IF_ERROR_RETURN 8259 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16)); 8260 } 8261 SOC_IF_ERROR_RETURN 8262 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8263 PHY84740_PMAD_AER_ADDR_REG, 0)); 8264 } else { /* single lane */ 8265 /* 0xca85[3]=1, 32K download */ 8266 mask16 = (1 << 3); 8267 data16 = mask16; 8268 SOC_IF_ERROR_RETURN 8269 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA85, data16,mask16)); 8270 8271 /* 0xc848[15]=1, SPI-ROM downloading to RAM, 0xc848[14]=1, serial boot */ 8272 mask16 = (1 << 15) | (1 << 14); 8273 data16 = mask16; 8274 SOC_IF_ERROR_RETURN 8275 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16)); 8276 8277 /* 0xc848[13]=0, SPI-ROM downloading not done, 0xc848[2]=0, spi port enable */ 8278 mask16 = (1 << 13) | (1 << 2); 8279 data16 = 0; 8280 SOC_IF_ERROR_RETURN 8281 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16)); 8282 8283 /* apply software reset to download code from SPI-ROM */ 8284 SOC_IF_ERROR_RETURN 8285 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 8286 MII_CTRL_RESET, MII_CTRL_RESET)); 8287 8288 /* wait for at least 50ms */ 8289 sal_usleep(100000); 8290 SOC_IF_ERROR_RETURN 8291 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 8292 LOG_INFO(BSL_LS_SOC_PHY, 8293 (BSL_META_U(unit, 8294 "u=%d p=%d SPI-ROM download done msg 0x%x\n"), 8295 unit, port,data16)); 8296 8297 } 8298 return SOC_E_NONE; 8299 } 8300 8301 /* 8302 * Flip the tx/rx polarities based on the configuration. 8303 */ 8304 STATIC int 8305 _phy_84741_polarity_flip_set(int unit,soc_port_t port) 8306 { 8307 int lane; 8308 phy_ctrl_t *pc; 8309 uint16 tx_pol,rx_pol; 8310 uint16 data16,mask16; 8311 8312 pc = EXT_PHY_SW_STATE(unit, port); 8313 8314 8315 tx_pol = 0; 8316 rx_pol = 0; 8317 8318 /* get the reset default value. The 84740 device has the TX polarity flipped 8319 * by default. Construct the init default value 8320 */ 8321 8322 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 8323 for (lane = 0; lane < NUM_LANES; lane++) { 8324 /* point to the each lane starting at lane0 */ 8325 SOC_IF_ERROR_RETURN 8326 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8327 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane))); 8328 8329 /* read both TX/RX polarities */ 8330 SOC_IF_ERROR_RETURN( 8331 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG, 8332 &data16)); 8333 if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) { 8334 tx_pol |= POL_CONFIG_LANE_MASK(lane); 8335 } 8336 if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) { 8337 rx_pol |= POL_CONFIG_LANE_MASK(lane); 8338 } 8339 } 8340 } else { /* quad mode */ 8341 SOC_IF_ERROR_RETURN( 8342 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG, 8343 &data16)); 8344 if (data16 & PHY84740_TX_POLARITY_FLIP_MASK) { 8345 tx_pol = POL_CONFIG_ALL_LANES; 8346 } 8347 if (data16 & PHY84740_RX_POLARITY_FLIP_MASK) { 8348 rx_pol = POL_CONFIG_ALL_LANES; 8349 } 8350 } 8351 8352 tx_pol = soc_property_port_get(unit, port, 8353 spn_PHY_PCS_TX_POLARITY_FLIP, tx_pol); 8354 rx_pol = soc_property_port_get(unit, port, 8355 spn_PHY_PCS_RX_POLARITY_FLIP, rx_pol); 8356 8357 mask16 = PHY84740_TX_POLARITY_FLIP_MASK | 8358 PHY84740_RX_POLARITY_FLIP_MASK; 8359 8360 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 8361 for (lane = 0; lane < NUM_LANES; lane++) { 8362 data16 = 0; 8363 8364 /* point to the each lane starting at lane0 */ 8365 SOC_IF_ERROR_RETURN 8366 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8367 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane))); 8368 8369 if ((tx_pol == POL_CONFIG_ALL_LANES) || 8370 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) == 8371 POL_CONFIG_LANE_MASK(lane)) ) { 8372 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 8373 } 8374 if ((rx_pol == POL_CONFIG_ALL_LANES) || 8375 ((rx_pol & POL_CONFIG_LANE_MASK(lane)) == 8376 POL_CONFIG_LANE_MASK(lane)) ) { 8377 data16 |= PHY84740_RX_POLARITY_FLIP_MASK; 8378 } 8379 SOC_IF_ERROR_RETURN( 8380 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 8381 PHY84740_DIG_CTRL_REG, 8382 data16,mask16)); 8383 } 8384 /* point back to lane0 */ 8385 SOC_IF_ERROR_RETURN 8386 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 8387 } else { /* quad-port mode */ 8388 data16 = 0; 8389 tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol); 8390 if (tx_pol) { 8391 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 8392 } 8393 rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol); 8394 if (rx_pol) { 8395 data16 |= PHY84740_RX_POLARITY_FLIP_MASK; 8396 } 8397 SOC_IF_ERROR_RETURN( 8398 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_DIG_CTRL_REG, 8399 data16,mask16)); 8400 } 8401 8402 return SOC_E_NONE; 8403 } 8404 8405 /* 8406 * Squelch enable/disable 8407 */ 8408 STATIC int _phy_84741_squelch_enable(int unit, soc_port_t port, 8409 int intf, int enable, int force) 8410 { 8411 phy_ctrl_t *pc; 8412 int ix; 8413 int repeater_mode; 8414 uint16 data16, mask16,bit,speed_val; 8415 uint32 devid; 8416 8417 pc = EXT_PHY_SW_STATE(unit, port); 8418 SOC_IF_ERROR_RETURN(_phy_84741_config_devid 8419 (pc->unit, pc->port, pc, &devid)); 8420 8421 if (PHY84740_IS_QUADRA(devid)) { 8422 if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) && 8423 PHY_DIAG_INTF_SYS != intf) { 8424 if(PHY84740_SINGLE_PORT_MODE(pc)) { 8425 mask16 = (1 << 6); 8426 data16 = enable ? mask16 : 0; 8427 for (ix = 0; ix < NUM_LANES; ix++) { 8428 SOC_IF_ERROR_RETURN 8429 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8430 PHY84740_PMAD_AER_ADDR_REG, 8431 ix)); 8432 SOC_IF_ERROR_RETURN 8433 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8434 0xcd18, data16, mask16)); 8435 SOC_IF_ERROR_RETURN 8436 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8437 0xcd16, 8438 enable ? (1 << 4) : 0, 8439 (1 << 4))); 8440 } 8441 /* point back to lane0 */ 8442 SOC_IF_ERROR_RETURN 8443 (WRITE_PHY84740_MMF_PMA_PMD_REG 8444 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 8445 8446 } else {/*quad ports**/ 8447 SOC_IF_ERROR_RETURN 8448 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 8449 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 8450 if (repeater_mode) { 8451 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 8452 (unit, pc, 0xc81f, &speed_val)); 8453 bit = (speed_val & (1 << 2)) ? 3 : 4; 8454 mask16 = (1 << bit) | (1 << 6); 8455 data16 = enable ? mask16 : 0; 8456 SOC_IF_ERROR_RETURN 8457 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8458 0xcd18, data16, mask16)); 8459 } 8460 } 8461 } else { /*system side or not reverse mode*/ 8462 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8463 mask16 = (1 << 6) | (1 << 11); 8464 data16 = enable ? mask16 : 0; 8465 for (ix = 0; ix < NUM_LANES; ix++) { 8466 SOC_IF_ERROR_RETURN 8467 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8468 PHY84740_PMAD_AER_ADDR_REG, 8469 ix)); 8470 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 8471 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, 8472 pc, 8473 0xcd18, 8474 data16, 8475 mask16)); 8476 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 8477 } 8478 /* point back to lane0 */ 8479 SOC_IF_ERROR_RETURN 8480 (WRITE_PHY84740_MMF_PMA_PMD_REG 8481 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 8482 } else {/* quad port*/ 8483 SOC_IF_ERROR_RETURN 8484 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 8485 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 8486 if (repeater_mode) { 8487 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 8488 (unit, pc, 0xc81f, &speed_val)); 8489 bit = (speed_val & (1 << 2)) ? 3 : 4; 8490 mask16 = (1 << bit) | (1 << 6); 8491 data16 = enable ? mask16 : 0; 8492 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 8493 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc, 8494 0xcd18, 8495 data16, 8496 mask16)); 8497 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 8498 } 8499 } 8500 } 8501 } else { 8502 if ((PHY_DIAG_INTF_LINE == intf || REVERSE_MODE(pc)) && 8503 PHY_DIAG_INTF_SYS != intf) { 8504 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8505 8506 /* Note: following line needed as workaround */ 8507 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 8508 8509 mask16 = (1 << 6); 8510 data16 = enable ? mask16 : 0; 8511 8512 for (ix = 0; ix < NUM_LANES; ix++) { 8513 SOC_IF_ERROR_RETURN 8514 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8515 PHY84740_PMAD_AER_ADDR_REG, 8516 ix)); 8517 8518 SOC_IF_ERROR_RETURN 8519 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8520 0xcd18, data16, mask16)); 8521 8522 SOC_IF_ERROR_RETURN 8523 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8524 0xcd16, 8525 enable ? 8526 (force ?((1 << 3)|(1 << 4)) 8527 :(1 << 4)) 8528 : 0, 8529 (1 << 3)|(1 << 4))); 8530 } 8531 /* point back to lane0 */ 8532 SOC_IF_ERROR_RETURN 8533 (WRITE_PHY84740_MMF_PMA_PMD_REG 8534 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 8535 } else { 8536 SOC_IF_ERROR_RETURN 8537 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 8538 8539 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 8540 if (repeater_mode) { 8541 mask16 = (1 << 4) | (1 << 6); 8542 data16 = enable ? mask16 : 0; 8543 8544 SOC_IF_ERROR_RETURN 8545 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8546 0xcd18, data16, mask16)); 8547 } 8548 } 8549 8550 } else { /*system side or not reverse mode*/ 8551 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8552 8553 mask16 = (1 << 6) | (1 << 11); 8554 data16 = enable ? mask16 : 0; 8555 8556 for (ix = 0; ix < NUM_LANES; ix++) { 8557 SOC_IF_ERROR_RETURN 8558 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 8559 PHY84740_PMAD_AER_ADDR_REG, 8560 ix)); 8561 8562 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 8563 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, 8564 pc, 8565 0xcd18, 8566 data16, 8567 mask16)); 8568 8569 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 8570 } 8571 /* point back to lane0 */ 8572 SOC_IF_ERROR_RETURN 8573 (WRITE_PHY84740_MMF_PMA_PMD_REG 8574 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 8575 } else { 8576 SOC_IF_ERROR_RETURN 8577 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 8578 8579 repeater_mode = ((data16 & 0x6) == 0x6) ? TRUE : FALSE; 8580 if (repeater_mode) { 8581 mask16 = (1 << 4) | (1 << 6); 8582 data16 = enable ? mask16 : 0; 8583 8584 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 8585 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_XFI_PMA_PMD_REG(unit, pc, 8586 0xcd18, 8587 data16, 8588 mask16)); 8589 8590 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 8591 } 8592 } 8593 } 8594 } 8595 return SOC_E_NONE; 8596 } 8597 8598 8599 STATIC int 8600 _phy_84741_firmware_is_downloaded(int unit, soc_port_t port, int ext_rom) 8601 { 8602 int rv = 0; 8603 uint16 data16; 8604 phy_ctrl_t *pc; 8605 8606 pc = EXT_PHY_SW_STATE(unit, port); 8607 8608 if (soc_property_port_get(unit, port,spn_PHY_FORCE_FIRMWARE_LOAD, TRUE)) { 8609 return 0; 8610 } 8611 8612 /* 8613 * To determine whether the firmware has been downloaded, it must 8614 * pass the following: 8615 * 1. firmware is in RAM: 1.c848.13==1 8616 * 2. expected checksum: 1.ca1c==600d 8617 * 3. version is non-zero: 1.ca1a!=0 8618 */ 8619 8620 /* 1. Firmware download status */ 8621 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, &data16); 8622 if (rv != SOC_E_NONE) { 8623 return 0; 8624 } 8625 if (ext_rom){ 8626 if ((data16 & 0xa000) != 0xa000) { 8627 return 0; 8628 } 8629 } else if ((data16 & 0x6000) != 0x6000) { 8630 return 0; 8631 } 8632 LOG_INFO(BSL_LS_SOC_PHY, 8633 (BSL_META_U(unit, 8634 "84741 FW download status=%x: u=%d p=%d\n"), data16, unit, port)); 8635 8636 /* 2. Expected checksum */ 8637 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16); 8638 if ((rv != SOC_E_NONE) || (data16 != 0x600D)) { 8639 return 0; 8640 } 8641 LOG_INFO(BSL_LS_SOC_PHY, 8642 (BSL_META_U(unit, 8643 "84741 FW checksum=%x: u=%d p=%d\n"), data16, unit, port)); 8644 8645 /* 3. non-zero version */ 8646 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16); 8647 if ((rv != SOC_E_NONE) || (data16 == 0)) { 8648 return 0; 8649 } 8650 LOG_INFO(BSL_LS_SOC_PHY, 8651 (BSL_META_U(unit, 8652 "84741 FW version=%x: u=%d p=%d\n"), data16, unit, port)); 8653 8654 return 1; 8655 } 8656 8657 /* Function: 8658 * phy_84741_init 8659 * Purpose: 8660 * Initialize 84740 phys 8661 * Parameters: 8662 * unit - StrataSwitch unit #. 8663 * port - StrataSwitch port #. 8664 * Returns: 8665 * SOC_E_NONE 8666 */ 8667 8668 STATIC int 8669 phy_84741_init(int unit, soc_port_t port) 8670 { 8671 soc_timeout_t to; 8672 int rv = SOC_E_NONE; 8673 uint16 data16,ucode_ver; 8674 uint16 chip_mode; 8675 phy_ctrl_t *pc; 8676 int ix; 8677 uint32 phy_ext_rom_boot = 0; 8678 uint16 mask16; 8679 uint32 devid; 8680 unsigned char *pdata; 8681 int data_len; 8682 uint32 l2p, l2p_map; 8683 8684 pc = EXT_PHY_SW_STATE(unit, port); 8685 LOG_INFO(BSL_LS_SOC_PHY, 8686 (BSL_META_U(unit, 8687 "PHY84740 init: u=%d p=%d desc=0x%x\n"), 8688 unit, port,PTR_TO_INT(pc + 1))); 8689 SOC_IF_ERROR_RETURN( 8690 _phy_84741_config_devid(pc->unit,pc->port, pc, &devid)); 8691 8692 /* initialize default p2l map */ 8693 for (ix = 0; ix < NUM_LANES; ix++) { 8694 P2L_MAP(pc,ix) = ix; 8695 } 8696 8697 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) || 8698 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 8699 PCS_REPEATER(pc) = FALSE; 8700 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8701 /* Always set repeater flag in single port mode */ 8702 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER); 8703 } else { 8704 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45); 8705 } 8706 8707 FCMAP_PASSTHROUGH(pc) = soc_property_port_get(unit, port, spn_PHY_FCMAP_PASSTHROUGH, 0); 8708 8709 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) { 8710 LOG_INFO(BSL_LS_SOC_PHY, 8711 (BSL_META_U(unit, 8712 "PHY84740 init pass1: u=%d p=%d\n"), unit, port)); 8713 8714 /* check if to use the bcst mode for RAM uC download */ 8715 phy_ext_rom_boot = soc_property_port_get(unit, port, 8716 spn_PHY_EXT_ROM_BOOT, 1); 8717 8718 SKIP_FW_DLOAD(pc) = _phy_84741_firmware_is_downloaded(unit, port, 8719 phy_ext_rom_boot); 8720 8721 /* 8722 if (SKIP_FW_DLOAD(pc)) { 8723 LOG_CLI((BSL_META_U(unit, 8724 "u=%d, p=%d skipping firmware download\n"), 8725 unit, port)); 8726 } 8727 */ 8728 8729 if (!phy_ext_rom_boot) { 8730 if (!SKIP_FW_DLOAD(pc)) { 8731 pc->flags |= PHYCTRL_MDIO_BCST; 8732 } 8733 } else { 8734 /* 8735 * To enable firmware to be downloaded to ports which are out-of-order, 8736 * 1.c848.13 must be set on all ports first. The first port within the core that 8737 * has 1.c848.13 clear has control over the SPI-ROM, so later when the 8738 * firmware is actually being downloaded, that port will first clear 1.c848.13 8739 * and obtain control over the SPI-ROM. 8740 */ 8741 data16 = (1 << 15) | (1 << 14) | (1 << 13); 8742 mask16 = data16; 8743 SOC_IF_ERROR_RETURN 8744 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc848, data16, mask16)); 8745 } 8746 8747 /* configure to quad-port mode to prepare for the broadcast mode */ 8748 SOC_IF_ERROR_RETURN( 8749 READ_PHY84740_MMF_PMA_PMD_REG(pc->unit, pc, 8750 PHY84740_PMAD_CHIP_MODE_REG,&chip_mode)); 8751 8752 /* switch to quad-port mode if not already in */ 8753 if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == PHY84740_PMAD_MODE_40G) { 8754 SOC_IF_ERROR_RETURN( 8755 _phy_84741_single_to_quad_mode(pc->unit,pc->port,pc)); 8756 LOG_INFO(BSL_LS_SOC_PHY, 8757 (BSL_META_U(unit, 8758 "PHY84740 init pass1 mode S to Q switch: u=%d p=%d\n"), unit, port)); 8759 } 8760 8761 /* indicate second pass of init is needed */ 8762 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 8763 return SOC_E_NONE; 8764 } 8765 } 8766 8767 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 8768 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 8769 LOG_INFO(BSL_LS_SOC_PHY, 8770 (BSL_META_U(unit, 8771 "PHY84740 init pass2: u=%d p=%d\n"), unit, port)); 8772 SOC_IF_ERROR_RETURN( 8773 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&chip_mode)); 8774 8775 /* check the current chip mode */ 8776 if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == PHY84740_PMAD_MODE_40G) { 8777 /* 8778 * switch to configured mode(quad mode) if current chip mode is single mode 8779 * In quad mode, the supported speed modes are 10G and 1G forced, 1G autoneg. 8780 * However 1G currently is only working with QSFP fiber cable not Cu cable. 8781 */ 8782 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { 8783 LOG_WARN(BSL_LS_SOC_PHY, 8784 (BSL_META_U(unit, 8785 "PHY84740 init pass2 mode switch: u=%d p=%d\n"), unit, port)); 8786 SOC_IF_ERROR_RETURN( 8787 _phy_84741_single_to_quad_mode(unit,port,NULL)); 8788 8789 } else { /* configured mode is single mode */ 8790 /* if configured mode(single mode) matches current chip mode. Make sure 8791 * it is SR4/LR4. If a optical module is plugged in when the device is 8792 * configured in CR4 mode, it may damage the optical module because of big 8793 * voltage sway in CR4 mode. For now, the device is configured in 8794 * LR4/SR4 mode by default. If a QSFP Cu is used, EDC mode should be set to 8795 * 0x55. In case there is a need to go to CR4 mode, user can use interface 8796 * set function to change to the CR4 mode. In this mode, both autoneg and 8797 * forced 40G speed is supported. 8798 */ 8799 /* config DAC mode and backplane mode for LR4/SR4 */ 8800 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK; 8801 if (devid == PHY84740_ID_84064) { 8802 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 8803 } else { 8804 data16 = 0; 8805 } 8806 8807 SOC_IF_ERROR_RETURN( 8808 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 8809 data16, mask16)); 8810 8811 SOC_IF_ERROR_RETURN 8812 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 8813 MII_CTRL_RESET, MII_CTRL_RESET)); 8814 } 8815 } else { /* current chip mode is quad mode */ 8816 /* switch to configured mode(single mode) if current chip mode is quad mode */ 8817 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8818 8819 SOC_IF_ERROR_RETURN( 8820 _phy_84741_quad_to_single_mode(unit,port)); 8821 } else { /* configured mode is quad mode */ 8822 8823 /* chip already in configured mode. config DAC/backplane mode */ 8824 mask16 = PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK; 8825 if (devid == PHY84740_ID_84064) { 8826 data16 = PHY84740_PMAD_BKPLANE_MODE_MASK; 8827 } else { 8828 data16 = 0; 8829 } 8830 8831 SOC_IF_ERROR_RETURN( 8832 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 8833 data16, mask16)); 8834 } 8835 } 8836 8837 /* should be done before reset */ 8838 l2p = soc_property_port_get(unit, port,spn_PHY_LANE0_L2P_MAP, 0); 8839 if (l2p >= NUM_LANES) { 8840 LOG_ERROR(BSL_LS_SOC_PHY, 8841 (BSL_META_U(unit, 8842 "PHY84740 invalid L2P lane configuration: u=%d p=%d, l2p=%d\n"), 8843 unit, port,l2p)); 8844 return SOC_E_PARAM; 8845 } 8846 8847 SINGLE_LPMODE(pc) = soc_property_port_get(unit, port, spn_PHY_TX_DISABLE_NO_LPMODE, 0); 8848 8849 /* 8850 * 1.c701 8851 * - Quebec devices specifies the physical channel number designated as 8852 * logical channel 0 8853 * - Quadra devices specifies the mapping of all physical channels to 8854 * logical channels 8855 */ 8856 data16 = 0; 8857 l2p_map = 0; 8858 if (PHY84740_IS_QUADRA(devid)) { 8859 for (ix = 0; ix < NUM_LANES; ix++) { 8860 l2p_map |= ((l2p + ix) % NUM_LANES) << (ix * 4); 8861 } 8862 data16 = l2p_map; 8863 mask16 = 0xffff; 8864 for (ix = 0; ix < NUM_LANES; ix++) { 8865 P2L_MAP(pc,((l2p_map >> (ix * 4)) & 0xf)) = ix; 8866 } 8867 } else { 8868 data16 = l2p; 8869 mask16 = PHY84740_L2P_PHYSICAL_LANE_MASK; 8870 8871 /* physical to logical lane map, index is physical lane */ 8872 for (ix = 0; ix < NUM_LANES; ix++) { 8873 P2L_MAP(pc,(l2p + ix) % NUM_LANES) = ix; 8874 } 8875 } 8876 8877 SOC_IF_ERROR_RETURN( 8878 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_LANE0_L2P_REG, 8879 data16, mask16)); 8880 8881 /* do a soft reset */ 8882 SOC_IF_ERROR_RETURN 8883 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 8884 MII_CTRL_RESET, MII_CTRL_RESET)); 8885 8886 /* Wait for device to come out of reset */ 8887 soc_timeout_init(&to, 10000, 0); 8888 while (!soc_timeout_check(&to)) { 8889 rv = READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &data16); 8890 if (((data16 & MII_CTRL_RESET) == 0) || 8891 SOC_FAILURE(rv)) { 8892 break; 8893 } 8894 } 8895 if (((data16 & MII_CTRL_RESET) != 0) || SOC_FAILURE(rv)) { 8896 LOG_WARN(BSL_LS_SOC_PHY, 8897 (BSL_META_U(unit, 8898 "PHY84740 reset failed: u=%d p=%d\n"), 8899 unit, port)); 8900 return SOC_E_FAIL; 8901 } 8902 8903 if (pc->flags & PHYCTRL_UCODE_BCST_DONE) { 8904 /* ucode is already loaded thru bcst */ 8905 8906 /* Not clearing PHYCTRL_UCODE_BCST_DONE --> 8907 This bit can be checked again, in case init is called again, 8908 to avoid an additional firmware download */ 8909 8910 phy_ext_rom_boot = 0; 8911 } else { 8912 phy_ext_rom_boot = soc_property_port_get(unit, port, 8913 spn_PHY_EXT_ROM_BOOT, 1); 8914 8915 if (SKIP_FW_DLOAD(pc)) { 8916 /* do nothing */ 8917 } else 8918 if (phy_ext_rom_boot) { 8919 SOC_IF_ERROR_RETURN 8920 (_phy84741_rom_firmware_download(unit, port, pc)); 8921 } else { /* MDIO download to RAM */ 8922 /* check if the firmware is delivered by user */ 8923 if (phy_84741_uc_firmware_hook && 8924 phy_84741_uc_firmware_hook(unit,port,devid,&pdata,&data_len) ) { 8925 SOC_IF_ERROR_RETURN 8926 (_phy84741_mdio_firmware_download(unit,port,pc,pdata,data_len)); 8927 } else if (PHY84740_IS_MONTREAL(devid)) { 8928 /* do nothing since bcst mdio download was skipped */ 8929 } else { 8930 if (devid == PHY84740_ID_84754) { 8931 SOC_IF_ERROR_RETURN 8932 (_phy84741_mdio_firmware_download(unit,port,pc,phy84754_ucode_bin, 8933 phy84754_ucode_bin_len)); 8934 } else if (devid == PHY84740_ID_84740) { 8935 /* do not use 84753/84754 ucode for 84740. There is a voltage differece */ 8936 SOC_IF_ERROR_RETURN 8937 (_phy84741_mdio_firmware_download(unit,port,pc,phy84740_ucode_bin, 8938 phy84740_ucode_bin_len)); 8939 } else if (devid == PHY84740_ID_84064) { 8940 SOC_IF_ERROR_RETURN 8941 (_phy84741_mdio_firmware_download(unit,port,pc,phy84064_ucode_bin, 8942 phy84064_ucode_bin_len)); 8943 } else if (devid == PHY84740_ID_84753) { 8944 SOC_IF_ERROR_RETURN 8945 (_phy84741_mdio_firmware_download(unit,port,pc,phy84753_ucode_bin, 8946 phy84753_ucode_bin_len)); 8947 } else if (devid == PHY84740_ID_84752) { 8948 SOC_IF_ERROR_RETURN 8949 (_phy84741_mdio_firmware_download(unit,port,pc,phy84752_ucode_bin, 8950 phy84752_ucode_bin_len)); 8951 } else if (devid == PHY84740_ID_84784) { 8952 SOC_IF_ERROR_RETURN 8953 (_phy84741_mdio_firmware_download(unit,port,pc,phy84784_ucode_bin, 8954 phy84784_ucode_bin_len)); 8955 } else if (devid == PHY84740_ID_84780) { 8956 SOC_IF_ERROR_RETURN 8957 (_phy84741_mdio_firmware_download(unit,port,pc,phy84780_ucode_bin, 8958 phy84780_ucode_bin_len)); 8959 } else if (PHY84740_IS_QUADRA(devid)) { 8960 SOC_IF_ERROR_RETURN 8961 (_phy84741_mdio_firmware_download(unit,port,pc,phy84758_ucode_bin, 8962 phy84758_ucode_bin_len)); 8963 } else { 8964 LOG_WARN(BSL_LS_SOC_PHY, 8965 (BSL_META_U(unit, 8966 "84740: p=%d unknown device id: 0x%x\n"), 8967 port,devid)); 8968 } 8969 } 8970 } 8971 } 8972 8973 /* reset will restart the uC. wait a few ms for checksum to be written*/ 8974 sal_udelay(42000); 8975 8976 /* read the microcode revision */ 8977 SOC_IF_ERROR_RETURN 8978 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver)); 8979 8980 /* check the completion of the microcode download. */ 8981 if (PHY84740_SINGLE_PORT_MODE(pc)) { 8982 uint16 cksum[4]; 8983 int ret = SOC_E_NONE; 8984 8985 for (ix = 0; ix < NUM_LANES; ix++) { 8986 SOC_IF_ERROR_RETURN 8987 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, ix)); 8988 8989 /* check the completion of the microcode download. */ 8990 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &cksum[ix]); 8991 if (cksum[ix] != 0x600D || SOC_FAILURE(rv)) { 8992 ret = SOC_E_FAIL; 8993 } 8994 } 8995 if (ret == SOC_E_FAIL) { 8996 LOG_WARN(BSL_LS_SOC_PHY, 8997 (BSL_META_U(unit, 8998 "84740: p=%d SPI-ROM load: Bad Checksum lane 0,1,2,3 (0x%x)," 8999 "(0x%x), (0x%x), (0x%x)\n"), 9000 port, cksum[0],cksum[1],cksum[2],cksum[3])); 9001 return SOC_E_FAIL; 9002 } 9003 } else { 9004 rv = READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16); 9005 if (data16 != 0x600D || SOC_FAILURE(rv)) { 9006 LOG_WARN(BSL_LS_SOC_PHY, 9007 (BSL_META_U(unit, 9008 "84740: p=%d SPI-ROM load: Bad Checksum (0x%x)\n"), 9009 port, data16)); 9010 return SOC_E_FAIL; 9011 } 9012 } 9013 9014 LOG_WARN(BSL_LS_SOC_PHY, 9015 (BSL_META_U(unit, 9016 "%x init u=%d port=%d rom code ver. 0x%x: %s boot\n"), devid, 9017 unit, port, ucode_ver,phy_ext_rom_boot? "SPI-ROM":"MDIO_TO_RAM")); 9018 9019 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { 9020 /* clear 1.0xcd17 to enable the PCS */ 9021 SOC_IF_ERROR_RETURN( 9022 WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 9023 PHY84740_RESET_CONTROL_REGISTER, 0)); 9024 } else { 9025 /* 40G no autoneg support */ 9026 /* EDC mode for SR4/LR4 0x44, done in ucode, no need to set for CR4 */ 9027 /* disable cl72 */ 9028 SOC_IF_ERROR_RETURN 9029 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0x0000)); 9030 /* disable AN */ 9031 SOC_IF_ERROR_RETURN 9032 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0x0)); 9033 } 9034 9035 REVERSE_MODE(pc) = soc_property_port_get(unit, port, spn_PORT_PHY_MODE_REVERSE, 0); 9036 9037 9038 mask16 = PHY84740_RXLOS_OVERRIDE_MASK | 9039 PHY84740_MOD_ABS_OVERRIDE_MASK; 9040 data16 = 0; 9041 9042 RX_LOS(pc) = soc_property_port_get(unit, port,spn_PHY_RX_LOS, 0); 9043 MOD_ABS(pc) = soc_property_port_get(unit, port,spn_PHY_MOD_ABS, 0); 9044 RX_LOS_INVERT(pc) = soc_property_port_get(unit, port,spn_PHY_RX_LOS_INVERT, 0); 9045 MOD_ABS_INVERT(pc) = soc_property_port_get(unit, port,spn_PHY_MOD_ABS_INVERT, 0); 9046 MOD_AUTO_DETECT(pc) = soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0); 9047 9048 /* default: override RX_LOS signalling */ 9049 if (!RX_LOS(pc)) { 9050 data16 |= PHY84740_RXLOS_OVERRIDE_MASK; 9051 } 9052 /* default: override MOD_ABS signalling */ 9053 if (!MOD_ABS(pc)) { 9054 data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK; 9055 } 9056 9057 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9058 for (ix = 0; ix < NUM_LANES; ix++) { 9059 SOC_IF_ERROR_RETURN 9060 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 9061 PHY84740_PMAD_AER_ADDR_REG, ix)); 9062 SOC_IF_ERROR_RETURN 9063 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 9064 PHY84740_PMAD_OPTICAL_CFG_REG, 9065 data16, mask16)); 9066 } 9067 } else { 9068 SOC_IF_ERROR_RETURN 9069 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 9070 PHY84740_PMAD_OPTICAL_CFG_REG, 9071 data16, mask16)); 9072 } 9073 9074 mask16 = PHY84740_RXLOS_LVL_MASK | PHY84740_MOD_ABS_LVL_MASK; 9075 data16 = 0; 9076 /* default: RX_LOS level high */ 9077 if (!RX_LOS_INVERT(pc)) { 9078 data16 |= PHY84740_RXLOS_LVL_MASK; 9079 } 9080 /* default: MOD_ABS level high */ 9081 if (!MOD_ABS_INVERT(pc)) { 9082 data16 |= PHY84740_MOD_ABS_LVL_MASK; 9083 } 9084 9085 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9086 for (ix = 0; ix < NUM_LANES; ix++) { 9087 SOC_IF_ERROR_RETURN 9088 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 9089 PHY84740_PMAD_AER_ADDR_REG, ix)); 9090 SOC_IF_ERROR_RETURN 9091 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 9092 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 9093 data16, mask16)); 9094 } 9095 /* point back to lane0 */ 9096 SOC_IF_ERROR_RETURN 9097 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 9098 } else { 9099 SOC_IF_ERROR_RETURN 9100 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 9101 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 9102 data16, mask16)); 9103 } 9104 9105 if (soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 0)) { 9106 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 9107 /* put device in repeat mode. Single port is already in repeat mode */ 9108 SOC_IF_ERROR_RETURN( 9109 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xc806, 0x6,0x6)); 9110 /* in repeater mode, 84740 will use autoneg from internal serdes. But 9111 * 84064 will still use cl73/cl72 from ifself. 9112 */ 9113 if (devid != PHY84740_ID_84064) { 9114 PCS_REPEATER(pc) = TRUE; 9115 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER); 9116 } 9117 } 9118 } 9119 9120 SOC_IF_ERROR_RETURN(_phy_84741_squelch_enable(unit, port, -1, TRUE, FALSE)); 9121 9122 if (FCMAP_PASSTHROUGH(pc)) { 9123 if ((!PHY84740_SINGLE_PORT_MODE(pc)) && (PHY84740_IS_QUADRA(devid))) { 9124 /* put device in the fcmap passthrough mode. */ 9125 SOC_IF_ERROR_RETURN( 9126 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 0x3, 0x3)); 9127 SOC_IF_ERROR_RETURN( 9128 MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, MII_CTRL_RESET, MII_CTRL_RESET)); 9129 } else { 9130 FCMAP_PASSTHROUGH(pc) = FALSE; 9131 } 9132 } 9133 9134 /* Polarity configuration */ 9135 SOC_IF_ERROR_RETURN 9136 (_phy_84741_polarity_flip_set(unit,port)); 9137 9138 9139 /* check if module auto detect enabled */ 9140 if (MOD_AUTO_DETECT(pc)) { 9141 if ((ucode_ver & 0x0fff) < 0x105) { 9142 LOG_ERROR(BSL_LS_SOC_PHY, 9143 (BSL_META_U(unit, 9144 "84740 module auto detect requires ucode ver 0x105 or newer: " 9145 "u=%d p%d\n"), unit, port)); 9146 } else if (!(RX_LOS(pc) && MOD_ABS(pc))) { 9147 MOD_AUTO_DETECT(pc) = 0; 9148 LOG_ERROR(BSL_LS_SOC_PHY, 9149 (BSL_META_U(unit, 9150 "84740 module auto detect requires mod_abs and rx_lost " 9151 "to be configured: u=%d p%d\n"), unit, port)); 9152 } else if (PHY84740_SINGLE_PORT_MODE(pc)) { 9153 LOG_INFO(BSL_LS_SOC_PHY, 9154 (BSL_META_U(unit, 9155 "PHY84740 QSFP module auto detect enabled: u=%d p=%d\n"), 9156 unit, port)); 9157 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_GEN_PURPOSE_REG, 9158 PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN, 9159 PHY84740_PMAD_GEN_PURPOSE_MOD_AUTO_DETECT_EN); 9160 if (SOC_FAILURE(rv)) { 9161 LOG_ERROR(BSL_LS_SOC_PHY, 9162 (BSL_META_U(unit, 9163 "PHY84740 setting QSP module auto detect failed: u=%d p%d\n"), 9164 unit, port)); 9165 } else { 9166 MOD_AUTO_DETECT_MSG(pc) = 1; 9167 } 9168 } else if (devid == PHY84740_ID_84754) { 9169 LOG_INFO(BSL_LS_SOC_PHY, 9170 (BSL_META_U(unit, 9171 "PHY84740 SFP module auto detect on: u=%d p=%d\n"), 9172 unit, port)); 9173 rv = MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_MOD_AUTO_DETECT_STS_REG, 9174 PHY84740_MOD_AUTO_DETECT_STS_SFP_EN, 9175 PHY84740_MOD_AUTO_DETECT_STS_SFP_EN); 9176 if (SOC_FAILURE(rv)) { 9177 LOG_ERROR(BSL_LS_SOC_PHY, 9178 (BSL_META_U(unit, 9179 "PHY84740 setting SFP module auto detect failed: u=%d p%d\n"), 9180 unit, port)); 9181 } else { 9182 MOD_AUTO_DETECT_MSG(pc) = 1; 9183 } 9184 } else { 9185 LOG_ERROR(BSL_LS_SOC_PHY, 9186 (BSL_META_U(unit, 9187 "PHY84740 module auto detect not supported: u=%d p%d\n"), 9188 unit, port)); 9189 } 9190 } 9191 } 9192 return SOC_E_NONE; 9193 } 9194 9195 /* 9196 * Function: 9197 * phy_84741_an_get 9198 * Purpose: 9199 * Get the current auto-negotiation status (enabled/busy) 9200 * Parameters: 9201 * unit - StrataSwitch unit #. 9202 * port - StrataSwitch port #. 9203 * an - (OUT) if true, auto-negotiation is enabled. 9204 * an_done - (OUT) if true, auto-negotiation is complete. This 9205 * value is undefined if an == false. 9206 * Returns: 9207 * SOC_E_XXX 9208 */ 9209 9210 STATIC int 9211 phy_84741_an_get(int unit, soc_port_t port, int *an, int *an_done) 9212 { 9213 phy_ctrl_t *pc; 9214 uint16 an_status; 9215 9216 pc = EXT_PHY_SW_STATE(unit, port); 9217 9218 if (FCMAP_PASSTHROUGH(pc)) { 9219 *an = TRUE; 9220 *an_done = TRUE; 9221 return SOC_E_NONE; 9222 } 9223 9224 SOC_IF_ERROR_RETURN( 9225 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_INTR_VALUE_REG, 9226 &an_status)); 9227 *an_done = (an_status & PHY84740_AUTONEG_COMPLETE)? TRUE: FALSE; 9228 9229 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9230 SOC_IF_ERROR_RETURN 9231 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, &an_status)); 9232 *an = (an_status & PHY84740_AN_ENABLE)? TRUE: FALSE; 9233 } else { 9234 SOC_IF_ERROR_RETURN 9235 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, &an_status)); 9236 *an = (an_status & PHY84740_AN_ENABLE)? TRUE: FALSE; 9237 } 9238 return SOC_E_NONE; 9239 } 9240 9241 /* 9242 * Function: 9243 * phy_84741_an_set 9244 * Purpose: 9245 * Enable or disabled auto-negotiation on the specified port. 9246 * Parameters: 9247 * unit - StrataSwitch unit #. 9248 * port - StrataSwitch port #. 9249 * an - Boolean, if true, auto-negotiation is enabled 9250 * (and/or restarted). If false, autonegotiation is disabled. 9251 * Returns: 9252 * SOC_E_XXX 9253 */ 9254 STATIC int 9255 phy_84741_an_set(int unit, soc_port_t port, int an) 9256 { 9257 phy_ctrl_t *pc; 9258 phy_ctrl_t *int_pc; 9259 uint16 mode; 9260 9261 pc = EXT_PHY_SW_STATE(unit, port); 9262 9263 LOG_INFO(BSL_LS_SOC_PHY, 9264 (BSL_META_U(unit, 9265 "phy_84741_an_set: u=%d p=%d an=%d\n"), 9266 unit, port, an)); 9267 /* make sure internal autoneg is turned off always */ 9268 int_pc = INT_PHY_SW_STATE(unit, port); 9269 9270 if (FCMAP_PASSTHROUGH(pc)) { 9271 if (NULL != int_pc) { 9272 SOC_IF_ERROR_RETURN( 9273 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, FALSE)); 9274 } 9275 return SOC_E_NONE; 9276 } 9277 9278 if (REVERSE_MODE(pc) && IS_HG_PORT(unit, port)) { 9279 /* Both WC and external phy need to set AN off @ 10G or 40G */ 9280 an = 0; 9281 if (NULL != int_pc) { 9282 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9283 /* 9284 * Internal Serdes needs to be in forced KR4 (a misnomer), meaning 9285 * DFE is enabled but cl73 (or cl37) are turned off. This enables 9286 * the equalizer as required for KR backplane interfaces 9287 */ 9288 SOC_IF_ERROR_RETURN( 9289 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, 0)); 9290 SOC_IF_ERROR_RETURN( 9291 PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_KR4)); 9292 SOC_IF_ERROR_RETURN( 9293 PHY_SPEED_SET(int_pc->pd, unit, port, 40000)); 9294 9295 /* disable cl72: 1.96=0 (device 1, register 0x96) */ 9296 SOC_IF_ERROR_RETURN 9297 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, 0)); 9298 /* disable AN: 7.0=0 (device 7, register 0) */ 9299 SOC_IF_ERROR_RETURN 9300 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 0)); 9301 } 9302 } 9303 } 9304 9305 if (NULL != int_pc) { 9306 if (REVERSE_MODE(pc)) { 9307 SOC_IF_ERROR_RETURN( 9308 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an)); 9309 } else { 9310 /* if in passthru mode, enable autoneg on internal serdes */ 9311 if (PCS_REPEATER(pc)) { 9312 SOC_IF_ERROR_RETURN( 9313 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an)); 9314 } else { 9315 SOC_IF_ERROR_RETURN( 9316 PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, FALSE)); 9317 } 9318 } 9319 } 9320 9321 /* 0xc700(0xc710 once firmware fixed), PCS link status overide for CR4 autoneg. 9322 * bit 4 enable override, bit 1 status indication 9323 * system side link status check in 40G 0xcd04, this is per lane register 9324 */ 9325 SOC_IF_ERROR_RETURN( 9326 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&mode)); 9327 9328 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9329 /* make sure internal speed is set to 40G */ 9330 if (an) { 9331 if (NULL != int_pc) { 9332 if (!REVERSE_MODE(pc)) { 9333 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 9334 PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR); 9335 } 9336 SOC_IF_ERROR_RETURN( 9337 PHY_SPEED_SET(int_pc->pd, unit, port, 40000)); 9338 } 9339 } 9340 } 9341 9342 /* autoneg only supported in CR4 mode */ 9343 /* no autoneg if in SR4/LR4 mode */ 9344 if (!(mode & (PHY84740_PMAD_DAC_MODE_MASK | PHY84740_PMAD_BKPLANE_MODE_MASK)) || 9345 (REVERSE_MODE(pc) && IS_HG_PORT(unit, port))) { 9346 an = 0; 9347 } 9348 9349 /* enable/disable cl72 */ 9350 SOC_IF_ERROR_RETURN 9351 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an? 2:0)); 9352 /* enable/disable AN */ 9353 SOC_IF_ERROR_RETURN 9354 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 9355 an? AN_ENABLE | AN_RESTART: 0x0)); 9356 9357 return SOC_E_NONE; 9358 } else { /* quad mode, cl73 for backplane */ 9359 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 9360 /* make sure internal speed is set to 10G */ 9361 if (an) { 9362 if (NULL != int_pc) { 9363 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 9364 PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR); 9365 } 9366 SOC_IF_ERROR_RETURN( 9367 PHY_SPEED_SET(int_pc->pd, unit, port, 10000)); 9368 } 9369 } 9370 9371 /* enable/disable cl72 */ 9372 SOC_IF_ERROR_RETURN 9373 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x0096, an? 2:0)); 9374 /* enable/disable AN */ 9375 SOC_IF_ERROR_RETURN 9376 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_CTRL_REG, 9377 an? AN_ENABLE | AN_RESTART: 0x0)); 9378 } 9379 } 9380 9381 if (an) { 9382 /* Enable Clause 37 AN */ 9383 SOC_IF_ERROR_RETURN 9384 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, MII_CTRL_AE | MII_CTRL_RAN)); 9385 SOC_IF_ERROR_RETURN 9386 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, 0, (1 << 5))); 9387 } else { 9388 /* disable Clause 37 AN */ 9389 SOC_IF_ERROR_RETURN 9390 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE0, 0x0)); 9391 9392 /* Enable encoded forced speed derived from ieeeControl1 and ieeeControl2 */ 9393 SOC_IF_ERROR_RETURN 9394 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x8309, (1 << 5), (1 << 5))); 9395 } 9396 9397 return SOC_E_NONE; 9398 } 9399 9400 /* 9401 * Function: 9402 * phy_84741_ability_advert_get 9403 * Purpose: 9404 * Get the current advertisement for auto-negotiation. 9405 * Parameters: 9406 * unit - StrataSwitch unit #. 9407 * port - StrataSwitch port #. 9408 * mode - (OUT) Port mode mask indicating supported options/speeds. 9409 * Returns: 9410 * SOC_E_XXX 9411 * Notes: 9412 * The advertisement is retrieved for the ACTIVE medium. 9413 * No synchronization performed at this level. 9414 */ 9415 9416 STATIC int 9417 phy_84741_ability_advert_get(int unit, soc_port_t port, 9418 soc_port_ability_t *ability) 9419 { 9420 uint16 an_adv; 9421 soc_port_mode_t mode; 9422 phy_ctrl_t *pc; 9423 9424 if (NULL == ability) { 9425 return (SOC_E_PARAM); 9426 } 9427 pc = EXT_PHY_SW_STATE(unit, port); 9428 9429 if (FCMAP_PASSTHROUGH(pc)) { 9430 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 9431 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 9432 return SOC_E_NONE; 9433 } 9434 9435 if (PCS_REPEATER(pc)) { 9436 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 9437 if (NULL != int_pc) { 9438 SOC_IF_ERROR_RETURN( 9439 PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, ability)); 9440 } 9441 return SOC_E_NONE; 9442 } 9443 9444 mode = 0; 9445 ability->pause = 0; 9446 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9447 /* advert register 1 */ 9448 SOC_IF_ERROR_RETURN 9449 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, &an_adv)); 9450 9451 mode |= (an_adv & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0; 9452 mode |= (an_adv & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0; 9453 mode |= (an_adv & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0; 9454 mode |= (an_adv & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0; 9455 ability->speed_full_duplex = mode; 9456 9457 SOC_IF_ERROR_RETURN 9458 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, &an_adv)); 9459 9460 switch (an_adv & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) { 9461 case AN_ADVERT_PAUSE: 9462 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 9463 break; 9464 case AN_ADVERT_PAUSE_ASYM: 9465 ability->pause = SOC_PA_PAUSE_TX; 9466 break; 9467 case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM: 9468 ability->pause = SOC_PA_PAUSE_RX; 9469 break; 9470 } 9471 } else { 9472 /* check Full Duplex advertisement on Clause 37 */ 9473 SOC_IF_ERROR_RETURN 9474 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, &an_adv)); 9475 mode |= (an_adv & MII_ANA_C37_FD) ? SOC_PA_SPEED_1000MB : 0; 9476 9477 ability->speed_full_duplex = mode; 9478 9479 switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) { 9480 case MII_ANA_C37_PAUSE: 9481 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 9482 break; 9483 case MII_ANA_C37_ASYM_PAUSE: 9484 ability->pause = SOC_PA_PAUSE_TX; 9485 break; 9486 case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE: 9487 ability->pause = SOC_PA_PAUSE_RX; 9488 break; 9489 } 9490 } 9491 9492 LOG_INFO(BSL_LS_SOC_PHY, 9493 (BSL_META_U(unit, 9494 "phy_84741_ability_advert_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 9495 unit, port, ability->speed_full_duplex, ability->pause)); 9496 return SOC_E_NONE; 9497 } 9498 9499 /* 9500 * Function: 9501 * phy_84741_ability_remote_get 9502 * Purpose: 9503 * Get the device's complete abilities. 9504 * Parameters: 9505 * unit - StrataSwitch unit #. 9506 * port - StrataSwitch port #. 9507 * ability - return device's abilities. 9508 * Returns: 9509 * SOC_E_XXX 9510 */ 9511 9512 STATIC int 9513 phy_84741_ability_remote_get(int unit, soc_port_t port, 9514 soc_port_ability_t *ability) 9515 { 9516 phy_ctrl_t *pc; 9517 uint16 lp_abil; 9518 9519 if (NULL == ability) { 9520 return SOC_E_PARAM; 9521 } 9522 9523 pc = EXT_PHY_SW_STATE(unit, port); 9524 9525 if (FCMAP_PASSTHROUGH(pc)) { 9526 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 9527 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 9528 return SOC_E_NONE; 9529 } 9530 9531 if (PCS_REPEATER(pc)) { 9532 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 9533 if (NULL != int_pc) { 9534 SOC_IF_ERROR_RETURN( 9535 PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability)); 9536 } 9537 return SOC_E_NONE; 9538 } 9539 9540 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 9541 9542 /* check CL73 first */ 9543 SOC_IF_ERROR_RETURN 9544 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_1_REG, &lp_abil)); 9545 ability->speed_full_duplex = (lp_abil & AN_ADVERT_40GCR4) ? SOC_PA_SPEED_40GB : 0; 9546 ability->speed_full_duplex |= (lp_abil & AN_ADVERT_40GKR4) ? SOC_PA_SPEED_40GB : 0; 9547 ability->speed_full_duplex |= (lp_abil & AN_ADVERT_10GKR) ? SOC_PA_SPEED_10GB : 0; 9548 ability->speed_full_duplex |= (lp_abil & AN_ADVERT_1GKX) ? SOC_PA_SPEED_1000MB : 0; 9549 9550 SOC_IF_ERROR_RETURN 9551 (READ_PHY84740_MMF_AN_REG(unit, pc, AN_LP_ABILITY_0_REG, &lp_abil)); 9552 9553 ability->pause = 0; 9554 switch (lp_abil & (AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)) { 9555 case AN_ADVERT_PAUSE: 9556 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 9557 break; 9558 case AN_ADVERT_PAUSE_ASYM: 9559 ability->pause = SOC_PA_PAUSE_TX; 9560 break; 9561 case AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM: 9562 ability->pause = SOC_PA_PAUSE_RX; 9563 break; 9564 } 9565 9566 /* check CL37 */ 9567 SOC_IF_ERROR_RETURN 9568 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xFFE5, &lp_abil)); 9569 ability->speed_full_duplex |= (lp_abil & MII_ANA_C37_FD) ? 9570 SOC_PA_SPEED_1000MB : 0; 9571 9572 switch (lp_abil & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) { 9573 case MII_ANP_C37_PAUSE: 9574 ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 9575 break; 9576 case MII_ANP_C37_ASYM_PAUSE: 9577 ability->pause |= SOC_PA_PAUSE_TX; 9578 break; 9579 case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE: 9580 ability->pause |= SOC_PA_PAUSE_RX; 9581 break; 9582 } 9583 9584 LOG_INFO(BSL_LS_SOC_PHY, 9585 (BSL_META_U(unit, 9586 "phy_84741_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 9587 unit, port, ability->speed_full_duplex, ability->pause)); 9588 9589 return (SOC_E_NONE); 9590 } 9591 9592 /* 9593 * Function: 9594 * phy_84741_ability_advert_set 9595 * Purpose: 9596 * Set the current advertisement for auto-negotiation. 9597 * Parameters: 9598 * unit - StrataSwitch unit #. 9599 * port - StrataSwitch port #. 9600 * mode - Port mode mask indicating supported options/speeds. 9601 * Returns: 9602 * SOC_E_XXX 9603 * Notes: 9604 * The advertisement is set only for the ACTIVE medium. 9605 * No synchronization performed at this level. 9606 */ 9607 9608 STATIC int 9609 phy_84741_ability_advert_set(int unit, soc_port_t port, 9610 soc_port_ability_t *ability) 9611 { 9612 uint16 an_adv,an_adv_cl37,mode; 9613 phy_ctrl_t *pc; 9614 9615 if (NULL == ability) { 9616 return (SOC_E_PARAM); 9617 } 9618 9619 pc = EXT_PHY_SW_STATE(unit, port); 9620 9621 if (FCMAP_PASSTHROUGH(pc)) { 9622 return SOC_E_NONE; 9623 } 9624 9625 if (PCS_REPEATER(pc)) { 9626 phy_ctrl_t *int_pc = INT_PHY_SW_STATE(unit, port); 9627 if (NULL != int_pc) { 9628 SOC_IF_ERROR_RETURN( 9629 PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, ability)); 9630 } 9631 return SOC_E_NONE; 9632 } 9633 9634 SOC_IF_ERROR_RETURN( 9635 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&mode)); 9636 9637 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9638 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 9639 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ? 9640 AN_ADVERT_40GKR4 : 0; 9641 an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ? 9642 AN_ADVERT_10GKR : 0; 9643 } else { 9644 9645 /* only advertise 40G CR4 */ 9646 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_40GB) ? 9647 AN_ADVERT_40GCR4 : 0; 9648 } 9649 9650 /* CL73 advert register 1 */ 9651 SOC_IF_ERROR_RETURN 9652 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv)); 9653 9654 } else { /* quad-port mode */ 9655 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 9656 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ? 9657 AN_ADVERT_10GKR : 0; 9658 an_adv |= (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 9659 AN_ADVERT_1GKX : 0; 9660 9661 /* CL73 advert register 1 */ 9662 SOC_IF_ERROR_RETURN 9663 (WRITE_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_1_REG, an_adv)); 9664 } 9665 9666 /* only 1G CL37 autoneg */ 9667 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? 9668 AN_ADVERT_1G : 0; 9669 9670 /* write Full Duplex advertisement on Clause 37 */ 9671 SOC_IF_ERROR_RETURN 9672 (WRITE_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4,an_adv)); 9673 } 9674 9675 an_adv = an_adv_cl37 = 0; 9676 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 9677 case SOC_PA_PAUSE_TX: 9678 an_adv = AN_ADVERT_PAUSE_ASYM; 9679 an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE; 9680 break; 9681 case SOC_PA_PAUSE_RX: 9682 an_adv = AN_ADVERT_PAUSE_ASYM | AN_ADVERT_PAUSE; 9683 an_adv_cl37 = MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE; 9684 break; 9685 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 9686 an_adv_cl37 = MII_ANA_C37_PAUSE; 9687 an_adv = AN_ADVERT_PAUSE; 9688 break; 9689 } 9690 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9691 SOC_IF_ERROR_RETURN 9692 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv, 9693 AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)); 9694 } else { 9695 if (mode & PHY84740_PMAD_BKPLANE_MODE_MASK) { 9696 SOC_IF_ERROR_RETURN 9697 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, AN_ADVERT_0_REG, an_adv, 9698 AN_ADVERT_PAUSE | AN_ADVERT_PAUSE_ASYM)); 9699 } 9700 9701 /* write Pause advertisement on Clause 37 */ 9702 SOC_IF_ERROR_RETURN 9703 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0xFFE4, an_adv_cl37, 9704 MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE)); 9705 } 9706 9707 LOG_INFO(BSL_LS_SOC_PHY, 9708 (BSL_META_U(unit, 9709 "phy_8072_ability_advert_set: u=%d p=%d pause=0x%08x adv_reg1=0x%04x\n"), 9710 unit, port, ability->pause, an_adv)); 9711 9712 return SOC_E_NONE; 9713 } 9714 9715 /* 9716 * Function: 9717 * phy_84741_ability_local_get 9718 * Purpose: 9719 * Get the device's complete abilities. 9720 * Parameters: 9721 * unit - StrataSwitch unit #. 9722 * port - StrataSwitch port #. 9723 * ability - return device's abilities. 9724 * Returns: 9725 * SOC_E_XXX 9726 */ 9727 9728 STATIC int 9729 phy_84741_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 9730 { 9731 phy_ctrl_t *pc; 9732 phy_ctrl_t *int_pc; 9733 pc = EXT_PHY_SW_STATE(unit, port); 9734 int_pc = INT_PHY_SW_STATE(unit, port); 9735 9736 LOG_INFO(BSL_LS_SOC_PHY, 9737 (BSL_META_U(unit, 9738 "phy_84741_ability_local_get: u=%d p=%d\n"), 9739 unit, port)); 9740 9741 if (NULL == ability) { 9742 return SOC_E_PARAM; 9743 } 9744 9745 if (FCMAP_PASSTHROUGH(pc)) { 9746 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 9747 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 9748 return SOC_E_NONE; 9749 } 9750 9751 if (NULL != int_pc && PCS_REPEATER(pc)) { 9752 SOC_IF_ERROR_RETURN( 9753 PHY_ABILITY_LOCAL_GET(int_pc->pd, unit, port, ability)); 9754 return SOC_E_NONE; 9755 } 9756 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 9757 9758 switch(pc->speed_max) { 9759 case 42000: 9760 /* fall through */ 9761 case 40000: 9762 ability->speed_full_duplex = SOC_PA_SPEED_40GB; 9763 break; 9764 case 10000: 9765 default: 9766 ability->speed_full_duplex = SOC_PA_SPEED_1000MB; 9767 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 9768 break; 9769 } 9770 9771 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 9772 ability->interface = SOC_PA_INTF_XGMII; 9773 ability->medium = SOC_PA_MEDIUM_FIBER; 9774 ability->loopback = SOC_PA_LB_PHY; 9775 9776 LOG_INFO(BSL_LS_SOC_PHY, 9777 (BSL_META_U(unit, 9778 "phy_84741_ability_local_get: u=%d p=%d speed=0x%x\n"), 9779 unit, port, ability->speed_full_duplex)); 9780 9781 return (SOC_E_NONE); 9782 } 9783 9784 STATIC int 9785 _phy84741_mod_auto_detect_update(int unit, soc_port_t port) 9786 { 9787 phy_ctrl_t *pc; 9788 uint16 data; 9789 uint16 status; 9790 9791 pc = EXT_PHY_SW_STATE(unit, port); 9792 9793 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9794 /* point to lane 0 */ 9795 SOC_IF_ERROR_RETURN 9796 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 9797 } 9798 9799 /* check for presence */ 9800 SOC_IF_ERROR_RETURN 9801 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 9802 PHY84740_PMAD_OPTICAL_CFG_REG,&data)); 9803 if (data & PHY84740_PMAD_OPTICAL_CFG_MOD_PRESENCE) { 9804 SOC_IF_ERROR_RETURN 9805 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 9806 PHY84740_MOD_AUTO_DETECT_STS_REG, &status)); 9807 /* make sure auto detection completed */ 9808 if (!(status & PHY84740_MOD_AUTO_DETECT_STS_NOT_DONE)) { 9809 if (MOD_AUTO_DETECT_MSG(pc)) { 9810 /* present and must print message */ 9811 MOD_AUTO_DETECT_MSG(pc) = 0; 9812 if (status & PHY84740_MOD_AUTO_DETECT_STS_NOT_RES) { 9813 uint16 mod_130 = 0, mod_131 = 0; 9814 (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f2, &mod_130)); 9815 (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f3, &mod_131)); 9816 LOG_ERROR(BSL_LS_SOC_PHY, 9817 (BSL_META_U(unit, 9818 "PHY84740 could not detect module, " 9819 "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"), 9820 unit, port, status, mod_130, mod_131)); 9821 } else { 9822 /* auto detect done and successfully resolved */ 9823 SOC_IF_ERROR_RETURN 9824 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&data)); 9825 LOG_ERROR(BSL_LS_SOC_PHY, 9826 (BSL_META_U(unit, 9827 "PHY84740 %s module detected: u=%d p=%d\n"), 9828 (data & PHY84740_PMAD_DAC_MODE_MASK) ? "CR4" : "SR4", 9829 unit, port)); 9830 } 9831 } 9832 } else if (!(status & PHY84740_MOD_AUTO_DETECT_STS_I2C_FAIL) && 9833 (MOD_AUTO_DETECT_MSG(pc))) { 9834 uint16 mod_130 = 0, mod_131 = 0; 9835 (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f2, &mod_130)); 9836 (void) (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x81f3, &mod_131)); 9837 MOD_AUTO_DETECT_MSG(pc) = 0; 9838 LOG_ERROR(BSL_LS_SOC_PHY, 9839 (BSL_META_U(unit, 9840 "PHY84740 i2c failed while detecting module, " 9841 "defaulting to SR(4): u=%d p=%d sts=0x%x (0x%x:0x%x)\n"), 9842 unit, port, status, mod_130, mod_131)); 9843 } 9844 } else { 9845 if (!MOD_AUTO_DETECT_MSG(pc)) { 9846 /* module not present */ 9847 LOG_ERROR(BSL_LS_SOC_PHY, 9848 (BSL_META_U(unit, 9849 "PHY84740 module removed u=%d p=%d\n"), unit, port)); 9850 MOD_AUTO_DETECT_MSG(pc) = 1; 9851 } 9852 } 9853 return SOC_E_NONE; 9854 } 9855 9856 /* 9857 * Function: 9858 * phy_84741_link_get 9859 * Purpose: 9860 * Get layer2 connection status. 9861 * Parameters: 9862 * unit - StrataSwitch unit #. 9863 * port - StrataSwitch port #. 9864 * link - address of memory to store link up/down state. 9865 * Returns: 9866 * SOC_E_NONE 9867 */ 9868 STATIC int 9869 phy_84741_link_get(int unit, soc_port_t port, int *link) 9870 { 9871 uint16 pma_mii_stat, pcs_mii_stat, link_stat; 9872 phy_ctrl_t *pc; 9873 phy_ctrl_t *int_pc; 9874 int cur_speed = 0; 9875 int an = 0,an_done = 0; 9876 uint16 speed_val; 9877 int rv; 9878 9879 if (link == NULL) { 9880 return SOC_E_NONE; 9881 } 9882 9883 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 9884 *link = FALSE; 9885 return SOC_E_NONE; 9886 } 9887 9888 pc = EXT_PHY_SW_STATE(unit, port); 9889 int_pc = INT_PHY_SW_STATE(unit, port); 9890 9891 if (!REVERSE_MODE(pc)) { 9892 if (PCS_REPEATER(pc)) { 9893 rv = PHY_LINK_GET(int_pc->pd, unit, port, link); 9894 return rv; 9895 } 9896 } 9897 if (FCMAP_PASSTHROUGH(pc)) { 9898 rv = PHY_LINK_GET(int_pc->pd, unit, port, link); 9899 return rv; 9900 } 9901 9902 phy_84741_an_get(unit,port,&an,&an_done); 9903 9904 /* only supports 40G. PHY PCS is not used. Check PMD link only */ 9905 if (PHY84740_SINGLE_PORT_MODE(pc)) { 9906 int serdes_link = TRUE; 9907 9908 if (REVERSE_MODE(pc)) { 9909 SOC_IF_ERROR_RETURN 9910 (PHY84740_XFI(unit,pc)); 9911 } 9912 9913 SOC_IF_ERROR_RETURN 9914 (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat)); 9915 *link = pma_mii_stat == 0xffff ? FALSE : 9916 ((pma_mii_stat & MII_STAT_LA) ? TRUE : FALSE); 9917 9918 if (REVERSE_MODE(pc)) { 9919 SOC_IF_ERROR_RETURN 9920 (PHY84740_MMF(unit,pc)); 9921 } 9922 9923 if (!REVERSE_MODE(pc)) { 9924 if ((NULL != int_pc) && an) { 9925 rv = PHY_LINK_GET(int_pc->pd, unit, port, &serdes_link); 9926 } 9927 } 9928 9929 if (MOD_AUTO_DETECT(pc)) { 9930 _phy84741_mod_auto_detect_update(unit, port); 9931 } 9932 9933 *link = (*link) && serdes_link; 9934 return SOC_E_NONE; 9935 } 9936 9937 /* return link false if in the middle of autoneg */ 9938 if (an == TRUE && an_done == FALSE) { 9939 *link = FALSE; 9940 return SOC_E_NONE; 9941 } 9942 9943 /* AN only supports 1G */ 9944 if (!an) { 9945 SOC_IF_ERROR_RETURN 9946 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL2_REG, 9947 &speed_val)); 9948 if ((speed_val & PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK) != 9949 PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX) { 9950 cur_speed = 10000; 9951 } 9952 } else { 9953 cur_speed = 1000; 9954 } 9955 9956 if (REVERSE_MODE(pc)) { 9957 SOC_IF_ERROR_RETURN 9958 (PHY84740_XFI(unit,pc)); 9959 } 9960 9961 if (cur_speed == 10000) { /* check all 3 device's link status if 10G */ 9962 9963 /* MMF Link status */ 9964 /* Read Status 2 register to get rid of Local faults */ 9965 SOC_IF_ERROR_RETURN 9966 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG, 9967 &pma_mii_stat)); 9968 SOC_IF_ERROR_RETURN 9969 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_STAT2_REG, 9970 &pma_mii_stat)); 9971 /* Receive Link status */ 9972 SOC_IF_ERROR_RETURN 9973 (READ_PHY84740_PCS_STATr(unit, pc, &pcs_mii_stat)); 9974 9975 SOC_IF_ERROR_RETURN 9976 (READ_PHY84740_PMA_PMD_STATr(unit, pc, &pma_mii_stat)); 9977 9978 /* MMF link status */ 9979 link_stat = pma_mii_stat & pcs_mii_stat; 9980 *link = link_stat == 0xffff ? FALSE : 9981 ((link_stat & MII_STAT_LA) ? TRUE : FALSE); 9982 } else { 9983 SOC_IF_ERROR_RETURN 9984 (READ_PHY84740_MMF_AN_REG(unit, pc, 0xffe1, 9985 &link_stat)); 9986 *link = link_stat == 0xffff ? FALSE : 9987 ((link_stat & MII_STAT_LA) ? TRUE : FALSE); 9988 } 9989 9990 if (REVERSE_MODE(pc)) { 9991 SOC_IF_ERROR_RETURN 9992 (PHY84740_MMF(unit,pc)); 9993 } 9994 9995 if (MOD_AUTO_DETECT(pc)) { 9996 _phy84741_mod_auto_detect_update(unit, port); 9997 } 9998 LOG_VERBOSE(BSL_LS_SOC_PHY, 9999 (BSL_META_U(unit, 10000 "phy_84741_link_get: u=%d port%d: link:%s\n"), 10001 unit, port, *link ? "Up": "Down")); 10002 10003 return SOC_E_NONE; 10004 } 10005 10006 /* 10007 * Function: 10008 * phy_84741_enable_set 10009 * Purpose: 10010 * Enable/Disable phy 10011 * Parameters: 10012 * unit - StrataSwitch unit #. 10013 * port - StrataSwitch port #. 10014 * enable - on/off state to set 10015 * Returns: 10016 * SOC_E_NONE 10017 */ 10018 10019 STATIC int 10020 phy_84741_enable_set(int unit, soc_port_t port, int enable) 10021 { 10022 uint16 data; /* Holder for new value to write to PHY reg */ 10023 uint16 mask; /* Holder for bit mask to update in PHY reg */ 10024 int ix; 10025 uint16 tx_ctrl; 10026 phy_ctrl_t *pc; 10027 10028 pc = EXT_PHY_SW_STATE(unit, port); 10029 10030 if (enable) { 10031 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 10032 } else { 10033 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 10034 } 10035 10036 if (REVERSE_MODE(pc)) { 10037 SOC_IF_ERROR_RETURN 10038 (PHY84740_XFI(unit,pc)); 10039 } 10040 10041 if (SINGLE_LPMODE(pc) && !(PHY84740_SINGLE_PORT_MODE(pc))) { 10042 /* Use 1.cd16 to disable tx */ 10043 data = enable ? 0 : (1 << 3); 10044 mask = 1 << 3; 10045 SOC_IF_ERROR_RETURN 10046 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_GENSIG_8071_REGISTER, 10047 data, mask)); 10048 } else { 10049 /* TX transmitter enable/disable. BCST register in single-port mode */ 10050 data = enable ? 0 : (1 << 0); 10051 mask = 1 << 0; /* Global PMD transmit disable */ 10052 SOC_IF_ERROR_RETURN 10053 (MODIFY_PHY84740_PMA_PMD_TX_DISABLEr(unit, pc, data, mask)); 10054 } 10055 10056 if (REVERSE_MODE(pc)) { 10057 SOC_IF_ERROR_RETURN 10058 (PHY84740_MMF(unit,pc)); 10059 } 10060 10061 for (ix = 0; ix < NUM_LANES; ix++) { 10062 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10063 SOC_IF_ERROR_RETURN 10064 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10065 PHY84740_PMAD_AER_ADDR_REG, ix)); 10066 } 10067 10068 /* TxOn control */ 10069 SOC_IF_ERROR_RETURN 10070 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10071 PHY84740_PMAD_OPTICAL_CFG_REG, 10072 enable? 0: (1 << 12), 10073 (1 << 12))); 10074 if (enable) { 10075 SOC_IF_ERROR_RETURN 10076 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10077 PHY84740_PMAD_OPTICAL_CFG_REG,&data)); 10078 10079 /* c8e4[4] indicates the TX active state, 0 means TX active, 1 means inactive. 10080 * This state = TxOnOff pin XOR c800[7] when c8e4[12]=0. 10081 * The default value of c800[7] is 1. 10082 * If user straps the TxOnOff to 0, 10083 * then the Tx won't be enabled until this function is called. 10084 * Toggle 0xc800[7] to enable the Tx when c8e4[4]=1. 10085 */ 10086 SOC_IF_ERROR_RETURN 10087 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10088 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, &tx_ctrl)); 10089 tx_ctrl &= (1 << 7); 10090 if (data & (1 << 4)) { 10091 SOC_IF_ERROR_RETURN 10092 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10093 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 10094 tx_ctrl? 0:(1 << 7), 10095 (1 << 7))); 10096 } 10097 } 10098 /* power on/off the lane */ 10099 SOC_IF_ERROR_RETURN 10100 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10101 PHY84740_PMAD_OPTICAL_CFG_REG, 10102 enable? 0: (1 << 4), 10103 (1 << 4))); 10104 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 10105 break; 10106 } 10107 } 10108 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10109 /* point back to lane0 */ 10110 SOC_IF_ERROR_RETURN 10111 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 10112 } 10113 return (SOC_E_NONE); 10114 } 10115 10116 /* 10117 * Function: 10118 * phy_84741_lb_set 10119 * Purpose: 10120 * Put 84740 in PHY PMA/PMD loopback 10121 * Parameters: 10122 * unit - StrataSwitch unit #. 10123 * port - StrataSwitch port #. 10124 * enable - binary value for on/off (1/0) 10125 * Returns: 10126 * SOC_E_NONE 10127 */ 10128 10129 STATIC int phy_84741_lb_set(int unit, soc_port_t port, int enable) 10130 { 10131 phy_ctrl_t *pc; 10132 uint16 tmp; 10133 uint16 lane; 10134 uint16 data16 = 0, mask16 = 0; 10135 int intf_tx; 10136 int intf_rx; 10137 10138 pc = EXT_PHY_SW_STATE(unit, port); 10139 10140 intf_tx = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ? 10141 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 10142 10143 intf_rx = ( intf_tx == PHY_DIAG_INTF_LINE ) ? 10144 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 10145 10146 /* TX Enable(Disable) Squelch(FORCE) when we Enable(Disable) loopback */ 10147 SOC_IF_ERROR_RETURN 10148 (_phy_84741_squelch_enable(unit, port, 10149 intf_tx, enable ? TRUE : FALSE, enable ? TRUE : FALSE )); 10150 10151 /* RX Disable(Enable) Squelch when we Enable(Disable) loopback */ 10152 SOC_IF_ERROR_RETURN 10153 (_phy_84741_squelch_enable(unit, port, 10154 intf_rx, enable ? FALSE : TRUE, /* force = */ FALSE)); 10155 10156 tmp = enable ? PHY84740_MII_CTRL_PMA_LOOPBACK : 0; 10157 10158 if (REVERSE_MODE(pc)) { 10159 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 10160 } 10161 10162 SOC_IF_ERROR_RETURN 10163 (MODIFY_PHY84740_PMA_PMD_CTRLr(unit, pc, 10164 tmp, PHY84740_MII_CTRL_PMA_LOOPBACK)); 10165 10166 if (PCS_REPEATER(pc)) { 10167 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 10168 for (lane = 0; lane < NUM_LANES; lane++) { 10169 data16 = 0; 10170 10171 /* point to the each lane starting at lane0 */ 10172 SOC_IF_ERROR_RETURN 10173 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10174 PHY84740_PMAD_AER_ADDR_REG, lane)); 10175 10176 SOC_IF_ERROR_RETURN 10177 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a, 10178 enable? 1:0, 1)); 10179 10180 SOC_IF_ERROR_RETURN( 10181 READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10182 PHY84740_DIG_CTRL_REG, 10183 &data16)); 10184 10185 /* 1.cd08.10 = 1.cd08.10 XOR 1.cd08.9 */ 10186 tmp = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1; 10187 data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp; 10188 mask16 = PHY84740_TX_POLARITY_FLIP_MASK; 10189 10190 10191 SOC_IF_ERROR_RETURN( 10192 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10193 PHY84740_DIG_CTRL_REG, 10194 data16,mask16)); 10195 } 10196 /* point back to lane0 */ 10197 SOC_IF_ERROR_RETURN 10198 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 10199 } else { /* quad-port mode */ 10200 data16 = 0; 10201 10202 SOC_IF_ERROR_RETURN 10203 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a, 10204 enable? 1:0, 1)); 10205 10206 SOC_IF_ERROR_RETURN( 10207 READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10208 PHY84740_DIG_CTRL_REG, 10209 &data16)); 10210 10211 /* 1.cd08.10 = 1.cd08.10 XOR 1.cd08.9 */ 10212 tmp = (data16 & PHY84740_RX_POLARITY_FLIP_MASK) << 1; 10213 data16 = (data16 & PHY84740_TX_POLARITY_FLIP_MASK) ^ tmp; 10214 mask16 = PHY84740_TX_POLARITY_FLIP_MASK; 10215 10216 SOC_IF_ERROR_RETURN( 10217 MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_DIG_CTRL_REG, 10218 data16,mask16)); 10219 } 10220 } 10221 10222 if (REVERSE_MODE(pc)) { 10223 SOC_IF_ERROR_RETURN 10224 (PHY84740_MMF(unit,pc)); 10225 } 10226 10227 return SOC_E_NONE; 10228 } 10229 10230 /* 10231 * Function: 10232 * phy_84741_lb_get 10233 * Purpose: 10234 * Get 84740 PHY loopback state 10235 * Parameters: 10236 * unit - StrataSwitch unit #. 10237 * port - StrataSwitch port #. 10238 * enable - address of location to store binary value for on/off (1/0) 10239 * Returns: 10240 * SOC_E_NONE 10241 */ 10242 10243 STATIC int 10244 phy_84741_lb_get(int unit, soc_port_t port, int *enable) 10245 { 10246 uint16 tmp; 10247 phy_ctrl_t *pc; 10248 10249 pc = EXT_PHY_SW_STATE(unit, port); 10250 10251 if (REVERSE_MODE(pc)) { 10252 SOC_IF_ERROR_RETURN 10253 (PHY84740_XFI(unit,pc)); 10254 } 10255 10256 SOC_IF_ERROR_RETURN 10257 (READ_PHY84740_PMA_PMD_CTRLr(unit, pc, &tmp)); 10258 /* ctrl != 0xffff check is to handle removable PHY daughter cards */ 10259 *enable = ((tmp != 0xffff) && 10260 (tmp & PHY84740_MII_CTRL_PMA_LOOPBACK)) ? TRUE : FALSE; 10261 10262 if (REVERSE_MODE(pc)) { 10263 SOC_IF_ERROR_RETURN 10264 (PHY84740_MMF(unit,pc)); 10265 } 10266 10267 LOG_INFO(BSL_LS_SOC_PHY, 10268 (BSL_META_U(unit, 10269 "phy_84741_lb_get: u=%d port%d: loopback:%s\n"), 10270 unit, port, *enable ? "Enabled": "Disabled")); 10271 10272 return SOC_E_NONE; 10273 } 10274 10275 STATIC int 10276 _phy_84741_control_tx_driver_set(int unit, soc_port_t port, int interface, 10277 soc_phy_control_t type, uint32 value) 10278 { 10279 uint16 data; /* Temporary holder of reg value to be written */ 10280 uint16 mask; /* Bit mask of reg value to be updated */ 10281 int ix; 10282 int lane; 10283 int start; 10284 int end; 10285 uint16 post_pre_tap = 0, force_preemph = 0; 10286 uint16 main_tap = 0; 10287 phy_ctrl_t *pc; /* PHY software state */ 10288 int reg; 10289 10290 pc = EXT_PHY_SW_STATE(unit, port); 10291 10292 10293 switch(type) { 10294 case SOC_PHY_CONTROL_DRIVER_CURRENT: 10295 /* fall through */ 10296 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 10297 /* fall through */ 10298 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 10299 /* fall through */ 10300 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 10301 /* fall through */ 10302 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 10303 data = (uint16)(value & 0xf); 10304 data = data << 12; 10305 mask = 0xf000; 10306 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 10307 if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) { 10308 lane = 0; 10309 } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) { 10310 lane = 1; 10311 } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) { 10312 lane = 2; 10313 } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) { 10314 lane = 3; 10315 } else { /* SOC_PHY_CONTROL_DRIVER_CURRENT */ 10316 lane = 4; /* all lanes */ 10317 } 10318 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10319 start = lane == 4? 0: lane; 10320 end = lane == 4? 4: lane + 1; 10321 for (ix = start; ix < end; ix++) { 10322 10323 PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10324 10325 SOC_IF_ERROR_RETURN 10326 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10327 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix))); 10328 10329 PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10330 10331 SOC_IF_ERROR_RETURN 10332 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask)); 10333 } 10334 } else { 10335 SOC_IF_ERROR_RETURN 10336 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask)); 10337 } 10338 break; 10339 10340 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 10341 /* fall through */ 10342 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 10343 /* fall through */ 10344 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 10345 /* fall through */ 10346 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 10347 /* fall through */ 10348 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 10349 data = (uint16)(value & 0xf); 10350 data = data << 8; 10351 mask = 0x0f00; 10352 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90a : 0xca01; 10353 if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) { 10354 lane = 0; 10355 } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) { 10356 lane = 1; 10357 } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) { 10358 lane = 2; 10359 } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) { 10360 lane = 3; 10361 } else { /* SOC_PHY_CONTROL_PRE_DRIVER_CURRENT */ 10362 lane = 4; /* all lanes */ 10363 } 10364 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10365 start = lane == 4? 0: lane; 10366 end = lane == 4? 4: lane + 1; 10367 for (ix = start; ix < end; ix++) { 10368 10369 PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10370 SOC_IF_ERROR_RETURN 10371 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10372 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix))); 10373 10374 PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10375 SOC_IF_ERROR_RETURN 10376 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask)); 10377 } 10378 } else { 10379 SOC_IF_ERROR_RETURN 10380 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, data, mask)); 10381 } 10382 break; 10383 case SOC_PHY_CONTROL_PREEMPHASIS: 10384 /* fall through */ 10385 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 10386 /* fall through */ 10387 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 10388 /* fall through */ 10389 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 10390 /* fall through */ 10391 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 10392 /* The value format: 10393 * bit 15: 1 enable forced preemphasis ctrl, 0 auto config 10394 * bit 14:10: post_tap value 10395 * bit 09:04: main tap value 10396 * bit 03:00: pre_tap value 10397 * 10398 * set 1.CA07[8] = 0, 1.CA02[15:11] for main_tap and 1.CA05[7:4] for post tap. 10399 * main tap control is in the register field 0xCA02[15:11]. 10400 * If a wrong value is written to the same register, field 0xCA02[9:7], 10401 * it may DAMAGE the device. User must avoid writing to 0xCA02[9:7] 10402 */ 10403 /* Register bit8, 0 force preemphasis, 1 auto config, 1.CA07 */ 10404 force_preemph = PHY84740_PREEMPH_GET_FORCE(value)? 0: 10405 PHY84740_PREEMPH_REG_FORCE_MASK; 10406 10407 /* add post tap value */ 10408 post_pre_tap = PHY84740_PREEMPH_GET_POST_TAP(value) << 10409 PHY84740_PREEMPH_REG_POST_TAP_SHFT; 10410 10411 /* add pre tap value */ 10412 post_pre_tap |= PHY84740_PREEMPH_GET_PRE_TAP(value) << 10413 PHY84740_PREEMPH_REG_PRE_TAP_SHFT; 10414 10415 /* main tap in 1.CA02 */ 10416 main_tap = PHY84740_PREEMPH_GET_MAIN_TAP(value) << 10417 PHY84740_PREEMPH_REG_MAIN_TAP_SHFT; 10418 10419 reg = (interface == PHY_DIAG_INTF_SYS) ? 0xc90c : 0xca06; 10420 10421 if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) { 10422 lane = 0; 10423 } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) { 10424 lane = 1; 10425 } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) { 10426 lane = 2; 10427 } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) { 10428 lane = 3; 10429 } else { /* SOC_PHY_CONTROL_PREEMPHASIS_LANE */ 10430 lane = 4; /* all lanes */ 10431 } 10432 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10433 start = lane == 4? 0: lane; 10434 end = lane == 4? 4: lane + 1; 10435 } else { 10436 /* just make sure execute once */ 10437 start = 0; 10438 end = 1; 10439 } 10440 for (ix = start; ix < end; ix++) { 10441 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10442 10443 PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10444 SOC_IF_ERROR_RETURN 10445 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10446 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix))); 10447 PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10448 } 10449 SOC_IF_ERROR_RETURN 10450 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, reg, 10451 post_pre_tap, PHY84740_PREEMPH_REG_POST_TAP_MASK | 10452 PHY84740_PREEMPH_REG_PRE_TAP_MASK)); 10453 10454 /* N/A on system side */ 10455 if( interface != PHY_DIAG_INTF_SYS) { 10456 SOC_IF_ERROR_RETURN 10457 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca07, 10458 force_preemph, PHY84740_PREEMPH_REG_FORCE_MASK)); 10459 } 10460 10461 /* always clear tx_pwrdn bit. The read/modify/write may accidently 10462 * set the bit 0xCA02[10]. Because the CA02[10] read value is: 10463 * CA02[10]_read_value = CA02[10] OR Digital_State_Machine 10464 * The problem will occur when the Digital_State_Machine output is 1 10465 * at the time of reading this register. 10466 */ 10467 SOC_IF_ERROR_RETURN 10468 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10469 (interface == PHY_DIAG_INTF_SYS) ? 0xc90b : 0xca02, 10470 main_tap, 10471 PHY84740_PREEMPH_REG_MAIN_TAP_MASK | 10472 PHY84740_PREEMPH_REG_TX_PWRDN_MASK)); 10473 } 10474 break; 10475 10476 default: 10477 /* should never get here */ 10478 return SOC_E_PARAM; 10479 } 10480 10481 #ifdef PHY84740_FCS_ERROR_WAR 10482 /* Toggle Transmit lane output so that the link partner 10483 resets itself to a good signal. Othwerise, it could 10484 sync to a sub optimal signal and can see FCS errors. 10485 */ 10486 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10487 start = lane == 4? 0: lane; 10488 end = lane == 4? 4: lane + 1; 10489 } else { 10490 /* just make sure execute once */ 10491 start = 0; 10492 end = 1; 10493 } 10494 for (ix = start; ix < end; ix++) { 10495 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10496 10497 PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10498 SOC_IF_ERROR_RETURN 10499 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10500 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,ix))); 10501 PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10502 10503 data = mask = 0x1 << (12+ P2L_MAP(pc,ix)); /* per lane */ 10504 SOC_IF_ERROR_RETURN 10505 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 10506 10507 data = 0; 10508 SOC_IF_ERROR_RETURN 10509 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 10510 } else { 10511 data = mask = (lane == 4)? 10512 0x1 << 11 : /* Global */ 10513 0x1 << (12 + P2L_MAP(pc,lane)); /* per lane */ 10514 SOC_IF_ERROR_RETURN 10515 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 10516 data = 0; 10517 SOC_IF_ERROR_RETURN 10518 (MODIFY_PHY84740_MMF_AN_REG(unit, pc, 0x800e, data, mask)); 10519 } 10520 } 10521 #endif /* PHY84740_FCS_ERROR_WAR */ 10522 10523 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10524 PHY84740_MMF_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10525 /* point back to lane0 */ 10526 SOC_IF_ERROR_RETURN 10527 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10528 PHY84740_PMAD_AER_ADDR_REG, 0)); 10529 PHY84740_XFI_IF_INTF(unit, pc, interface, PHY_DIAG_INTF_SYS); 10530 } 10531 return SOC_E_NONE; 10532 } 10533 10534 STATIC int 10535 _phy_84741_control_tx_driver_get(int unit, soc_port_t port, 10536 soc_phy_control_t type, uint32 *value) 10537 { 10538 uint16 data16; /* Temporary holder of a reg value */ 10539 uint16 main_tap; 10540 uint16 post_tap; 10541 int lane; 10542 phy_ctrl_t *pc; /* PHY software state */ 10543 10544 pc = EXT_PHY_SW_STATE(unit, port); 10545 10546 data16 = 0; 10547 switch(type) { 10548 case SOC_PHY_CONTROL_PREEMPHASIS: 10549 /* fall through */ 10550 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 10551 /* fall through */ 10552 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 10553 /* fall through */ 10554 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 10555 /* fall through */ 10556 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 10557 if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE0) { 10558 lane = 0; 10559 } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE1) { 10560 lane = 1; 10561 } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE2) { 10562 lane = 2; 10563 } else if (type == SOC_PHY_CONTROL_PREEMPHASIS_LANE3) { 10564 lane = 3; 10565 } else { 10566 lane = 0; 10567 } 10568 /* 1.CA05[15] = 0, set 1.CA02[15:11] for main_tap and 10569 * 1.CA05[7:4] for postcursor 10570 */ 10571 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10572 SOC_IF_ERROR_RETURN 10573 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10574 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane))); 10575 } 10576 SOC_IF_ERROR_RETURN 10577 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca02, &main_tap)); 10578 SOC_IF_ERROR_RETURN 10579 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca05, &post_tap)); 10580 10581 /* bit15 force flag, 14:10 post_tap, 09:04 main tap */ 10582 *value = (post_tap & PHY84740_PREEMPH_REG_FORCE_MASK)? 0: 10583 (1 << PHY84740_PREEMPH_CTRL_FORCE_SHFT); 10584 *value |= ((post_tap & PHY84740_PREEMPH_REG_POST_TAP_MASK) >> 10585 PHY84740_PREEMPH_REG_POST_TAP_SHFT) << 10586 PHY84740_PREEMPH_CTRL_POST_TAP_SHFT; 10587 *value |= ((main_tap & PHY84740_PREEMPH_REG_MAIN_TAP_MASK) >> 10588 PHY84740_PREEMPH_REG_MAIN_TAP_SHFT) << 10589 PHY84740_PREEMPH_CTRL_MAIN_TAP_SHFT; 10590 10591 break; 10592 10593 case SOC_PHY_CONTROL_DRIVER_CURRENT: 10594 /* fall through */ 10595 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 10596 /* fall through */ 10597 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 10598 /* fall through */ 10599 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 10600 /* fall through */ 10601 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 10602 if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0) { 10603 lane = 0; 10604 } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1) { 10605 lane = 1; 10606 } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2) { 10607 lane = 2; 10608 } else if (type == SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3) { 10609 lane = 3; 10610 } else { 10611 lane = 0; 10612 } 10613 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10614 SOC_IF_ERROR_RETURN 10615 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10616 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane))); 10617 } 10618 SOC_IF_ERROR_RETURN 10619 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca01, &data16)); 10620 *value = (data16 & 0xf000) >> 12; 10621 break; 10622 10623 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 10624 /* fall through */ 10625 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 10626 /* fall through */ 10627 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 10628 /* fall through */ 10629 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 10630 /* fall through */ 10631 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 10632 if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0) { 10633 lane = 0; 10634 } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1) { 10635 lane = 1; 10636 } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2) { 10637 lane = 2; 10638 } else if (type == SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3) { 10639 lane = 3; 10640 } else { 10641 lane = 0; 10642 } 10643 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10644 SOC_IF_ERROR_RETURN 10645 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10646 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc,lane))); 10647 } 10648 SOC_IF_ERROR_RETURN 10649 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xca01, &data16)); 10650 *value = (data16 & 0x0f00) >> 8; 10651 break; 10652 10653 default: 10654 /* should never get here */ 10655 return SOC_E_PARAM; 10656 } 10657 10658 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10659 /* point back to lane0 */ 10660 SOC_IF_ERROR_RETURN 10661 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 10662 } 10663 return SOC_E_NONE; 10664 } 10665 10666 STATIC int 10667 _phy_84741_control_edc_mode_set(int unit, soc_port_t port, uint32 value) 10668 { 10669 uint16 data16; 10670 uint16 mask16; 10671 phy_ctrl_t *pc; /* PHY software state */ 10672 int ix; 10673 10674 pc = EXT_PHY_SW_STATE(unit, port); 10675 10676 /* clear software overrides */ 10677 mask16 = 0; 10678 if (!RX_LOS(pc)) { 10679 mask16 |= PHY84740_RXLOS_OVERRIDE_MASK; 10680 } 10681 /* default: override MOD_ABS signalling */ 10682 if (!MOD_ABS(pc)) { 10683 mask16 |= PHY84740_MOD_ABS_OVERRIDE_MASK; 10684 } 10685 10686 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10687 for (ix = 0; ix < NUM_LANES; ix++) { 10688 SOC_IF_ERROR_RETURN 10689 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10690 PHY84740_PMAD_AER_ADDR_REG, ix)); 10691 SOC_IF_ERROR_RETURN 10692 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10693 PHY84740_PMAD_OPTICAL_CFG_REG, 0, 10694 mask16)); 10695 } 10696 } else { 10697 SOC_IF_ERROR_RETURN 10698 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10699 PHY84740_PMAD_OPTICAL_CFG_REG, 0, 10700 mask16)); 10701 } 10702 10703 for (ix = 0; ix < NUM_LANES; ix++) { 10704 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10705 SOC_IF_ERROR_RETURN 10706 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10707 PHY84740_PMAD_AER_ADDR_REG, ix)); 10708 } 10709 10710 /* EDC mode programming sequence*/ 10711 mask16 = 1 << 9; 10712 10713 /* induce LOS condition: toggle register bit 0xc800.9 */ 10714 SOC_IF_ERROR_RETURN 10715 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10716 PHY84740_PMAD_OPTICAL_SIG_LVL_REG,&data16)); 10717 10718 /* only change toggled bit 9 */ 10719 SOC_IF_ERROR_RETURN 10720 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10721 PHY84740_PMAD_OPTICAL_SIG_LVL_REG,~data16,mask16)); 10722 10723 /* program EDC mode */ 10724 SOC_IF_ERROR_RETURN 10725 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xCA1A,(uint16)value, 10726 PHY84740_EDC_MODE_MASK)); 10727 10728 /* remove LOS condition: restore back original value of bit 0xc800.9 */ 10729 SOC_IF_ERROR_RETURN 10730 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10731 PHY84740_PMAD_OPTICAL_SIG_LVL_REG,data16,mask16)); 10732 10733 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 10734 break; 10735 } 10736 } 10737 10738 /* restore software override */ 10739 data16 = 0; 10740 mask16 = PHY84740_RXLOS_OVERRIDE_MASK | PHY84740_MOD_ABS_OVERRIDE_MASK; 10741 if (!RX_LOS(pc)) { 10742 data16 |= PHY84740_RXLOS_OVERRIDE_MASK; 10743 } 10744 /* default: override MOD_ABS signalling */ 10745 if (!MOD_ABS(pc)) { 10746 data16 |= PHY84740_MOD_ABS_OVERRIDE_MASK; 10747 } 10748 10749 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10750 for (ix = 0; ix < NUM_LANES; ix++) { 10751 SOC_IF_ERROR_RETURN 10752 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10753 PHY84740_PMAD_AER_ADDR_REG, ix)); 10754 SOC_IF_ERROR_RETURN 10755 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10756 PHY84740_PMAD_OPTICAL_CFG_REG, 10757 data16, 10758 mask16)); 10759 } 10760 10761 /* point back to lane0 */ 10762 SOC_IF_ERROR_RETURN 10763 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 10764 } else { 10765 /* XXX temp 0xc0c0: RXLOS override: 0x0808 MOD_ABS override */ 10766 SOC_IF_ERROR_RETURN 10767 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 10768 PHY84740_PMAD_OPTICAL_CFG_REG, 10769 data16, 10770 mask16)); 10771 } 10772 10773 return SOC_E_NONE; 10774 } 10775 10776 /* 10777 * enable/disable syncE recoverd clock for 10G/40G modes. 10778 */ 10779 STATIC int 10780 _phy_84741_control_recovery_clock_set(int unit, soc_port_t port, int enable) 10781 { 10782 uint16 data16; 10783 uint16 mask16; 10784 int lane; 10785 phy_ctrl_t *pc; /* PHY software state */ 10786 10787 pc = EXT_PHY_SW_STATE(unit, port); 10788 10789 /* 10790 * 1.CB27[3] = 0 to disable FC recovered clock to appear at TESTP/N. 10791 * 1.CA1D[11] = 0 to disable PLL clock to appear at TESTP/N. 10792 * 1.CA1D[1:0] = 00 to disable bandgap voltage and vco_control voltage appear at TESTP/N. 10793 * 1.CB27[0] = 1 enables rx recovered clock to come out of TESTP/N pads. 10794 * 1.CB26[14:13] = 11 for 156.25Mhz syncE divider select 10795 * 1.CB26[12] = 1 for syncE clock out. 10796 */ 10797 10798 for (lane = 0; lane < NUM_LANES; lane++) { 10799 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10800 SOC_IF_ERROR_RETURN 10801 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10802 PHY84740_PMAD_AER_ADDR_REG, lane)); 10803 } 10804 /* set to 0 in both enable/disable cases */ 10805 10806 /* disable FC recovered clock to appear at TESTP/N. */ 10807 SOC_IF_ERROR_RETURN 10808 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 10809 0,(1 << 3))); 10810 /* disable PLL clock to appear at TESTP/N 10811 * disable bandgap voltage and vco_control voltage appear at TESTP/N 10812 */ 10813 mask16 = (1 << 11) | 0x3; 10814 SOC_IF_ERROR_RETURN 10815 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,0xCA1D, 0,mask16)); 10816 10817 /* enables rx recovered clock to come out of TESTP/N pads*/ 10818 mask16 = PHY84740_RECOVERY_CLK_ENABLE_MASK; 10819 data16 = enable? mask16: 0; 10820 SOC_IF_ERROR_RETURN 10821 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 10822 data16,mask16)); 10823 10824 /* always use bits 14:13 to select the sync clock frequency */ 10825 mask16 = (0x1 << 12); 10826 data16 = mask16; 10827 SOC_IF_ERROR_RETURN 10828 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 10829 data16,mask16)); 10830 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 10831 break; 10832 } 10833 } 10834 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10835 /* point back to lane0 */ 10836 SOC_IF_ERROR_RETURN 10837 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 10838 } 10839 return SOC_E_NONE; 10840 } 10841 10842 /* 10843 * set the frequency of the syncE recoverd clock. 10844 */ 10845 STATIC int 10846 _phy_84741_control_recovery_clock_freq_set(int unit, soc_port_t port, int freq) 10847 { 10848 phy_ctrl_t *pc; /* PHY software state */ 10849 int lane; 10850 uint16 freq_ctrl; 10851 10852 pc = EXT_PHY_SW_STATE(unit, port); 10853 10854 /* 10855 * 1.CB26[14:13] 10856 * Select the frequency of SyncE clock to be sent to the test port: 10857 * 00 : Power down syncE clock dividers 10858 * 01 : 125 MHz (divide by 82.5) 10859 * 10 : 195.3125 MHz (divide by 52.8) 10860 * 11 : 156.25 MHz (divide by 66) 10861 */ 10862 10863 switch (freq) { 10864 case 125000: 10865 freq_ctrl = 0x1; 10866 break; 10867 case 195312: 10868 freq_ctrl = 0x2; 10869 break; 10870 case 156250: 10871 freq_ctrl = 0x3; 10872 break; 10873 default: 10874 freq_ctrl = 0x0; 10875 break; 10876 } 10877 10878 for (lane = 0; lane < NUM_LANES; lane++) { 10879 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10880 SOC_IF_ERROR_RETURN 10881 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10882 PHY84740_PMAD_AER_ADDR_REG, lane)); 10883 } 10884 10885 SOC_IF_ERROR_RETURN 10886 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 10887 PHY84740_RECOVERY_CLK_FREQf(freq_ctrl), 10888 PHY84740_RECOVERY_CLK_FREQ_MASK)); 10889 10890 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 10891 break; 10892 } 10893 } 10894 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10895 /* point back to lane0 */ 10896 SOC_IF_ERROR_RETURN 10897 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 10898 } 10899 return SOC_E_NONE; 10900 } 10901 10902 STATIC int 10903 _phy_84741_control_prbs_tx_invert_data_set(int unit, soc_port_t port, int invert) 10904 { 10905 phy_ctrl_t *pc; /* PHY software state */ 10906 uint16 data16; 10907 10908 pc = EXT_PHY_SW_STATE(unit, port); 10909 10910 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10911 return SOC_E_UNAVAIL; 10912 } else { /* quad-port mode */ 10913 /* tx inversion */ 10914 data16 = invert? PHY84740_USER_PRBS_TX_INVERT: 0; 10915 10916 SOC_IF_ERROR_RETURN 10917 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10918 PHY84740_USER_PRBS_CONTROL_0_REGISTER, data16, 10919 PHY84740_USER_PRBS_TX_INVERT)); 10920 } 10921 return SOC_E_NONE; 10922 } 10923 10924 STATIC int 10925 _phy_84741_control_prbs_rx_invert_data_set(int unit, soc_port_t port, int invert) 10926 { 10927 phy_ctrl_t *pc; /* PHY software state */ 10928 uint16 data16; 10929 uint16 mask16; 10930 10931 pc = EXT_PHY_SW_STATE(unit, port); 10932 10933 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10934 return SOC_E_UNAVAIL; 10935 } else { /* quad-port mode */ 10936 /* rx inversion */ 10937 data16 = invert? PHY84740_USER_PRBS_RX_INVERT: 0; 10938 mask16 = PHY84740_USER_PRBS_RX_INVERT; 10939 SOC_IF_ERROR_RETURN 10940 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10941 PHY84740_USER_PRBS_CONTROL_0_REGISTER, data16, 10942 mask16)); 10943 } 10944 return SOC_E_NONE; 10945 } 10946 10947 STATIC int 10948 _phy_84741_control_prbs_polynomial_set(int unit, soc_port_t port,int poly_ctrl, 10949 int tx) /* tx or rx */ 10950 { 10951 phy_ctrl_t *pc; /* PHY software state */ 10952 uint16 data16; 10953 uint16 mask16; 10954 10955 /* 10956 * poly_ctrl: 10957 * 0x0 = prbs7 10958 * 0x1 = prbs15 10959 * 0x2 = prbs23 10960 * 0x3 = prbs31 10961 */ 10962 pc = EXT_PHY_SW_STATE(unit, port); 10963 10964 if (PHY84740_SINGLE_PORT_MODE(pc)) { 10965 /* only two types available PRBS9 and PRBS31 */ 10966 if (poly_ctrl == 3) { 10967 data16 = PHY84740_40G_PRBS31; 10968 } else { 10969 data16 = PHY84740_40G_PRBS9; 10970 } 10971 10972 SOC_IF_ERROR_RETURN 10973 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 10974 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 10975 data16, 10976 PHY84740_40G_PRBS9 | PHY84740_40G_PRBS31)); 10977 } else { /* quad-port mode */ 10978 /* 001 : prbs7 10979 010 : prbs9 10980 011 : prbs11 10981 100 : prbs15 10982 101 : prbs23 10983 110 : prbs31 10984 */ 10985 10986 if (poly_ctrl == 0) { 10987 data16 = 1; 10988 } else if (poly_ctrl == 1) { 10989 data16 = 4; 10990 } else if (poly_ctrl == 2) { 10991 data16 = 5; 10992 } else if (poly_ctrl == 3) { 10993 data16 = 6; 10994 } else { 10995 return SOC_E_PARAM; 10996 } 10997 mask16 = PHY84740_USER_PRBS_TYPE_MASK; 10998 10999 /* default is tx */ 11000 if (!tx) { /* rx */ 11001 data16 = data16 << 12; 11002 mask16 = mask16 << 12; 11003 } 11004 11005 /* both tx/rx types */ 11006 SOC_IF_ERROR_RETURN 11007 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11008 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 11009 data16, mask16)); 11010 } 11011 return SOC_E_NONE; 11012 } 11013 STATIC int 11014 _phy_84741_control_prbs_enable_set(int unit, soc_port_t port, int enable) 11015 { 11016 phy_ctrl_t *pc; /* PHY software state */ 11017 int lane; 11018 int repeater_mode; 11019 uint16 data16; 11020 11021 pc = EXT_PHY_SW_STATE(unit, port); 11022 11023 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11024 for (lane = 0; lane < NUM_LANES; lane++) { 11025 SOC_IF_ERROR_RETURN 11026 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11027 PHY84740_PMAD_AER_ADDR_REG, lane)); 11028 11029 /* GENSIG_8071_REGISTER Clocks enable */ 11030 SOC_IF_ERROR_RETURN 11031 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11032 PHY84740_GENSIG_8071_REGISTER, enable? 0x3:0)); 11033 11034 /* RESET_CONTROL_REGISTER */ 11035 SOC_IF_ERROR_RETURN 11036 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11037 PHY84740_RESET_CONTROL_REGISTER, 0x0)); 11038 11039 /* DATA_MUX_SEL_CNTRL_REGISTER */ 11040 SOC_IF_ERROR_RETURN 11041 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd58, enable?0x2:0)); 11042 11043 /* 40G_PRBS_PATTERN_TESTING_CONTROL_STATUS */ 11044 SOC_IF_ERROR_RETURN 11045 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11046 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, 11047 enable?PHY84740_40G_PRBS_ENABLE:0, 11048 0xf)); 11049 } 11050 /* point back to lane0 */ 11051 SOC_IF_ERROR_RETURN 11052 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 11053 } else { /* quad-port mode */ 11054 SOC_IF_ERROR_RETURN 11055 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc81d, &data16)); 11056 11057 repeater_mode = ((data16 & 0x6) == 0x6)? TRUE: FALSE; 11058 if (repeater_mode) { 11059 /* Enable retimer prbs clocks inside SFI */ 11060 SOC_IF_ERROR_RETURN 11061 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11062 PHY84740_GENSIG_8071_REGISTER, 11063 enable?0x3:0,0x3)); 11064 11065 /* Enable the retimer datapath */ 11066 SOC_IF_ERROR_RETURN 11067 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd58, 11068 enable?0x2:0,0x3)); 11069 } 11070 /* clear PRBS control if disabled */ 11071 if (!enable) { 11072 SOC_IF_ERROR_RETURN 11073 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11074 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 0, 11075 PHY84740_USER_PRBS_TYPE_MASK | 11076 PHY84740_USER_PRBS_TYPE_MASK << 12)); /* rx type*/ 11077 } 11078 11079 /* program the PRBS enable */ 11080 SOC_IF_ERROR_RETURN 11081 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11082 PHY84740_USER_PRBS_CONTROL_0_REGISTER, 11083 enable? PHY84740_USER_PRBS_ENABLE: 0,PHY84740_USER_PRBS_ENABLE)); 11084 } 11085 return SOC_E_NONE; 11086 } 11087 11088 STATIC int 11089 _phy_84741_control_prbs_enable_get(int unit, soc_port_t port, uint32 *value) 11090 { 11091 uint16 data16; 11092 phy_ctrl_t *pc; /* PHY software state */ 11093 11094 pc = EXT_PHY_SW_STATE(unit, port); 11095 11096 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11097 SOC_IF_ERROR_RETURN 11098 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11099 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, &data16)); 11100 if ((data16 & PHY84740_40G_PRBS_ENABLE) == PHY84740_40G_PRBS_ENABLE) { 11101 *value = TRUE; 11102 } else { 11103 *value = FALSE; 11104 } 11105 } else { /* quad-port mode */ 11106 SOC_IF_ERROR_RETURN 11107 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11108 PHY84740_USER_PRBS_CONTROL_0_REGISTER, &data16)); 11109 if (data16 & PHY84740_USER_PRBS_ENABLE) { 11110 *value = TRUE; 11111 } else { 11112 *value = FALSE; 11113 } 11114 } 11115 11116 return SOC_E_NONE; 11117 } 11118 STATIC int 11119 _phy_84741_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value) 11120 { 11121 phy_ctrl_t *pc; /* PHY software state */ 11122 uint16 poly_ctrl; 11123 11124 pc = EXT_PHY_SW_STATE(unit, port); 11125 11126 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11127 SOC_IF_ERROR_RETURN 11128 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11129 PHY84740_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS, &poly_ctrl)); 11130 if (poly_ctrl & PHY84740_40G_PRBS31) { 11131 *value = 3; 11132 } else { 11133 *value = 0; /* 0 indicates PRBS9 */ 11134 } 11135 } else { /* quad-port mode */ 11136 SOC_IF_ERROR_RETURN 11137 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11138 PHY84740_USER_PRBS_CONTROL_0_REGISTER, &poly_ctrl)); 11139 poly_ctrl &= PHY84740_USER_PRBS_TYPE_MASK; 11140 11141 if (poly_ctrl == 1) { 11142 *value = 0; 11143 } else if (poly_ctrl == 4) { 11144 *value = 1; 11145 } else if (poly_ctrl == 5) { 11146 *value = 2; 11147 } else if (poly_ctrl == 6) { 11148 *value = 3; 11149 } else { 11150 *value = poly_ctrl; 11151 } 11152 } 11153 11154 return SOC_E_NONE; 11155 } 11156 11157 STATIC int 11158 _phy_84741_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value) 11159 { 11160 phy_ctrl_t *pc; /* PHY software state */ 11161 uint16 data16; 11162 11163 pc = EXT_PHY_SW_STATE(unit, port); 11164 11165 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11166 return SOC_E_UNAVAIL; 11167 } else { /* quad-port mode */ 11168 SOC_IF_ERROR_RETURN 11169 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11170 PHY84740_USER_PRBS_CONTROL_0_REGISTER, &data16)); 11171 if (data16 & PHY84740_USER_PRBS_TX_INVERT) { 11172 *value = TRUE; 11173 } else { 11174 *value = FALSE; 11175 } 11176 } 11177 return SOC_E_NONE; 11178 } 11179 11180 STATIC int 11181 _phy_84741_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value) 11182 { 11183 phy_ctrl_t *pc; /* PHY software state */ 11184 uint16 data16; 11185 int lane; 11186 11187 pc = EXT_PHY_SW_STATE(unit, port); 11188 11189 *value = 0; 11190 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11191 for (lane = 0; lane < 4; lane++) { 11192 SOC_IF_ERROR_RETURN 11193 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11194 PHY84740_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0 + lane, &data16)); 11195 if (!(data16 & 0xfff)) { 11196 /* PRBS is in sync */ 11197 continue; 11198 } else { 11199 /* Get errors */ 11200 *value += (data16 & 0xfff); 11201 } 11202 } 11203 } else { /* quad-port mode */ 11204 SOC_IF_ERROR_RETURN 11205 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11206 PHY84740_USER_PRBS_STATUS_0_REGISTER, &data16)); 11207 if (data16 == 0x8000) { /* PRBS lock and error free */ 11208 *value = 0; 11209 } else if (!(data16 & 0x8000)) { 11210 *value = -1; 11211 } else { 11212 *value = data16 & 0x7fff; 11213 } 11214 } 11215 11216 return SOC_E_NONE; 11217 } 11218 11219 STATIC int 11220 _phy_84741_control_edc_mode_get(int unit, soc_port_t port, uint32 *value) 11221 { 11222 uint16 data16; 11223 phy_ctrl_t *pc; /* PHY software state */ 11224 11225 pc = EXT_PHY_SW_STATE(unit, port); 11226 11227 /* get EDC mode */ 11228 SOC_IF_ERROR_RETURN 11229 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xCA1A,&data16)); 11230 11231 *value = data16 & PHY84740_EDC_MODE_MASK; 11232 11233 return SOC_E_NONE; 11234 } 11235 11236 11237 STATIC int 11238 _phy_84741_remote_loopback_set(int unit, soc_port_t port,int intf,uint32 enable) 11239 { 11240 phy_ctrl_t *pc; /* PHY software state */ 11241 int lane; 11242 11243 pc = EXT_PHY_SW_STATE(unit, port); 11244 11245 if (intf == PHY_DIAG_INTF_SYS) { 11246 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 11247 for (lane = 0; lane < NUM_LANES; lane++) { 11248 /* targeted to the system side */ 11249 SOC_IF_ERROR_RETURN 11250 (PHY84740_XFI(unit,pc)); 11251 11252 SOC_IF_ERROR_RETURN 11253 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11254 PHY84740_PMAD_AER_ADDR_REG, lane)); 11255 SOC_IF_ERROR_RETURN 11256 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a, 11257 enable? 1:0, 1)); 11258 11259 /* targeted to the system side, switch back */ 11260 SOC_IF_ERROR_RETURN 11261 (PHY84740_MMF(unit,pc)); 11262 } 11263 /* point back to lane0 */ 11264 SOC_IF_ERROR_RETURN 11265 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 11266 } else { 11267 SOC_IF_ERROR_RETURN 11268 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xcd0a, 11269 enable? 1:0, 1)); 11270 } 11271 } 11272 return SOC_E_NONE; 11273 } 11274 11275 STATIC int 11276 _phy_84741_debug_info(int unit, soc_port_t port) 11277 { 11278 phy_ctrl_t *pc; 11279 phy_ctrl_t *int_pc; 11280 int lane; 11281 const char *if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 11282 struct dbgi { 11283 uint16 ucode_rev; 11284 uint16 pl2_reg; 11285 uint16 pma_mii_stat; 11286 uint16 tx_polarity_reg[NUM_LANES]; 11287 uint16 rx_polarity_reg[NUM_LANES]; 11288 soc_port_if_t iif; 11289 int ilink; 11290 int ispeed; 11291 int ian; 11292 int ian_done; 11293 } dbgi; 11294 11295 11296 pc = EXT_PHY_SW_STATE(unit, port); 11297 int_pc = INT_PHY_SW_STATE(unit, port); 11298 11299 SOC_IF_ERROR_RETURN 11300 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &dbgi.ucode_rev)); 11301 11302 SOC_IF_ERROR_RETURN 11303 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_LANE0_L2P_REG, &dbgi.pl2_reg)); 11304 11305 for (lane = 0; lane < NUM_LANES; lane++) { 11306 /* point to the each lane starting at lane0 */ 11307 SOC_IF_ERROR_RETURN 11308 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11309 PHY84740_PMAD_AER_ADDR_REG, P2L_MAP(pc, lane))); 11310 11311 SOC_IF_ERROR_RETURN( 11312 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG, 11313 &dbgi.tx_polarity_reg[lane])); 11314 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 11315 SOC_IF_ERROR_RETURN( 11316 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_DIG_CTRL_REG, 11317 &dbgi.rx_polarity_reg[lane])); 11318 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 11319 } 11320 11321 LOG_CLI((BSL_META_U(unit, 11322 "Port %-3d(mdio=0x%x): ver(1.%04x)=0x%x, single lpmode=%d, " 11323 "p2lreg(1.%04x)=0x%04x, p2lmap=%d%d%d%d\n"), 11324 port, pc->phy_id, 0xce00, dbgi.ucode_rev, 11325 SINGLE_LPMODE(pc), 11326 PHY84740_PMAD_LANE0_L2P_REG, dbgi.pl2_reg, 11327 P2L_MAP(pc, 3), P2L_MAP(pc, 2), P2L_MAP(pc, 1), P2L_MAP(pc, 0))); 11328 11329 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11330 SOC_IF_ERROR_RETURN 11331 (READ_PHY84740_PMA_PMD_STATr(unit, pc, &dbgi.pma_mii_stat)); 11332 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &dbgi.ilink)); 11333 LOG_CLI((BSL_META_U(unit, 11334 " pma_link(1.0x%04x)=0x%0x(%s), serdes_link=%s\n"), 11335 1, dbgi.pma_mii_stat, 11336 (dbgi.pma_mii_stat & MII_STAT_LA) ? "up" : "down", 11337 dbgi.ilink ? "up" : "down")); 11338 LOG_CLI((BSL_META_U(unit, 11339 " line polarity(1.%04x)=(ln0=%04x, " 11340 "ln1=%04x, ln2=%04x, ln3=%04x)\n"), 11341 PHY84740_DIG_CTRL_REG, 11342 dbgi.tx_polarity_reg[0], dbgi.tx_polarity_reg[1], 11343 dbgi.tx_polarity_reg[2], dbgi.tx_polarity_reg[3])); 11344 LOG_CLI((BSL_META_U(unit, 11345 " sys polarity(1.%04x)=(ln0=%04x, " 11346 "ln1=%04x, ln2=%04x, ln3=%04x)\n"), 11347 PHY84740_DIG_CTRL_REG, 11348 dbgi.rx_polarity_reg[0], dbgi.rx_polarity_reg[1], 11349 dbgi.tx_polarity_reg[2], dbgi.rx_polarity_reg[3])); 11350 } else { 11351 LOG_CLI((BSL_META_U(unit, 11352 " line polarity(1.%04x)=%04x\n"), 11353 PHY84740_DIG_CTRL_REG, dbgi.tx_polarity_reg[0])); 11354 LOG_CLI((BSL_META_U(unit, 11355 " sys polarity(1.%04x)=%04x\n"), 11356 PHY84740_DIG_CTRL_REG, dbgi.rx_polarity_reg[0])); 11357 } 11358 if (int_pc) { 11359 SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &dbgi.iif)); 11360 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &dbgi.ispeed)); 11361 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_GET(int_pc->pd, unit, port, &dbgi.ian, &dbgi.ian_done)); 11362 LOG_CLI((BSL_META_U(unit, 11363 " Internal: type=%s, speed=%d, an=%d\n"), 11364 if_names[dbgi.iif], 11365 dbgi.ispeed, dbgi.ian)); 11366 } 11367 LOG_CLI((BSL_META_U(unit, 11368 "=======\n"))); 11369 return SOC_E_NONE; 11370 } 11371 11372 /* 11373 * Function: 11374 * phy_84741_control_set 11375 * Purpose: 11376 * Configure PHY device specific control fucntion. 11377 * Parameters: 11378 * unit - StrataSwitch unit #. 11379 * port - StrataSwitch port #. 11380 * type - Control to update 11381 * value - New setting for the control 11382 * Returns: 11383 * SOC_E_NONE 11384 */ 11385 STATIC int 11386 _phy_84741_control_set(int unit, soc_port_t port, int intf,int lane, 11387 soc_phy_control_t type, uint32 value) 11388 { 11389 phy_ctrl_t *pc; /* PHY software state */ 11390 phy_ctrl_t *int_pc; 11391 int rv; 11392 11393 pc = EXT_PHY_SW_STATE(unit, port); 11394 int_pc = INT_PHY_SW_STATE(unit, port); 11395 11396 PHY_CONTROL_TYPE_CHECK(type); 11397 11398 rv = SOC_E_UNAVAIL; 11399 if (intf == PHY_DIAG_INTF_SYS) { 11400 /* if is targeted to the system side */ 11401 SOC_IF_ERROR_RETURN 11402 (PHY84740_XFI(unit,pc)); 11403 } 11404 switch(type) { 11405 case SOC_PHY_CONTROL_PREEMPHASIS: 11406 /* fall through */ 11407 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 11408 /* fall through */ 11409 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 11410 /* fall through */ 11411 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 11412 /* fall through */ 11413 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 11414 /* fall through */ 11415 case SOC_PHY_CONTROL_DRIVER_CURRENT: 11416 /* fall through */ 11417 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 11418 /* fall through */ 11419 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 11420 /* fall through */ 11421 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 11422 /* fall through */ 11423 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 11424 /* fall through */ 11425 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 11426 /* fall through */ 11427 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 11428 /* fall through */ 11429 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 11430 /* fall through */ 11431 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 11432 /* fall through */ 11433 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 11434 rv = _phy_84741_control_tx_driver_set(unit, port, intf, type, value); 11435 break; 11436 case SOC_PHY_CONTROL_EDC_MODE: 11437 rv = _phy_84741_control_edc_mode_set(unit,port,value); 11438 break; 11439 case SOC_PHY_CONTROL_CLOCK_ENABLE: 11440 rv = _phy_84741_control_recovery_clock_set(unit,port,value); 11441 break; 11442 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 11443 rv = _phy_84741_control_recovery_clock_freq_set(unit,port,value); 11444 break; 11445 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 11446 /* on line side, rx poly type is auto-detected. On system side, 11447 * need to enable the rx type as well. 11448 */ 11449 rv = _phy_84741_control_prbs_polynomial_set(unit, port, value, TRUE); 11450 if (intf == PHY_DIAG_INTF_SYS) { 11451 rv = _phy_84741_control_prbs_polynomial_set(unit, port,value,FALSE); 11452 } 11453 break; 11454 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 11455 /* on line side, rx invertion is auto-detected. On system side, 11456 * need to enable the rx as well. 11457 */ 11458 rv = _phy_84741_control_prbs_tx_invert_data_set(unit, port, value); 11459 if (intf == PHY_DIAG_INTF_SYS) { 11460 rv = _phy_84741_control_prbs_rx_invert_data_set(unit, port, value); 11461 } 11462 break; 11463 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 11464 /* fall through */ 11465 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 11466 /* tx/rx is enabled at the same time. no seperate control */ 11467 rv = _phy_84741_control_prbs_enable_set(unit, port, value); 11468 break; 11469 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 11470 rv = _phy_84741_remote_loopback_set(unit, port,PHY_DIAG_INTF_SYS,value); 11471 break; 11472 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 11473 if(int_pc) { 11474 SOC_IF_ERROR_RETURN 11475 (PHY_CONTROL_SET(int_pc->pd, unit, port, type, value)); 11476 SOFTWARE_RX_LOS(pc) = value ? 1 : 0; 11477 rv = SOC_E_NONE; 11478 } 11479 break; 11480 case SOC_PHY_CONTROL_DUMP: 11481 rv = _phy_84741_debug_info(unit, port); 11482 break; 11483 #ifdef PHY84756_UNTESTED_CODE 11484 case SOC_PHY_CONTROL_TX_POLARITY: 11485 if (PHY84740_IS_QUADRA(devid)) { /* Quadra */ 11486 rv = phy_84741_tx_polarity_flip_set(unit, port, value); 11487 } else { 11488 rv = SOC_E_UNAVAIL; 11489 } 11490 break; 11491 case SOC_PHY_CONTROL_RX_POLARITY: 11492 if (PHY84740_IS_QUADRA(devid)) { /* Quadra */ 11493 rv = phy_84741_rx_polarity_flip_set(unit, port, value); 11494 } else { 11495 rv = SOC_E_UNAVAIL; 11496 } 11497 break; 11498 #endif /* PHY84756_UNTESTED_CODE */ 11499 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 11500 rv = _phy_84741_squelch_enable(unit, port, intf, value, FALSE); 11501 break; 11502 default: 11503 rv = SOC_E_UNAVAIL; 11504 break; 11505 } 11506 if (intf == PHY_DIAG_INTF_SYS) { 11507 /* if it is targeted to the system side, switch back */ 11508 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 11509 } 11510 return rv; 11511 } 11512 11513 #ifdef PHY84756_UNTESTED_CODE 11514 STATIC int phy_84741_tx_polarity_flip_set(int unit, int port, uint32 value) 11515 { 11516 int lane; 11517 phy_ctrl_t *pc; 11518 uint16 tx_pol; 11519 uint16 data16, mask16; 11520 11521 pc = EXT_PHY_SW_STATE(unit, port); 11522 tx_pol = value; 11523 11524 /* get the reset default value. The 84740 device has the TX polarity flipped 11525 * by default. Construct the init default value 11526 */ 11527 11528 mask16 = PHY84740_TX_POLARITY_FLIP_MASK; 11529 11530 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 11531 for (lane = 0; lane < NUM_LANES; lane++) { 11532 data16 = 0; 11533 11534 /* point to the each lane starting at lane0 */ 11535 SOC_IF_ERROR_RETURN 11536 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11537 PHY84740_PMAD_AER_ADDR_REG, 11538 P2L_MAP(pc, lane))); 11539 11540 if ((tx_pol == POL_CONFIG_ALL_LANES) || 11541 ((tx_pol & POL_CONFIG_LANE_MASK(lane)) == 11542 POL_CONFIG_LANE_MASK(lane))) { 11543 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 11544 } 11545 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11546 PHY84740_DIG_CTRL_REG, 11547 data16, 11548 mask16)); 11549 } 11550 /* point back to lane0 */ 11551 SOC_IF_ERROR_RETURN 11552 (WRITE_PHY84740_MMF_PMA_PMD_REG 11553 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 11554 } else { /* quad-port mode */ 11555 data16 = 0; 11556 tx_pol = PHY84740_10G_POL_CFG_GET(pc, tx_pol); 11557 if (tx_pol) { 11558 data16 = PHY84740_TX_POLARITY_FLIP_MASK; 11559 } 11560 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 11561 (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16)); 11562 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 11563 (unit, pc, PHY84740_DIG_CTRL_REG, &data16)); 11564 } 11565 11566 return SOC_E_NONE; 11567 } 11568 11569 STATIC int phy_84741_rx_polarity_flip_set(int unit, int port, uint32 value) 11570 { 11571 int lane; 11572 phy_ctrl_t *pc; 11573 uint16 rx_pol; 11574 uint16 data16, mask16; 11575 11576 pc = EXT_PHY_SW_STATE(unit, port); 11577 11578 rx_pol = value; 11579 /* get the reset default value. The 84740 device has the TX polarity flipped 11580 * by default. Construct the init default value 11581 */ 11582 mask16 = PHY84740_RX_POLARITY_FLIP_MASK; 11583 11584 if ((PHY84740_SINGLE_PORT_MODE(pc))) { 11585 for (lane = 0; lane < NUM_LANES; lane++) { 11586 data16 = 0; 11587 11588 /* point to the each lane starting at lane0 */ 11589 SOC_IF_ERROR_RETURN 11590 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11591 PHY84740_PMAD_AER_ADDR_REG, 11592 P2L_MAP(pc, lane))); 11593 if ((rx_pol == POL_CONFIG_ALL_LANES) 11594 || ((rx_pol & POL_CONFIG_LANE_MASK(lane)) == 11595 POL_CONFIG_LANE_MASK(lane))) { 11596 data16 |= PHY84740_RX_POLARITY_FLIP_MASK; 11597 } 11598 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 11599 PHY84740_DIG_CTRL_REG, 11600 data16, 11601 mask16)); 11602 } 11603 /* point back to lane0 */ 11604 SOC_IF_ERROR_RETURN 11605 (WRITE_PHY84740_MMF_PMA_PMD_REG 11606 (unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 11607 } else { /* quad-port mode */ 11608 data16 = 0; 11609 rx_pol = PHY84740_10G_POL_CFG_GET(pc, rx_pol); 11610 if (rx_pol) { 11611 data16 = PHY84740_RX_POLARITY_FLIP_MASK; 11612 } 11613 SOC_IF_ERROR_RETURN(MODIFY_PHY84740_MMF_PMA_PMD_REG 11614 (unit, pc, PHY84740_DIG_CTRL_REG, data16, mask16)); 11615 SOC_IF_ERROR_RETURN(READ_PHY84740_MMF_PMA_PMD_REG 11616 (unit, pc, PHY84740_DIG_CTRL_REG, &data16)); 11617 } 11618 return SOC_E_NONE; 11619 } 11620 #endif /* PHY84756_UNTESTED_CODE */ 11621 11622 STATIC int 11623 phy_84741_control_set(int unit, soc_port_t port, 11624 soc_phy_control_t type, uint32 value) 11625 { 11626 phy_ctrl_t *pc; /* PHY software state */ 11627 int intf; 11628 11629 pc = EXT_PHY_SW_STATE(unit, port); 11630 11631 intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL))? 11632 PHY_DIAG_INTF_SYS: PHY_DIAG_INTF_LINE; 11633 SOC_IF_ERROR_RETURN 11634 (_phy_84741_control_set(unit, port, intf, 11635 PHY_DIAG_LN_DFLT, type, value)); 11636 return SOC_E_NONE; 11637 } 11638 /* 11639 * Function: 11640 * phy_84741_control_get 11641 * Purpose: 11642 * Get current control settign of the PHY. 11643 * Parameters: 11644 * unit - StrataSwitch unit #. 11645 * port - StrataSwitch port #. 11646 * type - Control to update 11647 * value - (OUT)Current setting for the control 11648 * Returns: 11649 * SOC_E_NONE 11650 */ 11651 STATIC int 11652 _phy_84741_control_get(int unit, soc_port_t port, int intf,int lane, 11653 soc_phy_control_t type, uint32 *value) 11654 { 11655 phy_ctrl_t *pc; /* PHY software state */ 11656 int rv; 11657 uint16 data16; 11658 11659 pc = EXT_PHY_SW_STATE(unit, port); 11660 11661 PHY_CONTROL_TYPE_CHECK(type); 11662 11663 if (intf == PHY_DIAG_INTF_SYS) { 11664 /* targeted to the system side */ 11665 SOC_IF_ERROR_RETURN(PHY84740_XFI(unit, pc)); 11666 } 11667 rv = SOC_E_UNAVAIL; 11668 switch(type) { 11669 case SOC_PHY_CONTROL_PREEMPHASIS: 11670 /* fall through */ 11671 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 11672 /* fall through */ 11673 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 11674 /* fall through */ 11675 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 11676 /* fall through */ 11677 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 11678 /* fall through */ 11679 case SOC_PHY_CONTROL_DRIVER_CURRENT: 11680 /* fall through */ 11681 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 11682 /* fall through */ 11683 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 11684 /* fall through */ 11685 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 11686 /* fall through */ 11687 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 11688 /* fall through */ 11689 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 11690 /* fall through */ 11691 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 11692 /* fall through */ 11693 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 11694 /* fall through */ 11695 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 11696 /* fall through */ 11697 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 11698 rv = _phy_84741_control_tx_driver_get(unit, port, type, value); 11699 break; 11700 case SOC_PHY_CONTROL_EDC_MODE: 11701 rv = _phy_84741_control_edc_mode_get(unit,port,value); 11702 break; 11703 case SOC_PHY_CONTROL_CLOCK_ENABLE: 11704 SOC_IF_ERROR_RETURN 11705 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 11706 &data16)); 11707 *value = (data16 & PHY84740_RECOVERY_CLK_ENABLE_MASK)? TRUE: FALSE; 11708 rv = SOC_E_NONE; 11709 break; 11710 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 11711 rv = _phy_84741_control_prbs_polynomial_get(unit, port, value); 11712 break; 11713 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 11714 rv = _phy_84741_control_prbs_tx_invert_data_get(unit, port, value); 11715 break; 11716 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 11717 /* fall through */ 11718 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 11719 rv = _phy_84741_control_prbs_enable_get(unit, port, value); 11720 break; 11721 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 11722 rv = _phy_84741_control_prbs_rx_status_get(unit, port, value); 11723 break; 11724 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 11725 SOC_IF_ERROR_RETURN 11726 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 11727 &data16)); 11728 switch ((data16 >> PHY84740_RECOVERY_CLK_FREQ_SHIFT) & 0x3) { 11729 case 0x1: 11730 *value = 125000; 11731 break; 11732 case 0x2: 11733 *value = 195312; 11734 break; 11735 case 0x3: 11736 *value = 156250; 11737 break; 11738 default: 11739 *value = 0x0; 11740 break; 11741 } 11742 rv = SOC_E_NONE; 11743 break; 11744 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 11745 *value = SOFTWARE_RX_LOS(pc); 11746 rv = SOC_E_NONE; 11747 break; 11748 11749 default: 11750 rv = SOC_E_UNAVAIL; 11751 break; 11752 } 11753 11754 if (intf == PHY_DIAG_INTF_SYS) { 11755 /* if it is targeted to the system side, switch back */ 11756 SOC_IF_ERROR_RETURN(PHY84740_MMF(unit, pc)); 11757 } 11758 return rv; 11759 } 11760 STATIC int 11761 phy_84741_control_get(int unit, soc_port_t port, 11762 soc_phy_control_t type, uint32 *value) 11763 { 11764 int intf; 11765 phy_ctrl_t *pc; /* PHY software state */ 11766 11767 pc = EXT_PHY_SW_STATE(unit, port); 11768 11769 intf = (REVERSE_MODE(pc) || (pc->flags & PHYCTRL_SYS_SIDE_CTRL)) ? 11770 PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 11771 11772 SOC_IF_ERROR_RETURN 11773 (_phy_84741_control_get(unit, port, intf, 11774 PHY_DIAG_LN_DFLT, type, value)); 11775 return SOC_E_NONE; 11776 } 11777 11778 STATIC int 11779 phy_84741_diag_ctrl( 11780 int unit, /* unit */ 11781 soc_port_t port, /* port */ 11782 uint32 inst, /* the specific device block the control action directs to */ 11783 int op_type, /* operation types: read,write or command sequence */ 11784 int op_cmd, /* command code */ 11785 void *arg) /* command argument */ 11786 { 11787 int lane; 11788 int intf; 11789 11790 LOG_INFO(BSL_LS_SOC_PHY, 11791 (BSL_META_U(unit, 11792 "phy_84741_diag_ctrl: u=%d p=%d ctrl=0x%x\n"), 11793 unit, port,op_cmd)); 11794 11795 lane = PHY_DIAG_INST_LN(inst); 11796 intf = PHY_DIAG_INST_INTF(inst); 11797 if (intf == PHY_DIAG_INTF_DFLT) { 11798 intf = PHY_DIAG_INTF_LINE; 11799 } 11800 11801 if (op_type == PHY_DIAG_CTRL_GET) { 11802 SOC_IF_ERROR_RETURN 11803 (_phy_84741_control_get(unit, port, intf, lane, 11804 op_cmd,(uint32 *)arg)); 11805 } else if (op_type == PHY_DIAG_CTRL_SET) { 11806 SOC_IF_ERROR_RETURN 11807 (_phy_84741_control_set(unit, port, intf, lane, 11808 op_cmd, PTR_TO_INT(arg))); 11809 } 11810 return SOC_E_NONE; 11811 } 11812 11813 /* 11814 * Function: 11815 * phy_84741_speed_set 11816 * Purpose: 11817 * Set PHY speed 11818 * Parameters: 11819 * unit - StrataSwitch unit #. 11820 * port - StrataSwitch port #. 11821 * speed - link speed in Mbps 11822 * Returns: 11823 * SOC_E_NONE 11824 */ 11825 11826 STATIC int phy_84741_speed_set(int unit, soc_port_t port, int speed) 11827 { 11828 phy_ctrl_t *pc; 11829 phy_ctrl_t *int_pc; 11830 int rv = SOC_E_NONE; 11831 11832 COMPILER_REFERENCE(unit); 11833 COMPILER_REFERENCE(port); 11834 11835 int_pc = INT_PHY_SW_STATE(unit, port); 11836 pc = EXT_PHY_SW_STATE(unit, port); 11837 11838 LOG_INFO(BSL_LS_SOC_PHY, 11839 (BSL_META_U(unit, 11840 "phy_84741_speed_set: u=%d p=%d speed=%d\n"), 11841 unit, port,speed)); 11842 11843 if (FCMAP_PASSTHROUGH(pc)) { 11844 return SOC_E_NONE; 11845 } 11846 11847 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11848 if (speed != 40000) { 11849 return SOC_E_PARAM; 11850 } 11851 11852 /* single port mode: doesn't use PCS. should be already in repeater mode */ 11853 /* it is always in 40G speed, make sure internal device is in 40G */ 11854 if (NULL != int_pc) { 11855 if (REVERSE_MODE(pc)) { 11856 if (IS_HG_PORT(unit, port)) { 11857 SOC_IF_ERROR_RETURN 11858 (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_KR4)); 11859 } else { 11860 SOC_IF_ERROR_RETURN 11861 (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SR4)); 11862 } 11863 } else { 11864 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 11865 rv = PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR); 11866 } 11867 } 11868 11869 rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed); 11870 } 11871 return rv; 11872 } 11873 11874 /* quad lane mode */ 11875 if ((!(speed == 10000 || speed == 1000)) && 11876 (!PCS_REPEATER(pc))) { 11877 return SOC_E_PARAM; 11878 } 11879 11880 if (speed == 10000) { 11881 SOC_IF_ERROR_RETURN 11882 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL_REG, 11883 MII_CTRL_SS_MSB | MII_CTRL_SS_LSB)); 11884 SOC_IF_ERROR_RETURN 11885 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL2_REG, 11886 PHY84740_PMAD_CTRL2r_PMA_TYPE_10G_LRM, 11887 PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK)); 11888 11889 } else { 11890 SOC_IF_ERROR_RETURN 11891 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, PHY84740_PMAD_CTRL2_REG, 11892 PHY84740_PMAD_CTRL2r_PMA_TYPE_1G_KX, 11893 PHY84740_PMAD_CTRL2r_PMA_TYPE_MASK)); 11894 SOC_IF_ERROR_RETURN 11895 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit,pc, MII_CTRL_REG, 11896 0, MII_CTRL_SS_LSB)); 11897 } 11898 /* need to set the internal phy's speed accordingly */ 11899 11900 if (NULL != int_pc) { 11901 if (REVERSE_MODE(pc)) { 11902 SOC_IF_ERROR_RETURN 11903 (PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_SR)); 11904 } else { 11905 /* For long XFI channel, it is best to use SFP+ DAC mode 11906 * in the serdes side to provide adequate Rx equalization 11907 */ 11908 if (soc_property_port_get(unit, port, spn_PHY_LONG_XFI, 0)) { 11909 if (!PHY84740_SINGLE_PORT_MODE(pc)) { 11910 rv = PHY_INTERFACE_SET(int_pc->pd, unit, port, SOC_PORT_IF_CR); 11911 } 11912 } 11913 } 11914 rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed); 11915 } 11916 return rv; 11917 } 11918 11919 /* 11920 * Function: 11921 * phy_84741_speed_get 11922 * Purpose: 11923 * Get PHY speed 11924 * Parameters: 11925 * unit - StrataSwitch unit #. 11926 * port - StrataSwitch port #. 11927 * speed - current link speed in Mbps 11928 * Returns: 11929 * SOC_E_NONE 11930 */ 11931 11932 STATIC int 11933 phy_84741_speed_get(int unit, soc_port_t port, int *speed) 11934 { 11935 phy_ctrl_t *pc; 11936 uint16 speed_val; 11937 11938 pc = EXT_PHY_SW_STATE(unit, port); 11939 11940 if (PCS_REPEATER(pc)) { 11941 phy_ctrl_t *int_pc; 11942 11943 int_pc = INT_PHY_SW_STATE(unit, port); 11944 SOC_IF_ERROR_RETURN 11945 (PHY_SPEED_GET(int_pc->pd, unit, port, speed)); 11946 return SOC_E_NONE; 11947 } else if (FCMAP_PASSTHROUGH(pc)) { 11948 *speed = 10000; 11949 return SOC_E_NONE; 11950 } 11951 11952 /* this register contains the speed info for both single/quad modes */ 11953 SOC_IF_ERROR_RETURN 11954 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 0xc81f, &speed_val)); 11955 11956 if (speed_val & (1 << 5)) { 11957 *speed = 40000; 11958 } else if (speed_val & (1 << 4)) { 11959 *speed = 10000; 11960 } else if (speed_val & (1 << 2)) { 11961 *speed = 1000; 11962 } else { /* default */ 11963 if (PHY84740_SINGLE_PORT_MODE(pc)) { 11964 *speed = 40000; 11965 } else { 11966 *speed = 10000; 11967 } 11968 } 11969 return SOC_E_NONE; 11970 } 11971 11972 /* 11973 * Function: 11974 * phy_84741_interface_set 11975 * Purpose: 11976 * Set either CR4 interface or SR4/LR4. The valid interface are SOC_PORT_IF_CR4 11977 * and SOC_PORT_IF_XLAUI which put device in default mode: SR4/LR4 mode 11978 * Parameters: 11979 * unit - StrataSwitch unit #. 11980 * port - StrataSwitch port #. 11981 * pif - one of SOC_PORT_IF_* 11982 * Returns: 11983 * SOC_E_NONE - success 11984 * SOC_E_UNAVAIL - unsupported interface 11985 */ 11986 11987 STATIC int 11988 phy_84741_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 11989 { 11990 phy_ctrl_t *pc; 11991 phy_ctrl_t *int_pc; 11992 uint16 ucode_ver; 11993 uint16 sig_lvl_reg[4]; 11994 uint16 rxlos_reg[4]; 11995 uint16 pol_reg[4]; 11996 int lane; 11997 soc_port_ability_t ability; 11998 11999 int_pc = INT_PHY_SW_STATE(unit, port); 12000 pc = EXT_PHY_SW_STATE(unit, port); 12001 12002 if (int_pc != NULL) { 12003 if (REVERSE_MODE(pc)) { 12004 SOC_IF_ERROR_RETURN 12005 (PHY_INTERFACE_SET(int_pc->pd, unit, port, pif)); 12006 SOC_IF_ERROR_RETURN( 12007 PHY_ABILITY_ADVERT_GET(int_pc->pd, unit, port, &ability)); 12008 SOC_IF_ERROR_RETURN( 12009 PHY_ABILITY_ADVERT_SET(int_pc->pd, unit, port, &ability)); 12010 } 12011 } 12012 12013 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { 12014 return phy_null_interface_set(unit,port,pif); 12015 } 12016 12017 switch (pif) { 12018 case SOC_PORT_IF_CR4: 12019 SOC_IF_ERROR_RETURN 12020 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 12021 PHY84740_PMAD_DAC_MODE_MASK, PHY84740_PMAD_DAC_MODE_MASK)); 12022 break; 12023 12024 case SOC_PORT_IF_XLAUI: 12025 SOC_IF_ERROR_RETURN 12026 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG, 12027 0, PHY84740_PMAD_DAC_MODE_MASK)); 12028 break; 12029 default: 12030 break; 12031 } 12032 12033 SOC_IF_ERROR_RETURN 12034 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xce00, &ucode_ver)); 12035 12036 if (ucode_ver >= 0x0104) { 12037 /* For 40G mode, Do not reset the PHY if ucode is D104 on newer */ 12038 return SOC_E_NONE; 12039 } 12040 12041 12042 /* After switching mode, user need to redo the configuration */ 12043 if (pif == SOC_PORT_IF_CR4 || pif == SOC_PORT_IF_XLAUI) { 12044 12045 /* save the register settings */ 12046 for (lane = 0; lane < NUM_LANES; lane++) { 12047 /* point to the each lane starting at lane0 */ 12048 SOC_IF_ERROR_RETURN 12049 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 12050 PHY84740_PMAD_AER_ADDR_REG, lane)); 12051 SOC_IF_ERROR_RETURN( 12052 READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 12053 PHY84740_DIG_CTRL_REG, 12054 &pol_reg[lane])); 12055 12056 SOC_IF_ERROR_RETURN 12057 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 12058 PHY84740_PMAD_OPTICAL_CFG_REG, 12059 &rxlos_reg[lane])); 12060 SOC_IF_ERROR_RETURN 12061 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc, 12062 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 12063 &sig_lvl_reg[lane])); 12064 } 12065 12066 /* perform IEEE reset */ 12067 SOC_IF_ERROR_RETURN 12068 (MODIFY_PHY84740_PMA_PMD_CTRLr(pc->unit, pc, 12069 MII_CTRL_RESET, MII_CTRL_RESET)); 12070 12071 sal_udelay(100); /* Wait for 100us */ 12072 12073 /* restore back saved register values */ 12074 for (lane = 0; lane < NUM_LANES; lane++) { 12075 /* point to the each lane starting at lane0 */ 12076 SOC_IF_ERROR_RETURN 12077 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 12078 PHY84740_PMAD_AER_ADDR_REG, lane)); 12079 SOC_IF_ERROR_RETURN( 12080 WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc, 12081 PHY84740_DIG_CTRL_REG, 12082 pol_reg[lane])); 12083 12084 SOC_IF_ERROR_RETURN 12085 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc, 12086 PHY84740_PMAD_OPTICAL_CFG_REG, 12087 rxlos_reg[lane])); 12088 SOC_IF_ERROR_RETURN 12089 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc, 12090 PHY84740_PMAD_OPTICAL_SIG_LVL_REG, 12091 sig_lvl_reg[lane])); 12092 } 12093 12094 /* redo Polarity configuration */ 12095 SOC_IF_ERROR_RETURN 12096 (_phy_84741_polarity_flip_set(unit,port)); 12097 12098 /* point back to lane0 */ 12099 SOC_IF_ERROR_RETURN 12100 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 12101 } 12102 12103 return SOC_E_NONE; 12104 } 12105 12106 /* 12107 * Function: 12108 * phy_84741_interface_get 12109 * Purpose: 12110 * Get the current operating mode of the PHY. 12111 * Parameters: 12112 * unit - StrataSwitch unit #. 12113 * port - StrataSwitch port #. 12114 * pif - (OUT) one of SOC_PORT_IF_* 12115 * Returns: 12116 * SOC_E_NONE 12117 */ 12118 12119 STATIC int 12120 phy_84741_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 12121 { 12122 phy_ctrl_t *pc; 12123 uint16 mode; 12124 12125 pc = EXT_PHY_SW_STATE(unit, port); 12126 12127 if (!(PHY84740_SINGLE_PORT_MODE(pc))) { 12128 *pif = SOC_PORT_IF_XAUI; 12129 return SOC_E_NONE; 12130 } 12131 12132 SOC_IF_ERROR_RETURN 12133 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&mode)); 12134 if (mode & PHY84740_PMAD_DAC_MODE_MASK) { 12135 *pif = SOC_PORT_IF_CR4; 12136 } else { 12137 *pif = SOC_PORT_IF_XLAUI; 12138 } 12139 12140 return SOC_E_NONE; 12141 } 12142 12143 /* 12144 * Function: * phy_84741_rom_wait 12145 * 12146 * Purpose: 12147 * Wait for data to be written to the SPI-ROM. 12148 * Input: 12149 * unit, port 12150 */ 12151 STATIC int 12152 phy_84741_rom_wait(int unit, int port) 12153 { 12154 uint16 rd_data; 12155 uint16 wr_data; 12156 uint16 data16; 12157 int count; 12158 phy_ctrl_t *pc; 12159 soc_timeout_t to; 12160 int SPI_READY; 12161 12162 pc = EXT_PHY_SW_STATE(unit, port); 12163 12164 rd_data = 0; 12165 soc_timeout_init(&to, WR_TIMEOUT, 0); 12166 do { 12167 /* Write SPI Control Register Read Command. */ 12168 count = 1; 12169 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 12170 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12171 wr_data = SPI_CTRL_1_L; 12172 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12173 12174 /* extra reads to clear the status */ 12175 SOC_IF_ERROR_RETURN 12176 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 12177 SOC_IF_ERROR_RETURN 12178 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 12179 12180 if (rd_data & 0x0100) { 12181 break; 12182 } 12183 } while (!soc_timeout_check(&to)); 12184 if (!(rd_data & 0x0100)) { 12185 LOG_ERROR(BSL_LS_SOC_PHY, 12186 (BSL_META_U(unit, 12187 "phy_84741_rom_program: u = %d p = %d " 12188 "timeout 1\n"), unit, port)); 12189 return SOC_E_TIMEOUT; 12190 } 12191 12192 SPI_READY = 1; 12193 while (SPI_READY == 1) { 12194 /* Set-up SPI Controller To Receive SPI EEPROM Status. */ 12195 count = 1; 12196 wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count); 12197 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12198 wr_data = SPI_CTRL_2_H; 12199 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12200 wr_data = 0x0100; 12201 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12202 /* Fill-up SPI Transmit Fifo To check SPI Status. */ 12203 count = 2; 12204 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12205 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12206 /* Write Tx Fifo Register Address. */ 12207 wr_data = SPI_TXFIFO; 12208 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12209 12210 /* Write SPI Tx Fifo Control Word-1. */ 12211 wr_data = ((1 * 0x0100) | MSGTYPE_HRD); 12212 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12213 /* Write SPI Tx Fifo Control Word-2. */ 12214 wr_data = RDSR_OPCODE; 12215 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12216 /* Write SPI Control Register Write Command. */ 12217 count = 2; 12218 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12219 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12220 /* Write SPI Control -1 Register Address. */ 12221 wr_data = SPI_CTRL_1_L; 12222 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12223 /* Write SPI Control -1 Register Word-1. */ 12224 wr_data = 0x0101; 12225 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12226 /* Write SPI Control -1 Register Word-2. */ 12227 wr_data = 0x0100; 12228 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12229 /* Write SPI Control Register Write Command. */ 12230 count = 1; 12231 wr_data = ((WR_CPU_CTRL_REGS * 0x0100) | count); 12232 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12233 /* Write SPI Control -1 Register Address. */ 12234 wr_data = SPI_CTRL_1_H; 12235 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12236 /* Write SPI Control -1 Register Word-2. */ 12237 wr_data = 0x0103; 12238 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12239 /* Wait For 64 bytes To be written. */ 12240 rd_data = 0x0000; 12241 soc_timeout_init(&to, WR_TIMEOUT, 0); 12242 do { 12243 count = 1; 12244 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 12245 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12246 wr_data = SPI_CTRL_1_L; 12247 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12248 12249 /* extra reads to clear the status */ 12250 SOC_IF_ERROR_RETURN 12251 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 12252 SOC_IF_ERROR_RETURN 12253 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 12254 12255 if (rd_data & 0x0100) { 12256 break; 12257 } 12258 } while (!soc_timeout_check(&to)); 12259 if (!(rd_data & 0x0100)) { 12260 LOG_ERROR(BSL_LS_SOC_PHY, 12261 (BSL_META_U(unit, 12262 "phy_84741_rom_program: u = %d p = %d " 12263 "timeout 2\n"), unit, port)); 12264 return SOC_E_TIMEOUT; 12265 } 12266 /* Write SPI Control Register Read Command. */ 12267 count = 1; 12268 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 12269 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12270 /* Write SPI Control -1 Register Address. */ 12271 wr_data = SPI_RXFIFO; 12272 12273 SOC_IF_ERROR_RETURN 12274 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wr_data)); 12275 SOC_IF_ERROR_RETURN 12276 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data)); 12277 12278 /* Clear LASI Message Out Status. */ 12279 SOC_IF_ERROR_RETURN 12280 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &wr_data)); 12281 12282 if ((rd_data & 0x1) == 0) { 12283 SPI_READY = 0; 12284 } 12285 /* extra reads to clear the status */ 12286 SOC_IF_ERROR_RETURN 12287 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 12288 SOC_IF_ERROR_RETURN 12289 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 12290 } /* SPI_READY */ 12291 return SOC_E_NONE; 12292 } 12293 12294 12295 /* 12296 * Function: 12297 * phy_84741_rom_write_enable_set 12298 * 12299 * Purpose: 12300 * Enable disable protection on SPI_EEPROM 12301 * 12302 * Input: 12303 * unit 12304 * port 12305 * enable 12306 * Output: 12307 * SOC_E_xxx 12308 * 12309 * Notes: 12310 * 25AA256 256Kbit Serial EEPROM 12311 * STATUS Register 12312 * +------------------------------------------+ 12313 * | WPEN | x | x | x | BP1 | BP0 | WEL | WIP | 12314 * +------------------------------------------+ 12315 * BP1 BP0 : Protected Blocks 12316 * 0 0 : Protect None 12317 * 1 1 : Protect All 12318 * 12319 * WEL : Write Latch Enable 12320 * 0 : Do not allow writes 12321 * 1 : Allow writes 12322 */ 12323 12324 STATIC int 12325 phy_84741_rom_write_enable_set(int unit, int port, int enable) 12326 { 12327 uint16 rd_data; 12328 uint16 wr_data; 12329 uint8 wrsr_data; 12330 int count; 12331 phy_ctrl_t *pc; 12332 12333 pc = EXT_PHY_SW_STATE(unit, port); 12334 12335 /* 12336 * Write SPI Control Register Write Command. 12337 */ 12338 count = 2; 12339 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12340 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12341 12342 /* 12343 * Write SPI Control -2 Register Address. 12344 */ 12345 wr_data = SPI_CTRL_2_L; 12346 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12347 12348 /* 12349 * Write SPI Control -2 Register Word-1. 12350 */ 12351 wr_data = 0x8200; 12352 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12353 12354 /* 12355 * Write SPI Control -2 Register Word-2. 12356 */ 12357 wr_data = 0x0100; 12358 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12359 12360 /* 12361 * Fill-up SPI Transmit Fifo With SPI EEPROM Messages. 12362 * Write SPI Control Register Write Command. 12363 */ 12364 count = 4; 12365 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12366 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12367 12368 /* 12369 * Write Tx Fifo Register Address. 12370 */ 12371 wr_data = SPI_TXFIFO; 12372 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12373 12374 /* 12375 * Write SPI Tx Fifo Control Word-1. 12376 */ 12377 wr_data = ((1 * 0x0100) | MSGTYPE_HWR); 12378 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12379 12380 /* 12381 * Write SPI Tx Fifo Control Word-2. 12382 */ 12383 wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE); 12384 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12385 12386 /* 12387 * Write SPI Tx Fifo Control Word-3. 12388 */ 12389 wr_data = ((WRSR_OPCODE * 0x100) | (0x2)); 12390 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12391 12392 /* 12393 * Write SPI Tx Fifo Control Word-4. 12394 */ 12395 wrsr_data = enable ? 0x2 : 0xc; 12396 wr_data = ((wrsr_data * 0x0100) | wrsr_data); 12397 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12398 12399 /* 12400 * Write SPI Control Register Write Command. 12401 */ 12402 count = 2; 12403 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12404 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12405 12406 /* 12407 * Write SPI Control -1 Register Address. 12408 */ 12409 wr_data = SPI_CTRL_1_L; 12410 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12411 12412 /* 12413 * Write SPI Control -1 Register Word-1. 12414 */ 12415 wr_data = 0x0101; 12416 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12417 12418 /* 12419 * Write SPI Control -1 Register Word-2. 12420 */ 12421 wr_data = 0x0003; 12422 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12423 12424 /* 12425 * Wait For WRSR Command To be written. 12426 */ 12427 SOC_IF_ERROR_RETURN(phy_84741_rom_wait(unit, port)); 12428 12429 return SOC_E_NONE; 12430 } 12431 12432 STATIC int 12433 _phy84741_init_ucode_bcst(int unit, int port, int cmd) 12434 { 12435 uint16 data16; 12436 uint16 mask16; 12437 uint16 phy_id; 12438 int j; 12439 uint16 num_words; 12440 int i; 12441 uint16 chip_mode; 12442 int num_lanes; 12443 uint8 *fw_ptr; 12444 int fw_length; 12445 phy_ctrl_t *pc; 12446 12447 pc = EXT_PHY_SW_STATE(unit, port); 12448 num_lanes = PHY84740_SINGLE_PORT_MODE(pc) ? 4 : 1; 12449 12450 if (cmd == PHYCTRL_UCODE_BCST_SETUP) { 12451 SOC_IF_ERROR_RETURN( 12452 READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_CHIP_MODE_REG,&chip_mode)); 12453 12454 LOG_INFO(BSL_LS_SOC_PHY, 12455 (BSL_META_U(unit, 12456 "PHY84740 BCST start: u=%d p=%d\n"), unit, port)); 12457 /* check the current chip mode, switch to quad if in single port mode */ 12458 if ((chip_mode & PHY84740_PMAD_CHIP_MODE_MASK) == PHY84740_PMAD_MODE_40G) { 12459 LOG_INFO(BSL_LS_SOC_PHY, 12460 (BSL_META_U(unit, 12461 "PHY84740 BCST mode switch: u=%d p=%d\n"), unit, port)); 12462 SOC_IF_ERROR_RETURN( 12463 _phy_84741_single_to_quad_mode(unit,port,NULL)); 12464 } 12465 12466 /* program the bcst register. do 4 lanes for single port configuration */ 12467 phy_id = pc->phy_id; 12468 /* configure all four ports */ 12469 for (i = 0; i < num_lanes; i++) { 12470 if (num_lanes > 1) { 12471 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 12472 } 12473 SOC_IF_ERROR_RETURN 12474 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff)); 12475 } 12476 /* restore the original phy_id */ 12477 pc->phy_id = phy_id; 12478 return SOC_E_NONE; 12479 } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) { 12480 LOG_INFO(BSL_LS_SOC_PHY, 12481 (BSL_META_U(unit, 12482 "PHY84740 BCST1: u=%d p=%d\n"), unit, port)); 12483 /* clear SPA ctrl reg bit 15 and bit 13. 12484 * bit 15, 0-use MDIO download to SRAM, 1 SPI-ROM download to SRAM 12485 * bit 13, 0 clear download done status, 1 skip download 12486 */ 12487 mask16 = (1 << 13) | (1 << 15); 12488 data16 = 0; 12489 SOC_IF_ERROR_RETURN 12490 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 12491 data16,mask16)); 12492 12493 /* set SPA ctrl reg bit 14, 1 RAM boot, 0 internal ROM boot */ 12494 mask16 = 1 << 14; 12495 data16 = mask16; 12496 SOC_IF_ERROR_RETURN 12497 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_SPA_CTRL_REG, 12498 data16,mask16)); 12499 12500 /* misc_ctrl1 reg bit 3 to 1 for 32k downloading size */ 12501 mask16 = 1 << 3; 12502 data16 = mask16; 12503 SOC_IF_ERROR_RETURN 12504 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_MISC_CTRL1_REG, 12505 data16,mask16)); 12506 12507 /* apply bcst Reset to start download code from MDIO */ 12508 SOC_IF_ERROR_RETURN 12509 (WRITE_PHY84740_PMA_PMD_CTRLr(unit, pc, 0x8000)); 12510 return SOC_E_NONE; 12511 } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) { 12512 LOG_INFO(BSL_LS_SOC_PHY, 12513 (BSL_META_U(unit, 12514 "PHY84740 BCST2: u=%d p=%d\n"), unit, port)); 12515 12516 /* reset clears bcst register */ 12517 /* restore bcst register after reset */ 12518 phy_id = pc->phy_id; 12519 /* configure all four ports */ 12520 for (i = 0; i < num_lanes; i++) { 12521 if (num_lanes > 1) { 12522 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 12523 } 12524 SOC_IF_ERROR_RETURN 12525 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0xffff)); 12526 } 12527 /* restore the original phy_id */ 12528 pc->phy_id = phy_id; 12529 return SOC_E_NONE; 12530 } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) { 12531 LOG_INFO(BSL_LS_SOC_PHY, 12532 (BSL_META_U(unit, 12533 "firmware_bcst,device name %s: u=%d p=%d\n"), 12534 pc->dev_name? pc->dev_name: "NULL", unit, port)); 12535 /* find the right firmware */ 12536 if (pc->dev_name == dev_name_84740) { 12537 fw_ptr = phy84740_ucode_bin; 12538 fw_length = phy84740_ucode_bin_len; 12539 } else if (pc->dev_name == dev_name_84752) { 12540 fw_ptr = phy84752_ucode_bin; 12541 fw_length = phy84752_ucode_bin_len; 12542 } else if (pc->dev_name == dev_name_84753) { 12543 fw_ptr = phy84753_ucode_bin; 12544 fw_length = phy84753_ucode_bin_len; 12545 } else if (pc->dev_name == dev_name_84754) { 12546 fw_ptr = phy84754_ucode_bin; 12547 fw_length = phy84754_ucode_bin_len; 12548 } else if (pc->dev_name == dev_name_84064) { 12549 fw_ptr = phy84064_ucode_bin; 12550 fw_length = phy84064_ucode_bin_len; 12551 } else if (pc->dev_name == dev_name_84784) { 12552 fw_ptr = phy84784_ucode_bin; 12553 fw_length = phy84784_ucode_bin_len; 12554 } else { 12555 /* invalid device name */ 12556 LOG_WARN(BSL_LS_SOC_PHY, 12557 (BSL_META_U(unit, 12558 "firmware_bcst,invalid device name %s: u=%d p=%d\n"), 12559 pc->dev_name? pc->dev_name: "NULL", unit, port)); 12560 return SOC_E_NONE; 12561 } 12562 12563 /* wait for 2ms for M8051 start and 5ms to initialize the RAM */ 12564 sal_usleep(10000); /* Wait for 10ms */ 12565 12566 /* Write Starting Address, where the Code will reside in SRAM */ 12567 data16 = 0x8000; 12568 SOC_IF_ERROR_RETURN 12569 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 12570 12571 /* make sure address word is read by the micro */ 12572 sal_udelay(10); /* Wait for 10us */ 12573 12574 /* Write SPI SRAM Count Size */ 12575 data16 = (fw_length)/2; 12576 SOC_IF_ERROR_RETURN 12577 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, data16)); 12578 12579 /* make sure read by the micro */ 12580 sal_udelay(10); /* Wait for 10us */ 12581 12582 /* Fill in the SRAM */ 12583 num_words = (fw_length - 1); 12584 for (j = 0; j < num_words; j+=2) { 12585 /* Make sure the word is read by the Micro */ 12586 sal_udelay(10); 12587 12588 data16 = (fw_ptr[j] << 8) | fw_ptr[j+1]; 12589 12590 SOC_IF_ERROR_RETURN 12591 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_M8051_MSGIN_REG, 12592 data16)); 12593 } 12594 return SOC_E_NONE; 12595 } else if (cmd == PHYCTRL_UCODE_BCST_END) { 12596 LOG_INFO(BSL_LS_SOC_PHY, 12597 (BSL_META_U(unit, 12598 "PHY84740 BCST end: u=%d p=%d\n"), unit, port)); 12599 12600 /* make sure last code word is read by the micro */ 12601 sal_udelay(20); 12602 12603 /* first disable bcst mode */ 12604 phy_id = pc->phy_id; 12605 for (i = 0; i < num_lanes; i++) { 12606 if (num_lanes > 1) { 12607 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 12608 } 12609 SOC_IF_ERROR_RETURN 12610 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xc8fe, 0x0)); 12611 12612 /* Read Hand-Shake message (Done) from Micro */ 12613 SOC_IF_ERROR_RETURN 12614 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_M8051_MSGOUT_REG, 12615 &data16)); 12616 12617 /* Download done message */ 12618 LOG_INFO(BSL_LS_SOC_PHY, 12619 (BSL_META_U(unit, 12620 "u=%d p=%d MDIO firmware download done message: 0x%x\n"), 12621 unit, port,data16)); 12622 12623 /* Clear LASI status */ 12624 SOC_IF_ERROR_RETURN 12625 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 12626 } 12627 /* restore the original phy_id */ 12628 pc->phy_id = phy_id; 12629 12630 12631 /* Wait for LASI to be asserted when M8051 writes checksum to MSG_OUTr */ 12632 sal_udelay(100); /* Wait for 100 usecs */ 12633 12634 phy_id = pc->phy_id; 12635 for (i = 0; i < num_lanes; i++) { 12636 if (num_lanes > 1) { 12637 pc->phy_id = (phy_id & (~0x3)) + i; /* Port 3, 2, 1 and 0 */ 12638 } 12639 SOC_IF_ERROR_RETURN 12640 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_M8051_MSGOUT_REG,&data16)); 12641 12642 /* Need to check if checksum is correct */ 12643 SOC_IF_ERROR_RETURN 12644 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1C, &data16)); 12645 12646 if (data16 != 0x600D) { 12647 /* Bad CHECKSUM */ 12648 LOG_CLI((BSL_META_U(unit, 12649 "firmware_bcst downlad failure: port %d " 12650 "Incorrect Checksum %x\n"), port,data16)); 12651 return SOC_E_FAIL; 12652 } 12653 12654 /* read Rev-ID */ 12655 SOC_IF_ERROR_RETURN 12656 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA1A, &data16)); 12657 LOG_INFO(BSL_LS_SOC_PHY, 12658 (BSL_META_U(unit, 12659 "u=%d p=%d MDIO Firmware download revID: 0x%x\n"), 12660 unit, port,data16)); 12661 } 12662 /* restore the original phy_id */ 12663 pc->phy_id = phy_id; 12664 12665 return SOC_E_NONE; 12666 } else { 12667 LOG_WARN(BSL_LS_SOC_PHY, 12668 (BSL_META_U(unit, 12669 "u=%d p=%d firmware_bcst: invalid cmd 0x%x\n"), 12670 unit, port,cmd)); 12671 } 12672 12673 return SOC_E_FAIL; 12674 } 12675 12676 /* 12677 * Function: 12678 * phy_84741_firmware_set 12679 * Purpose: 12680 * program the given firmware into the SPI-ROM 12681 * Parameters: 12682 * unit - StrataSwitch unit #. 12683 * port - StrataSwitch port #. 12684 * offset - offset to the data stream 12685 * array - the given data 12686 * datalen- the data length 12687 * Returns: 12688 * SOC_E_NONE 12689 */ 12690 12691 STATIC int 12692 phy_84741_firmware_set(int unit, int port, int offset, uint8 *array,int datalen) 12693 { 12694 uint16 saved_phy_addr; 12695 int ix; 12696 phy_ctrl_t *pc; 12697 uint32 devid; 12698 uint32 uCode_devid; 12699 12700 /* overload this function a littl bit if array == NULL 12701 * special handling for init. uCode broadcast. Internal use only 12702 */ 12703 if (array == NULL) { 12704 return _phy84741_init_ucode_bcst(unit,port,offset); 12705 } 12706 12707 pc = EXT_PHY_SW_STATE(unit, port); 12708 12709 SOC_IF_ERROR_RETURN( 12710 _phy_84741_config_devid(pc->unit,pc->port, pc, &devid)); 12711 12712 /* first validate the firmware is for the configured device 12713 * 84740 has 1.5V from TXDRV pin, 84754 is internally wired at 1.0V. 12714 * If the 84754 firmware which programs chip for 1.0V is loaded 12715 * to the 84740, then it may damage the device and module. 12716 * 12717 * Chip ID is at addresses 0x7FF9, 0x7FFA, 0x7FFB.e.g. 12718 * for 84740, [0x7FF9] = 0x08, [0x7FFA] = 0x47, [0x7FFB] = 0x40. 12719 * Version number is at 0x7FFC-0x7FFD 12720 */ 12721 12722 /* length should be at least 0xFFFE */ 12723 if (datalen < PHY84740_UCODE_DEVID_ADDR+3) { 12724 LOG_WARN(BSL_LS_SOC_PHY, 12725 (BSL_META_U(unit, 12726 "firmware_set, wrong firmware len=0x%x : u=%d p=%d\n"), 12727 datalen, unit, port)); 12728 return SOC_E_PARAM; 12729 } 12730 12731 /* check the firmware devid matches the configured devid */ 12732 ix = PHY84740_UCODE_DEVID_ADDR; 12733 uCode_devid = (array[ix] << 16) | (array[ix+1] << 8) | 12734 array[ix+2]; 12735 12736 if (uCode_devid != devid) { 12737 LOG_WARN(BSL_LS_SOC_PHY, 12738 (BSL_META_U(unit, 12739 "firmware_set,u=%d p=%d: Firmware device " 12740 "type(0x%x) does not match configured device type(0x%x)\n"), 12741 unit, port,uCode_devid,devid)); 12742 return SOC_E_PARAM; 12743 } 12744 12745 if (PHY84740_SINGLE_PORT_MODE(pc)) { 12746 /* switch to quad-mode */ 12747 SOC_IF_ERROR_RETURN( 12748 _phy_84741_single_to_quad_mode(unit,port,NULL)); 12749 } 12750 saved_phy_addr = pc->phy_id; 12751 12752 LOG_INFO(BSL_LS_SOC_PHY, 12753 (BSL_META_U(unit, 12754 "firmware_set init,quad port : u=%d p=%d\n"), 12755 unit, port)); 12756 /* configure all four lanes to bcst mode */ 12757 for (ix = 0; ix < 4; ix++) { 12758 pc->phy_id = (saved_phy_addr & (~0x3)) + ix; 12759 SOC_IF_ERROR_RETURN 12760 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_BCST_REG,0xffff)); 12761 } 12762 pc->phy_id = saved_phy_addr; 12763 12764 /* place all uC in reset */ 12765 SOC_IF_ERROR_RETURN 12766 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0x018f)); 12767 12768 /* disable all port's SPI */ 12769 SOC_IF_ERROR_RETURN 12770 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x000f)); 12771 12772 SOC_IF_ERROR_RETURN 12773 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x000c)); 12774 12775 /* Set bit 0 (spa enable) in C848 for master channel ? */ 12776 SOC_IF_ERROR_RETURN 12777 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0x2000,0x2000)); 12778 12779 /* disable the bcst mode for all channels */ 12780 SOC_IF_ERROR_RETURN 12781 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc,PHY84740_PMAD_BCST_REG,0xfffe)); 12782 12783 SOC_IF_ERROR_RETURN 12784 (_phy_84741_firmware_to_rom(unit,port,offset,array,datalen)); 12785 12786 /* switch back to single mode */ 12787 if (PHY84740_SINGLE_PORT_MODE(pc)) { 12788 /* switch to quad-mode */ 12789 SOC_IF_ERROR_RETURN( 12790 _phy_84741_quad_to_single_mode(unit,port)); 12791 } 12792 return SOC_E_NONE; 12793 } 12794 STATIC int 12795 _phy_84741_firmware_to_rom(int unit, int port, int offset, uint8 *array,int datalen) 12796 { 12797 uint16 rd_data; 12798 uint16 wr_data; 12799 int j; 12800 int i = 0; 12801 int count; 12802 uint8 spi_values[WR_BLOCK_SIZE]; 12803 uint16 data16; 12804 soc_timeout_t to; 12805 phy_ctrl_t *pc; 12806 12807 pc = EXT_PHY_SW_STATE(unit, port); 12808 12809 /* 12810 * Enable SPI for Port0 12811 */ 12812 SOC_IF_ERROR_RETURN 12813 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC843, 0x0000)); 12814 SOC_IF_ERROR_RETURN 12815 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC840, 0x0000)); 12816 /* 12817 * Remove M8051 resets for port 0. 12818 * and wait for Micro to complete Init. 12819 */ 12820 /* clear bits 3:0 */ 12821 SOC_IF_ERROR_RETURN 12822 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA10, 0,0xf)); 12823 sal_usleep(10000); 12824 12825 /* set bit(request) in 0xc848 for the required channel, remove done bit */ 12826 SOC_IF_ERROR_RETURN 12827 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0,0x2000)); 12828 12829 /* enable SPI port enable */ 12830 SOC_IF_ERROR_RETURN 12831 (MODIFY_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xC848, 0xc004,0xc004)); 12832 12833 /* 12834 * Read LASI Status registers To clear initial Failure status. 12835 */ 12836 SOC_IF_ERROR_RETURN 12837 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data)); 12838 SOC_IF_ERROR_RETURN 12839 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9004, &rd_data)); 12840 SOC_IF_ERROR_RETURN 12841 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &rd_data)); 12842 12843 /* 12844 * Enable the LASI For Message out. 12845 */ 12846 SOC_IF_ERROR_RETURN 12847 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9000, 0x0004)); 12848 /* 12849 * 0x9002, bit 2 Is Rx Alarm enabled For LASI. 12850 */ 12851 SOC_IF_ERROR_RETURN 12852 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9002, 0x0004)); 12853 /* 12854 * Read Any Residual Message out register. 12855 */ 12856 SOC_IF_ERROR_RETURN 12857 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &rd_data)); 12858 /* 12859 * Clear LASI Message Out Status. 12860 */ 12861 SOC_IF_ERROR_RETURN 12862 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &rd_data)); 12863 12864 /* set SPI-ROM write enable */ 12865 SOC_IF_ERROR_RETURN(phy_84741_rom_write_enable_set(unit, port, 1)); 12866 12867 LOG_INFO(BSL_LS_SOC_PHY, 12868 (BSL_META_U(unit, 12869 "init0: u=%d p=%d\n"), 12870 unit, port)); 12871 12872 for (j = 0; j < datalen; j += WR_BLOCK_SIZE) { 12873 /* 12874 * Setup SPI Controller. 12875 */ 12876 count = 2; 12877 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12878 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12879 12880 /* Write SPI Control -2 Register Address.*/ 12881 wr_data = SPI_CTRL_2_L; 12882 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12883 12884 /* Write SPI Control -2 Register Word-1. */ 12885 wr_data = 0x8200; 12886 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12887 12888 /* Write SPI Control -2 Register Word-2. */ 12889 wr_data = 0x0100; 12890 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12891 12892 /* Fill-up SPI Transmit Fifo. 12893 * Write SPI Control Register Write Command. 12894 */ 12895 count = 4 + (WR_BLOCK_SIZE / 2); 12896 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12897 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12898 12899 /* Write Tx Fifo Register Address. */ 12900 wr_data = SPI_TXFIFO; 12901 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12902 12903 /* Write SPI Tx Fifo Control Word-1. */ 12904 wr_data = ((1 * 0x0100) | MSGTYPE_HWR); 12905 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12906 12907 /* Write SPI Tx Fifo Control Word-2. */ 12908 wr_data = ((MSGTYPE_HWR * 0x0100) | WREN_OPCODE); 12909 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12910 12911 /* Write SPI Tx Fifo Control Word-3. */ 12912 wr_data = ((WR_OPCODE * 0x0100) | (0x3 + WR_BLOCK_SIZE)); 12913 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12914 12915 /* Write SPI Tx Fifo Control Word-4. */ 12916 wr_data = (((j & 0x00FF) * 0x0100) | ((j & 0xFF00) / 0x0100)); 12917 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12918 12919 LOG_INFO(BSL_LS_SOC_PHY, 12920 (BSL_META_U(unit, 12921 "loop: u=%d p=%d,inxj: %d,inxi:%d\n"), 12922 unit, port,j,i)); 12923 12924 if (datalen < (j + WR_BLOCK_SIZE)) { /* last block */ 12925 sal_memset(spi_values,0,WR_BLOCK_SIZE); 12926 sal_memcpy(spi_values,&array[j],datalen - j); 12927 12928 for (i = 0; i < WR_BLOCK_SIZE; i += 2) { 12929 /* Write SPI Tx Fifo Data Word-4. */ 12930 wr_data = ((spi_values[i+1] * 0x0100) | spi_values[i]); 12931 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data)); 12932 } 12933 } else { 12934 for (i = 0; i < WR_BLOCK_SIZE; i += 2) { 12935 /* Write SPI Tx Fifo Data Word-4. */ 12936 wr_data = ((array[j+i+1] * 0x0100) | array[j+i]); 12937 SOC_IF_ERROR_RETURN(write_message(unit, pc,wr_data, &rd_data)); 12938 } 12939 } 12940 12941 /* 12942 * Set-up SPI Controller To Transmit. 12943 * Write SPI Control Register Write Command. 12944 */ 12945 count = 2; 12946 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12947 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12948 12949 wr_data = SPI_CTRL_1_L; 12950 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12951 12952 /* Write SPI Control -1 Register Word-1. */ 12953 wr_data = 0x0501; 12954 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12955 12956 /* Write SPI Control -1 Register Word-2. */ 12957 wr_data = 0x0003; 12958 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12959 12960 /* Wait For 64 bytes To be written. */ 12961 SOC_IF_ERROR_RETURN(phy_84741_rom_wait(unit,port)); 12962 12963 } /* SPI_WRITE */ 12964 12965 /* clear SPI-ROM write enable */ 12966 SOC_IF_ERROR_RETURN(phy_84741_rom_write_enable_set(unit, port, 0)); 12967 12968 /* Disable SPI EEPROM. */ 12969 count = 2; 12970 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12971 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12972 12973 /* Write SPI Control -2 Register Address. */ 12974 wr_data = SPI_CTRL_2_L; 12975 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12976 12977 /* Write SPI Control -2 Register Word-1. */ 12978 wr_data = 0x8200; 12979 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12980 12981 /* Write SPI Control -2 Register Word-2. */ 12982 wr_data = 0x0100; 12983 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12984 12985 12986 /* Fill-up SPI Transmit Fifo With SPI EEPROM Messages. */ 12987 count = 2; 12988 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 12989 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12990 12991 /* Write Tx Fifo Register Address. */ 12992 wr_data = SPI_TXFIFO; 12993 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12994 12995 /* Write SPI Tx Fifo Control Word-1. */ 12996 wr_data = ((0x1*0x0100) | MSGTYPE_HWR); 12997 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 12998 12999 /* Write SPI Tx Fifo Control Word-2. */ 13000 wr_data = WRDI_OPCODE; 13001 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 13002 13003 /* Write SPI Control Register Write Command. */ 13004 count = 2; 13005 wr_data = ((WR_CPU_CTRL_FIFO * 0x0100) | count); 13006 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 13007 13008 /* Write SPI Control -1 Register Address. */ 13009 wr_data = SPI_CTRL_1_L; 13010 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 13011 13012 /* Write SPI Control -1 Register Word-1. */ 13013 wr_data = 0x0101; 13014 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 13015 13016 /* Write SPI Control -1 Register Word-2. */ 13017 wr_data = 0x0003; 13018 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 13019 13020 /* Wait For WRDI Command To be written */ 13021 rd_data = 0; 13022 soc_timeout_init(&to, WR_TIMEOUT, 0); 13023 do { 13024 /* Write SPI Control Register Read Command. */ 13025 count = 1; 13026 wr_data = ((RD_CPU_CTRL_REGS * 0x0100) | count); 13027 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 13028 wr_data = SPI_CTRL_1_L; 13029 SOC_IF_ERROR_RETURN(write_message(unit, pc, wr_data, &rd_data)); 13030 13031 /* extra reads to clear the status */ 13032 SOC_IF_ERROR_RETURN 13033 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &data16)); 13034 SOC_IF_ERROR_RETURN 13035 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &data16)); 13036 13037 if (rd_data & 0x0100) { 13038 break; 13039 } 13040 } while (!soc_timeout_check(&to)); 13041 13042 if (!(rd_data & 0x0100)) { 13043 LOG_ERROR(BSL_LS_SOC_PHY, 13044 (BSL_META_U(unit, 13045 "phy_84741_rom_program: u = %d p = %d " 13046 "WRDI command timeout\n"), unit, port)); 13047 return SOC_E_TIMEOUT; 13048 } 13049 13050 LOG_INFO(BSL_LS_SOC_PHY, 13051 (BSL_META_U(unit, 13052 "phy_84741_rom_program: u=%d p=%d done\n"), unit, port)); 13053 13054 return SOC_E_NONE; 13055 } 13056 13057 static int 13058 write_message(int unit, phy_ctrl_t *pc, uint16 wrdata, uint16 *rddata) 13059 { 13060 13061 uint16 tmp_data = 0; 13062 soc_timeout_t to; 13063 13064 SOC_IF_ERROR_RETURN 13065 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA12, wrdata)); 13066 13067 soc_timeout_init(&to, WR_TIMEOUT, 0); 13068 do { 13069 SOC_IF_ERROR_RETURN 13070 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9005, &tmp_data)); 13071 if (tmp_data & 0x4) 13072 break; 13073 } while (!soc_timeout_check(&to)); 13074 if (!(tmp_data & 0x4)) { 13075 LOG_ERROR(BSL_LS_SOC_PHY, 13076 (BSL_META_U(unit, 13077 "write_message failed: wrdata %04x\n"), wrdata)); 13078 return SOC_E_FAIL; 13079 } 13080 13081 SOC_IF_ERROR_RETURN 13082 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xCA13, &tmp_data)); 13083 *rddata = tmp_data; 13084 SOC_IF_ERROR_RETURN 13085 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x9003, &tmp_data)); 13086 13087 return SOC_E_NONE; 13088 } 13089 13090 /* 13091 * Function: 13092 * phy_84741_probe 13093 * Purpose: 13094 * Complement the generic phy probe routine to identify this phy when its 13095 * phy id0 and id1 is same as some other phy's. 13096 * Parameters: 13097 * unit - StrataSwitch unit #. 13098 * pc - phy ctrl descriptor. 13099 * Returns: 13100 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 13101 */ 13102 STATIC int 13103 phy_84741_probe(int unit, phy_ctrl_t *pc) 13104 { 13105 uint32 devid; 13106 13107 SOC_IF_ERROR_RETURN( 13108 _phy_84741_config_devid(pc->unit,pc->port, pc, &devid)); 13109 13110 if (devid == PHY84740_ID_84740) { 13111 pc->dev_name = dev_name_84740; 13112 } else if (devid == PHY84740_ID_84752) { 13113 pc->dev_name = dev_name_84752; 13114 } else if (devid == PHY84740_ID_84753) { 13115 pc->dev_name = dev_name_84753; 13116 } else if (devid == PHY84740_ID_84754) { 13117 pc->dev_name = dev_name_84754; 13118 } else if (devid == PHY84740_ID_84064) { 13119 pc->dev_name = dev_name_84064; 13120 } else if (PHY84740_IS_QUADRA(devid)) { 13121 /*pc->dev_name = already set;*/ 13122 } else if (devid == PHY84740_ID_84741) { 13123 pc->dev_name = dev_name_84741; 13124 } else if (devid == PHY84740_ID_84744) { 13125 pc->dev_name = dev_name_84744; 13126 } else if (pc->size == -1) { 13127 pc->size = 0; 13128 return SOC_E_NOT_FOUND; 13129 } else { /* not found */ 13130 LOG_WARN(BSL_LS_SOC_PHY, 13131 (BSL_META_U(unit, 13132 "port %d: BCM84xxx type PHY device detected, please use " 13133 "phy_84<xxx> config variable to select the specific type\n"), 13134 pc->port)); 13135 return SOC_E_NOT_FOUND; 13136 } 13137 pc->size = sizeof(PHY84740_DEV_DESC_t); 13138 return SOC_E_NONE; 13139 } 13140 13141 STATIC int 13142 _phy_84741_bsc_rw(int unit, soc_port_t port, int dev_addr, int opr, 13143 int addr, int count, void *data_array,uint32 ram_start) 13144 { 13145 phy_ctrl_t *pc; 13146 soc_timeout_t to; 13147 uint16 data16; 13148 int i; 13149 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 13150 sal_usecs_t start; 13151 sal_usecs_t end; 13152 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 13153 int access_type; 13154 int data_type; 13155 13156 LOG_INFO(BSL_LS_SOC_PHY, 13157 (BSL_META_U(unit, 13158 "phy_84741_bsc_read: u=%d p=%d addr=%04x\n"), 13159 unit, port, addr)); 13160 13161 if (!data_array) { 13162 return SOC_E_PARAM; 13163 } 13164 13165 if (count > PHY84740_BSC_XFER_MAX) { 13166 return SOC_E_PARAM; 13167 } 13168 13169 pc = EXT_PHY_SW_STATE(unit, port); 13170 data_type = PHY84740_I2C_DATA_TYPE(opr); 13171 access_type = PHY84740_I2C_ACCESS_TYPE(opr); 13172 13173 if (access_type == PHY84740_I2CDEV_WRITE) { 13174 for (i = 0; i < count; i++) { 13175 if (data_type == PHY84740_I2C_8BIT) { 13176 SOC_IF_ERROR_RETURN 13177 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i, 13178 ((uint8 *)data_array)[i])); 13179 } else { /* 16 bit */ 13180 SOC_IF_ERROR_RETURN 13181 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, ram_start + i, 13182 ((uint16 *)data_array)[i])); 13183 } 13184 } 13185 } 13186 13187 data16 = ram_start; 13188 SOC_IF_ERROR_RETURN 13189 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8004, data16)); 13190 SOC_IF_ERROR_RETURN 13191 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8003, addr)); 13192 SOC_IF_ERROR_RETURN 13193 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8002, count)); 13194 13195 data16 = 1; 13196 data16 |= (dev_addr<<9); 13197 if (access_type == PHY84740_I2CDEV_WRITE) { 13198 data16 |= PHY84740_WR_FREQ_400KHZ; 13199 } 13200 13201 SOC_IF_ERROR_RETURN 13202 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit,pc,0x8005,data16)); 13203 13204 if (access_type == PHY84740_I2CDEV_WRITE) { 13205 data16 = 0x8000 | PHY84740_BSC_WRITE_OP; 13206 } else { 13207 data16 = 0x8000 | PHY84740_BSC_READ_OP; 13208 } 13209 13210 if (data_type == PHY84740_I2C_16BIT) { 13211 data16 |= (1 << 12); 13212 } 13213 13214 /* for single port mode, there should be only one I2C interface active 13215 * from lane0. The 0x800x register block is bcst type registers. If writing 13216 * to 0x8000 directly, it will enable all four I2C masters. Use indirect access 13217 * to enable only the lane 0. 13218 */ 13219 13220 if (PHY84740_SINGLE_PORT_MODE(pc)) { 13221 13222 /* point to lane 0 */ 13223 SOC_IF_ERROR_RETURN 13224 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_PMAD_AER_ADDR_REG, 0)); 13225 13226 /* indirect access: 0x8000=data16 */ 13227 SOC_IF_ERROR_RETURN 13228 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0c, 0x8000)); 13229 SOC_IF_ERROR_RETURN 13230 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd0d, data16)); 13231 13232 /* issue the indirect access command */ 13233 SOC_IF_ERROR_RETURN 13234 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, 0x3)); 13235 13236 soc_timeout_init(&to, 1000000, 0); 13237 while (!soc_timeout_check(&to)) { 13238 SOC_IF_ERROR_RETURN 13239 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0xcd13, &data16)); 13240 if (!data16) { 13241 break; 13242 } 13243 } 13244 if (data16) { 13245 LOG_WARN(BSL_LS_SOC_PHY, 13246 (BSL_META_U(unit, 13247 "port %d: Fail register 0xcd13 status 0x%x\n"), 13248 port,data16)); 13249 return SOC_E_TIMEOUT; 13250 } 13251 } else { 13252 SOC_IF_ERROR_RETURN 13253 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, data16)); 13254 } 13255 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 13256 start = sal_time_usecs(); 13257 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 13258 soc_timeout_init(&to, 1000000, 0); 13259 while (!soc_timeout_check(&to)) { 13260 SOC_IF_ERROR_RETURN 13261 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, 0x8000, &data16)); 13262 if (((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE)) { 13263 break; 13264 } 13265 } 13266 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 13267 end = sal_time_usecs(); 13268 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 13269 /* need some delays */ 13270 sal_usleep(10000); 13271 13272 #if defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT) 13273 LOG_INFO(BSL_LS_SOC_PHY, 13274 (BSL_META_U(unit, 13275 "BSC command status %d time=%d\n"), 13276 (data16 & PHY84740_2W_STAT), SAL_USECS_SUB(end, start))); 13277 #endif /* defined(BROADCOM_DEBUG) || defined(DEBUG_PRINT */ 13278 13279 if (access_type == PHY84740_I2CDEV_WRITE) { 13280 return SOC_E_NONE; 13281 } 13282 13283 if ((data16 & PHY84740_2W_STAT) == PHY84740_2W_STAT_COMPLETE) { 13284 for (i = 0; i < count; i++) { 13285 SOC_IF_ERROR_RETURN 13286 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, (ram_start+i), &data16)); 13287 if (data_type == PHY84740_I2C_16BIT) { 13288 ((uint16 *)data_array)[i] = data16; 13289 LOG_INFO(BSL_LS_SOC_PHY, 13290 (BSL_META_U(unit, 13291 "%04x "), data16)); 13292 } else { 13293 ((uint8 *)data_array)[i] = (uint8)data16; 13294 LOG_INFO(BSL_LS_SOC_PHY, 13295 (BSL_META_U(unit, 13296 "%02x "), data16)); 13297 } 13298 } 13299 } 13300 return SOC_E_NONE; 13301 } 13302 13303 /* 13304 * Read a slave device such as NVRAM/EEPROM connected to the 84740's I2C 13305 * interface. This function will be mainly used for diagnostic or workaround 13306 * purpose. 13307 * Note: 13308 * The size of read_array buffer must be greater than or equal to the 13309 * parameter nbytes. 13310 * usage example: 13311 * Retrieve the first 100 byte data of the non-volatile storage device with 13312 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 13313 * port 2. 13314 * uint8 data8[100]; 13315 * phy_84741_i2cdev_read(0,2,0x50,0,100,data8); 13316 */ 13317 int 13318 phy_84741_i2cdev_read(int unit, 13319 soc_port_t port, 13320 int dev_addr, /* 7 bit I2C bus device address */ 13321 int offset, /* starting data address to read */ 13322 int nbytes, /* number of bytes to read */ 13323 uint8 *read_array) /* buffer to hold retrieved data */ 13324 { 13325 return _phy_84741_bsc_rw(unit, port, dev_addr,PHY84740_I2CDEV_READ, 13326 offset, nbytes, (void *)read_array,PHY84740_READ_START_ADDR); 13327 13328 } 13329 13330 /* 13331 * Write to a slave device such as NVRAM/EEPROM connected to the 84740's I2C 13332 * interface. This function will be mainly used for diagnostic or workaround 13333 * purpose. 13334 * Note: 13335 * The size of write_array buffer should be equal to the parameter nbytes. 13336 * The EEPROM may limit the maximun write size to 16 bytes 13337 * usage example: 13338 * Write to first 100 byte space of the non-volatile storage device with 13339 * I2C bus device address 0x50(default SPF eeprom I2C address) on unit 0, 13340 * port 2, with written data specified in array data8. 13341 * uint8 data8[100]; 13342 * *** initialize the data8 array with written data *** 13343 * 13344 * phy_84741_i2cdev_write(0,2,0x50,0,100,data8); 13345 */ 13346 13347 int 13348 phy_84741_i2cdev_write(int unit, 13349 soc_port_t port, 13350 int dev_addr, /* I2C bus device address */ 13351 int offset, /* starting data address to write to */ 13352 int nbytes, /* number of bytes to write */ 13353 uint8 *write_array) /* buffer to hold written data */ 13354 { 13355 int j; 13356 int rv = SOC_E_NONE; 13357 13358 for (j = 0; j < (nbytes/PHY84740_BSC_WR_MAX); j++) { 13359 rv = _phy_84741_bsc_rw(unit, port, dev_addr,PHY84740_I2CDEV_WRITE, 13360 offset + j * PHY84740_BSC_WR_MAX, PHY84740_BSC_WR_MAX, 13361 (void *)(write_array + j * PHY84740_BSC_WR_MAX), 13362 PHY84740_WRITE_START_ADDR); 13363 if (rv != SOC_E_NONE) { 13364 return rv; 13365 } 13366 sal_usleep(20000); 13367 } 13368 if (nbytes%PHY84740_BSC_WR_MAX) { 13369 rv = _phy_84741_bsc_rw(unit, port, dev_addr,PHY84740_I2CDEV_WRITE, 13370 offset + j * PHY84740_BSC_WR_MAX, nbytes%PHY84740_BSC_WR_MAX, 13371 (void *)(write_array + j * PHY84740_BSC_WR_MAX), 13372 PHY84740_WRITE_START_ADDR); 13373 } 13374 return rv; 13375 } 13376 13377 /* 13378 * Callout interface to phy_84741_i2cdev_read(); 13379 * TBD: Extend to handle max_size > PHY84740_BSC_XFER_MAX. 13380 */ 13381 13382 STATIC int 13383 phy_84741_multi_get(int unit, soc_port_t port, uint32 flags, 13384 uint32 dev_addr, uint32 offset, int max_size, uint8 *data, int *actual_size) 13385 { 13386 int rv; 13387 13388 rv = phy_84741_i2cdev_read(unit, port,(int)dev_addr,(int)offset, max_size, data); 13389 13390 if (SOC_FAILURE(rv)) { 13391 *actual_size = 0; 13392 return SOC_E_FAIL; 13393 } 13394 13395 *actual_size = max_size; 13396 return SOC_E_NONE; 13397 } 13398 13399 /* 13400 * Function: 13401 * phy_84741_reg_read 13402 * Purpose: 13403 * Routine to read PHY register 13404 * Parameters: 13405 * uint - BCM unit number 13406 * port - port number 13407 * flags - Flags which specify the register type 13408 * phy_reg_addr - Encoded register address 13409 * phy_data - (OUT) Value read from PHY register 13410 * Note: 13411 * This register read function is not thread safe. Higher level 13412 * function that calls this function must obtain a per port lock 13413 * to avoid overriding register page mapping between threads. 13414 */ 13415 STATIC int 13416 phy_84741_reg_read(int unit, soc_port_t port, uint32 flags, 13417 uint32 phy_reg_addr, uint32 *phy_data) 13418 { 13419 uint16 data16; 13420 uint16 regdata; 13421 phy_ctrl_t *pc; /* PHY software state */ 13422 int rv = SOC_E_NONE; 13423 int rd_cnt; 13424 13425 pc = EXT_PHY_SW_STATE(unit, port); 13426 13427 rd_cnt = 1; 13428 13429 if (flags & SOC_PHY_I2C_DATA8) { 13430 13431 SOC_IF_ERROR_RETURN 13432 (phy_84741_i2cdev_read(unit, port, 13433 SOC_PHY_I2C_DEVAD(phy_reg_addr), 13434 SOC_PHY_I2C_REGAD(phy_reg_addr), 13435 rd_cnt, 13436 (uint8 *)&data16)); 13437 *phy_data = *((uint8 *)&data16); 13438 13439 } else if (flags & SOC_PHY_I2C_DATA16) { 13440 /* This operation is generally targeted to access 16-bit device, 13441 * such as PHY IC inside the SFP. However there is no 16-bit 13442 * scratch register space on the device. Use 1.800e 13443 * for this operation. 13444 */ 13445 SOC_IF_ERROR_RETURN 13446 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 13447 ®data)); 13448 13449 rv = _phy_84741_bsc_rw(unit, port, 13450 SOC_PHY_I2C_DEVAD(phy_reg_addr), 13451 PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_READ,PHY84740_I2C_16BIT), 13452 SOC_PHY_I2C_REGAD(phy_reg_addr),1, 13453 (void *)&data16,PHY84740_I2C_TEMP_RAM); 13454 13455 *phy_data = data16; 13456 13457 /* restore the ram register value */ 13458 SOC_IF_ERROR_RETURN 13459 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 13460 regdata)); 13461 } else { 13462 SOC_IF_ERROR_RETURN 13463 (READ_PHY_REG(unit, pc, phy_reg_addr, &data16)); 13464 *phy_data = data16; 13465 } 13466 13467 return rv; 13468 } 13469 13470 /* 13471 * Function: 13472 * phy_84741_reg_write 13473 * Purpose: 13474 * Routine to write PHY register 13475 * Parameters: 13476 * uint - BCM unit number 13477 * port - port number 13478 * flags - Flags which specify the register type 13479 * phy_reg_addr - Encoded register address 13480 * phy_data - Value write to PHY register 13481 * Note: 13482 * This register read function is not thread safe. Higher level 13483 * function that calls this function must obtain a per port lock 13484 * to avoid overriding register page mapping between threads. 13485 */ 13486 STATIC int 13487 phy_84741_reg_write(int unit, soc_port_t port, uint32 flags, 13488 uint32 phy_reg_addr, uint32 phy_data) 13489 { 13490 uint8 data8[4]; 13491 uint16 data16[2]; 13492 uint16 regdata[2]; 13493 phy_ctrl_t *pc; /* PHY software state */ 13494 int rv = SOC_E_NONE; 13495 int wr_cnt; 13496 13497 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 13498 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 13499 return SOC_E_NONE; 13500 } 13501 #endif /* BCM_WARM_BOOT_SUPPORT */ 13502 13503 pc = EXT_PHY_SW_STATE(unit, port); 13504 13505 wr_cnt = 1; 13506 13507 if (flags & SOC_PHY_I2C_DATA8) { 13508 data8[0] = (uint8)phy_data; 13509 SOC_IF_ERROR_RETURN 13510 (phy_84741_i2cdev_write(unit, port, 13511 SOC_PHY_I2C_DEVAD(phy_reg_addr), 13512 SOC_PHY_I2C_REGAD(phy_reg_addr), 13513 wr_cnt, 13514 data8)); 13515 } else if (flags & SOC_PHY_I2C_DATA16) { 13516 /* This operation is generally targeted to access 16-bit device, 13517 * such as PHY IC inside the SFP. However there is no 16-bit 13518 * scratch register space on the device. Use 1.800e 13519 * for this operation. 13520 */ 13521 /* save the temp ram register */ 13522 SOC_IF_ERROR_RETURN 13523 (READ_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 13524 ®data[0])); 13525 data16[0] = phy_data; 13526 rv = _phy_84741_bsc_rw(unit, port, 13527 SOC_PHY_I2C_DEVAD(phy_reg_addr), 13528 PHY84740_I2C_OP_TYPE(PHY84740_I2CDEV_WRITE,PHY84740_I2C_16BIT), 13529 SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt, 13530 (void *)data16,PHY84740_I2C_TEMP_RAM); 13531 13532 /* restore the ram register value */ 13533 SOC_IF_ERROR_RETURN 13534 (WRITE_PHY84740_MMF_PMA_PMD_REG(unit, pc, PHY84740_I2C_TEMP_RAM, 13535 regdata[0])); 13536 } else { 13537 SOC_IF_ERROR_RETURN 13538 (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16)phy_data)); 13539 } 13540 13541 return rv; 13542 } 13543 13544 /* 13545 * Variable: 13546 * phy_84741_drv 13547 * Purpose: 13548 * Phy Driver for 40G PHY. 13549 */ 13550 13551 phy_driver_t phy_84741drv_xe = { 13552 "84740 10-Gigabit PHY Driver", 13553 phy_84741_init, /* Init */ 13554 phy_null_reset, /* Reset (dummy) */ 13555 phy_84741_link_get, /* Link get */ 13556 phy_84741_enable_set, /* Enable set */ 13557 phy_null_enable_get, /* Enable get */ 13558 phy_null_set, /* Duplex set */ 13559 phy_null_one_get, /* Duplex get */ 13560 phy_84741_speed_set, /* Speed set */ 13561 phy_84741_speed_get, /* Speed get */ 13562 phy_null_set, /* Master set */ 13563 phy_null_zero_get, /* Master get */ 13564 phy_84741_an_set, /* ANA set */ 13565 phy_84741_an_get, /* ANA get */ 13566 NULL, /* Local Advert set */ 13567 NULL, /* Local Advert get */ 13568 phy_null_mode_get, /* Remote Advert get */ 13569 phy_84741_lb_set, /* PHY loopback set */ 13570 phy_84741_lb_get, /* PHY loopback set */ 13571 phy_84741_interface_set, /* IO Interface set */ 13572 phy_84741_interface_get, /* IO Interface get */ 13573 NULL, /* PHY abilities mask */ 13574 NULL, 13575 NULL, 13576 phy_null_mdix_set, 13577 phy_null_mdix_get, 13578 phy_null_mdix_status_get, 13579 NULL, 13580 NULL, 13581 phy_null_medium_get, 13582 NULL, /* phy_cable_diag */ 13583 NULL, /* phy_link_change */ 13584 phy_84741_control_set, /* phy_control_set */ 13585 phy_84741_control_get, /* phy_control_get */ 13586 phy_84741_reg_read, /* phy_reg_read */ 13587 phy_84741_reg_write, /* phy_reg_write */ 13588 NULL, /* phy_reg_modify */ 13589 NULL, /* phy_notify */ 13590 phy_84741_probe, /* pd_probe */ 13591 phy_84741_ability_advert_set, /* pd_ability_advert_set */ 13592 phy_84741_ability_advert_get, /* pd_ability_advert_get */ 13593 phy_84741_ability_remote_get, /* pd_ability_remote_get */ 13594 phy_84741_ability_local_get, /* pd_ability_local_get */ 13595 phy_84741_firmware_set, /* pd_firmware_set */ 13596 NULL, /* pd_timesync_config_set */ 13597 NULL, /* pd_timesync_config_get */ 13598 NULL, /* pd_timesync_control_set */ 13599 NULL, /* pd_timesync_control_get */ 13600 phy_84741_diag_ctrl, /* pd_diag_ctrl */ 13601 NULL, /* pd_lane_control_set */ 13602 NULL, /* pd_lane_control_get */ 13603 NULL, /* pd_lane_reg_read */ 13604 NULL, /* pd_lane_reg_write */ 13605 NULL, /* pd_oam_config_set */ 13606 NULL, /* pd_oam_config_get */ 13607 NULL, /* pd_oam_control_set */ 13608 NULL, /* pd_oam_control_get */ 13609 NULL, /* pd_timesync_enhanced_capture_get */ 13610 phy_84741_multi_get /* pd_multi_get */ 13611 }; 13612 13613 #else /* INCLUDE_PHY_84756 */ 13614 int _phy_84741_not_empty; 13615 #endif /* INCLUDE_PHY_84756 */ 13616 13617 13618 #else /* INCLUDE_PHY_84756 */ 13619 int _phy_84756_fcmap_not_empty; 13620 #endif /* INCLUDE_PHY_84756 */ 13621 #endif /* INCLUDE_FCMAP */