phy542xx.c (365671B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 */ 6 7 /* 8 * File: phy542xx.c 9 * Purpose: PHY driver for BCM542xx (Non-MacSec) 10 * 11 * Supported BCM542X Family of PHY devices: 12 * 13 * Device Ports Media MAC Interface 14 * --------- ----- ------------------ --------------- 15 * 54210 1 1 Copper / Fiber SGMII/RGMII 16 * 54220 2 2 Copper / Fiber SGMII/RGMII 17 * 54240 4 4 Copper / Fiber SGMII 18 * 54294 4 4 Copper / Fiber SGMII 19 * 54140/94 4 4 Copper / Fiber SGMII 20 * 54290/80 8 8 Copper only SGMII 21 * 54180/90 8 8 Copper only SGMII 22 * 54292/82 8 8 Copper only QSGMII*2 23 * 54182 8 8 Copper only QSGMII*2 24 * 54192 8 8 Copper only QSGMII*2 25 * 54296 4 4 Copper / Fiber QSGMII 26 * 54295 8 8 Copper / 4 Fiber QSGMII*2 27 * 54185 8 8 Copper / 8 Fiber QSGMII*2 28 * 54195 8 8 Copper / 8 Fiber QSGMII*2 29 * 54285 8 8 Copper / Fiber QSGMII*2 30 * 31 * Workarounds: 32 * 33 * Notes: 34 */ 35 36 #include <sal/types.h> 37 #include <sal/core/spl.h> 38 #include <shared/bsl.h> 39 #include <soc/drv.h> 40 #include <soc/debug.h> 41 #include <soc/error.h> 42 #include <soc/phyreg.h> 43 44 #include <soc/phy.h> 45 #include <soc/phy/phyctrl.h> 46 #include <soc/phy/drv.h> 47 #include "phydefs.h" /* Must include before other phy related includes */ 48 49 #if defined(INCLUDE_PHY_542XX) 50 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 51 #include "phyident.h" 52 #include "phyreg.h" 53 #include "phyfege.h" 54 #include "phy542xx_int.h" 55 #include "phy542xx_regdefs.h" 56 #ifdef INCLUDE_PLP_IMACSEC 57 #include "bcm_imacsec.h" 58 #include "bcm_iunimac.h" 59 #include "phy_mac_ctrl.h" 60 #endif 61 #include <soc/oam.h> 62 63 #define DISABLE_CLK125 0 /* Disable if unused to reduce */ 64 /* EMI emissions */ 65 66 #define LC_CM_DISABLE_WORKAROUND 67 #define AUTO_MDIX_WHEN_AN_DIS 0 68 69 #ifdef INCLUDE_PLP_IMACSEC 70 71 #define IMACSEC_MDIO_ADDR_GET(id) (id & 0x3ff) 72 73 #define IMACSEC_DES_PTR_GET(_pc)\ 74 ((bcm_plp_base_t_sec_phy_access_t *)(((char *)((_pc) + 1) + (_pc)->size) - sizeof(bcm_plp_base_t_sec_phy_access_t))) 75 76 extern void _bcm_plp_register_mdio_primitives( 77 int unit, unsigned int slice, unsigned int secy_phy_id, 78 int (*read)(int, uint32, uint32, uint16*), /* HW read */ 79 int (*write)(int, uint32, uint32, uint16));/* HW write */ 80 81 82 /* 83 * Function: 84 * imacsec_blmi_io_mmi2 85 * Purpose: 86 * Access to UNIMAC and SECY register space 87 * Parameters: 88 * unit - Switch unit (dev_addr is overloaded by this) 89 * port - Switch port (dev_port is overloaded by this) 90 * op - access type (read/write register ) 91 * io_addr - Register address 92 * word_sz - word size 93 * num_entry - number of words 94 * data - data buffer 95 * Notes: 96 * Existing "phy_mac_ctrl" infrastructure uses dev_addr/dev_port 97 * for i/o access. For IMACSEC i/o access we will overload these 98 * with (Switch unit)/(Switch port). 99 */ 100 static int 101 imacsec_blmi_io_mmi2( uint32 unit, /* Switch unit */ 102 int port, /* Switch port */ 103 blmi_io_op_t op, /* I/O operation */ 104 uint32 io_addr, /* I/O address */ 105 int word_sz, /* Word size */ 106 int num_entry, /* Num entry */ 107 uint32 *data) /* Data buffer */ 108 { 109 int rv; 110 111 switch(op) { 112 113 case BLMI_IO_REG_WR: 114 rv = imacsec_plp_addr_write(unit, port, io_addr, *data); 115 break; 116 default: 117 rv = imacsec_plp_addr_read(unit, port, io_addr, data); 118 break; 119 } 120 121 return rv; 122 } 123 124 #define SPEED_MAPPING(_sp, _spr) do { \ 125 switch ( _sp ) { \ 126 case 0: return BLMI_E_NONE; \ 127 case 10: _spr = 0; break; \ 128 case 100: _spr = 1; break; \ 129 case 1000: _spr = 2; break; \ 130 default: return (BLMI_E_CONFIG); } } while(0)\ 131 132 static int get_port(const bcm_plp_base_t_access_t *pa) 133 { 134 unsigned char lm = pa->lane_map ; 135 136 switch(lm) 137 { 138 case 0x80: 139 return 7; 140 case 0x40: 141 return 6; 142 case 0x20: 143 return 5; 144 case 0x10: 145 return 4; 146 case 0x08: 147 return 3; 148 case 0x04: 149 return 2; 150 case 0x02: 151 return 1; 152 default: 153 return 0; 154 } 155 } 156 157 /* 158 * Function: 159 * _bcm_phy5419x_phy_mac_driver_detach 160 * Purpose: 161 * Delete Mapping of PHY device address and Device port 162 * Parameters: 163 * phy_dev_addr - PHY Device Address 164 * Notes: 165 */ 166 int 167 _bcm_phy5419x_phy_mac_driver_detach(phy_ctrl_t *pc) 168 { 169 int rv = SOC_E_NONE; 170 bcm_plp_base_t_sec_phy_access_t *imacsec_des; 171 172 imacsec_des = IMACSEC_DES_PTR_GET(pc); 173 174 if (imacsec_des->unimac) { 175 phy_mac_driver_detach((phy_mac_ctrl_t *)imacsec_des->unimac); 176 imacsec_des->unimac = 0; 177 } 178 return rv; 179 } 180 181 182 /* 183 * Function: 184 * _bcm_phy5419x_phy_mac_driver_attach 185 * Purpose: 186 * Add Mapping of PHY device address, Device port 187 * Parameters: 188 * phy_dev_addr - PHY Device Address 189 * dev_port - Port number 190 * Notes: 191 */ 192 int 193 _bcm_phy5419x_phy_mac_driver_attach(phy_ctrl_t *pc, 194 uint32 ms_dev_addr, 195 int dev_port, blmi_dev_io_f mmi_cbf) 196 { 197 bcm_plp_base_t_sec_phy_access_t *imacsec_des; 198 199 /* Delete the mapping if already present */ 200 (void)_bcm_phy5419x_phy_mac_driver_detach(pc); 201 202 imacsec_des = IMACSEC_DES_PTR_GET(pc); 203 204 /* Alloc unimac driver and attach */ 205 imacsec_des->unimac = 206 phy_mac_driver_attach(imacsec_des->macsec_dev_addr, 207 PHY_MAC_CORE_UNIMAC, mmi_cbf); 208 if (!imacsec_des->unimac) { 209 _bcm_phy5419x_phy_mac_driver_detach(pc); 210 return SOC_E_INTERNAL; 211 } 212 213 214 phy_mac_driver_config((phy_mac_ctrl_t *) imacsec_des->unimac, 215 PHY_MAC_CORE_UNIMAC, 216 PHY_MAC_CTRL_FLAG_UNIMAC_V2); 217 218 phy_mac_driver_unit_set((phy_mac_ctrl_t *) imacsec_des->unimac, 219 PHY_MAC_CORE_UNIMAC, 220 pc->unit); 221 222 223 return SOC_E_NONE; 224 } 225 226 227 228 #endif /* INCLUDE_PLP_IMACSEC */ 229 230 /*Copper*/ 231 #define ADVERT_ALL_COPPER_FLOW_CTRL (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX) 232 #define ADVERT_ALL_COPPER_HD_SPEED (SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB) 233 #define ADVERT_ALL_COPPER_FD_SPEED (SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB) 234 #define ADVERT_ALL_COPPER_EEE_SPEED (SOC_PA_EEE_100MB_BASETX | \ 235 SOC_PA_EEE_1GB_BASET | \ 236 SOC_PA_EEE_10GB_BASET) 237 /*Fiber*/ 238 #define ADVERT_ALL_FIBER_FLOW_CTRL (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX) 239 #define ADVERT_ALL_FIBER_FD_SPEED (SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB) 240 241 242 #define SET_FLOW_CTRL_ABILITY(ability, p) ((ability)->pause |= p) 243 #define SET_HD_SPEED_ABILITY(ability, s) ((ability)->speed_half_duplex |= s) 244 #define SET_FD_SPEED_ABILITY(ability, s) ((ability)->speed_full_duplex |= s) 245 #define SET_EEE_SPEED_ABILITY(ability, s) ((ability)->eee |= s) 246 247 #define ADVERT_ALL_COPPER(ability) do { \ 248 SET_FLOW_CTRL_ABILITY(ability, ADVERT_ALL_COPPER_FLOW_CTRL); \ 249 SET_HD_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_HD_SPEED); \ 250 SET_FD_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_FD_SPEED); \ 251 SET_EEE_SPEED_ABILITY(ability, ADVERT_ALL_COPPER_EEE_SPEED); \ 252 } while ( 0 ) 253 254 #define ADVERT_ALL_FIBER(ability) do { \ 255 SET_FLOW_CTRL_ABILITY(ability, ADVERT_ALL_FIBER_FLOW_CTRL); \ 256 SET_FD_SPEED_ABILITY(ability, ADVERT_ALL_FIBER_FD_SPEED); \ 257 } while ( 0 ) 258 259 #define PHY_IS_BCM54210(_pc) (PHY_MODEL_CHECK((_pc), \ 260 PHY_BCM54210_OUI, \ 261 PHY_BCM54210_MODEL)) 262 #define PHY_IS_BCM54220(_pc) (PHY_MODEL_CHECK((_pc), \ 263 PHY_BCM54220_OUI, \ 264 PHY_BCM54220_MODEL)) 265 #define PHY_IS_BCM54280(_pc) (PHY_MODEL_CHECK((_pc), \ 266 PHY_BCM54280_OUI, \ 267 PHY_BCM54280_MODEL)) 268 #define PHY_IS_BCM54180(_pc) (PHY_MODEL_CHECK((_pc), \ 269 PHY_BCM54180_OUI, \ 270 PHY_BCM54180_MODEL) \ 271 && (!(((_pc)->phy_rev & 0x8))) ) 272 #define PHY_IS_BCM54182(_pc) (PHY_MODEL_CHECK((_pc), \ 273 PHY_BCM54182_OUI, \ 274 PHY_BCM54182_MODEL)) 275 #define PHY_IS_BCM54185(_pc) (PHY_MODEL_CHECK((_pc), \ 276 PHY_BCM54185_OUI, \ 277 PHY_BCM54185_MODEL)\ 278 && (((_pc)->phy_rev & 0x8)) ) 279 #define PHY_IS_BCM54140(_pc) (PHY_MODEL_CHECK((_pc), \ 280 PHY_BCM54140_OUI, \ 281 PHY_BCM54140_MODEL) \ 282 && (((_pc)->phy_rev & 0x8)) ) 283 #define PHY_IS_BCM54190(_pc) (PHY_MODEL_CHECK((_pc), \ 284 PHY_BCM54190_OUI, \ 285 PHY_BCM54190_MODEL) \ 286 && (!(((_pc)->phy_rev & 0x8))) ) 287 #define PHY_IS_BCM54192(_pc) (PHY_MODEL_CHECK((_pc), \ 288 PHY_BCM54192_OUI, \ 289 PHY_BCM54192_MODEL)) 290 #define PHY_IS_BCM54195(_pc) (PHY_MODEL_CHECK((_pc), \ 291 PHY_BCM54195_OUI, \ 292 PHY_BCM54195_MODEL)\ 293 && (((_pc)->phy_rev & 0x8)) ) 294 #define PHY_IS_BCM54194(_pc) (PHY_MODEL_CHECK((_pc), \ 295 PHY_BCM54194_OUI, \ 296 PHY_BCM54194_MODEL) \ 297 && (((_pc)->phy_rev & 0x8)) ) 298 #define PHY_IS_BCM54282(_pc) (PHY_MODEL_CHECK((_pc), \ 299 PHY_BCM54282_OUI, \ 300 PHY_BCM54282_MODEL) \ 301 && ((_pc)->phy_rev & 0x8)) 302 #define PHY_IS_BCM54240(_pc) (PHY_MODEL_CHECK((_pc), \ 303 PHY_BCM54240_OUI, \ 304 PHY_BCM54240_MODEL)) 305 #define PHY_IS_BCM54285(_pc) (PHY_MODEL_CHECK((_pc), \ 306 PHY_BCM54285_OUI, \ 307 PHY_BCM54285_MODEL) \ 308 && (!((_pc)->phy_rev & 0x8))) 309 #define PHY_IS_BCM5428x(pc) ( PHY_IS_BCM54280(pc) \ 310 || PHY_IS_BCM54282(pc) \ 311 || PHY_IS_BCM54240(pc) \ 312 || PHY_IS_BCM54285(pc) ) 313 #define PHY_IS_BCM54210_220(pc) (PHY_IS_BCM54210(pc) \ 314 || PHY_IS_BCM54220(pc) ) 315 #define PHY_IS_BCM5418x_19x(pc) (PHY_IS_BCM54140(pc) \ 316 || PHY_IS_BCM54180(pc) \ 317 || PHY_IS_BCM54182(pc) \ 318 || PHY_IS_BCM54185(pc) \ 319 || PHY_IS_BCM54190(pc) \ 320 || PHY_IS_BCM54192(pc) \ 321 || PHY_IS_BCM54194(pc) \ 322 || PHY_IS_BCM54195(pc) ) 323 #if 0 324 #define PHY_BCM54282_QSGMII_DEV_ADDR(phy_base_addr) (phy_base_addr + 8) 325 #define PHY_BCM54282_QSGMII_DEV_ADDR_SHARED(phy_base_addr) (phy_base_addr + 3) 326 #endif 327 328 #define PHY_BCM54282_QSGMII_DEV_ADDR(_pc) \ 329 (PHY_BCM542XX_FLAGS((_pc)) & PHY_BCM542XX_PHYADDR_REVERSE) \ 330 ? (PHY_BCM542XX_DEV_PHY_ID_BASE(_pc) + 1) \ 331 : (PHY_BCM542XX_DEV_PHY_ID_BASE(_pc) + 8) 332 333 #define PHY_BCM54282_QSGMII_DEV_ADDR_SHARED(_pc) PHY_BCM542XX_SLICE_ADDR((_pc), 3) 334 335 #define PHY_BCM54240_28X_REV_BO(model, rev) ( \ 336 ((rev & 0x7) == 0x1) && \ 337 ((model == PHY_BCM54280_MODEL) || \ 338 (model == PHY_BCM54282_MODEL) || \ 339 (model == PHY_BCM54285_MODEL) || \ 340 (model == PHY_BCM54240_MODEL)) ) 341 #define PHY_BCM54240_28X_REV_C1(model, rev) ( \ 342 ((rev & 0x7) == 0x3) && \ 343 ((model == PHY_BCM54280_MODEL) || \ 344 (model == PHY_BCM54282_MODEL) || \ 345 (model == PHY_BCM54285_MODEL) || \ 346 (model == PHY_BCM54240_MODEL)) ) 347 #define PHY_BCM54240_28X_REV_C0_OR_OLDER(model, rev) ( \ 348 ((rev & 0x7) < 0x3) && \ 349 ((model == PHY_BCM54280_MODEL) || \ 350 (model == PHY_BCM54282_MODEL) || \ 351 (model == PHY_BCM54285_MODEL) || \ 352 (model == PHY_BCM54240_MODEL)) ) 353 354 #define PHY_IS_BCM54290(_pc) (PHY_MODEL_CHECK((_pc), \ 355 PHY_BCM54290_OUI, \ 356 PHY_BCM54290_MODEL) \ 357 && (!((_pc)->phy_rev & 0x8)) ) 358 #define PHY_IS_BCM54292(_pc) (PHY_MODEL_CHECK((_pc), \ 359 PHY_BCM54292_OUI, \ 360 PHY_BCM54292_MODEL)) 361 #define PHY_IS_BCM54294(_pc) (PHY_MODEL_CHECK((_pc), \ 362 PHY_BCM54294_OUI, \ 363 PHY_BCM54294_MODEL)\ 364 && ((_pc)->phy_rev & 0x8)) 365 #define PHY_IS_BCM54295(_pc) (PHY_MODEL_CHECK((_pc), \ 366 PHY_BCM54295_OUI, \ 367 PHY_BCM54295_MODEL) \ 368 && (((_pc)->phy_rev & 0x8))) 369 #define PHY_IS_BCM54296 PHY_IS_BCM54295 370 #define PHY_IS_BCM5429X(pc) ( PHY_IS_BCM54290(pc) \ 371 || PHY_IS_BCM54294(pc) \ 372 || PHY_IS_BCM54292(pc) \ 373 || PHY_IS_BCM54295(pc) ) 374 375 #define SOC_IF_ERROR_BREAK(op, _rv) if ( ((_rv) = (op)) < 0 ) { break; } 376 #define PHY_RETAIN_SUPER_ISOLATE 0x80 377 /* macros for ext_phy_autodetect_en and ext_phy_fiber_iface */ 378 #define EXT_PHY_AUTODETECT_DIS 0x0 379 #define EXT_PHY_AUTODETECT_EN 0x1 380 #define EXT_PHY_FIBER_IFACE_1000X 0x0 381 #define EXT_PHY_FIBER_IFACE_100FX 0x1 382 #define EXT_PHY_FIBER_IFACE_SGMII 0x2 383 384 int phy_bcm542xx_reset(int unit, soc_port_t port, void *user_arg); 385 STATIC int _phy_bcm542xx_no_reset_setup(int unit, soc_port_t port); 386 STATIC int phy_bcm542xx_duplex_get(int unit, soc_port_t port, int *duplex); 387 STATIC int phy_bcm542xx_duplex_set(int unit, soc_port_t port, int duplex); 388 STATIC int phy_bcm542xx_speed_get(int unit, soc_port_t port, int *speed); 389 STATIC int phy_bcm542xx_speed_set(int unit, soc_port_t port, int speed); 390 STATIC int phy_bcm542xx_master_get(int unit, soc_port_t port, int *master); 391 STATIC int phy_bcm542xx_master_set(int unit, soc_port_t port, int master); 392 STATIC int phy_bcm542xx_autoneg_get(int unit, soc_port_t port, int *autoneg, int *autoneg_done); 393 STATIC int phy_bcm542xx_autoneg_set(int unit, soc_port_t port, int autoneg); 394 STATIC int phy_bcm542xx_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode); 395 STATIC int phy_bcm542xx_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode); 396 STATIC int phy_bcm542xx_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability); 397 STATIC int phy_bcm542xx_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability); 398 STATIC int phy_bcm542xx_init_setup(int unit, soc_port_t port, int reset, int automedium, 399 int fiber_preferred, int fiber_detect, 400 int fiber_enable, int copper_enable, 401 int ext_phy_autodetect_en, int ext_phy_fiber_iface); 402 STATIC int phy_bcm542xx_control_set(int unit, soc_port_t port, 403 soc_phy_control_t type, uint32 value); 404 int phy_bcm542xx_oam_config_get(int unit, soc_port_t port, soc_port_config_phy_oam_t *conf); 405 extern int phy_ecd_cable_diag_init_40nm(int unit, soc_port_t port); 406 extern int phy_ecd_cable_diag_40nm(int unit, soc_port_t port, 407 soc_port_cable_diag_t *status, uint16 ecd_ctrl); 408 int _phy_bcm542xx_rgmii_to_copper_mode(int unit, soc_port_t port); 409 int _phy_bcm542xx_rgmii_to_fiber_mode(int unit, soc_port_t port); 410 411 /*********************************************************************** 412 * 413 * HELPER FUNCTIONS 414 */ 415 416 int 417 phy_bcm542xx_reg_read(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 418 uint8 reg_addr, uint16 *data) 419 { 420 int rv; 421 uint16 val; 422 423 rv = SOC_E_NONE; 424 if ( flags & PHY_BCM542XX_REG_QSGMII ) { 425 /* Do not apply shadow register logic for QSGMII register access */ 426 rv = PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, data); 427 428 } else if ( flags & (PHY_BCM542XX_REG_1000X | 429 PHY_BCM542XX_REG_PRI_SERDES) ) { /* fiber registers */ 430 if ( reg_addr <= 0x0f ) { 431 if ( PHY_IS_BCM54210_220(pc) && (flags & PHY_BCM542XX_REG_1000X) ) { 432 /* 54220/210 fiber is controlled by Secondary SerDes */ 433 rv = phy_bcm542xx_direct_reg_read(unit, pc, (uint16) 434 reg_addr | PHY_BCM542XX_2ND_SERDES_BASE_OFFSET, 435 data); 436 } else { /* not 54220_210 or PHY_BCM542XX_REG_PRI_SERDES */ 437 /* Map 1000X page */ 438 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 439 uint16 blk_sel, val; 440 val = 0x7c00; 441 SOC_IF_ERROR_RETURN 442 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 443 SOC_IF_ERROR_RETURN 444 (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x1c, &blk_sel)); 445 val = blk_sel | 0x8001; 446 SOC_IF_ERROR_RETURN 447 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 448 #else 449 SOC_IF_ERROR_RETURN( 450 phy_bcm542xx_direct_reg_modify(unit, pc, 451 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 452 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN, 453 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) ); 454 #endif 455 /* Read 1000X IEEE register */ 456 SOC_IF_ERROR_RETURN 457 (PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, data)); 458 459 /* Restore IEEE mapping */ 460 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 461 val = (blk_sel & 0xfffe) | 0x8000; 462 SOC_IF_ERROR_RETURN 463 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 464 #else 465 SOC_IF_ERROR_RETURN( 466 phy_bcm542xx_direct_reg_modify(unit, pc, 467 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 468 PHY_BCM542XX_MODE_CONTROL_REG_1000X_DIS, 469 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) ); 470 #endif 471 } 472 } else { /* (reg_addr > 0xf) */ 473 rv = SOC_E_PARAM; 474 } 475 476 } else { 477 switch ( reg_addr ) { 478 /* Map shadow registers */ 479 case 0x15: 480 SOC_IF_ERROR_RETURN 481 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x17, reg_bank)); 482 break; 483 case 0x18: 484 if ( reg_bank <= 0x0007 ) { 485 val = (reg_bank << 12) | 0x7; 486 SOC_IF_ERROR_RETURN 487 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val)); 488 } else { 489 rv = SOC_E_PARAM; 490 } 491 break; 492 case 0x1C: 493 if ( reg_bank <= 0x001F ) { 494 val = (reg_bank << 10); 495 SOC_IF_ERROR_RETURN 496 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val)); 497 } else { 498 rv = SOC_E_PARAM; 499 } 500 break; 501 case 0x1D: 502 if ( reg_bank <= 0x0001 ) { 503 val = reg_bank << 15; 504 SOC_IF_ERROR_RETURN 505 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val)); 506 } else { 507 rv = SOC_E_PARAM; 508 } 509 break; 510 } 511 if ( SOC_SUCCESS(rv) ) { 512 rv = PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, data); 513 } 514 } 515 516 if ( SOC_FAILURE(rv) ) { 517 LOG_INFO(BSL_LS_SOC_PHY, 518 (BSL_META_U(unit, 519 "phy_bcm542xx_reg_read: failed:" 520 "phy_id=0x%2x reg_bank=0x%04x reg_addr=0x%02x " 521 "rv=%d\n"), pc->phy_id, reg_bank, reg_addr, rv)); 522 } 523 return rv; 524 } 525 526 527 int 528 phy_bcm542xx_reg_write(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 529 uint8 reg_addr, uint16 data) 530 { 531 int rv; 532 533 if ( flags & PHY_BCM542XX_REG_QSGMII ) { 534 /* Do not apply shadow register logic for QSGMII register access */ 535 SOC_IF_ERROR_RETURN 536 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, data)); 537 return SOC_E_NONE; 538 } 539 540 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 541 return SOC_E_NONE; 542 } 543 rv = SOC_E_NONE; 544 545 if ( flags & (PHY_BCM542XX_REG_1000X | 546 PHY_BCM542XX_REG_PRI_SERDES) ) { /* fiber registers */ 547 if ( reg_addr <= 0x0f ) { 548 if ( PHY_IS_BCM54210_220(pc) && (flags & PHY_BCM542XX_REG_1000X) ) { 549 /* 54220/210 fiber is controlled by Secondary SerDes */ 550 rv = phy_bcm542xx_direct_reg_write(unit, pc,(uint16) 551 reg_addr | PHY_BCM542XX_2ND_SERDES_BASE_OFFSET, 552 data); 553 } else { /* not 54220_210 or PHY_BCM542XX_REG_PRI_SERDES */ 554 /* Map 1000X page */ 555 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 556 uint16 blk_sel, val; 557 val = 0x7c00; 558 SOC_IF_ERROR_RETURN 559 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 560 SOC_IF_ERROR_RETURN 561 (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x1c, &blk_sel)); 562 val = blk_sel | 0x8001; 563 SOC_IF_ERROR_RETURN 564 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 565 #else 566 SOC_IF_ERROR_RETURN( 567 phy_bcm542xx_direct_reg_modify(unit, pc, 568 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 569 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN, 570 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) ); 571 #endif 572 /* Write 1000X IEEE register */ 573 SOC_IF_ERROR_RETURN 574 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, data)); 575 576 /* Restore IEEE mapping */ 577 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 578 val = (blk_sel & 0xfffe) | 0x8000; 579 SOC_IF_ERROR_RETURN 580 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 581 #else 582 SOC_IF_ERROR_RETURN( 583 phy_bcm542xx_direct_reg_modify(unit, pc, 584 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 585 PHY_BCM542XX_MODE_CONTROL_REG_1000X_DIS, 586 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) ); 587 #endif 588 } 589 } else { /* (reg_addr > 0xf) */ 590 rv = SOC_E_PARAM; 591 } 592 593 } else { 594 switch ( reg_addr ) { 595 /* Map shadow registers */ 596 case 0x15: 597 SOC_IF_ERROR_RETURN 598 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x17, reg_bank)); 599 break; 600 case 0x18: 601 if ( reg_bank <= 0x0007 ) { 602 if (reg_bank == 0x0007) { 603 data |= 0x8000; 604 } 605 data = (data & ~(0x0007)) | reg_bank; 606 } else { 607 rv = SOC_E_PARAM; 608 } 609 break; 610 case 0x1C: 611 if ( reg_bank <= 0x001F ) { 612 data = 0x8000 | (reg_bank << 10) | (data & 0x03FF); 613 } else { 614 rv = SOC_E_PARAM; 615 } 616 break; 617 case 0x1D: 618 if ( reg_bank == 0x0000 ) { 619 data = data & 0x07FFF; 620 } else { 621 rv = SOC_E_PARAM; 622 } 623 break; 624 } 625 if ( SOC_SUCCESS(rv) ) { 626 rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, data); 627 } 628 } 629 630 if ( SOC_FAILURE(rv) ) { 631 LOG_INFO(BSL_LS_SOC_PHY, 632 (BSL_META_U(unit, 633 "phy_bcm542xx_reg_write: failed:" 634 "phy_id=0x%2x reg_bank=0x%04x reg_addr=0x%02x " 635 "rv=%d\n"), pc->phy_id, reg_bank, reg_addr, rv)); 636 } 637 return rv; 638 } 639 640 int 641 phy_bcm542xx_reg_modify(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 642 uint8 reg_addr, uint16 data, uint16 mask) 643 { 644 int rv; 645 uint16 val; 646 647 if ( flags & PHY_BCM542XX_REG_QSGMII ) { 648 /* Do not apply shadow register logic for QSGMII register access */ 649 SOC_IF_ERROR_RETURN 650 (PHY_BCM542XX_MODIFY_PHY_REG(unit, pc, reg_addr, data, mask)); 651 return SOC_E_NONE; 652 } 653 654 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 655 return SOC_E_NONE; 656 } 657 rv = SOC_E_NONE; 658 659 if ( flags & (PHY_BCM542XX_REG_1000X | 660 PHY_BCM542XX_REG_PRI_SERDES) ) { /* fiber registers */ 661 if ( reg_addr <= 0x0f ) { 662 if ( PHY_IS_BCM54210_220(pc) && (flags & PHY_BCM542XX_REG_1000X) ) { 663 /* 54220/210 fiber is controlled by Secondary SerDes */ 664 rv = phy_bcm542xx_direct_reg_modify(unit, pc,(uint16) 665 reg_addr | PHY_BCM542XX_2ND_SERDES_BASE_OFFSET, 666 data, mask); 667 } else { /* not 54220_210 or PHY_BCM542XX_REG_PRI_SERDES */ 668 /* Map 1000X page */ 669 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 670 uint16 blk_sel; 671 val = 0x7c00; 672 SOC_IF_ERROR_RETURN 673 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 674 SOC_IF_ERROR_RETURN 675 (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x1c, &blk_sel)); 676 val = blk_sel | 0x8001; 677 SOC_IF_ERROR_RETURN 678 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 679 #else 680 SOC_IF_ERROR_RETURN( 681 phy_bcm542xx_direct_reg_modify(unit, pc, 682 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 683 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN, 684 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) ); 685 #endif 686 /* Modify 1000X IEEE register */ 687 SOC_IF_ERROR_RETURN 688 (PHY_BCM542XX_MODIFY_PHY_REG(unit, pc, reg_addr, data, mask)); 689 690 /* Restore IEEE mapping */ 691 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 692 val = (blk_sel & 0xfffe) | 0x8000; 693 SOC_IF_ERROR_RETURN 694 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x1c, val)); 695 #else 696 SOC_IF_ERROR_RETURN( 697 phy_bcm542xx_direct_reg_modify(unit, pc, 698 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 699 PHY_BCM542XX_MODE_CONTROL_REG_1000X_DIS, 700 PHY_BCM542XX_MODE_CONTROL_REG_1000X_EN) ); 701 #endif 702 } 703 } else { /* (reg_addr > 0xf) */ 704 rv = SOC_E_PARAM; 705 } 706 707 } else { 708 switch ( reg_addr ) { 709 /* Map shadow registers */ 710 case 0x15: 711 SOC_IF_ERROR_RETURN 712 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x17, reg_bank)); 713 break; 714 case 0x18: 715 if ( reg_bank <= 0x0007 ) { 716 val = (reg_bank << 12) | 0x7; 717 SOC_IF_ERROR_RETURN 718 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val)); 719 720 if (reg_bank == 0x0007) { 721 data |= 0x8000; 722 mask |= 0x8000; 723 } 724 mask &= ~(0x0007); 725 } else { 726 rv = SOC_E_PARAM; 727 } 728 break; 729 case 0x1C: 730 if ( reg_bank <= 0x001F ) { 731 val = (reg_bank << 10); 732 SOC_IF_ERROR_RETURN 733 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, val)); 734 data |= 0x8000; 735 mask |= 0x8000; 736 mask &= ~(0x1F << 10); 737 } else { 738 rv = SOC_E_PARAM; 739 } 740 break; 741 case 0x1D: 742 if ( reg_bank == 0x0000 ) { 743 mask &= 0x07FFF; 744 } else { 745 rv = SOC_E_PARAM; 746 } 747 break; 748 } 749 if ( SOC_SUCCESS(rv) ) { 750 rv = PHY_BCM542XX_MODIFY_PHY_REG(unit, pc, reg_addr, data, mask); 751 } 752 } 753 754 if ( SOC_FAILURE(rv) ) { 755 LOG_INFO(BSL_LS_SOC_PHY, 756 (BSL_META_U(unit, 757 "phy_bcm542xx_reg_modify: failed:" 758 "phy_id=0x%2x reg_bank=0x%04x reg_addr=0x%02x " 759 "rv=%d\n"), pc->phy_id, reg_bank, reg_addr, rv)); 760 } 761 return rv; 762 } 763 764 int 765 phy_bcm542xx_reg_read_modify_write(int unit, phy_ctrl_t *pc, uint32 reg_addr, 766 uint16 reg_data, uint16 reg_mask) 767 { 768 uint16 tmp, otmp; 769 770 reg_data = reg_data & reg_mask; 771 772 SOC_IF_ERROR_RETURN 773 (PHY_BCM542XX_READ_PHY_REG(unit, pc, reg_addr, &tmp)); 774 otmp = tmp; 775 tmp &= ~(reg_mask); 776 tmp |= reg_data; 777 778 if (otmp != tmp) { 779 SOC_IF_ERROR_RETURN 780 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, reg_addr, tmp)); 781 } 782 return SOC_E_NONE; 783 } 784 785 786 /* 787 * Function: 788 * phy_bcm542xx_rdb_reg_read 789 * Purpose: RDB register read 790 * (works ONLY under RDB register addressing mode !!) 791 * Parameters: 792 * reg_addr - RDB register address 793 * data - the 16-bit value got from the specific RDB register 794 * Returns: 795 */ 796 int phy_bcm542xx_rdb_reg_read(int unit, phy_ctrl_t *pc, 797 uint16 reg_addr, uint16 *data) 798 { 799 int rv; 800 801 /* MDIO write the RDB reg. address to reg.0x1E = <reg_addr> */ 802 rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 803 PHY_BCM542XX_RDB_ADDR_REG_OFFSET, 804 PHY_BCM542XX_RDB_ADDR_REG_ADDR & reg_addr); 805 if ( SOC_E_NONE == rv ) { 806 /* MDIO read from reg.0x1F to get the RDB register's value as <data> */ 807 rv = PHY_BCM542XX_READ_PHY_REG(unit, pc, 808 PHY_BCM542XX_RDB_DATA_REG_OFFSET, data); 809 } 810 811 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 812 if ( SOC_E_NONE != rv ) { /* failed to access reg. 0x1e or 0x1f */ 813 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* quit RDB assess mode */ 814 _SHR_ERROR_TRACE(rv); 815 } 816 #endif 817 return (rv); 818 } 819 820 /* 821 * Function: 822 * phy_bcm542xx_rdb_reg_write 823 * Purpose: RDB register write 824 * (works ONLY under RDB register addressing mode !!) 825 * Parameters: 826 * reg_addr - RDB register address 827 * data - 16-bit value writting to the specific RDB register 828 * Returns: 829 */ 830 int phy_bcm542xx_rdb_reg_write(int unit, phy_ctrl_t *pc, 831 uint16 reg_addr, uint16 data) 832 { 833 int rv; 834 835 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 836 return SOC_E_NONE; 837 } 838 839 /* MDIO write the RDB reg. address to reg.0x1E = <reg_addr> */ 840 rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 841 PHY_BCM542XX_RDB_ADDR_REG_OFFSET, 842 PHY_BCM542XX_RDB_ADDR_REG_ADDR & reg_addr); 843 if ( SOC_E_NONE == rv ) { 844 /* MDIO write to reg.0x1F to set the RDB resister's value as <data> */ 845 rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 846 PHY_BCM542XX_RDB_DATA_REG_OFFSET, data); 847 } 848 849 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 850 if ( SOC_E_NONE != rv ) { /* failed to access reg. 0x1e or 0x1f */ 851 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* quit RDB assess mode */ 852 _SHR_ERROR_TRACE(rv); 853 } 854 #endif 855 return (rv); 856 } 857 858 /* 859 * Function: 860 * phy_bcm542xx_rdb_reg_modify 861 * Purpose: RDB register modification 862 * (works ONLY under RDB register addressing mode !!) 863 * Parameters: 864 * reg_addr - RDB register address 865 * data - 16-bit value writting to the specific RDB register 866 * mask - bit mask 867 * Returns: 868 */ 869 int phy_bcm542xx_rdb_reg_modify(int unit, phy_ctrl_t *pc, 870 uint16 reg_addr, uint16 data, uint16 mask) 871 { 872 int rv; 873 874 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 875 return SOC_E_NONE; 876 } 877 878 /* MDIO write the RDB reg. address to reg.0x1E = <reg_addr> */ 879 rv = PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 880 PHY_BCM542XX_RDB_ADDR_REG_OFFSET, 881 PHY_BCM542XX_RDB_ADDR_REG_ADDR & reg_addr); 882 if ( SOC_E_NONE == rv ) { 883 /* MDIO read from reg.0x1F to modify the RDB register's value */ 884 rv = PHY_BCM542XX_MODIFY_PHY_REG(unit, pc, 885 PHY_BCM542XX_RDB_DATA_REG_OFFSET, data, mask); 886 } 887 888 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 889 if ( SOC_E_NONE != rv ) { /* failed to access reg. 0x1e or 0x1f */ 890 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* quit RDB assess mode */ 891 _SHR_ERROR_TRACE(rv); 892 } 893 #endif 894 return (rv); 895 } 896 897 898 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 899 900 /* 901 * Function: 902 * phy_bcm542xx_direct_reg_read 903 * Purpose: 904 * switching to RDB access mode and read an RDB register, 905 * then back to the legacy access mode (quit the RDB mode). 906 * Parameters: 907 * Returns: 908 */ 909 int phy_bcm542xx_direct_reg_read(int unit, phy_ctrl_t *pc, 910 uint16 reg_addr, uint16 *data) 911 { 912 int rv; 913 914 PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc); /* set RDB register access mode */ 915 rv = phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, data); 916 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */ 917 return (rv); 918 } 919 920 /* 921 * Function: 922 * phy_bcm542xx_direct_reg_write 923 * Purpose: 924 * switching to RDB access mode and write an RDB register, 925 * then back to the legacy access mode (quit the RDB mode). 926 * Parameters: 927 * Returns: 928 */ 929 int phy_bcm542xx_direct_reg_write(int unit, phy_ctrl_t *pc, 930 uint16 reg_addr, uint16 data) 931 { 932 int rv; 933 934 PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc); /* set RDB register access mode */ 935 rv = phy_bcm542xx_rdb_reg_write(unit, pc, reg_addr, data); 936 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */ 937 return (rv); 938 } 939 940 /* 941 * Function: 942 * phy_bcm542xx_direct_reg_modify 943 * Purpose: 944 * switching to RDB access mode and modify an RDB register, 945 * then back to the legacy access mode (quit the RDB mode). 946 * Parameters: 947 * Returns: 948 */ 949 int phy_bcm542xx_direct_reg_modify(int unit, phy_ctrl_t *pc, 950 uint16 reg_addr, uint16 data, uint16 mask) 951 { 952 int rv; 953 954 PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc); /* set RDB register access mode */ 955 rv = phy_bcm542xx_rdb_reg_modify(unit, pc, reg_addr, data, mask); 956 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */ 957 return (rv); 958 } 959 960 #endif /* PHY_BCM542XX_DEFAULT_TO_LEGACY_ACCESS */ 961 962 /* 963 * QSGMII register READ 964 */ 965 int 966 phy_bcm542xx_qsgmii_reg_read(int unit, phy_ctrl_t *pc, 967 int dev_port, uint16 block, 968 uint8 reg, uint16 *data) 969 { 970 uint16 val; 971 972 /* Lanes from 0 to 7 */ 973 if ((dev_port < 0) || (dev_port > 7) ) { 974 return SOC_E_FAIL; 975 } 976 977 /* Set BAR to AER */ 978 if ( PHY_IS_BCM5418x_19x(pc) ) { 979 val = 0xFFDE; 980 } else { 981 val = 0xFFD0; 982 } 983 SOC_IF_ERROR_RETURN 984 (phy_bcm542xx_reg_write(unit, pc, PHY_BCM542XX_REG_QSGMII, 985 0, 0x1F, val)); 986 987 /* Set AER reg to access SGMII lane */ 988 val = dev_port; 989 SOC_IF_ERROR_RETURN 990 (phy_bcm542xx_reg_write(unit, pc, PHY_BCM542XX_REG_QSGMII, 991 0, 0x1E, val)); 992 993 /* Set BAR to Register Block */ 994 val = (block & 0xfff0); 995 SOC_IF_ERROR_RETURN 996 (phy_bcm542xx_reg_write(unit, pc, PHY_BCM542XX_REG_QSGMII, 997 0, 0x1F, val)); 998 /* Read the register */ 999 if ( block >= 0x8000 ) { 1000 reg |= 0x10; 1001 } 1002 1003 SOC_IF_ERROR_RETURN 1004 (phy_bcm542xx_reg_read(unit, pc, PHY_BCM542XX_REG_QSGMII, 1005 0, reg, data)); 1006 1007 return SOC_E_NONE; 1008 1009 } 1010 1011 /* 1012 * QSGMII register WRITE 1013 */ 1014 int 1015 phy_bcm542xx_qsgmii_reg_write(int unit, phy_ctrl_t *pc, 1016 int dev_port, uint16 block, uint8 reg, 1017 uint16 data) 1018 { 1019 uint16 val; 1020 1021 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 1022 return SOC_E_NONE; 1023 } 1024 1025 /* Lanes from 0 to 7 */ 1026 if ((dev_port < 0) || (dev_port > 7) ) { 1027 return SOC_E_FAIL; 1028 } 1029 1030 /* Set BAR to AER */ 1031 if ( PHY_IS_BCM5418x_19x(pc) ) { 1032 val = 0xFFDE; 1033 } else { 1034 val = 0xFFD0; 1035 } 1036 1037 SOC_IF_ERROR_RETURN 1038 (phy_bcm542xx_reg_write(unit, pc, 1039 PHY_BCM542XX_REG_QSGMII, 0, 0x1F, val)); 1040 1041 /* set aer reg to access sgmii lane */ 1042 val = dev_port; 1043 SOC_IF_ERROR_RETURN 1044 (phy_bcm542xx_reg_write(unit, pc, 1045 PHY_BCM542XX_REG_QSGMII, 0, 0x1E, val)); 1046 1047 /* set bar to register block */ 1048 val = (block & 0xfff0); 1049 SOC_IF_ERROR_RETURN 1050 (phy_bcm542xx_reg_write(unit, pc, 1051 PHY_BCM542XX_REG_QSGMII, 0, 0x1F, val)); 1052 1053 /* Write the register */ 1054 if (block >= 0x8000) { 1055 reg |= 0x10; 1056 } 1057 1058 SOC_IF_ERROR_RETURN 1059 (phy_bcm542xx_reg_write(unit, pc, 1060 PHY_BCM542XX_REG_QSGMII, 0, reg, data)); 1061 1062 return SOC_E_NONE; 1063 } 1064 1065 /* 1066 * QSGMII register MODIFY 1067 */ 1068 int 1069 phy_bcm542xx_qsgmii_reg_modify(int unit, phy_ctrl_t *pc, 1070 int dev_port, uint16 block, 1071 uint8 reg_addr, uint16 reg_data, 1072 uint16 reg_mask) 1073 { 1074 uint16 tmp, otmp; 1075 1076 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 1077 return SOC_E_NONE; 1078 } 1079 1080 reg_data = reg_data & reg_mask; 1081 1082 phy_bcm542xx_qsgmii_reg_read(unit, pc, dev_port, block, 1083 reg_addr, &tmp); 1084 otmp = tmp; 1085 tmp &= ~(reg_mask); 1086 tmp |= reg_data; 1087 1088 if (otmp != tmp) { 1089 phy_bcm542xx_qsgmii_reg_write(unit, pc, dev_port, block, 1090 reg_addr, tmp); 1091 } 1092 return SOC_E_NONE; 1093 } 1094 1095 /* 1096 * Function: 1097 * phy_bcm542xx_cl45_reg_read 1098 * Purpose: 1099 * Read Clause 45 Register using Clause 22 register access 1100 * Parameters: 1101 * unit - StrataSwitch unit #. 1102 * pc - Phy control 1103 * flags - Flags 1104 * dev_addr - Clause 45 Device 1105 * reg_addr - Register Address to read 1106 * val - Value Read 1107 * Returns: 1108 * SOC_E_XXX 1109 */ 1110 1111 int 1112 phy_bcm542xx_cl45_reg_read(int unit, phy_ctrl_t *pc, uint8 dev_addr, 1113 uint16 reg_addr, uint16 *val) 1114 { 1115 uint16 temp16 = (dev_addr & 0x001f); 1116 1117 /* Write Device Address to register 0x0D (Set Function field to Address) */ 1118 SOC_IF_ERROR_RETURN 1119 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16)); 1120 1121 /* Select the register by writing to register address to register 0x0E */ 1122 SOC_IF_ERROR_RETURN 1123 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0E, reg_addr)); 1124 1125 temp16 = 0x4000 | (dev_addr & 0x001f); 1126 /* Write Device Address to register 0x0D (Set Function field to Data) */ 1127 SOC_IF_ERROR_RETURN 1128 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16)); 1129 1130 /* Read register 0x0E to get the value */ 1131 SOC_IF_ERROR_RETURN 1132 (PHY_BCM542XX_READ_PHY_REG( unit, pc, 0x0E, val)); 1133 1134 return SOC_E_NONE; 1135 } 1136 1137 /* 1138 * Function: 1139 * phy_bcm542xx_cl45_reg_write 1140 * Purpose: 1141 * Write Clause 45 Register content using Clause 22 register access 1142 * Parameters: 1143 * unit - StrataSwitch unit #. 1144 * pc - Phy control 1145 * flags - Flags 1146 * dev_addr - Clause 45 Device 1147 * reg_addr - Register Address to read 1148 * val - Value to be written 1149 * Returns: 1150 * SOC_E_XXX 1151 */ 1152 1153 int 1154 phy_bcm542xx_cl45_reg_write(int unit, phy_ctrl_t *pc, uint8 dev_addr, 1155 uint16 reg_addr, uint16 val) 1156 { 1157 uint16 temp16 = (dev_addr & 0x001f); 1158 1159 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 1160 return SOC_E_NONE; 1161 } 1162 1163 /* Write Device Address to register 0x0D (Set Function field to Address)*/ 1164 SOC_IF_ERROR_RETURN 1165 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16)); 1166 1167 /* Select the register by writing to register address to register 0x0E */ 1168 SOC_IF_ERROR_RETURN 1169 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0E, reg_addr)); 1170 1171 temp16 = 0x4000 | (dev_addr & 0x001f); 1172 /* Write Device Address to register 0x0D (Set Function field to Data)*/ 1173 SOC_IF_ERROR_RETURN 1174 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0D, temp16)); 1175 1176 /* Write register 0x0E to write the value */ 1177 SOC_IF_ERROR_RETURN 1178 (PHY_BCM542XX_WRITE_PHY_REG(unit, pc, 0x0E, val)); 1179 1180 return SOC_E_NONE; 1181 } 1182 1183 /* 1184 * Function: 1185 * _phy_bcm542xx_cl45_reg_modify 1186 * Purpose: 1187 * Modify Clause 45 Register contents using Clause 22 register access 1188 * Parameters: 1189 * unit - StrataSwitch unit #. 1190 * pc - Phy control 1191 * flags - Flags 1192 * reg_bank - Register bank 1193 * dev_addr - Clause 45 Device 1194 * reg_addr - Register Address to read 1195 * val - Value 1196 * mask - Mask for modifying the contents of the register 1197 * Returns: 1198 * SOC_E_XXX 1199 */ 1200 1201 int 1202 phy_bcm542xx_cl45_reg_modify(int unit, phy_ctrl_t *pc, uint8 dev_addr, 1203 uint16 reg_addr, uint16 val, uint16 mask) 1204 { 1205 uint16 value = 0; 1206 1207 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 1208 return SOC_E_NONE; 1209 } 1210 1211 phy_bcm542xx_cl45_reg_read(unit, pc, dev_addr, reg_addr, &value); 1212 1213 value = (val & mask) | (value & ~mask); 1214 1215 phy_bcm542xx_cl45_reg_write(unit, pc, dev_addr, reg_addr, value); 1216 1217 return SOC_E_NONE; 1218 } 1219 1220 /* 1221 * Function: 1222 * _phy_bcm542xx_hidden_rev_num_get 1223 * Purpose: 1224 * Get hidden revision number from CORE_ExpFA - Hidden Identifier Reg. 1225 * For distinguishing 54296 vs. 54295 ( 0x8 vs. 0x0 ) 1226 * Parameters: 1227 * 1228 * Notes: 1229 */ 1230 STATIC uint16 1231 _phy_bcm542xx_hidden_rev_num_get(int unit, phy_ctrl_t *pc) 1232 { 1233 uint16 hidden_rev; 1234 /* CORE_ExpFA - Hidden Identifier Reg., RDB.0x0FA[3:0] HIDDEN_REV_NUM */ 1235 phy_bcm542xx_direct_reg_read(unit, pc, 1236 PHY_BCM542XX_HIDDEN_IDENTIFIER_REG_OFFSET, &hidden_rev); 1237 return (hidden_rev & PHY_BCM542XX_HIDDEN_REV_NUM_MASK); 1238 } 1239 1240 /* 1241 * Function: 1242 * _phy_bcm542xx_get_model_rev 1243 * Purpose: 1244 * Get OUI, Model and Revision of the PHY 1245 * Parameters: 1246 * phy_dev_addr - PHY Device Address 1247 * oui - (OUT) Organization Unique Identifier 1248 * model - (OUT)Device Model number` 1249 * rev - (OUT)Device Revision number 1250 * Notes: 1251 */ 1252 STATIC int 1253 _phy_bcm542xx_model_rev_get(int unit, phy_ctrl_t *pc, 1254 int *oui, int *model, int *rev) 1255 { 1256 uint16 id0, id1; 1257 1258 SOC_IF_ERROR_RETURN 1259 (PHY_READ_BCM542XX_MII_PHY_ID0r(unit, pc, &id0)); 1260 SOC_IF_ERROR_RETURN 1261 (PHY_READ_BCM542XX_MII_PHY_ID1r(unit, pc, &id1)); 1262 1263 *oui = PHY_OUI(id0, id1); 1264 *model = PHY_MODEL(id0, id1); 1265 *rev = PHY_REV(id0, id1); 1266 1267 return SOC_E_NONE; 1268 } 1269 1270 1271 /* 1272 * Function: 1273 * _phy_bcm542xx_auto_negotiate_ew (Autoneg-ed mode with E@W on). 1274 * Purpose: 1275 * Determine autoneg-ed mode between 1276 * two ends of a link 1277 * Parameters: 1278 * unit - StrataSwitch unit #. 1279 * port - StrataSwitch port #. 1280 * speed - (OUT) greatest common speed. 1281 * duplex - (OUT) greatest common duplex. 1282 * link - (OUT) Boolean, true indicates link established. 1283 * Returns: 1284 * SOC_E_XXX 1285 * Notes: 1286 * No synchronization performed at this level. 1287 */ 1288 1289 static int 1290 _phy_bcm542xx_auto_negotiate_ew(int unit, phy_ctrl_t *pc, int *speed, int *duplex) 1291 { 1292 int t_speed, t_duplex; 1293 uint16 mii_assr; 1294 1295 SOC_IF_ERROR_RETURN 1296 (PHY_READ_BCM542XX_MII_AUX_STATUSr(unit, pc,&mii_assr)); 1297 1298 switch ((mii_assr >> 8) & 0x7) { 1299 case 0x7: 1300 t_speed = 1000; 1301 t_duplex = TRUE; 1302 break; 1303 case 0x6: 1304 t_speed = 1000; 1305 t_duplex = FALSE; 1306 break; 1307 case 0x5: 1308 t_speed = 100; 1309 t_duplex = TRUE; 1310 break; 1311 case 0x3: 1312 t_speed = 100; 1313 t_duplex = FALSE; 1314 break; 1315 case 0x2: 1316 t_speed = 10; 1317 t_duplex = TRUE; 1318 break; 1319 case 0x1: 1320 t_speed = 10; 1321 t_duplex = FALSE; 1322 break; 1323 default: 1324 t_speed = 0; /* 0x4 is 100BASE-T4 which is not supported */ 1325 t_duplex = FALSE; 1326 break; 1327 } 1328 1329 if (speed) *speed = t_speed; 1330 if (duplex) *duplex = t_duplex; 1331 1332 return(SOC_E_NONE); 1333 } 1334 1335 /* 1336 * Function: 1337 * _phy_bcm542xx_auto_negotiate_gcd (greatest common denominator). 1338 * Purpose: 1339 * Determine the current greatest common denominator between 1340 * two ends of a link 1341 * Parameters: 1342 * speed - (OUT) greatest common speed. 1343 * duplex - (OUT) greatest common duplex. 1344 * link - (OUT) Boolean, true indicates link established. 1345 * Notes: 1346 */ 1347 1348 STATIC int 1349 _phy_bcm542xx_auto_negotiate_gcd(int unit,soc_port_t port, phy_ctrl_t *pc, int *speed, int *duplex) 1350 { 1351 int t_speed, t_duplex; 1352 uint16 mii_ana, mii_anp, mii_stat; 1353 uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; 1354 #ifdef INCLUDE_PLP_IMACSEC 1355 int speed_m; 1356 unsigned int port_m; 1357 bcm_plp_base_t_sec_phy_access_t *imacsec_des; 1358 uint16 imacsec_cfg; 1359 soc_port_t port_s; 1360 PHY_BCM542XX_DEV_DESC_t *phy_des=NULL; 1361 unsigned int speed_mask=0x3; 1362 #else 1363 COMPILER_REFERENCE(port); 1364 #endif 1365 #ifdef INCLUDE_PLP_IMACSEC 1366 imacsec_des = IMACSEC_DES_PTR_GET(pc); 1367 phy_des = (PHY_BCM542XX_DEV_DESC_t *)(pc+1); 1368 #endif 1369 1370 mii_gb_stat = 0; /* Start off 0 */ 1371 mii_gb_ctrl = 0; /* Start off 0 */ 1372 1373 SOC_IF_ERROR_RETURN( 1374 PHY_READ_BCM542XX_MII_ANAr(unit, pc,&mii_ana)); 1375 SOC_IF_ERROR_RETURN( 1376 PHY_READ_BCM542XX_MII_ANPr(unit, pc,&mii_anp)); 1377 SOC_IF_ERROR_RETURN( 1378 PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat)); 1379 1380 if (mii_stat & PHY_BCM542XX_MII_STAT_ES) { /* Supports extended status */ 1381 /* 1382 * If the PHY supports extended status, check if it is 1000MB 1383 * capable. If it is, check the 1000Base status register to see 1384 * if 1000MB negotiated. 1385 */ 1386 SOC_IF_ERROR_RETURN( 1387 PHY_READ_BCM542XX_MII_ESRr(unit, pc,&mii_esr)); 1388 1389 if (mii_esr & (PHY_BCM542XX_MII_ESR_1000_X_FD | PHY_BCM542XX_MII_ESR_1000_X_HD | 1390 PHY_BCM542XX_MII_ESR_1000_T_FD | PHY_BCM542XX_MII_ESR_1000_T_HD) ) { 1391 SOC_IF_ERROR_RETURN( 1392 PHY_READ_BCM542XX_MII_GB_STATr(unit, pc, 1393 &mii_gb_stat)); 1394 SOC_IF_ERROR_RETURN( 1395 PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc, 1396 &mii_gb_ctrl)); 1397 } 1398 } 1399 1400 /* 1401 * At this point, if we did not see Gig status, one of mii_gb_stat or 1402 * mii_gb_ctrl will be 0. This will cause the first 2 cases below to 1403 * fail and fall into the default 10/100 cases. 1404 */ 1405 mii_ana &= mii_anp; 1406 1407 if ((mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD) && 1408 (mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000FD) ) { 1409 t_speed = 1000; 1410 t_duplex = 1; 1411 } else if ((mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD) && 1412 (mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000HD) ) { 1413 t_speed = 1000; 1414 t_duplex = 0; 1415 } else if (mii_ana & PHY_BCM542XX_MII_ANA_FD_100) { /* [a] */ 1416 t_speed = 100; 1417 t_duplex = 1; 1418 } else if (mii_ana & PHY_BCM542XX_MII_ANA_T4) { /* [b] */ 1419 t_speed = 100; 1420 t_duplex = 0; 1421 } else if (mii_ana & PHY_BCM542XX_MII_ANA_HD_100) { /* [c] */ 1422 t_speed = 100; 1423 t_duplex = 0; 1424 } else if (mii_ana & PHY_BCM542XX_MII_ANA_FD_10) { /* [d] */ 1425 t_speed = 10; 1426 t_duplex = 1 ; 1427 } else if (mii_ana & PHY_BCM542XX_MII_ANA_HD_10) { /* [e] */ 1428 t_speed = 10; 1429 t_duplex = 0; 1430 } else { 1431 return(SOC_E_FAIL); 1432 } 1433 1434 if (speed) { 1435 *speed = t_speed; 1436 } 1437 if (duplex) { 1438 if (t_duplex) { 1439 *duplex = TRUE; 1440 } else { 1441 *duplex = FALSE; 1442 } 1443 } 1444 #ifdef INCLUDE_PLP_IMACSEC 1445 if((phy_des->port_pre_speed != 1000) && (t_speed == 1000)){ /* If speed changed from 10M/100M to 1G speed, MAC need to be reconfigured again to restart the autoneg */ 1446 if(pc->macsec_enable){ 1447 port_m = get_port(&imacsec_des->phy_info); 1448 SPEED_MAPPING(t_speed,speed_m); 1449 /* Use base phy id to write top register */ 1450 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 1451 /* SW set speed MACSEC_CONFIG2 reg */ 1452 SOC_IF_ERROR_RETURN 1453 (phy_bcm542xx_cl45_reg_read(unit, pc, 0x7, 0x9870, &imacsec_cfg)); 1454 imacsec_cfg |= 1<<port_m; 1455 SOC_IF_ERROR_RETURN 1456 (phy_bcm542xx_cl45_reg_write(unit, pc, 0x7, 0x9870, imacsec_cfg)); 1457 /* SW set speed MACSEC_CONFIG3 reg */ 1458 SOC_IF_ERROR_RETURN 1459 (phy_bcm542xx_cl45_reg_read(unit, pc, 0x7, 0x9871, &imacsec_cfg)); 1460 imacsec_cfg &= ~(speed_mask << (port_m*2)); 1461 imacsec_cfg |= (speed_m << (port_m*2)); 1462 SOC_IF_ERROR_RETURN 1463 (phy_bcm542xx_cl45_reg_write(unit, pc, 0x7, 0x9871, imacsec_cfg)); 1464 /* Restore the phy mdio address */ 1465 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 1466 1467 port_s= PHY_UNIMAC_V2_SWITCH_PORT(port); 1468 SOC_IF_ERROR_RETURN( 1469 BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 0)); 1470 1471 SOC_IF_ERROR_RETURN( 1472 BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 1)); 1473 } 1474 } 1475 phy_des->port_pre_speed = t_speed; 1476 #endif 1477 1478 return SOC_E_NONE; 1479 } 1480 1481 1482 STATIC int 1483 _phy_bcm542xx_serdes_update(int unit, soc_port_t port) 1484 { 1485 phy_ctrl_t *pc; 1486 pc = EXT_PHY_SW_STATE(unit, port); 1487 1488 /* check if ( Copper_disabled ) or ( fiber enabled and preferred ) */ 1489 if ( (!(pc->copper.enable)) || 1490 ((pc->fiber.enable) && (pc->fiber.preferred)) ) { 1491 /* turn on the passive external SerDes 100FX if fiber 100FX mode */ 1492 uint16 serdes_mode = (pc->fiber.force_speed== 100) 1493 ? PHY_BCM542XX_EXT_SERDES_FX : 0; 1494 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ 1495 SOC_IF_ERROR_RETURN( 1496 PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, serdes_mode, 1497 PHY_BCM542XX_EXT_SERDES_FX_MASK) ); 1498 } 1499 return SOC_E_NONE; 1500 } 1501 1502 /* 1503 * Function: 1504 * phy_bcm542xx_medium_status 1505 * Purpose: 1506 * Indicate the current active medium 1507 * Parameters: 1508 * unit - StrataSwitch unit #. 1509 * port - StrataSwitch port #. 1510 * medium - (OUT) One of: 1511 * SOC_PORT_MEDIUM_COPPER 1512 * SOC_PORT_MEDIUM_FIBER 1513 * Returns: 1514 * SOC_E_NONE 1515 */ 1516 STATIC int 1517 phy_bcm542xx_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 1518 { 1519 if ( PHY_COPPER_MODE(unit, port) ) { 1520 *medium = SOC_PORT_MEDIUM_COPPER; 1521 } else if ( PHY_FIBER_MODE(unit, port) ) { 1522 *medium = SOC_PORT_MEDIUM_FIBER; 1523 } else { 1524 return SOC_E_INTERNAL; 1525 } 1526 return SOC_E_NONE; 1527 } 1528 1529 /* 1530 * Function: 1531 * _phy_bcm542xx_medium_config_update 1532 * Purpose: 1533 * Update the PHY with config parameters 1534 * Parameters: 1535 * unit - StrataSwitch unit #. 1536 * port - StrataSwitch port #. 1537 * cfg - Config structure. 1538 * Returns: 1539 * SOC_E_XXX 1540 */ 1541 1542 STATIC int 1543 _phy_bcm542xx_medium_config_update(int unit, soc_port_t port, 1544 soc_phy_config_t *cfg) 1545 { 1546 SOC_IF_ERROR_RETURN 1547 (phy_bcm542xx_speed_set(unit, port, cfg->force_speed)); 1548 SOC_IF_ERROR_RETURN 1549 (phy_bcm542xx_duplex_set(unit, port, cfg->force_duplex)); 1550 SOC_IF_ERROR_RETURN 1551 (phy_bcm542xx_master_set(unit, port, cfg->master)); 1552 SOC_IF_ERROR_RETURN 1553 (phy_bcm542xx_ability_advert_set(unit, port, &cfg->advert_ability)); 1554 SOC_IF_ERROR_RETURN 1555 (phy_bcm542xx_autoneg_set(unit, port, cfg->autoneg_enable)); 1556 SOC_IF_ERROR_RETURN 1557 (phy_bcm542xx_mdix_set(unit, port, cfg->mdix)); 1558 1559 return SOC_E_NONE; 1560 } 1561 1562 /* 1563 * Function: 1564 * _phy_bcm542xx_medium_check 1565 * Purpose: 1566 * Determine if chip should operate in copper or fiber mode. 1567 * Parameters: 1568 * unit - StrataSwitch unit #. 1569 * port - StrataSwitch port #. 1570 * medium - (OUT) SOC_PORT_MEDIUM_XXX 1571 * Returns: 1572 * SOC_E_XXX 1573 */ 1574 STATIC int 1575 _phy_bcm542xx_medium_check(int unit, soc_port_t port, soc_port_medium_t *medium) 1576 { 1577 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 1578 uint16 mode_ctrl; 1579 1580 *medium = SOC_PORT_MEDIUM_COPPER; 1581 1582 if ( pc->automedium) { 1583 SOC_IF_ERROR_RETURN 1584 (PHY_READ_BCM542XX_MODE_CTRLr(unit, pc,&mode_ctrl)); 1585 1586 if ( pc->fiber.preferred) { 1587 if ((mode_ctrl & 0x30) == 0x20) { 1588 /* Only Copper is linked up */ 1589 *medium = SOC_PORT_MEDIUM_COPPER; 1590 } else { 1591 *medium = SOC_PORT_MEDIUM_FIBER; 1592 } 1593 } else { 1594 if ((mode_ctrl & 0x30) == 0x10) { 1595 /* Only Fiber is linked up */ 1596 *medium = SOC_PORT_MEDIUM_FIBER; 1597 } else { 1598 *medium = SOC_PORT_MEDIUM_COPPER; 1599 } 1600 } 1601 } else { 1602 *medium = pc->fiber.preferred ? SOC_PORT_MEDIUM_FIBER 1603 : SOC_PORT_MEDIUM_COPPER; 1604 } 1605 LOG_VERBOSE(BSL_LS_SOC_PHY, 1606 (BSL_META_U(unit, "_phy_bcm542xx_medium_check: " 1607 "u=%d p=%d fiber_pref=%d fiber=%d\n"), 1608 unit, port, pc->fiber.preferred, 1609 (*medium == SOC_PORT_MEDIUM_FIBER) ? 1 : 0)); 1610 return SOC_E_NONE; 1611 } 1612 1613 /* 1614 * Function: 1615 * _phy_bcm542xx_medium_change 1616 * Purpose: 1617 * Change medium when media change detected or forced 1618 * Parameters: 1619 * unit - StrataSwitch unit #. 1620 * port - StrataSwitch port #. 1621 * force_update - Force update 1622 * force_medium - Force update medium 1623 * Returns: 1624 * SOC_E_XXX 1625 */ 1626 STATIC int 1627 _phy_bcm542xx_medium_change(int unit, soc_port_t port, 1628 soc_port_medium_t force_medium) 1629 { 1630 phy_ctrl_t *pc; 1631 soc_port_medium_t medium; 1632 1633 pc = EXT_PHY_SW_STATE(unit, port); 1634 1635 SOC_IF_ERROR_RETURN 1636 (_phy_bcm542xx_medium_check(unit, port, &medium)); 1637 1638 if ( ((medium == SOC_PORT_MEDIUM_COPPER) && (!PHY_COPPER_MODE(unit, port))) 1639 || (force_medium == SOC_PORT_MEDIUM_COPPER) ) { 1640 /* Was fiber or being forced copper */ 1641 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 1642 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 1643 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 1644 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 1645 1646 SOC_IF_ERROR_RETURN 1647 (_phy_bcm542xx_no_reset_setup(unit, port)); 1648 SOC_IF_ERROR_RETURN 1649 (_phy_bcm542xx_serdes_update(unit, port)); 1650 1651 /* Do Not power up the interface if medium is disabled */ 1652 if ( pc->copper.enable) { 1653 SOC_IF_ERROR_RETURN 1654 (_phy_bcm542xx_medium_config_update(unit, port, &pc->copper)); 1655 } 1656 LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit, 1657 "%s() u=%d p=%d [F->C] force_medium=%d\n"), __func__, 1658 unit, port, force_medium)); 1659 1660 /* Configure BCM542XX to RGMII-to-copper mode */ 1661 if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) { 1662 _phy_bcm542xx_rgmii_to_copper_mode(unit, port); 1663 } 1664 1665 } else 1666 if ( ((medium == SOC_PORT_MEDIUM_FIBER) && (PHY_COPPER_MODE(unit, port))) 1667 || (force_medium == SOC_PORT_MEDIUM_FIBER) ) { 1668 /* Was copper or being forced fiber */ 1669 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 1670 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 1671 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 1672 1673 SOC_IF_ERROR_RETURN 1674 (_phy_bcm542xx_no_reset_setup(unit, port)); 1675 SOC_IF_ERROR_RETURN 1676 (_phy_bcm542xx_serdes_update(unit, port)); 1677 1678 if ( pc->fiber.enable ) { 1679 SOC_IF_ERROR_RETURN 1680 (_phy_bcm542xx_medium_config_update(unit, port, &pc->fiber)); 1681 } 1682 LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit, 1683 "%s() u=%d p=%d [C->F] force_medium=%d\n"), __func__, 1684 unit, port, force_medium)); 1685 1686 /* Configure BCM542XX to RGMII-to-Fiber mode */ 1687 if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) { 1688 _phy_bcm542xx_rgmii_to_fiber_mode(unit, port); 1689 } 1690 } 1691 1692 return SOC_E_NONE; 1693 } 1694 1695 /*********************************************************************** 1696 * 1697 * PHY542xx DRIVER ROUTINES 1698 */ 1699 1700 /* 1701 * Function: 1702 * phy_bcm542xx_medium_config_set 1703 * Purpose: 1704 * Set the operating parameters that are automatically selected 1705 * when medium switches type. 1706 * Parameters: 1707 * unit - StrataSwitch unit # 1708 * port - Port number 1709 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1710 * cfg - Operating parameters 1711 * Returns: 1712 * SOC_E_XXX 1713 */ 1714 STATIC int 1715 phy_bcm542xx_medium_config_set(int unit, soc_port_t port, 1716 soc_port_medium_t medium, 1717 soc_phy_config_t *cfg) 1718 { 1719 phy_ctrl_t *pc; 1720 soc_phy_config_t *active_medium; /* Currently active medium */ 1721 soc_phy_config_t *change_medium; /* Requested medium */ 1722 soc_phy_config_t *other_medium; /* The other medium */ 1723 soc_port_ability_t advert_ability; 1724 int medium_update; 1725 1726 if ( NULL == cfg ) { 1727 return SOC_E_PARAM; 1728 } 1729 pc = EXT_PHY_SW_STATE(unit, port); 1730 medium_update = FALSE; 1731 /* clear the struct advert_ability */ 1732 sal_memset(&advert_ability, 0, sizeof(soc_port_ability_t)); 1733 1734 switch ( medium ) { 1735 case SOC_PORT_MEDIUM_COPPER: 1736 if (!pc->automedium && !PHY_COPPER_MODE(unit, port) ) { 1737 return SOC_E_UNAVAIL; 1738 } 1739 change_medium = &pc->copper; 1740 other_medium = &pc->fiber; 1741 ADVERT_ALL_COPPER(&advert_ability); 1742 1743 break; 1744 case SOC_PORT_MEDIUM_FIBER: 1745 if (!pc->automedium && !PHY_FIBER_MODE(unit, port) ) { 1746 return SOC_E_UNAVAIL; 1747 } 1748 change_medium = &pc->fiber; 1749 other_medium = &pc->copper; 1750 ADVERT_ALL_FIBER(&advert_ability); 1751 break; 1752 default: 1753 return SOC_E_PARAM; 1754 } 1755 1756 /* Changes take effect immediately if the *\ 1757 \* target medium is active or the preferred medium changes. */ 1758 if ( change_medium->enable != cfg->enable ) { 1759 medium_update = TRUE; 1760 } 1761 if ( change_medium->preferred != cfg->preferred ) { 1762 /* Make sure that only one medium is preferred */ 1763 other_medium->preferred = !cfg->preferred; 1764 medium_update = TRUE; 1765 } 1766 1767 /* copy given cfg to change_medium and update advert_ability */ 1768 sal_memcpy(change_medium, cfg, sizeof(*change_medium)); 1769 change_medium->advert_ability.pause &= advert_ability.pause; 1770 change_medium->advert_ability.speed_half_duplex &= advert_ability.speed_half_duplex; 1771 change_medium->advert_ability.speed_full_duplex &= advert_ability.speed_full_duplex; 1772 change_medium->advert_ability.interface &= advert_ability.interface; 1773 change_medium->advert_ability.medium &= advert_ability.medium; 1774 change_medium->advert_ability.loopback &= advert_ability.loopback; 1775 change_medium->advert_ability.flags &= advert_ability.flags; 1776 1777 SOC_IF_ERROR_RETURN( _phy_bcm542xx_serdes_update(unit, port) ); 1778 1779 if ( medium_update ) { 1780 /* The new config may cause medium change. Check and update medium */ 1781 SOC_IF_ERROR_RETURN 1782 (_phy_bcm542xx_medium_change(unit, port, medium)); 1783 } else { 1784 active_medium = (PHY_COPPER_MODE(unit, port)) ? &pc->copper 1785 : &pc->fiber; 1786 if ( active_medium == change_medium ) { 1787 /* If the medium to update is active, update the configuration */ 1788 SOC_IF_ERROR_RETURN 1789 (_phy_bcm542xx_medium_config_update(unit, port, change_medium)); 1790 } 1791 else { 1792 /* Make sure that connected medium has been updated if port is disabled */ 1793 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ) { 1794 /* Check for medium change and update HW/SW accordingly. */ 1795 SOC_IF_ERROR_RETURN 1796 (_phy_bcm542xx_medium_change(unit, port, SOC_PORT_MEDIUM_NONE)); 1797 } 1798 } 1799 } 1800 return SOC_E_NONE; 1801 } 1802 1803 /* 1804 * Function: 1805 * phy_bcm542xx_medium_config_get 1806 * Purpose: 1807 * Get the operating parameters that are automatically selected 1808 * when medium switches type. 1809 * Parameters: 1810 * unit - StrataSwitch unit # 1811 * port - Port number 1812 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1813 * cfg - (OUT) Operating parameters 1814 * Returns: 1815 * SOC_E_XXX 1816 */ 1817 1818 STATIC int 1819 phy_bcm542xx_medium_config_get(int unit, soc_port_t port, 1820 soc_port_medium_t medium, 1821 soc_phy_config_t *cfg) 1822 { 1823 int rv; 1824 phy_ctrl_t *pc; 1825 1826 pc = EXT_PHY_SW_STATE(unit, port); 1827 rv = SOC_E_NONE; 1828 1829 switch ( medium ) { 1830 case SOC_PORT_MEDIUM_COPPER: 1831 if ( pc->automedium || PHY_COPPER_MODE(unit, port) ) { 1832 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 1833 } else { 1834 rv = SOC_E_UNAVAIL; 1835 } 1836 break; 1837 case SOC_PORT_MEDIUM_FIBER: 1838 if ( pc->automedium || PHY_FIBER_MODE(unit, port) ) { 1839 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 1840 } else { 1841 rv = SOC_E_UNAVAIL; 1842 } 1843 break; 1844 default: 1845 rv = SOC_E_PARAM; 1846 break; 1847 } 1848 1849 return rv; 1850 } 1851 1852 /* 1853 * Function: 1854 * _phy_bcm542xx_no_reset_setup 1855 * Purpose: 1856 * Setup the operating parameters of the PHY without resetting PHY 1857 * Parameters: 1858 * unit - StrataSwitch unit # 1859 * port - Port number 1860 * Returns: 1861 * SOC_E_XXX 1862 */ 1863 1864 STATIC int 1865 _phy_bcm542xx_no_reset_setup(int unit, soc_port_t port) 1866 { 1867 phy_ctrl_t *pc; 1868 int rv = SOC_E_NONE; 1869 1870 LOG_INFO(BSL_LS_SOC_PHY, 1871 (BSL_META_U(unit, "%s: u=%d p=%d medium=%s\n"), 1872 __func__, unit, port, 1873 PHY_COPPER_MODE(unit, port) ? "COPPER" : "FIBER")); 1874 1875 pc = EXT_PHY_SW_STATE(unit, port); 1876 rv = phy_bcm542xx_init_setup(unit, port, 0, 1877 pc->automedium, 1878 pc->fiber.preferred, 1879 pc->fiber_detect, 1880 pc->fiber.enable, 1881 pc->copper.enable, 1882 pc->ext_phy_autodetect_en, 1883 pc->ext_phy_fiber_iface); 1884 if ( rv != SOC_E_NONE ) { 1885 return SOC_E_FAIL; 1886 } 1887 return rv; 1888 } 1889 1890 /* 1891 * Function: 1892 * phy_bcm542xx_set_led_selectors 1893 * Purpose: 1894 * Set LED modes and Control. 1895 * Parameters: 1896 * phy_dev_addr - PHY's device address 1897 * led_mode0 - LED Mode 0 1898 * led_mode1 - LED Mode 1 1899 * led_mode2 - LED Mode 2 1900 * led_mode3 - LED Mode 3 1901 * led_select - LED select 1902 * led_select_ctrl - LED Control 1903 * Returns: 1904 */ 1905 int 1906 phy_bcm542xx_set_led_selectors(int unit, phy_ctrl_t *pc) 1907 { 1908 uint16 data; 1909 uint16 led_link_speed_mode; 1910 1911 /* Configure LED selectors */ 1912 data = (((pc->ledmode[1] & 0xf) << 4) | (pc->ledmode[0] & 0xf)); 1913 SOC_IF_ERROR_RETURN 1914 (PHY_WRITE_BCM542XX_LED_SELECTOR_1r(unit, pc, data)); 1915 1916 data = ((pc->ledmode[3] & 0xf) << 4) | (pc->ledmode[2] & 0xf); 1917 SOC_IF_ERROR_RETURN 1918 (PHY_WRITE_BCM542XX_LED_SELECTOR_2r(unit, pc, data)); 1919 1920 data = (pc->ledctrl & 0x3ff); 1921 SOC_IF_ERROR_RETURN 1922 (PHY_WRITE_BCM542XX_LED_CTRLr(unit, pc, data)); 1923 1924 SOC_IF_ERROR_RETURN 1925 (PHY_WRITE_BCM542XX_EXP_LED_SELECTORr(unit, pc, pc->ledselect)); 1926 1927 led_link_speed_mode = soc_property_port_get(unit, pc->port, 1928 spn_PHY_LED_LINK_SPEED_MODE, 0x0); 1929 switch(led_link_speed_mode) { 1930 case 1: 1931 SOC_IF_ERROR_RETURN 1932 (PHY_MODIFY_BCM542XX_SPARE_CTRLr(unit, pc, 1933 PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED, 1934 PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED 1935 | PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED)); 1936 break; 1937 case 2: 1938 SOC_IF_ERROR_RETURN 1939 (PHY_MODIFY_BCM542XX_SPARE_CTRLr(unit, pc, 1940 PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED, 1941 PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED 1942 | PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED)); 1943 break; 1944 default: 1945 SOC_IF_ERROR_RETURN 1946 (PHY_MODIFY_BCM542XX_SPARE_CTRLr(unit, pc, 1947 0, 1948 PHY_BCM542XX_SPARE_CTRL_REG_LINK_LED 1949 | PHY_BCM542XX_SPARE_CTRL_REG_LINK_SPEED_LED)); 1950 break; 1951 } 1952 1953 return SOC_E_NONE; 1954 } 1955 1956 /* 1957 * Function: 1958 * phy_bcm54280_init ( for 54280 / 290 ) 1959 * Purpose: 1960 * 54280 Device specific Initialization 1961 * Parameters: 1962 * unit, port - 1963 * Notes: 1964 */ 1965 STATIC int 1966 _phy_bcm54280_init(int unit, soc_port_t port) 1967 { 1968 phy_ctrl_t *pc; 1969 #ifdef INCLUDE_PLP_IMACSEC 1970 int rv; 1971 int uport; 1972 unsigned int ms_dev_addr = 1973 soc_property_port_get(unit, port, spn_MACSEC_DEV_ADDR, -1); 1974 1975 unsigned int ms_slice = 1976 soc_property_port_get(unit, port, spn_MACSEC_PORT_INDEX, 0); 1977 1978 int imacsec_mdio_addr; 1979 bcm_plp_base_t_sec_phy_access_t *imacsec_des; 1980 #endif 1981 1982 pc = EXT_PHY_SW_STATE(unit, port); 1983 pc->driver_data = (void *)(pc+1); 1984 #ifdef INCLUDE_PLP_IMACSEC 1985 /* Base PHY ID is used to access MACSEC core */ 1986 imacsec_mdio_addr = soc_property_port_get(unit, port, 1987 spn_MACSEC_DEV_ADDR, -1); 1988 pc->macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0); 1989 imacsec_des = IMACSEC_DES_PTR_GET(pc); 1990 imacsec_des->macsec_dev_addr = IMACSEC_MDIO_ADDR_GET(imacsec_mdio_addr); 1991 imacsec_des->phy_info.lane_map = 1992 soc_property_port_get(unit, port, spn_MACSEC_PORT_INDEX, 0); 1993 imacsec_des->phy_info.lane_map = 1 << imacsec_des->phy_info.lane_map ; 1994 #endif 1995 /* 1996 * Configure LED mode and Jumbo frame, set max Jumbo packet length to 18KB 1997 */ 1998 1999 /* 2000 * PHY Extended Control Reg., RDB.0x000, Legacy Reg.0x10 2001 * bit[0] GMII_FIFO_JUMBO_LSB 2002 * bit[5] LED_TRAFFIC_EN, Enable LED traffic mode 2003 */ 2004 SOC_IF_ERROR_RETURN 2005 (PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc, 2006 PHY_BCM542XX_MII_ECR_FIFO_ELAST_0 2007 | PHY_BCM542XX_MII_ECR_EN_LEDT, 2008 PHY_BCM542XX_MII_ECR_FIFO_ELAST_0 2009 | PHY_BCM542XX_MII_ECR_EN_LEDT)); 2010 2011 /* 2012 * Pattern Generator Status Reg., RDB.0x006, Legacy EXP_Reg.0x46 2013 * bit[14] GMII_FIFO_JUMBO_MSB 2014 * bit[15] GMII_FIFO_JUMBO_MSB 2015 */ 2016 SOC_IF_ERROR_RETURN 2017 (PHY_MODIFY_BCM542XX_EXP_PATT_GEN_STATr(unit, pc, 2018 PHY_BCM542XX_PATT_GEN_STAT_FIFO_ELAST_1 2019 | PHY_BCM542XX_PATT_GEN_STAT_GMII_FIFO_JUMBO_MSB, 2020 PHY_BCM542XX_PATT_GEN_STAT_FIFO_ELAST_1 2021 | PHY_BCM542XX_PATT_GEN_STAT_GMII_FIFO_JUMBO_MSB)); 2022 2023 /* Disable USGMII mode. Clear RDB.0x0810 Bit[6] */ 2024 if (PHY_IS_BCM54182(pc) || PHY_IS_BCM54185(pc) || 2025 PHY_IS_BCM54192(pc) || PHY_IS_BCM54195(pc) ) { 2026 SOC_IF_ERROR_RETURN( 2027 phy_bcm542xx_rdb_reg_modify(unit, pc, 2028 PHY_BCM542XX_DISABLE_USGMII, 2029 0, PHY_BCM542XX_DISABLE_USGMII_6U_BIT_SEL) ); 2030 } 2031 2032 /* 2033 * Misc 1000-X Control 2 Reg., RDB.0x236, Legacy Reg.0x1C shadow 0x16 2034 * bit[0] PRIMARY_SERDES_JUMBO_MSB 2035 */ 2036 SOC_IF_ERROR_RETURN 2037 (PHY_MODIFY_BCM542XX_1ST_SERDES_CTRLr(unit, pc, 2038 PHY_BCM542XX_SERDES_CTRL_JUMBO_MSB, 2039 PHY_BCM542XX_SERDES_CTRL_JUMBO_MSB)); 2040 2041 /* 2042 * Auto Detect SGMII MC Reg., RDB.0x238 2043 * bit[2] GMII_FIFO_JUMBO_LSB 2044 */ 2045 SOC_IF_ERROR_RETURN 2046 (phy_bcm542xx_direct_reg_modify(unit, pc, 2047 PHY_BCM542XX_AUTO_DETECT_SGMII_MC_REG_OFFSET, 2048 PHY_BCM542XX_AUTO_DETECT_GMII_FIFO_JUMBO_LSB, 2049 PHY_BCM542XX_AUTO_DETECT_GMII_FIFO_JUMBO_LSB)); 2050 2051 /* 2052 * Auxiliary 1000-X Contro Reg., RDB.0x23B, Legacy Reg.0x1C shadow 0x1B 2053 * bit[1] PRIMARY_SERDES_JUMBO_LSB 2054 */ 2055 SOC_IF_ERROR_RETURN 2056 (PHY_MODIFY_BCM542XX_AUX_1000X_CTRLr(unit, pc, 2057 PHY_BCM542XX_SERDES_CTRL_JUMBO_LSB, 2058 PHY_BCM542XX_SERDES_CTRL_JUMBO_LSB)); 2059 2060 /* 2061 * Secondary Serdes MISC 1000-X Control 2 Reg. RDB.0xB16 2062 * bit[0] SECONDARY_SERDES_JUMBO_MSB 2063 */ 2064 SOC_IF_ERROR_RETURN 2065 (phy_bcm542xx_direct_reg_modify(unit, pc, 2066 PHY_BCM542XX_2ND_SERDES_MISC_1000x_CTL_2_REG_OFFSET, 2067 PHY_BCM542XX_2ND_SERDES_MISC_1000x_CTL_2_2ND_SERDES_MSB, 2068 PHY_BCM542XX_2ND_SERDES_MISC_1000x_CTL_2_2ND_SERDES_MSB)); 2069 2070 /* 2071 * Secondary Serdes Auxiliary 1000-X Control Reg. RDB.0xB1B 2072 * bit[1] SECONDARY_SERDES_JUMBO_LSB 2073 */ 2074 SOC_IF_ERROR_RETURN 2075 (phy_bcm542xx_direct_reg_modify(unit, pc, 2076 PHY_BCM542XX_2ND_SERDES_AUX_1000x_CTL_REG_OFFSET, 2077 PHY_BCM542XX_2ND_SERDES_AUX_1000x_CTL_2ND_SERDES_LSB, 2078 PHY_BCM542XX_2ND_SERDES_AUX_1000x_CTL_2ND_SERDES_LSB)); 2079 2080 /* 2081 * Copper Auxiliary Control Reg., RDB.0x028, Legacy Reg.0x18 shadow 0 2082 * bit[14] EXT_PKT_LEN(100BT_JUMBO), 100BASE-Tx jumbo frames support 2083 */ 2084 SOC_IF_ERROR_RETURN 2085 (PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 2086 PHY_BCM542XX_MII_AUX_CTRL_REG_EXT_PKT_LEN, 2087 PHY_BCM542XX_MII_AUX_CTRL_REG_EXT_PKT_LEN)); 2088 2089 /* 2090 * Secondary Serdes 1000-X Error Counter Setting Reg. RDB.0xB10 2091 * bit[0] EXT_PKT_LEN 2092 */ 2093 SOC_IF_ERROR_RETURN 2094 (phy_bcm542xx_direct_reg_modify(unit, pc, 2095 PHY_BCM542XX_2ND_SERDES_1000x_ERR_CNT_SET_REG_OFFSET, 2096 PHY_BCM542XX_2ND_SERDES_1000x_ERR_CNT_SET_EXT_PKT_LEN, 2097 PHY_BCM542XX_2ND_SERDES_1000x_ERR_CNT_SET_EXT_PKT_LEN)); 2098 2099 2100 #if defined (INCLUDE_PLP_IMACSEC) /* */ 2101 if(pc->macsec_enable){ 2102 /* MACSEC is ENABLED 2103 * MACSEC Specific Initialization 2104 * 2105 * Some reasonable defaults 2106 */ 2107 /* default MACSEC MAC policy: MACSEC_SWITCH_FOLLOWS_LINE == 1 */ 2108 pc->macsec_mac_policy = soc_property_port_get(unit, port, 2109 spn_MACSEC_SWITCH_SIDE_POLICY, 2110 1); 2111 2112 pc->macsec_switch_fixed_speed = 0; 2113 /* If switch mac policy is PHY_MAC_SWITCH_DUPLEX_GATEWAY set the 2114 * duplex mode on line side as half duplex and system side as full duplex */ 2115 2116 pc->macsec_switch_fixed_duplex = 1; 2117 pc->macsec_switch_fixed_pause = 1; 2118 pc->macsec_pause_rx_fwd = 0; 2119 pc->macsec_pause_tx_fwd = 0; 2120 pc->macsec_line_ipg = 0xc; 2121 pc->macsec_switch_ipg = 0xc; 2122 2123 2124 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 2125 2126 /* DATAPATH_SELECT : 2127 * [15:8] 0 means port NOT bypassed , [7:0] 0 means 1588 not encrypted 2128 */ 2129 SOC_IF_ERROR_RETURN 2130 (phy_bcm542xx_direct_reg_modify(unit, pc, 0x84a, 0x0000, 2131 1 << (ms_slice + 8) | 0xff )); 2132 2133 /* MACSEC_PWRDN : 2134 * [15] 1 means MACSEC MDIO enabled 2135 * [14:10] 0 reset value for QUAD1 PHY addr 2136 * [9:8] 0 means quad1,quad0 power up 2137 * [7:0] 0 means port power up 2138 */ 2139 SOC_IF_ERROR_RETURN 2140 (phy_bcm542xx_direct_reg_modify(unit, pc, 0x84b, 0x8000, 2141 0xff00 | 1 << (ms_slice ) )); 2142 /* MACSEC_OVERRIDE enable 2143 * [14] 1 means 1: overwrite with bit 13 2144 * bit 13, 0: macsec not disabled 2145 */ 2146 2147 SOC_IF_ERROR_RETURN 2148 (phy_bcm542xx_direct_reg_modify(unit, pc, 0x84d, 0x40ff, 2149 0xffff )); 2150 2151 /* Switch side speed config2 reg */ 2152 /* bit 0 to 7 value = 0 means use line side , 1 means use config3 reg */ 2153 SOC_IF_ERROR_RETURN 2154 (phy_bcm542xx_cl45_reg_write(unit, pc, 0x7, 0x9870, 0xFF)); 2155 2156 /* Switch side speed config3 reg */ 2157 SOC_IF_ERROR_RETURN 2158 (phy_bcm542xx_cl45_reg_write(unit, pc, 0x7, 0x9871, 0xAAAA)); 2159 2160 2161 /* Restore the phy mdio address */ 2162 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 2163 2164 2165 2166 /* register mdio read/write */ 2167 _bcm_plp_register_mdio_primitives( 2168 unit, ms_slice, ms_dev_addr, pc->read , pc->write); 2169 2170 2171 /* Attach MAC driver */ 2172 rv = _bcm_phy5419x_phy_mac_driver_attach( pc, 2173 ms_dev_addr, 2174 pc->port, 2175 imacsec_blmi_io_mmi2); 2176 if(rv != SOC_E_NONE) { 2177 LOG_WARN(BSL_LS_SOC_PHY, 2178 (BSL_META_U(unit, 2179 "phy_mac_driver_attach " 2180 "returned error for u=%d p=%d\n"), unit, port)); 2181 return SOC_E_FAIL; 2182 } 2183 2184 2185 /* Initialize the Line side MAC */ 2186 uport = PHY_UNIMAC_V2_LINE_PORT(pc->port); 2187 SOC_IF_ERROR_RETURN( 2188 BMACSEC_MAC_INIT((phy_mac_ctrl_t *)imacsec_des->unimac, uport)); 2189 2190 /* Initialize the Switch side MAC */ 2191 uport = PHY_UNIMAC_V2_SWITCH_PORT(pc->port); 2192 SOC_IF_ERROR_RETURN( 2193 BMACSEC_MAC_INIT((phy_mac_ctrl_t *)imacsec_des->unimac, uport)); 2194 } 2195 #endif /* INCLUDE_PLP_IMACSEC */ 2196 2197 return SOC_E_NONE; 2198 } 2199 2200 /* 2201 * Function: 2202 * phy_bcm54282_init ( for 54282 / 292 ) 2203 * Purpose: 2204 * Initalize the PHY device. 2205 * Parameters: 2206 * unit, port - 2207 * Notes: 2208 */ 2209 STATIC int 2210 _phy_bcm54282_init(int unit, soc_port_t port) 2211 { 2212 phy_ctrl_t *pc; 2213 pc = EXT_PHY_SW_STATE(unit, port); 2214 2215 /* 2216 * Configure extended control register for led mode and 2217 * jumbo frame support 2218 */ 2219 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); /* RV */ 2220 2221 /* Enable QSGMII MDIO sharing feature 2222 - Enable access to QSGMII reg space using port3's MDIO address 2223 - Use PHYA[4:0]+3 (Port3's MDIO) instead of PHYA[4:0)+8 as MDIO address. 2224 - It saves one MDIO address for customer. 2225 - Access to this top level register via port 0 only 2226 */ 2227 SOC_IF_ERROR_RETURN 2228 (phy_bcm542xx_direct_reg_modify(unit, pc, 2229 PHY_BCM542XX_TOP_MISC_TOP_CFG_REG_OFFSET, 2230 PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_SEL 2231 | PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_PHYA, 2232 PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_SEL 2233 | PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_PHYA)); 2234 2235 /* replace it with qsgmii phy id */ 2236 pc->phy_id = PHY_BCM54282_QSGMII_DEV_ADDR_SHARED(pc); 2237 2238 /* QSGMII FIFO Elasticity */ 2239 SOC_IF_ERROR_RETURN 2240 (phy_bcm542xx_qsgmii_reg_write(unit, pc, 2241 (int) PHY_BCM542XX_DEV_PHY_SLICE(pc) /*dev_port*/, 2242 0x8300, 0x12, 0x0006)); 2243 2244 /* Restore access to Copper/Fiber register space. 2245 * TOP lvl register, access through port0 only 2246 */ 2247 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 2248 SOC_IF_ERROR_RETURN 2249 (phy_bcm542xx_direct_reg_modify(unit, pc, 2250 PHY_BCM542XX_TOP_MISC_TOP_CFG_REG_OFFSET, 2251 0, 2252 PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_SEL 2253 | PHY_BCM542XX_TOP_MISC_CFG_REG_QSGMII_PHYA)); 2254 /* Restore the phy mdio address */ 2255 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 2256 2257 /* Configure LED mode and turn on jumbo frame support */ 2258 _phy_bcm54280_init(unit, port); 2259 2260 /* In case of QSGMII devices, there is a LPI pass through mode 2261 which has to be enabled for native EEE to work. In case of VNG, 2262 it is already set by default. To enable it: 2263 SOC_IF_ERROR_RETURN 2264 (phy_bcm542xx_qsgmii_reg_write(PHY_BCM54282_QSGMII_DEV_ADDR(_pc), 2265 (int)PHY_BCM542XX_DEV_PHY_SLICE(pc), 2266 0x833e, 0x0e, 0xc000)); 2267 */ 2268 return SOC_E_NONE; 2269 } 2270 2271 int 2272 _phy_bcm542xx_rgmii_to_copper_mode(int unit, soc_port_t port) 2273 { 2274 phy_ctrl_t *pc; 2275 pc = EXT_PHY_SW_STATE(unit, port); 2276 2277 /* Configure BCM542XX to RGMII-to-copper mode */ 2278 SOC_IF_ERROR_RETURN 2279 (PHY_WRITE_BCM542XX_MII_MISC_CTRLr(unit, pc, 0x71E7)); 2280 SOC_IF_ERROR_RETURN 2281 (PHY_WRITE_BCM542XX_CLK_ALIGN_CTRLr(unit, pc, 0x0E00)); 2282 SOC_IF_ERROR_RETURN 2283 (PHY_WRITE_BCM542XX_TOP_LVL_CONFGr(unit, pc, 0x00B0)); 2284 SOC_IF_ERROR_RETURN 2285 (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C01)); 2286 SOC_IF_ERROR_RETURN 2287 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1940)); 2288 SOC_IF_ERROR_RETURN 2289 (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C00)); 2290 SOC_IF_ERROR_RETURN 2291 (PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc, 0x0200)); 2292 SOC_IF_ERROR_RETURN 2293 (PHY_WRITE_BCM542XX_1000X_MII_ANAr(unit, pc, 0x01E1)); 2294 SOC_IF_ERROR_RETURN 2295 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1340)); 2296 2297 return SOC_E_NONE; 2298 } 2299 2300 int 2301 _phy_bcm542xx_rgmii_to_fiber_mode(int unit, soc_port_t port) 2302 { 2303 phy_ctrl_t *pc; 2304 pc = EXT_PHY_SW_STATE(unit, port); 2305 2306 /* Configure BCM542XX to RGMII-to-Fiber mode */ 2307 SOC_IF_ERROR_RETURN 2308 (PHY_WRITE_BCM542XX_MII_MISC_CTRLr(unit, pc, 0x71E7)); 2309 SOC_IF_ERROR_RETURN 2310 (PHY_WRITE_BCM542XX_CLK_ALIGN_CTRLr(unit, pc, 0x0E00)); 2311 SOC_IF_ERROR_RETURN 2312 (PHY_WRITE_BCM542XX_TOP_LVL_CONFGr(unit, pc, 0x00B0)); 2313 SOC_IF_ERROR_RETURN 2314 (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C02)); 2315 SOC_IF_ERROR_RETURN 2316 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1940)); 2317 SOC_IF_ERROR_RETURN 2318 (PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7C03)); 2319 SOC_IF_ERROR_RETURN 2320 (PHY_WRITE_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, 0x78E2)); 2321 SOC_IF_ERROR_RETURN 2322 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 0x1140)); 2323 2324 return SOC_E_NONE; 2325 } 2326 2327 2328 /* 2329 * Function: 2330 * phy_bcm54200_init ( for 54210/220/240/285/294/295/296/140 ) dual media 2331 * Purpose: 2332 * Initalize the dual media (combo) PHY device. 2333 * Parameters: 2334 * automedium - Automedium select in combo ports 2335 * fiber_preferred - Fiber preferrence over copper 2336 * fiber_detect - Fiber Signal Detect 2337 * ext_phy_autodetect_en - Enable/Disable SGMII Slave Autodetect function 2338 * ext_phy_fiber_iface - Fiber interface when Autodetect is disabled. 2339 * Notes: 2340 * Fiber Detect Detect Fiber signal 2341 * Automedium Fiber Preferred Active Medium 2342 * ------------ ------------------- ----------------------------------------- 2343 * 0 1 Fiber mode is forced 2344 * 0 0 Copper mode is forced 2345 * 1 1 Auto medium is enabled, Fiber preferred 2346 * 1 0 Auto medium is enabled, Copper preferred 2347 */ 2348 STATIC int 2349 _phy_bcm54200_init(int unit, soc_port_t port, int automedium, 2350 int fiber_preferred, int fiber_detect, 2351 int fiber_enable , int copper_enable, 2352 int ext_phy_autodetect_en, int ext_phy_fiber_iface) 2353 { 2354 uint16 data, mask; 2355 phy_ctrl_t *pc; 2356 /* 2357 * Don't power up the PHY if PHY is administratively disabled. 2358 */ 2359 uint16 pwr_down_bit = PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ? PHY_BCM542XX_MII_CTRL_PWR_DOWN : 0; 2360 2361 pc = EXT_PHY_SW_STATE(unit, port); 2362 2363 /* Configure Auto-detect Medium (0x1c shadow 11110, RDB.0x23e) */ 2364 mask = PHY_BCM542XX_MII_AUTO_DET_MASK; /* Auto-detect bit mask */ 2365 data = 0x0; 2366 if ( PHY_IS_BCM54210_220(pc) ) { 2367 /* Enable dual serdes auto-detect medium */ /* 0xfae7 */ 2368 data |= (PHY_BCM542XX_MII_AUTO_DET_MED_2ND_SERDES | 2369 PHY_BCM542XX_MII_FIBER_IN_USE_LED | 2370 PHY_BCM542XX_MII_FIBER_LED | 2371 PHY_BCM542XX_MII_FIBER_SD_SYNC); 2372 } 2373 if ( automedium ) { 2374 /* Enable auto-detect medium */ 2375 data |= PHY_BCM542XX_MII_AUTO_DET_MED_EN; 2376 } 2377 2378 /* When no link partner exists, fiber should be default medium */ 2379 /* When both link partners exipc, fiber should be prefered medium 2380 * for the following reasons. 2381 * 1. Most fiber module generates signal detect when the fiber cable is 2382 * plugged in regardless of any activity even if the link partner is 2383 * powered down. 2384 * 2. Fiber mode consume much lesser power than copper mode. 2385 */ 2386 if ( fiber_preferred ) { 2387 /* Fiber selected when both media are active */ 2388 data |= (PHY_BCM542XX_MII_AUTO_DET_MED_PRI | 2389 PHY_BCM542XX_MII_AUTO_DET_MED_DEFAULT); 2390 /* Fiber selected when no medium is active */ 2391 } 2392 2393 /* Qulalify fiber link with SYNC from PCS. */ 2394 data |= PHY_BCM542XX_MII_FIBER_SD_SYNC; 2395 2396 /* 2397 * Enable internal inversion of LED2/SD input pin. Used only if 2398 * the fiber module provides RX_LOS instead of Signal Detect. 2399 */ 2400 if ( fiber_detect < 0 ) { 2401 /* Fiber signal detect is active low from pin */ 2402 data |= PHY_BCM542XX_MII_INV_FIBER_SD; 2403 } 2404 2405 /* Auto-Detect Medium Register (DIGX_SHD1C_1E, RDB.0x23e) */ 2406 /* coverity[copy_paste_error : FALSE] */ 2407 SOC_IF_ERROR_RETURN 2408 (PHY_MODIFY_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, data, mask)); 2409 2410 if ( PHY_IS_BCM54210_220(pc) ) { 2411 /* Power up primary SerDes, Fiber MII_CONTROL Reg. bit[11]*/ 2412 SOC_IF_ERROR_RETURN 2413 (PHY_MODIFY_BCM542XX_PRI_SERDES_MII_CTRLr(unit, pc, 0, 2414 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 2415 data = PHY_BCM542XX_MODE_SEL_SGMII_2_COPPER; 2416 } else { 2417 data = PHY_BCM542XX_MODE_SEL_COPPER_2_SGMII; 2418 } 2419 /* MODE_CONTROL register, DIGX_SHD_1C_1F, RDB_0x21 */ 2420 SOC_IF_ERROR_RETURN 2421 (PHY_MODIFY_BCM542XX_MODE_CTRLr(unit, pc, data, 2422 PHY_BCM542XX_MODE_CNTL_MODE_SEL_MASK)); 2423 2424 /*----------- COPPER INTERFACE ---------- */ 2425 if ( (! copper_enable) || (!automedium && fiber_preferred) ) { 2426 SOC_IF_ERROR_RETURN 2427 (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, 2428 PHY_BCM542XX_MII_CTRL_PWR_DOWN, 2429 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 2430 } else { 2431 if (!pwr_down_bit) { 2432 SOC_IF_ERROR_RETURN 2433 (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, 2434 0, 2435 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 2436 } 2437 SOC_IF_ERROR_RETURN 2438 (PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc, 2439 PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD 2440 | PHY_BCM542XX_MII_GB_CTRL_PT)); 2441 SOC_IF_ERROR_RETURN 2442 (PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, 2443 PHY_BCM542XX_MII_CTRL_FD 2444 | PHY_BCM542XX_MII_CTRL_SS_10 2445 | PHY_BCM542XX_MII_CTRL_SS_100 2446 | PHY_BCM542XX_MII_CTRL_AN_EN 2447 | pwr_down_bit 2448 | PHY_BCM542XX_MII_CTRL_RST_AN)); 2449 2450 /* Enable/disable auto-detection between SGMII-slave and 1000BASE-X */ 2451 if ( PHY_IS_BCM54210_220(pc) ) { 2452 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ 2453 SOC_IF_ERROR_RETURN 2454 (PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, 0x0, 2455 PHY_BCM542XX_EXT_SERDES_FX_MASK)); 2456 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ 2457 SOC_IF_ERROR_RETURN 2458 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0, 2459 PHY_BCM542XX_SGMII_SLAVE_AUTO)); 2460 } else { /* PHY is 54240/28x/29x */ 2461 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ 2462 SOC_IF_ERROR_RETURN 2463 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 2464 PHY_BCM542XX_SGMII_SLAVE_AUTO, 2465 PHY_BCM542XX_SGMII_SLAVE_AUTO)); 2466 SOC_IF_ERROR_RETURN /* Power down SerDes */ 2467 (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, 2468 PHY_BCM542XX_MII_CTRL_PWR_DOWN, 2469 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 2470 } 2471 2472 /* Configure BCM542XX to RGMII-to-copper mode */ 2473 if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) { 2474 _phy_bcm542xx_rgmii_to_copper_mode(unit, port); 2475 } 2476 } 2477 2478 /*----------- FIBER INTERFACE ---------- */ 2479 if ( fiber_enable && (automedium || fiber_preferred) ) { 2480 /* remove power down of SerDes */ 2481 if (!pwr_down_bit) { 2482 SOC_IF_ERROR_RETURN 2483 (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, 0, 2484 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 2485 } 2486 /* set the advertisement of serdes */ 2487 data = PHY_BCM542XX_1000X_MII_ANA_FD | 2488 PHY_BCM542XX_1000X_MII_ANA_HD | 2489 PHY_BCM542XX_1000X_MII_ANA_PAUSE | 2490 PHY_BCM542XX_1000X_MII_ANA_ASYM_PAUSE; 2491 /*Advertising Next Page capability in 1000X AN mode*/ 2492 if (fiber_preferred && pc->fiber.autoneg_enable && 2493 (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS) && 2494 (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_1000X)) { 2495 data |= PHY_BCM542XX_1000X_MII_ANA_NP; 2496 } 2497 2498 mask = data; 2499 SOC_IF_ERROR_RETURN 2500 (PHY_MODIFY_BCM542XX_1000X_MII_ANAr(unit, pc, data, mask)); 2501 2502 /* Enable auto-detection between SGMII-slave and 1000BASE-X */ 2503 if ( PHY_IS_BCM54210_220(pc) ) { 2504 data = PHY_BCM542XX_EXT_SERDES_LED | PHY_BCM542XX_EXT_SEL_SYNC_ST | 2505 PHY_BCM542XX_EXT_SELECT_SD | PHY_BCM542XX_EXT_SERDES_SEL; 2506 if ( fiber_preferred ) { 2507 data |= 0; /* don't support PHY_BCM542XX_EXT_SERDES_AUTO_FX */ 2508 } 2509 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ 2510 SOC_IF_ERROR_RETURN /* 0xd1cf */ 2511 (PHY_WRITE_BCM542XX_EXT_SERDES_CTRLr(unit, pc, data)); 2512 2513 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ 2514 SOC_IF_ERROR_RETURN 2515 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0, 2516 PHY_BCM542XX_SGMII_SLAVE_AUTO)); 2517 /* Miscellanous Control Reg., CORE_SHD18_111, RDB_0x02f */ 2518 SOC_IF_ERROR_RETURN 2519 (PHY_WRITE_BCM542XX_MII_MISC_CTRLr(unit, pc, 2520 PHY_BCM542XX_MII_MISC_CTRL_CLEARALL)); 2521 /* Second SERDES 100-FX CONTROL Register, RDB_0xb17 */ 2522 SOC_IF_ERROR_RETURN 2523 (phy_bcm542xx_direct_reg_write(unit, pc, 2524 PHY_BCM542XX_2ND_SERDES_MISC_1000x_REG_OFFSET, 2525 PHY_BCM542XX_2ND_SERDES_MISC_1000x_INIT)); 2526 2527 } else { /* PHY is 54240/28x/29x */ 2528 if (fiber_preferred && (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_EN)) { 2529 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ 2530 SOC_IF_ERROR_RETURN 2531 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 2532 PHY_BCM542XX_SGMII_SLAVE_AUTO, 2533 PHY_BCM542XX_SGMII_SLAVE_AUTO)); 2534 } else if(fiber_preferred && (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS)) { 2535 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ 2536 SOC_IF_ERROR_RETURN 2537 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0, 2538 PHY_BCM542XX_SGMII_SLAVE_AUTO)); 2539 } else { 2540 /* SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ 2541 SOC_IF_ERROR_RETURN 2542 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 2543 PHY_BCM542XX_SGMII_SLAVE_AUTO, 2544 PHY_BCM542XX_SGMII_SLAVE_AUTO)); 2545 } 2546 /* MODE_CONTROL register, DIGX_SHD_1C_1F, RDB_0x21 */ 2547 SOC_IF_ERROR_RETURN 2548 (PHY_MODIFY_BCM542XX_MODE_CTRLr(unit, pc, 2549 PHY_BCM542XX_MODE_SEL_FIBER_2_SGMII, 2550 PHY_BCM542XX_MODE_CNTL_MODE_SEL_MASK)); 2551 } 2552 if (fiber_preferred && (ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS) 2553 && (ext_phy_fiber_iface >= EXT_PHY_FIBER_IFACE_1000X)) { 2554 2555 if (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_1000X) { /*1000x Fiber more*/ 2556 /* Enable 1000X mode. MODE_CONTROL register, DIGX_SHD_1C_1F, RDB_0x21 */ 2557 SOC_IF_ERROR_RETURN 2558 (PHY_MODIFY_BCM542XX_MODE_CTRLr(unit, pc, PHY_BCM542XX_MODE_CNTL_1000X_EN, 2559 PHY_BCM542XX_MODE_CNTL_1000X_EN)); 2560 2561 if (pc->fiber.autoneg_enable) { 2562 /* 2563 * Misc 1000-X Control 2 Reg., RDB.0x236, Legacy Reg.0x1C shadow 0x16 2564 * bit[0] SERDES_AUTONEG_PARALLEL_DETECT_EN 2565 */ 2566 SOC_IF_ERROR_RETURN 2567 (PHY_MODIFY_BCM542XX_1ST_SERDES_CTRLr(unit, pc, 2568 PHY_BCM542XX_SERDES_CTRL_AN_PD_EN, 2569 PHY_BCM542XX_SERDES_CTRL_AN_PD_EN)); 2570 2571 /* Default SerDes config & restart autonegotiation */ 2572 SOC_IF_ERROR_RETURN 2573 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 2574 PHY_BCM542XX_MII_CTRL_FD 2575 | PHY_BCM542XX_MII_CTRL_SS_1000 2576 | PHY_BCM542XX_MII_CTRL_AN_EN 2577 | pwr_down_bit 2578 | PHY_BCM542XX_MII_CTRL_RST_AN)); 2579 } else { 2580 SOC_IF_ERROR_RETURN 2581 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 2582 PHY_BCM542XX_MII_CTRL_FD 2583 | PHY_BCM542XX_MII_CTRL_SS_1000)); 2584 } 2585 } else if (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_100FX) { 2586 if (! PHY_IS_BCM54210_220(pc) ) { 2587 PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX); 2588 /* Enable 100BASE-FX mode*/ 2589 /* SERDES 100BASE-FX Control Reg., DIGX_SHD_1C_13, RDB_0x233 */ 2590 SOC_IF_ERROR_RETURN( 2591 phy_bcm542xx_direct_reg_modify(unit, pc, 2592 PHY_BCM542XX_100FX_CTRL_REG_OFFSET, 2593 PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN, 2594 PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN) ); 2595 } 2596 } else if (ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_SGMII) { 2597 if (! PHY_IS_BCM54210_220(pc) ) { 2598 /* Enable SGMII Slave mode. SGMII Slave Control Register, DIGX_SHD_1C_15, RDB_0x235 */ 2599 SOC_IF_ERROR_RETURN 2600 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, PHY_BCM542XX_SGMII_SLAVE_EN, 2601 PHY_BCM542XX_SGMII_SLAVE_EN)); 2602 } 2603 } else { 2604 /* 2605 * Incorrect fiber interface setting provided, applying 2606 * Default SerDes config & restart autonegotiation 2607 */ 2608 SOC_IF_ERROR_RETURN 2609 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 2610 PHY_BCM542XX_MII_CTRL_FD 2611 | PHY_BCM542XX_MII_CTRL_SS_1000 2612 | PHY_BCM542XX_MII_CTRL_AN_EN 2613 | pwr_down_bit 2614 | PHY_BCM542XX_MII_CTRL_RST_AN)); 2615 } 2616 } else { 2617 /* Default SerDes config & restart autonegotiation */ 2618 SOC_IF_ERROR_RETURN 2619 (PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, 2620 PHY_BCM542XX_MII_CTRL_FD 2621 | PHY_BCM542XX_MII_CTRL_SS_1000 2622 | PHY_BCM542XX_MII_CTRL_AN_EN 2623 | pwr_down_bit 2624 | PHY_BCM542XX_MII_CTRL_RST_AN)); 2625 } 2626 /* Configure BCM542XX to RGMII-to-Fiber mode */ 2627 if ( IS_GMII_PORT(unit, port) && PHY_IS_BCM54210_220(pc) ) { 2628 _phy_bcm542xx_rgmii_to_fiber_mode(unit, port); 2629 } 2630 2631 2632 } 2633 2634 /* Configure LED mode and turn on jumbo frame support */ 2635 _phy_bcm54280_init(unit, port); 2636 2637 return SOC_E_NONE; 2638 } 2639 2640 /* 2641 * Function: 2642 * phy_bcm542xx_dev_init 2643 * Purpose: 2644 * Initialize the PHY without reset. 2645 * Parameters: 2646 * phy_dev_addr - PHY Device Address 2647 * automedium - Automedium select in combo ports 2648 * fiber_preferred - Fiber preferrence over copper 2649 * fiber_detect - Fiber Signal Detect 2650 * ext_phy_autodetect_en - Enable/Disable SGMII Slave Autodetect function 2651 * ext_phy_fiber_iface - Fiber interface when Autodetect is disabled. 2652 * Notes: 2653 */ 2654 STATIC int 2655 phy_bcm542xx_dev_init(int unit, soc_port_t port, int automedium, 2656 int fiber_preferred, int fiber_detect, 2657 int fiber_enable , int copper_enable, 2658 int ext_phy_autodetect_en, int ext_phy_fiber_iface) 2659 { 2660 int oui = 0, model = 0, rev = 0; 2661 int rv = SOC_E_NONE; 2662 phy_ctrl_t *pc; 2663 2664 pc = EXT_PHY_SW_STATE(unit, port); 2665 2666 rv = _phy_bcm542xx_model_rev_get(unit, pc,&oui, &model, &rev); 2667 if (rv != SOC_E_NONE) { 2668 return SOC_E_FAIL; 2669 } 2670 2671 switch ( model ) { 2672 2673 case (PHY_BCM54192_MODEL | PHY_BCM54195_MODEL): 2674 case (PHY_BCM54182_MODEL | PHY_BCM54185_MODEL): 2675 if ( rev & 0x8 ) { /* PHY_BCM54185_MODEL */ 2676 rv = _phy_bcm54200_init(unit, port, automedium, 2677 fiber_preferred, 2678 fiber_detect, 2679 fiber_enable, 2680 copper_enable, 2681 ext_phy_autodetect_en, 2682 ext_phy_fiber_iface); 2683 } else { 2684 rv = _phy_bcm54282_init(unit, port); 2685 } 2686 break; 2687 2688 case PHY_BCM54280_MODEL: 2689 rv = _phy_bcm54280_init(unit, port); 2690 break; 2691 2692 case (PHY_BCM54190_MODEL | PHY_BCM54194_MODEL): 2693 case (PHY_BCM54180_MODEL | PHY_BCM54140_MODEL): 2694 if ( rev & 0x8 ) { /* PHY_BCM54140_MODEL */ 2695 rv = _phy_bcm54200_init(unit, port, automedium, 2696 fiber_preferred, 2697 fiber_detect, 2698 fiber_enable, 2699 copper_enable, 2700 ext_phy_autodetect_en, 2701 ext_phy_fiber_iface); 2702 } else { 2703 rv = _phy_bcm54280_init(unit, port); 2704 } 2705 break; 2706 2707 case (PHY_BCM54282_MODEL | PHY_BCM54285_MODEL): 2708 case PHY_BCM5428X_MODEL: 2709 if ( rev & 0x8 ) { /* PHY_BCM54282_MODEL */ 2710 rv = _phy_bcm54282_init(unit, port); 2711 2712 } else { /* PHY_BCM54285_MODEL */ 2713 rv = _phy_bcm54200_init(unit, port, automedium, 2714 fiber_preferred, 2715 fiber_detect, 2716 fiber_enable, 2717 copper_enable, 2718 ext_phy_autodetect_en, 2719 ext_phy_fiber_iface); 2720 } 2721 break; 2722 case PHY_BCM54210_MODEL: 2723 case PHY_BCM54220_MODEL: 2724 case PHY_BCM54240_MODEL: 2725 rv = _phy_bcm54200_init(unit, port, automedium, 2726 fiber_preferred, 2727 fiber_detect, 2728 fiber_enable, 2729 copper_enable, 2730 ext_phy_autodetect_en, 2731 ext_phy_fiber_iface); 2732 2733 break; 2734 case (PHY_BCM54292_MODEL | PHY_BCM54295_MODEL | PHY_BCM54296_MODEL): 2735 if ( rev & 0x8 ) { /* PHY_BCM54295/296_MODEL */ 2736 if ( 0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc) ) { 2737 PHY_BCM542XX_SET_REAR_HALF(pc); 2738 } 2739 rv = _phy_bcm54200_init(unit, port, automedium, 2740 fiber_preferred, 2741 fiber_detect, 2742 fiber_enable, 2743 copper_enable, 2744 ext_phy_autodetect_en, 2745 ext_phy_fiber_iface); 2746 } else { /* PHY_BCM54292_MODEL */ 2747 rv = _phy_bcm54282_init(unit, port); 2748 } 2749 break; 2750 case (PHY_BCM54290_MODEL | PHY_BCM54294_MODEL): 2751 if ( rev & 0x8 ) { /* PHY_BCM54294_MODEL */ 2752 PHY_BCM542XX_SET_REAR_HALF(pc); 2753 rv = _phy_bcm54200_init(unit, port, automedium, 2754 fiber_preferred, 2755 fiber_detect, 2756 fiber_enable, 2757 copper_enable, 2758 ext_phy_autodetect_en, 2759 ext_phy_fiber_iface); 2760 } else { /* PHY_BCM54290_MODEL */ 2761 rv = _phy_bcm54280_init(unit, port); 2762 } 2763 break; 2764 2765 default : 2766 return SOC_E_FAIL; 2767 } 2768 2769 return rv; 2770 } 2771 2772 #if 0 /* 54240/28x do not go to production with Rev.B0 */ 2773 /* 2774 * Function: 2775 * phy_bcm542xx_power_seq_war 2776 * Purpose: A failure to link can sometimes 2777 * occur after initial power up. 2778 * This is the workaround. 2779 * 2780 * Parameters: 2781 * phy_id - PHY Device Address 2782 * Notes: 2783 */ 2784 STATIC int 2785 phy_bcm542xx_power_seq_war(int unit, soc_port_t port) 2786 { 2787 phy_ctrl_t *pc; 2788 int index=0, num_ports; 2789 int oui=0, model=0, rev=0; 2790 2791 pc = EXT_PHY_SW_STATE(unit, port); 2792 2793 _phy_bcm542xx_model_rev_get(unit, pc,&oui, &model, &rev); 2794 2795 /* Recommended: 2796 To be done in this fixed sequence for a power sequencing 2797 bug. All the ports in one-go as it is not advisable to enter and exit 2798 test mode for each port. 2799 Use pc_base->phy_id as the filter to escape this in context of other ports 2800 since it will be already be done during pc_base's turn. 2801 - Do it after power recycle. 2802 */ 2803 if ( pc->phy_id == PHY_BCM542XX_DEV_PHY_ID_BASE(pc) ) { 2804 /* POWER SEQUENCE FIX */ 2805 if ( (model == PHY_BCM54240_MODEL) || (model == PHY_BCM54294_MODEL) ) { 2806 num_ports = 4; 2807 } else if ( model == PHY_BCM54210_MODEL ) { 2808 num_ports = 1; 2809 } else if ( model == PHY_BCM54220_MODEL ) { 2810 num_ports = 2; 2811 } else { 2812 num_ports = 8; 2813 } 2814 2815 for ( index = 0; index < num_ports; ++index ) { 2816 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc) + index; 2817 2818 /* enable dsp clock */ 2819 PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 2820 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK, 2821 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK); 2822 phy_bcm542xx_direct_reg_write(unit, pc, 2823 PHY_BCM542XX_LED_2_SEL_REG_OFFSET, 2824 0xB8EE); 2825 phy_bcm542xx_direct_reg_write(unit, pc, 2826 PHY_BCM542XX_LED_1_SEL_REG_OFFSET, 2827 0xB4EE); 2828 phy_bcm542xx_direct_reg_write(unit, pc, 2829 PHY_BCM542XX_DSP_TAP17_C0_REG_OFFSET, 2830 0x0009); 2831 phy_bcm542xx_direct_reg_write(unit, pc, 2832 PHY_BCM542XX_DSP_TAP17_C1_REG_OFFSET, 2833 0x0001); 2834 phy_bcm542xx_direct_reg_write(unit, pc, 2835 PHY_BCM542XX_DSP_TAP17_C1_REG_OFFSET, 2836 0x0003); 2837 /* Disable dsp clock */ 2838 PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 2839 0, 2840 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK); 2841 2842 } 2843 /*********************************************************************** 2844 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 2845 * To access TOP level registers use phy_id of port0. Override this ports 2846 */ 2847 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 2848 2849 #if 0 2850 phy_bcm542xx_direct_reg_write(unit, pc, 2851 PHY_BCM542XX_TOP_MISC_BOOT_REG_1_OFFSET, 2852 0x8800); 2853 phy_bcm542xx_direct_reg_write(unit, pc, 2854 PHY_BCM542XX_TOP_MISC_BOOT_REG_1_OFFSET, 2855 0x0000); 2856 2857 phy_bcm542xx_direct_reg_write(unit, pc, 2858 PHY_BCM542XX_TOP_MISC_BOOT_REG_0_OFFSET, 2859 0x0DA3); 2860 2861 phy_bcm542xx_direct_reg_write(unit, pc, 2862 PHY_BCM542XX_TOP_MISC_BOOT_REG_0_OFFSET, 2863 0x0D23); 2864 phy_bcm542xx_direct_reg_write(unit, pc, 2865 PHY_BCM542XX_TOP_MISC_BOOT_REG_1_OFFSET, 2866 0x8000); 2867 #else 2868 WRITE_PHY_REG(unit, pc,0x17, 0xD19); 2869 WRITE_PHY_REG(unit, pc,0x15, 0x8800); 2870 WRITE_PHY_REG(unit, pc,0x17, 0xD19); 2871 WRITE_PHY_REG(unit, pc,0x15, 0x0000); 2872 WRITE_PHY_REG(unit, pc,0x17, 0xD18); 2873 WRITE_PHY_REG(unit, pc,0x15, 0x0DA3); 2874 WRITE_PHY_REG(unit, pc,0x17, 0xD18); 2875 WRITE_PHY_REG(unit, pc,0x15, 0x0D23); 2876 WRITE_PHY_REG(unit, pc,0x17, 0xD19); 2877 WRITE_PHY_REG(unit, pc,0x15, 0x8000); 2878 #endif 2879 2880 /*********************************************************************** 2881 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 2882 * To access TOP level registers use phy_id of port0. Now restore back 2883 */ 2884 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 2885 } 2886 return SOC_E_NONE; 2887 } 2888 #endif /* 0 */ /* 54240/28x do not go to production with Rev.B0 */ 2889 2890 /* 2891 * Function: 2892 * phy_bcm542xx_reset_setup 2893 * Purpose: 2894 * Reset the PHY. 2895 * Parameters: 2896 * phy_id - PHY Device Address of the PHY to reset 2897 */ 2898 int 2899 phy_bcm542xx_reset_setup(int unit, soc_port_t port, 2900 int automedium, 2901 int fiber_preferred, 2902 int fiber_detect, 2903 int fiber_enable, 2904 int copper_enable, 2905 int ext_phy_autodetect_en, 2906 int ext_phy_fiber_iface) 2907 { 2908 soc_port_t primary_port; 2909 int index; 2910 phy_ctrl_t *pc; 2911 int oui = 0, model = 0, rev = 0; 2912 2913 pc = EXT_PHY_SW_STATE(unit, port); 2914 2915 /* Set primary port & offset */ 2916 if ( soc_phy_primary_and_offset_get(unit, port, &primary_port, &index) 2917 == SOC_E_NONE) { 2918 if ( index & 0x80 ) { 2919 PHY_BCM542XX_FLAGS(pc) |= PHY_BCM542XX_PHYADDR_REVERSE; 2920 } else { 2921 PHY_BCM542XX_FLAGS(pc) &= ~PHY_BCM542XX_PHYADDR_REVERSE; 2922 } 2923 2924 /* Do not change the order */ 2925 index &= ~0x80; /* clear reverse bit (PHYA_REV) */ 2926 PHY_BCM542XX_DEV_PHY_ID_ORIG(pc) = pc->phy_id; 2927 PHY_BCM542XX_DEV_PHY_SLICE(pc) = index; 2928 PHY_BCM542XX_DEV_SET_BASE_ADDR(pc); /* phy address of port 0 */ 2929 2930 SOC_IF_ERROR_RETURN 2931 (phy_bcm542xx_control_set(unit, port, 2932 SOC_PHY_CONTROL_PORT_PRIMARY, 2933 primary_port)); 2934 SOC_IF_ERROR_RETURN 2935 (phy_bcm542xx_control_set(unit, port, 2936 SOC_PHY_CONTROL_PORT_OFFSET, 2937 index )); 2938 } else { 2939 LOG_WARN(BSL_LS_SOC_PHY, 2940 (BSL_META_U(unit, 2941 "phy_bcm542xx_reset_setup: Config property " 2942 "'phy_port_primary_and_offset' " 2943 "not set for u=%d, p=%d\n"), unit, port)); 2944 return SOC_E_FAIL; 2945 } 2946 2947 /* PHY reset */ 2948 SOC_IF_ERROR_RETURN( phy_bcm542xx_reset(unit, port, (void*) NULL) ); 2949 if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_INIT_DONE) ) { 2950 /* Reset the Top level register block (RDB Reg.0x800-0xAFF) *\ 2951 \* during the 1st initialization only. */ 2952 phy_bcm542xx_direct_reg_modify(unit, pc, 2953 PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_OFFSET, 2954 PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TOP_MII_SOFT | 2955 PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TIMESYNC, 2956 PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TOP_MII_SOFT | 2957 PHY_BCM542XX_TOP_MISC_GLOBAL_RESET_TIMESYNC); 2958 } 2959 2960 /* get the model & revision ID of PHY chip */ 2961 SOC_IF_ERROR_RETURN( 2962 _phy_bcm542xx_model_rev_get(unit, pc,&oui, &model, &rev)); 2963 2964 if (PHY_IS_BCM54180(pc) || PHY_IS_BCM54182(pc) || PHY_IS_BCM54185(pc) || PHY_IS_BCM54140(pc) ) { 2965 SOC_IF_ERROR_RETURN( 2966 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E7, 0xA008)); 2967 SOC_IF_ERROR_RETURN( 2968 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0028, 0x0C30)); 2969 SOC_IF_ERROR_RETURN( 2970 phy_bcm542xx_rdb_reg_write(unit, pc, 0x00D8, 0x0020)); 2971 SOC_IF_ERROR_RETURN( 2972 phy_bcm542xx_rdb_reg_write(unit, pc, 0x012D, 0x0352)); 2973 SOC_IF_ERROR_RETURN( 2974 phy_bcm542xx_rdb_reg_write(unit, pc, 0x012E, 0xA04D)); 2975 SOC_IF_ERROR_RETURN( 2976 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0164, 0x0500)); 2977 SOC_IF_ERROR_RETURN( 2978 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0165, 0x7859)); 2979 SOC_IF_ERROR_RETURN( 2980 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0125, 0x091B)); 2981 SOC_IF_ERROR_RETURN( 2982 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E8, 0x00C3)); 2983 SOC_IF_ERROR_RETURN( 2984 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E9, 0x00CC)); 2985 SOC_IF_ERROR_RETURN( 2986 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01EA, 0x0300)); 2987 SOC_IF_ERROR_RETURN( 2988 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E2, 0x02E3)); 2989 SOC_IF_ERROR_RETURN( 2990 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E3, 0x7FC1)); 2991 SOC_IF_ERROR_RETURN( 2992 phy_bcm542xx_rdb_reg_write(unit, pc, 0x01E5, 0xA7AB)); 2993 SOC_IF_ERROR_RETURN( 2994 phy_bcm542xx_rdb_reg_write(unit, pc, 0x0028, 0x0430)); 2995 2996 } 2997 2998 #if 0 /* 54240/28x do not go to production with Rev.B0 */ 2999 /* WAR only for B0 rev */ 3000 if ( PHY_BCM54240_28X_REV_BO(model, rev) ) { 3001 phy_bcm542xx_power_seq_war(unit, port); 3002 } 3003 #endif 3004 3005 /* WAR for C0 and revisions before C0 */ 3006 if ( PHY_BCM54240_28X_REV_C0_OR_OLDER(model, rev) ) { 3007 /* EEE: Suggested defailt settings for these registers */ 3008 /* ENable dsp clock */ 3009 phy_bcm542xx_direct_reg_write(unit, pc, 3010 PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 3011 0x0C00); 3012 phy_bcm542xx_direct_reg_write(unit, pc, 3013 PHY_BCM542XX_DSP_TAP33_C2_REG_OFFSET, 3014 0x8787); 3015 phy_bcm542xx_direct_reg_write(unit, pc, 3016 PHY_BCM542XX_DSP_TAP34_C2_REG_OFFSET, 3017 0x017D); 3018 /* DISable dsp clock */ 3019 phy_bcm542xx_direct_reg_write(unit, pc, 3020 PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 3021 0x0400); 3022 3023 /* Recommended INIT default settings for registers */ 3024 phy_bcm542xx_direct_reg_write(unit, pc, 3025 PHY_BCM542XX_AFE_RXCONFIG_0_REG_OFFSET, 3026 0xD771); 3027 phy_bcm542xx_direct_reg_write(unit, pc, 3028 PHY_BCM542XX_AFE_RXCONFIG_2_REG_OFFSET, 3029 0x0072); 3030 phy_bcm542xx_direct_reg_write(unit, pc, 3031 PHY_BCM542XX_AFE_HPF_TRIM_REG_OFFSET, 3032 0x0006); 3033 phy_bcm542xx_direct_reg_write(unit, pc, 3034 PHY_BCM542XX_HALT_AGC_CTRL_REG_OFFSET, 3035 0x0020); 3036 phy_bcm542xx_direct_reg_write(unit, pc, 3037 PHY_BCM542XX_AFE_AFE_PLLCTRL_4_REG_OFFSET, 3038 0x0500); 3039 phy_bcm542xx_direct_reg_write(unit, pc, 3040 PHY_BCM542XX_AFE_VDACCTRL_1_REG_OFFSET, 3041 0xC100); 3042 phy_bcm542xx_direct_reg_write(unit, pc, 3043 PHY_BCM542XX_ANLOG_PWR_CTRL_OVRIDE_REG_OFFSET, 3044 0x1000); 3045 phy_bcm542xx_direct_reg_write(unit, pc, 3046 PHY_BCM542XX_TDR_OVRIDE_VAL_REG_OFFSET, 3047 0x7C00); 3048 phy_bcm542xx_direct_reg_write(unit, pc, 3049 PHY_BCM542XX_TDR_OVRIDE_VAL_REG_OFFSET, 3050 0x0000); 3051 } 3052 3053 /* 54240/5428x C1 rev */ 3054 if ( PHY_BCM54240_28X_REV_C1(model, rev) ) { 3055 /* 54240/5428x C1 Long Cable BER suppor, JIRA PHY-1629. *\ 3056 \* Errata 54240-ES101-R, 54280-ES101-R */ 3057 /* ENable dsp clock */ 3058 phy_bcm542xx_direct_reg_write(unit, pc, 3059 PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 3060 0x0C00); 3061 phy_bcm542xx_direct_reg_write(unit, pc, 3062 PHY_BCM542XX_AFE_VDACCTRL_2_REG_OFFSET, 3063 0x0007); 3064 phy_bcm542xx_direct_reg_write(unit, pc, 3065 PHY_BCM542XX_DSP_TAP33_C2_REG_OFFSET, 3066 0x87F6); 3067 phy_bcm542xx_direct_reg_write(unit, pc, 3068 PHY_BCM542XX_DSP_TAP10_REG_OFFSET, 3069 0x011B); 3070 /* DISable dsp clock */ 3071 phy_bcm542xx_direct_reg_write(unit, pc, 3072 PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 3073 0x0400); 3074 } 3075 3076 /* Recommended DSP_TAP10 setting for all the revisions */ 3077 phy_bcm542xx_direct_reg_write(unit, pc, 3078 PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 3079 0x0C00); 3080 phy_bcm542xx_direct_reg_write(unit, pc, 3081 PHY_BCM542XX_DSP_TAP10_REG_OFFSET, 3082 0x011B); 3083 /* config property PHY_OPERATIONAL_MODE == 0x80 or 0x8000 or 0x8080 *\ 3084 \* means to keep Super Isolate setting (depend on HW strap pin) */ 3085 if ( 0 == (PHY_RETAIN_SUPER_ISOLATE & 3086 soc_property_port_get(unit, port, spn_PHY_OPERATIONAL_MODE, 0)) ) { 3087 /* Remove Super Isolate */ 3088 phy_bcm542xx_direct_reg_modify(unit, pc, 3089 PHY_BCM542XX_POWER_MII_CTRL_REG_OFFSET, 0x0, 3090 PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE); 3091 LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit, 3092 "Remove Super Isolate: u=%d p=%d\n"), unit, port)); 3093 } 3094 3095 /* Enable current mode LED */ 3096 phy_bcm542xx_direct_reg_write(unit, pc, 3097 PHY_BCM542XX_LED_GPIO_CTRL_STATUS_REG_OFFSET, 3098 0xBC00); 3099 3100 SOC_IF_ERROR_RETURN( 3101 phy_bcm542xx_dev_init(unit, port, automedium, 3102 fiber_preferred, fiber_detect, 3103 fiber_enable, copper_enable, 3104 ext_phy_autodetect_en, 3105 ext_phy_fiber_iface)); 3106 3107 return SOC_E_NONE; 3108 } 3109 3110 /* 3111 * Function: 3112 * phy_bcm542xx_init_setup 3113 * Purpose: 3114 * Initialize the PHY with PHY reset. 3115 * Parameters: 3116 * phy_dev_addr - PHY Device Address 3117 * automedium - Automedium select in combo ports 3118 * fiber_preferred - Fiber preferrence over copper 3119 * fiber_detect - Fiber Signal Detect 3120 * ext_phy_autodetect_en - Enable/Disable SGMII Slave Autodetect function 3121 * ext_phy_fiber_iface - Fiber interface when Autodetect is disabled. 3122 * Notes: 3123 */ 3124 STATIC int 3125 phy_bcm542xx_init_setup( int unit, 3126 soc_port_t port, 3127 int reset, 3128 int automedium, 3129 int fiber_preferred, 3130 int fiber_detect, 3131 int fiber_enable, 3132 int copper_enable, 3133 int ext_phy_autodetect_en, 3134 int ext_phy_fiber_iface) 3135 { 3136 phy_ctrl_t *pc; 3137 int dev_port; 3138 3139 pc = EXT_PHY_SW_STATE(unit, port); 3140 3141 if ( reset ) { 3142 SOC_IF_ERROR_RETURN( 3143 phy_bcm542xx_reset_setup(unit, port, automedium, 3144 fiber_preferred, fiber_detect, 3145 fiber_enable, 3146 copper_enable, 3147 ext_phy_autodetect_en, 3148 ext_phy_fiber_iface)); 3149 } else { 3150 SOC_IF_ERROR_RETURN( 3151 phy_bcm542xx_dev_init( unit, port, automedium, 3152 fiber_preferred, fiber_detect, 3153 fiber_enable, 3154 copper_enable, 3155 ext_phy_autodetect_en, 3156 ext_phy_fiber_iface)); 3157 /* called by _phy_bcm542xx_no_reset_setup() or _phy_bcm542xx_medium_change() *\ 3158 \* no need to do the remaining RESET process below */ 3159 return SOC_E_NONE; 3160 } 3161 3162 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 3163 return SOC_E_NONE; 3164 } 3165 3166 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 3167 3168 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 3169 of the device. For example to enable autogrEEEn on port0, 3170 rdb register for port 4 0x808 need to be used. 3171 Refer package configuration document. 3172 */ 3173 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 3174 dev_port += 4; 3175 } 3176 3177 /* Reset EEE to default state i.e disable */ 3178 3179 /* Native */ 3180 /* Disable LPI feature */ 3181 SOC_IF_ERROR_RETURN( 3182 PHY_MODIFY_BCM542XX_EEE_803Dr(unit, pc, 0x0000, 0xC000) ); 3183 /* Reset counters and other settings */ 3184 SOC_IF_ERROR_RETURN( 3185 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 0x0000, 0x3fff) ); 3186 3187 /* AutogrEEEn */ 3188 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 3189 /* Disable AutogrEEEn and reset other settings */ 3190 SOC_IF_ERROR_RETURN( 3191 phy_bcm542xx_direct_reg_write(unit, pc, 3192 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 3193 0x8000) ); 3194 3195 /* Long cable EEE support */ 3196 if ( PHY_IS_BCM5429X(pc) ) { 3197 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 3198 PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc); /* set RDB register access mode */ 3199 #endif 3200 /* ENable dsp clock */ 3201 SOC_IF_ERROR_RETURN( 3202 phy_bcm542xx_rdb_reg_write(unit, pc, 3203 PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 0x0C00)); 3204 3205 SOC_IF_ERROR_RETURN( 3206 phy_bcm542xx_rdb_reg_write(unit, pc, 3207 PHY_BCM542XX_AFE_RXCONFIG_2_REG_OFFSET, 0x1872)); 3208 SOC_IF_ERROR_RETURN( 3209 phy_bcm542xx_rdb_reg_write(unit, pc, 3210 0x1C1, 0xA5F5)); 3211 SOC_IF_ERROR_RETURN( 3212 phy_bcm542xx_rdb_reg_write(unit, pc, 3213 0x150, 0xC70B)); 3214 3215 /* DISable dsp clock */ 3216 SOC_IF_ERROR_RETURN( 3217 phy_bcm542xx_rdb_reg_write(unit, pc, 3218 PHY_BCM542XX_AUX_CTRL_REG_OFFSET, 0x0400)); 3219 3220 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 3221 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */ 3222 #endif 3223 } 3224 3225 /* restore original phy_id */ 3226 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 3227 3228 #if AUTO_MDIX_WHEN_AN_DIS 3229 /* Enable Auto-MDIX When autoneg disabled */ 3230 SOC_IF_ERROR_RETURN( 3231 PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc, 3232 PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE, 3233 PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE) ); 3234 #endif 3235 3236 #ifdef LC_CM_DISABLE_WORKAROUND 3237 SOC_IF_ERROR_RETURN( /* Disable LED current mode */ 3238 phy_bcm542xx_direct_reg_write(unit, pc, 0x1F, 0xBC0F) ); 3239 #endif 3240 3241 return SOC_E_NONE; 3242 } 3243 3244 /* 3245 * Function: 3246 * phy_bcm542xx_init 3247 * Purpose: 3248 * Init function for 542xx PHY. 3249 * Parameters: 3250 * unit - StrataSwitch unit #. 3251 * port - StrataSwitch port #. 3252 * Returns: 3253 * SOC_E_NONE 3254 */ 3255 3256 STATIC int 3257 phy_bcm542xx_init(int unit, soc_port_t port) 3258 { 3259 phy_ctrl_t *pc; 3260 int fiber_capable = 0, rv; 3261 int fiber_preferred; 3262 PHY_BCM542XX_DEV_DESC_t *pDesc; 3263 3264 LOG_INFO(BSL_LS_SOC_PHY, 3265 (BSL_META_U(unit, "phy_bcm542xxx_init: u=%d p=%d\n"), 3266 unit, port)); 3267 3268 pc = EXT_PHY_SW_STATE(unit, port); 3269 3270 /* Only SGMII interface to switch MAC is supported */ 3271 if (IS_GMII_PORT(unit, port) && !(PHY_IS_BCM54210_220(pc)) ) { 3272 return SOC_E_CONFIG; 3273 } 3274 3275 if ( IS_GMII_PORT(unit, port) ) { 3276 pc->interface = SOC_PORT_IF_GMII; 3277 } else { 3278 /* interface type has been determined by phy_bcm542xx_probe() */ 3279 } 3280 3281 if ( ! (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) ) { 3282 /* if not during warmboot or reloading */ 3283 PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc); 3284 } 3285 3286 /* all 542xx support Energy-Efficient Ethernet */ 3287 PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_CAPABLE); 3288 3289 /* 3290 * get the PHY description structure, the software table 3291 * recording the PHY address info and OAM config. 3292 */ 3293 pDesc = (PHY_BCM542XX_DEV_DESC_t *)(pc+1); 3294 sal_memset(pDesc, 0, sizeof(PHY_BCM542XX_DEV_DESC_t)); /* clear the memory */ 3295 3296 /* 3297 * Default settings for the PHY control table (phy_ctrl_t *pc) 3298 */ 3299 3300 /* fiber_capable? */ 3301 if ( PHY_IS_BCM54140(pc) || PHY_IS_BCM54185(pc) || 3302 PHY_IS_BCM54194(pc) || PHY_IS_BCM54195(pc) || 3303 PHY_IS_BCM54210(pc) || PHY_IS_BCM54220(pc) || 3304 PHY_IS_BCM54240(pc) || PHY_IS_BCM54285(pc) || 3305 PHY_IS_BCM54294(pc) || PHY_IS_BCM54295(pc) || PHY_IS_BCM54296(pc) ) { 3306 fiber_capable = 1; 3307 } 3308 3309 if ( fiber_capable == 0 ) { /* not fiber capable */ 3310 fiber_preferred = 0; 3311 pc->automedium = 0; 3312 pc->fiber_detect = 0; 3313 pc->ext_phy_autodetect_en = -1; 3314 pc->ext_phy_fiber_iface = -1; 3315 } else { /* Change it to copper prefer for default. */ 3316 fiber_preferred = soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 0); 3317 pc->automedium = soc_property_port_get(unit, port, spn_PHY_AUTOMEDIUM, 0); 3318 pc->fiber_detect = soc_property_port_get(unit, port, spn_PHY_FIBER_DETECT, -4); 3319 pc->ext_phy_autodetect_en = soc_property_port_get(unit, port, spn_EXT_PHY_AUTODETECT_EN, -1); 3320 pc->ext_phy_fiber_iface = soc_property_port_get(unit, port, spn_EXT_PHY_SERDES_FIBER_IFACE, -1); 3321 } 3322 LOG_INFO(BSL_LS_SOC_PHY, 3323 (BSL_META_U(unit, 3324 "phy_542xx_init: u=%d p=%d type=bcm542xx%s " 3325 "automedium=%d fiber_pref=%d detect=%d " 3326 "ext_phy_autodetect_en=%d ext_phy_fiber_iface=%d\n"), 3327 unit, port, fiber_capable ? "S" : "", 3328 pc->automedium, fiber_preferred, pc->fiber_detect, 3329 pc->ext_phy_autodetect_en, pc->ext_phy_fiber_iface)); 3330 3331 pc->copper.enable = TRUE; 3332 pc->copper.preferred = ! fiber_preferred; 3333 pc->copper.autoneg_enable = TRUE; 3334 ADVERT_ALL_COPPER(&pc->copper.advert_ability); 3335 pc->copper.force_speed = 1000; 3336 pc->copper.force_duplex = TRUE; 3337 pc->copper.master = SOC_PORT_MS_AUTO; 3338 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 3339 3340 pc->fiber.enable = fiber_capable; 3341 pc->fiber.preferred = fiber_preferred; 3342 /* Auto-neg is unsupported in 100FX mode */ 3343 if (fiber_preferred && (pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS) && 3344 (pc->ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_100FX)) { 3345 pc->fiber.autoneg_enable = 0; 3346 } else { 3347 pc->fiber.autoneg_enable = fiber_capable; 3348 } 3349 3350 ADVERT_ALL_FIBER(&pc->fiber.advert_ability); 3351 pc->fiber.force_speed = 1000; 3352 pc->fiber.force_duplex = TRUE; 3353 pc->fiber.master = SOC_PORT_MS_NONE; 3354 pc->fiber.mdix = SOC_PORT_MDIX_NORMAL; 3355 3356 /* Initially configure for the preferred medium. */ 3357 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 3358 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 3359 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 3360 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 3361 if ( pc->fiber.preferred ) { 3362 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 3363 } else { 3364 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 3365 } 3366 3367 if (fiber_preferred && (pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS)) { 3368 if (pc->ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_100FX) { 3369 PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX); 3370 pc->fiber.force_speed = 100; 3371 } 3372 } 3373 3374 /* Get Requested LED selectors (defaults are hardware defaults) */ 3375 pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 3376 pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1); 3377 pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3); 3378 pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6); 3379 pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8); 3380 pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0); 3381 3382 /* Init PHYS and MACs to defaults */ 3383 rv = phy_bcm542xx_init_setup(unit, port, 1, 3384 pc->automedium, 3385 fiber_preferred, 3386 pc->fiber_detect, 3387 pc->fiber.enable, 3388 pc->copper.enable, 3389 pc->ext_phy_autodetect_en, 3390 pc->ext_phy_fiber_iface); 3391 if ( rv != SOC_E_NONE ) { 3392 return SOC_E_FAIL; 3393 } 3394 3395 #ifdef BCM_WARM_BOOT_SUPPORT 3396 /* if WarmBoot, retrieve PHY states from PHY registers */ 3397 if ( SOC_WARM_BOOT(unit) ) { 3398 soc_port_medium_t medium; 3399 int andone; 3400 3401 /* retrieve the medium mode (copper or fiber) */ 3402 SOC_IF_ERROR_RETURN( _phy_bcm542xx_medium_check(unit, port, &medium) ); 3403 3404 if ( medium == SOC_PORT_MEDIUM_COPPER ) { 3405 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 3406 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 3407 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 3408 /* retrieve copper staus from MII registers */ 3409 SOC_IF_ERROR_RETURN( 3410 phy_bcm542xx_ability_advert_get(unit, port, &(pc->copper.advert_ability)) ); 3411 SOC_IF_ERROR_RETURN( 3412 phy_bcm542xx_autoneg_get(unit, port, &(pc->copper.autoneg_enable), &andone) ); 3413 SOC_IF_ERROR_RETURN( 3414 phy_bcm542xx_duplex_get(unit, port, &(pc->copper.force_duplex)) ); 3415 SOC_IF_ERROR_RETURN( 3416 phy_bcm542xx_master_get(unit, port, &(pc->copper.master)) ); 3417 SOC_IF_ERROR_RETURN( 3418 phy_bcm542xx_speed_get(unit, port, &(pc->copper.force_speed)) ); 3419 if ( pc->copper.force_speed == 0 ) { 3420 pc->copper.force_speed = 1000; /* default speed */ 3421 } 3422 SOC_IF_ERROR_RETURN( 3423 phy_bcm542xx_mdix_get(unit, port, &(pc->copper.mdix)) ); 3424 } else { /* SOC_PORT_MEDIUM_FIBER */ 3425 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 3426 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 3427 /* retrieve fiber status from MII registers */ 3428 SOC_IF_ERROR_RETURN( 3429 phy_bcm542xx_ability_advert_get(unit, port, &(pc->fiber.advert_ability)) ); 3430 SOC_IF_ERROR_RETURN( 3431 phy_bcm542xx_autoneg_get(unit, port, &(pc->fiber.autoneg_enable), &andone) ); 3432 SOC_IF_ERROR_RETURN( 3433 phy_bcm542xx_duplex_get(unit, port, &(pc->fiber.force_duplex)) ); 3434 SOC_IF_ERROR_RETURN( 3435 phy_bcm542xx_master_get(unit, port, &(pc->fiber.master)) ); 3436 SOC_IF_ERROR_RETURN( 3437 phy_bcm542xx_speed_get(unit, port, &(pc->fiber.force_speed)) ); 3438 if ( pc->fiber.force_speed == 0 ) { 3439 pc->fiber.force_speed = 1000; /* default speed */ 3440 } else if ( pc->fiber.force_speed == 100 ) { 3441 PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX); 3442 } 3443 } 3444 3445 if ( fiber_capable == 1 ) { 3446 uint16 val16; 3447 /* determine default medium, copper or fiber */ 3448 SOC_IF_ERROR_RETURN( 3449 PHY_READ_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, &val16) ); 3450 pc->fiber_detect = ( val16 & BIT(8) ) ? -4 : 0; 3451 pc->fiber.preferred = ( val16 & BIT(1) ) ? TRUE : FALSE; 3452 pc->copper.preferred = ! pc->fiber.preferred; 3453 } 3454 } /* if (WARM_BOOT) */ 3455 3456 /* retreve the OAM setting from chip registers */ 3457 phy_bcm542xx_oam_config_get(unit, port, &(pDesc->oam_config)); 3458 #endif /* BCM_WARM_BOOT_SUPPORT */ 3459 3460 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 3461 return SOC_E_NONE; 3462 /* if WarmBoot, skip the following steps */ 3463 } 3464 3465 /* Set LED Modes and Control */ 3466 rv = phy_bcm542xx_set_led_selectors(unit, pc); 3467 if (rv != SOC_E_NONE) { 3468 return SOC_E_FAIL; 3469 } 3470 3471 /* Access LED related register */ 3472 if ( soc_property_port_get(unit, port, "phy_led3_output_disable", 0) ) { 3473 SOC_IF_ERROR_RETURN( 3474 phy_bcm542xx_direct_reg_modify(unit, pc, 0x814, 0x0001, 0x0001) ); 3475 } 3476 3477 SOC_IF_ERROR_RETURN 3478 (_phy_bcm542xx_medium_config_update(unit, port, 3479 PHY_COPPER_MODE(unit, port) ? 3480 &pc->copper : 3481 &pc->fiber)); 3482 return SOC_E_NONE; 3483 } 3484 3485 3486 /* 3487 * Function: 3488 * phy_bcm542xx_reset 3489 * Purpose: 3490 * Reset PHY and wait for it to come out of reset. 3491 * Parameters: 3492 * unit - StrataSwitch unit #. 3493 * port - StrataSwitch port #. 3494 * Returns: 3495 * SOC_E_XXX 3496 */ 3497 3498 int 3499 phy_bcm542xx_reset(int unit, soc_port_t port, void *user_arg) 3500 { 3501 int rv; 3502 phy_ctrl_t* pc = EXT_PHY_SW_STATE(unit, port); 3503 3504 rv = phy_fe_ge_reset(unit, port, NULL); 3505 PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc); 3506 return ( rv ); 3507 } 3508 3509 /* 3510 * Function: 3511 * phy_bcm542xx_enable_set 3512 * Purpose: 3513 * Enable or disable the physical interface. 3514 * Parameters: 3515 * unit - StrataSwitch unit #. 3516 * port - StrataSwitch port #. 3517 * enable - Boolean, true = enable PHY, false = disable. 3518 * Returns: 3519 * SOC_E_XXX 3520 */ 3521 3522 STATIC int 3523 phy_bcm542xx_enable_set(int unit, soc_port_t port, int enable) 3524 { 3525 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 3526 uint16 power = (enable) ? 0 : PHY_BCM542XX_MII_CTRL_PWR_DOWN; 3527 /* 3528 * Updated _phy_bcm54200_init to not power up the fiber and 3529 * copper PHY if port PHY is disabled. Here we need to power them up. 3530 * There is a timing issue that the fiber medium otherwise may not 3531 * be detected when both mediums are present at the boot time. 3532 */ 3533 if ( PHY_COPPER_MODE(unit, port) || pc->automedium ) { 3534 SOC_IF_ERROR_RETURN 3535 (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, power, 3536 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 3537 } 3538 if ( PHY_FIBER_MODE(unit, port) || pc->automedium ) { 3539 SOC_IF_ERROR_RETURN 3540 (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, power, 3541 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 3542 } 3543 3544 if ( pc->automedium || PHY_FIBER_MODE(unit, port) ) { 3545 phy_ctrl_t* int_pc = INT_PHY_SW_STATE(unit, port); 3546 3547 if ( NULL != int_pc ) { 3548 SOC_IF_ERROR_RETURN 3549 (PHY_ENABLE_SET(int_pc->pd, unit, port, enable)); 3550 } 3551 LOG_INFO(BSL_LS_SOC_PHY, 3552 (BSL_META_U(unit, "phy_bcm542xx_enable_set: " 3553 "Power %s fiber medium, u=%d p=%d\n"), 3554 (enable) ? "up" : "down", unit, port)); 3555 } 3556 3557 /* Update software state */ 3558 SOC_IF_ERROR_RETURN(phy_fe_ge_enable_set(unit, port, enable)); 3559 3560 return SOC_E_NONE; 3561 } 3562 3563 /* 3564 * Function: 3565 * phy_bcm542xx_enable_get 3566 * Purpose: 3567 * Enable or disable the physical interface for a 542xx device. 3568 * Parameters: 3569 * unit - StrataSwitch unit #. 3570 * port - StrataSwitch port #. 3571 * enable - (OUT) Boolean, true = enable PHY, false = disable. 3572 * Returns: 3573 * SOC_E_XXX 3574 */ 3575 3576 STATIC int 3577 phy_bcm542xx_enable_get(int unit, soc_port_t port, int *enable) 3578 { 3579 return phy_fe_ge_enable_get(unit, port, enable); 3580 } 3581 3582 /* 3583 * Function: 3584 * phy_bcm542xx_link_get 3585 * Purpose: 3586 * Determine the current link up/down status for a 542xx device. 3587 * Parameters: 3588 * unit - StrataSwitch unit #. 3589 * port - StrataSwitch port #. 3590 * link - (OUT) Boolean, true indicates link established. 3591 * Returns: 3592 * SOC_E_XXX 3593 * Notes: 3594 * If using automedium, also switches the mode. 3595 */ 3596 STATIC int 3597 phy_bcm542xx_link_get(int unit, soc_port_t port, int *link) 3598 { 3599 phy_ctrl_t *pc; 3600 uint16 powerdown; 3601 uint16 mii_stat, temp16; 3602 pc = EXT_PHY_SW_STATE(unit, port); 3603 *link = FALSE; /* Default return */ 3604 3605 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ) { 3606 return SOC_E_NONE; 3607 } 3608 3609 if (!pc->fiber.enable && !pc->copper.enable) { 3610 return SOC_E_NONE; 3611 } 3612 3613 if ( PHY_IS_BCM54240(pc) || PHY_IS_BCM54285(pc) ) { 3614 SOC_IF_ERROR_RETURN 3615 (phy_bcm542xx_direct_reg_read(unit, pc, 3616 PHY_BCM542XX_OPER_MODE_STATUS_REG_OFFSET, &temp16)); 3617 if ( (!(temp16 & BIT(5))) && ((temp16 & 0x1f) == 0xb) ) { 3618 /* no sync and in SGMII slave */ 3619 /* Disable auto-detection between SGMII-slave and 1000BASE-X 3620 and set mode to 1000BASE-X */ 3621 SOC_IF_ERROR_RETURN 3622 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0, 0x3)); 3623 /* Now enable auto-detection between SGMII-slave and 1000BASE-X */ 3624 SOC_IF_ERROR_RETURN 3625 (PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 1, 1)); 3626 } 3627 } 3628 3629 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 3630 if ( pc->automedium) { 3631 /* Check for medium change and update HW/SW accordingly. */ 3632 SOC_IF_ERROR_RETURN 3633 (_phy_bcm542xx_medium_change(unit, port, SOC_PORT_MEDIUM_NONE)); 3634 } 3635 3636 if ( PHY_COPPER_MODE(unit, port) ) { 3637 SOC_IF_ERROR_RETURN(phy_fe_ge_link_get(unit, port, link)); 3638 } else if ( PHY_FIBER_MODE(unit, port) ) { 3639 SOC_IF_ERROR_RETURN 3640 (PHY_READ_BCM542XX_1000X_MII_STATr(unit, pc,&mii_stat)); 3641 *link = (mii_stat & PHY_BCM542XX_MII_STAT_LA) ? TRUE : FALSE; 3642 } else { 3643 return SOC_E_INTERNAL; 3644 } 3645 3646 /* If preferred medium is up, disable the other medium to prevent false link. */ 3647 if ( pc->automedium ) { 3648 if ( pc->copper.preferred ) { 3649 if ( PHY_IS_BCM54210_220(pc) ) { 3650 /* don't power down fiber at 54220/210, it impacts traffic Tx/Rx */ 3651 powerdown = 0; 3652 } else if ( pc->fiber.enable ) { 3653 /* Power down Serdes if Copper mode is up */ 3654 powerdown = (*link && PHY_COPPER_MODE(unit, port)) 3655 ? PHY_BCM542XX_MII_CTRL_PWR_DOWN : 0; 3656 } else { 3657 powerdown = PHY_BCM542XX_MII_CTRL_PWR_DOWN; 3658 3659 } 3660 SOC_IF_ERROR_RETURN 3661 (PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, powerdown, 3662 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 3663 } else { /* pc->fiber.preferred */ 3664 if ( pc->copper.enable ) { 3665 powerdown = (*link && PHY_FIBER_MODE(unit, port)) 3666 ? PHY_BCM542XX_MII_CTRL_PWR_DOWN : 0; 3667 } else { 3668 powerdown = PHY_BCM542XX_MII_CTRL_PWR_DOWN; 3669 } 3670 SOC_IF_ERROR_RETURN 3671 (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, powerdown, 3672 PHY_BCM542XX_MII_CTRL_PWR_DOWN)); 3673 } 3674 } /* if ( automedium ) */ 3675 3676 LOG_VERBOSE(BSL_LS_SOC_PHY, 3677 (BSL_META_U(unit, "phy_bcm542xx_link_get: " 3678 "u=%d p=%d mode=%s%s link=%d\n"), 3679 unit, port, 3680 PHY_COPPER_MODE(unit, port) ? "C" : "F", 3681 PHY_FIBER_100FX_MODE(unit, port)? "(100FX)" : "", 3682 *link)); 3683 3684 return SOC_E_NONE; 3685 } 3686 3687 3688 /* 3689 * Function: 3690 * phy_bcm542xx_duplex_set 3691 * Purpose: 3692 * Set the current duplex mode (forced). 3693 * Parameters: 3694 * unit - StrataSwitch unit #. 3695 * port - StrataSwitch port #. 3696 * duplex - Boolean, true indicates full duplex, false indicates half. 3697 * Returns: 3698 * SOC_E_NONE 3699 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 3700 * Notes: 3701 * The duplex is set only for the ACTIVE medium. 3702 * No synchronization performed at this level. 3703 * Autonegotiation is not manipulated. 3704 */ 3705 3706 STATIC int 3707 phy_bcm542xx_duplex_set(int unit, soc_port_t port, int duplex) 3708 { 3709 phy_ctrl_t *pc; 3710 uint16 data, is_duplex; 3711 3712 pc = EXT_PHY_SW_STATE(unit, port); 3713 is_duplex = (duplex == SOC_PORT_DUPLEX_FULL) ? TRUE : FALSE; 3714 data = (is_duplex) ? PHY_BCM542XX_MII_CTRL_FD : 0; 3715 3716 if ( PHY_COPPER_MODE(unit, port) ) { 3717 SOC_IF_ERROR_RETURN( 3718 PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, data, 3719 PHY_BCM542XX_MII_CTRL_FD) ); 3720 pc->copper.force_duplex = duplex; 3721 3722 } else if ( PHY_FIBER_MODE(unit, port) ) { 3723 SOC_IF_ERROR_RETURN( 3724 PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, data, 3725 PHY_BCM542XX_MII_CTRL_FD) ); 3726 3727 if ( PHY_FIBER_100FX_MODE(unit, port) ) { 3728 data = (is_duplex) ? PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES : 0; 3729 SOC_IF_ERROR_RETURN( 3730 phy_bcm542xx_direct_reg_modify(unit, pc, 3731 PHY_BCM542XX_100FX_CTRL_REG_OFFSET, data, 3732 PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES) ); 3733 if ( PHY_IS_BCM54210_220(pc) ) { 3734 data = (is_duplex) ? PHY_BCM542XX_EXT_SERDES_FX_FD : 0; 3735 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ 3736 SOC_IF_ERROR_RETURN( 3737 PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, data, 3738 PHY_BCM542XX_EXT_SERDES_FX_FD) ); 3739 } 3740 pc->fiber.force_duplex = duplex; 3741 } else { /* 1000BASE-X */ 3742 if ( ! is_duplex ) { /* 1000X must be full-duplex */ 3743 return SOC_E_UNAVAIL; 3744 } 3745 } 3746 3747 } else { 3748 return SOC_E_INTERNAL; 3749 } 3750 LOG_INFO(BSL_LS_SOC_PHY, 3751 (BSL_META_U(unit, "phy_bcm542xx_duplex_set: u=%d p=%d d=%d\n"), 3752 unit, port, duplex)); 3753 return ( SOC_E_NONE ); 3754 } 3755 3756 /* 3757 * Function: 3758 * phy_bcm542xx_duplex_get 3759 * Purpose: 3760 * Get the current operating duplex mode. If autoneg is enabled, 3761 * then operating mode is returned, otherwise forced mode is returned. 3762 * Parameters: 3763 * unit - StrataSwitch unit #. 3764 * port - StrataSwitch port #. 3765 * duplex - (OUT) Boolean, true indicates full duplex, false 3766 * indicates half. 3767 * Returns: 3768 * SOC_E_NONE 3769 * Notes: 3770 * The duplex is retrieved for the ACTIVE medium. 3771 * No synchronization performed at this level. Autonegotiation is 3772 * not manipulated. 3773 */ 3774 3775 STATIC int 3776 phy_bcm542xx_duplex_get(int unit, soc_port_t port, int *duplex) 3777 { 3778 int rv = SOC_E_NONE; 3779 phy_ctrl_t *pc; 3780 uint16 opt_mode; 3781 uint16 mii_ctrl, mii_stat; 3782 3783 pc = EXT_PHY_SW_STATE(unit, port); 3784 3785 if ( PHY_FIBER_MODE(unit, port) ) { 3786 *duplex = TRUE; 3787 } 3788 3789 if ( PHY_COPPER_MODE(unit, port) ) { 3790 SOC_IF_ERROR_RETURN( 3791 PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl)); 3792 SOC_IF_ERROR_RETURN( 3793 PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat)); 3794 3795 if ( mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN ) { /* Auto-negotiation enabled */ 3796 if ( ! (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ) { /* Auto-neg NOT complete */ 3797 *duplex = FALSE; 3798 } else { 3799 uint16 misc_ctrl; 3800 SOC_IF_ERROR_RETURN( 3801 PHY_READ_BCM542XX_MII_MISC_CTRLr(unit, pc,&misc_ctrl)); 3802 /* First check for Ethernet@Wirespeed */ 3803 if ( misc_ctrl & BIT(4) ) { /* Ethernet@Wirespeed enabled */ 3804 rv = _phy_bcm542xx_auto_negotiate_ew(unit, pc, NULL, duplex); 3805 } else { 3806 rv = _phy_bcm542xx_auto_negotiate_gcd(unit, port, pc, NULL, duplex); 3807 } 3808 } 3809 } else { /* Auto-negotiation disabled */ 3810 *duplex = (mii_ctrl & PHY_BCM542XX_MII_CTRL_FD) ? TRUE : FALSE; 3811 } 3812 3813 } else if ( PHY_FIBER_MODE(unit, port) ) { /* Fiber mode */ 3814 if ( PHY_FIBER_100FX_MODE(unit, port) ) { 3815 SOC_IF_ERROR_RETURN 3816 (PHY_READ_BCM542XX_EXP_OPT_MODE_STATr(unit, pc,&opt_mode)); 3817 if ( opt_mode & PHY_BCM542XX_OPER_MODE_STATUS_SERDES_DUPLEX ) { 3818 *duplex = TRUE; 3819 } else { 3820 *duplex = FALSE; 3821 } 3822 } else { /* 1000X */ 3823 *duplex = TRUE; 3824 } 3825 3826 } else { 3827 return SOC_E_INTERNAL; 3828 } 3829 return rv; 3830 } 3831 3832 /* 3833 * Function: 3834 * phy_bcm542xx_speed_set 3835 * Purpose: 3836 * Set the current operating speed (forced). 3837 * Parameters: 3838 * unit - StrataSwitch unit #. 3839 * port - StrataSwitch port #. 3840 * speed - Requested speed, only 1000 supported. 3841 * Returns: 3842 * SOC_E_XXX 3843 * Notes: 3844 * The speed is set only for the ACTIVE medium. 3845 */ 3846 3847 STATIC int 3848 phy_bcm542xx_speed_set(int unit, soc_port_t port, int speed) 3849 { 3850 phy_ctrl_t *pc; 3851 uint16 mii_ctrl = 0; 3852 uint16 serdes_100fx_ctrl = 0x0; 3853 uint16 serdes_100fx_ctrl_mask = PHY_BCM542XX_100FX_CTRL_REG_RX_QUALIFY_DIS; 3854 #ifdef INCLUDE_PLP_IMACSEC 3855 int speed_m; 3856 unsigned int port_m; 3857 bcm_plp_base_t_sec_phy_access_t *imacsec_des; 3858 uint16 imacsec_cfg; 3859 soc_port_t port_s; 3860 unsigned int speed_mask=0x3; 3861 #endif 3862 pc = EXT_PHY_SW_STATE(unit, port); 3863 #ifdef INCLUDE_PLP_IMACSEC 3864 imacsec_des = IMACSEC_DES_PTR_GET(pc); 3865 #endif 3866 3867 #ifdef INCLUDE_PLP_IMACSEC 3868 if(pc->macsec_enable){ 3869 port_m = get_port(&imacsec_des->phy_info); 3870 SPEED_MAPPING(speed,speed_m); 3871 /* Use base phy id to write top register */ 3872 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 3873 /* SW set speed MACSEC_CONFIG2 reg */ 3874 SOC_IF_ERROR_RETURN 3875 (phy_bcm542xx_cl45_reg_read(unit, pc, 0x7, 0x9870, &imacsec_cfg)); 3876 imacsec_cfg |= 1<<port_m; 3877 SOC_IF_ERROR_RETURN 3878 (phy_bcm542xx_cl45_reg_write(unit, pc, 0x7, 0x9870, imacsec_cfg)); 3879 /* SW set speed MACSEC_CONFIG3 reg */ 3880 SOC_IF_ERROR_RETURN 3881 (phy_bcm542xx_cl45_reg_read(unit, pc, 0x7, 0x9871, &imacsec_cfg)); 3882 imacsec_cfg &= ~(speed_mask << (port_m*2)); 3883 imacsec_cfg |= (speed_m << (port_m*2)); 3884 SOC_IF_ERROR_RETURN 3885 (phy_bcm542xx_cl45_reg_write(unit, pc, 0x7, 0x9871, imacsec_cfg)); 3886 /* Restore the phy mdio address */ 3887 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 3888 3889 port_s= PHY_UNIMAC_V2_SWITCH_PORT(port); 3890 SOC_IF_ERROR_RETURN( 3891 BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 0)); 3892 3893 SOC_IF_ERROR_RETURN( 3894 BMACSEC_MAC_AUTO_CONFIG_SET((phy_mac_ctrl_t *)imacsec_des->unimac, port_s, 1)); 3895 } 3896 #endif 3897 /* get current MII control Register */ 3898 if ( PHY_COPPER_MODE(unit, port) ) { /* copper mode */ 3899 SOC_IF_ERROR_RETURN( 3900 PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) ); 3901 } else { /* fiber mode */ 3902 if ( speed == 10 ) { 3903 return SOC_E_UNAVAIL; /* nehter 1000Base-X nor 100Base-FX */ 3904 } 3905 SOC_IF_ERROR_RETURN( 3906 PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) ); 3907 } 3908 /* mask off the Speed Selection bit[6,13] */ 3909 mii_ctrl &= ~(PHY_BCM542XX_MII_CTRL_SS_LSB | PHY_BCM542XX_MII_CTRL_SS_MSB); 3910 3911 switch ( speed ) { 3912 case 10: 3913 mii_ctrl |= PHY_BCM542XX_MII_CTRL_SS_10; 3914 break; 3915 case 100: 3916 mii_ctrl |= PHY_BCM542XX_MII_CTRL_SS_100; 3917 serdes_100fx_ctrl = (PHY_IS_BCM54210_220(pc)) ? 0 : 3918 PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN; 3919 serdes_100fx_ctrl_mask |= PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN | 3920 PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES; 3921 if ( pc->fiber.force_duplex) { 3922 serdes_100fx_ctrl |= PHY_BCM542XX_100FX_CTRL_REG_FD_FX_SERDES; 3923 } 3924 break; 3925 case 1000: 3926 mii_ctrl |= PHY_BCM542XX_MII_CTRL_SS_1000; 3927 serdes_100fx_ctrl_mask |= PHY_BCM542XX_100FX_CTRL_REG_FX_SERDES_EN; 3928 break; 3929 default: 3930 return SOC_E_CONFIG; 3931 } 3932 3933 if ( PHY_COPPER_MODE(unit, port) ) { /* COPPER mode */ 3934 SOC_IF_ERROR_RETURN( 3935 PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, mii_ctrl) ); 3936 pc->copper.force_speed = speed; 3937 3938 } else { /* FIBER mode */ 3939 if ( speed == 100 ) { 3940 /* Disable autoneg for 100Base-FX speed */ 3941 pc->fiber.autoneg_enable = FALSE; 3942 if ( PHY_IS_BCM54140(pc) || PHY_IS_BCM54194(pc) || 3943 PHY_IS_BCM54185(pc) || PHY_IS_BCM54195(pc) ) { 3944 /* turn on RX_QUALIFY_DIS for 28nm SerDes AFE, RDB.0x233[5] */ 3945 serdes_100fx_ctrl |= PHY_BCM542XX_100FX_CTRL_REG_RX_QUALIFY_DIS; 3946 } 3947 } 3948 /* Select 1000x/100fx and duplexity in case of 100fx */ 3949 /* SERDES 100BASE-FX Control Reg., DIGX_SHD_1C_13, RDB_0x233 */ 3950 SOC_IF_ERROR_RETURN( 3951 phy_bcm542xx_direct_reg_modify(unit, pc, 3952 PHY_BCM542XX_100FX_CTRL_REG_OFFSET, 3953 serdes_100fx_ctrl, serdes_100fx_ctrl_mask) ); 3954 3955 if ( pc->fiber.autoneg_enable ) { 3956 mii_ctrl |= MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_FD; 3957 } else { 3958 mii_ctrl |= MII_CTRL_FD; 3959 } 3960 3961 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ) { 3962 mii_ctrl |= PHY_BCM542XX_MII_CTRL_PWR_DOWN; 3963 } 3964 SOC_IF_ERROR_RETURN( 3965 PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, mii_ctrl) ); 3966 3967 if ( speed == 100 ) { 3968 if ( PHY_IS_BCM54210_220(pc) ) { 3969 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ 3970 SOC_IF_ERROR_RETURN( 3971 PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, 3972 PHY_BCM542XX_EXT_SERDES_FX, 3973 PHY_BCM542XX_EXT_SERDES_FX_MASK) ); 3974 } 3975 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 3976 PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX); 3977 } 3978 /* Enforce duplexity to full for 1000X */ 3979 if ( speed == 1000 ) { 3980 if ( PHY_IS_BCM54210_220(pc) ) { 3981 /* 54220_210_B0 don't support PHY_BCM542XX_EXT_SERDES_AUTO_FX, */ 3982 /* External Serdes Control Reg., DIGX_SHD_1C_14, RDB_0x234 */ 3983 SOC_IF_ERROR_RETURN( 3984 PHY_MODIFY_BCM542XX_EXT_SERDES_CTRLr(unit, pc, 0, 3985 PHY_BCM542XX_EXT_SERDES_FX_MASK) ); 3986 } 3987 pc->fiber.force_duplex = TRUE; 3988 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 3989 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 3990 } 3991 3992 pc->fiber.force_speed = speed; 3993 } 3994 LOG_INFO(BSL_LS_SOC_PHY, 3995 (BSL_META_U(unit, 3996 "phy_bcm542xx_speed_set: u=%d p=%d s=%d fiber=%d\n"), 3997 unit, port, speed, PHY_FIBER_MODE(unit, port))); 3998 return ( SOC_E_NONE ); 3999 } 4000 4001 /* 4002 * Function: 4003 * phy_bcm542xx_speed_get 4004 * Purpose: 4005 * Get the current operating speed for a bcm542xx device. 4006 * Parameters: 4007 * unit - StrataSwitch unit #. 4008 * port - StrataSwitch port #. 4009 * duplex - (OUT) Boolean, true indicates full duplex, false 4010 * indicates half. 4011 * Returns: 4012 * SOC_E_NONE 4013 * Notes: 4014 * The speed is retrieved for the ACTIVE medium. 4015 */ 4016 4017 STATIC int 4018 phy_bcm542xx_speed_get(int unit, soc_port_t port, int *speed) 4019 { 4020 phy_ctrl_t *pc; 4021 uint16 mii_ctrl, mii_aux_stat, temp16; 4022 #ifdef INCLUDE_PLP_IMACSEC 4023 int speed_m; 4024 bcm_plp_base_t_sec_phy_access_t *imacsec_des; 4025 #endif 4026 pc = EXT_PHY_SW_STATE(unit, port); 4027 #ifdef INCLUDE_PLP_IMACSEC 4028 imacsec_des = IMACSEC_DES_PTR_GET(pc); 4029 #endif 4030 4031 if ( PHY_COPPER_MODE(unit, port) ) { 4032 SOC_IF_ERROR_RETURN( 4033 PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl)); 4034 4035 if ( mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN ) { /* Auto-negotiation enabled */ 4036 SOC_IF_ERROR_RETURN( 4037 PHY_READ_BCM542XX_MII_AUX_STATUSr(unit, pc,&mii_aux_stat)); 4038 4039 if ( ! (mii_aux_stat & PHY_BCM542XX_MII_ASSR_ANC) ) { 4040 /* Auto-neg NOT complete */ 4041 *speed = 0; 4042 } else { 4043 switch ( mii_aux_stat & PHY_BCM542XX_MII_ASSR_AUTONEG_HCD_MASK ) { 4044 case PHY_BCM542XX_MII_ASSR_HCD_FD_1000: 4045 case PHY_BCM542XX_MII_ASSR_HCD_HD_1000: 4046 *speed = 1000; 4047 break; 4048 case PHY_BCM542XX_MII_ASSR_HCD_FD_100: 4049 case PHY_BCM542XX_MII_ASSR_HCD_HD_100: 4050 case PHY_BCM542XX_MII_ASSR_HCD_T4_100: 4051 *speed = 100; 4052 break; 4053 case PHY_BCM542XX_MII_ASSR_HCD_FD_10: 4054 case PHY_BCM542XX_MII_ASSR_HCD_HD_10: 4055 *speed = 10; 4056 break; 4057 default: 4058 *speed = 0; 4059 } 4060 } 4061 } else { /* Auto-negotiation disabled */ 4062 /* Pick up the values we force in CTRL register */ 4063 switch(PHY_BCM542XX_MII_CTRL_SS(mii_ctrl) ) { 4064 case PHY_BCM542XX_MII_CTRL_SS_10: 4065 *speed = 10; 4066 break; 4067 case PHY_BCM542XX_MII_CTRL_SS_100: 4068 *speed = 100; 4069 break; 4070 case PHY_BCM542XX_MII_CTRL_SS_1000: 4071 *speed = 1000; 4072 break; 4073 default: /* Pass error back */ 4074 return SOC_E_UNAVAIL; 4075 } 4076 } 4077 4078 } else if ( PHY_FIBER_MODE(unit, port) ) { 4079 if (pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS && 4080 pc->ext_phy_fiber_iface == EXT_PHY_FIBER_IFACE_SGMII) { 4081 SOC_IF_ERROR_RETURN( 4082 PHY_READ_BCM542XX_SGMII_SLAVEr(unit, pc, &temp16)); 4083 switch ( temp16 & PHY_BCM542XX_SGMII_SPEED ) { 4084 case PHY_BCM542XX_SGMII_SPEED_10: 4085 *speed = 10; 4086 break; 4087 case PHY_BCM542XX_SGMII_SPEED_100: 4088 *speed = 100; 4089 break; 4090 case PHY_BCM542XX_SGMII_SPEED_1000: 4091 *speed = 1000; 4092 break; 4093 default: 4094 return SOC_E_UNAVAIL; 4095 } 4096 } else { 4097 phy_bcm542xx_direct_reg_read(unit, pc, 4098 PHY_BCM542XX_OPER_MODE_STATUS_REG_OFFSET, &temp16); 4099 switch ( temp16 & PHY_BCM542XX_OPER_MODE_STATUS_REG_SERDES_SPEED ) { 4100 case PHY_BCM542XX_OPER_MODE_STATUS_SERDES_SPEED_10: 4101 *speed = 10; 4102 break; 4103 case PHY_BCM542XX_OPER_MODE_STATUS_SERDES_SPEED_100: 4104 *speed = 100; 4105 break; 4106 case PHY_BCM542XX_OPER_MODE_STATUS_SERDES_SPEED_1000: 4107 *speed = 1000; 4108 break; 4109 default: 4110 return SOC_E_UNAVAIL; 4111 } 4112 } 4113 } else { 4114 return SOC_E_INTERNAL; 4115 } 4116 #ifdef INCLUDE_PLP_IMACSEC 4117 if(pc->macsec_enable){ 4118 SOC_IF_ERROR_RETURN( 4119 BMACSEC_MAC_SPEED_GET((phy_mac_ctrl_t *)imacsec_des->unimac, port, &speed_m)); 4120 if(*speed !=0 && *speed == speed_m){ 4121 LOG_INFO(BSL_LS_SOC_PHY, 4122 (BSL_META_U(unit, "phy_bcm542xx_speed_get: u=%d p=%d sp=%d\n"), 4123 unit, port, speed_m)); 4124 4125 return ( SOC_E_NONE ); 4126 } 4127 } 4128 #endif 4129 LOG_INFO(BSL_LS_SOC_PHY, 4130 (BSL_META_U(unit, "phy_bcm542xx_speed_get: u=%d p=%d sp=%d\n"), 4131 unit, port, *speed)); 4132 4133 return ( SOC_E_NONE ); 4134 } 4135 4136 /* 4137 * Function: 4138 * phy_bcm542xx_master_set 4139 * Purpose: 4140 * Set the current master mode 4141 * Parameters: 4142 * unit - StrataSwitch unit #. 4143 * port - StrataSwitch port #. 4144 * master - SOC_PORT_MS_* 4145 * Returns: 4146 * SOC_E_XXX 4147 * Notes: 4148 * The master mode is set only for the ACTIVE medium. 4149 */ 4150 STATIC int 4151 phy_bcm542xx_master_set(int unit, soc_port_t port, int master) 4152 { 4153 phy_ctrl_t *pc; 4154 uint16 mii_gb_ctrl; 4155 4156 pc = EXT_PHY_SW_STATE(unit, port); 4157 4158 if ( PHY_COPPER_MODE(unit, port) ) { 4159 SOC_IF_ERROR_RETURN( 4160 PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl)); 4161 switch (master) { 4162 case SOC_PORT_MS_SLAVE: 4163 mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_MS_MAN; 4164 mii_gb_ctrl &= ~PHY_BCM542XX_MII_GB_CTRL_MS; 4165 break; 4166 case SOC_PORT_MS_MASTER: 4167 mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_MS_MAN; 4168 mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_MS; 4169 break; 4170 case SOC_PORT_MS_AUTO: 4171 mii_gb_ctrl &= ~PHY_BCM542XX_MII_GB_CTRL_MS_MAN; 4172 break; 4173 case SOC_PORT_MS_NONE: 4174 break; 4175 default: 4176 return SOC_E_CONFIG; 4177 } 4178 4179 SOC_IF_ERROR_RETURN( 4180 PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc, mii_gb_ctrl) ); 4181 pc->copper.master = master; 4182 } 4183 4184 LOG_INFO(BSL_LS_SOC_PHY, 4185 (BSL_META_U(unit, "phy_bcm542xx_master_set: " 4186 "u=%d p=%d master=%d fiber=%d\n"), 4187 unit, port, master, PHY_FIBER_MODE(unit, port))); 4188 return ( SOC_E_NONE ); 4189 } 4190 4191 /* 4192 * Function: 4193 * phy_bcm542xx_master_get 4194 * Purpose: 4195 * Get the current master mode for a bcm542xx device. 4196 * Parameters: 4197 * unit - StrataSwitch unit #. 4198 * port - StrataSwitch port #. 4199 * master - (OUT) SOC_PORT_MS_* 4200 * Returns: 4201 * SOC_E_NONE 4202 * Notes: 4203 * The master mode is retrieved for the ACTIVE medium. 4204 */ 4205 4206 STATIC int 4207 phy_bcm542xx_master_get(int unit, soc_port_t port, int *master) 4208 { 4209 phy_ctrl_t *pc; 4210 uint16 mii_gb_ctrl; 4211 4212 pc = EXT_PHY_SW_STATE(unit, port); 4213 4214 if ( PHY_COPPER_MODE(unit, port) ) { 4215 SOC_IF_ERROR_RETURN( 4216 PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl) ); 4217 4218 if ( ! (mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_MS_MAN) ) { 4219 *master = SOC_PORT_MS_AUTO; 4220 } else if ( mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_MS ) { 4221 *master = SOC_PORT_MS_MASTER; 4222 } else { 4223 *master = SOC_PORT_MS_SLAVE; 4224 } 4225 4226 } else if ( PHY_FIBER_MODE(unit, port) ) { 4227 *master = SOC_PORT_MS_NONE; 4228 4229 } else { 4230 return SOC_E_INTERNAL; 4231 } 4232 4233 return ( SOC_E_NONE ); 4234 } 4235 4236 /* 4237 * Function: 4238 * phy_bcm542xx_autoneg_set 4239 * Purpose: 4240 * Enable or disable auto-negotiation on the specified port. 4241 * Parameters: 4242 * unit - StrataSwitch unit #. 4243 * port - StrataSwitch port #. 4244 * autoneg - Boolean, if true, auto-negotiation is enabled 4245 * (and/or restarted). If false, autonegotiation is disabled. 4246 * Returns: 4247 * SOC_E_XXX 4248 * Notes: 4249 * The autoneg mode is set only for the ACTIVE medium. 4250 */ 4251 4252 STATIC int 4253 phy_bcm542xx_autoneg_set(int unit, soc_port_t port, int autoneg) 4254 { 4255 phy_ctrl_t *pc; 4256 uint16 mii_ctrl; 4257 pc = EXT_PHY_SW_STATE(unit, port); 4258 4259 if ( PHY_COPPER_MODE(unit, port) ) { 4260 SOC_IF_ERROR_RETURN( 4261 PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl)); 4262 4263 if (autoneg) { 4264 mii_ctrl |= PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN; 4265 } else { 4266 mii_ctrl &= ~(PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN); 4267 } 4268 SOC_IF_ERROR_RETURN( 4269 PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, mii_ctrl)); 4270 4271 pc->copper.autoneg_enable = autoneg ? TRUE : FALSE; 4272 4273 } else if ( PHY_FIBER_MODE(unit, port) ) { 4274 if (PHY_FIBER_100FX_MODE(unit, port)) { 4275 /* 100FX mode doesn't support autoneg*/ 4276 autoneg = 0; 4277 } 4278 if ( autoneg ) { 4279 /* When enabling autoneg, set the default speed to 1000Mbps first. 4280 * PHY will not enable autoneg if the PHY is in 100FX mode. 4281 */ 4282 SOC_IF_ERROR_RETURN 4283 (phy_bcm542xx_speed_set(unit, port, 1000)); 4284 } 4285 4286 /* Disable/Enable auto-detection between SGMII-slave and 1000BASE-X */ 4287 /* don't change SGMII_SLAVE_AUTO_DET at 54220/210, it impacts traffic Tx/Rx */ 4288 if ( ! PHY_IS_BCM54210_220(pc) ) { 4289 if (pc->fiber.preferred && pc->ext_phy_autodetect_en == EXT_PHY_AUTODETECT_DIS) { 4290 /* SGMII Slave Register, DIGX_SHD1C_15 bit[1] SGMII_SLAVE_AUTO_DET*/ 4291 SOC_IF_ERROR_RETURN( 4292 PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc, 0, 4293 PHY_BCM542XX_SGMII_SLAVE_AUTO) ); 4294 } else { 4295 /* SGMII Slave Register, DIGX_SHD1C_15 bit[0] SGMII_SLAVE_AUTO_DET*/ 4296 SOC_IF_ERROR_RETURN( 4297 PHY_MODIFY_BCM542XX_SGMII_SLAVEr(unit, pc,(autoneg ? 1 : 0), 1) ); 4298 } 4299 } 4300 4301 SOC_IF_ERROR_RETURN( 4302 phy_bcm542xx_ability_advert_set(unit, port, &pc->fiber.advert_ability) ); 4303 4304 SOC_IF_ERROR_RETURN( 4305 PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) ); 4306 4307 if ( autoneg ) { 4308 mii_ctrl |= PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN; 4309 } else { 4310 mii_ctrl &= ~(PHY_BCM542XX_MII_CTRL_AN_EN | PHY_BCM542XX_MII_CTRL_RST_AN); 4311 } 4312 SOC_IF_ERROR_RETURN( 4313 PHY_WRITE_BCM542XX_1000X_MII_CTRLr(unit, pc, mii_ctrl) ); 4314 4315 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE; 4316 4317 } else { 4318 return SOC_E_INTERNAL; 4319 } 4320 4321 LOG_INFO(BSL_LS_SOC_PHY, 4322 (BSL_META_U(unit, 4323 "phy_bcm542xx_autoneg_set: u=%d p=%d autoneg=%d\n"), 4324 unit, port, autoneg)); 4325 return ( SOC_E_NONE ); 4326 } 4327 4328 /* 4329 * Function: 4330 * phy_bcm542xx_autoneg_get 4331 * Purpose: 4332 * Get the current auto-negotiation status (enabled/busy). 4333 * Parameters: 4334 * unit - StrataSwitch unit #. 4335 * port - StrataSwitch port #. 4336 * autoneg - (OUT) if true, auto-negotiation is enabled. 4337 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 4338 * value is undefined if autoneg == FALSE. 4339 * Returns: 4340 * SOC_E_XXX 4341 * Notes: 4342 * The autoneg mode is retrieved for the ACTIVE medium. 4343 */ 4344 4345 STATIC int 4346 phy_bcm542xx_autoneg_get(int unit, soc_port_t port, 4347 int *autoneg, int *autoneg_done) 4348 { 4349 phy_ctrl_t *pc; 4350 uint16 mii_ctrl, mii_stat; 4351 4352 pc = EXT_PHY_SW_STATE(unit, port); 4353 4354 *autoneg = FALSE; 4355 *autoneg_done = FALSE; 4356 4357 if ( PHY_COPPER_MODE(unit, port) ) { 4358 SOC_IF_ERROR_RETURN( 4359 PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) ); 4360 SOC_IF_ERROR_RETURN( 4361 PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat) ); 4362 4363 *autoneg = (mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN) ? 1 : 0; 4364 *autoneg_done = (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ? 1 : 0; 4365 4366 } else if ( PHY_FIBER_MODE(unit, port) ) { 4367 /* autoneg is not enabled in 100FX mode */ 4368 if ( PHY_FIBER_100FX_MODE(unit, port) ) { 4369 *autoneg = FALSE; 4370 *autoneg_done = TRUE; 4371 } else { 4372 SOC_IF_ERROR_RETURN( 4373 PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) ); 4374 SOC_IF_ERROR_RETURN( 4375 PHY_READ_BCM542XX_1000X_MII_STATr(unit, pc,&mii_stat) ); 4376 4377 *autoneg = (mii_ctrl & PHY_BCM542XX_MII_CTRL_AN_EN) ? 1 : 0; 4378 *autoneg_done = (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ? 1 : 0; 4379 } 4380 4381 } else { 4382 return SOC_E_INTERNAL; 4383 } 4384 4385 return ( SOC_E_NONE ); 4386 } 4387 4388 /* 4389 * Function: 4390 * phy_bcm542xx_ability_advert_set 4391 * Purpose: 4392 * Set the current advertisement for auto-negotiation. 4393 * Parameters: 4394 * unit - StrataSwitch unit #. 4395 * port - StrataSwitch port #. 4396 * mode - Port mode mask indicating supported options/speeds. 4397 * Returns: 4398 * SOC_E_XXX 4399 * Notes: 4400 * The advertisement is set only for the ACTIVE medium. 4401 * No synchronization performed at this level. 4402 */ 4403 STATIC int 4404 phy_bcm542xx_ability_advert_set(int unit, soc_port_t port, 4405 soc_port_ability_t *ability) 4406 { 4407 phy_ctrl_t *pc; 4408 uint16 mii_adv, mii_gb_ctrl; 4409 4410 pc = EXT_PHY_SW_STATE(unit, port); 4411 4412 if ( PHY_COPPER_MODE(unit, port) ) { 4413 mii_adv = PHY_BCM542XX_MII_ANA_ASF_802_3; 4414 SOC_IF_ERROR_RETURN 4415 (PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl)); 4416 4417 mii_gb_ctrl &= ~(PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD | 4418 PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD); 4419 mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_PT; /* repeater / switch port */ 4420 4421 if ( (ability->speed_half_duplex) & SOC_PA_SPEED_10MB ) { 4422 mii_adv |= PHY_BCM542XX_MII_ANA_HD_10; 4423 } 4424 if ( (ability->speed_full_duplex) & SOC_PA_SPEED_10MB ) { 4425 mii_adv |= PHY_BCM542XX_MII_ANA_FD_10; 4426 } 4427 if ( (ability->speed_half_duplex) & SOC_PA_SPEED_100MB ) { 4428 mii_adv |= PHY_BCM542XX_MII_ANA_HD_100; 4429 } 4430 if ( (ability->speed_full_duplex) & SOC_PA_SPEED_100MB ) { 4431 mii_adv |= PHY_BCM542XX_MII_ANA_FD_100; 4432 } 4433 if ( (ability->speed_half_duplex) & SOC_PA_SPEED_1000MB ) { 4434 mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD; 4435 } 4436 if ( (ability->speed_full_duplex) & SOC_PA_SPEED_1000MB ) { 4437 mii_gb_ctrl |= PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD; 4438 } 4439 4440 if ( ((ability->pause) & SOC_PA_PAUSE) == SOC_PA_PAUSE ) { 4441 /* Advertise symmetric pause */ 4442 mii_adv |= PHY_BCM542XX_MII_ANA_PAUSE; 4443 } else { 4444 if ( (ability->pause) & SOC_PA_PAUSE_TX ) { 4445 mii_adv |= PHY_BCM542XX_MII_ANA_ASYM_PAUSE; 4446 } else { 4447 if ( (ability->pause) & SOC_PA_PAUSE_RX ) { 4448 mii_adv |= PHY_BCM542XX_MII_ANA_ASYM_PAUSE; 4449 mii_adv |= PHY_BCM542XX_MII_ANA_PAUSE; 4450 } 4451 } 4452 } 4453 4454 SOC_IF_ERROR_RETURN 4455 (PHY_WRITE_BCM542XX_MII_ANAr(unit, pc, mii_adv)); 4456 SOC_IF_ERROR_RETURN 4457 (PHY_WRITE_BCM542XX_MII_GB_CTRLr(unit, pc, mii_gb_ctrl)); 4458 4459 /* EEE advertisement settings */ 4460 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 4461 uint16 eee_ability = 0; 4462 if (ability->eee & SOC_PA_EEE_10GB_BASET) { 4463 eee_ability |= PHY_BCM542XX_EEE_ADV_10G; 4464 } 4465 if (ability->eee & SOC_PA_EEE_1GB_BASET) { 4466 eee_ability |= PHY_BCM542XX_EEE_ADV_1000; 4467 } 4468 if (ability->eee & SOC_PA_EEE_100MB_BASETX) { 4469 eee_ability |= PHY_BCM542XX_EEE_ADV_100; 4470 } 4471 SOC_IF_ERROR_RETURN 4472 (PHY_MODIFY_BCM542XX_EEE_ADVr(unit, pc, eee_ability, 4473 PHY_BCM542XX_EEE_ADV_MASK)); 4474 } 4475 4476 /* update the PHY property software table (phy_ctrl_t) */ 4477 sal_memcpy( &(pc->copper.advert_ability), ability, 4478 sizeof(soc_port_ability_t) ); 4479 4480 } else if ( PHY_FIBER_MODE(unit, port) ) { 4481 mii_adv = PHY_BCM542XX_MII_ANA_C37_FD; /* Always advertise 1000X full duplex */ 4482 switch ( ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX) ) { 4483 case SOC_PA_PAUSE_TX: 4484 mii_adv |= PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE; 4485 break; 4486 case SOC_PA_PAUSE_RX: 4487 mii_adv |= (PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE | 4488 PHY_BCM542XX_MII_ANA_C37_PAUSE); 4489 break; 4490 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 4491 mii_adv |= PHY_BCM542XX_MII_ANA_C37_PAUSE; 4492 break; 4493 } 4494 /* Write to SerDes Auto-Neg Advertisement Reg */ 4495 SOC_IF_ERROR_RETURN 4496 (PHY_WRITE_BCM542XX_1000X_MII_ANAr(unit, pc, mii_adv)); 4497 4498 /* update the PHY property software table (phy_ctrl_t) */ 4499 sal_memcpy( &(pc->fiber.advert_ability), ability, 4500 sizeof(soc_port_ability_t) ); 4501 } else { 4502 return SOC_E_INTERNAL; 4503 } 4504 4505 LOG_INFO(BSL_LS_SOC_PHY, 4506 (BSL_META_U(unit, "phy_bcm542xx_adv_local_set: u=%d p=%d " 4507 "ability_hd_speed=0x%x, ability_fd_speed=0x%x, " 4508 "ability_pause=0x%x\n"), 4509 unit, port, ability->speed_half_duplex, ability->speed_full_duplex, 4510 ability->pause)); 4511 return ( SOC_E_NONE ); 4512 } 4513 4514 /* 4515 * Function: 4516 * phy_bcm542xx_ability_advert_get 4517 * Purpose: 4518 * Get the current advertisement for auto-negotiation. 4519 * Parameters: 4520 * unit - StrataSwitch unit #. 4521 * port - StrataSwitch port #. 4522 * mode - (OUT) Port mode mask indicating supported options/speeds. 4523 * Returns: 4524 * SOC_E_XXX 4525 * Notes: 4526 * The advertisement is retrieved for the ACTIVE medium. 4527 * No synchronization performed at this level. 4528 */ 4529 4530 STATIC int 4531 phy_bcm542xx_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability) 4532 { 4533 phy_ctrl_t *pc; 4534 uint16 mii_ana, mii_gb_ctrl, mii_adv; 4535 4536 if ( NULL == ability ) { 4537 return SOC_E_PARAM; 4538 } 4539 sal_memset(ability, 0, sizeof(soc_port_ability_t)); /* zero initialize */ 4540 4541 pc = EXT_PHY_SW_STATE(unit, port); 4542 4543 if ( PHY_COPPER_MODE(unit, port) ) { 4544 SOC_IF_ERROR_RETURN 4545 (PHY_READ_BCM542XX_MII_ANAr(unit, pc,&mii_ana)); 4546 SOC_IF_ERROR_RETURN 4547 (PHY_READ_BCM542XX_MII_GB_CTRLr(unit, pc,&mii_gb_ctrl)); 4548 4549 if ( mii_ana & PHY_BCM542XX_MII_ANA_HD_10 ) { 4550 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 4551 } 4552 if ( mii_ana & PHY_BCM542XX_MII_ANA_FD_10 ) { 4553 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 4554 } 4555 if ( mii_ana & PHY_BCM542XX_MII_ANA_HD_100 ) { 4556 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 4557 } 4558 if ( mii_ana & PHY_BCM542XX_MII_ANA_FD_100 ) { 4559 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 4560 } 4561 4562 if ( mii_ana & PHY_BCM542XX_MII_ANA_ASYM_PAUSE ) { 4563 if ( mii_ana & PHY_BCM542XX_MII_ANA_PAUSE ) { 4564 ability->pause |= SOC_PA_PAUSE_RX; 4565 } else { 4566 ability->pause |= SOC_PA_PAUSE_TX; 4567 } 4568 } else if (mii_ana & PHY_BCM542XX_MII_ANA_PAUSE ) { 4569 ability->pause |= SOC_PA_PAUSE; 4570 } 4571 4572 /* GE Specific values */ 4573 if ( mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000FD ) { 4574 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 4575 } 4576 if ( mii_gb_ctrl & PHY_BCM542XX_MII_GB_CTRL_ADV_1000HD ) { 4577 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 4578 } 4579 /* EEE advertisement settings */ 4580 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 4581 uint16 eee_ability; 4582 SOC_IF_ERROR_RETURN 4583 (PHY_READ_BCM542XX_EEE_ADVr(unit, pc, &eee_ability)); 4584 if (eee_ability & PHY_BCM542XX_EEE_ADV_10G) { 4585 ability->eee |= SOC_PA_EEE_10GB_BASET; 4586 } 4587 if (eee_ability & PHY_BCM542XX_EEE_ADV_1000) { 4588 ability->eee |= SOC_PA_EEE_1GB_BASET; 4589 } 4590 if (eee_ability & PHY_BCM542XX_EEE_ADV_100) { 4591 ability->eee |= SOC_PA_EEE_100MB_BASETX; 4592 } 4593 } 4594 4595 } else if ( PHY_FIBER_MODE(unit, port) ) { 4596 SOC_IF_ERROR_RETURN( 4597 PHY_READ_BCM542XX_1000X_MII_ANAr(unit, pc,&mii_adv) ); 4598 4599 if ( mii_adv & PHY_BCM542XX_MII_ANA_C37_FD ) { 4600 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 4601 } 4602 if ( mii_adv & PHY_BCM542XX_MII_ANA_C37_HD ) { 4603 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 4604 } 4605 4606 switch ( mii_adv & (PHY_BCM542XX_MII_ANA_C37_PAUSE | 4607 PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE) ) { 4608 case PHY_BCM542XX_MII_ANA_C37_PAUSE: 4609 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 4610 break; 4611 case PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE: 4612 ability->pause = SOC_PA_PAUSE_TX; 4613 break; 4614 case (PHY_BCM542XX_MII_ANA_C37_PAUSE | PHY_BCM542XX_MII_ANA_C37_ASYM_PAUSE): 4615 ability->pause = SOC_PA_PAUSE_RX; 4616 break; 4617 } 4618 4619 } else { 4620 return SOC_E_INTERNAL; 4621 } 4622 4623 LOG_INFO(BSL_LS_SOC_PHY, 4624 (BSL_META_U(unit, "phy_bcm542xx_adv_local_get: u=%d p=%d " 4625 "ability_hd_speed=0x%x, ability_fd_speed=0x%x, " 4626 "ability_pause=0x%x\n"), 4627 unit, port, ability->speed_half_duplex, 4628 ability->speed_full_duplex, ability->pause)); 4629 return ( SOC_E_NONE ); 4630 } 4631 4632 /* 4633 * Function: 4634 * phy_bcm542xx0_ability_remote_get 4635 * Purpose: 4636 * Get partners current advertisement for auto-negotiation. 4637 * Parameters: 4638 * unit - StrataSwitch unit #. 4639 * port - StrataSwitch port #. 4640 * mode - (OUT) Port mode mask indicating supported options/speeds. 4641 * Returns: 4642 * SOC_E_XXX 4643 * Notes: 4644 * The remote advertisement is retrieved for the ACTIVE medium. 4645 * No synchronization performed at this level. If Autonegotiation is 4646 * disabled or in progress, this routine will return an error. 4647 */ 4648 4649 STATIC int 4650 phy_bcm542xx_ability_remote_get(int unit, soc_port_t port, 4651 soc_port_ability_t *ability) 4652 { 4653 phy_ctrl_t *pc; 4654 uint16 mii_stat, mii_anp, mii_gb_stat; 4655 uint16 eee_resolution; 4656 4657 if (NULL == ability) { 4658 return SOC_E_PARAM; 4659 } 4660 4661 sal_memset(ability, 0, sizeof(soc_port_ability_t)); /*zero init*/ 4662 pc = EXT_PHY_SW_STATE(unit, port); 4663 4664 if ( PHY_COPPER_MODE(unit, port) ) { 4665 SOC_IF_ERROR_RETURN 4666 (PHY_READ_BCM542XX_MII_STATr(unit, pc,&mii_stat)); 4667 4668 if ( ! (mii_stat & PHY_BCM542XX_MII_STAT_AN_DONE) ) { 4669 return SOC_E_NONE; 4670 } 4671 4672 SOC_IF_ERROR_RETURN 4673 (PHY_READ_BCM542XX_MII_ANPr(unit, pc,&mii_anp)); 4674 SOC_IF_ERROR_RETURN 4675 (PHY_READ_BCM542XX_MII_GB_STATr(unit, pc,&mii_gb_stat)); 4676 4677 if ( mii_anp & PHY_BCM542XX_MII_ANA_HD_10 ) { 4678 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 4679 } 4680 if ( mii_anp & PHY_BCM542XX_MII_ANA_FD_10 ) { 4681 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 4682 } 4683 if ( mii_anp & PHY_BCM542XX_MII_ANA_HD_100 ) { 4684 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 4685 } 4686 if ( mii_anp & PHY_BCM542XX_MII_ANA_FD_100 ) { 4687 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 4688 } 4689 if ( mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000HD ) { 4690 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 4691 } 4692 if ( mii_gb_stat & PHY_BCM542XX_MII_GB_STAT_LP_1000FD ) { 4693 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 4694 } 4695 4696 if ( mii_anp & PHY_BCM542XX_MII_ANA_ASYM_PAUSE ) { 4697 if ( mii_anp & PHY_BCM542XX_MII_ANA_PAUSE ) { 4698 ability->pause |= SOC_PA_PAUSE_RX; 4699 } else { 4700 ability->pause |= SOC_PA_PAUSE_TX; 4701 } 4702 } else { 4703 if ( mii_anp & PHY_BCM542XX_MII_ANA_PAUSE ) { 4704 ability->pause |= SOC_PA_PAUSE; 4705 } 4706 } 4707 4708 /* EEE settings */ 4709 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 4710 SOC_IF_ERROR_RETURN 4711 (PHY_READ_BCM542XX_EEE_RESOLUTION_STATr(unit, pc,&eee_resolution)); 4712 if ( eee_resolution & 0x04 ) { 4713 ability->eee |= SOC_PA_EEE_1GB_BASET; 4714 } 4715 if ( eee_resolution & 0x02 ) { 4716 ability->eee |= SOC_PA_EEE_100MB_BASETX; 4717 } 4718 } 4719 4720 } else if ( PHY_FIBER_MODE(unit, port) ) { 4721 SOC_IF_ERROR_RETURN 4722 (PHY_READ_BCM542XX_1000X_MII_ANPr(unit, pc,&mii_anp)); 4723 if ( mii_anp & PHY_BCM542XX_MII_ANP_SGMII_MODE ) { /* Link partner is SGMII master */ 4724 if ( mii_anp & PHY_BCM542XX_MII_ANP_SGMII_FD ) { /* Full Duplex */ 4725 switch(mii_anp & PHY_BCM542XX_MII_ANP_SGMII_SS_MASK) { 4726 case PHY_BCM542XX_MII_ANP_SGMII_SS_10: 4727 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 4728 break; 4729 case PHY_BCM542XX_MII_ANP_SGMII_SS_100: 4730 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 4731 break; 4732 case PHY_BCM542XX_MII_ANP_SGMII_SS_1000: 4733 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 4734 break; 4735 } 4736 } else { /* Half duplex */ 4737 switch(mii_anp & PHY_BCM542XX_MII_ANP_SGMII_SS_MASK) { 4738 case PHY_BCM542XX_MII_ANP_SGMII_SS_10: 4739 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 4740 break; 4741 case PHY_BCM542XX_MII_ANP_SGMII_SS_100: 4742 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 4743 break; 4744 case PHY_BCM542XX_MII_ANP_SGMII_SS_1000: 4745 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 4746 break; 4747 } 4748 } 4749 4750 } else { 4751 if ( mii_anp & PHY_BCM542XX_MII_ANP_C37_FD ) { 4752 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 4753 } 4754 if ( mii_anp & PHY_BCM542XX_MII_ANP_C37_HD ) { 4755 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 4756 } 4757 4758 switch ( mii_anp & (PHY_BCM542XX_MII_ANP_C37_PAUSE | 4759 PHY_BCM542XX_MII_ANP_C37_ASYM_PAUSE) ) { 4760 case PHY_BCM542XX_MII_ANP_C37_PAUSE: 4761 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 4762 break; 4763 case PHY_BCM542XX_MII_ANP_C37_ASYM_PAUSE: 4764 ability->pause = SOC_PA_PAUSE_TX; 4765 break; 4766 case (PHY_BCM542XX_MII_ANP_C37_PAUSE | PHY_BCM542XX_MII_ANP_C37_ASYM_PAUSE): 4767 ability->pause = SOC_PA_PAUSE_RX; 4768 break; 4769 } 4770 } 4771 4772 } else { 4773 return SOC_E_INTERNAL; 4774 } 4775 4776 LOG_INFO(BSL_LS_SOC_PHY, 4777 (BSL_META_U(unit, "phy_bcm542xx_adv_remote_get: u=%d p=%d " 4778 "ability_hd_speed=0x%x ability_fd_speed=0x%x " 4779 "ability_pause=0x%x\n"), 4780 unit, port, ability->speed_half_duplex, 4781 ability->speed_full_duplex, ability->pause)); 4782 return ( SOC_E_NONE ); 4783 } 4784 4785 4786 /* 4787 * Function: 4788 * phy_bcm542xx_ability_local_get 4789 * Purpose: 4790 * Get the abilities of the local gigabit PHY. 4791 * Parameters: 4792 * unit - StrataSwitch unit #. 4793 * port - StrataSwitch port #. 4794 * mode - (OUT) Port mode mask indicating supported options/speeds. 4795 * Returns: 4796 * SOC_E_NONE 4797 * Notes: 4798 * The ability is retrieved only for the ACTIVE medium. 4799 */ 4800 4801 STATIC int 4802 phy_bcm542xx_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 4803 { 4804 phy_ctrl_t *pc; 4805 4806 if (NULL == ability) { 4807 return SOC_E_PARAM; 4808 } 4809 pc = EXT_PHY_SW_STATE(unit, port); 4810 sal_memset(ability, 0, sizeof(soc_port_ability_t)); /* zero initialize */ 4811 4812 if ( PHY_COPPER_MODE(unit, port) ) { 4813 ability->speed_half_duplex = SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB; 4814 ability->speed_full_duplex = SOC_PA_SPEED_1000MB | 4815 SOC_PA_SPEED_100MB | 4816 SOC_PA_SPEED_10MB; 4817 4818 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 4819 ability->interface = SOC_PA_INTF_SGMII; 4820 ability->medium = SOC_PA_MEDIUM_COPPER; 4821 ability->loopback = SOC_PA_LB_PHY; 4822 ability->flags = SOC_PA_AUTONEG; 4823 4824 /* EEE settings */ 4825 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 4826 ability->eee |= SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX; 4827 } 4828 4829 if ( pc->automedium ) { 4830 ability->flags |= SOC_PA_COMBO; 4831 } 4832 } else if ( PHY_FIBER_MODE(unit, port) ) { 4833 ability->speed_half_duplex = SOC_PA_SPEED_100MB; 4834 ability->speed_full_duplex = SOC_PA_SPEED_1000MB |SOC_PA_SPEED_100MB; 4835 4836 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 4837 ability->interface = SOC_PA_INTF_SGMII; 4838 ability->medium = SOC_PA_MEDIUM_FIBER; 4839 ability->loopback = SOC_PA_LB_PHY; 4840 ability->flags = SOC_PA_AUTONEG; 4841 4842 if ( pc->automedium ) { 4843 ability->flags |= SOC_PA_COMBO; 4844 } 4845 4846 } else { 4847 return SOC_E_INTERNAL; 4848 } 4849 4850 LOG_INFO(BSL_LS_SOC_PHY, 4851 (BSL_META_U(unit, "phy_bcm542xx_ability_local_get: u=%d p=%d " 4852 "ability_hd_speed=0x%x, ability_fd_speed=0x%x, " 4853 "ability_pause=0x%x\n"), 4854 unit, port, ability->speed_half_duplex, 4855 ability->speed_full_duplex, ability->pause)); 4856 return ( SOC_E_NONE ); 4857 } 4858 4859 /* 4860 * Function: 4861 * phy_bcm542xx_lb_set 4862 * Purpose: 4863 * Set the local PHY loopback mode. 4864 * Parameters: 4865 * unit - StrataSwitch unit #. 4866 * port - StrataSwitch port #. 4867 * loopback - Boolean: true = enable loopback, false = disable. 4868 * Returns: 4869 * SOC_E_XXX 4870 * Notes: 4871 * The loopback mode is set only for the ACTIVE medium. 4872 * No synchronization performed at this level. 4873 */ 4874 4875 STATIC int 4876 phy_bcm542xx_lb_set(int unit, soc_port_t port, int enable) 4877 { 4878 int rv = SOC_E_NONE; 4879 phy_ctrl_t *pc; 4880 uint16 mii_ctrl, temp16; 4881 pc = EXT_PHY_SW_STATE(unit, port); 4882 PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc); 4883 4884 if ( PHY_COPPER_MODE(unit, port) ) { 4885 #if AUTO_MDIX_WHEN_AN_DIS 4886 { 4887 /* Disable Auto-MDIX When autoneg disabled */ 4888 /* Enable Auto-MDIX When autoneg disabled */ 4889 temp16 = (enable) ? 0x0000 : PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE; 4890 PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc, temp16, 4891 PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE); 4892 } 4893 #endif 4894 /* Set loopback setting for 1G/100M/10M */ 4895 SOC_IF_ERROR_RETURN( PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) ); 4896 mii_ctrl &= ~PHY_BCM542XX_MII_CTRL_LPBK_EN; 4897 mii_ctrl |= (enable) ? PHY_BCM542XX_MII_CTRL_LPBK_EN : 0; 4898 SOC_IF_ERROR_RETURN( 4899 PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, mii_ctrl) ); 4900 /* Force link is required for 100/10M speeds to work in loopback */ 4901 phy_bcm542xx_direct_reg_modify(unit, pc, 4902 PHY_BCM542XX_TEST1_REG_OFFSET, 4903 (enable) ? PHY_BCM542XX_TEST1_REG_FORCE_LINK : 0, 4904 PHY_BCM542XX_TEST1_REG_FORCE_LINK); 4905 4906 } else if ( PHY_FIBER_MODE(unit, port) ) { 4907 temp16 = (enable) ? PHY_BCM542XX_1000BASE_X_CTRL_REG_LE : 0; 4908 rv = PHY_MODIFY_BCM542XX_1000X_MII_CTRLr(unit, pc, temp16, 4909 PHY_BCM542XX_1000BASE_X_CTRL_REG_LE); 4910 4911 if (enable && SOC_SUCCESS(rv) ) { 4912 uint16 stat; 4913 int link; 4914 soc_timeout_t to; 4915 4916 /* Wait up to 5000 msec for link up */ 4917 soc_timeout_init(&to, 5000000, 0); 4918 link = 0; 4919 while ( ! soc_timeout_check(&to) ) { 4920 rv = PHY_READ_BCM542XX_1000X_MII_STATr(unit, pc,&stat); 4921 link = stat & PHY_BCM542XX_1000BASE_X_STAT_REG_LA; 4922 if ( link || SOC_FAILURE(rv) ) { 4923 break; 4924 } 4925 } 4926 if ( ! link ) { 4927 LOG_WARN(BSL_LS_SOC_PHY, 4928 (BSL_META_U(unit, 4929 "phy_bcm542xx_lb_set: u=%d p=%d TIMEOUT\n"), 4930 unit, port)); 4931 4932 rv = SOC_E_TIMEOUT; 4933 } 4934 } 4935 4936 } else { 4937 return SOC_E_INTERNAL; 4938 } 4939 4940 LOG_INFO(BSL_LS_SOC_PHY, 4941 (BSL_META_U(unit, "phy_bcm542xx_lb_set: u=%d p=%d en=%d rv=%d\n"), 4942 unit, port, enable, rv)); 4943 return rv; 4944 } 4945 4946 /* 4947 * Function: 4948 * phy_bcm542xx_lb_get 4949 * Purpose: 4950 * Get the local PHY loopback mode. 4951 * Parameters: 4952 * unit - StrataSwitch unit #. 4953 * port - StrataSwitch port #. 4954 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 4955 * Returns: 4956 * SOC_E_XXX 4957 * Notes: 4958 * The loopback mode is retrieved for the ACTIVE medium. 4959 */ 4960 STATIC int 4961 phy_bcm542xx_lb_get(int unit, soc_port_t port, int *enable) 4962 { 4963 uint16 mii_ctrl; 4964 phy_ctrl_t *pc; 4965 4966 pc = EXT_PHY_SW_STATE(unit, port); 4967 4968 if ( PHY_COPPER_MODE(unit, port) ) { 4969 SOC_IF_ERROR_RETURN( 4970 PHY_READ_BCM542XX_MII_CTRLr(unit, pc,&mii_ctrl) ); 4971 *enable = (mii_ctrl & PHY_BCM542XX_MII_CTRL_LPBK_EN) ? 1 : 0; 4972 } else if ( PHY_FIBER_MODE(unit, port) ) { 4973 SOC_IF_ERROR_RETURN( 4974 PHY_READ_BCM542XX_1000X_MII_CTRLr(unit, pc,&mii_ctrl) ); 4975 *enable = (mii_ctrl & PHY_BCM542XX_1000BASE_X_CTRL_REG_LE) ? 1 : 0; 4976 } else { 4977 return SOC_E_INTERNAL; 4978 } 4979 4980 return ( SOC_E_NONE ); 4981 } 4982 4983 /* 4984 * Function: 4985 * phy_bcm542xx_interface_set 4986 * Purpose: 4987 * Set the current operating mode of the PHY. 4988 * Parameters: 4989 * unit - StrataSwitch unit #. 4990 * port - StrataSwitch port #. 4991 * pif - one of SOC_PORT_IF_* 4992 * Returns: 4993 * SOC_E_NONE - success 4994 * SOC_E_UNAVAIL - unsupported interface 4995 */ 4996 4997 STATIC int 4998 phy_bcm542xx_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 4999 { 5000 COMPILER_REFERENCE(unit); 5001 COMPILER_REFERENCE(port); 5002 5003 switch (pif) { 5004 case SOC_PORT_IF_QSGMII: 5005 case SOC_PORT_IF_SGMII: 5006 case SOC_PORT_IF_GMII: 5007 case SOC_PORT_IF_RGMII: 5008 return SOC_E_NONE; 5009 default: 5010 return SOC_E_UNAVAIL; 5011 } 5012 } 5013 5014 /* 5015 * Function: 5016 * phy_bcm542xx_interface_get 5017 * Purpose: 5018 * Get the current operating mode of the PHY. 5019 * Parameters: 5020 * unit - StrataSwitch unit #. 5021 * port - StrataSwitch port #. 5022 * pif - (OUT) one of SOC_PORT_IF_* 5023 * Returns: 5024 * SOC_E_NONE 5025 */ 5026 5027 STATIC int 5028 phy_bcm542xx_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 5029 { 5030 COMPILER_REFERENCE(unit); 5031 COMPILER_REFERENCE(port); 5032 5033 if ( IS_GMII_PORT(unit, port) ) { 5034 *pif = SOC_PORT_IF_GMII; 5035 } else { 5036 *pif = SOC_PORT_IF_SGMII; 5037 } 5038 return SOC_E_NONE; 5039 } 5040 5041 5042 /* 5043 * Function: 5044 * phy_bcm542xx_mdix_set 5045 * Description: 5046 * Set the Auto-MDIX mode of a port/PHY 5047 * Parameters: 5048 * unit - Device number 5049 * port - Port number 5050 * mode - One of: 5051 * SOC_PORT_MDIX_AUTO 5052 * Enable auto-MDIX when autonegotiation is enabled 5053 * SOC_PORT_MDIX_FORCE_AUTO 5054 * Enable auto-MDIX always 5055 * SOC_PORT_MDIX_NORMAL 5056 * Disable auto-MDIX 5057 * SOC_PORT_MDIX_XOVER 5058 * Disable auto-MDIX, and swap cable pairs 5059 * Return Value: 5060 * SOC_E_XXX 5061 */ 5062 STATIC int 5063 phy_bcm542xx_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode) 5064 { 5065 int rv = SOC_E_NONE; 5066 phy_ctrl_t *pc; 5067 int speed = 0; 5068 5069 pc = EXT_PHY_SW_STATE(unit, port); 5070 PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc); 5071 5072 if ( PHY_COPPER_MODE(unit, port) ) { 5073 switch( mode ) { 5074 case SOC_PORT_MDIX_AUTO: 5075 /* Clear bit 14 for automatic MDI crossover */ 5076 SOC_IF_ERROR_RETURN( 5077 PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc, 0, 5078 PHY_BCM542XX_MII_ECR_DAMC) ); 5079 /* Clear bit 9 to disable forced auto MDI xover */ 5080 SOC_IF_ERROR_RETURN( 5081 PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc, 0, 5082 PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE) ); 5083 break; 5084 case SOC_PORT_MDIX_FORCE_AUTO: 5085 /* Clear bit 14 for automatic MDI crossover */ 5086 SOC_IF_ERROR_RETURN( 5087 PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc, 0, 5088 PHY_BCM542XX_MII_ECR_DAMC) ); 5089 5090 /* Set bit 9 to enable forced auto MDI xover */ 5091 SOC_IF_ERROR_RETURN( 5092 PHY_MODIFY_BCM542XX_MII_MISC_CTRLr(unit, pc, 5093 PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE, 5094 PHY_BCM542XX_MII_FORCE_AUTO_MDIX_MODE) ); 5095 break; 5096 case SOC_PORT_MDIX_NORMAL: 5097 rv = phy_bcm542xx_speed_get(unit, port, &speed); 5098 if (SOC_FAILURE(rv) ) { 5099 return SOC_E_FAIL; 5100 } 5101 if (speed == 0 || speed == 10 || speed == 100) { 5102 /* Set bit 14 for automatic MDI crossover */ 5103 SOC_IF_ERROR_RETURN( 5104 PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc, 5105 PHY_BCM542XX_MII_ECR_DAMC, 5106 PHY_BCM542XX_MII_ECR_DAMC) ); 5107 SOC_IF_ERROR_RETURN( 5108 PHY_WRITE_BCM542XX_TEST1r(unit, pc, 0)); 5109 } else { 5110 return SOC_E_UNAVAIL; 5111 } 5112 break; 5113 case SOC_PORT_MDIX_XOVER: 5114 rv = phy_bcm542xx_speed_get(unit, port, &speed); 5115 if (SOC_FAILURE(rv) ) { 5116 return SOC_E_FAIL; 5117 } 5118 if (speed == 0 || speed == 10 || speed == 100) { 5119 /* Set bit 14 for automatic MDI crossover */ 5120 SOC_IF_ERROR_RETURN( 5121 PHY_MODIFY_BCM542XX_MII_ECRr(unit, pc, 5122 PHY_BCM542XX_MII_ECR_DAMC, 5123 PHY_BCM542XX_MII_ECR_DAMC) ); 5124 SOC_IF_ERROR_RETURN( 5125 PHY_WRITE_BCM542XX_TEST1r(unit, pc, 0x0080)); 5126 } else { 5127 return SOC_E_UNAVAIL; 5128 } 5129 break; 5130 default : 5131 return SOC_E_CONFIG; 5132 } 5133 pc->copper.mdix = mode; 5134 5135 } else if ( PHY_FIBER_MODE(unit, port) ) { 5136 if ( mode != SOC_PORT_MDIX_NORMAL ) { 5137 return SOC_E_UNAVAIL; 5138 } 5139 5140 } else { 5141 return SOC_E_INTERNAL; 5142 } 5143 5144 return SOC_E_NONE; 5145 } 5146 5147 #if defined(BCM_WARM_BOOT_SUPPORT) 5148 /* 5149 * Function: 5150 * phy_542xx_mdix_wb_update 5151 * Description: 5152 * Read the hw, derive the mode and update the mdix mode in sw structure 5153 * during wb. 5154 * Parameters: 5155 * unit - (IN) Device number 5156 * port - (IN) Port number 5157 * mode - (OUT) :One of: 5158 * SOC_PORT_MDIX_AUTO 5159 * Enable auto-MDIX when autonegotiation is enabled 5160 * SOC_PORT_MDIX_FORCE_AUTO 5161 * Enable auto-MDIX always 5162 * SOC_PORT_MDIX_NORMAL 5163 * Disable auto-MDIX 5164 * SOC_PORT_MDIX_XOVER 5165 * Disable auto-MDIX, and swap cable pairs 5166 * Return Value: 5167 * SOC_E_XXX 5168 */ 5169 STATIC int 5170 phy_542xx_mdix_wb_update(int unit, soc_port_t port) 5171 { 5172 phy_ctrl_t *pc; 5173 int speed; 5174 int mode = 0; 5175 uint16 val = 0; 5176 5177 pc = EXT_PHY_SW_STATE(unit, port); 5178 5179 /* Check bit 14 for automatic MDI crossover */ 5180 SOC_IF_ERROR_RETURN (PHY_READ_BCM542XX_MII_ECRr(unit, pc, &val)); 5181 if(val & 0x4000) { 5182 SOC_IF_ERROR_RETURN(phy_bcm542xx_speed_get(unit, port, &speed)); 5183 if (speed == 0 || speed == 10 || speed == 100) { 5184 SOC_IF_ERROR_RETURN (PHY_READ_BCM542XX_TEST1r(unit, pc, &val)); 5185 if (0 == val) { 5186 mode = SOC_PORT_MDIX_NORMAL; 5187 } else if (0x80 == val) { 5188 mode = SOC_PORT_MDIX_XOVER; 5189 } else { 5190 return SOC_E_UNAVAIL; 5191 } 5192 } else { 5193 return SOC_E_UNAVAIL; 5194 } 5195 } else { 5196 /* Check bit 9 forced auto MDI xover */ 5197 SOC_IF_ERROR_RETURN (PHY_READ_BCM542XX_MII_MISC_CTRLr(unit, pc,&val)); 5198 if (val & 0x200) { 5199 /* bit 9 Set, forced auto MDI xover */ 5200 mode = SOC_PORT_MDIX_FORCE_AUTO; 5201 } else { 5202 /* bit 9 Clear, forced auto MDI xover */ 5203 mode = SOC_PORT_MDIX_AUTO; 5204 } 5205 } 5206 pc->copper.mdix = mode; 5207 5208 return SOC_E_NONE; 5209 } 5210 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */ 5211 5212 5213 /* 5214 * Function: 5215 * phy_bcm542xx_mdix_get 5216 * Description: 5217 * Get the Auto-MDIX mode of a port/PHY 5218 * Parameters: 5219 * unit - Device number 5220 * port - Port number 5221 * mode - (Out) One of: 5222 * SOC_PORT_MDIX_AUTO 5223 * Enable auto-MDIX when autonegotiation is enabled 5224 * SOC_PORT_MDIX_FORCE_AUTO 5225 * Enable auto-MDIX always 5226 * SOC_PORT_MDIX_NORMAL 5227 * Disable auto-MDIX 5228 * SOC_PORT_MDIX_XOVER 5229 * Disable auto-MDIX, and swap cable pairs 5230 * Return Value: 5231 * SOC_E_XXX 5232 */ 5233 STATIC int 5234 phy_bcm542xx_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode) 5235 { 5236 phy_ctrl_t *pc; 5237 int speed = 0; 5238 5239 if ( mode == NULL ) { 5240 return SOC_E_PARAM; 5241 } 5242 5243 #if defined(BCM_WARM_BOOT_SUPPORT) 5244 if (SOC_WARM_BOOT(unit)) { 5245 return phy_542xx_mdix_wb_update(unit, port); 5246 } 5247 #endif /* defined(BCM_WARM_BOOT_SUPPORT) */ 5248 5249 pc = EXT_PHY_SW_STATE(unit, port); 5250 5251 if ( PHY_COPPER_MODE(unit, port) ) { 5252 SOC_IF_ERROR_RETURN(phy_bcm542xx_speed_get(unit, port, &speed)); 5253 if (speed == 1000) { 5254 *mode = SOC_PORT_MDIX_AUTO; 5255 } else { 5256 *mode = pc->copper.mdix; 5257 } 5258 } else { 5259 *mode = SOC_PORT_MDIX_NORMAL; 5260 } 5261 5262 return SOC_E_NONE; 5263 } 5264 5265 /* 5266 * Function: 5267 * phy_bcm542xx_mdix_status_get 5268 * Description: 5269 * Get the current MDIX status on a port/PHY 5270 * Parameters: 5271 * unit - Device number 5272 * port - Port number 5273 * status - (OUT) One of: 5274 * SOC_PORT_MDIX_STATUS_NORMAL 5275 * Straight connection 5276 * SOC_PORT_MDIX_STATUS_XOVER 5277 * Crossover has been performed 5278 * Return Value: 5279 * SOC_E_XXX 5280 */ 5281 STATIC int 5282 phy_bcm542xx_mdix_status_get(int unit, soc_port_t port, 5283 soc_port_mdix_status_t *status) 5284 { 5285 phy_ctrl_t *pc; 5286 uint16 mii_esrr; 5287 5288 if ( status == NULL ) { 5289 return SOC_E_PARAM; 5290 } 5291 pc = EXT_PHY_SW_STATE(unit, port); 5292 5293 if ( PHY_COPPER_MODE(unit, port) ) { 5294 SOC_IF_ERROR_RETURN 5295 (phy_bcm542xx_direct_reg_read(unit, pc, 5296 PHY_BCM542XX_PHY_EXT_STATUS_REG_OFFSET, 5297 &mii_esrr)); 5298 if ( mii_esrr & 0x2000 ) { 5299 *status = SOC_PORT_MDIX_STATUS_XOVER; 5300 } else { 5301 *status = SOC_PORT_MDIX_STATUS_NORMAL; 5302 } 5303 5304 } else if ( PHY_FIBER_MODE(unit, port) ) { 5305 *status = SOC_PORT_MDIX_STATUS_NORMAL; 5306 5307 } else { 5308 return SOC_E_INTERNAL; 5309 } 5310 5311 return SOC_E_NONE; 5312 } 5313 5314 /* 5315 * Function: 5316 * phy_bcm542xx_encode_gmode 5317 * Purpose: 5318 * Global synchronization mode selection 5319 * P1588 NSE DPLL NCO Register 6, RDB.0xA7F[15:14] GMODE 5320 * Parameters: 5321 * 5322 * Returns: 5323 */ 5324 void phy_bcm542xx_encode_gmode(soc_port_phy_timesync_global_mode_t mode, 5325 uint16 *value) 5326 { 5327 switch ( mode ) { 5328 case SOC_PORT_PHY_TIMESYNC_MODE_FREE: 5329 *value = 0x1; 5330 break; 5331 case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN: 5332 *value = 0x2; 5333 break; 5334 case SOC_PORT_PHY_TIMESYNC_MODE_CPU: 5335 *value = 0x3; 5336 break; 5337 default: 5338 break; 5339 } 5340 } 5341 5342 /* 5343 * Function: 5344 * phy_bcm542xx_decode_gmode 5345 * Purpose: 5346 * Global synchronization mode selection 5347 * P1588 NSE DPLL NCO Register 6, RDB.0xA7F[15:14] GMODE 5348 * Parameters: 5349 * 5350 * Returns: 5351 */ 5352 void phy_bcm542xx_decode_gmode(uint16 value, 5353 soc_port_phy_timesync_global_mode_t *mode) 5354 { 5355 switch ( value & 0x3 ) { 5356 case 0x1: 5357 *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 5358 break; 5359 case 0x2: 5360 *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN; 5361 break; 5362 case 0x3: 5363 *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU; 5364 break; 5365 default: 5366 break; 5367 } 5368 } 5369 5370 /* 5371 * Function: 5372 * phy_bcm542xx_encode_framesync_mode 5373 * Purpose: 5374 * FrameSync mode selection 5375 * P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE 5376 * Parameters: 5377 * 5378 * Returns: 5379 */ 5380 void phy_bcm542xx_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode, 5381 uint16 *value) 5382 { 5383 switch ( mode & 0xf ) { 5384 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0: 5385 *value = BIT(0); 5386 break; 5387 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1: 5388 *value = BIT(1); 5389 break; 5390 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT: 5391 *value = BIT(2); 5392 break; 5393 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU: 5394 *value = BIT(3); 5395 break; 5396 default: 5397 *value = 0; 5398 break; 5399 } 5400 } 5401 5402 /* 5403 * Function: 5404 * phy_bcm542xx_decode_framesync_mode 5405 * Purpose: 5406 * FrameSync mode selection 5407 * P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE 5408 * Parameters: 5409 * 5410 * Returns: 5411 */ 5412 void phy_bcm542xx_decode_framesync_mode(uint16 value, 5413 soc_port_phy_timesync_framesync_mode_t *mode) 5414 { 5415 switch ( value & 0xf ) { 5416 case BIT(0): 5417 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0; 5418 break; 5419 case BIT(1): 5420 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1; 5421 break; 5422 case BIT(2): 5423 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT; 5424 break; 5425 case BIT(3): 5426 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU; 5427 break; 5428 default: 5429 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE; 5430 break; 5431 } 5432 } 5433 5434 5435 /* 5436 * Function: 5437 * phy_bcm542xx_encode_sync_out_mode 5438 * Purpose: 5439 * Sync_Out mode selection 5440 * P1588 NSE DPLL NCO Register 6, RDB.0xA7F[1:0] SYNC_OUT_MODE 5441 * Parameters: 5442 * 5443 * Returns: 5444 */ 5445 void phy_bcm542xx_encode_sync_out_mode(soc_port_phy_timesync_syncout_mode_t mode, 5446 uint16 *value) 5447 { 5448 switch ( mode ) { 5449 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE: 5450 *value = 0x0; 5451 break; 5452 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME: 5453 *value = 0x1; 5454 break; 5455 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN: 5456 *value = 0x2; 5457 break; 5458 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC: 5459 *value = 0x3; 5460 break; 5461 default: 5462 break; 5463 } 5464 } 5465 5466 5467 /* 5468 * Function: 5469 * phy_bcm542xx_decode_sync_out_mode 5470 * Purpose: 5471 * Sync_Out mode selection 5472 * P1588 NSE DPLL NCO Register 6, RDB.0xA7F[1:0] SYNC_OUT_MODE 5473 * Parameters: 5474 * 5475 * Returns: 5476 */ 5477 void phy_bcm542xx_decode_sync_out_mode(uint16 value, 5478 soc_port_phy_timesync_syncout_mode_t *mode) 5479 { 5480 switch ( value & 0x3 ) { 5481 case 0x0: 5482 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 5483 break; 5484 case 0x1: 5485 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME; 5486 break; 5487 case 0x2: 5488 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN; 5489 break; 5490 case 0x3: 5491 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC; 5492 break; 5493 } 5494 } 5495 5496 /* 5497 * Function: 5498 * phy_bcm542xx_encode_egress_message_mode 5499 * Purpose: 5500 * P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n) 5501 * for Message 0-3 ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) 5502 * Parameters: 5503 * 5504 * Returns: 5505 */ 5506 void phy_bcm542xx_encode_egress_message_mode( 5507 soc_port_phy_timesync_event_message_egress_mode_t mode, 5508 int offset, uint16 *value, uint16 *mask) 5509 { 5510 switch ( mode ) { 5511 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE: 5512 *value |= (0x0 << offset); 5513 break; 5514 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD: 5515 *value |= (0x1 << offset); 5516 break; 5517 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN: 5518 *value |= (0x2 << offset); 5519 break; 5520 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP: 5521 *value |= (0x3 << offset); 5522 break; 5523 default: 5524 break; 5525 } 5526 *mask |= 0x3 << offset; 5527 } 5528 5529 /* 5530 * Function: 5531 * phy_bcm542xx_decode_egress_message_mode 5532 * Purpose: 5533 * P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n) 5534 * for Message 0-3 ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) 5535 * Parameters: 5536 * 5537 * Returns: 5538 */ 5539 void phy_bcm542xx_decode_egress_message_mode(uint16 value, int offset, 5540 soc_port_phy_timesync_event_message_egress_mode_t *mode) 5541 { 5542 switch ( (value >> offset) & 0x3 ) { 5543 case 0x0: 5544 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE; 5545 break; 5546 case 0x1: 5547 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD; 5548 break; 5549 case 0x2: 5550 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN; 5551 break; 5552 case 0x3: 5553 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP; 5554 break; 5555 } 5556 } 5557 5558 /* 5559 * Function: 5560 * phy_bcm542xx_encode_ingress_message_mode 5561 * Purpose: 5562 * P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n) 5563 * for Message 0-3 ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) 5564 * Parameters: 5565 * 5566 * Returns: 5567 */ 5568 void phy_bcm542xx_encode_ingress_message_mode( 5569 soc_port_phy_timesync_event_message_ingress_mode_t mode, 5570 int offset, uint16 *value, uint16 *mask) 5571 { 5572 switch ( mode ) { 5573 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE: 5574 *value |= (0x0 << offset); 5575 break; 5576 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD: 5577 *value |= (0x1 << offset); 5578 break; 5579 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP: 5580 *value |= (0x2 << offset); 5581 break; 5582 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME: 5583 *value |= (0x3 << offset); 5584 break; 5585 default: 5586 break; 5587 } 5588 *mask |= 0x3 << offset; 5589 } 5590 5591 /* 5592 * Function: 5593 * phy_bcm542xx_decode_ingress_message_mode 5594 * Purpose: 5595 * P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n) 5596 * for Message 0-3 ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) 5597 * Parameters: 5598 * 5599 * Returns: 5600 */ 5601 void phy_bcm542xx_decode_ingress_message_mode(uint16 value, int offset, 5602 soc_port_phy_timesync_event_message_ingress_mode_t *mode) 5603 { 5604 switch ((value >> offset) & 0x3) { 5605 case 0x0: 5606 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE; 5607 break; 5608 case 0x1: 5609 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD; 5610 break; 5611 case 0x2: 5612 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP; 5613 break; 5614 case 0x3: 5615 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME; 5616 break; 5617 } 5618 } 5619 5620 /* 5621 * Function: 5622 * phy_bcm542xx_timesync_config_set 5623 * Purpose: 5624 * 5625 * Parameters: 5626 * 5627 * Returns: 5628 */ 5629 int 5630 phy_bcm542xx_timesync_config_set(int unit, soc_port_t port, 5631 soc_port_phy_timesync_config_t *conf) 5632 { 5633 uint16 dev_port = 0; 5634 uint16 rx_control_reg = 0, tx_control_reg = 0; 5635 uint16 en_control_reg = 0, tx_capture_en_reg = 0, rx_capture_en_reg = 0; 5636 uint16 nse_nco_6 = 0, nse_nco_2c = 0, gmode =0, framesync_mode=0; 5637 uint16 syncout_mode=0, tx_ts_event_cap = 0, rx_ts_event_cap = 0; 5638 uint16 mpls_control_reg_tx = 0, mpls_control_reg_rx = 0, i; 5639 uint16 data16 = 0, mask16 = 0; 5640 phy_ctrl_t *pc; 5641 5642 if ( NULL == conf ) { 5643 return SOC_E_PARAM; 5644 } 5645 5646 pc = EXT_PHY_SW_STATE(unit, port); 5647 5648 /* Dev port numbers from 0-7 */ 5649 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 5650 5651 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 5652 of the device. For example to enable autogrEEEn on port0, 5653 rdb register for port 4 0x808 need to be used. 5654 Refer package configuration document. 5655 */ 5656 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 5657 dev_port += 4; 5658 } 5659 5660 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE ) { 5661 en_control_reg |= ( BIT(dev_port + 8) | BIT(dev_port) ); 5662 data16 = PHY_BCM542XX_EXPF5_TIME_SYNC_ENABLE; 5663 } else { 5664 data16 = 0; 5665 } 5666 /* CORE_EXPF5 - Time Sync control, RDB.0x0f5, bit[0] TIMESYNC_EN */ 5667 SOC_IF_ERROR_RETURN 5668 (PHY_MODIFY_BCM542XX_TIME_SYNC_CTRLr(unit, pc, data16, 5669 PHY_BCM542XX_EXPF5_TIME_SYNC_ENABLE)); 5670 5671 /* Enable TX SOP & RX SOP capability in 10bt. */ 5672 /* CORE_EXP45 - Pattern Generator Control, RDB.0x005, bit[12] TX_CRC_CHECKER_EN */ 5673 phy_bcm542xx_direct_reg_modify(unit, pc, 5674 PHY_BCM542XX_PATT_GEN_CTRL_REG_OFFSET, 5675 PHY_BCM542XX_PATT_GEN_CTRL_REG_TX_CRC_CHECK_EN, 5676 PHY_BCM542XX_PATT_GEN_CTRL_REG_TX_CRC_CHECK_EN); 5677 /* CORE_EXPF5 - Time Sync control, RDB.0x0f5, bit[8:7] */ 5678 phy_bcm542xx_direct_reg_modify(unit, pc, 5679 PHY_BCM542XX_EXPF5_TIME_SYNC_REG_OFFSET, 5680 PHY_BCM542XX_EXPF5_TIME_SYNC_TX_SOP_10BT_EN 5681 | PHY_BCM542XX_EXPF5_TIME_SYNC_RX_SOP_10BT_EN, 5682 PHY_BCM542XX_EXPF5_TIME_SYNC_TX_SOP_10BT_EN 5683 | PHY_BCM542XX_EXPF5_TIME_SYNC_RX_SOP_10BT_EN); 5684 5685 /*********************************************************************** 5686 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 5687 * To access TOP level registers use phy_id of port0. Override this ports 5688 */ 5689 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 5690 5691 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE ) { 5692 data16 = 0; 5693 } else { 5694 data16 = PHY_BCM542XX_TOP_INTERRUPT_MASK; 5695 } 5696 /* TOP_MISCREG_INTERRUPT_MASK, RDB.0x82d */ 5697 SOC_IF_ERROR_RETURN 5698 (phy_bcm542xx_direct_reg_modify(unit, pc, 5699 PHY_BCM542XX_TOP_INTERRUPT_MASK_OFFSET, data16, 5700 PHY_BCM542XX_TOP_INTERRUPT_MASK)); 5701 5702 /* Enable/disable 1588 tx/rx per port*/ 5703 phy_bcm542xx_direct_reg_modify(unit, pc, 5704 PHY_BCM542XX_TOP_1588_SLICE_EN_CTRL_REG_OFFSET, 5705 en_control_reg, en_control_reg); 5706 /* TOP_1588_SLICE_ENABLE, RDB.0xa10 */ 5707 phy_bcm542xx_direct_reg_read(unit, pc, 5708 PHY_BCM542XX_TOP_1588_SLICE_EN_CTRL_REG_OFFSET, 5709 &en_control_reg); 5710 5711 /* Enable TS capture + Select TS capture for event message type */ 5712 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE ) { 5713 tx_capture_en_reg |= BIT(dev_port); 5714 rx_capture_en_reg |= BIT(dev_port); 5715 5716 /* TOP_1588_NSE_NCO_6, RDB.0xa7f[12], Initialize NSE Block */ 5717 phy_bcm542xx_direct_reg_modify(unit, pc, 5718 PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, 5719 PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN, 5720 PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN); 5721 5722 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE ) { 5723 tx_ts_event_cap |= BIT(8); 5724 } 5725 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE ) { 5726 rx_ts_event_cap |= BIT(8); 5727 } 5728 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE ) { 5729 tx_ts_event_cap |= BIT(9); 5730 } 5731 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE ) { 5732 rx_ts_event_cap |= BIT(9); 5733 } 5734 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE ) { 5735 tx_ts_event_cap |= BIT(10); 5736 } 5737 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE ) { 5738 rx_ts_event_cap |= BIT(10); 5739 } 5740 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE ) { 5741 tx_ts_event_cap |= BIT(11); 5742 } 5743 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE ) { 5744 rx_ts_event_cap |= BIT(11); 5745 } 5746 } 5747 5748 /* Select TS capture for event message type */ 5749 /* TOP_1588_TX_PORT_n_TS_OFFSET_MSB, RDB.0xa35..., bit[11:8] */ 5750 phy_bcm542xx_direct_reg_modify(unit, pc, 5751 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 5752 tx_ts_event_cap, 5753 tx_ts_event_cap); 5754 /* TOP_1588_RX_PORT_n_TS_OFFSET_MSB, RDB.0xa45..., bit[11:8] */ 5755 phy_bcm542xx_direct_reg_modify(unit, pc, 5756 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 5757 rx_ts_event_cap, 5758 rx_ts_event_cap); 5759 5760 /* Timestamp capture enable for Rx & TX */ 5761 /* P1588 TX SOP Timestamp Capture Enable, RDB.0xa21 */ 5762 phy_bcm542xx_direct_reg_modify(unit, pc, 5763 PHY_BCM542XX_TOP_1588_TX_TS_CAP_REG_OFFSET, 5764 tx_capture_en_reg, 5765 BIT(dev_port)); 5766 /* P1588 RX SOP Timestamp Capture Enable, RDB.0xa22 */ 5767 phy_bcm542xx_direct_reg_modify(unit, pc, 5768 PHY_BCM542XX_TOP_1588_RX_TS_CAP_REG_OFFSET, 5769 rx_capture_en_reg, 5770 BIT(dev_port)); 5771 5772 /* Enable timestamp capture on the next frame sync event */ 5773 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE ) { 5774 nse_nco_6 |= PHY_BCM542XX_TOP_1588_NSE_NCO_6_TS_CAP; 5775 } 5776 /* P1588 NSE DPLL NCO Reg.6, RDB.0xa7f, bit[13] */ 5777 phy_bcm542xx_direct_reg_modify(unit, pc, 5778 PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, 5779 nse_nco_6, 5780 PHY_BCM542XX_TOP_1588_NSE_NCO_6_TS_CAP); 5781 5782 /* Enable the CRC check in PTP detection receiving side */ 5783 data16 = (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) 5784 ? PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_RX_CRC_EN : 0; 5785 /* P1588 Receive/Transmit Control, RDB.0xa62, bit[3] */ 5786 phy_bcm542xx_direct_reg_modify(unit, pc, 5787 PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_OFFSET, data16, 5788 PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_RX_CRC_EN); 5789 5790 /* Enable different packet detections & checks in Rx & Tx direction */ 5791 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE ) { 5792 rx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_AS_EN; 5793 tx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_AS_EN; 5794 } 5795 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE ) { 5796 rx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_L2_EN; 5797 tx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_L2_EN; 5798 } 5799 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE ) { 5800 rx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_IPV4_UDP_EN; 5801 tx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV4_UDP_EN; 5802 } 5803 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE ) { 5804 rx_control_reg |= PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV6_UDP_EN; 5805 tx_control_reg |= PHY_BCM542XX_TOP_1588_RX_CTL_REG_RX_IPV6_UDP_EN; 5806 } 5807 phy_bcm542xx_direct_reg_write(unit, pc, 5808 PHY_BCM542XX_TOP_1588_TX_CTL_REG_OFFSET, 5809 tx_control_reg); 5810 phy_bcm542xx_direct_reg_write(unit, pc, 5811 PHY_BCM542XX_TOP_1588_RX_CTL_REG_OFFSET, 5812 rx_control_reg); 5813 5814 /* Set input for NCO adder */ 5815 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 5816 nse_nco_2c &= ~PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL; 5817 } else { 5818 nse_nco_2c |= PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL; 5819 } 5820 5821 phy_bcm542xx_direct_reg_modify(unit, pc, 5822 PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET, 5823 nse_nco_2c, 5824 PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL); 5825 5826 5827 /* VLAN Tags */ 5828 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID ) { 5829 phy_bcm542xx_direct_reg_write(unit, pc, 5830 PHY_BCM542XX_TOP_1588_VLAN_ITPID_REG_OFFSET, 5831 conf->itpid); 5832 } 5833 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID ) { 5834 5835 phy_bcm542xx_direct_reg_write(unit, pc, 5836 PHY_BCM542XX_TOP_1588_VLAN_OTPID_REG_OFFSET, 5837 conf->otpid); 5838 } 5839 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2 ) { 5840 phy_bcm542xx_direct_reg_write(unit, pc, 5841 PHY_BCM542XX_TOP_1588_OTHER_OTPID_REG_OFFSET, 5842 conf->otpid2); 5843 } 5844 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER ) { 5845 phy_bcm542xx_direct_reg_write(unit, pc, 5846 PHY_BCM542XX_TOP_1588_NSE_NCO_4_REG_OFFSET, 5847 conf->ts_divider & 0xfff); 5848 } 5849 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY ) { 5850 phy_bcm542xx_direct_reg_write(unit, pc, 5851 PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_LSB(dev_port), 5852 conf->rx_link_delay & 0xffff); 5853 phy_bcm542xx_direct_reg_write(unit, pc, 5854 PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_MSB(dev_port), 5855 (conf->rx_link_delay>>16) & 0xffff); 5856 } 5857 5858 /* TIMECODE */ 5859 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE ) { 5860 /* P1588 Original Time Code Register 0-4 (80 bits), RDB.0xa54-a58 */ 5861 phy_bcm542xx_direct_reg_write(unit, pc, 5862 PHY_BCM542XX_TOP_1588_TIME_CODE_0_REG_OFFSET, 5863 (uint16)(conf->original_timecode.nanoseconds & 0xffff)); 5864 phy_bcm542xx_direct_reg_write(unit, pc, 5865 PHY_BCM542XX_TOP_1588_TIME_CODE_1_REG_OFFSET, 5866 (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff)); 5867 phy_bcm542xx_direct_reg_write(unit, pc, 5868 PHY_BCM542XX_TOP_1588_TIME_CODE_2_REG_OFFSET, 5869 (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff)); 5870 phy_bcm542xx_direct_reg_write(unit, pc, 5871 PHY_BCM542XX_TOP_1588_TIME_CODE_3_REG_OFFSET, 5872 (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) & 0xffff)); 5873 phy_bcm542xx_direct_reg_write(unit, pc, 5874 PHY_BCM542XX_TOP_1588_TIME_CODE_4_REG_OFFSET, 5875 (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff)); 5876 } 5877 5878 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE ) { 5879 /* P1588 NSE DPLL NCO Reg.6, bit[15:14] Global sync mode selection */ 5880 phy_bcm542xx_encode_gmode(conf->gmode, &gmode); 5881 } 5882 5883 /* FrameSync */ 5884 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE ) { 5885 phy_bcm542xx_encode_framesync_mode(conf->framesync.mode, &framesync_mode); 5886 5887 /* P1588 NSE DPLL NCO Register 7, RDB.0xA80-A81 */ 5888 phy_bcm542xx_direct_reg_write(unit, pc, 5889 PHY_BCM542XX_1588_NSE_DPLL_NCO_7_0_REG_OFFSET, 5890 conf->framesync.length_threshold); 5891 phy_bcm542xx_direct_reg_write(unit, pc, 5892 PHY_BCM542XX_1588_NSE_DPLL_NCO_7_1_REG_OFFSET, 5893 conf->framesync.event_offset); 5894 } 5895 5896 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE ) { 5897 phy_bcm542xx_encode_sync_out_mode(conf->syncout.mode, &syncout_mode); 5898 5899 /* Interval & pulse width of syncout pulse */ 5900 /* P1588 NSE DPLL NCO Register 3, RDB.0xA78-A7A */ 5901 phy_bcm542xx_direct_reg_write(unit, pc, 5902 PHY_BCM542XX_TOP_1588_NSE_NCO_3_0_REG_OFFSET, 5903 conf->syncout.interval & 0xffff); 5904 phy_bcm542xx_direct_reg_write(unit, pc, 5905 PHY_BCM542XX_TOP_1588_NSE_NCO_3_1_REG_OFFSET, 5906 ( ((conf->syncout.pulse_1_length & 0x3) << 14) 5907 | ((conf->syncout.interval >> 16) & 0x3fff )) ); 5908 phy_bcm542xx_direct_reg_write(unit, pc, 5909 PHY_BCM542XX_TOP_1588_NSE_NCO_3_2_REG_OFFSET , 5910 ( ((conf->syncout.pulse_2_length & 0x1ff) << 7) 5911 | ((conf->syncout.pulse_1_length >> 2) & 0x7f )) ); 5912 5913 /* Local timer for SYNC_OUT */ 5914 /* P1588 NSE DPLL NCO Register 5, RDB.0xA7C-A7E, SYNOUT_TS_REG */ 5915 phy_bcm542xx_direct_reg_write(unit, pc, 5916 PHY_BCM542XX_TOP_1588_NSE_NCO_5_0_REG_OFFSET, 5917 (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xffff)); 5918 phy_bcm542xx_direct_reg_write(unit, pc, 5919 PHY_BCM542XX_TOP_1588_NSE_NCO_5_1_REG_OFFSET, 5920 (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff)); 5921 phy_bcm542xx_direct_reg_write(unit, pc, 5922 PHY_BCM542XX_TOP_1588_NSE_NCO_5_2_REG_OFFSET, 5923 (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff)); 5924 } 5925 5926 /* GMODE */ /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F */ 5927 /* GMODE[15:14] FRAMESUNC_EN[12] FRAMESYNC_MODE[5:2] SYNC_OUT_MODE[1:0] */ 5928 phy_bcm542xx_direct_reg_modify( unit, pc, 5929 PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, 5930 (gmode << PHY_BCM542XX_TOP_1588_NSE_NCO_6_GMODE_SHIFT) | 5931 (framesync_mode << PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_MODE_SHIFT) | 5932 (syncout_mode << PHY_BCM542XX_TOP_1588_NSE_NCO_6_SYNCOUT_MODE_SHIFT)| 5933 (framesync_mode ? PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN : 0), 5934 ( PHY_BCM542XX_TOP_1588_NSE_NCO_6_GMODE 5935 | PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_EN 5936 | PHY_BCM542XX_TOP_1588_NSE_NCO_6_FRMSYN_MODE 5937 | PHY_BCM542XX_TOP_1588_NSE_NCO_6_SYNCOUT_MODE) ); 5938 5939 /* TX TS OFFSET */ 5940 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET ) { 5941 phy_bcm542xx_direct_reg_write(unit, pc, 5942 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port), 5943 (uint16)(conf->tx_timestamp_offset & 0xffff)); 5944 phy_bcm542xx_direct_reg_modify(unit, pc, 5945 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 5946 (uint16)((conf->tx_timestamp_offset >> 16) & 0xf ), 5947 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_TX_MSB); 5948 } 5949 5950 /* RX TS OFFSET */ 5951 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET ) { 5952 phy_bcm542xx_direct_reg_write(unit, pc, 5953 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port), 5954 (uint16)(conf->rx_timestamp_offset & 0xffff)); 5955 phy_bcm542xx_direct_reg_modify(unit, pc, 5956 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 5957 (uint16)((conf->rx_timestamp_offset >> 16) & 0xf), 5958 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_RX_MSB); 5959 } 5960 5961 /* Tx Event Message Mode for Message 0-3 */ 5962 /* ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */ 5963 data16 = mask16 = 0; 5964 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE ) { 5965 phy_bcm542xx_encode_egress_message_mode(conf->tx_sync_mode, 5966 0, &data16, &mask16); 5967 } 5968 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE ) { 5969 phy_bcm542xx_encode_egress_message_mode(conf->tx_delay_request_mode, 5970 2, &data16, &mask16); 5971 } 5972 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE ) { 5973 phy_bcm542xx_encode_egress_message_mode(conf->tx_pdelay_request_mode, 5974 4, &data16, &mask16); 5975 } 5976 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE ) { 5977 phy_bcm542xx_encode_egress_message_mode(conf->tx_pdelay_response_mode, 5978 6, &data16, &mask16); 5979 } 5980 /* P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n) */ 5981 phy_bcm542xx_direct_reg_modify(unit, pc, 5982 PHY_BCM542XX_TOP_1588_TX_MODE_PORT_N_OFFSET(dev_port), 5983 data16, mask16); 5984 5985 /* Rx Event Message Mode for Message 0-3 */ 5986 /* ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */ 5987 data16 = mask16 = 0; 5988 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE ) { 5989 phy_bcm542xx_encode_ingress_message_mode(conf->rx_sync_mode, 5990 0, &data16, &mask16); 5991 } 5992 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE ) { 5993 phy_bcm542xx_encode_ingress_message_mode(conf->rx_delay_request_mode, 5994 2, &data16, &mask16); 5995 } 5996 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE ) { 5997 phy_bcm542xx_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 5998 4, &data16, &mask16); 5999 } 6000 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE ) { 6001 phy_bcm542xx_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 6002 6, &data16, &mask16); 6003 } 6004 /* P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n) */ 6005 phy_bcm542xx_direct_reg_modify(unit, pc, 6006 PHY_BCM542XX_TOP_1588_RX_MODE_PORT_N_OFFSET(dev_port), 6007 data16, mask16); 6008 6009 /* DPLL initial reference phase */ 6010 /* P1588 NSE DPLL Register 2 , RDB.0xA67-0xA69 (48 bits) */ 6011 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 6012 /* REF_PHASE[15:0] */ 6013 phy_bcm542xx_direct_reg_write(unit, pc, 6014 PHY_BCM542XX_TOP_1588_NSE_DPLL_2_0_REG_OFFSET, 6015 (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff)); 6016 /* REF_PHASE[31:16] */ 6017 phy_bcm542xx_direct_reg_write(unit, pc, 6018 PHY_BCM542XX_TOP_1588_NSE_DPLL_2_1_REG_OFFSET, 6019 (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff)); 6020 /* REF_PHASE[47:32] */ 6021 phy_bcm542xx_direct_reg_write(unit, pc, 6022 PHY_BCM542XX_TOP_1588_NSE_DPLL_2_2_REG_OFFSET, 6023 (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff)); 6024 } 6025 6026 /* P1588 NSE DPLL Register 3 , RDB.0xA6A-0xA6B (32 bits) */ 6027 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 6028 /* Ref phase delta [15:0] */ 6029 phy_bcm542xx_direct_reg_write(unit, pc, 6030 PHY_BCM542XX_TOP_1588_NSE_DPLL_3_LSB_REG_OFFSET, 6031 (uint16)(conf->phy_1588_dpll_ref_phase_delta & 0xffff)); 6032 /* Ref phase delta [31:16] */ 6033 phy_bcm542xx_direct_reg_write(unit, pc, 6034 PHY_BCM542XX_TOP_1588_NSE_DPLL_3_MSB_REG_OFFSET, 6035 (uint16)((conf->phy_1588_dpll_ref_phase_delta >> 16)& 0xffff)); 6036 } 6037 6038 /* P1588 NSE DPLL Register 4/5/6 (K1/K2/K3) , RDB.0xA6C/0xA6D/0xA6E */ 6039 /* DPLL K1 */ 6040 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 6041 phy_bcm542xx_direct_reg_write(unit, pc, 6042 PHY_BCM542XX_TOP_1588_NSE_DPLL_4_REG_OFFSET, 6043 conf->phy_1588_dpll_k1 & 0xff); 6044 } 6045 6046 /* DPLL K2 */ 6047 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 6048 phy_bcm542xx_direct_reg_write(unit, pc, 6049 PHY_BCM542XX_TOP_1588_NSE_DPLL_5_REG_OFFSET, 6050 conf->phy_1588_dpll_k2 & 0xff); 6051 } 6052 6053 /* DPLL K3 */ 6054 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 6055 phy_bcm542xx_direct_reg_write(unit, pc, 6056 PHY_BCM542XX_TOP_1588_NSE_DPLL_6_REG_OFFSET, 6057 conf->phy_1588_dpll_k3 & 0xff); 6058 } 6059 6060 /* P1588 NSE DPLL Register 7 , RDB.0xA6F-0xA72 (64 bits) */ 6061 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER) { 6062 /* Initial loop filter[15:0] */ 6063 phy_bcm542xx_direct_reg_write(unit, pc, 6064 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_0_REG_OFFSET, 6065 (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) & 0xffff)); 6066 /* Initial loop filter[31:16] */ 6067 phy_bcm542xx_direct_reg_write(unit, pc, 6068 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_1_REG_OFFSET, 6069 (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff)); 6070 6071 /* Initial loop filter[47:32] */ 6072 phy_bcm542xx_direct_reg_write(unit, pc, 6073 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_2_REG_OFFSET, 6074 (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) & 0xffff)); 6075 6076 6077 /* Initial loop filter[63:48] */ 6078 phy_bcm542xx_direct_reg_write(unit, pc, 6079 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_3_REG_OFFSET, 6080 (uint16)((COMPILER_64_HI(conf->phy_1588_dpll_loop_filter) >> 16) & 0xffff)); 6081 } 6082 6083 /* P1588 MPLS */ 6084 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL ) { 6085 /* MPLS controls */ 6086 if ( conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE ) { 6087 mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN; 6088 mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN; 6089 } 6090 6091 if (!(conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE) ) { 6092 mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS; 6093 mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS; 6094 } 6095 6096 if ( conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE ) { 6097 mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN; 6098 mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN; 6099 } 6100 6101 if ( conf->mpls_control.flags & SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE ) { 6102 mpls_control_reg_tx |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_SP_LBL_EN; 6103 mpls_control_reg_rx |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_SP_LBL_EN; 6104 } 6105 6106 phy_bcm542xx_direct_reg_modify(unit, pc, 6107 PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 6108 mpls_control_reg_tx, 6109 PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN 6110 | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS 6111 | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN 6112 | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_SP_LBL_EN); 6113 6114 6115 phy_bcm542xx_direct_reg_modify(unit, pc, 6116 PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 6117 mpls_control_reg_rx, 6118 PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN 6119 | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS 6120 | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN 6121 | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_SP_LBL_EN); 6122 6123 for ( i = 0 ; i < conf->mpls_control.size; i++ ) { 6124 phy_bcm542xx_direct_reg_write( unit, pc, 6125 PHY_BCM542XX_TOP_1588_LABEL_N_LSB_MASK_REG_OFFSET(i), 6126 (conf->mpls_control.labels[i].mask & 0xffff) ); 6127 phy_bcm542xx_direct_reg_modify( unit, pc, 6128 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(i), 6129 ((conf->mpls_control.labels[i].mask >> 16) & 0xf), 0xf ); 6130 phy_bcm542xx_direct_reg_write( unit, pc, 6131 PHY_BCM542XX_TOP_1588_LABEL_N_LSB_VAL_REG_OFFSET(i), 6132 (conf->mpls_control.labels[i].value & 0xffff) ); 6133 phy_bcm542xx_direct_reg_modify( unit, pc, 6134 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_VAL_REG_OFFSET(i), 6135 ((conf->mpls_control.labels[i].value >> 16) & 0xf), 0xf ); 6136 /*Enable comparison for MPLS label value N */ 6137 phy_bcm542xx_direct_reg_modify( unit, pc, 6138 PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 6139 (BIT(6) << i), (BIT(6) << i) ); 6140 phy_bcm542xx_direct_reg_modify( unit, pc, 6141 PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 6142 (BIT(6) << i), (BIT(6) << i) ); 6143 } 6144 } 6145 6146 /* P1588 direct Timer adjustment */ 6147 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TIMER_ADJUSTMENT ) { 6148 int val32 = conf->timer_adjust.delta; 6149 6150 /* Timer adjustment delta should be a 14-bit two's complement value */ 6151 if ( val32 > PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MAX ) { 6152 /* over the 14-bit range, set the max. */ 6153 data16 = PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MAX; 6154 } else 6155 if ( val32 < PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MIN ) { 6156 /* under the 14-bit range, set the min. */ 6157 data16 = PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MIN; 6158 } else { 6159 /* value in range, extract the 14-bit two's complement value */ 6160 data16 = ((uint16 ) val32) & 6161 PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MASK; 6162 } 6163 6164 /* determine which counter to be adjusted, 80- or 48-bit or both */ 6165 if ( conf->timer_adjust.mode & 6166 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT ) { 6167 data16 |= PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_48BIT; 6168 } 6169 if ( conf->timer_adjust.mode & 6170 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT ) { 6171 data16 |= PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_80BIT; 6172 } 6173 6174 /* P1588 Timestamp Delta Register, RDB.0xAf7 */ 6175 phy_bcm542xx_direct_reg_write(unit, pc, 6176 PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_REG_OFFSET, data16); 6177 } 6178 6179 /* IEEE-1588 Gen-2 Inband operation */ 6180 if ( conf->validity_mask & 6181 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL ) { 6182 /* 6183 * Inband control parameters setting 6184 */ 6185 data16 = (conf->inband_control.resv0_id 6186 << PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_SHIFT) 6187 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID; 6188 if ( conf->inband_control.flags & 6189 SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE ) { 6190 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_SYNC_EN; 6191 } 6192 if ( conf->inband_control.flags & 6193 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE ) { 6194 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_DELAY_REQ_EN; 6195 } 6196 if ( conf->inband_control.flags & 6197 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE ) { 6198 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_REQ_EN; 6199 } 6200 if ( conf->inband_control.flags & 6201 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE ) { 6202 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_RESP_EN; 6203 } 6204 6205 if ( conf->inband_control.flags & 6206 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK ) { 6207 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_CHECK; 6208 } 6209 if ( conf->inband_control.flags & 6210 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE ) { 6211 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_UPDATE; 6212 } 6213 if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE) || 6214 (conf->inband_control.flags & 6215 SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST) ) { 6216 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_FOLLOW_UP | 6217 PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_CAP_MODE; 6218 } 6219 if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE) || 6220 (conf->inband_control.flags & 6221 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST) ) { 6222 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_DELAY_RSP | 6223 PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_CAP_MODE; 6224 } 6225 if ( conf->inband_control.flags & 6226 SOC_PORT_PHY_TIMESYNC_INBAND_TIMER_MODE_SELECT ) { 6227 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_SEL; 6228 } 6229 if ( conf->inband_control.timer_mode & 6230 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT ) { 6231 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_SEL; 6232 } 6233 6234 if ( conf->inband_control.flags & 6235 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR ) { 6236 data16 |= PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_ADDR_EN; 6237 } 6238 if ( conf->inband_control.flags & 6239 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR ) { 6240 data16 |= (PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_ADDR_EN | 6241 PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_MAC_SEL); 6242 } 6243 6244 /* P1588 Inband Control Port_n Register, RDB.0xAEE~Af5 */ 6245 phy_bcm542xx_direct_reg_write(unit, pc, 6246 PHY_BCM542XX_TOP_1588_INBAND_CNTL_N_REG_OFFSET(dev_port), 6247 data16); 6248 6249 /* 6250 * MPLS setting for the label_1 mask 6251 */ 6252 data16 = 0; 6253 if ( conf->inband_control.flags & 6254 SOC_PORT_PHY_TIMESYNC_INBAND_CAP_SRC_PORT_CLK_ID) { 6255 data16 |= PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID; 6256 } 6257 if ( conf->inband_control.flags & 6258 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM) { 6259 data16 |= PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM; 6260 } 6261 if ( conf->inband_control.flags & 6262 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID) { 6263 data16 |= PHY_BCM542XX_TOP_1588_MATCH_VLAN_ID; 6264 } 6265 mask16 = PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID 6266 | PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM 6267 | PHY_BCM542XX_TOP_1588_MATCH_VLAN_ID; 6268 6269 /* P1588 MPLS label1 mask msb bit, RDB.0xA98, bit[15:13] */ 6270 phy_bcm542xx_direct_reg_modify( unit, pc, 6271 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(dev_port), 6272 data16, mask16 ); 6273 6274 /* 6275 * Timestamp capture enable for Rx & TX 6276 */ 6277 /* P1588 TX SOP Timestamp Capture Enable, RDB.0xa21 */ 6278 phy_bcm542xx_direct_reg_modify( unit, pc, 6279 PHY_BCM542XX_TOP_1588_TX_TS_CAP_REG_OFFSET, 6280 BIT(dev_port), BIT(dev_port) ); 6281 /* P1588 RX SOP Timestamp Capture Enable, RDB.0xa22 */ 6282 phy_bcm542xx_direct_reg_modify( unit, pc, 6283 PHY_BCM542XX_TOP_1588_RX_TS_CAP_REG_OFFSET, 6284 BIT(dev_port), BIT(dev_port) ); 6285 6286 /* P1588 RX CF + Insertion Reg., RDB.0xAC0 */ 6287 phy_bcm542xx_direct_reg_modify( unit, pc, 6288 PHY_BCM542XX_TOP_1588_RX_CF_REG_OFFSET, 6289 PHY_BCM542XX_TOP_1588_RX_CF_UPD(dev_port) 6290 | PHY_BCM542XX_TOP_1588_RX_CS_UPD(dev_port), 6291 PHY_BCM542XX_TOP_1588_RX_CF_UPD(dev_port) 6292 | PHY_BCM542XX_TOP_1588_RX_CS_UPD(dev_port) ); 6293 /* P1588 TX CS Update Reg., RDB.0xAC1 */ 6294 phy_bcm542xx_direct_reg_modify( unit, pc, 6295 PHY_BCM542XX_TOP_1588_TX_CS_UPD_REG_OFFSET, 6296 PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE2(dev_port) 6297 | PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE3(dev_port), 6298 PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE2(dev_port) 6299 | PHY_BCM542XX_TOP_1588_TX_CS_UPD_MODE3(dev_port) ); 6300 /* P1588 P1588 TIMECODE Select Reg., RDB.0xAC3 */ 6301 phy_bcm542xx_direct_reg_modify( unit, pc, 6302 PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_REG_OFFSET, 6303 PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_RX_N(dev_port) 6304 | PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_TX_N(dev_port), 6305 PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_RX_N(dev_port) 6306 | PHY_BCM542XX_TOP_1588_64b_TIMECODE_SEL_TX_N(dev_port) ); 6307 /* P1588 P1588 DPLL Debug Select Reg., RDB.0xA5B */ 6308 phy_bcm542xx_direct_reg_modify( unit, pc, 6309 PHY_BCM542XX_TOP_1588_DPLL_DB_SEL_REG_OFFSET, 6310 PHY_BCM542XX_TOP_1588_DPLL_DB_SEL_RSVD, 6311 PHY_BCM542XX_TOP_1588_DPLL_DB_SEL_RSVD ); 6312 }/* TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */ 6313 6314 /* Tx/Rx gphycore SOP or internal 1588 SOP: Select internal 1588 SOP (1) */ 6315 /* P1588 SOP Selection Register, RDB.0xAF8, TX[7:0] RX[15:8] */ 6316 phy_bcm542xx_direct_reg_modify( unit, pc, 6317 PHY_BCM542XX_TOP_1588_SOP_SEL_REG_OFFSET, 6318 PHY_BCM542XX_TOP_1588_SOP_SEL_TX_PORT_N(dev_port) 6319 | PHY_BCM542XX_TOP_1588_SOP_SEL_RX_PORT_N(dev_port), 6320 PHY_BCM542XX_TOP_1588_SOP_SEL_TX_PORT_N(dev_port) 6321 | PHY_BCM542XX_TOP_1588_SOP_SEL_RX_PORT_N(dev_port) ); 6322 6323 /*********************************************************************** 6324 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 6325 * To access TOP level registers use phy_id of port0. Now restore back 6326 */ 6327 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 6328 6329 return SOC_E_NONE; 6330 } 6331 6332 /* 6333 * Function: 6334 * phy_bcm542xx_timesync_config_get 6335 * Purpose: 6336 * 6337 * Parameters: 6338 * 6339 * Returns: 6340 */ 6341 int 6342 phy_bcm542xx_timesync_config_get(int unit, soc_port_t port, 6343 soc_port_phy_timesync_config_t *conf) 6344 { 6345 uint16 dev_port, tx_control_reg = 0, en_control_reg = 0; 6346 uint16 tx_capture_en_reg = 0, rx_capture_en_reg=0, rx_tx_control_reg; 6347 uint16 nse_nco_6 = 0, nse_nco_2_2 = 0; 6348 uint16 i, temp1, temp2, temp3, temp4, value, mpls_control_reg_rx; 6349 uint16 data16; 6350 6351 soc_port_phy_timesync_global_mode_t gmode 6352 = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 6353 soc_port_phy_timesync_framesync_mode_t framesync_mode 6354 = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1; 6355 soc_port_phy_timesync_syncout_mode_t syncout_mode 6356 = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 6357 phy_ctrl_t *pc; 6358 6359 if ( NULL == conf ) { 6360 return SOC_E_PARAM; 6361 } 6362 6363 pc = EXT_PHY_SW_STATE(unit, port); 6364 6365 /*********************************************************************** 6366 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 6367 * To access TOP level registers use phy_id of port0. Override this ports 6368 */ 6369 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 6370 6371 /* Dev port numbers from 0-7 */ 6372 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 6373 6374 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 6375 of the device. For example to enable autogrEEEn on port0, 6376 rdb register for port 4 0x808 need to be used. 6377 Refer package configuration document. 6378 */ 6379 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 6380 dev_port += 4; 6381 } 6382 6383 conf->flags = 0; 6384 6385 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 6386 /* SLICE ENABLE CONTROL register */ 6387 phy_bcm542xx_direct_reg_read(unit, pc, 6388 PHY_BCM542XX_TOP_1588_SLICE_EN_CTRL_REG_OFFSET, 6389 &en_control_reg); 6390 6391 /* Tx & Rx (+8) */ 6392 if ( (en_control_reg & BIT(dev_port)) && 6393 (en_control_reg & BIT(dev_port + 8)) ) { 6394 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE; 6395 } 6396 6397 /* TxRx SOP TS CAPTURE ENABLE reg */ 6398 phy_bcm542xx_direct_reg_read(unit, pc, 6399 PHY_BCM542XX_TOP_1588_TX_TS_CAP_REG_OFFSET, 6400 &tx_capture_en_reg); 6401 6402 phy_bcm542xx_direct_reg_read(unit, pc, 6403 PHY_BCM542XX_TOP_1588_RX_TS_CAP_REG_OFFSET, 6404 &rx_capture_en_reg); 6405 6406 if ( (tx_capture_en_reg & BIT(dev_port)) && 6407 (rx_capture_en_reg & BIT(dev_port)) ) { 6408 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 6409 } 6410 6411 /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F */ 6412 /* GMODE[15:14] FRAMESYNC_MODE[5:2] SYNC_OUT_MODE[1:0] */ 6413 phy_bcm542xx_direct_reg_read(unit, pc, 6414 PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, 6415 &nse_nco_6); 6416 6417 if ( nse_nco_6 & PHY_BCM542XX_TOP_1588_NSE_NCO_6_TS_CAP) { 6418 conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE; 6419 } 6420 6421 /* RX TX CONTROL register */ 6422 phy_bcm542xx_direct_reg_read(unit, pc, 6423 PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_OFFSET, 6424 &rx_tx_control_reg); 6425 6426 if ( rx_tx_control_reg & PHY_BCM542XX_TOP_1588_RX_TX_CTL_REG_RX_CRC_EN ) { 6427 conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE; 6428 } 6429 6430 /* TX CONTROL register */ 6431 phy_bcm542xx_direct_reg_read(unit, pc, 6432 PHY_BCM542XX_TOP_1588_TX_CTL_REG_OFFSET, 6433 &tx_control_reg); 6434 6435 if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_AS_EN ) { 6436 conf->flags |= SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE; 6437 } 6438 6439 if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_L2_EN ) { 6440 conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE; 6441 } 6442 6443 if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV4_UDP_EN ) { 6444 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE; 6445 } 6446 6447 if ( tx_control_reg & PHY_BCM542XX_TOP_1588_TX_CTL_REG_TX_IPV6_UDP_EN ) { 6448 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE; 6449 } 6450 phy_bcm542xx_direct_reg_read(unit, pc, 6451 PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET, 6452 &nse_nco_2_2); 6453 6454 if ( !(nse_nco_2_2 & PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_FREQ_MDIO_SEL) ) { 6455 conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 6456 } 6457 } 6458 6459 /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F */ 6460 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE ) { 6461 /* P1588 NSE DPLL NCO Reg.6, bit[15:14] Global sync mode selection */ 6462 phy_bcm542xx_decode_gmode((nse_nco_6 >> 14), &gmode); 6463 conf->gmode = gmode; 6464 } 6465 6466 /* framesync */ 6467 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE ) { 6468 /* P1588 NSE DPLL NCO Reg.6, FRAMESYNC_MODE[5:2] */ 6469 phy_bcm542xx_decode_framesync_mode((nse_nco_6 >> 2), &framesync_mode); 6470 conf->framesync.mode = framesync_mode; 6471 6472 /* P1588 NSE DPLL NCO Register 7, RDB.0xa80-a81 */ 6473 phy_bcm542xx_direct_reg_read(unit, pc, 6474 PHY_BCM542XX_1588_NSE_DPLL_NCO_7_0_REG_OFFSET, 6475 &value); 6476 conf->framesync.length_threshold = value; 6477 phy_bcm542xx_direct_reg_read(unit, pc, 6478 PHY_BCM542XX_1588_NSE_DPLL_NCO_7_1_REG_OFFSET, 6479 &value); 6480 conf->framesync.event_offset = value; 6481 } 6482 6483 /* Syncout */ 6484 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE ) { 6485 /* P1588 NSE DPLL NCO Reg.6, SYNC_OUT_MODE[1:0] */ 6486 phy_bcm542xx_decode_sync_out_mode((nse_nco_6 ), &syncout_mode); 6487 conf->syncout.mode = syncout_mode; 6488 6489 /* TOP_1588_NSE_NCO_3 - P1588 NSE DPLL NCO Register 3, RDB.0xa78-a7a */ 6490 phy_bcm542xx_direct_reg_read(unit, pc, 6491 PHY_BCM542XX_TOP_1588_NSE_NCO_3_0_REG_OFFSET, 6492 &temp1); 6493 phy_bcm542xx_direct_reg_read(unit, pc, 6494 PHY_BCM542XX_TOP_1588_NSE_NCO_3_1_REG_OFFSET, 6495 &temp2); 6496 phy_bcm542xx_direct_reg_read(unit, pc, 6497 PHY_BCM542XX_TOP_1588_NSE_NCO_3_2_REG_OFFSET, 6498 &temp3); 6499 /* PULSE_TRAIN_LENGTH */ 6500 conf->syncout.pulse_1_length = ((temp3 & 0x7f) << 2) 6501 | ((temp2 >> 14) & 0x3); 6502 /* FRMSYNC_PULSE_LENGTH */ 6503 conf->syncout.pulse_2_length = (temp3 >> 7) & 0x1ff; 6504 /* INTERVAL_LENGTH */ 6505 conf->syncout.interval = ((temp2 & 0x3fff) << 16) | temp1; 6506 6507 /* TOP_1588_NSE_NCO_5_0 - P1588 NSE DPLL NCO Register, RDB.0xa7c-a7e */ 6508 phy_bcm542xx_direct_reg_read(unit, pc, 6509 PHY_BCM542XX_TOP_1588_NSE_NCO_5_0_REG_OFFSET, 6510 &temp1); 6511 phy_bcm542xx_direct_reg_read(unit, pc, 6512 PHY_BCM542XX_TOP_1588_NSE_NCO_5_1_REG_OFFSET, 6513 &temp2); 6514 phy_bcm542xx_direct_reg_read(unit, pc, 6515 PHY_BCM542XX_TOP_1588_NSE_NCO_5_2_REG_OFFSET, 6516 &temp3); 6517 /* SYNOUT_TS_REG (48 bits, but only [47:4] are useful) 6518 time interval to trigger SYNC pulse */ 6519 COMPILER_64_SET( conf->syncout.syncout_ts, ((uint32)temp3), 6520 (((uint32)temp2 << 16) | ((uint32)temp1)) ); 6521 } 6522 6523 /* VLAN Tags */ 6524 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID ) { 6525 6526 phy_bcm542xx_direct_reg_read(unit, pc, 6527 PHY_BCM542XX_TOP_1588_VLAN_ITPID_REG_OFFSET, 6528 &conf->itpid); 6529 } 6530 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID ) { 6531 6532 phy_bcm542xx_direct_reg_read(unit, pc, 6533 PHY_BCM542XX_TOP_1588_VLAN_OTPID_REG_OFFSET, 6534 &conf->otpid); 6535 } 6536 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2 ) { 6537 phy_bcm542xx_direct_reg_read(unit, pc, 6538 PHY_BCM542XX_TOP_1588_OTHER_OTPID_REG_OFFSET, 6539 &conf->otpid2); 6540 } 6541 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER ) { 6542 phy_bcm542xx_direct_reg_read(unit, pc, 6543 PHY_BCM542XX_TOP_1588_NSE_NCO_4_REG_OFFSET, 6544 &conf->ts_divider); 6545 } 6546 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY ) { 6547 phy_bcm542xx_direct_reg_read(unit, pc, 6548 PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_LSB(dev_port), 6549 &temp1); 6550 phy_bcm542xx_direct_reg_read(unit, pc, 6551 PHY_BCM542XX_TOP_1588_RX_PORTN_LINK_DELAY_MSB(dev_port), 6552 &temp2); 6553 conf->rx_link_delay = ((uint32)temp2 << 16) | temp1; 6554 } 6555 6556 /* TIMECODE */ 6557 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE ) { 6558 /* P1588 Original Time Code Register 0-4 (80 bits), RDB.0xa54-a58 */ 6559 phy_bcm542xx_direct_reg_read(unit, pc, 6560 PHY_BCM542XX_TOP_1588_TIME_CODE_0_REG_OFFSET, 6561 &temp1); 6562 phy_bcm542xx_direct_reg_read(unit, pc, 6563 PHY_BCM542XX_TOP_1588_TIME_CODE_1_REG_OFFSET, 6564 &temp2); 6565 conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1; 6566 6567 phy_bcm542xx_direct_reg_read(unit, pc, 6568 PHY_BCM542XX_TOP_1588_TIME_CODE_2_REG_OFFSET, 6569 &temp1); 6570 phy_bcm542xx_direct_reg_read(unit, pc, 6571 PHY_BCM542XX_TOP_1588_TIME_CODE_3_REG_OFFSET, 6572 &temp2); 6573 phy_bcm542xx_direct_reg_read(unit, pc, 6574 PHY_BCM542XX_TOP_1588_TIME_CODE_4_REG_OFFSET, 6575 &temp3); 6576 COMPILER_64_SET( conf->original_timecode.seconds, ((uint32)temp3), 6577 (((uint32)temp2 << 16) | ((uint32)temp1)) ); 6578 } 6579 6580 /* TX TS OFFSET */ 6581 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET ) { 6582 phy_bcm542xx_direct_reg_read(unit, pc, 6583 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port), 6584 &temp1); 6585 phy_bcm542xx_direct_reg_read(unit, pc, 6586 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 6587 &temp2); 6588 conf->tx_timestamp_offset = ((temp2 & 0xf) << 16) | temp1; 6589 } 6590 6591 /* RX TS OFFSET */ 6592 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET ) { 6593 phy_bcm542xx_direct_reg_read(unit, pc, 6594 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port), 6595 &temp1); 6596 phy_bcm542xx_direct_reg_read(unit, pc, 6597 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 6598 &temp2); 6599 conf->rx_timestamp_offset = ((temp2 & 0xf) << 16) | temp1; 6600 } 6601 6602 /* P1588 Port_n TX Event Message Mode1/2 Selection Reg., RDB.0xa11+(n) */ 6603 phy_bcm542xx_direct_reg_read(unit, pc, 6604 PHY_BCM542XX_TOP_1588_TX_MODE_PORT_N_OFFSET(dev_port), 6605 &value); 6606 /* Tx Event Message Mode for Message 0-3 */ 6607 /* ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */ 6608 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE ) { 6609 phy_bcm542xx_decode_egress_message_mode(value, 0, &conf->tx_sync_mode); 6610 } 6611 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE ) { 6612 phy_bcm542xx_decode_egress_message_mode(value, 2, &conf->tx_delay_request_mode); 6613 } 6614 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE ) { 6615 phy_bcm542xx_decode_egress_message_mode(value, 4, &conf->tx_pdelay_request_mode); 6616 } 6617 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE ) { 6618 phy_bcm542xx_decode_egress_message_mode(value, 6, &conf->tx_pdelay_response_mode); 6619 } 6620 6621 /* P1588 Port_n RX Event Message Mode1/2 Selection Reg., RDB.0xa19+(n) */ 6622 phy_bcm542xx_direct_reg_read(unit, pc, 6623 PHY_BCM542XX_TOP_1588_RX_MODE_PORT_N_OFFSET(dev_port), 6624 &value); 6625 /* Rx Event Message Mode for Message 0-3 */ 6626 /* ( Sync, Delay_Req, Pdelay_Req, Pdelay_Resp ) */ 6627 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE ) { 6628 phy_bcm542xx_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode); 6629 } 6630 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE ) { 6631 phy_bcm542xx_decode_ingress_message_mode(value, 2, &conf->rx_delay_request_mode); 6632 } 6633 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE ) { 6634 phy_bcm542xx_decode_ingress_message_mode(value, 4, &conf->rx_pdelay_request_mode); 6635 } 6636 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE ) { 6637 phy_bcm542xx_decode_ingress_message_mode(value, 6, &conf->rx_pdelay_response_mode); 6638 } 6639 6640 /* DPLL initial reference phase */ 6641 /* P1588 NSE DPLL Register 2 , RDB.0xA67-0xA69 (48 bits) */ 6642 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 6643 /*[15:0]*/ 6644 phy_bcm542xx_direct_reg_read(unit, pc, 6645 PHY_BCM542XX_TOP_1588_NSE_DPLL_2_0_REG_OFFSET, 6646 &temp1); 6647 /*[31:16]*/ 6648 phy_bcm542xx_direct_reg_read(unit, pc, 6649 PHY_BCM542XX_TOP_1588_NSE_DPLL_2_1_REG_OFFSET, 6650 &temp2); 6651 /*[47:32]*/ 6652 phy_bcm542xx_direct_reg_read(unit, pc, 6653 PHY_BCM542XX_TOP_1588_NSE_DPLL_2_2_REG_OFFSET, 6654 &temp3); 6655 COMPILER_64_SET( conf->phy_1588_dpll_ref_phase, ((uint32)temp3), 6656 (((uint32)temp2 << 16) | ((uint32)temp1)) ); 6657 } 6658 6659 /* P1588 NSE DPLL Register 3 , RDB.0xA6A-0xA6B (32 bits) */ 6660 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA ) { 6661 /* Ref phase delta [15:0] */ 6662 phy_bcm542xx_direct_reg_read(unit, pc, 6663 PHY_BCM542XX_TOP_1588_NSE_DPLL_3_LSB_REG_OFFSET, 6664 &temp1); 6665 /* Ref phase delta [31:16] */ 6666 phy_bcm542xx_direct_reg_read(unit, pc, 6667 PHY_BCM542XX_TOP_1588_NSE_DPLL_3_MSB_REG_OFFSET, 6668 &temp2); 6669 conf->phy_1588_dpll_ref_phase_delta = (temp2 << 16) | temp1; 6670 } 6671 6672 /* P1588 NSE DPLL Register 4/5/6 (K1/K2/K3) , RDB.0xA6C/0xA6D/0xA6E */ 6673 /* DPLL K1 */ 6674 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 6675 phy_bcm542xx_direct_reg_read(unit, pc, 6676 PHY_BCM542XX_TOP_1588_NSE_DPLL_4_REG_OFFSET, 6677 &temp1); 6678 conf->phy_1588_dpll_k1 = temp1 & 0xff; 6679 } 6680 6681 /* DPLL K2 */ 6682 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 6683 phy_bcm542xx_direct_reg_read(unit, pc, 6684 PHY_BCM542XX_TOP_1588_NSE_DPLL_5_REG_OFFSET, 6685 &temp1); 6686 conf->phy_1588_dpll_k2 = temp1 & 0xff; 6687 } 6688 6689 /* DPLL K3 */ 6690 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 6691 phy_bcm542xx_direct_reg_read(unit, pc, 6692 PHY_BCM542XX_TOP_1588_NSE_DPLL_6_REG_OFFSET, 6693 &temp1); 6694 conf->phy_1588_dpll_k3 = temp1 & 0xff; 6695 } 6696 6697 /* P1588 NSE DPLL Register 7 , RDB.0xA6F-0xA72 (64 bits) */ 6698 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_LOOP_FILTER ) { 6699 /* Initial loop filter[15:0] */ 6700 phy_bcm542xx_direct_reg_read(unit, pc, 6701 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_0_REG_OFFSET, 6702 &temp1); 6703 /* Initial loop filter[31:16] */ 6704 phy_bcm542xx_direct_reg_read(unit, pc, 6705 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_1_REG_OFFSET, 6706 &temp2); 6707 /* Initial loop filter[47:32] */ 6708 phy_bcm542xx_direct_reg_read(unit, pc, 6709 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_2_REG_OFFSET, 6710 &temp3); 6711 /* Initial loop filter[63:48] */ 6712 phy_bcm542xx_direct_reg_read(unit, pc, 6713 PHY_BCM542XX_TOP_1588_NSE_DPLL_7_3_REG_OFFSET, 6714 &temp4); 6715 COMPILER_64_SET( conf->phy_1588_dpll_loop_filter, 6716 (((uint32)temp4 << 16) | ((uint32)temp3)), 6717 (((uint32)temp2 << 16) | ((uint32)temp1)) ); 6718 } 6719 6720 /* P1588 MPLS */ 6721 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_MPLS_CONTROL) { 6722 /* MPLS controls */ 6723 #if 0 6724 phy_bcm542xx_direct_reg_read(unit, pc, 6725 PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 6726 &mpls_control_reg_tx); 6727 #endif 6728 phy_bcm542xx_direct_reg_read(unit, pc, 6729 PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 6730 &mpls_control_reg_rx); 6731 6732 if ( (mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN) 6733 /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN)*/) { 6734 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENTROPY_ENABLE; 6735 } 6736 if ( !(mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS)) 6737 /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS)*/ { 6738 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_CONTROL_WORD_ENABLE; 6739 } 6740 if ( (mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN) 6741 /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN)*/) { 6742 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_ENABLE; 6743 } 6744 if ( (mpls_control_reg_rx & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_SP_LBL_EN) 6745 /*&& (mpls_control_reg_tx & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_SP_LBL_EN)*/) { 6746 conf->mpls_control.flags |= SOC_PORT_PHY_TIMESYNC_MPLS_SPECIAL_LABEL_ENABLE; 6747 } 6748 6749 for ( i = 0 ; i < conf->mpls_control.size; i++ ) { 6750 phy_bcm542xx_direct_reg_read( unit, pc, 6751 PHY_BCM542XX_TOP_1588_LABEL_N_LSB_MASK_REG_OFFSET(i), 6752 &temp1 ); 6753 conf->mpls_control.labels[i].mask = temp1; 6754 phy_bcm542xx_direct_reg_read( unit, pc, 6755 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(i), 6756 &temp1 ); 6757 conf->mpls_control.labels[i].mask |= (temp1 & 0xf) << 16; 6758 6759 phy_bcm542xx_direct_reg_read( unit, pc, 6760 PHY_BCM542XX_TOP_1588_LABEL_N_LSB_VAL_REG_OFFSET(i), 6761 &temp1 ); 6762 conf->mpls_control.labels[i].value = temp1; 6763 phy_bcm542xx_direct_reg_read( unit, pc, 6764 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_VAL_REG_OFFSET(i), 6765 &temp1 ); 6766 conf->mpls_control.labels[i].value |= (temp1 & 0xf) << 16; 6767 } 6768 } 6769 6770 /* P1588 direct Timer adjustment */ 6771 if ( conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TIMER_ADJUSTMENT ) { 6772 uint16 val16; 6773 /* P1588 Timestamp Delta Register, RDB.0xAf7 */ 6774 phy_bcm542xx_direct_reg_read(unit, pc, 6775 PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_REG_OFFSET, &data16); 6776 6777 /* Timestamp Delta Reg. bit[13:0] = Timer adjustment delta value */ 6778 val16 = data16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_MASK; 6779 /* Timer adjustment delta is a 14-bit two's complement value */ 6780 if ( val16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_SIGN ) { 6781 /* sign extension if negative */ 6782 val16 |= PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_VALUE_SIGN_EXT; 6783 } 6784 conf->timer_adjust.delta = (int) val16; 6785 6786 if ( data16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_48BIT ) { 6787 conf->timer_adjust.mode |= SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT; 6788 } 6789 if ( data16 & PHY_BCM542XX_TOP_1588_TIMESTAMP_DELTA_80BIT ) { 6790 conf->timer_adjust.mode |= SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT; 6791 } 6792 } 6793 6794 /* IEEE-1588 Gen-2 Inband operations */ 6795 if ( (conf->validity_mask & 6796 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL) ) { 6797 /* P1588 Inband Control Port_n Register, RDB.0xAEE~Af5 */ 6798 phy_bcm542xx_direct_reg_read(unit, pc, 6799 PHY_BCM542XX_TOP_1588_INBAND_CNTL_N_REG_OFFSET(dev_port), 6800 &data16); 6801 conf->inband_control.resv0_id = /* Rev0_ID[7:4] */ 6802 (data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID) 6803 >> PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_SHIFT; 6804 6805 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_SYNC_EN ) { 6806 conf->inband_control.flags |= 6807 SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE; 6808 } 6809 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_DELAY_REQ_EN ) { 6810 conf->inband_control.flags |= 6811 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE; 6812 } 6813 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_REQ_EN ) { 6814 conf->inband_control.flags |= 6815 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE; 6816 } 6817 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_PDELAY_RESP_EN ) { 6818 conf->inband_control.flags |= 6819 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE; 6820 } 6821 6822 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_CHECK ) { 6823 conf->inband_control.flags |= 6824 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK; 6825 } 6826 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_RESV0_ID_UPDATE ) { 6827 conf->inband_control.flags |= 6828 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE; 6829 } 6830 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_FOLLOW_UP ) { 6831 conf->inband_control.flags |= 6832 SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST; 6833 conf->flags |= 6834 SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE; 6835 } 6836 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_UPD_DELAY_RSP ) { 6837 conf->inband_control.flags |= 6838 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST; 6839 conf->flags |= 6840 SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE; 6841 } 6842 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_TS_SEL ) { 6843 conf->inband_control.timer_mode |= 6844 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT; 6845 } else { 6846 conf->inband_control.timer_mode |= 6847 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT; 6848 } 6849 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_ADDR_EN ) { 6850 if ( data16 & PHY_BCM542XX_TOP_1588_INBAND_CNTL_IP_MAC_SEL ) { 6851 conf->inband_control.flags |= 6852 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR; 6853 } else { 6854 conf->inband_control.flags |= 6855 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR; 6856 } 6857 } 6858 6859 /* P1588 MPLS label1 mask msb bit, RDB.0xA98, bit[15:13] */ 6860 phy_bcm542xx_direct_reg_read(unit, pc, 6861 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(dev_port), 6862 &data16); 6863 if ( data16 & PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID ) { 6864 conf->inband_control.flags |= 6865 SOC_PORT_PHY_TIMESYNC_INBAND_CAP_SRC_PORT_CLK_ID; 6866 } 6867 if ( data16 & PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM ) { 6868 conf->inband_control.flags |= 6869 PHY_BCM542XX_TOP_1588_MATCH_SRC_PORT_NUM; 6870 } 6871 if ( data16 & PHY_BCM542XX_TOP_1588_MATCH_VLAN_ID ) { 6872 conf->inband_control.flags |= 6873 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID; 6874 } 6875 }/* SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */ 6876 6877 /* TOP LEVEL REGISTER ACCESS -> RESTORE *\ 6878 \* To access TOP level registers use phy_id of port0. Now restore back */ 6879 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 6880 6881 return SOC_E_NONE; 6882 } 6883 6884 /* 6885 * Function: 6886 * phy_bcm542xx_timesync_control_set 6887 * Purpose: 6888 * 6889 * Parameters: 6890 * 6891 * Returns: 6892 */ 6893 int 6894 phy_bcm542xx_timesync_control_set(int unit, soc_port_t port, 6895 soc_port_control_phy_timesync_t type, 6896 uint64 value) 6897 { 6898 int rv = SOC_E_NONE; 6899 uint16 dev_port, temp1, temp2; 6900 uint32 value32; 6901 phy_ctrl_t *pc; 6902 6903 pc = EXT_PHY_SW_STATE(unit, port); 6904 6905 /*********************************************************************** 6906 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 6907 * To access TOP level registers use phy_id of port0. Override this ports 6908 */ 6909 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 6910 6911 /* Dev port numbers from 0-7 */ 6912 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 6913 6914 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 6915 of the device. For example to enable autogrEEEn on port0, 6916 rdb register for port 4 0x808 need to be used. 6917 Refer package configuration document. 6918 */ 6919 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 6920 dev_port += 4; 6921 } 6922 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 6923 PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc); /* set RDB register access mode */ 6924 #endif 6925 6926 switch ( type ) { 6927 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 6928 /* TOP_1588_HEARTBEAT, Heartbeat (48 bits), RDB.0xa86-0xa88 */ 6929 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 6930 /* TOP_1588_TIME_STAMP, Tx Timestamp (48 bits), RDB.0xa89-0xa8b */ 6931 return SOC_E_FAIL; /* read-only registers */ 6932 6933 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 6934 /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE */ 6935 SOC_IF_ERROR_BREAK( 6936 phy_bcm542xx_rdb_reg_modify(unit, pc, 6937 PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, 6938 (COMPILER_64_LO(value) & 0x0f) << 2, (0x0f << 2)), rv ); 6939 break; 6940 6941 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 6942 /* TOP_1588_NSE_NCO_1, NSE_REG_NCO_FREQCNTR (32 bits), RDB.0xa73-0xa74 */ 6943 SOC_IF_ERROR_BREAK( 6944 phy_bcm542xx_rdb_reg_write(unit, pc, /* LSB 16 bits */ 6945 PHY_BCM542XX_TOP_1588_NSE_NCO_1_0_REG_OFFSET, 6946 (uint16) (COMPILER_64_LO(value) & 0xffff)), rv ); 6947 SOC_IF_ERROR_BREAK( 6948 phy_bcm542xx_rdb_reg_write(unit, pc, /* MSB 16 bits */ 6949 PHY_BCM542XX_TOP_1588_NSE_NCO_1_1_REG_OFFSET, 6950 (uint16) ((COMPILER_64_LO(value) >> 16) & 0xffff)), rv); 6951 break; 6952 6953 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 6954 /* TOP_1588_NSE_NCO_2, Local Time (44 bits), RDB.0xa75-0xa77 */ 6955 SOC_IF_ERROR_BREAK( 6956 phy_bcm542xx_rdb_reg_write(unit, pc, 6957 PHY_BCM542XX_TOP_1588_NSE_NCO_2_0_REG_OFFSET, 6958 (uint16) (COMPILER_64_LO(value) & 0xffff)), rv ); 6959 SOC_IF_ERROR_BREAK( 6960 phy_bcm542xx_rdb_reg_write(unit, pc, 6961 PHY_BCM542XX_TOP_1588_NSE_NCO_2_1_REG_OFFSET, 6962 (uint16) ((COMPILER_64_LO(value) >> 16) & 0xffff)), rv); 6963 SOC_IF_ERROR_BREAK( 6964 phy_bcm542xx_rdb_reg_modify(unit, pc, 6965 PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET, 6966 (uint16) (COMPILER_64_HI(value) & 0xfff), 0xfff), rv ); 6967 break; 6968 6969 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 6970 temp1 = temp2 = 0; 6971 value32 = COMPILER_64_LO(value); 6972 6973 if ( value32 & SOC_PORT_PHY_TIMESYNC_TN_LOAD ) { 6974 temp1 |= BIT(11); 6975 } 6976 if ( value32 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD ) { 6977 temp2 |= BIT(11); 6978 } 6979 if ( value32 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD ) { 6980 temp1 |= BIT(10); 6981 } 6982 if ( value32 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD ) { 6983 temp2 |= BIT(10); 6984 } 6985 if ( value32 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD ) { 6986 temp1 |= BIT(9); 6987 } 6988 if ( value32 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD ) { 6989 temp2 |= BIT(9); 6990 } 6991 if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD ) { 6992 temp1 |= BIT(8); 6993 } 6994 if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD ) { 6995 temp2 |= BIT(8); 6996 } 6997 if ( value32 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD ) { 6998 temp1 |= BIT(7); 6999 } 7000 if ( value32 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD ) { 7001 temp2 |= BIT(7); 7002 } 7003 if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD ) { 7004 temp1 |= BIT(6); 7005 } 7006 if ( value32 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD ) { 7007 temp2 |= BIT(6); 7008 } 7009 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD ) { 7010 temp1 |= BIT(5); 7011 } 7012 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD ) { 7013 temp2 |= BIT(5); 7014 } 7015 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD ) { 7016 temp1 |= BIT(4); 7017 } 7018 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD ) { 7019 temp2 |= BIT(4); 7020 } 7021 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD ) { 7022 temp1 |= BIT(3); 7023 } 7024 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD ) { 7025 temp2 |= BIT(3); 7026 } 7027 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD ) { 7028 temp1 |= BIT(2); 7029 } 7030 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD ) { 7031 temp2 |= BIT(2); 7032 } 7033 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD ) { 7034 temp1 |= BIT(1); 7035 } 7036 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD ) { 7037 temp2 |= BIT(1); 7038 } 7039 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD ) { 7040 temp1 |= BIT(0); 7041 } 7042 if ( value32 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD ) { 7043 temp2 |= BIT(0); 7044 } 7045 7046 SOC_IF_ERROR_BREAK( 7047 phy_bcm542xx_rdb_reg_write(unit, pc, 7048 PHY_BCM542XX_TOP_1588_SHD_LD_REG_OFFSET , temp1), rv ); 7049 SOC_IF_ERROR_BREAK( 7050 phy_bcm542xx_rdb_reg_write(unit, pc, 7051 PHY_BCM542XX_TOP_1588_SHD_CTL_REG_OFFSET, temp2), rv ); 7052 break; 7053 7054 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 7055 /* disables the interrupt */ 7056 temp1 = 0; 7057 value32 = COMPILER_64_LO(value); 7058 if ( value32 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK) { 7059 temp1 |= BIT((dev_port + 1)); 7060 } 7061 if ( value32 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK) { 7062 temp1 |= BIT(0); 7063 } 7064 SOC_IF_ERROR_BREAK( 7065 phy_bcm542xx_rdb_reg_modify(unit, pc, 7066 PHY_BCM542XX_TOP_1588_INT_MASK_REG_OFFSET, 7067 temp1, BIT((dev_port + 1)) | BIT(0)), rv ); 7068 break; 7069 7070 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 7071 value32 = COMPILER_64_LO(value); 7072 SOC_IF_ERROR_BREAK( 7073 phy_bcm542xx_rdb_reg_write(unit, pc, 7074 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port), 7075 (uint16) (value32 & 0xffff)), rv ); 7076 SOC_IF_ERROR_BREAK( 7077 phy_bcm542xx_rdb_reg_modify(unit, pc, 7078 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 7079 (uint16) ((value32 >> 16) & 0xf ), 7080 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_TX_MSB), rv ); 7081 break; 7082 7083 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 7084 value32 = COMPILER_64_LO(value); 7085 SOC_IF_ERROR_BREAK( 7086 phy_bcm542xx_rdb_reg_write(unit, pc, 7087 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port), 7088 (uint16) (value32 & 0xffff)), rv ); 7089 SOC_IF_ERROR_BREAK( 7090 phy_bcm542xx_rdb_reg_modify(unit, pc, 7091 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 7092 (uint16) ((value32 >> 16) & 0xf), 7093 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_RX_MSB), rv ); 7094 break; 7095 7096 default: 7097 rv = SOC_E_UNAVAIL; 7098 break; 7099 } 7100 7101 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 7102 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */ 7103 #endif 7104 /* NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE */ 7105 /* To access TOP level registers use phy_id of port0. Now restore back */ 7106 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7107 7108 return (rv); 7109 } 7110 7111 /* 7112 * Function: 7113 * phy_bcm542xx_timesync_control_get 7114 * Purpose: 7115 * 7116 * Parameters: 7117 * 7118 * Returns: 7119 */ 7120 int 7121 phy_bcm542xx_timesync_control_get(int unit, soc_port_t port, 7122 soc_port_control_phy_timesync_t type, 7123 uint64 *value) 7124 { 7125 int rv = SOC_E_NONE; 7126 uint32 value32 = 0; 7127 uint16 dev_port, value0, value1, value2; 7128 7129 phy_ctrl_t *pc; 7130 7131 pc = EXT_PHY_SW_STATE(unit, port); 7132 7133 /*********************************************************************** 7134 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 7135 * To access TOP level registers use phy_id of port0. Override this ports 7136 */ 7137 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 7138 7139 /* Dev port numbers from 0-7 */ 7140 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 7141 7142 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 7143 of the device. For example to enable autogrEEEn on port0, 7144 rdb register for port 4 0x808 need to be used. 7145 Refer package configuration document. 7146 */ 7147 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 7148 dev_port += 4; 7149 } 7150 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 7151 PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc); /* set RDB register access mode */ 7152 #endif 7153 7154 switch ( type ) { 7155 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 7156 /* P1588 Control/Debug Register, RDB.0xa8e[11:10] HB_CNTL */ 7157 SOC_IF_ERROR_BREAK( 7158 phy_bcm542xx_rdb_reg_modify(unit, pc, 7159 PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET, 7160 PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_RD_START, 7161 PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_CNTL), rv); 7162 /* TOP_1588_HEARTBEAT, Heartbeat (48 bits), RDB.0xa86-0xa88 */ 7163 SOC_IF_ERROR_BREAK( 7164 phy_bcm542xx_rdb_reg_read(unit, pc, 7165 PHY_BCM542XX_TOP_1588_HEARTBEAT_0_REG_OFFSET, &value0), rv); 7166 SOC_IF_ERROR_BREAK( 7167 phy_bcm542xx_rdb_reg_read(unit, pc, 7168 PHY_BCM542XX_TOP_1588_HEARTBEAT_1_REG_OFFSET, &value1), rv); 7169 SOC_IF_ERROR_BREAK( 7170 phy_bcm542xx_rdb_reg_read(unit, pc, 7171 PHY_BCM542XX_TOP_1588_HEARTBEAT_2_REG_OFFSET, &value2), rv); 7172 /* P1588 Control/Debug Register, RDB.0xa8e[11:10] HB_CNTL */ 7173 SOC_IF_ERROR_BREAK( 7174 phy_bcm542xx_rdb_reg_modify(unit, pc, 7175 PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET, 7176 PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_RD_END, 7177 PHY_BCM542XX_TOP_1588_CNTR_DBG_HB_CNTL), rv); 7178 COMPILER_64_SET( (*value), ((uint32)value2), 7179 (((uint32)value1 << 16) | ((uint32)value0)) ); 7180 break; 7181 7182 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 7183 /* P1588 Control/Debug Register, RDB.0xa8e[9:7] TS_SLICE_SEL */ 7184 SOC_IF_ERROR_BREAK( 7185 phy_bcm542xx_rdb_reg_modify(unit, pc, 7186 PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET, 7187 (dev_port << CNTR_DBG_TS_SLICE_SEL_SHIFT), 7188 PHY_BCM542XX_TOP_1588_CNTR_DBG_TS_SLICE_SEL), rv); 7189 /* P1588 Timestamp READ START/END Register, RDB.0xa85 */ 7190 SOC_IF_ERROR_BREAK( 7191 phy_bcm542xx_rdb_reg_write(unit, pc, 7192 PHY_BCM542XX_TOP_1588_TS_RD_START_END_REG_OFFSET, 7193 PHY_BCM542XX_TOP_1588_TS_RD_START(dev_port)), rv); 7194 7195 /* TOP_1588_TIME_STAMP, Tx Timestamp (48 bits), RDB.0xa89-0xa8b */ 7196 SOC_IF_ERROR_BREAK( 7197 phy_bcm542xx_rdb_reg_read(unit, pc, 7198 PHY_BCM542XX_TOP_1588_TIMESTAMP_0_REG_OFFSET, &value0), rv); 7199 SOC_IF_ERROR_BREAK( 7200 phy_bcm542xx_rdb_reg_read(unit, pc, 7201 PHY_BCM542XX_TOP_1588_TIMESTAMP_1_REG_OFFSET, &value1), rv); 7202 SOC_IF_ERROR_BREAK( 7203 phy_bcm542xx_rdb_reg_read(unit, pc, 7204 PHY_BCM542XX_TOP_1588_TIMESTAMP_2_REG_OFFSET, &value2), rv); 7205 SOC_IF_ERROR_BREAK( 7206 7207 /* P1588 Timestamp READ START/END Register, RDB.0xa85 */ 7208 phy_bcm542xx_rdb_reg_write(unit, pc, 7209 PHY_BCM542XX_TOP_1588_TS_RD_START_END_REG_OFFSET, 7210 PHY_BCM542XX_TOP_1588_TS_RD_END(dev_port)), rv); 7211 SOC_IF_ERROR_BREAK( 7212 phy_bcm542xx_rdb_reg_write(unit, pc, 7213 PHY_BCM542XX_TOP_1588_TS_RD_START_END_REG_OFFSET, 0), rv); 7214 7215 COMPILER_64_SET( (*value), ((uint32)value2), 7216 (((uint32)value1 << 16) | ((uint32)value0)) ); 7217 break; 7218 7219 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 7220 /* P1588 NSE DPLL NCO Register 6, RDB.0xA7F[5:2] FRAMESYNC_MODE */ 7221 SOC_IF_ERROR_BREAK( 7222 phy_bcm542xx_rdb_reg_read(unit, pc, 7223 PHY_BCM542XX_TOP_1588_NSE_NCO_6_REG_OFFSET, &value0), rv); 7224 COMPILER_64_SET( (*value), 0, ((uint32) value0 >> 2) & 0x0f ); 7225 break; 7226 7227 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 7228 /* TOP_1588_NSE_NCO_1, NSE_REG_NCO_FREQCNTR (32 bits), RDB.0xa73-0xa74 */ 7229 SOC_IF_ERROR_BREAK( 7230 phy_bcm542xx_rdb_reg_read(unit, pc, 7231 PHY_BCM542XX_TOP_1588_NSE_NCO_1_0_REG_OFFSET, &value0), rv); 7232 SOC_IF_ERROR_BREAK( 7233 phy_bcm542xx_rdb_reg_read(unit, pc, 7234 PHY_BCM542XX_TOP_1588_NSE_NCO_1_1_REG_OFFSET, &value1), rv); 7235 COMPILER_64_SET( (*value), ((uint32) 0), 7236 (((uint32)value1 << 16) | ((uint32)value0)) ); 7237 break; 7238 7239 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 7240 /* TOP_1588_NSE_NCO_2, Local Time (44 bits), RDB.0xa75-0xa77 */ 7241 SOC_IF_ERROR_BREAK( 7242 phy_bcm542xx_rdb_reg_read(unit, pc, 7243 PHY_BCM542XX_TOP_1588_NSE_NCO_2_0_REG_OFFSET, &value0), rv); 7244 SOC_IF_ERROR_BREAK( 7245 phy_bcm542xx_rdb_reg_read(unit, pc, 7246 PHY_BCM542XX_TOP_1588_NSE_NCO_2_1_REG_OFFSET, &value1), rv); 7247 SOC_IF_ERROR_BREAK( 7248 phy_bcm542xx_rdb_reg_read(unit, pc, 7249 PHY_BCM542XX_TOP_1588_NSE_NCO_2_2_REG_OFFSET, &value2), rv); 7250 COMPILER_64_SET( (*value), (value2 & 0x0fff), /* bit [43:32] */ 7251 ((uint32)value1 << 16) | value0 ); /* bit [31:0] */ 7252 COMPILER_64_SHL((*value), 4); 7253 break; 7254 7255 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 7256 SOC_IF_ERROR_BREAK( 7257 phy_bcm542xx_rdb_reg_read(unit, pc, 7258 PHY_BCM542XX_TOP_1588_SHD_LD_REG_OFFSET , &value1), rv); 7259 SOC_IF_ERROR_BREAK( 7260 phy_bcm542xx_rdb_reg_read(unit, pc, 7261 PHY_BCM542XX_TOP_1588_SHD_CTL_REG_OFFSET, &value2), rv); 7262 7263 if ( value1 & BIT(11) ) { 7264 value32 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD; 7265 } 7266 if ( value2 & BIT(11) ) { 7267 value32 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD; 7268 } 7269 if ( value1 & BIT(10) ) { 7270 value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD; 7271 } 7272 if ( value2 & BIT(10) ) { 7273 value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD; 7274 } 7275 if ( value1 & BIT(9) ) { 7276 value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD; 7277 } 7278 if ( value2 & BIT(9) ) { 7279 value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD; 7280 } 7281 if ( value1 & BIT(8) ) { 7282 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD; 7283 } 7284 if ( value1 & BIT(8) ) { 7285 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD; 7286 } 7287 if ( value1 & BIT(7) ) { 7288 value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD; 7289 } 7290 if ( value1 & BIT(7) ) { 7291 value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD; 7292 } 7293 if ( value1 & BIT(6) ) { 7294 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD; 7295 } 7296 if ( value2 & BIT(6) ) { 7297 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD; 7298 } 7299 if ( value1 & BIT(5) ) { 7300 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD; 7301 } 7302 if ( value2 & BIT(5) ) { 7303 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD; 7304 } 7305 if ( value1 & BIT(4) ) { 7306 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD; 7307 } 7308 if ( value2 & BIT(4) ) { 7309 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD; 7310 } 7311 if ( value1 & BIT(3) ) { 7312 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD; 7313 } 7314 if ( value2 & BIT(3) ) { 7315 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD; 7316 } 7317 if ( value1 & BIT(2) ) { 7318 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD; 7319 } 7320 if ( value2 & BIT(2) ) { 7321 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD; 7322 } 7323 if ( value1 & BIT(1) ) { 7324 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD; 7325 } 7326 if ( value2 & BIT(1) ) { 7327 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD; 7328 } 7329 if ( value1 & BIT(0) ) { 7330 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD; 7331 } 7332 if ( value2 & BIT(0) ) { 7333 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD; 7334 } 7335 7336 COMPILER_64_SET((*value), (0), (value32)); 7337 break; 7338 7339 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 7340 /* This doesn't clear the interrupts. 7341 To clear read the timestamp. 7342 */ 7343 SOC_IF_ERROR_BREAK( 7344 phy_bcm542xx_rdb_reg_read(unit, pc, 7345 PHY_BCM542XX_TOP_1588_INT_STATUS_REG_OFFSET, &value1), rv); 7346 if ( value1 & BIT((dev_port + 1)) ) { 7347 value32 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT; 7348 } 7349 if ( value1 & BIT(0) ) { 7350 value32 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT; 7351 } 7352 COMPILER_64_SET((*value), (uint32)((value1 >> 1) & 0xff), (value32)); 7353 break; 7354 7355 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 7356 SOC_IF_ERROR_BREAK( 7357 phy_bcm542xx_rdb_reg_read(unit, pc, 7358 PHY_BCM542XX_TOP_1588_INT_MASK_REG_OFFSET, &value1), rv); 7359 if ( value1 & BIT((dev_port + 1)) ) { 7360 value32 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT_MASK; 7361 } 7362 if ( value1 & BIT(0) ) { 7363 value32 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT_MASK; 7364 } 7365 COMPILER_64_SET((*value), (0), (value32)); 7366 break; 7367 7368 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 7369 SOC_IF_ERROR_BREAK( 7370 phy_bcm542xx_rdb_reg_read(unit, pc, 7371 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_LSB(dev_port), 7372 &value1), rv); 7373 SOC_IF_ERROR_BREAK( 7374 phy_bcm542xx_rdb_reg_read(unit, pc, 7375 PHY_BCM542XX_TOP_1588_TX_PORT_N_TS_OFFSET_MSB(dev_port), 7376 &value2), rv); 7377 COMPILER_64_SET((*value), 0, (((value2 & 0xf) << 16) | value1)); 7378 break; 7379 7380 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 7381 SOC_IF_ERROR_BREAK( 7382 phy_bcm542xx_rdb_reg_read(unit, pc, 7383 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_LSB(dev_port), 7384 &value1), rv); 7385 SOC_IF_ERROR_BREAK( 7386 phy_bcm542xx_rdb_reg_read(unit, pc, 7387 PHY_BCM542XX_TOP_1588_RX_PORT_N_TS_OFFSET_MSB(dev_port), 7388 &value2), rv); 7389 COMPILER_64_SET((*value), 0, (((value2 & 0xf) << 16) | value1)); 7390 break; 7391 7392 default: 7393 rv = SOC_E_UNAVAIL; 7394 } 7395 7396 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 7397 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */ 7398 #endif 7399 /* NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE */ 7400 /* To access TOP level registers use phy_id of port0. Now restore back */ 7401 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7402 7403 return (rv); 7404 } 7405 7406 STATIC int 7407 _phy_phy542xx_inband_timesync_get_msg_type(uint16 value, 7408 soc_port_phy_timesync_msg_t *msg_type) { 7409 value = (value >> PHY_BCM542XX_TOP_1588_TS_INFO_MSG_TYPE_SHIFT) 7410 & PHY_BCM542XX_TOP_1588_TS_INFO_MSG_TYPE; 7411 switch(value) { 7412 case 0: 7413 *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_SYNC; 7414 break; 7415 case 1: 7416 *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_DELAY_REQ; 7417 break; 7418 case 2: 7419 *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_PDELAY_REQ; 7420 break; 7421 case 3: 7422 *msg_type = SOC_PORT_PHY_TIMESYNC_MSG_PDELAY_RESP; 7423 break; 7424 default: 7425 return SOC_E_UNAVAIL; 7426 } 7427 return SOC_E_NONE; 7428 } 7429 7430 STATIC int 7431 _phy_phy542xx_inband_timesync_get_protocol(uint16 value, 7432 soc_port_phy_timesync_prot_t *protocol) { 7433 value = (value >> PHY_BCM542XX_TOP_1588_TS_INFO_DOMAIN_NUM_SHIFT) 7434 & PHY_BCM542XX_TOP_1588_TS_INFO_DOMAIN_NUM; 7435 switch(value) { 7436 case 0: 7437 *protocol = SOC_PORT_PHY_TIMESYNC_PROT_LAYER2; 7438 break; 7439 case 1: 7440 *protocol = SOC_PORT_PHY_TIMESYNC_PROT_IPV4_UDP; 7441 break; 7442 case 2: 7443 *protocol = SOC_PORT_PHY_TIMESYNC_PROT_IPV6_UDP; 7444 break; 7445 default: 7446 return SOC_E_UNAVAIL; 7447 } 7448 return SOC_E_NONE; 7449 } 7450 7451 STATIC int 7452 phy_bcm542xx_timesync_enhanced_capture_get(int unit, soc_port_t port, 7453 soc_port_phy_timesync_enhanced_capture_t *value) { 7454 uint16 dev_port, value0, value1, value2, value3; 7455 phy_ctrl_t *pc; 7456 uint16 data16 = 0; 7457 7458 pc = EXT_PHY_SW_STATE(unit, port); 7459 7460 /*********************************************************************** 7461 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 7462 * To access TOP level registers use phy_id of port0. Override this ports 7463 */ 7464 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 7465 7466 /* Dev port numbers from 0-7 */ 7467 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 7468 7469 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 7470 of the device. For example to enable autogrEEEn on port0, 7471 rdb register for port 4 0x808 need to be used. 7472 Refer package configuration document. 7473 */ 7474 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 7475 dev_port += 4; 7476 } 7477 7478 /* MSG_TYPE, PROTOCOL, DIRECTION */ 7479 SOC_IF_ERROR_RETURN( 7480 phy_bcm542xx_direct_reg_modify(unit, pc, 7481 PHY_BCM542XX_TOP_1588_CNTR_DBG_REG_OFFSET, 7482 (dev_port << CNTR_DBG_TS_SLICE_SEL_SHIFT), 7483 PHY_BCM542XX_TOP_1588_CNTR_DBG_TS_SLICE_SEL) ); 7484 7485 SOC_IF_ERROR_RETURN( 7486 phy_bcm542xx_direct_reg_read(unit, pc, 7487 PHY_BCM542XX_TOP_1588_TS_INFO_1_REG_OFFSET, &value0) ); 7488 SOC_IF_ERROR_RETURN( 7489 _phy_phy542xx_inband_timesync_get_msg_type(value0, &value->msg_type) ); 7490 SOC_IF_ERROR_RETURN( 7491 _phy_phy542xx_inband_timesync_get_protocol(value0, &value->protocol) ); 7492 7493 value->direction = ( ((value0 >> PHY_BCM542XX_TOP_1588_TS_INFO_DIR_SHIFT) 7494 & PHY_BCM542XX_TOP_1588_TS_INFO_DIR) == 0 ) 7495 ? SOC_PORT_PHY_TIMESYNC_DIR_EGRESS 7496 : SOC_PORT_PHY_TIMESYNC_DIR_INGRESS; 7497 /* SEQ_ID */ 7498 SOC_IF_ERROR_RETURN( 7499 phy_bcm542xx_direct_reg_read(unit, pc, 7500 PHY_BCM542XX_TOP_1588_TS_INFO_2_REG_OFFSET, &value0) ); 7501 value->seq_id = (value0 >> PHY_BCM542XX_TOP_1588_TS_INFO_SEQ_ID_SHIFT) 7502 & PHY_BCM542XX_TOP_1588_TS_INFO_SEQ_ID; 7503 7504 /* DOMAIN */ 7505 7506 /* TIMESTAMP */ 7507 7508 /* SRC PORT ID selected? */ 7509 SOC_IF_ERROR_RETURN( 7510 phy_bcm542xx_direct_reg_read(unit, pc, 7511 PHY_BCM542XX_TOP_1588_LABEL_N_MSB_MASK_REG_OFFSET(dev_port), 7512 &data16) ); 7513 7514 if ( data16 & PHY_BCM542XX_TOP_1588_CAP_SRC_PORT_CLK_ID ) { 7515 SOC_IF_ERROR_RETURN( 7516 phy_bcm542xx_direct_reg_read(unit, pc, 7517 PHY_BCM542XX_TOP_1588_TS_INFO_3_REG_OFFSET, &value0) ); 7518 value0 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_1; 7519 SOC_IF_ERROR_RETURN( 7520 phy_bcm542xx_direct_reg_read(unit, pc, 7521 PHY_BCM542XX_TOP_1588_TS_INFO_4_REG_OFFSET, &value1) ); 7522 value1 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_2; 7523 SOC_IF_ERROR_RETURN( 7524 phy_bcm542xx_direct_reg_read(unit, pc, 7525 PHY_BCM542XX_TOP_1588_TS_INFO_5_REG_OFFSET, &value2) ); 7526 value2 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_3; 7527 SOC_IF_ERROR_RETURN( 7528 phy_bcm542xx_direct_reg_read(unit, pc, 7529 PHY_BCM542XX_TOP_1588_TS_INFO_6_REG_OFFSET, &value3) ); 7530 value3 &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_CLK_ID_4; 7531 COMPILER_64_SET( (value->source_port_identity), 7532 (value3 << 16) | value2, 7533 (value1 << 16) | value0 ); 7534 } else { 7535 COMPILER_64_SET((value->source_port_identity), 0, 0); 7536 } 7537 7538 7539 /* SRC PORT */ 7540 SOC_IF_ERROR_RETURN( 7541 phy_bcm542xx_direct_reg_read(unit, pc, 7542 PHY_BCM542XX_TOP_1588_TS_INFO_7_REG_OFFSET, &value0) ); 7543 value->source_port &= PHY_BCM542XX_TOP_1588_TS_INFO_SRC_PORT_NUM; 7544 7545 /* VLAN ID */ 7546 SOC_IF_ERROR_RETURN( 7547 phy_bcm542xx_direct_reg_read(unit, pc, 7548 PHY_BCM542XX_TOP_1588_TS_INFO_8_REG_OFFSET, &value0) ); 7549 value->vlan_id &= PHY_BCM542XX_TOP_1588_TS_INFO_VLAN_ID; 7550 7551 /*********************************************************************** 7552 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 7553 * To access TOP level registers use phy_id of port0. Now restore back 7554 */ 7555 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7556 7557 return SOC_E_NONE; 7558 } 7559 7560 7561 /* 7562 * Function: 7563 * phy_54280_cable_diag_dispatch 7564 * Purpose: 7565 * Run 54280 cable diagnostics 7566 * Parameters: 7567 * unit - device number 7568 * port - port number 7569 * status - (OUT) cable diagnotic status structure 7570 * Returns: 7571 * SOC_E_XXX 7572 */ 7573 STATIC int 7574 phy_54280_cable_diag_dispatch(int unit, soc_port_t port, 7575 soc_port_cable_diag_t *status) 7576 { 7577 /* ECD_CTRL : break link */ 7578 uint16 ecd_ctrl = 0x1000; 7579 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 7580 7581 /* ECD functions use legacy register addressing mode */ 7582 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); 7583 7584 7585 SOC_IF_ERROR_RETURN( 7586 phy_ecd_cable_diag_init_40nm(unit, port)); 7587 7588 SOC_IF_ERROR_RETURN( 7589 phy_ecd_cable_diag_40nm(unit, port, status, ecd_ctrl)); 7590 7591 PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc); 7592 return SOC_E_NONE; 7593 } 7594 7595 /* 7596 * Function: 7597 * phy_bcm542xx_clock_enable_set 7598 * Purpose: 7599 * SyncE primary/secondary recovery clodk 7600 * Parameters: 7601 * bit_shift : 0 for primary, 4 for secondary 7602 * Returns: 7603 */ 7604 int 7605 phy_bcm542xx_clock_enable_set(int unit, phy_ctrl_t *pc, 7606 int bit_shift, uint32 enable) 7607 { 7608 int rv = SOC_E_NONE; 7609 uint16 data = 0; 7610 int dev_port; 7611 7612 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 7613 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 7614 of the device. For example to enable autogrEEEn on port0, 7615 rdb register for port 4 0x808 need to be used. 7616 Refer package configuration document. 7617 */ 7618 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 7619 dev_port += 4; 7620 } 7621 7622 /* act on the 1st port of this chip */ 7623 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 7624 7625 /* SyncE Recovery Clock Registe, RDB.0x83c *\ 7626 |* bit[7]: disable secondary, bit[6:4] source of secondary clock *| 7627 \* bit[3]: disable primary , bit[2:0] source of primary clock */ 7628 data = (enable) 7629 ? ((dev_port & PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_SEL) 7630 << bit_shift) 7631 : ((bit_shift == 0) ? (PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK1_DIS) 7632 : (PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK2_DIS)); 7633 /* Set bit[14]: primary recovery clock, bit[13]: secondary recovery clock for BCM54292*/ 7634 if(enable && (PHY_IS_BCM54292(pc))) { 7635 data |= ((bit_shift == 0) ? PHY_BCM542XX_SYNCE_RECOVERY_CLK1_EN 7636 : PHY_BCM542XX_SYNCE_RECOVERY_CLK2_EN); 7637 } 7638 7639 /* write to SYNCE Recovery Clock Registe, RDB 0x83c */ 7640 if (PHY_IS_BCM54292(pc)) { 7641 rv = phy_bcm542xx_direct_reg_modify( unit, pc, 7642 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, data, 7643 ((PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_MASK << bit_shift) | 7644 ((bit_shift == 0) ? PHY_BCM542XX_SYNCE_RECOVERY_CLK1_EN : PHY_BCM542XX_SYNCE_RECOVERY_CLK2_EN))); 7645 } else { 7646 rv = phy_bcm542xx_direct_reg_modify( unit, pc, 7647 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, data, 7648 (PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_MASK << bit_shift)); 7649 } 7650 7651 /* resume to the original phy id */ 7652 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7653 return rv; 7654 } 7655 7656 /* 7657 * Function: 7658 * phy_bcm542xx_clock_enable_get 7659 * Purpose: 7660 * SyncE primary/secondary recovery clock 7661 * Parameters: 7662 * bit_shift : 0 for primary, 4 for secondary 7663 * Returns: 7664 */ 7665 int 7666 phy_bcm542xx_clock_enable_get(int unit, phy_ctrl_t *pc, 7667 int bit_shift, uint32 *value) 7668 { 7669 int rv = SOC_E_NONE; 7670 uint16 data = 0; 7671 int dev_port; 7672 7673 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 7674 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 7675 of the device. For example to enable autogrEEEn on port0, 7676 rdb register for port 4 0x808 need to be used. 7677 Refer package configuration document. 7678 */ 7679 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 7680 dev_port += 4; 7681 } 7682 7683 /* act on the 1st port of this chip */ 7684 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 7685 7686 /* read from SYNCE Recovery Clock Registe, RDB 0x83c */ 7687 rv = phy_bcm542xx_direct_reg_read( unit, pc, 7688 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, &data ); 7689 7690 /* resume to the original phy id */ 7691 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7692 7693 /* SyncE Recovery Clock Registe, RDB.0x83c *\ 7694 |* bit[7]: disable secondary, bit[6:4] source of secondary clock *| 7695 \* bit[3]: disable primary , bit[2:0] source of primary clock */ 7696 data >>= bit_shift; 7697 *value = ( (data & PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_DIS) || 7698 ((data & PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK_SEL) != dev_port) ) 7699 ? FALSE : TRUE; 7700 return rv; 7701 } 7702 7703 /* 7704 * Function: 7705 * phy_bcm542xx_clock_control_set 7706 * Purpose: 7707 * Parameters: 7708 * Returns: 7709 */ 7710 STATIC int 7711 _phy_bcm542xx_clock_control_set(int unit, phy_ctrl_t *pc, 7712 uint16 mask, uint32 value) 7713 { 7714 int rv = SOC_E_NONE; 7715 7716 /* act on the 1st port of this chip */ 7717 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 7718 7719 /* TOP_MISCREG_SYNCE - SYNCE Recovery Clock Registe, RDB.0x83c */ 7720 rv = phy_bcm542xx_direct_reg_modify(unit, pc, 7721 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, 7722 ((value) ? mask : 0), mask ); 7723 /* resume to the original phy id */ 7724 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7725 return rv; 7726 } 7727 7728 /* 7729 * Function: 7730 * phy_bcm542xx_clock_control_get 7731 * Purpose: 7732 * Parameters: 7733 * Returns: 7734 */ 7735 STATIC int 7736 _phy_bcm542xx_clock_control_get(int unit, phy_ctrl_t *pc, 7737 uint16 mask, uint32 *value) 7738 { 7739 int rv = SOC_E_NONE; 7740 uint16 data; 7741 7742 /* act on the 1st port of this chip */ 7743 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 7744 7745 /* TOP_MISCREG_SYNCE - SYNCE Recovery Clock Registe, RDB.0x83c */ 7746 rv = phy_bcm542xx_direct_reg_read( unit, pc, 7747 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_OFFSET, &data ); 7748 *value = (data & mask) ? TRUE : FALSE; 7749 7750 /* resume to the original phy id */ 7751 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7752 return rv; 7753 } 7754 7755 /* 7756 * Function: 7757 * phy_bcm542xx_power_mode_set 7758 * Purpose: 7759 * Parameters: 7760 * Returns: 7761 */ 7762 int 7763 phy_bcm542xx_power_mode_set(int unit, phy_ctrl_t *pc, int mode) 7764 { 7765 if ( pc->power_mode == mode) { 7766 return SOC_E_NONE; 7767 } 7768 7769 if (mode == SOC_PHY_CONTROL_POWER_LOW) { 7770 /* enable dsp clock */ 7771 PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 7772 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK, 7773 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK); 7774 7775 if (1) { /* CHECK if the interface is SGMII? */ 7776 /* Select mode: SGMII->Copper */ 7777 phy_bcm542xx_direct_reg_modify(unit, pc, 7778 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 7779 PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL 7780 & MODE_SELECT_SGMII_2_COPPER, 7781 PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL); 7782 7783 /* Power down SGMII Interface */ 7784 phy_bcm542xx_direct_reg_modify(unit, pc, 7785 PHY_BCM542XX_SGMII_CONTROL_REG_OFFSET, 7786 PHY_BCM542XX_SGMII_CONTROL_REG_POWER_DOWN, 7787 PHY_BCM542XX_SGMII_CONTROL_REG_POWER_DOWN); 7788 } 7789 7790 /* disable dsp clock */ 7791 PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 0x00, 7792 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK); 7793 7794 } else if (mode == SOC_PHY_CONTROL_POWER_FULL) { 7795 /* enable dsp clock */ 7796 PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 7797 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK, 7798 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK); 7799 7800 if (1) { /* CHECK if the interface is SGMII? */ 7801 /* Select mode: SGMII->Copper */ 7802 phy_bcm542xx_direct_reg_modify(unit, pc, 7803 PHY_BCM542XX_MODE_CONTROL_REG_OFFSET, 7804 PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL 7805 & MODE_SELECT_SGMII_2_COPPER, 7806 PHY_BCM542XX_MODE_CONTROL_REG_MODE_SEL); 7807 7808 /* Normal operation mode - disable power down - SGMII Interface */ 7809 phy_bcm542xx_direct_reg_modify(unit, pc, 7810 PHY_BCM542XX_SGMII_CONTROL_REG_OFFSET, 7811 0x00, 7812 PHY_BCM542XX_SGMII_CONTROL_REG_POWER_DOWN); 7813 } 7814 7815 /* disable dsp clock */ 7816 PHY_MODIFY_BCM542XX_MII_AUX_CTRLr(unit, pc, 0x00, 7817 PHY_BCM542XX_MII_AUX_CTRL_REG_EN_DSP_CLK); 7818 7819 /* disable the auto power mode */ 7820 phy_bcm542xx_direct_reg_modify( unit, pc, 7821 PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 7822 0x00, 7823 PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE); 7824 } else if (mode == SOC_PHY_CONTROL_POWER_AUTO) { 7825 phy_bcm542xx_direct_reg_modify( unit, pc, 7826 PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 7827 PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE, 7828 PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE); 7829 } else if (mode == SOC_PHY_CONTROL_POWER_AUTO_DISABLE) { 7830 phy_bcm542xx_direct_reg_modify( unit, pc, 7831 PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 7832 0, 7833 PHY_BCM542XX_POWER_AUTO_DOWN_REG_APD_MODE); 7834 } else { 7835 return SOC_E_UNAVAIL; 7836 } 7837 7838 pc->power_mode = mode; 7839 return SOC_E_NONE; 7840 } 7841 7842 /* 7843 * Function: 7844 * phy_bcm542xx_power_auto_wake_time_set 7845 * Purpose: 7846 * Parameters: 7847 * Returns: 7848 */ 7849 int 7850 phy_bcm542xx_power_auto_wake_time_set(int unit, phy_ctrl_t *pc, int value) 7851 { 7852 value = (value < PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_MAX)? value : PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_MAX; 7853 /* at least one unit */ 7854 value = (value < PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT)? PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT : value; 7855 7856 phy_bcm542xx_direct_reg_modify(unit, pc, 7857 PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 7858 PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL 7859 & (value/PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT), 7860 PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL); 7861 7862 return SOC_E_NONE; 7863 } 7864 7865 /* 7866 * Function: 7867 * phy_bcm542xx_power_auto_wake_time_get 7868 * Purpose: 7869 * Parameters: 7870 * Returns: 7871 */ 7872 int 7873 phy_bcm542xx_power_auto_wake_time_get(int unit, phy_ctrl_t *pc, uint32 *value) 7874 { 7875 uint16 data; 7876 phy_bcm542xx_direct_reg_read(unit, pc, 7877 PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, &data); 7878 7879 data &= PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL; 7880 *value = data * PHY_BCM542XX_AUTO_PWRDWN_WAKEUP_UNIT; 7881 return SOC_E_NONE; 7882 } 7883 7884 /* 7885 * Function: 7886 * phy_bcm542xx_power_auto_sleep_time_set 7887 * Purpose: 7888 * Parameters: 7889 * Returns: 7890 */ 7891 int 7892 phy_bcm542xx_power_auto_sleep_time_set(int unit, phy_ctrl_t *pc, int value) 7893 { 7894 /* sleep time configuration is either 2.7s or 5.4 s, default is 2.7s */ 7895 value = (value < PHY_BCM542XX_AUTO_PWRDWN_SLEEP_MAX)? 0x00 : PHY_BCM542XX_POWER_AUTO_DOWN_REG_WAKE_UP_TIMER_SEL; 7896 phy_bcm542xx_direct_reg_modify( unit, pc, 7897 PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, 7898 value, 7899 PHY_BCM542XX_POWER_AUTO_DOWN_REG_SLEEP_TIMER_SEL); 7900 7901 return SOC_E_NONE; 7902 } 7903 7904 /* 7905 * Function: 7906 * phy_bcm542xx_power_auto_sleep_time_get 7907 * Purpose: 7908 * Parameters: 7909 * Returns: 7910 */ 7911 int 7912 phy_bcm542xx_power_auto_sleep_time_get(int unit, phy_ctrl_t *pc, uint32 *value) 7913 { 7914 uint16 data; 7915 phy_bcm542xx_direct_reg_read(unit, pc, 7916 PHY_BCM542XX_POWER_AUTO_DOWN_REG_OFFSET, &data); 7917 7918 *value = (data & PHY_BCM542XX_POWER_AUTO_DOWN_REG_SLEEP_TIMER_SEL) 7919 ? PHY_BCM542XX_AUTO_PWRDWN_SLEEP_MAX 7920 : PHY_BCM542XX_AUTO_PWRDWN_SLEEP_MIN; 7921 7922 return SOC_E_NONE; 7923 } 7924 7925 /* 7926 * Function: 7927 * phy_bcm542xx_eee_enable 7928 * Purpose: 7929 * Enable or disable EEE (Native) 7930 * Parameters: 7931 * unit - StrataSwitch unit #. 7932 * port - StrataSwitch port #. 7933 * mode - 0:Native EEE or 1:AutogrEEEn 7934 * enable - 1:Enable or 0:disable 7935 * Returns: 7936 * SOC_E_NONE 7937 */ 7938 int 7939 phy_bcm542xx_eee_enable(int unit, soc_port_t port, int mode, int enable) 7940 { 7941 int dev_port; 7942 phy_ctrl_t *pc; 7943 7944 if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 7945 return ( SOC_E_UNAVAIL ); 7946 } 7947 pc = EXT_PHY_SW_STATE(unit, port); 7948 7949 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); /* Dev port numbers from 0-7 */ 7950 7951 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 *\ 7952 | of the device. For example to enable autogrEEEn on port0, | 7953 | rdb register for port 4 0x808 need to be used. | 7954 \* Refer package configuration document. */ 7955 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 7956 dev_port += 4; 7957 } 7958 7959 if ( enable ) { 7960 soc_port_ability_t abi = { 0 }; 7961 /* Enable EEE 7962 * 1. Enable EEE mode 7963 * 2. Advertise EEE auto-negotiation capabilities 7964 * < Normal auto-negotiation properties > 7965 * < Enable optional variable/fixed latency modes > if AutogrEEEn 7966 * 3. Intiate auto-negotiation 7967 * 4. Enable AutogrEEEn / Native EEE 7968 */ 7969 7970 /* Enable EEE mode */ 7971 SOC_IF_ERROR_RETURN( /* 7.0x803D[15:14] */ 7972 PHY_MODIFY_BCM542XX_EEE_803Dr(unit, pc, 0xc000, 0xc000) ); 7973 /* Advertise EEE Auto Negotiation Capabilities */ 7974 SOC_IF_ERROR_RETURN( phy_bcm542xx_ability_advert_get(unit, port, &abi) ); 7975 abi.eee |= (SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 7976 SOC_IF_ERROR_RETURN( phy_bcm542xx_ability_advert_set(unit, port, &abi) ); 7977 /* Initiate Auto Negotiation */ 7978 SOC_IF_ERROR_RETURN( phy_bcm542xx_autoneg_set(unit, port, TRUE) ); 7979 7980 if ( SOC_PHY_CONTROL_EEE_AUTO == mode ) { /* AutogrEEEn mode */ 7981 /*********************************************************************** 7982 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 7983 * To access TOP level registers use phy_id of port0. Override this ports 7984 */ 7985 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 7986 7987 phy_bcm542xx_direct_reg_modify(unit, pc, 7988 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 7989 PHY_BCM542XX_TOP_MISC_MII_BUFF_EN, 7990 PHY_BCM542XX_TOP_MISC_MII_BUFF_EN); 7991 /*********************************************************************** 7992 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 7993 * To access TOP level registers use phy_id of port0. Now restore back 7994 */ 7995 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 7996 } 7997 /* 7998 Enable stat counters 7999 Clear BIT14 to get lower 16bits of the counters 8000 */ 8001 SOC_IF_ERROR_RETURN( 8002 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 8003 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN, 8004 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN 8005 | PHY_BCM542XX_EEE_STAT_CTRL_SATURATE_MODE) ); 8006 8007 } else { /* enable == 0 */ 8008 /* Disable EEE mode */ 8009 SOC_IF_ERROR_RETURN( /* 7.0x803D[15:14] */ 8010 PHY_MODIFY_BCM542XX_EEE_803Dr(unit, pc, 0x0000, 0xc000) ); 8011 phy_bcm542xx_autoneg_set(unit, port, 1); 8012 8013 if ( SOC_PHY_CONTROL_EEE_AUTO == mode ) { /* AutogrEEEn mode */ 8014 /*********************************************************************** 8015 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 8016 * To access TOP level registers use phy_id of port0. Override this ports 8017 */ 8018 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 8019 8020 phy_bcm542xx_direct_reg_modify(unit, pc, 8021 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 8022 0x00, 8023 PHY_BCM542XX_TOP_MISC_MII_BUFF_EN); 8024 /*********************************************************************** 8025 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8026 * To access TOP level registers use phy_id of port0. Now restore back 8027 */ 8028 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8029 } 8030 /* Reset stat counters */ 8031 SOC_IF_ERROR_RETURN( 8032 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 8033 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET, 8034 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET) ); 8035 /* Disable stat counters */ 8036 SOC_IF_ERROR_RETURN( 8037 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 0, 8038 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET 8039 | PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN) ); 8040 } 8041 8042 return SOC_E_NONE; 8043 } 8044 8045 STATIC int 8046 _phy_bcm542xx_get_eee_control_status(int unit, phy_ctrl_t *pc, uint32 *value) 8047 { 8048 int rv = SOC_E_NONE; 8049 uint16 temp16 = 0; 8050 8051 rv = PHY_READ_BCM542XX_EEE_803Dr(unit, pc,&temp16); /* 7.803d */ 8052 *value = ((temp16 & 0xC000) == 0xC000) ? 1 : 0; 8053 return rv; 8054 } 8055 8056 STATIC int 8057 _phy_bcm542xx_get_auto_eee_control_status(int unit, soc_port_t port, 8058 uint32 *value) 8059 { 8060 int rv = SOC_E_NONE; 8061 uint16 temp16 = 0; 8062 int dev_port; 8063 phy_ctrl_t *pc; 8064 8065 pc = EXT_PHY_SW_STATE(unit, port); 8066 /* Dev port numbers from 0-7 */ 8067 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 8068 8069 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 8070 of the device. For example to enable autogrEEEn on port0, 8071 rdb register for port 4 0x808 need to be used. 8072 Refer package configuration document. 8073 */ 8074 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 8075 dev_port += 4; 8076 } 8077 8078 /*********************************************************************** 8079 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 8080 * To access TOP level registers use phy_id of port0. Override this ports 8081 */ 8082 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 8083 /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */ 8084 rv = phy_bcm542xx_direct_reg_read(unit, pc, /* bit[0] MII_BUFFER_ENABLE */ 8085 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 8086 &temp16); 8087 8088 /*********************************************************************** 8089 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8090 * To access TOP level registers use phy_id of port0. Now restore back 8091 */ 8092 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8093 8094 *value = (temp16 & PHY_BCM542XX_TOP_MISC_MII_BUFF_EN)? 1: 0; 8095 return rv; 8096 } 8097 8098 /* 8099 * Function: 8100 * _phy_bcm542xx_eee_counter_get 8101 * Purpose: 8102 * Get the 32-bit value of EEE Statistic counter/timer 8103 * CORE_ExpAA, ExpAB, ExpAC, ExpAD 8104 * Parameters: 8105 * 8106 * Returns: 8107 */ 8108 STATIC int 8109 _phy_bcm542xx_eee_counter_get(int unit, phy_ctrl_t *pc, 8110 uint16 reg_addr, uint32 *value32) 8111 { 8112 uint16 msb1, lsb1, msb2, lsb2; 8113 8114 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 8115 PHY_BCM542XX_RDB_ACCESS_MODE(unit, pc); /* set RDB register access mode */ 8116 #endif 8117 8118 /* CORE_ExpAF - EEE Statistic counters ctrl/status, RDB 0x0af bit[14] */ 8119 /* STATISTIC_UPPER_16BITS_SEL=1 to get the upper 16-bit of counters first */ 8120 SOC_IF_ERROR_RETURN( 8121 phy_bcm542xx_rdb_reg_modify(unit, pc, 8122 PHY_BCM542XX_EEE_STAT_CTRL_REG_OFFSET, 8123 PHY_BCM542XX_EEE_STAT_CTRL_16U_BIT_SEL, 8124 PHY_BCM542XX_EEE_STAT_CTRL_16U_BIT_SEL) ); 8125 /* CORE_ExpAA/AB/AC/AD: EEE Statistic timer/counter, TxRx duration & event*/ 8126 SOC_IF_ERROR_RETURN( 8127 phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &msb1) ); /* upper 16 bits */ 8128 SOC_IF_ERROR_RETURN( 8129 phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &lsb1) ); /* lower 16 bits */ 8130 if ( PHY_IS_BCM54210_220(pc) ) { 8131 *value32 = (((uint32) msb1) << 16) | lsb1; 8132 } else { 8133 /* Workaround for old version of 5428x/29x/220/210 */ 8134 /* read the counter [CORE_ExpAA/AB/AC/AD] four times */ 8135 SOC_IF_ERROR_RETURN( 8136 phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &msb2) ); 8137 SOC_IF_ERROR_RETURN( 8138 phy_bcm542xx_rdb_reg_read(unit, pc, reg_addr, &lsb2) ); 8139 /* form the 32-bit value by concatenating the upper & lower 16 bits */ 8140 /* see the 'NOTE' section of RDB Reg.0x0AF spec */ 8141 /* in BCM54220SE/5428x Programmer's Reference Guide */ 8142 *value32 = ( lsb1 & BIT(15) ) ? (((uint32) msb1) << 16) | lsb1 8143 : (((uint32) msb2) << 16) | lsb1; 8144 } 8145 8146 #ifdef PHY_BCM542XX_DEFAULT_TO_LEGACY_ADDRESSING 8147 PHY_BCM542XX_LEGACY_ACCESS_MODE(unit, pc); /* legacy register access mode */ 8148 #endif 8149 return (SOC_E_NONE); 8150 } 8151 8152 /* 8153 * Function: 8154 * phy_bcm542xx_eee_control_set 8155 * Purpose: 8156 * Implements different 'setting' controls 8157 * for EEE 8158 * Parameters: 8159 * phy_id - PHY's device address 8160 * type - type of control 8161 * value - helps decide what needs to be 8162 * for the control type 'type' 8163 * Returns: 8164 */ 8165 int 8166 phy_bcm542xx_eee_control_set(int unit, soc_port_t port, soc_phy_control_t type, uint32 value) 8167 { 8168 int rv = SOC_E_NONE; 8169 uint16 temp16 = 0; 8170 int dev_port; 8171 phy_ctrl_t *pc; 8172 8173 if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 8174 return SOC_E_UNAVAIL; 8175 } 8176 pc = EXT_PHY_SW_STATE(unit, port); 8177 /* Dev port numbers from 0-7 */ 8178 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 8179 8180 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 8181 of the device. For example to enable autogrEEEn on port0, 8182 rdb register for port 4 0x808 need to be used. 8183 Refer package configuration document. 8184 */ 8185 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 8186 dev_port += 4; 8187 } 8188 8189 switch ( type ) { 8190 case (SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD): 8191 /*********************************************************************** 8192 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 8193 * To access TOP level registers use phy_id of port0. Override this ports 8194 */ 8195 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 8196 /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */ 8197 /* bit[10:8] WAIT_IFG_LENGTH */ 8198 rv = phy_bcm542xx_direct_reg_modify(unit, pc, 8199 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 8200 value << 8, 8201 PHY_BCM542XX_TOP_MISC_MII_BUFF_WAIT_IFG_LEN ); 8202 /*********************************************************************** 8203 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8204 * To access TOP level registers use phy_id of port0. Now restore back 8205 */ 8206 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8207 break; 8208 8209 case (SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY): 8210 /*********************************************************************** 8211 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 8212 * To access TOP level registers use phy_id of port0. Override this ports 8213 */ 8214 /* Fixed latency can have only 0 or 1 value */ 8215 if ((value != FALSE) && (value != TRUE)) { 8216 return SOC_E_PARAM; 8217 } 8218 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 8219 temp16 = (value == FALSE) ? PHY_BCM542XX_TOP_MISC_MII_BUFF_VAR_LAT_EN : 0; 8220 8221 /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */ 8222 /* bit[2] VARIABLE_LATENCY_EN */ 8223 rv = phy_bcm542xx_direct_reg_modify(unit, pc, 8224 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 8225 temp16, 8226 PHY_BCM542XX_TOP_MISC_MII_BUFF_VAR_LAT_EN ); 8227 /*********************************************************************** 8228 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8229 * To access TOP level registers use phy_id of port0. Now restore back 8230 */ 8231 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8232 8233 /* Need to set MII buffer register as well : phy54682 ? */ 8234 break; 8235 8236 case (SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR): 8237 if ( 1 == value ) { 8238 /* Enable stat counters, Soft reset the counters */ 8239 SOC_IF_ERROR_RETURN( 8240 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 8241 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET 8242 | PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN, 8243 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET 8244 | PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_EN) ); 8245 /*Clear the counter reset bit*/ 8246 SOC_IF_ERROR_RETURN( 8247 PHY_MODIFY_BCM542XX_EEE_STAT_CTRLr(unit, pc, 0x0, 8248 PHY_BCM542XX_EEE_STAT_CTRL_COUNTERS_RESET)); 8249 } 8250 break; 8251 8252 default: 8253 break; 8254 } /* switch (type) */ 8255 8256 return rv; 8257 } 8258 8259 /* 8260 * Function: 8261 * phy_bcm542xx_eee_control_get 8262 * Purpose: 8263 * Implements different 'get' controls 8264 * for EEE 8265 * Parameters: 8266 * phy_id - PHY's device address 8267 * type - type of control 8268 * value - gets the value for the 8269 * control 'type 8270 * Returns: 8271 * SOC_E_xxxx 8272 */ 8273 int 8274 phy_bcm542xx_eee_control_get(int unit, soc_port_t port, 8275 soc_phy_control_t type, uint32 *value) 8276 { 8277 int rv = SOC_E_NONE; 8278 uint16 temp16 = 0; 8279 int dev_port; 8280 phy_ctrl_t *pc; 8281 8282 if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 8283 return SOC_E_UNAVAIL; 8284 } 8285 8286 pc = EXT_PHY_SW_STATE(unit, port); 8287 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); /* Dev port numbers from 0-7 */ 8288 8289 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 8290 of the device. For example to enable autogrEEEn on port0, 8291 rdb register for port 4 0x808 need to be used. 8292 Refer package configuration document. 8293 */ 8294 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 8295 dev_port += 4; 8296 } 8297 8298 switch ( type ) { 8299 case (SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD): 8300 /*********************************************************************** 8301 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 8302 * To access TOP level registers use phy_id of port0. Override this ports 8303 */ 8304 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 8305 /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */ 8306 /* bit[10:8] WAIT_IFG_LENGTH */ 8307 rv = phy_bcm542xx_direct_reg_read(unit, pc, 8308 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 8309 &temp16); 8310 /*********************************************************************** 8311 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8312 * To access TOP level registers use phy_id of port0. Now restore back 8313 */ 8314 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8315 8316 *value = (temp16 & PHY_BCM542XX_TOP_MISC_MII_BUFF_WAIT_IFG_LEN) >> 8; 8317 break; 8318 8319 case (SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY): 8320 /*********************************************************************** 8321 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 8322 * To access TOP level registers use phy_id of port0. Override this ports 8323 */ 8324 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 8325 /* TOP_MISCREG_MII_BUFFER_CNTL_0 Reg., RDB 0x800+2n */ 8326 /* bit[2] VARIABLE_LATENCY_EN */ 8327 rv = phy_bcm542xx_direct_reg_read(unit, pc, 8328 PHY_BCM542XX_TOP_MISC_MII_BUFF_CNTL_PHYN(dev_port), 8329 &temp16); 8330 /*********************************************************************** 8331 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8332 * To access TOP level registers use phy_id of port0. Now restore back 8333 */ 8334 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8335 8336 *value = ((temp16 & PHY_BCM542XX_TOP_MISC_MII_BUFF_VAR_LAT_EN) == 0); 8337 break; 8338 8339 case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS: 8340 /* CORE_ExpAC - EEE Statistic loc lpi req 0_to_1 counter, RDB 0x0ac */ 8341 rv = _phy_bcm542xx_eee_counter_get(unit, pc, 8342 PHY_BCM542XX_EEE_STAT_TX_EVENTS_REG_OFFSET , value); 8343 break; 8344 case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION: 8345 /* CORE_ExpAA - EEE Statistic timer 12hours lpi, RDB 0x0aa */ 8346 rv = _phy_bcm542xx_eee_counter_get(unit, pc, 8347 PHY_BCM542XX_EEE_STAT_TX_DURATION_REG_OFFSET, value); 8348 break; 8349 case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS: 8350 /* CORE_ExpAD - EEE Statistic rem lpi_req 0_to_1 counter, RDB 0x0ad */ 8351 rv = _phy_bcm542xx_eee_counter_get(unit, pc, 8352 PHY_BCM542XX_EEE_STAT_RX_EVENTS_REG_OFFSET , value); 8353 break; 8354 case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION: 8355 /* CORE_ExpAB - EEE Statistic timer 12hours local, RDB 0x0ab */ 8356 rv = _phy_bcm542xx_eee_counter_get(unit, pc, 8357 PHY_BCM542XX_EEE_STAT_RX_DURATION_REG_OFFSET, value); 8358 break; 8359 8360 default: 8361 break; 8362 } /* switch (type) */ 8363 8364 return rv; 8365 } 8366 8367 /* 8368 * Function: 8369 * phy_bcm542xx_control_set 8370 * Purpose: 8371 * Configure PHY device specific control fucntion. 8372 * Parameters: 8373 * unit - StrataSwitch unit #. 8374 * port - StrataSwitch port #. 8375 * type - Control to update 8376 * value - New setting for the control 8377 * Returns: 8378 * SOC_E_NONE 8379 */ 8380 STATIC int 8381 phy_bcm542xx_control_set(int unit, soc_port_t port, 8382 soc_phy_control_t type, uint32 value) 8383 { 8384 int rv = SOC_E_NONE; 8385 phy_ctrl_t *pc; 8386 8387 pc = EXT_PHY_SW_STATE(unit, port); 8388 8389 PHY_CONTROL_TYPE_CHECK(type); 8390 8391 switch ( type ) { 8392 /* SyncE recovered clock controls */ 8393 case SOC_PHY_CONTROL_CLOCK_ENABLE: 8394 rv = phy_bcm542xx_clock_enable_set(unit, pc, 8395 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK1_SHIFT, 8396 value); 8397 break; 8398 case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE: 8399 rv = phy_bcm542xx_clock_enable_set(unit, pc, 8400 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK2_SHIFT, 8401 value); 8402 break; 8403 case SOC_PHY_CONTROL_CLOCK_MODE_AUTO: 8404 rv = _phy_bcm542xx_clock_control_set(unit, pc, 8405 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_CLK_DIS, 8406 value); 8407 break; 8408 case SOC_PHY_CONTROL_CLOCK_AUTO_SECONDARY: 8409 rv = _phy_bcm542xx_clock_control_set(unit, pc, 8410 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_SW_MODE, 8411 value); 8412 break; 8413 case SOC_PHY_CONTROL_CLOCK_SOURCE: 8414 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 8415 return SOC_E_UNAVAIL; 8416 break; 8417 8418 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 8419 if (PHY_IS_BCM54240(pc)) { 8420 if ( PHY_COPPER_MODE(unit, port) ) { 8421 SOC_IF_ERROR_RETURN( 8422 PHY_MODIFY_BCM542XX_MII_MISC_TESTr(unit, pc, (value) ? PHY_BCM542XX_MII_MISC_TEST_RMT_LB : 0, 8423 PHY_BCM542XX_MII_MISC_TEST_RMT_LB) ); 8424 SOC_IF_ERROR_RETURN 8425 (PHY_MODIFY_BCM542XX_MII_CTRLr(unit, pc, 1, PHY_BCM542XX_MII_CTRL_RST_AN)); 8426 } else {/* MEDIUM_FIBER */ 8427 if(value) { 8428 SOC_IF_ERROR_RETURN( 8429 PHY_WRITE_BCM542XX_AUTO_DETECT_MEDIUMr(unit, pc, 0x7800) ); 8430 SOC_IF_ERROR_RETURN( 8431 PHY_WRITE_BCM542XX_MODE_CTRLr(unit, pc, 0x7F06) ); 8432 SOC_IF_ERROR_RETURN( 8433 PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, 0x5140) ); 8434 } else { /* Diable loopback */ 8435 SOC_IF_ERROR_RETURN( 8436 PHY_WRITE_BCM542XX_MII_CTRLr(unit, pc, 0x1140) ); 8437 } 8438 } 8439 } else { 8440 return SOC_E_UNAVAIL; 8441 } 8442 break; 8443 8444 /* power controls */ 8445 case SOC_PHY_CONTROL_POWER: 8446 rv = phy_bcm542xx_power_mode_set(unit, pc, value); 8447 break; 8448 case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME: 8449 phy_bcm542xx_power_auto_wake_time_set(unit, pc, value); 8450 break; 8451 case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME: 8452 phy_bcm542xx_power_auto_sleep_time_set(unit, pc, value); 8453 break; 8454 /* port phy address setting */ 8455 case SOC_PHY_CONTROL_PORT_PRIMARY: 8456 SOC_IF_ERROR_RETURN 8457 (soc_phyctrl_primary_set(unit, port, (soc_port_t)value)); 8458 break; 8459 case SOC_PHY_CONTROL_PORT_OFFSET: 8460 SOC_IF_ERROR_RETURN 8461 (soc_phyctrl_offset_set(unit, port, (int)value)); 8462 break; 8463 case SOC_PHY_CONTROL_SUPER_ISOLATE: 8464 SOC_IF_ERROR_RETURN 8465 (phy_bcm542xx_direct_reg_modify(unit, pc, 8466 PHY_BCM542XX_POWER_MII_CTRL_REG_OFFSET, 8467 (value) ? PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE 8468 : 0, 8469 PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE) ); 8470 break; 8471 case SOC_PHY_CONTROL_SOFT_RESET: 8472 SOC_IF_ERROR_RETURN 8473 (phy_bcm542xx_direct_reg_modify(unit, pc, 8474 PHY_BCM542XX_SOFT_RESET_REG_OFFSET, 8475 (value) ? PHY_BCM542XX_SOFT_RESET_ISSUE_RESET : 0, 8476 PHY_BCM542XX_SOFT_RESET_ISSUE_RESET) ); 8477 PHY_BCM542XX_DEFAULT_REG_ACCESS_MODE(unit, pc); 8478 break; 8479 8480 /* EEE settings */ 8481 case SOC_PHY_CONTROL_EEE: 8482 if(value == 1 ) 8483 { 8484 /*First Disable Auto EEE*/ 8485 SOC_IF_ERROR_RETURN 8486 (phy_bcm542xx_eee_enable(unit, port, SOC_PHY_CONTROL_EEE_AUTO, 0)); 8487 } 8488 /*Enable/Disable Native EEE*/ 8489 SOC_IF_ERROR_RETURN 8490 (phy_bcm542xx_eee_enable(unit, port, type, value)); 8491 break; 8492 case SOC_PHY_CONTROL_EEE_AUTO: 8493 if(value == 1 ) 8494 { 8495 /*First Disable Native EEE*/ 8496 SOC_IF_ERROR_RETURN 8497 (phy_bcm542xx_eee_enable(unit, port, SOC_PHY_CONTROL_EEE, 0)); 8498 } 8499 /*Enable/Disable Auto EEE*/ 8500 SOC_IF_ERROR_RETURN 8501 (phy_bcm542xx_eee_enable(unit, port, type, value)); 8502 break; 8503 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 8504 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 8505 case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR: 8506 SOC_IF_ERROR_RETURN 8507 (phy_bcm542xx_eee_control_set(unit, port, type, value)); 8508 break; 8509 case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT: 8510 /* Buffer limit modification is not allowed */ 8511 case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME: 8512 case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME: 8513 case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME: 8514 case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME: 8515 case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME: 8516 case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME: 8517 case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME: 8518 return SOC_E_UNAVAIL; 8519 8520 default: /* -- unrecognized PHY control commands -- */ 8521 return SOC_E_UNAVAIL; 8522 } /* switch ( type ) */ 8523 8524 return rv; 8525 } 8526 8527 /* 8528 * Function: 8529 * phy_bcm542xx_control_get 8530 * Purpose: 8531 * Get current control settign of the PHY. 8532 * Parameters: 8533 * unit - StrataSwitch unit #. 8534 * port - StrataSwitch port #. 8535 * type - Control to update 8536 * value - (OUT)Current setting for the control 8537 * Returns: 8538 * SOC_E_NONE 8539 */ 8540 STATIC int 8541 phy_bcm542xx_control_get(int unit, soc_port_t port, 8542 soc_phy_control_t type, uint32 *value) 8543 { 8544 int rv = SOC_E_NONE; 8545 phy_ctrl_t *pc; 8546 soc_port_t primary; 8547 uint16 value16; 8548 8549 pc = EXT_PHY_SW_STATE(unit, port); 8550 8551 if ( NULL == value ) { 8552 return SOC_E_PARAM; 8553 } 8554 8555 PHY_CONTROL_TYPE_CHECK(type); 8556 8557 switch ( type ) { 8558 /* power controls */ 8559 case SOC_PHY_CONTROL_POWER: 8560 *value = pc->power_mode; 8561 break; 8562 case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME: 8563 phy_bcm542xx_power_auto_sleep_time_get(unit, pc, value); 8564 break; 8565 case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME: 8566 phy_bcm542xx_power_auto_wake_time_get(unit, pc, value); 8567 break; 8568 /* port phy address setting */ 8569 case SOC_PHY_CONTROL_PORT_PRIMARY: 8570 SOC_IF_ERROR_RETURN 8571 (soc_phyctrl_primary_get(unit, port, &primary)); 8572 *value = (uint32) primary; 8573 break; 8574 case SOC_PHY_CONTROL_PORT_OFFSET: 8575 *value = (uint32) PHY_BCM542XX_DEV_PHY_SLICE(pc); 8576 break; 8577 8578 /* SyncE recovered clock controls */ 8579 case SOC_PHY_CONTROL_CLOCK_ENABLE: 8580 rv = phy_bcm542xx_clock_enable_get(unit, pc, 8581 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK1_SHIFT, 8582 value); 8583 break; 8584 case SOC_PHY_CONTROL_CLOCK_SECONDARY_ENABLE: 8585 rv = phy_bcm542xx_clock_enable_get(unit, pc, 8586 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_REC_CLK2_SHIFT, 8587 value); 8588 break; 8589 case SOC_PHY_CONTROL_CLOCK_MODE_AUTO: 8590 rv = _phy_bcm542xx_clock_control_get(unit, pc, 8591 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_CLK_DIS, value); 8592 break; 8593 case SOC_PHY_CONTROL_CLOCK_AUTO_SECONDARY: 8594 rv = _phy_bcm542xx_clock_control_get(unit, pc, 8595 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_SW_MODE, value); 8596 break; 8597 case SOC_PHY_CONTROL_CLOCK_SOURCE: 8598 rv = _phy_bcm542xx_clock_control_get(unit, pc, 8599 PHY_BCM542XX_SYNCE_RECOVERY_CLK_REG_AUTO_SW_STS , value); 8600 *value = (0 == *value) ? SOC_PORT_PHY_CLOCK_SOURCE_PRIMARY 8601 : SOC_PORT_PHY_CLOCK_SOURCE_SECONDARY; 8602 break; 8603 case SOC_PHY_CONTROL_SUPER_ISOLATE: 8604 SOC_IF_ERROR_RETURN 8605 (phy_bcm542xx_direct_reg_read(unit, pc, 8606 PHY_BCM542XX_POWER_MII_CTRL_REG_OFFSET, &value16) ); 8607 8608 *value = ((value16) & PHY_BCM542XX_POWER_MII_CTRL_SUPER_ISOLATE) 8609 ? TRUE : FALSE; 8610 break; 8611 8612 /* EEE settings */ 8613 case SOC_PHY_CONTROL_EEE: 8614 if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 8615 rv = SOC_E_UNAVAIL; 8616 break; 8617 } 8618 rv = _phy_bcm542xx_get_eee_control_status(unit, pc, value); 8619 break; 8620 case SOC_PHY_CONTROL_EEE_AUTO: 8621 if ( ! PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 8622 rv = SOC_E_UNAVAIL; 8623 break; 8624 } 8625 rv = _phy_bcm542xx_get_auto_eee_control_status(unit, port, value); 8626 break; 8627 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 8628 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 8629 case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS: 8630 case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION: 8631 case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS: 8632 case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION: 8633 rv = phy_bcm542xx_eee_control_get(unit, port, type, value); 8634 break; 8635 8636 default: /* -- unrecognized PHY control commands -- */ 8637 return SOC_E_UNAVAIL; 8638 } 8639 8640 return rv; 8641 } 8642 8643 /* 8644 * Function: 8645 * phy_bcm542xx_probe 8646 * Purpose: 8647 * Complement the generic phy probe routine to identify this phy when its 8648 * phy id0 and id1 is same as some other phy's. 8649 * Parameters: 8650 * unit - StrataSwitch unit #. 8651 * pc - phy ctrl descriptor. 8652 * Returns: 8653 * SOC_E_NONE, SOC_E_NOT_FOUND and SOC_E_<error> 8654 */ 8655 STATIC int 8656 phy_bcm542xx_probe(int unit, phy_ctrl_t *pc) { 8657 int oui = 0, model = 0, rev = 0, rv = SOC_E_NONE; 8658 soc_phy_info_t *pi = &SOC_PHY_INFO(unit, pc->port); 8659 8660 if ( SOC_E_NONE != (rv = _phy_bcm542xx_model_rev_get(unit, pc, 8661 &oui, &model, &rev)) ) { 8662 return SOC_E_FAIL; 8663 } 8664 pc->interface = SOC_PORT_IF_SGMII; /* 54210/220/240/280/290/294/190/180/140 */ 8665 8666 /* determine the chip model */ 8667 switch ( model ) { 8668 8669 case PHY_BCM54210_MODEL: 8670 case PHY_BCM54220_MODEL: 8671 case PHY_BCM54280_MODEL: 8672 /*passthru*/ 8673 case PHY_BCM5428X_MODEL: 8674 /*passthru*/ 8675 case PHY_BCM54240_MODEL: 8676 break; 8677 8678 case (PHY_BCM54282_MODEL | PHY_BCM54285_MODEL): 8679 pi->phy_name = (rev & 0x8) ? "BCM54282" : "BCM54285"; 8680 pc->interface = SOC_PORT_IF_QSGMII; 8681 break; 8682 8683 case (PHY_BCM54290_MODEL | PHY_BCM54294_MODEL): 8684 pi->phy_name = (rev & 0x8) ? "BCM54294" : "BCM54290"; 8685 break; 8686 8687 case (PHY_BCM54292_MODEL | PHY_BCM54295_MODEL | PHY_BCM54296_MODEL): 8688 if ( rev & 0x8 ) { 8689 pi->phy_name = (0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc)) 8690 ? "BCM54296" : "BCM54295"; 8691 } else { 8692 pi->phy_name = "BCM54292"; 8693 } 8694 pc->interface = SOC_PORT_IF_QSGMII; 8695 break; 8696 8697 case (PHY_BCM54190_MODEL | PHY_BCM54194_MODEL): 8698 pi->phy_name = (rev & 0x8) ? "BCM54194" : "BCM54190"; 8699 break; 8700 8701 case (PHY_BCM54180_MODEL | PHY_BCM54140_MODEL): 8702 pi->phy_name = (rev & 0x8) ? "BCM54140" : "BCM54180"; 8703 break; 8704 8705 case (PHY_BCM54182_MODEL | PHY_BCM54185_MODEL): 8706 if ( rev & 0x8 ) { 8707 pi->phy_name = (0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc)) 8708 ? "BCM54186" : "BCM54185"; 8709 } else { 8710 pi->phy_name = "BCM54182"; 8711 } 8712 pc->interface = SOC_PORT_IF_QSGMII; 8713 break; 8714 8715 case (PHY_BCM54192_MODEL | PHY_BCM54195_MODEL): 8716 if ( rev & 0x8 ) { 8717 pi->phy_name = (0x8 & _phy_bcm542xx_hidden_rev_num_get(unit, pc)) 8718 ? "BCM54196" : "BCM54195"; 8719 } else { 8720 pi->phy_name = "BCM54192"; 8721 } 8722 pc->interface = SOC_PORT_IF_QSGMII; 8723 break; 8724 8725 default : 8726 return SOC_E_NOT_FOUND; 8727 } 8728 #ifdef INCLUDE_PLP_IMACSEC 8729 pc->size = sizeof(PHY_BCM542XX_DEV_DESC_t) + sizeof(bcm_plp_base_t_sec_phy_access_t); 8730 #else 8731 pc->size = sizeof(PHY_BCM542XX_DEV_DESC_t); 8732 #endif 8733 return rv; 8734 } 8735 8736 /* 8737 * Function: 8738 * phy_bcm542xx_link_up 8739 * Purpose: 8740 * Link up handler 8741 * Parameters: 8742 * unit - StrataSwitch unit #. 8743 * port - StrataSwitch port #. 8744 * Returns: 8745 * SOC_E_NONE 8746 */ 8747 STATIC int 8748 phy_bcm542xx_link_up(int unit, soc_port_t port) 8749 { 8750 int speed = 0; 8751 #ifdef INCLUDE_PLP_IMACSEC 8752 phy_ctrl_t* pc; 8753 pc = EXT_PHY_SW_STATE(unit, port); 8754 #endif 8755 SOC_IF_ERROR_RETURN 8756 (phy_bcm542xx_speed_get(unit, port, &speed)); 8757 8758 /* Notify interface to internal PHY */ 8759 SOC_IF_ERROR_RETURN 8760 (soc_phyctrl_notify(unit, port, phyEventInterface, IS_GMII_PORT(unit, port) ? SOC_PORT_IF_GMII : SOC_PORT_IF_SGMII)); 8761 8762 /* Situation observed with Saber devices XGXS16g1l+BCM54640E 8763 Linkscan is not updating speed for internal phy xgxs16g1l. 8764 It was observed that when speed is set to 100M the int phy 8765 is still set to 1G and traffic does not flow through untill 8766 int phy speed is also update to 100M. This applies to other 8767 speeds as well. 8768 Explicitly send speed notify to int phy from ext phy. 8769 */ 8770 SOC_IF_ERROR_RETURN 8771 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed)); 8772 #ifdef INCLUDE_PLP_IMACSEC 8773 /* Check if MACSEC_SWITCH_SIDE_POLICY is DUPLEX_GATEWAY mode 8774 * Half duplex mode is supported only in 10 Mbps and 100 Mbps*/ 8775 if (pc->macsec_enable) { 8776 int duplex; 8777 /* Duplex Gateway mode for supporting half-duplex-free switches: *\ 8778 |* When line-side PHY lilnks up at half-duplex, *| 8779 \* set half-duplex to line-side MAC, full-duplex to switch-side MAC*/ 8780 8781 /* get the duplex status from line side */ 8782 SOC_IF_ERROR_RETURN( 8783 phy_bcm542xx_duplex_get(unit, port, &duplex) ); 8784 if ( pc->macsec_switch_fixed_speed == speed && 8785 pc->macsec_switch_fixed_duplex == duplex) { 8786 return SOC_E_NONE; /* speed/duplex unchanged */ 8787 } 8788 8789 pc->macsec_switch_fixed_speed = speed; 8790 pc->macsec_switch_fixed_duplex = duplex; /* Change the duplex mode to half duplex */ 8791 /* Config duplex Gateway parameters accordingly */ 8792 SOC_IF_ERROR_RETURN( 8793 phy_unimac_switch_side_set_params(unit,port, 8794 pc->macsec_mac_policy, 8795 speed, duplex, pc->macsec_switch_fixed_pause) ); 8796 /* under DUPLEX_GATEWAY mode, always Full-Duplex on system side */ 8797 SOC_IF_ERROR_RETURN 8798 (soc_phyctrl_notify(unit, port, phyEventDuplex, TRUE)); 8799 } 8800 #endif 8801 return SOC_E_NONE; 8802 } 8803 8804 /* 8805 * Function: 8806 * phy_bcm542xx_oam_config_set 8807 * Purpose: 8808 * 8809 * Parameters: 8810 * 8811 * Returns: 8812 */ 8813 int 8814 phy_bcm542xx_oam_config_set(int unit, soc_port_t port, soc_port_config_phy_oam_t *conf) { 8815 uint16 data = 0, mask = 0; 8816 uint16 dm_tx_cntl_data = 0, dm_rx_cntl_data = 0; 8817 phy_ctrl_t *pc; 8818 soc_port_phy_timesync_config_t timesync_conf; 8819 8820 sal_memset(×ync_conf, 0, sizeof(soc_port_phy_timesync_config_t)); 8821 8822 if (NULL == conf) { 8823 return SOC_E_PARAM; 8824 } 8825 8826 pc = EXT_PHY_SW_STATE(unit, port); 8827 8828 /* 1. en_1588_softrst */ 8829 /* 2. en_RGMII_Timing_RGMII */ 8830 8831 /* Setup timesync 1588 */ 8832 timesync_conf.flags = SOC_PORT_PHY_TIMESYNC_ENABLE; 8833 phy_bcm542xx_timesync_config_set(unit, port, ×ync_conf); 8834 8835 /*********************************************************************** 8836 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 8837 * To access TOP level registers use phy_id of port0. Override this ports 8838 */ 8839 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 8840 8841 /* TX: Delay measurement mode */ 8842 switch( conf->tx_dm_config.mode ) { 8843 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731: 8844 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_EN; 8845 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { 8846 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL; 8847 } 8848 break; 8849 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH: 8850 data = 0; 8851 mask = 0; 8852 if (!(conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) { 8853 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS; 8854 } 8855 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) { 8856 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN; 8857 } 8858 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN; 8859 mask = PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN 8860 | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS 8861 | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN; 8862 phy_bcm542xx_direct_reg_modify(unit, pc, 8863 PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 8864 data, mask); 8865 8866 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { 8867 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL; 8868 } 8869 break; 8870 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF: 8871 data = 0; 8872 mask = 0; 8873 if (!(conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) { 8874 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS; 8875 } 8876 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) { 8877 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN; 8878 } 8879 data |= PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN; 8880 mask = PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN 8881 | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_CW_DIS 8882 | PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_ENTROPY_EN; 8883 phy_bcm542xx_direct_reg_modify(unit, pc, 8884 PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 8885 data, mask); 8886 8887 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_IETF_EN; 8888 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { 8889 /* Same bit as for BHH */ 8890 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL; 8891 } 8892 break; 8893 default: 8894 if ( conf->tx_dm_config.mode == 0) { 8895 break; 8896 } 8897 /******************************************************** 8898 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8899 * To access TOP level registers use phy_id of port0. 8900 Now restore back 8901 */ 8902 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8903 return SOC_E_CONFIG; 8904 } 8905 8906 /* RX: Delay measurement mode */ 8907 switch(conf->rx_dm_config.mode) { 8908 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731: 8909 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_EN; 8910 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { 8911 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_Y1731_TS_SEL; 8912 } 8913 break; 8914 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH: 8915 data = 0; 8916 mask = 0; 8917 if (!(conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) { 8918 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS; 8919 } 8920 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) { 8921 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN; 8922 } 8923 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN; 8924 mask = PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN 8925 | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS 8926 | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN; 8927 phy_bcm542xx_direct_reg_modify(unit, pc, 8928 PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 8929 data, mask); 8930 8931 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { 8932 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_BHH_TS_SEL; 8933 } 8934 break; 8935 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF: 8936 data = 0; 8937 mask = 0; 8938 if (!(conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE) ) { 8939 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS; 8940 } 8941 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) { 8942 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN; 8943 } 8944 data |= PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN; 8945 mask = PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN 8946 | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_CW_DIS 8947 | PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_ENTROPY_EN; 8948 phy_bcm542xx_direct_reg_modify(unit, pc, 8949 PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 8950 data, mask); 8951 8952 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_IETF_EN; 8953 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { 8954 /* Same bit as for BHH */ 8955 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_BHH_TS_SEL; 8956 } 8957 break; 8958 default: 8959 if ( conf->rx_dm_config.mode == 0) { 8960 break; 8961 } 8962 /******************************************************** 8963 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 8964 * To access TOP level registers use phy_id of port0. 8965 Now restore back 8966 */ 8967 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 8968 return SOC_E_CONFIG; 8969 } 8970 8971 /* Enable the 1588 counter includes the delay measurement packet */ 8972 dm_tx_cntl_data |= (dm_tx_cntl_data)? PHY_BCM542XX_TOP_1588_DM_TX_CNTL_1588_CNT_EN : dm_tx_cntl_data; 8973 dm_rx_cntl_data |= (dm_rx_cntl_data)? PHY_BCM542XX_TOP_1588_DM_TX_CNTL_1588_CNT_EN : dm_rx_cntl_data; 8974 8975 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ) { 8976 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_MAC_EN; 8977 } 8978 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ) { 8979 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_CW_EN; 8980 } 8981 if ( conf->tx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) { 8982 dm_tx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_TX_CNTL_ENTROPY_EN; 8983 } 8984 8985 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE ) { 8986 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_MAC_EN; 8987 } 8988 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE ) { 8989 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_CW_EN; 8990 } 8991 if ( conf->rx_dm_config.flags & SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE ) { 8992 dm_rx_cntl_data |= PHY_BCM542XX_TOP_1588_DM_RX_CNTL_ENTROPY_EN; 8993 } 8994 8995 mask = PHY_BCM542XX_TOP_1588_DM_TX_CNTL_EN 8996 | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_MAC_EN 8997 | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_CW_EN 8998 | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_ENTROPY_EN 8999 | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL 9000 | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL 9001 | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_IETF_EN 9002 | PHY_BCM542XX_TOP_1588_DM_TX_CNTL_1588_CNT_EN; 9003 9004 phy_bcm542xx_direct_reg_modify(unit, pc, 9005 PHY_BCM542XX_TOP_1588_DM_TX_CNTL_REG_OFFSET, 9006 dm_tx_cntl_data, mask); 9007 9008 mask = PHY_BCM542XX_TOP_1588_DM_RX_CNTL_EN 9009 | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_MAC_EN 9010 | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_CW_EN 9011 | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_ENTROPY_EN 9012 | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_Y1731_TS_SEL 9013 | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_BHH_TS_SEL 9014 | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_IETF_EN 9015 | PHY_BCM542XX_TOP_1588_DM_RX_CNTL_1588_CNT_EN; 9016 9017 phy_bcm542xx_direct_reg_modify(unit, pc, 9018 PHY_BCM542XX_TOP_1588_DM_RX_CNTL_REG_OFFSET, 9019 dm_rx_cntl_data, mask); 9020 9021 /*********************************************************************** 9022 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9023 * To access TOP level registers use phy_id of port0. Now restore back 9024 */ 9025 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9026 9027 /* Save the config */ 9028 sal_memcpy(PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc), conf, sizeof(soc_port_config_phy_oam_t)); 9029 9030 return SOC_E_NONE; 9031 } 9032 9033 /* 9034 * Function: 9035 * phy_bcm542xx_oam_config_get 9036 * Purpose: 9037 * 9038 * Parameters: 9039 * 9040 * Returns: 9041 */ 9042 int 9043 phy_bcm542xx_oam_config_get(int unit, soc_port_t port, soc_port_config_phy_oam_t *conf) { 9044 uint16 dm_tx_cntl_data = 0, dm_rx_cntl_data = 0; 9045 uint16 mpls_tx_cntl_data = 0, mpls_rx_cntl_data = 0; 9046 phy_ctrl_t *pc; 9047 9048 sal_memset(conf, 0, sizeof(soc_port_config_phy_oam_t)); 9049 9050 pc = EXT_PHY_SW_STATE(unit, port); 9051 9052 /*********************************************************************** 9053 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 9054 * To access TOP level registers use phy_id of port0. Override this ports 9055 */ 9056 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 9057 9058 /* Read config registers */ 9059 phy_bcm542xx_direct_reg_read(unit, pc, 9060 PHY_BCM542XX_TOP_1588_DM_TX_CNTL_REG_OFFSET, 9061 &dm_tx_cntl_data); 9062 phy_bcm542xx_direct_reg_read(unit, pc, 9063 PHY_BCM542XX_TOP_1588_DM_RX_CNTL_REG_OFFSET, 9064 &dm_rx_cntl_data); 9065 phy_bcm542xx_direct_reg_read(unit, pc, 9066 PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_OFFSET, 9067 &mpls_tx_cntl_data); 9068 phy_bcm542xx_direct_reg_read(unit, pc, 9069 PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_OFFSET, 9070 &mpls_rx_cntl_data); 9071 9072 /* Tx Config Mode */ 9073 if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_EN ) { 9074 conf->tx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_Y1731; 9075 if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL) { 9076 conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT; 9077 } 9078 } else if ((dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_IETF_EN) 9079 && (mpls_tx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN)){ 9080 conf->tx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_IETF; 9081 if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) { 9082 conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT; 9083 } 9084 } else if (mpls_tx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_TX_CNTL_REG_MPLS_EN ) { 9085 conf->tx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_BHH; 9086 if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) { 9087 conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT; 9088 } 9089 } 9090 9091 /* Rx Config Mode */ 9092 if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_EN ) { 9093 conf->rx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_Y1731; 9094 if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_Y1731_TS_SEL) { 9095 conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT; 9096 } 9097 } else if ((dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_IETF_EN) 9098 && (mpls_rx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN)){ 9099 conf->rx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_IETF; 9100 if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) { 9101 conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT; 9102 } 9103 } else if (mpls_rx_cntl_data & PHY_BCM542XX_TOP_1588_MPLS_RX_CNTL_REG_MPLS_EN ) { 9104 conf->rx_dm_config.mode = SOC_PORT_CONFIG_PHY_OAM_DM_BHH; 9105 if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_BHH_TS_SEL) { 9106 conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_TS_FORMAT; 9107 } 9108 } 9109 9110 /* Tx Config Flags */ 9111 if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_MAC_EN ) { 9112 conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE; 9113 } 9114 if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_CW_EN ) { 9115 conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE; 9116 } 9117 if (dm_tx_cntl_data & PHY_BCM542XX_TOP_1588_DM_TX_CNTL_ENTROPY_EN ) { 9118 conf->tx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE; 9119 } 9120 9121 /* Rx Config Flags */ 9122 if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_MAC_EN ) { 9123 conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_MAC_CHECK_ENABLE; 9124 } 9125 if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_CW_EN ) { 9126 conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_CONTROL_WORD_ENABLE; 9127 } 9128 if (dm_rx_cntl_data & PHY_BCM542XX_TOP_1588_DM_RX_CNTL_ENTROPY_EN ) { 9129 conf->rx_dm_config.flags |= SOC_PORT_PHY_OAM_DM_ENTROPY_ENABLE; 9130 } 9131 9132 /*********************************************************************** 9133 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9134 * To access TOP level registers use phy_id of port0. Now restore back 9135 */ 9136 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9137 /* Save the config */ 9138 sal_memcpy(PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc), conf, sizeof(soc_port_config_phy_oam_t)); 9139 return SOC_E_NONE; 9140 } 9141 9142 /* 9143 * Function: 9144 * phy_bcm542xx_oam_control_set 9145 * Purpose: 9146 * 9147 * Parameters: 9148 * 9149 * Returns: 9150 */ 9151 int 9152 phy_bcm542xx_oam_control_set(int unit, soc_port_t port, soc_port_control_phy_oam_t type, uint64 value) 9153 { 9154 uint16 dev_port = 0; 9155 phy_ctrl_t *pc = NULL; 9156 soc_port_config_phy_oam_t *config = NULL; 9157 soc_port_config_phy_oam_dm_mode_t tx_mode = 0; 9158 soc_port_config_phy_oam_dm_mode_t rx_mode = 0; 9159 uint32 tx_flags; 9160 9161 pc = EXT_PHY_SW_STATE(unit, port); 9162 9163 /* Dev port numbers from 0-7 */ 9164 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 9165 9166 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 9167 of the device. For example to enable autogrEEEn on port0, 9168 rdb register for port 4 0x808 need to be used. 9169 Refer package configuration document. 9170 */ 9171 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 9172 dev_port += 4; 9173 } 9174 9175 9176 /* Config saved during config _set or read during config _get */ 9177 config = PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc); 9178 tx_mode = config->tx_dm_config.mode; 9179 tx_flags = config->tx_dm_config.flags; 9180 rx_mode = config->rx_dm_config.mode; 9181 9182 /*********************************************************************** 9183 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 9184 * To access TOP level registers use phy_id of port0. Override this ports 9185 */ 9186 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 9187 9188 switch(type) { 9189 case SOC_PORT_CONTROL_PHY_OAM_DM_TX_ETHERTYPE: 9190 switch(tx_mode) { 9191 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731: 9192 if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */ 9193 phy_bcm542xx_direct_reg_write(unit, pc, 9194 PHY_BCM542XX_TOP_1588_DM_ETHTYPE2_REG_OFFSET, 9195 (COMPILER_64_LO(value) & 0xffff)); 9196 } else { /*PTP */ 9197 phy_bcm542xx_direct_reg_write(unit, pc, 9198 PHY_BCM542XX_TOP_1588_DM_ETHTYPE1_REG_OFFSET, 9199 (COMPILER_64_LO(value) & 0xffff)); 9200 } 9201 break; 9202 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH: 9203 if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */ 9204 phy_bcm542xx_direct_reg_write(unit, pc, 9205 PHY_BCM542XX_TOP_1588_DM_ETHTYPE4_REG_OFFSET, 9206 (COMPILER_64_LO(value) & 0xffff)); 9207 } else { /*PTP */ 9208 phy_bcm542xx_direct_reg_write(unit, pc, 9209 PHY_BCM542XX_TOP_1588_DM_ETHTYPE3_REG_OFFSET, 9210 (COMPILER_64_LO(value) & 0xffff)); 9211 } 9212 break; 9213 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF: 9214 phy_bcm542xx_direct_reg_write(unit, pc, 9215 PHY_BCM542XX_TOP_1588_DM_ETHTYPE9_REG_OFFSET, 9216 (COMPILER_64_LO(value) & 0xffff)); 9217 break; 9218 default: 9219 /******************************************************** 9220 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9221 * To access TOP level registers use phy_id of port0. 9222 Now restore back 9223 */ 9224 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9225 return SOC_E_CONFIG; 9226 } 9227 9228 break; 9229 case SOC_PORT_CONTROL_PHY_OAM_DM_RX_ETHERTYPE: 9230 switch(rx_mode) { 9231 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731: 9232 phy_bcm542xx_direct_reg_write(unit, pc, 9233 PHY_BCM542XX_TOP_1588_DM_ETHTYPE5_REG_OFFSET, 9234 (COMPILER_64_LO(value) & 0xffff)); 9235 break; 9236 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH: 9237 phy_bcm542xx_direct_reg_write(unit, pc, 9238 PHY_BCM542XX_TOP_1588_DM_ETHTYPE8_REG_OFFSET, 9239 (COMPILER_64_LO(value) & 0xffff)); 9240 break; 9241 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF: 9242 phy_bcm542xx_direct_reg_write(unit, pc, 9243 PHY_BCM542XX_TOP_1588_DM_ETHTYPE10_REG_OFFSET, 9244 (COMPILER_64_LO(value) & 0xffff)); 9245 break; 9246 default: 9247 /******************************************************** 9248 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9249 * To access TOP level registers use phy_id of port0. 9250 Now restore back 9251 */ 9252 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9253 return SOC_E_CONFIG; 9254 } 9255 break; 9256 case SOC_PORT_CONTROL_PHY_OAM_DM_TX_PORT_MAC_ADDRESS_INDEX: 9257 phy_bcm542xx_direct_reg_write(unit, pc, 9258 PHY_BCM542XX_TOP_1588_DM_MAC_CTL_0_REG_OFFSET, 9259 (COMPILER_64_LO(value) & 0x0003) << (dev_port*2)); 9260 break; 9261 case SOC_PORT_CONTROL_PHY_OAM_DM_RX_PORT_MAC_ADDRESS_INDEX: 9262 phy_bcm542xx_direct_reg_write(unit, pc, 9263 PHY_BCM542XX_TOP_1588_DM_MAC_CTL_1_REG_OFFSET, 9264 (COMPILER_64_LO(value) & 0x0003) << (dev_port*2)); 9265 break; 9266 case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_1: 9267 phy_bcm542xx_direct_reg_write(unit, pc, 9268 PHY_BCM542XX_TOP_1588_DM_MAC_L1_0_REG_OFFSET, 9269 (COMPILER_64_LO(value) & 0xffff)); 9270 phy_bcm542xx_direct_reg_write(unit, pc, 9271 PHY_BCM542XX_TOP_1588_DM_MAC_L1_1_REG_OFFSET, 9272 (COMPILER_64_LO(value) >> 16) & 0xffff); 9273 phy_bcm542xx_direct_reg_write(unit, pc, 9274 PHY_BCM542XX_TOP_1588_DM_MAC_L1_2_REG_OFFSET, 9275 (COMPILER_64_HI(value) & 0xffff)); 9276 break; 9277 case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_2: 9278 phy_bcm542xx_direct_reg_write(unit, pc, 9279 PHY_BCM542XX_TOP_1588_DM_MAC_L2_0_REG_OFFSET, 9280 (COMPILER_64_LO(value) & 0xffff)); 9281 phy_bcm542xx_direct_reg_write(unit, pc, 9282 PHY_BCM542XX_TOP_1588_DM_MAC_L2_1_REG_OFFSET, 9283 (COMPILER_64_LO(value) >> 16) & 0xffff); 9284 phy_bcm542xx_direct_reg_write(unit, pc, 9285 PHY_BCM542XX_TOP_1588_DM_MAC_L2_2_REG_OFFSET, 9286 (COMPILER_64_HI(value) & 0xffff)); 9287 break; 9288 case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_3: 9289 phy_bcm542xx_direct_reg_write(unit, pc, 9290 PHY_BCM542XX_TOP_1588_DM_MAC_L3_0_REG_OFFSET, 9291 (COMPILER_64_LO(value) & 0xffff)); 9292 phy_bcm542xx_direct_reg_write(unit, pc, 9293 PHY_BCM542XX_TOP_1588_DM_MAC_L3_1_REG_OFFSET, 9294 (COMPILER_64_LO(value) >> 16) & 0xffff); 9295 phy_bcm542xx_direct_reg_write(unit, pc, 9296 PHY_BCM542XX_TOP_1588_DM_MAC_L3_2_REG_OFFSET, 9297 (COMPILER_64_HI(value) & 0xffff)); 9298 break; 9299 default: 9300 /******************************************************** 9301 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9302 * To access TOP level registers use phy_id of port0. 9303 Now restore back 9304 */ 9305 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9306 return SOC_E_PARAM; 9307 } 9308 9309 9310 /*********************************************************************** 9311 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9312 * To access TOP level registers use phy_id of port0. Now restore back 9313 */ 9314 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9315 9316 return SOC_E_NONE; 9317 } 9318 9319 /* 9320 * Function: 9321 * phy_bcm542xx_oam_control_get 9322 * Purpose: 9323 * 9324 * Parameters: 9325 * 9326 * Returns: 9327 */ 9328 int 9329 phy_bcm542xx_oam_control_get(int unit, soc_port_t port, soc_port_control_phy_oam_t type, uint64 *value) { 9330 uint16 dev_port = 0; 9331 phy_ctrl_t *pc = NULL; 9332 soc_port_config_phy_oam_t *config = NULL; 9333 uint16 value01 = 0, value02 = 0, value03 = 0; 9334 soc_port_config_phy_oam_dm_mode_t tx_mode = 0, rx_mode = 0; 9335 uint32 tx_flags; 9336 9337 pc = EXT_PHY_SW_STATE(unit, port); 9338 9339 /* Dev port numbers from 0-7 */ 9340 dev_port = PHY_BCM542XX_DEV_PHY_SLICE(pc); 9341 9342 /* For BCM54294/296 package the logical ports p0-p3 are on port4-7 9343 of the device. For example to enable autogrEEEn on port0, 9344 rdb register for port 4 0x808 need to be used. 9345 Refer package configuration document. 9346 */ 9347 if ( PHY_BCM542XX_IS_REAR_HALF(pc) ) { 9348 dev_port += 4; 9349 } 9350 9351 /* Config saved during config _set */ 9352 config = PHY_BCM542XX_DEV_OAM_CONFIG_PTR(pc); 9353 tx_mode = config->tx_dm_config.mode; 9354 tx_flags = config->tx_dm_config.flags; 9355 rx_mode = config->rx_dm_config.mode; 9356 9357 /*********************************************************************** 9358 * NOTE: TOP LEVEL REGISTER ACCESS -> OVERRIDE 9359 * To access TOP level registers use phy_id of port0. Override this ports 9360 */ 9361 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_BASE(pc); 9362 9363 switch(type) { 9364 case SOC_PORT_CONTROL_PHY_OAM_DM_TX_ETHERTYPE: 9365 switch(tx_mode) { 9366 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731: 9367 if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */ 9368 phy_bcm542xx_direct_reg_read(unit, pc, 9369 PHY_BCM542XX_TOP_1588_DM_ETHTYPE2_REG_OFFSET, 9370 &value01); 9371 } else { /*PTP */ 9372 phy_bcm542xx_direct_reg_read(unit, pc, 9373 PHY_BCM542XX_TOP_1588_DM_ETHTYPE1_REG_OFFSET, 9374 &value01); 9375 } 9376 break; 9377 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH: 9378 if (tx_flags & SOC_PORT_PHY_OAM_DM_TS_FORMAT) { /*NTP */ 9379 phy_bcm542xx_direct_reg_read(unit, pc, 9380 PHY_BCM542XX_TOP_1588_DM_ETHTYPE4_REG_OFFSET, 9381 &value01); 9382 } else { /*PTP */ 9383 phy_bcm542xx_direct_reg_read(unit, pc, 9384 PHY_BCM542XX_TOP_1588_DM_ETHTYPE3_REG_OFFSET, 9385 &value01); 9386 } 9387 break; 9388 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF: 9389 phy_bcm542xx_direct_reg_read(unit, pc, 9390 PHY_BCM542XX_TOP_1588_DM_ETHTYPE9_REG_OFFSET, 9391 &value01); 9392 break; 9393 default: 9394 break; 9395 } 9396 9397 COMPILER_64_SET((*value), 0, (uint32)value01); 9398 9399 break; 9400 case SOC_PORT_CONTROL_PHY_OAM_DM_RX_ETHERTYPE: 9401 switch(rx_mode) { 9402 case SOC_PORT_CONFIG_PHY_OAM_DM_Y1731: 9403 phy_bcm542xx_direct_reg_read(unit, pc, 9404 PHY_BCM542XX_TOP_1588_DM_ETHTYPE5_REG_OFFSET, 9405 &value01); 9406 break; 9407 case SOC_PORT_CONFIG_PHY_OAM_DM_BHH: 9408 phy_bcm542xx_direct_reg_read(unit, pc, 9409 PHY_BCM542XX_TOP_1588_DM_ETHTYPE8_REG_OFFSET, 9410 &value01); 9411 break; 9412 case SOC_PORT_CONFIG_PHY_OAM_DM_IETF: 9413 phy_bcm542xx_direct_reg_read(unit, pc, 9414 PHY_BCM542XX_TOP_1588_DM_ETHTYPE10_REG_OFFSET, 9415 &value01); 9416 break; 9417 default: 9418 break; 9419 } 9420 COMPILER_64_SET((*value), 0, (uint32)value01); 9421 break; 9422 case SOC_PORT_CONTROL_PHY_OAM_DM_TX_PORT_MAC_ADDRESS_INDEX: 9423 phy_bcm542xx_direct_reg_read(unit, pc, 9424 PHY_BCM542XX_TOP_1588_DM_MAC_CTL_0_REG_OFFSET, 9425 &value01); 9426 COMPILER_64_SET((*value), 0, ((uint32)value01 >> (dev_port*2)) & 0x3); 9427 break; 9428 case SOC_PORT_CONTROL_PHY_OAM_DM_RX_PORT_MAC_ADDRESS_INDEX: 9429 phy_bcm542xx_direct_reg_read(unit, pc, 9430 PHY_BCM542XX_TOP_1588_DM_MAC_CTL_1_REG_OFFSET, 9431 &value01); 9432 COMPILER_64_SET((*value), 0, ((uint32)value01 >> (dev_port*2)) & 0x3); 9433 break; 9434 case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_1: 9435 phy_bcm542xx_direct_reg_read(unit, pc, 9436 PHY_BCM542XX_TOP_1588_DM_MAC_L1_0_REG_OFFSET, 9437 &value01); 9438 phy_bcm542xx_direct_reg_read(unit, pc, 9439 PHY_BCM542XX_TOP_1588_DM_MAC_L1_1_REG_OFFSET, 9440 &value02); 9441 phy_bcm542xx_direct_reg_read(unit, pc, 9442 PHY_BCM542XX_TOP_1588_DM_MAC_L1_2_REG_OFFSET, 9443 &value03); 9444 COMPILER_64_SET((*value), (uint32)value03, 9445 ((uint32)value02 << 16) | ((uint32)value01)); 9446 break; 9447 case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_2: 9448 phy_bcm542xx_direct_reg_read(unit, pc, 9449 PHY_BCM542XX_TOP_1588_DM_MAC_L2_0_REG_OFFSET, 9450 &value01); 9451 phy_bcm542xx_direct_reg_read(unit, pc, 9452 PHY_BCM542XX_TOP_1588_DM_MAC_L2_1_REG_OFFSET, 9453 &value02); 9454 phy_bcm542xx_direct_reg_read(unit, pc, 9455 PHY_BCM542XX_TOP_1588_DM_MAC_L2_2_REG_OFFSET, 9456 &value03); 9457 COMPILER_64_SET((*value), (uint32)value03, 9458 ((uint32)value02 << 16) | ((uint32)value01)); 9459 break; 9460 case SOC_PORT_CONTROL_PHY_OAM_DM_MAC_ADDRESS_3: 9461 phy_bcm542xx_direct_reg_read(unit, pc, 9462 PHY_BCM542XX_TOP_1588_DM_MAC_L3_0_REG_OFFSET, 9463 &value01); 9464 phy_bcm542xx_direct_reg_read(unit, pc, 9465 PHY_BCM542XX_TOP_1588_DM_MAC_L3_1_REG_OFFSET, 9466 &value02); 9467 phy_bcm542xx_direct_reg_read(unit, pc, 9468 PHY_BCM542XX_TOP_1588_DM_MAC_L3_2_REG_OFFSET, 9469 &value03); 9470 COMPILER_64_SET((*value), (uint32)value03, 9471 ((uint32)value02 << 16) | ((uint32)value01)); 9472 break; 9473 default: 9474 /******************************************************** 9475 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9476 * To access TOP level registers use phy_id of port0. 9477 Now restore back 9478 */ 9479 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9480 return SOC_E_PARAM; 9481 } 9482 /*********************************************************************** 9483 * NOTE: TOP LEVEL REGISTER ACCESS -> RESTORE 9484 * To access TOP level registers use phy_id of port0. Now restore back 9485 */ 9486 pc->phy_id = PHY_BCM542XX_DEV_PHY_ID_ORIG(pc); 9487 9488 return SOC_E_NONE; 9489 } 9490 9491 #ifdef BROADCOM_DEBUG 9492 9493 int 9494 phy_bcm542xx_rdb_reg_set(int unit, soc_port_t port, int rdb, int value){ 9495 phy_ctrl_t *pc = NULL; 9496 uint16 valuer; 9497 9498 pc = EXT_PHY_SW_STATE(unit, port); 9499 9500 phy_bcm542xx_direct_reg_write(unit, pc,(uint16)rdb, (uint16)(value & 0xffff)); 9501 phy_bcm542xx_direct_reg_read(unit, pc,(uint16)rdb, &valuer); 9502 9503 LOG_INFO(BSL_LS_SOC_PHY, 9504 (BSL_META_U(unit, "u=%d p=%d rdb=0x%04x value read back=0x%04x\n"), 9505 unit, port, (uint16) rdb, valuer)); 9506 return SOC_E_NONE; 9507 } 9508 9509 int 9510 phy_bcm542xx_rdb_reg_get(int unit, soc_port_t port, int rdb) { 9511 phy_ctrl_t *pc = NULL; 9512 uint16 value; 9513 9514 pc = EXT_PHY_SW_STATE(unit, port); 9515 9516 phy_bcm542xx_direct_reg_read(unit, pc,(uint16)rdb, &value); 9517 9518 LOG_INFO(BSL_LS_SOC_PHY, 9519 (BSL_META_U(unit,"u=%d p=%d rdb=0x%04x value=0x%04x\n"), 9520 unit, port, (uint16)rdb, value)); 9521 return SOC_E_NONE; 9522 } 9523 9524 #endif 9525 9526 /* 9527 * Variable: phy_542xxdrv_ge 9528 * Purpose: PHY driver for 542XX 9529 */ 9530 phy_driver_t phy_542xxdrv_ge = { 9531 "542XX Gigabit PHY Driver", 9532 phy_bcm542xx_init, 9533 phy_bcm542xx_reset, /* phy_fe_ge_reset */ 9534 phy_bcm542xx_link_get, 9535 phy_bcm542xx_enable_set, 9536 phy_bcm542xx_enable_get, 9537 phy_bcm542xx_duplex_set, 9538 phy_bcm542xx_duplex_get, 9539 phy_bcm542xx_speed_set, 9540 phy_bcm542xx_speed_get, 9541 phy_bcm542xx_master_set, 9542 phy_bcm542xx_master_get, 9543 phy_bcm542xx_autoneg_set, 9544 phy_bcm542xx_autoneg_get, 9545 NULL, /* pd_adv_local_set */ 9546 NULL, /* pd_adv_local_get */ 9547 NULL, /* pd_adv_remote_get */ 9548 phy_bcm542xx_lb_set, 9549 phy_bcm542xx_lb_get, 9550 phy_bcm542xx_interface_set, 9551 phy_bcm542xx_interface_get, 9552 NULL, /* pd_ability */ 9553 phy_bcm542xx_link_up, /* pd_linkup */ 9554 NULL, /* pd_linkdn_evt */ 9555 phy_bcm542xx_mdix_set, 9556 phy_bcm542xx_mdix_get, 9557 phy_bcm542xx_mdix_status_get, 9558 phy_bcm542xx_medium_config_set, 9559 phy_bcm542xx_medium_config_get, 9560 phy_bcm542xx_medium_status, 9561 phy_54280_cable_diag_dispatch, 9562 NULL, /* pd_link_change */ 9563 phy_bcm542xx_control_set, 9564 phy_bcm542xx_control_get, 9565 phy_ge_reg_read, 9566 phy_ge_reg_write, 9567 phy_ge_reg_modify, 9568 NULL, /* pd_notify */ 9569 phy_bcm542xx_probe, /* pd_probe */ 9570 phy_bcm542xx_ability_advert_set, 9571 phy_bcm542xx_ability_advert_get, 9572 phy_bcm542xx_ability_remote_get, 9573 phy_bcm542xx_ability_local_get, 9574 NULL, /* pd_firmware_set */ 9575 phy_bcm542xx_timesync_config_set, 9576 phy_bcm542xx_timesync_config_get, 9577 phy_bcm542xx_timesync_control_set, 9578 phy_bcm542xx_timesync_control_get, 9579 NULL, /* pd_diag_ctrl */ 9580 NULL, /* pd_lane_control_set */ 9581 NULL, /* pd_lane_control_get */ 9582 NULL, /* pd_lane_reg_read */ 9583 NULL, /* pd_lane_reg_write */ 9584 phy_bcm542xx_oam_config_set, 9585 phy_bcm542xx_oam_config_get, 9586 phy_bcm542xx_oam_control_set, 9587 phy_bcm542xx_oam_control_get, 9588 phy_bcm542xx_timesync_enhanced_capture_get 9589 }; 9590 9591 #else /* INCLUDE_PHY_542XX */ 9592 int _soc_phy_542xx_not_empty; 9593 #endif /* INCLUDE_PHY_542XX */