phy8481.c (396628B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: phy8481.c 8 * Purpose: PHY Driver support for Broadcom 8481/848xx Serial 10Gig 9 * transceiver with XAUI/XFI interface. 10 */ 11 12 #ifdef BCM_PLP_BASE_T_PHY /* ePIL standalone driver */ 13 #define PHYMOD_SUPPORT 14 #define INCLUDE_PHY_8481 15 #else /* switch SDK driver */ 16 #define BCM848XX_DIAG_DSC_SUPPORT 17 #endif /* BCM_PLP_BASE_T_PHY */ 18 19 #define BCM848XX_STATE_MFG_DIAG_SUPPORT 20 21 #include <sal/types.h> 22 #include <shared/bsl.h> 23 #include <soc/drv.h> 24 #include <soc/debug.h> 25 #include <soc/error.h> 26 #include <soc/phyreg.h> 27 28 #include <soc/phy.h> 29 #include <soc/phy/phyctrl.h> 30 #include <soc/phy/drv.h> 31 32 #ifdef BCM_PLP_BASE_T_PHY /** ePIL PLP standalone driver **/ 33 #define PHYMOD_SUPPORT 34 #define INCLUDE_PHY_8481 35 #include "legacy.h" 36 #include <soc/property.h> 37 #else /** switch SDK driver **/ 38 #define BCM848XX_DIAG_DSC_SUPPORT 39 #include <soc/drv.h> 40 #include <soc/debug.h> 41 #include "phydefs.h" /* Must include before other phy related includes */ 42 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 43 #include "phyident.h" 44 #include "phyreg.h" 45 #include "phynull.h" 46 #include "phyxehg.h" 47 #endif /* BCM_PLP_BASE_T_PHY */ 48 49 #define BCM848XX_STATE_MFG_DIAG_SUPPORT 50 51 #if defined(INCLUDE_PHY_8481) 52 53 #include "phy8481.h" 54 55 /* 56 #define PHY8481_ARM_MEM_DEBUG 57 #define PHY8481_DEBUG_AUTOMEDIUM 58 #define PHY8481_FW_DEBUG 59 #define PHY8185X_DEBUG_CMD_HANDLER 60 */ 61 extern uint8 bcm_8481_firmware[]; 62 extern int bcm_8481_firmware_size; 63 64 extern uint8 bcm_8482A0_firmware[]; 65 extern int bcm_8482A0_firmware_size; 66 67 extern uint8 bcm_8482B0_firmware[]; 68 extern int bcm_8482B0_firmware_size; 69 70 extern uint8 bcm_8482B1_firmware[]; 71 extern int bcm_8482B1_firmware_size; 72 73 extern uint8 bcm_84833_firmware[]; 74 extern int bcm_84833_firmware_size; 75 76 extern uint8 bcm_84844_firmware[]; 77 extern int bcm_84844_firmware_size; 78 79 extern uint8 bcm_84858_firmware[]; 80 extern int bcm_84858_firmware_size; 81 82 extern uint8 bcm_8486x_firmware[]; 83 extern int bcm_8486x_firmware_size; 84 85 extern uint8 bcm_84888A0_firmware[]; 86 extern int bcm_84888A0_firmware_size; 87 88 extern uint8 bcm_84888B0_firmware[]; 89 extern int bcm_84888B0_firmware_size; 90 91 extern void get_dsc_param_koi(void); 92 extern void get_dsc_param_orca(void); 93 94 extern void set_pc(phy_ctrl_t *pc); 95 extern void set_intpc(phy_ctrl_t *pc); 96 97 #define SOC_PORT_MEDIUM_XAUI SOC_PORT_MEDIUM_FIBER 98 #define PHY_FLAGS_XAUI PHY_FLAGS_FIBER 99 #define PHY_XAUI_MODE(unit, port) PHY_FIBER_MODE((unit), (port)) 100 #define SOC_PA_MEDIUM_XAUI SOC_PA_MEDIUM_FIBER 101 102 #define PHY8483X_MFG_TEST_SUPPORT 0x1 103 #define PHY8483X_STATE_TEST_SUPPORT 0x2 104 #define PHY8483X_FULL_SNR_SUPPORT 0x4 105 #define PHY8483X_TIMESYNC_ENABLED 0x8 106 #define PHY8483X_ATOMIC_ACCESS_SHD 0x10 107 108 /* PRBS */ 109 #define PHY84834_FORTYG_PRBS_PATTERN_TESTING_CONTROL_STATUS 0x0135 110 #define PHY84834_40G_PRBS31 (1 << 7) 111 #define PHY84834_40G_PRBS9 (1 << 6) 112 #define PHY84834_40G_PRBS_TX_ENABLE (1 << 3) 113 #define PHY84834_40G_PRBS_RX_ENABLE (1 << 0) 114 #define PHY84834_40G_PRBS_ENABLE (PHY84834_40G_PRBS_RX_ENABLE | \ 115 PHY84834_40G_PRBS_TX_ENABLE) 116 117 #define PHY84834_FORTYG_PRBS_RECEIVE_ERROR_COUNTER_LANE0 0x0140 118 #define PHY84834_USER_PRBS_CONTROL_0_REGISTER 0xCD14 119 #define PHY84834_USER_PRBS_TX_INVERT (1 << 4) 120 #define PHY84834_USER_PRBS_RX_INVERT (1 << 15) 121 #define PHY84834_USER_PRBS_INVERT (1 << 4 | 1 << 15) 122 #define PHY84834_USER_PRBS_ENABLE (1 << 7) 123 #define PHY84834_USER_PRBS_TYPE_MASK (0x7) 124 125 #define PHY84834_USER_PRBS_STATUS_0_REGISTER 0xCD15 126 #define PHY84834_GENSIG_8071_REGISTER 0xCD16 127 #define PHY84834_RESET_CONTROL_REGISTER 0xCD17 128 129 #define PHY8485X_MDIO_CONTROL_REGISTER 0x4110 130 #define PHY8485X_TX_PRBS_REGISTER 0xD0E1 131 #define PHY848XX_TX_PRBS_ADDR32_REGISTER 0xD203A1C2 132 #define PHY8485X_RX_PRBS_REGISTER 0xD0D1 133 #define PHY848XX_RX_PRBS_ADDR32_REGISTER 0xD203A1A2 134 #define PHY8485X_PRBS_STATUS_REGISTER 0xD0D9 135 #define PHY8485X_PRBS_ERR_COUNT_MSB_REGSTER 0xD0DA 136 #define PHY8485X_PRBS_ERR_COUNT_LSB_REGSTER 0xD0DB 137 #define PHY8488X_EN_CLK_MDC_XFI 0x8003 138 139 #define PHY8485X_USER_PRBS_TYPE_MASK 0x1 140 #define PHY8485X_USER_PRBS_ENABLE 0x1 141 142 #define PHY8488X_MDIO_CLOCK_CONTROL_REGISTER 0x8003 143 #define PHY8488X_EN_CLK_MDC_XFI_SHIFT 0 144 #define PHY8488X_EN_CLK_MDC_XFI_MASK BIT(PHY8488X_EN_CLK_MDC_XFI_SHIFT) 145 #define PHY84834_DIAG_CMD_ACCESS_32BIT_XFI_ADDR 0xC020 146 #define PHY848XX_PRBS_TX_ADDR32_REGISTER 0xD203A1C2 147 #define PHY848XX_PRBS_RX_ADDR32_REGISTER 0xD203A1A2 148 149 #define ADDR32BIT_HIGH(_addr32) ((uint16) ((_addr32) >> 16)) 150 #define ADDR32BIT_LOW(_addr32) ((uint16) ((_addr32) & 0xFFFF)) 151 #define ADDR32BIT_WRITE 0x0000 152 #define ADDR32BIT_READ 0x0001 153 154 #define PHY848XX_PRBS_INVERT_SHFT 4 155 #define PHY848XX_PRBS_POLYNOMIAL_SHFT 1 156 #define PHY848XX_PRBS_ENABLE_SHFT 0 157 #define PHY848XX_PRBS_INVERT_MASK (0x1U << PHY848XX_PRBS_INVERT_SHFT) 158 #define PHY848XX_PRBS_POLYNOMIAL_MASK (0x7U << PHY848XX_PRBS_POLYNOMIAL_SHFT) 159 #define PHY848XX_PRBS_ENABLE_MASK (0x1U << PHY848XX_PRBS_ENABLE_SHFT) 160 #define PHY848XX_PRBS_PARAMETER_MASK (PHY848XX_PRBS_INVERT_MASK | \ 161 PHY848XX_PRBS_POLYNOMIAL_MASK) 162 163 164 165 #define REG_GROUP_SHADOW18 0x18 166 #define REG_GROUP_SHADOW1c 0x1c 167 #define REG_GROUP_SHADOW_MISC_REG 0x17 168 #define REG_GROUP_SHADOW_EXP_REG 0xf 169 170 #define PHY8485X_PREEMPH_GET_PRE_TAP(_val) \ 171 ((_val) & 0xf) 172 173 #define PHY8485X_PREEMPH_CTRL_MAIN_TAP_SHFT 4 174 #define PHY8485X_PREEMPH_GET_MAIN_TAP(_val) \ 175 (((_val) >> PHY8485X_PREEMPH_CTRL_MAIN_TAP_SHFT) & 0x3f) 176 177 #define PHY8485X_PREEMPH_CTRL_POST_TAP1_SHFT 10 178 #define PHY8485X_PREEMPH_GET_POST_TAP1(_val) \ 179 (((_val) >> PHY8485X_PREEMPH_CTRL_POST_TAP1_SHFT) & 0x1f) 180 181 #define PHY8485X_PREEMPH_CTRL_POST_TAP2_SHFT 16 182 #define PHY8485X_PREEMPH_GET_POST_TAP2(_val) \ 183 (((_val) >> PHY8485X_PREEMPH_CTRL_POST_TAP2_SHFT) & 0x7) 184 185 #define PHY8485X_PREEMPH_CTRL_HPF_EN_SHFT 15 186 #define PHY8485X_PREEMPH_GET_HPF_EN(_val) \ 187 (((_val) >> PHY8485X_PREEMPH_CTRL_HPF_EN_SHFT) & 0x1) 188 189 /* 5 bits pre_tap for SOC_PHY_CONTROL_PREEMPHASIS */ 190 #define PHY8488X_PREEMPH_CTL_PRE_TAP_MASK 0x1f 191 #define PHY8488X_PREEMPH_CTL_PRE_TAP_SHFT 0 192 #define PHY8488X_PREEMPH_GET_PRE_TAP(_val) \ 193 (((_val) >> PHY8488X_PREEMPH_CTL_PRE_TAP_SHFT) & PHY8488X_PREEMPH_CTL_PRE_TAP_MASK) 194 #define PHY8488X_PREEMPH_SET_PRE_TAP(_val) \ 195 (((_val) & PHY8488X_PREEMPH_CTL_PRE_TAP_MASK) << PHY8488X_PREEMPH_CTL_PRE_TAP_SHFT) 196 /* 7 bits main_tap for SOC_PHY_CONTROL_PREEMPHASIS */ 197 #define PHY8488X_PREEMPH_CTL_MAIN_TAP_MASK 0x3f 198 #define PHY8488X_PREEMPH_CTL_MAIN_TAP_SHFT 5 199 #define PHY8488X_PREEMPH_GET_MAIN_TAP(_val) \ 200 (((_val) >> PHY8488X_PREEMPH_CTL_MAIN_TAP_SHFT) & PHY8488X_PREEMPH_CTL_MAIN_TAP_MASK) 201 #define PHY8488X_PREEMPH_SET_MAIN_TAP(_val) \ 202 (((_val) & PHY8488X_PREEMPH_CTL_MAIN_TAP_MASK) << PHY8488X_PREEMPH_CTL_MAIN_TAP_SHFT) 203 /* 6 bits post1_tap for SOC_PHY_CONTROL_PREEMPHASIS */ 204 #define PHY8488X_PREEMPH_CTL_POST1_MASK 0x3f 205 #define PHY8488X_PREEMPH_CTL_POST1_SHFT 12 206 #define PHY8488X_PREEMPH_GET_POST1_TAP(_val) \ 207 (((_val) >> PHY8488X_PREEMPH_CTL_POST1_SHFT) & PHY8488X_PREEMPH_CTL_POST1_MASK) 208 #define PHY8488X_PREEMPH_SET_POST1_TAP(_val) \ 209 (((_val) & PHY8488X_PREEMPH_CTL_POST1_MASK) << PHY8488X_PREEMPH_CTL_POST1_SHFT) 210 /* 5 bits post2_tap for SOC_PHY_CONTROL_PREEMPHASIS (signed) */ 211 #define PHY8488X_PREEMPH_CTL_POST2_MASK 0x1f 212 #define PHY8488X_PREEMPH_CTL_POST2_SHFT 18 213 #define PHY8488X_PREEMPH_GET_POST2_TAP(_val) \ 214 (((_val) >> PHY8488X_PREEMPH_CTL_POST2_SHFT) & PHY8488X_PREEMPH_CTL_POST2_MASK) 215 #define PHY8488X_PREEMPH_SET_POST2_TAP(_val) \ 216 (((_val) & PHY8488X_PREEMPH_CTL_POST2_MASK) << PHY8488X_PREEMPH_CTL_POST2_SHFT) 217 /* 4 bits post3_tap for SOC_PHY_CONTROL_PREEMPHASIS (signed) */ 218 #define PHY8488X_PREEMPH_CTL_POST3_MASK 0x0f 219 #define PHY8488X_PREEMPH_CTL_POST3_SHFT 24 220 #define PHY8488X_PREEMPH_GET_POST3_TAP(_val) \ 221 (((_val) >> PHY8488X_PREEMPH_CTL_POST3_SHFT) & PHY8488X_PREEMPH_CTL_POST3_MASK) 222 #define PHY8488X_PREEMPH_SET_POST3_TAP(_val) \ 223 (((_val) & PHY8488X_PREEMPH_CTL_POST3_MASK) << PHY8488X_PREEMPH_CTL_POST3_SHFT) 224 225 /* typedefs */ 226 typedef struct { 227 int flags; 228 soc_timeout_t to; 229 uint8 *firmware; 230 int firmware_len; 231 int dl_dividend; 232 int dl_divisor; 233 uint32 phy_ext_rom_boot; 234 int sys_forced_cl72; 235 int link_down; 236 int lb_speed; /* intended speed for PHY loopback */ 237 } PHY8481_PRIV_t; 238 239 #define LINK_DOWN(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->link_down) 240 #define FLAGS(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->flags) 241 #define TO(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->to) 242 #define FIRMWARE(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->firmware) 243 #define FIRMWARE_LEN(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->firmware_len) 244 #define DL_DIVIDEND(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->dl_dividend) 245 #define DL_DIVISOR(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->dl_divisor) 246 #define PHY_EXT_ROM_BOOT(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->phy_ext_rom_boot) 247 #define SYS_FORCED_CL72(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->sys_forced_cl72) 248 #define LB_SPEED(_pc) (((PHY8481_PRIV_t *)((_pc) + 1))->lb_speed) 249 250 #define PHY_ADDR_NONE 0xFF 251 #define NXT_PC(pc) ((phy_ctrl_t *)((pc)->driver_data)) 252 #define LAST_IN_CHAIN(pc) (PHY_IS_CHAINED((pc)->unit, (pc)->port) && !NXT_PC(pc)) 253 254 #define PHYDRV_CALL_NOARG(pc,name) \ 255 do { \ 256 if (pc->driver_data) { \ 257 int rv; \ 258 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 259 EXT_PHY_SW_STATE(pc->unit,pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 260 rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port); \ 261 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 262 if (SOC_FAILURE(rv)) { \ 263 return rv; \ 264 } \ 265 } \ 266 } while(0) 267 268 #define PHYDRV_CALL_ARG1(pc,name,arg0) \ 269 do { \ 270 if (pc->driver_data) { \ 271 int rv; \ 272 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 273 EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 274 rv = name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit, \ 275 (pc)->port,arg0); \ 276 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 277 if (SOC_FAILURE(rv)) { \ 278 return rv; \ 279 } \ 280 } \ 281 } while(0) 282 283 #define PHYDRV_CALL_ARG2(pc,name,arg0,arg1) \ 284 do { \ 285 if (pc->driver_data) { \ 286 int rv; \ 287 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 288 EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 289 rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \ 290 arg1); \ 291 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 292 if (SOC_FAILURE(rv)) { \ 293 return rv; \ 294 } \ 295 } \ 296 } while(0) 297 298 #define PHYDRV_CALL_ARG3(pc,name,arg0,arg1,arg2) \ 299 do { \ 300 if (pc->driver_data) { \ 301 int rv; \ 302 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 303 EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 304 rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \ 305 arg1,arg2); \ 306 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 307 if (SOC_FAILURE(rv)) { \ 308 return rv; \ 309 } \ 310 } \ 311 } while(0) 312 313 #define PHYDRV_CALL_ARG4(pc,name,arg0,arg1,arg2,arg3) \ 314 do { \ 315 if (pc->driver_data) { \ 316 int rv; \ 317 phy_ctrl_t * tmp_pc = EXT_PHY_SW_STATE(pc->unit, pc->port); \ 318 EXT_PHY_SW_STATE(pc->unit, pc->port) = (phy_ctrl_t *)(pc->driver_data); \ 319 rv=name(((phy_ctrl_t *)(pc->driver_data))->pd,(pc)->unit,(pc)->port,arg0, \ 320 arg1,arg2,arg3); \ 321 EXT_PHY_SW_STATE(pc->unit, pc->port) = tmp_pc; \ 322 if (SOC_FAILURE(rv)) { \ 323 return rv; \ 324 } \ 325 } \ 326 } while(0) 327 328 /* default MDIO addresses of phy device on the xaui port, per port based*/ 329 static uint8 ext_phy_dft_addr1[] = { 330 PHY_ADDR_NONE, /* 0 */ 331 PHY_ADDR_NONE, /* 1 */ 332 PHY_ADDR_NONE, /* 2 */ 333 PHY_ADDR_NONE, /* 3 */ 334 PHY_ADDR_NONE, /* 4 */ 335 PHY_ADDR_NONE, /* 5 */ 336 PHY_ADDR_NONE, /* 6 */ 337 PHY_ADDR_NONE, /* 7 */ 338 PHY_ADDR_NONE, /* 8 */ 339 PHY_ADDR_NONE, /* 9 */ 340 PHY_ADDR_NONE, /* 10 */ 341 PHY_ADDR_NONE, /* 11 */ 342 PHY_ADDR_NONE, /* 12 */ 343 PHY_ADDR_NONE, /* 13 */ 344 PHY_ADDR_NONE, /* 14 */ 345 PHY_ADDR_NONE, /* 15 */ 346 PHY_ADDR_NONE, /* 16 */ 347 PHY_ADDR_NONE, /* 17 */ 348 PHY_ADDR_NONE, /* 18 */ 349 PHY_ADDR_NONE, /* 19 */ 350 PHY_ADDR_NONE, /* 20 */ 351 PHY_ADDR_NONE, /* 21 */ 352 PHY_ADDR_NONE, /* 22 */ 353 PHY_ADDR_NONE, /* 23 */ 354 PHY_ADDR_NONE, /* 24 */ 355 PHY_ADDR_NONE, /* 25 */ 356 PHY_ADDR_NONE, /* 26 */ 357 PHY_ADDR_NONE, /* 27 */ 358 PHY_ADDR_NONE, /* 28 */ 359 PHY_ADDR_NONE, /* 29 */ 360 PHY_ADDR_NONE, /* 30 */ 361 PHY_ADDR_NONE, /* 31 */ 362 PHY_ADDR_NONE, /* 32 */ 363 PHY_ADDR_NONE, /* 33 */ 364 PHY_ADDR_NONE, /* 34 */ 365 PHY_ADDR_NONE, /* 35 */ 366 PHY_ADDR_NONE, /* 36 */ 367 PHY_ADDR_NONE /* 37 */ 368 }; 369 370 #define PHY_FW_HANDSHAKE(unit, port) \ 371 do { \ 372 if (PHY_HS_CAPABLE(unit, port)) { \ 373 soc_timeout_t to; \ 374 uint16 status; \ 375 int rv; \ 376 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); \ 377 sal_usleep(100); \ 378 soc_timeout_init(&to, 2000000, 0); \ 379 do { \ 380 rv = READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400e, &status); \ 381 if (((status & 0x2) == 0) || SOC_FAILURE(rv)) { \ 382 break; \ 383 } \ 384 } while (!soc_timeout_check(&to)); \ 385 if (((status & 0x2) != 0) && (status != 0xffff)) { \ 386 LOG_WARN(BSL_LS_SOC_PHY, \ 387 (BSL_META_U(unit, \ 388 "PHY8481 firmware handshake failed: u=%d p=%d status=0x%04x\n"), \ 389 unit, port, status)); \ 390 } \ 391 } else { \ 392 sal_usleep(700000); \ 393 } \ 394 } while (0) 395 396 #define PHY_IS_BCM84823(_pc) ( PHY_MODEL_CHECK((_pc), \ 397 PHY_BCM84823_OUI, \ 398 PHY_BCM84823_MODEL) ) 399 400 #define PHY_IS_BCM84833(_pc) ( PHY_MODEL_CHECK((_pc), \ 401 PHY_BCM84833_OUI, \ 402 PHY_BCM84833_MODEL) ) 403 404 #define PHY_IS_BCM84834(_pc) ( PHY_MODEL_CHECK((_pc), \ 405 PHY_BCM84834_OUI, \ 406 PHY_BCM84834_MODEL) ) 407 408 #define PHY_IS_BCM84844(_pc) ( PHY_MODEL_CHECK((_pc), \ 409 PHY_BCM84844_OUI, \ 410 PHY_BCM84844_MODEL) ) 411 412 #define PHY_IS_BCM8484X_A0(_pc) (PHY_IS_BCM8484X(_pc) \ 413 && ((_pc)->phy_rev == 0x8 )) 414 415 416 #define PHY_IS_BCM84836(_pc) ( PHY_MODEL_CHECK((_pc), \ 417 PHY_BCM84836_OUI, \ 418 PHY_BCM84836_MODEL) ) 419 420 #define PHY_IS_BCM84846(_pc) ( PHY_MODEL_CHECK((_pc), \ 421 PHY_BCM84846_OUI, \ 422 PHY_BCM84846_MODEL) ) 423 424 #define PHY_IS_BCM84848(_pc) ( PHY_MODEL_CHECK((_pc), \ 425 PHY_BCM84848_OUI, \ 426 PHY_BCM84848_MODEL) ) 427 428 #define PHY_IS_BCM8483X(_pc) \ 429 ( ((_pc)->phy_oui == PHY_BCM8483X_OUI) && \ 430 (((_pc)->phy_model == PHY_BCM84833_MODEL) || \ 431 ((_pc)->phy_model == PHY_BCM84834_MODEL) || \ 432 ((_pc)->phy_model == PHY_BCM84835_MODEL) || \ 433 ((_pc)->phy_model == PHY_BCM84836_MODEL)) ) 434 435 #define PHY_IS_BCM8484X(_pc) \ 436 ( ((_pc)->phy_oui == PHY_BCM8484X_OUI) && \ 437 (((_pc)->phy_model == PHY_BCM84844_MODEL) || \ 438 ((_pc)->phy_model == PHY_BCM84848_MODEL) || \ 439 ((_pc)->phy_model == PHY_BCM84846_MODEL)) ) 440 441 #define PHY_IS_BCM84858(_pc) ( PHY_MODEL_CHECK((_pc), \ 442 PHY_BCM84858_OUI, \ 443 PHY_BCM84858_MODEL) ) 444 445 #define PHY_IS_BCM84856(_pc) ( PHY_MODEL_CHECK((_pc), \ 446 PHY_BCM84856_OUI, \ 447 PHY_BCM84856_MODEL) ) 448 449 #define PHY_IS_BCM8485X(_pc) \ 450 ( ((_pc)->phy_oui == PHY_BCM8485X_OUI) && \ 451 (((_pc)->phy_model == PHY_BCM84858_MODEL) || \ 452 ((_pc)->phy_model == PHY_BCM84856_MODEL)) ) 453 #define PHY_IS_BCM8486X(_pc) \ 454 ( ((_pc)->phy_oui == PHY_BCM8486X_OUI) && \ 455 (((_pc)->phy_model == PHY_BCM84860_MODEL) || \ 456 ((_pc)->phy_model == PHY_BCM84861_MODEL) || \ 457 ((_pc)->phy_model == PHY_BCM84864_MODEL) || \ 458 ((_pc)->phy_model == PHY_BCM84868_MODEL)) ) 459 460 #define PHY_IS_BCM84888(_pc) ( PHY_MODEL_CHECK((_pc), \ 461 PHY_BCM84888_OUI, \ 462 PHY_BCM84888_MODEL) ) 463 464 #define PHY_IS_BCM84884(_pc) ( PHY_MODEL_CHECK((_pc), \ 465 PHY_BCM84884_OUI, \ 466 PHY_BCM84884_MODEL) ) 467 468 #define PHY_IS_BCM84888E(_pc) ( PHY_MODEL_CHECK((_pc), \ 469 PHY_BCM84888E_OUI, \ 470 PHY_BCM84888E_MODEL) ) 471 472 #define PHY_IS_BCM84884E(_pc) ( PHY_MODEL_CHECK((_pc), \ 473 PHY_BCM84884E_OUI, \ 474 PHY_BCM84884E_MODEL) ) 475 476 #define PHY_IS_BCM84881(_pc) ( PHY_MODEL_CHECK((_pc), \ 477 PHY_BCM84881_OUI, \ 478 PHY_BCM84881_MODEL) ) 479 480 #define PHY_IS_BCM84880(_pc) ( PHY_MODEL_CHECK((_pc), \ 481 PHY_BCM84880_OUI, \ 482 PHY_BCM84880_MODEL) ) 483 484 #define PHY_IS_BCM84888S(_pc) ( PHY_MODEL_CHECK((_pc), \ 485 PHY_BCM84888S_OUI, \ 486 PHY_BCM84888S_MODEL) ) 487 488 #define PHY_IS_BCM84885(_pc) ( PHY_MODEL_CHECK((_pc), \ 489 PHY_BCM84885_OUI, \ 490 PHY_BCM84885_MODEL) ) 491 492 #define PHY_IS_BCM84886(_pc) ( PHY_MODEL_CHECK((_pc), \ 493 PHY_BCM84886_OUI, \ 494 PHY_BCM84886_MODEL) ) 495 496 #define PHY_IS_BCM84887(_pc) ( PHY_MODEL_CHECK((_pc), \ 497 PHY_BCM84887_OUI, \ 498 PHY_BCM84887_MODEL) ) 499 500 #define PHY_IS_BCM8488X(_pc) \ 501 ( ((_pc)->phy_oui == PHY_BCM8488X_OUI) && \ 502 (((_pc)->phy_model == PHY_BCM84888_MODEL) || \ 503 ((_pc)->phy_model == PHY_BCM84884_MODEL) || \ 504 ((_pc)->phy_model == PHY_BCM84888E_MODEL) || \ 505 ((_pc)->phy_model == PHY_BCM84881_MODEL) || \ 506 ((_pc)->phy_model == PHY_BCM84880_MODEL) || \ 507 ((_pc)->phy_model == PHY_BCM84884E_MODEL) || \ 508 ((_pc)->phy_model == PHY_BCM84888S_MODEL) || \ 509 ((_pc)->phy_model == PHY_BCM84885_MODEL) || \ 510 ((_pc)->phy_model == PHY_BCM84886_MODEL) || \ 511 ((_pc)->phy_model == PHY_BCM84887_MODEL) ) ) 512 513 #define PHY_IS_BCM8488X_A0(_pc) \ 514 ( PHY_IS_BCM8488X(_pc) && \ 515 ((_pc)->phy_rev == 0x0) ) 516 517 #define PHY_IS_BCM8486X_AND_UP(_pc) \ 518 ( PHY_IS_BCM8486X((_pc)) || \ 519 PHY_IS_BCM8488X(_pc) ) 520 521 #define PHY_IS_BCM8485X_AND_UP(_pc) \ 522 ( PHY_IS_BCM8485X((_pc)) || \ 523 PHY_IS_BCM8486X((_pc)) || \ 524 PHY_IS_BCM8488X(_pc) ) 525 526 #define PHY_IS_BCM8484X_AND_UP(_pc) \ 527 ( PHY_IS_BCM8484X((_pc)) || \ 528 PHY_IS_BCM8485X((_pc)) || \ 529 PHY_IS_BCM8486X((_pc)) || \ 530 PHY_IS_BCM8488X(_pc) ) 531 532 #define PHY_IS_BCM8483X_AND_UP(_pc) \ 533 ( PHY_IS_BCM8483X((_pc)) || \ 534 PHY_IS_BCM8484X((_pc)) || \ 535 PHY_IS_BCM8485X((_pc)) || \ 536 PHY_IS_BCM8486X((_pc)) || \ 537 PHY_IS_BCM8488X(_pc) ) 538 539 #define PHY8481_IS_READY_FOR_CMD(_pc, _status) \ 540 ((PHY_IS_BCM8483X(_pc) || PHY_IS_BCM8484X(_pc)) \ 541 ? ( _status & PHY84834_CMD_OPEN_FOR_CMDS) \ 542 : ((_status != PHY8485X_CMD_SYSTEM_BUSY) && \ 543 (_status != PHY8485X_CMD_IN_PROGRESS)) ) 544 545 #define PHY8481_IS_OPEN_FOR_CMD(_pc, _status) \ 546 ((PHY_IS_BCM8483X(_pc) || PHY_IS_BCM8484X(_pc)) \ 547 ? ( _status & PHY84834_CMD_OPEN_FOR_CMDS) \ 548 : ((_status == PHY8485X_CMD_OPEN_FOR_CMDS) || \ 549 (_status == PHY8485X_CMD_COMPLETE_ERROR)) ) 550 551 #define PHY8481_IS_CMD_COMPLETE(_pc, _status) \ 552 ((PHY_IS_BCM8483X(_pc) || PHY_IS_BCM8484X(_pc)) \ 553 ? ((_status & PHY8481_CMD_COMPLETE_PASS) || \ 554 (_status & PHY8481_CMD_COMPLETE_ERROR)) \ 555 : ((_status == PHY8485X_CMD_OPEN_FOR_CMDS) || \ 556 (_status == PHY8485X_CMD_COMPLETE_ERROR)) ) 557 558 #define PHY8481_SET_FIBER_PREFERRED(unit, port, pc)\ 559 do { \ 560 int fiber_preferred; \ 561 uint16 data16; \ 562 if (!PHY_FORCED_COPPER_MODE(unit, port)) { \ 563 /* Read the strap value and set fiber pref accordingly. */ \ 564 SOC_IF_ERROR_RETURN \ 565 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16));\ 566 fiber_preferred = soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, (data16 & (1U << 8)) ? 1 : 0);\ 567 pc->automedium = TRUE; /* Always TRUE for this PHY */ } \ 568 else { fiber_preferred = FALSE; pc->automedium = FALSE; } \ 569 pc->copper.preferred = !fiber_preferred; \ 570 pc->fiber.preferred = fiber_preferred; \ 571 }while(0) 572 573 #define PHY8481_ENABLE_MEDIUM(_pc)\ 574 do { _pc->copper.enable = TRUE;\ 575 _pc->copper.force_duplex = TRUE;\ 576 _pc->copper.force_speed = 10000;\ 577 _pc->copper.autoneg_enable = TRUE;\ 578 _pc->copper.master = SOC_PORT_MS_AUTO;\ 579 _pc->copper.mdix = SOC_PORT_MDIX_AUTO;\ 580 _pc->fiber.enable = TRUE;\ 581 _pc->fiber.force_speed = 10000;\ 582 _pc->fiber.force_duplex = TRUE;\ 583 _pc->fiber.autoneg_enable = FALSE;\ 584 } while(0) 585 586 STATIC int phy_8481_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability); 587 STATIC int phy_8481_speed_get(int unit, soc_port_t port, int *speed); 588 STATIC int phy_8481_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability); 589 STATIC int phy_8481_an_get(int unit, soc_port_t port, int *an, int *an_done); 590 STATIC int phy_8481_an_set(int unit, soc_port_t port, int an); 591 STATIC int phy_8481_speed_set(int unit, soc_port_t port, int speed); 592 STATIC int phy_8481_duplex_set(int unit, soc_port_t port, int duplex); 593 STATIC int phy_8481_link_up(int unit, soc_port_t port); 594 STATIC int phy_8481_enable_set(int unit, soc_port_t port, int enable); 595 STATIC int phy_8481_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode); 596 597 STATIC int _phy_8481_xaui_an_get(int unit, soc_port_t port, int *an, int *an_done); 598 STATIC int _phy_8481_xaui_an_set(int unit, soc_port_t port, int an); 599 STATIC int _phy_8481_medium_change(int unit, soc_port_t port, int force_update); 600 STATIC int _phy_8481_medium_config_update(int unit, soc_port_t port,soc_phy_config_t *cfg); 601 STATIC int _phy_8481_xaui_speed_get(int unit, soc_port_t port, int *speed); 602 STATIC int _phy_8481_xaui_speed_set(int unit, soc_port_t port, int speed); 603 STATIC int _phy_8481_medium_check(int unit, soc_port_t port, int *medium); 604 STATIC int _phy_8481_xaui_enable_set(int unit, soc_port_t port, int enable); 605 STATIC int _phy_8481_xaui_enable_get(int unit, soc_port_t port, int *enable); 606 STATIC int _phy_8481_copper_enable_set(int unit, soc_port_t port, int enable); 607 STATIC int _phy_8481_copper_enable_get(int unit, soc_port_t port, int *enable); 608 STATIC int _phy_8481_halt(int unit, phy_ctrl_t *pc); 609 STATIC int _phy_8481_write_to_arm(int unit, phy_ctrl_t *pc, uint32 addr, uint8 *data,int len); 610 STATIC int _phy_8481_restart(int unit, phy_ctrl_t *pc); 611 STATIC int _phy_8481_copper_an_set(int unit, soc_port_t port, int an); 612 STATIC int _phy_8481_copper_lb_get(int unit, soc_port_t port, int *enable); 613 STATIC int _phy_8481_xaui_nxt_dev_probe(int unit, soc_port_t port); 614 /* STATIC */ int _phy84834_top_level_cmd_set(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size); 615 /* STATIC */ int _phy84834_top_level_cmd_get(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size); 616 /* STATIC */ int _phy84834_top_level_cmd_set_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size); 617 /* STATIC */ int _phy84834_top_level_cmd_get_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size); 618 STATIC int _phy8481_adjust_xfi_tx_preemphasis(int unit, int port, phy_ctrl_t *pc, uint32 phy_long_xfi); 619 STATIC int _phy848xx_short_reach_enable_set(int unit,phy_ctrl_t *pc, uint16 enable ); 620 STATIC int _phy_84834_power_mode_set (int unit, soc_port_t port, uint32 mode); 621 STATIC int _phy_84834_power_mode_get (int unit, soc_port_t port, uint32 *mode); 622 STATIC int _phy_8481_check_firmware(int unit,phy_ctrl_t *pc); 623 STATIC int _phy_8481_copper_speed_get(int unit, soc_port_t port, int *speed); 624 STATIC int _phy_8481_copper_duplex_get(int unit, soc_port_t port, int *duplex); 625 STATIC int _phy_8481_copper_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability); 626 STATIC int _phy_8481_copper_an_get(int unit, soc_port_t port, int *an, int *an_done); 627 STATIC int _phy_8481_xaui_duplex_get(int unit, soc_port_t port, int *duplex); 628 STATIC int _phy_8481_xaui_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability); 629 STATIC int _phy8485x_shadow_reg_read(int unit, phy_ctrl_t *pc, uint16 data1, uint16 data2, uint16 data3 , uint16 data4, uint16 *value); 630 STATIC int _phy8485x_shadow_reg_write(int unit, phy_ctrl_t *pc, uint16 reg_group, uint16 reg_addr, uint16 bit_mask, uint16 bit_shift, uint16 value); 631 STATIC int _phy84834_xfi_reg_set(int unit, phy_ctrl_t *pc, uint16 bank, uint16 offset, uint16 value); 632 STATIC int _phy_84834_control_set(int unit, soc_port_t port, int intf, int lane, soc_phy_control_t type, uint32 value); 633 STATIC int _phy_84834_control_get(int unit, soc_port_t port, int intf, int lane, soc_phy_control_t type, uint32 *value); 634 635 int 636 phy_8481_reg_xge_read(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 637 uint8 dev_addr, uint16 reg_addr, uint16 *data); 638 int 639 phy_8481_reg_xge_write(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 640 uint8 dev_addr, uint16 reg_addr, uint16 data); 641 int 642 phy_8481_reg_xge_modify(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 643 uint8 dev_addr, uint16 reg_addr, uint16 data, uint16 mask); 644 #ifdef PHY8185X_DEBUG_CMD_HANDLER 645 STATIC int _phy8485x_emi_mode_enable_get(int unit, phy_ctrl_t *pc, uint16 *status); 646 STATIC int _phy8485x_emi_mode_enable_set(int unit, phy_ctrl_t *pc, uint16 status); 647 STATIC int _phy8485x_sub_lf_rf_status_get(int unit, phy_ctrl_t *pc, uint16 *status); 648 STATIC int _phy8485x_sub_lf_rf_set(int unit, phy_ctrl_t *pc); 649 STATIC int _phy8485x_sub_lf_rf_clear(int unit, phy_ctrl_t *pc); 650 STATIC int _phy8485x_snr_get(int unit, phy_ctrl_t *pc); 651 STATIC int _phy8485x_current_temp_get(int unit, phy_ctrl_t *pc); 652 STATIC int _phy8485x_upper_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp); 653 STATIC int _phy8485x_upper_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp); 654 STATIC int _phy8485x_lower_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp); 655 STATIC int _phy8485x_lower_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp); 656 STATIC int _phy8486x_xfi_2p5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g); 657 STATIC int _phy84888_xfi_2p5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g, uint16 *mode_5g); 658 STATIC int _phy_848xx_led_type_get (int unit, soc_port_t port, uint32 *led_type, uint32 *led_mode); 659 STATIC int _phy_848xx_led_type_set (int unit, soc_port_t port, uint32 led_type, uint32 led_mode); 660 STATIC int _phy_848xx_pause_frame_mode_get (int unit, soc_port_t port, uint32 *enable); 661 STATIC int _phy_848xx_pause_frame_mode_set (int unit, soc_port_t port, uint32 enable); 662 #endif /* PHY8185X_DEBUG_CMD_HANDLER */ 663 STATIC int _phy_848xx_mgbase_802_3bz_type_get (int unit, phy_ctrl_t *pc, uint16 *frame_type, uint16 *frame_mode); 664 STATIC int _phy_848xx_mgbase_802_3bz_type_set (int unit, phy_ctrl_t *pc, uint16 frame_type, uint16 frame_mode); 665 666 STATIC int _phy848xx_xfi_2p5g_5g_mode_set(int unit, phy_ctrl_t *pc, uint16 mode_2p5g); 667 STATIC int _phy_8485x_force_cl72_config(int unit, phy_ctrl_t *pc, uint16 enable); 668 STATIC int _phy_8485x_force_cl72_status(int unit, phy_ctrl_t *pc, uint16 *value); 669 STATIC int _phy84834_jumbo_packet_set(int unit, phy_ctrl_t *pc, uint16 mode); 670 #if 0 671 STATIC int _phy84834_jumbo_packet_get(int unit, phy_ctrl_t *pc, uint16 *mode); 672 #endif 673 674 #ifdef BCM_WARM_BOOT_SUPPORT 675 STATIC int _phy84834_top_level_cmd_get_dispatch_v2(int unit,phy_ctrl_t *pc, uint16 cmd); 676 STATIC int _phy84834_top_level_cmd_get_retrive_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size); 677 STATIC int _phy_8481_reinit(int unit, soc_port_t port); 678 #endif 679 680 #if 1 681 682 #define PHY84834_TOP_LEVEL_CMD_SET _phy84834_top_level_cmd_set_v2 683 #define PHY84834_TOP_LEVEL_CMD_GET _phy84834_top_level_cmd_get_v2 684 #define PHY84834_DIAG_CMD_SET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_SET_EEE_MODE_V2 685 #define PHY84834_DIAG_CMD_GET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_GET_EEE_MODE_V2 686 #define PHY84834_DIAG_CMD_SET_PAIR_SWAP_GENERIC PHY84834_DIAG_CMD_SET_PAIR_SWAP_V2 687 #define PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_SET_1588_ENABLE_V2 688 #define PHY84834_DIAG_CMD_GET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_GET_1588_ENABLE_V2 689 #define PHY84834_DIAG_CMD_SET_XFI_M_REG_VALUES_GENERIC PHY84834_DIAG_CMD_SET_XFI_M_REG_VALUES_V2 690 #define PHY84834_DIAG_CMD_GET_XFI_M_REG_VALUES_GENERIC PHY84834_DIAG_CMD_GET_XFI_M_REG_VALUES_V2 691 #define PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS_GENERIC PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS 692 #define PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS 693 #define PHY84834_DIAG_CMD_SET_SHORT_REACH_ENABLE_GENERIC PHY84834_DIAG_CMD_SET_SHORT_REACH_ENABLE_V2 694 #define PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_GENERIC PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_V2 695 #define PHY84834_DIAG_CMD_GET_SUB_LF_RF_STATUS_GENERIC PHY84834_DIAG_CMD_GET_SUB_LF_RF_STATUS_V2 696 #define PHY84834_DIAG_CMD_CLEAR_SUB_LF_RF_GENERIC PHY84834_DIAG_CMD_CLEAR_SUB_LF_RF_V2 697 #define PHY84834_DIAG_CMD_SET_SUB_LF_RF_GENERIC PHY84834_DIAG_CMD_SET_SUB_LF_RF_V2 698 #define PHY84834_DIAG_CMD_GET_SNR_GENERIC PHY84834_DIAG_CMD_GET_SNR_V2 699 #define PHY84834_DIAG_CMD_GET_CURRENT_TEMP_GENERIC PHY84834_DIAG_CMD_GET_CURRENT_TEMP_V2 700 #define PHY84834_DIAG_CMD_SET_XFI_L_REG_VALUES_GENERIC PHY84834_DIAG_CMD_SET_XFI_L_REG_VALUES_V2 701 #define PHY84834_DIAG_CMD_GET_XFI_L_REG_VALUES_GENERIC PHY84834_DIAG_CMD_GET_XFI_L_REG_VALUES_V2 702 #define PHY8485X_DIAG_CMD_WRITE_SHADOW_REG PHY8485X_DIAG_CMD_WRITE_SHADOW_REG_V2 703 #define PHY8485X_DIAG_CMD_READ_SHADOW_REG PHY8485X_DIAG_CMD_READ_SHADOW_REG_V2 704 #define PHY8486x_DIAG_CMD_GET_XFI_2P5G_MODE PHY84834_DIAG_CMD_GET_XFI_2P5G_MODE_V2 705 #define PHY8486x_DIAG_CMD_SET_XFI_2P5G_MODE PHY84834_DIAG_CMD_SET_XFI_2P5G_MODE_V2 706 #define PHY848x_DIAG_CMD_SET_JUMBO_FRAME_MODE PHY848X_DIAG_CMD_WRITE_JUMBO_FRAME_REG_V2 707 #define PHY848x_DIAG_CMD_GET_JUMBO_FRAME_MODE PHY848X_DIAG_CMD_READ_JUMBO_FRAME_REG_V2 708 #define PHY84888_DIAG_CMD_SET_USXGMII_MODE PHY84834_DIAG_CMD_SET_USXGMII 709 #define PHY84888_DIAG_CMD_GET_USXGMII_MODE PHY84834_DIAG_CMD_GET_USXGMII 710 #define PHY84888_DIAG_CMD_SET_PAUSE_FRAME_MODE PHY84834_DIAG_CMD_SET_PAUSE_FRAME_MODE 711 #define PHY84888_DIAG_CMD_GET_PAUSE_FRAME_MODE PHY84834_DIAG_CMD_GET_PAUSE_FRAME_MODE 712 #define PHY84888_DIAG_CMD_SET_LED_TYPE PHY84834_DIAG_CMD_SET_LED_TYPE 713 #define PHY84888_DIAG_CMD_GET_LED_TYPE PHY84834_DIAG_CMD_GET_LED_TYPE 714 #define PHY84888_DIAG_CMD_SET_MGBASET_802_3BZ_TYPE PHY84834_DIAG_CMD_SET_MGBASET_802_3BZ_TYPE 715 #define PHY84888_DIAG_CMD_GET_MGBASET_802_3BZ_TYPE PHY84834_DIAG_CMD_GET_MGBASET_802_3BZ_TYPE 716 717 #else 718 719 #define PHY84834_TOP_LEVEL_CMD_SET _phy84834_top_level_cmd_set 720 #define PHY84834_TOP_LEVEL_CMD_GET _phy84834_top_level_cmd_get 721 #define PHY84834_DIAG_CMD_SET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_SET_EEE_MODE 722 #define PHY84834_DIAG_CMD_GET_EEE_MODE_GENERIC PHY84834_DIAG_CMD_GET_EEE_MODE 723 #define PHY84834_DIAG_CMD_SET_PAIR_SWAP_GENERIC PHY84834_DIAG_CMD_PAIR_SWAP_CHANGE 724 #define PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_SET_1588_ENABLE 725 #define PHY84834_DIAG_CMD_GET_1588_ENABLE_GENERIC PHY84834_DIAG_CMD_GET_1588_ENABLE 726 727 #endif 728 729 static char *dev_name_8481 = "BCM8481"; 730 static char *dev_name_84823 = "BCM84823"; 731 static char *dev_name_84834 = "BCM84834"; 732 static char *dev_name_84844 = "BCM84844"; 733 static char *dev_name_84858 = "BCM84858"; 734 static char *dev_name_8486x = "BCM8486x"; 735 static char *dev_name_84888 = "BCM84888"; 736 737 /* Function: 738 * phy_8481_init 739 * Purpose: 740 * Initialize 8481 phys 741 * Parameters: 742 * unit - StrataSwitch unit #. 743 * port - StrataSwitch port #. 744 * Returns: 745 * SOC_E_NONE 746 */ 747 STATIC int 748 phy_8481_init(int unit, soc_port_t port) 749 { 750 soc_timeout_t to; 751 phy_ctrl_t *pc; 752 uint16 fw_ver, data16 = 0; 753 soc_port_ability_t ability; 754 int rv, is_line = 0; 755 int medium; 756 uint32 phy_mdi_pair_map; 757 uint32 phy_long_xfi, sys_side = 0, priority = 0; 758 uint8 *fw = NULL; 759 int fw_len = 0; 760 uint16 cl72_value=0xff; 761 uint16 pair_swap_value; 762 763 pc = EXT_PHY_SW_STATE(unit, port); 764 765 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) || 766 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 767 768 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45); 769 FLAGS(pc) = 0; /* device specific private flags */ 770 LINK_DOWN(pc) = TRUE; 771 772 PHY_EXT_ROM_BOOT(pc) = soc_property_port_get(unit, port, 773 spn_PHY_EXT_ROM_BOOT, 1); 774 DL_DIVIDEND(pc) = soc_property_port_get(unit, port, 775 spn_RATE_EXT_DOWNLOAD_MDIO_DIVIDEND, 1); 776 DL_DIVISOR(pc) = soc_property_port_get(unit, port, 777 spn_RATE_EXT_DOWNLOAD_MDIO_DIVISOR, 0); 778 779 SYS_FORCED_CL72(pc) = soc_property_port_get(unit, port, spn_PORT_INIT_CL72, 0); 780 781 sys_side = soc_property_port_get(unit, port, spn_PHY_SERDES, 0); 782 /* Set Repeater flag according to config for Orca/Mako *\ 783 \* (PHY_SERDES == 2500 or 5000) means system side is 2500X or 5000X */ 784 if ( PHY_IS_BCM8486X_AND_UP(pc) && 785 (sys_side != 2500) && (sys_side != 5000) ) { 786 /* As setting 5G/2.5G line side speed ( @ 5G/2.5G over XFI mode), *\ 787 |* phy_8481_link_up() will notify internal SerDes with 10G speed. *| 788 \* set REPEATER flag to tell MAC driver don't notify speed again! */ 789 PHY_FLAGS_SET(unit, port, PHY_FLAGS_REPEATER); 790 } else { 791 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_REPEATER); 792 } 793 794 #ifdef BCM_WARM_BOOT_SUPPORT 795 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 796 rv = _phy_8481_reinit(unit, port); 797 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) && PHY_IS_BCM8483X_AND_UP(pc)) { 798 SOC_IF_ERROR_RETURN 799 (_phy84834_top_level_cmd_get_dispatch_v2(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EEE_MODE_V2)); 800 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 801 } else { 802 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_DEFAULT); 803 } 804 return rv; 805 } 806 #endif 807 808 #if 0 809 /* reset the GPHY core */ 810 SOC_IF_ERROR_RETURN 811 (MODIFY_PHY8481_MII_CTRLr(unit, pc, 812 MII_CTRL_RESET, MII_CTRL_RESET)); 813 /* Wait for device to come out of reset */ 814 soc_timeout_init(&to, 2000000, 0); 815 do { 816 rv = READ_PHY8481_MII_CTRLr(unit, pc, &data16); 817 if (((data16 & MII_CTRL_RESET) == 0) || 818 SOC_FAILURE(rv)) { 819 break; 820 } 821 } while (!soc_timeout_check(&to)); 822 if ((data16 & MII_CTRL_RESET) != 0) { 823 LOG_WARN(BSL_LS_SOC_PHY, 824 (BSL_META_U(unit, 825 "PHY8481 GPHY core reset failed: u=%d p=%d\n"), 826 unit, port)); 827 } 828 #endif 829 830 SOC_IF_ERROR_RETURN 831 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16)); 832 /* Compare config property with Config13 Strap pin (30.0x401a[13]) */ 833 if ( PHY_EXT_ROM_BOOT(pc) != ((data16 & (1U << 13)) >> 13) ) { 834 LOG_WARN( BSL_LS_SOC_PHY, (BSL_META_U(unit, 835 "Cannot load firmware from MDIO/SPIROM: " 836 "Config13 strap mismatch with the config property " 837 "phy_ext_rom_boot (unit=%d port=%d\n"), unit, port) ); 838 } 839 840 if ( soc_property_port_get(unit, port, spn_PHY_FORCE_FIRMWARE_LOAD, TRUE) ) { 841 fw_ver = 0; 842 } else { 843 /* Read the f/w version register, *\ 844 \* if != 0, that means f/w is running and no need to load */ 845 SOC_IF_ERROR_RETURN 846 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400f, &fw_ver)); 847 848 /* Disable loopback */ 849 /* PCS Control 1 Reg. DEVAD=3 Addr=0, bit[14] PCS loopback mode */ 850 SOC_IF_ERROR_RETURN 851 (MODIFY_PHY8481_PCS_CTRLr(unit, pc, 852 0, PCS_IEEE_CTL1_LPBK)); 853 /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFE0 bit[14] */ 854 SOC_IF_ERROR_RETURN 855 (MODIFY_PHY8481_MII_CTRLr(unit, pc, 0, MII_CTRL_LE)); 856 857 } 858 859 if ( (! fw_ver) && (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) 860 && (PHY_EXT_ROM_BOOT(pc)) ) { 861 LOG_INFO(BSL_LS_SOC_PHY, 862 (BSL_META_U(unit, 863 "PHY8481: SPI-ROM Attempting firmware download : u=%d p=%d\n"), 864 unit, port)); 865 /* Reset the device PMA/PMD and PCS */ 866 SOC_IF_ERROR_RETURN 867 (MODIFY_PHY8481_PMAD_CTRLr(unit, pc, MII_CTRL_RESET, 868 MII_CTRL_RESET) ); 869 /* Wait for device to come out of reset */ 870 soc_timeout_init(&to, 2000000, 0); 871 if ( PHY_IS_BCM8484X_A0(pc) ) { 872 sal_usleep(300000); 873 } 874 875 do { 876 rv = READ_PHY8481_PMAD_CTRLr(unit, pc, &data16); 877 if ( ((data16 & MII_CTRL_RESET) == 0) || SOC_FAILURE(rv) ) { 878 break; 879 } 880 } while ( ! soc_timeout_check(&to) ); 881 if ( ( data16 & MII_CTRL_RESET) != 0 ) { 882 LOG_WARN(BSL_LS_SOC_PHY, 883 (BSL_META_U(unit, "PHY8481 reset failed: u=%d p=%d\n"), 884 unit, port)); 885 /* failed to load FW from SPIROM, try MDIO FW load */ 886 PHY_EXT_ROM_BOOT(pc) = 0; 887 } 888 } 889 890 if ( (! fw_ver) && (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) 891 && (! PHY_EXT_ROM_BOOT(pc))) { 892 /* Attempting f/w download */ 893 LOG_INFO(BSL_LS_SOC_PHY, 894 (BSL_META_U(unit, 895 "PHY8481: Attempting firmware download : u=%d p=%d\n"), 896 unit, port)); 897 switch ( PHY_OUI_MODEL( PHY_OUI(pc->phy_id0, pc->phy_id1), 898 PHY_MODEL(pc->phy_id0, pc->phy_id1)) ) { 899 900 case PHY_OUI_MODEL(PHY_BCM8481X_OUI, PHY_BCM8481X_MODEL) : 901 if ((PHY_REV(pc->phy_id0, pc->phy_id1) >= 0x2)) { 902 /* C0 and beyond only */ 903 FIRMWARE(pc) = bcm_8481_firmware; 904 FIRMWARE_LEN(pc) = bcm_8481_firmware_size; 905 pc->dev_name = dev_name_8481; 906 } 907 break; 908 909 case PHY_OUI_MODEL(PHY_BCM84822_OUI, PHY_BCM84822_MODEL) : 910 case PHY_OUI_MODEL(PHY_BCM84823_OUI, PHY_BCM84823_MODEL) : 911 if (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x0) { 912 FIRMWARE(pc) = bcm_8482A0_firmware; 913 FIRMWARE_LEN(pc) = bcm_8482A0_firmware_size; 914 } 915 if (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x1) { 916 FIRMWARE(pc) = bcm_8482B0_firmware; 917 FIRMWARE_LEN(pc) = bcm_8482B0_firmware_size; 918 } 919 if (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x2) { 920 FIRMWARE(pc) = bcm_8482B1_firmware; 921 FIRMWARE_LEN(pc) = bcm_8482B1_firmware_size; 922 } 923 pc->flags |= PHYCTRL_MDIO_BCST; 924 pc->dev_name = dev_name_84823; 925 break; 926 927 case PHY_OUI_MODEL(PHY_BCM84833_OUI, PHY_BCM84833_MODEL) : 928 case PHY_OUI_MODEL(PHY_BCM84834_OUI, PHY_BCM84834_MODEL) : 929 case PHY_OUI_MODEL(PHY_BCM84835_OUI, PHY_BCM84835_MODEL) : 930 case PHY_OUI_MODEL(PHY_BCM84836_OUI, PHY_BCM84836_MODEL) : 931 FIRMWARE(pc) = bcm_84833_firmware; 932 FIRMWARE_LEN(pc) = bcm_84833_firmware_size; 933 pc->flags |= PHYCTRL_MDIO_BCST; 934 pc->dev_name = dev_name_84834; 935 break; 936 937 case PHY_OUI_MODEL(PHY_BCM84844_OUI, PHY_BCM84844_MODEL) : 938 case PHY_OUI_MODEL(PHY_BCM84846_OUI, PHY_BCM84846_MODEL) : 939 case PHY_OUI_MODEL(PHY_BCM84848_OUI, PHY_BCM84848_MODEL) : 940 FIRMWARE(pc) = bcm_84844_firmware; 941 FIRMWARE_LEN(pc) = bcm_84844_firmware_size; 942 pc->flags |= PHYCTRL_MDIO_BCST; 943 pc->dev_name = dev_name_84844; 944 break; 945 946 case PHY_OUI_MODEL(PHY_BCM84858_OUI, PHY_BCM84858_MODEL) : 947 case PHY_OUI_MODEL(PHY_BCM84856_OUI, PHY_BCM84856_MODEL) : 948 FIRMWARE(pc) = bcm_84858_firmware; 949 FIRMWARE_LEN(pc) = bcm_84858_firmware_size; 950 pc->flags |= PHYCTRL_MDIO_BCST; 951 pc->dev_name = dev_name_84858; 952 break; 953 954 case PHY_OUI_MODEL(PHY_BCM84860_OUI, PHY_BCM84860_MODEL) | 955 PHY_OUI_MODEL(PHY_BCM84861_OUI, PHY_BCM84861_MODEL) : 956 case PHY_OUI_MODEL(PHY_BCM84864_OUI, PHY_BCM84864_MODEL) | 957 PHY_OUI_MODEL(PHY_BCM84868_OUI, PHY_BCM84868_MODEL) : 958 FIRMWARE(pc) = bcm_8486x_firmware; 959 FIRMWARE_LEN(pc) = bcm_8486x_firmware_size; 960 pc->flags |= PHYCTRL_MDIO_BCST; 961 pc->dev_name = dev_name_8486x; 962 break; 963 964 case PHY_OUI_MODEL(PHY_BCM84888_OUI, PHY_BCM84888_MODEL) | 965 PHY_OUI_MODEL(PHY_BCM84887_OUI, PHY_BCM84887_MODEL) | 966 PHY_OUI_MODEL(PHY_BCM84884_OUI, PHY_BCM84884_MODEL) : 967 case PHY_OUI_MODEL(PHY_BCM84888E_OUI, PHY_BCM84888E_MODEL) | 968 PHY_OUI_MODEL(PHY_BCM84884E_OUI, PHY_BCM84884E_MODEL) : 969 case PHY_OUI_MODEL(PHY_BCM84881_OUI, PHY_BCM84881_MODEL) | 970 PHY_OUI_MODEL(PHY_BCM84880_OUI, PHY_BCM84880_MODEL) : 971 case PHY_OUI_MODEL(PHY_BCM84885_OUI, PHY_BCM84885_MODEL) | 972 PHY_OUI_MODEL(PHY_BCM84888S_OUI, PHY_BCM84888S_MODEL) | 973 PHY_OUI_MODEL(PHY_BCM84886_OUI, PHY_BCM84886_MODEL) : 974 if ( (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x0) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x4) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x8) ) { 975 FIRMWARE(pc) = bcm_84888A0_firmware; 976 FIRMWARE_LEN(pc) = bcm_84888A0_firmware_size; 977 } 978 if ( (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x1) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x5) || (PHY_REV(pc->phy_id0, pc->phy_id1) == 0x9) ) { 979 FIRMWARE(pc) = bcm_84888B0_firmware; 980 FIRMWARE_LEN(pc) = bcm_84888B0_firmware_size; 981 } 982 pc->flags |= PHYCTRL_MDIO_BCST; 983 pc->dev_name = dev_name_84888; 984 break; 985 986 default: 987 FIRMWARE(pc) = NULL; 988 FIRMWARE_LEN(pc) = 0; 989 break; 990 } 991 992 /* Now check whether a newer version of firmware is available for this model */ 993 rv = soc_phy_fw_get(pc->dev_name, &fw, &fw_len); 994 if (SOC_SUCCESS(rv)) { 995 FIRMWARE(pc) = fw; 996 FIRMWARE_LEN(pc) = fw_len; 997 } 998 999 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_CHAINED)) { 1000 /* No broadcast mode download in chained PHY. */ 1001 pc->flags &= ~PHYCTRL_MDIO_BCST; 1002 } 1003 1004 if ( FIRMWARE(pc) ) { 1005 if (pc->flags & PHYCTRL_MDIO_BCST) { 1006 /* indicate second pass of init is needed */ 1007 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 1008 return SOC_E_NONE; 1009 } 1010 1011 SOC_IF_ERROR_RETURN 1012 (_phy_8481_halt(unit, pc)); 1013 SOC_IF_ERROR_RETURN 1014 (_phy_8481_write_to_arm(unit, pc, 0, FIRMWARE(pc), FIRMWARE_LEN(pc))); 1015 1016 /* write_addr=0xc300_0000, data=0x0000_002c, enable bottom write protection 1017 and set VINITHI signal to 0 (reset vector at 0x0000_0000) */ 1018 1019 SOC_IF_ERROR_RETURN 1020 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 0x0000)); 1021 SOC_IF_ERROR_RETURN 1022 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000)); 1023 SOC_IF_ERROR_RETURN 1024 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300)); 1025 if (PHY_IS_BCM8485X_AND_UP(pc)) { 1026 SOC_IF_ERROR_RETURN 1027 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x0000)); 1028 } else { 1029 SOC_IF_ERROR_RETURN 1030 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x002c)); 1031 } 1032 SOC_IF_ERROR_RETURN 1033 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000)); 1034 SOC_IF_ERROR_RETURN 1035 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 1036 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT))); 1037 1038 /* Reset the processor to start execution of the code in the on-chip memory */ 1039 if ( PHY_IS_BCM8486X_AND_UP(pc) ) { 1040 SOC_IF_ERROR_RETURN 1041 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x8004,0x5555)); 1042 if ( PHY_IS_BCM8488X(pc) ) { 1043 /* Set 1e.0x0009[0] */ 1044 SOC_IF_ERROR_RETURN 1045 (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x0009, 1, PHY8488X_SOFT_RESET_MASK)); 1046 sal_usleep(200); 1047 } 1048 SOC_IF_ERROR_RETURN 1049 (WRITE_PHY8481_PMAD_REG(unit, pc, 0x0000 , 0x8000)); 1050 } else 1051 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 1052 SOC_IF_ERROR_RETURN 1053 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x0004)); 1054 SOC_IF_ERROR_RETURN 1055 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x0000)); 1056 } 1057 1058 /* check the strap pin Config13 */ 1059 SOC_IF_ERROR_RETURN 1060 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16)); 1061 if (data16 & (1U << 13)) { 1062 /* Now reset only the ARM core */ 1063 SOC_IF_ERROR_RETURN 1064 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040)); 1065 SOC_IF_ERROR_RETURN 1066 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000)); 1067 } else { 1068 SOC_IF_ERROR_RETURN 1069 (MODIFY_PHY8481_PMAD_CTRLr(unit, pc, 1070 MII_CTRL_RESET, MII_CTRL_RESET)); 1071 } 1072 1073 if (PHY_IS_BCM8484X_A0(pc)) { 1074 sal_usleep(300000); 1075 } 1076 soc_timeout_init(&TO(pc), 2000000, 0); 1077 1078 } else { 1079 LOG_WARN(BSL_LS_SOC_PHY, 1080 (BSL_META_U(unit, 1081 "PHY8481: firmware download not possible with this model: u=%d p=%d\n"), 1082 unit, port)); 1083 } 1084 } 1085 1086 /* Need to disable port here for 8484X firmware workaround */ 1087 /* Workaround (SDK-45594 Part 1 of 2) */ 1088 if (PHY_IS_BCM8484X(pc)) { 1089 SOC_IF_ERROR_RETURN 1090 (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, 1091 (1U << 7), 1U << 7)); 1092 } 1093 1094 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) { 1095 /* indicate second pass of init is needed */ 1096 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 1097 return SOC_E_NONE; 1098 } 1099 } 1100 1101 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 1102 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1103 1104 #ifdef BCM_WARM_BOOT_SUPPORT 1105 uint16 args[5]; 1106 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 1107 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) && PHY_IS_BCM8483X_AND_UP(pc)) { 1108 SOC_IF_ERROR_RETURN 1109 (_phy84834_top_level_cmd_get_retrive_v2(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EEE_MODE_V2, args, 4)); 1110 if (!args[0]) { 1111 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 1112 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE); 1113 LOG_INFO(BSL_LS_SOC_PHY, 1114 (BSL_META_U(unit, 1115 "u=%d p=%d recovered EEE None\n"), unit, port)); 1116 } else if (args[0] == 1) { 1117 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 1118 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE); 1119 LOG_INFO(BSL_LS_SOC_PHY, 1120 (BSL_META_U(unit, 1121 "u=%d p=%d recovered EEE Native\n"), unit, port)); 1122 } else if (args[0] == 2) { 1123 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 1124 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_MODE); 1125 LOG_INFO(BSL_LS_SOC_PHY, 1126 (BSL_META_U(unit, 1127 "u=%d p=%d recovered EEE AutogrEEEn\n"), unit, port)); 1128 } 1129 } 1130 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_DEFAULT); 1131 1132 PHY8481_SET_FIBER_PREFERRED(unit, port, pc); 1133 PHY8481_ENABLE_MEDIUM(pc); 1134 return SOC_E_NONE; 1135 } 1136 #endif 1137 1138 do { 1139 rv = READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400f, &fw_ver); 1140 if ( SOC_FAILURE(rv) ) { 1141 data16 = MII_CTRL_RESET; 1142 break; 1143 } 1144 rv = READ_PHY8481_PMAD_CTRLr(unit, pc, &data16); 1145 if ( SOC_FAILURE(rv) ) { 1146 break; 1147 } 1148 if ( fw_ver && (!(data16 & MII_CTRL_RESET)) ) { 1149 /* version is set and the reset bit has cleared */ 1150 break; 1151 } 1152 } while ( !soc_timeout_check(&TO(pc)) ); 1153 if ( (data16 & MII_CTRL_RESET) || (! fw_ver) ) { 1154 LOG_WARN(BSL_LS_SOC_PHY, 1155 (BSL_META_U(unit, 1156 "PHY8481 : u=%d p=%d : Firmware might not be running\n"), 1157 unit, port)); 1158 } 1159 1160 SOC_IF_ERROR_RETURN 1161 (_phy_8481_check_firmware(unit, pc)); 1162 1163 PHY8481_SET_FIBER_PREFERRED(unit, port, pc); 1164 /* software controlled medium selection is not available yet */ 1165 PHY8481_ENABLE_MEDIUM(pc); 1166 pc->power_mode = SOC_PHY_CONTROL_POWER_FULL; 1167 1168 /* Need to disable port here for 8484X firmware workaround */ 1169 /* Workaround (SDK-45594 Part 2 of 2) */ 1170 if (PHY_IS_BCM8484X(pc)) { 1171 SOC_IF_ERROR_RETURN( 1172 phy_8481_enable_set(unit,port, FALSE)); 1173 } 1174 1175 soc_timeout_init(&TO(pc), 700000, 0); 1176 1177 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) { 1178 /* indicate second pass of init is needed */ 1179 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3); 1180 return SOC_E_NONE; 1181 } 1182 } 1183 1184 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) || 1185 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1186 1187 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS4); 1188 1189 while (!soc_timeout_check(&TO(pc))) { 1190 if (PHY_HS_CAPABLE(unit, port)) { 1191 rv = READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400e, &data16); 1192 if (((data16 & 0x2) == 0) || SOC_FAILURE(rv)) { 1193 break; 1194 } 1195 } else { 1196 sal_usleep(100); 1197 } 1198 } 1199 1200 if ( PHY_IS_BCM8486X_AND_UP(pc) ) { /* Mako and Orca supports 5G/2.5G speed */ 1201 1202 if ( PHY_IS_BCM8488X(pc) ) { 1203 /* Default priority IEEE 802.3bz 5GBase-T & 2.5GBase-T */ 1204 priority = soc_property_port_get(unit, port, 1205 spn_PHY_MGBASET_802P3BZ_PRIORITY, 1); 1206 _phy_848xx_mgbase_802_3bz_type_set(unit, pc, 1207 (priority) ? 1 : 0, (priority) ? 1 : 0); 1208 } 1209 sys_side = soc_property_port_get(unit, port, spn_PHY_SERDES, 0); 1210 if ( (sys_side == 2500 && PHY_IS_BCM8486X(pc)) || 1211 (PHY_IS_BCM8488X(pc) && (sys_side == 2500 || sys_side == 5000)) ) { 1212 /* MAC interface defaults to 2500BASE-X mode */ 1213 data16 = PHY84834_DIAG_CMD_XFI_2P5G_MODE_2500X; 1214 } else { 1215 /* MAC interface is 5G/2.5G over XFI mode */ 1216 data16 = PHY84834_DIAG_CMD_XFI_2P5G_MODE_XFI; 1217 } 1218 /* command handler code SET_XFI_2P5G_MODE (0x8017) */ 1219 SOC_IF_ERROR_RETURN( 1220 _phy848xx_xfi_2p5g_5g_mode_set(unit, pc, data16) ); 1221 } 1222 1223 if (!PHY_FORCED_COPPER_MODE(unit, port)) { 1224 SOC_IF_ERROR_RETURN 1225 (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, 1226 pc->fiber.preferred ? 1U<<8 : 0, 1U<<8)); 1227 } 1228 1229 phy_mdi_pair_map = soc_property_port_get(unit, port, 1230 spn_PHY_MDI_PAIR_MAP, 0); 1231 if ( phy_mdi_pair_map ) { 1232 /* convert 16'b_00wW_00xX_00yY_00zZ --> 16'b_0000_0000_wWxX_yYzZ */ 1233 pair_swap_value = ((phy_mdi_pair_map & (0x3<<12)) >> 6) | 1234 ((phy_mdi_pair_map & (0x3<<8 )) >> 4) | 1235 ((phy_mdi_pair_map & (0x3<<4 )) >> 2) | 1236 ((phy_mdi_pair_map & (0x3<<0 )) >> 0) ; 1237 1238 if ( PHY_IS_BCM8484X_AND_UP(pc) ) { 1239 SOC_IF_ERROR_RETURN 1240 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 1241 (uint16) PHY84834_DIAG_CMD_SET_PAIR_SWAP_GENERIC, 1242 &pair_swap_value, 1) ); 1243 } else { 1244 SOC_IF_ERROR_RETURN 1245 (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x4005, 0, (1U << 1))); 1246 sal_udelay(35000); 1247 1248 SOC_IF_ERROR_RETURN 1249 (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x4009, pair_swap_value, 0xff)); 1250 1251 SOC_IF_ERROR_RETURN 1252 (MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 0x4005, 1253 (1U << 6)|(1U << 4)|(1U << 1), 1254 (1U << 6)|(1U << 4)|(1U << 1))); 1255 sal_udelay(35000); 1256 } 1257 } 1258 1259 /* By default XFI cannot drive long distance cables. TX premphasis needs 1260 * to be adjusted if long cables are used on the XFI side 1261 */ 1262 phy_long_xfi = soc_property_port_get(unit, port, 1263 spn_PHY_LONG_XFI, 0); 1264 if (phy_long_xfi) { 1265 if (!(pc->flags & PHYCTRL_SYS_SIDE_CTRL)) { 1266 is_line = 1; 1267 pc->flags |= PHYCTRL_SYS_SIDE_CTRL; 1268 } 1269 1270 SOC_IF_ERROR_RETURN( 1271 _phy8481_adjust_xfi_tx_preemphasis(unit, port, pc, phy_long_xfi)); 1272 1273 if (is_line) { 1274 pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL; 1275 is_line = 0; 1276 } 1277 } 1278 1279 if (!PHY_FORCED_COPPER_MODE(unit, port)) { 1280 /* check if there is another PHY device connected to the XAUI port */ 1281 rv = _phy_8481_xaui_nxt_dev_probe(unit,port); 1282 if (SOC_SUCCESS(rv)) { 1283 PHYDRV_CALL_NOARG(pc,PHY_INIT); 1284 } 1285 } else { 1286 pc->fiber.preferred = FALSE; 1287 pc->copper.preferred = TRUE; 1288 } 1289 1290 /* Copper - Set Local Advertising Configuration */ 1291 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 1292 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 1293 1294 if (!PHY_FORCED_COPPER_MODE(unit, port)) { 1295 PHY8481_SELECT_REGS_CU(unit, pc); 1296 } 1297 SOC_IF_ERROR_RETURN 1298 (phy_8481_ability_local_get(unit, port, &ability)); 1299 SOC_IF_ERROR_RETURN 1300 (phy_8481_ability_advert_set(unit, port, &ability)); 1301 1302 /* Fiber - Set Local Advertising Configuration */ 1303 if (!PHY_FORCED_COPPER_MODE(unit, port)) { 1304 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 1305 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 1306 PHY8481_SELECT_REGS_XAUI(unit, pc); 1307 SOC_IF_ERROR_RETURN 1308 (phy_8481_ability_local_get(unit, port, &ability)); 1309 SOC_IF_ERROR_RETURN 1310 (phy_8481_ability_advert_set(unit, port, &ability)); 1311 } 1312 1313 1314 /* The following should be done only after the chained PHY is probed as 1315 the PHY flags should be determined by the base PHY. 1316 */ 1317 SOC_IF_ERROR_RETURN 1318 (_phy_8481_medium_check(unit, port, &medium)); 1319 1320 1321 if (medium == SOC_PORT_MEDIUM_COPPER) { 1322 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 1323 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 1324 PHY8481_SELECT_REGS_CU(unit, pc); 1325 } else { /* Fiber */ 1326 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 1327 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 1328 PHY8481_SELECT_REGS_XAUI(unit, pc); 1329 } 1330 1331 /* 1332 * Configure Auxiliary 1000BASE-X control register to turn off 1333 * carrier extension. The Intel 7131 NIC does not accept carrier 1334 * extension and gets CRC errors. 1335 */ 1336 /* Disable carrier extension */ 1337 SOC_IF_ERROR_RETURN 1338 (MODIFY_PHY8481_AUX_1000X_CTRLr(unit, pc, 0x0040, 0x0040)); 1339 1340 if (PHY_IS_BCM8485X_AND_UP(pc) || PHY_IS_BCM8484X(pc)) { 1341 /* Enable Jumbo Packet */ 1342 SOC_IF_ERROR_RETURN( 1343 _phy84834_jumbo_packet_set(unit, pc, 1)); 1344 } else { 1345 /* Enable 18K jumbo frame support in 8482x and 8483x */ 1346 SOC_IF_ERROR_RETURN 1347 (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, (1U << 14), (1U << 14))); 1348 SOC_IF_ERROR_RETURN 1349 (MODIFY_PHY8481_PHY_ECRr(unit, pc, (1U << 0), (1U << 0))); 1350 SOC_IF_ERROR_RETURN 1351 (MODIFY_PHY8481_EXP_PATTERN_GENr(unit, pc, (1U << 14), (1U << 14))); 1352 SOC_IF_ERROR_RETURN 1353 (MODIFY_PHY8481_MISC_1000X_CTRL2r(unit, pc, (1U << 0), (1U << 0))); 1354 SOC_IF_ERROR_RETURN 1355 (MODIFY_PHY8481_AUX_1000X_CTRLr(unit, pc, (1U << 1), (1U << 1))); 1356 } 1357 1358 if (PHY_IS_BCM8484X(pc) && IS_HG_PORT(unit, port)) { 1359 SOC_IF_ERROR_RETURN( 1360 WRITE_PHY8481_PMAD_REG(unit, pc, 0xa939, 0x0183)); 1361 } 1362 1363 PHY_FW_HANDSHAKE(unit, port); 1364 1365 /* config property PHY_OPERATIONAL_MODE == 0x80 or 0x8000 or 0x8080 *\ 1366 \* means to keep Super Isolate enabled */ 1367 if ( (soc_property_port_get(unit, port, spn_PHY_OPERATIONAL_MODE, 0) 1368 & TOP_CONFIG_XGPHY_DISABLE) == 0 ) { 1369 /* Remove Super Isolate and XGPH Disable by default */ 1370 SOC_IF_ERROR_RETURN( 1371 MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, 0x00, 1372 TOP_CONFIG_XGPHY_DISABLE) ); 1373 } 1374 PHY_FW_HANDSHAKE(unit, port); 1375 1376 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 1377 if (SYS_FORCED_CL72(pc)) { 1378 _phy_8485x_force_cl72_config(unit, pc, 1); 1379 (_phy_8485x_force_cl72_status(unit, pc, (uint16 *)&cl72_value)); 1380 } else { 1381 (_phy_8485x_force_cl72_status(unit, pc, (uint16 *)&cl72_value)); 1382 } 1383 } 1384 } 1385 1386 return SOC_E_NONE; 1387 } 1388 1389 1390 #ifdef BCM_WARM_BOOT_SUPPORT 1391 STATIC int 1392 _phy_8481_reinit(int unit,soc_port_t port) { 1393 phy_ctrl_t *pc; 1394 int fiber_preferred, medium; 1395 uint16 data16; 1396 1397 pc = EXT_PHY_SW_STATE(unit, port); 1398 1399 SOC_IF_ERROR_RETURN 1400 (_phy_8481_check_firmware(unit, pc)); 1401 1402 SOC_IF_ERROR_RETURN 1403 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16)); 1404 fiber_preferred = data16 & (1U << 8) ? 1 : 0; 1405 1406 pc->copper.preferred = !fiber_preferred; 1407 pc->fiber.preferred = fiber_preferred; 1408 1409 pc->automedium = TRUE; /* Always TRUE for this PHY */ 1410 1411 SOC_IF_ERROR_RETURN 1412 (_phy_8481_medium_check(unit, port, &medium)); 1413 1414 if (medium == SOC_PORT_MEDIUM_COPPER) { 1415 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 1416 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 1417 SOC_IF_ERROR_RETURN 1418 (_phy_8481_copper_speed_get(unit, port, &pc->copper.force_speed)); 1419 SOC_IF_ERROR_RETURN 1420 (_phy_8481_copper_duplex_get(unit, port, &pc->copper.force_duplex)); 1421 SOC_IF_ERROR_RETURN 1422 (_phy_8481_copper_ability_advert_get(unit, port, &pc->copper.advert_ability)); 1423 SOC_IF_ERROR_RETURN 1424 (_phy_8481_copper_an_get(unit, port, &pc->copper.autoneg_enable, NULL)); 1425 } else { /* Fiber */ 1426 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 1427 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 1428 1429 SOC_IF_ERROR_RETURN 1430 (_phy_8481_xaui_speed_get(unit, port, &pc->fiber.force_speed)); 1431 SOC_IF_ERROR_RETURN 1432 (_phy_8481_xaui_duplex_get(unit, port, &pc->fiber.force_duplex)); 1433 SOC_IF_ERROR_RETURN 1434 (_phy_8481_xaui_ability_advert_get(unit, port, &pc->fiber.advert_ability)); 1435 SOC_IF_ERROR_RETURN 1436 (_phy_8481_xaui_an_get(unit, port, &pc->fiber.autoneg_enable, NULL)); 1437 } 1438 1439 pc->power_mode = SOC_PHY_CONTROL_POWER_FULL; 1440 1441 return SOC_E_NONE; 1442 } 1443 #endif 1444 1445 STATIC int 1446 _phy_8481_clear_eee_stats(int unit,phy_ctrl_t *pc) { 1447 uint16 temp; 1448 1449 /* Clearing 10G EEE stats: Enable clear on Read */ 1450 SOC_IF_ERROR_RETURN 1451 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc, 0x0003, 0x000f)); 1452 SOC_IF_ERROR_RETURN 1453 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc, 0x000f, 0x000f)); 1454 SOC_IF_ERROR_RETURN 1455 (READ_PHY8481_EXP_EEE_TX_EVENTS_HIGHr(unit, pc, &temp)); 1456 SOC_IF_ERROR_RETURN 1457 (READ_PHY8481_EXP_EEE_TX_EVENTS_LOWr(unit, pc, &temp)); 1458 /* Clearing 10G EEE stats: Disable clear on Read */ 1459 SOC_IF_ERROR_RETURN 1460 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc, 0x0002, 0x000f)); 1461 1462 /* Clearning 1G EEE stats */ 1463 SOC_IF_ERROR_RETURN 1464 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8002, 0x8002)); 1465 SOC_IF_ERROR_RETURN 1466 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8000, 0x8002)); 1467 1468 return SOC_E_NONE; 1469 } 1470 1471 STATIC int 1472 _phy_8481_check_firmware(int unit,phy_ctrl_t *pc) { 1473 uint16 tmp16; 1474 uint8 fw_ver_chip_rev, fw_ver_main, fw_ver_branch, fw_ver_sub_branch, 1475 fw_date_month, fw_date_day, fw_date_year, spirom_crc_check_status; 1476 1477 SOC_IF_ERROR_RETURN 1478 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400f, &tmp16)); 1479 fw_ver_chip_rev = (tmp16 >> 12) & 0xf; 1480 fw_ver_main = (tmp16 >> 7) & 0x1f; 1481 fw_ver_branch = tmp16 & 0x7f; 1482 1483 if (PHY_IS_BCM8485X_AND_UP(pc)) { 1484 fw_ver_sub_branch = fw_ver_chip_rev; 1485 } 1486 else { 1487 SOC_IF_ERROR_RETURN 1488 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x4011,&tmp16)); 1489 fw_ver_sub_branch = (tmp16 >> 11) & 0x1f; 1490 } 1491 1492 SOC_IF_ERROR_RETURN 1493 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x4010,&tmp16)); 1494 1495 fw_date_month = (tmp16 >> 9) & 0xf; /* BIT[12:9] */ 1496 fw_date_day = (tmp16 >> 4) & 0x1f; /* BIT[9:4] */ 1497 fw_date_year = (tmp16 & 0xf) | ((tmp16 & BIT(13)) >> 9); /* [13,3:0] */ 1498 1499 LOG_CLI((BSL_META_U(unit, 1500 "BCM848xx: u=%d p=%d: init. Chip Rev = %02d " 1501 "Version = %02d.%02d.%02d Date = %02d/%02d/20%02d (%s)\n"), 1502 unit, pc->port, fw_ver_chip_rev, fw_ver_main, fw_ver_branch, fw_ver_sub_branch, 1503 fw_date_month, fw_date_day, fw_date_year, 1504 PHY_EXT_ROM_BOOT(pc) ? "SPI" : "MDIO")); 1505 1506 SOC_IF_ERROR_RETURN 1507 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x400d, &tmp16)); 1508 spirom_crc_check_status = (tmp16 >> 14) & 0x3; 1509 if(spirom_crc_check_status == 0x2) { 1510 LOG_INFO(BSL_LS_SOC_PHY, (BSL_META_U(unit, "SPIROM bad CRC \n"))); 1511 } 1512 1513 if (PHY_IS_BCM84823(pc) && ((fw_ver_main > 3) || ((fw_ver_main == 3) && (fw_ver_branch >= 2)))) { 1514 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE); 1515 } 1516 if (PHY_IS_BCM84823(pc) && ((fw_ver_main > 4) || ((fw_ver_main == 4) && (fw_ver_branch >= 18)))) { 1517 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE); 1518 SOC_IF_ERROR_RETURN 1519 (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0x0002, 0x0003)); 1520 /* Clearing the stats: Disable clear on Read */ 1521 SOC_IF_ERROR_RETURN 1522 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0000, 0x0001)); 1523 } 1524 if (PHY_IS_BCM8483X(pc) && ((fw_ver_main > 1) || ((fw_ver_main == 1) && (fw_ver_branch >= 15)))) { 1525 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE); 1526 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE); 1527 /* Clearing the stats: Disable clear on Read */ 1528 SOC_IF_ERROR_RETURN 1529 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0000, 0x0001)); 1530 } 1531 if (PHY_IS_BCM8484X(pc) && ((fw_ver_main > 0) || ((fw_ver_main == 0) && (fw_ver_branch >= 3)))) { 1532 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE); 1533 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE); 1534 1535 /* Set flag for FW versions >= 1.08.00 */ 1536 if ( ((fw_ver_main == 1) && (fw_ver_branch >= 8)) || (fw_ver_main > 1) ) { 1537 FLAGS(pc) |= PHY8483X_ATOMIC_ACCESS_SHD; 1538 } 1539 } 1540 if (PHY_IS_BCM8483X(pc) && ((fw_ver_main > 1) || ((fw_ver_main == 1) && (fw_ver_branch >= 40)))) { 1541 FLAGS(pc) |= PHY8483X_MFG_TEST_SUPPORT; 1542 FLAGS(pc) |= PHY8483X_STATE_TEST_SUPPORT; 1543 } 1544 if (PHY_IS_BCM8484X(pc) && ((fw_ver_main > 0) || ((fw_ver_main == 0) && (fw_ver_branch >= 3)))) { 1545 FLAGS(pc) |= PHY8483X_MFG_TEST_SUPPORT; 1546 FLAGS(pc) |= PHY8483X_STATE_TEST_SUPPORT; 1547 FLAGS(pc) |= PHY8483X_FULL_SNR_SUPPORT; 1548 } 1549 if (PHY_IS_BCM8483X(pc) && ((fw_ver_main > 1) || ((fw_ver_main == 1) && (fw_ver_branch >= 52)))) { 1550 FLAGS(pc) |= PHY8483X_FULL_SNR_SUPPORT; 1551 } 1552 if ( (PHY_IS_BCM8485X(pc) && ((fw_ver_main > 0) || ((fw_ver_main == 0) && (fw_ver_branch >= 3 )))) || 1553 (PHY_IS_BCM8486X_AND_UP(pc)) ) { 1554 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_HS_CAPABLE); 1555 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE); 1556 FLAGS(pc) |= PHY8483X_FULL_SNR_SUPPORT; 1557 FLAGS(pc) |= PHY8483X_STATE_TEST_SUPPORT; 1558 FLAGS(pc) |= PHY8483X_MFG_TEST_SUPPORT; 1559 1560 /* Set flag for FW versions >= 1.00.05 */ 1561 if ( ((fw_ver_main == 1) && (fw_ver_branch >= 1)) || 1562 (fw_ver_main > 1) || (PHY_IS_BCM8486X_AND_UP(pc)) ) { 1563 FLAGS(pc) |= PHY8483X_ATOMIC_ACCESS_SHD; 1564 } 1565 } 1566 1567 return SOC_E_NONE; 1568 } 1569 1570 1571 1572 STATIC int 1573 _phy_8481_copper_link_get(int unit, soc_port_t port, int *link) { 1574 1575 uint16 pcs_mii_stat, pcs_mii_stat2, pcs_mii_stat3; 1576 uint16 speed_val, ctrl; 1577 phy_ctrl_t *pc; 1578 int an,an_done,cur_speed; 1579 1580 pc = EXT_PHY_SW_STATE(unit, port); 1581 1582 PHY8481_SELECT_REGS_CU(unit, pc); 1583 1584 SOC_IF_ERROR_RETURN 1585 (READ_PHY8481_MII_STATr(unit, pc, &pc->mii_stat)); 1586 1587 SOC_IF_ERROR_RETURN 1588 (phy_8481_an_get(unit,port,&an,&an_done)); 1589 1590 /* return link false if in the middle of autoneg */ 1591 if (an == TRUE && an_done == FALSE) { 1592 *link = FALSE; 1593 return SOC_E_NONE; 1594 } 1595 1596 /* PCS link status , DEVAD=3 */ 1597 SOC_IF_ERROR_RETURN 1598 (READ_PHY8481_PCS_STATr(unit, pc, &pcs_mii_stat)); 1599 1600 if (pcs_mii_stat == 0xffff) { 1601 /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ 1602 *link = FALSE; 1603 return SOC_E_NONE; 1604 } 1605 1606 /* check if the current speed is set to 10G */ 1607 cur_speed = 0; 1608 if (an) { /* autoneg is enabled */ 1609 SOC_IF_ERROR_RETURN 1610 (READ_PHY8481_TENG_AN_CTRLr(unit, pc, &ctrl)); 1611 if ((ctrl & TENG_IEEE_AN_CTRL_10GBT)&&(pcs_mii_stat & MII_STAT_LA)) { 1612 cur_speed = 10000; 1613 } 1614 } else { /* forced mode */ 1615 SOC_IF_ERROR_RETURN 1616 (READ_PHY8481_PMAD_CTRLr(unit, pc, &speed_val)); 1617 if ((speed_val & (IEEE_CTRLr_SPEED_10G_MASK|PMAD_MII_CTRL_SS_MASK))==IEEE_CTRLr_SPEED_10G) { 1618 cur_speed = 10000; 1619 } 1620 } 1621 1622 if (cur_speed == 10000) { /* check all 3 device's link status if 10G */ 1623 if PHY_IS_BCM84823(pc) { 1624 SOC_IF_ERROR_RETURN 1625 (READ_PHY8481_PCS_REG(unit, pc, 0x20, &pcs_mii_stat2)); 1626 1627 SOC_IF_ERROR_RETURN 1628 (READ_PHY8481_PCS_REG(unit, pc, 0x21, &pcs_mii_stat3)); 1629 1630 *link = (pcs_mii_stat & MII_STAT_LA) && ((pcs_mii_stat2 & 0x1001) == 0x1001) && 1631 (pcs_mii_stat3 & 0x8000) ? TRUE : FALSE; 1632 } else { 1633 *link = pcs_mii_stat & MII_STAT_LA ? TRUE : FALSE; 1634 } 1635 } else { 1636 *link = (pc->mii_stat & MII_STAT_LA) ? TRUE : FALSE; 1637 } 1638 1639 return SOC_E_NONE; 1640 } 1641 1642 STATIC int 1643 _phy_8481_xaui_link_get(int unit, soc_port_t port, int *link) { 1644 1645 phy_ctrl_t *pc; 1646 uint16 status; 1647 int an_done; 1648 int an; 1649 int speed; 1650 int speed_local; 1651 1652 pc = EXT_PHY_SW_STATE(unit, port); 1653 1654 if ((!PHY_COPPER_MODE(unit, port)) && NXT_PC(pc)) { 1655 /* there is a PHY device connected to this XAUI port */ 1656 /* When it is in AN mode, its negotiated speed needs to be 1657 * propagated to this device. Sync up here since this function is periodically 1658 * called by a dedicated linkscan task. 1659 */ 1660 PHYDRV_CALL_ARG1(pc,PHY_LINK_GET,link); 1661 1662 if (*link == TRUE) { 1663 /* check if in an mode */ 1664 PHYDRV_CALL_ARG2(pc,PHY_AUTO_NEGOTIATE_GET,&an,&an_done); 1665 1666 if (an == TRUE && an_done == TRUE) { 1667 /* get the speed */ 1668 PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET,&speed); 1669 SOC_IF_ERROR_RETURN 1670 (_phy_8481_xaui_speed_get(unit, port, &speed_local)); 1671 1672 if (speed && (speed != speed_local)) { 1673 /* set this device's speed accordingly */ 1674 SOC_IF_ERROR_RETURN 1675 (_phy_8481_xaui_speed_set(unit,port,speed)); 1676 } 1677 } 1678 } 1679 return SOC_E_NONE; 1680 } 1681 1682 SOC_IF_ERROR_RETURN 1683 (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status)); 1684 1685 /* status != 0xffff check is to handle removable PHY daughter cards */ 1686 *link = ((status != 0xffff) && (status & TOP_CONFIG_LINK_STATUS_REG_FIBER_LINK)) ? TRUE : FALSE; 1687 1688 return (SOC_E_NONE); 1689 } 1690 1691 1692 static int 1693 _phy8481_auto_negotiate_gcd(int unit, soc_port_t port, int *speed, int *duplex) 1694 { 1695 int t_speed, t_duplex; 1696 uint16 mii_ana, mii_anp; 1697 uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; 1698 phy_ctrl_t *pc; 1699 1700 t_speed = 0; 1701 t_duplex = 0; 1702 mii_gb_stat = 0; /* Start off 0 */ 1703 mii_gb_ctrl = 0; /* Start off 0 */ 1704 1705 pc = EXT_PHY_SW_STATE(unit, port); 1706 SOC_IF_ERROR_RETURN 1707 (READ_PHY8481_MII_ANAr(unit, pc, &mii_ana)); 1708 SOC_IF_ERROR_RETURN 1709 (READ_PHY8481_MII_ANPr(unit, pc, &mii_anp)); 1710 1711 if (pc->mii_stat & MII_STAT_ES) { /* Supports extended status */ 1712 /* 1713 * If the PHY supports extended status, check if it is 1000MB 1714 * capable. If it is, check the 1000Base status register to see 1715 * if 1000MB negotiated. 1716 */ 1717 SOC_IF_ERROR_RETURN 1718 (READ_PHY8481_MII_ESRr(unit, pc, &mii_esr)); 1719 1720 if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | 1721 MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { 1722 SOC_IF_ERROR_RETURN 1723 (READ_PHY8481_MII_GB_STATr(unit, pc, &mii_gb_stat)); 1724 SOC_IF_ERROR_RETURN 1725 (READ_PHY8481_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 1726 } 1727 } 1728 1729 /* 1730 * At this point, if we did not see Gig status, one of mii_gb_stat or 1731 * mii_gb_ctrl will be 0. This will cause the first 2 cases below to 1732 * fail and fall into the default 10/100 cases. 1733 */ 1734 1735 mii_ana &= mii_anp; 1736 1737 if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && 1738 (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { 1739 t_speed = 1000; 1740 t_duplex = 1; 1741 } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && 1742 (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { 1743 t_speed = 1000; 1744 t_duplex = 0; 1745 } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ 1746 t_speed = 100; 1747 t_duplex = 1; 1748 } else if (mii_ana & MII_ANA_T4) { /* [b] */ 1749 t_speed = 100; 1750 t_duplex = 0; 1751 } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ 1752 t_speed = 100; 1753 t_duplex = 0; 1754 } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ 1755 t_speed = 10; 1756 t_duplex = 1 ; 1757 } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ 1758 t_speed = 10; 1759 t_duplex = 0; 1760 } 1761 1762 if (speed) { 1763 *speed = t_speed; 1764 } 1765 if (duplex) { 1766 *duplex = t_duplex; 1767 } 1768 1769 return(SOC_E_NONE); 1770 } 1771 1772 /* 1773 * Function: 1774 * phy_8481_link_get 1775 * Purpose: 1776 * Get layer2 connection status. 1777 * Parameters: 1778 * unit - StrataSwitch unit #. 1779 * port - StrataSwitch port #. 1780 * link - address of memory to store link up/down state. 1781 * Returns: 1782 * SOC_E_NONE 1783 */ 1784 1785 STATIC int 1786 phy_8481_link_get(int unit, soc_port_t port, int *link) 1787 { 1788 1789 phy_ctrl_t *pc; 1790 1791 pc = EXT_PHY_SW_STATE(unit, port); 1792 1793 if (link == NULL) { 1794 return SOC_E_NONE; 1795 } 1796 1797 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1798 *link = FALSE; 1799 return SOC_E_NONE; 1800 } 1801 1802 if (pc->automedium) { 1803 SOC_IF_ERROR_RETURN 1804 (_phy_8481_medium_change(unit, port,FALSE)); 1805 } 1806 1807 if (PHY_COPPER_MODE(unit, port)) { 1808 SOC_IF_ERROR_RETURN(_phy_8481_copper_link_get(unit, port, link)); 1809 } else { 1810 SOC_IF_ERROR_RETURN(_phy_8481_xaui_link_get(unit, port, link)); 1811 } 1812 1813 LINK_DOWN(pc) = ! (*link); 1814 return SOC_E_NONE; 1815 } 1816 1817 /* 1818 * Function: 1819 * phy_8481_enable_set 1820 * Purpose: 1821 * Enable/Disable phy 1822 * Parameters: 1823 * unit - StrataSwitch unit #. 1824 * port - StrataSwitch port #. 1825 * enable - on/off state to set 1826 * Returns: 1827 * SOC_E_NONE 1828 */ 1829 1830 STATIC int 1831 _phy_8481_copper_enable_set(int unit, soc_port_t port, int enable) 1832 { 1833 phy_ctrl_t *pc; 1834 1835 pc = EXT_PHY_SW_STATE(unit, port); 1836 1837 PHY_FW_HANDSHAKE(unit, port); 1838 SOC_IF_ERROR_RETURN 1839 (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, enable ? 0:(1U << 7), 1U << 7)); 1840 PHY_FW_HANDSHAKE(unit, port); 1841 1842 return (SOC_E_NONE); 1843 } 1844 1845 STATIC int 1846 _phy_8481_copper_enable_get(int unit, soc_port_t port, int *enable) 1847 { 1848 phy_ctrl_t *pc; 1849 uint16 data16; 1850 pc = EXT_PHY_SW_STATE(unit, port); 1851 1852 SOC_IF_ERROR_RETURN 1853 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16)); 1854 if((data16 & (1U << 7)) != 0) { 1855 *enable = FALSE; 1856 } 1857 else { 1858 *enable = TRUE; 1859 } 1860 1861 return (SOC_E_NONE); 1862 } 1863 1864 STATIC int 1865 _phy_8481_xaui_enable_set(int unit, soc_port_t port, int enable) 1866 { 1867 phy_ctrl_t *pc; 1868 1869 pc = EXT_PHY_SW_STATE(unit, port); 1870 1871 PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,enable); 1872 1873 return (SOC_E_NONE); 1874 } 1875 1876 STATIC int 1877 _phy_8481_xaui_enable_get(int unit, soc_port_t port, int *enable) 1878 { 1879 phy_ctrl_t *pc; 1880 pc = EXT_PHY_SW_STATE(unit, port); 1881 1882 PHYDRV_CALL_ARG1(pc,PHY_ENABLE_GET,enable); 1883 1884 return (SOC_E_NONE); 1885 } 1886 1887 1888 STATIC int 1889 phy_8481_enable_set(int unit, soc_port_t port, int enable) 1890 { 1891 phy_ctrl_t *pc; 1892 1893 pc = EXT_PHY_SW_STATE(unit, port); 1894 1895 /* Do not incorrectly Power up the interface if medium is disabled and 1896 * global enable = true 1897 */ 1898 if (pc->copper.enable && (pc->automedium || PHY_COPPER_MODE(unit, port))) { 1899 SOC_IF_ERROR_RETURN 1900 (_phy_8481_copper_enable_set(unit, port, enable)); 1901 1902 LOG_INFO(BSL_LS_SOC_PHY, 1903 (BSL_META_U(unit, 1904 "phy_8481_enable_set: " 1905 "Power %s copper medium\n"), (enable) ? "up" : "down")); 1906 } 1907 1908 if (pc->fiber.enable && (pc->automedium || PHY_FIBER_MODE(unit, port))) { 1909 SOC_IF_ERROR_RETURN 1910 (_phy_8481_xaui_enable_set(unit, port, enable)); 1911 1912 LOG_INFO(BSL_LS_SOC_PHY, 1913 (BSL_META_U(unit, 1914 "phy_8481_enable_set: " 1915 "Power %s fiber medium\n"), (enable) ? "up" : "down")); 1916 } 1917 1918 /* Update software state */ 1919 if (enable) { 1920 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 1921 } else { 1922 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 1923 } 1924 1925 return SOC_E_NONE; 1926 } 1927 1928 /* 1929 * Function: 1930 * phy_8481_enable_get 1931 * Purpose: 1932 * Enable or disable the physical interface for a 8481 device. 1933 * Parameters: 1934 * unit - StrataSwitch unit #. 1935 * port - StrataSwitch port #. 1936 * enable - (OUT) Boolean, true = enable PHY, false = disable. 1937 * Returns: 1938 * SOC_E_XXX 1939 */ 1940 1941 STATIC int 1942 phy_8481_enable_get(int unit, soc_port_t port, int *enable) 1943 { 1944 int data16 = 0; 1945 *enable = FALSE; 1946 1947 if (PHY_COPPER_MODE(unit, port)) { /* Copper mode */ 1948 SOC_IF_ERROR_RETURN 1949 (_phy_8481_copper_enable_get(unit, port, &data16)); 1950 if(data16 == 1) { 1951 *enable = TRUE; 1952 } 1953 } 1954 else { /* Fiber mode */ 1955 SOC_IF_ERROR_RETURN 1956 (_phy_8481_xaui_enable_get(unit, port, &data16)); 1957 if(data16 == 1) { 1958 *enable = TRUE; 1959 } 1960 } 1961 1962 return SOC_E_NONE; 1963 } 1964 1965 /* 1966 * Function: 1967 * phy_8481_lb_set 1968 * Purpose: 1969 * Put 8481 in PHY PCS/PMA/PMD loopback 1970 * Parameters: 1971 * unit - StrataSwitch unit #. 1972 * port - StrataSwitch port #. 1973 * enable - binary value for on/off (1/0) 1974 * Returns: 1975 * SOC_E_NONE 1976 */ 1977 1978 STATIC int 1979 _phy_8481_copper_lb_set(int unit, soc_port_t port, int enable) 1980 { 1981 phy_ctrl_t *pc; 1982 uint16 data16 = 0; 1983 int lbmood, speed, rv = SOC_E_NONE; 1984 1985 pc = EXT_PHY_SW_STATE(unit, port); 1986 1987 if ( enable ) { /* enable loopback */ 1988 SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, &lbmood)); 1989 if ( lbmood ) { /* already in PHY loopback mode */ 1990 return SOC_E_NONE; /* do nothing */ 1991 } 1992 1993 /* try to get the intended loopback speed from LB_SPEED */ 1994 if ( 0 == (speed = LB_SPEED(pc)) ) { /* 0 means LB_SPEED not set */ 1995 /* intended loopback speed was not set, *\ 1996 \* get real line side speed to determine what registers to set */ 1997 SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_get(unit, port, &speed)); 1998 } 1999 if ( speed >= 2500 ) { /* 10G / 5G / 2.5G */ 2000 /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFe0 */ 2001 if ( PHY_IS_BCM8484X_AND_UP(pc) ) { 2002 /* turn off MII Control Loopback, and enable AutoNeg */ 2003 SOC_IF_ERROR_RETURN( 2004 MODIFY_PHY8481_MII_CTRLr(unit, pc, 2005 MII_CTRL_AE, 2006 MII_CTRL_AE | MII_CTRL_LE) ); 2007 } 2008 /* PCS Control 1 Reg. DEVAD=3 Addr=0, clear bit[14] PCS loopback mode */ 2009 if ( PHY_IS_BCM8488X(pc) ) { 2010 SOC_IF_ERROR_RETURN 2011 (MODIFY_PHY8481_PCS_CTRLr(unit, pc, 0, PCS_IEEE_CTL1_LPBK)); 2012 } 2013 2014 /* PCS control Reg.(3.0x0000), clear bits [5:2] */ 2015 if ( PHY_IS_BCM8488X(pc) ) { 2016 SOC_IF_ERROR_RETURN 2017 (MODIFY_PHY8481_PCS_CTRLr(unit, pc, 0, MGBASE_AN_CTRL_SPEED_MASK_LB)); 2018 } 2019 2020 if ( PHY_IS_BCM8486X_AND_UP(pc) ) { 2021 switch ( speed ) { 2022 case 2500 : 2023 PHY_FLAGS_SET(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC); 2024 data16 = (PHY_IS_BCM8488X(pc)) ? (PCS_IEEE_CTL1_SPEED_SEL_2P5G << 2) : MGBASE_AN_CTRL_SPEED_2P5G; 2025 break; 2026 case 5000 : 2027 PHY_FLAGS_SET(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC); 2028 data16 = (PHY_IS_BCM8488X(pc)) ? (PCS_IEEE_CTL1_SPEED_SEL_5G <<2) : MGBASE_AN_CTRL_SPEED_5G; 2029 break; 2030 case 10000 : 2031 if (PHY_IS_BCM8488X(pc)) { 2032 data16 = 0; 2033 } 2034 break; 2035 default : 2036 data16 = 0; 2037 } 2038 if ( PHY_IS_BCM8488X(pc) ) { 2039 /* PCS control Reg.(3.0x0000), Speed 10G/5G/2.5G [5:2] */ 2040 SOC_IF_ERROR_RETURN( 2041 MODIFY_PHY8481_PCS_CTRLr(unit, pc, 2042 data16, MGBASE_AN_CTRL_SPEED_MASK_LB) ); 2043 } else { 2044 /* MGBASE-T AN Control Reg.(30.0x0000), Speed_5G/2.5G[6:5] */ 2045 SOC_IF_ERROR_RETURN( 2046 MODIFY_PHY8481_MGBASET_AN_CTRLr(unit, pc, 2047 data16, MGBASE_AN_CTRL_SPEED_MASK) ); 2048 } 2049 } 2050 /* PCS Control 1 Reg. DEVAD=3 Addr=0, set bit[14] PCS loopback mode */ 2051 SOC_IF_ERROR_RETURN 2052 (MODIFY_PHY8481_PCS_CTRLr(unit, pc, 2053 PCS_IEEE_CTL1_LPBK, PCS_IEEE_CTL1_LPBK)); 2054 2055 } else { /* 1G / 100M / 10M */ 2056 /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFE0 */ 2057 if ( PHY_IS_BCM8484X_AND_UP(pc) ) { 2058 /* Clear PCS loopback bit */ 2059 SOC_IF_ERROR_RETURN 2060 (MODIFY_PHY8481_PCS_CTRLr(unit, pc, 2061 0, PCS_IEEE_CTL1_LPBK)); 2062 if ( speed == 100 ) { 2063 SOC_IF_ERROR_RETURN( 2064 WRITE_PHY8481_MII_CTRLr(unit, pc, 2065 PHY8481_MII_CTRL_LOOPBACK_100M) ); 2066 } else { /* speed = 1000 */ 2067 SOC_IF_ERROR_RETURN( 2068 WRITE_PHY8481_MII_CTRLr(unit, pc, 2069 PHY8481_MII_CTRL_LOOPBACK_1G) ); 2070 } 2071 } else { 2072 SOC_IF_ERROR_RETURN /* bit[14] : Internal Loopback */ 2073 (MODIFY_PHY8481_MII_CTRLr(unit, pc, MII_CTRL_LE, MII_CTRL_LE)); 2074 } 2075 } 2076 2077 } else { /* disable loopback */ 2078 LB_SPEED(pc) = 0; /* clear intended loopback speed */ 2079 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC); 2080 /* PCS Control 1 Reg. DEVAD=3 Addr=0, bit[14] PCS loopback mode */ 2081 SOC_IF_ERROR_RETURN 2082 (READ_PHY8481_PCS_CTRLr(unit, pc, &data16)); 2083 if ( data16 & PCS_IEEE_CTL1_LPBK ) { 2084 data16 &= (~PCS_IEEE_CTL1_LPBK); /* bit[14] : Internal Loopback */ 2085 SOC_IF_ERROR_RETURN 2086 (WRITE_PHY8481_PCS_CTRLr(unit, pc, data16)); 2087 } 2088 /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFE0 */ 2089 SOC_IF_ERROR_RETURN 2090 (READ_PHY8481_MII_CTRLr(unit, pc, &data16)); 2091 if ( data16 & MII_CTRL_LE ) { 2092 data16 &= (~MII_CTRL_LE); /* bit[14] : Internal Loopback */ 2093 SOC_IF_ERROR_RETURN 2094 (WRITE_PHY8481_MII_CTRLr(unit, pc, data16)); 2095 } 2096 } 2097 sal_udelay(180); /* wait for the loopback setting to take effect */ 2098 2099 /* wait for MAC side Link UP/down state while enabling/disabling loopback */ 2100 if ( PHY_IS_BCM8483X_AND_UP(pc) ) { 2101 soc_timeout_init(&TO(pc), 1000000, 0); 2102 do { 2103 rv = READ_PHY84834_CORE_CFG_LINK_STATUSr(unit, pc, &data16); 2104 if ( (( enable) && ( (data16 & CORE_CFG_LINK_STAT_MAC_LINK_STATUS))) || 2105 ((!enable) && (!(data16 & CORE_CFG_LINK_STAT_MAC_LINK_STATUS))) || 2106 SOC_FAILURE(rv) ) { 2107 break; 2108 } 2109 } while ( ! soc_timeout_check(&TO(pc)) ); 2110 } 2111 2112 return rv; 2113 } 2114 2115 STATIC int 2116 _phy_8481_xaui_lb_set(int unit, soc_port_t port, int enable) 2117 { 2118 phy_ctrl_t *pc; 2119 2120 pc = EXT_PHY_SW_STATE(unit, port); 2121 2122 SOC_IF_ERROR_RETURN 2123 (MODIFY_PHY8481_PHYXS_L_CTRLr(unit, pc, (enable) ? MII_CTRL_LE : 0, MII_CTRL_LE)); 2124 2125 /* Configure Loopback in SerDes */ 2126 SOC_IF_ERROR_RETURN 2127 (MODIFY_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, 2128 (enable) ? MII_CTRL_LE : 0, 2129 MII_CTRL_LE)); 2130 return SOC_E_NONE; 2131 } 2132 2133 STATIC int 2134 phy_8481_lb_set(int unit, soc_port_t port, int enable) 2135 { 2136 phy_ctrl_t *pc; 2137 2138 pc = EXT_PHY_SW_STATE(unit, port); 2139 2140 if ( PHY_COPPER_MODE(unit, port) ) { 2141 SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_set(unit, port, enable)); 2142 } else { 2143 if ( NXT_PC(pc) ) { 2144 PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_SET,enable); 2145 return SOC_E_NONE; 2146 } 2147 SOC_IF_ERROR_RETURN(_phy_8481_xaui_lb_set(unit, port, enable)); 2148 } 2149 2150 if ( enable ) { 2151 /* set link-down flag in order to notify appropriate speed *\ 2152 \* in phy_8481_link_up() */ 2153 LINK_DOWN(pc) = TRUE; 2154 /* PHY driver has to call phy_8481_link_up() when setting loopback */ 2155 SOC_IF_ERROR_RETURN( phy_8481_link_up(unit, port) ); 2156 } 2157 2158 return SOC_E_NONE; 2159 } 2160 2161 /* 2162 * Function: 2163 * phy_8481_lb_get 2164 * Purpose: 2165 * Get 8481 PHY loopback state 2166 * Parameters: 2167 * unit - StrataSwitch unit #. 2168 * port - StrataSwitch port #. 2169 * enable - address of location to store binary value for on/off (1/0) 2170 * Returns: 2171 * SOC_E_NONE 2172 */ 2173 2174 STATIC int 2175 _phy_8481_copper_lb_get(int unit, soc_port_t port, int *enable) 2176 { 2177 phy_ctrl_t *pc; 2178 uint16 tmp; 2179 2180 pc = EXT_PHY_SW_STATE(unit, port); 2181 2182 /* PCS Control 1 Reg. DEVAD=3 Addr=0, bit[14] PCS loopback mode */ 2183 SOC_IF_ERROR_RETURN 2184 (READ_PHY8481_PCS_CTRLr(unit, pc, &tmp)); 2185 /* ctrl != 0xffff check is to handle removable PHY daughter cards */ 2186 *enable = ((tmp != 0xffff) && (tmp & PCS_IEEE_CTL1_LPBK)) ? TRUE : FALSE; 2187 2188 if ( ! (*enable) ) { 2189 /* 1000BASE-T/100BASE-TX MII Contol Reg. DEVAD=7, Addr=0xFFe0 */ 2190 SOC_IF_ERROR_RETURN /* bit[14] : Internal Loopback */ 2191 (READ_PHY8481_MII_CTRLr(unit, pc, &tmp)); 2192 /* ctrl != 0xffff check is to handle removable PHY daughter cards */ 2193 *enable = ((tmp != 0xffff) && (tmp & MII_CTRL_LE)) ? TRUE : FALSE; 2194 } 2195 2196 LOG_INFO(BSL_LS_SOC_PHY, 2197 (BSL_META_U(unit, 2198 "phy_8481_lb_get: u=%d port%d: loopback:%s\n"), 2199 unit, port, *enable ? "Enabled": "Disabled")); 2200 2201 2202 return SOC_E_NONE; 2203 } 2204 2205 STATIC int 2206 _phy_8481_xaui_lb_get(int unit, soc_port_t port, int *enable) 2207 { 2208 uint16 mii_ctrl; 2209 phy_ctrl_t *pc; 2210 2211 pc = EXT_PHY_SW_STATE(unit, port); 2212 2213 SOC_IF_ERROR_RETURN 2214 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl)); 2215 /* ctrl != 0xffff check is to handle removable PHY daughter cards */ 2216 *enable = (mii_ctrl != 0xffff) && ((mii_ctrl & MII_CTRL_LE) == MII_CTRL_LE); 2217 2218 return (SOC_E_NONE); 2219 } 2220 2221 STATIC int 2222 phy_8481_lb_get(int unit, soc_port_t port, int *enable) 2223 { 2224 phy_ctrl_t *pc; 2225 2226 pc = EXT_PHY_SW_STATE(unit, port); 2227 2228 if (PHY_COPPER_MODE(unit, port)) { 2229 SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, enable)); 2230 } else { 2231 if (NXT_PC(pc)) { 2232 PHYDRV_CALL_ARG1(pc,PHY_LOOPBACK_GET,enable); 2233 return SOC_E_NONE; 2234 } 2235 SOC_IF_ERROR_RETURN(_phy_8481_xaui_lb_get(unit, port, enable)); 2236 } 2237 2238 return SOC_E_NONE; 2239 } 2240 2241 int 2242 phy_8481_xehg_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 2243 { 2244 int speed =0; 2245 2246 SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed)); 2247 switch (speed) { 2248 case 100 : /* fall through */ 2249 case 1000 : 2250 *pif = SOC_PORT_IF_SGMII; 2251 break; 2252 case 10000: 2253 *pif = SOC_PORT_IF_XFI; 2254 break; 2255 case 2500 : /* fall through */ 2256 case 5000 : 2257 if ( PHY_REPEATER(unit, port) ) { 2258 /* MAC interface is in XFI mode */ 2259 *pif = SOC_PORT_IF_XFI; 2260 } else { 2261 /* MAC interface is in 2500/5000BASE-X mode */ 2262 *pif = SOC_PORT_IF_SGMII; 2263 } 2264 break; 2265 case 0 : 2266 *pif = SOC_PORT_IF_XFI; 2267 break; 2268 default: 2269 return SOC_E_PARAM; 2270 } 2271 2272 return SOC_E_NONE; 2273 } 2274 2275 #ifdef PHY8481_DEBUG_AUTOMEDIUM 2276 int 2277 show_phy_8481_clkrst_reg(int unit, soc_port_t port) 2278 { 2279 phy_ctrl_t *pc; 2280 uint16 status=0; 2281 2282 pc = EXT_PHY_SW_STATE(unit, port); 2283 2284 SOC_IF_ERROR_RETURN 2285 (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status)); 2286 2287 LOG_CLI((BSL_META_U(unit, 2288 "TOP_CONFIG_LINK_STATUS_REG = %x\n"), status)); 2289 2290 return SOC_E_NONE; 2291 } 2292 #endif 2293 2294 STATIC int 2295 _phy_8481_medium_check(int unit, soc_port_t port, int *medium) 2296 { 2297 phy_ctrl_t *pc; 2298 uint16 status; 2299 2300 pc = EXT_PHY_SW_STATE(unit, port); 2301 2302 if (PHY_FORCED_COPPER_MODE(unit, port)) { 2303 *medium = SOC_PORT_MEDIUM_COPPER; 2304 return SOC_E_NONE; 2305 } 2306 2307 SOC_IF_ERROR_RETURN 2308 (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status)); 2309 2310 2311 if ( status & TOP_CONFIG_LINK_STATUS_REG_FIBER_PRIO ) { 2312 if ( status & TOP_CONFIG_LINK_STATUS_REG_FIBER_ACT ) { 2313 *medium = SOC_PORT_MEDIUM_FIBER; 2314 } else if ( status & TOP_CONFIG_LINK_STATUS_REG_COPPER_ACT ) { 2315 *medium = SOC_PORT_MEDIUM_COPPER; 2316 } else { 2317 *medium = SOC_PORT_MEDIUM_FIBER; 2318 } 2319 } else { 2320 if ( status & TOP_CONFIG_LINK_STATUS_REG_COPPER_ACT ) { 2321 *medium = SOC_PORT_MEDIUM_COPPER; 2322 } else if ( status & TOP_CONFIG_LINK_STATUS_REG_FIBER_ACT ) { 2323 *medium = SOC_PORT_MEDIUM_FIBER; 2324 } else { 2325 *medium = SOC_PORT_MEDIUM_COPPER; 2326 } 2327 } 2328 2329 return SOC_E_NONE; 2330 } 2331 2332 STATIC int 2333 _phy_8481_medium_change(int unit, soc_port_t port, int force_update) 2334 { 2335 phy_ctrl_t *pc; 2336 int medium; 2337 2338 pc = EXT_PHY_SW_STATE(unit, port); 2339 2340 SOC_IF_ERROR_RETURN 2341 (_phy_8481_medium_check(unit, port, &medium)); 2342 2343 if (medium == SOC_PORT_MEDIUM_COPPER) { 2344 if ((!PHY_COPPER_MODE(unit, port)) || force_update) { /* Was fiber */ 2345 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 2346 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 2347 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 2348 PHY8481_SELECT_REGS_CU(unit, pc); 2349 2350 if (pc->copper.enable) { 2351 /* PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,FALSE); */ 2352 SOC_IF_ERROR_RETURN 2353 (_phy_8481_medium_config_update(unit, port, &pc->copper)); 2354 } 2355 2356 LOG_INFO(BSL_LS_SOC_PHY, 2357 (BSL_META_U(unit, 2358 "_phy_8481_link_auto_detect: u=%d p=%d [F->X]\n"), 2359 unit, port)); 2360 } 2361 } else { /* Fiber */ 2362 if ((!PHY_FIBER_MODE(unit, port)) || force_update) { /* Was copper */ 2363 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 2364 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 2365 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 2366 PHY8481_SELECT_REGS_XAUI(unit, pc); 2367 2368 if (pc->fiber.enable) { 2369 /* PHYDRV_CALL_ARG1(pc,PHY_ENABLE_SET,TRUE); */ 2370 SOC_IF_ERROR_RETURN 2371 (_phy_8481_medium_config_update(unit, port, &pc->fiber)); 2372 } 2373 2374 LOG_INFO(BSL_LS_SOC_PHY, 2375 (BSL_META_U(unit, 2376 "_phy_8481_link_auto_detect: u=%d p=%d [C->X]\n"), 2377 unit, port)); 2378 } 2379 } 2380 2381 return SOC_E_NONE; 2382 } 2383 2384 /* 2385 * Function: 2386 * phy_8481_medium_status 2387 * Purpose: 2388 * Indicate the current active medium 2389 * Parameters: 2390 * unit - StrataSwitch unit #. 2391 * port - StrataSwitch port #. 2392 * medium - (OUT) One of: 2393 * SOC_PORT_MEDIUM_COPPER 2394 * SOC_PORT_MEDIUM_XAUI 2395 * Returns: 2396 * SOC_E_NONE 2397 */ 2398 2399 STATIC int 2400 phy_8481_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 2401 { 2402 if (PHY_COPPER_MODE(unit, port)) { 2403 *medium = SOC_PORT_MEDIUM_COPPER; 2404 } else { 2405 *medium = SOC_PORT_MEDIUM_XAUI; 2406 } 2407 2408 return SOC_E_NONE; 2409 } 2410 2411 /* 2412 * Function: 2413 * _phy_8481_medium_config_update 2414 * Purpose: 2415 * Update the PHY with config parameters 2416 * Parameters: 2417 * unit - StrataSwitch unit #. 2418 * port - StrataSwitch port #. 2419 * cfg - Config structure. 2420 * Returns: 2421 * SOC_E_XXX 2422 */ 2423 2424 STATIC int 2425 _phy_8481_medium_config_update(int unit, soc_port_t port, 2426 soc_phy_config_t *cfg) 2427 { 2428 2429 SOC_IF_ERROR_RETURN 2430 (phy_8481_speed_set(unit, port, cfg->force_speed)); 2431 SOC_IF_ERROR_RETURN 2432 (phy_8481_duplex_set(unit, port, cfg->force_duplex)); 2433 SOC_IF_ERROR_RETURN 2434 (phy_8481_ability_advert_set(unit, port, &cfg->advert_ability)); 2435 SOC_IF_ERROR_RETURN 2436 (phy_8481_an_set(unit, port, cfg->autoneg_enable)); 2437 SOC_IF_ERROR_RETURN 2438 (phy_8481_mdix_set(unit, port, cfg->mdix)); 2439 2440 return SOC_E_NONE; 2441 } 2442 2443 /* 2444 * Function: 2445 * phy_8481_medium_config_set 2446 * Purpose: 2447 * Set the operating parameters that are automatically selected 2448 * when medium switches type. 2449 * Parameters: 2450 * unit - StrataSwitch unit # 2451 * port - Port number 2452 * medium - SOC_PORT_MEDIUM_COPPER/XAUI 2453 * cfg - Operating parameters 2454 * Returns: 2455 * SOC_E_XXX 2456 */ 2457 2458 STATIC int 2459 phy_8481_medium_config_set(int unit, soc_port_t port, 2460 soc_port_medium_t medium, 2461 soc_phy_config_t *cfg) 2462 { 2463 phy_ctrl_t *pc; 2464 soc_phy_config_t *active_medium; /* Currently active medium */ 2465 soc_phy_config_t *change_medium; /* Requested medium */ 2466 soc_phy_config_t *other_medium; /* The other medium */ 2467 int medium_update; 2468 2469 if (NULL == cfg || cfg->enable != TRUE) { 2470 return SOC_E_PARAM; 2471 } 2472 2473 pc = EXT_PHY_SW_STATE(unit, port); 2474 medium_update = FALSE; 2475 2476 switch (medium) { 2477 case SOC_PORT_MEDIUM_COPPER: 2478 if (!pc->automedium) { 2479 if (!PHY_COPPER_MODE(unit, port)) { 2480 return SOC_E_UNAVAIL; 2481 } 2482 /* check if device is fiber capable before switching */ 2483 if (cfg->preferred == 0) { 2484 if (PHY_FORCED_COPPER_MODE(unit, port)) { 2485 /* return if not fiber capable*/ 2486 return SOC_E_UNAVAIL; 2487 } 2488 } 2489 } 2490 change_medium = &pc->copper; 2491 other_medium = &pc->fiber; 2492 break; 2493 case SOC_PORT_MEDIUM_FIBER: 2494 if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) { 2495 return SOC_E_UNAVAIL; 2496 } 2497 change_medium = &pc->fiber; 2498 other_medium = &pc->copper; 2499 break; 2500 default: 2501 return SOC_E_PARAM; 2502 } 2503 2504 /* 2505 * Changes take effect immediately if the target medium is active or 2506 * the preferred medium changes. 2507 */ 2508 if (change_medium->enable != cfg->enable) { 2509 medium_update = TRUE; 2510 } 2511 if (change_medium->preferred != cfg->preferred) { 2512 /* Make sure that only one medium is preferred */ 2513 other_medium->preferred = !cfg->preferred; 2514 medium_update = TRUE; 2515 } 2516 2517 sal_memcpy(change_medium, cfg, sizeof(*change_medium)); 2518 2519 if (!PHY_FORCED_COPPER_MODE(unit, port)) { 2520 PHY_FW_HANDSHAKE(unit, port); 2521 SOC_IF_ERROR_RETURN 2522 (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, pc->fiber.preferred ? 1U<<8 : 0, 1U<<8)); 2523 PHY_FW_HANDSHAKE(unit, port); 2524 } 2525 2526 if (medium_update) { 2527 /* The new configuration may cause medium change. Check 2528 * and update medium. 2529 */ 2530 SOC_IF_ERROR_RETURN 2531 (_phy_8481_medium_change(unit, port,TRUE)); 2532 } else { 2533 active_medium = (PHY_COPPER_MODE(unit, port)) ? 2534 &pc->copper : &pc->fiber; 2535 if (active_medium == change_medium) { 2536 /* If the medium to update is active, update the configuration */ 2537 SOC_IF_ERROR_RETURN 2538 (_phy_8481_medium_config_update(unit, port, change_medium)); 2539 } 2540 } 2541 return SOC_E_NONE; 2542 } 2543 2544 /* 2545 * Function: 2546 * phy_8481_medium_config_get 2547 * Purpose: 2548 * Get the operating parameters that are automatically selected 2549 * when medium switches type. 2550 * Parameters: 2551 * unit - StrataSwitch unit # 2552 * port - Port number 2553 * medium - SOC_PORT_MEDIUM_COPPER/XAUI 2554 * cfg - (OUT) Operating parameters 2555 * Returns: 2556 * SOC_E_XXX 2557 */ 2558 2559 STATIC int 2560 phy_8481_medium_config_get(int unit, soc_port_t port, 2561 soc_port_medium_t medium, 2562 soc_phy_config_t *cfg) 2563 { 2564 int rv; 2565 phy_ctrl_t *pc; 2566 2567 pc = EXT_PHY_SW_STATE(unit, port); 2568 rv = SOC_E_NONE; 2569 2570 switch (medium) { 2571 case SOC_PORT_MEDIUM_COPPER: 2572 if (pc->automedium || PHY_COPPER_MODE(unit, port)) { 2573 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 2574 } else { 2575 rv = SOC_E_UNAVAIL; 2576 } 2577 break; 2578 case SOC_PORT_MEDIUM_FIBER: 2579 if (pc->automedium || (!PHY_COPPER_MODE(unit, port))) { 2580 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 2581 } else { 2582 rv = SOC_E_UNAVAIL; 2583 } 2584 break; 2585 default: 2586 rv = SOC_E_PARAM; 2587 break; 2588 } 2589 2590 return rv; 2591 } 2592 2593 /* STATIC */ int 2594 _phy84834_top_level_cmd_set(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size) 2595 { 2596 soc_timeout_t to; 2597 int rv; 2598 uint16 status; 2599 2600 if ((size < 1) || (size > 4)) { 2601 return (SOC_E_PARAM); 2602 } 2603 2604 if (cmd == PHY84834_DIAG_CMD_PAIR_SWAP_CHANGE) { 2605 SOC_IF_ERROR_RETURN 2606 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, PHY84834_CMD_OPEN_OVERRIDE)); 2607 } 2608 2609 soc_timeout_init(&to, 7000000, 0); 2610 do { 2611 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status); 2612 if (((status & PHY84834_CMD_OPEN_FOR_CMDS) != 0) || 2613 SOC_FAILURE(rv)) { 2614 break; 2615 } 2616 } while (!soc_timeout_check(&to)); 2617 if ((status & PHY84834_CMD_OPEN_FOR_CMDS) == 0) { 2618 LOG_CLI((BSL_META_U(unit, 2619 "PHY84834_TOP_LEVEL_CMD_SET failed: u=%d p=%d cmd=%08x\n"), 2620 unit, pc->port, cmd)); 2621 return (SOC_E_FAIL); 2622 } 2623 2624 if (size-- > 0) { 2625 if (cmd == PHY84834_DIAG_CMD_PAIR_SWAP_CHANGE) { 2626 SOC_IF_ERROR_RETURN 2627 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_4r(unit, pc, arg[0])); 2628 } else { 2629 SOC_IF_ERROR_RETURN 2630 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_3r(unit, pc, arg[0])); 2631 } 2632 } 2633 if (size-- > 0) { 2634 SOC_IF_ERROR_RETURN 2635 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_4r(unit, pc, arg[1])); 2636 } 2637 /* coverity[dead_error_condition:FALSE] */ 2638 if (size-- > 0) { 2639 /* coverity[dead_error_begin] */ 2640 SOC_IF_ERROR_RETURN 2641 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_12r(unit, pc, arg[2])); 2642 } 2643 /* coverity[dead_error_condition:FALSE] */ 2644 if (size-- > 0) { 2645 /* coverity[dead_error_begin] */ 2646 SOC_IF_ERROR_RETURN 2647 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_13r(unit, pc, arg[3])); 2648 } 2649 2650 SOC_IF_ERROR_RETURN 2651 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd)); 2652 2653 soc_timeout_init(&to, 1000000, 0); 2654 do { 2655 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status); 2656 if (((status & (PHY84834_CMD_COMPLETE_PASS | PHY84834_CMD_COMPLETE_ERROR)) != 0) || 2657 SOC_FAILURE(rv)) { 2658 break; 2659 } 2660 } while (!soc_timeout_check(&to)); 2661 if ((status & PHY84834_CMD_COMPLETE_PASS) == 0) { 2662 LOG_CLI((BSL_META_U(unit, 2663 "PHY84834_TOP_LEVEL_CMD_SET failed: u=%d p=%d cmd=%08x\n"), 2664 unit, pc->port, cmd)); 2665 return (SOC_E_FAIL); 2666 } 2667 2668 SOC_IF_ERROR_RETURN 2669 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE)); 2670 2671 return (SOC_E_NONE); 2672 } 2673 2674 /* STATIC */ int 2675 _phy84834_top_level_cmd_get(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size) 2676 { 2677 soc_timeout_t to; 2678 int rv; 2679 uint16 status; 2680 2681 if ((size < 1) || (size > 4)) { 2682 return (SOC_E_PARAM); 2683 } 2684 2685 soc_timeout_init(&to, 7000000, 0); 2686 do { 2687 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status); 2688 if (((status & PHY84834_CMD_OPEN_FOR_CMDS) != 0) || 2689 SOC_FAILURE(rv)) { 2690 break; 2691 } 2692 } while (!soc_timeout_check(&to)); 2693 if ((status & PHY84834_CMD_OPEN_FOR_CMDS) == 0) { 2694 LOG_CLI((BSL_META_U(unit, 2695 "PHY84834_TOP_LEVEL_CMD_GET failed: u=%d p=%d cmd=%08x\n"), 2696 unit, pc->port, cmd)); 2697 return (SOC_E_FAIL); 2698 } 2699 SOC_IF_ERROR_RETURN 2700 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd)); 2701 2702 soc_timeout_init(&to, 1000000, 0); 2703 2704 do { 2705 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, &status); 2706 if (((status & (PHY84834_CMD_COMPLETE_PASS | PHY84834_CMD_COMPLETE_ERROR)) != 0) || 2707 SOC_FAILURE(rv)) { 2708 break; 2709 } 2710 } while (!soc_timeout_check(&to)); 2711 if ((status & PHY84834_CMD_COMPLETE_PASS) == 0) { 2712 LOG_CLI((BSL_META_U(unit, 2713 "PHY84834_TOP_LEVEL_CMD_GET failed: u=%d p=%d cmd=%08x\n"), 2714 unit, pc->port, cmd)); 2715 return (SOC_E_FAIL); 2716 } 2717 if (size-- > 0) { 2718 SOC_IF_ERROR_RETURN 2719 (READ_PHY84834_TOP_CONFIG_SCRATCH_3r(unit, pc, &arg[0])); 2720 } 2721 if (size-- > 0) { 2722 SOC_IF_ERROR_RETURN 2723 (READ_PHY84834_TOP_CONFIG_SCRATCH_4r(unit, pc, &arg[1])); 2724 } 2725 /* coverity[dead_error_condition:FALSE] */ 2726 if (size-- > 0) { 2727 /* coverity[dead_error_begin] */ 2728 SOC_IF_ERROR_RETURN 2729 (READ_PHY84834_TOP_CONFIG_SCRATCH_12r(unit, pc, &arg[2])); 2730 } 2731 /* coverity[dead_error_condition:FALSE] */ 2732 if (size-- > 0) { 2733 /* coverity[dead_error_begin] */ 2734 SOC_IF_ERROR_RETURN 2735 (READ_PHY84834_TOP_CONFIG_SCRATCH_13r(unit, pc, &arg[3])); 2736 } 2737 2738 SOC_IF_ERROR_RETURN 2739 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_2r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE)); 2740 2741 return (SOC_E_NONE); 2742 2743 } 2744 2745 /* STATIC */ int 2746 _phy84834_top_level_cmd_set_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size) 2747 { 2748 soc_timeout_t to; 2749 int rv; 2750 uint16 status; 2751 2752 if ((size < 1) || (size > 5)) { 2753 return (SOC_E_PARAM); 2754 } 2755 2756 soc_timeout_init(&to, 7000000, 0); 2757 do { 2758 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 2759 if (PHY8481_IS_READY_FOR_CMD(pc, status) || SOC_FAILURE(rv)) { 2760 break; 2761 } 2762 } while (!soc_timeout_check(&to)); 2763 if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) { 2764 LOG_CLI((BSL_META_U(unit, 2765 "PHY84834_TOP_LEVEL_CMD_SET failed:<1> u=%d p=%d " 2766 "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status)); 2767 return (SOC_E_FAIL); 2768 } 2769 2770 if (size-- > 0) { 2771 if (cmd == PHY84834_DIAG_CMD_SET_PAIR_SWAP_V2) { 2772 SOC_IF_ERROR_RETURN 2773 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, arg[0])); 2774 } else { 2775 SOC_IF_ERROR_RETURN 2776 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, arg[0])); 2777 } 2778 } 2779 if (size-- > 0) { 2780 SOC_IF_ERROR_RETURN 2781 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, arg[1])); 2782 } 2783 /* coverity[dead_error_condition:FALSE] */ 2784 if (size-- > 0) { 2785 /* coverity[dead_error_begin] */ 2786 SOC_IF_ERROR_RETURN 2787 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, arg[2])); 2788 } 2789 /* coverity[dead_error_condition:FALSE] */ 2790 if (size-- > 0) { 2791 /* coverity[dead_error_begin] */ 2792 SOC_IF_ERROR_RETURN 2793 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, arg[3])); 2794 } 2795 /* coverity[dead_error_condition:FALSE] */ 2796 if (size-- > 0) { 2797 /* coverity[dead_error_begin] */ 2798 SOC_IF_ERROR_RETURN 2799 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, arg[4])); 2800 } 2801 2802 SOC_IF_ERROR_RETURN 2803 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd)); 2804 2805 soc_timeout_init(&to, 7000000, 0); 2806 do { 2807 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 2808 if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) { 2809 break; 2810 } 2811 } while (!soc_timeout_check(&to)); 2812 if (status != PHY8481_CMD_COMPLETE_PASS) { 2813 LOG_CLI((BSL_META_U(unit, 2814 "PHY84834_TOP_LEVEL_CMD_SET failed:<2> u=%d p=%d " 2815 "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status)); 2816 return (SOC_E_FAIL); 2817 } 2818 2819 if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) { 2820 SOC_IF_ERROR_RETURN 2821 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE)); 2822 } 2823 return (SOC_E_NONE); 2824 } 2825 2826 /* STATIC */ int 2827 _phy84834_top_level_cmd_get_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size) 2828 { 2829 soc_timeout_t to; 2830 int rv; 2831 uint16 status; 2832 2833 if ((size < 1) || (size > 5)) { 2834 return (SOC_E_PARAM); 2835 } 2836 2837 soc_timeout_init(&to, 7000000, 0); 2838 do { 2839 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 2840 if (PHY8481_IS_READY_FOR_CMD(pc, status) || SOC_FAILURE(rv)) { 2841 break; 2842 } 2843 } while (!soc_timeout_check(&to)); 2844 if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) { 2845 LOG_CLI((BSL_META_U(unit, 2846 "PHY84834_TOP_LEVEL_CMD_GET failed:<1> u=%d p=%d " 2847 "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status)); 2848 return (SOC_E_FAIL); 2849 } 2850 SOC_IF_ERROR_RETURN 2851 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd)); 2852 2853 soc_timeout_init(&to, 1000000, 0); 2854 do { 2855 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 2856 if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) { 2857 break; 2858 } 2859 } while (!soc_timeout_check(&to)); 2860 if (status != PHY8481_CMD_COMPLETE_PASS) { 2861 LOG_CLI((BSL_META_U(unit, 2862 "PHY84834_TOP_LEVEL_CMD_GET failed:<2> u=%d p=%d " 2863 "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status)); 2864 return (SOC_E_FAIL); 2865 } 2866 2867 if (size-- > 0) { 2868 if (cmd == PHY84834_DIAG_CMD_GET_PAIR_SWAP_V2 && !(PHY_IS_BCM8488X(pc)) ) { 2869 SOC_IF_ERROR_RETURN 2870 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[0])); 2871 } else { 2872 SOC_IF_ERROR_RETURN 2873 (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &arg[0])); 2874 } 2875 } 2876 if (size-- > 0) { 2877 SOC_IF_ERROR_RETURN 2878 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[1])); 2879 } 2880 /* coverity[dead_error_condition:FALSE] */ 2881 if (size-- > 0) { 2882 /* coverity[dead_error_begin] */ 2883 SOC_IF_ERROR_RETURN 2884 (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &arg[2])); 2885 } 2886 /* coverity[dead_error_condition:FALSE] */ 2887 if (size-- > 0) { 2888 /* coverity[dead_error_begin] */ 2889 SOC_IF_ERROR_RETURN 2890 (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &arg[3])); 2891 } 2892 /* coverity[dead_error_condition:FALSE] */ 2893 if (size-- > 0) { 2894 /* coverity[dead_error_begin] */ 2895 SOC_IF_ERROR_RETURN 2896 (READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, &arg[4])); 2897 } 2898 2899 if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) { 2900 SOC_IF_ERROR_RETURN 2901 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE)); 2902 } 2903 2904 return (SOC_E_NONE); 2905 2906 } 2907 2908 /* READ a register: 32-bit addressing mode */ 2909 int 2910 _phy848xx_addr32_reg_read(int unit, phy_ctrl_t *pc, uint32 addr32, uint16 *val) 2911 { 2912 uint16 cmd_args[3]; 2913 2914 cmd_args[0] = ADDR32BIT_HIGH(addr32); 2915 cmd_args[1] = ADDR32BIT_LOW( addr32); 2916 cmd_args[2] = ADDR32BIT_READ; 2917 SOC_IF_ERROR_RETURN( 2918 PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 2919 PHY84834_DIAG_CMD_ACCESS_32BIT_XFI_ADDR, 2920 cmd_args, 3) ); 2921 SOC_IF_ERROR_RETURN( /* get the value from Command Handler Data 5 Reg. */ 2922 READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, val) ); 2923 return SOC_E_NONE; 2924 } 2925 2926 /* WRITE a register: 32-bit addressing mode */ 2927 int 2928 _phy848xx_addr32_reg_write(int unit, phy_ctrl_t *pc, uint32 addr32, uint16 val) 2929 { 2930 uint16 cmd_args[4]; 2931 2932 cmd_args[0] = ADDR32BIT_HIGH(addr32); 2933 cmd_args[1] = ADDR32BIT_LOW( addr32); 2934 cmd_args[2] = ADDR32BIT_WRITE; 2935 cmd_args[3] = val; /* 16-bit data to be written to the register */ 2936 SOC_IF_ERROR_RETURN( 2937 PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 2938 PHY84834_DIAG_CMD_ACCESS_32BIT_XFI_ADDR, 2939 cmd_args, 4) ); 2940 return SOC_E_NONE; 2941 } 2942 2943 /* MODIFY a register: 32-bit addressing mode */ 2944 int 2945 _phy848xx_addr32_reg_modify(int unit, phy_ctrl_t *pc, uint32 addr32, 2946 uint16 val, uint16 mask) 2947 { 2948 uint16 data16; 2949 SOC_IF_ERROR_RETURN( _phy848xx_addr32_reg_read(unit, pc, addr32, &data16) ); 2950 data16 = (data16 & (~mask)) | val; 2951 SOC_IF_ERROR_RETURN( _phy848xx_addr32_reg_write(unit, pc, addr32, data16) ); 2952 return SOC_E_NONE; 2953 } 2954 2955 #ifdef BCM_WARM_BOOT_SUPPORT 2956 STATIC int 2957 _phy84834_top_level_cmd_get_dispatch_v2(int unit,phy_ctrl_t *pc, uint16 cmd) 2958 { 2959 int rv; 2960 uint16 status; 2961 2962 soc_timeout_init(&TO(pc), 7000000, 0); 2963 2964 do { 2965 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 2966 if (PHY8481_IS_READY_FOR_CMD(pc, status) ||SOC_FAILURE(rv)) { 2967 break; 2968 } 2969 } while (!soc_timeout_check(&TO(pc))); 2970 if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) { 2971 LOG_CLI((BSL_META_U(unit, 2972 "PHY84834_TOP_LEVEL_CMD_GET (dispatch) failed:<1>" 2973 " u=%d p=%d cmd=%04x status=%04x\n"), 2974 unit, pc->port, cmd, status)); 2975 return SOC_E_FAIL; 2976 } 2977 SOC_IF_ERROR_RETURN 2978 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, cmd)); 2979 2980 soc_timeout_init(&TO(pc), 1000000, 0); 2981 2982 return SOC_E_NONE; 2983 } 2984 2985 STATIC int 2986 _phy84834_top_level_cmd_get_retrive_v2(int unit,phy_ctrl_t *pc, uint16 cmd, uint16 arg[], int size) 2987 { 2988 int rv; 2989 uint16 status; 2990 2991 do { 2992 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 2993 if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) { 2994 break; 2995 } 2996 } while (!soc_timeout_check(&TO(pc))); 2997 if (status != PHY8481_CMD_COMPLETE_PASS) { 2998 LOG_CLI((BSL_META_U(unit, 2999 "PHY84834_TOP_LEVEL_CMD_GET failed:<2> u=%d p=%d" 3000 "cmd=%04x status=%04x\n"), unit, pc->port, cmd, status)); 3001 return SOC_E_FAIL; 3002 } 3003 if (size-- > 0) { 3004 if (cmd == PHY84834_DIAG_CMD_GET_PAIR_SWAP_V2) { 3005 SOC_IF_ERROR_RETURN 3006 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[0])); 3007 } else { 3008 SOC_IF_ERROR_RETURN 3009 (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &arg[0])); 3010 } 3011 } 3012 3013 if (size-- > 0) { 3014 SOC_IF_ERROR_RETURN 3015 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &arg[1])); 3016 } 3017 if (size-- > 0) { 3018 SOC_IF_ERROR_RETURN 3019 (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &arg[2])); 3020 } 3021 if (size-- > 0) { 3022 SOC_IF_ERROR_RETURN 3023 (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &arg[3])); 3024 } 3025 if (size-- > 0) { 3026 SOC_IF_ERROR_RETURN 3027 (READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, &arg[4])); 3028 } 3029 3030 if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) { 3031 SOC_IF_ERROR_RETURN 3032 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE)); 3033 } 3034 3035 return SOC_E_NONE; 3036 } 3037 #endif 3038 3039 STATIC int 3040 _phy84834_eee_mode_set(int unit,phy_ctrl_t *pc, uint16 mode, uint16 ag_th_high, uint16 ag_th_low, uint16 latency ) 3041 { 3042 uint16 args[5]; 3043 args[0] = mode; 3044 args[1] = ag_th_high; 3045 args[2] = ag_th_low; 3046 args[3] = latency; 3047 3048 SOC_IF_ERROR_RETURN 3049 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_EEE_MODE_GENERIC, args, 4)); 3050 3051 return (SOC_E_NONE); 3052 } 3053 3054 STATIC int 3055 _phy84834_eee_mode_get(int unit,phy_ctrl_t *pc, uint16 *mode, uint16 *ag_th_high, uint16 *ag_th_low, uint16 *latency ) 3056 { 3057 uint16 args[5]; 3058 3059 SOC_IF_ERROR_RETURN 3060 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EEE_MODE_GENERIC, args, 4)); 3061 3062 if (mode) { 3063 *mode = args[0]; 3064 } 3065 if (ag_th_high) { 3066 *ag_th_high = args[1]; 3067 } 3068 if (ag_th_low) { 3069 *ag_th_low = args[2]; 3070 } 3071 if (latency) { 3072 *latency = args[3]; 3073 } 3074 3075 return (SOC_E_NONE); 3076 } 3077 3078 STATIC int 3079 _phy84834_jumbo_packet_set(int unit, phy_ctrl_t *pc, uint16 mode) 3080 { 3081 uint16 args[2]; 3082 args[0] = mode; 3083 3084 SOC_IF_ERROR_RETURN 3085 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY848x_DIAG_CMD_SET_JUMBO_FRAME_MODE, args, 1)); 3086 3087 return (SOC_E_NONE); 3088 } 3089 3090 #if 0 3091 STATIC int 3092 _phy84834_jumbo_packet_get(int unit,phy_ctrl_t *pc, uint16 *mode) 3093 { 3094 uint16 args[2]; 3095 3096 SOC_IF_ERROR_RETURN 3097 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY848x_DIAG_CMD_GET_JUMBO_FRAME_MODE, args, 1)); 3098 3099 if (mode) { 3100 *mode = args[0]; 3101 } 3102 3103 return (SOC_E_NONE); 3104 } 3105 #endif 3106 3107 STATIC int 3108 _phy84834_chip_current_temp_get(int unit,phy_ctrl_t *pc, uint16 *digital_temp, uint16 *analog_temp ) 3109 { 3110 uint16 args[3]; 3111 3112 SOC_IF_ERROR_RETURN 3113 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_CURRENT_TEMP_GENERIC, args, 2)); 3114 3115 if (digital_temp) { 3116 *digital_temp = args[0]; 3117 } 3118 if (analog_temp) { 3119 *analog_temp = args[1]; 3120 } 3121 3122 return (SOC_E_NONE); 3123 } 3124 3125 STATIC int 3126 _phy84834_xfi_reg_set(int unit,phy_ctrl_t *pc, uint16 bank, uint16 offset, uint16 value ) 3127 { 3128 uint16 args[5]; 3129 uint16 cmd; 3130 args[0] = bank; 3131 args[1] = offset; 3132 args[2] = value; 3133 3134 if (pc->flags & PHYCTRL_SYS_SIDE_CTRL) 3135 cmd = (uint16)PHY84834_DIAG_CMD_SET_XFI_M_REG_VALUES_GENERIC; 3136 else 3137 cmd = (uint16)PHY84834_DIAG_CMD_SET_XFI_L_REG_VALUES_GENERIC; 3138 3139 SOC_IF_ERROR_RETURN 3140 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)cmd, args, 3)); 3141 3142 return (SOC_E_NONE); 3143 } 3144 3145 STATIC int 3146 _phy84834_xfi_reg_get(int unit,phy_ctrl_t *pc, uint16 bank, uint16 offset, uint16 *value ) 3147 { 3148 uint16 args[5]; 3149 uint16 cmd; 3150 args[0] = bank; 3151 args[1] = offset; 3152 3153 if (pc->flags & PHYCTRL_SYS_SIDE_CTRL) 3154 cmd = (uint16)PHY84834_DIAG_CMD_GET_XFI_M_REG_VALUES_GENERIC; 3155 else 3156 cmd = (uint16)PHY84834_DIAG_CMD_GET_XFI_L_REG_VALUES_GENERIC; 3157 3158 SOC_IF_ERROR_RETURN 3159 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, args[0])); 3160 SOC_IF_ERROR_RETURN 3161 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, args[1])); 3162 3163 SOC_IF_ERROR_RETURN 3164 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)cmd, args, 3)); 3165 3166 if (value) { 3167 *value = args[2]; 3168 } 3169 3170 return (SOC_E_NONE); 3171 } 3172 3173 3174 STATIC int 3175 _phy84834_xfi_reg_set_v2(int unit, phy_ctrl_t *pc, uint16 pre_tap, uint16 main_tap, uint16 post1_tap, uint16 post2_tap, uint16 HPF_en) 3176 { 3177 uint16 args[5]; 3178 3179 args[0] = pre_tap; 3180 args[1] = main_tap; 3181 args[2] = post1_tap; 3182 args[3] = post2_tap; 3183 args[4] = HPF_en; 3184 3185 /* Koi BCM8485X only supports system side preemphasis */ 3186 if ( pc->flags & PHYCTRL_SYS_SIDE_CTRL ) { 3187 return PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 3188 (uint16) PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS_GENERIC, args, 5); 3189 } 3190 return (SOC_E_UNAVAIL); 3191 } 3192 3193 STATIC int 3194 _phy84834_xfi_reg_get_v2(int unit, phy_ctrl_t *pc, uint16 *pre_tap, uint16 *main_tap, uint16 *post1_tap, uint16 *post2_tap, uint16 *HPF_en ) 3195 { 3196 uint16 args[5]; 3197 uint16 cmd = 0; 3198 3199 /* Koi BCM8485X only supports system side preemphasis */ 3200 if (pc->flags & PHYCTRL_SYS_SIDE_CTRL) 3201 cmd = (uint16)PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC; 3202 3203 SOC_IF_ERROR_RETURN 3204 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)cmd, args, 5)); 3205 3206 if (pre_tap) { 3207 *pre_tap = args[0]; 3208 } 3209 if (main_tap) { 3210 *main_tap = args[1]; 3211 } 3212 if (post1_tap) { 3213 *post1_tap = args[2]; 3214 } 3215 if (post2_tap) { 3216 *post2_tap = args[3]; 3217 } 3218 if (HPF_en) { 3219 *HPF_en = args[4]; 3220 } 3221 3222 return (SOC_E_NONE); 3223 } 3224 3225 3226 STATIC uint16 3227 _sign_extend_16(uint16 val, uint8 ori_sz_in_bit) 3228 { 3229 uint16 neg_max = 0x1 << (ori_sz_in_bit - 1); 3230 uint16 mask = (0x1 << ori_sz_in_bit) - 1; 3231 /* 3232 * example of ori_sz_in_bit = 5 3233 * neg_max = 0x0010 = 0x1 << (5 - 1) 3234 * mask = 0x001f = (0x1 << 5) - 1 3235 * ~mask = 0xffe0 = ~0x001f [extension prefix for negative num] 3236 */ 3237 val &= mask; 3238 if ( val & neg_max ) { /* if a negative number */ 3239 val |= (~mask); /* sign extension for 16-bit number */ 3240 } 3241 3242 return val; 3243 } 3244 3245 #define BITMASK_7_0 (0xFF) 3246 #define XFIM 0 3247 #define XFIL 1 3248 3249 STATIC int 3250 _phy8488x_xfi_tx_filter_set(int unit, phy_ctrl_t *pc, uint16 pre_tap, uint16 main_tap, 3251 uint16 post1_tap, uint16 post2_tap, uint16 post3_tap) 3252 { 3253 uint16 args[5]; 3254 3255 /* 8488x supports XFI Config Type = 0 (XFIM) only */ 3256 args[0] = 0; /* (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? XFIM : XFIL; */ 3257 /* get the current values of XFI_TX_FILTERS first */ 3258 PHY84834_TOP_LEVEL_CMD_GET(unit, pc, 3259 (uint16) PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC, args, 5); 3260 args[0] = 0; 3261 args[1] = (main_tap << 8) | (pre_tap & BITMASK_7_0); 3262 args[2] = (post2_tap << 8) | (post1_tap & BITMASK_7_0); 3263 args[3] &= ~BITMASK_7_0; /* retain the bit[15:8] of DATA4 */ 3264 args[3] |= post3_tap & BITMASK_7_0; 3265 args[4] = 0; /* amp_ctrl & driver_mode are always 0 for 8488x */ 3266 3267 return PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 3268 (uint16) PHY84834_DIAG_CMD_SET_XFI_TX_FILTERS_GENERIC, args, 5); 3269 } 3270 3271 STATIC int 3272 _phy8488x_xfi_tx_filter_get(int unit, phy_ctrl_t *pc, uint16 *pre_tap, uint16 *main_tap, 3273 uint16 *post1_tap, uint16 *post2_tap, uint16 *post3_tap) 3274 { 3275 uint16 args[5]; 3276 3277 /* 8488x supports XFI Config Type = 0 (XFIM) only */ 3278 args[0] = 0; /* (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? XFIM : XFIL; */ 3279 SOC_IF_ERROR_RETURN( 3280 PHY84834_TOP_LEVEL_CMD_GET(unit, pc, 3281 (uint16) PHY84834_DIAG_CMD_GET_XFI_TX_FILTERS_GENERIC, args, 5) ); 3282 if ( pre_tap ) { 3283 *pre_tap = args[1] & BITMASK_7_0; 3284 } 3285 if ( main_tap ) { 3286 *main_tap = args[1] >> 8; 3287 } 3288 if ( post1_tap ) { 3289 *post1_tap = args[2] & BITMASK_7_0; 3290 } 3291 if ( post2_tap ) { /* -15 <= Post2 <= 15 */ 3292 *post2_tap = _sign_extend_16((args[2] >> 8), 8); 3293 } 3294 if ( post3_tap ) { /* -7 <= Post2 <= 7 */ 3295 *post3_tap = _sign_extend_16((args[3] & BITMASK_7_0), 8); 3296 } 3297 3298 return (SOC_E_NONE); 3299 } 3300 3301 STATIC int 3302 _phy8485x_shadow_reg_write(int unit, phy_ctrl_t *pc, uint16 reg_group, uint16 reg_addr, uint16 bit_mask, uint16 bit_shift, uint16 value) 3303 { 3304 uint16 args[5]; 3305 uint16 cmd; 3306 args[0] = reg_group; 3307 args[1] = reg_addr; 3308 args[2] = bit_mask; 3309 args[3] = bit_shift; 3310 args[4] = value; 3311 3312 cmd = (uint16)PHY8485X_DIAG_CMD_WRITE_SHADOW_REG; 3313 3314 SOC_IF_ERROR_RETURN 3315 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)cmd, args, 5)); 3316 3317 return (SOC_E_NONE); 3318 } 3319 3320 STATIC int 3321 _phy8485x_shadow_reg_read(int unit, phy_ctrl_t *pc, uint16 reg_group, uint16 reg_addr, uint16 bit_mask, uint16 bit_shift, uint16 *value) 3322 { 3323 uint16 args[5]; 3324 uint16 cmd; 3325 args[0] = reg_group; 3326 args[1] = reg_addr; 3327 args[2] = bit_mask; 3328 args[3] = bit_shift; 3329 3330 cmd = (uint16)PHY8485X_DIAG_CMD_READ_SHADOW_REG; 3331 3332 SOC_IF_ERROR_RETURN 3333 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, args[0])); 3334 SOC_IF_ERROR_RETURN 3335 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, args[1])); 3336 SOC_IF_ERROR_RETURN 3337 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, args[2])); 3338 SOC_IF_ERROR_RETURN 3339 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, args[3])); 3340 3341 SOC_IF_ERROR_RETURN 3342 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)cmd, args, 5)); 3343 3344 if (value) { 3345 *value = args[4]; 3346 } 3347 3348 return (SOC_E_NONE); 3349 } 3350 3351 STATIC int 3352 _phy8481_adjust_xfi_tx_preemphasis(int unit, int port, phy_ctrl_t *pc, uint32 phy_long_xfi) 3353 { 3354 uint16 pre_tap = 0; 3355 uint16 main_tap = 0; 3356 uint16 post_tap1 = 0; 3357 uint16 post_tap2 = 0; 3358 uint16 HPF_en = 0; 3359 3360 switch(phy_long_xfi) { 3361 3362 case 1: 3363 if (PHY_IS_BCM8485X_AND_UP(pc)) { 3364 3365 /* The value format: 3366 * bit 16:18: post_tap2 value 3367 * bit 15: 1 enable forced preemphasis ctrl, 0 auto config 3368 * bit 14:10: post_tap value 3369 * bit 09:04: main tap value 3370 * bit 03:00: pre_tap value 3371 */ 3372 3373 /* main_tap = 32d, post_tap = 12d, pre_tap=8d for long channel on KOI */ 3374 pre_tap = 0x8; 3375 main_tap = 0x20; 3376 post_tap1 = 0xC; 3377 post_tap2 = 0x0; 3378 HPF_en = 0x0; 3379 3380 SOC_IF_ERROR_RETURN( 3381 _phy84834_xfi_reg_set_v2(unit, pc, pre_tap, main_tap, post_tap1, post_tap2, HPF_en)); 3382 3383 } else { 3384 /* Register bank = 0x2 offset = 0xC value = 0x3AF7 */ 3385 SOC_IF_ERROR_RETURN( 3386 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xC, 0x3AF7)); 3387 3388 } 3389 break; 3390 3391 default: 3392 break; 3393 } 3394 3395 return SOC_E_NONE; 3396 } 3397 3398 /* 3399 * Function: 3400 * _phy_8481_control_tx_driver_set 3401 * Purpose: 3402 * Configure PHY device specific control function. 3403 * Parameters: 3404 * unit - StrataSwitch unit #. 3405 * port - StrataSwitch port #. 3406 * type - Control to update 3407 * value - New setting for the control 3408 * Returns: 3409 * SOC_E_NONE 3410 */ 3411 STATIC int 3412 _phy_8481_control_tx_driver_set(int unit, soc_port_t port, 3413 soc_phy_control_t type, uint32 value) 3414 { 3415 int rv; 3416 phy_ctrl_t *pc; /* PHY software state */ 3417 uint16 data; /* Temporary holder of reg value to be written */ 3418 uint16 tmp ; /* Temporary holder of reg value read */ 3419 uint16 mask; /* Bit mask of reg value to be updated */ 3420 uint16 HPF_en = 0; 3421 uint16 pre_tap = 0; 3422 uint16 main_tap = 0; 3423 uint16 post1_tap = 0; 3424 uint16 post2_tap = 0; 3425 uint16 post3_tap = 0; 3426 3427 pc = EXT_PHY_SW_STATE(unit, port); 3428 3429 #if 0 3430 /* Support only system side in copper mode - for now */ 3431 if (PHY_COPPER_MODE(unit, port) && !(pc->flags & PHYCTRL_SYS_SIDE_CTRL)) { 3432 return SOC_E_UNAVAIL; 3433 } 3434 #endif 3435 3436 rv = SOC_E_NONE; 3437 switch ( type ) { 3438 case SOC_PHY_CONTROL_PREEMPHASIS: 3439 if ( PHY_IS_BCM8488X(pc) ) { 3440 /* format of 'value': Decimal Hexadecimal 3441 * bit 27:24 post3 [-7,7] [0x9 ,0x7] 3442 * bit 22:18 post2 [-15,15] [0x11,0x0f] 3443 * bit 17:12 post1 [0,63] [0x00,0x3f] 3444 * bit 11:05 main tap [0,112] [0x00,0x70] 3445 * bit 04:00 pre_tap [0,31] [0x00,0x1f] 3446 * criterion A: ( main + 48 > pre + post1 + post2 + post3 ) 3447 * criterion B: ( main + pre + post1 + |post2| + |post3| <= 112 ) 3448 */ 3449 pre_tap = PHY8488X_PREEMPH_GET_PRE_TAP(value); 3450 main_tap = PHY8488X_PREEMPH_GET_MAIN_TAP(value); 3451 post1_tap = PHY8488X_PREEMPH_GET_POST1_TAP(value); 3452 post2_tap = _sign_extend_16(PHY8488X_PREEMPH_GET_POST2_TAP(value), 5); 3453 post3_tap = _sign_extend_16(PHY8488X_PREEMPH_GET_POST3_TAP(value), 4); 3454 3455 /* Set Data 1 - Data 5 values */ 3456 SOC_IF_ERROR_RETURN( 3457 _phy8488x_xfi_tx_filter_set(unit, pc, pre_tap, main_tap, 3458 post1_tap, post2_tap, post3_tap)); 3459 3460 } else 3461 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 3462 /* The value format: 3463 * bit 18:16: post_tap2 value 3464 * bit 15: 1 enable forced preemphasis ctrl, 0 auto config 3465 * bit 14:10: post_tap value 3466 * bit 09:04: main tap value 3467 * bit 03:00: pre_tap value 3468 */ 3469 pre_tap = PHY8485X_PREEMPH_GET_PRE_TAP(value); 3470 main_tap = PHY8485X_PREEMPH_GET_MAIN_TAP(value); 3471 post1_tap = PHY8485X_PREEMPH_GET_POST_TAP1(value); 3472 post2_tap = PHY8485X_PREEMPH_GET_POST_TAP2(value); 3473 HPF_en = PHY8485X_PREEMPH_GET_HPF_EN(value); 3474 /* Set Data 1 - Data 5 values */ 3475 SOC_IF_ERROR_RETURN( 3476 _phy84834_xfi_reg_set_v2(unit, pc, pre_tap, main_tap, post1_tap, post2_tap, HPF_en)); 3477 } 3478 else { 3479 mask = 0xf800; /* Main Tap */ 3480 /* Register bank = 0x2 offset = 0xB value */ 3481 SOC_IF_ERROR_RETURN( 3482 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xB, (value & mask))); 3483 mask = 0x00f7; /* Pre/Post Cursor */ 3484 /* Register bank = 0x2 offset = 0xC value */ 3485 SOC_IF_ERROR_RETURN( 3486 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xC, (value & mask))); 3487 } 3488 break; 3489 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3490 if (PHY_IS_BCM8485X_AND_UP(pc)) { 3491 /* register bit fields idriver no longer exist in Merlin Core */ 3492 rv = SOC_E_UNAVAIL; 3493 } 3494 else { 3495 data = (uint16)(value & 0xf); 3496 data = data << 12; 3497 mask = 0xf000; 3498 data = data & mask; /* Mask off other bits */ 3499 /* Register bank = 0x2 offset = 0xA value */ 3500 SOC_IF_ERROR_RETURN( 3501 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &tmp)); 3502 3503 tmp &= ~(mask); 3504 tmp |= data; 3505 3506 /* Register bank = 0x2 offset = 0xA value */ 3507 SOC_IF_ERROR_RETURN( 3508 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xA, tmp)); 3509 } 3510 break; 3511 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3512 if (PHY_IS_BCM8485X_AND_UP(pc)) { 3513 /* register bit fields ipredriver no longer exist in Merlin Core */ 3514 rv = SOC_E_UNAVAIL; 3515 } 3516 else { 3517 data = (uint16)(value & 0xf); 3518 data = data << 8; 3519 mask = 0x0f00; 3520 data = data & mask; /* Mask off other bits */ 3521 /* Register bank = 0x2 offset = 0xA value */ 3522 SOC_IF_ERROR_RETURN( 3523 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &tmp)); 3524 3525 tmp &= ~(mask); 3526 tmp |= data; 3527 3528 /* Register bank = 0x2 offset = 0xA value */ 3529 SOC_IF_ERROR_RETURN( 3530 _phy84834_xfi_reg_set(unit, pc, 0x2, 0xA, tmp)); 3531 } 3532 break; 3533 default: 3534 rv = SOC_E_PARAM; 3535 break; 3536 } 3537 return rv; 3538 } 3539 3540 /* 3541 * Function: 3542 * _phy_8481_control_tx_driver_get 3543 * Purpose: 3544 * Configure PHY device specific control function. 3545 * Parameters: 3546 * unit - StrataSwitch unit #. 3547 * port - StrataSwitch port #. 3548 * type - Control to update 3549 * value - New setting for the control 3550 * Returns: 3551 * SOC_E_NONE 3552 */ 3553 STATIC int 3554 _phy_8481_control_tx_driver_get(int unit, soc_port_t port, 3555 soc_phy_control_t type, uint32 *value) 3556 { 3557 int rv; 3558 phy_ctrl_t *pc; /* PHY software state */ 3559 uint16 data; 3560 uint32 temp = 0; 3561 uint16 HPF_en = 0; 3562 uint16 pre_tap = 0; 3563 uint16 main_tap = 0; 3564 uint16 post1_tap = 0; 3565 uint16 post2_tap = 0; 3566 uint16 post3_tap = 0; 3567 3568 pc = EXT_PHY_SW_STATE(unit, port); 3569 #if 0 3570 /* Support only system side in copper mode - for now */ 3571 if (PHY_COPPER_MODE(unit, port) && !(pc->flags & PHYCTRL_SYS_SIDE_CTRL)) { 3572 return SOC_E_UNAVAIL; 3573 } 3574 #endif 3575 rv = SOC_E_NONE; 3576 switch(type) { 3577 case SOC_PHY_CONTROL_PREEMPHASIS: 3578 if ( PHY_IS_BCM8488X(pc) ) { 3579 /* format of 'value': Decimal Hexadecimal 3580 * bit 27:24 post3 [-7,7] [0x9 ,0x7] 3581 * bit 22:18 post2 [-15,15] [0x11,0x0f] 3582 * bit 17:12 post1 [0,63] [0x00,0x3f] 3583 * bit 11:05 main tap [0,112] [0x00,0x70] 3584 * bit 04:00 pre_tap [0,31] [0x00,0x1f] 3585 */ 3586 SOC_IF_ERROR_RETURN( 3587 _phy8488x_xfi_tx_filter_get(unit, pc, &pre_tap, &main_tap, 3588 &post1_tap, &post2_tap, &post3_tap)); 3589 *value = PHY8488X_PREEMPH_SET_PRE_TAP(pre_tap) 3590 | PHY8488X_PREEMPH_SET_MAIN_TAP(main_tap) 3591 | PHY8488X_PREEMPH_SET_POST1_TAP(post1_tap) 3592 | PHY8488X_PREEMPH_SET_POST2_TAP(post2_tap) 3593 | PHY8488X_PREEMPH_SET_POST3_TAP(post3_tap); 3594 3595 } else 3596 if (PHY_IS_BCM8485X_AND_UP(pc)) { 3597 SOC_IF_ERROR_RETURN( 3598 _phy84834_xfi_reg_get_v2(unit, pc, &pre_tap, &main_tap, &post1_tap, &post2_tap, &HPF_en)); 3599 3600 *value = 0; 3601 *value |= pre_tap; 3602 main_tap = ((temp | main_tap) << 4); 3603 post1_tap = ((temp | post1_tap) << 10); 3604 HPF_en = ((temp | HPF_en) << 15); 3605 post2_tap = ((temp | post2_tap) << 16); 3606 3607 *value |= (main_tap | post1_tap | HPF_en | post2_tap); 3608 } 3609 else { 3610 /* Register bank = 0x2 offset = 0xB value */ 3611 SOC_IF_ERROR_RETURN( 3612 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xB, &data)); 3613 *value = data & 0xf800; /* Main */ 3614 /* Register bank = 0x2 offset = 0xC value */ 3615 SOC_IF_ERROR_RETURN( 3616 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xC, &data)); 3617 *value |= (data & 0x00f7); /* Post and Pre cursor */ 3618 } 3619 break; 3620 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3621 if (PHY_IS_BCM8485X_AND_UP(pc)) { 3622 /* register bit fields idriver no longer exist in Merlin Core */ 3623 rv = SOC_E_UNAVAIL; 3624 } 3625 else { 3626 /* Register bank = 0x2 offset = 0xA value */ 3627 SOC_IF_ERROR_RETURN( 3628 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &data)); 3629 *value = ((data & 0xf000) >> 12); 3630 } 3631 break; 3632 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3633 if (PHY_IS_BCM8485X_AND_UP(pc)) { 3634 /* register bit fields ipredriver no longer exist in Merlin Core */ 3635 rv = SOC_E_UNAVAIL; 3636 } 3637 else { 3638 /* Register bank = 0x2 offset = 0xA value */ 3639 SOC_IF_ERROR_RETURN( 3640 _phy84834_xfi_reg_get(unit, pc, 0x2, 0xA, &data)); 3641 *value = ((data & 0x0f00) >> 8); 3642 } 3643 break; 3644 default: 3645 rv = SOC_E_PARAM; 3646 break; 3647 } 3648 return rv; 3649 } 3650 3651 STATIC int 3652 _phy_8485x_force_cl72_config(int unit, phy_ctrl_t *pc, uint16 enable) 3653 { 3654 uint16 args[5]={0,}; 3655 3656 args[0] = enable; 3657 SOC_IF_ERROR_RETURN 3658 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_KR_MODE_ENABLE_V2, args, 1)); 3659 3660 return (SOC_E_NONE); 3661 } 3662 3663 int 3664 _phy_8481_copper_control_driver_set(int unit, soc_port_t port, 3665 soc_phy_control_t type, uint32 value) 3666 { 3667 phy_ctrl_t *pc; /* PHY software state */ 3668 uint16 temp; 3669 int rv = SOC_E_NONE; 3670 uint16 mode; 3671 int intf; 3672 3673 pc = EXT_PHY_SW_STATE(unit, port); 3674 3675 switch(type) { 3676 case SOC_PHY_CONTROL_PREEMPHASIS: 3677 /* fall through */ 3678 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3679 /* fall through */ 3680 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3681 rv = _phy_8481_control_tx_driver_set(unit, port, type, value); 3682 break; 3683 case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL: 3684 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 3685 SOC_IF_ERROR_RETURN 3686 (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, value ? 1U<<15 : 0, 1U<<15)); 3687 break; 3688 case SOC_PHY_CONTROL_EEE: 3689 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3690 return SOC_E_UNAVAIL; 3691 } 3692 3693 if (value) { 3694 /* Clearing 10G/1G EEE stats */ 3695 SOC_IF_ERROR_RETURN( _phy_8481_clear_eee_stats(unit, pc) ); 3696 3697 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3698 /* 1G IEEE EEE, 10G IEEE EEE */ 3699 if (PHY_IS_BCM8484X_AND_UP(pc)) { 3700 mode = 5; 3701 } else { 3702 mode = 1; 3703 } 3704 SOC_IF_ERROR_RETURN 3705 (_phy84834_eee_mode_set(unit, pc, mode, 0x0000, 0x0000, 0x0000 )); 3706 } else { 3707 /* Disable AUTO EEE if native is enabled */ 3708 SOC_IF_ERROR_RETURN 3709 (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0, 0x1)); 3710 } 3711 SOC_IF_ERROR_RETURN 3712 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x000e, 0x000e)); 3713 3714 pc->copper.advert_ability.eee |= (SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 3715 temp = pc->copper.autoneg_enable; 3716 /* Initiate AN */ 3717 SOC_IF_ERROR_RETURN 3718 (_phy_8481_copper_an_set(unit, port, 1)); 3719 pc->copper.autoneg_enable = temp; 3720 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3721 SOC_IF_ERROR_RETURN 3722 (_phy84834_eee_mode_get(unit, pc, &temp, NULL, NULL, NULL)); 3723 } 3724 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 3725 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE); 3726 } else { 3727 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3728 SOC_IF_ERROR_RETURN 3729 (_phy84834_eee_mode_set(unit, pc, 0, 0x0000, 0x0000, 0x0000 )); 3730 } 3731 SOC_IF_ERROR_RETURN 3732 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x0000, 0x000e)); 3733 pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 3734 SOC_IF_ERROR_RETURN 3735 (_phy_8481_copper_an_set(unit, port, pc->copper.autoneg_enable ? 1 : 0)); 3736 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 3737 } 3738 break; 3739 3740 case SOC_PHY_CONTROL_EEE_AUTO: 3741 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3742 return SOC_E_UNAVAIL; 3743 } 3744 3745 if (value) { 3746 /* Clearing 10G/1G EEE stats */ 3747 SOC_IF_ERROR_RETURN( _phy_8481_clear_eee_stats(unit, pc) ); 3748 3749 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3750 /* 1G IEEE EEE, 10G IEEE EEE */ 3751 if (PHY_IS_BCM8484X_AND_UP(pc)) { 3752 mode = 0xa; 3753 } else { 3754 mode = 2; 3755 } 3756 SOC_IF_ERROR_RETURN 3757 (_phy84834_eee_mode_set(unit, pc, mode, 0x0000, 0x3d09, ((PHY_IS_BCM8488X(pc)) ? 0x0480 : 0x047e) )); 3758 3759 } else { 3760 SOC_IF_ERROR_RETURN 3761 (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0x0001, 0x0001)); 3762 } 3763 SOC_IF_ERROR_RETURN 3764 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x000e, 0x000e)); 3765 3766 pc->copper.advert_ability.eee |= (SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 3767 temp = pc->copper.autoneg_enable; 3768 /* Initiate AN */ 3769 SOC_IF_ERROR_RETURN 3770 (_phy_8481_copper_an_set(unit, port, 1)); 3771 pc->copper.autoneg_enable = temp; 3772 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3773 SOC_IF_ERROR_RETURN 3774 (_phy84834_eee_mode_get(unit, pc, &temp, NULL, NULL, NULL)); 3775 } 3776 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 3777 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_MODE); 3778 } else { 3779 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3780 SOC_IF_ERROR_RETURN 3781 (_phy84834_eee_mode_set(unit, pc, 0, 0x0000, 0x0000, 0x0000 )); 3782 } else { 3783 SOC_IF_ERROR_RETURN 3784 (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, 0x0000, 0x0001)); 3785 } 3786 SOC_IF_ERROR_RETURN 3787 (MODIFY_PHY8481_EEE_ADVr(unit, pc, 0x0000, 0x000e)); 3788 SOC_IF_ERROR_RETURN 3789 (WRITE_PHY8481_PHYC_CTL_AI_LPI_CTLr(unit, pc, 0x8000)); 3790 SOC_IF_ERROR_RETURN 3791 (WRITE_PHY8481_PHYC_CTL_AI_LPI_CTLr(unit, pc, 0x0000)); 3792 pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 3793 SOC_IF_ERROR_RETURN 3794 (_phy_8481_copper_an_set(unit, port, pc->copper.autoneg_enable ? 1 : 0)); 3795 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_ENABLED); 3796 } 3797 break; 3798 3799 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 3800 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3801 return SOC_E_UNAVAIL; 3802 } 3803 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3804 uint16 mode=0, latency=0, th_high=0, th_low=0; 3805 SOC_IF_ERROR_RETURN 3806 (_phy84834_eee_mode_get(unit, pc, &mode, &th_high, &th_low, &latency )); 3807 /* Fixed latency can have only 0 or 1 value */ 3808 if ((value != FALSE) && (value != TRUE)) { 3809 return SOC_E_PARAM; 3810 } 3811 if (value == FALSE) { 3812 /* Variable latency */ 3813 SOC_IF_ERROR_RETURN 3814 (_phy84834_eee_mode_set(unit, pc, 3, th_high, th_low, latency )); 3815 } else { 3816 /* Fixed latency */ 3817 SOC_IF_ERROR_RETURN 3818 (_phy84834_eee_mode_set(unit, pc, 2, th_high, th_low, latency )); 3819 } 3820 } else { 3821 SOC_IF_ERROR_RETURN 3822 (MODIFY_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, value ? 1U<<1 : 0, 1U<<1)); 3823 } 3824 break; 3825 3826 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 3827 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3828 return SOC_E_UNAVAIL; 3829 } 3830 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3831 uint16 mode=0, buffer_len=0; 3832 SOC_IF_ERROR_RETURN 3833 (_phy84834_eee_mode_get(unit, pc, &mode, NULL, NULL, &buffer_len )); 3834 SOC_IF_ERROR_RETURN 3835 (_phy84834_eee_mode_set(unit, pc, mode, (uint16)((value >> 16) & 0xffff), (uint16)(value & 0xffff), buffer_len )); 3836 } else { 3837 SOC_IF_ERROR_RETURN 3838 (WRITE_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_LOWr(unit, pc, (uint16)(value & 0xffff))); 3839 SOC_IF_ERROR_RETURN 3840 (WRITE_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_HIGHr(unit, pc, (uint16)((value >> 16) & 0xffff))); 3841 } 3842 3843 break; 3844 case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR: 3845 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3846 return SOC_E_UNAVAIL; 3847 } 3848 3849 /* Clearing 10G EEE stats: Enable clear on Read */ 3850 SOC_IF_ERROR_RETURN 3851 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0003, 0x000f)); 3852 SOC_IF_ERROR_RETURN 3853 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000f, 0x000f)); 3854 SOC_IF_ERROR_RETURN 3855 (READ_PHY8481_EXP_EEE_TX_EVENTS_HIGHr(unit, pc, &temp)); 3856 SOC_IF_ERROR_RETURN 3857 (READ_PHY8481_EXP_EEE_TX_EVENTS_LOWr(unit, pc, &temp)); 3858 /* Clearing 10G EEE stats: Disable clear on Read */ 3859 SOC_IF_ERROR_RETURN 3860 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x0002, 0x000f)); 3861 3862 /* Clearing 1G EEE stats */ 3863 SOC_IF_ERROR_RETURN 3864 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8002, 0x8002)); 3865 SOC_IF_ERROR_RETURN 3866 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8000, 0x8002)); 3867 break; 3868 3869 case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT: 3870 case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME: 3871 case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME: 3872 case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME: 3873 case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME: 3874 case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME: 3875 case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME: 3876 case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME: 3877 return SOC_E_UNAVAIL; 3878 3879 case SOC_PHY_CONTROL_POWER: 3880 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3881 SOC_IF_ERROR_RETURN 3882 (_phy_84834_power_mode_set(unit,port,value)); 3883 } 3884 break; 3885 3886 case SOC_PHY_CONTROL_CL72: 3887 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 3888 rv = _phy_8485x_force_cl72_config(unit, pc, value); 3889 break; 3890 } else { 3891 return SOC_E_UNAVAIL; 3892 } 3893 3894 case SOC_PHY_CONTROL_MGBASET_802P3BZ_PRIORITY: 3895 if ( PHY_IS_BCM8488X(pc) ) { 3896 rv = _phy_848xx_mgbase_802_3bz_type_set(unit, pc, value, value); 3897 break; 3898 } else { 3899 return SOC_E_UNAVAIL; 3900 } 3901 3902 case SOC_PHY_CONTROL_SUPER_ISOLATE : 3903 rv = MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, 3904 (value) ? TOP_CONFIG_XGPHY_DISABLE : 0x0, 3905 TOP_CONFIG_XGPHY_DISABLE); 3906 break; 3907 3908 default: 3909 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 3910 SOC_IF_ERROR_RETURN 3911 (_phy_84834_control_set(unit, port, intf, PHY_DIAG_LN_DFLT, type, value)); 3912 break; 3913 } 3914 3915 return rv; 3916 } 3917 3918 3919 STATIC int 3920 _phy_8485x_force_cl72_status(int unit, phy_ctrl_t *pc, uint16 *value) 3921 { 3922 uint16 args[5] = {0,}; 3923 3924 args[0] = 0; 3925 SOC_IF_ERROR_RETURN 3926 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_KR_MODE_ENABLE_V2, args, 1)); 3927 *value = args[0]; 3928 3929 return SOC_E_NONE; 3930 } 3931 3932 int 3933 _phy_8481_copper_control_driver_get(int unit, soc_port_t port, 3934 soc_phy_control_t type, uint32 *value) 3935 { 3936 phy_ctrl_t *pc; /* PHY software state */ 3937 uint16 temp, temp1; 3938 uint16 digital_temp = 0, analog_temp = 0, frame_priority = 0; 3939 int rv = SOC_E_NONE; 3940 int speed=0; 3941 int intf; 3942 3943 pc = EXT_PHY_SW_STATE(unit, port); 3944 3945 switch(type) { 3946 case SOC_PHY_CONTROL_PREEMPHASIS: 3947 /* fall through */ 3948 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3949 /* fall through */ 3950 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3951 rv = _phy_8481_control_tx_driver_get(unit, port, type, value); 3952 break; 3953 case SOC_PHY_CONTROL_LOOPBACK_EXTERNAL: 3954 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 3955 SOC_IF_ERROR_RETURN 3956 (READ_PHY8481_MII_AUX_CTRLr(unit, pc, &temp)); 3957 *value = temp & (1U<<15) ? 1 : 0; 3958 break; 3959 3960 case SOC_PHY_CONTROL_EEE: 3961 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3962 return SOC_E_UNAVAIL; 3963 } 3964 *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 3965 !PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0; 3966 break; 3967 3968 case SOC_PHY_CONTROL_EEE_AUTO: 3969 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3970 return SOC_E_UNAVAIL; 3971 } 3972 *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 3973 PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0; 3974 break; 3975 3976 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 3977 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3978 return SOC_E_UNAVAIL; 3979 } 3980 if (PHY_IS_BCM8483X_AND_UP(pc)) { 3981 uint16 mode=0, latency=0; 3982 SOC_IF_ERROR_RETURN 3983 (_phy84834_eee_mode_get(unit, pc, &mode, NULL, NULL, &latency )); 3984 if (mode == 2 || mode == 6 || mode == 0xa) { 3985 *value = 1; 3986 } 3987 else if (mode == 3 || mode == 7 || mode == 0xb) { 3988 *value = 0; 3989 } 3990 } else { 3991 SOC_IF_ERROR_RETURN 3992 (READ_PHY8481_TOP_CONFIG_AUTOGREEN_CONFIG1r(unit, pc, &temp)); 3993 *value = (temp>>1) & 0x1; 3994 } 3995 break; 3996 3997 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 3998 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 3999 return SOC_E_UNAVAIL; 4000 } 4001 if (PHY_IS_BCM8483X_AND_UP(pc)) { 4002 SOC_IF_ERROR_RETURN 4003 (_phy84834_eee_mode_get(unit, pc, NULL, &temp1, &temp, NULL)); 4004 } else { 4005 SOC_IF_ERROR_RETURN 4006 (READ_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_LOWr(unit, pc, &temp)); 4007 SOC_IF_ERROR_RETURN 4008 (READ_PHY8481_TOP_CONFIG_AUTOGREEN_THRESHOLD_HIGHr(unit, pc, &temp1)); 4009 } 4010 *value = (((uint32) temp1) << 16) | temp; 4011 break; 4012 4013 case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS: 4014 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 4015 return SOC_E_UNAVAIL; 4016 } 4017 4018 SOC_IF_ERROR_RETURN 4019 (phy_8481_speed_get(unit, port, &speed)); 4020 4021 if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) { 4022 if (speed == 10000) { 4023 /* Latch the stats: Write 1 to bit 2 and 3 */ 4024 SOC_IF_ERROR_RETURN 4025 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c)); 4026 } 4027 else 4028 if (speed == 1000) { 4029 SOC_IF_ERROR_RETURN 4030 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001)); 4031 } 4032 } 4033 4034 /* Speed 1G */ 4035 if (speed == 1000 ) { 4036 SOC_IF_ERROR_RETURN 4037 (READ_PHY8481_EXP_1G_TX_EVENT(unit, pc,(uint16 *) value)); 4038 } 4039 /* Speed 10G */ 4040 else 4041 if (speed == 10000 ) { 4042 SOC_IF_ERROR_RETURN 4043 (READ_PHY8481_EXP_EEE_TX_EVENTS_LOWr(unit, pc, &temp)); 4044 SOC_IF_ERROR_RETURN 4045 (READ_PHY8481_EXP_EEE_TX_EVENTS_HIGHr(unit, pc, &temp1)); 4046 *value = (((uint32) temp1) << 16) | temp; 4047 } 4048 break; 4049 4050 case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION: 4051 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 4052 return SOC_E_UNAVAIL; 4053 } 4054 4055 SOC_IF_ERROR_RETURN 4056 (phy_8481_speed_get(unit, port, &speed)); 4057 4058 if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) { 4059 if (speed == 10000) { 4060 /* Latch the stats: Write 1 to bit 2 and 3 */ 4061 SOC_IF_ERROR_RETURN 4062 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c)); 4063 } 4064 else 4065 if (speed == 1000) { 4066 SOC_IF_ERROR_RETURN 4067 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001)); 4068 } 4069 } 4070 4071 /* Speed 1G */ 4072 if (speed == 1000 ) { 4073 SOC_IF_ERROR_RETURN 4074 (READ_PHY8481_EXP_1G_TX_DURATION(unit, pc,(uint16 *) value)); 4075 } 4076 /* Speed 10G */ 4077 else 4078 if (speed == 10000 ) { 4079 SOC_IF_ERROR_RETURN 4080 (READ_PHY8481_EXP_EEE_TX_DURATION_LOWr(unit, pc, &temp)); 4081 SOC_IF_ERROR_RETURN 4082 (READ_PHY8481_EXP_EEE_TX_DURATION_HIGHr(unit, pc, &temp1)); 4083 *value = (((uint32) temp1) << 16) | temp; 4084 } 4085 break; 4086 4087 case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS: 4088 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 4089 return SOC_E_UNAVAIL; 4090 } 4091 4092 SOC_IF_ERROR_RETURN 4093 (phy_8481_speed_get(unit, port, &speed)); 4094 4095 if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) { 4096 if (speed == 10000) { 4097 /* Latch the stats: Write 1 to bit 2 and 3 */ 4098 SOC_IF_ERROR_RETURN 4099 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c)); 4100 } 4101 else 4102 if (speed == 1000) { 4103 SOC_IF_ERROR_RETURN 4104 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001)); 4105 } 4106 } 4107 4108 /* Speed 1G */ 4109 if (speed == 1000 ) { 4110 SOC_IF_ERROR_RETURN 4111 (READ_PHY8481_EXP_1G_RX_EVENT(unit, pc,(uint16 *) value)); 4112 } 4113 /* Speed 10G */ 4114 else 4115 if (speed == 10000 ) { 4116 SOC_IF_ERROR_RETURN 4117 (READ_PHY8481_EXP_EEE_RX_EVENTS_LOWr(unit, pc, &temp)); 4118 SOC_IF_ERROR_RETURN 4119 (READ_PHY8481_EXP_EEE_RX_EVENTS_HIGHr(unit, pc, &temp1)); 4120 *value = (((uint32) temp1) << 16) | temp; 4121 } 4122 break; 4123 4124 case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION: 4125 if (!PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 4126 return SOC_E_UNAVAIL; 4127 } 4128 4129 SOC_IF_ERROR_RETURN 4130 (phy_8481_speed_get(unit, port, &speed)); 4131 4132 if (PHY_IS_BCM8484X(pc) || PHY_IS_BCM8485X_AND_UP(pc)) { 4133 if (speed == 10000) { 4134 /* Latch the stats: Write 1 to bit 2 and 3 */ 4135 SOC_IF_ERROR_RETURN 4136 (MODIFY_PHY8481_EEE_STATISTICS_CTLr(unit, pc,0x000c, 0x000c)); 4137 } 4138 else 4139 if (speed == 1000) { 4140 SOC_IF_ERROR_RETURN 4141 (MODIFY_PHY8481_1G_EEE_STATISTICS_CTLr(unit, pc, 0x8001, 0x4001)); 4142 } 4143 } 4144 4145 /* Speed 1G */ 4146 if (speed == 1000 ) { 4147 SOC_IF_ERROR_RETURN 4148 (READ_PHY8481_EXP_1G_RX_DURATION(unit, pc,(uint16 *) value)); 4149 } 4150 /* Speed 10G */ 4151 else 4152 if (speed == 10000 ) { 4153 SOC_IF_ERROR_RETURN 4154 (READ_PHY8481_EXP_EEE_RX_DURATION_LOWr(unit, pc, &temp)); 4155 SOC_IF_ERROR_RETURN 4156 (READ_PHY8481_EXP_EEE_RX_DURATION_HIGHr(unit, pc, &temp1)); 4157 *value = (((uint32) temp1) << 16) | temp; 4158 } 4159 break; 4160 4161 case SOC_PHY_CONTROL_POWER: 4162 if (PHY_IS_BCM8483X_AND_UP(pc)) { 4163 SOC_IF_ERROR_RETURN 4164 (_phy_84834_power_mode_get(unit,port,value)); 4165 } else { 4166 *value = pc->power_mode; 4167 } 4168 break; 4169 4170 case SOC_PHY_CONTROL_DIGITAL_TEMP: 4171 if (PHY_IS_BCM8483X_AND_UP(pc)) { 4172 SOC_IF_ERROR_RETURN 4173 (_phy84834_chip_current_temp_get(unit, pc, &digital_temp, NULL)); 4174 } 4175 *value = digital_temp; 4176 break; 4177 4178 case SOC_PHY_CONTROL_ANALOG_TEMP: 4179 if (PHY_IS_BCM8483X_AND_UP(pc)) { 4180 SOC_IF_ERROR_RETURN 4181 (_phy84834_chip_current_temp_get(unit, pc, NULL, &analog_temp)); 4182 } 4183 *value = analog_temp; 4184 /* Invalid analog temperature value is returned */ 4185 rv=SOC_E_UNAVAIL; 4186 break; 4187 4188 case SOC_PHY_CONTROL_MGBASET_802P3BZ_PRIORITY: 4189 if ( PHY_IS_BCM8488X(pc) ) { 4190 rv = _phy_848xx_mgbase_802_3bz_type_get(unit, pc, NULL, &frame_priority); 4191 *value = frame_priority; 4192 } else { 4193 rv=SOC_E_UNAVAIL; 4194 } 4195 break; 4196 4197 case SOC_PHY_CONTROL_SUPER_ISOLATE : 4198 SOC_IF_ERROR_RETURN( 4199 READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &temp) ); 4200 *value = (temp & TOP_CONFIG_XGPHY_DISABLE) ? TRUE : FALSE; 4201 break; 4202 4203 default: 4204 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY_DIAG_INTF_SYS : PHY_DIAG_INTF_LINE; 4205 SOC_IF_ERROR_RETURN 4206 (_phy_84834_control_get(unit, port, intf, PHY_DIAG_LN_DFLT, type, value)); 4207 break; 4208 } 4209 4210 return rv; 4211 } 4212 4213 int 4214 _phy_8481_xaui_control_driver_set(int unit, soc_port_t port, 4215 soc_phy_control_t type, uint32 value) 4216 { 4217 switch(type) { 4218 case SOC_PHY_CONTROL_PREEMPHASIS: 4219 /*Fall through*/ 4220 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4221 /*Fall through*/ 4222 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4223 _phy_8481_control_tx_driver_set(unit, port, type, value); 4224 break; 4225 4226 default: 4227 /* should never get here */ 4228 return SOC_E_UNAVAIL; 4229 } 4230 4231 4232 4233 return SOC_E_NONE; 4234 } 4235 4236 int 4237 _phy_8481_xaui_control_driver_get(int unit, soc_port_t port, 4238 soc_phy_control_t type, uint32 *value) 4239 { 4240 switch(type) { 4241 case SOC_PHY_CONTROL_PREEMPHASIS: 4242 /*Fall through*/ 4243 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4244 /*Fall through*/ 4245 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4246 _phy_8481_control_tx_driver_get(unit, port, type, value); 4247 break; 4248 4249 default: 4250 /* should never get here */ 4251 return SOC_E_UNAVAIL; 4252 } 4253 4254 return SOC_E_NONE; 4255 } 4256 4257 /* 4258 * Function: 4259 * phy_8481_control_set 4260 * Purpose: 4261 * Configure PHY device specific control fucntion. 4262 * Parameters: 4263 * unit - StrataSwitch unit #. 4264 * port - StrataSwitch port #. 4265 * type - Control to update 4266 * value - New setting for the control 4267 * Returns: 4268 * SOC_E_NONE 4269 */ 4270 STATIC int 4271 phy_8481_control_set(int unit, soc_port_t port, 4272 soc_phy_control_t type, uint32 value) 4273 { 4274 phy_ctrl_t *pc; /* PHY software state */ 4275 4276 pc = EXT_PHY_SW_STATE(unit, port); 4277 4278 if (PHY_COPPER_MODE(unit, port)) { 4279 return(_phy_8481_copper_control_driver_set(unit, port, type, value)); 4280 } else { 4281 if (NXT_PC(pc)) { 4282 PHYDRV_CALL_ARG2(pc,PHY_CONTROL_SET,type,value); 4283 return SOC_E_NONE; 4284 } 4285 return(_phy_8481_xaui_control_driver_set(unit, port, type, value)); 4286 } 4287 4288 } 4289 /* 4290 * Function: 4291 * phy_8481_control_get 4292 * Purpose: 4293 * Get current control settign of the PHY. 4294 * Parameters: 4295 * unit - StrataSwitch unit #. 4296 * port - StrataSwitch port #. 4297 * type - Control to update 4298 * value - (OUT)Current setting for the control 4299 * Returns: 4300 * SOC_E_NONE 4301 */ 4302 STATIC int 4303 phy_8481_control_get(int unit, soc_port_t port, 4304 soc_phy_control_t type, uint32 *value) 4305 { 4306 phy_ctrl_t *pc; /* PHY software state */ 4307 4308 pc = EXT_PHY_SW_STATE(unit, port); 4309 4310 if (PHY_COPPER_MODE(unit, port)) { 4311 return(_phy_8481_copper_control_driver_get(unit, port, type, value)); 4312 } else { 4313 if (NXT_PC(pc)) { 4314 PHYDRV_CALL_ARG2(pc,PHY_CONTROL_GET,type,value); 4315 return SOC_E_NONE; 4316 } 4317 return(_phy_8481_xaui_control_driver_get(unit, port, type, value)); 4318 } 4319 4320 } 4321 4322 /* 4323 * Function: 4324 * phy_8481_probe 4325 * Purpose: 4326 * Complement the generic phy probe routine to identify this phy when its 4327 * phy id0 and id1 is same as some other phy's. 4328 * Parameters: 4329 * unit - StrataSwitch unit #. 4330 * pc - phy ctrl descriptor. 4331 * Returns: 4332 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 4333 */ 4334 4335 4336 STATIC int 4337 phy_8481_probe(int unit, phy_ctrl_t *pc) 4338 { 4339 uint16 id0, id1; 4340 4341 if ( READ_PHY8481_TOPLVL1_ID0r(unit, pc, &id0) < 0 ) { 4342 return SOC_E_NOT_FOUND; 4343 } 4344 4345 if ( READ_PHY8481_TOPLVL1_ID1r(unit, pc, &id1) < 0 ) { 4346 return SOC_E_NOT_FOUND; 4347 } 4348 4349 /* check OUI & MODEL ID to identify the PHY chip */ 4350 switch ( PHY_OUI_MODEL(PHY_OUI(id0, id1), PHY_MODEL(id0, id1)) ) { 4351 4352 case PHY_OUI_MODEL(PHY_BCM8481X_OUI, PHY_BCM8481X_MODEL) : 4353 if ( PHY_REV(id0, id1) == 0x7) { 4354 /* 84812 detected */ 4355 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4356 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_XAUI); 4357 pc->dev_name = "BCM84812"; 4358 } 4359 break; 4360 4361 case PHY_OUI_MODEL(PHY_BCM84822_OUI, PHY_BCM84822_MODEL) : 4362 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4363 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_XAUI); 4364 if ( PHY_REV(id0, id1) != 0x0) { 4365 /* A0 does not support EEE */ 4366 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE); 4367 } 4368 break; 4369 4370 case PHY_OUI_MODEL(PHY_BCM84823_OUI, PHY_BCM84823_MODEL) : 4371 if ( PHY_REV(id0, id1) != 0x0) { 4372 /* A0 does not support EEE */ 4373 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_CAPABLE); 4374 } 4375 break; 4376 4377 case PHY_OUI_MODEL(PHY_BCM84833_OUI, PHY_BCM84833_MODEL) : 4378 if ( id1 & 0x8 ) { 4379 #ifdef INCLUDE_MACSEC 4380 if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) { 4381 return SOC_E_NOT_FOUND; 4382 } 4383 #endif 4384 pc->dev_name = "BCM84333"; 4385 } 4386 break; 4387 4388 case PHY_OUI_MODEL(PHY_BCM84836_OUI, PHY_BCM84836_MODEL) : 4389 if ( id1 & 0x8 ) { 4390 #ifdef INCLUDE_MACSEC 4391 if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) { 4392 return SOC_E_NOT_FOUND; 4393 } 4394 #endif 4395 pc->dev_name = "BCM84336"; 4396 } 4397 break; 4398 4399 case PHY_OUI_MODEL(PHY_BCM84834_OUI, PHY_BCM84834_MODEL) : 4400 if ( id1 & 0x8 ) { 4401 #ifdef INCLUDE_MACSEC 4402 if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) { 4403 return SOC_E_NOT_FOUND; 4404 } 4405 #endif 4406 pc->dev_name = "BCM84334"; 4407 } 4408 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4409 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4410 break; 4411 4412 case PHY_OUI_MODEL(PHY_BCM84835_OUI, PHY_BCM84835_MODEL) : 4413 if ( id1 & 0x8 ) { 4414 return SOC_E_NOT_FOUND; 4415 } 4416 break; 4417 4418 case PHY_OUI_MODEL(PHY_BCM84846_OUI, PHY_BCM84846_MODEL) : 4419 #ifdef INCLUDE_MACSEC 4420 if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) { 4421 return SOC_E_NOT_FOUND; 4422 } 4423 #endif 4424 break; 4425 4426 case PHY_OUI_MODEL(PHY_BCM84844_OUI, PHY_BCM84844_MODEL) : 4427 case PHY_OUI_MODEL(PHY_BCM84848_OUI, PHY_BCM84848_MODEL) : 4428 #ifdef INCLUDE_MACSEC 4429 if ( soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0) ) { 4430 return SOC_E_NOT_FOUND; 4431 } 4432 #endif 4433 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4434 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4435 break; 4436 4437 case PHY_OUI_MODEL(PHY_BCM84856_OUI, PHY_BCM84856_MODEL) : 4438 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4439 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4440 pc->dev_name = "BCM84856"; 4441 break; 4442 case PHY_OUI_MODEL(PHY_BCM84858_OUI, PHY_BCM84858_MODEL) : 4443 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4444 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4445 pc->dev_name = "BCM84858"; 4446 break; 4447 4448 case PHY_OUI_MODEL(PHY_BCM84860_OUI, PHY_BCM84860_MODEL) | 4449 PHY_OUI_MODEL(PHY_BCM84861_OUI, PHY_BCM84861_MODEL) : 4450 if ( PHY_REV(id0, id1) == 0x0) { 4451 pc->dev_name = "BCM84861"; 4452 } 4453 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4454 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4455 break; 4456 4457 case PHY_OUI_MODEL(PHY_BCM84864_OUI, PHY_BCM84864_MODEL) | 4458 PHY_OUI_MODEL(PHY_BCM84868_OUI, PHY_BCM84868_MODEL) : 4459 if ( PHY_REV(id0, id1) == 0x0) { 4460 pc->dev_name = "BCM84868"; 4461 } 4462 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4463 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4464 break; 4465 4466 case PHY_OUI_MODEL(PHY_BCM84888_OUI, PHY_BCM84888_MODEL) | 4467 PHY_OUI_MODEL(PHY_BCM84887_OUI, PHY_BCM84887_MODEL) | 4468 PHY_OUI_MODEL(PHY_BCM84884_OUI, PHY_BCM84884_MODEL) : 4469 if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) ) { 4470 pc->dev_name = "BCM84888"; 4471 } else 4472 if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) ) { 4473 pc->dev_name = "BCM84884"; 4474 } else 4475 if ( (PHY_REV(id0, id1) == 0x4) || (PHY_REV(id0, id1) == 0x5) ) { 4476 pc->dev_name = "BCM84887"; 4477 } 4478 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4479 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4480 break; 4481 4482 case PHY_OUI_MODEL(PHY_BCM84888E_OUI, PHY_BCM84888E_MODEL) | 4483 PHY_OUI_MODEL(PHY_BCM84884E_OUI, PHY_BCM84884E_MODEL) : 4484 if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) ) { 4485 pc->dev_name = "BCM84888E"; 4486 } else 4487 if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) ) { 4488 pc->dev_name = "BCM84884E"; 4489 } 4490 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4491 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4492 break; 4493 4494 case PHY_OUI_MODEL(PHY_BCM84881_OUI, PHY_BCM84881_MODEL) | 4495 PHY_OUI_MODEL(PHY_BCM84880_OUI, PHY_BCM84880_MODEL) : 4496 if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) ) { 4497 pc->dev_name = "BCM84881"; 4498 } else 4499 if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) ) { 4500 pc->dev_name = "BCM84880"; 4501 } 4502 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4503 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4504 break; 4505 4506 case PHY_OUI_MODEL(PHY_BCM84888S_OUI, PHY_BCM84888S_MODEL) | 4507 PHY_OUI_MODEL(PHY_BCM84886_OUI, PHY_BCM84886_MODEL) | 4508 PHY_OUI_MODEL(PHY_BCM84885_OUI, PHY_BCM84885_MODEL) : 4509 if ( (PHY_REV(id0, id1) == 0x0) || (PHY_REV(id0, id1) == 0x1) ) { 4510 pc->dev_name = "BCM84886"; 4511 } else 4512 if ( (PHY_REV(id0, id1) == 0x8) || (PHY_REV(id0, id1) == 0x9) ) { 4513 pc->dev_name = "BCM84885"; 4514 } else 4515 if ( (PHY_REV(id0, id1) == 0x4) || (PHY_REV(id0, id1) == 0x5) ) { 4516 pc->dev_name = "BCM84888S"; 4517 } 4518 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 4519 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_FIBER); 4520 break; 4521 4522 case PHY_OUI_MODEL(PHY_BCM84812CE_OUI, PHY_BCM84812CE_MODEL) : 4523 case PHY_OUI_MODEL(PHY_BCM84821_OUI, PHY_BCM84821_MODEL) : 4524 4525 break; 4526 4527 default: 4528 return SOC_E_NOT_FOUND; 4529 4530 } 4531 pc->size = sizeof(PHY8481_PRIV_t); 4532 4533 return SOC_E_NONE; 4534 4535 } 4536 4537 /* 4538 * Function: 4539 * phy_8481_speed_set 4540 * Purpose: 4541 * Set PHY speed 4542 * Parameters: 4543 * unit - StrataSwitch unit #. 4544 * port - StrataSwitch port #. 4545 * speed - link speed in Mbps 4546 * Returns: 4547 * SOC_E_NONE 4548 */ 4549 4550 STATIC int 4551 _phy_8481_copper_speed_set(int unit, soc_port_t port, int speed) 4552 { 4553 phy_ctrl_t *pc; 4554 phy_ctrl_t *int_pc; 4555 uint16 speed_c45 = 0, speed_c22 = 0, speed_mg = 0; 4556 int lb_enable = 0, rv = SOC_E_NONE; 4557 4558 LOG_INFO(BSL_LS_SOC_PHY, 4559 (BSL_META_U(unit, "phy_8481_speed_set: u=%d p=%d speed=%d\n"), 4560 unit, port, speed)); 4561 pc = EXT_PHY_SW_STATE(unit, port); 4562 /* coverity[dead_error_condition:FALSE] */ 4563 int_pc = INT_PHY_SW_STATE(unit, port); 4564 switch ( speed ) { 4565 case 5000: 4566 speed_mg = MGBASE_AN_CTRL_MG_ENABLE | MGBASE_AN_CTRL_SPEED_5G; 4567 break; 4568 4569 case 2500: 4570 speed_mg = MGBASE_AN_CTRL_MG_ENABLE | MGBASE_AN_CTRL_SPEED_2P5G; 4571 break; 4572 4573 case 10000: 4574 speed_c45 = IEEE_CTRLr_SPEED_10G; 4575 speed_c22 = PMAD_MII_CTRL_SS_MSB | PMAD_MII_CTRL_SS_LSB; 4576 break; 4577 4578 case 1000: 4579 speed_c45 = 0; 4580 speed_c22 = PMAD_MII_CTRL_SS_1000; 4581 break; 4582 4583 case 100: 4584 speed_c45 = 0; 4585 speed_c22 = PMAD_MII_CTRL_SS_100; 4586 break; 4587 4588 case 10: 4589 speed_c45 = 0; 4590 speed_c22 = PMAD_MII_CTRL_SS_10; 4591 break; 4592 4593 default: 4594 return SOC_E_PARAM; 4595 4596 } 4597 4598 if ( PHY_IS_BCM8486X_AND_UP(pc) ) { /* Mako support 5G/2.5G */ 4599 /* MGBASE-T AN Control Reg.(30.0x0000), Speed_Select_5G/2.5G[6:5] */ 4600 SOC_IF_ERROR_RETURN( 4601 MODIFY_PHY8481_MGBASET_AN_CTRLr(unit, pc, speed_mg, 4602 (MGBASE_AN_CTRL_SPEED_MASK | MGBASE_AN_CTRL_ADV_MASK)) ); 4603 } 4604 4605 /* XFI PMA/PMD Control 1 Reg. (1.0x0000), speed_10G[5:2] speed_sel[13,6] */ 4606 SOC_IF_ERROR_RETURN 4607 (MODIFY_PHY8481_PMAD_CTRLr(unit, pc, speed_c45 | speed_c22, 4608 IEEE_CTRLr_SPEED_10G_MASK | PMAD_MII_CTRL_SS_MASK )); 4609 4610 if ( ! PHY_IS_BCM8486X_AND_UP(pc)) { 4611 /* Only allow forced 100M in case of no loopback and AN off */ 4612 SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, &lb_enable)); 4613 if(!lb_enable) { 4614 speed_c22 = PMAD_MII_CTRL_SS_100; 4615 } 4616 } 4617 4618 if ( PHY_IS_BCM8483X_AND_UP(pc) ) { 4619 /* 1000/100BASE-T MII Control Reg. (7.0xFFE0), speed_select[13,6] */ 4620 SOC_IF_ERROR_RETURN 4621 (MODIFY_PHY8481_MII_CTRLr(unit, pc, speed_c22, PMAD_MII_CTRL_SS_MASK)); 4622 } else { 4623 /* Sync the speed bits with the GPHY MII CTRL reg. */ 4624 SOC_IF_ERROR_RETURN 4625 (MODIFY_PHY8481_AN_REG(unit, pc, 0x8000, (1U<<13), (1U << 13))); 4626 } 4627 /* coverity[dead_error_condition:FALSE] */ 4628 /* need to set the internal phy's speed accordingly */ 4629 if ( NULL != int_pc ) { 4630 /* coverity[dead_error_begin] */ 4631 rv = PHY_SPEED_SET(int_pc->pd, unit, port, speed); 4632 } 4633 LB_SPEED(pc) = speed; 4634 4635 return rv; 4636 } 4637 4638 STATIC int 4639 _phy_8481_xaui_speed_set(int unit, soc_port_t port, int speed) 4640 { 4641 phy_ctrl_t *pc; 4642 uint16 strap1 = 0; 4643 4644 pc = EXT_PHY_SW_STATE(unit, port); 4645 /* Select 1G Fiber */ 4646 if ( speed == 1000 ) { 4647 strap1 = (1U << 12); 4648 } 4649 PHY_FW_HANDSHAKE(unit, port); 4650 SOC_IF_ERROR_RETURN 4651 (MODIFY_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, strap1, (1U << 12))); 4652 PHY_FW_HANDSHAKE(unit, port); 4653 4654 return (SOC_E_NONE); 4655 } 4656 4657 4658 STATIC int 4659 phy_8481_speed_set(int unit, soc_port_t port, int speed) 4660 { 4661 phy_ctrl_t *pc; 4662 4663 pc = EXT_PHY_SW_STATE(unit, port); 4664 4665 if ( PHY_COPPER_MODE(unit, port)) { 4666 SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_set(unit, port, speed)); 4667 pc->copper.force_speed = speed; 4668 } else { 4669 PHYDRV_CALL_ARG1(pc,PHY_SPEED_SET,speed); 4670 SOC_IF_ERROR_RETURN(_phy_8481_xaui_speed_set(unit, port, speed)); 4671 pc->fiber.force_speed = speed; 4672 } 4673 4674 return SOC_E_NONE; 4675 } 4676 4677 /* 4678 * Function: 4679 * phy_8481_speed_get 4680 * Purpose: 4681 * Get PHY speed 4682 * Parameters: 4683 * unit - StrataSwitch unit #. 4684 * port - StrataSwitch port #. 4685 * speed - current link speed in Mbps 4686 * Returns: 4687 * SOC_E_NONE 4688 */ 4689 STATIC int 4690 _phy_8481_copper_speed_get(int unit, soc_port_t port, int *speed) 4691 { 4692 phy_ctrl_t *pc; 4693 uint16 ctrl, status, speed_c45; 4694 int an = 0; 4695 int an_done = 0; 4696 4697 pc = EXT_PHY_SW_STATE(unit, port); 4698 4699 if ( PHY_IS_BCM8484X_AND_UP(pc) ) { 4700 /* Core Config Status Register (30.0x400D), Copper_Speed[2,4:3] */ 4701 SOC_IF_ERROR_RETURN( 4702 READ_PHY84834_CORE_CFG_LINK_STATUSr(unit, pc, &status) ); 4703 4704 if (PHY_IS_BCM8484X(pc)) { 4705 /* Do not include Status Register bit 2 for speed determination 4706 * on BCM8484X, because bit 2 is priority bit other than speed MSB.*/ 4707 status &= ~CORE_CFG_LINK_STAT_SPEED_MSB; 4708 } 4709 4710 speed_c45 = (status & CORE_CFG_LINK_STAT_SPEED_MSB) | 4711 ((status & CORE_CFG_LINK_STAT_SPEED_LSB) 4712 >> CORE_CFG_LINK_STAT_SPEED_LSB_SHIFT); 4713 switch ( speed_c45 ) { 4714 case 1 : 4715 *speed = 100; break; 4716 case 2 : 4717 *speed = 1000; break; 4718 case 3 : 4719 *speed = 10000; break; 4720 case 4 : 4721 *speed = 2500; break; 4722 case 5 : 4723 *speed = 5000; break; 4724 default: 4725 *speed = 0; break; 4726 } 4727 if( *speed != 0) { 4728 return SOC_E_NONE; 4729 } 4730 } 4731 4732 /* legacy way for determining current link-down speed */ 4733 SOC_IF_ERROR_RETURN 4734 (phy_8481_an_get(unit, port, &an, &an_done)); 4735 4736 if ( an ) { /* autoneg is enabled */ 4737 if ( an_done ) { 4738 SOC_IF_ERROR_RETURN 4739 (READ_PHY8481_TENG_AN_CTRLr(unit, pc, &ctrl)); 4740 SOC_IF_ERROR_RETURN 4741 (READ_PHY8481_TENG_AN_STATr(unit, pc, &status)); 4742 if ( (ctrl & TENG_IEEE_AN_CTRL_10GBT ) && 4743 (status & TENG_IEEE_AN_STAT_LP_10GBT) ) { 4744 *speed = 10000; 4745 } else { 4746 /* look at the CL22 regs and determine the gcd */ 4747 SOC_IF_ERROR_RETURN 4748 (_phy8481_auto_negotiate_gcd(unit, port, speed, NULL)); 4749 } 4750 } else { 4751 *speed = 0; 4752 return(SOC_E_NONE); 4753 } 4754 4755 } else { /* autoNego is no t enabled, forced speed */ 4756 /* read the MII Ctrl reg. */ 4757 4758 SOC_IF_ERROR_RETURN 4759 (READ_PHY8481_PMAD_CTRLr(unit, pc, &speed_c45)); 4760 switch(MII_CTRL_SS(speed_c45)) { 4761 case PMAD_MII_CTRL_SS_10: 4762 *speed = 10; 4763 break; 4764 case PMAD_MII_CTRL_SS_100: 4765 *speed = 100; 4766 break; 4767 case PMAD_MII_CTRL_SS_1000: 4768 *speed = 1000; 4769 break; 4770 default: 4771 if ( (speed_c45 & (IEEE_CTRLr_SPEED_10G_MASK|PMAD_MII_CTRL_SS_MASK)) 4772 == IEEE_CTRLr_SPEED_10G ) { 4773 *speed = 10000; 4774 break; 4775 } else { 4776 *speed = 0; 4777 return(SOC_E_NONE); 4778 } 4779 } 4780 } 4781 4782 return SOC_E_NONE; 4783 } 4784 4785 STATIC int 4786 _phy_8481_xaui_speed_get(int unit, soc_port_t port, int *speed) 4787 { 4788 phy_ctrl_t *pc; 4789 uint16 strap1; 4790 pc = EXT_PHY_SW_STATE(unit, port); 4791 4792 SOC_IF_ERROR_RETURN 4793 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &strap1)); 4794 4795 if ( strap1 & (1U << 12)) { 4796 *speed = 1000; 4797 } else { 4798 *speed = 10000; 4799 } 4800 return (SOC_E_NONE); 4801 } 4802 4803 STATIC int 4804 phy_8481_speed_get(int unit, soc_port_t port, int *speed) 4805 { 4806 phy_ctrl_t *pc; 4807 4808 pc = EXT_PHY_SW_STATE(unit, port); 4809 4810 if ( PHY_COPPER_MODE(unit, port)) { 4811 SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_get(unit, port, speed)); 4812 } else { 4813 if ( NXT_PC(pc)) { 4814 PHYDRV_CALL_ARG1(pc,PHY_SPEED_GET,speed); 4815 return SOC_E_NONE; 4816 } 4817 SOC_IF_ERROR_RETURN(_phy_8481_xaui_speed_get(unit, port, speed)); 4818 } 4819 4820 return SOC_E_NONE; 4821 } 4822 4823 STATIC int 4824 _phy_8481_copper_duplex_set(int unit, soc_port_t port, int duplex) 4825 { 4826 uint16 mii_ctrl; 4827 phy_ctrl_t *pc; 4828 4829 pc = EXT_PHY_SW_STATE(unit, port); 4830 4831 SOC_IF_ERROR_RETURN 4832 (READ_PHY8481_MII_CTRLr(unit, pc, &mii_ctrl)); 4833 4834 if ( duplex) { 4835 mii_ctrl |= MII_CTRL_FD; 4836 } else { 4837 mii_ctrl &= ~MII_CTRL_FD; 4838 } 4839 4840 SOC_IF_ERROR_RETURN 4841 (WRITE_PHY8481_MII_CTRLr(unit, pc, mii_ctrl)); 4842 4843 pc->copper.force_duplex = duplex; 4844 4845 return(SOC_E_NONE); 4846 } 4847 4848 STATIC int 4849 _phy_8481_xaui_duplex_set(int unit, soc_port_t port, int duplex) 4850 { 4851 uint16 mii_ctrl; 4852 phy_ctrl_t *pc; 4853 4854 pc = EXT_PHY_SW_STATE(unit, port); 4855 4856 SOC_IF_ERROR_RETURN 4857 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl)); 4858 4859 if ( duplex) { 4860 mii_ctrl |= MII_CTRL_FD; 4861 } else { 4862 mii_ctrl &= ~MII_CTRL_FD; 4863 } 4864 4865 SOC_IF_ERROR_RETURN 4866 (WRITE_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, mii_ctrl)); 4867 4868 pc->fiber.force_duplex = duplex; 4869 4870 return SOC_E_NONE; 4871 } 4872 4873 STATIC int 4874 phy_8481_duplex_set(int unit, soc_port_t port, int duplex) 4875 { 4876 phy_ctrl_t *pc; 4877 4878 pc = EXT_PHY_SW_STATE(unit, port); 4879 4880 if ( PHY_COPPER_MODE(unit, port)) { 4881 SOC_IF_ERROR_RETURN(_phy_8481_copper_duplex_set(unit, port, duplex)); 4882 } else { 4883 PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_SET,duplex); 4884 SOC_IF_ERROR_RETURN(_phy_8481_xaui_duplex_set(unit, port, duplex)); 4885 } 4886 4887 return SOC_E_NONE; 4888 } 4889 4890 4891 STATIC int 4892 _phy_8481_copper_duplex_get(int unit, soc_port_t port, int *duplex) 4893 { 4894 int rv, speed, lbmode; 4895 uint16 mii_ctrl; 4896 phy_ctrl_t *pc; 4897 4898 pc = EXT_PHY_SW_STATE(unit, port); 4899 4900 /* check if it's under PHY loopback mode ? */ 4901 SOC_IF_ERROR_RETURN(_phy_8481_copper_lb_get(unit, port, &lbmode)); 4902 /* if under loopback & lb_speed is set, use the intended loopback speed */ 4903 if ( (! lbmode) || (0 == (speed = LB_SPEED(pc))) ) { /* 0 means LB_SPEED not set */ 4904 /* not loopback mode or don't know the intended speed for loopback, *\ 4905 \* call _phy_8481_copper_speed_get() to get the current speed */ 4906 SOC_IF_ERROR_RETURN(_phy_8481_copper_speed_get(unit, port, &speed)); 4907 } 4908 4909 if ( ( speed == 10000 ) || ( speed == 0 ) || 4910 ( speed == 5000 ) || ( speed == 2500 ) ) { 4911 *duplex = TRUE; 4912 return SOC_E_NONE; 4913 } 4914 4915 SOC_IF_ERROR_RETURN 4916 (READ_PHY8481_MII_CTRLr(unit, pc, &mii_ctrl)); 4917 4918 rv = SOC_E_NONE; 4919 if ( mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ 4920 if ( !(pc->mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ 4921 *duplex = FALSE; 4922 } else { 4923 rv = _phy8481_auto_negotiate_gcd(unit, port, NULL, duplex); 4924 } 4925 } else { /* Auto-negotiation disabled */ 4926 *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE; 4927 } 4928 4929 return(rv); 4930 } 4931 4932 STATIC int 4933 _phy_8481_xaui_duplex_get(int unit, soc_port_t port, int *duplex) 4934 { 4935 uint16 reg0_16; 4936 uint16 mii_ctrl; 4937 phy_ctrl_t *pc; 4938 4939 pc = EXT_PHY_SW_STATE(unit, port); 4940 4941 *duplex = TRUE; 4942 4943 SOC_IF_ERROR_RETURN 4944 (READ_PHY8481_PHYXS_L_GP_STATUS_STATUS1000X1r(unit, pc, ®0_16)); 4945 4946 if ( reg0_16 & GP_STATUS_STATUS1000X1_SGMII_MODE_MASK) { 4947 4948 /* retrieve the duplex setting in SGMII mode */ 4949 SOC_IF_ERROR_RETURN 4950 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIICNTLr(unit, pc, &mii_ctrl)); 4951 4952 if ( mii_ctrl & MII_CTRL_AE) { 4953 SOC_IF_ERROR_RETURN 4954 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGLPABILr(unit,pc,®0_16)); 4955 4956 /* make sure link partner is also in SGMII mode 4957 * otherwise fall through to use the FD bit in MII_CTRL reg 4958 */ 4959 if ( reg0_16 & MII_ANP_SGMII_MODE) { 4960 if ( reg0_16 & MII_ANP_SGMII_FD) { 4961 *duplex = TRUE; 4962 } else { 4963 *duplex = FALSE; 4964 } 4965 4966 return SOC_E_NONE; 4967 } 4968 } 4969 *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE; 4970 } 4971 4972 return SOC_E_NONE; 4973 } 4974 4975 STATIC int 4976 phy_8481_duplex_get(int unit, soc_port_t port, int *duplex) 4977 { 4978 phy_ctrl_t *pc; 4979 int tmp = 0; 4980 4981 pc = EXT_PHY_SW_STATE(unit, port); 4982 4983 if ( PHY_COPPER_MODE(unit, port)) { 4984 SOC_IF_ERROR_RETURN(_phy_8481_copper_duplex_get(unit, port, duplex)); 4985 } else { 4986 SOC_IF_ERROR_RETURN(_phy_8481_xaui_duplex_get(unit, port, duplex)); 4987 if ( NXT_PC(pc)) { 4988 tmp = *duplex; 4989 PHYDRV_CALL_ARG1(pc,PHY_DUPLEX_GET,duplex); 4990 *duplex = (tmp == TRUE && *duplex == TRUE) ? TRUE : FALSE; 4991 } 4992 } 4993 4994 return SOC_E_NONE; 4995 } 4996 4997 /* 4998 * Function: 4999 * phy_8481_an_get 5000 * Purpose: 5001 * Get the current auto-negotiation status (enabled/busy) 5002 * Parameters: 5003 * unit - StrataSwitch unit #. 5004 * port - StrataSwitch port #. 5005 * an - (OUT) if true, auto-negotiation is enabled. 5006 * an_done - (OUT) if true, auto-negotiation is complete. This 5007 * value is undefined if an == false. 5008 * Returns: 5009 * SOC_E_XXX 5010 */ 5011 STATIC int 5012 _phy_8481_copper_an_get(int unit, soc_port_t port, int *an, int *an_done) 5013 { 5014 phy_ctrl_t *pc; 5015 uint16 mii_ctrl; 5016 5017 pc = EXT_PHY_SW_STATE(unit, port); 5018 5019 SOC_IF_ERROR_RETURN 5020 (READ_PHY8481_MII_STATr(unit, pc, &pc->mii_stat)); 5021 5022 SOC_IF_ERROR_RETURN 5023 (READ_PHY8481_MII_CTRLr(unit, pc, &mii_ctrl)); 5024 5025 /* Looking at the MII regs would suffice */ 5026 *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE; 5027 5028 if (NULL != an_done) { 5029 *an_done = (pc->mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE; 5030 } 5031 5032 return SOC_E_NONE; 5033 } 5034 5035 STATIC int 5036 _phy_8481_xaui_an_get(int unit, soc_port_t port, int *an, int *an_done) 5037 { 5038 COMPILER_REFERENCE(unit); 5039 COMPILER_REFERENCE(port); 5040 5041 *an = FALSE; 5042 if (NULL != an_done) { 5043 *an_done = FALSE; 5044 } 5045 5046 return (SOC_E_NONE); 5047 } 5048 5049 STATIC int 5050 phy_8481_an_get(int unit, soc_port_t port, int *an, int *an_done) 5051 { 5052 phy_ctrl_t *pc; 5053 5054 pc = EXT_PHY_SW_STATE(unit, port); 5055 5056 if (PHY_COPPER_MODE(unit, port)) { 5057 SOC_IF_ERROR_RETURN(_phy_8481_copper_an_get(unit, port, an, an_done)); 5058 } else { 5059 if (NXT_PC(pc)) { 5060 PHYDRV_CALL_ARG2(pc,PHY_AUTO_NEGOTIATE_GET,an,an_done); 5061 return SOC_E_NONE; 5062 } 5063 5064 SOC_IF_ERROR_RETURN(_phy_8481_xaui_an_get(unit, port, an, an_done)); 5065 } 5066 5067 return SOC_E_NONE; 5068 } 5069 5070 /* 5071 * Function: 5072 * phy_8481_an_set 5073 * Purpose: 5074 * Enable or disabled auto-negotiation on the specified port. 5075 * Parameters: 5076 * unit - StrataSwitch unit #. 5077 * port - StrataSwitch port #. 5078 * an - Boolean, if true, auto-negotiation is enabled 5079 * (and/or restarted). If false, autonegotiation is disabled. 5080 * Returns: 5081 * SOC_E_XXX 5082 */ 5083 STATIC int 5084 _phy_8481_copper_an_set(int unit, soc_port_t port, int an) 5085 { 5086 phy_ctrl_t *pc; 5087 int pan = 0; 5088 int pan_done = 0; 5089 5090 SOC_IF_ERROR_RETURN 5091 (phy_8481_an_get(unit, port, &pan, &pan_done)); 5092 5093 pc = EXT_PHY_SW_STATE(unit, port); 5094 5095 if (pan != 0 && an == 0) { 5096 /* Workaround to avoid 1000BASET force mode which is causing *\ 5097 \* the PHY to misbehave (0x2100 puts PHY in 100BT force mode ) */ 5098 SOC_IF_ERROR_RETURN 5099 (WRITE_PHY8481_MII_CTRLr(unit, pc, 0x2100)); 5100 } 5101 5102 /* 1000T/100TX MII Control Reg.(7.0xFFE0), AN_Enable[12] Restart_AN[9] */ 5103 SOC_IF_ERROR_RETURN( 5104 MODIFY_PHY8481_MII_CTRLr(unit, pc, 5105 (an ? (MII_CTRL_AE | MII_CTRL_RAN) : 0), 5106 MII_CTRL_AE | MII_CTRL_RAN) ); 5107 /* 10GBASE-T AutoNeg Control Reg.(7.0x0000), AN_Enable[12] Restart_AN[9] */ 5108 SOC_IF_ERROR_RETURN( 5109 MODIFY_PHY8481_AN_CTRLr( unit, pc, 5110 (an ? (AN_IEEE_CTRL_REG_AN_ENA_RESTART) : 0), 5111 AN_IEEE_CTRL_REG_AN_ENA_RESTART) ); 5112 pc->copper.autoneg_enable = an; 5113 return SOC_E_NONE; 5114 } 5115 5116 STATIC int 5117 _phy_8481_xaui_an_set(int unit, soc_port_t port, int an) 5118 { 5119 COMPILER_REFERENCE(unit); 5120 COMPILER_REFERENCE(port); 5121 COMPILER_REFERENCE(an); 5122 5123 return SOC_E_NONE; 5124 } 5125 5126 STATIC int 5127 phy_8481_an_set(int unit, soc_port_t port, int an) 5128 { 5129 phy_ctrl_t *pc, *int_pc; 5130 5131 pc = EXT_PHY_SW_STATE(unit, port); 5132 int_pc = INT_PHY_SW_STATE(unit, port); 5133 5134 if ( PHY_COPPER_MODE(unit, port) ) { 5135 SOC_IF_ERROR_RETURN(_phy_8481_copper_an_set(unit, port, an)); 5136 #if 1 5137 if ( SYS_FORCED_CL72(pc) ) { 5138 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an)); 5139 } 5140 #endif 5141 } else { 5142 if ( NXT_PC(pc) ) { 5143 PHYDRV_CALL_ARG1(pc,PHY_AUTO_NEGOTIATE_SET,an); 5144 SOC_IF_ERROR_RETURN(_phy_8481_xaui_an_set(unit, port, FALSE)); 5145 return SOC_E_NONE; 5146 } 5147 SOC_IF_ERROR_RETURN(_phy_8481_xaui_an_set(unit, port, an)); 5148 } 5149 5150 return SOC_E_NONE; 5151 } 5152 5153 5154 /* 5155 * Function: 5156 * phy_8481_ability_advert_get 5157 * Purpose: 5158 * Get the current advertisement for auto-negotiation. 5159 * Parameters: 5160 * unit - StrataSwitch unit #. 5161 * port - StrataSwitch port #. 5162 * ability - (OUT) Port ability masks indicating supported options/speeds. 5163 * Returns: 5164 * SOC_E_XXX 5165 * Notes: 5166 * The advertisement is retrieved for the ACTIVE medium. 5167 * No synchronization performed at this level. 5168 */ 5169 STATIC int 5170 _phy_8481_copper_ability_advert_get(int unit, soc_port_t port, 5171 soc_port_ability_t *ability) 5172 { 5173 phy_ctrl_t *pc; 5174 uint16 data16; 5175 int rv; 5176 5177 pc = EXT_PHY_SW_STATE(unit, port); 5178 rv = SOC_E_NONE; 5179 5180 sal_memset(ability, 0, sizeof(*ability)); 5181 5182 /* Copper AutoNeg Advertisement Reg.(7.0xFFE4) */ 5183 SOC_IF_ERROR_RETURN 5184 (READ_PHY8481_MII_ANAr(unit, pc, &data16)); 5185 if ( data16 & MII_ANA_HD_100 ) { 5186 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 5187 } 5188 if ( data16 & MII_ANA_FD_100 ) { 5189 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 5190 } 5191 5192 if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) { /* only 8481/8482x support 10M */ 5193 if ( data16 & MII_ANA_HD_10 ) { 5194 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 5195 } 5196 if ( data16 & MII_ANA_FD_10 ) { 5197 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 5198 } 5199 } 5200 5201 switch ( data16 & (MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE) ) { 5202 case MII_ANA_PAUSE: 5203 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 5204 break; 5205 case MII_ANA_ASYM_PAUSE: 5206 ability->pause = SOC_PA_PAUSE_TX; 5207 break; 5208 case MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE: 5209 ability->pause = SOC_PA_PAUSE_RX; 5210 break; 5211 } 5212 5213 /* 1000BASE-T Control Reg.(7.0xFFE9) */ 5214 SOC_IF_ERROR_RETURN 5215 (READ_PHY8481_MII_GB_CTRLr(unit, pc, &data16)); 5216 /* GE Specific values */ 5217 if ( data16 & MII_GB_CTRL_ADV_1000HD ) { 5218 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 5219 } 5220 if ( data16 & MII_GB_CTRL_ADV_1000FD ) { 5221 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 5222 } 5223 5224 /* 10GBASE-T AN Control Reg.(7.0x0020) */ 5225 SOC_IF_ERROR_RETURN 5226 (READ_PHY8481_TENG_AN_CTRLr(unit, pc, &data16)); 5227 /* 10G Specific values */ 5228 if ( data16 & TENG_IEEE_AN_CTRL_10GBT ) { 5229 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 5230 } 5231 5232 if (PHY_IS_BCM8486X_AND_UP(pc)) { 5233 if ( PHY_IS_BCM8488X(pc) ) { 5234 /* check bit[8:7] of 10GBASE-T AN Control Reg.(7.0x0020) *\ 5235 \* for 5GBASE-T / 2.5GBASE-T support */ 5236 if ( data16 & TENG_IEEE_AN_CTRL_2p5GBT ) { 5237 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 5238 } 5239 if ( data16 & TENG_IEEE_AN_CTRL_5GBT ) { 5240 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB; 5241 } 5242 }/* if PHY_IS_BCM8488X */ 5243 5244 /* Broadcom MGBASE-T 5G / 2.5G Specific values *\ 5245 \* MGBASE-T AN Control Reg.(30.0x0000), Advert_5G/2.5G_capability[2:1] */ 5246 SOC_IF_ERROR_RETURN( 5247 READ_PHY8481_MGBASET_AN_CTRLr(unit, pc, &data16) ); 5248 if ( data16 & MGBASE_AN_CTRL_ADV_2P5G ) { 5249 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 5250 } 5251 if ( data16 & MGBASE_AN_CTRL_ADV_5G ) { 5252 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB; 5253 } 5254 }/* if PHY_IS_BCM8486X_AND_UP */ 5255 5256 /* EEE settings */ 5257 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 5258 SOC_IF_ERROR_RETURN 5259 (READ_PHY8481_EEE_ADVr(unit, pc, &data16)); 5260 if ( data16 & 0x08 ) { 5261 ability->eee |= SOC_PA_EEE_10GB_BASET; 5262 } 5263 if ( data16 & 0x04 ) { 5264 ability->eee |= SOC_PA_EEE_1GB_BASET; 5265 } 5266 if ( data16 & 0x02 ) { 5267 ability->eee |= SOC_PA_EEE_100MB_BASETX; 5268 } 5269 } 5270 5271 return rv; 5272 } 5273 5274 STATIC int 5275 _phy_8481_xaui_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability) 5276 { 5277 phy_ctrl_t *pc; 5278 uint16 an_adv; 5279 uint16 adv_over1g; 5280 5281 pc = EXT_PHY_SW_STATE(unit, port); 5282 5283 sal_memset(ability, 0, sizeof(*ability)); 5284 5285 SOC_IF_ERROR_RETURN 5286 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGADVr(unit, pc, &an_adv)); 5287 5288 switch (an_adv & (MII_ANP_C37_ASYM_PAUSE | MII_ANP_C37_PAUSE)) { 5289 case MII_ANP_C37_ASYM_PAUSE: 5290 ability->pause |= SOC_PA_PAUSE_TX; 5291 break; 5292 case (MII_ANP_C37_ASYM_PAUSE | MII_ANP_C37_PAUSE): 5293 ability->pause |= SOC_PA_PAUSE_RX; 5294 break; 5295 case MII_ANP_C37_PAUSE: 5296 ability->pause |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 5297 break; 5298 } 5299 5300 ability->speed_full_duplex |= (an_adv & MII_ANP_C37_FD) ? SOC_PA_SPEED_1000MB : 0; 5301 5302 SOC_IF_ERROR_RETURN 5303 (READ_PHY8481_PHYXS_L_OVER1G_UP1r(unit, pc, &adv_over1g)); 5304 ability->speed_full_duplex |= (adv_over1g & OVER1G_UP1_DATARATE_10GCX4_MASK) ? 5305 SOC_PA_SPEED_10GB : 0; 5306 5307 return SOC_E_NONE; 5308 } 5309 5310 STATIC int 5311 phy_8481_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability) 5312 { 5313 phy_ctrl_t *pc; 5314 5315 pc = EXT_PHY_SW_STATE(unit, port); 5316 5317 if (NULL == ability) { 5318 return (SOC_E_PARAM); 5319 } 5320 5321 if (PHY_COPPER_MODE(unit, port)) { 5322 SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_advert_get(unit, port, ability)); 5323 } else { 5324 if (NXT_PC(pc)) { 5325 PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_GET,ability); 5326 return SOC_E_NONE; 5327 } 5328 SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_advert_get(unit, port, ability)); 5329 } 5330 5331 return SOC_E_NONE; 5332 } 5333 5334 5335 /* 5336 * Function: 5337 * phy_8481_ability_advert_set 5338 * Purpose: 5339 * Set the current advertisement for auto-negotiation. 5340 * Parameters: 5341 * unit - StrataSwitch unit #. 5342 * port - StrataSwitch port #. 5343 * ability - Port ability masks indicating supported options/speeds. 5344 * Returns: 5345 * SOC_E_XXX 5346 * Notes: 5347 * The advertisement is set only for the ACTIVE medium. 5348 * No synchronization performed at this level. 5349 */ 5350 5351 5352 STATIC int 5353 _phy_8481_copper_ability_advert_set(int unit, soc_port_t port, 5354 soc_port_ability_t *ability) 5355 { 5356 phy_ctrl_t *pc; 5357 uint16 mii_adv, mii_gb_ctrl, mask; 5358 int rv; 5359 5360 pc = EXT_PHY_SW_STATE(unit, port); 5361 rv = SOC_E_NONE; 5362 5363 mii_adv = MII_ANA_ASF_802_3; 5364 5365 SOC_IF_ERROR_RETURN 5366 (READ_PHY8481_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 5367 5368 mii_gb_ctrl &= ~(MII_GB_CTRL_ADV_1000HD | MII_GB_CTRL_ADV_1000FD); 5369 if ( PHY_IS_BCM8484X(pc) ) { 5370 mii_gb_ctrl &= ~MII_GB_CTRL_PT; /* DTE device (JIRA PHY-1772) */ 5371 } else { 5372 mii_gb_ctrl |= MII_GB_CTRL_PT; /* repeater / switch port */ 5373 } 5374 5375 if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) { /* only 8481/8482x support 10M */ 5376 if ( ability->speed_half_duplex & SOC_PA_SPEED_10MB ) { 5377 mii_adv |= MII_ANA_HD_10; 5378 LB_SPEED(pc) = 10; 5379 } 5380 if ( ability->speed_full_duplex & SOC_PA_SPEED_10MB ) { 5381 mii_adv |= MII_ANA_FD_10; 5382 LB_SPEED(pc) = 10; 5383 } 5384 } 5385 5386 if ( ability->speed_half_duplex & SOC_PA_SPEED_100MB ) { 5387 mii_adv |= MII_ANA_HD_100; 5388 LB_SPEED(pc) = 100; 5389 } 5390 if ( ability->speed_full_duplex & SOC_PA_SPEED_100MB ) { 5391 mii_adv |= MII_ANA_FD_100; 5392 LB_SPEED(pc) = 100; 5393 } 5394 if ( ability->speed_half_duplex & SOC_PA_SPEED_1000MB ) { 5395 mii_gb_ctrl |= MII_GB_CTRL_ADV_1000HD; 5396 LB_SPEED(pc) = 1000; 5397 } 5398 if ( ability->speed_full_duplex & SOC_PA_SPEED_1000MB ) { 5399 mii_gb_ctrl |= MII_GB_CTRL_ADV_1000FD; 5400 LB_SPEED(pc) = 1000; 5401 } 5402 if ( (ability->speed_half_duplex & SOC_PA_SPEED_2500MB) || 5403 (ability->speed_full_duplex & SOC_PA_SPEED_2500MB) ) { 5404 LB_SPEED(pc) = 2500; 5405 } 5406 if ( (ability->speed_half_duplex & SOC_PA_SPEED_5000MB) || 5407 (ability->speed_full_duplex & SOC_PA_SPEED_5000MB) ) { 5408 LB_SPEED(pc) = 5000; 5409 } 5410 if ( (ability->speed_half_duplex & SOC_PA_SPEED_10GB) || 5411 (ability->speed_full_duplex & SOC_PA_SPEED_10GB) ) { 5412 LB_SPEED(pc) = 10000; 5413 } 5414 5415 if ( (ability->speed_half_duplex & SOC_PA_SPEED_10MB) || 5416 (ability->speed_full_duplex & SOC_PA_SPEED_10MB) ) { 5417 if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) { /* only 8481/8482x support 10M */ 5418 LB_SPEED(pc) = 10; 5419 } 5420 } 5421 5422 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 5423 case SOC_PA_PAUSE_TX: 5424 mii_adv |= MII_ANA_ASYM_PAUSE; 5425 break; 5426 case SOC_PA_PAUSE_RX: 5427 mii_adv |= MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE; 5428 break; 5429 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 5430 mii_adv |= MII_ANA_PAUSE; 5431 break; 5432 } 5433 5434 mask = MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE | 5435 MII_ANA_FD_100 | MII_ANA_HD_100 | MII_ANA_ASF_802_3; 5436 if ( ! PHY_IS_BCM8483X_AND_UP(pc) ) { /* only 8481/8482x support 10M */ 5437 mask |= (MII_ANA_FD_10 | MII_ANA_HD_10); 5438 } 5439 SOC_IF_ERROR_RETURN 5440 (MODIFY_PHY8481_MII_ANAr(unit, pc, mii_adv, mask)); 5441 5442 SOC_IF_ERROR_RETURN 5443 (MODIFY_PHY8481_MII_GB_CTRLr(unit, pc, mii_gb_ctrl, 5444 MII_GB_CTRL_PT | MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_ADV_1000HD)); 5445 5446 if ( PHY_IS_BCM8486X_AND_UP(pc) ) { 5447 /* 5G / 2.5G Specific values */ 5448 mii_gb_ctrl = (ability->speed_full_duplex & SOC_PA_SPEED_5000MB) 5449 ? (MGBASE_AN_CTRL_ADV_5G | MGBASE_AN_CTRL_MG_ENABLE) : 0; 5450 mii_gb_ctrl |= (ability->speed_full_duplex & SOC_PA_SPEED_2500MB) 5451 ? (MGBASE_AN_CTRL_ADV_2P5G | MGBASE_AN_CTRL_MG_ENABLE) : 0; 5452 /* MGBASE-T AN Control Reg.(30.0x0000), Advert_5G/2.5G_capability[2:1] */ 5453 SOC_IF_ERROR_RETURN( 5454 MODIFY_PHY8481_MGBASET_AN_CTRLr(unit, pc, mii_gb_ctrl, 5455 MGBASE_AN_CTRL_ADV_MASK) ); 5456 } 5457 5458 /* 10G Specific values ( 7.0x0020 bit[12] ) */ 5459 mii_gb_ctrl = (ability->speed_full_duplex & SOC_PA_SPEED_10GB) 5460 ? TENG_IEEE_AN_CTRL_10GBT : 0; 5461 if ( PHY_IS_BCM8488X(pc) ) { 5462 /* 5G / 2.5G Specific values ( 7.0x0020 bit[8:7] ) */ 5463 mii_gb_ctrl |= (ability->speed_full_duplex & SOC_PA_SPEED_5000MB) 5464 ? TENG_IEEE_AN_CTRL_5GBT : 0; 5465 mii_gb_ctrl |= (ability->speed_full_duplex & SOC_PA_SPEED_2500MB) 5466 ? TENG_IEEE_AN_CTRL_2p5GBT : 0; 5467 } 5468 /* 10GBASE-T AN Control Reg.(7.0x0020), Advert_10G/5G/2.5G_capability */ 5469 SOC_IF_ERROR_RETURN( 5470 MODIFY_PHY8481_TENG_AN_CTRLr(unit, pc, mii_gb_ctrl, 5471 TENG_IEEE_AN_CTRL_10GBT | 5472 TENG_IEEE_AN_CTRL_5GBT | 5473 TENG_IEEE_AN_CTRL_2p5GBT) ); 5474 5475 /* EEE settings */ 5476 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) ) { 5477 uint16 eee_ability = 0; 5478 if (ability->eee & SOC_PA_EEE_10GB_BASET) { 5479 eee_ability |= 0x8; 5480 } 5481 if (ability->eee & SOC_PA_EEE_1GB_BASET) { 5482 eee_ability |= 0x4; 5483 } 5484 if (ability->eee & SOC_PA_EEE_100MB_BASETX) { 5485 eee_ability |= 0x2; 5486 } 5487 SOC_IF_ERROR_RETURN 5488 (MODIFY_PHY8481_EEE_ADVr(unit, pc, eee_ability, 0xe)); 5489 } 5490 5491 return rv; 5492 } 5493 5494 STATIC int 5495 _phy_8481_xaui_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability) 5496 { 5497 phy_ctrl_t *pc; 5498 uint16 an_adv; 5499 5500 pc = EXT_PHY_SW_STATE(unit, port); 5501 5502 /* Support only full duplex */ 5503 an_adv = (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) ? MII_ANP_C37_FD : 0; 5504 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 5505 case SOC_PA_PAUSE_TX: 5506 an_adv |= MII_ANP_C37_ASYM_PAUSE; 5507 break; 5508 case SOC_PA_PAUSE_RX: 5509 an_adv |= MII_ANP_C37_ASYM_PAUSE | MII_ANP_C37_PAUSE; 5510 break; 5511 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 5512 an_adv |= MII_ANP_C37_PAUSE; 5513 break; 5514 } 5515 SOC_IF_ERROR_RETURN 5516 (WRITE_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGADVr(unit, pc, an_adv)); 5517 5518 if (ability->speed_full_duplex & SOC_PA_SPEED_10GB) { 5519 SOC_IF_ERROR_RETURN 5520 (WRITE_PHY8481_PHYXS_L_OVER1G_UP1r(unit, pc, OVER1G_UP1_DATARATE_10GCX4_MASK)); 5521 } else { 5522 SOC_IF_ERROR_RETURN 5523 (WRITE_PHY8481_PHYXS_L_OVER1G_UP1r(unit, pc, 0)); 5524 } 5525 5526 return SOC_E_NONE; 5527 } 5528 5529 5530 STATIC int 5531 phy_8481_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability) 5532 { 5533 phy_ctrl_t *pc; 5534 5535 pc = EXT_PHY_SW_STATE(unit, port); 5536 5537 if (NULL == ability) { 5538 return (SOC_E_PARAM); 5539 } 5540 5541 if (PHY_COPPER_MODE(unit, port)) { 5542 SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_advert_set(unit, port, ability)); 5543 pc->copper.advert_ability = *ability; 5544 } else { 5545 pc->fiber.advert_ability = *ability; 5546 if (NXT_PC(pc)) { 5547 PHYDRV_CALL_ARG1(pc,PHY_ABILITY_ADVERT_SET,ability); 5548 return SOC_E_NONE; 5549 } 5550 SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_advert_set(unit, port, ability)); 5551 } 5552 5553 return SOC_E_NONE; 5554 } 5555 5556 STATIC int 5557 _phy_8481_xaui_nxt_dev_probe(int unit, soc_port_t port) 5558 { 5559 phy_ctrl_t *pc; 5560 phy_ctrl_t phy_ctrl; 5561 soc_phy_info_t phy_info; 5562 extern int _ext_phy_probe(int unit, soc_port_t port,soc_phy_info_t *pi, 5563 phy_ctrl_t *ext_pc); 5564 5565 pc = EXT_PHY_SW_STATE(unit, port); 5566 5567 /* initialize the phy_ctrl for the next device connected to the xaui port */ 5568 sal_memset(&phy_ctrl, 0, sizeof(phy_ctrl_t)); 5569 phy_ctrl.unit = unit; 5570 phy_ctrl.port = port; 5571 phy_ctrl.speed_max = pc->speed_max; 5572 phy_ctrl.read = pc->read; /* use same MDIO read routine as this device's */ 5573 phy_ctrl.write = pc->write; /* use same MDIO write routine as this device's */ 5574 5575 /* coverity[overrun-call] */ 5576 /* get the mdio address of the next device */ 5577 phy_ctrl.phy_id = soc_property_port_get(unit, port, 5578 spn_PORT_PHY_ADDR1, 5579 port < sizeof(ext_phy_dft_addr1)/sizeof(ext_phy_dft_addr1[0])? 5580 ext_phy_dft_addr1[port]:0); 5581 5582 /* probe the next device at the given address */ 5583 SOC_IF_ERROR_RETURN 5584 (_ext_phy_probe(unit, port, &phy_info, &phy_ctrl)); 5585 5586 if ((phy_ctrl.pd == NULL) || ((phy_ctrl.phy_model == pc->phy_model) && 5587 (phy_ctrl.phy_oui == pc->phy_oui))) { 5588 pc->driver_data = NULL; 5589 /* device not found */ 5590 return SOC_E_NONE; 5591 } 5592 LOG_INFO(BSL_LS_SOC_PHY, 5593 (BSL_META_U(unit, 5594 "_phy_8481_xaui_nxt_dev_probe: found phy device" 5595 " u=%d p=%d id0=0x%x id1=0x%x\n"), 5596 unit, port,phy_ctrl.phy_id0,phy_ctrl.phy_id1)); 5597 /* set the chained flag */ 5598 PHY_FLAGS_SET(phy_ctrl.unit, phy_ctrl.port, PHY_FLAGS_CHAINED); 5599 5600 /* Found device, allocate control structure */ 5601 pc->driver_data = (void *)sal_alloc ((sizeof (phy_ctrl_t) + phy_ctrl.size), phy_ctrl.pd->drv_name); 5602 if (pc->driver_data == NULL) { 5603 return SOC_E_MEMORY; 5604 } 5605 sal_memcpy(pc->driver_data, &phy_ctrl, sizeof(phy_ctrl_t)); 5606 return SOC_E_NONE; 5607 } 5608 5609 /* 5610 * Function: 5611 * phy_8481_ability_remote_get 5612 * Purpose: 5613 * Get the current remoteisement for auto-negotiation. 5614 * Parameters: 5615 * unit - StrataSwitch unit #. 5616 * port - StrataSwitch port #. 5617 * ability - (OUT) Port ability masks indicating supported options/speeds. 5618 * Returns: 5619 * SOC_E_XXX 5620 * Notes: 5621 * The remoteisement is retrieved for the ACTIVE medium. 5622 * No synchronization performed at this level. 5623 */ 5624 5625 STATIC int 5626 _phy_8481_copper_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability) 5627 { 5628 phy_ctrl_t *pc; 5629 uint16 mii_anp, mii_gb_stat, teng_an_stat; 5630 int rv; 5631 5632 pc = EXT_PHY_SW_STATE(unit, port); 5633 rv = SOC_E_NONE; 5634 5635 sal_memset(ability, 0, sizeof(*ability)); 5636 5637 if ((pc->mii_stat & (MII_STAT_AN_DONE | MII_STAT_LA)) 5638 == (MII_STAT_AN_DONE | MII_STAT_LA)) { 5639 /* Decode remote advertisement only when link is up *\ 5640 \* and autoneg is completed. */ 5641 5642 /* Copper AutoNeg Link Partner ability (7.0xFFE5) */ 5643 SOC_IF_ERROR_RETURN 5644 (READ_PHY8481_MII_ANPr(unit, pc, &mii_anp)); 5645 /* 1000BASE-T Status (7.0xFFEA) */ 5646 SOC_IF_ERROR_RETURN 5647 (READ_PHY8481_MII_GB_STATr(unit, pc, &mii_gb_stat)); 5648 /* 10GBASE-T Status (7.0x0021), LP_10G_Capability[11] */ 5649 SOC_IF_ERROR_RETURN 5650 (READ_PHY8481_TENG_AN_STATr(unit, pc, &teng_an_stat)); 5651 5652 if (mii_anp & MII_ANA_HD_10) { 5653 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 5654 } 5655 if (mii_anp & MII_ANA_FD_10) { 5656 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 5657 } 5658 if (mii_anp & MII_ANA_HD_100) { 5659 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 5660 } 5661 if (mii_anp & MII_ANA_FD_100) { 5662 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 5663 } 5664 5665 ability->pause = 0; 5666 switch (mii_anp & (MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE)) { 5667 case MII_ANA_PAUSE: 5668 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 5669 break; 5670 case MII_ANA_ASYM_PAUSE: 5671 ability->pause = SOC_PA_PAUSE_TX; 5672 break; 5673 case MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE: 5674 ability->pause = SOC_PA_PAUSE_RX; 5675 break; 5676 } 5677 5678 /* GE Specific values */ 5679 5680 if (mii_gb_stat & MII_GB_STAT_LP_1000HD) { 5681 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 5682 } 5683 if (mii_gb_stat & MII_GB_STAT_LP_1000FD) { 5684 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 5685 } 5686 5687 /* 10G Specific values */ 5688 if (teng_an_stat & TENG_IEEE_AN_STAT_LP_10GBT) { 5689 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 5690 } 5691 5692 /* EEE settings */ 5693 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE)) { 5694 uint16 eee_ability; 5695 SOC_IF_ERROR_RETURN 5696 (READ_PHY8481_EEE_LPABILr(unit, pc, &eee_ability)); 5697 if (eee_ability & 0x08) { 5698 ability->eee |= SOC_PA_EEE_10GB_BASET; 5699 } 5700 if (eee_ability & 0x04) { 5701 ability->eee |= SOC_PA_EEE_1GB_BASET; 5702 } 5703 if (eee_ability & 0x02) { 5704 ability->eee |= SOC_PA_EEE_100MB_BASETX; 5705 } 5706 } 5707 } else { 5708 return (SOC_E_FAIL); 5709 } 5710 5711 return rv; 5712 } 5713 5714 STATIC int 5715 _phy_8481_xaui_ability_remote_get(int unit, soc_port_t port, 5716 soc_port_ability_t *ability) 5717 { 5718 uint16 mii_stat_combo; 5719 uint16 link_stat_gp; 5720 uint16 an_adv; 5721 soc_port_mode_t mode; 5722 phy_ctrl_t *pc; 5723 5724 pc = EXT_PHY_SW_STATE(unit, port); 5725 5726 sal_memset(ability, 0, sizeof(*ability)); 5727 5728 SOC_IF_ERROR_RETURN 5729 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_MIISTATr(unit, pc, &mii_stat_combo)); 5730 SOC_IF_ERROR_RETURN 5731 (READ_PHY8481_PHYXS_L_GP_STATUS_XGXSSTATUS3r(unit, pc, &link_stat_gp)); 5732 5733 LOG_INFO(BSL_LS_SOC_PHY, 5734 (BSL_META_U(unit, 5735 "u=%d p=%d mii_stat_combo=%04x link_stat_gp=%04x\n"), 5736 unit, port, mii_stat_combo, link_stat_gp)); 5737 5738 5739 mode = 0; 5740 if ((link_stat_gp & GP_STATUS_XGXSSTATUS3_LINK_MASK) && 5741 (mii_stat_combo & MII_STAT_AN_DONE)) { 5742 /* Decode remote advertisement only when link is up and autoneg is 5743 * completed. 5744 */ 5745 5746 SOC_IF_ERROR_RETURN 5747 (READ_PHY8481_PHYXS_L_GP_STATUS_LP_UP1r(unit, pc, &an_adv)); 5748 5749 mode |= (an_adv & OVER1G_LP_UP1_DATARATE_10GCX4_MASK) ? 5750 SOC_PA_SPEED_10GB : 0; 5751 5752 LOG_INFO(BSL_LS_SOC_PHY, 5753 (BSL_META_U(unit, 5754 "u=%d p=%d over1G an_adv=%04x\n"), 5755 unit, port, an_adv)); 5756 SOC_IF_ERROR_RETURN 5757 (READ_PHY8481_PHYXS_L_COMBO_IEEE0_AUTONEGLPABILr(unit, pc, &an_adv)); 5758 LOG_INFO(BSL_LS_SOC_PHY, 5759 (BSL_META_U(unit, 5760 "u=%d p=%d combo an_adv=%04x\n"), 5761 unit, port, an_adv)); 5762 5763 mode |= (an_adv & MII_ANP_C37_FD) ? SOC_PA_SPEED_1000MB : 0; 5764 ability->speed_full_duplex = mode; 5765 5766 mode = 0; 5767 switch (an_adv & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) { 5768 case MII_ANP_C37_PAUSE: 5769 mode |= SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 5770 break; 5771 case MII_ANP_C37_ASYM_PAUSE: 5772 mode |= SOC_PA_PAUSE_TX; 5773 break; 5774 case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE: 5775 mode |= SOC_PA_PAUSE_RX; 5776 break; 5777 } 5778 ability->pause = mode; 5779 5780 if (PHY_CLAUSE73_MODE(unit, port)) { 5781 5782 } 5783 } else { 5784 return (SOC_E_FAIL); 5785 } 5786 LOG_INFO(BSL_LS_SOC_PHY, 5787 (BSL_META_U(unit, 5788 "phy_8481_xaui_ability_remote_get:unit=%d p=%d pause=%08x sp=%08x\n"), 5789 unit, port, ability->pause, ability->speed_full_duplex)); 5790 5791 return (SOC_E_NONE); 5792 } 5793 5794 STATIC int 5795 phy_8481_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability) 5796 { 5797 phy_ctrl_t *pc; 5798 5799 pc = EXT_PHY_SW_STATE(unit, port); 5800 5801 if (NULL == ability) { 5802 return (SOC_E_PARAM); 5803 } 5804 5805 if (PHY_COPPER_MODE(unit, port)) { 5806 SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_remote_get(unit, port, ability)); 5807 } else { 5808 if (NXT_PC(pc)) { 5809 PHYDRV_CALL_ARG1(pc,PHY_ABILITY_REMOTE_GET,ability); 5810 return SOC_E_NONE; 5811 } 5812 SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_remote_get(unit, port, ability)); 5813 } 5814 5815 return SOC_E_NONE; 5816 } 5817 5818 /* 5819 * Function: 5820 * phy_8481_ability_local_get 5821 * Purpose: 5822 * Get the device's complete abilities. 5823 * Parameters: 5824 * unit - StrataSwitch unit #. 5825 * port - StrataSwitch port #. 5826 * ability - return device's abilities. 5827 * Returns: 5828 * SOC_E_XXX 5829 */ 5830 5831 STATIC int 5832 _phy_8481_copper_ability_local_get(int unit, soc_port_t port, 5833 soc_port_ability_t *ability) 5834 { 5835 phy_ctrl_t *pc; 5836 5837 pc = EXT_PHY_SW_STATE(unit, port); 5838 5839 if ( PHY_IS_BCM8483X_AND_UP(pc) ) { 5840 ability->speed_half_duplex = SOC_PA_SPEED_100MB; 5841 ability->speed_full_duplex = SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB | 5842 SOC_PA_SPEED_100MB; 5843 } else { 5844 ability->speed_half_duplex = SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB; 5845 ability->speed_full_duplex = SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB | 5846 SOC_PA_SPEED_100MB | SOC_PA_SPEED_10MB; 5847 } 5848 5849 ability->interface = SOC_PA_INTF_XGMII; 5850 if ( PHY_IS_BCM8486X_AND_UP(pc) ) { /* Mako supports 5G/2.5G speed */ 5851 if ( PHY_REPEATER(unit, port) ) { /* check MAC interface mode */ 5852 /* 5G/2.5G over XFI mode (XGMII) support both speed */ 5853 ability->speed_full_duplex |= (SOC_PA_SPEED_5000MB | 5854 SOC_PA_SPEED_2500MB); 5855 } else { 5856 /* 2500BASE-X mode (SGMII) supports 2.5G only */ 5857 ability->speed_full_duplex |= (SOC_PA_SPEED_2500MB | SOC_PA_SPEED_5000MB); 5858 ability->interface = SOC_PA_INTF_SGMII; 5859 5860 } 5861 } 5862 5863 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_CAPABLE) && 5864 PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) ) { 5865 ability->eee = SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | 5866 SOC_PA_EEE_100MB_BASETX; 5867 } 5868 5869 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 5870 ability->medium = SOC_PA_MEDIUM_COPPER; 5871 ability->loopback = SOC_PA_LB_PHY; 5872 ability->flags = SOC_PA_AUTONEG; 5873 5874 return (SOC_E_NONE); 5875 } 5876 5877 STATIC int 5878 _phy_8481_xaui_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 5879 { 5880 5881 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 5882 ability->speed_full_duplex = SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB; 5883 5884 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 5885 ability->interface = SOC_PA_INTF_XGMII; 5886 ability->medium = SOC_PA_MEDIUM_XAUI; 5887 ability->loopback = SOC_PA_LB_PHY; 5888 ability->flags = SOC_PA_ABILITY_NONE; 5889 5890 return (SOC_E_NONE); 5891 } 5892 5893 STATIC int 5894 phy_8481_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 5895 { 5896 if (NULL == ability) { 5897 return SOC_E_PARAM; 5898 } 5899 5900 sal_memset(ability, 0, sizeof(*ability)); 5901 5902 if (PHY_COPPER_MODE(unit, port)) { 5903 SOC_IF_ERROR_RETURN(_phy_8481_copper_ability_local_get(unit, port, ability)); 5904 } else { 5905 SOC_IF_ERROR_RETURN(_phy_8481_xaui_ability_local_get(unit, port, ability)); 5906 } 5907 5908 return (SOC_E_NONE); 5909 } 5910 5911 STATIC int 5912 phy_8481_link_up(int unit, soc_port_t port) 5913 { 5914 int lbmode, speed_line, speed_sys, an, an_done; 5915 phy_ctrl_t *pc; 5916 phy_ctrl_t *int_pc; 5917 5918 int_pc = INT_PHY_SW_STATE(unit, port); 5919 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC); 5920 5921 pc = EXT_PHY_SW_STATE(unit, port); 5922 SOC_IF_ERROR_RETURN 5923 (phy_8481_an_get(unit,port,&an,&an_done)); 5924 5925 SOC_IF_ERROR_RETURN 5926 (_phy_8481_copper_lb_get(unit, port, &lbmode)); 5927 /* if the intended loopback speed was set, use the LB_SPEED */ 5928 if ( (! (lbmode) ) || (0 == (speed_line = LB_SPEED(pc))) ) { /* 0 means LB_SPEED not set */ 5929 /* don't know the intended speed for loopback, *\ 5930 \* call phy_8481_speed_get() to get the current speed */ 5931 SOC_IF_ERROR_RETURN( phy_8481_speed_get(unit, port, &speed_line) ); 5932 } 5933 5934 /* notify parameters to the system side */ 5935 switch ( speed_line ) { 5936 5937 case 10000: 5938 case 5000: 5939 case 2500: 5940 if ( ! LAST_IN_CHAIN(pc) ) { 5941 /* MAC side interface type -- XGMII: 5G/2.5G over XFI mode *\ 5942 \* -- 2500X: 2500BASE-X mode */ 5943 SOC_IF_ERROR_RETURN( 5944 soc_phyctrl_notify(unit, port, phyEventInterface, 5945 (PHY_REPEATER(unit, port)) ? SOC_PORT_IF_XFI : 5946 ((speed_line == 2500) ? SOC_PORT_IF_2500X 5947 : SOC_PORT_IF_5000X)) ); 5948 /* if MAC side in 5G/2.5G over XFI mode, force it to 10G speed */ 5949 if ( PHY_REPEATER(unit, port) ) { 5950 if ( 10000 != speed_line ) { 5951 /* system side is in 5G/2.5G over XFI (idle stuffing) *\ 5952 |* mode when line side speed is 5G/2.5G, notify *| 5953 \* the system side of 10G speed and set this flag */ 5954 PHY_FLAGS_SET(unit, port, PHY_FLAGS_NO_SYS_LINE_SPD_SYNC); 5955 } 5956 /* if MAC side in 5G/2.5G over XFI mode, *\ 5957 \* always notify system side of 10G speed */ 5958 speed_sys = 10000; 5959 } else { 5960 /* not 5G/2.5G over XFI mode, system side speed is same as line side */ 5961 speed_sys = speed_line; 5962 } 5963 /* notify internal SerDes of system side speed */ 5964 SOC_IF_ERROR_RETURN 5965 (soc_phyctrl_notify(unit, port, phyEventSpeed , speed_sys)); 5966 /* notify internal SerDes of line side speed */ 5967 SOC_IF_ERROR_RETURN 5968 (soc_phyctrl_notify(unit, port, phyEventSpeedLine, speed_line)); 5969 /* notify internal SerDes of Resume event */ 5970 SOC_IF_ERROR_RETURN 5971 (soc_phyctrl_notify(unit, port, phyEventResume, 1)); 5972 } 5973 break; 5974 5975 case 1000: 5976 if ( ! LAST_IN_CHAIN(pc) ) { 5977 if ( PHY_COPPER_MODE(unit, port) ) { 5978 SOC_IF_ERROR_RETURN 5979 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII)); 5980 SOC_IF_ERROR_RETURN 5981 (soc_phyctrl_notify(unit, port, phyEventSpeed , 1000)); 5982 SOC_IF_ERROR_RETURN 5983 (soc_phyctrl_notify(unit, port, phyEventSpeedLine, 1000)); 5984 } else { 5985 SOC_IF_ERROR_RETURN 5986 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_XAUI)); 5987 } 5988 SOC_IF_ERROR_RETURN 5989 (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, (1U << 14), (1U << 14))); 5990 } 5991 break; 5992 5993 case 100: 5994 case 10: 5995 if ( ! LAST_IN_CHAIN(pc) ) { 5996 SOC_IF_ERROR_RETURN 5997 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII)); 5998 SOC_IF_ERROR_RETURN 5999 (soc_phyctrl_notify(unit, port, phyEventSpeed , speed_line)); 6000 SOC_IF_ERROR_RETURN 6001 (soc_phyctrl_notify(unit, port, phyEventSpeedLine, speed_line)); 6002 } 6003 SOC_IF_ERROR_RETURN 6004 (MODIFY_PHY8481_MII_AUX_CTRLr(unit, pc, (1U << 14), (1U << 14))); 6005 break; 6006 6007 default: 6008 break; 6009 } 6010 6011 /* misc. settings */ 6012 if ( PHY_IS_BCM84836(pc) || PHY_IS_BCM84846(pc) || PHY_IS_BCM84856(pc) ) { 6013 /* for fiber media */ 6014 SOC_IF_ERROR_RETURN 6015 (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 0x8061, 0, (1U << 5))); 6016 SOC_IF_ERROR_RETURN 6017 (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 0x80ba, 0, (3U << 2))); 6018 } 6019 if ( PHY_IS_BCM84834(pc) || PHY_IS_BCM84836(pc) || 6020 PHY_IS_BCM84844(pc) || PHY_IS_BCM84846(pc) || PHY_IS_BCM84848(pc) ) { 6021 /* XFI LPI pass-thru for native mode EEE */ 6022 SOC_IF_ERROR_RETURN 6023 (WRITE_PHY8481_PHYXS_M_REG(unit, pc, 0x8390, 0x007c)); 6024 } 6025 #if 1 6026 if ( SYS_FORCED_CL72(pc) ) { 6027 SOC_IF_ERROR_RETURN(PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, an)); 6028 } 6029 #endif 6030 6031 /* Workaround for PHY-1570 Runt pkts on 84844 ports */ 6032 if ( FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD ) { 6033 if ( (speed_line == 100) && (an == FALSE) ) { 6034 _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0018, 0xffff, 0, 0x9c00); 6035 _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0019, 0xffff, 0, 0x1000); 6036 _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0018, 0xffff, 0, 0x0000); 6037 _phy8485x_shadow_reg_write(unit, pc, REG_GROUP_SHADOW_MISC_REG, 0x0019, 0xffff, 0, 0x0000); 6038 } 6039 } 6040 6041 LINK_DOWN(pc) = FALSE; 6042 return (SOC_E_NONE); 6043 } 6044 6045 STATIC int 6046 phy_8481_link_down(int unit, soc_port_t port) 6047 { 6048 phy_ctrl_t *pc; 6049 6050 pc = EXT_PHY_SW_STATE(unit, port); 6051 6052 LB_SPEED(pc) = 0; /* clear the intended speed for loopback */ 6053 LINK_DOWN(pc) = TRUE; /* set link-down flag */ 6054 return (SOC_E_NONE); 6055 } 6056 6057 /* 6058 * Function: 6059 * phy_8481_mdix_set 6060 * Description: 6061 * Set the Auto-MDIX mode of a port/PHY 6062 * Parameters: 6063 * unit - Device number 6064 * port - Port number 6065 * mode - One of: 6066 * SOC_PORT_MDIX_AUTO 6067 * Enable auto-MDIX when autonegotiation is enabled 6068 * SOC_PORT_MDIX_FORCE_AUTO 6069 * Enable auto-MDIX always 6070 * SOC_PORT_MDIX_NORMAL 6071 * Disable auto-MDIX 6072 * SOC_PORT_MDIX_XOVER 6073 * Disable auto-MDIX, and swap cable pairs 6074 * Return Value: 6075 * SOC_E_XXX 6076 */ 6077 STATIC int 6078 phy_8481_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode) 6079 { 6080 phy_ctrl_t *pc; 6081 int speed; 6082 6083 pc = EXT_PHY_SW_STATE(unit, port); 6084 6085 if (!PHY_COPPER_MODE(unit, port)) { 6086 return SOC_E_NONE; 6087 } 6088 6089 switch (mode) { 6090 case SOC_PORT_MDIX_AUTO: 6091 /* Clear bit 14 for automatic MDI crossover */ 6092 SOC_IF_ERROR_RETURN 6093 (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0, 0x4000)); 6094 6095 /* 6096 * Write the result in the register 0x18, shadow copy 7 6097 */ 6098 /* Clear bit 9 to disable forced auto MDI xover */ 6099 SOC_IF_ERROR_RETURN 6100 (MODIFY_PHY8481_MII_MISC_CTRLr(unit, pc, 0, 0x0200)); 6101 break; 6102 6103 case SOC_PORT_MDIX_FORCE_AUTO: 6104 /* Clear bit 14 for automatic MDI crossover */ 6105 SOC_IF_ERROR_RETURN 6106 (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0, 0x4000)); 6107 6108 /* 6109 * Write the result in the register 0x18, shadow copy 7 6110 */ 6111 /* Set bit 9 to force automatic MDI crossover */ 6112 SOC_IF_ERROR_RETURN 6113 (MODIFY_PHY8481_MII_MISC_CTRLr(unit, pc, 0x0200, 0x0200)); 6114 break; 6115 6116 case SOC_PORT_MDIX_NORMAL: 6117 SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed)); 6118 if (speed == 0 || speed == 10 || speed == 100) { 6119 /* Set bit 14 for manual MDI crossover */ 6120 SOC_IF_ERROR_RETURN 6121 (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0x4000, 0x4000)); 6122 6123 SOC_IF_ERROR_RETURN 6124 (WRITE_PHY8481_TEST1r(unit, pc, 0)); 6125 } else { 6126 return SOC_E_UNAVAIL; 6127 } 6128 break; 6129 6130 case SOC_PORT_MDIX_XOVER: 6131 SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed)); 6132 if (speed == 0 || speed == 10 || speed == 100) { 6133 /* Set bit 14 for manual MDI crossover */ 6134 SOC_IF_ERROR_RETURN 6135 (MODIFY_PHY8481_PHY_ECRr(unit, pc, 0x4000, 0x4000)); 6136 6137 SOC_IF_ERROR_RETURN 6138 (WRITE_PHY8481_TEST1r(unit, pc, 0x0080)); 6139 } else { 6140 return SOC_E_UNAVAIL; 6141 } 6142 break; 6143 6144 default: 6145 return SOC_E_PARAM; 6146 } 6147 6148 pc->copper.mdix = mode; 6149 return SOC_E_NONE; 6150 6151 } 6152 6153 /* 6154 * Function: 6155 * phy_8481_mdix_get 6156 * Description: 6157 * Get the Auto-MDIX mode of a port/PHY 6158 * Parameters: 6159 * unit - Device number 6160 * port - Port number 6161 * mode - (Out) One of: 6162 * SOC_PORT_MDIX_AUTO 6163 * Enable auto-MDIX when autonegotiation is enabled 6164 * SOC_PORT_MDIX_FORCE_AUTO 6165 * Enable auto-MDIX always 6166 * SOC_PORT_MDIX_NORMAL 6167 * Disable auto-MDIX 6168 * SOC_PORT_MDIX_XOVER 6169 * Disable auto-MDIX, and swap cable pairs 6170 * Return Value: 6171 * SOC_E_XXX 6172 */ 6173 STATIC int 6174 phy_8481_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode) 6175 { 6176 phy_ctrl_t *pc; 6177 int speed; 6178 6179 pc = EXT_PHY_SW_STATE(unit, port); 6180 6181 if (!PHY_COPPER_MODE(unit, port)) { 6182 *mode = SOC_PORT_MDIX_NORMAL; 6183 return SOC_E_NONE; 6184 } 6185 6186 SOC_IF_ERROR_RETURN(phy_8481_speed_get(unit, port, &speed)); 6187 if (speed == 1000) { 6188 *mode = SOC_PORT_MDIX_AUTO; 6189 } else { 6190 *mode = pc->copper.mdix; 6191 } 6192 6193 return SOC_E_NONE; 6194 } 6195 6196 /* 6197 * Function: 6198 * phy_8481_mdix_status_get 6199 * Description: 6200 * Get the current MDIX status on a port/PHY 6201 * Parameters: 6202 * unit - Device number 6203 * port - Port number 6204 * status - (OUT) One of: 6205 * SOC_PORT_MDIX_STATUS_NORMAL 6206 * Straight connection 6207 * SOC_PORT_MDIX_STATUS_XOVER 6208 * Crossover has been performed 6209 * Return Value: 6210 * SOC_E_XXX 6211 */ 6212 STATIC int 6213 phy_8481_mdix_status_get(int unit, soc_port_t port, 6214 soc_port_mdix_status_t *status) 6215 { 6216 phy_ctrl_t *pc; 6217 uint16 tmp; 6218 6219 pc = EXT_PHY_SW_STATE(unit, port); 6220 6221 if (!PHY_COPPER_MODE(unit, port)) { 6222 *status = SOC_PORT_MDIX_STATUS_NORMAL; 6223 return SOC_E_NONE; 6224 } 6225 SOC_IF_ERROR_RETURN 6226 (READ_PHY8481_PHY_ESRr(unit, pc, &tmp)); 6227 if (tmp & 0x2000) { 6228 *status = SOC_PORT_MDIX_STATUS_XOVER; 6229 } else { 6230 *status = SOC_PORT_MDIX_STATUS_NORMAL; 6231 } 6232 6233 return SOC_E_NONE; 6234 } 6235 6236 /* 6237 * Function: 6238 * phy_8481_master_set 6239 * Purpose: 6240 * Set the master mode for the PHY. 6241 * Parameters: 6242 * unit - StrataSwitch unit #. 6243 * port - StrataSwitch port #. 6244 * master - SOC_PORT_MS_* 6245 * Returns: 6246 * SOC_E_XXX 6247 * Notes: 6248 * No synchronization performed at this level. Autonegotiation is 6249 * not manipulated. 6250 */ 6251 6252 STATIC int 6253 phy_8481_master_set(int unit, soc_port_t port, int master) 6254 { 6255 uint16 mii_gb_ctrl; 6256 phy_ctrl_t *pc; 6257 6258 pc = EXT_PHY_SW_STATE(unit, port); 6259 6260 if (!PHY_COPPER_MODE(unit, port)) { 6261 return SOC_E_NONE; 6262 } 6263 6264 SOC_IF_ERROR_RETURN 6265 (READ_PHY8481_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 6266 6267 switch (master) { 6268 case SOC_PORT_MS_SLAVE: 6269 mii_gb_ctrl |= MII_GB_CTRL_MS_MAN; 6270 mii_gb_ctrl &= ~MII_GB_CTRL_MS; 6271 break; 6272 case SOC_PORT_MS_MASTER: 6273 mii_gb_ctrl |= MII_GB_CTRL_MS_MAN; 6274 mii_gb_ctrl |= MII_GB_CTRL_MS; 6275 break; 6276 case SOC_PORT_MS_AUTO: 6277 mii_gb_ctrl &= ~MII_GB_CTRL_MS_MAN; 6278 break; 6279 } 6280 6281 SOC_IF_ERROR_RETURN 6282 (WRITE_PHY8481_MII_GB_CTRLr(unit, pc, mii_gb_ctrl)); 6283 6284 pc->copper.master = master; 6285 6286 return(SOC_E_NONE); 6287 } 6288 6289 /* 6290 * Function: 6291 * phy_8481_master_get 6292 * Purpose: 6293 * Get the master mode for the PHY. If mode is forced, then 6294 * forced mode is returned; otherwise operating mode is returned. 6295 * Parameters: 6296 * unit - StrataSwitch unit #. 6297 * port - StrataSwitch port #. 6298 * master - (OUT) SOC_PORT_MS_* 6299 * Returns: 6300 * SOC_E_XXX 6301 * Notes: 6302 * No synchronization performed at this level. Autonegotiation is 6303 * not manipulated. 6304 */ 6305 6306 STATIC int 6307 phy_8481_master_get(int unit, soc_port_t port, int *master) 6308 { 6309 uint16 mii_gb_ctrl; 6310 phy_ctrl_t *pc; 6311 6312 pc = EXT_PHY_SW_STATE(unit, port); 6313 6314 if (!PHY_COPPER_MODE(unit, port)) { 6315 *master = SOC_PORT_MS_NONE; 6316 return SOC_E_NONE; 6317 } 6318 SOC_IF_ERROR_RETURN 6319 (READ_PHY8481_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 6320 6321 if (!(mii_gb_ctrl & MII_GB_CTRL_MS_MAN)) { 6322 *master = SOC_PORT_MS_AUTO; 6323 } 6324 else if (mii_gb_ctrl & MII_GB_CTRL_MS) { 6325 *master = SOC_PORT_MS_MASTER; 6326 } else { 6327 *master = SOC_PORT_MS_SLAVE; 6328 } 6329 6330 return SOC_E_NONE; 6331 } 6332 6333 6334 6335 STATIC int 6336 _phy_8481_halt(int unit, phy_ctrl_t *pc) 6337 { 6338 uint16 data16; 6339 6340 /* LED control stuff */ 6341 SOC_IF_ERROR_RETURN 6342 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82c,0xffff)); 6343 SOC_IF_ERROR_RETURN 6344 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82d,0x0000)); 6345 SOC_IF_ERROR_RETURN 6346 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82e,0x0000)); 6347 SOC_IF_ERROR_RETURN 6348 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa82f,0x0000)); 6349 SOC_IF_ERROR_RETURN 6350 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa830,0x0000)); 6351 SOC_IF_ERROR_RETURN 6352 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa831,0x0000)); 6353 SOC_IF_ERROR_RETURN 6354 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa832,0x0000)); 6355 SOC_IF_ERROR_RETURN 6356 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa833,0x0000)); 6357 SOC_IF_ERROR_RETURN 6358 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa834,0x0000)); 6359 SOC_IF_ERROR_RETURN 6360 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa835,0x0000)); 6361 SOC_IF_ERROR_RETURN 6362 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa836,0x0000)); 6363 SOC_IF_ERROR_RETURN 6364 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa837,0x0000)); 6365 SOC_IF_ERROR_RETURN 6366 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa838,0x0000)); 6367 SOC_IF_ERROR_RETURN 6368 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa839,0x0000)); 6369 SOC_IF_ERROR_RETURN 6370 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83a,0x0000)); 6371 SOC_IF_ERROR_RETURN 6372 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83b,0xb6db)); 6373 SOC_IF_ERROR_RETURN 6374 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83c,0xffff)); 6375 SOC_IF_ERROR_RETURN 6376 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xa83d,0x0000)); 6377 6378 if (PHY_IS_BCM8485X_AND_UP(pc)) { 6379 if ( PHY_EXT_ROM_BOOT(pc) ) { 6380 /* SPI ROM firmware download */ 6381 SOC_IF_ERROR_RETURN 6382 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x418c, 0x0000)); 6383 } else { 6384 if (PHY_IS_BCM8488X(pc)) { 6385 SOC_IF_ERROR_RETURN 6386 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x418c, 0x0000)); 6387 } 6388 /* MDIO firmware download */ 6389 data16 = (PHY_IS_BCM8486X_AND_UP(pc)) ? 0x48f0 : 0x0040; 6390 SOC_IF_ERROR_RETURN 6391 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4188, data16)); 6392 } 6393 } 6394 6395 SOC_IF_ERROR_RETURN 6396 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x017c)); /* assert reset for the whole ARM system */ 6397 SOC_IF_ERROR_RETURN 6398 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x8000)); /* enable global reset */ 6399 SOC_IF_ERROR_RETURN 6400 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040)); /* deassert reset for the whole ARM system 6401 but the ARM processor */ 6402 6403 if (PHY_IS_BCM8488X(pc)) { 6404 SOC_IF_ERROR_RETURN 6405 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4186,0x8000)); /* enable global reset */ 6406 } 6407 /* write_addr=0xc300_0000, data=0x0000_001e, remove bottom write protection 6408 and set VINITHI signal to 1 in order to have the ARM processor start executing 6409 bootrom space 0xffff 0000 */ 6410 6411 if (!PHY_IS_BCM8485X_AND_UP(pc)) { 6412 SOC_IF_ERROR_RETURN 6413 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000)); 6414 SOC_IF_ERROR_RETURN 6415 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300)); 6416 } 6417 else { 6418 if (PHY_IS_BCM8488X(pc)) { 6419 SOC_IF_ERROR_RETURN 6420 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0000)); 6421 SOC_IF_ERROR_RETURN 6422 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xc300)); 6423 SOC_IF_ERROR_RETURN 6424 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0001)); 6425 SOC_IF_ERROR_RETURN 6426 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x0000)); 6427 SOC_IF_ERROR_RETURN 6428 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6429 } else { 6430 SOC_IF_ERROR_RETURN 6431 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0000)); 6432 SOC_IF_ERROR_RETURN 6433 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xc300)); 6434 SOC_IF_ERROR_RETURN 6435 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0010)); 6436 SOC_IF_ERROR_RETURN 6437 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x0000)); 6438 SOC_IF_ERROR_RETURN 6439 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6440 SOC_IF_ERROR_RETURN 6441 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0000)); 6442 SOC_IF_ERROR_RETURN 6443 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6444 SOC_IF_ERROR_RETURN 6445 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x1018)); 6446 SOC_IF_ERROR_RETURN 6447 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe59f)); 6448 SOC_IF_ERROR_RETURN 6449 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6450 SOC_IF_ERROR_RETURN 6451 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0004)); 6452 SOC_IF_ERROR_RETURN 6453 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6454 SOC_IF_ERROR_RETURN 6455 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x1f11)); 6456 SOC_IF_ERROR_RETURN 6457 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xee09)); 6458 SOC_IF_ERROR_RETURN 6459 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6460 SOC_IF_ERROR_RETURN 6461 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0008)); 6462 SOC_IF_ERROR_RETURN 6463 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6464 SOC_IF_ERROR_RETURN 6465 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0000)); 6466 SOC_IF_ERROR_RETURN 6467 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe3a0)); 6468 SOC_IF_ERROR_RETURN 6469 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6470 SOC_IF_ERROR_RETURN 6471 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x000c)); 6472 SOC_IF_ERROR_RETURN 6473 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6474 SOC_IF_ERROR_RETURN 6475 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x1806)); 6476 SOC_IF_ERROR_RETURN 6477 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe3a0)); 6478 SOC_IF_ERROR_RETURN 6479 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6480 SOC_IF_ERROR_RETURN 6481 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0010)); 6482 SOC_IF_ERROR_RETURN 6483 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6484 SOC_IF_ERROR_RETURN 6485 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0002)); 6486 SOC_IF_ERROR_RETURN 6487 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe8a0)); 6488 SOC_IF_ERROR_RETURN 6489 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6490 SOC_IF_ERROR_RETURN 6491 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0014)); 6492 SOC_IF_ERROR_RETURN 6493 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6494 SOC_IF_ERROR_RETURN 6495 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0001)); 6496 SOC_IF_ERROR_RETURN 6497 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xe150)); 6498 SOC_IF_ERROR_RETURN 6499 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6500 SOC_IF_ERROR_RETURN 6501 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0018)); 6502 SOC_IF_ERROR_RETURN 6503 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6504 SOC_IF_ERROR_RETURN 6505 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0xfffc)); 6506 SOC_IF_ERROR_RETURN 6507 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x3aff)); 6508 SOC_IF_ERROR_RETURN 6509 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6510 SOC_IF_ERROR_RETURN 6511 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x001c)); 6512 SOC_IF_ERROR_RETURN 6513 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6514 SOC_IF_ERROR_RETURN 6515 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0xfffe)); 6516 SOC_IF_ERROR_RETURN 6517 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0xeaff)); 6518 SOC_IF_ERROR_RETURN 6519 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6520 SOC_IF_ERROR_RETURN 6521 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA819 , 0x0020)); 6522 SOC_IF_ERROR_RETURN 6523 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81a , 0xffff)); 6524 SOC_IF_ERROR_RETURN 6525 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81B , 0x0021)); 6526 SOC_IF_ERROR_RETURN 6527 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA81C , 0x0004)); 6528 SOC_IF_ERROR_RETURN 6529 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0009)); 6530 } 6531 } 6532 if (!PHY_IS_BCM8488X(pc)) { 6533 SOC_IF_ERROR_RETURN 6534 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16)); 6535 if (data16 & (1U << 13)) { 6536 SOC_IF_ERROR_RETURN 6537 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x001e)); 6538 } else { 6539 /* Halt CPU if doing PMA/PMD reset. */ 6540 if ( ! (PHY_IS_BCM8485X_AND_UP(pc)) ) { 6541 SOC_IF_ERROR_RETURN 6542 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x001f)); 6543 } 6544 } 6545 } 6546 if ( ! (PHY_IS_BCM8485X_AND_UP(pc)) ) { 6547 SOC_IF_ERROR_RETURN 6548 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000)); 6549 SOC_IF_ERROR_RETURN 6550 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 6551 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT))); 6552 } 6553 6554 /* write_addr=0xffff_0000, data=0xeaff_fffe, replace the first 32 bits of bootrom 6555 at 0xffff0000 with the instruction "B 0xffff0000" to loop the processor in the 6556 bootrom address space */ 6557 if (!PHY_IS_BCM8485X_AND_UP(pc)) { 6558 SOC_IF_ERROR_RETURN 6559 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000)); 6560 SOC_IF_ERROR_RETURN 6561 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xffff)); 6562 SOC_IF_ERROR_RETURN 6563 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0xfffe)); 6564 SOC_IF_ERROR_RETURN 6565 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0xeaff)); 6566 SOC_IF_ERROR_RETURN 6567 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 6568 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT))); 6569 } 6570 6571 SOC_IF_ERROR_RETURN 6572 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000)); /* deassert reset */ 6573 6574 return (SOC_E_NONE); 6575 } 6576 6577 STATIC int 6578 _phy_8481_prog_eeprom(int unit, phy_ctrl_t *pc) 6579 { 6580 soc_timeout_t to_prog; 6581 6582 /* write_addr=0xc300_0000, data=0x0000_002c, enable bottom write protection 6583 and set VINITHI signal to 0 */ 6584 6585 SOC_IF_ERROR_RETURN 6586 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000)); 6587 SOC_IF_ERROR_RETURN 6588 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300)); 6589 SOC_IF_ERROR_RETURN 6590 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, 0x002c)); 6591 SOC_IF_ERROR_RETURN 6592 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000)); 6593 SOC_IF_ERROR_RETURN 6594 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 6595 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT))); 6596 6597 SOC_IF_ERROR_RETURN 6598 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040)); 6599 SOC_IF_ERROR_RETURN 6600 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000)); 6601 6602 soc_timeout_init(&to_prog, 10000000, 0); 6603 6604 do { 6605 soc_timeout_t to_status; 6606 int rv; 6607 uint16 status, data_low, data_high; 6608 6609 SOC_IF_ERROR_RETURN 6610 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0010)); 6611 SOC_IF_ERROR_RETURN 6612 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300)); 6613 SOC_IF_ERROR_RETURN 6614 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 6615 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_RD_SHIFT))); 6616 6617 soc_timeout_init(&to_status, 10000, 0); 6618 6619 do { 6620 rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status); 6621 if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) || 6622 SOC_FAILURE(rv)) { 6623 break; 6624 } 6625 } while (!soc_timeout_check(&to_status)); 6626 6627 if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) { 6628 SOC_IF_ERROR_RETURN 6629 (WRITE_PHY8481_MDIO2ARM_CTL_REG( unit, pc, 0 )); 6630 LOG_WARN(BSL_LS_SOC_PHY, 6631 (BSL_META_U(unit, 6632 "PHY8481 MDIO2ARM read failed: u=%d p=%d\n"), unit, pc->port )); 6633 return (SOC_E_FAIL); 6634 } 6635 6636 SOC_IF_ERROR_RETURN 6637 (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data_low)); 6638 SOC_IF_ERROR_RETURN 6639 (READ_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, &data_high)); 6640 6641 if ( (data_low == 0x600d) || (data_high == 0x600d) ) { 6642 return (SOC_E_NONE); 6643 } 6644 6645 if ( (data_low == 0xdead) || (data_high == 0xdead) ) { 6646 return (SOC_E_FAIL); 6647 } 6648 6649 } while(!soc_timeout_check(&to_prog)); 6650 6651 LOG_WARN(BSL_LS_SOC_PHY, 6652 (BSL_META_U(unit, 6653 "PHY8481 firmware programming timed out !.: u=%d p=%d\n"), unit, pc->port )); 6654 6655 return (SOC_E_FAIL); 6656 } 6657 6658 STATIC int 6659 _phy_8481_restart(int unit, phy_ctrl_t *pc) 6660 { 6661 SOC_IF_ERROR_RETURN 6662 (MODIFY_PHY8481_PMAD_CTRLr(unit, pc, MII_CTRL_RESET, MII_CTRL_RESET)); 6663 6664 return (SOC_E_NONE); 6665 } 6666 6667 #define WRITE_BLK_SIZE 4 6668 6669 /* This routine should be used only when the ARM CPU is halted/looping. */ 6670 6671 STATIC int 6672 _phy_8481_write_to_arm(int unit, phy_ctrl_t *pc, uint32 addr, uint8 *data,int len) 6673 { 6674 int n_writes, i; 6675 6676 #ifdef PHY8481_MEASSURE_DOWNLOAD_TIME 6677 sal_usecs_t t; 6678 t = sal_time_usecs(); 6679 #endif 6680 6681 n_writes = (len + WRITE_BLK_SIZE -1) / WRITE_BLK_SIZE; 6682 6683 SOC_IF_ERROR_RETURN 6684 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 6685 (1U << MDIO2ARM_CTL_MDIO2ARM_SELF_INC_ADDR_SHIFT) 6686 | (1U << MDIO2ARM_CTL_MDIO2ARM_BURST_SHIFT) 6687 | (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT) 6688 | (1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT))); 6689 6690 SOC_IF_ERROR_RETURN 6691 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff))); 6692 SOC_IF_ERROR_RETURN 6693 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff))); 6694 6695 for ( i = 0; i < n_writes; i++ ) { 6696 6697 SOC_IF_ERROR_RETURN 6698 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 6699 ((*( data + WRITE_BLK_SIZE/2 + 1 ))<<8)|( *( data + WRITE_BLK_SIZE/2 )))); 6700 SOC_IF_ERROR_RETURN 6701 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, ((*( data + 1 ))<<8)|(*( data + 0 )))); 6702 6703 data += WRITE_BLK_SIZE; 6704 6705 } 6706 SOC_IF_ERROR_RETURN 6707 (WRITE_PHY8481_MDIO2ARM_CTL_REG( unit, pc, 0 )); 6708 6709 #ifdef PHY8481_MEASSURE_DOWNLOAD_TIME 6710 LOG_CLI((BSL_META_U(unit, 6711 "u=%d p=%d raw download took %u us\n"), unit, pc->port, SAL_USECS_SUB(sal_time_usecs(), t))); 6712 #endif 6713 6714 return (SOC_E_NONE); 6715 } 6716 6717 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT 6718 6719 #define READ_BLK_SIZE 4 6720 6721 STATIC int 6722 _phy_8481_read_from_arm(int unit, phy_ctrl_t *pc, uint32 addr, uint8 *data, int len) 6723 { 6724 soc_timeout_t to; 6725 int rv; 6726 int n_reads, i; 6727 uint16 data16_high, data16_low, status; 6728 6729 n_reads = (len + READ_BLK_SIZE -1) / READ_BLK_SIZE; 6730 6731 SOC_IF_ERROR_RETURN 6732 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, (1U << MDIO2ARM_CTL_MDIO2ARM_SELF_INC_ADDR_SHIFT) | 6733 (1U << MDIO2ARM_CTL_MDIO2ARM_BURST_SHIFT) | 6734 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT) | 6735 (1U << MDIO2ARM_CTL_MDIO2ARM_RD_SHIFT))); 6736 6737 SOC_IF_ERROR_RETURN 6738 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff))); 6739 SOC_IF_ERROR_RETURN 6740 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff))); 6741 6742 SOC_IF_ERROR_RETURN 6743 (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data16_low)); /* dummy read */ 6744 6745 for ( i = 0; i < n_reads; i++ ) { 6746 6747 soc_timeout_init(&to, 10000, 0); 6748 do { 6749 rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status); 6750 if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) || 6751 SOC_FAILURE(rv)) { 6752 break; 6753 } 6754 } while (!soc_timeout_check(&to)); 6755 if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) { 6756 LOG_WARN(BSL_LS_SOC_PHY, 6757 (BSL_META_U(unit, 6758 "PHY8481 MDIO2ARM read failed: u=%d p=%d addr=%08x\n"), unit, pc->port, addr)); 6759 return (SOC_E_FAIL); 6760 } 6761 SOC_IF_ERROR_RETURN 6762 (READ_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, &data16_high)); 6763 SOC_IF_ERROR_RETURN 6764 (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data16_low)); /* causes auto inc of addr */ 6765 6766 *(data++) = data16_low & 0xff; 6767 *(data++) = (data16_low>>8) & 0xff; 6768 *(data++) = data16_high & 0xff; 6769 *(data++) = (data16_high>>8) & 0xff; 6770 } 6771 6772 SOC_IF_ERROR_RETURN 6773 (WRITE_PHY8481_MDIO2ARM_CTL_REG( unit, pc, 0 )); 6774 6775 return (SOC_E_NONE); 6776 } 6777 #endif /* BCM848XX_STATE_MFG_DIAG_SUPPORT */ 6778 6779 /* This routine could be used while the ARM CPU is running. */ 6780 6781 STATIC int 6782 _phy_8481_mdio2arm_read(int unit, soc_port_t port, uint32 addr, uint32 *val, int access32) 6783 { 6784 soc_timeout_t to; 6785 int rv; 6786 uint16 data_low = 0, data_high = 0, status; 6787 phy_ctrl_t *pc; 6788 6789 pc = EXT_PHY_SW_STATE(unit, port); 6790 6791 SOC_IF_ERROR_RETURN 6792 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff))); 6793 SOC_IF_ERROR_RETURN 6794 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff))); 6795 6796 SOC_IF_ERROR_RETURN 6797 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 6798 ((access32 ? 2U : 1U) << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT) | 6799 (1U << MDIO2ARM_CTL_MDIO2ARM_RD_SHIFT))); 6800 6801 soc_timeout_init(&to, 10000, 0); 6802 6803 do { 6804 rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status); 6805 if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) || 6806 SOC_FAILURE(rv)) { 6807 break; 6808 } 6809 } while (!soc_timeout_check(&to)); 6810 if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) { 6811 LOG_WARN(BSL_LS_SOC_PHY, 6812 (BSL_META_U(unit, 6813 "PHY8481 MDIO2ARM read failed: u=%d p=%d addr=%08x\n"), unit, port, addr)); 6814 return (SOC_E_FAIL); 6815 } 6816 6817 SOC_IF_ERROR_RETURN 6818 (READ_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, &data_low)); 6819 6820 if (access32) { 6821 SOC_IF_ERROR_RETURN 6822 (READ_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, &data_high)); 6823 } 6824 6825 *val = (data_high<<16)|data_low; 6826 6827 return (SOC_E_NONE); 6828 6829 } 6830 6831 /* This routine could be used while the ARM CPU is running. */ 6832 6833 STATIC int 6834 _phy_8481_mdio2arm_write(int unit, soc_port_t port, uint32 addr, uint32 val, int access32) 6835 { 6836 soc_timeout_t to; 6837 int rv; 6838 uint16 status; 6839 phy_ctrl_t *pc; 6840 6841 pc = EXT_PHY_SW_STATE(unit, port); 6842 6843 SOC_IF_ERROR_RETURN 6844 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, (addr & 0xffff))); 6845 SOC_IF_ERROR_RETURN 6846 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, ((addr>>16) & 0xffff))); 6847 6848 SOC_IF_ERROR_RETURN 6849 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, (val & 0xffff))); 6850 6851 if (access32) { 6852 SOC_IF_ERROR_RETURN 6853 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, ((val>>16) & 0xffff))); 6854 } 6855 6856 SOC_IF_ERROR_RETURN 6857 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 6858 ((access32 ? 2U : 1U) << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)| 6859 (1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT))); 6860 6861 soc_timeout_init(&to, 10000, 0); 6862 6863 do { 6864 rv = READ_PHY8481_MDIO2ARM_STS_REG(unit, pc, &status); 6865 if (((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) != 0) || 6866 SOC_FAILURE(rv)) { 6867 break; 6868 } 6869 } while (!soc_timeout_check(&to)); 6870 if ((status & MDIO2ARM_STS_MDIO2ARM_DONE_MASK) == 0) { 6871 LOG_WARN(BSL_LS_SOC_PHY, 6872 (BSL_META_U(unit, 6873 "PHY8481 MDIO2ARM write failed: u=%d p=%d addr=%08x\n"), unit, port, addr)); 6874 return (SOC_E_FAIL); 6875 } 6876 6877 return (SOC_E_NONE); 6878 6879 } 6880 6881 int 6882 _phy_8481_mdio2arm_read32(int unit, soc_port_t port, uint32 addr, uint32 *val) 6883 { 6884 SOC_IF_ERROR_RETURN 6885 (_phy_8481_mdio2arm_read(unit, port, addr, val, TRUE)); 6886 return (SOC_E_NONE); 6887 } 6888 6889 int 6890 _phy_8481_mdio2arm_write32(int unit, soc_port_t port, uint32 addr, uint32 val) 6891 { 6892 SOC_IF_ERROR_RETURN 6893 (_phy_8481_mdio2arm_write(unit, port, addr, val, TRUE)); 6894 return (SOC_E_NONE); 6895 } 6896 6897 #ifdef PHY8481_ARM_MEM_DEBUG 6898 6899 int 6900 _phy_8481_mdio2arm_read16(int unit, soc_port_t port, uint32 addr, uint16 *val) 6901 { 6902 uint32 data; 6903 6904 SOC_IF_ERROR_RETURN 6905 (_phy_8481_mdio2arm_read(unit, port, addr, &data, FALSE)); 6906 *val = data; 6907 6908 return (SOC_E_NONE); 6909 } 6910 6911 int 6912 _phy_8481_mdio2arm_write16(int unit, soc_port_t port, uint32 addr, uint16 val) 6913 { 6914 SOC_IF_ERROR_RETURN 6915 (_phy_8481_mdio2arm_write(unit, port, addr, (uint32)val, FALSE)); 6916 return (SOC_E_NONE); 6917 } 6918 6919 6920 int 6921 _phy_8481_show_arm16(int unit, soc_port_t port, uint32 addr) 6922 { 6923 uint16 data; 6924 6925 SOC_IF_ERROR_RETURN 6926 (_phy_8481_mdio2arm_read16(unit, port, addr, &data)); 6927 6928 LOG_CLI((BSL_META_U(unit, 6929 "Value = %04x\n"), data)); 6930 6931 return (SOC_E_NONE); 6932 } 6933 6934 int 6935 _phy_8481_show_arm32(int unit, soc_port_t port, uint32 addr) 6936 { 6937 uint32 data; 6938 6939 SOC_IF_ERROR_RETURN 6940 (_phy_8481_mdio2arm_read32(unit, port, addr, &data)); 6941 6942 LOG_CLI((BSL_META_U(unit, 6943 "Value = %08x\n"), data)); 6944 6945 return (SOC_E_NONE); 6946 } 6947 6948 #endif 6949 6950 /* 6951 * Function: 6952 * phy_8481_firmware_set 6953 * Purpose: 6954 * program the given firmware into the SPI-ROM 6955 * Parameters: 6956 * unit - StrataSwitch unit #. 6957 * port - StrataSwitch port #. 6958 * offset - offset to the data stream 6959 * array - the given data 6960 * datalen- the data length 6961 * Returns: 6962 * SOC_E_NONE 6963 */ 6964 6965 STATIC int 6966 phy_8481_firmware_set(int unit, int port, int offset, uint8 *data,int len) 6967 { 6968 phy_ctrl_t *pc; 6969 uint16 saved_phy_addr, data16; 6970 int dividend, divisor, rv = SOC_E_FAIL; 6971 uint16 temp1, temp2; 6972 6973 pc = EXT_PHY_SW_STATE(unit, port); 6974 6975 if (data) { 6976 if ((!PHY_COPPER_MODE(unit, port)) && NXT_PC(pc)) { 6977 /* there is a PHY device connected to this XAUI port. Always program the 6978 * outmost PHY device. To program the next external device in the chain, 6979 * detach/remove the outmost phy device first 6980 */ 6981 PHYDRV_CALL_ARG3(pc,PHY_FIRMWARE_SET,offset,data,len); 6982 return SOC_E_NONE; 6983 } 6984 LOG_CLI((BSL_META_U(unit, 6985 "Step 1: Halting the system.\n"))); 6986 6987 SOC_IF_ERROR_RETURN 6988 (_phy_8481_halt(unit, pc)); 6989 6990 LOG_CLI((BSL_META_U(unit, 6991 "Step 2: Uploading the SPI loader and data" 6992 " into main memory.\n"))); 6993 6994 SOC_IF_ERROR_RETURN 6995 (_phy_8481_write_to_arm(unit, pc, (uint32) offset, data, len)); 6996 6997 LOG_CLI((BSL_META_U(unit, 6998 "Step 3: Waiting for the Programming phase" 6999 " to be completed.\n"))); 7000 7001 SOC_IF_ERROR_RETURN 7002 (_phy_8481_prog_eeprom(unit, pc)); 7003 7004 LOG_CLI((BSL_META_U(unit, 7005 "Step 4: Restarting system.\n"))); 7006 7007 SOC_IF_ERROR_RETURN 7008 (_phy_8481_restart(unit, pc)); 7009 } else { 7010 switch (offset) { 7011 case PHYCTRL_UCODE_BCST_SETUP: 7012 if ( ! PHY_IS_BCM8485X_AND_UP(pc) ) { 7013 /* Turn on broadcast mode */ 7014 SOC_IF_ERROR_RETURN 7015 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x411e,0xf003)); 7016 SOC_IF_ERROR_RETURN 7017 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x410e,0x0401)); 7018 } 7019 /* halt the system */ 7020 SOC_IF_ERROR_RETURN( _phy_8481_halt(unit, pc) ); 7021 break; 7022 case PHYCTRL_UCODE_BCST_uC_SETUP: 7023 break; 7024 case PHYCTRL_UCODE_BCST_ENABLE: 7025 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 7026 /* Turn on broadcast mode after halting system */ 7027 SOC_IF_ERROR_RETURN 7028 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4117, 0xf003)); 7029 SOC_IF_ERROR_RETURN 7030 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4107, 0x0401)); 7031 } 7032 break; 7033 case PHYCTRL_UCODE_BCST_LOAD: 7034 saved_phy_addr = pc->phy_id; 7035 pc->phy_id &= ~0x1f; 7036 SOC_IF_ERROR_RETURN 7037 (READ_PHY8481_PMAD_REG(unit, pc, 0x2, &temp1)); 7038 SOC_IF_ERROR_RETURN 7039 (READ_PHY8481_PMAD_REG(unit, pc, 0x3, &temp2)); 7040 if(temp1 != 0xffff) { 7041 if((temp1 != pc->phy_id0) || (temp2 != pc->phy_id1)) { 7042 LOG_WARN(BSL_LS_SOC_PHY, 7043 (BSL_META_U(unit, 7044 "Another PHY already exist on same boradcast MDIO address.\n"))); 7045 } 7046 } 7047 7048 if (DL_DIVIDEND(pc) && DL_DIVISOR(pc)) { 7049 rv = soc_cmic_rate_param_get(unit, ÷nd, &divisor); 7050 if (SOC_SUCCESS(rv)) { 7051 rv = soc_cmic_rate_param_set(unit, DL_DIVIDEND(pc), DL_DIVISOR(pc)); 7052 } 7053 } 7054 7055 SOC_IF_ERROR_RETURN 7056 (_phy_8481_write_to_arm(unit, pc, 0, FIRMWARE(pc), FIRMWARE_LEN(pc))); 7057 /* write_addr=0xc300_0000, data=0x0000_000c, enable bottom write protection 7058 and set VINITHI signal to 0 (reset vector at 0x0000_0000) */ 7059 7060 data16 = (PHY_IS_BCM8485X_AND_UP(pc)) ? 0x0000 : 0x000c; 7061 SOC_IF_ERROR_RETURN 7062 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 0x0000)); 7063 SOC_IF_ERROR_RETURN 7064 (WRITE_PHY8481_MDIO2ARM_ADDR_LOW_REG(unit, pc, 0x0000)); 7065 SOC_IF_ERROR_RETURN 7066 (WRITE_PHY8481_MDIO2ARM_ADDR_HIGH_REG(unit, pc, 0xc300)); 7067 SOC_IF_ERROR_RETURN 7068 (WRITE_PHY8481_MDIO2ARM_DATA_LOW_REG(unit, pc, data16)); 7069 SOC_IF_ERROR_RETURN 7070 (WRITE_PHY8481_MDIO2ARM_DATA_HIGH_REG(unit, pc, 0x0000)); 7071 SOC_IF_ERROR_RETURN 7072 (WRITE_PHY8481_MDIO2ARM_CTL_REG(unit, pc, 7073 (2U << MDIO2ARM_CTL_MDIO2ARM_SIZE_SHIFT)|(1U << MDIO2ARM_CTL_MDIO2ARM_WR_SHIFT))); 7074 7075 if (SOC_SUCCESS(rv)) { 7076 /* rv contains the return value of previous soc_cmic_rate_param_set() */ 7077 SOC_IF_ERROR_RETURN 7078 (soc_cmic_rate_param_set(unit, dividend, divisor)); 7079 } 7080 pc->phy_id = saved_phy_addr; 7081 break; 7082 case PHYCTRL_UCODE_BCST_END: 7083 /* Turn off broadcast mode */ 7084 if (PHY_IS_BCM8485X_AND_UP(pc)) { 7085 /* Before reset the processor, add OSF setting for all ports */ 7086 SOC_IF_ERROR_RETURN 7087 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA817 , 0x0000)); 7088 SOC_IF_ERROR_RETURN 7089 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA008 , 0x0000)); 7090 SOC_IF_ERROR_RETURN 7091 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x8004,0x5555)); 7092 if ( PHY_IS_BCM8488X(pc) ) { 7093 SOC_IF_ERROR_RETURN 7094 (WRITE_PHY8481_PMAD_REG(unit, pc, 0xA003 , 0x0000)); 7095 SOC_IF_ERROR_RETURN 7096 (WRITE_PHY8481_PMAD_REG(unit, pc, 0x0000 , 0x8000)); 7097 } else { 7098 SOC_IF_ERROR_RETURN 7099 (WRITE_PHY8481_PMAD_REG(unit, pc, 0x0000 , 0x8000)); 7100 SOC_IF_ERROR_RETURN 7101 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4107,0x0000)); 7102 } 7103 } else { 7104 SOC_IF_ERROR_RETURN 7105 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x410e,0x0000)); 7106 } 7107 7108 SOC_IF_ERROR_RETURN 7109 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &data16)); 7110 if (data16 & (1U << 13)) { 7111 /* Now reset only the ARM core */ 7112 SOC_IF_ERROR_RETURN 7113 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0040)); 7114 SOC_IF_ERROR_RETURN 7115 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 0x4181,0x0000)); 7116 } else { 7117 SOC_IF_ERROR_RETURN 7118 (MODIFY_PHY8481_PMAD_CTRLr(unit, pc, 7119 MII_CTRL_RESET, MII_CTRL_RESET)); 7120 } 7121 7122 if (PHY_IS_BCM8484X_A0(pc)) { 7123 sal_usleep(300000); 7124 } 7125 soc_timeout_init(&TO(pc), 2000000, 0); 7126 break; 7127 default: 7128 break; 7129 } 7130 } 7131 7132 return SOC_E_NONE; 7133 } 7134 7135 STATIC int 7136 _phy_84834_control_prbs_invert_data_set(int unit, soc_port_t port, 7137 int tx, int invert) 7138 { 7139 uint16 data16; 7140 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 7141 7142 data16 = (invert) ? PHY848XX_PRBS_INVERT_MASK : 0; 7143 if ( PHY_IS_BCM8488X_A0(pc) ) { 7144 /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */ 7145 uint32 reg32 = (tx) ? PHY848XX_TX_PRBS_ADDR32_REGISTER 7146 : PHY848XX_RX_PRBS_ADDR32_REGISTER; 7147 SOC_IF_ERROR_RETURN( 7148 _phy848xx_addr32_reg_modify(unit, pc, reg32, 7149 data16, PHY848XX_PRBS_INVERT_MASK) ); 7150 } else 7151 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 7152 uint32 reg = (tx) ? PHY8485X_TX_PRBS_REGISTER 7153 : PHY8485X_RX_PRBS_REGISTER; 7154 SOC_IF_ERROR_RETURN( 7155 MODIFY_PHY8481_PMAD_REG(unit, pc, reg, 7156 data16, PHY848XX_PRBS_INVERT_MASK) ); 7157 } 7158 else { /* 8483x / 8484x */ 7159 uint16 mask16; 7160 if ( tx ) { 7161 data16 = (invert) ? PHY84834_USER_PRBS_TX_INVERT : 0; 7162 mask16 = PHY84834_USER_PRBS_TX_INVERT; 7163 } else { 7164 data16 = (invert) ? PHY84834_USER_PRBS_RX_INVERT : 0; 7165 mask16 = PHY84834_USER_PRBS_RX_INVERT; 7166 } 7167 SOC_IF_ERROR_RETURN 7168 (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 7169 PHY84834_USER_PRBS_CONTROL_0_REGISTER, data16, mask16) ); 7170 } 7171 return SOC_E_NONE; 7172 } 7173 7174 STATIC int 7175 _phy_84834_control_prbs_polynomial_set(int unit, soc_port_t port, 7176 int poly_ctrl, int tx) /* tx or rx */ 7177 { 7178 phy_ctrl_t *pc; /* PHY software state */ 7179 uint16 data16; 7180 uint16 mask16; 7181 7182 /* 7183 * poly_ctrl: 7184 * 0x0 = prbs7 7185 * 0x1 = prbs15 7186 * 0x2 = prbs23 7187 * 0x3 = prbs31 7188 */ 7189 pc = EXT_PHY_SW_STATE(unit, port); 7190 7191 /* 001 : prbs7 7192 010 : prbs9 7193 011 : prbs11 7194 100 : prbs15 7195 101 : prbs23 7196 110 : prbs31 7197 */ 7198 7199 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 7200 if ( PHY_IS_BCM8488X(pc) ) { 7201 /* Turn on MDC clock for XFI */ 7202 SOC_IF_ERROR_RETURN( 7203 MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 7204 PHY8488X_MDIO_CLOCK_CONTROL_REGISTER, 7205 PHY8488X_EN_CLK_MDC_XFI_MASK, 7206 PHY8488X_EN_CLK_MDC_XFI_MASK) ); 7207 } 7208 7209 /* Change XGP table to point to XFI */ 7210 SOC_IF_ERROR_RETURN 7211 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 7212 PHY8485X_MDIO_CONTROL_REGISTER, 0x2004)); 7213 7214 if ( (poly_ctrl >= 0) && (poly_ctrl <= 6) ) { 7215 data16 = poly_ctrl << 1; 7216 } else { 7217 return SOC_E_PARAM; /* 8485x/6x/8x support polynominal 0-6 */ 7218 } 7219 7220 if ( PHY_IS_BCM8488X_A0(pc) ) { 7221 /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */ 7222 uint32 reg32 = (tx) ? PHY848XX_TX_PRBS_ADDR32_REGISTER 7223 : PHY848XX_RX_PRBS_ADDR32_REGISTER; 7224 SOC_IF_ERROR_RETURN( 7225 _phy848xx_addr32_reg_write(unit, pc, reg32, data16) ); 7226 } else { 7227 uint32 reg = (tx) ? PHY8485X_TX_PRBS_REGISTER 7228 : PHY8485X_RX_PRBS_REGISTER; 7229 SOC_IF_ERROR_RETURN( 7230 WRITE_PHY8481_PMAD_REG(unit, pc, reg, data16) ); 7231 } 7232 } 7233 else { /* 8483x / 8484x */ 7234 if (poly_ctrl == 0) { 7235 data16 = 1; 7236 } else if (poly_ctrl == 1) { 7237 data16 = 4; 7238 } else if (poly_ctrl == 2) { 7239 data16 = 5; 7240 } else if (poly_ctrl == 3) { 7241 data16 = 6; 7242 } else { 7243 return SOC_E_PARAM; 7244 } 7245 mask16 = PHY84834_USER_PRBS_TYPE_MASK; 7246 7247 /* default is tx */ 7248 if (!tx) { /* rx */ 7249 data16 = data16 << 12; 7250 mask16 = mask16 << 12; 7251 } 7252 7253 /* both tx/rx types */ 7254 SOC_IF_ERROR_RETURN 7255 (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 7256 PHY84834_USER_PRBS_CONTROL_0_REGISTER, 7257 data16, mask16)); 7258 } 7259 7260 return SOC_E_NONE; 7261 } 7262 7263 STATIC int 7264 _phy_84834_control_prbs_enable_set(int unit, soc_port_t port, int enable) 7265 { 7266 phy_ctrl_t *pc; /* PHY software state */ 7267 7268 pc = EXT_PHY_SW_STATE(unit, port); 7269 7270 if ( PHY_IS_BCM8485X_AND_UP(pc) ) { 7271 /* clear PRBS control if disabled */ 7272 if ( ! enable ) { /* disable Tx/Rx PRBS */ 7273 if ( PHY_IS_BCM8488X_A0(pc) ) { 7274 /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */ 7275 SOC_IF_ERROR_RETURN( 7276 _phy848xx_addr32_reg_modify(unit, pc, 7277 PHY848XX_TX_PRBS_ADDR32_REGISTER, 7278 0, PHY848XX_PRBS_ENABLE_MASK) ); 7279 SOC_IF_ERROR_RETURN( 7280 _phy848xx_addr32_reg_modify(unit, pc, 7281 PHY848XX_RX_PRBS_ADDR32_REGISTER, 7282 0, PHY848XX_PRBS_ENABLE_MASK) ); 7283 } else { 7284 SOC_IF_ERROR_RETURN 7285 (MODIFY_PHY8481_PMAD_REG(unit, pc, 7286 PHY8485X_TX_PRBS_REGISTER, 0, PHY8485X_USER_PRBS_TYPE_MASK)); 7287 SOC_IF_ERROR_RETURN 7288 (MODIFY_PHY8481_PMAD_REG(unit, pc, 7289 PHY8485X_RX_PRBS_REGISTER, 0, PHY8485X_USER_PRBS_TYPE_MASK)); 7290 } 7291 /* Restore XGP table to point to XFI */ 7292 SOC_IF_ERROR_RETURN 7293 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 7294 PHY8485X_MDIO_CONTROL_REGISTER, 0x3)); 7295 if ( PHY_IS_BCM8488X(pc) ) { 7296 /* Turn off MDC clock for XFI */ 7297 SOC_IF_ERROR_RETURN( 7298 MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 7299 PHY8488X_MDIO_CLOCK_CONTROL_REGISTER, 7300 0, PHY8488X_EN_CLK_MDC_XFI_MASK) ); 7301 } 7302 } else { /* enable PRBS generator/checker */ 7303 if ( PHY_IS_BCM8488X(pc) ) { 7304 /* Turn on MDC clock for XFI */ 7305 SOC_IF_ERROR_RETURN( 7306 MODIFY_PHY8481_TOPLVL1_REG(unit, pc, 7307 PHY8488X_MDIO_CLOCK_CONTROL_REGISTER, 7308 PHY8488X_EN_CLK_MDC_XFI_MASK, 7309 PHY8488X_EN_CLK_MDC_XFI_MASK) ); 7310 } 7311 /* Change XGP table to point to XFI */ 7312 SOC_IF_ERROR_RETURN 7313 (WRITE_PHY8481_TOPLVL1_REG(unit, pc, 7314 PHY8485X_MDIO_CONTROL_REGISTER, 0x2004)); 7315 7316 if ( PHY_IS_BCM8488X_A0(pc) ) { 7317 /* Orca A0 workaround: must use 32-bit addressing mode for PRBS */ 7318 SOC_IF_ERROR_RETURN( 7319 _phy848xx_addr32_reg_modify(unit, pc, 7320 PHY848XX_TX_PRBS_ADDR32_REGISTER, 7321 PHY848XX_PRBS_ENABLE_MASK, 7322 PHY848XX_PRBS_ENABLE_MASK) ); 7323 SOC_IF_ERROR_RETURN( 7324 _phy848xx_addr32_reg_modify(unit, pc, 7325 PHY848XX_RX_PRBS_ADDR32_REGISTER, 7326 PHY848XX_PRBS_ENABLE_MASK, 7327 PHY848XX_PRBS_ENABLE_MASK) ); 7328 } else { 7329 SOC_IF_ERROR_RETURN 7330 (MODIFY_PHY8481_PMAD_REG(unit, pc, 7331 PHY8485X_TX_PRBS_REGISTER, 1, PHY8485X_USER_PRBS_TYPE_MASK)); 7332 SOC_IF_ERROR_RETURN 7333 (MODIFY_PHY8481_PMAD_REG(unit, pc, 7334 PHY8485X_RX_PRBS_REGISTER, 1, PHY8485X_USER_PRBS_TYPE_MASK)); 7335 } 7336 } 7337 } else { 7338 /* clear PRBS control if disabled */ 7339 if (!enable) { 7340 SOC_IF_ERROR_RETURN 7341 (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 7342 PHY84834_USER_PRBS_CONTROL_0_REGISTER, 0, 7343 PHY84834_USER_PRBS_TYPE_MASK | 7344 PHY84834_USER_PRBS_TYPE_MASK << 12)); /* rx type*/ 7345 } 7346 7347 /* program the PRBS enable */ 7348 SOC_IF_ERROR_RETURN 7349 (MODIFY_PHY8481_PHYXS_M_REG(unit, pc, 7350 PHY84834_USER_PRBS_CONTROL_0_REGISTER, 7351 enable? PHY84834_USER_PRBS_ENABLE: 0,PHY84834_USER_PRBS_ENABLE)); 7352 } 7353 7354 return SOC_E_NONE; 7355 } 7356 7357 STATIC int 7358 _phy_84834_control_prbs_enable_get(int unit, soc_port_t port, uint32 *value) 7359 { 7360 uint16 data16; 7361 phy_ctrl_t *pc; /* PHY software state */ 7362 7363 pc = EXT_PHY_SW_STATE(unit, port); 7364 7365 if (PHY_IS_BCM8485X_AND_UP(pc)) { 7366 SOC_IF_ERROR_RETURN 7367 (READ_PHY8481_PMAD_REG(unit, pc, 7368 PHY8485X_TX_PRBS_REGISTER, &data16)); 7369 if (data16 & PHY8485X_USER_PRBS_TYPE_MASK) { 7370 *value = TRUE; 7371 } else { 7372 *value = FALSE; 7373 } 7374 } else { 7375 SOC_IF_ERROR_RETURN 7376 (READ_PHY8481_PHYXS_M_REG(unit, pc, 7377 PHY84834_USER_PRBS_CONTROL_0_REGISTER, &data16)); 7378 if (data16 & PHY84834_USER_PRBS_ENABLE) { 7379 *value = TRUE; 7380 } else { 7381 *value = FALSE; 7382 } 7383 } 7384 7385 return SOC_E_NONE; 7386 } 7387 7388 STATIC int 7389 _phy_84834_control_prbs_polynomial_get(int unit, soc_port_t port, uint32 *value) 7390 { 7391 phy_ctrl_t *pc; /* PHY software state */ 7392 uint16 poly_ctrl; 7393 7394 pc = EXT_PHY_SW_STATE(unit, port); 7395 7396 if (PHY_IS_BCM8485X_AND_UP(pc)) { 7397 SOC_IF_ERROR_RETURN 7398 (READ_PHY8481_PMAD_REG(unit, pc, 7399 PHY8485X_TX_PRBS_REGISTER, &poly_ctrl)); 7400 *value = (poly_ctrl & 0xE) >> 1; 7401 } else { 7402 SOC_IF_ERROR_RETURN 7403 (READ_PHY8481_PHYXS_M_REG(unit, pc, 7404 PHY84834_USER_PRBS_CONTROL_0_REGISTER, &poly_ctrl)); 7405 poly_ctrl &= PHY84834_USER_PRBS_TYPE_MASK; 7406 7407 if (poly_ctrl == 1) { 7408 *value = 0; 7409 } else if (poly_ctrl == 4) { 7410 *value = 1; 7411 } else if (poly_ctrl == 5) { 7412 *value = 2; 7413 } else if (poly_ctrl == 6) { 7414 *value = 3; 7415 } else { 7416 *value = poly_ctrl; 7417 } 7418 } 7419 return SOC_E_NONE; 7420 } 7421 7422 STATIC int 7423 _phy_84834_control_prbs_tx_invert_data_get(int unit, soc_port_t port, uint32 *value) 7424 { 7425 phy_ctrl_t *pc; /* PHY software state */ 7426 uint16 data16; 7427 7428 pc = EXT_PHY_SW_STATE(unit, port); 7429 7430 if (PHY_IS_BCM8485X_AND_UP(pc)) { 7431 *value = FALSE; 7432 return SOC_E_UNAVAIL; 7433 } 7434 7435 SOC_IF_ERROR_RETURN 7436 (READ_PHY8481_PHYXS_M_REG(unit, pc, 7437 PHY84834_USER_PRBS_CONTROL_0_REGISTER, &data16)); 7438 if (data16 & PHY84834_USER_PRBS_TX_INVERT) { 7439 *value = TRUE; 7440 } else { 7441 *value = FALSE; 7442 } 7443 return SOC_E_NONE; 7444 } 7445 7446 STATIC int 7447 _phy_84834_control_prbs_rx_status_get(int unit, soc_port_t port, uint32 *value) 7448 { 7449 phy_ctrl_t *pc; /* PHY software state */ 7450 uint16 data16; 7451 uint16 err_cnt_low, err_cnt_high; 7452 uint32 err_cnt = 0; 7453 7454 pc = EXT_PHY_SW_STATE(unit, port); 7455 7456 if (PHY_IS_BCM8485X_AND_UP(pc)) { 7457 /* Read register 0xD0D9 twice */ 7458 SOC_IF_ERROR_RETURN 7459 (READ_PHY8481_PMAD_REG(unit, pc, 7460 PHY8485X_PRBS_STATUS_REGISTER, &data16)); 7461 SOC_IF_ERROR_RETURN 7462 (READ_PHY8481_PMAD_REG(unit, pc, 7463 PHY8485X_PRBS_STATUS_REGISTER, &data16)); 7464 7465 /* Read error count register twice */ 7466 SOC_IF_ERROR_RETURN 7467 (READ_PHY8481_PMAD_REG(unit, pc, 7468 PHY8485X_PRBS_ERR_COUNT_LSB_REGSTER, &err_cnt_low)); 7469 SOC_IF_ERROR_RETURN 7470 (READ_PHY8481_PMAD_REG(unit, pc, 7471 PHY8485X_PRBS_ERR_COUNT_LSB_REGSTER, &err_cnt_low)); 7472 SOC_IF_ERROR_RETURN 7473 (READ_PHY8481_PMAD_REG(unit, pc, 7474 PHY8485X_PRBS_ERR_COUNT_MSB_REGSTER, &err_cnt_high)); 7475 SOC_IF_ERROR_RETURN 7476 (READ_PHY8481_PMAD_REG(unit, pc, 7477 PHY8485X_PRBS_ERR_COUNT_MSB_REGSTER, &err_cnt_high)); 7478 7479 err_cnt = (err_cnt_high << 16) | err_cnt_low; 7480 7481 if ((!err_cnt) && (data16 & 0x1)) { 7482 *value = 0; 7483 } else if (err_cnt) { 7484 *value = err_cnt; 7485 } else { 7486 *value = -1; 7487 } 7488 } else { 7489 *value = 0; 7490 SOC_IF_ERROR_RETURN 7491 (READ_PHY8481_PHYXS_M_REG(unit, pc, 7492 PHY84834_USER_PRBS_STATUS_0_REGISTER, &data16)); 7493 if (data16 == 0x8000) { /* PRBS lock and error free */ 7494 *value = 0; 7495 } else if (!(data16 & 0x8000)) { 7496 *value = -1; 7497 } else { 7498 *value = data16 & 0x7fff; 7499 } 7500 } 7501 7502 return SOC_E_NONE; 7503 } 7504 7505 7506 STATIC int 7507 _phy_84834_remote_loopback_set(int unit, soc_port_t port,int intf,uint32 enable) 7508 { 7509 phy_ctrl_t *pc; /* PHY software state */ 7510 7511 pc = EXT_PHY_SW_STATE(unit, port); 7512 7513 if (intf == PHY_DIAG_INTF_SYS) { 7514 SOC_IF_ERROR_RETURN 7515 (MODIFY_PHY8481_PHYXS_M_REG(unit,pc, 0x0000, 7516 enable ? (1<<14):0, (1<<14))); 7517 } 7518 return SOC_E_NONE; 7519 } 7520 7521 7522 /* 7523 * Function: 7524 * phy_84834_control_set 7525 * Purpose: 7526 * Configure PHY device specific control fucntion. 7527 * Parameters: 7528 * unit - StrataSwitch unit #. 7529 * port - StrataSwitch port #. 7530 * type - Control to update 7531 * value - New setting for the control 7532 * Returns: 7533 * SOC_E_NONE 7534 */ 7535 STATIC int 7536 _phy_84834_control_set(int unit, soc_port_t port, int intf,int lane, 7537 soc_phy_control_t type, uint32 value) 7538 { 7539 #if 0 7540 phy_ctrl_t *pc; /* PHY software state */ 7541 #endif 7542 int rv; 7543 7544 #if 0 7545 pc = EXT_PHY_SW_STATE(unit, port); 7546 #endif 7547 7548 PHY_CONTROL_TYPE_CHECK(type); 7549 7550 rv = SOC_E_UNAVAIL; 7551 #if 0 7552 if (intf == PHY_DIAG_INTF_SYS) { 7553 /* if is targeted to the system side */ 7554 SOC_IF_ERROR_RETURN 7555 (PHY84740_XFI(unit,pc)); 7556 } 7557 #endif 7558 switch(type) { 7559 case SOC_PHY_CONTROL_PREEMPHASIS: 7560 /* fall through */ 7561 case SOC_PHY_CONTROL_DRIVER_CURRENT: 7562 /* fall through */ 7563 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 7564 rv = _phy_8481_control_tx_driver_set(unit, port, type, value); 7565 break; 7566 #if 0 7567 case SOC_PHY_CONTROL_EDC_MODE: 7568 rv = _phy_84740_control_edc_mode_set(unit,port,value); 7569 break; 7570 case SOC_PHY_CONTROL_CLOCK_ENABLE: 7571 rv = _phy_84740_control_recovery_clock_set(unit,port,value); 7572 break; 7573 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 7574 rv = _phy_84740_control_recovery_clock_freq_set(unit,port,value); 7575 break; 7576 #endif 7577 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 7578 if (intf != PHY_DIAG_INTF_SYS) { 7579 /* PRBS line side not supported */ 7580 rv = SOC_E_UNAVAIL; 7581 } 7582 else { 7583 /* on line side, rx poly type is auto-detected. On system side, 7584 * need to enable the rx type as well. 7585 */ 7586 rv = _phy_84834_control_prbs_polynomial_set(unit, port, value, TRUE); 7587 if (intf == PHY_DIAG_INTF_SYS) { 7588 rv = _phy_84834_control_prbs_polynomial_set(unit, port,value,FALSE); 7589 } 7590 } 7591 break; 7592 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 7593 /* on line side, rx invertion is auto-detected. On system side, 7594 * need to enable the rx as well. 7595 */ 7596 rv = _phy_84834_control_prbs_invert_data_set(unit, port, 2, value); 7597 if (intf == PHY_DIAG_INTF_SYS) { 7598 rv |= _phy_84834_control_prbs_invert_data_set(unit, port, 1, value); 7599 } 7600 break; 7601 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 7602 /* fall through */ 7603 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 7604 /* tx/rx is enabled at the same time. no seperate control */ 7605 rv = _phy_84834_control_prbs_enable_set(unit, port, value); 7606 break; 7607 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 7608 rv = _phy_84834_remote_loopback_set(unit, port,PHY_DIAG_INTF_SYS,value); 7609 break; 7610 default: 7611 rv = SOC_E_UNAVAIL; 7612 break; 7613 } 7614 #if 0 7615 if (intf == PHY_DIAG_INTF_SYS) { 7616 /* if it is targeted to the system side, switch back */ 7617 SOC_IF_ERROR_RETURN 7618 (PHY84740_MMF(unit,pc)); 7619 } 7620 #endif 7621 return rv; 7622 } 7623 7624 /* 7625 * Function: 7626 * phy_84834_control_get 7627 * Purpose: 7628 * Get current control settign of the PHY. 7629 * Parameters: 7630 * unit - StrataSwitch unit #. 7631 * port - StrataSwitch port #. 7632 * type - Control to update 7633 * value - (OUT)Current setting for the control 7634 * Returns: 7635 * SOC_E_NONE 7636 */ 7637 STATIC int 7638 _phy_84834_control_get(int unit, soc_port_t port, int intf,int lane, 7639 soc_phy_control_t type, uint32 *value) 7640 { 7641 #if 0 7642 phy_ctrl_t *pc; /* PHY software state */ 7643 #endif 7644 int rv; 7645 /* uint16 data16; */ 7646 7647 #if 0 7648 pc = EXT_PHY_SW_STATE(unit, port); 7649 #endif 7650 7651 PHY_CONTROL_TYPE_CHECK(type); 7652 7653 #if 0 7654 if (intf == PHY_DIAG_INTF_SYS) { 7655 /* targeted to the system side */ 7656 SOC_IF_ERROR_RETURN 7657 (PHY84740_XFI(unit,pc)); 7658 } 7659 #endif 7660 rv = SOC_E_UNAVAIL; 7661 switch(type) { 7662 case SOC_PHY_CONTROL_PREEMPHASIS: 7663 /* fall through */ 7664 case SOC_PHY_CONTROL_DRIVER_CURRENT: 7665 /* fall through */ 7666 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 7667 rv = _phy_8481_control_tx_driver_get(unit, port, type, value); 7668 break; 7669 #if 0 7670 case SOC_PHY_CONTROL_EDC_MODE: 7671 rv = _phy_84740_control_edc_mode_get(unit,port,value); 7672 break; 7673 case SOC_PHY_CONTROL_CLOCK_ENABLE: 7674 SOC_IF_ERROR_RETURN 7675 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_REG, 7676 &data16)); 7677 *value = (data16 & PHY84740_RECOVERY_CLK_ENABLE_MASK)? TRUE: FALSE; 7678 rv = SOC_E_NONE; 7679 break; 7680 #endif 7681 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 7682 if (intf == PHY_DIAG_INTF_SYS) { 7683 rv = _phy_84834_control_prbs_polynomial_get(unit, port, value); 7684 } 7685 else { /* PRBS line side not supported */ 7686 rv = SOC_E_UNAVAIL; 7687 } 7688 break; 7689 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 7690 rv = _phy_84834_control_prbs_tx_invert_data_get(unit, port, value); 7691 break; 7692 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 7693 /* fall through */ 7694 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 7695 rv = _phy_84834_control_prbs_enable_get(unit, port, value); 7696 break; 7697 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 7698 rv = _phy_84834_control_prbs_rx_status_get(unit, port, value); 7699 break; 7700 #if 0 7701 case SOC_PHY_CONTROL_CLOCK_FREQUENCY: 7702 SOC_IF_ERROR_RETURN 7703 (READ_PHY84740_MMF_PMA_PMD_REG(unit,pc,PHY84740_PMAD_RECOVERY_CLK_FREQ_REG, 7704 &data16)); 7705 switch ((data16 >> PHY84740_RECOVERY_CLK_FREQ_SHIFT) & 0x3) { 7706 case 0x1: 7707 *value = 125000; 7708 break; 7709 case 0x2: 7710 *value = 195312; 7711 break; 7712 case 0x3: 7713 *value = 156250; 7714 break; 7715 default: 7716 *value = 0x0; 7717 break; 7718 } 7719 rv = SOC_E_NONE; 7720 break; 7721 #endif 7722 7723 default: 7724 rv = SOC_E_UNAVAIL; 7725 break; 7726 } 7727 7728 #if 0 7729 if (intf == PHY_DIAG_INTF_SYS) { 7730 /* if it is targeted to the system side, switch back */ 7731 SOC_IF_ERROR_RETURN 7732 (PHY84740_MMF(unit,pc)); 7733 } 7734 #endif 7735 return rv; 7736 } 7737 7738 7739 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT 7740 7741 STATIC int 7742 _phy_8481_mfg_test_fw_ready(int unit, phy_ctrl_t *pc, uint16 val, uint16 mask) 7743 { 7744 int rv; 7745 uint16 status; 7746 7747 soc_timeout_init(&TO(pc), 25000000, 0); 7748 do { 7749 sal_usleep(50000); 7750 rv = READ_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, &status); 7751 if ( SOC_FAILURE(rv) ) { 7752 break; /* failed to read register */ 7753 } 7754 7755 if ( (status & mask) == val ) { 7756 return SOC_E_NONE; /* status check OK */ 7757 } 7758 } while ( ! soc_timeout_check(&TO(pc)) ); 7759 7760 /* register read or status check failed */ 7761 LOG_WARN(BSL_LS_SOC_PHY, 7762 (BSL_META_U(unit, 7763 "PHY848X manufacturing diagnostics failed: unit=%d port=%d\n"), 7764 unit, pc->port)); 7765 return SOC_E_FAIL; 7766 } 7767 7768 STATIC int 7769 _phy_8481_mfg_test_set(int unit, soc_port_t port, int op_cmd, int arg) 7770 { 7771 phy_ctrl_t *pc; 7772 7773 pc = EXT_PHY_SW_STATE(unit, port); 7774 if ( ! (FLAGS(pc) & PHY8483X_MFG_TEST_SUPPORT) ) { 7775 return SOC_E_UNAVAIL; 7776 } 7777 7778 switch ( op_cmd ) { 7779 case PHY_DIAG_CTRL_MFG_HYB_CANC: 7780 case PHY_DIAG_CTRL_MFG_DENC: 7781 SOC_IF_ERROR_RETURN /* MFG Test init */ 7782 (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0xf003)); 7783 break; 7784 7785 case PHY_DIAG_CTRL_MFG_TX_ON: 7786 SOC_IF_ERROR_RETURN 7787 (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, (((arg & 0xf) << 12) | 0x3))); 7788 break; 7789 7790 case PHY_DIAG_CTRL_MFG_EXIT: 7791 SOC_IF_ERROR_RETURN 7792 (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0x7)); 7793 return SOC_E_NONE; 7794 7795 default: 7796 return SOC_E_UNAVAIL; 7797 } 7798 7799 if(!(PHY_IS_BCM8485X_AND_UP(pc))) { 7800 SOC_IF_ERROR_RETURN 7801 (MODIFY_PHY8481_PMD_IEEE_TST_MODE_10G_REG(unit, pc, (0x5 << 13), (0x7 << 13))); 7802 } else { 7803 SOC_IF_ERROR_RETURN 7804 (MODIFY_PHY8481_PMD_IEEE_TST_MODE_10G_REG(unit, pc, (0x1 << 13), (0x7 << 13))); 7805 } 7806 /* MFG Test init done. PHYC_CTL_SPARE_GRP5_REG should be reset to 0xF000 */ 7807 SOC_IF_ERROR_RETURN 7808 (_phy_8481_mfg_test_fw_ready(unit, pc, 0xf000, 0xffff)); 7809 7810 LOG_WARN(BSL_LS_SOC_PHY, 7811 (BSL_META_U(unit, 7812 "PHY848X manufacturing diagnostics init: unit=%d port=%d\n"), unit, port)); 7813 7814 return SOC_E_NONE; 7815 } 7816 #endif /* BCM848XX_STATE_MFG_DIAG_SUPPORT */ 7817 7818 #ifdef PHY8185X_DEBUG_CMD_HANDLER 7819 STATIC int 7820 _phy_8585x_generic_command_handler_test_get(int unit, phy_ctrl_t *pc) 7821 { 7822 uint16 status; 7823 7824 _phy8485x_emi_mode_enable_get(unit, pc, &status); 7825 _phy8485x_sub_lf_rf_status_get(unit, pc, &status); 7826 _phy8485x_snr_get(unit, pc); 7827 _phy8485x_current_temp_get(unit, pc); 7828 return SOC_E_NONE; 7829 } 7830 7831 STATIC int 7832 _phy_8585x_generic_command_handler_test_set(int unit, phy_ctrl_t *pc) 7833 { 7834 uint16 status = 1; 7835 7836 _phy8485x_emi_mode_enable_set(unit, pc, status); 7837 7838 return SOC_E_NONE; 7839 } 7840 #endif 7841 7842 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT 7843 STATIC int 7844 _phy_8481_mfg_test_get(int unit, soc_port_t port, int op_cmd, uint32 arg[]) 7845 { 7846 phy_ctrl_t *pc; 7847 uint16 status; 7848 int requested_cmd, data_len; 7849 7850 pc = EXT_PHY_SW_STATE(unit, port); 7851 if ( ! (FLAGS(pc) & PHY8483X_MFG_TEST_SUPPORT) ) { 7852 return SOC_E_UNAVAIL; 7853 } 7854 7855 switch ( op_cmd ) { 7856 case PHY_DIAG_CTRL_MFG_HYB_CANC: 7857 SOC_IF_ERROR_RETURN 7858 (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0x1)); 7859 break; 7860 case PHY_DIAG_CTRL_MFG_DENC: 7861 SOC_IF_ERROR_RETURN 7862 (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0x2)); 7863 break; 7864 7865 case PHY_DIAG_CTRL_MFG_TX_ON: 7866 break; 7867 case PHY_DIAG_CTRL_MFG_EXIT: 7868 return SOC_E_NONE; 7869 default: 7870 return SOC_E_UNAVAIL; 7871 } 7872 7873 /* MFG Test done. PHYC_CTL_SPARE_GRP5_REG[2:0] should be reset to 000 */ 7874 SOC_IF_ERROR_RETURN 7875 (_phy_8481_mfg_test_fw_ready(unit, pc, 0x0, 0x0007)); 7876 7877 switch (op_cmd) { 7878 case PHY_DIAG_CTRL_MFG_HYB_CANC: 7879 requested_cmd = 0x1; 7880 data_len = 770*4; 7881 break; 7882 case PHY_DIAG_CTRL_MFG_DENC: 7883 requested_cmd = 0x2; 7884 data_len = 44*4; 7885 break; 7886 case PHY_DIAG_CTRL_MFG_TX_ON: 7887 requested_cmd = 0x3; 7888 data_len = 0; 7889 break; 7890 /* 7891 * COVERITY 7892 * 7893 * This default is unreachable. It is kept intentionally as a defensive default for future development. 7894 */ 7895 /* coverity[dead_error_begin] */ 7896 default: 7897 return SOC_E_UNAVAIL; 7898 } 7899 7900 /* ACK from FW, should be identical to MFG_CMD in PHYC_CTL_SPARE_GRP5[2:0] */ 7901 SOC_IF_ERROR_RETURN 7902 (READ_PHY8481_PHYC_CTL_SPARE_GRP6_REG(unit, pc, &status)); 7903 if ( (status & 0x7) != requested_cmd ) { 7904 LOG_WARN(BSL_LS_SOC_PHY, 7905 (BSL_META_U(unit, 7906 "PHY848X manufacturing diagnostics command mismatch: u=%d p=%d\n"), unit, port)); 7907 return SOC_E_FAIL; 7908 } 7909 7910 if ( data_len ) { 7911 uint32 addr; 7912 SOC_IF_ERROR_RETURN 7913 (_phy_8481_mdio2arm_read(unit, port, 0xc300003c, &addr, 1)); 7914 SOC_IF_ERROR_RETURN 7915 (_phy_8481_read_from_arm(unit, pc, soc_ntohl_load(&addr), (uint8*)arg, data_len)); 7916 } 7917 7918 /* Turn off the transmission */ 7919 SOC_IF_ERROR_RETURN 7920 (WRITE_PHY8481_PHYC_CTL_SPARE_GRP5_REG(unit, pc, 0xf003)); 7921 SOC_IF_ERROR_RETURN /* and wait for the operation done */ 7922 (_phy_8481_mfg_test_fw_ready(unit, pc, 0xf000, 0xffff)); 7923 7924 LOG_WARN(BSL_LS_SOC_PHY, 7925 (BSL_META_U(unit, 7926 "PHY848X manufacturing diagnostics OK: unit=%d port=%d\n"), unit, port)); 7927 7928 return SOC_E_NONE; 7929 } 7930 7931 STATIC int 7932 _phy_8481_diag_dsc_get(phy_ctrl_t *pc) 7933 { 7934 #ifdef BCM848XX_DIAG_DSC_SUPPORT 7935 if ( PHY_IS_BCM8488X(pc) ) { 7936 set_intpc(pc); 7937 get_dsc_param_orca(); 7938 } else { 7939 set_pc(pc); 7940 get_dsc_param_koi(); 7941 } 7942 #else 7943 LOG_CLI((BSL_META_U(pc->unit, "*** Diag DSC not supported: " 7944 "unit=%d port=%d\n"), pc->unit, pc->port)); 7945 #endif 7946 7947 return SOC_E_NONE; 7948 } 7949 7950 STATIC int 7951 _phy_8481_state_test_set(int unit, soc_port_t port, int op_cmd, int arg) 7952 { 7953 phy_ctrl_t *pc; 7954 uint16 status; 7955 int rv; 7956 7957 pc = EXT_PHY_SW_STATE(unit, port); 7958 7959 if (!(FLAGS(pc) & PHY8483X_STATE_TEST_SUPPORT)) { 7960 return SOC_E_UNAVAIL; 7961 } 7962 switch (op_cmd) { 7963 case PHY_DIAG_CTRL_STATE_TRACE1: 7964 break; 7965 case PHY_DIAG_CTRL_STATE_TRACE2: 7966 break; 7967 case PHY_DIAG_CTRL_STATE_WHEREAMI: 7968 case PHY_DIAG_CTRL_STATE_TEMP: 7969 soc_timeout_init(&TO(pc), 7000000, 0); 7970 do { 7971 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 7972 if (PHY8481_IS_READY_FOR_CMD(pc, status) || SOC_FAILURE(rv)) { 7973 break; 7974 } 7975 } while (!soc_timeout_check(&TO(pc))); 7976 7977 if (!PHY8481_IS_OPEN_FOR_CMD(pc, status)) { 7978 LOG_CLI((BSL_META_U(unit, 7979 "_phy_8481_state_test_set not ready u=%d " 7980 "p=%d status=%04x\n"), 7981 unit, pc->port, status)); 7982 return SOC_E_FAIL; 7983 } 7984 SOC_IF_ERROR_RETURN 7985 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_0r(unit, pc, (op_cmd == PHY_DIAG_CTRL_STATE_WHEREAMI) ? 7986 PHY84834_DIAG_CMD_GET_SNR_V2 : PHY84834_DIAG_CMD_GET_CURRENT_TEMP_V2)); 7987 7988 soc_timeout_init(&TO(pc), 1000000, 0); 7989 break; 7990 case PHY_DIAG_CTRL_STATE_GENERIC: 7991 #ifdef PHY8185X_DEBUG_CMD_HANDLER 7992 if (PHY_IS_BCM8485X_AND_UP(pc)) { 7993 _phy_8585x_generic_command_handler_test_set(unit, pc); 7994 } else { 7995 return SOC_E_NONE; 7996 } 7997 #endif 7998 break; 7999 default: 8000 return SOC_E_UNAVAIL; 8001 } 8002 8003 return SOC_E_NONE; 8004 } 8005 8006 STATIC int 8007 _phy_8481_state_test_get(int unit, soc_port_t port, int op_cmd, uint32 arg[]) 8008 { 8009 phy_ctrl_t *pc; 8010 uint32 addr = 0; 8011 int len = 0, rv; 8012 XGPHY_DIAG_DATA_t *data = (XGPHY_DIAG_DATA_t *) arg; 8013 uint16 temp0, temp1, status; 8014 8015 pc = EXT_PHY_SW_STATE(unit, port); 8016 8017 if (!(FLAGS(pc) & PHY8483X_STATE_TEST_SUPPORT)) { 8018 return SOC_E_UNAVAIL; 8019 } 8020 8021 switch (op_cmd) { 8022 case PHY_DIAG_CTRL_STATE_TRACE1: 8023 addr = 0x50800; 8024 len = 2048*4; 8025 break; 8026 case PHY_DIAG_CTRL_STATE_TRACE2: 8027 addr = 0x53000; 8028 len = 1024*4; 8029 break; 8030 case PHY_DIAG_CTRL_STATE_WHEREAMI: 8031 case PHY_DIAG_CTRL_STATE_TEMP: 8032 do { 8033 rv = READ_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, &status); 8034 if (PHY8481_IS_CMD_COMPLETE(pc, status) || SOC_FAILURE(rv)) { 8035 break; 8036 } 8037 } while (!soc_timeout_check(&TO(pc))); 8038 if (PHY_IS_BCM8483X(pc) || PHY_IS_BCM8484X(pc)) { 8039 SOC_IF_ERROR_RETURN 8040 (WRITE_PHY84834_TOP_CONFIG_SCRATCH_26r(unit, pc, PHY84834_CMD_CLEAR_COMPLETE)); 8041 } 8042 if ((status & PHY84834_CMD_COMPLETE_PASS) == 0) { 8043 LOG_CLI((BSL_META_U(unit, 8044 "_phy_8481_state_test_get failed: u=%d p=%d " 8045 "status=%04x\n"), unit, pc->port, status)); 8046 return SOC_E_FAIL; 8047 } 8048 break; 8049 case PHY_DIAG_CTRL_STATE_GENERIC: 8050 #ifdef PHY8185X_DEBUG_CMD_HANDLER 8051 if (PHY_IS_BCM8485X_AND_UP(pc)) { 8052 _phy_8585x_generic_command_handler_test_get(unit, pc); 8053 } else { 8054 return SOC_E_NONE; 8055 } 8056 #endif 8057 break; 8058 default: 8059 return SOC_E_UNAVAIL; 8060 } 8061 8062 if (op_cmd == PHY_DIAG_CTRL_STATE_WHEREAMI) { 8063 if (PHY_IS_BCM8485X_AND_UP(pc)) { 8064 sal_memset(data->snr_block, 0, sizeof(data->snr_block)); 8065 8066 SOC_IF_ERROR_RETURN 8067 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &temp1)); /* DATA2 */ 8068 soc_htolel_store(&data->snr_block[16], temp1); 8069 soc_htolel_store(&data->snr_block[0], temp1); /* SNR OK */ 8070 8071 SOC_IF_ERROR_RETURN 8072 (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &temp1)); /* DATA3 */ 8073 soc_htolel_store(&data->snr_block[20], temp1); 8074 soc_htolel_store(&data->snr_block[4], temp1); /* SNR OK */ 8075 8076 SOC_IF_ERROR_RETURN 8077 (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &temp1)); /* DATA4 */ 8078 soc_htolel_store(&data->snr_block[24], temp1); 8079 soc_htolel_store(&data->snr_block[8], temp1); /* SNR OK */ 8080 8081 SOC_IF_ERROR_RETURN 8082 (READ_PHY84834_TOP_CONFIG_SCRATCH_31r(unit, pc, &temp1)); /* DATA5 */ 8083 soc_htolel_store(&data->snr_block[28], temp1); 8084 soc_htolel_store(&data->snr_block[12], temp1); /* SNR OK */ 8085 8086 data->serr = data->cerr = data->block_lock = data->block_point_id = 0; 8087 data->flags = FLAGS(pc) & PHY8483X_FULL_SNR_SUPPORT ? PHY_DIAG_FULL_SNR_SUPPORT : 0; 8088 } else { 8089 /* 8090 SOC_IF_ERROR_RETURN 8091 (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &dr1)); 8092 */ 8093 SOC_IF_ERROR_RETURN 8094 (READ_PHY84834_TOP_CONFIG_SCRATCH_29r(unit, pc, &temp1)); /* DATA3 */ 8095 SOC_IF_ERROR_RETURN 8096 (READ_PHY84834_TOP_CONFIG_SCRATCH_30r(unit, pc, &temp0)); /* DATA4 */ 8097 8098 SOC_IF_ERROR_RETURN 8099 (_phy_8481_read_from_arm(unit, pc, ((uint32)temp1) << 16 | temp0, 8100 data->snr_block, (FLAGS(pc) & PHY8483X_FULL_SNR_SUPPORT) ? sizeof(data->snr_block) : 16)); 8101 8102 temp1 = soc_letohl_load(&data->snr_block[16]) - 32768; 8103 soc_htolel_store(&data->snr_block[16], temp1); 8104 temp1 = soc_letohl_load(&data->snr_block[20]) - 32768; 8105 soc_htolel_store(&data->snr_block[20], temp1); 8106 temp1 = soc_letohl_load(&data->snr_block[24]) - 32768; 8107 soc_htolel_store(&data->snr_block[24], temp1); 8108 temp1 = soc_letohl_load(&data->snr_block[28]) - 32768; 8109 soc_htolel_store(&data->snr_block[28], temp1); 8110 8111 SOC_IF_ERROR_RETURN 8112 (READ_PHY8481_PMAD_REG(unit, pc, 0xb089,&temp0)); 8113 SOC_IF_ERROR_RETURN 8114 (READ_PHY8481_PMAD_REG(unit, pc, 0xb08a,&temp1)); 8115 data->serr = ((uint32)temp1) << 16 | temp0; 8116 8117 SOC_IF_ERROR_RETURN 8118 (READ_PHY8481_PMAD_REG(unit, pc, 0xb08b,&temp0)); 8119 SOC_IF_ERROR_RETURN 8120 (READ_PHY8481_PMAD_REG(unit, pc, 0xb08c,&temp1)); 8121 data->cerr = ((uint32)temp1) << 16 | temp0; 8122 8123 SOC_IF_ERROR_RETURN 8124 (READ_PHY8481_TOPLVL1_REG(unit, pc, 0x405c,&temp0)); 8125 SOC_IF_ERROR_RETURN 8126 (READ_PHY8481_PCS_REG(unit, pc, 0x21, &temp1)); 8127 SOC_IF_ERROR_RETURN 8128 (READ_PHY8481_PCS_REG(unit, pc, 0x21, &temp1)); /* read twice to clear latch */ 8129 data->block_point_id = temp0; 8130 data->block_lock = (temp1 >> 15) & 0x1; 8131 8132 data->flags = FLAGS(pc) & PHY8483X_FULL_SNR_SUPPORT ? PHY_DIAG_FULL_SNR_SUPPORT : 0; 8133 } 8134 8135 } else if (op_cmd == PHY_DIAG_CTRL_STATE_TEMP) { 8136 SOC_IF_ERROR_RETURN 8137 (READ_PHY84834_TOP_CONFIG_SCRATCH_27r(unit, pc, &data->digital_temp)); /* DATA1 */ 8138 SOC_IF_ERROR_RETURN 8139 (READ_PHY84834_TOP_CONFIG_SCRATCH_28r(unit, pc, &data->analog_temp)); /* DATA2 */ 8140 } else { 8141 SOC_IF_ERROR_RETURN 8142 (_phy_8481_read_from_arm(unit, pc, addr, (uint8 *)arg, len)); 8143 } 8144 8145 return SOC_E_NONE; 8146 } 8147 #endif /* BCM848XX_STATE_MFG_DIAG_SUPPORT */ 8148 8149 STATIC int 8150 phy_8481_diag_ctrl( 8151 int unit, /* unit */ 8152 soc_port_t port, /* port */ 8153 uint32 inst, /* the specific device block the control action directs to */ 8154 int op_type, /* operation types: read,write or command sequence */ 8155 int op_cmd, /* command code */ 8156 void *arg) /* command argument */ 8157 { 8158 #ifdef BCM848XX_STATE_MFG_DIAG_SUPPORT 8159 int lane; 8160 int intf; 8161 phy_ctrl_t *pc; 8162 8163 pc = EXT_PHY_SW_STATE(unit, port); 8164 8165 LOG_INFO(BSL_LS_SOC_PHY, 8166 (BSL_META_U(unit, 8167 "phy_8481_diag_ctrl: u=%d p=%d ctrl=0x%x\n"), 8168 unit, port,op_cmd)); 8169 8170 lane = PHY_DIAG_INST_LN(inst); 8171 intf = PHY_DIAG_INST_INTF(inst); 8172 if (intf == PHY_DIAG_INTF_DFLT) { 8173 intf = PHY_DIAG_INTF_LINE; 8174 } 8175 8176 if (op_type == PHY_DIAG_CTRL_GET) { 8177 switch (op_cmd) { 8178 case PHY_DIAG_CTRL_MFG_HYB_CANC: 8179 case PHY_DIAG_CTRL_MFG_DENC: 8180 case PHY_DIAG_CTRL_MFG_TX_ON: 8181 case PHY_DIAG_CTRL_MFG_EXIT: 8182 SOC_IF_ERROR_RETURN 8183 (_phy_8481_mfg_test_get(unit, port, 8184 op_cmd,(uint32 *)arg)); 8185 break; 8186 case PHY_DIAG_CTRL_STATE_TRACE1: 8187 case PHY_DIAG_CTRL_STATE_TRACE2: 8188 case PHY_DIAG_CTRL_STATE_WHEREAMI: 8189 case PHY_DIAG_CTRL_STATE_TEMP: 8190 case PHY_DIAG_CTRL_STATE_GENERIC: 8191 SOC_IF_ERROR_RETURN 8192 (_phy_8481_state_test_get(unit, port, 8193 op_cmd,(uint32 *)arg)); 8194 break; 8195 default: 8196 SOC_IF_ERROR_RETURN 8197 (_phy_84834_control_get(unit, port, intf, lane, 8198 op_cmd,(uint32 *)arg)); 8199 break; 8200 } 8201 } else if (op_type == PHY_DIAG_CTRL_SET) { 8202 switch (op_cmd) { 8203 case PHY_DIAG_CTRL_MFG_HYB_CANC: 8204 case PHY_DIAG_CTRL_MFG_DENC: 8205 case PHY_DIAG_CTRL_MFG_TX_ON: 8206 case PHY_DIAG_CTRL_MFG_EXIT: 8207 SOC_IF_ERROR_RETURN 8208 (_phy_8481_mfg_test_set(unit, port, 8209 op_cmd, PTR_TO_INT(arg))); 8210 break; 8211 case PHY_DIAG_CTRL_STATE_TRACE1: 8212 case PHY_DIAG_CTRL_STATE_TRACE2: 8213 case PHY_DIAG_CTRL_STATE_WHEREAMI: 8214 case PHY_DIAG_CTRL_STATE_TEMP: 8215 case PHY_DIAG_CTRL_STATE_GENERIC: 8216 SOC_IF_ERROR_RETURN 8217 (_phy_8481_state_test_set(unit, port, 8218 op_cmd, PTR_TO_INT(arg))); 8219 break; 8220 default: 8221 SOC_IF_ERROR_RETURN 8222 (_phy_84834_control_set(unit, port, intf, lane, 8223 op_cmd, PTR_TO_INT(arg))); 8224 break; 8225 } 8226 } else if (op_type == PHY_DIAG_CTRL_CMD) { 8227 switch (op_cmd) { 8228 case PHY_DIAG_CTRL_DSC: 8229 /* Diag DSC supported on system side of BCM8485X */ 8230 if (PHY_IS_BCM8485X_AND_UP(pc) && intf == PHY_DIAG_INTF_SYS) { 8231 SOC_IF_ERROR_RETURN 8232 (_phy_8481_diag_dsc_get(pc)); 8233 } 8234 else { 8235 return SOC_E_UNAVAIL; 8236 } 8237 break; 8238 } 8239 } 8240 #endif /* BCM848XX_STATE_MFG_DIAG_SUPPORT */ 8241 return SOC_E_NONE; 8242 } 8243 8244 STATIC int 8245 _phy848xx_short_reach_enable_set(int unit,phy_ctrl_t *pc, uint16 enable ) 8246 { 8247 uint16 args[5]; 8248 args[0] = enable; 8249 8250 if (PHY_IS_BCM8488X(pc) && enable) { 8251 args[1] = enable; 8252 } 8253 SOC_IF_ERROR_RETURN 8254 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_SHORT_REACH_ENABLE_GENERIC, args, (PHY_IS_BCM8488X(pc) && enable) ? 2 : 1)); 8255 8256 return (SOC_E_NONE); 8257 } 8258 8259 STATIC int 8260 _phy848xx_short_reach_enable_get(int unit, phy_ctrl_t *pc, uint16 *enable, uint16 *fenable) 8261 { 8262 uint16 args[5]; 8263 *fenable = 0; 8264 8265 if ( !PHY_IS_BCM8488X(pc) ) { 8266 SOC_IF_ERROR_RETURN 8267 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_GENERIC, args, 1)); 8268 8269 if (enable) { 8270 *enable = args[0]; 8271 } 8272 } 8273 else { /* Orca */ 8274 SOC_IF_ERROR_RETURN 8275 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_SHORT_REACH_ENABLE_GENERIC, args, 2)); 8276 8277 if (enable) { 8278 *enable = args[0]; 8279 } 8280 8281 if (args[0]) { 8282 *fenable = args[1]; 8283 } 8284 } 8285 return (SOC_E_NONE); 8286 } 8287 8288 STATIC int 8289 _phy_84834_power_mode_set (int unit, soc_port_t port, uint32 mode) 8290 { 8291 phy_ctrl_t *pc; 8292 8293 pc = EXT_PHY_SW_STATE(unit, port); 8294 8295 if (pc->power_mode == mode) { 8296 return SOC_E_NONE; 8297 } 8298 if (mode == SOC_PHY_CONTROL_POWER_LOW) { 8299 SOC_IF_ERROR_RETURN 8300 (_phy848xx_short_reach_enable_set(unit, pc, 1)); 8301 } else if (mode == SOC_PHY_CONTROL_POWER_FULL) { 8302 SOC_IF_ERROR_RETURN 8303 (_phy848xx_short_reach_enable_set(unit, pc, 0)); 8304 } else { 8305 return SOC_E_UNAVAIL; 8306 } 8307 8308 pc->power_mode = mode; 8309 8310 return SOC_E_NONE; 8311 } 8312 8313 STATIC int 8314 _phy_84834_power_mode_get (int unit, soc_port_t port, uint32 *mode) 8315 { 8316 phy_ctrl_t *pc; 8317 uint16 temp1=0, temp2=0; 8318 8319 pc = EXT_PHY_SW_STATE(unit, port); 8320 8321 SOC_IF_ERROR_RETURN 8322 (_phy848xx_short_reach_enable_get(unit, pc, &temp1, &temp2)); 8323 if (temp1) { 8324 if (PHY_IS_BCM8488X(pc)) { 8325 if (temp2) { 8326 *mode = SOC_PHY_CONTROL_POWER_LOW; 8327 } else { 8328 *mode = SOC_PHY_CONTROL_POWER_FULL; 8329 } 8330 } else { 8331 *mode = SOC_PHY_CONTROL_POWER_LOW; 8332 } 8333 } else { 8334 *mode = SOC_PHY_CONTROL_POWER_FULL; 8335 } 8336 pc->power_mode = *mode; 8337 8338 return SOC_E_NONE; 8339 } 8340 8341 STATIC int 8342 phy_8481_cable_diag(int unit, soc_port_t port, 8343 soc_port_cable_diag_t *status) 8344 { 8345 phy_ctrl_t *pc; 8346 soc_timeout_t to; 8347 int i, rv, enable = 0, an = 0, an_done = 0, speed = 0; 8348 uint16 ctrl_status, result, length; 8349 8350 8351 pc = EXT_PHY_SW_STATE(unit, port); 8352 8353 /* ECD not supported on disabled port for KOI and later PHYs */ 8354 if (PHY_IS_BCM8485X_AND_UP(pc)) { 8355 SOC_IF_ERROR_RETURN 8356 (phy_8481_enable_get(unit, port, &enable)); 8357 if (!enable) { 8358 return SOC_E_UNAVAIL; 8359 } 8360 8361 SOC_IF_ERROR_RETURN 8362 (phy_8481_an_get(unit, port, &an, &an_done)); 8363 SOC_IF_ERROR_RETURN 8364 (phy_8481_speed_get(unit, port, &speed)); 8365 8366 /* KOI does not support ECD for forced 100M */ 8367 if ( (speed == 100) && !(an) ) { 8368 return SOC_E_UNAVAIL; 8369 } 8370 } 8371 8372 status->fuzz_len = 10; 8373 status->npairs = 4; 8374 status->state = SOC_PORT_CABLE_STATE_OK; 8375 8376 /* run now, not at AN, enanle inter pair short check, don't break link, length in meters */ 8377 SOC_IF_ERROR_RETURN 8378 (MODIFY_PHY8481_TOP_CONFIG_CABLE_DIAG_CTRL_STAT_REG(unit, pc, (1U<<15)|(1U<<10), 8379 (1U<<15)|(1U<<14)|(1U<<13)|(1U<<12)|(1U<<10))); 8380 8381 sal_usleep(100); 8382 soc_timeout_init(&to, 50000000, 0); 8383 8384 do { 8385 rv = READ_PHY8481_TOP_CONFIG_CABLE_DIAG_CTRL_STAT_REG(unit, pc, &ctrl_status); 8386 if (((ctrl_status & (1U<<11)) == 0) || 8387 SOC_FAILURE(rv)) { 8388 break; 8389 } 8390 } while (!soc_timeout_check(&to)); 8391 8392 if ((ctrl_status & (1U<<11)) != 0) { 8393 LOG_WARN(BSL_LS_SOC_PHY, 8394 (BSL_META_U(unit, 8395 "PHY848X Cable Diagnostics failed: u=%d p=%d\n"), unit, port )); 8396 return (SOC_E_FAIL); 8397 } 8398 8399 SOC_IF_ERROR_RETURN 8400 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_RESULT_REG(unit, pc, &result)); 8401 8402 for( i=3; i>=0; i--) { 8403 8404 switch (result & 0xf) { 8405 case 0x1: 8406 status->pair_state[i] = SOC_PORT_CABLE_STATE_OK; 8407 break; 8408 case 0x2: 8409 status->pair_state[i] = SOC_PORT_CABLE_STATE_OPEN; 8410 break; 8411 case 0x3: 8412 status->pair_state[i] = SOC_PORT_CABLE_STATE_SHORT; 8413 break; 8414 case 0x4: 8415 status->pair_state[i] = SOC_PORT_CABLE_STATE_CROSSTALK; 8416 break; 8417 default: 8418 status->pair_state[i] = SOC_PORT_CABLE_STATE_UNKNOWN; 8419 break; 8420 } 8421 8422 if (status->pair_state[i] > status->state) { 8423 status->state = status->pair_state[i]; 8424 } 8425 8426 switch (i) { 8427 case 3: 8428 SOC_IF_ERROR_RETURN 8429 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR78_LEN_REG(unit, pc, &length)); 8430 break; 8431 case 2: 8432 SOC_IF_ERROR_RETURN 8433 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR56_LEN_REG(unit, pc, &length)); 8434 break; 8435 case 1: 8436 SOC_IF_ERROR_RETURN 8437 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR34_LEN_REG(unit, pc, &length)); 8438 break; 8439 case 0: 8440 SOC_IF_ERROR_RETURN 8441 (READ_PHY8481_PHYC_CTL_CABLE_DIAG_PAIR12_LEN_REG(unit, pc, &length)); 8442 break; 8443 } 8444 status->pair_len[i] = length; 8445 result >>= 4; 8446 } 8447 8448 return SOC_E_NONE; 8449 } 8450 8451 STATIC int 8452 _phy84834_timesync_enable_set(int unit,phy_ctrl_t *pc, uint16 enable ) 8453 { 8454 uint16 args[5]; 8455 args[0] = enable; 8456 8457 if ( enable ) { 8458 if ( ! (FLAGS(pc) & PHY8483X_TIMESYNC_ENABLED) ) { 8459 SOC_IF_ERROR_RETURN 8460 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 8461 (uint16) PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC, 8462 args, 1)); 8463 FLAGS(pc) |= PHY8483X_TIMESYNC_ENABLED; 8464 /* PTP_PARSER_EG_CNTR_[ALL/PTP]_PKT_[EN/CLR] registers *\ 8465 \* 1.0xda20,0xda30,0xda21,0xda31 , bit[0] */ 8466 SOC_IF_ERROR_RETURN 8467 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8468 PHY84834_PTP_PARSER_EG_CNTR_ALL_PKT_EN , 0x1, 0x1)); 8469 SOC_IF_ERROR_RETURN 8470 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8471 PHY84834_PTP_PARSER_EG_CNTR_PTP_PKT_EN , 0x1, 0x1)); 8472 SOC_IF_ERROR_RETURN 8473 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8474 PHY84834_PTP_PARSER_EG_CNTR_ALL_PKT_CLR, 0x1, 0x1)); 8475 SOC_IF_ERROR_RETURN 8476 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8477 PHY84834_PTP_PARSER_EG_CNTR_PTP_PKT_CLR, 0x1, 0x1)); 8478 /* PTP_PARSER_IG_CNTR_[ALL/PTP]_PKT_[EN/CLR] registers *\ 8479 \* 1.0xdaa0,0xdab0,0xdaa1,0xdab1 , bit[0] */ 8480 SOC_IF_ERROR_RETURN 8481 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8482 PHY84834_PTP_PARSER_IG_CNTR_ALL_PKT_EN , 0x1, 0x1)); 8483 SOC_IF_ERROR_RETURN 8484 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8485 PHY84834_PTP_PARSER_IG_CNTR_PTP_PKT_EN , 0x1, 0x1)); 8486 SOC_IF_ERROR_RETURN 8487 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8488 PHY84834_PTP_PARSER_IG_CNTR_ALL_PKT_CLR, 0x1, 0x1)); 8489 SOC_IF_ERROR_RETURN 8490 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8491 PHY84834_PTP_PARSER_IG_CNTR_PTP_PKT_CLR, 0x1, 0x1)); 8492 } 8493 8494 } else { /* disable */ 8495 if ((FLAGS(pc) & PHY8483X_TIMESYNC_ENABLED)) { 8496 SOC_IF_ERROR_RETURN 8497 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 8498 (uint16)PHY84834_DIAG_CMD_SET_1588_ENABLE_GENERIC, 8499 args, 1)); 8500 FLAGS(pc) &= ~PHY8483X_TIMESYNC_ENABLED; 8501 SOC_IF_ERROR_RETURN 8502 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8503 PHY84834_PTP_PARSER_EG_CNTR_ALL_PKT_EN, 0x0, 0x1)); 8504 SOC_IF_ERROR_RETURN 8505 (MODIFY_PHY8481_PMAD_REG(unit, pc, 8506 PHY84834_PTP_PARSER_IG_CNTR_ALL_PKT_EN, 0x0, 0x1)); 8507 } 8508 } 8509 SOC_IF_ERROR_RETURN 8510 (phy_8481_an_set(unit, pc->port, 1)); 8511 8512 return (SOC_E_NONE); 8513 } 8514 8515 STATIC int 8516 _phy84834_timesync_enable_get(int unit,phy_ctrl_t *pc, uint16 *enable ) 8517 { 8518 uint16 args[5]; 8519 8520 SOC_IF_ERROR_RETURN 8521 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_1588_ENABLE_GENERIC, args, 1)); 8522 8523 if (enable) { 8524 *enable = args[0]; 8525 } 8526 8527 return (SOC_E_NONE); 8528 } 8529 8530 void _phy84834_encode_egress_message_mode(soc_port_phy_timesync_event_message_egress_mode_t mode, 8531 int offset, uint16 *value) 8532 { 8533 switch (mode) { 8534 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE: 8535 *value |= (0x0 << offset); 8536 break; 8537 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD: 8538 *value |= (0x1 << offset); 8539 break; 8540 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN: 8541 *value |= (0x2 << offset); 8542 break; 8543 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP: 8544 *value |= (0x3 << offset); 8545 break; 8546 default: 8547 break; 8548 } 8549 } 8550 8551 void _phy84834_encode_ingress_message_mode(soc_port_phy_timesync_event_message_ingress_mode_t mode, 8552 int offset, uint16 *value) 8553 { 8554 switch (mode) { 8555 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE: 8556 *value |= (0x0 << offset); 8557 break; 8558 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD: 8559 *value |= (0x1 << offset); 8560 break; 8561 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP: 8562 *value |= (0x2 << offset); 8563 break; 8564 case SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME: 8565 *value |= (0x3 << offset); 8566 break; 8567 default: 8568 break; 8569 } 8570 } 8571 8572 void _phy84834_decode_egress_message_mode(uint16 value, int offset, 8573 soc_port_phy_timesync_event_message_egress_mode_t *mode) 8574 { 8575 switch ((value >> offset) & 0x7) { 8576 case 0x0: 8577 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_NONE; 8578 break; 8579 case 0x1: 8580 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_UPDATE_CORRECTIONFIELD; 8581 break; 8582 case 0x2: 8583 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_REPLACE_CORRECTIONFIELD_ORIGIN; 8584 break; 8585 case 0x3: 8586 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_EGRESS_MODE_CAPTURE_TIMESTAMP; 8587 break; 8588 default: 8589 break; 8590 } 8591 } 8592 8593 void _phy84834_decode_ingress_message_mode(uint16 value, int offset, 8594 soc_port_phy_timesync_event_message_ingress_mode_t *mode) 8595 { 8596 switch ((value >> offset) & 0x7) { 8597 case 0x0: 8598 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_NONE; 8599 break; 8600 case 0x1: 8601 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_UPDATE_CORRECTIONFIELD; 8602 break; 8603 case 0x2: 8604 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_TIMESTAMP; 8605 break; 8606 case 0x3: 8607 *mode = SOC_PORT_PHY_TIMESYNC_EVENT_MESSAGE_INGRESS_MODE_INSERT_DELAYTIME; 8608 break; 8609 default: 8610 break; 8611 } 8612 } 8613 8614 void _phy84834_encode_gmode(soc_port_phy_timesync_global_mode_t mode, 8615 uint16 *value) 8616 { 8617 switch (mode) { 8618 case SOC_PORT_PHY_TIMESYNC_MODE_FREE: 8619 *value = 0x1; 8620 break; 8621 case SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN: 8622 *value = 0x2; 8623 break; 8624 case SOC_PORT_PHY_TIMESYNC_MODE_CPU: 8625 *value = 0x3; 8626 break; 8627 default: 8628 break; 8629 } 8630 } 8631 8632 void _phy84834_decode_gmode(uint16 value, soc_port_phy_timesync_global_mode_t *mode) 8633 { 8634 switch (value & 0x3) { 8635 case 0x1: 8636 *mode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 8637 break; 8638 case 0x2: 8639 *mode = SOC_PORT_PHY_TIMESYNC_MODE_SYNCIN; 8640 break; 8641 case 0x3: 8642 *mode = SOC_PORT_PHY_TIMESYNC_MODE_CPU; 8643 break; 8644 default: 8645 break; 8646 } 8647 } 8648 8649 8650 void _phy84834_encode_framesync_mode(soc_port_phy_timesync_framesync_mode_t mode, 8651 uint16 *value) 8652 { 8653 switch (mode) { 8654 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0: 8655 *value = 1; 8656 break; 8657 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1: 8658 *value = 2; 8659 break; 8660 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT: 8661 *value = 3; 8662 break; 8663 case SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU: 8664 *value = 4; 8665 break; 8666 default: 8667 break; 8668 } 8669 } 8670 8671 void _phy84834_decode_framesync_mode(uint16 value, soc_port_phy_timesync_framesync_mode_t *mode) 8672 { 8673 switch (value & 0xf) { 8674 case 1: 8675 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN0; 8676 break; 8677 case 2: 8678 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCIN1; 8679 break; 8680 case 3: 8681 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_SYNCOUT; 8682 break; 8683 case 4: 8684 *mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_CPU; 8685 break; 8686 default: 8687 break; 8688 } 8689 } 8690 8691 void _phy84834_encode_syncout_mode(soc_port_phy_timesync_syncout_mode_t mode, 8692 uint16 *value) 8693 { 8694 switch (mode) { 8695 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE: 8696 *value = 0x0; 8697 break; 8698 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME: 8699 *value = 0x1; 8700 break; 8701 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN: 8702 *value = 0x2; 8703 break; 8704 case SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC: 8705 *value = 0x3; 8706 break; 8707 default: 8708 break; 8709 } 8710 } 8711 8712 #ifdef PHY8185X_DEBUG_CMD_HANDLER 8713 STATIC int 8714 _phy8485x_emi_mode_enable_get(int unit, phy_ctrl_t *pc, uint16 *status) 8715 { 8716 uint16 args[2]; 8717 8718 SOC_IF_ERROR_RETURN 8719 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_EMI_MODE_ENABLE_V2, args, 1)); 8720 8721 *status = args[0]; 8722 8723 return (SOC_E_NONE); 8724 } 8725 8726 STATIC int 8727 _phy8485x_emi_mode_enable_set(int unit, phy_ctrl_t *pc, uint16 status) 8728 { 8729 uint16 args[2]; 8730 8731 args[0] = status; 8732 SOC_IF_ERROR_RETURN 8733 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_EMI_MODE_ENABLE_V2, args, 1)); 8734 8735 return (SOC_E_NONE); 8736 } 8737 8738 STATIC int 8739 _phy8485x_sub_lf_rf_status_get(int unit, phy_ctrl_t *pc, uint16 *status) 8740 { 8741 uint16 args[2]; 8742 8743 SOC_IF_ERROR_RETURN 8744 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_SUB_LF_RF_V2, args, 1)); 8745 8746 *status = args[0]; 8747 8748 return (SOC_E_NONE); 8749 } 8750 8751 STATIC int 8752 _phy8485x_sub_lf_rf_set(int unit, phy_ctrl_t *pc) 8753 { 8754 uint16 args[2]; 8755 args[0]=1; 8756 8757 SOC_IF_ERROR_RETURN 8758 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_SUB_LF_RF_GENERIC, args, 1)); 8759 8760 return (SOC_E_NONE); 8761 } 8762 8763 STATIC int 8764 _phy8485x_sub_lf_rf_clear(int unit, phy_ctrl_t *pc) 8765 { 8766 uint16 args[2]; 8767 args[0]=1; 8768 8769 SOC_IF_ERROR_RETURN 8770 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_CLEAR_SUB_LF_RF_GENERIC, args, 1)); 8771 8772 return (SOC_E_NONE); 8773 } 8774 8775 STATIC int 8776 _phy8485x_snr_get(int unit, phy_ctrl_t *pc) 8777 { 8778 uint16 args[5]; 8779 args[0]=0; 8780 8781 SOC_IF_ERROR_RETURN 8782 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_SNR_GENERIC, args, 5)); 8783 8784 return (SOC_E_NONE); 8785 } 8786 8787 STATIC int 8788 _phy8485x_current_temp_get(int unit, phy_ctrl_t *pc) 8789 { 8790 uint16 args[2]; 8791 args[0]=0; 8792 8793 SOC_IF_ERROR_RETURN 8794 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_CURRENT_TEMP_GENERIC, args, 1)); 8795 8796 return (SOC_E_NONE); 8797 } 8798 8799 STATIC int 8800 _phy8485x_upper_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp) 8801 { 8802 uint16 args[2]; 8803 args[0]=0; 8804 8805 SOC_IF_ERROR_RETURN 8806 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_UPPER_TEMP_WARNING_LEVEL_V2, args, 1)); 8807 8808 *temp = args[0]; 8809 8810 return (SOC_E_NONE); 8811 } 8812 8813 STATIC int 8814 _phy8485x_upper_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp) 8815 { 8816 uint16 args[2]; 8817 args[0]=temp; 8818 8819 SOC_IF_ERROR_RETURN 8820 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_UPPER_TEMP_WARNING_LEVEL_V2, args, 1)); 8821 8822 return (SOC_E_NONE); 8823 } 8824 8825 STATIC int 8826 _phy8485x_lower_temp_warn_level_get(int unit, phy_ctrl_t *pc, uint16 *temp) 8827 { 8828 uint16 args[2]; 8829 args[0]=0; 8830 8831 SOC_IF_ERROR_RETURN 8832 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84834_DIAG_CMD_GET_LOWER_TEMP_WARNING_LEVEL_V2, args, 1)); 8833 8834 *temp = args[0]; 8835 8836 return (SOC_E_NONE); 8837 } 8838 8839 STATIC int 8840 _phy8485x_lower_temp_warn_level_set(int unit, phy_ctrl_t *pc, uint16 temp) 8841 { 8842 uint16 args[2]; 8843 args[0]=temp; 8844 8845 SOC_IF_ERROR_RETURN 8846 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84834_DIAG_CMD_SET_LOWER_TEMP_WARNING_LEVEL_V2, args, 1)); 8847 8848 return (SOC_E_NONE); 8849 } 8850 8851 STATIC int 8852 _phy8486x_xfi_2p5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g) 8853 { 8854 uint16 args[2] = { 0, 0 }; 8855 8856 SOC_IF_ERROR_RETURN 8857 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, 8858 (uint16) PHY84834_DIAG_CMD_GET_XFI_2P5G_MODE_V2, args, 1) ); 8859 *mode_2p5g = args[0]; 8860 8861 return (SOC_E_NONE); 8862 } 8863 8864 STATIC int 8865 _phy848xx_xfi_2p5g_5g_mode_get(int unit, phy_ctrl_t *pc, uint16 *mode_2p5g, uint16 *mode_5g) 8866 { 8867 uint16 args[2] = { 0, 0 }; 8868 8869 SOC_IF_ERROR_RETURN 8870 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, 8871 (uint16) PHY84834_DIAG_CMD_GET_XFI_2P5G_MODE_V2, args, (PHY_IS_BCM8488X(pc) ? 2 : 1)) ); 8872 *mode_2p5g = args[0]; 8873 if (PHY_IS_BCM8488X(pc)) { 8874 *mode_5g = args[1]; 8875 } 8876 return (SOC_E_NONE); 8877 } 8878 8879 STATIC int 8880 _phy_848xx_led_type_get (int unit, soc_port_t port, uint32 *led_type, uint32 *led_mode) 8881 { 8882 uint16 args[5]; 8883 phy_ctrl_t *pc; 8884 8885 pc = EXT_PHY_SW_STATE(unit, port); 8886 8887 SOC_IF_ERROR_RETURN 8888 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84888_DIAG_CMD_GET_LED_TYPE, args, 2)); 8889 8890 if (led_type) { 8891 *led_type = args[0]; 8892 } 8893 if ( PHY_IS_BCM8488X(pc) && (args[0] == 2) ) { 8894 *led_mode = args[1]; 8895 } 8896 8897 return (SOC_E_NONE); 8898 } 8899 8900 STATIC int 8901 _phy_848xx_led_type_set (int unit, soc_port_t port, uint32 led_type, uint32 led_mode) 8902 { 8903 uint16 args[5]; 8904 phy_ctrl_t *pc; 8905 8906 pc = EXT_PHY_SW_STATE(unit, port); 8907 args[0] = led_type; 8908 8909 if (led_type == 2) { 8910 args[1] = led_mode; 8911 } 8912 8913 SOC_IF_ERROR_RETURN 8914 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84888_DIAG_CMD_SET_LED_TYPE, args, 2)); 8915 8916 return (SOC_E_NONE); 8917 } 8918 8919 STATIC int 8920 _phy_848xx_pause_frame_mode_get (int unit, soc_port_t port, uint32 *enable) 8921 { 8922 uint16 args[2]; 8923 phy_ctrl_t *pc; 8924 8925 pc = EXT_PHY_SW_STATE(unit, port); 8926 8927 SOC_IF_ERROR_RETURN 8928 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84888_DIAG_CMD_GET_PAUSE_FRAME_MODE, args, 1)); 8929 *enable = args[0]; 8930 8931 return (SOC_E_NONE); 8932 } 8933 8934 STATIC int 8935 _phy_848xx_pause_frame_mode_set (int unit, soc_port_t port, uint32 enable) 8936 { 8937 uint16 args[2]; 8938 phy_ctrl_t *pc; 8939 8940 pc = EXT_PHY_SW_STATE(unit, port); 8941 args[0] = enable; 8942 8943 SOC_IF_ERROR_RETURN 8944 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84888_DIAG_CMD_SET_PAUSE_FRAME_MODE, args, 1)); 8945 8946 return (SOC_E_NONE); 8947 } 8948 #endif /* PHY8185X_DEBUG_CMD_HANDLER */ 8949 8950 STATIC int 8951 _phy_848xx_mgbase_802_3bz_type_get (int unit, phy_ctrl_t *pc, uint16 *frame_type, uint16 *frame_mode) 8952 { 8953 uint16 args[5]; 8954 8955 SOC_IF_ERROR_RETURN 8956 (PHY84834_TOP_LEVEL_CMD_GET(unit, pc, (uint16)PHY84888_DIAG_CMD_GET_MGBASET_802_3BZ_TYPE, args, 2)); 8957 8958 *frame_type = args[0]; 8959 *frame_mode = args[1]; 8960 8961 return (SOC_E_NONE); 8962 } 8963 8964 STATIC int 8965 _phy_848xx_mgbase_802_3bz_type_set (int unit, phy_ctrl_t *pc, uint16 frame_type, uint16 frame_mode) 8966 { 8967 uint16 args[5]; 8968 8969 args[0] = frame_type; 8970 args[1] = frame_mode; 8971 8972 SOC_IF_ERROR_RETURN 8973 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, (uint16)PHY84888_DIAG_CMD_SET_MGBASET_802_3BZ_TYPE, args, 2)); 8974 8975 return (SOC_E_NONE); 8976 } 8977 8978 STATIC int 8979 _phy848xx_xfi_2p5g_5g_mode_set(int unit, phy_ctrl_t *pc, uint16 mode_2p5g) 8980 { 8981 uint16 args[2]; 8982 8983 args[0] = mode_2p5g; 8984 if ( PHY_IS_BCM8488X(pc) ) { 8985 args[1] = mode_2p5g; 8986 } 8987 SOC_IF_ERROR_RETURN 8988 (PHY84834_TOP_LEVEL_CMD_SET(unit, pc, 8989 (uint16)PHY84834_DIAG_CMD_SET_XFI_2P5G_MODE_V2, args, (PHY_IS_BCM8488X(pc) ? 2 : 1)) ); 8990 return (SOC_E_NONE); 8991 } 8992 8993 void _phy84834_decode_syncout_mode(uint16 value, 8994 soc_port_phy_timesync_syncout_mode_t *mode) 8995 { 8996 switch (value & 0x3) { 8997 case 0x0: 8998 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 8999 break; 9000 case 0x1: 9001 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_ONE_TIME; 9002 break; 9003 case 0x2: 9004 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN; 9005 break; 9006 case 0x3: 9007 *mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_PULSE_TRAIN_WITH_SYNC; 9008 break; 9009 } 9010 } 9011 9012 9013 /* 9014 * Function: 9015 * phy84834_timesync_config_set 9016 * Purpose: 9017 * 9018 * Parameters: 9019 * 9020 * Returns: 9021 */ 9022 int 9023 phy84834_timesync_config_set(int unit, soc_port_t port, 9024 soc_port_phy_timesync_config_t *conf) 9025 { 9026 uint16 eg_config= 0, ig_config = 0, 9027 nse_sc_cfg = 0, value = 0, nse_nco_cfg = 0, temp16 = 0,temp1 = 0,temp2 = 0, 9028 gmode = 0, syncout_mode = 0, framesync_mode = 0; 9029 phy_ctrl_t *pc; 9030 9031 pc = EXT_PHY_SW_STATE(unit, port); 9032 9033 if(NULL == conf) { 9034 return SOC_E_PARAM; 9035 } 9036 if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) { 9037 return SOC_E_UNAVAIL; 9038 } 9039 9040 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 9041 SOC_IF_ERROR_RETURN 9042 (_phy84834_timesync_enable_set(unit, pc, 9043 (conf->flags & SOC_PORT_PHY_TIMESYNC_ENABLE) ? 1 : 0 )); 9044 9045 /* Capture PKT INFO - Rx & Tx*/ 9046 temp1 = temp2 = 0; 9047 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE) { 9048 temp1 |= PHY84834_PTP_EG_PTP_PKT_CFG_CAPT_PTP_ALL; 9049 temp2 |= PHY84834_PTP_IG_PTP_PKT_CFG_CAPT_PTP_ALL; 9050 } 9051 /* Egress Parser PTP Config Reg. 1.DA08[15,11,7,3] */ 9052 SOC_IF_ERROR_RETURN 9053 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9054 PHY84834_PTP_EG_PTP_PKT_CFG_REG, 9055 temp1, PHY84834_PTP_EG_PTP_PKT_CFG_CAPT_PTP_ALL)); 9056 /* Ingress Parser PTP Config Reg. 1.DA88[15,11,7,3] */ 9057 SOC_IF_ERROR_RETURN 9058 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9059 PHY84834_PTP_IG_PTP_PKT_CFG_REG, 9060 temp2, PHY84834_PTP_IG_PTP_PKT_CFG_CAPT_PTP_ALL)); 9061 9062 /* Timestamp/Source_port capturing configuration */ 9063 /* Capture full 80-bit src_port or 16-bit src port + 64-bit IP/MAC */ 9064 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_FULL_SOURCE_PORT) { 9065 temp16 |= PHY8486X_PTP_PIC_CONFIG_FULL_SRC_PORT; 9066 } 9067 /* Capture packet's 48-bit countstamp or 64 LSB of 80-bit timestamp */ 9068 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CAPTURE_LONG_TIMESTAMP) { 9069 temp16 |= PHY8486X_PTP_PIC_CONFIG_LONG_TIMESTAMP; 9070 } 9071 /* PIC Configuration Reg. 1.DB01[1:0] */ 9072 SOC_IF_ERROR_RETURN 9073 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9074 PHY8486X_PTP_PIC_CONFIG_REG, 9075 temp16, PHY8486X_PTP_PIC_CONFIG_MASK) ); 9076 9077 /* Enable timestamp capture on the next frame sync event */ 9078 nse_sc_cfg |= PHY84834_PTP_NSE_SC_CFG_FSYNC_EN; 9079 if (conf->flags & SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE) { 9080 nse_sc_cfg |= PHY84834_PTP_NSE_SC_CFG_FSYNC_TS_EN; 9081 } 9082 SOC_IF_ERROR_RETURN 9083 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9084 PHY84834_PTP_NSE_SC_CFG_REG, 9085 nse_sc_cfg, 9086 PHY84834_PTP_NSE_SC_CFG_FSYNC_EN | 9087 PHY84834_PTP_NSE_SC_CFG_FSYNC_TS_EN) ); 9088 9089 /* Enable the FCS/CRC check in PTP detection receiving side */ 9090 temp16 = 0; 9091 if (conf->flags & SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE) { 9092 temp16 |= PHY84834_PTP_IG_CFG_FCS_CHECK_EN; 9093 } 9094 SOC_IF_ERROR_RETURN 9095 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9096 PHY84834_PTP_IG_CFG_REG, 9097 temp16, 9098 PHY84834_PTP_IG_CFG_FCS_CHECK_EN)); 9099 9100 /* Enable different packet detections & checks in Rx & Tx direction */ 9101 if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE) || 9102 (conf->flags & SOC_PORT_PHY_TIMESYNC_L2_ENABLE) ) { 9103 ig_config |= PHY84834_PTP_IG_CFG_L2_802AS_EN; 9104 eg_config |= PHY84834_PTP_EG_CFG_L2_802AS_EN; 9105 } 9106 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP4_ENABLE ) { 9107 ig_config |= PHY84834_PTP_IG_CFG_L4_IP4_UDP_EN; 9108 eg_config |= PHY84834_PTP_EG_CFG_L4_IP4_UDP_EN; 9109 } 9110 if ( conf->flags & SOC_PORT_PHY_TIMESYNC_IP6_ENABLE ) { 9111 ig_config |= PHY84834_PTP_IG_CFG_L4_IP6_UDP_EN; 9112 eg_config |= PHY84834_PTP_EG_CFG_L4_IP6_UDP_EN; 9113 } 9114 #if 0 9115 if (conf->flags & SOC_PORT_PHY_TIMESYNC_L4_IPV6_ADDR_ENABLE) { 9116 ig_config |= PHY84834_PTP_IG_CFG_L4_IP6_UDP_ACH_EN; 9117 eg_config |= PHY84834_PTP_EG_CFG_L4_IP6_UDP_ACH_EN; 9118 } 9119 if (conf->flags & SOC_PORT_PHY_TIMESYNC_L4_IP_ADDR_ENABLE) { 9120 ig_config |= PHY84834_PTP_IG_CFG_L4_IP4_UDP_ACH_EN; 9121 eg_config |= PHY84834_PTP_EG_CFG_L4_IP4_UDP_ACH_EN; 9122 } 9123 if ((conf->flags & SOC_PORT_PHY_TIMESYNC_L2_DS_ENABLE) 9124 || (conf->flags & SOC_PORT_PHY_TIMESYNC_AS_DS_ENABLE)) { 9125 ig_config |= PHY84834_PTP_IG_CFG_L2_802AS_ACH_EN; 9126 eg_config |= PHY84834_PTP_EG_CFG_L2_802AS_ACH_EN; 9127 } 9128 #endif 9129 /* IG Config */ 9130 SOC_IF_ERROR_RETURN 9131 (WRITE_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_IG_CFG_REG, ig_config)); 9132 /* EG Config */ 9133 SOC_IF_ERROR_RETURN 9134 (WRITE_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_EG_CFG_REG, eg_config)); 9135 9136 9137 /* Set input for NCO adder */ 9138 if (conf->flags & SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT) { 9139 nse_nco_cfg |= (uint16) PHY84834_PTP_NSE_NCO_CFG_FCW_SEL; 9140 } else { 9141 nse_nco_cfg &= (uint16) ~PHY84834_PTP_NSE_NCO_CFG_FCW_SEL; 9142 } 9143 9144 /* NSE NCO CFG register */ 9145 SOC_IF_ERROR_RETURN 9146 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9147 PHY84834_PTP_NSE_NCO_CFG_REG, 9148 nse_nco_cfg, 9149 PHY84834_PTP_NSE_NCO_CFG_FCW_SEL)); 9150 } 9151 9152 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 9153 SOC_IF_ERROR_RETURN 9154 (WRITE_PHY8481_PMAD_REG(unit, pc, 9155 PHY84834_PTP_VLAN_1TAG_TPID_REG, conf->itpid)); 9156 } 9157 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 9158 SOC_IF_ERROR_RETURN 9159 (WRITE_PHY8481_PMAD_REG(unit, pc, 9160 PHY84834_PTP_VLAN_2TAG_OTPID_REG, conf->otpid)); 9161 } 9162 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 9163 SOC_IF_ERROR_RETURN 9164 (WRITE_PHY8481_PMAD_REG(unit, pc, 9165 PHY84834_PTP_VLAN_2TAG_OTPID_1_REG, conf->otpid2)); 9166 } 9167 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 9168 SOC_IF_ERROR_RETURN 9169 (WRITE_PHY8481_PMAD_REG(unit, pc, 9170 PHY84834_PTP_NSE_SHDW_DPLL_SYNC_DIV_REG, 9171 conf->ts_divider & 0x0fff)); 9172 /* Enable loading shadow reg value to active copy on next framesync */ 9173 SOC_IF_ERROR_RETURN 9174 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9175 PHY84834_PTP_NSE_SHDW_CTL_REG, 9176 PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV, 9177 PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV)); 9178 } 9179 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 9180 /* Do nothing 9181 * 9182 * In some chips there are two registers Rx timestamp offset & 9183 * Rx link delay. These two registers do similar funtion. 9184 * The offset was added to the internal timestamp, the 9185 * link delay was subtracted from it. Rx link delay control not required 9186 * in this chip. Tx/RX timestamp offset does the job. The signed value will 9187 * be added to the timestamp. 9188 */ 9189 } 9190 9191 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 9192 SOC_IF_ERROR_RETURN 9193 (WRITE_PHY8481_PMAD_REG(unit, pc, 9194 PHY84834_PTP_NSE_SHDW_ORG_TS_0_REG, 9195 (uint16)(conf->original_timecode.nanoseconds & 0xffff))); 9196 SOC_IF_ERROR_RETURN 9197 (WRITE_PHY8481_PMAD_REG(unit, pc, 9198 PHY84834_PTP_NSE_SHDW_ORG_TS_1_REG, 9199 (uint16)((conf->original_timecode.nanoseconds >> 16) & 0xffff))); 9200 SOC_IF_ERROR_RETURN 9201 (WRITE_PHY8481_PMAD_REG(unit, pc, 9202 PHY84834_PTP_NSE_SHDW_ORG_TS_2_REG, 9203 (uint16)(COMPILER_64_LO(conf->original_timecode.seconds) & 0xffff))); 9204 SOC_IF_ERROR_RETURN 9205 (WRITE_PHY8481_PMAD_REG(unit, pc, 9206 PHY84834_PTP_NSE_SHDW_ORG_TS_3_REG, 9207 (uint16)((COMPILER_64_LO(conf->original_timecode.seconds) >> 16) 9208 & 0xffff))); 9209 SOC_IF_ERROR_RETURN 9210 (WRITE_PHY8481_PMAD_REG(unit, pc, 9211 PHY84834_PTP_NSE_SHDW_ORG_TS_4_REG, 9212 (uint16)(COMPILER_64_HI(conf->original_timecode.seconds) & 0xffff))); 9213 /* Enable loading shadow reg value to active copy on next framesync */ 9214 SOC_IF_ERROR_RETURN 9215 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9216 PHY84834_PTP_NSE_SHDW_CTL_REG, 9217 PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS, 9218 PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS)); 9219 } 9220 9221 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 9222 _phy84834_encode_gmode(conf->gmode,&gmode); 9223 } 9224 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 9225 _phy84834_encode_framesync_mode(conf->framesync.mode, &framesync_mode); 9226 SOC_IF_ERROR_RETURN 9227 (WRITE_PHY8481_PMAD_REG(unit, pc, 9228 PHY84834_NSE_SYNCIN_FSYNC_LEN_0_REG, 9229 conf->framesync.length_threshold & 0xffff));/*[15:0]*/ 9230 SOC_IF_ERROR_RETURN 9231 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9232 PHY84834_NSE_SYNCIN_FSYNC_LEN_1_REG, 9233 (conf->framesync.length_threshold >> 16) & 0x7, 9234 0x7));/*[18:16]*/ 9235 SOC_IF_ERROR_RETURN 9236 (WRITE_PHY8481_PMAD_REG(unit, pc, 9237 PHY84834_NSE_SYNCIN_FSYNC_DLY_0_REG, 9238 conf->framesync.event_offset & 0xffff));/*[15:0]*/ 9239 SOC_IF_ERROR_RETURN 9240 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9241 PHY84834_NSE_SYNCIN_FSYNC_DLY_1_REG, 9242 (conf->framesync.event_offset >> 16) & 0x7, 9243 0x7));/*[18:16]*/ 9244 } 9245 9246 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 9247 _phy84834_encode_syncout_mode(conf->syncout.mode, &syncout_mode); 9248 9249 /* Interval & pulse width of syncout pulse */ 9250 SOC_IF_ERROR_RETURN 9251 (WRITE_PHY8481_PMAD_REG(unit, pc, 9252 PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_0_REG, 9253 conf->syncout.interval & 0xffff)); 9254 SOC_IF_ERROR_RETURN 9255 (WRITE_PHY8481_PMAD_REG(unit, pc, 9256 PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_1_REG, 9257 ((conf->syncout.interval >> 16) & 0xffff))); 9258 SOC_IF_ERROR_RETURN 9259 (WRITE_PHY8481_PMAD_REG(unit, pc, 9260 PHY84834_PTP_NSE_SHDW_SOUT_PULSE1_LEN_REG, 9261 conf->syncout.pulse_1_length & 0x0fff)); 9262 SOC_IF_ERROR_RETURN 9263 (WRITE_PHY8481_PMAD_REG(unit, pc, 9264 PHY84834_PTP_NSE_SHDW_SOUT_PULSE2_LEN_REG, 9265 conf->syncout.pulse_2_length & 0x0fff)); 9266 /* Local timer for SYNC_OUT */ 9267 SOC_IF_ERROR_RETURN 9268 (WRITE_PHY8481_PMAD_REG(unit, pc, 9269 PHY84834_PTP_NSE_SOUT_TS_CMP_0_REG, 9270 (uint16)(COMPILER_64_LO(conf->syncout.syncout_ts) & 0xffff))); 9271 SOC_IF_ERROR_RETURN 9272 (WRITE_PHY8481_PMAD_REG(unit, pc, 9273 PHY84834_PTP_NSE_SOUT_TS_CMP_1_REG, 9274 (uint16)((COMPILER_64_LO(conf->syncout.syncout_ts) >> 16) & 0xffff))); 9275 SOC_IF_ERROR_RETURN 9276 (WRITE_PHY8481_PMAD_REG(unit, pc, 9277 PHY84834_PTP_NSE_SOUT_TS_CMP_2_REG, 9278 (uint16)(COMPILER_64_HI(conf->syncout.syncout_ts) & 0xffff))); 9279 9280 /* Enable loading shadow reg value to active copy on next framesync */ 9281 SOC_IF_ERROR_RETURN 9282 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9283 PHY84834_PTP_NSE_SHDW_CTL_REG, 9284 PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT, 9285 PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT)); 9286 } 9287 9288 /* GMODE */ 9289 SOC_IF_ERROR_RETURN 9290 (MODIFY_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG, 9291 (gmode << 0) | (framesync_mode << 4) | (syncout_mode << 8), 9292 ( PHY84834_PTP_NSE_SC_CFG_GS_MODE | 9293 PHY84834_PTP_NSE_SC_CFG_SI_MODE | 9294 PHY84834_PTP_NSE_SC_CFG_SO_MODE)) ); 9295 /* TX TS OFFSET register */ 9296 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 9297 SOC_IF_ERROR_RETURN 9298 (WRITE_PHY8481_PMAD_REG(unit, pc, 9299 PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 9300 (uint16)(conf->tx_timestamp_offset & 0xffff))); 9301 SOC_IF_ERROR_RETURN 9302 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9303 PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 9304 (uint16)((conf->tx_timestamp_offset >> 16) & 0xf ), 9305 0xf)); 9306 9307 } 9308 9309 /* RX TS OFFSET register */ 9310 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 9311 SOC_IF_ERROR_RETURN 9312 (WRITE_PHY8481_PMAD_REG(unit, pc, 9313 PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 9314 (uint16)(conf->rx_timestamp_offset & 0xffff))); 9315 SOC_IF_ERROR_RETURN 9316 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9317 PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 9318 (uint16)((conf->rx_timestamp_offset >> 16) & 0xf ), 9319 0xf)); 9320 } 9321 9322 /* PTP TX action */ 9323 value = 0; 9324 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 9325 _phy84834_encode_egress_message_mode(conf->tx_sync_mode, 0, &value); 9326 } 9327 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 9328 _phy84834_encode_egress_message_mode(conf->tx_delay_request_mode, 4, &value); 9329 } 9330 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 9331 _phy84834_encode_egress_message_mode(conf->tx_pdelay_request_mode, 8, &value); 9332 } 9333 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 9334 _phy84834_encode_egress_message_mode(conf->tx_pdelay_response_mode, 12, &value); 9335 } 9336 SOC_IF_ERROR_RETURN 9337 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9338 PHY84834_PTP_EG_PTP_PKT_CFG_REG, 9339 value, 9340 ( PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_SYNC 9341 | PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_DREQ 9342 | PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_PDREQ 9343 | PHY84834_PTP_EG_PTP_PKT_CFG_ACTION_PTP_PDRESP)) ); 9344 /* PTP RX action */ 9345 value = 0; 9346 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 9347 _phy84834_encode_ingress_message_mode(conf->rx_sync_mode, 0, &value); 9348 } 9349 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 9350 _phy84834_encode_ingress_message_mode(conf->rx_delay_request_mode, 4, &value); 9351 } 9352 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 9353 _phy84834_encode_ingress_message_mode(conf->rx_pdelay_request_mode, 8, &value); 9354 } 9355 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 9356 _phy84834_encode_ingress_message_mode(conf->rx_pdelay_response_mode, 12, &value); 9357 } 9358 SOC_IF_ERROR_RETURN 9359 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9360 PHY84834_PTP_IG_PTP_PKT_CFG_REG, 9361 value, 9362 ( PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_SYNC 9363 | PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_DREQ 9364 | PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_PDREQ 9365 | PHY84834_PTP_IG_PTP_PKT_CFG_ACTION_PTP_PDRESP)) ); 9366 9367 /* DPLL initial reference phase */ 9368 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 9369 /* [15:0] */ 9370 SOC_IF_ERROR_RETURN 9371 (WRITE_PHY8481_PMAD_REG(unit, pc, 9372 PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_0_REG, 9373 (uint16)(COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) & 0xffff))); 9374 /* [31:16] */ 9375 SOC_IF_ERROR_RETURN 9376 (WRITE_PHY8481_PMAD_REG(unit, pc, 9377 PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_1_REG, 9378 (uint16)((COMPILER_64_LO(conf->phy_1588_dpll_ref_phase) >> 16) & 0xffff))); 9379 /* [47:32] */ 9380 SOC_IF_ERROR_RETURN 9381 (WRITE_PHY8481_PMAD_REG(unit, pc, 9382 PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_2_REG, 9383 (uint16)(COMPILER_64_HI(conf->phy_1588_dpll_ref_phase) & 0xffff))); 9384 /* Enable loading shadow reg value to active copy on next framesync */ 9385 SOC_IF_ERROR_RETURN 9386 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9387 PHY84834_PTP_NSE_SHDW_CTL_REG, 9388 PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE, 9389 PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE)); 9390 } 9391 9392 /* DPLL REF PHASE */ 9393 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 9394 SOC_IF_ERROR_RETURN 9395 (WRITE_PHY8481_PMAD_REG(unit, pc, 9396 PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_0_REG, 9397 conf->phy_1588_dpll_ref_phase_delta & 0xffff)); 9398 SOC_IF_ERROR_RETURN 9399 (WRITE_PHY8481_PMAD_REG(unit, pc, 9400 PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_1_REG, 9401 (conf->phy_1588_dpll_ref_phase_delta >> 16) & 0xffff)); 9402 /* Enable loading shadow reg value to active copy on next framesync */ 9403 SOC_IF_ERROR_RETURN 9404 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9405 PHY84834_PTP_NSE_SHDW_CTL_REG, 9406 PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD, 9407 PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD)); 9408 } 9409 9410 /* DPLL K1 */ 9411 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 9412 SOC_IF_ERROR_RETURN 9413 (WRITE_PHY8481_PMAD_REG(unit, pc, 9414 PHY84834_PTP_NSE_DPLL_SHDW_GAIN_1_REG, 9415 conf->phy_1588_dpll_k1 & 0x3f)); 9416 /* Enable loading shadow reg value to active copy on next framesync */ 9417 SOC_IF_ERROR_RETURN 9418 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9419 PHY84834_PTP_NSE_SHDW_CTL_REG, 9420 PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1, 9421 PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1)); 9422 } 9423 9424 /* DPLL K2 */ 9425 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 9426 SOC_IF_ERROR_RETURN 9427 (WRITE_PHY8481_PMAD_REG(unit, pc, 9428 PHY84834_PTP_NSE_DPLL_SHDW_GAIN_2_REG, 9429 conf->phy_1588_dpll_k2 & 0x3f)); 9430 /* Enable loading shadow reg value to active copy on next framesync */ 9431 SOC_IF_ERROR_RETURN 9432 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9433 PHY84834_PTP_NSE_SHDW_CTL_REG, 9434 PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2, 9435 PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2)); 9436 } 9437 9438 /* DPLL K3 */ 9439 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 9440 SOC_IF_ERROR_RETURN 9441 (WRITE_PHY8481_PMAD_REG(unit, pc, 9442 PHY84834_PTP_NSE_DPLL_SHDW_GAIN_3_REG, 9443 conf->phy_1588_dpll_k3 & 0x3f)); 9444 /* Enable loading shadow reg value to active copy on next framesync */ 9445 SOC_IF_ERROR_RETURN 9446 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9447 PHY84834_PTP_NSE_SHDW_CTL_REG, 9448 PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3, 9449 PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3)); 9450 } 9451 9452 /* IEEE-1588 Gen-2 Inband operation */ 9453 if ( conf->validity_mask & 9454 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL ) { 9455 /* 9456 * Inband control parameters setting 9457 */ 9458 temp16 = (conf->inband_control.resv0_id 9459 << PHY848XX_PTP_INBAND_CNTL_RESV0_ID_SHIFT) 9460 & PHY848XX_PTP_INBAND_CNTL_RESV0_ID; 9461 if ( conf->inband_control.flags & 9462 SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE ) { 9463 temp16 |= PHY848XX_PTP_INBAND_CNTL_SYNC_EN; 9464 } 9465 if ( conf->inband_control.flags & 9466 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE ) { 9467 temp16 |= PHY848XX_PTP_INBAND_CNTL_DREQ_EN; 9468 } 9469 if ( conf->inband_control.flags & 9470 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE ) { 9471 temp16 |= PHY848XX_PTP_INBAND_CNTL_PREQ_EN; 9472 } 9473 if ( conf->inband_control.flags & 9474 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE ) { 9475 temp16 |= PHY848XX_PTP_INBAND_CNTL_PRSP_EN; 9476 } 9477 9478 if ( conf->inband_control.flags & 9479 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK ) { 9480 temp16 |= PHY848XX_PTP_INBAND_CNTL_RESV0_ID_CHECK; 9481 } 9482 if ( conf->inband_control.flags & 9483 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE ) { 9484 temp16 |= PHY848XX_PTP_INBAND_CNTL_RESV0_ID_UPDATE; 9485 } 9486 if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE) || 9487 (conf->inband_control.flags & 9488 SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST) ) { 9489 temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_UPD_FOLLOW_UP | 9490 PHY848XX_PTP_INBAND_CNTL_TS_CAP_MODE; 9491 } 9492 if ( (conf->flags & SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE) || 9493 (conf->inband_control.flags & 9494 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST) ) { 9495 temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_UPD_DELAY_RSP | 9496 PHY848XX_PTP_INBAND_CNTL_TS_CAP_MODE; 9497 } 9498 if ( conf->inband_control.flags & 9499 SOC_PORT_PHY_TIMESYNC_INBAND_TIMER_MODE_SELECT ) { 9500 temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_SEL; 9501 } 9502 if ( conf->inband_control.timer_mode & 9503 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT ) { 9504 temp16 |= PHY848XX_PTP_INBAND_CNTL_TS_SEL; 9505 } 9506 /* PTP Inband Control Register, 01.0xDC00 */ 9507 SOC_IF_ERROR_RETURN 9508 (WRITE_PHY8481_PMAD_REG(unit, pc, 9509 PHY848XX_PTP_INBAND_CNTL_REG, temp16) ); 9510 9511 /* config the comparison of IP, VLAN & Source_Port in SOP memory */ 9512 temp16 = 0; 9513 if ( conf->inband_control.flags & 9514 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID) { 9515 temp16 |= PHY848XX_PTP_INBAND_CTL2_CMP_VLAN_ID; 9516 } 9517 if ( conf->inband_control.flags & 9518 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM) { 9519 temp16 |= PHY848XX_PTP_INBAND_CTL2_CMP_SRC_PORT; 9520 } 9521 if ( conf->inband_control.flags & 9522 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR ) { 9523 temp16 |= PHY848XX_PTP_INBAND_CTL2_CMP_IP_ADDR; 9524 } 9525 /* PTP Inband Control 2 Register, 01.0xDC01 */ 9526 SOC_IF_ERROR_RETURN 9527 (MODIFY_PHY8481_PMAD_REG(unit, pc, 9528 PHY848XX_PTP_INBAND_CTL2_REG, temp16, 9529 PHY848XX_PTP_INBAND_CTL2_CMP_MASK) ); 9530 } /* TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */ 9531 9532 return SOC_E_NONE; 9533 } 9534 9535 /* 9536 * Function: 9537 * phy84834_timesync_config_get 9538 * Purpose: 9539 * 9540 * Parameters: 9541 * 9542 * Returns: 9543 */ 9544 9545 int 9546 phy84834_timesync_config_get(int unit, soc_port_t port, 9547 soc_port_phy_timesync_config_t *conf) 9548 { 9549 uint16 eg_config = 0, value = 0, 9550 nse_sc_cfg = 0, nse_nco_cfg = 0, temp1, temp2, temp3, temp16 = 0 ; 9551 soc_port_phy_timesync_global_mode_t gmode = SOC_PORT_PHY_TIMESYNC_MODE_FREE; 9552 soc_port_phy_timesync_framesync_mode_t framesync_mode = SOC_PORT_PHY_TIMESYNC_FRAMESYNC_NONE; 9553 soc_port_phy_timesync_syncout_mode_t syncout_mode = SOC_PORT_PHY_TIMESYNC_SYNCOUT_DISABLE; 9554 phy_ctrl_t *pc; 9555 9556 pc = EXT_PHY_SW_STATE(unit, port); 9557 9558 if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) { 9559 return SOC_E_UNAVAIL; 9560 } 9561 conf->flags = 0; 9562 9563 /* NSE SC CFG register */ 9564 SOC_IF_ERROR_RETURN 9565 (READ_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG, &nse_sc_cfg)); 9566 9567 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FLAGS) { 9568 SOC_IF_ERROR_RETURN 9569 (_phy84834_timesync_enable_get(unit, pc, &value )); 9570 9571 if (value) { 9572 conf->flags |= SOC_PORT_PHY_TIMESYNC_ENABLE; 9573 } 9574 9575 /* Capture pkt info enabled 9576 * Note: Both tx and rx pkt capture need to be enabled 9577 * to consider this flag to be set 9578 */ 9579 temp1 = temp2 = 0; 9580 SOC_IF_ERROR_RETURN 9581 (READ_PHY8481_PMAD_REG(unit, pc, 9582 PHY84834_PTP_EG_PTP_PKT_CFG_REG, &temp1)); 9583 SOC_IF_ERROR_RETURN 9584 (READ_PHY8481_PMAD_REG(unit, pc, 9585 PHY84834_PTP_IG_PTP_PKT_CFG_REG, &temp2)); 9586 9587 if ( (temp1 & PHY84834_PTP_EG_PTP_PKT_CFG_CAPT_PTP_SYNC) && 9588 (temp2 & PHY84834_PTP_IG_PTP_PKT_CFG_CAPT_PTP_SYNC)) { 9589 conf->flags |= SOC_PORT_PHY_TIMESYNC_CAPTURE_TS_ENABLE; 9590 } 9591 9592 /* The Heartbeat registers ensure that ToD is synchronized *\ 9593 \* across the whole system. */ 9594 if (nse_sc_cfg & PHY84834_PTP_NSE_SC_CFG_FSYNC_TS_EN) { 9595 conf->flags |= SOC_PORT_PHY_TIMESYNC_HEARTBEAT_TS_ENABLE; 9596 } 9597 9598 /* RX CRC -- Igress Parser Configuration Register, Reg. 1.DA81[0] */ 9599 SOC_IF_ERROR_RETURN 9600 (READ_PHY8481_PMAD_REG(unit, pc, 9601 PHY84834_PTP_IG_CFG_REG, &temp16)); 9602 if ( temp16 & PHY84834_PTP_IG_CFG_FCS_CHECK_EN) { 9603 conf->flags |= SOC_PORT_PHY_TIMESYNC_RX_CRC_ENABLE; 9604 } 9605 9606 /* EG Config: addr check enable & packet detection *\ 9607 \* Egress Parser Configuration Register 1.DA01 */ 9608 SOC_IF_ERROR_RETURN 9609 (READ_PHY8481_PMAD_REG(unit, pc, 9610 PHY84834_PTP_EG_CFG_REG, &eg_config)); 9611 if ( eg_config & PHY84834_PTP_IG_CFG_L2_802AS_EN ) { 9612 conf->flags |= SOC_PORT_PHY_TIMESYNC_L2_ENABLE | 9613 SOC_PORT_PHY_TIMESYNC_8021AS_ENABLE; 9614 } 9615 if ( eg_config & PHY84834_PTP_IG_CFG_L4_IP4_UDP_EN ) { 9616 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP4_ENABLE; 9617 } 9618 if ( eg_config & PHY84834_PTP_IG_CFG_L4_IP6_UDP_EN ) { 9619 conf->flags |= SOC_PORT_PHY_TIMESYNC_IP6_ENABLE; 9620 } 9621 #if 0 9622 if (eg_config & PHY84834_PTP_EG_CFG_L4_IP6_UDP_ACH_EN) { 9623 eg_config |= SOC_PORT_PHY_TIMESYNC_L4_IPV6_ADDR_ENABLE; 9624 } 9625 if (eg_config & PHY84834_PTP_EG_CFG_L4_IP4_UDP_ACH_EN) { 9626 eg_config |= SOC_PORT_PHY_TIMESYNC_L4_IP_ADDR_ENABLE; 9627 } 9628 if (eg_config & PHY84834_PTP_IG_CFG_L2_802AS_ACH_EN) { 9629 eg_config |= SOC_PORT_PHY_TIMESYNC_L2_DS_ENABLE 9630 | SOC_PORT_PHY_TIMESYNC_AS_DS_ENABLE; 9631 } 9632 #endif 9633 /* CLK src for NCO */ 9634 SOC_IF_ERROR_RETURN 9635 (READ_PHY8481_PMAD_REG(unit, pc, 9636 PHY84834_PTP_NSE_NCO_CFG_REG, &nse_nco_cfg)); 9637 9638 if ( nse_nco_cfg & PHY84834_PTP_NSE_NCO_CFG_FCW_SEL ) { 9639 conf->flags |= SOC_PORT_PHY_TIMESYNC_CLOCK_SRC_EXT; 9640 } 9641 } 9642 9643 9644 /* Gmode */ 9645 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_GMODE) { 9646 _phy84834_decode_gmode(nse_sc_cfg ,&gmode); 9647 conf->gmode = gmode; 9648 } 9649 9650 /* Framesync */ 9651 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_FRAMESYNC_MODE) { 9652 _phy84834_decode_framesync_mode((nse_sc_cfg >> 4), &framesync_mode); 9653 conf->framesync.mode = framesync_mode; 9654 /* Length threshold */ 9655 SOC_IF_ERROR_RETURN 9656 (READ_PHY8481_PMAD_REG(unit, pc, 9657 PHY84834_NSE_SYNCIN_FSYNC_LEN_1_REG, 9658 &temp16)); /*[18:16]*/ 9659 conf->framesync.length_threshold = (temp16 & 0x7); 9660 conf->framesync.length_threshold <<= 16; 9661 9662 SOC_IF_ERROR_RETURN 9663 (READ_PHY8481_PMAD_REG(unit, pc, 9664 PHY84834_NSE_SYNCIN_FSYNC_LEN_0_REG, 9665 &temp16));/*[15:0]*/ 9666 conf->framesync.length_threshold |= temp16; 9667 9668 /* Event offset */ 9669 SOC_IF_ERROR_RETURN 9670 (READ_PHY8481_PMAD_REG(unit, pc, 9671 PHY84834_NSE_SYNCIN_FSYNC_DLY_1_REG, 9672 &temp16)); /*[18:16]*/ 9673 conf->framesync.event_offset = (temp16 & 0x7); 9674 conf->framesync.event_offset <<= 16; 9675 9676 SOC_IF_ERROR_RETURN 9677 (READ_PHY8481_PMAD_REG(unit, pc, 9678 PHY84834_NSE_SYNCIN_FSYNC_DLY_0_REG, 9679 &temp16));/*[15:0]*/ 9680 conf->framesync.event_offset |= temp16; 9681 9682 } 9683 9684 /* SYNC OUT */ 9685 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_SYNCOUT_MODE) { 9686 _phy84834_decode_syncout_mode((nse_sc_cfg >> 8), &syncout_mode); 9687 conf->syncout.mode = syncout_mode; 9688 9689 /* Syncout interval */ 9690 SOC_IF_ERROR_RETURN 9691 (READ_PHY8481_PMAD_REG(unit, pc, 9692 PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_1_REG, 9693 &temp16)); 9694 conf->syncout.interval = temp16; 9695 conf->syncout.interval <<= 16; 9696 9697 SOC_IF_ERROR_RETURN 9698 (READ_PHY8481_PMAD_REG(unit, pc, 9699 PHY84834_PTP_NSE_SHDW_SOUT_INTERVAL_0_REG, 9700 &temp16)); 9701 conf->syncout.interval |= temp16; 9702 9703 /* Syncout pulse 1 */ 9704 temp16 = 0; 9705 SOC_IF_ERROR_RETURN 9706 (READ_PHY8481_PMAD_REG(unit, pc, 9707 PHY84834_PTP_NSE_SHDW_SOUT_PULSE1_LEN_REG, 9708 &temp16)); 9709 conf->syncout.pulse_1_length = temp16 & 0x0fff; 9710 9711 /* Syncout pulse 2 */ 9712 temp16 = 0; 9713 SOC_IF_ERROR_RETURN 9714 (READ_PHY8481_PMAD_REG(unit, pc, 9715 PHY84834_PTP_NSE_SHDW_SOUT_PULSE2_LEN_REG, 9716 &temp16)); 9717 conf->syncout.pulse_2_length = temp16 & 0x0fff; 9718 9719 /* Syncout timestamp match value */ 9720 SOC_IF_ERROR_RETURN 9721 (READ_PHY8481_PMAD_REG(unit, pc, 9722 PHY84834_PTP_NSE_SOUT_TS_CMP_0_REG, 9723 &temp1)); 9724 SOC_IF_ERROR_RETURN 9725 (READ_PHY8481_PMAD_REG(unit, pc, 9726 PHY84834_PTP_NSE_SOUT_TS_CMP_1_REG, 9727 &temp2)); 9728 SOC_IF_ERROR_RETURN 9729 (READ_PHY8481_PMAD_REG(unit, pc, 9730 PHY84834_PTP_NSE_SOUT_TS_CMP_2_REG, 9731 &temp3)); 9732 COMPILER_64_SET(conf->syncout.syncout_ts, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 9733 } 9734 9735 /* VLAN TAG register */ 9736 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ITPID) { 9737 SOC_IF_ERROR_RETURN 9738 (READ_PHY8481_PMAD_REG(unit, pc, 9739 PHY84834_PTP_VLAN_1TAG_TPID_REG, 9740 &conf->itpid)); 9741 } 9742 9743 /* OUTER VLAN TAG register */ 9744 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID) { 9745 SOC_IF_ERROR_RETURN 9746 (READ_PHY8481_PMAD_REG(unit, pc, 9747 PHY84834_PTP_VLAN_2TAG_OTPID_REG, 9748 &conf->otpid)); 9749 } 9750 9751 /* INNER VLAN TAG register */ 9752 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_OTPID2) { 9753 SOC_IF_ERROR_RETURN 9754 (READ_PHY8481_PMAD_REG(unit, pc, 9755 PHY84834_PTP_VLAN_2TAG_OTPID_1_REG, 9756 &conf->otpid2)); 9757 } 9758 9759 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TS_DIVIDER) { 9760 SOC_IF_ERROR_RETURN 9761 (READ_PHY8481_PMAD_REG(unit, pc, 9762 PHY84834_PTP_NSE_SHDW_DPLL_SYNC_DIV_REG, 9763 &conf->ts_divider)); 9764 conf->ts_divider &= 0xfff; 9765 } 9766 9767 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_LINK_DELAY) { 9768 /* Do nothing 9769 * 9770 * In some chips there are two registers Rx timestamp offset & 9771 * Rx link delay. These two registers do similar funtion. 9772 * The offset is added to the internal timestamp, the 9773 * link delay is subtracted from it. Rx link delay control not required 9774 * in this chip. Tx/RX timestamp offset does the job. The signed value will 9775 * be added to the timestamp. 9776 */ 9777 } 9778 9779 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_ORIGINAL_TIMECODE) { 9780 /* TIME CODE 0 register */ 9781 SOC_IF_ERROR_RETURN 9782 (READ_PHY8481_PMAD_REG(unit, pc, 9783 PHY84834_PTP_NSE_SHDW_ORG_TS_0_REG, 9784 &temp1)); 9785 9786 /* TIME CODE 1 register */ 9787 SOC_IF_ERROR_RETURN 9788 (READ_PHY8481_PMAD_REG(unit, pc, 9789 PHY84834_PTP_NSE_SHDW_ORG_TS_1_REG, 9790 &temp2)); 9791 9792 conf->original_timecode.nanoseconds = ((uint32)temp2 << 16) | temp1; 9793 9794 /* TIME CODE 2 register */ 9795 SOC_IF_ERROR_RETURN 9796 (READ_PHY8481_PMAD_REG(unit, pc, 9797 PHY84834_PTP_NSE_SHDW_ORG_TS_2_REG, 9798 &temp1)); 9799 /* TIME CODE 3 register */ 9800 SOC_IF_ERROR_RETURN 9801 (READ_PHY8481_PMAD_REG(unit, pc, 9802 PHY84834_PTP_NSE_SHDW_ORG_TS_3_REG, 9803 &temp2)); 9804 /* TIME CODE 4 register */ 9805 SOC_IF_ERROR_RETURN 9806 (READ_PHY8481_PMAD_REG(unit, pc, 9807 PHY84834_PTP_NSE_SHDW_ORG_TS_4_REG, 9808 &temp3)); 9809 COMPILER_64_SET(conf->original_timecode.seconds, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 9810 } 9811 9812 /* TX TS OFFSET register */ 9813 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_TIMESTAMP_OFFSET) { 9814 9815 SOC_IF_ERROR_RETURN 9816 (READ_PHY8481_PMAD_REG(unit, pc, 9817 PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 9818 &temp1)); 9819 SOC_IF_ERROR_RETURN 9820 (READ_PHY8481_PMAD_REG(unit, pc, 9821 PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 9822 &temp2)); 9823 conf->tx_timestamp_offset = ((uint32)temp2 & 0xf) << 16 | temp1; 9824 } 9825 9826 /* RX TS OFFSET register */ 9827 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_TIMESTAMP_OFFSET) { 9828 SOC_IF_ERROR_RETURN 9829 (READ_PHY8481_PMAD_REG(unit, pc, 9830 PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 9831 (uint16 *)&temp1)); 9832 SOC_IF_ERROR_RETURN 9833 (READ_PHY8481_PMAD_REG(unit, pc, 9834 PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 9835 &temp2)); 9836 conf->rx_timestamp_offset = ((uint32)temp2 & 0xf) << 16 | temp1; 9837 } 9838 9839 /* PTP TX action */ 9840 SOC_IF_ERROR_RETURN 9841 (READ_PHY8481_PMAD_REG(unit, pc, 9842 PHY84834_PTP_EG_PTP_PKT_CFG_REG, &value)); 9843 9844 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_SYNC_MODE) { 9845 _phy84834_decode_egress_message_mode(value, 0, &conf->tx_sync_mode); 9846 } 9847 9848 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_DELAY_REQUEST_MODE) { 9849 _phy84834_decode_egress_message_mode(value, 4, &conf->tx_delay_request_mode); 9850 } 9851 9852 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_REQUEST_MODE) { 9853 _phy84834_decode_egress_message_mode(value, 8, &conf->tx_pdelay_request_mode); 9854 } 9855 9856 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_TX_PDELAY_RESPONSE_MODE) { 9857 _phy84834_decode_egress_message_mode(value, 12, &conf->tx_pdelay_response_mode); 9858 } 9859 9860 /* PTP RX action */ 9861 SOC_IF_ERROR_RETURN 9862 (READ_PHY8481_PMAD_REG(unit, pc, 9863 PHY84834_PTP_IG_PTP_PKT_CFG_REG, &value)); 9864 9865 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_SYNC_MODE) { 9866 _phy84834_decode_ingress_message_mode(value, 0, &conf->rx_sync_mode); 9867 } 9868 9869 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_DELAY_REQUEST_MODE) { 9870 _phy84834_decode_ingress_message_mode(value, 4, &conf->rx_delay_request_mode); 9871 } 9872 9873 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_REQUEST_MODE) { 9874 _phy84834_decode_ingress_message_mode(value, 8, &conf->rx_pdelay_request_mode); 9875 } 9876 9877 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_RX_PDELAY_RESPONSE_MODE) { 9878 _phy84834_decode_ingress_message_mode(value, 12, &conf->rx_pdelay_response_mode); 9879 } 9880 9881 /* DPLL initial reference phase */ 9882 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE) { 9883 /* [15:0] */ 9884 SOC_IF_ERROR_RETURN 9885 (READ_PHY8481_PMAD_REG(unit, pc, 9886 PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_0_REG, 9887 &temp1)); 9888 9889 /* [31:16] */ 9890 SOC_IF_ERROR_RETURN 9891 (READ_PHY8481_PMAD_REG(unit, pc, 9892 PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_1_REG, 9893 &temp2)); 9894 9895 /* [47:32] */ 9896 SOC_IF_ERROR_RETURN 9897 (READ_PHY8481_PMAD_REG(unit, pc, 9898 PHY84834_PTP_NSE_DPLL_SHDW_REF_PHASE_2_REG, 9899 &temp3)); 9900 9901 COMPILER_64_SET(conf->phy_1588_dpll_ref_phase, ((uint32)temp3), (((uint32)temp2<<16)|((uint32)temp1))); 9902 } 9903 9904 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_REF_PHASE_DELTA) { 9905 SOC_IF_ERROR_RETURN 9906 (READ_PHY8481_PMAD_REG(unit, pc, 9907 PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_0_REG, 9908 &temp1)); 9909 SOC_IF_ERROR_RETURN 9910 (READ_PHY8481_PMAD_REG(unit, pc, 9911 PHY84834_PTP_NSE_DPLL_SHDW_REF_PERIOD_1_REG, 9912 &temp2)); 9913 9914 conf->phy_1588_dpll_ref_phase_delta = ((uint32)temp2 << 16) | temp1; 9915 } 9916 9917 /* DPLL K1 */ 9918 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K1) { 9919 SOC_IF_ERROR_RETURN 9920 (READ_PHY8481_PMAD_REG(unit, pc, 9921 PHY84834_PTP_NSE_DPLL_SHDW_GAIN_1_REG, 9922 &conf->phy_1588_dpll_k1)); 9923 conf->phy_1588_dpll_k1 &= 0x3f; 9924 } 9925 9926 /* DPLL K2 */ 9927 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K2) { 9928 SOC_IF_ERROR_RETURN 9929 (READ_PHY8481_PMAD_REG(unit, pc, 9930 PHY84834_PTP_NSE_DPLL_SHDW_GAIN_2_REG, 9931 &conf->phy_1588_dpll_k2)); 9932 conf->phy_1588_dpll_k2 &= 0x3f; 9933 } 9934 9935 /* DPLL K3 */ 9936 if (conf->validity_mask & SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_DPLL_K3) { 9937 SOC_IF_ERROR_RETURN 9938 (READ_PHY8481_PMAD_REG(unit, pc, 9939 PHY84834_PTP_NSE_DPLL_SHDW_GAIN_3_REG, 9940 &conf->phy_1588_dpll_k3)); 9941 conf->phy_1588_dpll_k3 &= 0x3f; 9942 } 9943 9944 /* IEEE-1588 Gen-2 Inband operations */ 9945 if ( (conf->validity_mask & 9946 SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL) ) { 9947 /* PTP Inband Control Register, 1.0xDC00 */ 9948 SOC_IF_ERROR_RETURN 9949 (READ_PHY8481_PMAD_REG(unit, pc, 9950 PHY848XX_PTP_INBAND_CNTL_REG, &temp16) ); 9951 conf->inband_control.resv0_id = /* Rev0_ID[7:4] */ 9952 (temp16 & PHY848XX_PTP_INBAND_CNTL_RESV0_ID) 9953 >> PHY848XX_PTP_INBAND_CNTL_RESV0_ID_SHIFT; 9954 9955 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_SYNC_EN ) { 9956 conf->inband_control.flags |= 9957 SOC_PORT_PHY_TIMESYNC_INBAND_SYNC_ENABLE; 9958 } 9959 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_DREQ_EN ) { 9960 conf->inband_control.flags |= 9961 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RQ_ENABLE; 9962 } 9963 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_PREQ_EN ) { 9964 conf->inband_control.flags |= 9965 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RQ_ENABLE; 9966 } 9967 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_PRSP_EN ) { 9968 conf->inband_control.flags |= 9969 SOC_PORT_PHY_TIMESYNC_INBAND_PDELAY_RESP_ENABLE; 9970 } 9971 9972 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_RESV0_ID_CHECK ) { 9973 conf->inband_control.flags |= 9974 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_CHECK; 9975 } 9976 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_RESV0_ID_UPDATE ) { 9977 conf->inband_control.flags |= 9978 SOC_PORT_PHY_TIMESYNC_INBAND_RESV0_ID_UPDATE; 9979 } 9980 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_TS_UPD_FOLLOW_UP ) { 9981 conf->inband_control.flags |= 9982 SOC_PORT_PHY_TIMESYNC_INBAND_FOLLOW_UP_ASSIST; 9983 conf->flags |= 9984 SOC_PORT_PHY_TIMESYNC_FOLLOW_UP_ASSIST_ENABLE; 9985 } 9986 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_TS_UPD_DELAY_RSP ) { 9987 conf->inband_control.flags |= 9988 SOC_PORT_PHY_TIMESYNC_INBAND_DELAY_RESP_ASSIST; 9989 conf->flags |= 9990 SOC_PORT_PHY_TIMESYNC_DELAY_RESP_ASSIST_ENABLE; 9991 } 9992 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_TS_SEL ) { 9993 conf->inband_control.timer_mode |= 9994 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_80BIT; 9995 } else { 9996 conf->inband_control.timer_mode |= 9997 SOC_PORT_PHY_TIMESYNC_TIMER_MODE_48BIT; 9998 } 9999 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_IP_ADDR_EN ) { 10000 if ( temp16 & PHY848XX_PTP_INBAND_CNTL_IP_MAC_SEL ) { 10001 conf->inband_control.flags |= 10002 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_MAC_ADDR; 10003 } else { 10004 conf->inband_control.flags |= 10005 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR; 10006 } 10007 } 10008 10009 /* PTP Inband Control 2 Register, 01.0xDC01 */ 10010 SOC_IF_ERROR_RETURN 10011 (READ_PHY8481_PMAD_REG(unit, pc, 10012 PHY848XX_PTP_INBAND_CTL2_REG, &temp16) ); 10013 /* comparison of IP, VLAN & Source_Port in SOP memory */ 10014 if ( temp16 & PHY848XX_PTP_INBAND_CTL2_CMP_VLAN_ID ) { 10015 conf->inband_control.flags |= 10016 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_VLAN_ID; 10017 } 10018 if ( temp16 & PHY848XX_PTP_INBAND_CTL2_CMP_SRC_PORT ) { 10019 conf->inband_control.flags |= 10020 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_SRC_PORT_NUM; 10021 } 10022 if ( temp16 & PHY848XX_PTP_INBAND_CTL2_CMP_IP_ADDR ) { 10023 conf->inband_control.flags |= 10024 SOC_PORT_PHY_TIMESYNC_INBAND_MATCH_IP_ADDR; 10025 } 10026 } /* SOC_PORT_PHY_TIMESYNC_VALID_PHY_1588_INBAND_CONTROL */ 10027 10028 return SOC_E_NONE; 10029 } 10030 10031 10032 /* 10033 * Function: 10034 * phy84834_timesync_control_set 10035 * Purpose: 10036 * 10037 * Parameters: 10038 * 10039 * Returns: 10040 */ 10041 int 10042 phy84834_timesync_control_set(int unit, soc_port_t port, 10043 soc_port_control_phy_timesync_t type, 10044 uint64 value) 10045 { 10046 uint16 temp1, temp2; 10047 uint32 value0; 10048 phy_ctrl_t *pc; 10049 10050 pc = EXT_PHY_SW_STATE(unit, port); 10051 10052 if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) { 10053 return SOC_E_UNAVAIL; 10054 } 10055 10056 switch (type) { 10057 10058 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 10059 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 10060 return SOC_E_UNAVAIL; 10061 10062 10063 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 10064 SOC_IF_ERROR_RETURN 10065 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10066 PHY84834_PTP_NSE_NCO_CFG_REG, 10067 NCO_SHADOW_REG_STATIC_FCW, 10068 PHY84834_PTP_NSE_NCO_CFG_FCW_SEL)); 10069 SOC_IF_ERROR_RETURN 10070 (WRITE_PHY8481_PMAD_REG(unit, pc, 10071 PHY84834_NSE_NCO_SHADOW_FCW_0_REG, 10072 (uint16)(COMPILER_64_LO(value) & 0xffff))); 10073 SOC_IF_ERROR_RETURN 10074 (WRITE_PHY8481_PMAD_REG(unit, pc, 10075 PHY84834_NSE_NCO_SHADOW_FCW_1_REG, 10076 (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff))); 10077 /* Enable loading of shadow reg on next framesync */ 10078 SOC_IF_ERROR_RETURN 10079 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10080 PHY84834_PTP_NSE_SHDW_CTL_REG, 10081 PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW, 10082 PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW)); 10083 break; 10084 10085 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 10086 SOC_IF_ERROR_RETURN 10087 (MODIFY_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG, 10088 (uint16) ((COMPILER_64_LO(value) & 0x07) << 4), 10089 PHY84834_PTP_NSE_SC_CFG_SI_MODE)); 10090 break; 10091 10092 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 10093 SOC_IF_ERROR_RETURN 10094 (WRITE_PHY8481_PMAD_REG(unit, pc, 10095 PHY84834_NSE_NCO_SHADOW_TIME_HIGH_0_REG, 10096 (uint16)(COMPILER_64_LO(value) & 0xffff))); 10097 SOC_IF_ERROR_RETURN 10098 (WRITE_PHY8481_PMAD_REG(unit, pc, 10099 PHY84834_NSE_NCO_SHADOW_TIME_HIGH_1_REG, 10100 (uint16)((COMPILER_64_LO(value) >> 16) & 0xffff))); 10101 SOC_IF_ERROR_RETURN 10102 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10103 PHY84834_NSE_NCO_SHADOW_TIME_HIGH_2_REG, 10104 (uint16)COMPILER_64_HI(value), 0x0fff)); 10105 /* Enable loading of shadow reg on next framesync */ 10106 SOC_IF_ERROR_RETURN 10107 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10108 PHY84834_PTP_NSE_SHDW_CTL_REG, 10109 PHY84834_PTP_NSW_SHDW_CTL_LOAD_COUNT_HIGH, 10110 PHY84834_PTP_NSW_SHDW_CTL_LOAD_COUNT_HIGH)); 10111 break; 10112 10113 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 10114 temp1 = temp2 = 0; 10115 value0 = COMPILER_64_LO(value); 10116 10117 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD) { 10118 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS; 10119 } 10120 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD) { 10121 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_ORIG_TS; 10122 } 10123 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD) { 10124 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT; 10125 } 10126 if (value0 & SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD) { 10127 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNCOUT; 10128 } 10129 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD) { 10130 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV; 10131 } 10132 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD) { 10133 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNC_DIV; 10134 } 10135 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_LOAD) { 10136 temp1 |= PHY84834_PTP_NSW_SHDW_CTL_LOAD_NTP_TIME; 10137 } 10138 if (value0 & SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD) { 10139 temp2 |= PHY84834_PTP_NSW_SHDW_CLR_LOAD_NTP_TIME; 10140 } 10141 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD) { 10142 temp1 |= PHY84834_PTP_NSW_SHDW_CTL_LOAD_TIME_COUNT; 10143 } 10144 if (value0 & SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD) { 10145 temp2 |= PHY84834_PTP_NSW_SHDW_CLR_LOAD_TIME_COUNT; 10146 } 10147 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD) { 10148 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW; 10149 } 10150 if (value0 & SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD) { 10151 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_NCO_FCW; 10152 } 10153 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD) { 10154 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_FCW; 10155 } 10156 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD) { 10157 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_FCW; 10158 } 10159 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD) { 10160 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE; 10161 } 10162 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD) { 10163 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PHASE; 10164 } 10165 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD) { 10166 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD; 10167 } 10168 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD) { 10169 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PERIOD; 10170 } 10171 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD) { 10172 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3; 10173 } 10174 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD) { 10175 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN3; 10176 } 10177 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD) { 10178 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2; 10179 } 10180 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD) { 10181 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN2; 10182 } 10183 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD) { 10184 temp1 |= PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1; 10185 } 10186 if (value0 & SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD) { 10187 temp2 |= PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN1; 10188 } 10189 SOC_IF_ERROR_RETURN 10190 (WRITE_PHY8481_PMAD_REG(unit, pc, 10191 PHY84834_PTP_NSE_SHDW_CTL_REG, temp1)); 10192 SOC_IF_ERROR_RETURN 10193 (WRITE_PHY8481_PMAD_REG(unit, pc, 10194 PHY84834_PTP_NSE_SHDW_CLR_REG, temp2)); 10195 break; 10196 10197 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT_MASK: 10198 temp1 = 0; 10199 value0 = COMPILER_64_LO(value); 10200 10201 if (value0 & SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT) { 10202 temp1 |= PHY84834_PTP_INT_PIC_EN; 10203 } 10204 if (value0 & SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT) { 10205 temp1 |= PHY84834_PTP_INT_FSYNC_EN; 10206 } 10207 SOC_IF_ERROR_RETURN 10208 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10209 PHY84834_PTP_INT_EN_REG, 10210 temp1, 10211 (PHY84834_PTP_INT_PIC_EN | 10212 PHY84834_PTP_INT_FSYNC_EN))); 10213 break; 10214 10215 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 10216 value0 = COMPILER_64_LO(value); 10217 SOC_IF_ERROR_RETURN 10218 (WRITE_PHY8481_PMAD_REG(unit, pc, 10219 PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 10220 (uint16)(value0 & 0xffff))); 10221 SOC_IF_ERROR_RETURN 10222 (WRITE_PHY8481_PMAD_REG(unit, pc, 10223 PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 10224 (uint16)((value0 >> 16) & 0xf))); 10225 break; 10226 10227 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 10228 value0 = COMPILER_64_LO(value); 10229 SOC_IF_ERROR_RETURN 10230 (WRITE_PHY8481_PMAD_REG(unit, pc, 10231 PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 10232 (uint16)(value0 & 0xffff))); 10233 SOC_IF_ERROR_RETURN 10234 (WRITE_PHY8481_PMAD_REG(unit, pc, 10235 PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 10236 (uint16)((value0 >> 16) & 0xf))); 10237 break; 10238 10239 default: 10240 return SOC_E_UNAVAIL; 10241 break; 10242 } 10243 10244 return SOC_E_NONE; 10245 } 10246 10247 /* 10248 * Function: 10249 * phy84834_timesync_control_get 10250 * Purpose: 10251 * 10252 * Parameters: 10253 * 10254 * Returns: 10255 */ 10256 int 10257 phy84834_timesync_control_get(int unit, soc_port_t port, 10258 soc_port_control_phy_timesync_t type, 10259 uint64 *value) 10260 { 10261 uint16 value0 = 0; 10262 uint16 value1 = 0; 10263 uint16 value2 = 0; 10264 uint16 value3 = 0; 10265 uint32 value32; 10266 phy_ctrl_t *pc; 10267 10268 pc = EXT_PHY_SW_STATE(unit, port); 10269 10270 if ( PHY_IS_BCM8488X(pc) || (! PHY_IS_BCM8483X_AND_UP(pc)) ) { 10271 return SOC_E_UNAVAIL; 10272 } 10273 10274 switch (type) { 10275 case SOC_PORT_CONTROL_PHY_TIMESYNC_HEARTBEAT_TIMESTAMP: 10276 10277 SOC_IF_ERROR_RETURN 10278 (READ_PHY8481_PMAD_REG(unit, pc, 10279 PHY84834_PTP_NSE_SC_COUNTSTAMP_FSYNC_0_REG, 10280 &value0)); 10281 SOC_IF_ERROR_RETURN 10282 (READ_PHY8481_PMAD_REG(unit, pc, 10283 PHY84834_PTP_NSE_SC_COUNTSTAMP_FSYNC_1_REG, 10284 &value1)); 10285 SOC_IF_ERROR_RETURN 10286 (READ_PHY8481_PMAD_REG(unit, pc, 10287 PHY84834_PTP_NSE_SC_COUNTSTAMP_FSYNC_2_REG, 10288 &value2)); 10289 COMPILER_64_SET((*value), (((uint32)value3<<16)|((uint32)value2)), 10290 (((uint32)value1<<16)|((uint32)value0))); 10291 break; 10292 10293 case SOC_PORT_CONTROL_PHY_TIMESYNC_CAPTURE_TIMESTAMP: 10294 10295 SOC_IF_ERROR_RETURN 10296 (READ_PHY8481_PMAD_REG(unit, pc, 10297 PHY84834_PTP_PIC_FIFO_RD_PKT_TS_0_REG, 10298 &value0)); 10299 SOC_IF_ERROR_RETURN 10300 (READ_PHY8481_PMAD_REG(unit, pc, 10301 PHY84834_PTP_PIC_FIFO_RD_PKT_TS_1_REG, 10302 &value1)); 10303 SOC_IF_ERROR_RETURN 10304 (READ_PHY8481_PMAD_REG(unit, pc, 10305 PHY84834_PTP_PIC_FIFO_RD_PKT_TS_2_REG, 10306 &value2)); 10307 SOC_IF_ERROR_RETURN 10308 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10309 PHY84834_PTP_PIC_FIFO_CTL_REG, 0x0001, 0x0001)); 10310 10311 COMPILER_64_SET((*value), (((uint32)value3<<16)|((uint32)value2)), 10312 (((uint32)value1<<16)|((uint32)value0))); 10313 break; 10314 10315 case SOC_PORT_CONTROL_PHY_TIMESYNC_NCOADDEND: 10316 SOC_IF_ERROR_RETURN 10317 (READ_PHY8481_PMAD_REG(unit, pc, 10318 PHY84834_NSE_NCO_SHADOW_FCW_0_REG, 10319 &value0)); 10320 SOC_IF_ERROR_RETURN 10321 (READ_PHY8481_PMAD_REG(unit, pc, 10322 PHY84834_NSE_NCO_SHADOW_FCW_1_REG, 10323 &value1)); 10324 COMPILER_64_SET((*value), (((uint32)value3<<16)|((uint32)value2)), 10325 (((uint32)value1<<16)|((uint32)value0))); 10326 break; 10327 10328 case SOC_PORT_CONTROL_PHY_TIMESYNC_FRAMESYNC: 10329 SOC_IF_ERROR_RETURN 10330 (READ_PHY8481_PMAD_REG(unit, pc, PHY84834_PTP_NSE_SC_CFG_REG, 10331 &value0)); 10332 COMPILER_64_SET((*value), 0, 10333 (value0 & (PHY84834_PTP_NSE_SC_CFG_SI_MODE)) >> 4); 10334 LOG_WARN(BSL_LS_SOC_PHY, (BSL_META_U(unit, "u=%d p=%d v0=0x%x v=0x%x\n"), unit,pc->port,value0,(COMPILER_64_LO(*value)))); 10335 break; 10336 10337 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOCAL_TIME: 10338 SOC_IF_ERROR_RETURN 10339 (READ_PHY8481_PMAD_REG(unit, pc, 10340 PHY84834_NSE_NCO_SHADOW_TIME_HIGH_0_REG, 10341 &value0)); 10342 SOC_IF_ERROR_RETURN 10343 (READ_PHY8481_PMAD_REG(unit, pc, 10344 PHY84834_NSE_NCO_SHADOW_TIME_HIGH_1_REG, 10345 &value1)); 10346 SOC_IF_ERROR_RETURN 10347 (READ_PHY8481_PMAD_REG(unit, pc, 10348 PHY84834_NSE_NCO_SHADOW_TIME_HIGH_2_REG, 10349 &value2)); 10350 10351 COMPILER_64_SET((*value), ((uint32)(value2 & 0x0fff)), 10352 (((uint32)value1<<16)|((uint32)value0))); 10353 break; 10354 10355 case SOC_PORT_CONTROL_PHY_TIMESYNC_LOAD_CONTROL: 10356 value32 = 0; 10357 SOC_IF_ERROR_RETURN 10358 (READ_PHY8481_PMAD_REG(unit, pc, 10359 PHY84834_PTP_NSE_SHDW_CTL_REG, &value1)); 10360 SOC_IF_ERROR_RETURN 10361 (READ_PHY8481_PMAD_REG(unit, pc, 10362 PHY84834_PTP_NSE_SHDW_CLR_REG, &value2)); 10363 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_ORIG_TS) { 10364 value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_LOAD; 10365 } 10366 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_ORIG_TS) { 10367 value32 |= SOC_PORT_PHY_TIMESYNC_TIMECODE_ALWAYS_LOAD; 10368 } 10369 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNCOUT) { 10370 value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_LOAD; 10371 } 10372 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNCOUT) { 10373 value32 |= SOC_PORT_PHY_TIMESYNC_SYNCOUT_ALWAYS_LOAD; 10374 } 10375 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_SYNC_DIV) { 10376 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_LOAD; 10377 } 10378 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_SYNC_DIV) { 10379 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_DIVIDER_ALWAYS_LOAD; 10380 } 10381 if (value1 & PHY84834_PTP_NSW_SHDW_CTL_LOAD_NTP_TIME) { 10382 value32 |= SOC_PORT_PHY_TIMESYNC_TN_LOAD; 10383 } 10384 if (value2 & PHY84834_PTP_NSW_SHDW_CLR_LOAD_NTP_TIME) { 10385 value32 |= SOC_PORT_PHY_TIMESYNC_TN_ALWAYS_LOAD; 10386 } 10387 if (value1 & PHY84834_PTP_NSW_SHDW_CTL_LOAD_TIME_COUNT) { 10388 value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_LOAD; 10389 } 10390 if (value2 & PHY84834_PTP_NSW_SHDW_CLR_LOAD_TIME_COUNT) { 10391 value32 |= SOC_PORT_PHY_TIMESYNC_LOCAL_TIME_ALWAYS_LOAD; 10392 } 10393 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_NCO_FCW) { 10394 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_LOAD; 10395 } 10396 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_NCO_FCW) { 10397 value32 |= SOC_PORT_PHY_TIMESYNC_NCO_ADDEND_ALWAYS_LOAD; 10398 } 10399 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_FCW ) { 10400 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_LOAD; 10401 } 10402 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_FCW ) { 10403 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_LOOP_FILTER_ALWAYS_LOAD; 10404 } 10405 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PHASE) { 10406 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_LOAD; 10407 } 10408 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PHASE) { 10409 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_ALWAYS_LOAD; 10410 } 10411 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_REF_PERIOD) { 10412 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_LOAD; 10413 } 10414 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_REF_PERIOD) { 10415 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_REF_PHASE_DELTA_ALWAYS_LOAD; 10416 } 10417 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN3) { 10418 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_LOAD; 10419 } 10420 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN3) { 10421 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K3_ALWAYS_LOAD; 10422 } 10423 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN2) { 10424 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_LOAD; 10425 } 10426 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN2) { 10427 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K2_ALWAYS_LOAD; 10428 } 10429 if (value1 & PHY84834_PTP_NSE_SHDW_CTL_LOAD_DPLL_GAIN1) { 10430 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_LOAD; 10431 } 10432 if (value2 & PHY84834_PTP_NSE_SHDW_CLR_LOAD_DPLL_GAIN1) { 10433 value32 |= SOC_PORT_PHY_TIMESYNC_DPLL_K1_ALWAYS_LOAD; 10434 } 10435 COMPILER_64_SET((*value), 0, (uint32)value32); 10436 break; 10437 10438 case SOC_PORT_CONTROL_PHY_TIMESYNC_INTERRUPT: 10439 SOC_IF_ERROR_RETURN 10440 (READ_PHY8481_PMAD_REG(unit, pc, 10441 PHY84834_PTP_INT_STATUS_REG, 10442 &value1)); 10443 value32 = 0; 10444 if (value1 & PHY84834_PTP_INT_STATUS_PIC) { 10445 /* Clear the interrupt status. Not self clearing! */ 10446 SOC_IF_ERROR_RETURN 10447 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10448 PHY84834_PTP_INT_CLEAR_REG, 10449 PHY84834_PTP_INT_CLEAR_PIC, 10450 PHY84834_PTP_INT_CLEAR_PIC)); 10451 value32 |= SOC_PORT_PHY_TIMESYNC_TIMESTAMP_INTERRUPT; 10452 } 10453 if (value1 & PHY84834_PTP_INT_CLEAR_FSYNC) { 10454 /* Clear the interrupt status. Not self clearing! */ 10455 SOC_IF_ERROR_RETURN 10456 (MODIFY_PHY8481_PMAD_REG(unit, pc, 10457 PHY84834_PTP_INT_CLEAR_REG, 10458 PHY84834_PTP_INT_CLEAR_FSYNC, 10459 PHY84834_PTP_INT_CLEAR_FSYNC)); 10460 value32 |= SOC_PORT_PHY_TIMESYNC_FRAMESYNC_INTERRUPT; 10461 } 10462 COMPILER_64_SET((*value), 0, (uint32)value32); 10463 break; 10464 10465 case SOC_PORT_CONTROL_PHY_TIMESYNC_TX_TIMESTAMP_OFFSET: 10466 SOC_IF_ERROR_RETURN 10467 (READ_PHY8481_PMAD_REG(unit, pc, 10468 PHY84834_PTP_TS_EG_SOP_OFFSET_0_REG, 10469 &value0)); 10470 SOC_IF_ERROR_RETURN 10471 (READ_PHY8481_PMAD_REG(unit, pc, 10472 PHY84834_PTP_TS_EG_SOP_OFFSET_1_REG, 10473 &value1)); 10474 COMPILER_64_SET((*value), 0, ((uint32)(value1 & 0xf) << 16) | (uint32)(value0 & 0x0fff)); 10475 break; 10476 10477 case SOC_PORT_CONTROL_PHY_TIMESYNC_RX_TIMESTAMP_OFFSET: 10478 SOC_IF_ERROR_RETURN 10479 (READ_PHY8481_PMAD_REG(unit, pc, 10480 PHY84834_PTP_TS_IG_SOP_OFFSET_0_REG, 10481 &value0)); 10482 SOC_IF_ERROR_RETURN 10483 (READ_PHY8481_PMAD_REG(unit, pc, 10484 PHY84834_PTP_TS_IG_SOP_OFFSET_1_REG, 10485 &value1)); 10486 COMPILER_64_SET((*value), 0, ((uint32)(value1 & 0xf) << 16) | (uint32)(value0 & 0x0fff)); 10487 break; 10488 10489 default: 10490 return SOC_E_UNAVAIL; 10491 } 10492 10493 return SOC_E_NONE; 10494 } 10495 10496 /* 10497 * Function: 10498 * phy_8481_reg_read 10499 * Purpose: 10500 * Routine to read PHY register 10501 * Parameters: 10502 * uint - BCM unit number 10503 * port - port number 10504 * flags - Flags which specify the register type 10505 * phy_reg_addr - Encoded register address 10506 * phy_data - (OUT) Value read from PHY register 10507 */ 10508 STATIC int 10509 phy_8481_reg_read(int unit, soc_port_t port, uint32 flags, 10510 uint32 phy_reg_addr, uint32 *phy_data) 10511 { 10512 phy_ctrl_t *pc; 10513 uint32 reg_flags; 10514 uint16 reg_bank; 10515 uint8 reg_addr; 10516 uint16 data16; 10517 10518 pc = EXT_PHY_SW_STATE(unit, port); 10519 10520 if (PHY_COPPER_MODE(unit, port)) { 10521 if ((SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr) == 0x7) && 10522 (SOC_PHY_CLAUSE45_REGAD(phy_reg_addr) >= 0xffe0)) { 10523 reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr); 10524 reg_bank = SOC_PHY_REG_BANK(phy_reg_addr); 10525 reg_addr = SOC_PHY_REG_ADDR(phy_reg_addr); 10526 /* handle gphy registers */ 10527 SOC_IF_ERROR_RETURN 10528 (phy_8481_reg_xge_read(unit, pc, reg_flags, reg_bank, PHY8481_C45_DEV_AN, reg_addr, &data16)); 10529 } else { 10530 SOC_IF_ERROR_RETURN 10531 (READ_PHY_REG(unit, pc, phy_reg_addr, &data16)); 10532 } 10533 *phy_data = (uint32)data16; 10534 } else { 10535 if (NXT_PC(pc)) { 10536 PHYDRV_CALL_ARG3(pc,PHY_REG_READ,flags,phy_reg_addr,phy_data); 10537 } 10538 } 10539 return SOC_E_NONE; 10540 } 10541 10542 /* 10543 * Function: 10544 * phy_8481_reg_write 10545 * Purpose: 10546 * Routine to write PHY register 10547 * Parameters: 10548 * uint - BCM unit number 10549 * port - port number 10550 * flags - Flags which specify the register type 10551 * phy_reg_addr - Encoded register address 10552 * phy_data - (IN) Value written to PHY register 10553 */ 10554 STATIC int 10555 phy_8481_reg_write(int unit, soc_port_t port, uint32 flags, 10556 uint32 phy_reg_addr, uint32 phy_data) 10557 { 10558 phy_ctrl_t *pc; /* PHY software state */ 10559 uint32 reg_flags; 10560 uint16 reg_bank; 10561 uint8 reg_addr; 10562 uint16 data16; 10563 10564 pc = EXT_PHY_SW_STATE(unit, port); 10565 10566 if (PHY_COPPER_MODE(unit, port)) { 10567 data16 = (uint16)(phy_data & 0xffff); 10568 10569 if ((SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr) == 0x7) && 10570 (SOC_PHY_CLAUSE45_REGAD(phy_reg_addr) >= 0xffe0)) { 10571 reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr); 10572 reg_bank = SOC_PHY_REG_BANK(phy_reg_addr); 10573 reg_addr = SOC_PHY_REG_ADDR(phy_reg_addr); 10574 /* handle gphy registers */ 10575 SOC_IF_ERROR_RETURN 10576 (phy_8481_reg_xge_write(unit, pc, reg_flags, reg_bank, PHY8481_C45_DEV_AN, reg_addr, data16)); 10577 } else { 10578 SOC_IF_ERROR_RETURN 10579 (WRITE_PHY_REG(unit, pc, phy_reg_addr, data16)); 10580 } 10581 } else { 10582 if (NXT_PC(pc)) { 10583 PHYDRV_CALL_ARG3(pc, PHY_REG_WRITE, flags, phy_reg_addr, phy_data); 10584 } 10585 } 10586 return SOC_E_NONE; 10587 } 10588 10589 /* 10590 * Function: 10591 * phy_8481_reg_modify 10592 * Purpose: 10593 * Routine to read PHY register 10594 * Parameters: 10595 * uint - BCM unit number 10596 * port - port number 10597 * flags - Flags which specify the register type 10598 * phy_reg_addr - Encoded register address 10599 * phy_data - (IN) Value written to PHY register 10600 * phy_data_mask - (IN) Mask used for writing 10601 */ 10602 STATIC int 10603 phy_8481_reg_modify(int unit, soc_port_t port, uint32 flags, 10604 uint32 phy_reg_addr, uint32 phy_data, uint32 phy_data_mask) 10605 { 10606 phy_ctrl_t *pc; /* PHY software state */ 10607 uint32 reg_flags; 10608 uint16 reg_bank; 10609 uint8 reg_addr; 10610 uint16 data16; 10611 uint16 mask16; 10612 10613 pc = EXT_PHY_SW_STATE(unit, port); 10614 10615 if (PHY_COPPER_MODE(unit, port)) { 10616 data16 = (uint16)(phy_data & 0xffff); 10617 mask16 = (uint16)(phy_data_mask & 0xffff); 10618 10619 if ((SOC_PHY_CLAUSE45_DEVAD(phy_reg_addr) == 0x7) && 10620 (SOC_PHY_CLAUSE45_REGAD(phy_reg_addr) >= 0xffe0)) { 10621 reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr); 10622 reg_bank = SOC_PHY_REG_BANK(phy_reg_addr); 10623 reg_addr = SOC_PHY_REG_ADDR(phy_reg_addr); 10624 /* handle gphy registers */ 10625 SOC_IF_ERROR_RETURN 10626 (phy_8481_reg_xge_modify(unit, pc, reg_flags, reg_bank, PHY8481_C45_DEV_AN, reg_addr, data16, mask16)); 10627 } else { 10628 SOC_IF_ERROR_RETURN 10629 (MODIFY_PHY_REG(unit, pc, phy_reg_addr, data16, mask16)); 10630 } 10631 } else { 10632 if (NXT_PC(pc)) { 10633 PHYDRV_CALL_ARG4(pc, PHY_REG_MODIFY, flags, phy_reg_addr, phy_data, phy_data_mask); 10634 } 10635 } 10636 return SOC_E_NONE; 10637 } 10638 10639 int 10640 phy_8481_reg_xge_read(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 10641 uint8 dev_addr, uint16 reg_addr, uint16 *data) 10642 { 10643 uint32 value; 10644 uint16 tmp, tmp2 = 0; 10645 uint16 reg_group, bit_shift; 10646 int rv = SOC_E_NONE; 10647 10648 /* Atomic read/write way - new FW */ 10649 if ( FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD ) { 10650 switch(reg_addr) { 10651 /* Map shadow registers */ 10652 case 0xfff5: 10653 reg_group = REG_GROUP_SHADOW_MISC_REG; 10654 bit_shift = 0x0; 10655 break; 10656 case 0xfff8: 10657 reg_group = REG_GROUP_SHADOW18; 10658 bit_shift = 0x0; 10659 break; 10660 case 0xfffc: 10661 reg_group = REG_GROUP_SHADOW1c; 10662 bit_shift = 0x0; 10663 break; 10664 case 0xfffd: 10665 reg_group = REG_GROUP_SHADOW_EXP_REG; 10666 bit_shift = 0x0; 10667 break; 10668 default: 10669 if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { 10670 /* Must not read from reserved registers */ 10671 if (reg_addr > 0xfffe) { 10672 rv = SOC_E_PARAM; 10673 } 10674 } 10675 reg_group = REG_GROUP_SHADOW_EXP_REG; 10676 bit_shift = 0x0; 10677 if (SOC_SUCCESS(rv)) { 10678 rv = READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data); 10679 return rv; 10680 } 10681 break; 10682 } 10683 if (SOC_SUCCESS(rv)) { 10684 if(!(flags & SOC_PHY_REG_DUMMY_ACCESS)) { 10685 rv = _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank, 0xffff , bit_shift, data); 10686 } else { 10687 10688 reg_group = REG_GROUP_SHADOW_EXP_REG; 10689 bit_shift = 0x0; 10690 10691 do { 10692 rv = _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp); 10693 if (SOC_FAILURE(rv)) { 10694 break; 10695 } 10696 rv = _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp); 10697 if (SOC_FAILURE(rv)) { 10698 break; 10699 } 10700 rv = _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp); 10701 if (SOC_FAILURE(rv)) { 10702 break; 10703 } 10704 rv = _phy8485x_shadow_reg_read(unit, pc, reg_group, reg_bank & 0xff , 0xffff , bit_shift, &tmp2); 10705 } while(0); 10706 10707 value = tmp2; 10708 value <<= 16; /*upper count*/ 10709 value |= tmp; 10710 * ((uint32 *) data) = value; 10711 } 10712 } 10713 } 10714 else { /* (! PHY8483X_ATOMIC_ACCESS_SHD), old way if FW is old */ 10715 rv = READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data); 10716 } 10717 10718 if ( SOC_FAILURE(rv) ) { 10719 LOG_INFO(BSL_LS_SOC_PHY, 10720 (BSL_META_U(unit, 10721 "phy_8481_reg_xge_read failed:" 10722 " u=%d phy_id=0x%2x dev_addr=0x%02x reg_bank=0x%04x reg_addr=0x%02x" 10723 " rv=%d\n"), unit, pc->phy_id, dev_addr, reg_bank, reg_addr, rv)); 10724 } 10725 return rv; 10726 } 10727 10728 int 10729 phy_8481_reg_xge_write(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 10730 uint8 dev_addr, uint16 reg_addr, uint16 data) 10731 { 10732 uint16 reg_group, bit_shift; 10733 int rv = SOC_E_NONE; 10734 10735 if ( SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ) { 10736 return rv; 10737 } 10738 10739 /* Atomic read/write way - new FW */ 10740 if ( FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD ) { 10741 /* Map shadow registers */ 10742 switch(reg_addr) { 10743 case 0xfff5: 10744 reg_group = REG_GROUP_SHADOW_MISC_REG; 10745 bit_shift = 0x0; 10746 break; 10747 case 0xfff8: 10748 reg_group = REG_GROUP_SHADOW18; 10749 bit_shift = 0x0; 10750 break; 10751 case 0xfffc: 10752 reg_group = REG_GROUP_SHADOW1c; 10753 bit_shift = 0x0; 10754 break; 10755 case 0xfffd: 10756 reg_group = REG_GROUP_SHADOW_EXP_REG; 10757 bit_shift = 0x0; 10758 break; 10759 default: 10760 if ( ! (flags & SOC_PHY_REG_RESERVE_ACCESS) ) { 10761 /* Must not write to reserved registers */ 10762 if (reg_addr > 0xfffe) { 10763 rv = SOC_E_PARAM; 10764 } 10765 } 10766 reg_group = REG_GROUP_SHADOW_EXP_REG; 10767 bit_shift = 0x0; 10768 if ( SOC_SUCCESS(rv) ) { 10769 rv = WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data); 10770 return rv; 10771 } 10772 break; 10773 } 10774 if (SOC_SUCCESS(rv)) { 10775 rv = _phy8485x_shadow_reg_write(unit, pc, reg_group, reg_bank, 0xffff , bit_shift, data); 10776 } 10777 } 10778 else { /* (! PHY8483X_ATOMIC_ACCESS_SHD), old way if FW is old */ 10779 rv = WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data); 10780 } 10781 10782 if (SOC_FAILURE(rv)) { 10783 if ( SOC_FAILURE(rv) ) { 10784 LOG_INFO(BSL_LS_SOC_PHY, 10785 (BSL_META_U(unit, 10786 "phy_8481_reg_xge_write failed:" 10787 " u=%d phy_id=0x%2x dev_addr=0x%02x reg_bank=0x%04x reg_addr=0x%02x" 10788 " rv=%d\n"), unit, pc->phy_id, dev_addr, reg_bank, reg_addr, rv)); 10789 } 10790 } 10791 10792 PHY8481_D7_FFXX_REG_VERIFY(unit, pc, flags, reg_bank, reg_addr); 10793 return rv; 10794 } 10795 10796 int 10797 phy_8481_reg_xge_modify(int unit, phy_ctrl_t *pc, uint32 flags, uint16 reg_bank, 10798 uint8 dev_addr, uint16 reg_addr, uint16 data, uint16 mask) 10799 { 10800 int rv; 10801 uint16 reg_group, bit_shift; 10802 10803 rv = SOC_E_NONE; 10804 10805 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) { 10806 return rv; 10807 } 10808 10809 /* Atomic read/write way - new FW */ 10810 if (FLAGS(pc) & PHY8483X_ATOMIC_ACCESS_SHD) { 10811 switch(reg_addr) { 10812 /* Map shadow registers */ 10813 case 0xfff5: 10814 reg_group = REG_GROUP_SHADOW_MISC_REG; 10815 bit_shift = 0x0; 10816 break; 10817 case 0xfff8: 10818 reg_group = REG_GROUP_SHADOW18; 10819 bit_shift = 0x0; 10820 if (reg_bank == 0x0007) { 10821 data |= 0x8000; 10822 mask |= 0x8000; 10823 } 10824 break; 10825 case 0xfffc: 10826 reg_group = REG_GROUP_SHADOW1c; 10827 bit_shift = 0x0; 10828 break; 10829 case 0xfffd: 10830 reg_group = REG_GROUP_SHADOW_EXP_REG; 10831 bit_shift = 0x0; 10832 break; 10833 default: 10834 if (!(flags & SOC_PHY_REG_RESERVE_ACCESS)) { 10835 /* Must not write to reserved registers */ 10836 if (reg_addr > 0xfffe) { 10837 rv = SOC_E_PARAM; 10838 } 10839 } 10840 reg_group = REG_GROUP_SHADOW_EXP_REG; 10841 bit_shift = 0x0; 10842 if (SOC_SUCCESS(rv)) { 10843 rv = MODIFY_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data, mask); 10844 return rv; 10845 } 10846 break; 10847 } 10848 if (SOC_SUCCESS(rv)) { 10849 rv = _phy8485x_shadow_reg_write(unit, pc, reg_group, reg_bank, mask , bit_shift, data); 10850 } 10851 } 10852 else { /* (! PHY8483X_ATOMIC_ACCESS_SHD), old way if FW is old */ 10853 rv = MODIFY_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(dev_addr, reg_addr), data, mask); 10854 } 10855 10856 if (SOC_FAILURE(rv)) { 10857 LOG_INFO(BSL_LS_SOC_PHY, 10858 (BSL_META_U(unit, 10859 "phy_8481_reg_xge_modify failed:" 10860 " u=%d phy_id=0x%2x dev_addr=0x%02x reg_bank=0x%04x reg_addr=0x%02x" 10861 " rv=%d\n"), unit, pc->phy_id, dev_addr, reg_bank, reg_addr, rv)); 10862 } 10863 10864 PHY8481_D7_FFXX_REG_VERIFY( unit, pc, flags, reg_bank, reg_addr); 10865 return rv; 10866 } 10867 10868 10869 #ifdef PHY8481_FW_DEBUG 10870 int 10871 phy_8481_fw_reg_dump(int unit, soc_port_t port) 10872 { 10873 phy_ctrl_t *pc; 10874 uint16 config, status; 10875 char *mac_mode, *line_mode, *cu_speed, *fiber_speed, *line_device, *mac_device, *crc_status; 10876 10877 pc = EXT_PHY_SW_STATE(unit, port); 10878 10879 SOC_IF_ERROR_RETURN 10880 (READ_PHY8481_TOP_CONFIG_XGPHY_STRAP1_REG(unit, pc, &config)); 10881 10882 SOC_IF_ERROR_RETURN 10883 (READ_PHY8481_TOP_CONFIG_LINK_STATUS_REG(unit, pc, &status)); 10884 10885 LOG_CLI((BSL_META_U(unit, 10886 "TOP_CONFIG_XGPHY_STRAP1_REG = 0x%04x\n"), config)); 10887 10888 switch ((config >> 3) & 0x3) { 10889 case 0: 10890 mac_mode = "00 - XAUI_M - Disabled, XFI - Enabled"; 10891 break; 10892 case 1: 10893 mac_mode = "01 - XAUI_M - Enabled, XFI - Disabled"; 10894 break; 10895 case 2: 10896 mac_mode = "10 - RESERVED"; 10897 break; 10898 case 3: 10899 mac_mode = "11 - RESERVED"; 10900 break; 10901 default: 10902 mac_mode = '\0'; 10903 break; 10904 } 10905 10906 switch ((config >> 5) & 0x3) { 10907 case 0: 10908 line_mode = "00 - XAUI_L - Disabled, XFI - Disabled"; 10909 break; 10910 case 1: 10911 line_mode = "01 - XAUI_L - Enabled (Autodetect with Cu), XFI - Disabled"; 10912 break; 10913 case 2: 10914 line_mode = "10 - XAUI_L - Disabled, XFI - Enabled (Autodetect with Cu)"; 10915 break; 10916 case 3: 10917 line_mode = "11 - RESERVED"; 10918 break; 10919 default: 10920 line_mode = '\0'; 10921 break; 10922 } 10923 10924 /* Print the config results */ 10925 LOG_CLI((BSL_META_U(unit, 10926 "MAC mode = %s\n"), mac_mode)); 10927 10928 LOG_CLI((BSL_META_U(unit, 10929 "LINE mode = %s\n"), line_mode)); 10930 10931 LOG_CLI((BSL_META_U(unit, 10932 "CU PWRDN = %s\n"), (config & (1U<<7)) ? "Yes" : "No")); 10933 10934 LOG_CLI((BSL_META_U(unit, 10935 "FIBER Prio = %s\n"), (config & (1U<<8)) ? "Yes" : "No")); 10936 10937 LOG_CLI((BSL_META_U(unit, 10938 "SD Invert = %s\n"), (config & (1U<<9)) ? "Yes" : "No")); 10939 10940 LOG_CLI((BSL_META_U(unit, 10941 "RANGE = %s\n"), (config & (1U<<10)) ? "30M" : "100M")); 10942 10943 LOG_CLI((BSL_META_U(unit, 10944 "LED User Control = %s\n"), (config & (1U<<11)) ? "Yes" : "No")); 10945 10946 10947 LOG_CLI((BSL_META_U(unit, 10948 "\nTOP_CONFIG_LINK_STATUS (400d) = 0x%04x\n"), status)); 10949 10950 switch ((status >> 3) & 0x3) { 10951 case 0: 10952 cu_speed = "00 - 10M"; 10953 break; 10954 case 1: 10955 cu_speed = "01 - 100M"; 10956 break; 10957 case 2: 10958 cu_speed = "10 - 1G"; 10959 break; 10960 case 3: 10961 cu_speed = "11 - 10G"; 10962 break; 10963 default: 10964 cu_speed = '\0'; 10965 break; 10966 } 10967 10968 switch ((status >> 6) & 0x3) { 10969 case 0: 10970 fiber_speed = "00 - 10M"; 10971 break; 10972 case 1: 10973 fiber_speed = "01 - 100M"; 10974 break; 10975 case 2: 10976 fiber_speed = "10 - 1G"; 10977 break; 10978 case 3: 10979 fiber_speed = "11 - 10G"; 10980 break; 10981 default: 10982 fiber_speed = '\0'; 10983 break; 10984 } 10985 10986 switch ((status >> 9) & 0x3) { 10987 case 0: 10988 mac_device = "00 - Reserved"; 10989 break; 10990 case 1: 10991 mac_device = "01 - XAUI"; 10992 break; 10993 case 2: 10994 mac_device = "10 - XFI"; 10995 break; 10996 case 3: 10997 mac_device = "11 - Reserved"; 10998 break; 10999 default: 11000 mac_device = '\0'; 11001 break; 11002 } 11003 11004 switch ((status >> 11) & 0x3) { 11005 case 0: 11006 line_device = "00 - CU"; 11007 break; 11008 case 1: 11009 line_device = "01 - XAUI"; 11010 break; 11011 case 2: 11012 line_device = "10 - XFI"; 11013 break; 11014 case 3: 11015 line_device = "11 - Reserved"; 11016 break; 11017 default: 11018 line_device = '\0'; 11019 break; 11020 } 11021 11022 switch ((status >> 14) & 0x3) { 11023 case 0: 11024 crc_status = "00 - CRC check going on (May indicate ARM hang)"; 11025 break; 11026 case 1: 11027 crc_status = "01 - Good CRC"; 11028 break; 11029 case 2: 11030 crc_status = "10 - Bad CRC"; 11031 break; 11032 case 3: 11033 crc_status = "11 - Reserved"; 11034 break; 11035 default: 11036 crc_status = '\0'; 11037 break; 11038 } 11039 11040 /* Print the status results */ 11041 11042 LOG_CLI((BSL_META_U(unit, 11043 "FIBER Detected = %s\n"), (status & (1U<<0)) ? "Yes" : "No")); 11044 11045 LOG_CLI((BSL_META_U(unit, 11046 "CU Detected = %s\n"), (status & (1U<<1)) ? "Yes" : "No")); 11047 11048 LOG_CLI((BSL_META_U(unit, 11049 "FIBER Prio = %s\n"), (status & (1U<<2)) ? "Yes" : "No")); 11050 11051 LOG_CLI((BSL_META_U(unit, 11052 "CU speed = %s\n"), cu_speed)); 11053 11054 LOG_CLI((BSL_META_U(unit, 11055 "CU Link = %s\n"), (status & (1U<<5)) ? "Yes" : "No")); 11056 11057 LOG_CLI((BSL_META_U(unit, 11058 "Fiber speed = %s\n"), fiber_speed)); 11059 11060 LOG_CLI((BSL_META_U(unit, 11061 "Fiber Link = %s\n"), (status & (1U<<8)) ? "Yes" : "No")); 11062 11063 LOG_CLI((BSL_META_U(unit, 11064 "MAC device = %s\n"), mac_device)); 11065 11066 LOG_CLI((BSL_META_U(unit, 11067 "LINE device = %s\n"), line_device)); 11068 11069 LOG_CLI((BSL_META_U(unit, 11070 "MAC Link Up = %s\n"), (status & (1U<<13)) ? "Yes" : "No")); 11071 11072 LOG_CLI((BSL_META_U(unit, 11073 "CRC Status = %s\n"), crc_status)); 11074 11075 return SOC_E_NONE; 11076 } 11077 #endif 11078 11079 /* 11080 * Variable: 11081 * phy_8481_drv 11082 * Purpose: 11083 * Phy Driver for 10G (XAUI x 4) Serdes PHY. 11084 */ 11085 11086 phy_driver_t phy_8481drv_xe = { 11087 "8481 10-Gigabit PHY Driver", 11088 phy_8481_init, /* Init */ 11089 phy_null_reset, /* Reset */ 11090 phy_8481_link_get, /* Link get */ 11091 phy_8481_enable_set, /* Enable set */ 11092 phy_8481_enable_get, /* Enable get */ 11093 phy_8481_duplex_set, /* Duplex set */ 11094 phy_8481_duplex_get, /* Duplex get */ 11095 phy_8481_speed_set, /* Speed set */ 11096 phy_8481_speed_get, /* Speed get */ 11097 phy_8481_master_set, /* Master set */ 11098 phy_8481_master_get, /* Master get */ 11099 phy_8481_an_set, /* ANA set */ 11100 phy_8481_an_get, /* ANA get */ 11101 NULL, /* Local Advert set, deprecated */ 11102 NULL, /* Local Advert get, deprecated */ 11103 NULL, /* Remote Advert get, deprecated */ 11104 phy_8481_lb_set, /* PHY loopback set */ 11105 phy_8481_lb_get, /* PHY loopback set */ 11106 phy_null_interface_set, /* IO Interface set */ 11107 phy_8481_xehg_interface_get, /* IO Interface get */ 11108 NULL, /* pd_ability, deprecated */ 11109 phy_8481_link_up, 11110 phy_8481_link_down, 11111 phy_8481_mdix_set, 11112 phy_8481_mdix_get, 11113 phy_8481_mdix_status_get, 11114 phy_8481_medium_config_set, /* medium config setting set */ 11115 phy_8481_medium_config_get, /* medium config setting get */ 11116 phy_8481_medium_status, /* active medium */ 11117 phy_8481_cable_diag, /* phy_cable_diag */ 11118 NULL, /* phy_link_change */ 11119 phy_8481_control_set, /* phy_control_set */ 11120 phy_8481_control_get, /* phy_control_get */ 11121 phy_8481_reg_read, /* phy_reg_read */ 11122 phy_8481_reg_write, /* phy_reg_write */ 11123 phy_8481_reg_modify, /* phy_reg_modify */ 11124 NULL, /* phy_notify */ 11125 phy_8481_probe, /* pd_probe */ 11126 phy_8481_ability_advert_set, /* pd_ability_advert_set */ 11127 phy_8481_ability_advert_get, /* pd_ability_advert_get */ 11128 phy_8481_ability_remote_get, /* pd_ability_remote_get */ 11129 phy_8481_ability_local_get, /* pd_ability_local_get */ 11130 phy_8481_firmware_set, 11131 phy84834_timesync_config_set, 11132 phy84834_timesync_config_get, 11133 phy84834_timesync_control_set, 11134 phy84834_timesync_control_get, 11135 phy_8481_diag_ctrl /* pd_diag_ctrl */ 11136 }; 11137 11138 #else /* INCLUDE_PHY_8481 */ 11139 int _phy_8481_not_empty; 11140 #endif /* INCLUDE_PHY_8481 */ 11141