phy_unimac.c (26304B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 */ 7 int phy_unimac_not_empty; 8 #if defined(INCLUDE_FCMAP) || defined(INCLUDE_MACSEC) || defined(INCLUDE_PLP_IMACSEC) 9 #include <sal/types.h> 10 #include <sal/core/alloc.h> 11 #include <sal/core/spl.h> 12 #include <sal/core/libc.h> 13 14 #include "phy_unimac.h" 15 #include "phy_mac_ctrl.h" 16 17 #if !defined(INCLUDE_FCMAP) && !defined(INCLUDE_MACSEC) 18 extern void sal_usleep(uint32 usec); 19 #define BMF_SAL_USLEEP sal_usleep 20 #define BLMI_E_IF_ERROR_RETURN(op) \ 21 do { int __rv__; if ((__rv__ = (op)) < 0) return(__rv__); } while(0) 22 #else 23 #include <buser_sal.h> 24 #include <blmi_err.h> 25 #endif 26 #define SPEED_MAPPING(_sp, _spr) do { \ 27 switch ( _sp ) { \ 28 case 0: return BLMI_E_NONE; \ 29 case 10: _spr = 0; break; \ 30 case 100: _spr = 1; break; \ 31 case 1000: _spr = 2; break; \ 32 default: return (BLMI_E_CONFIG); } } while(0) 33 34 /* JIRA BMACSEC-255 specific enhancement */ 35 #define UNIMAC_REG_BKP_IPG_CONFIG_RX_MASK 0x7c 36 #define UNIMAC_REG_BKP_IPG_CONFIG_RX_SHIFT 2 37 /*************************************************************** 38 * MACSEC driver functions. 39 */ 40 /* 41 * Function: 42 * phy_unimac_mac_init 43 * Purpose: 44 * Initialize the MAC 45 * Parameters: 46 * mmc - mac driver control 47 * dev_port - Port number 48 * Notes: 49 * The MAC will be put in Auto config mode at initilization 50 * MAX Frame Size = 0x3fff 51 * IPG = 12 52 * TX and RX are enabled 53 */ 54 int 55 phy_unimac_mac_init(phy_mac_ctrl_t *mmc, int dev_port) 56 { 57 58 uint32 macsec_ctrl, cmd_cfg; 59 60 /* Set MAC in Auto Config Mode */ 61 BLMI_E_IF_ERROR_RETURN( 62 phy_unimac_mac_auto_cfg(mmc, dev_port, 1)); 63 64 /* Set MAX Frame length to 0x3fff */ 65 BLMI_E_IF_ERROR_RETURN( 66 phy_unimac_mac_max_frame_set(mmc, dev_port, 67 UNIMAC_REG_DEFAULT_MAX_FRAME_SIZE)); 68 69 /* Set IPG to 12 */ 70 BLMI_E_IF_ERROR_RETURN( 71 phy_unimac_mac_update_ipg(mmc, dev_port, 72 UNIMAC_REG_DEFAULT_IPG)); 73 74 /* Enable TX and RX */ 75 BLMI_E_IF_ERROR_RETURN( 76 phy_unimac_mac_enable_set(mmc, dev_port, 1)); 77 78 /* Enable the TX CRC corrupt in MACSEC Control register */ 79 BLMI_E_IF_ERROR_RETURN( 80 UNIMAC_READ_MACSEC_CNTL_REG(mmc, dev_port, 81 &macsec_ctrl)); 82 macsec_ctrl &= ~(UNIMAC_REG_TX_CRC_ENABLE_MASK); 83 macsec_ctrl |= (UNIMAC_REG_TX_CRC_ENABLE << 84 UNIMAC_REG_TX_CRC_ENABLE_SHIFT); 85 BLMI_E_IF_ERROR_RETURN( 86 UNIMAC_WRITE_MACSEC_CNTL_REG(mmc, dev_port,macsec_ctrl)); 87 88 /* Set terminate CRC in the MAC and Pass MAC control Frames*/ 89 BLMI_E_IF_ERROR_RETURN( 90 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_cfg)); 91 cmd_cfg &= ~(UNIMAC_REG_CMD_CFG_CRC_FWD_MASK); 92 cmd_cfg &= ~(UNIMAC_REG_CMD_CFG_CTL_FRM_ENA_MASK); 93 cmd_cfg |= (UNIMAC_REG_CMD_CFG_CRC_FWD_DISABLE << 94 UNIMAC_REG_CMD_CFG_CRC_FWD_SHIFT); 95 cmd_cfg |= (1 << UNIMAC_REG_CMD_CTL_FRM_ENA_SHIFT); 96 BLMI_E_IF_ERROR_RETURN( 97 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_cfg)); 98 /* OVERFLOW check enable */ 99 #ifdef INCLUDE_PLP_IMACSEC 100 BLMI_E_IF_ERROR_RETURN( 101 UNIMAC_READ_UMAC_EEE_CTRL_REG(mmc, dev_port, &cmd_cfg)); 102 cmd_cfg |= UNIMAC_REG_EEE_CTRL_RX_FIFO_CHECK; 103 BLMI_E_IF_ERROR_RETURN( 104 UNIMAC_WRITE_UMAC_EEE_CTRL_REG(mmc, dev_port, cmd_cfg)); 105 BLMI_E_IF_ERROR_RETURN( 106 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_cfg)); 107 cmd_cfg |= UNIMAC_REG_CMD_CFG_OVERFLOW_EN; 108 BLMI_E_IF_ERROR_RETURN( 109 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_cfg)); 110 #endif 111 112 return BLMI_E_NONE; 113 } 114 115 /* 116 * Function: 117 * phy_unimac_mac_auto_cfg 118 * Purpose: 119 * This function puts the MAC in auto config if auto_cfg is 1. 120 * Parameters: 121 * mmc - mac driver control 122 * dev_port - Port number 123 * auto_cfg - Auto configuration flag 124 * 1 = Auto configuration 125 * 0 = Forced mode 126 * Notes: 127 */ 128 int 129 phy_unimac_mac_auto_cfg(phy_mac_ctrl_t *mmc, int dev_port, int auto_cfg) 130 { 131 uint32 cmd_reg, val; 132 133 val = (auto_cfg) ? 1 : 0; 134 135 BLMI_E_IF_ERROR_RETURN( 136 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 137 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_ENA_EXA_CONFIG_MASK); 138 cmd_reg |= (val << UNIMAC_REG_CMD_CFG_ENA_EXA_CONFIG_SHIFT); 139 BLMI_E_IF_ERROR_RETURN( 140 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 141 142 /* Need to sleep for 400ns (or 256 core clock cycles) */ 143 BMF_SAL_USLEEP(1); 144 145 return BLMI_E_NONE; 146 } 147 148 /* 149 */ 150 /* 151 * Function: 152 * phy_unimac_mac_reset 153 * Purpose: 154 * This function puts the MAC in reset if reset is 1 else takes mac 155 * out of reset 156 * Parameters: 157 * mmc - mac driver control 158 * dev_port - Port number 159 * reset - Reset MAC 160 * 1 = Put in Reset 161 * 0 = Take out of reset 162 * Notes: 163 */ 164 int 165 phy_unimac_mac_reset(phy_mac_ctrl_t *mmc, int dev_port, int reset) 166 { 167 uint32 cmd_reg, val; 168 169 val = (reset) ? 1 : 0; 170 171 BLMI_E_IF_ERROR_RETURN( 172 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 173 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_SW_RESET_MASK); 174 cmd_reg |= (val << UNIMAC_REG_CMD_CFG_SW_RESET_SHIFT); 175 BLMI_E_IF_ERROR_RETURN( 176 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 177 178 return BLMI_E_NONE; 179 } 180 181 /* 182 * Function: 183 * phy_unimac_mac_enable_set 184 * Purpose: 185 * Enable/Disable MAC 186 * Parameters: 187 * mmc - mac driver control 188 * dev_port - Port number 189 * enable - Enable flag 190 * 1 = Enable MAC 191 * 0 = Disable MAC 192 * Notes: 193 */ 194 int 195 phy_unimac_mac_enable_set(phy_mac_ctrl_t *mmc, int dev_port, int enable) 196 { 197 uint32 cmd_reg, val; 198 199 val = (enable) ? 1 : 0; 200 /* Put the mac in reset */ 201 BLMI_E_IF_ERROR_RETURN( 202 phy_unimac_mac_reset(mmc, dev_port, 1)); 203 204 BLMI_E_IF_ERROR_RETURN( 205 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 206 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_TXEN_MASK); 207 cmd_reg |= (val << UNIMAC_REG_CMD_CFG_TXEN_SHIFT); 208 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_RXEN_MASK); 209 cmd_reg |= (val << UNIMAC_REG_CMD_CFG_RXEN_SHIFT); 210 BLMI_E_IF_ERROR_RETURN( 211 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 212 213 /* Take mac out of reset */ 214 BLMI_E_IF_ERROR_RETURN( 215 phy_unimac_mac_reset(mmc, dev_port, 0)); 216 217 return BLMI_E_NONE; 218 } 219 220 /* 221 * Function: 222 * phy_unimac_mac_enable_get 223 * Purpose: 224 * Get the enable status of MAC 225 * Parameters: 226 * mmc - mac driver control 227 * dev_port - Port number 228 * enable - (OUT)Enable flag 229 * 1 = Enable MAC 230 * 0 = Disable MAC 231 * Notes: 232 */ 233 int 234 phy_unimac_mac_enable_get(phy_mac_ctrl_t *mmc, int dev_port, int *enable) 235 { 236 uint32 cmd_reg, val ; 237 238 BLMI_E_IF_ERROR_RETURN( 239 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 240 val = (cmd_reg & UNIMAC_REG_CMD_CFG_TXEN_MASK) >> 241 UNIMAC_REG_CMD_CFG_TXEN_SHIFT; 242 243 *(enable) = (val) ? 1 : 0; 244 245 return BLMI_E_NONE; 246 } 247 248 /* 249 * Function: 250 * phy_unimac_mac_speed_set 251 * Purpose: 252 * Set Speed of the MAC 253 * Parameters: 254 * mmc - mac driver control 255 * dev_port - Port number 256 * speed - 1000 - 1000Mbps 257 * 100 - 100Mbps 258 * 10 - 10Mbps 259 * Notes: 260 */ 261 int 262 phy_unimac_mac_speed_set(phy_mac_ctrl_t *mmc, int dev_port, int speed) 263 { 264 uint32 cmd_reg; 265 int speed_select; 266 267 switch (speed) { 268 case 0: /* No change */ 269 return BLMI_E_NONE; 270 case 10: 271 speed_select = 0; 272 break; 273 case 100: 274 speed_select = 1; 275 break; 276 case 1000: 277 speed_select = 2; 278 break; 279 default: 280 return (BLMI_E_CONFIG); 281 } 282 283 BLMI_E_IF_ERROR_RETURN( 284 phy_unimac_mac_reset(mmc, dev_port, 1)); 285 286 BLMI_E_IF_ERROR_RETURN( 287 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 288 289 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_SPEED_MASK); 290 cmd_reg |= (speed_select << UNIMAC_REG_CMD_CFG_SPEED_SHIFT); 291 292 BLMI_E_IF_ERROR_RETURN( 293 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 294 295 BLMI_E_IF_ERROR_RETURN( 296 phy_unimac_mac_reset(mmc, dev_port, 0)); 297 298 return BLMI_E_NONE; 299 } 300 301 /* 302 * Function: 303 * phy_unimac_mac_speed_get 304 * Purpose: 305 * Get Speed of the MAC 306 * Parameters: 307 * mmc - mac driver control 308 * dev_port - Port number 309 * speed - (OUT) 1000 - 1000Mbps 310 * 100 - 100Mbps 311 * 10 - 10Mbps 312 * Notes: 313 */ 314 int 315 phy_unimac_mac_speed_get(phy_mac_ctrl_t *mmc, int dev_port, int *speed) 316 { 317 int speed_select; 318 uint32 cmd_reg; 319 320 BLMI_E_IF_ERROR_RETURN( 321 UNIMAC_READ_MAC_MODE_REG(mmc, dev_port, &cmd_reg)); 322 speed_select = (cmd_reg & UNIMAC_REG_MAC_MODE_SPEED_MASK) >> 323 UNIMAC_REG_MAC_MODE_SPEED_SHIFT; 324 325 switch (speed_select) { 326 case 0: 327 *speed = 10; 328 break; 329 case 1: 330 *speed = 100; 331 break; 332 case 2: 333 *speed= 1000; 334 break; 335 default: 336 return (BLMI_E_INTERNAL); 337 } 338 return BLMI_E_NONE; 339 } 340 341 342 /* 343 * Function: 344 * phy_unimac_mac_duplex_set 345 * Purpose: 346 * Set Duplex of the MAC 347 * Parameters: 348 * mmc - mac driver control 349 * dev_port - Port number 350 * duplex - 1 - Full Duplex 351 * 0 - Half Duplex 352 * Notes: 353 */ 354 int 355 phy_unimac_mac_duplex_set(phy_mac_ctrl_t *mmc, int dev_port, int duplex) 356 { 357 358 uint32 cmd_reg; 359 int hd_enable, speed, rv = BLMI_E_NONE; 360 361 hd_enable = (duplex) ? 0 : 1; 362 363 BLMI_E_IF_ERROR_RETURN( 364 phy_unimac_mac_reset(mmc, dev_port, 1)); 365 366 BLMI_E_IF_ERROR_RETURN( 367 phy_unimac_mac_speed_get(mmc, dev_port, &speed)); 368 if ((speed >= 1000) && (hd_enable == 1)) { 369 /* Half duplex with Gigabit speed not supported */ 370 rv = BLMI_E_PARAM; 371 goto error; 372 } 373 374 BLMI_E_IF_ERROR_RETURN( 375 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 376 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_DUPLEX_MASK); 377 cmd_reg |= (hd_enable << UNIMAC_REG_CMD_CFG_DUPLEX_SHIFT); 378 BLMI_E_IF_ERROR_RETURN( 379 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 380 381 error: 382 BLMI_E_IF_ERROR_RETURN( 383 phy_unimac_mac_reset(mmc, dev_port, 0)); 384 return rv; 385 } 386 387 388 /* 389 * Function: 390 * phy_unimac_mac_duplex_get 391 * Purpose: 392 * Get Duplex of the MAC 393 * Parameters: 394 * mmc - mac driver control 395 * dev_port - Port number 396 * duplex - (OUT) 0 - Full Duplex 397 * 1 - Half Duplex 398 * Notes: 399 */ 400 int 401 phy_unimac_mac_duplex_get(phy_mac_ctrl_t *mmc, int dev_port, int *fd) 402 { 403 uint32 cmd_reg; 404 int hd_enable; 405 406 BLMI_E_IF_ERROR_RETURN( 407 UNIMAC_READ_MAC_MODE_REG(mmc, dev_port, &cmd_reg)); 408 hd_enable = (cmd_reg & UNIMAC_REG_MAC_MODE_DUPLEX_MASK) >> 409 UNIMAC_REG_MAC_MODE_DUPLEX_SHIFT; 410 411 *fd = (hd_enable) ? 1 : 0; 412 return BLMI_E_NONE; 413 } 414 415 416 417 /* 418 * Function: 419 * phy_unimac_mac_pause_set 420 * Purpose: 421 * Set pause of the MAC 422 * Parameters: 423 * mmc - mac driver control 424 * dev_port - Port number 425 * pause - 1 - Pause enable 426 * 0 - Pause disable 427 * Notes: 428 */ 429 int 430 phy_unimac_mac_pause_set(phy_mac_ctrl_t *mmc, int dev_port, int pause) 431 { 432 uint32 cmd_reg; 433 int tx_pause_ignore, rx_pause_ignore; 434 int duplex, rv = BLMI_E_NONE; 435 436 if(pause == 1) { 437 tx_pause_ignore = 0; 438 rx_pause_ignore = 0; 439 } else { 440 tx_pause_ignore = 1; 441 rx_pause_ignore = 1; 442 } 443 444 BLMI_E_IF_ERROR_RETURN( 445 phy_unimac_mac_reset(mmc, dev_port, 1)); 446 447 BLMI_E_IF_ERROR_RETURN( 448 phy_unimac_mac_duplex_get(mmc, dev_port, &duplex)); 449 450 /* handling of PAUSE is differnet in Half duplex more */ 451 if(duplex == 1) { /* Full Duplex */ 452 BLMI_E_IF_ERROR_RETURN( 453 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 454 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_TX_PAUSE_IGNORE_MASK); 455 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_RX_PAUSE_IGNORE_MASK); 456 cmd_reg |= (tx_pause_ignore << 457 UNIMAC_REG_CMD_CFG_TX_PAUSE_IGNORE_SHIFT); 458 cmd_reg |= (rx_pause_ignore << 459 UNIMAC_REG_CMD_CFG_RX_PAUSE_IGNORE_SHIFT); 460 BLMI_E_IF_ERROR_RETURN( 461 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 462 } else { 463 464 } 465 466 BLMI_E_IF_ERROR_RETURN( 467 phy_unimac_mac_reset(mmc, dev_port, 0)); 468 return rv; 469 } 470 471 472 /* 473 * Function: 474 * phy_unimac_mac_update_ipg 475 * Purpose: 476 * Set IPG of the MAC 477 * Parameters: 478 * mmc - mac driver control 479 * dev_port - Port number 480 * ipg - IPG value 481 * Notes: 482 */ 483 int 484 phy_unimac_mac_update_ipg(phy_mac_ctrl_t *mmc, int dev_port, int ipg) 485 { 486 uint32 ipg_reg; 487 488 if((ipg < 8) || (ipg > 64)) { 489 return BLMI_E_PARAM; 490 } 491 492 ipg_reg = ipg; 493 BLMI_E_IF_ERROR_RETURN( 494 UNIMAC_WRITE_TX_IPG_REG(mmc, dev_port, ipg_reg)); 495 496 return BLMI_E_NONE; 497 } 498 499 500 /* 501 * Function: 502 * phy_unimac_mac_max_frame_set 503 * Purpose: 504 * Set Max frame of the MAC 505 * Parameters: 506 * mmc - MAC control structure pointer 507 * dev_port - Port number 508 * max_frame - Max frame value 509 * Notes: 510 */ 511 int 512 phy_unimac_mac_max_frame_set(phy_mac_ctrl_t *mmc, int dev_port, 513 uint32 max_frame) 514 { 515 /* 516 * Maximum Frame size shouldn;t be less 48 and cannot be greater than 517 * 0x3fff 518 */ 519 if((max_frame < 48) || (max_frame > 0x3fff)) { 520 return BLMI_E_PARAM; 521 } 522 BLMI_E_IF_ERROR_RETURN( 523 UNIMAC_WRITE_FRM_LEN_REG(mmc, dev_port, max_frame)); 524 525 return BLMI_E_NONE; 526 } 527 528 /* 529 * Function: 530 * phy_unimac_mac_frame_len_check_enable 531 * Purpose: 532 * Enable the frame length check error mask in RSV vector 533 * to signal error to encryption block 534 * Parameters: 535 * mmc - MAC control structure pointer 536 * dev_port - Port number 537 * enable - Enable the error mask 538 * 1 - enable 539 * 0 - disable 540 * Notes: 541 */ 542 int 543 phy_unimac_mac_frame_len_check_enable(phy_mac_ctrl_t *mmc, int dev_port, int enable) 544 { 545 uint32 cmd_reg,rsv_mask; 546 /* */ 547 BLMI_E_IF_ERROR_RETURN( 548 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 549 if(enable){ 550 cmd_reg &= ~UNIMAC_REG_CMD_CFG_CTL_FRM_NO_LGTH_CHECK_MASK; 551 }else{ 552 cmd_reg |= UNIMAC_REG_CMD_CFG_CTL_FRM_NO_LGTH_CHECK_MASK; 553 } 554 BLMI_E_IF_ERROR_RETURN( 555 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 556 BLMI_E_IF_ERROR_RETURN( 557 UNIMAC_READ_GPORT_RSV_MASK_REG(mmc, dev_port, &rsv_mask)); 558 if(enable){ 559 rsv_mask |= UNIMAC_REG_GPORT_RSV_FRM_LEN_CHK_MASK; 560 }else{ 561 rsv_mask &= ~UNIMAC_REG_GPORT_RSV_FRM_LEN_CHK_MASK; 562 } 563 BLMI_E_IF_ERROR_RETURN( 564 UNIMAC_WRITE_GPORT_RSV_MASK_REG(mmc, dev_port, rsv_mask)); 565 566 return BLMI_E_NONE; 567 } 568 569 /* 570 * Function: 571 * phy_unimac_mac_rx_enable_set 572 * Purpose: 573 * Enable/Disable MAC RX 574 * Parameters: 575 * mmc - MAC control structure pointer 576 * dev_port - Port number 577 * enable - Enable the Rx 578 * 1 - enable 579 * 0 - disable 580 * Notes: 581 */ 582 int 583 phy_unimac_mac_rx_enable_set(phy_mac_ctrl_t *mmc, int dev_port, int enable) 584 { 585 uint32 cmd_reg; 586 BLMI_E_IF_ERROR_RETURN( 587 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 588 if(enable){ 589 cmd_reg |= UNIMAC_REG_CMD_CFG_RXEN_MASK; 590 }else{ 591 cmd_reg &= ~UNIMAC_REG_CMD_CFG_RXEN_MASK; 592 } 593 BLMI_E_IF_ERROR_RETURN( 594 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 595 return BLMI_E_NONE; 596 } 597 598 /* 599 * Function: 600 * phy_unimac_mac_tx_enable_set 601 * Purpose: 602 * Enable/Disable MAC TX 603 * Parameters: 604 * mmc - MAC control structure pointer 605 * dev_port - Port number 606 * enable - Enable the Tx 607 * 1 - enable 608 * 0 - disable 609 * Notes: 610 */ 611 612 int 613 phy_unimac_mac_tx_enable_set(phy_mac_ctrl_t *mmc, int dev_port, int enable) 614 { 615 uint32 cmd_reg; 616 BLMI_E_IF_ERROR_RETURN( 617 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 618 if(enable){ 619 cmd_reg |= UNIMAC_REG_CMD_CFG_TXEN_MASK; 620 }else{ 621 cmd_reg &= ~UNIMAC_REG_CMD_CFG_TXEN_MASK; 622 } 623 BLMI_E_IF_ERROR_RETURN( 624 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 625 return BLMI_E_NONE; 626 } 627 628 /* 629 * Function: 630 * phy_unimac_mac_tx_datapath_flush 631 * Purpose: 632 * TX-FIFO flush control enable 633 * Parameters: 634 * mmc - MAC control structure pointer 635 * dev_port - Port number 636 * 637 * Notes: Before calling TX datapath flush user has to disable pause function 638 * once TX_FIFO is empty reenable the pause function 639 */ 640 int 641 phy_unimac_mac_tx_datapath_flush(phy_mac_ctrl_t *mmc, int dev_port, int enable) 642 { 643 uint32 flush_ctrl; 644 BLMI_E_IF_ERROR_RETURN( 645 UNIMAC_READ_TX_FLUSH_CTRL_REG(mmc, dev_port, &flush_ctrl)); 646 if(enable){ 647 flush_ctrl |= UNIMAC_REG_TX_FLUSH_CTRL_MASK; 648 }else{ 649 flush_ctrl &= ~UNIMAC_REG_TX_FLUSH_CTRL_MASK; 650 } 651 652 BLMI_E_IF_ERROR_RETURN( 653 UNIMAC_WRITE_TX_FLUSH_CTRL_REG(mmc, dev_port, flush_ctrl)); 654 655 656 return BLMI_E_NONE; 657 } 658 /* 659 * Function: 660 * phy_unimac_mac_max_frame_get 661 * Purpose: 662 * Get Max frame of the MAC 663 * Parameters: 664 * mmc - MAC control structure pointer 665 * dev_port - Port number 666 * max_frame - (OUT) Max frame 667 * Notes: 668 */ 669 int 670 phy_unimac_mac_max_frame_get(phy_mac_ctrl_t *mmc, int dev_port, 671 uint32 *max_frame) 672 { 673 uint32 frame_len; 674 675 BLMI_E_IF_ERROR_RETURN( 676 UNIMAC_READ_FRM_LEN_REG(mmc, dev_port, &frame_len)); 677 *max_frame = frame_len & UNIMAC_REG_FRM_LENr_FMR_LEN_MASK; 678 679 return BLMI_E_NONE; 680 } 681 682 /* 683 * Function: 684 * phy_unimac_mac_pause_frame_fwd_set 685 * Purpose: 686 * Enable/Disable Pause Frame Forward 687 * Parameters: 688 * mmc - MAC control structure pointer 689 * dev_port - Port number 690 * pause_fwd - Pause forward 691 * 1 - Forward pause 692 * 0 - Consume PAUSE. 693 * Notes: 694 */ 695 int 696 phy_unimac_mac_pause_frame_fwd_set(phy_mac_ctrl_t *mmc, int dev_port, 697 int pause_fwd) 698 { 699 int pause; 700 uint32 cmd_reg; 701 702 if (pause_fwd == 1) { 703 pause = 1; 704 } else { 705 if (pause_fwd == 0) { 706 pause = 0; 707 } else { 708 return BLMI_E_CONFIG; 709 } 710 } 711 BLMI_E_IF_ERROR_RETURN( 712 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg)); 713 cmd_reg &= ~(UNIMAC_REG_CMD_CFG_PAUSE_FWD_MASK); 714 cmd_reg |= (pause << UNIMAC_REG_CMD_CFG_PAUSE_FWD_SHIFT); 715 BLMI_E_IF_ERROR_RETURN( 716 UNIMAC_WRITE_CMD_CFG_REG(mmc, dev_port, cmd_reg)); 717 718 return BLMI_E_NONE; 719 } 720 721 /* 722 * Function: 723 * phy_unimac_mac_pause_frame_fwd_get 724 * Purpose: 725 * Get the status of Pause Frame Forward 726 * Parameters: 727 * mmc - MAC control structure pointer 728 * dev_port - Port number 729 * pause_fwd - Pause forward 730 * 1 - Forward pause 731 * 0 - Consume PAUSE. 732 * Notes: 733 */ 734 int 735 phy_unimac_mac_pause_frame_fwd_get(phy_mac_ctrl_t *mmc, int dev_port, 736 int *pause_fwd) 737 { 738 uint32 cmd_reg; 739 740 BLMI_E_IF_ERROR_RETURN( 741 UNIMAC_READ_CMD_CFG_REG(mmc, dev_port, &cmd_reg) ); 742 *pause_fwd = (cmd_reg & UNIMAC_REG_CMD_CFG_PAUSE_FWD_MASK) 743 >> UNIMAC_REG_CMD_CFG_PAUSE_FWD_SHIFT; 744 745 return BLMI_E_NONE; 746 } 747 748 /* 749 * Function: 750 * phy_unimac_mac_hd_flow_cntl_set 751 * Purpose: 752 * Enable/Disable Half-Duplex Flow Control 753 * Parameters: 754 * mmc - mac driver control 755 * dev_port - Port number 756 * enable - Enable flag 757 * 1 = Enable Half-Duplex Flow Control 758 * 0 = Disable Half-Duplex Flow Control 759 * Notes: 760 */ 761 int 762 phy_unimac_mac_hd_flow_cntl_set(phy_mac_ctrl_t *mmc, int dev_port, int enable) 763 { 764 uint32 cmd_reg, val; 765 766 val = (enable) ? 1 : 0; 767 768 BLMI_E_IF_ERROR_RETURN( 769 UNIMAC_READ_IPG_HD_BKP_CNTL_REG(mmc, dev_port, &cmd_reg)); 770 cmd_reg &= ~(UNIMAC_REG_BKP_HD_FC_ENA_MASK) | 771 ~(UNIMAC_REG_BKP_HD_FC_BKOFF_MASK); 772 cmd_reg |= (val << UNIMAC_REG_BKP_HD_FC_ENA_SHIFT) | 773 (val << UNIMAC_REG_BKP_HD_FC_BKOFF_SHIFT); 774 BLMI_E_IF_ERROR_RETURN( 775 UNIMAC_WRITE_IPG_HD_BKP_CNTL_REG(mmc, dev_port, cmd_reg) ); 776 777 return BLMI_E_NONE; 778 } 779 780 /* 781 * Function: 782 * phy_unimac_mac_hd_flow_cntl_get 783 * Purpose: 784 * Get the enable status of Half-Duplex Flow Control 785 * Parameters: 786 * mmc - mac driver control 787 * dev_port - Port number 788 * enable - (OUT)Enable flag 789 * 1 = Enable Half-Duplex Flow Control 790 * 0 = Disable Half-Duplex Flow Control 791 * Notes: 792 */ 793 int 794 phy_unimac_mac_hd_flow_cntl_get(phy_mac_ctrl_t *mmc, int dev_port, int *enable) 795 { 796 uint32 cmd_reg; 797 798 BLMI_E_IF_ERROR_RETURN( 799 UNIMAC_READ_IPG_HD_BKP_CNTL_REG(mmc, dev_port, &cmd_reg) ); 800 *(enable) = (cmd_reg & UNIMAC_REG_BKP_HD_FC_ENA_MASK) 801 >> UNIMAC_REG_BKP_HD_FC_ENA_SHIFT; 802 return BLMI_E_NONE; 803 } 804 805 806 /* Duplex Gateway support : Line-side MAC = half-duplex *\ 807 \* Switch-side MAC = full-duplex */ 808 809 /* 810 * Function: 811 * _mac_duplex_gateway_set 812 * Purpose: 813 * Config line/switch-side MAC for Duplex Gateway mode 814 * Notes: 815 */ 816 static int 817 _mac_duplex_gateway_set(phy_mac_ctrl_t *mmc, int port, 818 int speed, int fullduplex, 819 int ipg, int max_frame, int line_side) 820 { 821 uint32 cmd_reg; 822 823 /* Put the MAC in reset */ 824 BLMI_E_IF_ERROR_RETURN( 825 phy_unimac_mac_reset(mmc, port, 1) ); 826 827 /* set Max Frame Size and Interpacket Gap */ 828 BLMI_E_IF_ERROR_RETURN( 829 phy_unimac_mac_max_frame_set(mmc, port, max_frame) ); 830 BLMI_E_IF_ERROR_RETURN( 831 phy_unimac_mac_update_ipg(mmc, port, ipg) ); 832 /* enable back-pressure in half-duplex mode for the line-side MAC */ 833 BLMI_E_IF_ERROR_RETURN( 834 phy_unimac_mac_hd_flow_cntl_set(mmc, port, 835 (line_side && (!fullduplex)) ? 1 : 0) ); 836 837 /* read the COMMAND_CONFIG register */ 838 BLMI_E_IF_ERROR_RETURN( 839 UNIMAC_READ_CMD_CFG_REG(mmc, port, &cmd_reg)); 840 841 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, speed, 842 UNIMAC_REG_CMD_CFG_SPEED_MASK, 843 UNIMAC_REG_CMD_CFG_SPEED_SHIFT); 844 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, ((fullduplex) ? 0 : 1), 845 UNIMAC_REG_CMD_CFG_DUPLEX_MASK, 846 UNIMAC_REG_CMD_CFG_DUPLEX_SHIFT); 847 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, ((line_side) ? 1 : 0), 848 UNIMAC_REG_CMD_CFG_ENA_EXA_CONFIG_MASK, 849 UNIMAC_REG_CMD_CFG_ENA_EXA_CONFIG_SHIFT); 850 851 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, 1, UNIMAC_REG_CMD_CFG_TXEN_MASK, 852 UNIMAC_REG_CMD_CFG_TXEN_SHIFT); 853 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, 1, UNIMAC_REG_CMD_CFG_RXEN_MASK, 854 UNIMAC_REG_CMD_CFG_RXEN_SHIFT); 855 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, 1, UNIMAC_REG_CMD_CFG_PROMIS_EN_MASK, 856 UNIMAC_REG_CMD_CFG_PROMIS_EN_SHIFT); 857 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, 0, UNIMAC_REG_CMD_CFG_CRC_FWD_MASK, 858 UNIMAC_REG_CMD_CFG_CRC_FWD_SHIFT); 859 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, 0, UNIMAC_REG_CMD_CFG_PAUSE_FWD_MASK, 860 UNIMAC_REG_CMD_CFG_PAUSE_FWD_SHIFT); 861 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, ((line_side) ? 0 : 1), 862 UNIMAC_REG_CMD_CFG_SW_OVERRIDE_TX_MASK, 863 UNIMAC_REG_CMD_CFG_SW_OVERRIDE_TX_SHIFT); 864 BMACSEC_MAC_REG_FIELD_SET(cmd_reg, ((line_side) ? 0 : 1), 865 UNIMAC_REG_CMD_CFG_SW_OVERRIDE_RX_MASK, 866 UNIMAC_REG_CMD_CFG_SW_OVERRIDE_RX_SHIFT); 867 868 /* write to COMMAND_CONFIG register */ 869 BLMI_E_IF_ERROR_RETURN( 870 UNIMAC_WRITE_CMD_CFG_REG(mmc, port, cmd_reg)); 871 872 /* JIRA BMACSEC-255 specific enhancement */ 873 if(!line_side) { 874 uint32 data; 875 BLMI_E_IF_ERROR_RETURN(UNIMAC_READ_IPG_HD_BKP_CNTL_REG(mmc, port, &data)); 876 if(speed == 0 || speed== 1) { /* 0 is 10M mode, 1 is 100M mode */ 877 data &= ~(UNIMAC_REG_BKP_IPG_CONFIG_RX_MASK); 878 data |= 10 << UNIMAC_REG_BKP_IPG_CONFIG_RX_SHIFT; 879 } else { /* Otherwise, 1G or above mode */ 880 data &= ~(UNIMAC_REG_BKP_IPG_CONFIG_RX_MASK); 881 data |= 5 << UNIMAC_REG_BKP_IPG_CONFIG_RX_SHIFT; 882 } 883 BLMI_E_IF_ERROR_RETURN(UNIMAC_WRITE_IPG_HD_BKP_CNTL_REG(mmc, port, data)); 884 } 885 886 /* Take MAC out of reset */ 887 BLMI_E_IF_ERROR_RETURN( 888 phy_unimac_mac_reset(mmc, port, 0)); 889 890 return BLMI_E_NONE; 891 } 892 893 /* 894 * Function: 895 * unimac_mac_duplex_gateway_set 896 * Purpose: 897 * Set Duplex Gateway mode 898 * Parameters: 899 * mmc - mac driver control 900 * dgw - duplex gateway control structure 901 * Notes: 902 */ 903 int 904 phy_unimac_mac_duplex_gateway_set(phy_mac_ctrl_t *mmc, 905 phy_mac_duplex_gateway_t *dgw) 906 { 907 int speed; 908 SPEED_MAPPING(dgw->speed, speed); 909 910 /* config line-side MAC */ 911 BLMI_E_IF_ERROR_RETURN( 912 _mac_duplex_gateway_set(mmc, dgw->lport, 913 speed, dgw->duplex, dgw->ipg, dgw->max_frame, 1) ); 914 /* config switch-side MAC, always full-duplex */ 915 BLMI_E_IF_ERROR_RETURN( 916 _mac_duplex_gateway_set(mmc, dgw->sport, 917 speed, 1 , dgw->ipg, dgw->max_frame, 0) ); 918 919 return BLMI_E_NONE; 920 } 921 922 /***************************************************/ 923 /* MAC Driver Functions */ 924 phy_mac_drv_t phy_unimac_drv = { 925 phy_unimac_mac_init, 926 phy_unimac_mac_reset, 927 phy_unimac_mac_auto_cfg, 928 phy_unimac_mac_enable_set, 929 phy_unimac_mac_enable_get, 930 phy_unimac_mac_speed_set, 931 phy_unimac_mac_speed_get, 932 phy_unimac_mac_duplex_set, 933 phy_unimac_mac_duplex_get, 934 phy_unimac_mac_update_ipg, 935 phy_unimac_mac_max_frame_set, 936 phy_unimac_mac_max_frame_get, 937 phy_unimac_mac_pause_set, 938 NULL, 939 phy_unimac_mac_pause_frame_fwd_set, 940 phy_unimac_mac_pause_frame_fwd_get, 941 phy_unimac_mac_duplex_gateway_set, 942 phy_unimac_mac_frame_len_check_enable, 943 phy_unimac_mac_rx_enable_set, 944 phy_unimac_mac_tx_enable_set, 945 phy_unimac_mac_tx_datapath_flush 946 }; 947 948 #endif /* defined(INCLUDE_FCMAP) || defined (INCLUDE_MACSEC) */