pm4x25td.c (15989B)
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 10 #include <soc/types.h> 11 #include <soc/error.h> 12 #include <soc/drv.h> 13 #include <soc/wb_engine.h> 14 #include <soc/portmod/portmod_internal.h> 15 #include <soc/portmod/portmod.h> 16 #include <soc/portmod/portmod_dispatch.h> 17 #include <soc/portmod/portmod_chain.h> 18 #include <soc/portmod/portmod_common.h> 19 #include <soc/mcm/memregs.h> 20 21 #ifdef _ERR_MSG_MODULE_NAME 22 #error "_ERR_MSG_MODULE_NAME redefined" 23 #endif 24 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT 25 26 #ifdef PORTMOD_PM4X25TD_SUPPORT 27 28 #include <soc/portmod/clmac.h> 29 #include <soc/portmod/pm4x25.h> 30 #include <soc/portmod/pm4x25_shared.h> 31 32 #define PORTMOD_MAX_LINK_WAIT_TIMEOUT 10000 33 #define PORTMOD_WAIT_TIMEOUT_PER_ITER 1000 34 35 /* 36 * Function Prototypes 37 */ 38 STATIC 39 void pm4x25td_port_mac_link_up_wait(int unit, int port, pm_info_t pm_info); 40 41 int pm4x25td_port_tsc_reset_set(int unit, int port, int in_reset) 42 { 43 static int rst_flag = 0; 44 SOC_INIT_FUNC_DEFS; 45 46 if (!in_reset && !rst_flag) { 47 _SOC_IF_ERR_EXIT(soc_tsc_xgxs_reset(unit, port, 0)); 48 _SOC_IF_ERR_EXIT(soc_tsc_xgxs_reset(unit, port, 1)); 49 _SOC_IF_ERR_EXIT(soc_tsc_xgxs_reset(unit, port, 2)); 50 _SOC_IF_ERR_EXIT(soc_tsc_xgxs_reset(unit, port, 3)); 51 rst_flag = 1; 52 } 53 54 exit: 55 SOC_FUNC_RETURN; 56 } 57 58 int pm4x25td_port_lag_failover_status_toggle (int unit, soc_port_t port, pm_info_t pm_info) 59 { 60 uint32_t rval; 61 SOC_INIT_FUNC_DEFS; 62 63 pm4x25td_port_mac_link_up_wait(unit, port, pm_info); 64 /* Toggle link bit to notify IPIPE on link up */ 65 _SOC_IF_ERR_EXIT(READ_CPORT_LAG_FAILOVER_CONFIGr(unit, port, &rval)); 66 soc_reg_field_set(unit, CPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 1); 67 _SOC_IF_ERR_EXIT(WRITE_CPORT_LAG_FAILOVER_CONFIGr(unit, port, rval)); 68 soc_reg_field_set(unit, CPORT_LAG_FAILOVER_CONFIGr, &rval, LINK_STATUS_UPf, 0); 69 _SOC_IF_ERR_EXIT(WRITE_CPORT_LAG_FAILOVER_CONFIGr(unit, port, rval)); 70 71 exit: 72 SOC_FUNC_RETURN; 73 } 74 75 76 int pm4x25td_port_cntmaxsize_get(int unit, int port, pm_info_t pm_info, int *val) 77 { 78 int rv; 79 rv = READ_PGW_CNTMAXSIZEr(unit, port, (uint32_t *)val); 80 return rv; 81 } 82 83 int pm4x25td_port_cntmaxsize_set(int unit, int port, pm_info_t pm_info, int val) 84 { 85 int rv; 86 rv = WRITE_PGW_CNTMAXSIZEr(unit, port, (uint32_t)val); 87 return rv; 88 } 89 90 int pm4x25td_port_modid_set (int unit, int port, pm_info_t pm_info, int value) 91 { 92 uint32_t rval, modid; 93 int flen; 94 SOC_INIT_FUNC_DEFS; 95 96 flen = soc_reg_field_length(unit, CPORT_CONFIGr, MY_MODIDf)? value : 0; 97 modid = (value < (1 << flen))? value : 0; 98 99 _SOC_IF_ERR_EXIT(READ_CPORT_CONFIGr(unit, port, &rval)); 100 soc_reg_field_set(unit, CPORT_CONFIGr, &rval, MY_MODIDf, modid); 101 _SOC_IF_ERR_EXIT(WRITE_CPORT_CONFIGr(unit, port, rval)); 102 103 exit: 104 SOC_FUNC_RETURN; 105 } 106 107 int pm4x25td_port_higig2_mode_set (int unit, int port, pm_info_t pm_info, int mode) 108 { 109 uint32_t rval; 110 SOC_INIT_FUNC_DEFS; 111 112 _SOC_IF_ERR_EXIT(READ_CPORT_CONFIGr(unit, port, &rval)); 113 soc_reg_field_set(unit, CPORT_CONFIGr, &rval, HIGIG2_MODEf, mode); 114 _SOC_IF_ERR_EXIT(WRITE_CPORT_CONFIGr(unit, port, rval)); 115 116 exit: 117 SOC_FUNC_RETURN; 118 } 119 120 int pm4x25td_port_higig2_mode_get (int unit, int port, pm_info_t pm_info, int *mode) 121 { 122 uint32_t rval; 123 SOC_INIT_FUNC_DEFS; 124 125 _SOC_IF_ERR_EXIT(READ_CPORT_CONFIGr(unit, port, &rval)); 126 *(mode) = soc_reg_field_get(unit, CPORT_CONFIGr, rval, HIGIG2_MODEf); 127 128 exit: 129 SOC_FUNC_RETURN; 130 } 131 132 int pm4x25td_port_higig_mode_set (int unit, int port, pm_info_t pm_info, int mode) 133 { 134 uint32_t rval; 135 SOC_INIT_FUNC_DEFS; 136 137 _SOC_IF_ERR_EXIT(READ_CPORT_CONFIGr(unit, port, &rval)); 138 soc_reg_field_set(unit, CPORT_CONFIGr, &rval, HIGIG_MODEf, mode); 139 _SOC_IF_ERR_EXIT(WRITE_CPORT_CONFIGr(unit, port, rval)); 140 141 exit: 142 SOC_FUNC_RETURN; 143 } 144 145 int pm4x25td_port_higig_mode_get (int unit, int port, pm_info_t pm_info, int *mode) 146 { 147 uint32_t rval; 148 SOC_INIT_FUNC_DEFS; 149 150 _SOC_IF_ERR_EXIT(READ_CPORT_CONFIGr(unit, port, &rval)); 151 *(mode) = soc_reg_field_get(unit, CPORT_CONFIGr, rval, HIGIG_MODEf); 152 153 exit: 154 SOC_FUNC_RETURN; 155 } 156 157 int pm4x25td_port_config_port_type_set (int unit, int port, pm_info_t pm_info, int type) 158 { 159 160 uint32_t rval; 161 SOC_INIT_FUNC_DEFS; 162 163 _SOC_IF_ERR_EXIT(READ_CPORT_CONFIGr(unit, port, &rval)); 164 soc_reg_field_set(unit, CPORT_CONFIGr, &rval, PORT_TYPEf, type); 165 _SOC_IF_ERR_EXIT(WRITE_CPORT_CONFIGr(unit, port, rval)); 166 167 exit: 168 SOC_FUNC_RETURN; 169 } 170 171 int pm4x25td_port_config_port_type_get (int unit, int port, pm_info_t pm_info, int *type) 172 { 173 174 uint32_t rval; 175 SOC_INIT_FUNC_DEFS; 176 177 _SOC_IF_ERR_EXIT(READ_CPORT_CONFIGr(unit, port, &rval)); 178 *(type) = soc_reg_field_get(unit, CPORT_CONFIGr, rval, PORT_TYPEf); 179 180 exit: 181 SOC_FUNC_RETURN; 182 } 183 184 int pm4x25td_port_led_chain_config (int unit, int port, pm_info_t *pm, 185 int value) 186 { 187 SOC_INIT_FUNC_DEFS; 188 189 _SOC_IF_ERR_EXIT(WRITE_CPORT_LED_CHAIN_CONFIGr (unit, port, value)); 190 191 exit: 192 SOC_FUNC_RETURN; 193 } 194 195 196 int _pm4x25td_pm_enable(int unit, int port, pm_info_t pm_info, int port_index, const portmod_port_add_info_t* add_info, int enable) 197 { 198 uint32 reg_val; 199 uint32 rsv_mask; 200 int rv; 201 SOC_INIT_FUNC_DEFS; 202 203 if(enable) { 204 /* Power Save */ 205 _SOC_IF_ERR_EXIT(READ_CPORT_POWER_SAVEr(unit, port, ®_val)); 206 soc_reg_field_set(unit, CPORT_POWER_SAVEr, ®_val, CPORT_COREf, 0); 207 _SOC_IF_ERR_EXIT(WRITE_CPORT_POWER_SAVEr(unit, port, reg_val)); 208 209 210 /* Bring MAC OOR */ 211 _SOC_IF_ERR_EXIT(READ_CPORT_MAC_CONTROLr(unit, port, ®_val)); 212 soc_reg_field_set(unit, CPORT_MAC_CONTROLr, ®_val, CMAC_RESETf, 0); 213 _SOC_IF_ERR_EXIT(WRITE_CPORT_MAC_CONTROLr(unit, port, reg_val)); 214 215 if (add_info->interface_config.interface == SOC_PORT_IF_CAUI) { 216 rv = WRITE_CPORT_MODE_REGr(unit, port, 1); 217 _SOC_IF_ERR_EXIT(rv); 218 } else { 219 rv = WRITE_CPORT_MODE_REGr(unit, port, 0); 220 _SOC_IF_ERR_EXIT(rv); 221 } 222 223 /* RSV Mask */ 224 rsv_mask = 0; 225 SHR_BITSET(&rsv_mask, 3); /* Receive terminate/code error */ 226 SHR_BITSET(&rsv_mask, 4); /* CRC error */ 227 SHR_BITSET(&rsv_mask, 6); /* Truncated/Frame out of Range */ 228 SHR_BITSET(&rsv_mask, 17); /* RUNT detected*/ 229 _SOC_IF_ERR_EXIT(WRITE_PGW_MAC_RSV_MASKr(unit, port, rsv_mask)); 230 231 if (PM_4x25_INFO(pm_info)->nof_phys[0]> 0) { 232 /* Get Serdes OOR */ 233 _SOC_IF_ERR_EXIT(pm4x25td_port_tsc_reset_set(unit, port, 1)); 234 _SOC_IF_ERR_EXIT(pm4x25td_port_tsc_reset_set(unit, port, 0)); 235 } 236 } else { /* disable */ 237 238 rv = WRITE_CPORT_MODE_REGr(unit, port, 0); 239 _SOC_IF_ERR_EXIT(rv); 240 241 /* Put Serdes in reset*/ 242 _SOC_IF_ERR_EXIT(pm4x25td_port_tsc_reset_set(unit, port, 1)); 243 244 /* put MAC in reset */ 245 _SOC_IF_ERR_EXIT(READ_CPORT_MAC_CONTROLr(unit, port, ®_val)); 246 soc_reg_field_set(unit, CPORT_MAC_CONTROLr, ®_val, CMAC_RESETf, 1); 247 _SOC_IF_ERR_EXIT(WRITE_CPORT_MAC_CONTROLr(unit, port, reg_val)); 248 249 /* Turn on Power Save */ 250 _SOC_IF_ERR_EXIT(READ_CPORT_POWER_SAVEr(unit, port, ®_val)); 251 soc_reg_field_set(unit, CPORT_POWER_SAVEr, ®_val, CPORT_COREf, 1); 252 _SOC_IF_ERR_EXIT(WRITE_CPORT_POWER_SAVEr(unit, port, reg_val)); 253 } 254 255 exit: 256 SOC_FUNC_RETURN; 257 } 258 259 int _pm4x25td_pm_port_init(int unit, int port, int internal_port, 260 const portmod_port_add_info_t* add_info, int enable) 261 { 262 int rv; 263 uint32 reg_val, flags; 264 SOC_INIT_FUNC_DEFS; 265 266 if(enable) { 267 268 /* Soft reset */ 269 _SOC_IF_ERR_EXIT(READ_CPORT_SOFT_RESETr(unit, port, ®_val)); 270 soc_reg_field_set(unit, CPORT_SOFT_RESETr, ®_val, CPORT_COREf, 1); 271 _SOC_IF_ERR_EXIT(WRITE_CPORT_SOFT_RESETr(unit, port, reg_val)); 272 273 soc_reg_field_set(unit, CPORT_SOFT_RESETr, ®_val, CPORT_COREf, 0); 274 _SOC_IF_ERR_EXIT(WRITE_CPORT_SOFT_RESETr(unit, port, reg_val)); 275 276 /* Port enable */ 277 _SOC_IF_ERR_EXIT(READ_CPORT_ENABLE_REGr(unit, port, ®_val)); 278 soc_reg_field_set(unit, CPORT_ENABLE_REGr, ®_val, PORT0f, 1); 279 _SOC_IF_ERR_EXIT(WRITE_CPORT_ENABLE_REGr(unit, port, reg_val)); 280 281 /* Init MAC */ 282 flags = 0; 283 if(PORTMOD_PORT_ADD_F_RX_SRIP_CRC_GET(add_info)) { 284 flags |= CLMAC_INIT_F_RX_STRIP_CRC; 285 } 286 287 if(PORTMOD_PORT_ADD_F_TX_APPEND_CRC_GET(add_info)) { 288 flags |= CLMAC_INIT_F_TX_APPEND_CRC; 289 } 290 291 if(PORTMOD_PORT_ADD_F_TX_REPLACE_CRC_GET(add_info)) { 292 flags |= CLMAC_INIT_F_TX_REPLACE_CRC; 293 } 294 295 if(PORTMOD_PORT_ADD_F_TX_PASS_THROUGH_CRC_GET(add_info)) { 296 flags |= CLMAC_INIT_F_TX_PASS_THROUGH_CRC_MODE; 297 } 298 299 flags |= CLMAC_INIT_F_IPG_CHECK_DISABLE; 300 301 if(PHYMOD_INTF_MODES_HIGIG_GET(&(add_info->interface_config))) { 302 flags |= CLMAC_INIT_F_IS_HIGIG; 303 } 304 305 rv = clmac_init(unit, port, flags); 306 _SOC_IF_ERR_EXIT(rv); 307 308 /* LSS */ 309 _SOC_IF_ERR_EXIT(READ_CPORT_FAULT_LINK_STATUSr(unit, port, ®_val)); 310 soc_reg_field_set(unit, CPORT_FAULT_LINK_STATUSr, ®_val, 311 REMOTE_FAULTf, 1); 312 soc_reg_field_set(unit, CPORT_FAULT_LINK_STATUSr, ®_val, 313 LOCAL_FAULTf, 1); 314 _SOC_IF_ERR_EXIT(WRITE_CPORT_FAULT_LINK_STATUSr(unit, port, reg_val)); 315 316 317 /* Counter MAX size */ 318 _SOC_IF_ERR_EXIT(READ_PGW_CNTMAXSIZEr(unit, port, ®_val)); 319 soc_reg_field_set(unit, PGW_CNTMAXSIZEr, ®_val, CNTMAXSIZEf, 1518); 320 _SOC_IF_ERR_EXIT(WRITE_PGW_CNTMAXSIZEr(unit, port, reg_val)); 321 322 } else { 323 /* Port disable */ 324 _SOC_IF_ERR_EXIT(READ_CPORT_ENABLE_REGr(unit, port, ®_val)); 325 soc_reg_field_set(unit, CPORT_ENABLE_REGr, ®_val ,PORT0f, 0); 326 _SOC_IF_ERR_EXIT(WRITE_CPORT_ENABLE_REGr(unit, port, reg_val)); 327 328 /* Soft reset */ 329 _SOC_IF_ERR_EXIT(READ_CPORT_SOFT_RESETr(unit, port, ®_val)); 330 soc_reg_field_set(unit, CPORT_SOFT_RESETr, ®_val, CPORT_COREf, 1); 331 _SOC_IF_ERR_EXIT(WRITE_CPORT_SOFT_RESETr(unit, port, reg_val)); 332 } 333 334 exit: 335 SOC_FUNC_RETURN; 336 } 337 338 int pm4x25td_port_soft_reset_toggle(int unit, int port, pm_info_t pm_info, int idx) 339 { 340 uint32 reg_val, old_val; 341 SOC_INIT_FUNC_DEFS; 342 _SOC_IF_ERR_EXIT(READ_CPORT_SOFT_RESETr(unit, port, ®_val)); 343 old_val = reg_val; 344 soc_reg_field_set(unit, CPORT_SOFT_RESETr, ®_val, CPORT_COREf, 1); 345 _SOC_IF_ERR_EXIT(WRITE_CPORT_SOFT_RESETr(unit, port, reg_val)); 346 _SOC_IF_ERR_EXIT(WRITE_CPORT_SOFT_RESETr(unit, port, old_val)); 347 348 exit: 349 SOC_FUNC_RETURN; 350 351 } 352 353 int pm4x25td_ext_phy_attach_to_pm(int unit, pm_info_t pm_info, const phymod_core_access_t* ext_phy_access, uint32 first_phy_lane) 354 { 355 /* empty happy function */ 356 return SOC_E_NONE; 357 } 358 359 360 int pm4x25td_ext_phy_detach_from_pm(int unit, pm_info_t pm_info, phymod_core_access_t* ext_phy_access) 361 { 362 /* empty happy function */ 363 return SOC_E_NONE; 364 } 365 366 int pm4x25td_xphy_lane_attach_to_pm(int unit, pm_info_t pm_info, int iphy, int phyn, const portmod_xphy_lane_connection_t* lane_connection) 367 { 368 /* empty happy function. */ 369 return SOC_E_NONE; 370 } 371 372 373 int pm4x25td_xphy_lane_detach_from_pm(int unit, pm_info_t pm_info, int iphy, int phyn, portmod_xphy_lane_connection_t* lane_connection) 374 { 375 /* empty happy function. */ 376 return SOC_E_NONE; 377 } 378 379 int pm4x25td_port_pgw_reconfig(int unit, int port, pm_info_t pm_info, 380 const portmod_port_mode_info_t *pmode, int phy_port, int flags) 381 { 382 int rv; 383 uint32 reg_val; 384 385 SOC_INIT_FUNC_DEFS; 386 387 if (PORTMOD_PORT_PGW_MAC_RESET == flags) { 388 rv = clmac_discard_set(unit, port, 1); 389 /* 1.a st SOFT_RESET field in CLMAC_CTRL for new ports that use XLMAC */ 390 rv = clmac_soft_reset_set(unit, port, 1); 391 _SOC_IF_ERR_EXIT(rv); 392 393 _SOC_IF_ERR_EXIT(READ_CPORT_MAC_CONTROLr(unit, port, ®_val)); 394 soc_reg_field_set(unit, CPORT_MAC_CONTROLr, ®_val, CMAC_RESETf, 1); 395 _SOC_IF_ERR_EXIT(WRITE_CPORT_MAC_CONTROLr(unit, port, reg_val)); 396 397 /* 1.a set CPORT_CORE field in CPORT_SOFT_RESET for all new ports */ 398 _SOC_IF_ERR_EXIT(READ_CPORT_SOFT_RESETr(unit, port, ®_val)); 399 soc_reg_field_set(unit, CPORT_SOFT_RESETr, ®_val, CPORT_COREf, 1); 400 _SOC_IF_ERR_EXIT(WRITE_CPORT_SOFT_RESETr(unit, port, reg_val)); 401 402 /* Port enable */ 403 _SOC_IF_ERR_EXIT(READ_CPORT_ENABLE_REGr(unit, port, ®_val)); 404 soc_reg_field_set(unit, CPORT_ENABLE_REGr, ®_val, PORT0f, 0); 405 _SOC_IF_ERR_EXIT(WRITE_CPORT_ENABLE_REGr(unit, port, reg_val)); 406 /* cport_power_save.cport_core = 0; */ 407 _SOC_IF_ERR_EXIT(READ_CPORT_POWER_SAVEr(unit, port, ®_val)); 408 soc_reg_field_set(unit, CPORT_POWER_SAVEr, ®_val, CPORT_COREf, 0); 409 _SOC_IF_ERR_EXIT(WRITE_CPORT_POWER_SAVEr(unit, port, reg_val)); 410 } else if (PORTMOD_PORT_PGW_MAC_UNRESET == flags) { 411 /* cport_soft_reset.cport_core = 0; */ 412 _SOC_IF_ERR_EXIT(READ_CPORT_SOFT_RESETr(unit, port, ®_val)); 413 soc_reg_field_set(unit, CPORT_SOFT_RESETr, ®_val, CPORT_COREf, 0); 414 _SOC_IF_ERR_EXIT(WRITE_CPORT_SOFT_RESETr(unit, port, reg_val)); 415 416 /* cport_cport_enable.port0 = 1; */ 417 _SOC_IF_ERR_EXIT(READ_CPORT_ENABLE_REGr(unit, port, ®_val)); 418 soc_reg_field_set(unit, CPORT_ENABLE_REGr, ®_val, PORT0f, 1); 419 _SOC_IF_ERR_EXIT(WRITE_CPORT_ENABLE_REGr(unit, port, reg_val)); 420 421 /* cport_cport_mac_control.cmac_reset = 0; */ 422 _SOC_IF_ERR_EXIT(READ_CPORT_MAC_CONTROLr(unit, port, ®_val)); 423 soc_reg_field_set(unit, CPORT_MAC_CONTROLr, ®_val, CMAC_RESETf, 0); 424 _SOC_IF_ERR_EXIT(WRITE_CPORT_MAC_CONTROLr(unit, port, reg_val)); 425 426 rv = clmac_discard_set(unit, port, 0); 427 _SOC_IF_ERR_EXIT(rv); 428 rv = clmac_rx_enable_set(unit, port, 1); 429 _SOC_IF_ERR_EXIT(rv); 430 rv = clmac_tx_enable_set(unit, port, 1); 431 _SOC_IF_ERR_EXIT(rv); 432 rv = clmac_soft_reset_set(unit, port, 0); 433 _SOC_IF_ERR_EXIT(rv); 434 } 435 436 exit: 437 SOC_FUNC_RETURN; 438 } 439 440 int pm4x25td_port_pfc_config_set (int unit, int port,pm_info_t pm_info, 441 const portmod_pfc_config_t* pfc_cfg) 442 { 443 SOC_INIT_FUNC_DEFS; 444 445 if (pfc_cfg->classes != 8) { 446 return SOC_E_PARAM; 447 } 448 _SOC_IF_ERR_EXIT(clmac_pfc_config_set(unit, port, pfc_cfg)); 449 exit: 450 SOC_FUNC_RETURN; 451 } 452 453 int pm4x25td_port_pfc_config_get (int unit, int port,pm_info_t pm_info, 454 portmod_pfc_config_t* pfc_cfg) 455 { 456 SOC_INIT_FUNC_DEFS; 457 458 pfc_cfg->classes = 8; 459 _SOC_IF_ERR_EXIT(clmac_pfc_config_get(unit, port, pfc_cfg)); 460 exit: 461 SOC_FUNC_RETURN; 462 } 463 464 STATIC 465 void pm4x25td_port_mac_link_up_wait(int unit, int port, pm_info_t pm_info) 466 { 467 468 int i = 0, link = 0, rv = SOC_E_NONE; 469 uint32_t rval; 470 471 /* Link status to IPIPE is updated by H/W and driven based on both the 472 * rising edge of XLPORT_LAG_FAILOVER_CONFIG.LINK_STATUS_UP and 473 * actual link up status from Serdes. 474 * In some loopback scenarios it may take longer time to see Serdes 475 * link up status. 476 */ 477 478 do { 479 rv = READ_CPORT_XGXS0_LN0_STATUS0_REGr(unit, port, &rval); 480 481 if (SOC_FAILURE(rv)) { 482 break; 483 } 484 485 link = soc_reg_field_get(unit, CPORT_XGXS0_LN0_STATUS0_REGr, 486 rval, LINK_STATUSf); 487 if (link) { 488 break; 489 } 490 sal_udelay(PORTMOD_WAIT_TIMEOUT_PER_ITER); 491 } while((++i * PORTMOD_WAIT_TIMEOUT_PER_ITER) < 492 PORTMOD_MAX_LINK_WAIT_TIMEOUT); 493 494 return; 495 } 496 497 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 498 499 #undef _ERR_MSG_MODULE_NAME