unimac.c (47420B)
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 11 #include <soc/portmod/portmod.h> 12 #include <soc/portmod/unimac.h> 13 #include <soc/drv.h> 14 15 #if defined(PORTMOD_PM4x10Q_SUPPORT) || defined(PORTMOD_PM_QTC_SUPPORT) || defined(PORTMOD_PM4X10_QTC_SUPPORT) 16 17 18 #ifdef _ERR_MSG_MODULE_NAME 19 #error "_ERR_MSG_MODULE_NAME redefined" 20 #endif 21 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT 22 23 24 #define SOC_UNIMAC_SPEED_10 0x0 25 #define SOC_UNIMAC_SPEED_100 0x1 26 #define SOC_UNIMAC_SPEED_1000 0x2 27 #define SOC_UNIMAC_SPEED_2500 0x3 28 29 #define SOC_UNIMAC_MAX_FRAME_SIZE 16360 30 #define SOC_UNIMAC_WAKE_TIMER 17 31 #define SOC_UNIMAC_LPI_TIMER 4 32 33 /* EEE related defination */ 34 #define SOC_UNIMAC_MAX_EEE_SPEED 2500 35 #define SOC_UNIMAC_EEE_REF_CNT 250 36 37 38 /* 39 * Function: 40 * _unimac_soft_reset_and_config_set 41 * Purpose: 42 * In register COMMAND_CONFIGr, some field must be set under software reset. 43 * This function checks software reset status and then set these fields. 44 * Parameters: 45 * unit - StrataSwitch unit #. 46 * port - StrataSwitch port # on unit. 47 * config - value for COMMAND_CONFIGr. 48 * Returns: 49 * SOC_E_XXX 50 */ 51 STATIC 52 int _unimac_soft_reset_and_config_set (int unit, soc_port_t port, uint32 config) 53 { 54 uint32 command_config; 55 int rx_enable = 0, reset = 0; 56 57 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 58 59 reset = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, SW_RESETf); 60 rx_enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf); 61 62 if (!reset) { 63 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, FLUSH_CONTROLr, port, FLUSHf, 1)); 64 65 /* First put the MAC in reset */ 66 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, TRUE)); 67 /* Update config */ 68 soc_reg_field_set(unit, COMMAND_CONFIGr, &config, SW_RESETf, 1); 69 if (rx_enable) { 70 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, FALSE)); 71 /* Update config */ 72 soc_reg_field_set(unit, COMMAND_CONFIGr, &config, RX_ENAf, 0); 73 74 sal_udelay(2); 75 } 76 } 77 78 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, config)); 79 80 if (!reset) { 81 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, FLUSH_CONTROLr, port, FLUSHf, 0)); 82 /* Bring the MAC out of reset */ 83 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, FALSE)); 84 if (rx_enable) { 85 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, TRUE)); 86 } 87 } 88 89 return SOC_E_NONE; 90 } 91 92 /* 93 * Function: 94 * unimac_init 95 * Purpose: 96 * Initialize UniMAC into a known good state. 97 * Parameters: 98 * unit - StrataSwitch unit #. 99 * port - StrataSwitch port # on unit. 100 * Returns: 101 * SOC_E_XXX 102 * Notes: 103 * The initialization speed/duplex is arbitrary and must be 104 * updated by linkscan before enabling the MAC. 105 */ 106 107 int unimac_init(int unit, soc_port_t port, int init_flags) 108 { 109 uint32 command_config, old_command_config, reg_val; 110 int frame_max, ignore_pause; 111 int is_crc_fwd; 112 113 is_crc_fwd = (init_flags & UNIMAC_INIT_F_RX_STRIP_CRC) ? 0 : 1; 114 115 /* Get MAC configurations from config settings. */ 116 117 frame_max = SOC_UNIMAC_MAX_FRAME_SIZE; 118 SOC_IF_ERROR_RETURN(unimac_rx_max_size_set(unit, port, frame_max)); 119 120 /* First put the MAC in reset and sleep */ 121 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, TRUE)); 122 123 /* Do the initialization */ 124 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 125 old_command_config = command_config; 126 127 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0); 128 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 129 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, ETH_SPEEDf, SOC_UNIMAC_SPEED_1000); 130 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PROMIS_ENf, 1); 131 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAD_ENf, 0); 132 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CRC_FWDf, is_crc_fwd); 133 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_FWDf, 0); 134 135 /* Ignore pause if using as stack port */ 136 ignore_pause = IS_ST_PORT(unit, port) ? 1 : 0; 137 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_IGNOREf, ignore_pause); 138 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, IGNORE_TX_PAUSEf, ignore_pause); 139 140 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ADDR_INSf, 0); 141 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, HD_ENAf, 0); 142 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LOOP_ENAf, 0); 143 144 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, NO_LGTH_CHECKf, 1); 145 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LINE_LOOPBACKf, 0); 146 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ERR_DISCf, 0); 147 148 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CNTL_FRM_ENAf, 1); 149 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, ENA_EXT_CONFIGf, (init_flags & UNIMAC_INIT_F_AUTO_CFG) ? 1 : 0); 150 151 if (init_flags & UNIMAC_INIT_F_AUTO_CFG) { 152 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_OVERRIDE_RXf, 1); 153 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_OVERRIDE_TXf, 1); 154 } 155 156 if (old_command_config != command_config) { 157 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 158 } 159 160 SOC_IF_ERROR_RETURN(READ_TAG_0r(unit, port, ®_val)); 161 soc_reg_field_set(unit, TAG_0r, ®_val, CONFIG_OUTER_TPID_ENABLEf, 0); 162 SOC_IF_ERROR_RETURN(WRITE_TAG_0r(unit, port, reg_val)); 163 164 SOC_IF_ERROR_RETURN(READ_TAG_1r(unit, port, ®_val)); 165 soc_reg_field_set(unit, TAG_1r, ®_val, CONFIG_INNER_TPID_ENABLEf, 0); 166 SOC_IF_ERROR_RETURN(WRITE_TAG_1r(unit, port, reg_val)); 167 168 SOC_IF_ERROR_RETURN(READ_UMAC_TIMESTAMP_ADJUSTr(unit, port, ®_val)); 169 soc_reg_field_set(unit, UMAC_TIMESTAMP_ADJUSTr, ®_val, AUTO_ADJUSTf, 0); 170 SOC_IF_ERROR_RETURN(WRITE_UMAC_TIMESTAMP_ADJUSTr(unit, port, reg_val)); 171 172 /* Bring the UniMAC out of reset */ 173 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, FALSE)); 174 175 reg_val = 0; 176 soc_reg_field_set(unit, PAUSE_CONTROLr, ®_val, ENABLEf, 1); 177 soc_reg_field_set(unit, PAUSE_CONTROLr, ®_val, VALUEf, 0x1ffff); 178 SOC_IF_ERROR_RETURN(WRITE_PAUSE_CONTROLr(unit, port, reg_val)); 179 180 SOC_IF_ERROR_RETURN(WRITE_PAUSE_QUANTr(unit, port, 0xffff)); 181 182 SOC_IF_ERROR_RETURN(READ_MAC_PFC_REFRESH_CTRLr(unit, port, ®_val)); 183 soc_reg_field_set(unit, MAC_PFC_REFRESH_CTRLr, ®_val, PFC_REFRESH_ENf, 1); 184 soc_reg_field_set(unit, MAC_PFC_REFRESH_CTRLr, ®_val, PFC_REFRESH_TIMERf, 0xc000); 185 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_REFRESH_CTRLr(unit, port, reg_val)); 186 187 SOC_IF_ERROR_RETURN(WRITE_TX_IPG_LENGTHr(unit, port, 12)); 188 189 /* Set egress enable */ 190 191 192 /* assigning proper setting for EEE feature : 193 * Note : GE speed force assigned for timer setting 194 */ 195 if (soc_feature(unit, soc_feature_eee)) { 196 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, UMAC_EEE_REF_COUNTr, port, EEE_REF_COUNTf, SOC_UNIMAC_EEE_REF_CNT)); 197 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, GMII_EEE_WAKE_TIMERr, port, GMII_EEE_WAKE_TIMERf, SOC_UNIMAC_WAKE_TIMER)); 198 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, GMII_EEE_DELAY_ENTRY_TIMERr, port, GMII_EEE_LPI_TIMERf, SOC_UNIMAC_LPI_TIMER)); 199 } 200 201 return SOC_E_NONE; 202 } 203 204 205 /* 206 * Function: 207 * unimac_deinit 208 * Purpose: 209 * Deinitialize UniMAC into a default state. 210 * Parameters: 211 * unit - StrataSwitch unit #. 212 * port - StrataSwitch port # on unit. 213 * Returns: 214 * SOC_E_XXX 215 * Notes: 216 */ 217 218 int unimac_deinit(int unit, soc_port_t port) 219 { 220 uint32 command_config, old_command_config, reg_val; 221 222 223 SOC_IF_ERROR_RETURN(WRITE_TX_IPG_LENGTHr(unit, port, 0)); 224 225 SOC_IF_ERROR_RETURN(READ_MAC_PFC_REFRESH_CTRLr(unit, port, ®_val)); 226 soc_reg_field_set(unit, MAC_PFC_REFRESH_CTRLr, ®_val, PFC_REFRESH_ENf, 0); 227 soc_reg_field_set(unit, MAC_PFC_REFRESH_CTRLr, ®_val, PFC_REFRESH_TIMERf, 0x7fff); 228 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_REFRESH_CTRLr(unit, port, reg_val)); 229 230 231 reg_val = 0; 232 soc_reg_field_set(unit, PAUSE_CONTROLr, ®_val, ENABLEf, 1); 233 soc_reg_field_set(unit, PAUSE_CONTROLr, ®_val, VALUEf, 0xffff); 234 SOC_IF_ERROR_RETURN(WRITE_PAUSE_CONTROLr(unit, port, reg_val)); 235 236 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, TRUE)); 237 238 SOC_IF_ERROR_RETURN(READ_UMAC_TIMESTAMP_ADJUSTr(unit, port, ®_val)); 239 soc_reg_field_set(unit, UMAC_TIMESTAMP_ADJUSTr, ®_val, AUTO_ADJUSTf, 0x1); 240 SOC_IF_ERROR_RETURN(WRITE_UMAC_TIMESTAMP_ADJUSTr(unit, port, reg_val)); 241 242 SOC_IF_ERROR_RETURN(READ_TAG_0r(unit, port, ®_val)); 243 soc_reg_field_set(unit, TAG_0r, ®_val, CONFIG_OUTER_TPID_ENABLEf, 0x1); 244 SOC_IF_ERROR_RETURN(WRITE_TAG_0r(unit, port, reg_val)); 245 246 SOC_IF_ERROR_RETURN(READ_TAG_1r(unit, port, ®_val)); 247 soc_reg_field_set(unit, TAG_1r, ®_val, CONFIG_INNER_TPID_ENABLEf, 0x1); 248 SOC_IF_ERROR_RETURN(WRITE_TAG_1r(unit, port, reg_val)); 249 250 /* Do the deinitialization */ 251 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 252 old_command_config = command_config; 253 254 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0); 255 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 256 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, ETH_SPEEDf, 0x2); 257 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PROMIS_ENf, 1); 258 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAD_ENf, 0); 259 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CRC_FWDf, 1); 260 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_FWDf, 1); 261 262 /* Ignore pause if using as stack port */ 263 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_IGNOREf, 0); 264 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, IGNORE_TX_PAUSEf, 0); 265 266 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ADDR_INSf, 0); 267 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, HD_ENAf, 0); 268 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LOOP_ENAf, 0); 269 270 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, NO_LGTH_CHECKf, 1); 271 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LINE_LOOPBACKf, 0); 272 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ERR_DISCf, 0); 273 274 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CNTL_FRM_ENAf, 0); 275 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, ENA_EXT_CONFIGf, 0); 276 277 278 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_OVERRIDE_RXf, 0); 279 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_OVERRIDE_TXf, 0); 280 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 0); 281 282 if (old_command_config != command_config) { 283 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 284 } 285 286 287 SOC_IF_ERROR_RETURN(WRITE_FRM_LENGTHr(unit, port, 0x5ee)); 288 289 return SOC_E_NONE; 290 } 291 292 /* 293 * Function: 294 * unimac_rx_max_size_set 295 * Description: 296 * Set the maximum receive frame size for the GE port 297 * Parameters: 298 * unit - Device number 299 * port - Port number 300 * value - Maximum frame size in bytes 301 * Return Value: 302 * BCM_E_XXX 303 */ 304 int unimac_rx_max_size_set(int unit, soc_port_t port, int value) 305 { 306 uint32 command_config, rx_ena; 307 int speed = 0; 308 309 if (IS_ST_PORT(unit, port)) { 310 value += 16; /* Account for 16 bytes of Higig2 header */ 311 } 312 313 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 314 rx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf); 315 316 /* If Rx is enabled then disable RX */ 317 if (rx_ena) { 318 /* Disable RX */ 319 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 320 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 321 322 /* Wait for maximum frame receiption time(for 16K) based on speed */ 323 SOC_IF_ERROR_RETURN(unimac_speed_get(unit, port, &speed)); 324 switch (speed) { 325 case 2500: 326 sal_usleep(55); 327 break; 328 case 1000: 329 sal_usleep(131); 330 break; 331 case 100: 332 sal_usleep(1310); 333 break; 334 case 10: 335 sal_usleep(13100); 336 break; 337 default: 338 break; 339 } 340 } 341 342 SOC_IF_ERROR_RETURN(WRITE_FRM_LENGTHr(unit, port, value)); 343 344 /* if Rx was enabled before, restore it */ 345 if (rx_ena) { 346 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 1); 347 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 348 } 349 350 return SOC_E_NONE; 351 } 352 353 /* 354 * Function: 355 * unimac_rx_max_size_get 356 * Description: 357 * Set the maximum receive frame size for the GE port 358 * Parameters: 359 * unit - Device number 360 * port - Port number 361 * value - Maximum frame size in bytes 362 * Return Value: 363 * BCM_E_XXX 364 * Notes: 365 * Depending on chip or port type the actual maximum receive frame size 366 * might be slightly higher. 367 */ 368 int unimac_rx_max_size_get(int unit, soc_port_t port, int *value) 369 { 370 uint32 frame_length; 371 372 SOC_IF_ERROR_RETURN(READ_FRM_LENGTHr(unit, port, &frame_length)); 373 374 *value = (int) frame_length; 375 if (IS_ST_PORT(unit, port)) { 376 *value -= 16; /* Account for 16 bytes of Higig2 header */ 377 } 378 379 return SOC_E_NONE; 380 } 381 382 /* 383 * Function: 384 * unimac_loopback_set 385 * Purpose: 386 * Set GE MAC into/out-of loopback mode 387 * Parameters: 388 * unit - StrataSwitch unit #. 389 * port - Port number on unit. 390 * enable - Boolean: true -> loopback mode, false -> normal operation 391 * Returns: 392 * SOC_E_XXX 393 */ 394 int unimac_loopback_set(int unit, soc_port_t port, int enable) 395 { 396 uint32 command_config, old_command_config; 397 398 /* The MAC loopback will not work when ENA_EXT_CONFIGf=1 because hardware puts MAC 399 * in reset state if link is down. 400 * A simple workaround is to put PHY in loopback mode to get the link. This brings 401 * MAC out of reset state, and then clears ENA_EXT_CONFIGf. 402 */ 403 404 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 405 old_command_config = command_config; 406 407 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LOOP_ENAf, enable ? 1 : 0); 408 if (command_config == old_command_config) { 409 return SOC_E_NONE; 410 } 411 412 SOC_IF_ERROR_RETURN(_unimac_soft_reset_and_config_set(unit, port, command_config)); 413 414 return SOC_E_NONE; 415 } 416 417 /* 418 * Function: 419 * unimac_loopback_get 420 * Purpose: 421 * Get current GE MAC loopback mode setting. 422 * Parameters: 423 * unit - StrataSwitch unit #. 424 * port - StrataSwitch port # on unit 425 * enable - (OUT) Boolean: true = loopback, false = normal 426 * Returns: 427 * SOC_E_XXX 428 */ 429 int unimac_loopback_get(int unit, soc_port_t port, int *enable) 430 { 431 uint32 command_config; 432 433 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 434 435 *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, LOOP_ENAf); 436 437 return SOC_E_NONE; 438 } 439 440 /* 441 * Function: 442 * unimac_soft_reset_set 443 * Purpose: 444 * Set UniMAC reset state 445 * Parameters: 446 * unit - StrataSwitch unit #. 447 * port - Port number on unit. 448 * enable - TRUE to put MAC in reset, FALSE to take MAC out of reset. 449 * Returns: 450 * SOC_E_XXX 451 */ 452 int unimac_soft_reset_set(int unit, soc_port_t port, int enable) 453 { 454 uint32 command_config; 455 int reset_sleep_usec; 456 457 if (SAL_BOOT_QUICKTURN) { 458 reset_sleep_usec = 50000; 459 } else { 460 /* Minimum of 5 clocks period with the slowest clock is required 461 * between each reset step. 462 * 10Mbps (2.5MHz) = 2000ns 463 * 100Mbps (25MHz) = 200ns 464 * 1000Mbps (125MHz) = 40ns 465 * 2500Mbps (133MHz) = 37.5ns 466 */ 467 reset_sleep_usec = 2; /* choose max delay */ 468 } 469 470 /* SIDE EFFECT: TX and RX are enabled when SW_RESET is set. */ 471 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 472 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, enable); 473 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 474 475 sal_udelay(reset_sleep_usec); 476 477 return SOC_E_NONE; 478 } 479 480 /* 481 * Function: 482 * unimac_soft_reset_get 483 * Purpose: 484 * Get UniMAC reset state 485 * Parameters: 486 * unit - StrataSwitch unit #. 487 * port - Port number on unit. 488 * enable - (OUT) TRUE if in reset, FALSE if out of reset 489 * Returns: 490 * SOC_E_XXX 491 */ 492 int unimac_soft_reset_get(int unit, soc_port_t port, int *enable) 493 { 494 uint32 command_config; 495 496 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 497 *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, SW_RESETf); 498 499 return SOC_E_NONE; 500 } 501 502 /* 503 * Function: 504 * unimac_enable_set 505 * Purpose: 506 * Enable or disable MAC 507 * Parameters: 508 * unit - StrataSwitch unit #. 509 * port - Port number on unit. 510 * flags - UNIMAC_ENABLE_SET_FLAGS_TX_EN or UNIMAC_ENABLE_SET_FLAGS_RX_EN 511 * enable - TRUE to enable, FALSE to disable 512 * Returns: 513 * SOC_E_XXX 514 */ 515 int unimac_enable_set(int unit, soc_port_t port, int flags, int enable) 516 { 517 uint32 command_config, tx_ena, rx_ena; 518 519 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 520 521 tx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, TX_ENAf); 522 rx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf); 523 524 if ((tx_ena && rx_ena && enable) || (!tx_ena && !rx_ena && !enable)) { 525 /* Nothing to do */ 526 return SOC_E_NONE; 527 } 528 529 /* First put the MAC in reset */ 530 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, TRUE)); 531 532 /* de-assert RX_ENA and/or TX_ENA */ 533 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1); 534 if (flags & UNIMAC_ENABLE_SET_FLAGS_TX_EN) { 535 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0); 536 } 537 if (flags & UNIMAC_ENABLE_SET_FLAGS_RX_EN) { 538 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 539 } 540 if (!(flags & UNIMAC_ENABLE_SET_FLAGS_RX_EN) && !(flags & UNIMAC_ENABLE_SET_FLAGS_TX_EN)) { 541 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0); 542 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 543 } 544 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 545 546 sal_udelay(2); 547 548 /* Bring the MAC out of reset */ 549 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, FALSE)); 550 551 if (enable) { 552 /* if enable, assert RX_ENA and TX_ENA */ 553 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 0); 554 if (flags & UNIMAC_ENABLE_SET_FLAGS_TX_EN) { 555 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 1); 556 } 557 if (flags & UNIMAC_ENABLE_SET_FLAGS_RX_EN) { 558 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 1); 559 } 560 if (!(flags & UNIMAC_ENABLE_SET_FLAGS_RX_EN) && !(flags & UNIMAC_ENABLE_SET_FLAGS_TX_EN)) { 561 /* if no flag was set, it means both Rx and Tx (according to enable_set/enable_get convention) */ 562 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 1); 563 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 1); 564 } 565 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 566 sal_udelay(2); 567 } else { 568 /*SOC_IF_ERROR_RETURN(_mac_uni_drain_cells(unit, port)); *//* ???? */ 569 SOC_IF_ERROR_RETURN(unimac_soft_reset_set(unit, port, TRUE)); 570 } 571 572 return SOC_E_NONE; 573 } 574 575 /* 576 * Function: 577 * mac_uni_enable_get 578 * Purpose: 579 * Get UniMAC enable state 580 * Parameters: 581 * unit - StrataSwitch unit #. 582 * port - Port number on unit. 583 * flags - UNIMAC_ENABLE_SET_FLAGS_TX_EN or UNIMAC_ENABLE_SET_FLAGS_RX_EN 584 * enable - (OUT) TRUE if enabled, FALSE if disabled 585 * Returns: 586 * SOC_E_XXX 587 */ 588 int unimac_enable_get(int unit, soc_port_t port, int flags, int *enable) 589 { 590 uint32 command_config; 591 592 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 593 if (flags & UNIMAC_ENABLE_SET_FLAGS_TX_EN) { 594 *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, TX_ENAf); 595 }else{ 596 *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf); 597 } 598 return SOC_E_NONE; 599 } 600 601 602 /* 603 * Function: 604 * unimac_tx_average_ipg_set 605 * Purpose: 606 * Set the IPG appropriate for current duplex 607 * Parameters: 608 * unit - StrataSwitch unit #. 609 * port - Port number on unit. 610 * ipg_val - IPG value to write. 611 * Notes: 612 * The current duplex is read from the hardware registers. 613 */ 614 int unimac_tx_average_ipg_set(int unit, soc_port_t port, int ipg_val) 615 { 616 int tx_en; 617 618 /* Modifiable under sw_reset or Tx disable */ 619 SOC_IF_ERROR_RETURN(unimac_tx_enable_get(unit, port, &tx_en)); 620 if (tx_en) { 621 SOC_IF_ERROR_RETURN(unimac_tx_enable_set(unit, port, FALSE)); 622 } 623 624 /* Silently adjust the specified ifp bits to valid value */ 625 /* valid value: 8 to 64 bytes (i.e. multiple of 8 bits) */ 626 ipg_val = ipg_val < 64 ? 64 : (ipg_val > 512 ? 512 : (ipg_val + 7) & (0x7f << 3)); 627 628 SOC_IF_ERROR_RETURN(WRITE_TX_IPG_LENGTHr(unit, port, ipg_val/8)); 629 if (tx_en) { 630 SOC_IF_ERROR_RETURN(unimac_tx_enable_set(unit, port, TRUE)); 631 } 632 633 return SOC_E_NONE; 634 } 635 636 /* 637 * Function: 638 * unimac_tx_average_ipg_get 639 * Purpose: 640 * Set the IPG appropriate for current duplex 641 * Parameters: 642 * unit - StrataSwitch unit #. 643 * port - Port number on unit. 644 * ipg_val - (OUT) IPG value to write. 645 * Returns: 646 * SOC_E_XXX 647 */ 648 int unimac_tx_average_ipg_get(int unit, soc_port_t port, int *ipg_val) 649 { 650 uint32 reg_val; 651 652 SOC_IF_ERROR_RETURN(READ_TX_IPG_LENGTHr(unit, port, ®_val)); 653 654 *ipg_val = soc_reg_field_get(unit, TX_IPG_LENGTHr, reg_val, TX_IPG_LENGTHf) * 8; 655 656 return SOC_E_NONE; 657 } 658 659 660 661 /* 662 * Function: 663 * unimac_encap_set 664 * Purpose: 665 * Set the port encapsulation mode. 666 * Parameters: 667 * unit - unit #. 668 * port - port # on unit. 669 * encap - encapsulation mode 670 * Returns: 671 * SOC_E_XXX 672 */ 673 int unimac_encap_set(int unit, soc_port_t port, portmod_encap_t encap) 674 { 675 return (encap == SOC_ENCAP_IEEE) ? SOC_E_NONE : SOC_E_PARAM; 676 } 677 678 /* 679 * Function: 680 * unimac_encap_get 681 * Purpose: 682 * Get the port encapsulation mode. 683 * Parameters: 684 * unit - unit #. 685 * port - port # on unit. 686 * encap - (INT) encapsulation mode 687 * Returns: 688 * SOC_E_XXX 689 */ 690 int unimac_encap_get(int unit, soc_port_t port, portmod_encap_t *encap) 691 { 692 *encap = SOC_ENCAP_IEEE; 693 694 return SOC_E_NONE; 695 } 696 697 698 /* 699 * Function: 700 * unimac_duplex_set 701 * Purpose: 702 * Set UniMAC in the specified duplex mode. 703 * Parameters: 704 * unit - StrataSwitch unit #. 705 * port - StrataSwitch port # on unit. 706 * duplex - Boolean: true --> full duplex, false --> half duplex. 707 * Returns: 708 * SOC_E_XXX 709 * Notes: 710 * Programs an IFG time appropriate to speed and duplex. 711 */ 712 713 int unimac_duplex_set(int unit, soc_port_t port, int duplex) 714 { 715 uint32 command_config, old_command_config; 716 int speed; 717 718 SOC_IF_ERROR_RETURN(unimac_speed_get(unit, port, &speed)); 719 720 if (speed >= 1000) { 721 /* program the bit full-duplex for speed 1000 or 2500Mbps. */ 722 duplex = 1; 723 } 724 725 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 726 old_command_config = command_config; 727 728 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, HD_ENAf, duplex ? 0 : 1); 729 if (command_config == old_command_config) { 730 return SOC_E_NONE; 731 } 732 733 SOC_IF_ERROR_RETURN(_unimac_soft_reset_and_config_set(unit, port, command_config)); 734 735 return SOC_E_NONE; 736 } 737 738 /* 739 * Function: 740 * unimac_duplex_get 741 * Purpose: 742 * Get UniMAC duplex mode. 743 * Parameters: 744 * unit - StrataSwitch unit #. 745 * port - StrataSwitch port # on unit. 746 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 747 * Returns: 748 * SOC_E_XXX 749 */ 750 751 int unimac_duplex_get(int unit, soc_port_t port, int *duplex) 752 { 753 uint32 command_config; 754 int speed; 755 756 SOC_IF_ERROR_RETURN(unimac_speed_get(unit, port, &speed)); 757 758 if ((1000 == speed) || (2500 == speed)) { 759 *duplex = TRUE; 760 } else { 761 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 762 *duplex = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, HD_ENAf) ? FALSE : TRUE; 763 } 764 765 return SOC_E_NONE; 766 } 767 768 769 770 /* 771 * Function: 772 * unimac_speed_set 773 * Purpose: 774 * Set UniMAC in the specified speed. 775 * Parameters: 776 * unit - StrataSwitch unit #. 777 * port - Port number on unit. 778 * speed - 10,100,1000, 2500 for speed. 779 * Returns: 780 * SOC_E_XXX 781 * Notes: 782 * Programs an IFG time appropriate to speed and duplex. 783 */ 784 int unimac_speed_set(int unit, soc_port_t port, int speed) 785 { 786 uint32 command_config; 787 int speed_select = 0; 788 789 switch (speed) { 790 case 10: 791 speed_select = SOC_UNIMAC_SPEED_10; 792 break; 793 /* support non-standard speed in Broadreach mode */ 794 case 20: 795 case 25: 796 case 33: 797 case 50: 798 /* fall through to case 100 */ 799 case 100: 800 speed_select = SOC_UNIMAC_SPEED_100; 801 break; 802 case 1000: 803 speed_select = SOC_UNIMAC_SPEED_1000; 804 break; 805 case 2500: 806 speed_select = SOC_UNIMAC_SPEED_2500; 807 break; 808 case 0: 809 return (SOC_E_NONE); /* Support NULL PHY */ 810 default: 811 return (SOC_E_CONFIG); 812 } 813 814 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 815 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, ETH_SPEEDf, speed_select); 816 817 SOC_IF_ERROR_RETURN(_unimac_soft_reset_and_config_set(unit, port, command_config)); 818 819 return (SOC_E_NONE); 820 } 821 822 /* 823 * Function: 824 * unimac_speed_get 825 * Purpose: 826 * Get GE MAC speed 827 * Parameters: 828 * unit - StrataSwitch unit #. 829 * port - Port number on unit. 830 * speed - (OUT) speed in Mb (10/100/1000) 831 * Returns: 832 * SOC_E_NONE 833 */ 834 835 int unimac_speed_get(int unit, soc_port_t port, int *speed) 836 { 837 uint32 command_config, uni_speed; 838 int rv = SOC_E_NONE; 839 840 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 841 842 uni_speed = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, ETH_SPEEDf); 843 844 switch(uni_speed) { 845 case SOC_UNIMAC_SPEED_10: 846 *speed = 10; 847 break; 848 case SOC_UNIMAC_SPEED_100: 849 *speed = 100; 850 break; 851 case SOC_UNIMAC_SPEED_1000: 852 *speed = 1000; 853 break; 854 case SOC_UNIMAC_SPEED_2500: 855 *speed = 2500; 856 break; 857 default: 858 rv = SOC_E_INTERNAL; 859 } 860 861 return(rv); 862 } 863 864 865 int unimac_rx_enable_set (int unit, soc_port_t port, int enable) 866 { 867 uint32 reg_val; 868 869 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, ®_val)); 870 soc_reg_field_set(unit, COMMAND_CONFIGr, ®_val, RX_ENAf, enable ? 1: 0); 871 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, reg_val)); 872 873 return(SOC_E_NONE); 874 } 875 876 int unimac_rx_enable_get (int unit, soc_port_t port, int *enable) 877 { 878 uint32 reg_val; 879 880 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, ®_val)); 881 *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, reg_val, RX_ENAf); 882 883 return(SOC_E_NONE); 884 } 885 886 887 /* 888 * Function: 889 * unimac_mac_sa_set 890 * Purpose: 891 * Set GE MAC source address for transmitted PAUSE frame 892 * Parameters: 893 * unit - StrataSwitch unit #. 894 * port - StrataSwitch port # on unit. 895 * mac - MAC address used for pause transmission. 896 * Returns: 897 * SOC_E_XXX 898 */ 899 900 int 901 unimac_mac_sa_set(int unit, soc_port_t port, sal_mac_addr_t mac) 902 { 903 uint32 mac_0, mac_1; 904 905 mac_0 = _shr_uint32_read(&mac[0]); 906 mac_1 = _shr_uint16_read(&mac[4]); 907 908 SOC_IF_ERROR_RETURN(WRITE_MAC_0r(unit, port, mac_0)); 909 SOC_IF_ERROR_RETURN(WRITE_MAC_1r(unit, port, mac_1)); 910 911 return SOC_E_NONE; 912 } 913 914 /* 915 * Function: 916 * unimac_mac_sa_get 917 * Purpose: 918 * Return current GE MAC source address for transmitted PAUSE frames 919 * Parameters: 920 * unit - StrataSwitch unit #. 921 * port - StrataSwitch port # on unit. 922 * mac - (OUT) MAC address used for pause transmission. 923 * Returns: 924 * SOC_E_XXX 925 */ 926 int 927 unimac_mac_sa_get(int unit, soc_port_t port, sal_mac_addr_t mac) 928 { 929 uint32 mac_0, mac_1; 930 931 SOC_IF_ERROR_RETURN(READ_MAC_0r(unit, port, &mac_0)); 932 SOC_IF_ERROR_RETURN(READ_MAC_1r(unit, port, &mac_1)); 933 934 mac[0] = (uint8)(mac_0 >> 24); 935 mac[1] = (uint8)(mac_0 >> 16); 936 mac[2] = (uint8)(mac_0 >> 8); 937 mac[3] = (uint8)(mac_0 >> 0); 938 mac[4] = (uint8)(mac_1 >> 8); 939 mac[5] = (uint8)(mac_1 >> 0); 940 941 return SOC_E_NONE; 942 } 943 944 /* 945 * Function: 946 * unimac_tx_preamble_length_set 947 * Purpose: 948 * Set the transmit preamble excluding SFD. 949 * Parameters: 950 * unit - StrataSwitch unit #. 951 * port - StrataSwitch port # on unit. 952 * length - length of preamble transmit. 953 * Returns: 954 * SOC_E_XXX 955 */ 956 int unimac_tx_preamble_length_set(int unit, soc_port_t port, int length) 957 { 958 uint32 reg_val; 959 960 if((length > 7) || length < 2){ 961 LOG_VERBOSE(BSL_LS_SOC_COMMON,(BSL_META_U(unit, "runt size should be between 2 and 7. got %d"), length)); 962 return (SOC_E_PARAM); 963 } 964 965 SOC_IF_ERROR_RETURN(READ_TX_PREAMBLEr(unit, port, ®_val)); 966 soc_reg_field_set(unit, TX_PREAMBLEr, ®_val, TX_PREAMBLEf, length); 967 968 return (WRITE_TX_PREAMBLEr(unit, port, reg_val)); 969 } 970 971 972 /* 973 * unimac_eee_set 974 * 975 * @brief EEE Control and Timer set 976 * 977 * @param [in] unit - unit id 978 * @param [in] port - logical port 979 * @param [in] eee - 980 */ 981 int unimac_eee_set(int unit, int port, const portmod_eee_t* eee) 982 { 983 int speed; 984 uint32 reg_val; 985 soc_reg_t reg; 986 soc_field_t field; 987 988 SOC_IF_ERROR_RETURN(READ_UMAC_EEE_CTRLr(unit ,port, ®_val)); 989 soc_reg_field_set(unit, UMAC_EEE_CTRLr, ®_val, EEE_ENf, eee->enable); 990 SOC_IF_ERROR_RETURN(WRITE_UMAC_EEE_CTRLr(unit ,port, reg_val)); 991 992 SOC_IF_ERROR_RETURN(unimac_speed_get(unit, port, &speed)); 993 if (speed > SOC_UNIMAC_MAX_EEE_SPEED) { 994 LOG_VERBOSE(BSL_LS_SOC_COMMON,(BSL_META_U(unit, "max speed for EEE is 2500Mbps"))); 995 return (SOC_E_PARAM); 996 } 997 998 reg = (speed >= 1000) ? GMII_EEE_WAKE_TIMERr : MII_EEE_WAKE_TIMERr; 999 field = (speed >= 1000) ? GMII_EEE_WAKE_TIMERf : MII_EEE_WAKE_TIMERf; 1000 1001 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, ®_val)); 1002 soc_reg_field_set(unit, reg, ®_val, field, eee->tx_wake_time); 1003 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, reg_val)); 1004 1005 reg = (speed >= 1000) ? GMII_EEE_DELAY_ENTRY_TIMERr : MII_EEE_DELAY_ENTRY_TIMERr; 1006 field = (speed >= 1000) ? GMII_EEE_LPI_TIMERf : MII_EEE_LPI_TIMERf; 1007 1008 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, ®_val)); 1009 soc_reg_field_set(unit, reg, ®_val, field, eee->tx_idle_time); 1010 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, reg_val)); 1011 1012 return SOC_E_NONE; 1013 } 1014 1015 1016 /* 1017 * unimac_eee_get 1018 * 1019 * @brief EEE Control and Timer get 1020 * 1021 * @param [in] unit - unit id 1022 * @param [in] port - logical port 1023 * @param [in] eee - 1024 */ 1025 int unimac_eee_get(int unit, int port, const portmod_eee_t* eee) 1026 { 1027 int speed; 1028 uint32 reg_val; 1029 soc_reg_t reg; 1030 soc_field_t field; 1031 portmod_eee_t* pEEE = (portmod_eee_t*)eee; 1032 1033 SOC_IF_ERROR_RETURN(READ_UMAC_EEE_CTRLr(unit, port, ®_val)); 1034 pEEE->enable = soc_reg_field_get (unit, UMAC_EEE_CTRLr, reg_val, EEE_ENf); 1035 1036 SOC_IF_ERROR_RETURN(unimac_speed_get(unit, port, &speed)); 1037 if (speed > SOC_UNIMAC_MAX_EEE_SPEED) { 1038 LOG_VERBOSE(BSL_LS_SOC_COMMON,(BSL_META_U(unit, "max speed for EEE is 2500Mbps"))); 1039 return (SOC_E_PARAM); 1040 } 1041 1042 reg = (speed >= 1000) ? GMII_EEE_WAKE_TIMERr : MII_EEE_WAKE_TIMERr; 1043 field = (speed >= 1000) ? GMII_EEE_WAKE_TIMERf : MII_EEE_WAKE_TIMERf; 1044 1045 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, ®_val)); 1046 pEEE->tx_wake_time = soc_reg_field_get(unit, reg, reg_val, field); 1047 1048 reg = (speed >= 1000) ? GMII_EEE_DELAY_ENTRY_TIMERr : MII_EEE_DELAY_ENTRY_TIMERr; 1049 field = (speed >= 1000) ? GMII_EEE_LPI_TIMERf : MII_EEE_LPI_TIMERf; 1050 1051 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, ®_val)); 1052 pEEE->tx_idle_time = soc_reg_field_get(unit, reg, reg_val, field); 1053 1054 return(SOC_E_NONE); 1055 } 1056 1057 1058 /* 1059 * unimac_pfc_config_set 1060 * 1061 * @brief set pass control frames. 1062 * 1063 * @param [in] unit - unit id 1064 * @param [in] port - logical port 1065 * @param [in] pfc_cfg - 1066 */ 1067 int unimac_pfc_config_set (int unit, int port, 1068 const portmod_pfc_config_t* pfc_cfg) 1069 { 1070 uint32 reg_val; 1071 int rx_en; 1072 portmod_pfc_control_t pfc_ctrl; 1073 1074 SOC_IF_ERROR_RETURN(READ_MAC_PFC_TYPEr(unit ,port, ®_val)); 1075 soc_reg_field_set(unit, MAC_PFC_TYPEr, ®_val, PFC_ETH_TYPEf, pfc_cfg->type); 1076 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_TYPEr(unit ,port, reg_val)); 1077 1078 SOC_IF_ERROR_RETURN(READ_MAC_PFC_OPCODEr(unit ,port, ®_val)); 1079 soc_reg_field_set(unit, MAC_PFC_OPCODEr, ®_val, PFC_OPCODEf, pfc_cfg->opcode); 1080 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_OPCODEr(unit ,port, reg_val)); 1081 1082 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, ®_val)); 1083 reg_val &= 0x00ffffff; 1084 reg_val |= (pfc_cfg->da_oui & 0xff) << 24; 1085 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DA_0r(unit, port, reg_val)); 1086 1087 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_1r(unit, port, ®_val)); 1088 soc_reg_field_set(unit, MAC_PFC_DA_1r, ®_val, PFC_MACDA_1f, pfc_cfg->da_oui >> 8); 1089 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DA_1r(unit, port, reg_val)); 1090 1091 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, ®_val)); 1092 reg_val &= 0xff000000; 1093 reg_val |= pfc_cfg->da_nonoui & 0xffffff; 1094 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DA_0r(unit, port, reg_val)); 1095 1096 SOC_IF_ERROR_RETURN(unimac_rx_enable_get(unit, port, &rx_en)); 1097 if (rx_en) { 1098 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, FALSE)); 1099 } 1100 SOC_IF_ERROR_RETURN(unimac_pfc_control_get(unit, port, &pfc_ctrl)); 1101 if (pfc_ctrl.rx_enable) { 1102 pfc_ctrl.rx_enable = FALSE; 1103 SOC_IF_ERROR_RETURN(unimac_pfc_control_set(unit, port, &pfc_ctrl)); 1104 pfc_ctrl.rx_enable = TRUE; 1105 } 1106 1107 /* Modifiable under sw_reset or PFC Rx disable. */ 1108 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, ®_val)); 1109 soc_reg_field_set(unit, MAC_PFC_CTRLr, ®_val, RX_PASS_PFC_FRMf, pfc_cfg->rxpass ? 1 : 0); 1110 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_CTRLr_REG32(unit, port, reg_val)); 1111 1112 if (pfc_ctrl.rx_enable) { 1113 SOC_IF_ERROR_RETURN(unimac_pfc_control_set(unit, port, &pfc_ctrl)); 1114 } 1115 if (rx_en) { 1116 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, TRUE)); 1117 } 1118 1119 return (SOC_E_NONE); 1120 } 1121 1122 1123 1124 /* 1125 * unimac_pfc_config_get 1126 * 1127 * @brief set pass control frames. 1128 * 1129 * @param [in] unit - unit id 1130 * @param [in] port - logical port 1131 * @param [in] pfc_cfg - 1132 */ 1133 int unimac_pfc_config_get (int unit, int port, 1134 const portmod_pfc_config_t* pfc_cfg) 1135 { 1136 uint32 reg_val; 1137 uint32 fval, fval0, fval1; 1138 portmod_pfc_config_t* pcfg = (portmod_pfc_config_t*) pfc_cfg; 1139 1140 SOC_IF_ERROR_RETURN(READ_MAC_PFC_TYPEr(unit, port, ®_val)); 1141 pcfg->type = soc_reg_field_get(unit, MAC_PFC_TYPEr, reg_val, PFC_ETH_TYPEf); 1142 1143 SOC_IF_ERROR_RETURN(READ_MAC_PFC_OPCODEr(unit, port, ®_val)); 1144 pcfg->opcode = soc_reg_field_get(unit, MAC_PFC_OPCODEr, reg_val, PFC_OPCODEf); 1145 1146 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, ®_val)); 1147 fval0 = soc_reg_field_get(unit, MAC_PFC_DA_0r, reg_val, PFC_MACDA_0f); 1148 1149 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_1r(unit, port, ®_val)); 1150 fval1 = soc_reg_field_get(unit, MAC_PFC_DA_1r, reg_val, PFC_MACDA_1f); 1151 pcfg->da_oui = (fval0 >> 24) | (fval1 << 8); 1152 1153 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, ®_val)); 1154 fval = soc_reg_field_get(unit, MAC_PFC_DA_0r, reg_val, PFC_MACDA_0f); 1155 1156 pcfg->da_nonoui = fval & 0xffffff; 1157 1158 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, ®_val)); 1159 pcfg->rxpass = soc_reg_field_get(unit, MAC_PFC_CTRLr, reg_val, RX_PASS_PFC_FRMf); 1160 1161 return (SOC_E_NONE); 1162 } 1163 1164 1165 /* 1166 * unimac_diag_fifo_status_get 1167 * 1168 * @brief get port timestamps in fifo 1169 * 1170 * @param [in] unit - unit id 1171 * @param [in] port - logical port 1172 * @param [in] diag_info - 1173 */ 1174 int unimac_diag_fifo_status_get (int unit, int port, 1175 const portmod_fifo_status_t* diag_info) 1176 { 1177 uint32 reg_val; 1178 portmod_fifo_status_t* pinfo =(portmod_fifo_status_t*)diag_info; 1179 1180 SOC_IF_ERROR_RETURN(READ_TS_STATUS_CNTRLr(unit, port, ®_val)); 1181 1182 if (soc_reg_field_get(unit, TS_STATUS_CNTRLr, reg_val, TX_TS_FIFO_EMPTYf)) { 1183 return SOC_E_EMPTY; 1184 } 1185 1186 SOC_IF_ERROR_RETURN(READ_TX_TS_SEQ_IDr(unit, port, ®_val)); 1187 if (soc_reg_field_get(unit, TX_TS_SEQ_IDr, reg_val, TSTS_VALIDf) == 0) { 1188 return SOC_E_EMPTY; 1189 } 1190 1191 SOC_IF_ERROR_RETURN(READ_TX_TS_DATAr(unit, port, ®_val)); 1192 pinfo->timestamps_in_fifo = soc_reg_field_get(unit, TX_TS_DATAr, reg_val, TX_TS_DATAf); 1193 1194 return (SOC_E_NONE); 1195 } 1196 1197 int unimac_pass_pause_frame_set(int unit, int port, uint32 value) 1198 { 1199 uint32 command_config; 1200 int rx_en; 1201 1202 SOC_IF_ERROR_RETURN(unimac_rx_enable_get(unit, port, &rx_en)); 1203 if (rx_en) { 1204 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, FALSE)); 1205 } 1206 1207 /* Modifiable under sw_reset or Rx disable */ 1208 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1209 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_FWDf, value ? 1 : 0); 1210 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1211 1212 if (rx_en) { 1213 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, TRUE)); 1214 } 1215 1216 return(SOC_E_NONE); 1217 } 1218 1219 int unimac_pass_pause_frame_get(int unit, int port, uint32* value) 1220 { 1221 uint32 command_config; 1222 1223 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1224 1225 *value = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, PAUSE_FWDf); 1226 1227 return(SOC_E_NONE); 1228 1229 } 1230 1231 int unimac_pass_control_frame_set(int unit, int port, int value) 1232 { 1233 uint32 command_config; 1234 int rx_en; 1235 1236 SOC_IF_ERROR_RETURN(unimac_rx_enable_get(unit, port, &rx_en)); 1237 if (rx_en) { 1238 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, FALSE)); 1239 } 1240 1241 /*Modifiable under sw_reset or Rx disable.*/ 1242 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1243 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CNTL_FRM_ENAf, value ? 1 : 0); 1244 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1245 1246 if (rx_en) { 1247 SOC_IF_ERROR_RETURN(unimac_rx_enable_set(unit, port, TRUE)); 1248 } 1249 1250 return(SOC_E_NONE); 1251 } 1252 1253 int unimac_pass_control_frame_get(int unit, int port, int* value) 1254 { 1255 uint32 command_config; 1256 1257 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1258 1259 *value = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, CNTL_FRM_ENAf); 1260 1261 return(SOC_E_NONE); 1262 } 1263 1264 int 1265 unimac_mac_ctrl_set(int unit, int port, uint32 mac_ctrl) 1266 { 1267 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, mac_ctrl)); 1268 return (0); 1269 } 1270 1271 int 1272 unimac_mac_ctrl_get(int unit, int port, uint32 *mac_ctrl, int *rx_en) 1273 { 1274 uint32 reg_val; 1275 1276 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, ®_val)); 1277 *mac_ctrl = reg_val; 1278 *rx_en = soc_reg_field_get(unit, COMMAND_CONFIGr, reg_val, RX_ENAf); 1279 1280 return (SOC_E_NONE); 1281 } 1282 1283 int unimac_drain_cell_get (int unit, int port, portmod_drain_cells_t *drain_cells) 1284 { 1285 uint32 reg_val; 1286 1287 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, ®_val)); 1288 drain_cells->rx_pfc_en = soc_reg_field_get(unit, MAC_PFC_CTRLr, reg_val, PFC_RX_ENBLf); 1289 1290 1291 drain_cells->llfc_en = 0; 1292 1293 SOC_IF_ERROR_RETURN(READ_MAC_MODEr(unit, port , ®_val)); 1294 drain_cells->rx_pause = soc_reg_field_get(unit, MAC_MODEr, reg_val, MAC_RX_PAUSEf); 1295 drain_cells->tx_pause = soc_reg_field_get(unit, MAC_MODEr, reg_val, MAC_TX_PAUSEf); 1296 1297 return (0); 1298 } 1299 1300 int unimac_rx_vlan_tag_set(int unit, soc_port_t port, int outer_vlan_tag, int inner_vlan_tag) 1301 { 1302 uint32 reg_val = 0; 1303 1304 SOC_IF_ERROR_RETURN(READ_TAG_1r(unit, port, ®_val)); 1305 if(inner_vlan_tag == -1) { 1306 soc_reg_field_set(unit, TAG_1r, ®_val, CONFIG_INNER_TPID_ENABLEf, 0); 1307 } else { 1308 soc_reg_field_set(unit, TAG_1r, ®_val, FRM_TAG_1f, inner_vlan_tag); 1309 soc_reg_field_set(unit, TAG_1r, ®_val, CONFIG_INNER_TPID_ENABLEf, 1); 1310 } 1311 SOC_IF_ERROR_RETURN(WRITE_TAG_1r(unit, port, reg_val)); 1312 1313 SOC_IF_ERROR_RETURN(READ_TAG_0r(unit, port, ®_val)); 1314 if(outer_vlan_tag == -1) { 1315 soc_reg_field_set(unit, TAG_0r, ®_val, CONFIG_OUTER_TPID_ENABLEf, 0); 1316 } else { 1317 soc_reg_field_set(unit, TAG_0r, ®_val, FRM_TAG_0f, outer_vlan_tag); 1318 soc_reg_field_set(unit, TAG_0r, ®_val, CONFIG_OUTER_TPID_ENABLEf, 1); 1319 } 1320 1321 return (WRITE_TAG_0r(unit, port, reg_val)); 1322 } 1323 1324 1325 int unimac_rx_vlan_tag_get(int unit, soc_port_t port, int *outer_vlan_tag, int *inner_vlan_tag) 1326 { 1327 uint32 reg_val; 1328 uint32 enable = 0; 1329 1330 SOC_IF_ERROR_RETURN(READ_TAG_1r(unit, port, ®_val)); 1331 1332 enable = soc_reg_field_get(unit, TAG_1r, reg_val, CONFIG_INNER_TPID_ENABLEf); 1333 1334 *inner_vlan_tag = enable ? soc_reg_field_get(unit, TAG_1r, reg_val, FRM_TAG_1f) : -1; 1335 1336 SOC_IF_ERROR_RETURN(READ_TAG_0r(unit, port, ®_val)); 1337 1338 enable = soc_reg_field_get(unit, TAG_0r, reg_val, CONFIG_OUTER_TPID_ENABLEf); 1339 1340 *outer_vlan_tag = enable ? soc_reg_field_get(unit, TAG_0r, reg_val, FRM_TAG_0f) : -1; 1341 1342 return (SOC_E_NONE); 1343 } 1344 1345 1346 int unimac_pause_control_set(int unit, soc_port_t port, const portmod_pause_control_t *control) 1347 { 1348 uint32 command_config, old_command_config; 1349 1350 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1351 old_command_config = command_config; 1352 1353 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_IGNOREf, control->rx_enable ? 0 : 1); 1354 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, IGNORE_TX_PAUSEf, control->tx_enable ? 0 : 1); 1355 1356 if (command_config == old_command_config) { 1357 return SOC_E_NONE; 1358 } 1359 1360 SOC_IF_ERROR_RETURN(_unimac_soft_reset_and_config_set(unit, port, command_config)); 1361 1362 return SOC_E_NONE; 1363 } 1364 1365 1366 int unimac_pause_control_get(int unit, soc_port_t port, portmod_pause_control_t *control) 1367 { 1368 uint32 command_config; 1369 1370 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1371 1372 control->rx_enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, PAUSE_IGNOREf) ? FALSE : TRUE; 1373 control->tx_enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, IGNORE_TX_PAUSEf) ? FALSE : TRUE; 1374 1375 return SOC_E_NONE; 1376 } 1377 1378 1379 int unimac_pfc_control_set(int unit, soc_port_t port, const portmod_pfc_control_t *control) 1380 { 1381 uint32 reg_val = 0; 1382 1383 SOC_IF_ERROR_RETURN(READ_MAC_PFC_REFRESH_CTRLr(unit, port, ®_val)); 1384 1385 if(control->refresh_timer){ 1386 soc_reg_field_set (unit, MAC_PFC_REFRESH_CTRLr, ®_val, PFC_REFRESH_TIMERf, control->refresh_timer); 1387 soc_reg_field_set (unit, MAC_PFC_REFRESH_CTRLr, ®_val, PFC_REFRESH_ENf, 1); 1388 } else { 1389 soc_reg_field_set (unit, MAC_PFC_REFRESH_CTRLr, ®_val, PFC_REFRESH_ENf, 0); 1390 } 1391 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_REFRESH_CTRLr(unit, port ,reg_val)); 1392 1393 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port ,®_val)); 1394 soc_reg_field_set(unit, MAC_PFC_CTRLr, ®_val, PFC_STATS_ENf, control->stats_en); 1395 soc_reg_field_set(unit, MAC_PFC_CTRLr, ®_val, FORCE_PFC_XONf, control->force_xon); 1396 soc_reg_field_set(unit, MAC_PFC_CTRLr, ®_val, PFC_TX_ENBLf, control->tx_enable); 1397 soc_reg_field_set(unit, MAC_PFC_CTRLr, ®_val, PFC_RX_ENBLf, control->rx_enable); 1398 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_CTRLr_REG32(unit, port , reg_val)); 1399 1400 SOC_IF_ERROR_RETURN(READ_PFC_XOFF_TIMERr(unit, port, ®_val)); 1401 soc_reg_field_set(unit, PFC_XOFF_TIMERr, ®_val, PFC_XOFF_TIMERf, control->xoff_timer); 1402 1403 return(WRITE_PFC_XOFF_TIMERr(unit, port ,reg_val)); 1404 } 1405 1406 1407 int unimac_pfc_control_get(int unit, soc_port_t port, portmod_pfc_control_t *control) 1408 { 1409 uint32 reg_val = 0; 1410 uint32 refresh_enable = 0; 1411 uint32 refresh_timer = 0; 1412 1413 SOC_IF_ERROR_RETURN(READ_MAC_PFC_REFRESH_CTRLr(unit, port , ®_val)); 1414 1415 refresh_enable = soc_reg_field_get (unit, MAC_PFC_REFRESH_CTRLr, reg_val, PFC_REFRESH_ENf); 1416 if (refresh_enable) { 1417 refresh_timer = soc_reg_field_get (unit, MAC_PFC_REFRESH_CTRLr, reg_val, PFC_REFRESH_TIMERf); 1418 } 1419 control->refresh_timer = refresh_timer; 1420 1421 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, ®_val)); 1422 control->stats_en = soc_reg_field_get (unit, MAC_PFC_CTRLr, reg_val, PFC_STATS_ENf); 1423 control->force_xon = soc_reg_field_get (unit, MAC_PFC_CTRLr, reg_val, FORCE_PFC_XONf); 1424 control->rx_enable = soc_reg_field_get (unit, MAC_PFC_CTRLr, reg_val, PFC_RX_ENBLf); 1425 control->tx_enable = soc_reg_field_get (unit, MAC_PFC_CTRLr, reg_val, PFC_TX_ENBLf); 1426 1427 SOC_IF_ERROR_RETURN(READ_PFC_XOFF_TIMERr(unit, port , ®_val)); 1428 control->xoff_timer = soc_reg_field_get (unit, PFC_XOFF_TIMERr, reg_val, PFC_XOFF_TIMERf); 1429 1430 return (SOC_E_NONE); 1431 } 1432 1433 int unimac_tx_enable_set(int unit, soc_port_t port, int enable) 1434 { 1435 uint32 reg_val; 1436 1437 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, ®_val)); 1438 soc_reg_field_set(unit, COMMAND_CONFIGr, ®_val, TX_ENAf, enable ? 1: 0); 1439 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, reg_val)); 1440 1441 return(SOC_E_NONE); 1442 } 1443 1444 int unimac_tx_enable_get(int unit, soc_port_t port, int *enable) 1445 { 1446 uint32 reg_val; 1447 1448 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, ®_val)); 1449 *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, reg_val, TX_ENAf); 1450 1451 return(SOC_E_NONE); 1452 } 1453 1454 int unimac_reset_check(int unit, int port, int enable, int *reset) 1455 { 1456 uint32 ctrl, octrl; 1457 1458 *reset = 1; 1459 1460 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &ctrl)); 1461 octrl = ctrl; 1462 1463 soc_reg_field_set(unit, COMMAND_CONFIGr, &ctrl, TX_ENAf, enable ? 1: 0); 1464 soc_reg_field_set(unit, COMMAND_CONFIGr, &ctrl, RX_ENAf, enable ? 1: 0); 1465 1466 if (ctrl == octrl) { 1467 if (enable) { 1468 *reset = 0; 1469 } else { 1470 if (soc_reg_field_get(unit, COMMAND_CONFIGr, ctrl, SW_RESETf)) { 1471 *reset = 0; 1472 } 1473 } 1474 } 1475 1476 return SOC_E_NONE; 1477 } 1478 1479 1480 #undef _ERR_MSG_MODULE_NAME 1481 1482 1483 #endif /* PORTMOD_PM4X10Q_SUPPORT */ 1484 1485 1486 1487 1488 1489