quadra28_cfg_seq.c (179061B)
1 /* 2 * 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 * 9 * File: quadra28.c 10 * Purpose: tier1 phymod microcode download support for Broadcom 40G Quadra28 11 * note 12 */ 13 /* 14 * Includes 15 */ 16 #include <phymod/phymod.h> 17 #include <phymod/phymod_system.h> 18 #include "quadra28_cfg_seq.h" 19 #include "quadra28_reg_access.h" 20 #include "bcmi_quadra28_defs.h" 21 #include "quadra28_serdes/common/srds_api_enum.h" 22 #include "quadra28_serdes/merlin_quadra28_functions.h" 23 static 24 int _quadra28_merlin_phy_reset_get(phymod_access_t *pa, phymod_phy_reset_t* reset); 25 static 26 int _quadra28_merlin_phy_reset_set(phymod_access_t *pa, const phymod_phy_reset_t* reset); 27 28 static int quadra28_power_set(const phymod_access_t *pa, const phymod_phy_power_t* power); 29 30 static int quadra28_power_get(const phymod_access_t *pa, phymod_phy_power_t* power); 31 32 int quadra28_channel_select (const phymod_access_t *pa, uint16_t lane) 33 { 34 BCMI_QUADRA28_CONFIG_ACCESSr_t single_pmd_bcast_sel; 35 ADDRESS_EXTENSIONr_t single_pmd_ch_sel; 36 37 PHYMOD_MEMSET(&single_pmd_bcast_sel, 0 , sizeof(BCMI_QUADRA28_CONFIG_ACCESSr_t)); 38 PHYMOD_MEMSET(&single_pmd_ch_sel, 0 , sizeof(ADDRESS_EXTENSIONr_t)); 39 40 PHYMOD_IF_ERR_RETURN( 41 BCMI_QUADRA28_READ_CONFIG_ACCESSr(pa, &single_pmd_bcast_sel)); 42 PHYMOD_IF_ERR_RETURN( 43 BCMI_QUADRA28_READ_ADDRESS_EXTENSIONr(pa, &single_pmd_ch_sel)); 44 45 if (lane == Q28_ALL_LANE) { 46 PHYMOD_IF_ERR_RETURN( 47 BCMI_QUADRA28_READ_ADDRESS_EXTENSIONr(pa, &single_pmd_ch_sel)); 48 BCMI_QUADRA28_ADDRESS_EXTENSIONr_AER_CHf_SET(single_pmd_ch_sel, 0); 49 PHYMOD_IF_ERR_RETURN( 50 BCMI_QUADRA28_WRITE_ADDRESS_EXTENSIONr(pa, single_pmd_ch_sel)); 51 52 /* Enable Broadcast mode*/ 53 BCMI_QUADRA28_CONFIG_ACCESSr_BROADCAST_ENABLEf_SET(single_pmd_bcast_sel,1); 54 PHYMOD_IF_ERR_RETURN( 55 BCMI_QUADRA28_WRITE_CONFIG_ACCESSr(pa, single_pmd_bcast_sel)); 56 } else { 57 BCMI_QUADRA28_ADDRESS_EXTENSIONr_AER_CHf_SET(single_pmd_ch_sel, lane); 58 PHYMOD_IF_ERR_RETURN( 59 BCMI_QUADRA28_WRITE_ADDRESS_EXTENSIONr(pa, single_pmd_ch_sel)); 60 } 61 return PHYMOD_E_NONE; 62 } 63 64 /** read chip ID 65 * This function is used to set the operating mode of the PHY 66 * 67 * @param pa Pointer to phymod access structure 68 * @return PHYMOD_E_NONE successful function execution 69 */ 70 uint32_t _quadra28_get_chip_id(const phymod_access_t *pa) 71 { 72 CHIP_ID0r_t chipid_lsb; 73 CHIP_ID1r_t chipid_msb; 74 int32_t chipid = 0; 75 76 PHYMOD_MEMSET(&chipid_lsb, 0, sizeof(CHIP_ID0r_t)); 77 PHYMOD_MEMSET(&chipid_msb, 0, sizeof(CHIP_ID1r_t)); 78 79 PHYMOD_IF_ERR_RETURN( 80 READ_CHIP_ID0r(pa, &chipid_lsb)); 81 PHYMOD_IF_ERR_RETURN( 82 READ_CHIP_ID1r(pa, &chipid_msb)); 83 chipid = CHIP_ID0r_GET(chipid_lsb); 84 chipid |= (CHIP_ID1r_GET(chipid_msb)) << 16; 85 86 return chipid; 87 } 88 /** poll intf update 89 * This function is used to set the operating mode of the PHY 90 * 91 * @param pa Pointer to phymod access structure 92 93 * @timeout timeout in us 94 * @return PHYMOD_E_NONE successful function execution 95 */ 96 int _quadra28_intf_update_wait_check(const phymod_access_t *pa, uint32_t apps_mode0_reg_val, 97 int32_t timeout) /* max wait time to check */ 98 { 99 uint32_t timer_counter = 0; 100 GENERAL_PURPOSE_3r_t gen_pur_reg_3r_val; 101 timer_counter = (timeout / DELAY_1_MS_FROM_US); 102 PHYMOD_MEMSET(&gen_pur_reg_3r_val, 0, sizeof(GENERAL_PURPOSE_3r_t)); 103 do { 104 /* Read C843 register & compare its value with apps_mod0_reg_val */ 105 PHYMOD_IF_ERR_RETURN(READ_GENERAL_PURPOSE_3r(pa,&gen_pur_reg_3r_val)); 106 if ((gen_pur_reg_3r_val.v[0] & 0xffff) == (apps_mode0_reg_val & 0xffff)) { 107 return PHYMOD_E_NONE; 108 } 109 PHYMOD_USLEEP(DELAY_1_MS_FROM_US); 110 timer_counter--; 111 } while(timer_counter > 0); 112 PHYMOD_DIAG_OUT(("Error Gp3:%x app:%x--:%x\n", gen_pur_reg_3r_val.v[0], apps_mode0_reg_val,pa->addr)); 113 return PHYMOD_E_FAIL; 114 } 115 116 /** Set config mode 117 * This function is used to set the operating mode of the PHY 118 * 119 * @param pa Pointer to phymod access structure 120 * @param intf Interface specified by user 121 * @param speed Speed val as specified by user 122 * @param ref_clk Reference clock frequency to set 123 * the PHY into specified interface 124 * and speed 125 * 126 * @return PHYMOD_E_NONE successful function execution 127 */ 128 int quadra28_set_config_mode(const phymod_phy_access_t *phy, 129 phymod_interface_t intf, 130 uint32_t speed, 131 phymod_ref_clk_t ref_clk, uint32_t datapath, 132 uint16_t retimer) 133 { 134 uint16_t single_pmd_mode = 0; 135 uint32_t pkg_side = 0; 136 phymod_access_t acc_cpy; 137 BCMI_QUADRA28_APPS_MODE_0r_t apps_mode0_reg_val; 138 MDIO_BROADCAST_CONTROLr_t mdio_broadcast_ctrl_reg; 139 uint32_t phy_id = 0, lane_index = 0; 140 int retry_cnt = 20; 141 BCMI_QUADRA28_APPS_MODE_1r_t apps_mode1_reg; 142 PHYMOD_MEMSET(&apps_mode1_reg, 0, sizeof(BCMI_QUADRA28_APPS_MODE_1r_t)); 143 PHYMOD_MEMSET(&apps_mode0_reg_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_0r_t)); 144 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 145 PHYMOD_MEMSET(&mdio_broadcast_ctrl_reg, 0, sizeof(MDIO_BROADCAST_CONTROLr_t)); 146 phy_id = (phy->access.addr & 0x1f); 147 QUADRA28_GET_LOC(phy, pkg_side); 148 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 149 150 PHYMOD_IF_ERR_RETURN(READ_APPS_MODE_0r(&acc_cpy,&apps_mode0_reg_val)); 151 152 if (speed >= Q28_SPEED_40G) { 153 for (lane_index = 0; lane_index < QUADRA28_MAX_LANE; lane_index ++) { 154 acc_cpy.addr = phy->access.addr + lane_index; 155 BCMI_QUADRA28_MDIO_BROADCAST_CONTROLr_MDIO_MCAST_ENf_SET(mdio_broadcast_ctrl_reg, 1); 156 MDIO_BROADCAST_CONTROLr_MDIO_MULTICAST_PHYADf_SET(mdio_broadcast_ctrl_reg, phy_id); 157 PHYMOD_IF_ERR_RETURN 158 (WRITE_MDIO_BROADCAST_CONTROLr(&acc_cpy, mdio_broadcast_ctrl_reg)); 159 } 160 acc_cpy.addr = phy->access.addr; 161 } 162 163 if ((speed <= Q28_SPEED_12P5G) || 164 BCMI_QUADRA28_APPS_MODE_0r_SPEEDf_GET(apps_mode0_reg_val) == 0x4 || 165 BCMI_QUADRA28_APPS_MODE_0r_SPEEDf_GET(apps_mode0_reg_val) == 0x7) { 166 PHYMOD_IF_ERR_RETURN ( 167 quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 168 } 169 if (datapath != 0xffff) { 170 if (datapath == phymodDatapathNormal) { 171 datapath = 0; 172 } else { 173 datapath = 1; 174 } 175 } 176 177 178 /* Configure port speed */ 179 PHYMOD_IF_ERR_RETURN(_quadra28_config_port_speed (speed, \ 180 (uint32_t*)&apps_mode0_reg_val.v[0], (uint16_t*)&single_pmd_mode)); 181 if(Q28_INTF_LINE == pkg_side) { 182 /* Configure line side interface */ 183 PHYMOD_IF_ERR_RETURN(_quadra28_config_line_interface(&phy->access, (uint32_t*)&apps_mode0_reg_val.v[0], 184 intf, speed)); 185 } else { 186 /* configure system side interface */ 187 PHYMOD_IF_ERR_RETURN(_quadra28_config_sys_interface(&phy->access, (uint32_t*)&apps_mode0_reg_val.v[0], 188 intf)); 189 } 190 191 if (speed >= Q28_SPEED_40G) { 192 PHYMOD_IF_ERR_RETURN ( 193 BCMI_QUADRA28_READ_APPS_MODE_1r(&acc_cpy, &apps_mode1_reg)); 194 BCMI_QUADRA28_APPS_MODE_1r_RETIMER_MODEf_SET(apps_mode1_reg, 0); 195 PHYMOD_IF_ERR_RETURN ( 196 BCMI_QUADRA28_WRITE_APPS_MODE_1r(&acc_cpy, apps_mode1_reg)); 197 } else { 198 if (retimer != 0xFFFF) { 199 PHYMOD_IF_ERR_RETURN ( 200 BCMI_QUADRA28_READ_APPS_MODE_1r(&acc_cpy, &apps_mode1_reg)); 201 BCMI_QUADRA28_APPS_MODE_1r_RETIMER_MODEf_SET(apps_mode1_reg, 202 (retimer == phymodOperationModeRetimer) ? 1 : 0); 203 PHYMOD_IF_ERR_RETURN ( 204 BCMI_QUADRA28_WRITE_APPS_MODE_1r(&acc_cpy, apps_mode1_reg)); 205 } 206 } 207 /* Resetting Datapath with the value got in core init*/ 208 if (datapath != 0xFFFF) { 209 BCMI_QUADRA28_APPS_MODE_0r_ENABLE_ULL_DATAPATHf_SET(apps_mode0_reg_val, datapath); 210 } 211 PHYMOD_IF_ERR_RETURN( 212 _quadra28_refclk_set(&acc_cpy, phymodRefClk156Mhz)); 213 214 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 0); 215 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 216 PHYMOD_USLEEP(10000); 217 /* Set bit 7 in C8D8 reg to update changes */ 218 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 1); 219 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 220 221 PHYMOD_IF_ERR_RETURN(_quadra28_intf_update_wait_check(&acc_cpy,apps_mode0_reg_val.v[0], 50000)); 222 223 { 224 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 225 BCMI_QUADRA28_CHIP_MODEr_t chip_mode; 226 BCMI_QUADRA28_MERLIN_MISC_CTRLr_t reset_done; 227 PHYMOD_MEMSET(&chip_mode, 0, sizeof(BCMI_QUADRA28_CHIP_MODEr_t)); 228 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 229 PHYMOD_MEMSET(&reset_done, 0, sizeof(BCMI_QUADRA28_MERLIN_MISC_CTRLr_t)); 230 231 PHYMOD_IF_ERR_RETURN( 232 BCMI_QUADRA28_READ_CHIP_MODEr(&acc_cpy, &chip_mode)); 233 if (speed == Q28_SPEED_40G) { 234 CHIP_MODEr_CHIP_MODEf_SET(chip_mode, 1); 235 } else { 236 CHIP_MODEr_CHIP_MODEf_SET(chip_mode, 0); 237 } 238 PHYMOD_IF_ERR_RETURN( 239 BCMI_QUADRA28_WRITE_CHIP_MODEr(&acc_cpy, chip_mode)); 240 241 PHYMOD_IF_ERR_RETURN( 242 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 243 BCMI_QUADRA28_PMD_CONTROLr_RESETf_SET(pmd_ctrl, 1); 244 PHYMOD_IF_ERR_RETURN( 245 BCMI_QUADRA28_WRITE_PMD_CONTROLr(&acc_cpy, pmd_ctrl)); 246 } 247 { 248 BCMI_QUADRA28_MERLIN_MISC_CTRLr_t reset_ack; 249 BCMI_QUADRA28_XGXSSTATUSr_t xgs_sts; 250 BCMI_QUADRA28_GENERAL_PURPOSE_1r_t gpreg_1; 251 PHYMOD_MEMSET(&gpreg_1, 0, sizeof(gpreg_1)); 252 do { 253 PHYMOD_IF_ERR_RETURN( 254 BCMI_QUADRA28_READ_MERLIN_MISC_CTRLr(&acc_cpy, &reset_ack)); 255 PHYMOD_USLEEP(1000); 256 retry_cnt --; 257 } while (((reset_ack.v[0] & 0x8000) != 0x8000) && retry_cnt); 258 if (retry_cnt <= 0) { 259 return PHYMOD_E_TIMEOUT; 260 } 261 retry_cnt = 20; 262 PHYMOD_IF_ERR_RETURN( 263 BCMI_QUADRA28_READ_GENERAL_PURPOSE_1r(&acc_cpy, &gpreg_1)); 264 if (BCMI_QUADRA28_GENERAL_PURPOSE_1r_TXON_PAD_STATUSf_GET(gpreg_1) != 0) { 265 do { 266 PHYMOD_IF_ERR_RETURN( 267 BCMI_QUADRA28_READ_XGXSSTATUSr(&acc_cpy, &xgs_sts)); 268 PHYMOD_USLEEP(800); 269 retry_cnt --; 270 } while (((xgs_sts.v[0] & 0x800) != 0x800) && retry_cnt); 271 if (retry_cnt <= 0) { 272 return PHYMOD_E_TIMEOUT; 273 } 274 } 275 } 276 apps_mode0_reg_val.v[0] &= 0xFF7F; 277 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 278 279 PHYMOD_IF_ERR_RETURN(_quadra28_intf_update_wait_check(&acc_cpy,apps_mode0_reg_val.v[0], 50000)); 280 return PHYMOD_E_NONE; 281 282 } 283 /** Get config mode 284 * This function is used to retrieve the operating mode of the PHY 285 * 286 * @param phy Pointer to phy structure 287 * @param intf Interface type 288 * @param speed Speed val retrieved from PHY 289 * @param ref_clk Reference clock 290 * @param interface_modes Supported interface modes 291 * 292 * @return PHYMOD_E_NONE successful function execution 293 */ 294 int quadra28_get_config_mode(const phymod_access_t *pa, 295 phymod_interface_t *intf, 296 uint32_t *speed, 297 phymod_ref_clk_t *ref_clk, 298 uint32_t *interface_modes) 299 { 300 uint16_t ref_clk_scaler_val = 0; 301 int pkg_side = 0; 302 APPS_MODE_2r_t apps_mod2_reg_val; 303 GENERAL_PURPOSE_3r_t gen_pur_reg_3r_val; 304 uint16_t config_speed = 0; 305 phymod_access_t acc_cpy; 306 307 *speed = 0; 308 *intf = 0; 309 *ref_clk = 0; 310 311 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 312 PHYMOD_MEMSET(&gen_pur_reg_3r_val, 0, sizeof(GENERAL_PURPOSE_3r_t)); 313 PHYMOD_MEMSET(&apps_mod2_reg_val, 0 , sizeof(BCMI_QUADRA28_APPS_MODE_2r_t)); 314 315 QUADRA28_GET_IF_SIDE(acc_cpy.flags, pkg_side); 316 if (acc_cpy.lane_mask == 0xf) { 317 PHYMOD_IF_ERR_RETURN( 318 quadra28_channel_select(&acc_cpy, 0)); 319 } else { 320 /* Check the speed of 1st channel of this DIE*/ 321 PHYMOD_IF_ERR_RETURN(READ_GENERAL_PURPOSE_3r(&acc_cpy, &gen_pur_reg_3r_val)); 322 /* Extract bits for speed */ 323 config_speed = (gen_pur_reg_3r_val.v[0] & 0xF); 324 if (0x1 == config_speed){ 325 *speed = Q28_SPEED_1G; 326 } else if (0x2 == config_speed) { 327 *speed = Q28_SPEED_10G; 328 } else if (0x8 == config_speed) { 329 *speed = Q28_SPEED_11P5G; 330 } else if (0xC == config_speed) { 331 *speed = Q28_SPEED_20G; 332 } else if (0x4 == config_speed) { 333 *speed = Q28_SPEED_40G; 334 } else if (0x7 == config_speed) { 335 *speed = Q28_SPEED_42G; 336 *interface_modes = PHYMOD_INTF_MODES_HIGIG; 337 } else if (0x5 == config_speed) { 338 *speed = Q28_SPEED_HG11; 339 *interface_modes = PHYMOD_INTF_MODES_HIGIG; 340 } 341 if (*speed <= Q28_SPEED_HG11) { 342 /* If lane mask is nott 0xF, assuming it as 10G*/ 343 Q28_10G_PHY_ID_WORK_AROUND(10000, acc_cpy); 344 } 345 } 346 347 PHYMOD_IF_ERR_RETURN(READ_APPS_MODE_2r(&acc_cpy, &apps_mod2_reg_val)); 348 ref_clk_scaler_val = APPS_MODE_2r_REFERENCE_CLOCKf_GET(apps_mod2_reg_val); 349 350 PHYMOD_IF_ERR_RETURN(READ_GENERAL_PURPOSE_3r(&acc_cpy, &gen_pur_reg_3r_val)); 351 352 /* Extract bits for speed */ 353 config_speed = (gen_pur_reg_3r_val.v[0] & 0xF); 354 if (0x1 == config_speed){ 355 *speed = Q28_SPEED_1G; 356 } else if (0x2 == config_speed) { 357 *speed = Q28_SPEED_10G; 358 } else if (0x8 == config_speed) { 359 *speed = Q28_SPEED_11P5G; 360 } else if (0xC == config_speed) { 361 *speed = Q28_SPEED_20G; 362 } else if (0x4 == config_speed) { 363 *speed = Q28_SPEED_40G; 364 } else if (0x7 == config_speed) { 365 *speed = Q28_SPEED_42G; 366 *interface_modes = PHYMOD_INTF_MODES_HIGIG; 367 } else if (0x5 == config_speed) { 368 *speed = Q28_SPEED_HG11; 369 *interface_modes = PHYMOD_INTF_MODES_HIGIG; 370 } 371 372 /* should use speed info & line side supported connections for Q28*/ 373 if (Q28_INTF_LINE == pkg_side) { 374 if ((Q28_SPEED_42G == *speed || Q28_SPEED_40G == *speed)) { 375 if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(14)) && 376 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(9)))) { 377 *intf = phymodInterfaceLR4; 378 } else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(9)) && 379 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(8))) && 380 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(14)))) { 381 *intf = phymodInterfaceCR4; 382 } else if ((!(gen_pur_reg_3r_val.v[0] & Q28_BIT(8))) && 383 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(14)))) { 384 *intf = phymodInterfaceSR4; 385 } else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(8)) && 386 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(14)))) { 387 *intf = phymodInterfaceKR4; 388 } else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(14)) && 389 (gen_pur_reg_3r_val.v[0] & Q28_BIT(9))) { 390 *intf = phymodInterfaceXLAUI; 391 } 392 } else if((Q28_SPEED_10G == *speed || Q28_SPEED_HG11 == *speed)) { 393 if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(9)) && 394 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(8))) && 395 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(14)))) { 396 *intf = phymodInterfaceCR; 397 } else if ((!(gen_pur_reg_3r_val.v[0] & Q28_BIT(8))) && 398 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(14)))) { 399 *intf = phymodInterfaceSR; 400 } else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(8)) && 401 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(14)))) { 402 *intf = phymodInterfaceKR; 403 } else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(14)) && 404 (gen_pur_reg_3r_val.v[0] & Q28_BIT(12)) && 405 (gen_pur_reg_3r_val.v[0] & Q28_BIT(9))) { 406 *intf = phymodInterfaceZR; 407 } else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(4)) && 408 (gen_pur_reg_3r_val.v[0] & Q28_BIT(5)) && 409 (gen_pur_reg_3r_val.v[0] & Q28_BIT(14))) { 410 *intf = phymodInterfaceLRM; 411 } else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(14)) && 412 (gen_pur_reg_3r_val.v[0] & Q28_BIT(9))) { 413 *intf = phymodInterfaceXFI; 414 } else if ((!(gen_pur_reg_3r_val.v[0] & Q28_BIT(9))) && 415 (gen_pur_reg_3r_val.v[0] & Q28_BIT(14))) { 416 *intf = phymodInterfaceLR; 417 } 418 } else if (Q28_SPEED_1G == *speed) { 419 if ((!(gen_pur_reg_3r_val.v[0] & Q28_BIT(8))) && 420 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(10)))) { 421 /**intf = phymodInterface1000X;*/ 422 /*Since interface 1000X is not supported in phyctrl 423 * returning as SR*/ 424 *intf = phymodInterfaceSR; 425 } else if (gen_pur_reg_3r_val.v[0] & Q28_BIT(8)) { 426 *intf = phymodInterfaceKX; 427 } 428 } 429 } else if (Q28_INTF_SYS == pkg_side) { 430 /* If speed is 40G or 42G, system side connections: XLAUI, Forced CL72 */ 431 if (Q28_SPEED_40G == *speed || Q28_SPEED_42G == *speed) { 432 if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(15)) && 433 (gen_pur_reg_3r_val.v[0] & Q28_BIT(11))) { 434 *intf = phymodInterfaceXLAUI; 435 } else if ((gen_pur_reg_3r_val.v[0] & (Q28_BIT(11))) && 436 !(gen_pur_reg_3r_val.v[0] & (Q28_BIT(15)))) { 437 *intf = phymodInterfaceCR4; 438 } else if ((gen_pur_reg_3r_val.v[0] & (Q28_BIT(10)))) { 439 *intf = phymodInterfaceKR4; 440 } 441 } else if((Q28_SPEED_10G == *speed || Q28_SPEED_HG11 == *speed)) { 442 if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(15)) && 443 (gen_pur_reg_3r_val.v[0] & Q28_BIT(11))) { 444 *intf = phymodInterfaceXFI; 445 } else if ((gen_pur_reg_3r_val.v[0] & (Q28_BIT(10)))) { 446 *intf = phymodInterfaceKR; 447 }else if ((gen_pur_reg_3r_val.v[0] & Q28_BIT(11))){ 448 *intf = phymodInterfaceCR; 449 } 450 } else if(*speed == Q28_SPEED_1G) { 451 if ((!(gen_pur_reg_3r_val.v[0] & Q28_BIT(8))) && 452 (!(gen_pur_reg_3r_val.v[0] & Q28_BIT(10)))) { 453 /**intf = phymodInterface1000X;*/ 454 /*Since interface 1000X is not supported in phyctrl 455 * returning as SR*/ 456 *intf = phymodInterfaceSR; 457 } else if (gen_pur_reg_3r_val.v[0] & Q28_BIT(8)) { 458 *intf = phymodInterfaceKX; 459 } 460 } 461 if (*intf == 0) { 462 return PHYMOD_E_FAIL; 463 } 464 } 465 466 if (phymodRefClk156Mhz == ref_clk_scaler_val) { 467 *ref_clk = phymodRefClk156Mhz; 468 } else { 469 *ref_clk = phymodRefClk155Mhz; /* check this */ 470 } 471 472 return PHYMOD_E_NONE; 473 } 474 475 /** Configure PRBS generator 476 * This function is used to configure PRBS generator with user provided 477 * polynomial and invert data information 478 * 479 * @param pa Pointer to phymod access structure 480 * @param flags Flags to prbs config 481 * @param prbs_mode User specified polynomial 482 * 0 - PRBS7 483 * 1 - PRBS9 484 * 2 - PRBS11 485 * 3 - PRBS15 486 * 4 - PRBS23 487 * 5 - PRBS31 488 * 6 - PRBS58 489 * 490 * @param prbs_inv User specified invert data config 491 * 0 - do not invert PRBS data 492 * 1 - invert PRBS data 493 * 494 * @return PHYMOD_E_NONE successful function execution 495 */ 496 int quara28_prbs_config_set(const phymod_phy_access_t *phy, 497 uint32_t flags, 498 uint32_t prbs_mode, 499 uint32_t prbs_inv) 500 { 501 502 int pkg_side = 0; 503 int num_lanes = QUADRA28_MAX_LANE; /* num of lanes in octal package core */ 504 int lane_index = 0, pmd_mode = 0; 505 unsigned short int lane_map = 0; 506 uint32_t speed = 0; 507 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 508 BCMI_QUADRA28_PRBS_CHK_CONFIGr_t ckr_cfg; 509 BCMI_QUADRA28_GENERAL_PURPOSE_3r_t gpreg3; 510 phymod_access_t acc_cpy; 511 512 /* Get the lane map from phymod access */ 513 lane_map = PHYMOD_ACC_LANE_MASK(&phy->access); 514 QUADRA28_GET_LOC(phy,pkg_side); 515 516 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 517 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 518 PHYMOD_MEMSET(&ckr_cfg, 0 , sizeof(BCMI_QUADRA28_PRBS_CHK_CONFIGr_t)); 519 PHYMOD_MEMSET(&gpreg3, 0 , sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_3r_t)); 520 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 521 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 522 QUADRA28_SELECT_SIDE(&acc_cpy, side_sel_reg_val, pkg_side); 523 if (pmd_mode == Q28_SINGLE_PMD) { 524 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 525 if (((lane_map >> lane_index) & 1) == 0x1) { 526 PHYMOD_IF_ERR_RETURN( 527 quadra28_channel_select(&acc_cpy, 528 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 529 530 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)){ 531 PHYMOD_IF_ERR_RETURN( 532 merlin_quadra28_config_tx_prbs(&acc_cpy, prbs_mode, (uint8_t)prbs_inv)); 533 } 534 /* Following code block for PRBS Checker or RX*/ 535 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 536 PHYMOD_IF_ERR_RETURN( 537 merlin_quadra28_config_rx_prbs(&acc_cpy, prbs_mode, PRBS_INITIAL_SEED_HYSTERESIS, (uint8_t)prbs_inv)); 538 } 539 if (Q28_ALL_LANE == lane_map){ 540 break; 541 } 542 } 543 } 544 } else { 545 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)){ 546 PHYMOD_IF_ERR_RETURN( 547 merlin_quadra28_config_tx_prbs(&acc_cpy, prbs_mode, (uint8_t)prbs_inv)); 548 } 549 /* Following code block for PRBS Checker or RX*/ 550 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 551 PHYMOD_IF_ERR_RETURN( 552 merlin_quadra28_config_rx_prbs(&acc_cpy, prbs_mode, PRBS_INITIAL_SEED_HYSTERESIS, (uint8_t)prbs_inv)); 553 PHYMOD_IF_ERR_RETURN( 554 BCMI_QUADRA28_READ_GENERAL_PURPOSE_3r(&acc_cpy, &gpreg3)); 555 if (gpreg3.v[0] & 0x20) { 556 PHYMOD_IF_ERR_RETURN( 557 BCMI_QUADRA28_READ_PRBS_CHK_CONFIGr(&acc_cpy, &ckr_cfg)); 558 BCMI_QUADRA28_PRBS_CHK_CONFIGr_PRBS_CHK_EN_AUTO_MODEf_SET(ckr_cfg,0); 559 PHYMOD_IF_ERR_RETURN( 560 BCMI_QUADRA28_WRITE_PRBS_CHK_CONFIGr(&acc_cpy, ckr_cfg)); 561 } 562 563 } 564 } 565 566 /* restore Q28_INTF_LINE side */ 567 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val,Q28_INTF_LINE); 568 569 return PHYMOD_E_NONE; 570 } 571 572 /** Get PRBS generator configuration 573 * This function is used to retrieve PRBS generator configuration from 574 * the chip 575 * 576 * @param pa Pointer to phymod access structure 577 * @param flags Flags for prbs 578 * @param prbs_mode Configured Polynomial retrieved from chip 579 * @param prbs_inv Configured invert data retrieved from chip 580 * 0 - do not invert PRBS data 581 * 1 - invert PRBS data 582 * 583 * @return PHYMOD_E_NONE successful function execution 584 */ 585 int quadra28_prbs_config_get(const phymod_phy_access_t *phy, 586 uint32_t flags, 587 enum srds_prbs_polynomial_enum *prbs_mode, 588 uint32_t *prbs_inv) 589 { 590 591 int lane_map = 0; 592 int pkg_side = 0; 593 int num_lanes = QUADRA28_MAX_LANE; 594 int lane_index = 0; 595 uint8_t prbs_invert = 0; 596 uint32_t prbs_checker_mode = 0; 597 phymod_access_t acc_cpy; 598 int pmd_mode = 0; 599 uint32_t speed = 0; 600 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 601 602 *prbs_inv = 0; 603 *prbs_mode = 0; 604 605 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 606 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 607 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 608 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 609 610 /* Get the lane map from phymod access */ 611 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 612 QUADRA28_GET_LOC(phy,pkg_side); 613 614 QUADRA28_SELECT_SIDE(&acc_cpy, side_sel_reg_val, pkg_side); 615 616 if (pmd_mode == Q28_SINGLE_PMD) { 617 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 618 if (((lane_map >> lane_index) & 1) == 0x1) { 619 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 620 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)){ 621 PHYMOD_IF_ERR_RETURN( 622 merlin_quadra28_get_tx_prbs_config(&acc_cpy, prbs_mode, &prbs_invert)); 623 *prbs_inv = prbs_invert; 624 } 625 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 626 /* Read Serdes API */ 627 PHYMOD_IF_ERR_RETURN( 628 merlin_quadra28_get_rx_prbs_config(&acc_cpy, prbs_mode, &prbs_checker_mode, &prbs_invert)); 629 *prbs_inv = prbs_invert; 630 } 631 break; 632 } 633 } 634 } else { 635 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)){ 636 PHYMOD_IF_ERR_RETURN( 637 merlin_quadra28_get_tx_prbs_config(&acc_cpy, prbs_mode, &prbs_invert)); 638 *prbs_inv = prbs_invert; 639 } 640 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 641 /* Read Serdes API */ 642 PHYMOD_IF_ERR_RETURN( 643 merlin_quadra28_get_rx_prbs_config(&acc_cpy, prbs_mode, &prbs_checker_mode, &prbs_invert)); 644 *prbs_inv = prbs_invert; 645 } 646 } 647 648 /* restore Q28_INTF_LINE side */ 649 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val,Q28_INTF_LINE); 650 return PHYMOD_E_NONE; 651 } 652 653 /** Enable PRBS generator and PRBS checker 654 * This function is used to enable or disable PRBS generator and PRBS checker 655 * as requested by the user 656 * 657 * @param pa Pointer to phymod access structure 658 * @param flags Flags for prbs 659 * @param enable Enable or disable as specified by the user 660 * 1 - Enable 661 * 0 - Disable 662 * 663 * @return PHYMOD_E_NONE successful function execution 664 */ 665 int quadra28_prbs_enable_set(const phymod_phy_access_t *phy, uint32_t flags, uint32_t enable_state) 666 { 667 int pkg_side = 0; 668 int num_lanes = QUADRA28_MAX_LANE; /* num of lanes in octal package core */ 669 int lane_index = 0; 670 int lane_map = 0; 671 phymod_access_t acc_cpy; 672 int pmd_mode = 0; 673 uint32_t speed = 0; 674 SIDE_SELECTIONr_t side_sel_reg; 675 BCMI_QUADRA28_PRBS_GEN_CONFIGr_t prbs_gen_config_reg_val; 676 BCMI_QUADRA28_PRBS_CHK_CONFIGr_t prbs_chk_config_reg_val; 677 678 PHYMOD_MEMSET(&prbs_gen_config_reg_val, 0, sizeof(BCMI_QUADRA28_PRBS_GEN_CONFIGr_t)); 679 PHYMOD_MEMSET(&prbs_chk_config_reg_val, 0, sizeof(BCMI_QUADRA28_PRBS_CHK_CONFIGr_t)); 680 PHYMOD_MEMSET(&side_sel_reg, 0, sizeof(SIDE_SELECTIONr_t)); 681 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 682 683 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 684 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 685 686 /* Get the lane map from phymod access */ 687 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 688 QUADRA28_GET_LOC(phy,pkg_side); 689 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg, pkg_side); 690 691 if (pmd_mode == Q28_SINGLE_PMD) { 692 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 693 if (((lane_map >> lane_index) & 1) == 0x1) { 694 PHYMOD_IF_ERR_RETURN( 695 quadra28_channel_select(&acc_cpy, 696 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 697 698 /* Select respective side */ 699 if ((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)) { 700 PHYMOD_IF_ERR_RETURN( 701 merlin_quadra28_tx_prbs_en(&acc_cpy, enable_state)); 702 } 703 /* Following code block for PRBS Checker or RX*/ 704 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 705 PHYMOD_IF_ERR_RETURN( 706 merlin_quadra28_rx_prbs_en(&acc_cpy, enable_state)); 707 } 708 if (lane_map == Q28_ALL_LANE) { 709 break; 710 } 711 } 712 } 713 } else { 714 /* Select respective side */ 715 if ((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)) { 716 PHYMOD_IF_ERR_RETURN( 717 merlin_quadra28_tx_prbs_en(&acc_cpy, enable_state)); 718 } 719 /* Following code block for PRBS Checker or RX*/ 720 if((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 721 PHYMOD_IF_ERR_RETURN( 722 merlin_quadra28_rx_prbs_en(&acc_cpy, enable_state)); 723 } 724 } 725 /* restore Q28_INTF_LINE side */ 726 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg,Q28_INTF_LINE); 727 return PHYMOD_E_NONE; 728 } 729 730 /** Get Enable status of PRBS generator and PRBS checker 731 * This function is used to retrieve the enable status of PRBS generator and 732 * PRBS checker 733 * 734 * @param pa Pointer to phymod access structure 735 * @param flags Flags for prbs 736 * @param enable Enable or disable read from chip 737 * 1 - Enable 738 * 0 - Disable 739 * 740 * @return PHYMOD_E_NONE successful function execution 741 */ 742 int quadra28_prbs_enable_get(const phymod_phy_access_t *phy, uint32_t flags, uint32_t *enable) 743 { 744 int pkg_side = 0; 745 int num_lanes = QUADRA28_MAX_LANE; /* num of lanes in octal package core */ 746 int lane_index = 0; 747 int lane_map = 0; 748 SIDE_SELECTIONr_t side_sel_reg; 749 BCMI_QUADRA28_PRBS_GEN_CONFIGr_t prbs_gen_config_reg_val; 750 BCMI_QUADRA28_PRBS_CHK_CONFIGr_t prbs_chk_config_reg_val; 751 uint8_t gen_en = 0; 752 uint8_t chk_en = 0; 753 phymod_access_t acc_cpy; 754 int pmd_mode = 0; 755 uint32_t speed = 0; 756 757 *enable = 0; 758 759 /* Get the lane map from phymod access */ 760 lane_map = PHYMOD_ACC_LANE_MASK(&phy->access); 761 QUADRA28_GET_LOC(phy,pkg_side); 762 763 PHYMOD_MEMSET(&prbs_gen_config_reg_val, 0, sizeof(BCMI_QUADRA28_PRBS_GEN_CONFIGr_t)); 764 PHYMOD_MEMSET(&prbs_chk_config_reg_val, 0, sizeof(BCMI_QUADRA28_PRBS_CHK_CONFIGr_t)); 765 PHYMOD_MEMSET(&side_sel_reg, 0, sizeof(BCMI_QUADRA28_PRBS_CHK_CONFIGr_t)); 766 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 767 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 768 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 769 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg, pkg_side); 770 771 if (pmd_mode == Q28_SINGLE_PMD) { 772 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 773 if (((lane_map >> lane_index) & 1) == 0x1) { 774 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 775 if ((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)) { 776 PHYMOD_IF_ERR_RETURN(merlin_quadra28_get_tx_prbs_en(&acc_cpy, &gen_en)); 777 *enable = gen_en; 778 } 779 if ((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 780 PHYMOD_IF_ERR_RETURN(merlin_quadra28_get_rx_prbs_en(&acc_cpy, &chk_en)); 781 *enable = chk_en; 782 } 783 break; 784 } 785 } 786 } else { 787 if ((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_TX)) { 788 PHYMOD_IF_ERR_RETURN(merlin_quadra28_get_tx_prbs_en(&acc_cpy, &gen_en)); 789 *enable = gen_en; 790 } 791 if ((flags == 0) || (flags == PHYMOD_PRBS_DIRECTION_RX)) { 792 PHYMOD_IF_ERR_RETURN(merlin_quadra28_get_rx_prbs_en(&acc_cpy, &chk_en)); 793 *enable = chk_en; 794 } 795 } 796 if (flags == 0) { 797 if(gen_en && chk_en) { 798 *enable = 1; 799 } else { 800 *enable = 0; 801 } 802 } 803 /* restore Q28_INTF_LINE side */ 804 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg,Q28_INTF_LINE); 805 return PHYMOD_E_NONE; 806 } 807 808 809 /** Get PRBS lock and error status 810 * This function is used to retrieve PRBS lock, loss of lock and error counts 811 * from the chip 812 * 813 * @param pa Pointer to phymod access structure 814 * @param lock_status PRBS lock status denotes PRBS generator and 815 * checker are locked to same polynomial data 816 * @param lock_loss Lo of lock denotes PRBS generator and checker 817 * are not in sync 818 * @param error_count PRBS error count retrieved from chip 819 * 820 * @return PHYMOD_E_NONE successful function execution 821 */ 822 int quadra28_prbs_status_get(const phymod_phy_access_t *phy, 823 uint32_t *lock_status, 824 uint32_t *lock_loss, 825 uint32_t *error_count) 826 { 827 int lane_map = 0; 828 int pkg_side = 0; 829 int num_lanes = QUADRA28_MAX_LANE; 830 int lane_index = 0; 831 uint8_t loss_of_lock = 0; 832 uint32_t per_lane_err_count = 0; 833 uint8_t prbs_chk_lock_stat; 834 phymod_access_t acc_cpy; 835 int pmd_mode = 0; 836 uint32_t speed = 0; 837 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 838 839 *lock_status = 1; 840 *lock_loss = 1; 841 *error_count = 0; 842 843 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 844 PHYMOD_MEMCPY(&acc_cpy,&phy->access, sizeof(phymod_access_t)); 845 846 /* Get the lane map from phymod access */ 847 lane_map = PHYMOD_ACC_LANE_MASK(&phy->access); 848 QUADRA28_GET_LOC(phy, pkg_side); 849 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 850 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 851 852 /* Select respective side */ 853 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 854 if (pmd_mode == Q28_SINGLE_PMD) { 855 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 856 if (((lane_map >> lane_index) & 1) == 0x1) { 857 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 858 859 PHYMOD_IF_ERR_RETURN(merlin_quadra28_prbs_chk_lock_state(&acc_cpy, (uint8_t*)&prbs_chk_lock_stat)); 860 861 *lock_status &= prbs_chk_lock_stat; 862 863 PHYMOD_IF_ERR_RETURN(merlin_quadra28_prbs_err_count_state(&acc_cpy, &per_lane_err_count, &loss_of_lock)); 864 *error_count |= per_lane_err_count; 865 *lock_loss &= loss_of_lock; 866 } 867 } 868 } else { 869 PHYMOD_IF_ERR_RETURN(merlin_quadra28_prbs_chk_lock_state(&acc_cpy, (uint8_t*)&prbs_chk_lock_stat)); 870 *lock_status &= prbs_chk_lock_stat; 871 PHYMOD_IF_ERR_RETURN(merlin_quadra28_prbs_err_count_state(&acc_cpy, &per_lane_err_count, &loss_of_lock)); 872 *error_count |= per_lane_err_count; 873 *lock_loss &= loss_of_lock; 874 } 875 /* restore Q28_INTF_LINE side */ 876 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val,Q28_INTF_LINE); 877 return PHYMOD_E_NONE; 878 } 879 /** Get link status of PHY 880 * This function is used to retrieve the link status of PHY chip 881 * 882 * @param pa Pointer to phymod access structure 883 * 884 * @param link_status link status of the PHY 885 * 1 - Up 886 * 0 - Down 887 * 888 * @return PHYMOD_E_NONE successful function execution 889 */ 890 int quadra28_link_status(const phymod_phy_access_t *phy, uint32_t *link_status) 891 { 892 int pkg_side = 0; 893 int num_lanes = QUADRA28_MAX_LANE; 894 int lane_map = 0; 895 uint32_t retime_enable = 0, pcs_status = 0; 896 int lane_index = 0; 897 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 898 BCMI_QUADRA28_PMD_STATUSr_t ieee_pmd_status1_reg_val; 899 BCMI_QUADRA28_PCS_STATUS1r_t pcs_status1_reg_val; 900 phymod_access_t acc_cpy; 901 int pmd_mode = 0; 902 uint32_t speed = 0; 903 904 905 PHYMOD_MEMSET(&side_sel_reg_val, 0, sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 906 PHYMOD_MEMSET(&ieee_pmd_status1_reg_val, 0, sizeof(BCMI_QUADRA28_PMD_STATUSr_t)); 907 PHYMOD_MEMSET(&pcs_status1_reg_val, 0, sizeof(BCMI_QUADRA28_PCS_STATUS1r_t)); 908 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 909 910 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 911 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 912 913 QUADRA28_GET_LOC(phy, pkg_side); 914 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 915 916 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val,pkg_side); 917 *link_status = 1; 918 919 if (pmd_mode == Q28_SINGLE_PMD) { 920 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 921 if (((lane_map >> lane_index) & 1) == 0x1) { 922 /* select a lane */ 923 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 924 925 /* Get PMD status */ 926 PHYMOD_IF_ERR_RETURN(BCMI_QUADRA28_READ_PMD_STATUSr(&acc_cpy, &ieee_pmd_status1_reg_val)); 927 *link_status &= BCMI_QUADRA28_PMD_STATUSr_LN_LKDTCDRf_GET(ieee_pmd_status1_reg_val); 928 } 929 } 930 } else { 931 /* Get PCS status if PCS is ON */ 932 PHYMOD_IF_ERR_RETURN( 933 _quadra28_phy_retimer_enable_get(&acc_cpy, &retime_enable)); 934 if (1 == retime_enable) { 935 if (speed == 1000) { 936 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_read(&acc_cpy, 0x7ffe1, &pcs_status)); 937 *link_status &= ((pcs_status & 0x4) >> 2); 938 } else { 939 PHYMOD_IF_ERR_RETURN( 940 BCMI_QUADRA28_READ_PCS_STATUS1r(&acc_cpy, &pcs_status1_reg_val)); 941 *link_status &= BCMI_QUADRA28_PCS_STATUS1r_PCS_RECEIVE_LINK_STATUSf_GET(pcs_status1_reg_val); 942 } 943 } 944 /* Get PMD status */ 945 PHYMOD_IF_ERR_RETURN(BCMI_QUADRA28_READ_PMD_STATUSr(&acc_cpy, &ieee_pmd_status1_reg_val)); 946 *link_status &= BCMI_QUADRA28_PMD_STATUSr_LN_LKDTCDRf_GET(ieee_pmd_status1_reg_val); 947 } 948 /* restore Q28_INTF_LINE side */ 949 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val,Q28_INTF_LINE); 950 return PHYMOD_E_NONE; 951 952 } 953 954 int _quadra28_refclk_set(const phymod_access_t *pa, uint32_t ref_clk) 955 { 956 BCMI_QUADRA28_APPS_MODE_2r_t apps_mod2_reg_val; 957 958 PHYMOD_MEMSET(&apps_mod2_reg_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_2r_t)); 959 PHYMOD_IF_ERR_RETURN(BCMI_QUADRA28_READ_APPS_MODE_2r(pa, &apps_mod2_reg_val)); 960 if (phymodRefClk156Mhz == ref_clk) { 961 BCMI_QUADRA28_APPS_MODE_2r_REFERENCE_CLOCKf_SET(apps_mod2_reg_val,0); 962 } else { 963 BCMI_QUADRA28_APPS_MODE_2r_REFERENCE_CLOCKf_SET(apps_mod2_reg_val,1); 964 } 965 966 PHYMOD_IF_ERR_RETURN(BCMI_QUADRA28_WRITE_APPS_MODE_2r(pa, apps_mod2_reg_val)); 967 968 return PHYMOD_E_NONE; 969 } 970 971 /** Set Tx Rx polarity 972 * This function is used to set Tx Rx polarity of a single lane 973 * or multiple lanes 974 * 975 * @param phy Pointer to phymod access structure 976 * @param tx_polarity Tx polarity 977 * @param rx_polarity Rx polarity 978 * 979 * @return PHYMOD_E_NONE successful function execution 980 */ 981 int quadra28_tx_rx_polarity_set (const phymod_phy_access_t *phy, uint32_t tx_polarity, uint32_t rx_polarity) 982 { 983 int lane_map = 0; 984 int pkg_side = 0; 985 int num_lanes = QUADRA28_MAX_LANE; 986 int lane_index = 0; 987 BCMI_QUADRA28_TX_CTRL_0r_t tx_ctrl0r_config; 988 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 989 BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_t tx_misc; 990 BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_t rx_misc; 991 phymod_access_t acc_cpy; 992 int pmd_mode = 0; 993 uint32_t speed = 0; 994 uint8_t datapath = 0; 995 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 996 PHYMOD_MEMSET(&tx_ctrl0r_config, 0 , sizeof(BCMI_QUADRA28_TX_CTRL_0r_t)); 997 PHYMOD_MEMSET(&tx_misc, 0 , sizeof(BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_t)); 998 PHYMOD_MEMSET(&rx_misc, 0 , sizeof(BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_t)); 999 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1000 1001 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1002 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1003 1004 /* Get the lane map from phymod access */ 1005 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1006 QUADRA28_GET_LOC(phy, pkg_side); 1007 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val,pkg_side); 1008 Q28_GET_DATAPATH(&acc_cpy, datapath); 1009 if (pmd_mode == Q28_SINGLE_PMD) { 1010 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 1011 if (((lane_map >> lane_index) & 1) == 0x1) { 1012 PHYMOD_IF_ERR_RETURN( 1013 quadra28_channel_select(&acc_cpy, lane_index)); 1014 if (datapath == phymodDatapathUll) { 1015 if (tx_polarity == 0xFFFF || tx_polarity == 0xFFFFFFFF) { 1016 continue; 1017 } 1018 /* Read 4bit tx config register for both line & sys side */ 1019 PHYMOD_IF_ERR_RETURN 1020 (BCMI_QUADRA28_READ_TX_CTRL_0r(&acc_cpy, &tx_ctrl0r_config)); 1021 /* Program 4-bit Line Side Tx Polarity Flip */ 1022 BCMI_QUADRA28_TX_CTRL_0r_LL_POLARITY_FLIPf_SET(tx_ctrl0r_config, 1023 ((tx_polarity >> lane_index) & 1)); 1024 /* Write to Rx config register - 4-bit */ 1025 PHYMOD_IF_ERR_RETURN( 1026 BCMI_QUADRA28_WRITE_TX_CTRL_0r(&acc_cpy, tx_ctrl0r_config)); 1027 } else { 1028 if (tx_polarity == 0xFFFF || tx_polarity == 0xFFFFFFFF) { 1029 continue; 1030 } 1031 PHYMOD_IF_ERR_RETURN( 1032 BCMI_QUADRA28_READ_TLB_TX_MISC_CONFIGr(&acc_cpy, &tx_misc)); 1033 BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_TX_PMD_DP_INVERTf_SET(tx_misc, 1034 ((tx_polarity >> lane_index) & 1)); 1035 PHYMOD_IF_ERR_RETURN( 1036 BCMI_QUADRA28_WRITE_TLB_TX_MISC_CONFIGr(&acc_cpy, tx_misc)); 1037 if (rx_polarity == 0xFFFF || rx_polarity == 0xFFFFFFFF) { 1038 continue; 1039 } 1040 PHYMOD_IF_ERR_RETURN( 1041 BCMI_QUADRA28_READ_TLB_RX_MISC_CONFIGr(&acc_cpy, &rx_misc)); 1042 BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_RX_PMD_DP_INVERTf_SET(rx_misc, 1043 ((rx_polarity >> lane_index) & 1)); 1044 PHYMOD_IF_ERR_RETURN( 1045 BCMI_QUADRA28_WRITE_TLB_RX_MISC_CONFIGr(&acc_cpy, rx_misc)); 1046 } 1047 } 1048 } /* End for */ 1049 } else { 1050 1051 if (datapath == phymodDatapathUll) { 1052 if ((tx_polarity != 0xFFFF) && (tx_polarity != 0xFFFFFFFF)) { 1053 /* Read 4bit tx config register for both line & sys side */ 1054 PHYMOD_IF_ERR_RETURN 1055 (BCMI_QUADRA28_READ_TX_CTRL_0r(&acc_cpy, &tx_ctrl0r_config)); 1056 1057 /* Program 4-bit Line Side Tx Polarity Flip */ 1058 BCMI_QUADRA28_TX_CTRL_0r_LL_POLARITY_FLIPf_SET(tx_ctrl0r_config, tx_polarity); 1059 1060 /* Write to Rx config register - 4-bit */ 1061 PHYMOD_IF_ERR_RETURN( 1062 BCMI_QUADRA28_WRITE_TX_CTRL_0r(&acc_cpy, tx_ctrl0r_config)); 1063 } 1064 } else { 1065 if ((tx_polarity != 0xFFFF) && (tx_polarity != 0xFFFFFFFF)) { 1066 PHYMOD_IF_ERR_RETURN( 1067 BCMI_QUADRA28_READ_TLB_TX_MISC_CONFIGr(&acc_cpy, &tx_misc)); 1068 BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_TX_PMD_DP_INVERTf_SET(tx_misc, tx_polarity); 1069 PHYMOD_IF_ERR_RETURN( 1070 BCMI_QUADRA28_WRITE_TLB_TX_MISC_CONFIGr(&acc_cpy, tx_misc)); 1071 } 1072 if ((rx_polarity != 0xFFFF) && (rx_polarity != 0xFFFFFFFF)) { 1073 PHYMOD_IF_ERR_RETURN( 1074 BCMI_QUADRA28_READ_TLB_RX_MISC_CONFIGr(&acc_cpy, &rx_misc)); 1075 BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_RX_PMD_DP_INVERTf_SET(rx_misc, rx_polarity); 1076 PHYMOD_IF_ERR_RETURN( 1077 BCMI_QUADRA28_WRITE_TLB_RX_MISC_CONFIGr(&acc_cpy, rx_misc)); 1078 } 1079 } 1080 } 1081 /* restore Q28_INTF_LINE side */ 1082 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val,Q28_INTF_LINE); 1083 return PHYMOD_E_NONE; 1084 } 1085 /** Get Tx Rx polarity 1086 * This function is used to get Tx Rx polarity of a specific lane 1087 * specified by user 1088 * 1089 * @param phy Pointer to phymod access structure 1090 * @param tx_polarity Tx polarity 1091 * @param rx_polarity Rx polarity 1092 * 1093 * @return PHYMOD_E_NONE successful function execution 1094 */ 1095 int quadra28_tx_rx_polarity_get (const phymod_phy_access_t *phy, uint32_t *tx_polarity, uint32_t *rx_polarity) 1096 { 1097 int lane_map = 0; 1098 int pkg_side = 0; 1099 int num_lanes = 0; 1100 int lane_index = 0; 1101 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 1102 phymod_access_t acc_cpy; 1103 int pmd_mode = 0; 1104 uint32_t speed = 0; 1105 BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_t tx_misc; 1106 BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_t rx_misc; 1107 uint8_t datapath = 0; 1108 BCMI_QUADRA28_TX_CTRL_0r_t tx_ctrl0r_config; 1109 1110 PHYMOD_MEMSET(&tx_misc, 0 , sizeof(BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_t)); 1111 PHYMOD_MEMSET(&rx_misc, 0 , sizeof(BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_t)); 1112 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 1113 PHYMOD_MEMSET(&tx_ctrl0r_config, 0 , sizeof(BCMI_QUADRA28_TX_CTRL_0r_t)); 1114 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1115 1116 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1117 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1118 1119 /* Get the lane map from phymod access */ 1120 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1121 QUADRA28_GET_LOC(phy, pkg_side); 1122 1123 Q28_GET_DATAPATH(&acc_cpy, datapath); 1124 num_lanes = QUADRA28_MAX_LANE; /* for octal pkg */ 1125 1126 *tx_polarity = 0; 1127 *rx_polarity = 0; 1128 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1129 1130 if (pmd_mode == Q28_SINGLE_PMD) { 1131 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 1132 if (((lane_map >> lane_index) & 1) == 0x1) { 1133 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1134 if (datapath == phymodDatapathUll) { 1135 PHYMOD_IF_ERR_RETURN 1136 (BCMI_QUADRA28_READ_TX_CTRL_0r(&acc_cpy, &tx_ctrl0r_config)); 1137 *tx_polarity |= (BCMI_QUADRA28_TX_CTRL_0r_LL_POLARITY_FLIPf_GET(tx_ctrl0r_config)) << lane_index; 1138 } else { 1139 PHYMOD_IF_ERR_RETURN( 1140 BCMI_QUADRA28_READ_TLB_TX_MISC_CONFIGr(&acc_cpy, &tx_misc)); 1141 *tx_polarity |= BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_TX_PMD_DP_INVERTf_GET(tx_misc) << lane_index; 1142 PHYMOD_IF_ERR_RETURN( 1143 BCMI_QUADRA28_READ_TLB_RX_MISC_CONFIGr(&acc_cpy, &rx_misc)); 1144 *rx_polarity |= BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_RX_PMD_DP_INVERTf_GET(rx_misc) << lane_index; 1145 } 1146 } 1147 } 1148 } else { 1149 if (datapath == phymodDatapathUll) { 1150 PHYMOD_IF_ERR_RETURN 1151 (BCMI_QUADRA28_READ_TX_CTRL_0r(&acc_cpy, &tx_ctrl0r_config)); 1152 *tx_polarity = BCMI_QUADRA28_TX_CTRL_0r_LL_POLARITY_FLIPf_GET(tx_ctrl0r_config); 1153 } else { 1154 PHYMOD_IF_ERR_RETURN( 1155 BCMI_QUADRA28_READ_TLB_TX_MISC_CONFIGr(&acc_cpy, &tx_misc)); 1156 *tx_polarity = BCMI_QUADRA28_TLB_TX_MISC_CONFIGr_TX_PMD_DP_INVERTf_GET(tx_misc); 1157 PHYMOD_IF_ERR_RETURN( 1158 BCMI_QUADRA28_READ_TLB_RX_MISC_CONFIGr(&acc_cpy, &rx_misc)); 1159 *rx_polarity = BCMI_QUADRA28_TLB_RX_MISC_CONFIGr_RX_PMD_DP_INVERTf_GET(rx_misc); 1160 } 1161 1162 } 1163 1164 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1165 return PHYMOD_E_NONE; 1166 } 1167 1168 /** PMD lock get 1169 * 1170 * @param pa Pointer to phymod access structure 1171 * @param rx_seq_done RX sew done status 1172 * 1173 * @return PHYMOD_E_NONE successful function execution 1174 */ 1175 int quadra28_pmd_lock_get(const phymod_phy_access_t *phy, uint32_t *rx_seq_done) 1176 { 1177 uint8_t rx_pmd_lock = 0; 1178 int lane_map = 0; 1179 int pkg_side = 0; 1180 int num_lanes = QUADRA28_MAX_LANE; 1181 int lane_index = 0; 1182 phymod_access_t acc_cpy; 1183 int pmd_mode = 0; 1184 uint32_t speed = 0; 1185 MDIO_BROADCAST_CONTROLr_t mdio_broadcast_ctrl; 1186 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 1187 1188 /* Initializing with invalid value*/ 1189 if(NULL != rx_seq_done) { 1190 *rx_seq_done = 0xFFFF; 1191 } else { 1192 return PHYMOD_E_PARAM; 1193 } 1194 PHYMOD_MEMSET(&mdio_broadcast_ctrl, 0 , sizeof(MDIO_BROADCAST_CONTROLr_t)); 1195 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 1196 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1197 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1198 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1199 1200 /* Get the lane map from phymod access */ 1201 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1202 QUADRA28_GET_LOC(phy, pkg_side); 1203 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1204 1205 if (pmd_mode == Q28_SINGLE_PMD) { 1206 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 1207 if (((lane_map >> lane_index) & 1) == 0x1) { 1208 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1209 PHYMOD_IF_ERR_RETURN( 1210 merlin_quadra28_pmd_lock_status(&acc_cpy, &rx_pmd_lock)); 1211 *rx_seq_done &= rx_pmd_lock; 1212 } 1213 } 1214 } else { 1215 if(NULL != rx_seq_done) { 1216 PHYMOD_IF_ERR_RETURN( 1217 merlin_quadra28_pmd_lock_status(&acc_cpy, &rx_pmd_lock)); 1218 *rx_seq_done &= rx_pmd_lock; 1219 } 1220 } 1221 /* restore Q28_INTF_LINE side */ 1222 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1223 return PHYMOD_E_NONE; 1224 } 1225 1226 /** Set line side interface 1227 * This function is used to set the operating mode of the PHY 1228 * 1229 * @param reg_val Pointer to apps mode reg 1230 * @param intf Interface specified by user 1231 * 1232 * @return PHYMOD_E_NONE successful function execution 1233 */ 1234 int _quadra28_config_line_interface(const phymod_access_t *pa, uint32_t* reg_val, phymod_interface_t intf, uint32_t speed) 1235 { 1236 int return_val = PHYMOD_E_NONE; 1237 uint32_t mask = 0, enable = 0; 1238 if (speed == Q28_SPEED_10G || speed == Q28_SPEED_HG11) { 1239 if ((intf != phymodInterfaceSR) && (intf != phymodInterfaceCR) && 1240 (intf != phymodInterfaceLR) && (intf != phymodInterfaceKR) && 1241 (intf != phymodInterfaceXFI) &&(intf != phymodInterfaceZR) && 1242 (intf != phymodInterfaceLRM)) { 1243 PHYMOD_DIAG_OUT(("Interface %d not supported, so setting default interface \n", intf)); 1244 intf = phymodInterfaceSR; 1245 } 1246 } else if(speed == Q28_SPEED_40G || speed == Q28_SPEED_42G) { 1247 if ((intf != phymodInterfaceSR4) && (intf != phymodInterfaceCR4) && 1248 (intf != phymodInterfaceLR4) && (intf != phymodInterfaceKR4) && 1249 (intf != phymodInterfaceXLAUI)) { 1250 PHYMOD_DIAG_OUT(("Interface %d not supported, so setting default interface \n", intf)); 1251 intf = phymodInterfaceSR4; 1252 } 1253 } else if (speed == Q28_SPEED_1G) { 1254 if ((intf != phymodInterface1000X) && (intf != phymodInterfaceKX) 1255 && (intf != phymodInterfaceSR)) { 1256 PHYMOD_DIAG_OUT(("Interface %d not supported, so setting default interface \n", intf)); 1257 intf = phymodInterface1000X; 1258 } 1259 } 1260 /* Need this, If Configured as ZR previously*/ 1261 if ((*reg_val & 0x5A00 ) == 0x5A00) { 1262 *reg_val |= (Q28_BIT(15)); 1263 } 1264 switch (intf) 1265 { 1266 case phymodInterfaceSR: 1267 case phymodInterfaceSR4: 1268 mask = ~(Q28_BIT(4) | Q28_BIT(5)| Q28_BIT(8) | 1269 Q28_BIT(14) | Q28_BIT(9) | Q28_BIT(12)); 1270 *reg_val &= mask; 1271 break; 1272 case phymodInterfaceKX: 1273 mask = ~ (Q28_BIT(4) | Q28_BIT(5)|Q28_BIT(8) | 1274 Q28_BIT(14) | Q28_BIT(9) | Q28_BIT(15) | 1275 Q28_BIT(11)); 1276 *reg_val &= mask; 1277 PHYMOD_IF_ERR_RETURN( 1278 _quadra28_phy_retimer_enable_get(pa, &enable)); 1279 /* Setting both line and sys*/ 1280 if (enable) { 1281 *reg_val |= 0x500; 1282 } else { 1283 /* Chip limitation: AN Will not work properly when its is enabled on both line and 1284 * system side in repeater mode*/ 1285 *reg_val |= 0x100; 1286 } 1287 break; 1288 case phymodInterfaceKR: 1289 case phymodInterfaceKR4: 1290 mask = ~(Q28_BIT(4) | Q28_BIT(5)|Q28_BIT(8) | 1291 Q28_BIT(14) | Q28_BIT(9)| Q28_BIT(12)); 1292 *reg_val &= mask; 1293 *reg_val |= 0x100; 1294 break; 1295 case phymodInterfaceCR: 1296 case phymodInterfaceCX: 1297 case phymodInterfaceCR4: 1298 mask = ~(Q28_BIT(4) | Q28_BIT(5)|Q28_BIT(8) | 1299 Q28_BIT(14) | Q28_BIT(9)| Q28_BIT(12)); 1300 *reg_val &= mask; 1301 *reg_val|= 0x200; 1302 break; 1303 1304 case phymodInterfaceLR: 1305 case phymodInterfaceLR4: 1306 mask = ~(Q28_BIT(4) | Q28_BIT(5) | Q28_BIT(8) 1307 | Q28_BIT(14) | Q28_BIT(9)| Q28_BIT(12)); 1308 *reg_val &= mask; 1309 *reg_val |= 0x4000; 1310 break; 1311 case phymodInterface1000X: 1312 mask = 0xF; 1313 *reg_val &= mask; 1314 break; 1315 case phymodInterfaceXLAUI: 1316 case phymodInterfaceXFI: 1317 mask = ~(Q28_BIT(4) | Q28_BIT(5) | Q28_BIT(8) | 1318 Q28_BIT(14) | Q28_BIT(9)| Q28_BIT(12)); 1319 *reg_val &= mask; 1320 *reg_val |= 0x4200; 1321 break; 1322 case phymodInterfaceZR: 1323 mask = ~(Q28_BIT(4) | Q28_BIT(5) | Q28_BIT(8) | 1324 Q28_BIT(14) | Q28_BIT(9) | Q28_BIT(15)); 1325 *reg_val &= mask; 1326 *reg_val |= 0x5A00; 1327 break; 1328 case phymodInterfaceLRM: 1329 *reg_val &= 0xF; 1330 *reg_val |= 0xC830; 1331 break; 1332 1333 default: 1334 return_val = PHYMOD_E_FAIL; 1335 break; 1336 } 1337 return return_val; 1338 } 1339 1340 /** Set sys side interface 1341 * This function is used to set the operating mode of the PHY 1342 * 1343 * @param reg_val Pointer to apps mode reg 1344 * @param intf Interface specified by user 1345 * 1346 * @return PHYMOD_E_NONE successful function execution 1347 */ 1348 int _quadra28_config_sys_interface(const phymod_access_t *pa, uint32_t* reg_val, phymod_interface_t intf) 1349 { 1350 uint32_t mask = 0, enable = 0; 1351 /* configure the System side port mode - interface type */ 1352 switch (intf) 1353 { 1354 case phymodInterfaceXLAUI: 1355 case phymodInterfaceXFI: 1356 mask = ~(Q28_BIT(11) | Q28_BIT(15) | Q28_BIT(10)); 1357 *reg_val &= mask; 1358 *reg_val |= 0x8800; 1359 break; 1360 case phymodInterface1000X: 1361 mask = ~(Q28_BIT(11) | Q28_BIT(15) | Q28_BIT(10)); 1362 *reg_val &= mask; 1363 break; 1364 case phymodInterfaceKX: 1365 mask = ~(Q28_BIT(11) | Q28_BIT(15) | Q28_BIT(10)); 1366 *reg_val &= mask; 1367 PHYMOD_IF_ERR_RETURN( 1368 _quadra28_phy_retimer_enable_get(pa, &enable)); 1369 /* Setting both line and sys*/ 1370 if (enable) { 1371 *reg_val |= 0x500; 1372 } else { 1373 /* Chip limitation: AN Will not work properly when its is enabled on both line and 1374 * system side in repeater mode*/ 1375 *reg_val |= 0x100; 1376 } 1377 break; 1378 case phymodInterfaceCR4: 1379 case phymodInterfaceCX4: 1380 case phymodInterfaceCR: 1381 mask = ~(Q28_BIT(11) | Q28_BIT(15) | Q28_BIT(10)); 1382 *reg_val &= mask; 1383 *reg_val |= 0x800; 1384 break; 1385 case phymodInterfaceKR4: 1386 case phymodInterfaceKR: 1387 mask = ~(Q28_BIT(11) | Q28_BIT(15) | Q28_BIT(10)); 1388 *reg_val &= mask; 1389 *reg_val |= 0x400; 1390 1391 break; 1392 default: 1393 return PHYMOD_E_FAIL; 1394 } 1395 return PHYMOD_E_NONE; 1396 } 1397 1398 /** Set port speed 1399 * This function is used to set the operating mode of the PHY 1400 * 1401 * @param reg_val Pointer to apps mode reg 1402 * @param speed Interface specified by user 1403 * @param mode_type port mode (single vs multiple) 1404 * 1405 * @return PHYMOD_E_NONE successful function execution 1406 */ 1407 int _quadra28_config_port_speed(uint32_t speed, uint32_t* reg_val, uint16_t* mode_type) 1408 { 1409 int return_val = PHYMOD_E_NONE; 1410 *reg_val &= ~(0xF); 1411 *mode_type = 0; 1412 switch (speed) 1413 { 1414 case SPEED_1G_OS8P25: 1415 *reg_val |= 0x1; 1416 break; 1417 1418 case Q28_SPEED_10G: 1419 *reg_val |= 0x2; 1420 break; 1421 1422 case Q28_SPEED_1G: 1423 *reg_val |= 0x1; 1424 break; 1425 1426 case Q28_SPEED_11P5G: 1427 *reg_val |= 0x8; 1428 break; 1429 1430 case Q28_SPEED_20G: /* KR2 2 * 10.3125G */ 1431 *reg_val |= 0xC; 1432 break; 1433 1434 case Q28_SPEED_40G: 1435 *reg_val |= 0x4; 1436 *mode_type = 1; 1437 break; 1438 1439 case Q28_SPEED_42G: 1440 *reg_val |= 0x7; 1441 *mode_type = 1; 1442 break; 1443 case Q28_SPEED_HG11: 1444 *reg_val |= 0x5; 1445 break; 1446 1447 default: 1448 return_val = PHYMOD_E_PARAM; 1449 break; 1450 1451 }/* End: Switch for speed */ 1452 return return_val; 1453 } 1454 1455 int quadra28_tx_lane_control_set(const phymod_phy_access_t *phy, 1456 phymod_phy_tx_lane_control_t tx_control) 1457 { 1458 int lane_map = 0; 1459 int pkg_side = 0; 1460 int num_lanes = QUADRA28_MAX_LANE; 1461 int lane_index = 0; 1462 uint16_t err_code = 0; 1463 PMD_TRANSMIT_DISABLEr_t tx_disable; 1464 #ifdef SA_PLP_SUPPORT 1465 BCMI_QUADRA28_MISC_CONTROL1r_t misc_ctrl; 1466 #endif 1467 BCMI_QUADRA28_SIDE_SELECTIONr_t side_sel_reg_val; 1468 int pmd_mode = 0; 1469 uint32_t speed = 0; 1470 phymod_access_t acc_cpy; 1471 phymod_access_t *pa=&acc_cpy; 1472 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(BCMI_QUADRA28_SIDE_SELECTIONr_t)); 1473 PHYMOD_MEMSET(&tx_disable, 0 , sizeof(PMD_TRANSMIT_DISABLEr_t)); 1474 #ifdef SA_PLP_SUPPORT 1475 PHYMOD_MEMSET(&misc_ctrl, 0 , sizeof(BCMI_QUADRA28_MISC_CONTROL1r_t)); 1476 #endif 1477 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1478 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1479 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1480 1481 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1482 1483 /* Get the lane map from phymod access */ 1484 QUADRA28_GET_LOC(phy, pkg_side); 1485 QUADRA28_SELECT_SIDE(&acc_cpy, side_sel_reg_val, pkg_side); 1486 1487 if (pmd_mode == Q28_SINGLE_PMD) { 1488 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 1489 if (((lane_map >> lane_index) & 1) == 0x1) { 1490 PHYMOD_IF_ERR_RETURN( 1491 quadra28_channel_select(&acc_cpy, 1492 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 1493 switch(tx_control) { 1494 case phymodTxSquelchOn: 1495 PHYMOD_IF_ERR_RETURN( 1496 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 1497 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET 1498 (tx_disable, 1); 1499 PHYMOD_IF_ERR_RETURN( 1500 WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_disable)); 1501 #ifdef SA_PLP_SUPPORT 1502 PHYMOD_IF_ERR_RETURN( 1503 BCMI_QUADRA28_READ_MISC_CONTROL1r(&acc_cpy,&misc_ctrl)); 1504 BCMI_QUADRA28_MISC_CONTROL1r_PMD_TX_DISABLE_PIN_DISf_SET(misc_ctrl,0); 1505 PHYMOD_IF_ERR_RETURN( 1506 BCMI_QUADRA28_WRITE_MISC_CONTROL1r(&acc_cpy,misc_ctrl)); 1507 #endif 1508 break; 1509 case phymodTxSquelchOff: 1510 PHYMOD_IF_ERR_RETURN( 1511 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 1512 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET 1513 (tx_disable, 0); 1514 PHYMOD_IF_ERR_RETURN( 1515 WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_disable)); 1516 #ifdef SA_PLP_SUPPORT 1517 PHYMOD_IF_ERR_RETURN( 1518 BCMI_QUADRA28_READ_MISC_CONTROL1r(&acc_cpy,&misc_ctrl)); 1519 BCMI_QUADRA28_MISC_CONTROL1r_PMD_TX_DISABLE_PIN_DISf_SET(misc_ctrl,1); 1520 PHYMOD_IF_ERR_RETURN( 1521 BCMI_QUADRA28_WRITE_MISC_CONTROL1r(&acc_cpy,misc_ctrl)); 1522 #endif 1523 break; 1524 case phymodTxReset: 1525 err_code = wr_ln_dp_s_rstb(0); 1526 if (err_code != ERR_CODE_NONE){ 1527 return err_code; 1528 } 1529 break; 1530 default: 1531 return PHYMOD_E_UNAVAIL; 1532 } 1533 if (Q28_ALL_LANE == lane_map) { 1534 break; 1535 } 1536 } 1537 } 1538 } else { 1539 switch(tx_control) { 1540 case phymodTxSquelchOn: 1541 PHYMOD_IF_ERR_RETURN( 1542 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 1543 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET 1544 (tx_disable, 1); 1545 PHYMOD_IF_ERR_RETURN( 1546 WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_disable)); 1547 #ifdef SA_PLP_SUPPORT 1548 PHYMOD_IF_ERR_RETURN( 1549 BCMI_QUADRA28_READ_MISC_CONTROL1r(&acc_cpy,&misc_ctrl)); 1550 BCMI_QUADRA28_MISC_CONTROL1r_PMD_TX_DISABLE_PIN_DISf_SET(misc_ctrl,0); 1551 PHYMOD_IF_ERR_RETURN( 1552 BCMI_QUADRA28_WRITE_MISC_CONTROL1r(&acc_cpy,misc_ctrl)); 1553 #endif 1554 break; 1555 case phymodTxSquelchOff: 1556 PHYMOD_IF_ERR_RETURN( 1557 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 1558 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET 1559 (tx_disable, 0); 1560 PHYMOD_IF_ERR_RETURN( 1561 WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_disable)); 1562 #ifdef SA_PLP_SUPPORT 1563 PHYMOD_IF_ERR_RETURN( 1564 BCMI_QUADRA28_READ_MISC_CONTROL1r(&acc_cpy,&misc_ctrl)); 1565 BCMI_QUADRA28_MISC_CONTROL1r_PMD_TX_DISABLE_PIN_DISf_SET(misc_ctrl,1); 1566 PHYMOD_IF_ERR_RETURN( 1567 BCMI_QUADRA28_WRITE_MISC_CONTROL1r(&acc_cpy,misc_ctrl)); 1568 #endif 1569 break; 1570 case phymodTxReset: 1571 err_code = wr_ln_dp_s_rstb(0); 1572 if (err_code != ERR_CODE_NONE){ 1573 return err_code; 1574 } 1575 break; 1576 default: 1577 return PHYMOD_E_UNAVAIL; 1578 } 1579 } 1580 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy, side_sel_reg_val, Q28_INTF_LINE); 1581 return PHYMOD_E_NONE; 1582 } 1583 1584 int quadra28_tx_squelch_get(const phymod_phy_access_t *phy, 1585 int *tx_squelch) 1586 { 1587 int lane_map = 0; 1588 int pkg_side = 0; 1589 int num_lanes = QUADRA28_MAX_LANE; 1590 int lane_index = 0; 1591 PMD_TRANSMIT_DISABLEr_t tx_disable; 1592 SIDE_SELECTIONr_t side_sel_reg_val; 1593 int pmd_mode = 0; 1594 uint32_t speed = 0; 1595 phymod_access_t acc_cpy; 1596 1597 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 1598 PHYMOD_MEMSET(&tx_disable, 0 , sizeof(PMD_TRANSMIT_DISABLEr_t)); 1599 PHYMOD_MEMCPY(&acc_cpy,&phy->access, sizeof(phymod_access_t)); 1600 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1601 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1602 1603 /* Get the lane map from phymod access */ 1604 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1605 QUADRA28_GET_LOC(phy, pkg_side); 1606 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1607 1608 if (pmd_mode == Q28_SINGLE_PMD) { 1609 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 1610 if (((lane_map >> lane_index) & 1) == 0x1) { 1611 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1612 PHYMOD_IF_ERR_RETURN( 1613 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 1614 *tx_squelch = 1615 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_GET(tx_disable); 1616 break; 1617 } 1618 } 1619 } else { 1620 PHYMOD_IF_ERR_RETURN( 1621 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 1622 *tx_squelch = 1623 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_GET(tx_disable); 1624 } 1625 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1626 1627 return PHYMOD_E_NONE; 1628 } 1629 1630 int quadra28_rx_lane_control_set(const phymod_phy_access_t *phy, 1631 phymod_phy_rx_lane_control_t rx_control) 1632 { 1633 int lane_map = 0; 1634 int pkg_side = 0; 1635 int num_lanes = QUADRA28_MAX_LANE; 1636 int lane_index = 0; 1637 uint16_t err_code = 0; 1638 SIDE_SELECTIONr_t side_sel_reg_val; 1639 SIGDET_CTRL_1r_t sigdet_ctrl1_reg; 1640 int pmd_mode = 0; 1641 uint32_t speed = 0; 1642 phymod_access_t acc_cpy; 1643 phymod_access_t *pa=&acc_cpy; 1644 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 1645 PHYMOD_MEMSET(&sigdet_ctrl1_reg, 0 , sizeof(SIGDET_CTRL_1r_t)); 1646 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1647 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1648 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1649 1650 /* Get the lane map from phymod access */ 1651 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1652 QUADRA28_GET_LOC(phy, pkg_side); 1653 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1654 1655 if (pmd_mode == Q28_SINGLE_PMD) { 1656 switch(rx_control) { 1657 case phymodRxSquelchOff: 1658 case phymodRxSquelchOn: 1659 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 1660 if (((lane_map >> lane_index) & 1) == 0x1) { 1661 PHYMOD_IF_ERR_RETURN( 1662 quadra28_channel_select(&acc_cpy, 1663 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 1664 PHYMOD_IF_ERR_RETURN( 1665 READ_SIGDET_CTRL_1r(&acc_cpy, &sigdet_ctrl1_reg)); 1666 SIGDET_CTRL_1r_SIGNAL_DETECT_FRC_VALf_SET(sigdet_ctrl1_reg, 1667 ((rx_control == phymodRxSquelchOn) ? 0 : 1)); 1668 SIGDET_CTRL_1r_SIGNAL_DETECT_FRCf_SET(sigdet_ctrl1_reg, 1); 1669 PHYMOD_IF_ERR_RETURN( 1670 WRITE_SIGDET_CTRL_1r(&acc_cpy, sigdet_ctrl1_reg)); 1671 /* If there is no RX squelch change the force to 0 1672 * i.e. get the RX status from Analog*/ 1673 if (rx_control == phymodRxSquelchOff) { 1674 SIGDET_CTRL_1r_SIGNAL_DETECT_FRCf_SET(sigdet_ctrl1_reg, 0); 1675 PHYMOD_IF_ERR_RETURN( 1676 WRITE_SIGDET_CTRL_1r(&acc_cpy, sigdet_ctrl1_reg)); 1677 1678 } 1679 if (Q28_ALL_LANE == lane_map) { 1680 break; 1681 } 1682 } 1683 } 1684 break; 1685 case phymodRxReset: 1686 err_code = wr_ln_dp_s_rstb(0); 1687 if (err_code != ERR_CODE_NONE){ 1688 return err_code; 1689 } 1690 break; 1691 default: 1692 return PHYMOD_E_UNAVAIL; 1693 } 1694 } else { 1695 switch(rx_control) { 1696 case phymodRxSquelchOn: 1697 case phymodRxSquelchOff: 1698 PHYMOD_IF_ERR_RETURN( 1699 READ_SIGDET_CTRL_1r(&acc_cpy, &sigdet_ctrl1_reg)); 1700 SIGDET_CTRL_1r_SIGNAL_DETECT_FRC_VALf_SET(sigdet_ctrl1_reg, 1701 ((rx_control == phymodRxSquelchOn) ? 0 : 1)); 1702 SIGDET_CTRL_1r_SIGNAL_DETECT_FRCf_SET(sigdet_ctrl1_reg, 1); 1703 PHYMOD_IF_ERR_RETURN( 1704 WRITE_SIGDET_CTRL_1r(&acc_cpy, sigdet_ctrl1_reg)); 1705 /* If there is no RX squelch change the force to 0 1706 * i.e. get the RX status from Analog*/ 1707 if (rx_control == phymodRxSquelchOff) { 1708 SIGDET_CTRL_1r_SIGNAL_DETECT_FRCf_SET(sigdet_ctrl1_reg, 0); 1709 PHYMOD_IF_ERR_RETURN( 1710 WRITE_SIGDET_CTRL_1r(&acc_cpy, sigdet_ctrl1_reg)); 1711 } 1712 1713 break; 1714 case phymodRxReset: 1715 err_code = wr_ln_dp_s_rstb(0); 1716 if (err_code != ERR_CODE_NONE){ 1717 return err_code; 1718 } 1719 break; 1720 default: 1721 return PHYMOD_E_UNAVAIL; 1722 } 1723 } 1724 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1725 return PHYMOD_E_NONE; 1726 } 1727 1728 int quadra28_rx_squelch_get(const phymod_phy_access_t *phy, int *rx_squelch) 1729 { 1730 int lane_map = 0; 1731 int pkg_side = 0; 1732 int num_lanes = QUADRA28_MAX_LANE; 1733 int lane_index = 0; 1734 SIDE_SELECTIONr_t side_sel_reg_val; 1735 SIGDET_CTRL_1r_t sigdet_ctrl1_reg; 1736 int pmd_mode = 0; 1737 uint32_t speed = 0; 1738 phymod_access_t acc_cpy; 1739 1740 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 1741 PHYMOD_MEMSET(&sigdet_ctrl1_reg, 0 , sizeof(SIGDET_CTRL_1r_t)); 1742 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1743 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1744 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1745 1746 /* Get the lane map from phymod access */ 1747 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1748 QUADRA28_GET_LOC(phy, pkg_side); 1749 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1750 1751 if (pmd_mode == Q28_SINGLE_PMD) { 1752 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 1753 if (((lane_map >> lane_index) & 1) == 0x1) { 1754 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1755 PHYMOD_IF_ERR_RETURN( 1756 READ_SIGDET_CTRL_1r(&acc_cpy, &sigdet_ctrl1_reg)); 1757 *rx_squelch = SIGDET_CTRL_1r_SIGNAL_DETECT_FRCf_GET(sigdet_ctrl1_reg) ? 1758 1 : 0; 1759 break; 1760 } 1761 } 1762 } else { 1763 PHYMOD_IF_ERR_RETURN( 1764 READ_SIGDET_CTRL_1r(&acc_cpy, &sigdet_ctrl1_reg)); 1765 *rx_squelch = SIGDET_CTRL_1r_SIGNAL_DETECT_FRCf_GET(sigdet_ctrl1_reg) ? 1766 1 : 0; 1767 } 1768 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1769 1770 return PHYMOD_E_NONE; 1771 } 1772 1773 int quadra28_display_eye_scan(const phymod_phy_access_t *phy) 1774 { 1775 int lane_map = 0; 1776 int pkg_side = 0; 1777 int num_lanes = QUADRA28_MAX_LANE; 1778 int lane_index = 0; 1779 SIDE_SELECTIONr_t side_sel_reg_val; 1780 int pmd_mode = 0; 1781 uint32_t speed = 0; 1782 phymod_access_t acc_cpy; 1783 1784 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 1785 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1786 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1787 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1788 /* Get the lane map from phymod access */ 1789 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1790 QUADRA28_GET_LOC(phy, pkg_side); 1791 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1792 if (pmd_mode == Q28_SINGLE_PMD) { 1793 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 1794 if (((lane_map >> lane_index) & 1) == 0x1) { 1795 PHYMOD_DIAG_OUT((" eyescan for lane = %d lanemap:%x\n", lane_index, lane_map)); 1796 1797 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1798 PHYMOD_IF_ERR_RETURN 1799 (merlin_quadra28_display_lane_state_hdr(&acc_cpy)); 1800 PHYMOD_IF_ERR_RETURN 1801 (merlin_quadra28_display_lane_state(&acc_cpy)); 1802 PHYMOD_IF_ERR_RETURN 1803 (merlin_quadra28_display_eye_scan(&acc_cpy)); 1804 } 1805 } 1806 } else { 1807 PHYMOD_IF_ERR_RETURN 1808 (merlin_quadra28_display_lane_state_hdr(&acc_cpy)); 1809 PHYMOD_IF_ERR_RETURN 1810 (merlin_quadra28_display_lane_state(&acc_cpy)); 1811 PHYMOD_IF_ERR_RETURN 1812 (merlin_quadra28_display_eye_scan(&acc_cpy)); 1813 } 1814 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1815 return PHYMOD_E_NONE; 1816 } 1817 1818 int quadra28_ber_proj (const phymod_phy_access_t *phy, const phymod_phy_eyescan_options_t* eyescan_options) 1819 { 1820 int lane_map = 0; 1821 int pkg_side = 0; 1822 int num_lanes = QUADRA28_MAX_LANE; 1823 int lane_index = 0; 1824 SIDE_SELECTIONr_t side_sel_reg_val; 1825 int pmd_mode = 0; 1826 uint32_t speed = 0; 1827 #ifdef SERDES_API_FLOATING_POINT 1828 USR_DOUBLE speedD; 1829 BCMI_QUADRA28_PRBS_CHK_CONFIGr_t chk_config; 1830 #endif 1831 phymod_access_t acc_cpy; 1832 1833 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 1834 #ifdef SERDES_API_FLOATING_POINT 1835 PHYMOD_MEMSET(&chk_config, 0 , sizeof(BCMI_QUADRA28_PRBS_CHK_CONFIGr_t)); 1836 #endif 1837 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1838 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1839 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1840 /* Get the lane map from phymod access */ 1841 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1842 QUADRA28_GET_LOC(phy, pkg_side); 1843 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1844 if (pmd_mode == Q28_SINGLE_PMD) { 1845 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 1846 if (((lane_map >> lane_index) & 1) == 0x1) { 1847 PHYMOD_DIAG_OUT((" BER proj for lane = %d lanemap:%x\n", lane_index, lane_map)); 1848 1849 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1850 #ifdef SERDES_API_FLOATING_POINT 1851 if ((speed == Q28_SPEED_40G) || (speed == Q28_SPEED_10G) 1852 || (speed == Q28_SPEED_20G) || (speed == Q28_SPEED_1G)) { 1853 speedD = 10312 * 1000.0 * 1000.0; 1854 } else if((speed == Q28_SPEED_42G) || (speed == Q28_SPEED_HG11)) { 1855 speedD = 10937 * 1000.0 * 1000.0; 1856 } else if(speed == Q28_SPEED_11P5G) { 1857 speedD = 11500 * 1000.0 * 1000.0; 1858 } else { 1859 speedD = 10312 * 1000.0 * 1000.0; 1860 } 1861 1862 PHYMOD_IF_ERR_RETURN 1863 (merlin_quadra28_eye_margin_proj((&acc_cpy), speedD, eyescan_options->ber_proj_scan_mode, 1864 eyescan_options->ber_proj_timer_cnt, eyescan_options->ber_proj_err_cnt)); 1865 PHYMOD_IF_ERR_RETURN( 1866 BCMI_QUADRA28_READ_PRBS_CHK_CONFIGr(&acc_cpy, &chk_config)); 1867 BCMI_QUADRA28_PRBS_CHK_CONFIGr_TRNSUM_ERROR_COUNT_ENf_SET(chk_config, 0); 1868 PHYMOD_IF_ERR_RETURN( 1869 BCMI_QUADRA28_WRITE_PRBS_CHK_CONFIGr(&acc_cpy, chk_config)); 1870 #else 1871 PHYMOD_DIAG_OUT(("BER PROJ needs SERDES_API_FLOATING_POINT define to operate\n")); 1872 return PHYMOD_E_RESOURCE; 1873 #endif 1874 1875 } 1876 } 1877 } else { 1878 #ifdef SERDES_API_FLOATING_POINT 1879 if ((speed == Q28_SPEED_40G) || (speed == Q28_SPEED_10G) 1880 || (speed == Q28_SPEED_20G) || (speed == Q28_SPEED_1G)) { 1881 speedD = 10312 * 1000.0 * 1000.0; 1882 } else if((speed == Q28_SPEED_42G) || (speed == Q28_SPEED_HG11)) { 1883 speedD = 10937 * 1000.0 * 1000.0; 1884 } else if(speed == Q28_SPEED_11P5G) { 1885 speedD = 11500 * 1000.0 * 1000.0; 1886 } else { 1887 speedD = 10312 * 1000.0 * 1000.0; 1888 } 1889 1890 PHYMOD_IF_ERR_RETURN 1891 (merlin_quadra28_eye_margin_proj((&acc_cpy), speedD, eyescan_options->ber_proj_scan_mode, 1892 eyescan_options->ber_proj_timer_cnt, eyescan_options->ber_proj_err_cnt)); 1893 PHYMOD_IF_ERR_RETURN( 1894 BCMI_QUADRA28_READ_PRBS_CHK_CONFIGr(&acc_cpy, &chk_config)); 1895 BCMI_QUADRA28_PRBS_CHK_CONFIGr_TRNSUM_ERROR_COUNT_ENf_SET(chk_config, 0); 1896 PHYMOD_IF_ERR_RETURN( 1897 BCMI_QUADRA28_WRITE_PRBS_CHK_CONFIGr(&acc_cpy, chk_config)); 1898 #else 1899 PHYMOD_DIAG_OUT(("BER PROJ needs SERDES_API_FLOATING_POINT define to operate\n")); 1900 return PHYMOD_E_RESOURCE; 1901 #endif 1902 1903 } 1904 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1905 return PHYMOD_E_NONE; 1906 } 1907 1908 int _quadra28_phy_status_dump(const phymod_phy_access_t *phy) 1909 { 1910 int lane_map = 0; 1911 int pkg_side = 0; 1912 int num_lanes = QUADRA28_MAX_LANE; 1913 int lane_index = 0; 1914 SIDE_SELECTIONr_t side_sel_reg_val; 1915 int pmd_mode = 0; 1916 uint32_t speed = 0; 1917 phymod_access_t acc_cpy; 1918 uint8_t trace_mem[768]; 1919 1920 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 1921 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1922 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1923 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1924 1925 /* Get the lane map from phymod access */ 1926 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1927 QUADRA28_GET_LOC(phy, pkg_side); 1928 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1929 1930 PHYMOD_DIAG_OUT((" ***************************************\n")); 1931 PHYMOD_DIAG_OUT((" ******* PHY status dump for Q28 PHY ID:0x%x ********\n", acc_cpy.addr)); 1932 PHYMOD_DIAG_OUT((" ***************************************\n")); 1933 PHYMOD_DIAG_OUT((" ***************************************\n")); 1934 PHYMOD_DIAG_OUT((" ******* PHY status dump for side:%x ********\n", pkg_side)); 1935 PHYMOD_DIAG_OUT((" ***************************************\n")); 1936 PHYMOD_IF_ERR_RETURN(merlin_quadra28_display_core_config(&acc_cpy)); 1937 PHYMOD_IF_ERR_RETURN(merlin_quadra28_display_core_state(&acc_cpy)); 1938 1939 if (pmd_mode == Q28_SINGLE_PMD) { 1940 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 1941 if (((lane_map >> lane_index) & 1) == 0x1) { 1942 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1943 PHYMOD_IF_ERR_RETURN 1944 (merlin_quadra28_display_lane_state_hdr(&acc_cpy)); 1945 PHYMOD_IF_ERR_RETURN(merlin_quadra28_display_lane_state(&acc_cpy)); 1946 PHYMOD_IF_ERR_RETURN(merlin_quadra28_display_lane_config(&acc_cpy)); 1947 if ((lane_index & 1) == 0) { 1948 PHYMOD_IF_ERR_RETURN( 1949 merlin_quadra28_read_event_log(&acc_cpy, trace_mem, 2)); 1950 } 1951 } 1952 } 1953 } else { 1954 PHYMOD_IF_ERR_RETURN 1955 (merlin_quadra28_display_lane_state_hdr(&acc_cpy)); 1956 PHYMOD_IF_ERR_RETURN(merlin_quadra28_display_lane_state(&acc_cpy)); 1957 PHYMOD_IF_ERR_RETURN(merlin_quadra28_display_lane_config(&acc_cpy)); 1958 PHYMOD_IF_ERR_RETURN( 1959 merlin_quadra28_read_event_log(&acc_cpy, trace_mem, 2)); 1960 1961 } 1962 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 1963 return PHYMOD_E_NONE; 1964 } 1965 1966 int _quadra28_phy_diagnostics_get(const phymod_phy_access_t *phy, phymod_phy_diagnostics_t* diag) 1967 { 1968 int lane_map = 0; 1969 int pkg_side = 0; 1970 int num_lanes = QUADRA28_MAX_LANE; 1971 int lane_index = 0; 1972 SIDE_SELECTIONr_t side_sel_reg_val; 1973 int pmd_mode = 0; 1974 uint32_t speed = 0; 1975 phymod_access_t acc_cpy; 1976 merlin_quadra28_lane_state_st_define state; 1977 1978 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 1979 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 1980 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 1981 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 1982 1983 /* Get the lane map from phymod access */ 1984 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 1985 QUADRA28_GET_LOC(phy, pkg_side); 1986 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 1987 if (pmd_mode == Q28_SINGLE_PMD) { 1988 for(lane_index = 0; lane_index < num_lanes; lane_index++) { 1989 if (((lane_map >> lane_index) & 1) == 0x1) { 1990 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 1991 PHYMOD_IF_ERR_RETURN 1992 (merlin_quadra28_read_lane_state_define(&acc_cpy, &state)); 1993 diag->signal_detect = state.sig_det; 1994 diag->osr_mode = state.osr_mode.tx_rx; 1995 diag->rx_lock = state.rx_lock; 1996 diag->tx_ppm = state.tx_ppm; 1997 diag->clk90_offset = state.clk90; 1998 diag->clkp1_offset = state.clkp1; 1999 diag->p1_lvl = state.p1_lvl; 2000 diag->dfe1_dcd = state.dfe1_dcd; 2001 diag->dfe2_dcd = state.dfe2_dcd; 2002 diag->slicer_offset.offset_pe = state.pe; 2003 diag->slicer_offset.offset_ze = state.ze; 2004 diag->slicer_offset.offset_me = state.me; 2005 diag->slicer_offset.offset_po = state.po; 2006 diag->slicer_offset.offset_zo = state.zo; 2007 diag->slicer_offset.offset_mo = state.mo; 2008 diag->eyescan.heye_left = state.heye_left; 2009 diag->eyescan.heye_right = state.heye_right; 2010 diag->eyescan.veye_upper = state.veye_upper; 2011 diag->eyescan.veye_lower = state.veye_lower; 2012 diag->link_time = state.link_time; 2013 diag->pf_main = state.pf_main; 2014 diag->pf_hiz = state.pf_hiz; 2015 diag->pf_bst = state.pf_bst; 2016 diag->pf_low = 0; /* Not Availble in serdes API*/ 2017 diag->pf2_ctrl = state.pf2_ctrl; 2018 diag->vga = state.vga; 2019 diag->dc_offset = state.dc_offset; 2020 diag->p1_lvl_ctrl = state.p1_lvl_ctrl; 2021 diag->dfe1 = state.dfe1; 2022 diag->dfe2 = state.dfe2; 2023 diag->dfe3 = state.dfe3; 2024 diag->dfe4 = state.dfe4; 2025 diag->dfe5 = state.dfe5; 2026 diag->dfe6 = state.dfe6; 2027 diag->txfir_pre = state.txfir_pre; 2028 diag->txfir_main = state.txfir_main; 2029 diag->txfir_post1 = state.txfir_post1; 2030 diag->txfir_post2 = state.txfir_post2; 2031 diag->txfir_post3 = state.txfir_post3; 2032 diag->tx_amp_ctrl = 0; /* Not Availble in serdes API*/ 2033 diag->br_pd_en = state.br_pd_en; 2034 break; 2035 } 2036 } 2037 } else { 2038 PHYMOD_IF_ERR_RETURN 2039 (merlin_quadra28_read_lane_state_define(&acc_cpy, &state)); 2040 diag->signal_detect = state.sig_det; 2041 diag->osr_mode = state.osr_mode.tx_rx; 2042 diag->rx_lock = state.rx_lock; 2043 diag->tx_ppm = state.tx_ppm; 2044 diag->clk90_offset = state.clk90; 2045 diag->clkp1_offset = state.clkp1; 2046 diag->p1_lvl = state.p1_lvl; 2047 diag->dfe1_dcd = state.dfe1_dcd; 2048 diag->dfe2_dcd = state.dfe2_dcd; 2049 diag->slicer_offset.offset_pe = state.pe; 2050 diag->slicer_offset.offset_ze = state.ze; 2051 diag->slicer_offset.offset_me = state.me; 2052 diag->slicer_offset.offset_po = state.po; 2053 diag->slicer_offset.offset_zo = state.zo; 2054 diag->slicer_offset.offset_mo = state.mo; 2055 diag->eyescan.heye_left = state.heye_left; 2056 diag->eyescan.heye_right = state.heye_right; 2057 diag->eyescan.veye_upper = state.veye_upper; 2058 diag->eyescan.veye_lower = state.veye_lower; 2059 diag->link_time = state.link_time; 2060 diag->pf_main = state.pf_main; 2061 diag->pf_hiz = state.pf_hiz; 2062 diag->pf_bst = state.pf_bst; 2063 diag->pf_low = 0; /* Not Availble in serdes API*/ 2064 diag->pf2_ctrl = state.pf2_ctrl; 2065 diag->vga = state.vga; 2066 diag->dc_offset = state.dc_offset; 2067 diag->p1_lvl_ctrl = state.p1_lvl_ctrl; 2068 diag->dfe1 = state.dfe1; 2069 diag->dfe2 = state.dfe2; 2070 diag->dfe3 = state.dfe3; 2071 diag->dfe4 = state.dfe4; 2072 diag->dfe5 = state.dfe5; 2073 diag->dfe6 = state.dfe6; 2074 diag->txfir_pre = state.txfir_pre; 2075 diag->txfir_main = state.txfir_main; 2076 diag->txfir_post1 = state.txfir_post1; 2077 diag->txfir_post2 = state.txfir_post2; 2078 diag->txfir_post3 = state.txfir_post3; 2079 diag->tx_amp_ctrl = 0; /* Not Availble in serdes API*/ 2080 diag->br_pd_en = state.br_pd_en; 2081 } 2082 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2083 return PHYMOD_E_NONE; 2084 } 2085 2086 int quadra28_soft_reset(const phymod_access_t* pa, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 2087 { 2088 int pkg_side = 0; 2089 uint32_t acc_flags = 0; 2090 SIDE_SELECTIONr_t side_sel_reg_val; 2091 uint32_t speed = 0; 2092 phymod_access_t acc_cpy; 2093 PMD_CONTROLr_t pmd_ctrl; 2094 2095 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2096 PHYMOD_MEMSET(&pmd_ctrl, 0 , sizeof(PMD_CONTROLr_t)); 2097 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 2098 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2099 2100 /* Get the lane map from phymod access */ 2101 acc_flags = PHYMOD_ACC_FLAGS(&acc_cpy); 2102 QUADRA28_GET_IF_SIDE(acc_flags, pkg_side); 2103 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2104 if (reset_mode == phymodResetModeSoft) { 2105 PHYMOD_IF_ERR_RETURN( 2106 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2107 BCMI_QUADRA28_PMD_CONTROLr_RESETf_SET(pmd_ctrl, 1); 2108 PHYMOD_IF_ERR_RETURN( 2109 BCMI_QUADRA28_WRITE_PMD_CONTROLr(&acc_cpy, pmd_ctrl)); 2110 } else { 2111 return PHYMOD_E_UNAVAIL; 2112 } 2113 2114 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2115 return PHYMOD_E_NONE; 2116 } 2117 2118 int _quadra28_phy_reset_set(const phymod_phy_access_t *phy, const phymod_phy_reset_t* reset) 2119 { 2120 int lane_map = 0; 2121 int pkg_side = 0; 2122 int num_lanes = QUADRA28_MAX_LANE; 2123 int lane_index = 0; 2124 SIDE_SELECTIONr_t side_sel_reg_val; 2125 int pmd_mode = 0; 2126 uint32_t speed = 0; 2127 phymod_access_t acc_cpy; 2128 2129 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2130 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2131 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2132 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2133 2134 /* Get the lane map from phymod access */ 2135 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2136 QUADRA28_GET_LOC(phy, pkg_side); 2137 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2138 2139 if (pmd_mode == Q28_SINGLE_PMD) { 2140 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2141 if (((lane_map >> lane_index) & 1) == 0x1) { 2142 PHYMOD_IF_ERR_RETURN( 2143 quadra28_channel_select(&acc_cpy, 2144 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 2145 PHYMOD_IF_ERR_RETURN( 2146 _quadra28_merlin_phy_reset_set(&acc_cpy, reset)); 2147 if (lane_map == Q28_ALL_LANE) { 2148 break; 2149 } 2150 } 2151 } 2152 } else { 2153 PHYMOD_IF_ERR_RETURN( 2154 _quadra28_merlin_phy_reset_set(&acc_cpy, reset)); 2155 } 2156 2157 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2158 return PHYMOD_E_NONE; 2159 } 2160 2161 static int _quadra28_merlin_phy_reset_set( phymod_access_t *pa, const phymod_phy_reset_t* reset) 2162 { 2163 /* TX AFE Lane Reset */ 2164 switch (reset->tx) { 2165 /* In Reset */ 2166 case phymodResetDirectionIn: 2167 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc_val(1)); 2168 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc(1)); 2169 break; 2170 /* Out Reset */ 2171 case phymodResetDirectionOut: 2172 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc_val(0)); 2173 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc(1)); 2174 break; 2175 /* Toggle Reset */ 2176 case phymodResetDirectionInOut: 2177 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc_val(1)); 2178 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc(1)); 2179 PHYMOD_USLEEP(10); 2180 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc_val(0)); 2181 PHYMOD_IF_ERR_RETURN(wr_afe_tx_reset_frc(1)); 2182 2183 break; 2184 default: 2185 break; 2186 } 2187 2188 /* RX AFE Lane Reset */ 2189 switch (reset->rx) { 2190 /* In Reset */ 2191 case phymodResetDirectionIn: 2192 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc_val(1)); 2193 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc(1)); 2194 break; 2195 /* Out Reset */ 2196 case phymodResetDirectionOut: 2197 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc_val(0)); 2198 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc(1)); 2199 break; 2200 /* Toggle Reset */ 2201 case phymodResetDirectionInOut: 2202 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc_val(1)); 2203 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc(1)); 2204 2205 PHYMOD_USLEEP(10); 2206 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc_val(0)); 2207 PHYMOD_IF_ERR_RETURN(wr_afe_rx_reset_frc(1)); 2208 2209 break; 2210 default: 2211 break; 2212 } 2213 2214 return PHYMOD_E_NONE; 2215 } 2216 2217 int _quadra28_phy_reset_get( const phymod_phy_access_t *phy, phymod_phy_reset_t* reset) 2218 { 2219 int lane_map = 0; 2220 int pkg_side = 0; 2221 int num_lanes = QUADRA28_MAX_LANE; 2222 int lane_index = 0; 2223 SIDE_SELECTIONr_t side_sel_reg_val; 2224 SIGDET_CTRL_1r_t sigdet_ctrl1_reg; 2225 int pmd_mode = 0; 2226 uint32_t speed = 0; 2227 phymod_access_t acc_cpy; 2228 2229 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2230 PHYMOD_MEMSET(&sigdet_ctrl1_reg, 0 , sizeof(SIGDET_CTRL_1r_t)); 2231 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2232 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2233 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2234 2235 /* Get the lane map from phymod access */ 2236 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2237 QUADRA28_GET_LOC(phy, pkg_side); 2238 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2239 2240 if (pmd_mode == Q28_SINGLE_PMD) { 2241 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2242 if (((lane_map >> lane_index) & 1) == 0x1) { 2243 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 2244 PHYMOD_IF_ERR_RETURN ( 2245 _quadra28_merlin_phy_reset_get(&acc_cpy, reset)); 2246 break; 2247 } 2248 } 2249 } else { 2250 PHYMOD_IF_ERR_RETURN ( 2251 _quadra28_merlin_phy_reset_get(&acc_cpy, reset)); 2252 2253 } 2254 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2255 2256 return PHYMOD_E_NONE; 2257 2258 } 2259 2260 static int _quadra28_merlin_phy_reset_get( phymod_access_t *pa, phymod_phy_reset_t* reset) 2261 { 2262 uint8_t data = 0; 2263 uint16_t __err = 0; 2264 data = rd_afe_tx_reset_frc_val(); 2265 if (data == 0) { 2266 /* Out of Reset */ 2267 reset->tx = phymodResetDirectionOut; 2268 } else { 2269 /* In Reset */ 2270 reset->tx = phymodResetDirectionIn; 2271 } 2272 data = rd_afe_rx_reset_frc_val(); 2273 if (data == 0) { 2274 /* Out of Reset */ 2275 reset->rx = phymodResetDirectionOut; 2276 } else { 2277 /* In Reset */ 2278 reset->rx = phymodResetDirectionIn; 2279 } 2280 return __err; 2281 } 2282 2283 int _quadra28_loopback_set(const phymod_phy_access_t *phy, phymod_loopback_mode_t loopback, uint32_t enable) 2284 { 2285 int lane_map = 0; 2286 int pkg_side = 0; 2287 int num_lanes = QUADRA28_MAX_LANE; 2288 int lane_index = 0; 2289 SIDE_SELECTIONr_t side_sel_reg_val; 2290 int pmd_mode = 0; 2291 uint32_t speed = 0; 2292 phymod_access_t acc_cpy; 2293 uint8_t datapath = 0; 2294 PMD_TRANSMIT_DISABLEr_t tx_disable; 2295 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 2296 2297 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 2298 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2299 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2300 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2301 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2302 2303 /* Get the lane map from phymod access */ 2304 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2305 QUADRA28_GET_LOC(phy, pkg_side); 2306 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2307 Q28_GET_DATAPATH(&acc_cpy, datapath); 2308 if (datapath == phymodDatapathUll && 2309 loopback == phymodLoopbackRemotePMD) { 2310 PHYMOD_DIAG_OUT(("Remote loopback doesnt support 4-bit datapath\n")); 2311 return PHYMOD_E_PARAM; 2312 } 2313 if (pmd_mode == Q28_SINGLE_PMD) { 2314 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2315 if (((lane_map >> lane_index) & 1) == 0x1) { 2316 PHYMOD_IF_ERR_RETURN( 2317 quadra28_channel_select(&acc_cpy, 2318 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 2319 if (loopback == phymodLoopbackGlobalPMD) { 2320 PHYMOD_IF_ERR_RETURN( 2321 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2322 BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_SET(pmd_ctrl, enable); 2323 PHYMOD_IF_ERR_RETURN( 2324 BCMI_QUADRA28_WRITE_PMD_CONTROLr(&acc_cpy, pmd_ctrl)); 2325 /*PHYMOD_IF_ERR_RETURN( 2326 merlin_quadra28_dig_lpbk(&acc_cpy, enable));*/ 2327 } else if (loopback == phymodLoopbackRemotePMD) { 2328 PHYMOD_IF_ERR_RETURN( 2329 merlin_quadra28_rmt_lpbk(&acc_cpy, enable)); 2330 } else if(loopback == phymodLoopbackGlobal) { 2331 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 2332 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 2333 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2334 /*PHYMOD_IF_ERR_RETURN( 2335 merlin_quadra28_dig_lpbk(&acc_cpy, enable));*/ 2336 PHYMOD_IF_ERR_RETURN( 2337 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2338 BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_SET(pmd_ctrl, enable); 2339 PHYMOD_IF_ERR_RETURN( 2340 BCMI_QUADRA28_WRITE_PMD_CONTROLr(&acc_cpy, pmd_ctrl)); 2341 /* Squelch TX */ 2342 PHYMOD_IF_ERR_RETURN( 2343 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 2344 BCMI_QUADRA28_PMD_TRANSMIT_DISABLEr_PMD_TRANSMITDISABLE_0f_SET 2345 (tx_disable, enable); 2346 PHYMOD_IF_ERR_RETURN( 2347 WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_disable)); 2348 } else { 2349 return PHYMOD_E_UNAVAIL; 2350 } 2351 if (lane_map == Q28_ALL_LANE) { 2352 break; 2353 } 2354 } 2355 } 2356 } else { 2357 if (loopback == phymodLoopbackGlobalPMD) { 2358 PHYMOD_IF_ERR_RETURN( 2359 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2360 BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_SET(pmd_ctrl, enable); 2361 PHYMOD_IF_ERR_RETURN( 2362 BCMI_QUADRA28_WRITE_PMD_CONTROLr(&acc_cpy, pmd_ctrl)); 2363 /*PHYMOD_IF_ERR_RETURN( 2364 merlin_quadra28_dig_lpbk(&acc_cpy, enable));*/ 2365 } else if (loopback == phymodLoopbackRemotePMD) { 2366 PHYMOD_IF_ERR_RETURN( 2367 merlin_quadra28_rmt_lpbk(&acc_cpy, enable)); 2368 } else if (loopback == phymodLoopbackGlobal) { 2369 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 2370 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 2371 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2372 2373 /*PHYMOD_IF_ERR_RETURN( 2374 merlin_quadra28_dig_lpbk(&acc_cpy, enable));*/ 2375 PHYMOD_IF_ERR_RETURN( 2376 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2377 BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_SET(pmd_ctrl, enable); 2378 PHYMOD_IF_ERR_RETURN( 2379 BCMI_QUADRA28_WRITE_PMD_CONTROLr(&acc_cpy, pmd_ctrl)); 2380 2381 /* Squelch TX */ 2382 PHYMOD_IF_ERR_RETURN( 2383 READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_disable)); 2384 BCMI_QUADRA28_PMD_TRANSMIT_DISABLEr_PMD_TRANSMITDISABLE_0f_SET 2385 (tx_disable, enable); 2386 PHYMOD_IF_ERR_RETURN( 2387 WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_disable)); 2388 } else { 2389 return PHYMOD_E_UNAVAIL; 2390 } 2391 } 2392 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2393 return PHYMOD_E_NONE; 2394 } 2395 2396 int _quadra28_loopback_get(const phymod_phy_access_t *phy, phymod_loopback_mode_t loopback, uint32_t* enable) 2397 { 2398 int lane_map = 0; 2399 int pkg_side = 0; 2400 int num_lanes = QUADRA28_MAX_LANE; 2401 int lane_index = 0; 2402 SIDE_SELECTIONr_t side_sel_reg_val; 2403 int pmd_mode = 0; 2404 uint32_t speed = 0; 2405 phymod_access_t acc_cpy; 2406 BCMI_QUADRA28_DIG_LPBK_CONFIGr_t dig_loopback; 2407 RMT_LPBK_CONFIGr_t rmt_loopback; 2408 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 2409 2410 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 2411 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2412 PHYMOD_MEMSET(&dig_loopback, 0 , sizeof(BCMI_QUADRA28_DIG_LPBK_CONFIGr_t)); 2413 PHYMOD_MEMSET(&rmt_loopback, 0 , sizeof(RMT_LPBK_CONFIGr_t)); 2414 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2415 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2416 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2417 2418 /* Get the lane map from phymod access */ 2419 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2420 QUADRA28_GET_LOC(phy, pkg_side); 2421 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2422 2423 if (pmd_mode == Q28_SINGLE_PMD) { 2424 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2425 if (((lane_map >> lane_index) & 1) == 0x1) { 2426 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 2427 if (loopback == phymodLoopbackGlobalPMD) { 2428 /*PHYMOD_IF_ERR_RETURN( 2429 READ_DIG_LPBK_CONFIGr(&acc_cpy, &dig_loopback));*/ 2430 PHYMOD_IF_ERR_RETURN( 2431 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2432 *enable = BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_GET(pmd_ctrl); 2433 } else if (loopback == phymodLoopbackGlobal) { 2434 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2435 PHYMOD_IF_ERR_RETURN( 2436 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2437 *enable = BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_GET(pmd_ctrl); 2438 } else if (loopback == phymodLoopbackRemotePMD) { 2439 PHYMOD_IF_ERR_RETURN( 2440 READ_RMT_LPBK_CONFIGr(&acc_cpy, &rmt_loopback)); 2441 *enable = RMT_LPBK_CONFIGr_RMT_LPBK_ENf_GET(rmt_loopback); 2442 } else { 2443 return PHYMOD_E_UNAVAIL; 2444 } 2445 break; 2446 } 2447 } 2448 } else { 2449 if (loopback == phymodLoopbackGlobalPMD) { 2450 PHYMOD_IF_ERR_RETURN( 2451 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2452 *enable = BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_GET(pmd_ctrl); 2453 } else if (loopback == phymodLoopbackRemotePMD) { 2454 PHYMOD_IF_ERR_RETURN( 2455 READ_RMT_LPBK_CONFIGr(&acc_cpy, &rmt_loopback)); 2456 *enable = RMT_LPBK_CONFIGr_RMT_LPBK_ENf_GET(rmt_loopback); 2457 } else if (loopback == phymodLoopbackGlobal) { 2458 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2459 PHYMOD_IF_ERR_RETURN( 2460 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 2461 *enable = BCMI_QUADRA28_PMD_CONTROLr_PMA_LOOPBACKf_GET(pmd_ctrl); 2462 2463 } else { 2464 return PHYMOD_E_UNAVAIL; 2465 } 2466 } 2467 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2468 2469 return PHYMOD_E_NONE; 2470 } 2471 2472 int _quadra28_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power) 2473 { 2474 int lane_map = 0; 2475 int pkg_side = 0; 2476 int num_lanes = QUADRA28_MAX_LANE; 2477 int lane_index = 0; 2478 SIDE_SELECTIONr_t side_sel_reg_val; 2479 int pmd_mode = 0; 2480 uint32_t speed = 0; 2481 phymod_access_t acc_cpy; 2482 2483 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2484 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2485 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2486 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2487 2488 /* Get the lane map from phymod access */ 2489 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2490 QUADRA28_GET_LOC(phy, pkg_side); 2491 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2492 2493 if (pmd_mode == Q28_SINGLE_PMD) { 2494 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2495 if (((lane_map >> lane_index) & 1) == 0x1) { 2496 PHYMOD_IF_ERR_RETURN( 2497 quadra28_channel_select(&acc_cpy, 2498 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 2499 PHYMOD_IF_ERR_RETURN(quadra28_power_set(&acc_cpy, power)); 2500 if (Q28_ALL_LANE == lane_map) { 2501 break; 2502 } 2503 } 2504 } 2505 } else { 2506 PHYMOD_IF_ERR_RETURN(quadra28_power_set(&acc_cpy, power)); 2507 } 2508 2509 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2510 return PHYMOD_E_NONE; 2511 } 2512 2513 static int quadra28_power_set(const phymod_access_t *pa, const phymod_phy_power_t* power) 2514 { 2515 2516 PMD_TRANSMIT_DISABLEr_t tx_disable; 2517 if (power->tx != phymodPowerNoChange) { 2518 if ( power->tx == phymodPowerOn) { 2519 PHYMOD_IF_ERR_RETURN(wr_ln_tx_s_pwrdn(0)); 2520 PHYMOD_IF_ERR_RETURN( 2521 READ_PMD_TRANSMIT_DISABLEr(pa, &tx_disable)); 2522 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET(tx_disable, 0); 2523 PHYMOD_IF_ERR_RETURN( 2524 WRITE_PMD_TRANSMIT_DISABLEr(pa, tx_disable)); 2525 } else if (power->tx == phymodPowerOff) { 2526 PHYMOD_IF_ERR_RETURN(wr_ln_tx_s_pwrdn(1)); 2527 PHYMOD_IF_ERR_RETURN( 2528 READ_PMD_TRANSMIT_DISABLEr(pa, &tx_disable)); 2529 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET(tx_disable, 1); 2530 PHYMOD_IF_ERR_RETURN( 2531 WRITE_PMD_TRANSMIT_DISABLEr(pa, tx_disable)); 2532 } else if (power->tx == phymodPowerOffOn) { 2533 PHYMOD_IF_ERR_RETURN(wr_ln_tx_s_pwrdn(1)); 2534 PHYMOD_IF_ERR_RETURN( 2535 READ_PMD_TRANSMIT_DISABLEr(pa, &tx_disable)); 2536 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET(tx_disable, 1); 2537 PHYMOD_IF_ERR_RETURN( 2538 WRITE_PMD_TRANSMIT_DISABLEr(pa, tx_disable)); 2539 PHYMOD_USLEEP(500); 2540 PHYMOD_IF_ERR_RETURN(wr_ln_tx_s_pwrdn(0)); 2541 PHYMOD_IF_ERR_RETURN( 2542 READ_PMD_TRANSMIT_DISABLEr(pa, &tx_disable)); 2543 PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET(tx_disable, 0); 2544 PHYMOD_IF_ERR_RETURN( 2545 WRITE_PMD_TRANSMIT_DISABLEr(pa, tx_disable)); 2546 } 2547 } 2548 if (power->rx != phymodPowerNoChange) { 2549 if (power->rx == phymodPowerOn) { 2550 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc_val(0)); 2551 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc(0)); 2552 } else if (power->rx == phymodPowerOff) { 2553 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc_val(1)); 2554 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc(1)); 2555 } else if (power->rx == phymodPowerOffOn) { 2556 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc_val(1)); 2557 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc(1)); 2558 2559 PHYMOD_USLEEP(500); 2560 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc_val(0)); 2561 PHYMOD_IF_ERR_RETURN(wr_afe_rx_pwrdn_frc(0)); 2562 2563 } 2564 } 2565 2566 return PHYMOD_E_NONE; 2567 } 2568 2569 int _quadra28_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power) 2570 { 2571 int lane_map = 0; 2572 int pkg_side = 0; 2573 int num_lanes = QUADRA28_MAX_LANE; 2574 int lane_index = 0; 2575 SIDE_SELECTIONr_t side_sel_reg_val; 2576 int pmd_mode = 0; 2577 uint32_t speed = 0; 2578 phymod_access_t acc_cpy; 2579 2580 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2581 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2582 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2583 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2584 2585 /* Get the lane map from phymod access */ 2586 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2587 QUADRA28_GET_LOC(phy, pkg_side); 2588 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2589 2590 if (pmd_mode == Q28_SINGLE_PMD) { 2591 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2592 if (((lane_map >> lane_index) & 1) == 0x1) { 2593 PHYMOD_IF_ERR_RETURN(quadra28_channel_select(&acc_cpy, lane_index)); 2594 PHYMOD_IF_ERR_RETURN ( 2595 quadra28_power_get(&acc_cpy, power)); 2596 break; 2597 } 2598 } 2599 } else { 2600 PHYMOD_IF_ERR_RETURN ( 2601 quadra28_power_get(&acc_cpy, power)); 2602 } 2603 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2604 return PHYMOD_E_NONE; 2605 2606 } 2607 static int quadra28_power_get(const phymod_access_t *pa, phymod_phy_power_t* power) 2608 { 2609 uint8_t temp = 0; 2610 uint16_t __err = 0; 2611 temp = rd_ln_tx_s_pwrdn(); 2612 if (temp == 0) { 2613 power->tx = phymodPowerOn; 2614 } else { 2615 power->tx = phymodPowerOff; 2616 } 2617 temp = rd_afe_rx_pwrdn_frc(); 2618 if (temp == 0) { 2619 power->rx = phymodPowerOn; 2620 } else { 2621 power->rx = phymodPowerOff; 2622 } 2623 return __err; 2624 } 2625 2626 int _quadra28_pll_seq_restart(const phymod_access_t *pa, uint32_t flag, phymod_sequencer_operation_t operation) 2627 { 2628 BCMI_QUADRA28_XGXSCONTROLr_t xgs_ctrl; 2629 int pkg_side = 0; 2630 uint32_t acc_flags = 0; 2631 SIDE_SELECTIONr_t side_sel_reg_val; 2632 int pmd_mode = 0; 2633 uint32_t speed = 0; 2634 phymod_access_t acc_cpy; 2635 2636 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2637 PHYMOD_MEMSET(&xgs_ctrl, 0 , sizeof(BCMI_QUADRA28_XGXSCONTROLr_t)); 2638 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 2639 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2640 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2641 2642 /* Get the lane map from phymod access */ 2643 acc_flags = PHYMOD_ACC_FLAGS(&acc_cpy); 2644 QUADRA28_GET_IF_SIDE(acc_flags, pkg_side); 2645 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2646 2647 if (pmd_mode == Q28_SINGLE_PMD) { 2648 PHYMOD_IF_ERR_RETURN( 2649 quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 2650 } 2651 PHYMOD_IF_ERR_RETURN( 2652 BCMI_QUADRA28_READ_XGXSCONTROLr(&acc_cpy, &xgs_ctrl)); 2653 if (operation == phymodSeqOpStop) { 2654 BCMI_QUADRA28_XGXSCONTROLr_START_SEQUENCERf_SET(xgs_ctrl, 0); 2655 PHYMOD_IF_ERR_RETURN( 2656 BCMI_QUADRA28_WRITE_XGXSCONTROLr(&acc_cpy, xgs_ctrl)); 2657 } else if(operation == phymodSeqOpStart) { 2658 BCMI_QUADRA28_XGXSCONTROLr_START_SEQUENCERf_SET(xgs_ctrl, 1); 2659 PHYMOD_IF_ERR_RETURN( 2660 BCMI_QUADRA28_WRITE_XGXSCONTROLr(&acc_cpy, xgs_ctrl)); 2661 } else if (operation == phymodSeqOpRestart) { 2662 BCMI_QUADRA28_XGXSCONTROLr_START_SEQUENCERf_SET(xgs_ctrl, 0); 2663 PHYMOD_IF_ERR_RETURN( 2664 BCMI_QUADRA28_WRITE_XGXSCONTROLr(&acc_cpy, xgs_ctrl)); 2665 PHYMOD_USLEEP(1000); 2666 BCMI_QUADRA28_XGXSCONTROLr_START_SEQUENCERf_SET(xgs_ctrl, 1); 2667 PHYMOD_IF_ERR_RETURN( 2668 BCMI_QUADRA28_WRITE_XGXSCONTROLr(&acc_cpy, xgs_ctrl)); 2669 } else { 2670 return PHYMOD_E_PARAM; 2671 } 2672 2673 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2674 2675 return PHYMOD_E_NONE; 2676 } 2677 2678 int _quadra28_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx) 2679 { 2680 int lane_map = 0; 2681 int pkg_side = 0; 2682 int num_lanes = QUADRA28_MAX_LANE; 2683 int lane_index = 0; 2684 SIDE_SELECTIONr_t side_sel_reg_val; 2685 int pmd_mode = 0; 2686 uint32_t speed = 0; 2687 phymod_access_t acc_cpy; 2688 2689 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2690 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2691 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2692 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2693 2694 /* Get the lane map from phymod access */ 2695 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2696 QUADRA28_GET_LOC(phy, pkg_side); 2697 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2698 2699 if (pmd_mode == Q28_SINGLE_PMD) { 2700 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2701 if (((lane_map >> lane_index) & 1) == 0x1) { 2702 PHYMOD_IF_ERR_RETURN( 2703 quadra28_channel_select(&acc_cpy, 2704 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 2705 PHYMOD_IF_ERR_RETURN( 2706 merlin_quadra28_apply_txfir_cfg(&acc_cpy, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2)); 2707 if (Q28_ALL_LANE == lane_map) { 2708 break; 2709 } 2710 } 2711 } 2712 } else { 2713 PHYMOD_IF_ERR_RETURN( 2714 merlin_quadra28_apply_txfir_cfg(&acc_cpy, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2)); 2715 } 2716 2717 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2718 return PHYMOD_E_NONE; 2719 } 2720 2721 int _quadra28_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx) 2722 { 2723 int lane_map = 0; 2724 int pkg_side = 0; 2725 int num_lanes = QUADRA28_MAX_LANE; 2726 int lane_index = 0; 2727 SIDE_SELECTIONr_t side_sel_reg_val; 2728 int pmd_mode = 0; 2729 uint32_t speed = 0; 2730 int8_t value; 2731 phymod_access_t acc_cpy; 2732 2733 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2734 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2735 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2736 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2737 2738 /* Get the lane map from phymod access */ 2739 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2740 QUADRA28_GET_LOC(phy, pkg_side); 2741 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2742 2743 if (pmd_mode == Q28_SINGLE_PMD) { 2744 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2745 if (((lane_map >> lane_index) & 1) == 0x1) { 2746 PHYMOD_IF_ERR_RETURN( 2747 quadra28_channel_select(&acc_cpy, lane_index)); 2748 break; 2749 } 2750 } 2751 } 2752 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_tx_afe(&acc_cpy, TX_AFE_PRE, &value)); 2753 tx->pre = value; 2754 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_tx_afe(&acc_cpy, TX_AFE_MAIN, &value)); 2755 tx->main = value; 2756 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_tx_afe(&acc_cpy, TX_AFE_POST1, &value)); 2757 tx->post = value; 2758 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_tx_afe(&acc_cpy, TX_AFE_POST2, &value)); 2759 tx->post2 = value; 2760 2761 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2762 return PHYMOD_E_NONE; 2763 } 2764 2765 int _quadra28_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx) 2766 { 2767 int lane_map = 0; 2768 int pkg_side = 0; 2769 int num_lanes = QUADRA28_MAX_LANE; 2770 int lane_index = 0; 2771 SIDE_SELECTIONr_t side_sel_reg_val; 2772 int pmd_mode = 0, idx = 0; 2773 uint32_t speed = 0; 2774 phymod_access_t acc_cpy; 2775 2776 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2777 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2778 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2779 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2780 2781 /* Get the lane map from phymod access */ 2782 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2783 QUADRA28_GET_LOC(phy, pkg_side); 2784 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2785 2786 if (pmd_mode == Q28_SINGLE_PMD) { 2787 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2788 if (((lane_map >> lane_index) & 1) == 0x1) { 2789 PHYMOD_IF_ERR_RETURN( 2790 quadra28_channel_select(&acc_cpy, 2791 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 2792 if (rx->vga.enable) { 2793 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2794 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_VGA, rx->vga.value)); 2795 } 2796 2797 for (idx = 0 ; idx < rx->num_of_dfe_taps ; idx++) { 2798 if (rx->dfe[idx].enable) { 2799 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2800 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_DFE1 + idx, 2801 rx->dfe[idx].value)); 2802 } 2803 } 2804 if (rx->peaking_filter.enable) { 2805 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2806 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_PF, rx->peaking_filter.value)); 2807 } 2808 if (rx->low_freq_peaking_filter.enable) { 2809 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2810 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_PF2, rx->low_freq_peaking_filter.value)); 2811 } 2812 2813 if (Q28_ALL_LANE == lane_map) { 2814 break; 2815 } 2816 } 2817 } 2818 } else { 2819 if (rx->vga.enable) { 2820 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2821 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_VGA, rx->vga.value)); 2822 } 2823 2824 for (idx = 0 ; idx < rx->num_of_dfe_taps ; idx++) { 2825 if (rx->dfe[idx].enable) { 2826 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2827 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_DFE1 + idx, 2828 rx->dfe[idx].value)); 2829 } 2830 } 2831 if (rx->peaking_filter.enable) { 2832 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2833 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_PF, rx->peaking_filter.value)); 2834 } 2835 if (rx->low_freq_peaking_filter.enable) { 2836 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 1)); 2837 PHYMOD_IF_ERR_RETURN(merlin_quadra28_write_rx_afe(&acc_cpy, RX_AFE_PF2, rx->low_freq_peaking_filter.value)); 2838 } 2839 } 2840 2841 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2842 return PHYMOD_E_NONE; 2843 } 2844 2845 int _quadra28_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx) 2846 { 2847 int lane_map = 0; 2848 int pkg_side = 0; 2849 int num_lanes = QUADRA28_MAX_LANE; 2850 int lane_index = 0; 2851 SIDE_SELECTIONr_t side_sel_reg_val; 2852 int pmd_mode = 0, idx = 0; 2853 uint32_t speed = 0; 2854 int8_t data = 0; 2855 phymod_access_t acc_cpy; 2856 2857 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 2858 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 2859 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2860 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2861 if (rx) { 2862 PHYMOD_MEMSET(rx, 0 , sizeof(phymod_rx_t)); 2863 }else{ 2864 return PHYMOD_E_MEMORY; 2865 } 2866 2867 /* Get the lane map from phymod access */ 2868 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 2869 QUADRA28_GET_LOC(phy, pkg_side); 2870 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 2871 2872 if (pmd_mode == Q28_SINGLE_PMD) { 2873 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 2874 if (((lane_map >> lane_index) & 1) == 0x1) { 2875 PHYMOD_IF_ERR_RETURN( 2876 quadra28_channel_select(&acc_cpy, lane_index)); 2877 break; 2878 } 2879 } 2880 } 2881 2882 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_rx_afe(&acc_cpy, RX_AFE_VGA, &data)); 2883 rx->vga.value = data; 2884 2885 for (idx = 0; idx < 5 ; idx++) { 2886 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_rx_afe(&acc_cpy, RX_AFE_DFE1 + idx, &data)); 2887 rx->dfe[idx].value = data; 2888 rx->dfe[idx].enable = 1 ; 2889 } 2890 rx->num_of_dfe_taps = 5; 2891 2892 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_rx_afe(&acc_cpy, RX_AFE_PF, &data)); 2893 rx->peaking_filter.value = data; 2894 PHYMOD_IF_ERR_RETURN(merlin_quadra28_read_rx_afe(&acc_cpy, RX_AFE_PF2, &data)); 2895 rx->low_freq_peaking_filter.value = data; 2896 2897 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 2898 return PHYMOD_E_NONE; 2899 } 2900 2901 int _quadra28_phy_autoneg_ability_set(const phymod_access_t* pa, q28_an_ability_t an_ability) 2902 { 2903 BCMI_QUADRA28_AN_ADVERTISEMENT_1r_t pause_adv; 2904 BCMI_QUADRA28_AN_ADVERTISEMENT_3r_t fec_adv; 2905 uint32_t speed = 0; 2906 phymod_access_t acc_cpy; 2907 int pmd_mode = 0; 2908 2909 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 2910 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2911 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2912 Q28_UNUSED_PARAM(pmd_mode); 2913 PHYMOD_MEMSET(&pause_adv, 0, sizeof(BCMI_QUADRA28_AN_ADVERTISEMENT_1r_t)); 2914 PHYMOD_MEMSET(&fec_adv, 0, sizeof(BCMI_QUADRA28_AN_ADVERTISEMENT_3r_t)); 2915 2916 PHYMOD_IF_ERR_RETURN( 2917 BCMI_QUADRA28_READ_AN_ADVERTISEMENT_1r(&acc_cpy, &pause_adv)); 2918 PHYMOD_IF_ERR_RETURN( 2919 BCMI_QUADRA28_READ_AN_ADVERTISEMENT_3r(&acc_cpy, &fec_adv)); 2920 2921 BCMI_QUADRA28_AN_ADVERTISEMENT_1r_PAUSEf_SET(pause_adv, an_ability.pause_ability); 2922 BCMI_QUADRA28_AN_ADVERTISEMENT_3r_FEC_REQUESTEDf_SET(fec_adv, an_ability.fec_ability); 2923 2924 PHYMOD_IF_ERR_RETURN( 2925 BCMI_QUADRA28_WRITE_AN_ADVERTISEMENT_1r(&acc_cpy, pause_adv)); 2926 PHYMOD_IF_ERR_RETURN( 2927 BCMI_QUADRA28_WRITE_AN_ADVERTISEMENT_3r(&acc_cpy, fec_adv)); 2928 2929 return PHYMOD_E_NONE; 2930 } 2931 2932 int _quadra28_phy_autoneg_ability_get(const phymod_access_t* pa, phymod_autoneg_ability_t* an_ability) 2933 { 2934 uint16_t ability; 2935 BCMI_QUADRA28_AN_ADVERTISEMENT_1r_t pause_ability; 2936 BCMI_QUADRA28_AN_ADVERTISEMENT_2r_t tech_ability; 2937 BCMI_QUADRA28_AN_ADVERTISEMENT_3r_t fec_ability; 2938 uint32_t speed = 0; 2939 phymod_access_t acc_cpy; 2940 int pmd_mode = 0; 2941 2942 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 2943 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 2944 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 2945 Q28_UNUSED_PARAM(pmd_mode); 2946 2947 PHYMOD_MEMSET(&pause_ability, 0, sizeof(BCMI_QUADRA28_AN_ADVERTISEMENT_1r_t)); 2948 PHYMOD_MEMSET(&tech_ability, 0, sizeof(BCMI_QUADRA28_AN_ADVERTISEMENT_2r_t)); 2949 PHYMOD_MEMSET(&fec_ability, 0, sizeof(BCMI_QUADRA28_AN_ADVERTISEMENT_3r_t)); 2950 2951 PHYMOD_IF_ERR_RETURN( 2952 BCMI_QUADRA28_READ_AN_ADVERTISEMENT_1r(&acc_cpy, &pause_ability)); 2953 PHYMOD_IF_ERR_RETURN( 2954 BCMI_QUADRA28_READ_AN_ADVERTISEMENT_2r(&acc_cpy, &tech_ability)); 2955 PHYMOD_IF_ERR_RETURN( 2956 BCMI_QUADRA28_READ_AN_ADVERTISEMENT_3r(&acc_cpy, &fec_ability)); 2957 2958 ability = BCMI_QUADRA28_AN_ADVERTISEMENT_1r_PAUSEf_GET(pause_ability); 2959 if (ability == Q28_SYMM_PAUSE) { 2960 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability); 2961 } else if(ability == Q28_ASYM_PAUSE) { 2962 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability); 2963 } else { 2964 PHYMOD_AN_CAP_SYMM_PAUSE_CLR(an_ability); 2965 PHYMOD_AN_CAP_ASYM_PAUSE_CLR(an_ability); 2966 } 2967 ability = BCMI_QUADRA28_AN_ADVERTISEMENT_2r_TECHABILITYf_GET(tech_ability); 2968 /*first check cl73 ability*/ 2969 switch (ability) { 2970 case Q28_CL73_100GBASE_CR10: 2971 PHYMOD_AN_CAP_100G_CR10_SET(an_ability->an_cap); 2972 break; 2973 case Q28_CL73_40GBASE_CR4: 2974 PHYMOD_AN_CAP_40G_CR4_SET(an_ability->an_cap); 2975 break; 2976 case Q28_CL73_40GBASE_KR4: 2977 PHYMOD_AN_CAP_40G_KR4_SET(an_ability->an_cap); 2978 break; 2979 case Q28_CL73_10GBASE_KR: 2980 PHYMOD_AN_CAP_10G_KR_SET(an_ability->an_cap); 2981 break; 2982 case Q28_CL73_1000BASE_KX: 2983 PHYMOD_AN_CAP_1G_KX_SET(an_ability->an_cap); 2984 break; 2985 case Q28_CL73_100GBASE_CR4: 2986 PHYMOD_AN_CAP_100G_CR4_SET(an_ability->an_cap); 2987 break; 2988 case Q28_CL73_100GBASE_KR4: 2989 PHYMOD_AN_CAP_100G_KR4_SET(an_ability->an_cap); 2990 break; 2991 default: 2992 break; 2993 } 2994 an_ability->an_fec = BCMI_QUADRA28_AN_ADVERTISEMENT_3r_FEC_REQUESTEDf_GET(fec_ability); 2995 2996 return PHYMOD_E_NONE; 2997 } 2998 2999 int _quadra28_phy_autoneg_get(const phymod_access_t* pa, phymod_autoneg_control_t* an, uint32_t* an_done) 3000 { 3001 BCMI_QUADRA28_AN_STATUSr_t an_status; 3002 BCMI_QUADRA28_AN_CONTROLr_t an_control; 3003 uint32_t speed = 0; 3004 phymod_access_t acc_cpy; 3005 phymod_interface_t intf; 3006 phymod_ref_clk_t ref_clk; 3007 uint32_t intf_modes = 0, an_enable = 0, an_cl37_sts = 0; 3008 3009 PHYMOD_MEMSET(&an_status, 0, sizeof(BCMI_QUADRA28_AN_STATUSr_t)); 3010 PHYMOD_MEMSET(&an_control, 0, sizeof(BCMI_QUADRA28_AN_CONTROLr)); 3011 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 3012 PHYMOD_IF_ERR_RETURN ( 3013 quadra28_get_config_mode(&acc_cpy, &intf, &speed, &ref_clk, &intf_modes)); 3014 Q28_UNUSED_PARAM(ref_clk); 3015 Q28_UNUSED_PARAM(intf_modes); 3016 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3017 3018 if ((speed == 1000) && (intf == phymodInterfaceSR)) { 3019 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_read(&acc_cpy, 0x7ffe0, &an_enable)); 3020 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_read(&acc_cpy, 0x7ffe1, &an_cl37_sts)); 3021 if (an_enable & (1 << 12)) { 3022 an->enable = 1; 3023 an->an_mode = phymod_AN_MODE_CL37; 3024 } else { 3025 an->enable = 0; 3026 } 3027 if (an_cl37_sts & (1 << 5)) { 3028 *an_done = 1; 3029 } else { 3030 *an_done = 0; 3031 } 3032 } else { 3033 PHYMOD_IF_ERR_RETURN( 3034 BCMI_QUADRA28_READ_AN_STATUSr(&acc_cpy, &an_status)); 3035 PHYMOD_IF_ERR_RETURN( 3036 BCMI_QUADRA28_READ_AN_CONTROLr(&acc_cpy, &an_control)); 3037 an->an_mode = phymod_AN_MODE_CL73; 3038 *an_done = BCMI_QUADRA28_AN_STATUSr_AUTO_NEGOTIATIONCOMPLETEf_GET(an_status); 3039 an->enable = BCMI_QUADRA28_AN_CONTROLr_AUTO_NEGOTIATIONENABLEf_GET(an_control); 3040 } 3041 3042 3043 3044 return PHYMOD_E_NONE; 3045 } 3046 3047 int _quadra28_phy_autoneg_set(const phymod_access_t* pa, const phymod_autoneg_control_t* an) 3048 { 3049 BCMI_QUADRA28_AN_CONTROLr_t an_control; 3050 uint32_t speed = 0; 3051 phymod_access_t acc_cpy; 3052 BCMI_QUADRA28_APPS_MODE_0r_t apps_mode0; 3053 BCMI_QUADRA28_GENERAL_PURPOSE_3r_t gp_reg3_reg_val; 3054 BCMI_QUADRA28_APPS_MODE_1r_t apps_mode1; 3055 BCMI_QUADRA28_PMD_TRANSMIT_DISABLEr_t tx_dis; 3056 unsigned int an_enable = 0, retry_cnt=20; 3057 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 3058 BCMI_QUADRA28_MERLIN_MISC_CTRLr_t reset_ack; 3059 BCMI_QUADRA28_XGXSSTATUSr_t xgs_sts; 3060 phymod_interface_t intf; 3061 phymod_ref_clk_t ref_clk; 3062 uint32_t intf_modes = 0; 3063 3064 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 3065 PHYMOD_MEMSET(&apps_mode0, 0, sizeof(apps_mode0)); 3066 PHYMOD_MEMSET(&apps_mode1, 0, sizeof(apps_mode1)); 3067 PHYMOD_MEMSET(&tx_dis, 0, sizeof(tx_dis)); 3068 PHYMOD_MEMSET(&gp_reg3_reg_val, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_3r_t)); 3069 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 3070 3071 PHYMOD_IF_ERR_RETURN ( 3072 quadra28_get_config_mode(&acc_cpy, &intf, &speed, &ref_clk, &intf_modes)); 3073 Q28_UNUSED_PARAM(ref_clk); 3074 Q28_UNUSED_PARAM(intf_modes); 3075 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3076 3077 PHYMOD_MEMSET(&an_control, 0, sizeof(BCMI_QUADRA28_AN_CONTROLr)); 3078 if (an->an_mode == phymod_AN_MODE_CL37 || 3079 ((speed == 1000) && (intf == phymodInterfaceSR))) { 3080 PHYMOD_IF_ERR_RETURN( 3081 BCMI_QUADRA28_READ_APPS_MODE_1r (&acc_cpy, &apps_mode1)); 3082 if (!BCMI_QUADRA28_APPS_MODE_1r_RETIMER_MODEf_GET(apps_mode1)) { 3083 /*CL37 will be set only if the chip is confiured as re-timer 3084 * Not enabling if re-time mode is not set*/ 3085 /* Fix for PHY-2821*/ 3086 return PHYMOD_E_NONE; 3087 } 3088 /* Configure 1G(1.25G)-retime */ 3089 PHYMOD_IF_ERR_RETURN( 3090 BCMI_QUADRA28_READ_GENERAL_PURPOSE_3r(&acc_cpy, &gp_reg3_reg_val)); 3091 apps_mode0.v[0] = gp_reg3_reg_val.v[0]; 3092 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0, 0); 3093 PHYMOD_IF_ERR_RETURN( 3094 BCMI_QUADRA28_WRITE_APPS_MODE_0r(&acc_cpy, apps_mode0)); 3095 3096 PHYMOD_IF_ERR_RETURN(_quadra28_intf_update_wait_check(&acc_cpy, 3097 apps_mode0.v[0], 50000)); 3098 /*PHYMOD_IF_ERR_RETURN( 3099 BCMI_QUADRA28_READ_APPS_MODE_1r (&acc_cpy, &apps_mode1)); 3100 BCMI_QUADRA28_APPS_MODE_1r_RETIMER_MODEf_SET(apps_mode1,1); 3101 PHYMOD_IF_ERR_RETURN( 3102 BCMI_QUADRA28_WRITE_APPS_MODE_1r (&acc_cpy, apps_mode1));*/ 3103 if (an->enable) { 3104 BCMI_QUADRA28_APPS_MODE_0r_SET(apps_mode0, 0x81); 3105 } else { 3106 BCMI_QUADRA28_APPS_MODE_0r_SET(apps_mode0, 0x83); 3107 } 3108 PHYMOD_IF_ERR_RETURN( 3109 BCMI_QUADRA28_WRITE_APPS_MODE_0r (&acc_cpy, apps_mode0)); 3110 3111 PHYMOD_IF_ERR_RETURN(_quadra28_intf_update_wait_check(&acc_cpy, 3112 apps_mode0.v[0], 50000)); 3113 if (an->enable) { 3114 BCMI_QUADRA28_APPS_MODE_0r_SET(apps_mode0, 0x1); 3115 } else { 3116 BCMI_QUADRA28_APPS_MODE_0r_SET(apps_mode0, 0x3); 3117 } 3118 PHYMOD_IF_ERR_RETURN( 3119 BCMI_QUADRA28_WRITE_APPS_MODE_0r (&acc_cpy, apps_mode0)); 3120 3121 PHYMOD_IF_ERR_RETURN(_quadra28_intf_update_wait_check(&acc_cpy, 3122 apps_mode0.v[0], 50000)); 3123 3124 /* Perform softreset and wait for reset to clear*/ 3125 PHYMOD_IF_ERR_RETURN( 3126 BCMI_QUADRA28_READ_PMD_CONTROLr(&acc_cpy, &pmd_ctrl)); 3127 BCMI_QUADRA28_PMD_CONTROLr_RESETf_SET(pmd_ctrl, 1); 3128 PHYMOD_IF_ERR_RETURN( 3129 BCMI_QUADRA28_WRITE_PMD_CONTROLr(&acc_cpy, pmd_ctrl)); 3130 do { 3131 PHYMOD_IF_ERR_RETURN( 3132 BCMI_QUADRA28_READ_MERLIN_MISC_CTRLr(&acc_cpy, &reset_ack)); 3133 PHYMOD_USLEEP(1000); 3134 retry_cnt --; 3135 } while (((reset_ack.v[0] & 0x8000) != 0x8000) && retry_cnt); 3136 if (retry_cnt <= 0) { 3137 return PHYMOD_E_TIMEOUT; 3138 } 3139 retry_cnt = 20; 3140 do { 3141 PHYMOD_IF_ERR_RETURN( 3142 BCMI_QUADRA28_READ_XGXSSTATUSr(&acc_cpy, &xgs_sts)); 3143 PHYMOD_USLEEP(800); 3144 retry_cnt --; 3145 } while (((xgs_sts.v[0] & 0x800) != 0x800) && retry_cnt); 3146 if (retry_cnt <= 0) { 3147 return PHYMOD_E_TIMEOUT; 3148 } 3149 /* Enable AN by disabling tx*/ 3150 PHYMOD_IF_ERR_RETURN( 3151 BCMI_QUADRA28_READ_PMD_TRANSMIT_DISABLEr(&acc_cpy, &tx_dis)); 3152 BCMI_QUADRA28_PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET(tx_dis,1); 3153 PHYMOD_IF_ERR_RETURN( 3154 BCMI_QUADRA28_WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_dis)); 3155 3156 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_read(&acc_cpy, 0x7ffe0, &an_enable)); 3157 if (an->enable == 1) { 3158 an_enable |= 1 << 12; 3159 } else { 3160 an_enable &= ~(1 << 12); 3161 } 3162 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(&acc_cpy, 0x7ffe0, an_enable)); 3163 BCMI_QUADRA28_PMD_TRANSMIT_DISABLEr_GLOBAL_PMDTRANSMIT_DISABLEf_SET(tx_dis,0); 3164 PHYMOD_IF_ERR_RETURN( 3165 BCMI_QUADRA28_WRITE_PMD_TRANSMIT_DISABLEr(&acc_cpy, tx_dis)); 3166 } else { 3167 PHYMOD_IF_ERR_RETURN( 3168 BCMI_QUADRA28_READ_AN_CONTROLr(&acc_cpy, &an_control)); 3169 3170 BCMI_QUADRA28_AN_CONTROLr_AUTO_NEGOTIATIONENABLEf_SET(an_control, an->enable); 3171 PHYMOD_IF_ERR_RETURN( 3172 BCMI_QUADRA28_WRITE_AN_CONTROLr(&acc_cpy, an_control)); 3173 } 3174 3175 return PHYMOD_E_NONE; 3176 } 3177 3178 int _quadra28_phy_autoneg_remote_ability_get(const phymod_access_t* pa, phymod_autoneg_ability_t* an_ability) 3179 { 3180 BCMI_QUADRA28_AN_LP_BASE_PAGE_ABILITY_1r_t lp_pause_ability; 3181 BCMI_QUADRA28_AN_LP_BASE_PAGE_ABILITY_2r_t lp_tech_ability; 3182 BCMI_QUADRA28_AN_LP_BASE_PAGE_ABILITY_3r_t lp_fec_ability; 3183 uint16_t ability; 3184 uint32_t speed = 0; 3185 phymod_access_t acc_cpy; 3186 int pmd_mode = 0; 3187 3188 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 3189 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3190 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3191 Q28_UNUSED_PARAM(pmd_mode); 3192 3193 PHYMOD_MEMSET(&lp_pause_ability, 0, sizeof(BCMI_QUADRA28_AN_LP_BASE_PAGE_ABILITY_1r_t)); 3194 PHYMOD_MEMSET(&lp_tech_ability, 0, sizeof(BCMI_QUADRA28_AN_LP_BASE_PAGE_ABILITY_2r_t)); 3195 PHYMOD_MEMSET(&lp_fec_ability, 0, sizeof(BCMI_QUADRA28_AN_LP_BASE_PAGE_ABILITY_3r_t)); 3196 3197 PHYMOD_IF_ERR_RETURN( 3198 BCMI_QUADRA28_READ_AN_LP_BASE_PAGE_ABILITY_1r(&acc_cpy, &lp_pause_ability)); 3199 PHYMOD_IF_ERR_RETURN( 3200 BCMI_QUADRA28_READ_AN_LP_BASE_PAGE_ABILITY_2r(&acc_cpy, &lp_tech_ability)); 3201 PHYMOD_IF_ERR_RETURN( 3202 BCMI_QUADRA28_READ_AN_LP_BASE_PAGE_ABILITY_3r(&acc_cpy, &lp_fec_ability)); 3203 3204 ability = (lp_pause_ability.v[0] >> 10) & 0x7; 3205 if (ability == Q28_SYMM_PAUSE) { 3206 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability); 3207 } else if(ability == Q28_ASYM_PAUSE) { 3208 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability); 3209 } else { 3210 PHYMOD_AN_CAP_SYMM_PAUSE_CLR(an_ability); 3211 PHYMOD_AN_CAP_ASYM_PAUSE_CLR(an_ability); 3212 } 3213 ability = (lp_tech_ability.v[0] >> 5) & 0x7ff; 3214 /*first check cl73 ability*/ 3215 switch (ability) { 3216 case Q28_CL73_100GBASE_CR10: 3217 PHYMOD_AN_CAP_100G_CR10_SET(an_ability->an_cap); 3218 break; 3219 case Q28_CL73_40GBASE_CR4: 3220 PHYMOD_AN_CAP_40G_CR4_SET(an_ability->an_cap); 3221 break; 3222 case Q28_CL73_40GBASE_KR4: 3223 PHYMOD_AN_CAP_40G_KR4_SET(an_ability->an_cap); 3224 break; 3225 case Q28_CL73_10GBASE_KR: 3226 PHYMOD_AN_CAP_10G_KR_SET(an_ability->an_cap); 3227 break; 3228 case Q28_CL73_1000BASE_KX: 3229 PHYMOD_AN_CAP_1G_KX_SET(an_ability->an_cap); 3230 break; 3231 case Q28_CL73_100GBASE_CR4: 3232 PHYMOD_AN_CAP_100G_CR4_SET(an_ability->an_cap); 3233 break; 3234 case Q28_CL73_100GBASE_KR4: 3235 PHYMOD_AN_CAP_100G_KR4_SET(an_ability->an_cap); 3236 break; 3237 default: 3238 break; 3239 } 3240 an_ability->an_fec = (lp_fec_ability.v[0] >> 14) & 0x3 ; 3241 3242 return PHYMOD_E_NONE; 3243 } 3244 3245 int _quadra28_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en) 3246 { 3247 int pkg_side = 0; 3248 int pmd_mode = 0; 3249 uint32_t speed = 0; 3250 phymod_access_t acc_cpy; 3251 BCMI_QUADRA28_APPS_MODE_0r_t apps_mode0_reg_val; 3252 3253 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 3254 PHYMOD_MEMSET(&apps_mode0_reg_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_0r_t)); 3255 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3256 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3257 3258 /* Get the lane map from phymod access */ 3259 QUADRA28_GET_LOC(phy, pkg_side); 3260 PHYMOD_IF_ERR_RETURN( 3261 BCMI_QUADRA28_READ_APPS_MODE_0r(&acc_cpy, &apps_mode0_reg_val)); 3262 if (pkg_side == Q28_INTF_LINE) { 3263 BCMI_QUADRA28_APPS_MODE_0r_LINE_FORCE_CL72f_SET(apps_mode0_reg_val, (cl72_en ? 1 :0)); 3264 } else { 3265 BCMI_QUADRA28_APPS_MODE_0r_SYSTEM_FORCE_CL72f_SET(apps_mode0_reg_val, (cl72_en ? 1 :0)); 3266 } 3267 if (pmd_mode == Q28_SINGLE_PMD) { 3268 PHYMOD_IF_ERR_RETURN (quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 3269 } 3270 PHYMOD_IF_ERR_RETURN( 3271 BCMI_QUADRA28_WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 3272 3273 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 1); 3274 3275 PHYMOD_IF_ERR_RETURN( 3276 BCMI_QUADRA28_WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 3277 3278 PHYMOD_IF_ERR_RETURN( 3279 _quadra28_intf_update_wait_check(&acc_cpy,apps_mode0_reg_val.v[0], 50000)); 3280 3281 PHYMOD_USLEEP(500); 3282 3283 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 0); 3284 3285 PHYMOD_IF_ERR_RETURN( 3286 BCMI_QUADRA28_WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 3287 3288 PHYMOD_IF_ERR_RETURN( 3289 _quadra28_intf_update_wait_check(&acc_cpy,apps_mode0_reg_val.v[0], 50000)); 3290 3291 return PHYMOD_E_NONE; 3292 } 3293 3294 int _quadra28_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en) 3295 { 3296 int pkg_side = 0; 3297 int pmd_mode = 0; 3298 uint32_t speed = 0; 3299 phymod_access_t acc_cpy; 3300 BCMI_QUADRA28_APPS_MODE_0r_t mode_sts_val; 3301 3302 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 3303 PHYMOD_MEMSET(&mode_sts_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_0r_t)); 3304 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3305 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3306 Q28_UNUSED_PARAM(pmd_mode); 3307 /* Get the lane map from phymod access */ 3308 QUADRA28_GET_LOC(phy, pkg_side); 3309 3310 PHYMOD_IF_ERR_RETURN( 3311 BCMI_QUADRA28_READ_APPS_MODE_0r(&acc_cpy, &mode_sts_val)); 3312 if (pkg_side == Q28_INTF_LINE) { 3313 *cl72_en = BCMI_QUADRA28_APPS_MODE_0r_LINE_FORCE_CL72f_GET(mode_sts_val); 3314 } else { 3315 *cl72_en = BCMI_QUADRA28_APPS_MODE_0r_SYSTEM_FORCE_CL72f_GET(mode_sts_val); 3316 } 3317 3318 return PHYMOD_E_NONE; 3319 } 3320 3321 int _quadra28_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status) 3322 { 3323 int lane_map = 0; 3324 int pkg_side = 0; 3325 SIDE_SELECTIONr_t side_sel_reg_val; 3326 int pmd_mode = 0; 3327 uint32_t speed = 0; 3328 uint32_t cl72_status = 0xFFFF; 3329 phymod_access_t acc_cpy; 3330 BCMI_QUADRA28_BASE_R_PMD_STATUS_151r_t cl72_sts; 3331 3332 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 3333 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 3334 PHYMOD_MEMSET(&cl72_sts, 0, sizeof(BCMI_QUADRA28_BASE_R_PMD_STATUS_151r_t)); 3335 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3336 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3337 3338 /* Get the lane map from phymod access */ 3339 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 3340 QUADRA28_GET_LOC(phy, pkg_side); 3341 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 3342 3343 PHYMOD_IF_ERR_RETURN ( 3344 BCMI_QUADRA28_READ_BASE_R_PMD_STATUS_151r(&acc_cpy, &cl72_sts)); 3345 3346 if (pmd_mode == Q28_SINGLE_PMD) { 3347 if (lane_map & 1) { 3348 cl72_status &= BCMI_QUADRA28_BASE_R_PMD_STATUS_151r_RECEIVER_STATUS_0f_GET(cl72_sts); 3349 } 3350 if (lane_map & 2) { 3351 cl72_status &= BCMI_QUADRA28_BASE_R_PMD_STATUS_151r_RECEIVER_STATUS_1f_GET(cl72_sts); 3352 } 3353 if (lane_map & 4) { 3354 cl72_status &= BCMI_QUADRA28_BASE_R_PMD_STATUS_151r_RECEIVER_STATUS_2f_GET(cl72_sts); 3355 } 3356 if (lane_map & 8) { 3357 cl72_status &= BCMI_QUADRA28_BASE_R_PMD_STATUS_151r_RECEIVER_STATUS_3f_GET(cl72_sts); 3358 } 3359 3360 } else { 3361 cl72_status &= BCMI_QUADRA28_BASE_R_PMD_STATUS_151r_RECEIVER_STATUS_0f_GET(cl72_sts); 3362 } 3363 status->locked = cl72_status; 3364 PHYMOD_IF_ERR_RETURN ( 3365 _quadra28_phy_cl72_get(phy, &status->enabled)); 3366 3367 3368 return PHYMOD_E_NONE; 3369 } 3370 3371 int _quadra28_finish_mask_seq(const phymod_access_t *pa) 3372 { 3373 int retry_cnt = 20; 3374 3375 BCMI_QUADRA28_APPS_MODE_0r_t apps_mode0_reg_val; 3376 PHYMOD_MEMSET(&apps_mode0_reg_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_0r_t)); 3377 3378 PHYMOD_IF_ERR_RETURN ( 3379 BCMI_QUADRA28_READ_APPS_MODE_0r(pa, &apps_mode0_reg_val)); 3380 3381 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 1); 3382 3383 PHYMOD_IF_ERR_RETURN( 3384 BCMI_QUADRA28_WRITE_APPS_MODE_0r(pa,apps_mode0_reg_val)); 3385 3386 PHYMOD_IF_ERR_RETURN( 3387 _quadra28_intf_update_wait_check(pa,apps_mode0_reg_val.v[0], 50000)); 3388 { 3389 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 3390 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 3391 3392 PHYMOD_IF_ERR_RETURN( 3393 BCMI_QUADRA28_READ_PMD_CONTROLr(pa, &pmd_ctrl)); 3394 BCMI_QUADRA28_PMD_CONTROLr_RESETf_SET(pmd_ctrl, 1); 3395 PHYMOD_IF_ERR_RETURN( 3396 BCMI_QUADRA28_WRITE_PMD_CONTROLr(pa, pmd_ctrl)); 3397 } 3398 { 3399 BCMI_QUADRA28_MERLIN_MISC_CTRLr_t reset_ack; 3400 BCMI_QUADRA28_XGXSSTATUSr_t xgs_sts; 3401 do { 3402 PHYMOD_IF_ERR_RETURN( 3403 BCMI_QUADRA28_READ_MERLIN_MISC_CTRLr(pa, &reset_ack)); 3404 PHYMOD_USLEEP(1000); 3405 retry_cnt --; 3406 } while (((reset_ack.v[0] & 0x8000) != 0x8000) && retry_cnt); 3407 if (retry_cnt <= 0) { 3408 return PHYMOD_E_TIMEOUT; 3409 } 3410 retry_cnt = 20; 3411 do { 3412 PHYMOD_IF_ERR_RETURN( 3413 BCMI_QUADRA28_READ_XGXSSTATUSr(pa, &xgs_sts)); 3414 PHYMOD_USLEEP(800); 3415 retry_cnt --; 3416 } while (((xgs_sts.v[0] & 0x800) != 0x800) && retry_cnt); 3417 if (retry_cnt <= 0) { 3418 return PHYMOD_E_TIMEOUT; 3419 } 3420 } 3421 3422 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 0); 3423 3424 PHYMOD_IF_ERR_RETURN( 3425 BCMI_QUADRA28_WRITE_APPS_MODE_0r(pa, apps_mode0_reg_val)); 3426 3427 PHYMOD_IF_ERR_RETURN( 3428 _quadra28_intf_update_wait_check(pa, apps_mode0_reg_val.v[0], 50000)); 3429 3430 return PHYMOD_E_NONE; 3431 3432 } 3433 3434 int _quadra28_phy_retimer_enable(const phymod_access_t *pa, uint32_t enable) 3435 { 3436 int pmd_mode = 0; 3437 uint32_t speed = 0; 3438 phymod_access_t acc_cpy; 3439 BCMI_QUADRA28_APPS_MODE_1r_t apps_mode1_reg; 3440 SIDE_SELECTIONr_t side_sel_reg_val; 3441 3442 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 3443 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 3444 PHYMOD_MEMSET(&apps_mode1_reg, 0, sizeof(BCMI_QUADRA28_APPS_MODE_1r_t)); 3445 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3446 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3447 3448 if (pmd_mode == Q28_SINGLE_PMD) { 3449 if (enable) { 3450 PHYMOD_DIAG_OUT(("Retimer not supported in 40G/42G. So enabling repeater\n")); 3451 return PHYMOD_E_NONE; 3452 } 3453 PHYMOD_IF_ERR_RETURN ( 3454 quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 3455 } 3456 PHYMOD_IF_ERR_RETURN ( 3457 BCMI_QUADRA28_READ_APPS_MODE_1r(&acc_cpy, &apps_mode1_reg)); 3458 3459 BCMI_QUADRA28_APPS_MODE_1r_RETIMER_MODEf_SET(apps_mode1_reg, enable); 3460 3461 PHYMOD_IF_ERR_RETURN ( 3462 BCMI_QUADRA28_WRITE_APPS_MODE_1r(&acc_cpy, apps_mode1_reg)); 3463 3464 PHYMOD_IF_ERR_RETURN ( 3465 _quadra28_finish_mask_seq(&acc_cpy)); 3466 3467 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 3468 return PHYMOD_E_NONE; 3469 } 3470 3471 int _quadra28_phy_retimer_enable_get(const phymod_access_t *pa, uint32_t *enable) 3472 { 3473 int pmd_mode = 0; 3474 uint32_t speed = 0; 3475 phymod_access_t acc_cpy; 3476 BCMI_QUADRA28_APPS_MODE_1r_t apps_mode1_reg; 3477 3478 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 3479 PHYMOD_MEMSET(&apps_mode1_reg, 0, sizeof(BCMI_QUADRA28_APPS_MODE_1r_t)); 3480 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3481 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3482 Q28_UNUSED_PARAM(pmd_mode); 3483 3484 PHYMOD_IF_ERR_RETURN ( 3485 BCMI_QUADRA28_READ_APPS_MODE_1r(&acc_cpy, &apps_mode1_reg)); 3486 3487 *enable = BCMI_QUADRA28_APPS_MODE_1r_RETIMER_MODEf_GET(apps_mode1_reg); 3488 3489 return PHYMOD_E_NONE; 3490 } 3491 3492 int _quadra28_phy_fec_enable_set(const phymod_phy_access_t* phy, uint32_t enable) 3493 { 3494 int pkg_side = 0; 3495 int pmd_mode = 0; 3496 uint32_t speed = 0; 3497 phymod_access_t acc_cpy; 3498 BCMI_QUADRA28_APPS_MODE_1r_t apps_mode1_reg_val; 3499 3500 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 3501 PHYMOD_MEMSET(&apps_mode1_reg_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_1r_t)); 3502 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3503 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3504 3505 /* Get the lane map from phymod access */ 3506 QUADRA28_GET_LOC(phy, pkg_side); 3507 PHYMOD_IF_ERR_RETURN( 3508 BCMI_QUADRA28_READ_APPS_MODE_1r(&acc_cpy, &apps_mode1_reg_val)); 3509 if (pkg_side == Q28_INTF_LINE) { 3510 apps_mode1_reg_val.v[0] &= 0xCFFF; 3511 apps_mode1_reg_val.v[0] |= (enable ? (0x3 << 12) : 0); 3512 } else { 3513 apps_mode1_reg_val.v[0] &= 0x3FFF; 3514 apps_mode1_reg_val.v[0] |= (enable ? (0xC << 12) : 0); 3515 } 3516 if (pmd_mode == Q28_SINGLE_PMD) { 3517 PHYMOD_IF_ERR_RETURN (quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 3518 } 3519 3520 PHYMOD_IF_ERR_RETURN( 3521 BCMI_QUADRA28_WRITE_APPS_MODE_1r(&acc_cpy,apps_mode1_reg_val)); 3522 3523 PHYMOD_IF_ERR_RETURN ( 3524 _quadra28_finish_mask_seq(&acc_cpy)); 3525 3526 return PHYMOD_E_NONE; 3527 } 3528 3529 int _quadra28_phy_fec_enable_get(const phymod_phy_access_t* phy, uint32_t* enable) 3530 { 3531 int pkg_side = 0; 3532 int pmd_mode = 0; 3533 uint32_t speed = 0; 3534 phymod_access_t acc_cpy; 3535 BCMI_QUADRA28_APPS_MODE_1r_t apps_mode1_reg_val; 3536 3537 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 3538 PHYMOD_MEMSET(&apps_mode1_reg_val, 0, sizeof(BCMI_QUADRA28_APPS_MODE_1r_t)); 3539 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3540 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3541 Q28_UNUSED_PARAM(pmd_mode); 3542 3543 /* Get the lane map from phymod access */ 3544 QUADRA28_GET_LOC(phy, pkg_side); 3545 PHYMOD_IF_ERR_RETURN( 3546 BCMI_QUADRA28_READ_APPS_MODE_1r(&acc_cpy, &apps_mode1_reg_val)); 3547 3548 if (pkg_side == Q28_INTF_LINE) { 3549 *enable = (apps_mode1_reg_val.v[0] & 0x3000) ? 1 : 0; 3550 } else { 3551 *enable = (apps_mode1_reg_val.v[0] & 0xC000) ? 1 : 0; 3552 } 3553 3554 return PHYMOD_E_NONE; 3555 } 3556 3557 int _quadra28_set_datapath(const phymod_access_t *pa, int speed, phymod_datapath_t op_datapath) 3558 { 3559 phymod_access_t acc_cpy; 3560 BCMI_QUADRA28_APPS_MODE_0r_t apps_mode0_reg_val; 3561 SIDE_SELECTIONr_t side_sel_reg_val; 3562 uint16_t max_lane = 0, lane_idx = 0, retry_cnt =0; 3563 uint32_t chip_id; 3564 GENERAL_PURPOSE_3r_t gen_pur_reg_3r_val; 3565 3566 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 3567 PHYMOD_MEMSET(&apps_mode0_reg_val, 0 , sizeof(BCMI_QUADRA28_APPS_MODE_0r_t)); 3568 PHYMOD_MEMSET(&gen_pur_reg_3r_val, 0 , sizeof(GENERAL_PURPOSE_3r_t)); 3569 PHYMOD_MEMCPY(&acc_cpy, pa, sizeof(phymod_access_t)); 3570 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3571 PHYMOD_IF_ERR_RETURN(READ_APPS_MODE_0r(&acc_cpy, &apps_mode0_reg_val)); 3572 if (speed >= Q28_SPEED_40G) { 3573 PHYMOD_IF_ERR_RETURN ( 3574 quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 3575 } 3576 if (op_datapath == phymodDatapathNormal) { 3577 BCMI_QUADRA28_APPS_MODE_0r_ENABLE_ULL_DATAPATHf_SET(apps_mode0_reg_val, 0); 3578 } else if (op_datapath == phymodDatapathUll) { 3579 BCMI_QUADRA28_APPS_MODE_0r_ENABLE_ULL_DATAPATHf_SET(apps_mode0_reg_val, 1); 3580 } else { 3581 BCMI_QUADRA28_APPS_MODE_0r_ENABLE_ULL_DATAPATHf_SET(apps_mode0_reg_val, 0); 3582 } 3583 3584 if (speed >= Q28_SPEED_40G) { 3585 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 3586 PHYMOD_IF_ERR_RETURN( 3587 _quadra28_finish_mask_seq(&acc_cpy)); 3588 } else { 3589 chip_id = _quadra28_get_chip_id(&acc_cpy); 3590 max_lane = (chip_id == QUADRA28_82752_CHIP_ID) ? 2 : QUADRA28_MAX_LANE; 3591 acc_cpy.addr &= ~(0x3); 3592 for (lane_idx = 0; lane_idx < max_lane; lane_idx ++) { 3593 retry_cnt = 20; 3594 acc_cpy.addr |= lane_idx; 3595 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 0); 3596 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 3597 do { 3598 PHYMOD_IF_ERR_RETURN( 3599 BCMI_QUADRA28_READ_GENERAL_PURPOSE_3r(&acc_cpy,&gen_pur_reg_3r_val)); 3600 PHYMOD_USLEEP(200); 3601 } while(((gen_pur_reg_3r_val.v[0] & 0x80) != 0) && retry_cnt--); 3602 if (retry_cnt == 0) { 3603 return PHYMOD_E_TIMEOUT; 3604 } 3605 PHYMOD_IF_ERR_RETURN( 3606 _quadra28_finish_mask_seq(&acc_cpy)); 3607 acc_cpy.addr &= ~(0x3); 3608 } 3609 acc_cpy.addr = pa->addr; 3610 } 3611 3612 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 3613 3614 return PHYMOD_E_NONE; 3615 } 3616 3617 3618 int _quadra28_i2c_write(const phymod_access_t *pa, uint32_t slv_addr, uint32_t start_addr, 3619 uint32_t no_of_bytes, const uint8_t *write_data) 3620 { 3621 BCMI_QUADRA28_I2C_CONTROLr_t i2c_ctrl; 3622 uint8_t data[QUADRA28_I2C_MAX_BYTE]; 3623 uint32_t index = 0; 3624 3625 if (no_of_bytes > QUADRA28_I2C_MAX_BYTE) { 3626 return PHYMOD_E_PARAM; 3627 } 3628 PHYMOD_MEMSET(&i2c_ctrl, 0, sizeof(BCMI_QUADRA28_I2C_CONTROLr_t)); 3629 PHYMOD_MEMSET(data, 0, QUADRA28_I2C_MAX_BYTE); 3630 PHYMOD_MEMCPY(data, write_data, no_of_bytes); 3631 3632 /* Clear the latched status */ 3633 PHYMOD_IF_ERR_RETURN 3634 (BCMI_QUADRA28_READ_I2C_CONTROLr(pa, &i2c_ctrl)); 3635 for (index = 0; index < (no_of_bytes/Q28_MAX_BYTES); index++) { 3636 PHYMOD_IF_ERR_RETURN 3637 (_quadra28_i2c_rw(pa, slv_addr, (start_addr+(index*Q28_MAX_BYTES)), Q28_MAX_BYTES, Q28_I2C_WRITE, (data+(index*Q28_MAX_BYTES)))); 3638 } 3639 3640 return PHYMOD_E_NONE; 3641 } 3642 3643 int _quadra28_i2c_read(const phymod_access_t *pa, uint32_t i2c_slave_addr, uint32_t slave_start_addr, 3644 uint32_t no_of_bytes, uint8_t *read_data) 3645 { 3646 BCMI_QUADRA28_I2C_CONTROLr_t i2c_ctrl; 3647 3648 PHYMOD_MEMSET(&i2c_ctrl, 0, sizeof(BCMI_QUADRA28_I2C_CONTROLr_t)); 3649 3650 /* Clear the latched status */ 3651 PHYMOD_IF_ERR_RETURN 3652 (BCMI_QUADRA28_READ_I2C_CONTROLr(pa, &i2c_ctrl)); 3653 PHYMOD_IF_ERR_RETURN 3654 (_quadra28_i2c_rw(pa, i2c_slave_addr, slave_start_addr, no_of_bytes, Q28_I2C_READ , read_data)); 3655 return PHYMOD_E_NONE; 3656 } 3657 3658 int _quadra28_i2c_rw(const phymod_access_t *pa, uint32_t slv_addr, 3659 uint32_t slave_start_addr, uint16_t xfer_cnt, uint8_t acc_type, uint8_t *data) 3660 { 3661 BCMI_QUADRA28_I2C_CONTROLr_t i2c_control; 3662 BCMI_QUADRA28_I2C_TRANSFER_SIZEr_t i2c_xfer_size; 3663 BCMI_QUADRA28_I2C_EXTERNAL_NVM_ADDRESSr_t eeprom_start_addr; 3664 BCMI_QUADRA28_I2C_INTERNAL_ADDRESSr_t nvram_addr; 3665 BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_t i2c_config; 3666 uint16_t cnt_index = 0, temp_cnt = xfer_cnt; 3667 uint32_t ram_data = 0; 3668 uint32_t tries = 10; 3669 3670 PHYMOD_MEMSET(&i2c_control, 0, sizeof(BCMI_QUADRA28_I2C_CONTROLr_t)); 3671 PHYMOD_MEMSET(&i2c_xfer_size, 0, sizeof(BCMI_QUADRA28_I2C_TRANSFER_SIZEr_t)); 3672 PHYMOD_MEMSET(&eeprom_start_addr, 0, sizeof(BCMI_QUADRA28_I2C_EXTERNAL_NVM_ADDRESSr_t)); 3673 PHYMOD_MEMSET(&nvram_addr, 0, sizeof(BCMI_QUADRA28_I2C_INTERNAL_ADDRESSr_t)); 3674 PHYMOD_MEMSET(&i2c_config, 0, sizeof(BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_t)); 3675 3676 if (acc_type == Q28_I2C_WRITE) { 3677 3678 /* Setup Starting address*/ 3679 BCMI_QUADRA28_I2C_EXTERNAL_NVM_ADDRESSr_SET(eeprom_start_addr, slave_start_addr); 3680 PHYMOD_IF_ERR_RETURN( 3681 BCMI_QUADRA28_WRITE_I2C_EXTERNAL_NVM_ADDRESSr(pa, eeprom_start_addr)); 3682 BCMI_QUADRA28_I2C_INTERNAL_ADDRESSr_SET(nvram_addr, QUADRA28_I2C_RAM_START_ADDRESS); 3683 PHYMOD_IF_ERR_RETURN( 3684 BCMI_QUADRA28_WRITE_I2C_INTERNAL_ADDRESSr(pa, nvram_addr)); 3685 3686 BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_IMC_SL_DEV_ADDf_SET(i2c_config, slv_addr); 3687 BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_IMC_I2C_SPEEDf_SET(i2c_config, 0); 3688 BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_IMC_XFER_ADDR_23_16f_SET(i2c_config, 1); 3689 PHYMOD_IF_ERR_RETURN( 3690 BCMI_QUADRA28_WRITE_I2C_SLAVE_ID_ADDRESSr(pa, i2c_config)); 3691 3692 /* Write Data in to RAM location*/ 3693 for (cnt_index = 0; cnt_index < temp_cnt; cnt_index++) { 3694 PHYMOD_IF_ERR_RETURN( 3695 phymod_raw_iblk_write(pa, (QUADRA28_I2C_RAM_START_ADDRESS + cnt_index),(0xff << 8) | data[cnt_index])); 3696 } 3697 3698 BCMI_QUADRA28_I2C_TRANSFER_SIZEr_IMC_XFER_CNTf_SET(i2c_xfer_size, xfer_cnt); 3699 3700 /* Add Tx count*/ 3701 PHYMOD_IF_ERR_RETURN( 3702 BCMI_QUADRA28_WRITE_I2C_TRANSFER_SIZEr(pa, i2c_xfer_size)); 3703 } else { 3704 BCMI_QUADRA28_I2C_TRANSFER_SIZEr_IMC_XFER_CNTf_SET(i2c_xfer_size, xfer_cnt); 3705 /* Add Tx count*/ 3706 PHYMOD_IF_ERR_RETURN( 3707 BCMI_QUADRA28_WRITE_I2C_TRANSFER_SIZEr(pa, i2c_xfer_size)); 3708 3709 /* Setup Starting address*/ 3710 BCMI_QUADRA28_I2C_EXTERNAL_NVM_ADDRESSr_SET(eeprom_start_addr, slave_start_addr); 3711 PHYMOD_IF_ERR_RETURN( 3712 BCMI_QUADRA28_WRITE_I2C_EXTERNAL_NVM_ADDRESSr(pa, eeprom_start_addr)); 3713 3714 /* Setting up internal RAm address*/ 3715 BCMI_QUADRA28_I2C_INTERNAL_ADDRESSr_SET(nvram_addr, QUADRA28_I2C_RAM_START_ADDRESS); 3716 PHYMOD_IF_ERR_RETURN( 3717 BCMI_QUADRA28_WRITE_I2C_INTERNAL_ADDRESSr(pa, nvram_addr)); 3718 3719 /* Setting up slave address*/ 3720 BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_IMC_SL_DEV_ADDf_SET(i2c_config, slv_addr); 3721 BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_IMC_I2C_SPEEDf_SET(i2c_config, 1); 3722 BCMI_QUADRA28_I2C_SLAVE_ID_ADDRESSr_IMC_XFER_ADDR_23_16f_SET(i2c_config, 1); 3723 PHYMOD_IF_ERR_RETURN( 3724 BCMI_QUADRA28_WRITE_I2C_SLAVE_ID_ADDRESSr(pa, i2c_config)); 3725 } 3726 3727 PHYMOD_IF_ERR_RETURN( 3728 BCMI_QUADRA28_READ_I2C_CONTROLr(pa, &i2c_control)); 3729 if (BCMI_QUADRA28_I2C_CONTROLr_I2C_STATUSf_GET(i2c_control) != 0) { 3730 return PHYMOD_E_CONFIG; 3731 } 3732 3733 BCMI_QUADRA28_I2C_CONTROLr_EXTENDED_R_Wf_SET(i2c_control, 2); 3734 BCMI_QUADRA28_I2C_CONTROLr_SLAVE_CMDf_SET(i2c_control, ((acc_type == Q28_I2C_WRITE) ? 1 : 0)); 3735 BCMI_QUADRA28_I2C_CONTROLr_I2C_MASTER_ENABLEf_SET(i2c_control, 1); 3736 PHYMOD_IF_ERR_RETURN( 3737 BCMI_QUADRA28_WRITE_I2C_CONTROLr(pa, i2c_control)); 3738 3739 do { 3740 PHYMOD_USLEEP(100 * xfer_cnt); 3741 PHYMOD_IF_ERR_RETURN( 3742 BCMI_QUADRA28_READ_I2C_CONTROLr(pa, &i2c_control)); 3743 } while((BCMI_QUADRA28_I2C_CONTROLr_I2C_STATUSf_GET(i2c_control) != 1) && (--tries > 0)); 3744 3745 if (BCMI_QUADRA28_I2C_CONTROLr_I2C_STATUSf_GET(i2c_control) != 1) { 3746 return PHYMOD_E_TIMEOUT; 3747 } 3748 if (acc_type == Q28_I2C_READ) { 3749 /* Write Data in to RAM location*/ 3750 for (cnt_index = 0; cnt_index < temp_cnt; cnt_index ++) { 3751 PHYMOD_IF_ERR_RETURN( 3752 phymod_raw_iblk_read(pa, (QUADRA28_I2C_RAM_START_ADDRESS + cnt_index),&ram_data)); 3753 *data = (ram_data & 0xff); 3754 data ++; 3755 } 3756 } 3757 return PHYMOD_E_NONE; 3758 } 3759 3760 int _quadra28_edc_config_set(const phymod_phy_access_t* phy, const phymod_edc_config_t* edc_config) 3761 { 3762 phymod_access_t acc_cpy; 3763 BCMI_QUADRA28_APPS_MODE_0r_t apps_mode0_reg_val; 3764 SIDE_SELECTIONr_t side_sel_reg_val; 3765 uint16_t retry_cnt =0; 3766 int speed = 0; 3767 GENERAL_PURPOSE_3r_t gen_pur_reg_3r_val; 3768 uint8_t datapath = 0; 3769 phymod_access_t pa = phy->access; 3770 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 3771 PHYMOD_MEMSET(&apps_mode0_reg_val, 0 , sizeof(BCMI_QUADRA28_APPS_MODE_0r_t)); 3772 PHYMOD_MEMSET(&gen_pur_reg_3r_val, 0 , sizeof(GENERAL_PURPOSE_3r_t)); 3773 PHYMOD_MEMCPY(&acc_cpy, &pa, sizeof(phymod_access_t)); 3774 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3775 Q28_GET_DATAPATH(&acc_cpy, datapath); 3776 PHYMOD_IF_ERR_RETURN(READ_APPS_MODE_0r(&acc_cpy, &apps_mode0_reg_val)); 3777 3778 if (speed >= Q28_SPEED_40G) { 3779 PHYMOD_IF_ERR_RETURN ( 3780 quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 3781 } 3782 if (edc_config->method != phymodEdcConfigMethodNone) { 3783 apps_mode0_reg_val.v[0] &= 0xf ; 3784 apps_mode0_reg_val.v[0] |= 0xC830; 3785 if (datapath == phymodDatapathUll) { 3786 BCMI_QUADRA28_APPS_MODE_0r_ENABLE_ULL_DATAPATHf_SET(apps_mode0_reg_val,1); 3787 } 3788 } else { 3789 apps_mode0_reg_val.v[0] &= 0xf ; 3790 BCMI_QUADRA28_APPS_MODE_0r_SYTEM_LRf_SET(apps_mode0_reg_val,1); 3791 BCMI_QUADRA28_APPS_MODE_0r_SYSTEM_CUf_SET(apps_mode0_reg_val,1); 3792 if (datapath == phymodDatapathUll) { 3793 BCMI_QUADRA28_APPS_MODE_0r_ENABLE_ULL_DATAPATHf_SET(apps_mode0_reg_val,1); 3794 } 3795 } 3796 3797 if (speed >= Q28_SPEED_40G) { 3798 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 3799 PHYMOD_IF_ERR_RETURN( 3800 _quadra28_finish_mask_seq(&acc_cpy)); 3801 } else { 3802 retry_cnt = 20; 3803 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(apps_mode0_reg_val, 0); 3804 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,apps_mode0_reg_val)); 3805 do { 3806 PHYMOD_IF_ERR_RETURN( 3807 BCMI_QUADRA28_READ_GENERAL_PURPOSE_3r(&acc_cpy,&gen_pur_reg_3r_val)); 3808 PHYMOD_USLEEP(200); 3809 } while(((gen_pur_reg_3r_val.v[0] & 0x80) != 0) && retry_cnt--); 3810 if (retry_cnt == 0) { 3811 return PHYMOD_E_TIMEOUT; 3812 } 3813 PHYMOD_IF_ERR_RETURN( 3814 _quadra28_finish_mask_seq(&acc_cpy)); 3815 } 3816 3817 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 3818 3819 return PHYMOD_E_NONE; 3820 } 3821 3822 int _quadra28_edc_config_get(const phymod_phy_access_t* phy, phymod_edc_config_t* edc_config) 3823 { 3824 phymod_access_t acc_cpy; 3825 GENERAL_PURPOSE_3r_t gen_pur_reg_3r_val; 3826 uint16_t temp = 0; 3827 int speed = 0; 3828 phymod_access_t pa = phy->access; 3829 3830 PHYMOD_MEMSET(&gen_pur_reg_3r_val, 0 , sizeof(GENERAL_PURPOSE_3r_t)); 3831 PHYMOD_MEMCPY(&acc_cpy, &pa, sizeof(phymod_access_t)); 3832 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3833 3834 PHYMOD_IF_ERR_RETURN( 3835 BCMI_QUADRA28_READ_GENERAL_PURPOSE_3r(&acc_cpy,&gen_pur_reg_3r_val)); 3836 temp = (BCMI_QUADRA28_GENERAL_PURPOSE_3r_GET(gen_pur_reg_3r_val) & 0x10) >> 4; 3837 3838 edc_config->method = (temp)? phymodEdcConfigMethodHardware: phymodEdcConfigMethodNone; 3839 3840 return PHYMOD_E_NONE; 3841 } 3842 3843 int _quadra28_soft_reset(phymod_access_t *pa) 3844 { 3845 BCMI_QUADRA28_PMD_CONTROLr_t pmd_ctrl; 3846 BCMI_QUADRA28_MERLIN_MISC_CTRLr_t reset_ack; 3847 BCMI_QUADRA28_XGXSSTATUSr_t xgs_sts; 3848 int retry_cnt = 20; 3849 3850 PHYMOD_MEMSET(&pmd_ctrl, 0, sizeof(BCMI_QUADRA28_PMD_CONTROLr_t)); 3851 3852 PHYMOD_IF_ERR_RETURN( 3853 BCMI_QUADRA28_READ_PMD_CONTROLr(pa, &pmd_ctrl)); 3854 BCMI_QUADRA28_PMD_CONTROLr_RESETf_SET(pmd_ctrl, 1); 3855 PHYMOD_IF_ERR_RETURN( 3856 BCMI_QUADRA28_WRITE_PMD_CONTROLr(pa, pmd_ctrl)); 3857 3858 do { 3859 PHYMOD_IF_ERR_RETURN( 3860 BCMI_QUADRA28_READ_MERLIN_MISC_CTRLr(pa, &reset_ack)); 3861 PHYMOD_USLEEP(1000); 3862 retry_cnt --; 3863 } while (((reset_ack.v[0] & 0x8000) != 0x8000) && retry_cnt); 3864 if (retry_cnt <= 0) { 3865 return PHYMOD_E_TIMEOUT; 3866 } 3867 retry_cnt = 20; 3868 do { 3869 PHYMOD_IF_ERR_RETURN( 3870 BCMI_QUADRA28_READ_XGXSSTATUSr(pa, &xgs_sts)); 3871 PHYMOD_USLEEP(800); 3872 retry_cnt --; 3873 } while (((xgs_sts.v[0] & 0x800) != 0x800) && retry_cnt); 3874 if (retry_cnt <= 0) { 3875 return PHYMOD_E_TIMEOUT; 3876 } 3877 return PHYMOD_E_NONE; 3878 } 3879 3880 int _quadra28_failover_mode_set(const phymod_phy_access_t* phy, phymod_failover_mode_t failover_mode) 3881 { 3882 uint32_t speed = 0; 3883 uint16_t if_side = 0; 3884 uint32_t fov_mode = 0, read_mode = 0; 3885 int pmd_mode = 0; 3886 uint8_t datapath = 0; 3887 int retry_cnt = 20; 3888 uint32_t chip_id = 0; 3889 uint8_t fov_port_phy = 0; 3890 SIDE_SELECTIONr_t side_sel_reg_val; 3891 phymod_access_t acc_cpy = phy->access; 3892 BCMI_QUADRA28_MDIO_BROADCAST_CONTROLr_t bcast_ctrl; 3893 BCMI_QUADRA28_APPS_MODE_2r_t aps_mode2; 3894 BCMI_QUADRA28_APPS_MODE_0r_t aps_mode0; 3895 uint16_t lane = 0; 3896 BCMI_QUADRA28_RING_CONFIGURATIONr_t ring_conf; 3897 3898 PHYMOD_MEMSET(&bcast_ctrl, 0, sizeof(bcast_ctrl)); 3899 PHYMOD_MEMSET(&aps_mode2, 0, sizeof(aps_mode2)); 3900 PHYMOD_MEMSET(&aps_mode0, 0, sizeof(aps_mode0)); 3901 PHYMOD_MEMSET(&ring_conf, 0, sizeof(ring_conf)); 3902 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 3903 Q28_GET_DATAPATH(&acc_cpy, datapath); 3904 QUADRA28_GET_LOC(phy, if_side); 3905 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 3906 fov_port_phy = (pmd_mode == Q28_SINGLE_PMD) ? 4 : 1; 3907 chip_id = _quadra28_get_chip_id(&acc_cpy); 3908 /*40G FOv can be performed only on 2 DIE(82780/8278f)*/ 3909 if (((chip_id != QUADRA28_82780_CHIP_ID) && (chip_id != QUADRA28_8278F_CHIP_ID)) 3910 && (pmd_mode == Q28_SINGLE_PMD)) { 3911 return PHYMOD_E_UNAVAIL; 3912 } 3913 if (datapath == phymodDatapathUll) { 3914 return PHYMOD_E_CONFIG; 3915 } 3916 if (failover_mode == phymodFailovermodeNone) { 3917 fov_mode = 0; 3918 } else if (if_side == Q28_INTF_LINE) { 3919 if (acc_cpy.addr & fov_port_phy) { 3920 fov_mode = Q28_FOV_TYPE_N1S0; 3921 } else { 3922 fov_mode = Q28_FOV_TYPE_N0S1; 3923 } 3924 } else { 3925 if (acc_cpy.addr & fov_port_phy) { 3926 fov_mode = Q28_FOV_TYPE_N0S1; 3927 } else { 3928 fov_mode = Q28_FOV_TYPE_N1S0; 3929 } 3930 } 3931 if (pmd_mode == Q28_SINGLE_PMD) { 3932 if ( fov_mode != 0) { 3933 /* As per programming seq, FOV can be configured only with 10G mode, so Changing mode for DIE 1*/ 3934 acc_cpy.addr = (acc_cpy.addr & ~0x7); 3935 PHYMOD_IF_ERR_RETURN(_quadra28_clear_mode_config(&acc_cpy)); 3936 /* As per programming seq, FOV can be configured only with 10G mode, so Changing mode for DIE 1*/ 3937 acc_cpy.addr = (acc_cpy.addr & ~0x7) | 4; 3938 PHYMOD_IF_ERR_RETURN(_quadra28_clear_mode_config(&acc_cpy)); 3939 3940 acc_cpy.addr = (acc_cpy.addr & ~0x7); 3941 /* Enable multicast for all the 8 lanes*/ 3942 for (lane = 0; lane <= 7; lane ++) { 3943 acc_cpy.addr &= ~7; 3944 acc_cpy.addr |= lane; 3945 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(&acc_cpy,0x1c8db,lane)); 3946 } 3947 /* Setting up multicast for octal channel, 3948 * No need to enable Multicast for ch1*/ 3949 for (lane = 1; lane <= 7; lane ++) { 3950 acc_cpy.addr &= ~7; 3951 acc_cpy.addr |= lane; 3952 if (lane == 0) { 3953 continue; 3954 } 3955 3956 PHYMOD_IF_ERR_RETURN( 3957 BCMI_QUADRA28_READ_MDIO_BROADCAST_CONTROLr(&acc_cpy, &bcast_ctrl)); 3958 BCMI_QUADRA28_MDIO_BROADCAST_CONTROLr_MDIO_MCAST_ENf_SET(bcast_ctrl, 1); 3959 BCMI_QUADRA28_MDIO_BROADCAST_CONTROLr_MDIO_MULTICAST_PHYADf_SET(bcast_ctrl, 0); 3960 PHYMOD_IF_ERR_RETURN( 3961 BCMI_QUADRA28_WRITE_MDIO_BROADCAST_CONTROLr(&acc_cpy, bcast_ctrl)); 3962 } 3963 PHYMOD_USLEEP(100000); /* Delay as per PGM seq*/ 3964 acc_cpy.addr &= (~7); 3965 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(&acc_cpy,Q28_TOP_GP_REG0,0)); 3966 BCMI_QUADRA28_APPS_MODE_2r_SET(aps_mode2, 0x8000 ); 3967 PHYMOD_IF_ERR_RETURN( 3968 BCMI_QUADRA28_WRITE_APPS_MODE_2r(&acc_cpy, aps_mode2)); 3969 3970 /*set Write finish mask*/ 3971 PHYMOD_IF_ERR_RETURN( 3972 BCMI_QUADRA28_READ_APPS_MODE_0r(&acc_cpy, &aps_mode0)); 3973 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(aps_mode0, 0); 3974 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,aps_mode0)); 3975 PHYMOD_IF_ERR_RETURN( 3976 _quadra28_intf_update_wait_check(&acc_cpy, aps_mode0.v[0], 50000)); 3977 3978 PHYMOD_USLEEP(100000); /* Delay as per PGM seq*/ 3979 /* Clear Write finish mask*/ 3980 aps_mode0.v[0] = 0x8884; /* As per PGM seq, it works only for SR4*/ 3981 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,aps_mode0)); 3982 PHYMOD_IF_ERR_RETURN( 3983 _quadra28_intf_update_wait_check(&acc_cpy, aps_mode0.v[0], 50000)); 3984 3985 /*set Write finish mask*/ 3986 PHYMOD_IF_ERR_RETURN( 3987 BCMI_QUADRA28_READ_APPS_MODE_0r(&acc_cpy, &aps_mode0)); 3988 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(aps_mode0, 0); 3989 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,aps_mode0)); 3990 PHYMOD_IF_ERR_RETURN( 3991 _quadra28_intf_update_wait_check(&acc_cpy, aps_mode0.v[0], 50000)); 3992 3993 acc_cpy.addr |= 4; /* Die 2 soft reset*/ 3994 PHYMOD_IF_ERR_RETURN(_quadra28_soft_reset(&acc_cpy)); 3995 3996 acc_cpy.addr &= ~7; 3997 /* Soft reset for die 1*/ 3998 PHYMOD_IF_ERR_RETURN(_quadra28_soft_reset(&acc_cpy)); 3999 4000 PHYMOD_USLEEP(200000); 4001 4002 /* Ring reset*/ 4003 acc_cpy.addr &= ~7; 4004 acc_cpy.addr |= 4; 4005 PHYMOD_IF_ERR_RETURN( 4006 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4007 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 1); 4008 PHYMOD_IF_ERR_RETURN( 4009 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4010 4011 acc_cpy.addr &= ~7; 4012 PHYMOD_IF_ERR_RETURN( 4013 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4014 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 1); 4015 PHYMOD_IF_ERR_RETURN( 4016 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4017 4018 acc_cpy.addr |= 4; 4019 PHYMOD_IF_ERR_RETURN( 4020 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4021 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 0); 4022 PHYMOD_IF_ERR_RETURN( 4023 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4024 4025 acc_cpy.addr &= ~7; 4026 PHYMOD_IF_ERR_RETURN( 4027 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4028 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 0); 4029 PHYMOD_IF_ERR_RETURN( 4030 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4031 4032 /* Enabling FOV mode*/ 4033 acc_cpy.addr &= ~7; 4034 PHYMOD_IF_ERR_RETURN ( 4035 quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 4036 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(&acc_cpy,Q28_TOP_GP_REG0,fov_mode)); 4037 do { 4038 PHYMOD_IF_ERR_RETURN( 4039 phymod_raw_iblk_read(&acc_cpy, Q28_TOP_GP_REG1, &read_mode)); 4040 PHYMOD_USLEEP(200); 4041 } while((retry_cnt--) && (read_mode != fov_mode)); 4042 4043 PHYMOD_IF_ERR_RETURN ( 4044 quadra28_channel_select(&acc_cpy, 0)); 4045 PHYMOD_USLEEP(100000); 4046 4047 acc_cpy.addr |= 4; /* Die 2 soft reset*/ 4048 PHYMOD_IF_ERR_RETURN(_quadra28_soft_reset(&acc_cpy)); 4049 4050 acc_cpy.addr &= ~7; 4051 /* Soft reset for die 1*/ 4052 PHYMOD_IF_ERR_RETURN(_quadra28_soft_reset(&acc_cpy)); 4053 4054 PHYMOD_USLEEP(200000); 4055 4056 /* Ring reset*/ 4057 acc_cpy.addr &= ~7; 4058 acc_cpy.addr |= 4; 4059 PHYMOD_IF_ERR_RETURN( 4060 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4061 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 1); 4062 PHYMOD_IF_ERR_RETURN( 4063 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4064 4065 acc_cpy.addr &= ~7; 4066 PHYMOD_IF_ERR_RETURN( 4067 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4068 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 1); 4069 PHYMOD_IF_ERR_RETURN( 4070 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4071 4072 acc_cpy.addr |= 4; 4073 PHYMOD_IF_ERR_RETURN( 4074 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4075 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 0); 4076 PHYMOD_IF_ERR_RETURN( 4077 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4078 4079 acc_cpy.addr &= ~7; 4080 PHYMOD_IF_ERR_RETURN( 4081 BCMI_QUADRA28_READ_RING_CONFIGURATIONr(&acc_cpy, &ring_conf)); 4082 BCMI_QUADRA28_RING_CONFIGURATIONr_RING_SOFTRESETf_SET(ring_conf, 0); 4083 PHYMOD_IF_ERR_RETURN( 4084 BCMI_QUADRA28_WRITE_RING_CONFIGURATIONr(&acc_cpy, ring_conf)); 4085 } else { 4086 phymod_phy_access_t local_phy; 4087 int16_t die; 4088 PHYMOD_MEMCPY(&local_phy, phy, sizeof(phymod_phy_access_t)); 4089 for (die = 1;die >=0; die --) { 4090 acc_cpy.addr &= ~7; 4091 acc_cpy.addr |= die * 4; 4092 PHYMOD_IF_ERR_RETURN ( 4093 quadra28_channel_select(&acc_cpy, Q28_ALL_LANE)); 4094 BCMI_QUADRA28_APPS_MODE_2r_SET(aps_mode2, 0); 4095 PHYMOD_IF_ERR_RETURN( 4096 BCMI_QUADRA28_WRITE_APPS_MODE_2r(&acc_cpy, aps_mode2)); 4097 PHYMOD_IF_ERR_RETURN( 4098 phymod_raw_iblk_write(&acc_cpy,Q28_TOP_GP_REG0,0)); 4099 aps_mode0.v[0] = 0x8882; /* As per PGM seq, it works only for SR*/ 4100 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,aps_mode0)); 4101 PHYMOD_IF_ERR_RETURN( 4102 _quadra28_intf_update_wait_check(&acc_cpy, aps_mode0.v[0], 50000)); 4103 4104 /*set Write finish mask*/ 4105 PHYMOD_IF_ERR_RETURN( 4106 BCMI_QUADRA28_READ_APPS_MODE_0r(&acc_cpy, &aps_mode0)); 4107 BCMI_QUADRA28_APPS_MODE_0r_FINISH_CHANGEf_SET(aps_mode0, 0); 4108 PHYMOD_IF_ERR_RETURN(WRITE_APPS_MODE_0r(&acc_cpy,aps_mode0)); 4109 PHYMOD_IF_ERR_RETURN( 4110 _quadra28_intf_update_wait_check(&acc_cpy, aps_mode0.v[0], 50000)); 4111 4112 PHYMOD_IF_ERR_RETURN(_quadra28_soft_reset(&acc_cpy)); 4113 } 4114 /* Move to 40G default mode*/ 4115 local_phy.access.addr &= ~0x7; 4116 PHYMOD_IF_ERR_RETURN( 4117 quadra28_set_config_mode(&local_phy, phymodInterfaceSR4, 40000, 4118 0, 0xFFFF, 0xFFFF)); 4119 local_phy.port_loc = phymodPortLocSys; 4120 PHYMOD_IF_ERR_RETURN( 4121 quadra28_set_config_mode(&local_phy, phymodInterfaceXLAUI, 40000, 4122 0, 0xFFFF, 0xFFFF)); 4123 4124 local_phy.port_loc = phymodPortLocLine; 4125 local_phy.access.addr |= 0x4; 4126 PHYMOD_IF_ERR_RETURN( 4127 quadra28_set_config_mode(&local_phy, phymodInterfaceSR4, 40000, 4128 0, 0xFFFF, 0xFFFF)); 4129 local_phy.port_loc = phymodPortLocSys; 4130 PHYMOD_IF_ERR_RETURN( 4131 quadra28_set_config_mode(&local_phy, phymodInterfaceXLAUI, 40000, 4132 0,0xFFFF, 0xFFFF)); 4133 } 4134 } else { 4135 /* Enable FOV for both the channels on a core*/ 4136 acc_cpy.addr &= (~1); 4137 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(&acc_cpy,Q28_TOP_GP_REG0,fov_mode)); 4138 do { 4139 PHYMOD_IF_ERR_RETURN( 4140 phymod_raw_iblk_read(&acc_cpy, Q28_TOP_GP_REG1, &read_mode)); 4141 PHYMOD_USLEEP(200); 4142 } while((retry_cnt--) && (read_mode != fov_mode)); 4143 4144 PHYMOD_IF_ERR_RETURN(_quadra28_soft_reset(&acc_cpy)); 4145 retry_cnt = 20; 4146 acc_cpy.addr |= 1; 4147 PHYMOD_IF_ERR_RETURN(phymod_raw_iblk_write(&acc_cpy,Q28_TOP_GP_REG0,fov_mode)); 4148 do { 4149 PHYMOD_IF_ERR_RETURN( 4150 phymod_raw_iblk_read(&acc_cpy, Q28_TOP_GP_REG1, &read_mode)); 4151 PHYMOD_USLEEP(200); 4152 } while((retry_cnt--) && (read_mode != fov_mode)); 4153 PHYMOD_IF_ERR_RETURN(_quadra28_soft_reset(&acc_cpy)); 4154 } 4155 4156 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 4157 return PHYMOD_E_NONE; 4158 } 4159 4160 int _quadra28_failover_mode_get(const phymod_phy_access_t* phy, phymod_failover_mode_t* failover_mode) 4161 { 4162 uint32_t speed = 0; 4163 uint32_t fov_mode = 0; 4164 uint8_t datapath = 0; 4165 phymod_access_t acc_cpy = phy->access; 4166 4167 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 4168 Q28_GET_DATAPATH(&acc_cpy, datapath); 4169 4170 if (datapath == phymodDatapathUll) { 4171 return PHYMOD_E_CONFIG; 4172 } 4173 4174 PHYMOD_IF_ERR_RETURN( 4175 phymod_raw_iblk_read(&acc_cpy, Q28_TOP_GP_REG1, &fov_mode)); 4176 if (fov_mode == 0) { 4177 *failover_mode = phymodFailovermodeNone; 4178 } else { 4179 *failover_mode = phymodFailovermodeEnable; 4180 } 4181 4182 return PHYMOD_E_NONE; 4183 } 4184 4185 int _quadra28_phy_rx_adaptation_resume(const phymod_phy_access_t *phy) 4186 { 4187 int lane_map = 0; 4188 int pkg_side = 0; 4189 int num_lanes = QUADRA28_MAX_LANE; 4190 int lane_index = 0; 4191 SIDE_SELECTIONr_t side_sel_reg_val; 4192 int pmd_mode = 0; 4193 uint32_t speed = 0; 4194 phymod_access_t acc_cpy; 4195 4196 PHYMOD_MEMSET(&side_sel_reg_val, 0 , sizeof(SIDE_SELECTIONr_t)); 4197 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 4198 Q28_GET_PMD_MODE(&acc_cpy, pmd_mode); 4199 Q28_10G_PHY_ID_WORK_AROUND(speed, acc_cpy); 4200 4201 /* Get the lane map from phymod access */ 4202 lane_map = PHYMOD_ACC_LANE_MASK(&acc_cpy); 4203 QUADRA28_GET_LOC(phy, pkg_side); 4204 QUADRA28_SELECT_SIDE(&acc_cpy,side_sel_reg_val, pkg_side); 4205 4206 if (pmd_mode == Q28_SINGLE_PMD) { 4207 for (lane_index = 0; lane_index < num_lanes; lane_index++) { 4208 if (((lane_map >> lane_index) & 1) == 0x1) { 4209 PHYMOD_IF_ERR_RETURN( 4210 quadra28_channel_select(&acc_cpy, 4211 ((lane_map == Q28_ALL_LANE)? Q28_ALL_LANE : lane_index))); 4212 4213 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 0)); 4214 if (lane_map == Q28_ALL_LANE) { 4215 break; 4216 } 4217 } 4218 } 4219 } else { 4220 PHYMOD_IF_ERR_RETURN(merlin_quadra28_stop_rx_adaptation(&acc_cpy, 0)); 4221 } 4222 4223 QUADRA28_RESET_SIDE_BCST_CTRL(&acc_cpy,side_sel_reg_val, Q28_INTF_LINE); 4224 4225 return PHYMOD_E_NONE; 4226 } 4227 4228 int _quadra28_phy_gpio_config_set(const phymod_phy_access_t* phy, int pin_no, phymod_gpio_mode_t gpio_mode) 4229 { 4230 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t gpio_config_ctrl_1; 4231 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t gpio_config_ctrl_2; 4232 phymod_access_t acc_cpy; 4233 uint16_t temp = 0; 4234 PHYMOD_MEMSET(&gpio_config_ctrl_1, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t)); 4235 PHYMOD_MEMSET(&gpio_config_ctrl_2, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t)); 4236 PHYMOD_MEMSET(&acc_cpy, 0, sizeof(phymod_access_t)); 4237 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 4238 4239 if (pin_no > 5) { 4240 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("Q28 has only 5 GPIOs (0 - 5)"))); 4241 } 4242 PHYMOD_IF_ERR_RETURN( 4243 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROLr(&acc_cpy, &gpio_config_ctrl_1)); 4244 4245 PHYMOD_IF_ERR_RETURN( 4246 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROL_2r(&acc_cpy, &gpio_config_ctrl_2)); 4247 4248 switch (gpio_mode) { 4249 case phymodGpioModeDisabled: 4250 return PHYMOD_E_NONE; 4251 case phymodGpioModeOutput: 4252 if (pin_no < 2) { 4253 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_GP_DISf_GET(gpio_config_ctrl_1); 4254 temp &= ~(1 << pin_no); 4255 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_GP_DISf_SET(gpio_config_ctrl_1,temp); 4256 } else if (pin_no == 2 || pin_no == 3) { 4257 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_OUT_GP_DISf_GET(gpio_config_ctrl_2); 4258 temp &= ~(1 << (pin_no - 2)); 4259 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_OUT_GP_DISf_SET(gpio_config_ctrl_2, temp); 4260 } else if (pin_no == 4) { 4261 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_OPRXLOS_DISf_SET(gpio_config_ctrl_1, 0); 4262 } else if (pin_no == 5) { 4263 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_MOD_ABS_DISf_SET(gpio_config_ctrl_1, 0); 4264 } 4265 4266 break; 4267 case phymodGpioModeInput: 4268 if (pin_no < 2) { 4269 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_GP_DISf_GET(gpio_config_ctrl_1); 4270 temp &= ~(1 << pin_no); 4271 temp |= (1 << pin_no); 4272 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_GP_DISf_SET(gpio_config_ctrl_1,temp); 4273 } else if (pin_no == 2 || pin_no == 3) { 4274 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_OUT_GP_DISf_GET(gpio_config_ctrl_2); 4275 temp &= ~(1 << (pin_no - 2)); 4276 temp |= (1 << (pin_no - 2)); 4277 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_OUT_GP_DISf_SET(gpio_config_ctrl_2, temp); 4278 } else if (pin_no == 4) { 4279 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_OPRXLOS_DISf_SET(gpio_config_ctrl_1, 1); 4280 } else if (pin_no == 5) { 4281 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_MOD_ABS_DISf_SET(gpio_config_ctrl_1, 1); 4282 } 4283 break; 4284 default: 4285 return PHYMOD_E_PARAM; 4286 } 4287 PHYMOD_IF_ERR_RETURN( 4288 BCMI_QUADRA28_WRITE_GENERAL_PURPOSE_IO_CONTROLr(&acc_cpy, gpio_config_ctrl_1)); 4289 4290 PHYMOD_IF_ERR_RETURN( 4291 BCMI_QUADRA28_WRITE_GENERAL_PURPOSE_IO_CONTROL_2r(&acc_cpy, gpio_config_ctrl_2)); 4292 4293 4294 return PHYMOD_E_NONE; 4295 } 4296 4297 int _quadra28_phy_gpio_config_get(const phymod_phy_access_t* phy, int pin_no, phymod_gpio_mode_t* gpio_mode) 4298 { 4299 phymod_access_t acc_cpy; 4300 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t gpio_config_ctrl_1; 4301 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t gpio_config_ctrl_2; 4302 uint16_t temp = 0; 4303 PHYMOD_MEMSET(&gpio_config_ctrl_1, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t)); 4304 PHYMOD_MEMSET(&gpio_config_ctrl_2, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t)); 4305 PHYMOD_MEMSET(&acc_cpy, 0, sizeof(phymod_access_t)); 4306 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 4307 4308 if (pin_no > 5) { 4309 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("Q28 has only 5 GPIOs (0 - 5)"))); 4310 } 4311 PHYMOD_IF_ERR_RETURN( 4312 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROLr(&acc_cpy, &gpio_config_ctrl_1)); 4313 4314 PHYMOD_IF_ERR_RETURN( 4315 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROL_2r(&acc_cpy, &gpio_config_ctrl_2)); 4316 4317 if (pin_no < 2) { 4318 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_GP_DISf_GET(gpio_config_ctrl_1); 4319 temp = (pin_no == 0) ? (temp & 1) : ((temp & 2) >> 1); 4320 } else if (pin_no == 2 || pin_no == 3) { 4321 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_OUT_GP_DISf_GET(gpio_config_ctrl_2); 4322 temp = (pin_no == 2) ? (temp & 1) : ((temp & 2) >> 1); 4323 } else if (pin_no == 4) { 4324 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_OPRXLOS_DISf_GET(gpio_config_ctrl_1); 4325 } else if (pin_no == 5) { 4326 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_MOD_ABS_DISf_GET(gpio_config_ctrl_1); 4327 } 4328 if (temp == 1) { 4329 *gpio_mode = phymodGpioModeInput; 4330 } else { 4331 *gpio_mode = phymodGpioModeOutput; 4332 } 4333 4334 return PHYMOD_E_NONE; 4335 } 4336 4337 int _quadra28_phy_gpio_pin_value_set(const phymod_phy_access_t* phy, int pin_no, int value) 4338 { 4339 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t gpio_config_ctrl_1; 4340 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t gpio_config_ctrl_2; 4341 phymod_access_t acc_cpy; 4342 uint16_t temp = 0; 4343 PHYMOD_MEMSET(&gpio_config_ctrl_1, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t)); 4344 PHYMOD_MEMSET(&gpio_config_ctrl_2, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t)); 4345 PHYMOD_MEMSET(&acc_cpy, 0, sizeof(phymod_access_t)); 4346 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 4347 4348 if (pin_no > 5) { 4349 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("Q28 has only 5 GPIOs (0 - 5)"))); 4350 } 4351 PHYMOD_IF_ERR_RETURN( 4352 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROLr(&acc_cpy, &gpio_config_ctrl_1)); 4353 4354 PHYMOD_IF_ERR_RETURN( 4355 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROL_2r(&acc_cpy, &gpio_config_ctrl_2)); 4356 4357 if (pin_no < 2) { 4358 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_GP_DATf_GET(gpio_config_ctrl_1); 4359 temp &= ~(1 << pin_no); 4360 temp |= (value << pin_no); 4361 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OUT_GP_DATf_SET(gpio_config_ctrl_1,temp); 4362 } else if (pin_no == 2 || pin_no == 3) { 4363 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_OUT_GP_DATf_GET(gpio_config_ctrl_2); 4364 temp &= ~(1 << (pin_no-2)); 4365 temp |= (value << (pin_no - 2)); 4366 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_OUT_GP_DATf_SET(gpio_config_ctrl_2, temp); 4367 } else if (pin_no == 4) { 4368 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_OPT_RX_LOS_OUTf_SET(gpio_config_ctrl_1, value); 4369 } else if (pin_no == 5) { 4370 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_MOD_ABS_OUTf_SET(gpio_config_ctrl_1, value); 4371 } 4372 PHYMOD_IF_ERR_RETURN( 4373 BCMI_QUADRA28_WRITE_GENERAL_PURPOSE_IO_CONTROLr(&acc_cpy, gpio_config_ctrl_1)); 4374 4375 PHYMOD_IF_ERR_RETURN( 4376 BCMI_QUADRA28_WRITE_GENERAL_PURPOSE_IO_CONTROL_2r(&acc_cpy, gpio_config_ctrl_2)); 4377 4378 return PHYMOD_E_NONE; 4379 } 4380 4381 int _quadra28_phy_gpio_pin_value_get(const phymod_phy_access_t* phy, int pin_no, int* value) 4382 { 4383 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t gpio_config_ctrl_1; 4384 BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t gpio_config_ctrl_2; 4385 phymod_access_t acc_cpy; 4386 uint16_t temp = 0; 4387 PHYMOD_MEMSET(&gpio_config_ctrl_1, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_t)); 4388 PHYMOD_MEMSET(&gpio_config_ctrl_2, 0, sizeof(BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_t)); 4389 PHYMOD_MEMSET(&acc_cpy, 0, sizeof(phymod_access_t)); 4390 PHYMOD_MEMCPY(&acc_cpy, &phy->access, sizeof(phymod_access_t)); 4391 4392 if (pin_no > 5) { 4393 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("Q28 has only 5 GPIOs (0 - 5)"))); 4394 } 4395 PHYMOD_IF_ERR_RETURN( 4396 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROLr(&acc_cpy, &gpio_config_ctrl_1)); 4397 4398 PHYMOD_IF_ERR_RETURN( 4399 BCMI_QUADRA28_READ_GENERAL_PURPOSE_IO_CONTROL_2r(&acc_cpy, &gpio_config_ctrl_2)); 4400 4401 if (pin_no < 2) { 4402 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_IN_GP_DATf_GET(gpio_config_ctrl_1); 4403 *value = (pin_no == 0)? (temp & 1) : ((temp & 2) >> 1); 4404 } else if (pin_no == 2 || pin_no == 3) { 4405 temp = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROL_2r_IN_GP_DATf_GET(gpio_config_ctrl_2); 4406 *value = (pin_no == 2)? (temp & 1) : ((temp & 2) >> 1); 4407 } else if (pin_no == 4) { 4408 *value = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_IN_OPRXLOS_DATf_GET(gpio_config_ctrl_1); 4409 } else if (pin_no == 5) { 4410 *value = BCMI_QUADRA28_GENERAL_PURPOSE_IO_CONTROLr_IN_MOD_ABS_DATf_GET(gpio_config_ctrl_1); 4411 } 4412 4413 return PHYMOD_E_NONE; 4414 } 4415