cdmac.c (75396B)
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: cdmac.c 10 * Purpose: 11 */ 12 13 #include <soc/portmod/portmod.h> 14 #include <soc/portmod/cdmac.h> 15 #include <soc/drv.h> 16 17 #if defined(PORTMOD_PM8X50_SUPPORT) 18 19 #ifdef _ERR_MSG_MODULE_NAME 20 #error "_ERR_MSG_MODULE_NAME redefined" 21 #endif 22 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT 23 24 /* Minimun and maximum average IPG value in bits */ 25 #define CDMAC_AVE_IPG_MIN 64 26 #define CDMAC_AVE_IPG_MAX 480 27 28 int cdmac_init(int unit, soc_port_t port, uint32 init_flags) 29 { 30 uint32 rval; 31 portmod_pause_control_t pause_control; 32 portmod_pfc_control_t pfc_control; 33 portmod_remote_fault_control_t remote_fault_control; 34 portmod_local_fault_control_t local_fault_control; 35 int crc_mode; 36 int is_strip_crc, is_append_crc, is_replace_crc, is_pass_through_crc; 37 int ctr_enable = 0, ctr_clear = 0; 38 SOC_INIT_FUNC_DEFS; 39 40 is_strip_crc = (init_flags & CDMAC_INIT_F_RX_STRIP_CRC ? 1 : 0); 41 is_append_crc = (init_flags & CDMAC_INIT_F_TX_APPEND_CRC ? 1 : 0); 42 is_replace_crc = (init_flags & CDMAC_INIT_F_TX_REPLACE_CRC ? 1 : 0); 43 is_pass_through_crc = (init_flags & CDMAC_INIT_F_TX_PASS_THROUGH_CRC_MODE? 44 1: 0); 45 46 if(is_append_crc + is_replace_crc + is_pass_through_crc > 1) { 47 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 48 (_SOC_MSG("CDMAC_INIT_F_TX_APPEND_CRC, " 49 "CDMAC_INIT_F_TX_REPLACE_CRC, and " 50 "CDMAC_INIT_F_TX_PASS_THROUGH_CRC_MODE " 51 "can't co-exist"))); 52 } 53 54 /* RX Max size */ 55 _SOC_IF_ERR_EXIT(cdmac_rx_max_size_set(unit, port, CDMAC_JUMBO_MAXSZ)); 56 57 /* 58 * Enable and Clear the CDMAC MIB counters 59 * No need to explicitly set the clear flag to 0 since the 60 * function internally unsets the clear flag 61 */ 62 ctr_enable = TRUE; 63 ctr_clear = TRUE; 64 _SOC_IF_ERR_EXIT(cdmac_mib_counter_control_set(unit, port, ctr_enable, 65 ctr_clear)); 66 67 /* RX Control */ 68 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 69 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, STRIP_CRCf, is_strip_crc); 70 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, RX_PASS_PAUSEf, 0); 71 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, RX_PASS_PFCf, 0); 72 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, RUNT_THRESHOLDf, 73 CDMAC_RUNT_THRESHOLD_DEFAULT); 74 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RX_CTRLr(unit, port, rval)); 75 76 /* TX Control */ 77 if(is_append_crc) { 78 /* CRC is computed on incoming packet data and appended. */ 79 crc_mode = 0; 80 } else if(is_replace_crc) { 81 /* Incoming pkt CRC is replaced with CRC value computed by the MAC */ 82 crc_mode = 2; 83 } else if(is_pass_through_crc) { 84 /* Incoming pkt CRC is passed through without modifications */ 85 crc_mode = 1; 86 } else { 87 /* The CRC mode is determined by the HW */ 88 crc_mode = 3; 89 } 90 91 _SOC_IF_ERR_EXIT(READ_CDMAC_TX_CTRLr(unit, port, &rval)); 92 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, CRC_MODEf, crc_mode); 93 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, DISCARDf, FALSE); 94 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, PAD_ENf, FALSE); 95 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, PAD_THRESHOLDf, 96 CDMAC_PAD_THRESHOLD_SIZE_DEFAULT); 97 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, AVERAGE_IPGf, 98 CDMAC_AVERAGE_IPG_DEFAULT); 99 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, TX_THRESHOLDf, 1); 100 _SOC_IF_ERR_EXIT(WRITE_CDMAC_TX_CTRLr(unit, port, rval)); 101 102 /* ECC control */ 103 /* TX CDC ecc control */ 104 _SOC_IF_ERR_EXIT(READ_CDMAC_ECC_CTRLr(unit, port, &rval)); 105 106 soc_reg_field_set(unit, CDMAC_ECC_CTRLr, &rval, 107 TX_CDC_ECC_CTRL_ENf, 1); 108 soc_reg_field_set(unit, CDMAC_ECC_CTRLr, &rval, TX_CDC_ECC_CTRL_ENf, TRUE); 109 soc_reg_field_set(unit, CDMAC_ECC_CTRLr, &rval, MIB_COUNTER_ECC_CTRL_ENf, 110 TRUE); 111 _SOC_IF_ERR_EXIT(WRITE_CDMAC_ECC_CTRLr(unit, port, rval)); 112 113 /* LSS */ 114 _SOC_IF_ERR_EXIT( 115 portmod_remote_fault_control_t_init(unit,&remote_fault_control)); 116 remote_fault_control.enable = TRUE; 117 remote_fault_control.drop_tx_on_fault = TRUE; 118 _SOC_IF_ERR_EXIT(cdmac_remote_fault_control_set(unit, port, 119 &remote_fault_control)); 120 121 _SOC_IF_ERR_EXIT( 122 portmod_local_fault_control_t_init(unit, &local_fault_control)); 123 local_fault_control.enable = TRUE; 124 local_fault_control.drop_tx_on_fault = TRUE; 125 _SOC_IF_ERR_EXIT(cdmac_local_fault_control_set(unit, port, 126 &local_fault_control)); 127 128 /* Pause */ 129 _SOC_IF_ERR_EXIT(portmod_pause_control_t_init(unit, &pause_control)); 130 pause_control.tx_enable = TRUE; 131 pause_control.rx_enable = TRUE; 132 _SOC_IF_ERR_EXIT(cdmac_pause_control_set(unit, port, &pause_control)); 133 134 /* PFC */ 135 _SOC_IF_ERR_EXIT(cdmac_pfc_control_get(unit, port, &pfc_control)); 136 pfc_control.rx_enable = FALSE; 137 pfc_control.tx_enable = FALSE; 138 pfc_control.stats_en = TRUE; 139 _SOC_IF_ERR_EXIT(cdmac_pfc_control_set(unit, port, &pfc_control)); 140 141 /* MAC control */ 142 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 143 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, LOCAL_LPBKf, FALSE); 144 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, TX_ENf, TRUE); 145 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, TRUE); 146 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, MAC_LINK_DOWN_SEQ_ENf, TRUE); 147 /* de-assert SOFT RESET */ 148 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, SOFT_RESETf, FALSE); 149 _SOC_IF_ERR_EXIT(WRITE_CDMAC_CTRLr(unit, port, rval)); 150 151 exit: 152 SOC_FUNC_RETURN; 153 } 154 155 int cdmac_speed_set(int unit, soc_port_t port, int flags, int speed) 156 { 157 /* 158 * There is nothing to be programmed in CDMAC for Speed. 159 * Speed setting is handled in the serdes. 160 */ 161 return (SOC_E_NONE); 162 } 163 164 int cdmac_speed_get(int unit, soc_port_t port, int *speed) 165 { 166 /* 167 * There is nothing to be programmed in CDMAC for Speed. 168 * Speed setting is handled in the serdes. 169 */ 170 return (SOC_E_NONE); 171 } 172 173 int cdmac_encap_set(int unit, soc_port_t port, int flags, 174 portmod_encap_t encap) 175 { 176 177 uint32 val = 0; 178 uint32 rval; 179 SOC_INIT_FUNC_DEFS; 180 181 /* 182 * Only IEEE encap support, HIGIG not supported. 183 */ 184 switch(encap){ 185 case SOC_ENCAP_IEEE: 186 val = 0; 187 break; 188 case SOC_ENCAP_SOP_ONLY: 189 /* no preamble or sfd, 0xFB is followed by mac da */ 190 val = 5; 191 break; 192 default: 193 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 194 (_SOC_MSG("illegal encap mode %d"), encap)); 195 break; 196 } 197 198 _SOC_IF_ERR_EXIT(READ_CDMAC_MODEr(unit, port, &rval)); 199 soc_reg_field_set(unit, CDMAC_MODEr, &rval, HDR_MODEf, val); 200 _SOC_IF_ERR_EXIT(WRITE_CDMAC_MODEr(unit, port, rval)); 201 202 exit: 203 SOC_FUNC_RETURN; 204 } 205 206 int cdmac_encap_get(int unit, soc_port_t port, int *flags, 207 portmod_encap_t *encap) 208 { 209 uint32 rval; 210 uint32 fld_val; 211 SOC_INIT_FUNC_DEFS; 212 213 (*flags) = 0; 214 215 _SOC_IF_ERR_EXIT(READ_CDMAC_MODEr(unit, port, &rval)); 216 fld_val = soc_reg_field_get(unit, CDMAC_MODEr, rval, HDR_MODEf); 217 218 switch(fld_val){ 219 case 0: 220 *encap = SOC_ENCAP_IEEE; 221 break; 222 case 5: 223 *encap = SOC_ENCAP_SOP_ONLY; 224 break; 225 default: 226 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 227 (_SOC_MSG("unknown encap mode %d"), fld_val)); 228 break; 229 } 230 231 exit: 232 SOC_FUNC_RETURN; 233 } 234 235 int cdmac_enable_set(int unit, soc_port_t port, int flags, int enable) 236 { 237 uint32 rval; 238 239 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 240 241 /* Don't disable TX since it stops egress and hangs if CPU sends */ 242 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, TX_ENf, 1); 243 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, enable? 1: 0); 244 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, SOFT_RESETf, enable? 0: 1); 245 246 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 247 248 return (SOC_E_NONE); 249 } 250 251 int cdmac_enable_get(int unit, soc_port_t port, int flags, int *enable) 252 { 253 uint32 rval; 254 255 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 256 257 if (flags & CDMAC_ENABLE_SET_FLAGS_TX_EN) { 258 *enable = soc_reg_field_get(unit, CDMAC_CTRLr, rval, TX_ENf); 259 } else { 260 *enable = soc_reg_field_get(unit, CDMAC_CTRLr, rval, RX_ENf); 261 } 262 263 return (SOC_E_NONE); 264 } 265 266 /* 267 * This function can be called to either set/reset 268 * the TX/RX or put the MAC in reset/bring the MAC 269 * out of reset. 270 * Only one operation allowed in a single call. 271 */ 272 int cdmac_enable_selective_set(int unit, soc_port_t port, 273 int flags, int enable) 274 { 275 uint32 rval, orig_rval; 276 SOC_INIT_FUNC_DEFS; 277 278 279 if (!(flags == CDMAC_ENABLE_SET_FLAGS_TX_EN) && 280 !(flags == CDMAC_ENABLE_SET_FLAGS_RX_EN) && 281 !(flags == CDMAC_ENABLE_SET_FLAGS_SOFT_RESET)) { 282 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 283 (_SOC_MSG("unknown control flag - %x"), flags)); 284 } 285 286 /* 287 * based on the flags passed the required fields are set/reset 288 */ 289 290 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 291 orig_rval = rval; 292 293 if (flags == CDMAC_ENABLE_SET_FLAGS_TX_EN) { 294 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, TX_ENf, enable? 1: 0); 295 } 296 297 if (flags == CDMAC_ENABLE_SET_FLAGS_RX_EN) { 298 if (enable) { 299 uint32 cdmac_tx_ctrl_rval; 300 301 SOC_IF_ERROR_RETURN(READ_CDMAC_TX_CTRLr(unit, port, &cdmac_tx_ctrl_rval)); 302 303 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 0); 304 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 305 306 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &cdmac_tx_ctrl_rval, DISCARDf, 1); 307 SOC_IF_ERROR_RETURN(WRITE_CDMAC_TX_CTRLr(unit, port, cdmac_tx_ctrl_rval)); 308 sal_usleep(10000); 309 310 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 1); 311 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 312 313 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &cdmac_tx_ctrl_rval, DISCARDf, 0); 314 SOC_IF_ERROR_RETURN(WRITE_CDMAC_TX_CTRLr(unit, port, cdmac_tx_ctrl_rval)); 315 sal_usleep(10000); 316 } else { 317 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 0); 318 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 319 } 320 } 321 322 /* 323 * if enable = 0, bring mac out of reset, else mac in reset. 324 */ 325 if (flags == CDMAC_ENABLE_SET_FLAGS_SOFT_RESET) { 326 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, SOFT_RESETf, enable? 1: 0); 327 } 328 329 /* write only if value changed */ 330 if(rval != orig_rval) { /* write only if value changed */ 331 _SOC_IF_ERR_EXIT(WRITE_CDMAC_CTRLr(unit, port, rval)); 332 } 333 334 exit: 335 SOC_FUNC_RETURN; 336 } 337 338 int cdmac_duplex_set(int unit, soc_port_t port, int duplex) 339 { 340 SOC_INIT_FUNC_DEFS; 341 if (!duplex) { 342 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, 343 (_SOC_MSG("half-duplex unsupported"))); 344 } 345 346 /* Only duplex support, nothing to be done here */ 347 exit: 348 SOC_FUNC_RETURN; 349 } 350 351 int cdmac_duplex_get(int unit, soc_port_t port, int *duplex) 352 { 353 SOC_INIT_FUNC_DEFS; 354 355 /* Only duplex support */ 356 *duplex = TRUE; 357 358 SOC_FUNC_RETURN; 359 } 360 361 362 int cdmac_loopback_set(int unit, soc_port_t port, portmod_loopback_mode_t lb, 363 int enable) 364 { 365 uint32 rval; 366 SOC_INIT_FUNC_DEFS; 367 368 /* only line side loopback supported */ 369 if (lb == portmodLoopbackMacOuter) { 370 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 371 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, LOCAL_LPBKf, 372 enable? 1: 0); 373 _SOC_IF_ERR_EXIT(WRITE_CDMAC_CTRLr(unit, port, rval)); 374 } else { 375 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 376 (_SOC_MSG("unsupported loopback type %d"), lb)); 377 } 378 379 exit: 380 SOC_FUNC_RETURN; 381 } 382 383 int cdmac_loopback_get(int unit, soc_port_t port, portmod_loopback_mode_t lb, 384 int *enable) 385 { 386 uint32 rval; 387 SOC_INIT_FUNC_DEFS; 388 389 if (lb == portmodLoopbackMacOuter) { 390 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 391 *enable = soc_reg_field_get(unit, CDMAC_CTRLr, rval, LOCAL_LPBKf); 392 } else { 393 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 394 (_SOC_MSG("unsupported loopback type %d"), lb)); 395 } 396 397 exit: 398 SOC_FUNC_RETURN; 399 } 400 401 /* 402 * portmod_port_tx_mac_enable_set is the caller function 403 */ 404 int cdmac_tx_enable_set (int unit, soc_port_t port, int enable) 405 { 406 return(cdmac_enable_selective_set(unit, port, 407 CDMAC_ENABLE_SET_FLAGS_TX_EN, enable)); 408 } 409 410 /* 411 * portmod_port_tx_mac_enable_get is the caller function 412 */ 413 int cdmac_tx_enable_get (int unit, soc_port_t port, int *enable) 414 { 415 uint32 rval; 416 417 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 418 *enable = soc_reg_field_get(unit, CDMAC_CTRLr, rval, TX_ENf); 419 420 return (SOC_E_NONE); 421 } 422 423 /* 424 * portmod_port_rx_mac_enable_set is the caller function 425 */ 426 int cdmac_rx_enable_set (int unit, soc_port_t port, int enable) 427 { 428 429 return(cdmac_enable_selective_set(unit, port, 430 CDMAC_ENABLE_SET_FLAGS_RX_EN, enable)); 431 } 432 433 /* 434 * portmod_port_rx_mac_enable_get is the caller function 435 */ 436 int cdmac_rx_enable_get (int unit, soc_port_t port, int *enable) 437 { 438 uint32 rval; 439 440 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 441 *enable = soc_reg_field_get(unit, CDMAC_CTRLr, rval, RX_ENf); 442 443 return (SOC_E_NONE); 444 } 445 446 /* 447 * portmod_port_mac_reset_set is the caller function 448 */ 449 int cdmac_soft_reset_set(int unit, soc_port_t port, int enable) 450 { 451 return(cdmac_enable_selective_set(unit, port, 452 CDMAC_ENABLE_SET_FLAGS_SOFT_RESET, enable)); 453 } 454 455 /* 456 * portmod_port_mac_reset_set is the caller function 457 */ 458 int cdmac_soft_reset_get(int unit, soc_port_t port, int *enable) 459 { 460 uint32 rval; 461 462 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 463 *enable = soc_reg_field_get(unit, CDMAC_CTRLr, rval, SOFT_RESETf); 464 465 return (SOC_E_NONE); 466 } 467 468 int cdmac_tx_mac_sa_set(int unit, soc_port_t port, sal_mac_addr_t mac) 469 { 470 uint64 rval64; 471 SOC_INIT_FUNC_DEFS; 472 473 /* 474 * Write bytes in the following order. 475 * mac[0] -> BYTE 5(MSB) of the MAC address in HW 476 * mac[1] -> BYTE 4 477 * mac[2] -> BYTE 3 478 * mac[3] -> BYTE 2 479 * mac[4] -> BYTE 1 480 * mac[5] -> BYTE 0(LSB) 481 */ 482 COMPILER_64_ZERO(rval64); 483 COMPILER_64_SET(rval64, _shr_uint16_read(&mac[0]), 484 _shr_uint32_read(&mac[2])); 485 486 _SOC_IF_ERR_EXIT(WRITE_CDMAC_TX_MAC_SAr(unit, port, rval64)); 487 488 exit: 489 SOC_FUNC_RETURN; 490 } 491 492 int cdmac_tx_mac_sa_get(int unit, soc_port_t port, sal_mac_addr_t mac) 493 { 494 uint64 rval64, field64; 495 uint32 mac_addr[2]; 496 SOC_INIT_FUNC_DEFS; 497 498 _SOC_IF_ERR_EXIT(READ_CDMAC_TX_MAC_SAr(unit, port, &rval64)); 499 field64 = soc_reg64_field_get(unit, CDMAC_TX_MAC_SAr, rval64, CTRL_SAf); 500 501 mac_addr[0] = COMPILER_64_HI(field64); 502 mac_addr[1] = COMPILER_64_LO(field64); 503 504 /* 505 * Extract bytes in the following order 506 * BYTE 5(MSB) -> mac[0] 507 * BYTE 4 -> mac[1] 508 * BYTE 3 -> mac[2] 509 * BYTE 2 -> mac[3] 510 * BYTE 1 -> mac[4] 511 * BYTE 0(LSB) -> mac[5] 512 */ 513 mac[0] = (mac_addr[0] & 0x0000ff00) >> 8; 514 mac[1] = (mac_addr[0] & 0x000000ff); 515 mac[2] = (mac_addr[1] & 0xff000000) >> 24; 516 mac[3] = (mac_addr[1] & 0x00ff0000) >> 16; 517 mac[4] = (mac_addr[1] & 0x0000ff00) >> 8; 518 mac[5] = (mac_addr[1] & 0x000000ff); 519 520 exit: 521 SOC_FUNC_RETURN; 522 } 523 524 int cdmac_rx_mac_sa_set(int unit, soc_port_t port, sal_mac_addr_t mac) 525 { 526 uint64 rval64; 527 SOC_INIT_FUNC_DEFS; 528 529 COMPILER_64_ZERO(rval64); 530 COMPILER_64_SET(rval64, _shr_uint16_read(&mac[0]), 531 _shr_uint32_read(&mac[2])); 532 533 /* 534 * Write bytes in the following order. 535 * mac[0] -> BYTE 5(MSB) of the MAC address in HW 536 * mac[1] -> BYTE 4 537 * mac[2] -> BYTE 3 538 * mac[3] -> BYTE 2 539 * mac[4] -> BYTE 1 540 * mac[5] -> BYTE 0(LSB) 541 */ 542 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RX_MAC_SAr(unit, port, rval64)); 543 544 exit: 545 SOC_FUNC_RETURN; 546 } 547 548 int cdmac_rx_mac_sa_get(int unit, soc_port_t port, sal_mac_addr_t mac) 549 { 550 uint64 rval64, field64; 551 uint32 mac_addr[2]; 552 SOC_INIT_FUNC_DEFS; 553 554 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_MAC_SAr(unit, port, &rval64)); 555 field64 = soc_reg64_field_get(unit, CDMAC_RX_MAC_SAr, rval64, RX_SAf); 556 557 mac_addr[0] = COMPILER_64_HI(field64); 558 mac_addr[1] = COMPILER_64_LO(field64); 559 560 /* 561 * Extract bytes in the following order 562 * BYTE 5(MSB) -> mac[0] 563 * BYTE 4 -> mac[1] 564 * BYTE 3 -> mac[2] 565 * BYTE 2 -> mac[3] 566 * BYTE 1 -> mac[4] 567 * BYTE 0(LSB) -> mac[5] 568 */ 569 mac[0] = (mac_addr[0] & 0x0000ff00) >> 8; 570 mac[1] = (mac_addr[0] & 0x000000ff); 571 mac[2] = (mac_addr[1] & 0xff000000) >> 24; 572 mac[3] = (mac_addr[1] & 0x00ff0000) >> 16; 573 mac[4] = (mac_addr[1] & 0x0000ff00) >> 8; 574 mac[5] = (mac_addr[1] & 0x000000ff); 575 576 exit: 577 SOC_FUNC_RETURN; 578 } 579 580 int cdmac_rx_vlan_tag_set(int unit, soc_port_t port, int outer_vlan_tag, 581 int inner_vlan_tag) 582 { 583 uint64 rval64; 584 SOC_INIT_FUNC_DEFS; 585 586 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_VLAN_TAGr(unit, port, &rval64)); 587 588 if(inner_vlan_tag == -1) { 589 soc_reg64_field32_set(unit, CDMAC_RX_VLAN_TAGr, &rval64, 590 INNER_VLAN_TAG_ENABLEf, 0); 591 } else { 592 soc_reg64_field32_set(unit, CDMAC_RX_VLAN_TAGr, &rval64, 593 INNER_VLAN_TAGf, inner_vlan_tag); 594 soc_reg64_field32_set(unit, CDMAC_RX_VLAN_TAGr, &rval64, 595 INNER_VLAN_TAG_ENABLEf, 1); 596 } 597 598 if(outer_vlan_tag == -1) { 599 soc_reg64_field32_set(unit, CDMAC_RX_VLAN_TAGr, &rval64, 600 OUTER_VLAN_TAG_ENABLEf, 0); 601 } else { 602 soc_reg64_field32_set(unit, CDMAC_RX_VLAN_TAGr, &rval64, 603 OUTER_VLAN_TAGf, outer_vlan_tag); 604 soc_reg64_field32_set(unit, CDMAC_RX_VLAN_TAGr, &rval64, 605 OUTER_VLAN_TAG_ENABLEf, 1); 606 } 607 608 exit: 609 SOC_FUNC_RETURN; 610 } 611 612 int cdmac_rx_vlan_tag_get(int unit, soc_port_t port, int *outer_vlan_tag, 613 int *inner_vlan_tag) 614 { 615 uint64 rval64; 616 uint32 is_enabled = 0; 617 SOC_INIT_FUNC_DEFS; 618 619 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_VLAN_TAGr(unit, port, &rval64)); 620 621 is_enabled = soc_reg64_field32_get(unit, CDMAC_RX_VLAN_TAGr, rval64, 622 INNER_VLAN_TAG_ENABLEf); 623 if(is_enabled == 0) { 624 *inner_vlan_tag = -1; 625 } else { 626 *inner_vlan_tag = soc_reg64_field32_get(unit, CDMAC_RX_VLAN_TAGr, 627 rval64, INNER_VLAN_TAGf); 628 } 629 630 is_enabled = soc_reg64_field32_get(unit, CDMAC_RX_VLAN_TAGr, rval64, 631 OUTER_VLAN_TAG_ENABLEf); 632 if(is_enabled == 0) { 633 *outer_vlan_tag = -1; 634 } else { 635 *outer_vlan_tag = soc_reg64_field32_get(unit, CDMAC_RX_VLAN_TAGr, 636 rval64, OUTER_VLAN_TAGf); 637 } 638 639 exit: 640 SOC_FUNC_RETURN; 641 } 642 643 int cdmac_rx_max_size_set(int unit, soc_port_t port, int value) 644 { 645 uint32 rval; 646 SOC_INIT_FUNC_DEFS; 647 648 /* 649 * Maximum packet size in receive direction, exclusive of preamble 650 * and CRC in strip mode. Packets greater than this size are 651 * truncated to this value. 652 */ 653 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_MAX_SIZEr(unit, port, &rval)); 654 soc_reg_field_set(unit, CDMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, value); 655 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RX_MAX_SIZEr(unit, port, rval)); 656 657 exit: 658 SOC_FUNC_RETURN; 659 } 660 661 int cdmac_rx_max_size_get(int unit, soc_port_t port, int *value) 662 { 663 uint32 rval; 664 SOC_INIT_FUNC_DEFS; 665 666 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_MAX_SIZEr(unit, port, &rval)); 667 *value = soc_reg_field_get(unit, CDMAC_RX_MAX_SIZEr, rval, RX_MAX_SIZEf); 668 669 exit: 670 SOC_FUNC_RETURN; 671 } 672 673 int cdmac_pad_size_set(int unit, soc_port_t port, int value) 674 { 675 uint32 rval; 676 SOC_INIT_FUNC_DEFS; 677 678 if (((value < CDMAC_PAD_THRESHOLD_SIZE_MIN) || 679 (value > CDMAC_PAD_THRESHOLD_SIZE_MAX)) && 680 (value != 0)) { 681 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 682 (_SOC_MSG("unsupported pad threshold size %d"), value)); 683 } 684 685 /* 686 * If PAD_EN is set, packets smaller than PAD_THRESHOLD are padded 687 * to this size. PAD_THRESHOLD must be >=64 and <= 96. 688 */ 689 _SOC_IF_ERR_EXIT(READ_CDMAC_TX_CTRLr(unit, port, &rval)); 690 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, PAD_ENf, value? 1: 0); 691 if (value) { 692 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, PAD_THRESHOLDf, value); 693 } 694 _SOC_IF_ERR_EXIT(WRITE_CDMAC_TX_CTRLr(unit, port, rval)); 695 696 exit: 697 SOC_FUNC_RETURN; 698 } 699 700 int cdmac_pad_size_get(int unit, soc_port_t port, int *value) 701 { 702 uint32 rval; 703 uint32 pad_en; 704 SOC_INIT_FUNC_DEFS; 705 706 _SOC_IF_ERR_EXIT(READ_CDMAC_TX_CTRLr(unit, port, &rval)); 707 pad_en = soc_reg_field_get(unit, CDMAC_TX_CTRLr, rval, PAD_ENf); 708 if(!pad_en) { 709 *value = 0; 710 } else { 711 *value = soc_reg_field_get(unit, CDMAC_TX_CTRLr, rval, PAD_THRESHOLDf); 712 } 713 714 exit: 715 SOC_FUNC_RETURN; 716 } 717 718 int cdmac_tx_average_ipg_set(int unit, soc_port_t port, int val) 719 { 720 uint32 rval; 721 SOC_INIT_FUNC_DEFS; 722 723 /* 724 * Average inter packet gap can be in the range 8 to 56 or 60. 725 * should be 56 for XLGMII, 60 for XGMII, 726 * default is 12. 727 * Granularity is in bytes. 728 * Input 'val' is in bits. 729 */ 730 if ((val < CDMAC_AVE_IPG_MIN) || (val > CDMAC_AVE_IPG_MAX)) { 731 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 732 (_SOC_MSG("Average IPG is out of range."))); 733 } 734 735 _SOC_IF_ERR_EXIT(READ_CDMAC_TX_CTRLr(unit, port, &rval)); 736 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, AVERAGE_IPGf, val/8); 737 _SOC_IF_ERR_EXIT(WRITE_CDMAC_TX_CTRLr(unit, port, rval)); 738 739 exit: 740 SOC_FUNC_RETURN; 741 } 742 743 int cdmac_tx_average_ipg_get(int unit, soc_port_t port, int *val) 744 { 745 uint32 rval; 746 SOC_INIT_FUNC_DEFS; 747 748 /* 749 * Register value is in bytes. 750 * Output 'val' is in bits. 751 */ 752 753 _SOC_IF_ERR_EXIT(READ_CDMAC_TX_CTRLr(unit, port, &rval)); 754 755 *val = soc_reg_field_get(unit, CDMAC_TX_CTRLr, rval, AVERAGE_IPGf) * 8; 756 757 exit: 758 SOC_FUNC_RETURN; 759 } 760 761 int cdmac_runt_threshold_set(int unit, soc_port_t port, int value) 762 { 763 uint32 rval; 764 SOC_INIT_FUNC_DEFS; 765 766 /* 767 * The threshold, below which the packets are dropped or 768 * marked as runt. Should be programmed >=64 and <= 96 bytes. 769 */ 770 if ((value < CDMAC_RUNT_THRESHOLD_MIN) || 771 (value > CDMAC_RUNT_THRESHOLD_MAX)) { 772 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 773 (_SOC_MSG("runt size should be greater than %d and " 774 "smaller than %d. got %d"), CDMAC_RUNT_THRESHOLD_MIN, 775 CDMAC_RUNT_THRESHOLD_MAX, value)); 776 } 777 778 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 779 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, RUNT_THRESHOLDf, value); 780 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RX_CTRLr(unit, port, rval)); 781 782 exit: 783 SOC_FUNC_RETURN; 784 } 785 786 int cdmac_runt_threshold_get(int unit, soc_port_t port, int *value) 787 { 788 uint32 rval; 789 SOC_INIT_FUNC_DEFS; 790 791 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 792 *value = soc_reg_field_get(unit, CDMAC_RX_CTRLr, rval, RUNT_THRESHOLDf); 793 794 exit: 795 SOC_FUNC_RETURN; 796 } 797 798 /* 799 * portmod_port_remote_fault_control_set is the caller of this function. 800 */ 801 int cdmac_remote_fault_control_set(int unit, soc_port_t port, 802 const portmod_remote_fault_control_t *control) 803 { 804 uint32 rval; 805 SOC_INIT_FUNC_DEFS; 806 807 /* 808 * REMOTE_FAULT_DISABLE determines the transmit response during remote 809 * fault state. The REMOTE_FAULT_STATUS bit is always updated irrespective 810 * of this configuration. 811 * If set, MAC will continue to transmit data irrespective of 812 * REMOTE_FAULT_STATUS. 813 * If reset, MAC transmit behavior is governed by 814 * DROP_TX_DATA_ON_REMOTE_FAULT configuration. 815 */ 816 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 817 818 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, REMOTE_FAULT_DISABLEf, 819 control->enable? 0: 1); /* flip */ 820 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, 821 DROP_TX_DATA_ON_REMOTE_FAULTf, 822 control->drop_tx_on_fault? 1: 0); 823 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RX_LSS_CTRLr(unit, port, rval)); 824 825 exit: 826 SOC_FUNC_RETURN; 827 } 828 829 /* 830 * portmod_port_remote_fault_control_get is the caller of this function. 831 */ 832 int cdmac_remote_fault_control_get(int unit, soc_port_t port, 833 portmod_remote_fault_control_t *control) 834 { 835 uint32 rval; 836 uint32 fval; 837 SOC_INIT_FUNC_DEFS; 838 839 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 840 841 fval = soc_reg_field_get(unit, CDMAC_RX_LSS_CTRLr, rval, 842 REMOTE_FAULT_DISABLEf); 843 /* if fval is reset, indicates enable */ 844 control->enable = (fval? 0: 1); 845 846 fval = soc_reg_field_get(unit, CDMAC_RX_LSS_CTRLr, rval, 847 DROP_TX_DATA_ON_REMOTE_FAULTf); 848 control->drop_tx_on_fault = (fval? 1: 0); 849 850 exit: 851 SOC_FUNC_RETURN; 852 } 853 854 /* 855 * portmod_port_remote_fault_status_get is the caller of this function. 856 * The status bit is clear on read, no seperate api for status_clear 857 * required. 858 */ 859 int cdmac_remote_fault_status_get(int unit, soc_port_t port, int *status) 860 { 861 uint32 rval; 862 uint32 fval; 863 SOC_INIT_FUNC_DEFS; 864 865 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &rval)); 866 /* fault status bits clear on read */ 867 fval = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 868 REMOTE_FAULT_STATUSf); 869 *status = (fval? 1: 0); 870 871 exit: 872 SOC_FUNC_RETURN; 873 } 874 875 /* 876 * portmod_port_local_fault_control_set is the caller of this function. 877 */ 878 int cdmac_local_fault_control_set(int unit, soc_port_t port, 879 const portmod_local_fault_control_t *control) 880 { 881 uint32 rval; 882 SOC_INIT_FUNC_DEFS; 883 884 /* 885 * LOCALFAULT_DISABLE determines the transmit response during remote 886 * fault state. The LOCAL_FAULT_STATUS bit is always updated irrespective 887 * of this configuration. 888 * If set, MAC will continue to transmit data irrespective of 889 * REMOTE_FAULT_STATUS. 890 * If reset, MAC transmit behavior is governed by 891 * DROP_TX_DATA_ON_LOCAL_FAULT configuration. 892 */ 893 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 894 895 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, LOCAL_FAULT_DISABLEf, 896 control->enable? 0: 1); /* flip */ 897 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, 898 DROP_TX_DATA_ON_LOCAL_FAULTf, 899 control->drop_tx_on_fault? 1: 0); 900 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RX_LSS_CTRLr(unit, port, rval)); 901 902 exit: 903 SOC_FUNC_RETURN; 904 } 905 906 /* 907 * portmod_port_local_fault_control_get is the caller of this function. 908 */ 909 int cdmac_local_fault_control_get(int unit, soc_port_t port, 910 portmod_local_fault_control_t *control) 911 { 912 uint32 rval; 913 uint32 fval; 914 SOC_INIT_FUNC_DEFS; 915 916 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 917 918 fval = soc_reg_field_get(unit, CDMAC_RX_LSS_CTRLr, rval, 919 LOCAL_FAULT_DISABLEf); 920 control->enable = (fval? 0: 1); 921 922 fval = soc_reg_field_get(unit, CDMAC_RX_LSS_CTRLr, rval, 923 DROP_TX_DATA_ON_LOCAL_FAULTf); 924 control->drop_tx_on_fault = (fval? 1: 0); 925 926 exit: 927 SOC_FUNC_RETURN; 928 } 929 930 /* 931 * portmod_port_local_fault_status_get is the caller of this function. 932 * The status bit is clear on read, no seperate api for status_clear 933 * required. 934 */ 935 int cdmac_local_fault_status_get(int unit, soc_port_t port, int *status) 936 { 937 uint32 rval; 938 uint32 fval; 939 SOC_INIT_FUNC_DEFS; 940 941 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &rval)); 942 /* fault status bits clear on read */ 943 fval = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 944 LOCAL_FAULT_STATUSf); 945 *status = (fval? 1: 0); 946 947 exit: 948 SOC_FUNC_RETURN; 949 } 950 951 /* 952 * portmod_port_pfc_control_set is the caller of this function. 953 */ 954 int cdmac_pfc_control_set(int unit, soc_port_t port, 955 const portmod_pfc_control_t *control) 956 { 957 uint64 rval64; 958 uint32 rval; 959 SOC_INIT_FUNC_DEFS; 960 961 _SOC_IF_ERR_EXIT(READ_CDMAC_PAUSE_CTRLr(unit, port, &rval64)); 962 963 /** When control->refresh_timer=-1 PFC_REFRESH_TIMER must be set to 964 * 0xFFFF and the PFC_REFRESH_EN must be 1, to be consistent with clmac/xlmac */ 965 if(control->refresh_timer) { 966 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 967 PFC_REFRESH_TIMERf, control->refresh_timer); 968 969 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 970 PFC_REFRESH_ENf, 1); 971 } else { 972 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 973 PFC_REFRESH_ENf, 0); 974 } 975 976 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 977 PFC_XOFF_TIMERf, control->xoff_timer); 978 979 _SOC_IF_ERR_EXIT(WRITE_CDMAC_PAUSE_CTRLr(unit, port, rval64)); 980 981 982 _SOC_IF_ERR_EXIT(READ_CDMAC_PFC_CTRLr(unit, port, &rval)); 983 984 soc_reg_field_set(unit, CDMAC_PFC_CTRLr, &rval, PFC_STATS_ENf, 985 control->stats_en); 986 soc_reg_field_set(unit, CDMAC_PFC_CTRLr, &rval, FORCE_PFC_XONf, 987 control->force_xon); 988 soc_reg_field_set(unit, CDMAC_PFC_CTRLr, &rval, TX_PFC_ENf, 989 control->tx_enable); 990 soc_reg_field_set(unit, CDMAC_PFC_CTRLr, &rval, RX_PFC_ENf, 991 control->rx_enable); 992 993 _SOC_IF_ERR_EXIT(WRITE_CDMAC_PFC_CTRLr(unit, port, rval)); 994 995 exit: 996 SOC_FUNC_RETURN; 997 } 998 999 int cdmac_pfc_control_get(int unit, soc_port_t port, 1000 portmod_pfc_control_t *control) 1001 { 1002 uint64 rval64; 1003 uint32 rval; 1004 uint32 refresh_enable = 0; 1005 uint32 refresh_timer = 0; 1006 SOC_INIT_FUNC_DEFS; 1007 1008 _SOC_IF_ERR_EXIT(READ_CDMAC_PAUSE_CTRLr(unit, port, &rval64)); 1009 1010 refresh_enable = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, rval64, 1011 PFC_REFRESH_ENf); 1012 1013 refresh_timer = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, rval64, 1014 PFC_REFRESH_TIMERf); 1015 1016 control->refresh_timer = (refresh_enable? refresh_timer: 0); 1017 1018 control->xoff_timer = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, 1019 rval64, PFC_XOFF_TIMERf); 1020 1021 _SOC_IF_ERR_EXIT(READ_CDMAC_PFC_CTRLr(unit, port, &rval)); 1022 1023 control->stats_en = soc_reg_field_get(unit, CDMAC_PFC_CTRLr, rval, 1024 PFC_STATS_ENf); 1025 control->force_xon = soc_reg_field_get(unit, CDMAC_PFC_CTRLr, rval, 1026 FORCE_PFC_XONf); 1027 control->tx_enable = soc_reg_field_get(unit, CDMAC_PFC_CTRLr, rval, 1028 TX_PFC_ENf); 1029 control->rx_enable = soc_reg_field_get(unit, CDMAC_PFC_CTRLr, rval, 1030 RX_PFC_ENf); 1031 1032 exit: 1033 SOC_FUNC_RETURN; 1034 } 1035 1036 int cdmac_pause_control_set(int unit, soc_port_t port, 1037 const portmod_pause_control_t *control) 1038 { 1039 uint64 rval64; 1040 SOC_INIT_FUNC_DEFS; 1041 1042 _SOC_IF_ERR_EXIT(READ_CDMAC_PAUSE_CTRLr(unit, port, &rval64)); 1043 1044 if(control->rx_enable || control->tx_enable) { 1045 if(control->refresh_timer > 0 ) { 1046 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 1047 PAUSE_REFRESH_TIMERf, control->refresh_timer); 1048 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 1049 PAUSE_REFRESH_ENf, 1); 1050 } else { 1051 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 1052 PAUSE_REFRESH_ENf, 0); 1053 } 1054 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, 1055 PAUSE_XOFF_TIMERf, control->xoff_timer); 1056 } 1057 1058 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, TX_PAUSE_ENf, 1059 control->tx_enable); 1060 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, RX_PAUSE_ENf, 1061 control->rx_enable); 1062 1063 _SOC_IF_ERR_EXIT(WRITE_CDMAC_PAUSE_CTRLr(unit, port, rval64)); 1064 1065 exit: 1066 SOC_FUNC_RETURN; 1067 } 1068 1069 int cdmac_pause_control_get(int unit, soc_port_t port, 1070 portmod_pause_control_t *control) 1071 { 1072 uint64 rval64; 1073 uint32 refresh_enable; 1074 uint32 refresh_timer; 1075 SOC_INIT_FUNC_DEFS; 1076 1077 _SOC_IF_ERR_EXIT(READ_CDMAC_PAUSE_CTRLr(unit, port, &rval64)); 1078 1079 refresh_enable = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, rval64, 1080 PAUSE_REFRESH_ENf); 1081 refresh_timer = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, rval64, 1082 PAUSE_REFRESH_TIMERf); 1083 1084 control->refresh_timer = (refresh_enable? refresh_timer: -1); 1085 control->xoff_timer = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, 1086 rval64, PAUSE_XOFF_TIMERf); 1087 1088 control->tx_enable = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, rval64, 1089 TX_PAUSE_ENf); 1090 control->rx_enable = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, rval64, 1091 RX_PAUSE_ENf); 1092 1093 exit: 1094 SOC_FUNC_RETURN; 1095 } 1096 1097 int cdmac_pfc_config_set (int unit, int port, 1098 const portmod_pfc_config_t* pfc_cfg) 1099 { 1100 uint32 rval; 1101 uint32 fval[2] = {0}; 1102 uint64 rval64; 1103 uint64 fval64; 1104 1105 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_TYPEr(unit, port, &rval)); 1106 soc_reg_field_set(unit, CDMAC_PFC_TYPEr, &rval, PFC_ETH_TYPEf, 1107 pfc_cfg->type); 1108 SOC_IF_ERROR_RETURN(WRITE_CDMAC_PFC_TYPEr(unit, port, rval)); 1109 1110 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_OPCODEr(unit, port, &rval)); 1111 soc_reg_field_set(unit, CDMAC_PFC_OPCODEr, &rval, PFC_OPCODEf, 1112 pfc_cfg->opcode); 1113 SOC_IF_ERROR_RETURN(WRITE_CDMAC_PFC_OPCODEr(unit, port, rval)); 1114 1115 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_DAr(unit, port, &rval64)); 1116 fval[0] |= pfc_cfg->da_nonoui; 1117 fval[0] |= (pfc_cfg->da_oui & 0xff) << 24; 1118 fval[1] |= (pfc_cfg->da_oui & 0xffff00) >> 8; 1119 1120 COMPILER_64_SET(fval64, fval[1], fval[0]); 1121 soc_reg64_field_set(unit, CDMAC_PFC_DAr, &rval64, PFC_MACDAf, fval64); 1122 SOC_IF_ERROR_RETURN(WRITE_CDMAC_PFC_DAr(unit, port, rval64)); 1123 1124 return (SOC_E_NONE); 1125 } 1126 1127 int cdmac_pfc_config_get (int unit, int port, portmod_pfc_config_t* pfc_cfg) 1128 { 1129 uint32 rval; 1130 uint32 fval[2] = {0}; 1131 uint64 rval64; 1132 uint64 fval64; 1133 1134 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_TYPEr(unit, port, &rval)); 1135 pfc_cfg->type = soc_reg_field_get(unit, CDMAC_PFC_TYPEr, rval, 1136 PFC_ETH_TYPEf); 1137 1138 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_OPCODEr(unit, port, &rval)); 1139 pfc_cfg->opcode = soc_reg_field_get(unit, CDMAC_PFC_OPCODEr, rval, 1140 PFC_OPCODEf); 1141 1142 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_DAr(unit, port, &rval64)); 1143 fval64 = soc_reg64_field_get(unit, CDMAC_PFC_DAr, rval64, PFC_MACDAf); 1144 fval[0] = COMPILER_64_LO(fval64); 1145 fval[1] = COMPILER_64_HI(fval64); 1146 1147 pfc_cfg->da_nonoui = fval[0] & 0xffffff; 1148 pfc_cfg->da_oui = (fval[1] << 8) | (fval[0] >> 24); 1149 1150 return (SOC_E_NONE); 1151 } 1152 1153 1154 int cdmac_pass_control_frame_set(int unit, int port, int value) 1155 { 1156 uint32 rval; 1157 1158 /* 1159 * This configuration is used to drop or pass all control frames 1160 * (with ether type 0x8808) except pause packets. 1161 * If set, all control frames are passed to system side. 1162 * if reset, control frames (including pfc frames wih ether type 0x8808)i 1163 * are dropped in CDMAC. 1164 */ 1165 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 1166 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, 1167 RX_PASS_CTRLf, (value? 1: 0)); 1168 SOC_IF_ERROR_RETURN(WRITE_CDMAC_RX_CTRLr(unit, port, rval)); 1169 1170 return (SOC_E_NONE); 1171 } 1172 1173 1174 int cdmac_pass_control_frame_get(int unit, int port, int *value) 1175 { 1176 uint32 rval; 1177 1178 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 1179 *value = soc_reg_field_get(unit, CDMAC_RX_CTRLr, rval, RX_PASS_CTRLf); 1180 1181 return (SOC_E_NONE); 1182 } 1183 1184 1185 int cdmac_pass_pfc_frame_set(int unit, int port, int value) 1186 { 1187 uint32 rval; 1188 1189 /* 1190 * This configuration is used to pass or drop PFC packets when 1191 * PFC_ETH_TYPE is not equal to 0x8808. 1192 * If set, PFC frames are passed to system side. 1193 * If reset, PFC frames are dropped in CDMAC. 1194 */ 1195 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 1196 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, 1197 RX_PASS_PFCf, (value? 1: 0)); 1198 SOC_IF_ERROR_RETURN(WRITE_CDMAC_RX_CTRLr(unit, port, rval)); 1199 1200 return (SOC_E_NONE); 1201 } 1202 1203 1204 int cdmac_pass_pfc_frame_get(int unit, int port, int *value) 1205 { 1206 uint32 rval; 1207 1208 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 1209 *value = soc_reg_field_get(unit, CDMAC_RX_CTRLr, rval, RX_PASS_PFCf); 1210 1211 return (SOC_E_NONE); 1212 } 1213 1214 1215 int cdmac_pass_pause_frame_set(int unit, int port, int value) 1216 { 1217 uint32 rval; 1218 1219 /* 1220 * If set, PAUSE frames are passed to sytem side. 1221 * If reset, PAUSE frames are dropped in CDMAC 1222 */ 1223 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 1224 soc_reg_field_set(unit, CDMAC_RX_CTRLr, &rval, 1225 RX_PASS_PAUSEf, (value? 1: 0)); 1226 SOC_IF_ERROR_RETURN(WRITE_CDMAC_RX_CTRLr(unit, port, rval)); 1227 1228 return (SOC_E_NONE); 1229 } 1230 1231 1232 int cdmac_pass_pause_frame_get(int unit, int port, int *value) 1233 { 1234 uint32 rval; 1235 1236 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_CTRLr(unit, port, &rval)); 1237 *value = soc_reg_field_get(unit, CDMAC_RX_CTRLr, rval, RX_PASS_PAUSEf); 1238 1239 return (SOC_E_NONE); 1240 } 1241 1242 /* 1243 * LAG FAILOVER 1244 * Following routines are used and invoked for the LAG 1245 * failover feature. 1246 * When a LAG(Trunk) member port goes down, if LAG failover 1247 * is enabled all the tx packets are loopback to RX path. 1248 * This is done by enabling loopback on the port which went 1249 * down, when the port comes back up, the software detects 1250 * the LINK UP event and removes the loopback. 1251 * Programming Sequence: 1252 * CDMAC_CTRL.LAG_FAILOVER_ENf 1/0, enable/disable feature. 1253 * If set, enable LAG Failover. 1254 * This bit has priority over LOCAL_LPBK. The lag failover 1255 * kicks in when the link status selected by LINK_STATUS_SELECT 1256 * transitions from 1 to 0. TSC clock and TSC credits must 1257 * be active for lag failover. 1258 * 1259 * portmod_port_trunk_hwfailover_config_set is the caller 1260 * of this function, which in turn is called by the bcm 1261 * application layer function calls handling the lag hardware 1262 * failover feature. 1263 */ 1264 int cdmac_lag_failover_en_set(int unit, int port, int val) 1265 { 1266 uint32 rval; 1267 1268 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1269 1270 /* need to disable MAC_LINK_DOWN_SEQ_ENf when faliover is enabled */ 1271 if (val) { 1272 uint32 cdmac_tx_ctrl_rval; 1273 SOC_IF_ERROR_RETURN(READ_CDMAC_TX_CTRLr(unit, port, &cdmac_tx_ctrl_rval)); 1274 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, MAC_LINK_DOWN_SEQ_ENf, FALSE); 1275 /* need to reable rx and disable tx discard */ 1276 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 1); 1277 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1278 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &cdmac_tx_ctrl_rval, DISCARDf, 0); 1279 SOC_IF_ERROR_RETURN(WRITE_CDMAC_TX_CTRLr(unit, port, cdmac_tx_ctrl_rval)); 1280 } else { 1281 /*once lag failover is disable, need to restore the MAC_LINK_DOWN_SEQ_EN bit */ 1282 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, MAC_LINK_DOWN_SEQ_ENf, TRUE); 1283 } 1284 1285 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, LAG_FAILOVER_ENf, val); 1286 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1287 1288 return (SOC_E_NONE); 1289 } 1290 1291 /* 1292 * portmod_port_trunk_hwfailover_config_get is the caller 1293 * of this function, returns if the hw lag failover feature 1294 * is enabled on a port. 1295 */ 1296 int cdmac_lag_failover_en_get(int unit, int port, int *val) 1297 { 1298 uint32 rval; 1299 1300 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1301 *val = soc_reg_field_get(unit, CDMAC_CTRLr, rval, LAG_FAILOVER_ENf); 1302 1303 return (SOC_E_NONE); 1304 } 1305 1306 /* 1307 * This function is used to disable the LAG failover feature 1308 * on a port. 1309 * portmod_port_lag_failover_disable is the caller 1310 * of this function, which in turn is called by the bcm 1311 * application layer function calls handling the lag hardware 1312 * failover feature. 1313 */ 1314 int cdmac_lag_failover_disable(int unit, int port) 1315 { 1316 uint32 rval; 1317 1318 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1319 1320 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, LAG_FAILOVER_ENf, 0); 1321 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, LINK_STATUS_SELECTf, 0); 1322 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, REMOVE_FAILOVER_LPBKf, 0); 1323 1324 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1325 1326 return (SOC_E_NONE); 1327 } 1328 1329 /* 1330 * portmod_port_lag_failover_loopback_set is the caller 1331 * of this function. 1332 */ 1333 int cdmac_lag_failover_loopback_set(int unit, int port, int val) 1334 { 1335 uint32 rval; 1336 1337 SOC_IF_ERROR_RETURN(READ_CDMAC_LAG_FAILOVER_STATUSr(unit, port, &rval)); 1338 /* If set, indicates that the port is in lag failover state */ 1339 soc_reg_field_set(unit, CDMAC_LAG_FAILOVER_STATUSr, &rval, 1340 LAG_FAILOVER_LOOPBACKf, val); 1341 SOC_IF_ERROR_RETURN(WRITE_CDMAC_LAG_FAILOVER_STATUSr(unit, port, rval)); 1342 1343 return (SOC_E_NONE); 1344 } 1345 1346 /* 1347 * portmod_port_lag_failover_loopback_get is the caller 1348 * of this function. This function is invoked as part of 1349 * LINK events from LINKSCAN thread 1350 */ 1351 int cdmac_lag_failover_loopback_get(int unit, int port, int *val) 1352 { 1353 uint32 rval; 1354 1355 SOC_IF_ERROR_RETURN(READ_CDMAC_LAG_FAILOVER_STATUSr(unit, port, &rval)); 1356 /* 1357 * The LAG_FAILOVER_LOOPBACK is SET by the hardware if 1358 * the LINK goes down and LAG_FAILOVER_ENf is set on the port. 1359 */ 1360 *val = soc_reg_field_get(unit, CDMAC_LAG_FAILOVER_STATUSr, rval, 1361 LAG_FAILOVER_LOOPBACKf); 1362 1363 return (SOC_E_NONE); 1364 } 1365 1366 /* 1367 * portmod_port_lag_remove_failover_lpbk_set is the caller 1368 * of this function. This function is invoked as part of 1369 * LINK events from LINKSCAN thread 1370 */ 1371 int cdmac_lag_remove_failover_lpbk_set(int unit, int port, int val) 1372 { 1373 uint32 rval; 1374 1375 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1376 /* 1377 * If set, CDMAC port will move from lag failover state to 1378 * normal operation. This bit should be set after link is up. 1379 * A transition from 0 to 1 is required, so first a write with 1380 * 0 should be followed by a write with 1. 1381 * The BCM layer should take care of the calling sequnce as 1382 * part of LINK events. 1383 */ 1384 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, REMOVE_FAILOVER_LPBKf, val); 1385 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1386 1387 return (SOC_E_NONE); 1388 } 1389 1390 /* 1391 * portmod_port_lag_remove_failover_lpbk_get is the caller 1392 * of this function. 1393 */ 1394 int cdmac_lag_remove_failover_lpbk_get(int unit, int port, int *val) 1395 { 1396 uint32 rval; 1397 1398 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1399 *val = soc_reg_field_get(unit, CDMAC_CTRLr, rval, REMOVE_FAILOVER_LPBKf); 1400 1401 return (SOC_E_NONE); 1402 } 1403 1404 int cdmac_reset_fc_timers_on_link_dn_get(int unit, soc_port_t port, int *val) 1405 { 1406 uint32 rval; 1407 1408 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 1409 *val = soc_reg_field_get(unit, CDMAC_RX_LSS_CTRLr, rval, 1410 RESET_FLOW_CONTROL_TIMERS_ON_LINK_DOWNf); 1411 1412 return (SOC_E_NONE); 1413 } 1414 1415 /* 1416 * portmod_port_trunk_hwfailover_config_set is the caller of this 1417 * function. This function is invoked during lag failover config 1418 * on a port. 1419 */ 1420 int cdmac_reset_fc_timers_on_link_dn_set(int unit, soc_port_t port, int val) 1421 { 1422 uint32 rval; 1423 1424 /* 1425 * If set, the receive pause and PFC timers are reset whenever the link 1426 * status is down, or local or remote faults are received. 1427 */ 1428 SOC_IF_ERROR_RETURN(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 1429 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, 1430 RESET_FLOW_CONTROL_TIMERS_ON_LINK_DOWNf, val); 1431 SOC_IF_ERROR_RETURN(WRITE_CDMAC_RX_LSS_CTRLr(unit, port, rval)); 1432 1433 return (SOC_E_NONE); 1434 } 1435 1436 1437 int cdmac_mac_ctrl_set(int unit, int port, uint64 ctrl) 1438 { 1439 uint32 rval; 1440 1441 COMPILER_64_TO_32_LO(rval, ctrl); 1442 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1443 return (SOC_E_NONE); 1444 } 1445 1446 int cdmac_drain_cell_get(int unit, int port, 1447 portmod_drain_cells_t *drain_cells) 1448 { 1449 uint32 rval; 1450 uint64 rval64; 1451 1452 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_CTRLr(unit, port, &rval)); 1453 drain_cells->rx_pfc_en = soc_reg_field_get(unit, CDMAC_PFC_CTRLr, rval, 1454 RX_PFC_ENf); 1455 1456 SOC_IF_ERROR_RETURN(READ_CDMAC_PAUSE_CTRLr(unit, port, &rval64)); 1457 drain_cells->rx_pause = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, 1458 rval64, RX_PAUSE_ENf); 1459 drain_cells->tx_pause = soc_reg64_field32_get(unit, CDMAC_PAUSE_CTRLr, 1460 rval64, TX_PAUSE_ENf); 1461 1462 return (SOC_E_NONE); 1463 } 1464 1465 1466 int cdmac_discard_set(int unit, soc_port_t port, int discard) 1467 { 1468 uint32 rval; 1469 1470 /* Clear Discard fields */ 1471 SOC_IF_ERROR_RETURN(READ_CDMAC_TX_CTRLr(unit, port, &rval)); 1472 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, DISCARDf, discard); 1473 SOC_IF_ERROR_RETURN(WRITE_CDMAC_TX_CTRLr(unit, port, rval)); 1474 1475 return (SOC_E_NONE); 1476 } 1477 1478 1479 int cdmac_drain_cell_stop(int unit, int port, 1480 const portmod_drain_cells_t *drain_cells) 1481 { 1482 uint32 rval; 1483 uint64 rval64; 1484 1485 /* Clear Discard fields */ 1486 SOC_IF_ERROR_RETURN(cdmac_discard_set(unit, port, 0)); 1487 1488 /* set pause fields */ 1489 SOC_IF_ERROR_RETURN(READ_CDMAC_PAUSE_CTRLr(unit, port, &rval64)); 1490 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, RX_PAUSE_ENf, 1491 drain_cells->rx_pause); 1492 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, TX_PAUSE_ENf, 1493 drain_cells->tx_pause); 1494 SOC_IF_ERROR_RETURN(WRITE_CDMAC_PAUSE_CTRLr(unit, port, rval64)); 1495 1496 /* set pfc rx_en fields */ 1497 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_CTRLr(unit, port, &rval)); 1498 soc_reg_field_set(unit, CDMAC_PFC_CTRLr, &rval, RX_PFC_ENf, 1499 drain_cells->rx_pfc_en); 1500 SOC_IF_ERROR_RETURN(WRITE_CDMAC_PFC_CTRLr(unit, port, rval)); 1501 1502 return (SOC_E_NONE); 1503 } 1504 1505 int cdmac_drain_cell_start(int unit, int port) 1506 { 1507 uint32 rval; 1508 uint64 rval64; 1509 1510 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1511 1512 /* Don't disable TX since it stops egress and hangs if CPU sends */ 1513 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, TX_ENf, 1); 1514 /* Disable RX */ 1515 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 0); 1516 1517 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1518 1519 SOC_IF_ERROR_RETURN(READ_CDMAC_PAUSE_CTRLr(unit, port, &rval64)); 1520 soc_reg64_field32_set(unit, CDMAC_PAUSE_CTRLr, &rval64, RX_PAUSE_ENf,0); 1521 SOC_IF_ERROR_RETURN(WRITE_CDMAC_PAUSE_CTRLr(unit, port, rval64)); 1522 1523 SOC_IF_ERROR_RETURN(READ_CDMAC_PFC_CTRLr(unit, port, &rval)); 1524 soc_reg_field_set(unit, CDMAC_PFC_CTRLr, &rval, RX_PFC_ENf, 0); 1525 SOC_IF_ERROR_RETURN(WRITE_CDMAC_PFC_CTRLr(unit, port, rval)); 1526 1527 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1528 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, SOFT_RESETf, 1); 1529 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1530 1531 SOC_IF_ERROR_RETURN(cdmac_discard_set(unit, port, 1)); 1532 1533 return (SOC_E_NONE); 1534 } 1535 1536 1537 int cdmac_txfifo_cell_cnt_get(int unit, int port, uint32* val) 1538 { 1539 uint32 rval; 1540 1541 SOC_IF_ERROR_RETURN(READ_CDMAC_TXFIFO_CELL_CNTr(unit, port, &rval)); 1542 *val = soc_reg_field_get(unit, CDMAC_TXFIFO_CELL_CNTr, rval, CELL_CNTf); 1543 1544 return (SOC_E_NONE); 1545 } 1546 1547 int cdmac_egress_queue_drain_get(int unit, int port, uint64 *mac_ctrl, 1548 int *rx_en) 1549 { 1550 uint32 rval; 1551 1552 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1553 COMPILER_64_SET(*mac_ctrl, 0, rval); 1554 1555 *rx_en = soc_reg_field_get(unit, CDMAC_CTRLr, rval, RX_ENf); 1556 1557 return (SOC_E_NONE); 1558 } 1559 1560 1561 int cdmac_drain_cells_rx_enable(int unit, int port, int rx_en) 1562 { 1563 uint32 rval, orig_rval; 1564 uint32 soft_reset = 0; 1565 1566 /* Enable both TX and RX, de-assert SOFT_RESET */ 1567 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1568 orig_rval = rval; 1569 1570 /* Don't disable TX since it stops egress and hangs if CPU sends */ 1571 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, TX_ENf, 1); 1572 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, rx_en ? 1: 0); 1573 1574 if (rval == orig_rval) { 1575 /* 1576 * To avoid the unexpected early return to prevent this problem. 1577 * 1. Problem occurred for disabling process only. 1578 * 2. To comply original designing scenario, CDMAC_CTRLr.SOFT_RESETf 1579 * is used to early check to see if this port is at disabled state 1580 * already. 1581 */ 1582 soft_reset = soc_reg_field_get(unit, CDMAC_CTRLr, rval, SOFT_RESETf); 1583 if ((rx_en) || (!rx_en && soft_reset)){ 1584 return SOC_E_NONE; 1585 } 1586 } 1587 1588 if (rx_en) { 1589 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, SOFT_RESETf, 0); 1590 } 1591 1592 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1593 1594 return (SOC_E_NONE); 1595 } 1596 1597 int cdmac_egress_queue_drain_rx_en(int unit, int port, int rx_en) 1598 { 1599 uint32 rval; 1600 1601 /* Enable RX, de-assert SOFT_RESET */ 1602 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1603 if (rx_en) { 1604 uint32 cdmac_tx_ctrl_rval; 1605 1606 SOC_IF_ERROR_RETURN(READ_CDMAC_TX_CTRLr(unit, port, &cdmac_tx_ctrl_rval)); 1607 1608 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 0); 1609 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1610 1611 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &cdmac_tx_ctrl_rval, DISCARDf, 1); 1612 SOC_IF_ERROR_RETURN(WRITE_CDMAC_TX_CTRLr(unit, port, cdmac_tx_ctrl_rval)); 1613 sal_usleep(10000); 1614 1615 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 1); 1616 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1617 1618 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &cdmac_tx_ctrl_rval, DISCARDf, 0); 1619 SOC_IF_ERROR_RETURN(WRITE_CDMAC_TX_CTRLr(unit, port, cdmac_tx_ctrl_rval)); 1620 sal_usleep(10000); 1621 } else { 1622 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, 0); 1623 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1624 } 1625 1626 /*Bring mac out of reset */ 1627 SOC_IF_ERROR_RETURN(cdmac_soft_reset_set(unit, port, 0)); 1628 1629 return (SOC_E_NONE); 1630 } 1631 1632 int cdmac_reset_check(int unit, int port, int enable, int *reset) 1633 { 1634 uint32 rval, orig_rval; 1635 1636 *reset = 1; 1637 1638 /* Enable both TX and RX, de-assert SOFT_RESET */ 1639 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1640 orig_rval = rval; 1641 1642 /* In cdmac_enable_set, we never disable TX since it stops egress 1643 * and hangs if CPU sends. 1644 * However, TX_EN will be disabled in bcmi_th3_port_disable 1645 * as part of port disable sequence within SDK. 1646 * As a result, in this functoin, if enable==0, the expected 1647 * register value will be TX_EN==0 && RX_EN==0. 1648 */ 1649 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, TX_ENf, enable? 1: 0); 1650 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, RX_ENf, enable? 1: 0); 1651 1652 if (rval == orig_rval) { 1653 if (enable) { 1654 *reset = 0; 1655 } else { 1656 if (soc_reg_field_get(unit, CDMAC_CTRLr, rval, SOFT_RESETf)) { 1657 *reset = 0; 1658 } 1659 } 1660 } 1661 1662 return (SOC_E_NONE); 1663 } 1664 1665 /* 1666 * portmod_port_trunk_hwfailover_config_set is the caller of this 1667 * function. This function is invoked during lag failover config 1668 * on a port. 1669 */ 1670 int cdmac_sw_link_status_select_set(int unit, soc_port_t port, int enable) 1671 { 1672 uint32 rval; 1673 1674 /* 1675 * This configuration chooses between link status indication from software 1676 * (SW_LINK_STATUSf) or the hardware link status indication from the PCS i 1677 * to MAC. If set, hardware link status is used. 1678 */ 1679 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1680 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, LINK_STATUS_SELECTf, enable); 1681 SOC_IF_ERROR_RETURN(WRITE_CDMAC_CTRLr(unit, port, rval)); 1682 1683 return (SOC_E_NONE); 1684 } 1685 1686 int cdmac_sw_link_status_select_get(int unit, soc_port_t port, int *enable) 1687 { 1688 uint32 rval; 1689 1690 SOC_IF_ERROR_RETURN(READ_CDMAC_CTRLr(unit, port, &rval)); 1691 *enable = soc_reg_field_get(unit, CDMAC_CTRLr, rval, LINK_STATUS_SELECTf); 1692 1693 return (SOC_E_NONE); 1694 } 1695 1696 int cdmac_sw_link_status_set (int unit, soc_port_t port, int link) 1697 { 1698 uint32 rval; 1699 SOC_INIT_FUNC_DEFS; 1700 1701 /* 1702 * This is valid only if LINK_STATUS_SELECT is 0, which means the 1703 * software drives the link status. If SW_LINK_STATUS is set, 1704 * it indicates that the link is active. The use case is if there is 1705 * some other mechanism used for the link status determination other 1706 * than hardware. 1707 */ 1708 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 1709 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, SW_LINK_STATUSf, link); 1710 _SOC_IF_ERR_EXIT(WRITE_CDMAC_CTRLr(unit, port, rval)); 1711 1712 exit: 1713 SOC_FUNC_RETURN; 1714 } 1715 1716 int cdmac_sw_link_status_get (int unit, soc_port_t port, int *link) 1717 { 1718 uint32 rval; 1719 int link_status_sel = 0; 1720 SOC_INIT_FUNC_DEFS; 1721 1722 /* 1723 * check if link status selection is software based, if yes return 1724 * sw_link_status. 1725 */ 1726 _SOC_IF_ERR_EXIT( 1727 cdmac_sw_link_status_select_get(unit, port, &link_status_sel)); 1728 1729 /* link status selection is software based */ 1730 if (!link_status_sel) { 1731 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 1732 *link = soc_reg_field_get(unit, CDMAC_CTRLr, rval, SW_LINK_STATUSf); 1733 } 1734 1735 exit: 1736 SOC_FUNC_RETURN; 1737 } 1738 1739 int cdmac_mib_counter_control_set(int unit, soc_port_t port, 1740 int enable, int clear) 1741 { 1742 uint32 rval; 1743 1744 /* 1745 * For enabling the MIB statistics counters for a port, the ENABLE field 1746 * must be set. 1747 * To reset/clear MIB statistics counters, CLEAR field should be set 1. 1748 * A low-to-high(0->1) transition on this bit(CLEAR field) will trigger 1749 * the counter-clear operation. 1750 * Please Note: 1751 * If a subsequent counter-clear operation is required, this bit has to 1752 * be first written to 0 and then written to 1. Instead of doing this 1753 * setting CLEAR field to 0 after setting to 1. 1754 * SW name for CLEAR field is CNT_CLEARf. 1755 */ 1756 SOC_IF_ERROR_RETURN(READ_CDMAC_MIB_COUNTER_CTRLr(unit, port, &rval)); 1757 soc_reg_field_set(unit, CDMAC_MIB_COUNTER_CTRLr, &rval, 1758 ENABLEf, enable); 1759 soc_reg_field_set(unit, CDMAC_MIB_COUNTER_CTRLr, &rval, CNT_CLEARf, clear); 1760 1761 SOC_IF_ERROR_RETURN(WRITE_CDMAC_MIB_COUNTER_CTRLr(unit, port, rval)); 1762 1763 /* 1764 * set CLEARf to 0, this operation is not mandatory, adding to 1765 * remove ambiguity in interpretation if a read on this register 1766 */ 1767 if (clear) { 1768 SOC_IF_ERROR_RETURN(READ_CDMAC_MIB_COUNTER_CTRLr(unit, port, &rval)); 1769 soc_reg_field_set(unit, CDMAC_MIB_COUNTER_CTRLr, &rval, CNT_CLEARf, 0); 1770 SOC_IF_ERROR_RETURN(WRITE_CDMAC_MIB_COUNTER_CTRLr(unit, port, rval)); 1771 } 1772 1773 return (SOC_E_NONE); 1774 } 1775 1776 /* 1777 * portmod_port_cntmaxsize_set is caller of this function 1778 */ 1779 int cdmac_cntmaxsize_set(int unit, int port, int val) 1780 { 1781 uint32 rval; 1782 int field_len = 0; 1783 SOC_INIT_FUNC_DEFS; 1784 1785 field_len = soc_reg_field_length(unit, CDMAC_MIB_COUNTER_CTRLr, 1786 CNTMAXSIZEf); 1787 1788 if ((!field_len) || (val > ((1 << field_len) - 1))) { 1789 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 1790 (_SOC_MSG("invalid field length(%d) or value(%d)"), 1791 field_len, val)); 1792 } 1793 /* 1794 * The maximum packet size that is used in statistics counter updates. 1795 * default size is 1518. Note if RX_MAX_SIZE(max frame size received) 1796 * is greater than CNTMAXSIZEf, a good packet that is valid CRC and 1797 * contains no other errors, will increment the OVR(oversize) counters 1798 * if the length of the packet > CNTMAXSIZE < RX_MAX_SIZE values. 1799 * Having CNTMAXSIZE > RX_MAX_SIZE is not recommended. 1800 * This is generally taken care in the statistics module while 1801 * accumulating the counts. 1802 */ 1803 _SOC_IF_ERR_EXIT(READ_CDMAC_MIB_COUNTER_CTRLr(unit, port, &rval)); 1804 soc_reg_field_set(unit, CDMAC_MIB_COUNTER_CTRLr, &rval, CNTMAXSIZEf, val); 1805 _SOC_IF_ERR_EXIT(WRITE_CDMAC_MIB_COUNTER_CTRLr(unit, port, rval)); 1806 1807 exit: 1808 SOC_FUNC_RETURN; 1809 } 1810 1811 /* 1812 * portmod_port_cntmaxsize_get is caller of this function 1813 */ 1814 int cdmac_cntmaxsize_get(int unit, int port, int *val) 1815 { 1816 uint32 rval; 1817 SOC_INIT_FUNC_DEFS; 1818 1819 _SOC_IF_ERR_EXIT(READ_CDMAC_MIB_COUNTER_CTRLr(unit, port, &rval)); 1820 *val = soc_reg_field_get(unit, CDMAC_MIB_COUNTER_CTRLr, rval, CNTMAXSIZEf); 1821 1822 exit: 1823 SOC_FUNC_RETURN; 1824 } 1825 1826 /* 1827 * This function controls which RSV(Receive statistics vector) event 1828 * causes a purge event that triggers RXERR to be set for the packet 1829 * sent by the MAC to the IP. These bits are used to mask RSV[34:16] 1830 * for CDMAC; bit[18] of MASK maps to bit[34] of RSV, bit[0] of MASK 1831 * maps to bit[16] of RSV. 1832 * Enable : Set 0. Go through 1833 * Disable: Set 1. Purged. 1834 * bit[18] --> PFC frame detected 1835 * bit[17] --> Reserved 1836 * bit[16] --> Reserved 1837 * bit[15] --> Unicast detected 1838 * bit[14] --> VLAN tag detected 1839 * bit[13] --> Unsupported opcode detected 1840 * bit[12] --> Pause frame received 1841 * bit[11] --> Control frame received 1842 * bit[10] --> Promiscuous packet detected 1843 * bit[ 9] --> Broadcast detected 1844 * bit[ 8] --> Multicast detected 1845 * bit[ 7] --> Receive OK 1846 * bit[ 6] --> Truncated/Frame out of Range 1847 * bit[ 5] --> Frame length not out of range, but incorrect - 1848 * IEEE length check failed 1849 * bit[ 4] --> CRC error 1850 * bit[ 3] --> Receive terminate/code error 1851 * bit[ 2] --> Unsupported DA for pause/PFC packets detected 1852 * bit[ 1] --> Stack VLAN detected 1853 * bit[ 0] --> Wrong SA 1854 */ 1855 int cdmac_rsv_mask_control_set(int unit, int port, uint32 flags, uint32 value) 1856 { 1857 1858 int i = 0; 1859 uint32 tmp_mask = CDMAC_RSV_MASK_MIN; 1860 uint32 rsv_mask = 0; 1861 SOC_INIT_FUNC_DEFS; 1862 1863 if (flags > CDMAC_RSV_MASK_ALL) { 1864 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 1865 (_SOC_MSG("invalid mask %x"), flags)); 1866 } 1867 1868 _SOC_IF_ERR_EXIT(cdmac_rsv_mask_get(unit, port, &rsv_mask)); 1869 1870 while(tmp_mask <= CDMAC_RSV_MASK_MAX) { 1871 if (flags & tmp_mask) { 1872 /* 1873 * if value = 1 means Enable, set the mask to 0. 1874 * if value = 0 means Purge, set the mask to 1. 1875 */ 1876 if (value) { 1877 SHR_BITCLR(&rsv_mask, i); 1878 } else { 1879 SHR_BITSET(&rsv_mask, i); 1880 } 1881 } 1882 tmp_mask = (1 << ++i); 1883 } 1884 1885 _SOC_IF_ERR_EXIT(cdmac_rsv_mask_set(unit, port, rsv_mask)); 1886 1887 exit: 1888 SOC_FUNC_RETURN; 1889 } 1890 1891 int cdmac_rsv_mask_control_get(int unit, int port, uint32 flags, uint32 *value) 1892 { 1893 1894 uint32 rsv_mask; 1895 SOC_INIT_FUNC_DEFS; 1896 1897 /* Check if only 1 bit is set in flags */ 1898 if ((flags > CDMAC_RSV_MASK_MAX) || ((flags) & (flags - 1))) { 1899 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 1900 (_SOC_MSG("invalid mask %x"), flags)); 1901 } 1902 1903 _SOC_IF_ERR_EXIT(cdmac_rsv_mask_get(unit, port, &rsv_mask)); 1904 1905 /* 1906 * if bit in rsv_mask = 0 means Enable, return 1. 1907 * if bit in rsv_mask = 1 means Purge, return 0. 1908 */ 1909 *value = (rsv_mask & flags)? 0: 1; 1910 1911 exit: 1912 SOC_FUNC_RETURN; 1913 } 1914 1915 int cdmac_rsv_mask_set(int unit, int port, uint32 rsv_mask) 1916 { 1917 uint32 rval; 1918 SOC_INIT_FUNC_DEFS; 1919 1920 if (rsv_mask > CDMAC_RSV_MASK_ALL) { 1921 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 1922 (_SOC_MSG("invalid mask %x"), rsv_mask)); 1923 } 1924 1925 _SOC_IF_ERR_EXIT(READ_CDMAC_RSV_MASKr(unit, port, &rval)); 1926 soc_reg_field_set(unit, CDMAC_RSV_MASKr, &rval, MASKf, rsv_mask); 1927 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RSV_MASKr(unit, port, rsv_mask)); 1928 1929 exit: 1930 SOC_FUNC_RETURN; 1931 } 1932 1933 int cdmac_rsv_mask_get(int unit, int port, uint32 *rsv_mask) 1934 { 1935 uint32 rval; 1936 SOC_INIT_FUNC_DEFS; 1937 1938 _SOC_IF_ERR_EXIT(READ_CDMAC_RSV_MASKr(unit, port, &rval)); 1939 *rsv_mask = soc_reg_field_get(unit, CDMAC_RSV_MASKr, rval, MASKf); 1940 1941 exit: 1942 SOC_FUNC_RETURN; 1943 } 1944 1945 int cdmac_link_down_sequence_enable_set(int unit, int port, uint32 value) 1946 { 1947 uint32 rval; 1948 SOC_INIT_FUNC_DEFS; 1949 1950 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 1951 soc_reg_field_set(unit, CDMAC_CTRLr, &rval, MAC_LINK_DOWN_SEQ_ENf, 1952 (value)? 1: 0); 1953 _SOC_IF_ERR_EXIT(WRITE_CDMAC_CTRLr(unit, port, rval)); 1954 1955 exit: 1956 SOC_FUNC_RETURN; 1957 } 1958 1959 int cdmac_link_down_sequence_enable_get(int unit, int port, uint32 *value) 1960 { 1961 uint32 rval; 1962 SOC_INIT_FUNC_DEFS; 1963 1964 _SOC_IF_ERR_EXIT(READ_CDMAC_CTRLr(unit, port, &rval)); 1965 *value = soc_reg_field_get(unit, CDMAC_CTRLr, rval, 1966 MAC_LINK_DOWN_SEQ_ENf); 1967 1968 exit: 1969 SOC_FUNC_RETURN; 1970 } 1971 1972 int cdmac_interrupt_enable_get(int unit, int port, int intr_type, uint32 *value) 1973 { 1974 uint32 rval; 1975 SOC_INIT_FUNC_DEFS; 1976 1977 _SOC_IF_ERR_EXIT(READ_CDMAC_INTR_ENABLEr(unit, port, &rval)); 1978 1979 switch(intr_type) { 1980 case portmodIntrTypeTxPktUnderflow : 1981 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 1982 TX_PKT_UNDERFLOWf); 1983 break; 1984 case portmodIntrTypeTxPktOverflow : 1985 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 1986 TX_PKT_OVERFLOWf); 1987 break; 1988 case portmodIntrTypeTxCdcSingleBitErr : 1989 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 1990 TX_CDC_SINGLE_BIT_ERRf); 1991 break; 1992 case portmodIntrTypeTxCdcDoubleBitErr : 1993 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 1994 TX_CDC_DOUBLE_BIT_ERRf); 1995 break; 1996 case portmodIntrTypeLocalFaultStatus : 1997 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 1998 LOCAL_FAULT_STATUSf); 1999 break; 2000 case portmodIntrTypeRemoteFaultStatus : 2001 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 2002 REMOTE_FAULT_STATUSf); 2003 break; 2004 case portmodIntrTypeLinkInterruptionStatus : 2005 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 2006 LINK_INTERRUPTION_STATUSf); 2007 break; 2008 case portmodIntrTypeMibMemSingleBitErr : 2009 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 2010 MIB_COUNTER_SINGLE_BIT_ERRf); 2011 break; 2012 case portmodIntrTypeMibMemDoubleBitErr : 2013 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 2014 MIB_COUNTER_DOUBLE_BIT_ERRf); 2015 break; 2016 case portmodIntrTypeMibMemMultipleBitErr : 2017 *value = soc_reg_field_get(unit, CDMAC_INTR_ENABLEr, rval, 2018 MIB_COUNTER_MULTIPLE_ERRf); 2019 break; 2020 default: 2021 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2022 (_SOC_MSG("Invalid interrupt type"))); 2023 break; 2024 } 2025 2026 exit: 2027 SOC_FUNC_RETURN; 2028 } 2029 2030 int cdmac_interrupt_enable_set(int unit, int port, int intr_type, uint32 value) 2031 { 2032 uint32 rval; 2033 SOC_INIT_FUNC_DEFS; 2034 2035 _SOC_IF_ERR_EXIT(READ_CDMAC_INTR_ENABLEr(unit, port, &rval)); 2036 2037 switch(intr_type) { 2038 case portmodIntrTypeTxPktUnderflow : 2039 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2040 TX_PKT_UNDERFLOWf, value); 2041 break; 2042 case portmodIntrTypeTxPktOverflow : 2043 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2044 TX_PKT_OVERFLOWf, value); 2045 break; 2046 case portmodIntrTypeTxCdcSingleBitErr : 2047 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2048 TX_CDC_SINGLE_BIT_ERRf, value); 2049 break; 2050 case portmodIntrTypeTxCdcDoubleBitErr : 2051 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2052 TX_CDC_DOUBLE_BIT_ERRf, value); 2053 break; 2054 case portmodIntrTypeLocalFaultStatus : 2055 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2056 LOCAL_FAULT_STATUSf, value); 2057 break; 2058 case portmodIntrTypeRemoteFaultStatus : 2059 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2060 REMOTE_FAULT_STATUSf, value); 2061 break; 2062 case portmodIntrTypeLinkInterruptionStatus : 2063 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2064 LINK_INTERRUPTION_STATUSf, value); 2065 break; 2066 case portmodIntrTypeMibMemSingleBitErr : 2067 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2068 MIB_COUNTER_SINGLE_BIT_ERRf, value); 2069 break; 2070 case portmodIntrTypeMibMemDoubleBitErr : 2071 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2072 MIB_COUNTER_DOUBLE_BIT_ERRf, value); 2073 break; 2074 case portmodIntrTypeMibMemMultipleBitErr : 2075 soc_reg_field_set(unit, CDMAC_INTR_ENABLEr, &rval, 2076 MIB_COUNTER_MULTIPLE_ERRf, value); 2077 break; 2078 default: 2079 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2080 (_SOC_MSG("Invalid interrupt type"))); 2081 break; 2082 } 2083 2084 _SOC_IF_ERR_EXIT(WRITE_CDMAC_INTR_ENABLEr(unit, port, rval)); 2085 2086 exit: 2087 SOC_FUNC_RETURN; 2088 } 2089 2090 int cdmac_interrupt_status_get(int unit, int port, int intr_type, uint32 *value) 2091 { 2092 uint32 rval; 2093 uint32 read_ecc_status = FALSE; 2094 soc_field_t field = INVALIDf; 2095 SOC_INIT_FUNC_DEFS; 2096 2097 switch(intr_type) { 2098 case portmodIntrTypeTxPktUnderflow : 2099 /* Clear on Read Operation */ 2100 _SOC_IF_ERR_EXIT(READ_CDMAC_FIFO_STATUSr(unit, port, &rval)); 2101 *value = soc_reg_field_get(unit, CDMAC_FIFO_STATUSr, rval, 2102 TX_PKT_UNDERFLOWf); 2103 break; 2104 case portmodIntrTypeTxPktOverflow : 2105 /* Clear on Read Operation */ 2106 _SOC_IF_ERR_EXIT(READ_CDMAC_FIFO_STATUSr(unit, port, &rval)); 2107 *value = soc_reg_field_get(unit, CDMAC_FIFO_STATUSr, rval, 2108 TX_PKT_OVERFLOWf); 2109 break; 2110 case portmodIntrTypeLocalFaultStatus : 2111 /* Clear on Read Operation */ 2112 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &rval)); 2113 *value = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 2114 LOCAL_FAULT_STATUSf); 2115 break; 2116 case portmodIntrTypeRemoteFaultStatus : 2117 /* Clear on Read Operation */ 2118 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &rval)); 2119 *value = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 2120 REMOTE_FAULT_STATUSf); 2121 break; 2122 case portmodIntrTypeLinkInterruptionStatus : 2123 /* Clear on Read Operation */ 2124 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &rval)); 2125 *value = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 2126 LINK_INTERRUPTION_STATUSf); 2127 break; 2128 case portmodIntrTypeTxCdcSingleBitErr : 2129 read_ecc_status = TRUE; 2130 field = TX_CDC_SINGLE_BIT_ERRf; 2131 break; 2132 case portmodIntrTypeTxCdcDoubleBitErr : 2133 read_ecc_status = TRUE; 2134 field = TX_CDC_DOUBLE_BIT_ERRf; 2135 break; 2136 case portmodIntrTypeMibMemSingleBitErr : 2137 read_ecc_status = TRUE; 2138 field = MIB_COUNTER_SINGLE_BIT_ERRf; 2139 break; 2140 case portmodIntrTypeMibMemDoubleBitErr : 2141 read_ecc_status = TRUE; 2142 field = MIB_COUNTER_DOUBLE_BIT_ERRf; 2143 break; 2144 case portmodIntrTypeMibMemMultipleBitErr : 2145 read_ecc_status = TRUE; 2146 field = MIB_COUNTER_MULTIPLE_ERRf; 2147 break; 2148 default: 2149 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2150 (_SOC_MSG("Invalid interrupt type"))); 2151 break; 2152 } 2153 2154 /* Read ECC status register */ 2155 if (read_ecc_status) { 2156 /* Clear on Read Operation */ 2157 _SOC_IF_ERR_EXIT(READ_CDMAC_ECC_STATUSr(unit, port, &rval)); 2158 2159 *value = soc_reg_field_get(unit, CDMAC_ECC_STATUSr, rval, field); 2160 } 2161 2162 exit: 2163 SOC_FUNC_RETURN; 2164 } 2165 2166 int cdmac_interrupts_status_get(int unit, int port, int arr_max_size, 2167 uint32* intr_arr, uint32* size) 2168 { 2169 uint32 cnt = 0; 2170 uint32 rval; 2171 SOC_INIT_FUNC_DEFS; 2172 2173 /* Clear on Read */ 2174 _SOC_IF_ERR_EXIT(READ_CDMAC_INTR_STATUSr(unit, port, &rval)); 2175 2176 /* Read FIFO STATUS - Clear on Read Operation */ 2177 _SOC_IF_ERR_EXIT(READ_CDMAC_FIFO_STATUSr(unit, port, &rval)); 2178 2179 if (soc_reg_field_get(unit, CDMAC_FIFO_STATUSr, rval, TX_PKT_UNDERFLOWf)) { 2180 if (cnt >= arr_max_size) { 2181 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2182 (_SOC_MSG("Insufficient Array size"))); 2183 } 2184 intr_arr[cnt++] = portmodIntrTypeTxPktUnderflow; 2185 } 2186 2187 if (soc_reg_field_get(unit, CDMAC_FIFO_STATUSr, rval, TX_PKT_OVERFLOWf)) { 2188 if (cnt >= arr_max_size) { 2189 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2190 (_SOC_MSG("Insufficient Array size"))); 2191 } 2192 intr_arr[cnt++] = portmodIntrTypeTxPktOverflow; 2193 } 2194 2195 /* Read RX LSS STATUS register - Clear on Read Operation */ 2196 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &rval)); 2197 2198 if (soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 2199 LOCAL_FAULT_STATUSf)) { 2200 if (cnt >= arr_max_size) { 2201 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2202 (_SOC_MSG("Insufficient Array size"))); 2203 } 2204 intr_arr[cnt++] = portmodIntrTypeLocalFaultStatus; 2205 } 2206 2207 if (soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 2208 REMOTE_FAULT_STATUSf)) { 2209 if (cnt >= arr_max_size) { 2210 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2211 (_SOC_MSG("Insufficient Array size"))); 2212 } 2213 intr_arr[cnt++] = portmodIntrTypeRemoteFaultStatus; 2214 } 2215 2216 if (soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 2217 LINK_INTERRUPTION_STATUSf)) { 2218 if (cnt >= arr_max_size) { 2219 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2220 (_SOC_MSG("Insufficient Array size"))); 2221 } 2222 intr_arr[cnt++] = portmodIntrTypeLinkInterruptionStatus; 2223 } 2224 2225 /* Read ECC STATUS register - Clear on Read Operation */ 2226 _SOC_IF_ERR_EXIT(READ_CDMAC_ECC_STATUSr(unit, port, &rval)); 2227 2228 if (soc_reg_field_get(unit, CDMAC_ECC_STATUSr, rval, 2229 TX_CDC_SINGLE_BIT_ERRf)) { 2230 if (cnt >= arr_max_size) { 2231 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2232 (_SOC_MSG("Insufficient Array size"))); 2233 } 2234 intr_arr[cnt++] = portmodIntrTypeTxCdcSingleBitErr; 2235 } 2236 2237 if (soc_reg_field_get(unit, CDMAC_ECC_STATUSr, rval, 2238 TX_CDC_DOUBLE_BIT_ERRf)) { 2239 if (cnt >= arr_max_size) { 2240 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2241 (_SOC_MSG("Insufficient Array size"))); 2242 } 2243 intr_arr[cnt++] = portmodIntrTypeTxCdcDoubleBitErr; 2244 } 2245 2246 if (soc_reg_field_get(unit, CDMAC_ECC_STATUSr, rval, 2247 MIB_COUNTER_SINGLE_BIT_ERRf)) { 2248 if (cnt >= arr_max_size) { 2249 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2250 (_SOC_MSG("Insufficient Array size"))); 2251 } 2252 intr_arr[cnt++] = portmodIntrTypeMibMemSingleBitErr; 2253 } 2254 2255 if (soc_reg_field_get(unit, CDMAC_ECC_STATUSr, rval, 2256 MIB_COUNTER_DOUBLE_BIT_ERRf)) { 2257 if (cnt >= arr_max_size) { 2258 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2259 (_SOC_MSG("Insufficient Array size"))); 2260 } 2261 intr_arr[cnt++] = portmodIntrTypeMibMemDoubleBitErr; 2262 } 2263 2264 if (soc_reg_field_get(unit, CDMAC_ECC_STATUSr, rval, 2265 MIB_COUNTER_MULTIPLE_ERRf)) { 2266 if (cnt >= arr_max_size) { 2267 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, 2268 (_SOC_MSG("Insufficient Array size"))); 2269 } 2270 intr_arr[cnt++] = portmodIntrTypeMibMemMultipleBitErr; 2271 } 2272 2273 *size = cnt; 2274 2275 exit: 2276 SOC_FUNC_RETURN; 2277 } 2278 2279 int cdmac_link_interrupt_ordered_set_enable(int unit, int port, uint32 enable) 2280 { 2281 uint32 rval; 2282 SOC_INIT_FUNC_DEFS; 2283 2284 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 2285 if (enable) { 2286 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, FORCE_LINK_INTERRUPT_OSf, 1); 2287 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, FAULT_SOURCE_FOR_TXf, 2); 2288 } else { 2289 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, FORCE_LINK_INTERRUPT_OSf, 0); 2290 soc_reg_field_set(unit, CDMAC_RX_LSS_CTRLr, &rval, FAULT_SOURCE_FOR_TXf, 0); 2291 } 2292 _SOC_IF_ERR_EXIT(WRITE_CDMAC_RX_LSS_CTRLr(unit, port, rval)); 2293 2294 exit: 2295 SOC_FUNC_RETURN; 2296 } 2297 2298 int cdmac_link_interrupt_ordered_set_enable_get(int unit, int port, uint32* enable) 2299 { 2300 uint32 rval; 2301 SOC_INIT_FUNC_DEFS; 2302 2303 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_CTRLr(unit, port, &rval)); 2304 *enable = soc_reg_field_get(unit, CDMAC_RX_LSS_CTRLr, rval, FORCE_LINK_INTERRUPT_OSf); 2305 2306 exit: 2307 SOC_FUNC_RETURN; 2308 } 2309 2310 2311 int cdmac_link_interruption_live_status_get(int unit, int port, uint32* status) 2312 { 2313 uint32 rval; 2314 SOC_INIT_FUNC_DEFS; 2315 2316 _SOC_IF_ERR_EXIT(READ_CDMAC_RX_LSS_STATUSr(unit, port, &rval)); 2317 /* fault status bits clear on read */ 2318 *status = soc_reg_field_get(unit, CDMAC_RX_LSS_STATUSr, rval, 2319 LINK_INTERRUPTION_LIVE_STATUSf); 2320 exit: 2321 SOC_FUNC_RETURN; 2322 } 2323 2324 int cdmac_tx_stall_enable_set(int unit, int port, uint32 enable) 2325 { 2326 uint32 rval; 2327 SOC_INIT_FUNC_DEFS; 2328 2329 _SOC_IF_ERR_EXIT(READ_CDMAC_TX_CTRLr(unit, port, &rval)); 2330 2331 soc_reg_field_set(unit, CDMAC_TX_CTRLr, &rval, STALL_TXf, enable); 2332 2333 _SOC_IF_ERR_EXIT(WRITE_CDMAC_TX_CTRLr(unit, port, rval)); 2334 2335 exit: 2336 SOC_FUNC_RETURN; 2337 } 2338 #undef _ERR_MSG_MODULE_NAME 2339 2340 #endif