tomahawk3_ep_init.c (42955B)
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 * File: tomahawk3_ep_init.c 8 * Purpose: 9 * Requires: 10 */ 11 12 13 #include <shared/bsl.h> 14 #include <soc/tdm/core/tdm_top.h> 15 16 #include <soc/defs.h> 17 #include <soc/mem.h> 18 19 #if defined(BCM_TOMAHAWK3_SUPPORT) 20 21 #include <soc/init/tomahawk3_ep_init.h> 22 #include <soc/flexport/flexport_common.h> 23 #include <soc/init/tomahawk3_tdm.h> 24 25 /*** START SDK API COMMON CODE ***/ 26 27 28 #define TH3_EP_SLOT_LAT_DPP_LATENCY_W_EFP 51 29 #define TH3_EP_SLOT_LAT_DPP_LATENCY_WO_EFP 37 30 #define TH3_EP_SLOT_LAT_CREDIT_LOOP 12 31 #define TH3_EP_SLOT_LAT_EXTRA_LAT_EARB_DPP 3 32 #define TH3_EP_SLOT_LAT_DOMAIN_CROSSING 3 33 #define TH3_EP_SLOT_LAT_OUTSTANDING_CREDIT 21 34 #define TH3_EP_SLOT_LAT_DEF_MARGIN 3 35 #define TH3_EP_SLOT_LAT_MAX_ACCUM_DPPR_1 4 36 #define TH3_EP_MAX_CT_CLASSES 16 37 #define TH3_EP_NUM_CT_CLASSES 8 38 39 /* EP2MMU credits for Aux ports */ 40 #define TH3_EP_EP2MMU_CRED_CPU 13 41 #define TH3_EP_EP2MMU_CRED_MGM 8 42 #define TH3_EP_EP2MMU_CRED_LBK 48 43 44 #define TH3_EP_XMIT_START_CNT_MGM 12 45 46 /*! @file tomahawk3_ep_init.c 47 * @brief EP (EDB) Init/FlexPort APIs for Tomahawk2. 48 * Details are shown below. 49 */ 50 51 52 /* EDB Credits and XMIT_CNT Table */ 53 static const soc_th3_ep_core_cfg_t 54 soc_th3_ep_core_cfg_tbl[] = { 55 /* speed ct ep2mmu ep2mmu xmit_cnt 56 * class credits credits 57 * general optimized saf ct 58 */ 59 { 0, 0, 0, 0, {{ 0, 0}} }, /* SAF */ 60 { 10000, 1, 8, 7, {{ 4, 23}} }, /* 10GE */ 61 { 25000, 2, 15, 11, {{10, 43}} }, /* 25GE */ 62 { 40000, 3, 20, 14, {{16, 26}} }, /* 40GE */ 63 { 50000, 4, 28, 20, {{20, 85}} }, /* 50GE */ 64 {100000, 5, 57, 42, {{23, 54}} }, /* 100GE */ 65 {200000, 6, 100, 71, {{28, 65}} }, /* 200GE */ 66 {400000, 7, 142, 110, {{29, 57}} } /* 400GE */ 67 }; 68 69 70 /*! @fn int soc_tomahawk3_div_round_up( 71 * int nominator, 72 * int denominator) 73 * @param int nominator 74 * @param int denominator 75 * @brief API for round int division 76 * Description: 77 * round int division 78 */ 79 static int soc_tomahawk3_div_round_up( 80 int nominator, 81 int denominator) 82 { 83 if (denominator == 0) { return 1; } 84 85 return ( (nominator + denominator - 1) / denominator ); 86 } 87 88 89 /*! @fn int soc_tomahawk3_div_round( 90 * int nominator, 91 * int denominator) 92 * @param int nominator 93 * @param int denominator 94 * @brief API for round int division 95 * Description: 96 * round int division 97 */ 98 int soc_tomahawk3_div_round( 99 int nominator, 100 int denominator) 101 { 102 int modulo; 103 104 if (denominator == 0) { return 1; } 105 106 modulo = nominator % denominator; 107 108 if (modulo >= ((denominator + 1) / 2)) { 109 return ( (nominator + denominator - 1) / denominator ); 110 } else { 111 return ( nominator / denominator ); 112 } 113 } 114 115 116 /*! @fn int soc_tomahawk3_get_set_slot_pipeline_latency() 117 * Return Value: 118 * SOC_E_* 119 * Description: 120 * Input parameters: 121 * Core frequency 122 * Dpp Frequency 123 * DPP Latency (DPPL) 124 * Extra latency in DPP clk (A) 125 * Domain crossing for output event fifo(B) 126 * N - Credit loop (12) 127 * C - Outstanding Credit (20) 128 * Default margin (D) 129 * Early retrieval in core clk (E) 130 */ 131 int soc_tomahawk3_get_set_slot_pipeline_latency( 132 int core_freq, 133 int dpp_freq, 134 int dppl, 135 int A_in, 136 int B_in, 137 int N_in, 138 int C_in, 139 int D_in, 140 int E_in, 141 int *slot_latency) 142 { 143 int max_accum_latency; 144 145 *slot_latency = soc_tomahawk3_div_round(((dppl + A_in + B_in) * core_freq), dpp_freq); 146 147 max_accum_latency = (core_freq == dpp_freq) ? TH3_EP_SLOT_LAT_MAX_ACCUM_DPPR_1 : 148 soc_tomahawk3_div_round_up(core_freq * 149 (C_in + TH3_EP_SLOT_LAT_MAX_ACCUM_DPPR_1), dpp_freq) 150 - N_in; 151 152 *slot_latency += D_in + E_in + max_accum_latency; 153 154 return SOC_E_NONE; 155 } 156 157 158 /*! @fn int soc_tomahawk3_ep_set_slot_pipeline_config( 159 * int unit, 160 * soc_port_schedule_state_t *port_schedule_state, 161 * int pipe_num) 162 * @param unit Chip unit number. 163 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 164 * struct variable. 165 * @param pipe pipe number. 166 * @brief API to initialize EPOST_SLOT_PIPELINE_CONFIG 167 * Description: 168 * API to initialize EPOST_SLOT_PIPELINE_CONFIG 169 * Regs/Mems configured: EP-EARB 170 * Parameters: 171 * unit - Device number 172 * *port_schedule_state_t - Agreed structure between SDK and DV 173 * Return Value: 174 * SOC_E_* 175 */ 176 int soc_tomahawk3_ep_set_slot_pipeline_config( 177 int unit, 178 soc_port_schedule_state_t *port_schedule_state) 179 { 180 soc_reg_t reg; 181 uint32 rval; 182 int dpp_clks_latency = 0; 183 int core_clks_latency, bypass_mode = 0; 184 int core_clock_freq, dpp_clock_freq; 185 186 reg = EPOST_SLOT_PIPELINE_CONFIGr; 187 188 /* 189 * slot_latency = ROUND[ (DPPL + A + B) * R] + M + D 190 * DPPL - DPP Latency (FULL = 57; EFP BYPASS = 44) 191 * A - Latency due to async interfaces in between Earb and DPP (6) 192 * B - Domain crossing for output event fifo (3) 193 * M - Maximum latency - see formula 194 * D - Default margin. This should be the minimal number that the 195 * DPP can work properly in order to have minimal latency (5) 196 * R - dpp ratio = (Foreq_core / Freq_dpp) 197 * 198 * 199 * M = ( R == 1) ? 4 : ROUND_UP[R*(N*(R-1)/R + C - N + 4)] 200 * N - Credit loop (12) 201 * C - Outstanding Credit (20) 202 */ 203 204 205 /* Set the latency in Slot Pipeline config register, need to be 206 * programmed before any traffic going through the EP */ 207 rval = 0; 208 bypass_mode = soc_property_get(unit, spn_SWITCH_BYPASS_MODE, SOC_SWITCH_BYPASS_MODE_NONE); 209 if (bypass_mode == 3) { 210 /* w/o EFP */ 211 dpp_clks_latency = TH3_EP_SLOT_LAT_DPP_LATENCY_WO_EFP; 212 } else { 213 /* w/ EFP */ 214 dpp_clks_latency = TH3_EP_SLOT_LAT_DPP_LATENCY_W_EFP; 215 } 216 217 core_clock_freq = port_schedule_state->frequency; 218 dpp_clock_freq = port_schedule_state->in_port_map.port_p2PBLK_inst_mapping[0]; 219 220 soc_tomahawk3_get_set_slot_pipeline_latency( 221 core_clock_freq, 222 dpp_clock_freq, 223 dpp_clks_latency, /* DPP Latency (DPPL) */ 224 TH3_EP_SLOT_LAT_EXTRA_LAT_EARB_DPP, /* Extra latency in DPP clk (A) */ 225 TH3_EP_SLOT_LAT_DOMAIN_CROSSING, /* Domain crossing for output event fifo(B) */ 226 TH3_EP_SLOT_LAT_CREDIT_LOOP, /* N - Credit loop (12) */ 227 TH3_EP_SLOT_LAT_OUTSTANDING_CREDIT, /* C - Outstanding Credit (20) */ 228 TH3_EP_SLOT_LAT_DEF_MARGIN, /* Default margin (D) */ 229 0, /* Early retrieval in core clk (E); 0 for EP*/ 230 &core_clks_latency); 231 232 soc_reg_field_set(unit, reg, &rval, WR_ENf, 0); 233 soc_reg_field_set(unit, reg, &rval, LATENCYf, core_clks_latency); 234 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 235 236 soc_reg_field_set(unit, reg, &rval, WR_ENf, 1); 237 soc_reg_field_set(unit, reg, &rval, LATENCYf, core_clks_latency); 238 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 239 240 return SOC_E_NONE; 241 } 242 243 244 /*! @fn int soc_tomahawk3_ep_set_dev_to_phy( 245 * int unit, 246 * soc_port_schedule_state_t *port_schedule_state, 247 * int pipe, 248 * int phy_port, 249 * int is_port_down) 250 * @param unit Chip unit number. 251 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 252 * struct variable. 253 * @param pipe pipe number. 254 * @param phy_port phy_port to configure. 255 * @param phy_port is_port_down. boolean to indicate if port goes down 256 * @brief API to initialize/clear per port EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPING 257 * Description: 258 * API to initialize/clear per port EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPING 259 * Regs/Mems configured: EDB 260 * Parameters: 261 * unit - Device number 262 * *port_schedule_state_t - Agreed structure between SDK and DV 263 * Return Value: 264 * SOC_E_* 265 */ 266 int soc_tomahawk3_ep_set_dev_to_phy( 267 int unit, 268 soc_port_schedule_state_t *port_schedule_state, 269 int pipe_num, 270 int phy_port, 271 int is_port_down) 272 { 273 soc_mem_t mem; 274 uint32 memfld; 275 uint32 entry[SOC_MAX_MEM_WORDS]; 276 int logical_port; 277 278 mem = EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGm; 279 if (0 == is_port_down) { 280 logical_port = port_schedule_state->out_port_map.port_p2l_mapping[phy_port]; 281 memfld = phy_port; 282 } else { 283 logical_port = port_schedule_state->in_port_map.port_p2l_mapping[phy_port]; 284 memfld = 0x1FF; 285 } 286 sal_memset(entry, 0, sizeof(uint32) * 287 soc_mem_entry_words(unit, EDB_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGm)); 288 soc_mem_field_set(unit, mem, entry, DATAf, &memfld); 289 290 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, logical_port, 291 entry)); 292 293 return SOC_E_NONE; 294 } 295 296 /*! @fn int soc_tomahawk3_ep_set_mmu_cell_credit( 297 * int unit, 298 * soc_port_schedule_state_t *port_schedule_state, 299 * int pipe, 300 * int phy_port, 301 * int is_port_down) 302 * @param unit Chip unit number. 303 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 304 * struct variable. 305 * @param pipe pipe number. 306 * @param phy_port phy_port to configure. 307 * @param phy_port is_port_down. boolean to indicate if port goes down 308 * @brief API to initialize/clear per port EGR_MMU_CELL_CREDIT 309 * Description: 310 * API to initialize/clear per port EGR_MMU_CELL_CREDIT 311 * Regs/Mems configured: EDB 312 * Parameters: 313 * unit - Device number 314 * *port_schedule_state_t - Agreed structure between SDK and DV 315 * Return Value: 316 * SOC_E_* 317 */ 318 int soc_tomahawk3_ep_set_mmu_cell_credit( 319 int unit, 320 soc_port_schedule_state_t *port_schedule_state, 321 int pipe_num, 322 int phy_port, 323 int is_port_down) 324 { 325 uint32 entry[SOC_MAX_MEM_WORDS]; 326 uint32 memfld; 327 soc_mem_t mem; 328 329 if (0 == is_port_down) { /* port up */ 330 memfld = soc_tomahawk3_ep_get_ep2mmu_credit(unit, port_schedule_state, 331 phy_port); 332 } else { /* port down */ 333 memfld = 0; 334 } 335 336 mem = EGR_MMU_CELL_CREDITm; 337 sal_memset(entry, 0, sizeof(uint32) * 338 soc_mem_entry_words(unit, EGR_MMU_CELL_CREDITm)); 339 soc_mem_field_set(unit, mem, entry, CREDITf, &memfld); 340 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port, 341 entry)); 342 return SOC_E_NONE; 343 } 344 345 346 /*! @fn int soc_tomahawk3_get_freq_encoding( 347 * int unit, 348 * soc_port_schedule_state_t *port_schedule_state) 349 * @param unit Chip unit number. 350 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 351 * struct variable. 352 * Calculates index into xmit_cnt_per_freq array 353 * Return Value: 354 * SOC_E_* 355 */ 356 static int soc_tomahawk3_get_freq_encoding( 357 int unit, 358 soc_port_schedule_state_t *port_schedule_state, 359 int *freq_encoding) 360 { 361 362 /* All Core/PP frequencies have the same settings for xmit_cnt */ 363 *freq_encoding = 0; 364 return SOC_E_NONE; 365 } 366 367 368 /*! @fn int soc_tomahawk3_get_speed_encoding( 369 * int speed, 370 * int *speed_encoding) 371 * @param speed Speed 372 * @param *speed_encoding speed encoding 373 * @brief Helper function to get CT class 374 */ 375 int 376 soc_tomahawk3_get_speed_encoding( 377 int speed, 378 int *speed_encoding) 379 { 380 *speed_encoding = 0; 381 switch (speed) { 382 case 10000: *speed_encoding = 1; break; 383 case 25000: *speed_encoding = 2; break; 384 case 40000: *speed_encoding = 3; break; 385 case 50000: *speed_encoding = 4; break; 386 case 100000: *speed_encoding = 5; break; 387 case 200000: *speed_encoding = 6; break; 388 case 400000: *speed_encoding = 7; break; 389 default: return SOC_E_PARAM; break; 390 } 391 return SOC_E_NONE; 392 } 393 394 /*! @fn int soc_tomahawk3_get_ct_class(int speed) 395 * @param speed Speed 396 * @brief Helper function to get CT class 397 */ 398 int 399 soc_tomahawk3_get_ct_class(int speed) 400 { 401 int speed_encoding; 402 SOC_IF_ERROR_RETURN( 403 soc_tomahawk3_get_speed_encoding(speed, &speed_encoding)); 404 return soc_th3_ep_core_cfg_tbl[speed_encoding].ct_class; 405 } 406 407 /*! @fn int soc_tomahawk3_ep_get_ep2mmu_credit(int unit, 408 * soc_port_schedule_state_t *port_schedule_state, int phy_port) 409 * @param unit Chip unit number. 410 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 411 * variable 412 * @param logical_port Dev port num 413 * @param ovs_ratio ovs_ratio inside {10-LR, 15-OVS 3:2, 20- OVS 2:1} 414 * @brief Helper function to get EP2MMU credit for a port; 415 * This API assumes that credits were retrieved for active ports after FlexPort 416 */ 417 int 418 soc_tomahawk3_ep_get_ep2mmu_credit( 419 int unit, soc_port_schedule_state_t *port_schedule_state, int phy_port) 420 { 421 int logical_port, speed; 422 int ep2mmu_credit = 0; 423 424 if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) { 425 /* Either Init or FlexPort, out_port_map should be used 426 * since this function is called only on port up */ 427 logical_port = 428 port_schedule_state->out_port_map.port_p2l_mapping[phy_port]; 429 speed = port_schedule_state->out_port_map.log_port_speed[logical_port]; 430 SOC_IF_ERROR_RETURN( 431 soc_tomahawk3_ep_get_ep2mmu_credit_per_speed( 432 unit, port_schedule_state, speed, &ep2mmu_credit)); 433 } else if (phy_port == _TH3_PHY_PORT_CPU) { 434 ep2mmu_credit = TH3_EP_EP2MMU_CRED_CPU; /* CPU credits for 25G */ 435 } else if ((phy_port == _TH3_PHY_PORT_MNG0) || 436 (phy_port == _TH3_PHY_PORT_MNG1) ) { 437 ep2mmu_credit = TH3_EP_EP2MMU_CRED_MGM; /* MGM credits for 10G */ 438 } else if ( (phy_port >= _TH3_PHY_PORT_LPBK0) && 439 (phy_port <= _TH3_PHY_PORT_LPBK7) ) { 440 ep2mmu_credit = TH3_EP_EP2MMU_CRED_LBK; /* LBK credits for >100G */ 441 } 442 443 return ep2mmu_credit; 444 } 445 446 /*! @fn int soc_tomahawk3_ep_get_ep2mmu_credit_per_speed(int unit, 447 * soc_port_schedule_state_t *port_schedule_state, 448 * int speed, int *credit) 449 */ 450 int 451 soc_tomahawk3_ep_get_ep2mmu_credit_per_speed( 452 int unit, 453 soc_port_schedule_state_t *port_schedule_state, 454 int speed, 455 int *credit) 456 { 457 int speed_encoding; 458 int core_clock_freq, dpp_clock_freq; 459 460 core_clock_freq = port_schedule_state->frequency; 461 dpp_clock_freq = port_schedule_state->in_port_map.port_p2PBLK_inst_mapping[0]; 462 463 SOC_IF_ERROR_RETURN( 464 soc_tomahawk3_get_speed_encoding(speed, &speed_encoding)); 465 466 if ((core_clock_freq == 1325) && 467 (dpp_clock_freq == 1000)) { /* PFC optimized for 1325/1000 */ 468 *credit = soc_th3_ep_core_cfg_tbl[speed_encoding].egr_mmu_credit_pfc_opt; 469 } else { 470 *credit = soc_th3_ep_core_cfg_tbl[speed_encoding].egr_mmu_credit; 471 } 472 473 return SOC_E_NONE; 474 } 475 476 477 /*! @fn int soc_tomahawk3_ep_set_ct_class( 478 * int unit, 479 * soc_port_schedule_state_t *port_schedule_state, 480 * int pipe, 481 * int phy_port, 482 * int is_port_down) 483 * @param unit Chip unit number. 484 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 485 * struct variable. 486 * @param pipe pipe number. 487 * @param phy_port phy_port to configure. 488 * @param phy_port is_port_down. boolean to indicate if port goes down 489 * @brief API to initialize/clear per port EGR_MMU_CELL_CREDIT 490 * Description: 491 * API to initialize/clear per port EGR_MMU_CELL_CREDIT 492 * Regs/Mems configured: EDB 493 * Parameters: 494 * unit - Device number 495 * *port_schedule_state_t - Agreed structure between SDK and DV 496 * Return Value: 497 * SOC_E_* 498 */ 499 int soc_tomahawk3_ep_set_ct_class( 500 int unit, 501 soc_port_schedule_state_t *port_schedule_state, 502 int pipe_num, 503 int phy_port, 504 int is_port_down) 505 { 506 soc_mem_t mem; 507 uint32 memfld; 508 uint32 entry[SOC_MAX_MEM_WORDS]; 509 int logical_port, speed; 510 511 /* Only Front Panel ports have CT configured */ 512 if (!_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) { return SOC_E_NONE; } 513 514 mem = EDB_IP_CUT_THRU_CLASSm; 515 logical_port = 516 port_schedule_state->out_port_map.port_p2l_mapping[phy_port]; 517 if (0 == is_port_down) { 518 speed = port_schedule_state->out_port_map.log_port_speed[logical_port]; 519 memfld = soc_tomahawk3_get_ct_class(speed); 520 } else { 521 /* FlexPort doesn't need to reset the entry when port goes down; 522 * needs to be touched when port goes up */ 523 memfld = 0; 524 } 525 sal_memset(entry, 0, sizeof(uint32) * 526 soc_mem_entry_words(unit, EDB_IP_CUT_THRU_CLASSm)); 527 soc_mem_field_set(unit, mem, entry, CUT_THRU_CLASSf, &memfld); 528 529 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, logical_port, 530 entry)); 531 return SOC_E_NONE; 532 } 533 534 535 /*! @fn int soc_tomahawk3_ep_set_xmit_start_cnt( 536 * int unit, 537 * soc_port_schedule_state_t *port_schedule_state, 538 * int pipe, 539 * int phy_port, 540 * int is_port_down) 541 * @param unit Chip unit number. 542 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 543 * struct variable. 544 * @param pipe pipe number. 545 * @param phy_port phy_port to configure. 546 * @param phy_port is_port_down. boolean to indicate if port goes down 547 * @brief API to initialize/clear per port EDB_XMIT_START_COUNT 548 * Description: 549 * API to initialize/clear per port EDB_XMIT_START_COUNT 550 * Regs/Mems configured: EDB 551 * Parameters: 552 * unit - Device number 553 * *port_schedule_state_t - Agreed structure between SDK and DV 554 * Return Value: 555 * SOC_E_* 556 */ 557 int soc_tomahawk3_ep_set_xmit_start_cnt( 558 int unit, 559 soc_port_schedule_state_t *port_schedule_state, 560 int pipe_num, 561 int phy_port, 562 int is_port_down) 563 { 564 soc_mem_t mem; 565 int pipe, class, mem_index; 566 uint32 memfld; 567 uint32 entry[SOC_MAX_MEM_WORDS]; 568 int xmit_start_cnt[TH3_EP_MAX_CT_CLASSES]; 569 soc_port_map_type_t *port_map; 570 int logical_port; 571 static const soc_mem_t ep_xmit_cnt_mems[_TH3_PIPES_PER_DEV] = { 572 EDB_XMIT_START_COUNT_PIPE0m, EDB_XMIT_START_COUNT_PIPE1m, 573 EDB_XMIT_START_COUNT_PIPE2m, EDB_XMIT_START_COUNT_PIPE3m, 574 EDB_XMIT_START_COUNT_PIPE4m, EDB_XMIT_START_COUNT_PIPE5m, 575 EDB_XMIT_START_COUNT_PIPE6m, EDB_XMIT_START_COUNT_PIPE7m 576 }; 577 578 /* Set reg's variables */ 579 if (1 == is_port_down) { /* in_port_map used at port down */ 580 port_map = &port_schedule_state->in_port_map; 581 } else { /* out_port_map used at port up */ 582 port_map = &port_schedule_state->out_port_map; 583 } 584 585 logical_port = port_map->port_p2l_mapping[phy_port]; 586 pipe = logical_port / _TH3_DEV_PORTS_PER_PIPE; 587 588 /* Set all XMIT START CNT values for a port; 0-SAF; 1-12 CT classes; 589 * 13-15 reserved 590 */ 591 mem = ep_xmit_cnt_mems[pipe]; 592 593 if (1 == is_port_down) { 594 for (class = 0; class < TH3_EP_MAX_CT_CLASSES; class++) { 595 xmit_start_cnt[class] = 0; 596 } 597 } else { 598 soc_tomahawk3_ep_get_xmit_start_count(unit, port_schedule_state, 599 logical_port, 600 xmit_start_cnt); 601 } 602 603 for (class = 0; class < TH3_EP_NUM_CT_CLASSES; class++) { 604 sal_memset(entry, 0, sizeof(uint32) * 605 soc_mem_entry_words(unit, EDB_XMIT_START_COUNT_PIPE0m)); 606 mem_index = (logical_port % _TH3_DEV_PORTS_PER_PIPE) * TH3_EP_MAX_CT_CLASSES + class; 607 memfld = xmit_start_cnt[class]; 608 soc_mem_field_set(unit, mem, entry, THRESHOLDf, &memfld); 609 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_index, 610 entry)); 611 } 612 613 return SOC_E_NONE; 614 } 615 616 617 /*! @fn int soc_tomahawk3_ep_get_xmit_start_count(int unit, 618 * soc_port_schedule_state_t *port_schedule_state, 619 * int logical_port, int *xmit_start_cnt) 620 * @param unit Chip unit number. 621 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 622 * variable 623 * @param logical_port Dev port num 624 * @param xmit_start_cnt array of 16 entries 0-SAF; 1-12 CT; 13-15 Unused 625 * @brief Helper function to get XMIT_START_CNT array for a port; 626 * This API assumes that credits were retrieved for active ports after FlexPort 627 */ 628 int 629 soc_tomahawk3_ep_get_xmit_start_count( 630 int unit, soc_port_schedule_state_t *port_schedule_state, 631 int logical_port, int *xmit_start_cnt) 632 { 633 int dst_ct_class, src_ct_class; 634 int speed, speed_encoding, freq_encoding; 635 int saf_xmit_start_cnt, dst_ct_xmit_start_cnt; 636 int phy_port; 637 638 phy_port = port_schedule_state->out_port_map.port_l2p_mapping[logical_port]; 639 640 for (src_ct_class=0; src_ct_class < TH3_EP_MAX_CT_CLASSES; src_ct_class++) { 641 xmit_start_cnt[src_ct_class] = 0; 642 } 643 644 SOC_IF_ERROR_RETURN( 645 soc_tomahawk3_get_freq_encoding(unit, port_schedule_state, &freq_encoding)); 646 647 /* Front Panel ports have SAF & CT settings */ 648 if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) { 649 speed = port_schedule_state->out_port_map.log_port_speed[logical_port]; 650 dst_ct_class = soc_tomahawk3_get_ct_class(speed); 651 652 SOC_IF_ERROR_RETURN( 653 soc_tomahawk3_get_speed_encoding(speed, &speed_encoding)); 654 655 saf_xmit_start_cnt = 656 soc_th3_ep_core_cfg_tbl[speed_encoding].xmit_cnt_per_freq[freq_encoding].saf; 657 dst_ct_xmit_start_cnt = 658 soc_th3_ep_core_cfg_tbl[speed_encoding].xmit_cnt_per_freq[freq_encoding].ct; 659 660 /* Populate xmit_start_cnt array */ 661 for (src_ct_class = 0; src_ct_class < TH3_EP_NUM_CT_CLASSES; src_ct_class++) { 662 if (src_ct_class < dst_ct_class) { 663 xmit_start_cnt[src_ct_class] = saf_xmit_start_cnt; 664 } else { 665 xmit_start_cnt[src_ct_class] = dst_ct_xmit_start_cnt; 666 } 667 } 668 } else if ((phy_port == _TH3_PHY_PORT_MNG0) || 669 (phy_port == _TH3_PHY_PORT_MNG1) ) { /* 10G SAF */ 670 xmit_start_cnt[0] = 671 TH3_EP_XMIT_START_CNT_MGM; 672 } else { /* CMIC & LOOPBACK */ 673 xmit_start_cnt[0] = 1; /* Low threshold */ 674 } 675 676 return SOC_E_NONE; 677 } 678 679 680 /*! @fn int soc_tomahawk3_ep_set_egr_enable( 681 * int unit, 682 * soc_port_schedule_state_t *port_schedule_state, 683 * int pipe, 684 * int phy_port, 685 * int is_port_down) 686 * @param unit Chip unit number. 687 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 688 * struct variable. 689 * @param pipe pipe number. 690 * @param phy_port phy_port to configure. 691 * @param phy_port is_port_down. boolean to indicate if port goes down 692 * @brief API to initialize/clear per port EGR_ENABLE 693 * Description: 694 * API to initialize/clear per port EGR_ENABLE 695 * Regs/Mems configured: EDB 696 * Parameters: 697 * unit - Device number 698 * *port_schedule_state_t - Agreed structure between SDK and DV 699 * Return Value: 700 * SOC_E_* 701 */ 702 int soc_tomahawk3_ep_set_egr_enable( 703 int unit, 704 soc_port_schedule_state_t *port_schedule_state, 705 int pipe_num, 706 int phy_port, 707 int is_port_down) 708 { 709 uint32 entry[SOC_MAX_MEM_WORDS]; 710 uint32 memfld; 711 soc_mem_t mem; 712 713 if (0 == is_port_down ) { 714 memfld = 1; 715 } else { 716 memfld = 0; 717 } 718 mem = EGR_ENABLEm; 719 sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit, EGR_ENABLEm)); 720 soc_mem_field_set(unit, mem, entry, PRT_ENABLEf, &memfld); 721 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port, 722 entry)); 723 return SOC_E_NONE; 724 } 725 726 727 728 /*! @fn int soc_tomahawk3_ep_init_egr_enable( 729 * int unit, 730 * soc_port_schedule_state_t *port_schedule_state) 731 * @param unit Chip unit number. 732 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 733 * struct variable. 734 * @param pipe pipe number. 735 * @param phy_port phy_port to configure. 736 * @param phy_port is_port_down. boolean to indicate if port goes down 737 * @brief API to initialize per CHIP EGR_ENABLE 738 * Description: 739 * API to initialize per CHIP EGR_ENABLE 740 * Regs/Mems configured: EDB 741 * Parameters: 742 * unit - Device number 743 * *port_schedule_state_t - Agreed structure between SDK and DV 744 * Return Value: 745 * SOC_E_* 746 */ 747 int soc_tomahawk3_ep_init_egr_enable( 748 int unit, 749 soc_port_schedule_state_t *port_schedule_state) 750 { 751 uint32 port, pipe; 752 int phy_port; 753 int is_port_down; 754 755 is_port_down = 0; 756 757 /* Configure per port registers: Front Panel ports; CPU; Loopback*/ 758 for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) { 759 if (port_schedule_state->out_port_map.log_port_speed[port] > 0 ) { 760 pipe = port / _TH3_DEV_PORTS_PER_PIPE; 761 phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port]; 762 soc_tomahawk3_ep_set_egr_enable(unit, port_schedule_state, 763 pipe, phy_port, is_port_down); 764 } 765 } 766 767 return SOC_E_NONE; 768 } 769 770 771 772 /*! @fn int soc_tomahawk3_ep_edb_init( 773 * int unit, 774 * soc_port_schedule_state_t *port_schedule_state) 775 * @param unit Chip unit number. 776 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 777 * struct variable. 778 * @param pipe pipe number. 779 * @param phy_port phy_port to configure. 780 * @param phy_port is_port_down. boolean to indicate if port goes down 781 * @brief API to initialize/clear per port EGR_ENABLE 782 * Description: 783 * API to initialize/clear per port EGR_ENABLE 784 * Regs/Mems configured: EDB 785 * Parameters: 786 * unit - Device number 787 * *port_schedule_state_t - Agreed structure between SDK and DV 788 * Return Value: 789 * SOC_E_* 790 */ 791 int soc_tomahawk3_ep_edb_init( 792 int unit, 793 soc_port_schedule_state_t *port_schedule_state) 794 { 795 uint32 port, pipe; 796 int phy_port; 797 int is_port_down; 798 int rst_on; 799 800 /* Toggle per port sft reset first on FP ports that are enabled */ 801 rst_on = 1; /* assert reset */ 802 for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) { 803 if (port_schedule_state->out_port_map.log_port_speed[port] > 0) { 804 pipe = port / _TH3_DEV_PORTS_PER_PIPE; 805 phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port]; 806 if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) { 807 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, 808 port_schedule_state, pipe, 809 phy_port, rst_on)); 810 } 811 } 812 } 813 814 rst_on = 0; /* de-assert reset */ 815 for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) { 816 if (port_schedule_state->out_port_map.log_port_speed[port] > 0) { 817 pipe = port / _TH3_DEV_PORTS_PER_PIPE; 818 phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port]; 819 if (_TH3_PHY_IS_FRONT_PANEL_PORT(phy_port)) { 820 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, 821 port_schedule_state, pipe, 822 phy_port, rst_on)); 823 } 824 } 825 } 826 827 is_port_down = 0; 828 /* Configure per port registers: Front Panel ports; CPU; Loopback*/ 829 for (port = 0; port < _TH3_DEV_PORTS_PER_DEV; port++) { 830 if (port_schedule_state->out_port_map.log_port_speed[port] > 0 ) { 831 pipe = port / _TH3_DEV_PORTS_PER_PIPE; 832 phy_port = port_schedule_state->out_port_map.port_l2p_mapping[port]; 833 soc_tomahawk3_ep_set_dev_to_phy(unit, port_schedule_state, 834 pipe, phy_port, is_port_down); 835 soc_tomahawk3_ep_set_mmu_cell_credit(unit, port_schedule_state, 836 pipe, phy_port, is_port_down); 837 soc_tomahawk3_ep_set_ct_class(unit, port_schedule_state, 838 pipe, phy_port, is_port_down); 839 soc_tomahawk3_ep_set_xmit_start_cnt(unit, port_schedule_state, 840 pipe, phy_port, is_port_down); 841 } 842 } 843 844 return SOC_E_NONE; 845 } 846 847 848 849 /*! @fn int soc_tomahawk3_ep_init( 850 * int unit, 851 * soc_port_schedule_state_t *port_schedule_state) 852 * @param unit Chip unit number. 853 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 854 * struct variable. 855 * @brief API to initialize EPIPE 856 * Description: 857 * API to initialize EPIPE 858 * Regs/Mems configured: EDB 859 * Parameters: 860 * unit - Device number 861 * *port_schedule_state_t - Agreed structure between SDK and DV 862 * Return Value: 863 * SOC_E_* 864 */ 865 int soc_tomahawk3_ep_init( 866 int unit, 867 soc_port_schedule_state_t *port_schedule_state) 868 { 869 /* Init EDB; per port config */ 870 soc_tomahawk3_ep_edb_init(unit, port_schedule_state); 871 872 /* Enable EGR ports */ 873 soc_tomahawk3_ep_init_egr_enable(unit, port_schedule_state); 874 875 return SOC_E_NONE; 876 } 877 878 879 /*! @fn int soc_tomahawk3_ep_drain_port( 880 * int unit, 881 * soc_port_schedule_state_t *port_schedule_state) 882 * @param unit Chip unit number. 883 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 884 * struct variable. 885 * @param pipe_num pipe number. 886 * @param phy_port phy_port to configure. 887 * @brief API to drain phy_port 888 * Description: 889 * API to drain phy_port 890 * Regs/Mems configured: EDB 891 * Parameters: 892 * unit - Device number 893 * *port_schedule_state_t - Agreed structure between SDK and DV 894 * Return Value: 895 * SOC_E_* 896 */ 897 int soc_tomahawk3_ep_drain_port( 898 int unit, 899 soc_port_schedule_state_t *port_schedule_state, 900 int pipe_num, 901 int phy_port) 902 { 903 uint32 rval_save, rval; 904 soc_reg_t reg; 905 uint32 entry[SOC_MAX_MEM_WORDS]; 906 uint32 util; 907 soc_mem_t mem; 908 int timeout_in_us, iter_in_us; 909 910 static const soc_reg_t misc_ctrl_regs[_TH3_PIPES_PER_DEV] = { 911 EDB_MISC_CTRL_PIPE0r, EDB_MISC_CTRL_PIPE1r, 912 EDB_MISC_CTRL_PIPE2r, EDB_MISC_CTRL_PIPE3r, 913 EDB_MISC_CTRL_PIPE4r, EDB_MISC_CTRL_PIPE5r, 914 EDB_MISC_CTRL_PIPE6r, EDB_MISC_CTRL_PIPE7r 915 }; 916 917 /* Configure EGR_EDB_MISC_CTRL such that EGR_MAX_USED_ENTRIES returns 918 * current buffer utilization 919 */ 920 reg = misc_ctrl_regs[pipe_num]; 921 rval_save = 0; 922 rval = 0; 923 SOC_IF_ERROR_RETURN(soc_reg32_rawport_get(unit, reg, REG_PORT_ANY, 0, 924 &rval_save)); 925 rval = rval_save; 926 soc_reg_field_set(unit, reg, &rval, SELECT_CURRENT_USED_ENTRIESf, 1); 927 SOC_IF_ERROR_RETURN(soc_reg32_rawport_set(unit, reg, REG_PORT_ANY, 0, rval)); 928 929 /* polling port's buffer utilization until is 0 */ 930 timeout_in_us = 70; /* account for IDB, MMU, EDB draining */ 931 iter_in_us = 0; 932 sal_memset(entry, 0, sizeof(entry)); 933 mem = EGR_MAX_USED_ENTRIESm; 934 do { 935 SOC_IF_ERROR_RETURN 936 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, 937 phy_port, entry)); 938 /* coverity[callee_ptr_arith : FALSE] */ 939 soc_mem_field_get(unit, mem, entry, LEVELf, &util); 940 if (0 == util) { break; } 941 942 sal_usleep(1 + (SAL_BOOT_QUICKTURN ? 1 : 0) * EMULATION_FACTOR); 943 iter_in_us++; 944 if (iter_in_us >= timeout_in_us) { 945 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, 946 "soc_tomahawk3_ep_drain_port()" 947 "TIMEOUT of %0d us reached when draining phy_port=%0d\n"), 948 timeout_in_us, phy_port)); 949 return SOC_E_FAIL; 950 } 951 } while (0 != util); 952 953 /* Configure EDB_MISC_CTRL back to previous value */ 954 SOC_IF_ERROR_RETURN(soc_reg32_rawport_set(unit, reg, REG_PORT_ANY, 0, 955 rval_save)); 956 957 return SOC_E_NONE; 958 } 959 960 /*! @fn int soc_tomahawk3_ep_credit_rst_port( 961 * int unit, 962 * soc_port_schedule_state_t *port_schedule_state) 963 * @param unit Chip unit number. 964 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 965 * struct variable. 966 * @param pipe_num pipe number. 967 * @param phy_port phy_port to configure. 968 * @brief API to sft_rst the phy_port 969 * Description: 970 * API to reset EDB credit the phy_port 971 * Regs/Mems configured: EDB 972 * Parameters: 973 * unit - Device number 974 * *port_schedule_state_t - Agreed structure between SDK and DV 975 * Return Value: 976 * SOC_E_* 977 */ 978 int soc_tomahawk3_ep_credit_rst_port( 979 int unit, 980 int phy_port) 981 { 982 uint32 entry[SOC_MAX_MEM_WORDS]; 983 uint32 memfld; 984 soc_mem_t mem; 985 986 mem = EGR_PORT_CREDIT_RESETm; 987 988 sal_memset(entry, 0, sizeof(entry)); 989 memfld = 1; 990 soc_mem_field_set(unit, mem, entry, VALUEf, &memfld); 991 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 992 phy_port, entry)); 993 994 memfld = 0; 995 soc_mem_field_set(unit, mem, entry, VALUEf, &memfld); 996 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 997 phy_port, entry)); 998 999 return SOC_E_NONE; 1000 } 1001 1002 1003 1004 /*! @fn int soc_tomahawk3_ep_sft_rst_port( 1005 * int unit, 1006 * soc_port_schedule_state_t *port_schedule_state) 1007 * @param unit Chip unit number. 1008 * @param port_schedule_state Pointer to a soc_port_schedule_state_t 1009 * struct variable. 1010 * @param pipe_num pipe number. 1011 * @param phy_port phy_port to configure. 1012 * @param rst_on if (rst_on==1) then sft rst the port 1013 * @brief API to sft_rst the phy_port 1014 * Description: 1015 * API to sft_rst the phy_port 1016 * Regs/Mems configured: EDB 1017 * Parameters: 1018 * unit - Device number 1019 * *port_schedule_state_t - Agreed structure between SDK and DV 1020 * Return Value: 1021 * SOC_E_* 1022 */ 1023 int soc_tomahawk3_ep_sft_rst_port( 1024 int unit, 1025 soc_port_schedule_state_t *port_schedule_state, 1026 int pipe_num, 1027 int phy_port, 1028 int rst_on) 1029 { 1030 uint32 entry[SOC_MAX_MEM_WORDS]; 1031 uint32 memfld; 1032 soc_mem_t mem; 1033 1034 mem = EGR_PER_PORT_BUFFER_SFT_RESETm; 1035 1036 if (rst_on == 1) { 1037 memfld = 1; 1038 } else { 1039 memfld = 0; 1040 } 1041 1042 sal_memset(entry, 0, sizeof(entry)); 1043 soc_mem_field_set(unit, mem, entry, ENABLEf, &memfld); 1044 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 1045 phy_port, entry)); 1046 1047 return SOC_E_NONE; 1048 } 1049 1050 /*! @fn int soc_tomahawk3_ep_port_down(int unit, 1051 * soc_port_schedule_state_t *port_schedule_state) 1052 * @param unit Chip unit number. 1053 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 1054 * variable 1055 * @brief Helper function to follow EDB port down sequence for flexport operation. 1056 * Does: 1057 * (1) Poll until EDB buffer is empty for ports going down 1058 * (2) Disables EDB for ports going down 1059 * (3) Asserts sft_rst EDB for ports going down 1060 * 1061 * @returns SOC_E_NONE 1062 */ 1063 int 1064 soc_tomahawk3_ep_port_down(int unit, 1065 soc_port_schedule_state_t *port_schedule_state) 1066 { 1067 int i, rst_on, is_port_down; 1068 int logical_port, physical_port; 1069 int pipe_num; 1070 1071 /* 1072 * Poll until EDB buffer is empty: 1073 * Set EGR_EDB_MISC_CTRL.SELECT_CURRENT_USED_ENTRIES to 1. 1074 * Poll until EGR_MAX_USED_ENTRIES[physical_port] is equal to 0. 1075 */ 1076 for (i = 0; i < port_schedule_state->nport; i++) { 1077 if (port_schedule_state->resource[i].physical_port == -1) { 1078 logical_port = port_schedule_state->resource[i].logical_port; 1079 pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE; 1080 /* assumes drain is done before FlexPort */ 1081 physical_port = 1082 port_schedule_state->in_port_map.port_l2p_mapping[logical_port]; 1083 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_drain_port(unit, 1084 port_schedule_state, pipe_num, physical_port)); 1085 } 1086 } 1087 1088 /* 1089 * Disables EDB to MMU cell request generation 1090 * Set EGR_ENABLE[device_port].PRT_ENABLE to 0. 1091 * Set EGR_PER_PORT_BUFFER_SFT_RESET[device_port] to 1. 1092 */ 1093 1094 is_port_down = 1; /* that is, disable port */ 1095 rst_on = 1; /* that is, assert sft_rst */ 1096 for (i = 0; i < port_schedule_state->nport; i++) { 1097 if (port_schedule_state->resource[i].physical_port == -1) { /* port DOWN */ 1098 logical_port = port_schedule_state->resource[i].logical_port; 1099 pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE; 1100 /* assumes drain is done before FlexPort */ 1101 physical_port = 1102 port_schedule_state->in_port_map.port_l2p_mapping[logical_port]; 1103 1104 /* Disable port : write EGR_ENABLEm */ 1105 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_set_egr_enable(unit, port_schedule_state, 1106 pipe_num, physical_port, is_port_down)); 1107 /* Assert sft_rst per port */ 1108 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, port_schedule_state, 1109 pipe_num, physical_port, rst_on)); 1110 } 1111 } 1112 1113 return SOC_E_NONE; 1114 } 1115 1116 1117 /*! @fn int soc_tomahawk3_ep_port_up(int unit, 1118 * soc_port_schedule_state_t *port_schedule_state) 1119 * @param unit Chip unit number. 1120 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 1121 * variable 1122 * @brief Main API that brings up all added ports in EGR pipe 1123 * Return Value: 1124 * SOC_E_* 1125 */ 1126 int 1127 soc_tomahawk3_ep_port_up(int unit, 1128 soc_port_schedule_state_t *port_schedule_state) 1129 { 1130 int i, rst_on, is_port_down; 1131 int logical_port, physical_port; 1132 int pipe_num; 1133 1134 /* 1135 * Toggle port rst: Set EGR_PER_PORT_BUFFER_SFT_RESET[device_port] to 1 1136 * Set EGR_PER_PORT_BUFFER_SFT_RESET[device_port] to 0 1137 * Set EGR_ENABLE[device_port].PRT_ENABLE to 1 1138 */ 1139 1140 rst_on = 1; /* assert reset */ 1141 for (i = 0; i < port_schedule_state->nport; i++) { 1142 physical_port = port_schedule_state->resource[i].physical_port; 1143 if (-1 != physical_port) { /* that is, port UP */ 1144 logical_port = port_schedule_state->resource[i].logical_port; 1145 pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE; 1146 /* De-assert sft_rst*/ 1147 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, port_schedule_state, 1148 pipe_num, physical_port, rst_on)); 1149 } 1150 } 1151 1152 rst_on = 0; /* de-assert reset */ 1153 for (i = 0; i < port_schedule_state->nport; i++) { 1154 physical_port = port_schedule_state->resource[i].physical_port; 1155 if (-1 != physical_port) { /* that is, port UP */ 1156 logical_port = port_schedule_state->resource[i].logical_port; 1157 pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE; 1158 /* De-assert sft_rst*/ 1159 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_sft_rst_port(unit, port_schedule_state, 1160 pipe_num, physical_port, rst_on)); 1161 } 1162 } 1163 1164 /* Enable Ports going up after PM sft_rst is de-asserted */ 1165 /* For ports going UP do: 1166 * 1. Enable port; write EGR_ENABLEm 1167 */ 1168 is_port_down = 0; /* that is, port UP */ 1169 for (i = 0; i < port_schedule_state->nport; i++) { 1170 physical_port = port_schedule_state->resource[i].physical_port; 1171 if (-1 != physical_port) { /* that is, port UP */ 1172 logical_port = port_schedule_state->resource[i].logical_port; 1173 pipe_num = logical_port / _TH3_DEV_PORTS_PER_PIPE; 1174 /* Enable port; write EGR_ENABLEm */ 1175 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_set_egr_enable(unit, port_schedule_state, 1176 pipe_num, physical_port, is_port_down)); 1177 } 1178 } 1179 1180 return SOC_E_NONE; 1181 } 1182 1183 /*! @fn int soc_tomahawk3_flex_ep_reconfigure_remove(int unit, 1184 * soc_port_schedule_state_t *port_schedule_state) 1185 * @param unit Chip unit number. 1186 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 1187 * variable 1188 * @brief Main API that reconfigures all ports from EGR pipe - remove ports 1189 * Return Value: 1190 * SOC_E_* 1191 */ 1192 int 1193 soc_tomahawk3_flex_ep_reconfigure_remove(int unit, 1194 soc_port_schedule_state_t *port_schedule_state) 1195 { 1196 int i, is_port_down; 1197 int log_port, phy_port, pipe; 1198 1199 /* For ports going DOWN do: 1200 * 1. Delete Dev 2 Phy mapping. 1201 * 2. Reset max Ep2MMU credits to 0. 1202 */ 1203 is_port_down = 1; /* that is, port DOWN */ 1204 for (i = 0; i < port_schedule_state->nport; i++) { 1205 phy_port = port_schedule_state->resource[i].physical_port; 1206 if (phy_port == -1) { /* that is, port DOWN */ 1207 log_port = port_schedule_state->resource[i].logical_port; 1208 phy_port = port_schedule_state->in_port_map.port_l2p_mapping[log_port]; 1209 pipe = log_port / _TH3_DEV_PORTS_PER_PIPE; 1210 soc_tomahawk3_ep_set_dev_to_phy(unit, port_schedule_state, 1211 pipe, phy_port, is_port_down); 1212 soc_tomahawk3_ep_set_mmu_cell_credit(unit, port_schedule_state, 1213 pipe, phy_port, is_port_down); 1214 } 1215 } 1216 1217 return SOC_E_NONE; 1218 } 1219 1220 1221 /*! @fn int soc_tomahawk3_flex_ep_reconfigure_add(int unit, 1222 * soc_port_schedule_state_t *port_schedule_state) 1223 * @param unit Chip unit number. 1224 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 1225 * variable 1226 * @brief Main API that reconfigures all ports from EGR pipe - add ports 1227 * Return Value: 1228 * SOC_E_* 1229 */ 1230 int 1231 soc_tomahawk3_flex_ep_reconfigure_add(int unit, 1232 soc_port_schedule_state_t *port_schedule_state) 1233 { 1234 int i, is_port_down; 1235 int log_port, phy_port, pipe; 1236 1237 1238 /* For ports going UP do: 1239 * 1. Map Dev 2 Phy for added port. 1240 * 2. Configure max Ep2MMU credits to proper value. 1241 * 3. Configure CT_class for added port. 1242 * 4. Configure XMIT_START_CNT entries for added port. 1243 */ 1244 is_port_down = 0; /* that is, port UP */ 1245 for (i = 0; i < port_schedule_state->nport; i++) { 1246 phy_port = port_schedule_state->resource[i].physical_port; 1247 if (phy_port != -1) { /* that is, port UP */ 1248 log_port = port_schedule_state->resource[i].logical_port; 1249 pipe = log_port / _TH3_DEV_PORTS_PER_PIPE; 1250 soc_tomahawk3_ep_set_dev_to_phy(unit, port_schedule_state, 1251 pipe, phy_port, is_port_down); 1252 soc_tomahawk3_ep_set_mmu_cell_credit(unit, port_schedule_state, 1253 pipe, phy_port, is_port_down); 1254 soc_tomahawk3_ep_set_ct_class(unit, port_schedule_state, 1255 pipe, phy_port, is_port_down); 1256 soc_tomahawk3_ep_set_xmit_start_cnt(unit, port_schedule_state, 1257 pipe, phy_port, is_port_down); 1258 } 1259 } 1260 1261 return SOC_E_NONE; 1262 } 1263 1264 /*** END SDK API COMMON CODE ***/ 1265 1266 #endif /* BCM_TOMAHAWK3_SUPPORT */ 1267