helix5_tdm.c (93671B)
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: helix5_tdm.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_HELIX5_SUPPORT) 20 #include <soc/helix5.h> 21 #include <soc/helix5_tdm.h> 22 #include <soc/tdm/helix5/tdm_hx5_defines.h> 23 24 25 /*** START SDK API COMMON CODE ***/ 26 27 /*! @fn void _soc_hx5_tdm_print_port_map( 28 int unit, 29 soc_port_map_type_t *port_map) 30 @param unit Chip unit number. 31 @param port_map Pointer to a soc_port_map_type_t struct variable. 32 @brief Debug API to print soc_port_map_type_t 33 */ 34 void 35 _soc_hx5_tdm_print_port_map(int unit, soc_port_map_type_t *port_map) 36 { 37 int port; 38 int is_hg2, is_ovs, is_mgm; 39 int speed, phy_port, idb_port, mmu_port, num_lanes, pblk; 40 int phy_bmap, p2l_map, m2p_map; 41 42 for (port = 0; port < HX5_NUM_EXT_PORTS; port++) { 43 is_mgm = SOC_PBMP_MEMBER(port_map->management_pbm, port) ? 1 : 0; 44 if ((is_mgm == 1) || (port_map->log_port_speed[port] > 0)) { 45 speed = is_mgm ? 10 : port_map->log_port_speed[port]/1000; 46 phy_port = port_map->port_l2p_mapping[port]; 47 idb_port = port_map->port_l2i_mapping[port]; 48 mmu_port = port_map->port_p2m_mapping[phy_port]; 49 num_lanes = port_map->port_num_lanes[port]; 50 pblk = port_map->port_p2PBLK_inst_mapping[phy_port]; 51 phy_bmap = SOC_PBMP_MEMBER(port_map->physical_pbm, 52 phy_port) ? 1 : 0; 53 is_hg2 = SOC_PBMP_MEMBER(port_map->hg2_pbm, 54 port) ? 1 : 0; 55 is_ovs = SOC_PBMP_MEMBER(port_map->oversub_pbm, port) ? 1 : 0; 56 p2l_map = port_map->port_p2l_mapping[phy_port]; 57 m2p_map = port_map->port_m2p_mapping[mmu_port]; 58 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 59 "log_port=%3d phy_port=%3d speed=%3dG " 60 "%s %s idb_port=%3d mmu_port=%3d " 61 "num_lanes=%1d pblk=%3d phy_bmap=%1d " 62 "p2l_map=%3d "), 63 port, phy_port, speed, 64 (is_hg2==1) ? "HG2" : "ETH", 65 (is_ovs==1) ? "OVS" : " LR", 66 idb_port, mmu_port, num_lanes, pblk, 67 phy_bmap, p2l_map)); 68 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "m2p_map=%3d %s\n"), 69 m2p_map, (is_mgm==1) ? "MGM" : "" )); 70 } 71 } 72 73 } 74 75 76 /*! @fn void _soc_hx5_tdm_print_tdm_info( 77 int unit, 78 soc_tdm_schedule_t *tdm_info, 79 int hpipe, 80 int is_ing) 81 @param unit Chip unit number. 82 @param tdm_info Pointer to a soc_tdm_schedule_t struct variable. 83 @param hpipe Half Pipe. 84 @param is_ing distinguishes between IP and EP schedulers 85 @brief Debug API to print soc_tdm_schedule_t 86 */ 87 void 88 _soc_hx5_tdm_print_tdm_info(int unit, soc_tdm_schedule_t *tdm_info, 89 int hpipe, int is_ing) 90 { 91 int cal_len, j, m; 92 93 if (hpipe == 0) { 94 for (cal_len = tdm_info->cal_len; cal_len > 0; cal_len--) { 95 if (tdm_info->linerate_schedule[cal_len - 1] != HX5_NUM_EXT_PORTS) { 96 break; 97 } 98 } 99 100 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 101 "\tMAIN CALENDAR: cal_len=%3d \n"), 102 cal_len )); 103 for (j=0; j < cal_len; j++) { 104 if (j%16==0) { 105 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 106 "\n %3d : %3d\t"), 107 j, j+15)); 108 } 109 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "%5d"), 110 tdm_info->linerate_schedule[j])); 111 } 112 } 113 114 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 115 "\n\n\tOVS TABLES: HPIPE= %3d \n"), 116 hpipe )); 117 for (j=0; j< tdm_info->num_ovs_groups; j++) { 118 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\nOVS_CAL[%d]:\t"), 119 j )); 120 for (m=0; m< tdm_info->ovs_group_len; m++) { 121 if (tdm_info->oversub_schedule[j][m] != HX5_NUM_EXT_PORTS) { 122 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "%d\t"), 123 tdm_info->oversub_schedule[j][m] )); 124 } else { 125 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "---\t"))); 126 } 127 } 128 } 129 130 if (is_ing == 1) { 131 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 132 "\n\n\tPKT_SCHEDULER: HPIPE= %3d \n"), 133 hpipe )); 134 for (j=0; j<tdm_info->pkt_sch_or_ovs_space_len; j++) { 135 if (j%16==0) { 136 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 137 "\n %3d : %3d\t"), 138 j, j+15 )); 139 } 140 if (tdm_info->pkt_sch_or_ovs_space[0][j] != HX5_NUM_EXT_PORTS) { 141 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\t%d"), 142 tdm_info->pkt_sch_or_ovs_space[0][j] )); 143 } else { 144 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\t---"))); 145 } 146 } 147 } 148 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit,"\n"))); 149 } 150 151 152 /*! @fn void _soc_hx5_tdm_print_port_resource( 153 int unit, 154 soc_port_resource_t *port_info, 155 int entry_num) 156 @param unit Chip unit number. 157 @param port_info Pointer to a soc_port_resource_t struct variable. 158 @param entry_num entry number. 159 @brief Debug API to print soc_port_resource_t 160 */ 161 void 162 _soc_hx5_tdm_print_port_resource(int unit, 163 soc_port_resource_t *port_info, 164 int entry_num) 165 { 166 int is_hg2, lane; 167 168 is_hg2 = 0; 169 if (port_info->encap == _SHR_PORT_ENCAP_HIGIG2) { 170 is_hg2=1; 171 } 172 173 if (port_info->physical_port == -1) { 174 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 175 "nport=%3d DOWN: " 176 "logical_port=%3d physical_port=%3d\n"), 177 entry_num, port_info->logical_port, 178 port_info->physical_port)); 179 } else { 180 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 181 "nport=%3d UP : " 182 "logical_port=%3d physical_port=%3d mmu_port=%3d "), 183 entry_num, port_info->logical_port, 184 port_info->physical_port, 185 port_info->mmu_port )); 186 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 187 "idb_port=%3d pipe=%3d speed=%3d num_lanes=%1d " 188 "%s %s\n"), 189 port_info->idb_port, 190 port_info->pipe, port_info->speed/1000, 191 port_info->num_lanes, 192 (is_hg2==1) ? "HG2": "ETH", 193 (port_info->oversub==1) ? "OVS": " LR" )); 194 for (lane = 0; lane < SOC_PORT_RESOURCE_LANES_MAX; lane++) { 195 if (port_info->lane_info[lane] != NULL) { 196 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 197 "nport=%3d lane_info[%d]: pgw=%3d" 198 "xlp=%3d port_index=%3d\n"), 199 entry_num, lane, 200 port_info->lane_info[lane]->pgw, 201 port_info->lane_info[lane]->xlp, 202 port_info->lane_info[lane]->port_index)); 203 } 204 } 205 } 206 } 207 208 209 /*! @fn void _soc_hx5_tdm_print_schedule_state( 210 int unit, 211 soc_port_schedule_state_t *sch_info) 212 @param unit Chip unit number. 213 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 214 @brief Debug API to print sch_info 215 */ 216 void 217 _soc_hx5_tdm_print_schedule_state(int unit, 218 soc_port_schedule_state_t *sch_info) 219 { 220 int i, pipe, hpipe, print_tdm; 221 soc_tdm_schedule_t *tdm_schedule; 222 223 print_tdm = 1; 224 225 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 226 "\n\nPRINTING soc_port_schedule_state_t \n"))); 227 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 228 "nport= %3d\n"), 229 sch_info->nport)); 230 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 231 "frequency= %4dMHz\n"), 232 sch_info->frequency)); 233 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 234 "bandwidth= %4d\n"), 235 sch_info->bandwidth)); 236 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 237 "io_bandwidth= %4d\n"), 238 sch_info->io_bandwidth)); 239 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 240 "lossless= %1d\n"), 241 sch_info->lossless)); 242 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 243 "is_flexport= %1d\n"), 244 sch_info->is_flexport)); 245 246 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 247 "\nPRINTING soc_port_schedule_state_t" 248 "::[in_port_map]\n"))); 249 _soc_hx5_tdm_print_port_map(unit, &sch_info->in_port_map); 250 251 if (sch_info->is_flexport == 1) { 252 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 253 "\nPRINTING soc_port_schedule_state_t" 254 "::[out_port_map]\n"))); 255 _soc_hx5_tdm_print_port_map(unit, &sch_info->out_port_map); 256 } 257 258 if (print_tdm == 1) { 259 for (pipe = 0; pipe< NUM_PIPE(unit); pipe++) { 260 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 261 "\n====== TDM Tables PIPE=%1d INGRESS\n"), 262 pipe)); 263 for (hpipe = 0; hpipe< MAX_SCH_SLICES; hpipe++) { 264 tdm_schedule = &(sch_info->tdm_ingress_schedule_pipe[ 265 pipe].tdm_schedule_slice[hpipe]); 266 _soc_hx5_tdm_print_tdm_info(unit, tdm_schedule, hpipe, 1); 267 } 268 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 269 "\n====== TDM Tables PIPE=%1d EGRESS\n"), 270 pipe)); 271 for (hpipe = 0; hpipe< MAX_SCH_SLICES; hpipe++) { 272 tdm_schedule = &(sch_info->tdm_egress_schedule_pipe[ 273 pipe].tdm_schedule_slice[hpipe]); 274 _soc_hx5_tdm_print_tdm_info(unit, tdm_schedule, hpipe, 0); 275 } 276 } 277 } 278 279 if ((sch_info->is_flexport == 1) && (sch_info->nport > 0)) { 280 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 281 "\n====== FLEXPORT RESOURCES ===== " 282 "num entries= %d = \n"), 283 sch_info->nport)); 284 for (i = 0; i < sch_info->nport; i++) { 285 _soc_hx5_tdm_print_port_resource(unit, &sch_info->resource[i], i); 286 } 287 } 288 } 289 290 291 /*! @fn void soc_hx5_tdm_get_port_ratio( 292 int unit, 293 soc_port_schedule_state_t *sch_info, 294 int pm_num, 295 int *pm_mode, 296 int prev_or_new) 297 @param unit Chip unit number. 298 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 299 @param pm_num PM block_id (0 to 31) 300 @param *pm_mode mode to be returned. 301 @param prev_or_new function looks in in_port_map or out_port_map. 302 @brief Help function to get port ratio. 303 */ 304 305 /* 306 * #1 single: 100 - x - x - x SOC_HX5_PORT_RATIO_SINGLE 307 * #2 single: 40 - x - x - x SOC_HX5_PORT_RATIO_TRI_023_2_1_1 308 * #3 dual: 50 - x - 50 - x SOC_HX5_PORT_RATIO_DUAL_1_1 309 * #4 dual: 40 - x - 40 - x SOC_HX5_PORT_RATIO_DUAL_1_1 310 * #5 dual: 20 - x - 20 - x SOC_HX5_PORT_RATIO_DUAL_1_1 311 * #6 dual: 40 - x - 20 - x SOC_HX5_PORT_RATIO_DUAL_2_1 312 * #7 dual: 20 - x - 40 - x SOC_HX5_PORT_RATIO_DUAL_1_2 313 * #8 tri: 50 - x - 25/x - 25/x SOC_HX5_PORT_RATIO_TRI_023_2_1_1 314 * #9 tri: 20 - x - 10/x - 10/x SOC_HX5_PORT_RATIO_TRI_023_2_1_1 315 * #10 tri: 40 - x - 10/x - 10/x SOC_HX5_PORT_RATIO_TRI_023_4_1_1 316 * #11 tri: 25/x - 25/x - 50 - x SOC_HX5_PORT_RATIO_TRI_012_1_1_2 317 * #12 tri: 10/x - 10/x - 20 - x SOC_HX5_PORT_RATIO_TRI_012_1_1_2 318 * #13 tri: 10/x - 10/x - 40 - x SOC_HX5_PORT_RATIO_TRI_012_1_1_4 319 * #14 quad: 25/x - 25/x - 25/x - 25/x SOC_HX5_PORT_RATIO_QUAD 320 * #15 quad: 10/x - 10/x - 10/x - 10/x SOC_HX5_PORT_RATIO_QUAD 321 */ 322 void 323 soc_hx5_tdm_get_port_ratio(int unit, 324 soc_port_schedule_state_t *sch_info, 325 int pm_num, int *pm_mode, int prev_or_new) 326 { 327 int port, phy_port_base, lane, mode = 0; 328 int num_lanes[HELIX5_TDM_PORTS_PER_PBLK]; 329 int speed_max[HELIX5_TDM_PORTS_PER_PBLK]; 330 soc_port_map_type_t *port_map; 331 332 sal_memset(num_lanes, 0, HELIX5_TDM_PORTS_PER_PBLK*sizeof(int)); 333 sal_memset(speed_max, 0, HELIX5_TDM_PORTS_PER_PBLK*sizeof(int)); 334 335 if (prev_or_new == 1) { 336 port_map = &(sch_info->in_port_map); 337 } else { 338 port_map = &(sch_info->out_port_map); 339 } 340 341 /* phy_port_base = 1 + (pm_num * HELIX5_TDM_PORTS_PER_PBLK); */ 342 phy_port_base = _soc_hx5_tdm_get_phy_port_base(pm_num); 343 for (lane = 0; lane < HELIX5_TDM_PORTS_PER_PBLK; lane += 2) { 344 port = port_map->port_p2l_mapping[phy_port_base + lane]; 345 if ( (port == -1) || (port_map->log_port_speed[port]==0) ) { 346 num_lanes[lane] = -1; 347 speed_max[lane] = -1; 348 } else { 349 num_lanes[lane] = port_map->port_num_lanes[port]; 350 speed_max[lane] = port_map->log_port_speed[port]; 351 } 352 } 353 354 if (num_lanes[0] == 4) { 355 mode = SOC_HX5_PORT_RATIO_SINGLE; 356 } else if (num_lanes[0] == 2 && num_lanes[2] == 2) { 357 if (speed_max[0] == speed_max[2]) { 358 mode = SOC_HX5_PORT_RATIO_DUAL_1_1; 359 } else if (speed_max[0] > speed_max[2]) { 360 mode = SOC_HX5_PORT_RATIO_DUAL_2_1; 361 } else { 362 mode = SOC_HX5_PORT_RATIO_DUAL_1_2; 363 } 364 } else if (num_lanes[0] == 2) { 365 if (num_lanes[2] == -1) { 366 mode = SOC_HX5_PORT_RATIO_DUAL_1_1; 367 } else { 368 mode = (speed_max[0] == 20000 || speed_max[0] == 21000 || 369 speed_max[0] == 50000 || speed_max[0] == 53000) ? 370 SOC_HX5_PORT_RATIO_TRI_023_2_1_1 : 371 SOC_HX5_PORT_RATIO_TRI_023_4_1_1; 372 } 373 } else if (num_lanes[2] == 2) { 374 if (num_lanes[0] == -1) { 375 mode = SOC_HX5_PORT_RATIO_DUAL_1_1; 376 } else { 377 mode = (speed_max[2] == 20000 || speed_max[2] == 21000 || 378 speed_max[2] == 50000 || speed_max[2] == 53000) ? 379 SOC_HX5_PORT_RATIO_TRI_012_1_1_2 : 380 SOC_HX5_PORT_RATIO_TRI_012_1_1_4; 381 } 382 } else { 383 mode = SOC_HX5_PORT_RATIO_QUAD; 384 } 385 386 *pm_mode = mode; 387 } 388 389 390 /*! @fn void _soc_hx5_tdm_get_pipe_map( 391 int unit, 392 soc_port_schedule_state_t *sch_info, 393 uint32 *pipe_map) 394 @param unit Chip unit number. 395 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 396 @param pipe_map Returned pipe map. 397 @brief Returns pipe bitmap. 398 * Description: 399 For init, a pipe gets 1 if exists active port within that pipe. 400 For flexport, a pipe gets 1 if exists flexed port within that pipe. 401 */ 402 void 403 _soc_hx5_tdm_get_pipe_map(int unit, 404 soc_port_schedule_state_t *sch_info, 405 uint32 *pipe_map) 406 { 407 uint32 port, pipe, i, pipe_bmap = 0; 408 409 if (sch_info->is_flexport == 0) { /* Init */ 410 for (port = 0; port < HELIX5_TDM_PHY_PORTS_PER_DEV; port++) { 411 if (sch_info->out_port_map.log_port_speed[port] > 0 ) { 412 pipe = port / HELIX5_TDM_PHY_PORTS_PER_PIPE; 413 pipe_bmap |= 1 << pipe; 414 } 415 } 416 } else { /* FlexPort */ 417 for (i = 0; i < sch_info->nport; i++) { 418 port = sch_info->resource[i].logical_port; 419 pipe = port / HELIX5_TDM_PHY_PORTS_PER_PIPE; 420 pipe_bmap |= 1 << pipe; 421 } 422 } 423 *pipe_map = pipe_bmap; 424 } 425 426 /*! @fn int _soc_hx5_tdm_get_mport_2_hp_num( 427 uint32 phy_num 428 ) 429 @param phy_num 430 @brief Returns PM ID.Needed correction as 76/4 results 19 pm instead 10 431 * Description: 432 Returns PM ID 433 */ 434 int 435 _soc_hx5_tdm_get_mport_2_hp_num(uint32 mmu_port_num 436 ) 437 { 438 if (mmu_port_num<= 7) 439 return((mmu_port_num)); 440 else if (mmu_port_num >= 8 && mmu_port_num<= 15) 441 return((mmu_port_num-8)); 442 else if (mmu_port_num >= 16 && mmu_port_num<= 39) 443 return((mmu_port_num-8)); 444 else if (mmu_port_num >= 40 && mmu_port_num<= 63) 445 return((mmu_port_num-32)); 446 else 447 return(62); 448 } 449 450 451 452 453 /*! @fn int _soc_hx5_tdm_get_cal_id( 454 uint32 phy_num 455 ) 456 @param phy_num 457 @brief Returns PM ID.Needed correction as 76/4 results 19 pm instead 10 458 * Description: 459 Returns PM ID 460 */ 461 int 462 _soc_hx5_tdm_get_cal_id(uint32 phy_num 463 ) 464 { 465 466 if (phy_num <= 48) 467 return((phy_num/16)); 468 else if(phy_num <= HELIX5_TDM_PHY_PORTS_PER_PIPE) { 469 return((phy_num/4)-9); 470 } 471 else 472 return(HX5_NUM_EXT_PORTS); 473 } 474 475 /*! @fn int _soc_hx5_tdm_get_phy_port_base ( 476 uint32 pm_num 477 ) 478 @param phy_num 479 @brief Returns PM ID.Needed correction as 76/4 results 19 pm instead 10 480 * Description: 481 Returns PM ID 482 */ 483 int 484 _soc_hx5_tdm_get_phy_port_base (uint32 pm_num) 485 { 486 if (pm_num < 3) 487 return((pm_num*16)+1); 488 else if(pm_num > 2 && pm_num <= 10) { 489 return((pm_num*4)+37); 490 } 491 else 492 return(HX5_NUM_EXT_PORTS); 493 } 494 495 496 497 /*! @fn void _soc_hx5_tdm_get_ovs_pipe_map( 498 int unit, 499 soc_port_schedule_state_t *sch_info, 500 uint32 *ovs_pipe_map) 501 @param unit Chip unit number. 502 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 503 @param ovs_pipe_map Returned pipe map. 504 @brief Returns OVS pipe bitmap. 505 * Description: 506 For init, a pipe gets 1 if exists oversub port within that pipe. 507 */ 508 void 509 _soc_hx5_tdm_get_ovs_pipe_map(int unit, 510 soc_port_schedule_state_t *sch_info, 511 uint32 *ovs_pipe_map) 512 { 513 uint32 port, pipe, pipe_bmap = 0; 514 int is_ovs_map; 515 516 if (sch_info->is_flexport == 0) { /* Init */ 517 for (port = 0; port < HELIX5_TDM_PHY_PORTS_PER_DEV; port++) { 518 is_ovs_map = SOC_PBMP_MEMBER(sch_info->out_port_map.oversub_pbm, 519 port) ? 1 : 0; 520 if ((sch_info->out_port_map.log_port_speed[port] > 0) && 521 (1 == is_ovs_map) ) { 522 pipe = port / HELIX5_TDM_PHY_PORTS_PER_PIPE; 523 pipe_bmap |= 1 << pipe; 524 } 525 } 526 } 527 *ovs_pipe_map = pipe_bmap; 528 } 529 530 531 /*! @fn int _soc_hx5_tdm_get_speed_ovs_class( 532 int unit, 533 int speed) 534 @param unit Chip unit number. 535 @param speed Speed 536 @return port_speed_class to be returned 537 @brief Help function to determine ovs class 538 * Description: 539 Oversubscription speed group class encoding 540 0 - 0 541 1 - 2 (10G) 542 2 - 4 (20G) 543 3 - 5 (25G) 544 4 - 8 (40G) 545 5 - 10 (50G) 546 6 - 20 (100G) 547 */ 548 int 549 _soc_hx5_tdm_get_speed_ovs_class(int unit, int speed) 550 { 551 int speed_class = 0; 552 /*uint16 dev_id = 0;*/ 553 /*uint8 rev_id = 0;*/ 554 555 if (speed >= 40000) { 556 if (speed >= 100000) { 557 speed_class = 6; 558 } else if (speed >= 50000) { 559 speed_class = 5; 560 } else { 561 speed_class = 4; 562 } 563 } else { 564 if (speed >= 25000) { 565 speed_class = 3; 566 } else if (speed >= 20000) { 567 speed_class = 2; 568 } else if (speed >= 10000) { 569 speed_class = 1; 570 } else if (speed >= 1000) { 571 /* take 1G speed as 10G in HX5 for ovsb port */ 572 speed_class = 1; 573 } 574 } 575 576 return (speed_class); 577 } 578 579 580 /*! @fn int _soc_hx5_tdm_check_is_hsp_port_e( 581 int unit, 582 int speed) 583 @param unit Chip unit number. 584 @param speed Speed 585 @return 1->high speed port; 0->not high speed port; 586 @brief To determine the same port spacing for egress pipe 587 * Description: 588 Oversubscription speed group class encoding 589 0 - 0 590 1 - 2 (10G) 591 2 - 4 (20G) 592 3 - 5 (25G) 593 4 - 8 (40G) 594 5 - 10 (50G) 595 6 - 20 (100G) 596 */ 597 STATIC int 598 _soc_hx5_tdm_check_is_hsp_port_e(int unit, int speed) 599 { 600 int speed_class, port_is_hsp = 0; 601 602 speed_class = _soc_hx5_tdm_get_speed_ovs_class(unit, speed); 603 switch (speed_class) { 604 case 4: /* 40G */ 605 case 5: /* 50G */ 606 case 6: /* 100G */ 607 port_is_hsp = 1; 608 break; 609 default: 610 port_is_hsp = 0; 611 break; 612 } 613 614 return (port_is_hsp); 615 } 616 617 /*! @fn int _soc_hx5_tdm_check_mgmt_enable( 618 int unit, 619 soc_port_schedule_state_t *sch_info) 620 @param unit Chip unit number. 621 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 622 @return 1-> management port enabled; 0 -> otherwise 623 @brief Help function to determine if management port is enabled. 624 */ 625 STATIC int 626 _soc_hx5_tdm_check_mgmt_enable(int unit, 627 soc_port_schedule_state_t *sch_info) 628 { 629 int port; 630 int mgmt_port_cnt = 0; 631 int mgmt_port_en = 0; 632 633 SOC_PBMP_ITER(sch_info->in_port_map.management_pbm, port) { 634 mgmt_port_cnt++; 635 } 636 if (mgmt_port_cnt>0) { 637 mgmt_port_en = 1; 638 } 639 640 return (mgmt_port_en); 641 } 642 643 #if 0 644 /*! @fn int _soc_hx5_tdm_check_2nd_mgmt_enable( 645 int unit, 646 soc_port_schedule_state_t *sch_info) 647 @param unit Chip unit number. 648 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 649 @return 1-> 2nd management port enabled; 0 -> otherwise 650 @brief Help function to determine if 2nd management port is enabled. 651 */ 652 STATIC int 653 _soc_hx5_tdm_check_2nd_mgmt_enable(int unit, 654 soc_port_schedule_state_t *sch_info) 655 { 656 int port; 657 int mgmt_port_cnt = 0; 658 int mgmt_2nd_port_en = 0; 659 660 SOC_PBMP_ITER(sch_info->in_port_map.management_pbm, port) { 661 mgmt_port_cnt++; 662 } 663 if (mgmt_port_cnt>1) { 664 mgmt_2nd_port_en = 1; 665 } 666 667 return (mgmt_2nd_port_en); 668 } 669 #endif 670 671 /*! @fn int _soc_hx5_tdm_get_same_port_spacing_e( 672 int unit, 673 int speed) 674 @param unit Chip unit number. 675 @param speed Speed 676 @return same port spacing of the given speed port 677 @brief To determine the same port spacing for egress pipe 678 - 8 for high speed port 679 - 14 for not high speed port 680 */ 681 int 682 _soc_hx5_tdm_get_same_port_spacing_e(int unit, int speed) 683 { 684 int port_same_spacing = 0; 685 686 if (_soc_hx5_tdm_check_is_hsp_port_e(unit, speed) == 1) { 687 port_same_spacing = 6; 688 } else { 689 port_same_spacing = 12; 690 } 691 692 return (port_same_spacing); 693 } 694 695 696 /*! @fn int _soc_hx5_tdm_get_sis_port_spacing_e( 697 int unit, 698 int speed) 699 @param unit Chip unit number. 700 @param speed Speed 701 @return same port spacing of the given speed port 702 @brief To determine the same port spacing for egress pipe 703 - 8 for high speed port 704 - 14 for not high speed port 705 */ 706 int 707 _soc_hx5_tdm_get_sis_port_spacing_e(int unit, int phy_port){ 708 int port_sis_spacing = 0; 709 710 if (phy_port >64) 711 { 712 port_sis_spacing = 2; 713 } else { 714 port_sis_spacing = 4; 715 } 716 717 return (port_sis_spacing); 718 } 719 720 721 722 /*! @fn int _soc_hx5_tdm_calculation( 723 int unit, 724 soc_port_schedule_state_t *sch_info) 725 @param unit Chip unit number. 726 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 727 @brief API to calculate TDM tables. 728 */ 729 int 730 _soc_hx5_tdm_calculation(int unit, soc_port_schedule_state_t *sch_info) 731 { 732 int i, j, pm_num, phy_port, lgc_port, port_lanes, phy_port_tmp; 733 int pipe, hpipe; 734 int lane, group, index; 735 int mgmt_pm_hg = 0, mgmt_mode = 0; 736 int tdm_idb_cal_len, tdm_mmu_cal_len, tdm_pipe_grp_num, tdm_pipe_grp_len; 737 int *tdm_idb_pipe_main, *tdm_mmu_pipe_main; 738 int **tdm_pipe_ovs_group; 739 tdm_soc_t _chip_pkg; 740 tdm_mod_t *_tdm_pkg; 741 uint32 port_speeds[HELIX5_TDM_PHY_PORTS_PER_DEV]; 742 uint32 port_states[HELIX5_TDM_PHY_PORTS_PER_DEV]; 743 744 745 /* soc_cm_get_id(unit, &dev_id, &rev_id); */ 746 /* LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "hx5_tdm_dev_id %0d\n"), dev_id)); */ 747 748 sal_memset(port_speeds, 0, HELIX5_TDM_PHY_PORTS_PER_DEV*sizeof(uint32)); 749 sal_memset(port_states, 0, HELIX5_TDM_PHY_PORTS_PER_DEV*sizeof(uint32)); 750 751 752 /* Remap input speeds to ETH bitrates */ 753 soc_helix5_port_schedule_speed_remap(unit, sch_info); 754 755 /* Set port states and speeds */ 756 for (lgc_port = 0; lgc_port < HELIX5_TDM_PHY_PORTS_PER_DEV; lgc_port++) { 757 phy_port = sch_info->in_port_map.port_l2p_mapping[lgc_port]; 758 if (phy_port < HELIX5_TDM_PHY_PORTS_PER_DEV) { 759 if (sch_info->in_port_map.log_port_speed[lgc_port] > 0 ) { 760 if (SOC_PBMP_MEMBER(sch_info->in_port_map.hg2_pbm,lgc_port)) { 761 port_states[phy_port] = 762 SOC_PBMP_MEMBER(sch_info->in_port_map.oversub_pbm, 763 lgc_port) ? PORT_STATE__OVERSUB_HG : 764 PORT_STATE__LINERATE_HG; 765 } else { 766 port_states[phy_port] = 767 SOC_PBMP_MEMBER(sch_info->in_port_map.oversub_pbm, 768 lgc_port) ? PORT_STATE__OVERSUB : 769 PORT_STATE__LINERATE; 770 } 771 port_lanes = sch_info->in_port_map.port_num_lanes[lgc_port]; 772 for (lane = 1; lane < port_lanes; lane++) { 773 phy_port_tmp = phy_port + lane; 774 if (phy_port_tmp < HELIX5_TDM_PHY_PORTS_PER_DEV) { 775 port_states[phy_port_tmp] = PORT_STATE__COMBINE; 776 } 777 } 778 port_speeds[phy_port] = 779 sch_info->in_port_map.log_port_speed[lgc_port]; 780 } 781 if (SOC_PBMP_MEMBER(sch_info->in_port_map.management_pbm, lgc_port)) { 782 if (SOC_PBMP_MEMBER(sch_info->in_port_map.hg2_pbm, 783 lgc_port)) { 784 mgmt_pm_hg = 1; /* HIGIG2 : ETHERNET */ 785 } 786 port_speeds[phy_port] = 0; 787 port_states[phy_port] = 0; 788 } 789 } 790 } 791 if (_soc_hx5_tdm_check_mgmt_enable(unit, sch_info) == 1) { 792 mgmt_mode = (mgmt_pm_hg == 1) ? 2 : 0; 793 } else { 794 mgmt_mode = 1; 795 } 796 /* Print input config */ 797 if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) { 798 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 799 "frequency: %dMHz\n"), 800 sch_info->frequency)); 801 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 802 "%8s%8s%8s\n"), 803 "port", "speed", "state")); 804 for (phy_port = 0; phy_port < HELIX5_TDM_PHY_PORTS_PER_DEV; 805 phy_port++) { 806 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 807 "%8d%8d%8d\n"), 808 phy_port, port_speeds[phy_port]/1000, 809 port_states[phy_port])); 810 } 811 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 812 } 813 /* Initialize input variables for SW TDM Generation: 814 -- unit 815 -- dev_id 816 -- num_ext_ports 817 -- state 818 -- speed 819 -- clk_freq 820 -- flex_port_en: 0->init, 1->flex 821 -- mgmt_pm_hg: 0->Ethernet mgmt, 1->HiGig2 mgmt 822 -- mgmt_mode: 823 0 -> Enable Etherner management port (default) 824 1 -> Disable management port 825 2 -> Enable HiGig management port 826 */ 827 sal_memset(&_chip_pkg, 0, sizeof(tdm_soc_t)); 828 _chip_pkg.unit = unit; 829 /* _chip_pkg.dev_id = dev_id; */ 830 _chip_pkg.num_ext_ports = HX5_NUM_EXT_PORTS; 831 _chip_pkg.state = sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int), 832 "port state list"); 833 if (_chip_pkg.state == NULL) { 834 return SOC_E_MEMORY; 835 } 836 _chip_pkg.speed = sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int), 837 "port speed list"); 838 if (_chip_pkg.speed == NULL) { 839 sal_free(_chip_pkg.state); 840 return SOC_E_MEMORY; 841 } 842 for (index = 0; index < _chip_pkg.num_ext_ports; index++) { 843 _chip_pkg.state[index] = 0; 844 _chip_pkg.speed[index] = 0; 845 } 846 for (index = 0; index < _chip_pkg.num_ext_ports && 847 index < HELIX5_TDM_PHY_PORTS_PER_DEV; index++) { 848 _chip_pkg.state[index] = port_states[index]; 849 _chip_pkg.speed[index] = port_speeds[index]; 850 } 851 /* Shift port state to left one position; required by C_TDM */ 852 for (index = 1; index < _chip_pkg.num_ext_ports; index++) { 853 _chip_pkg.state[index - 1] = _chip_pkg.state[index]; 854 } 855 _chip_pkg.clk_freq = sch_info->frequency; 856 _chip_pkg.flex_port_en = sch_info->is_flexport; 857 _chip_pkg.pmap = 0; 858 _chip_pkg.pmap_num_modules = 0; 859 _chip_pkg.pmap_num_lanes = 0; 860 _chip_pkg.pm_num_phy_modules = 0; 861 _chip_pkg.lr_idx_limit = 0; 862 _chip_pkg.tvec_size = 0; 863 _chip_pkg.soc_vars.hx5.mgmt_pm_hg= mgmt_pm_hg; 864 _chip_pkg.soc_vars.hx5.mgmt_mode = mgmt_mode; 865 866 /* Populate TDM tables by invoking SW TDM API */ 867 /* coverity[dont_call : FALSE] */ 868 _tdm_pkg = _soc_set_tdm_tbl(SOC_SEL_TDM(&_chip_pkg)); 869 870 /* Free the memory allocated to port states and speeds */ 871 sal_free(_chip_pkg.state); 872 sal_free(_chip_pkg.speed); 873 874 /* Copy TDM result into output structure */ 875 if (_tdm_pkg == NULL) { 876 LOG_CLI((BSL_META_U(unit, 877 "Unsupported config for TDM calendar generation\n"))); 878 return SOC_E_FAIL; 879 } else { 880 /* IDB calendar (0-3), MMU calendar (4-7) */ 881 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 882 switch (pipe) { 883 /* IDB_PIPE_0, MMU_PIPE_0 */ 884 /* 885 case 0: 886 tdm_pipe_ovs_group = _tdm_pkg->_chip_data.cal_0.cal_grp; 887 tdm_pipe_grp_num = _tdm_pkg->_chip_data.cal_0.grp_num; 888 tdm_pipe_grp_len = _tdm_pkg->_chip_data.cal_0.grp_len; 889 tdm_idb_pipe_main = _tdm_pkg->_chip_data.cal_0.cal_main; 890 tdm_idb_cal_len = _tdm_pkg->_chip_data.cal_0.cal_len; 891 tdm_mmu_pipe_main = _tdm_pkg->_chip_data.cal_4.cal_main; 892 tdm_mmu_cal_len = _tdm_pkg->_chip_data.cal_4.cal_len; 893 break; */ 894 /* IDB_PIPE_1, MMU_PIPE_1 */ 895 default: 896 tdm_pipe_ovs_group = _tdm_pkg->_chip_data.cal_0.cal_grp; 897 tdm_pipe_grp_num = _tdm_pkg->_chip_data.cal_0.grp_num; 898 tdm_pipe_grp_len = _tdm_pkg->_chip_data.cal_0.grp_len; 899 tdm_idb_pipe_main = _tdm_pkg->_chip_data.cal_0.cal_main; 900 tdm_idb_cal_len = _tdm_pkg->_chip_data.cal_0.cal_len; 901 tdm_mmu_pipe_main = _tdm_pkg->_chip_data.cal_4.cal_main; 902 tdm_mmu_cal_len = _tdm_pkg->_chip_data.cal_4.cal_len; 903 break; 904 } 905 if (tdm_pipe_ovs_group == NULL || 906 tdm_idb_pipe_main == NULL || 907 tdm_mmu_pipe_main == NULL) { 908 LOG_CLI((BSL_META_U(unit, 909 "Unsupported config for TDM calendar generation\n"))); 910 tdm_hx5_main_free(_tdm_pkg); 911 sal_free(_tdm_pkg); 912 return SOC_E_FAIL; 913 } else { 914 /* IDB TDM main calendar */ 915 for (index = 0; index < tdm_idb_cal_len; index++) { 916 sch_info->tdm_ingress_schedule_pipe[pipe]. 917 tdm_schedule_slice[0].linerate_schedule[index] = 918 tdm_idb_pipe_main[index]; 919 } 920 /* MMU TDM main calendar */ 921 for (index = 0; index < tdm_mmu_cal_len; index++) { 922 sch_info->tdm_egress_schedule_pipe[pipe]. 923 tdm_schedule_slice[0].linerate_schedule[index] = 924 tdm_mmu_pipe_main[index]; 925 } 926 927 /* IDB and MMU OverSub Groups */ 928 for (i = 0; i < tdm_pipe_grp_num; i++) { 929 /* Group 0:5 -> hpipe 0, Group 6:11 -> hpipe1 */ 930 hpipe = i / HELIX5_TDM_OVS_GROUPS_PER_HPIPE; 931 group = i % HELIX5_TDM_OVS_GROUPS_PER_HPIPE; 932 for (j = 0; j < tdm_pipe_grp_len; j++) { 933 sch_info->tdm_ingress_schedule_pipe[pipe]. 934 tdm_schedule_slice[hpipe].oversub_schedule[group][j] = 935 tdm_pipe_ovs_group[i][j]; 936 sch_info->tdm_egress_schedule_pipe[pipe]. 937 tdm_schedule_slice[hpipe].oversub_schedule[group][j] = 938 tdm_pipe_ovs_group[i][j]; 939 } 940 } 941 942 /* Packet shaper */ 943 for (hpipe = 0; hpipe < 2; hpipe++) { 944 for (j = 0; j < HX5_SHAPING_GRP_LEN; j++) { 945 sch_info->tdm_ingress_schedule_pipe[pipe]. 946 tdm_schedule_slice[hpipe].pkt_sch_or_ovs_space[0][j] = 947 tdm_pipe_ovs_group[hpipe+HX5_SHAPING_GRP_IDX_0][j]; 948 } 949 } 950 } 951 } 952 /* Re-evaluate this at FlexPort; 953 * Before calling FlexPort sch_info->in_port_map.port_p2PBLK_inst_mapping should be copied in pm_num_to_pblk 954 * After FlexPort pm_num_to_pblk should be copied back to sch_info->out_port_map.port_p2PBLK_inst_mapping 955 */ 956 sal_memset(sch_info->out_port_map.port_p2PBLK_inst_mapping, 957 0, sizeof(int) * SOC_MAX_NUM_PORTS); 958 for (pm_num = 0; pm_num < HX5_NUM_PHY_PM; pm_num++) { 959 for (lane = 0; lane < HELIX5_TDM_PORTS_PER_PBLK; lane++) { 960 sch_info->out_port_map.port_p2PBLK_inst_mapping[ 961 (pm_num * HELIX5_TDM_PORTS_PER_PBLK) + 1 + lane] = 962 _tdm_pkg->_chip_data.soc_pkg.soc_vars.hx5.pm_num_to_pblk[pm_num]; 963 } 964 } 965 /* Free the memory allocated in TDM algorithm code */ 966 tdm_hx5_main_free(_tdm_pkg); /* This function frees all pointers allocated during _soc_set_tdm_tbl call */ 967 sal_free(_tdm_pkg); 968 } 969 970 /* Print TDM result */ 971 if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) { 972 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 973 /* IDB TDM main calendar */ 974 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 975 "Pipe %d [IDB TDM main calendar]\n"), 976 pipe)); 977 for (index = 0; index < MAX_CAL_LEN; index++) { 978 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, " %3d"), 979 sch_info->tdm_ingress_schedule_pipe[pipe]. 980 tdm_schedule_slice[0].linerate_schedule[index])); 981 if (index % 16 == 0 && index > 0) { 982 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 983 } 984 } 985 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 986 /* Oversub groups */ 987 for (hpipe = 0; hpipe < HELIX5_TDM_HPIPES_PER_PIPE; hpipe++) { 988 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 989 "Pipe %d Half-Pipe %d [IDB TDM Oversub Groups]\n"), 990 pipe, hpipe)); 991 for (group = 0; group < HELIX5_TDM_OVS_GROUPS_PER_HPIPE; 992 group++) { 993 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 994 "oversub group %d: "), group)); 995 for (index = 0; index < HELIX5_TDM_OVS_GROUP_LENGTH; 996 index++) { 997 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, " %3d"), 998 sch_info->tdm_ingress_schedule_pipe[pipe]. 999 tdm_schedule_slice[hpipe].oversub_schedule[ 1000 group][index])); 1001 } 1002 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 1003 } 1004 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 1005 } 1006 /* Packet scheduler */ 1007 for (hpipe = 0; hpipe < HELIX5_TDM_HPIPES_PER_PIPE; hpipe++) { 1008 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1009 "Pipe %d Half-Pipe %d [IDB TDM PKT SCHEDULER]\n"), 1010 pipe, hpipe)); 1011 for (index = 0; index < HX5_SHAPING_GRP_LEN; index++) { 1012 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, " %3d"), 1013 sch_info->tdm_ingress_schedule_pipe[pipe]. 1014 tdm_schedule_slice[hpipe].pkt_sch_or_ovs_space[0][index])); 1015 if (index % 16 == 0 && index > 0) { 1016 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 1017 } 1018 } 1019 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 1020 } 1021 /* MMU TDM main calendar */ 1022 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 1023 "Pipe %d [MMU TDM main calendar]:\n"), pipe)); 1024 for (index = 0; index < MAX_CAL_LEN; index++) { 1025 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, " %3d"), 1026 sch_info->tdm_egress_schedule_pipe[pipe]. 1027 tdm_schedule_slice[0].linerate_schedule[index])); 1028 if (index % 16 == 0 && index > 0) { 1029 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 1030 } 1031 } 1032 LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META_U(unit, "\n"))); 1033 } 1034 } 1035 1036 /* If init then just copy in_port_map to out_port_map*/ 1037 if (sch_info->is_flexport == 0) { 1038 for (i= 0; i< SOC_MAX_NUM_PORTS;i++) { 1039 sch_info->out_port_map.log_port_speed[i] = 1040 sch_info->in_port_map.log_port_speed[i]; 1041 sch_info->out_port_map.port_p2l_mapping[i] = 1042 sch_info->in_port_map.port_p2l_mapping[i]; 1043 sch_info->out_port_map.port_l2p_mapping[i] = 1044 sch_info->in_port_map.port_l2p_mapping[i]; 1045 sch_info->out_port_map.port_p2m_mapping[i] = 1046 sch_info->in_port_map.port_p2m_mapping[i]; 1047 sch_info->out_port_map.port_num_lanes[i] = 1048 sch_info->in_port_map.port_num_lanes[i]; 1049 sch_info->out_port_map.port_l2i_mapping[i] = 1050 sch_info->in_port_map.port_l2i_mapping[i]; 1051 } 1052 for (i = 0; i < SOC_MAX_NUM_MMU_PORTS; i++) { 1053 sch_info->out_port_map.port_m2p_mapping[i] = 1054 sch_info->in_port_map.port_m2p_mapping[i]; 1055 } 1056 for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) { 1057 sch_info->out_port_map.physical_pbm.pbits[i] = 1058 sch_info->in_port_map.physical_pbm.pbits[i]; 1059 sch_info->out_port_map.hg2_pbm.pbits[i] = 1060 sch_info->in_port_map.hg2_pbm.pbits[i]; 1061 sch_info->out_port_map.management_pbm.pbits[i] = 1062 sch_info->in_port_map.management_pbm.pbits[i]; 1063 sch_info->out_port_map.oversub_pbm.pbits[i] = 1064 sch_info->in_port_map.oversub_pbm.pbits[i]; 1065 } 1066 } 1067 /* 1068 * else { 1069 * HERE future handling of FlexPort between in_port_map to out_port_map 1070 * } 1071 */ 1072 1073 _soc_hx5_tdm_print_schedule_state(unit, sch_info); 1074 return SOC_E_NONE; 1075 } 1076 1077 1078 /*! @fn int _soc_hx5_tdm_set_idb_calendar( 1079 int unit, 1080 soc_port_schedule_state_t *sch_info) 1081 @param unit Chip unit number. 1082 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1083 @brief API to initialize the HX5 IDB main calendar. 1084 */ 1085 int 1086 _soc_hx5_tdm_set_idb_calendar(int unit, soc_port_schedule_state_t *sch_info) 1087 { 1088 uint32 pipe_map; 1089 uint32 cal_len; 1090 soc_mem_t mem; 1091 soc_reg_t reg; 1092 soc_field_t cal_end_field; 1093 int pipe, slot, id, length, calendar_id; 1094 int phy_port, idb_port; 1095 int port; 1096 uint32 rval = 0; 1097 uint32 memfld; 1098 uint32 entry[SOC_MAX_MEM_WORDS]; 1099 uint32 mem_indx; 1100 static const soc_mem_t idb_tdm_cal_mem[HELIX5_TDM_PIPES_PER_DEV][2] = { 1101 {IS_TDM_CALENDAR0_PIPE0m, IS_TDM_CALENDAR1_PIPE0m}/* , 1102 {IS_TDM_CALENDAR0_PIPE1m, IS_TDM_CALENDAR1_PIPE1m} */ 1103 }; 1104 static const soc_reg_t idb_tdm_cfg_reg[HELIX5_TDM_PIPES_PER_DEV] = { 1105 IS_TDM_CONFIG_PIPE0r/* , IS_TDM_CONFIG_PIPE1r */ 1106 }; 1107 static const soc_field_t calendar_end_fields[] = { 1108 CAL0_ENDf, CAL1_ENDf 1109 }; 1110 1111 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1112 sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit, 1113 IS_TDM_CALENDAR0_PIPE0m)); 1114 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1115 /* coverity[overrun-local : FALSE] */ 1116 reg = idb_tdm_cfg_reg[pipe]; 1117 /* Pipe is empty */ 1118 if ((pipe_map & (1 << pipe)) == 0) { 1119 /* At init, even if the pipe doesn't have active ports, 1120 * enable scheduler for sbus accesses to PP IPIPE 1121 */ 1122 if (sch_info->is_flexport == 0) { 1123 rval = 0; 1124 soc_reg_field_set(unit, reg, &rval, ENABLEf, 1); 1125 SOC_IF_ERROR_RETURN( 1126 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1127 } 1128 continue; 1129 } 1130 /* Determine calendar_id : 0 or 1 */ 1131 if (sch_info->is_flexport == 1) { /* choose "the other calendar" */ 1132 SOC_IF_ERROR_RETURN( 1133 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1134 calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1; 1135 } else { 1136 /* At init use calendar_id=0 */ 1137 calendar_id = 0; 1138 /* Also, before writing the TDM calendar entries, make sure 1139 * calendar is disabled again; 1140 * IDB scheduler may be already enabled at this point to allow 1141 * sbus access to IPIPE for reset purpose (Sec. 3.1.2 SW_init doc) 1142 */ 1143 rval = 0; 1144 soc_reg_field_set(unit, reg, &rval, ENABLEf, 0); 1145 SOC_IF_ERROR_RETURN( 1146 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1147 } 1148 /* coverity[overrun-local : FALSE] */ 1149 mem = idb_tdm_cal_mem[pipe][calendar_id]; 1150 cal_end_field = calendar_end_fields[calendar_id]; 1151 1152 /* TDM Calendar is always taken from slice 0 */ 1153 cal_len = sch_info->tdm_ingress_schedule_pipe[pipe]. 1154 tdm_schedule_slice[0].cal_len; 1155 for (length = cal_len; length > 0; length--) { 1156 if (sch_info->tdm_ingress_schedule_pipe[pipe]. 1157 tdm_schedule_slice[0].linerate_schedule[length - 1] 1158 != HX5_NUM_EXT_PORTS) { 1159 break; 1160 } 1161 } 1162 for (slot = 0; slot < length; slot += 2) { 1163 /* EVEN */ 1164 phy_port = sch_info->tdm_ingress_schedule_pipe[pipe]. 1165 tdm_schedule_slice[0].linerate_schedule[slot]; 1166 if (phy_port == HX5_OVSB_TOKEN) { 1167 idb_port = HELIX5_TDM_IDB_OVSB_TOKEN; 1168 } else if (phy_port == HX5_IDL1_TOKEN) { 1169 idb_port = HELIX5_TDM_IDB_SBUS_TOKEN; 1170 } else if (phy_port == HX5_IDL2_TOKEN) { 1171 idb_port = HELIX5_TDM_IDB_OPT2_TOKEN; 1172 } else if (phy_port == HX5_NULL_TOKEN) { 1173 idb_port = HELIX5_TDM_IDB_NULL_TOKEN; 1174 } else if (phy_port == HX5_FAE_TOKEN) { 1175 idb_port = HELIX5_TDM_IDB_FAE_TOKEN; 1176 } else if (phy_port >= HX5_NUM_EXT_PORTS) { 1177 idb_port = HELIX5_TDM_IDB_UNUSED_TOKEN; 1178 } /* else if (phy_port == HX5_MGM1_TOKEN) { */ 1179 /* TDM code always allocates slots for management port. 1180 * If mgmt ports are omitted from config, this mapping 1181 * is not set up. 1182 */ 1183 /* idb_port = HELIX5_TDM_IDB_MGMT1_TOKEN; }*/ 1184 else { 1185 port = sch_info->out_port_map.port_p2l_mapping[phy_port]; 1186 idb_port = sch_info->out_port_map.port_l2i_mapping[port] & 0x7f; 1187 } 1188 if (idb_port > 68) { /* Not a general front panel port */ 1189 id = 0xf; 1190 } else { 1191 /* id = (phy_port - 1) / HELIX5_TDM_PORTS_PER_PBLK; */ 1192 id = _soc_hx5_tdm_get_cal_id((phy_port-1)); 1193 } 1194 memfld = idb_port & 0x7f; /* [0,69] && 127 */ 1195 soc_mem_field_set(unit, mem, entry, PORT_NUM_EVENf, &memfld); 1196 memfld = id & 0xf; 1197 soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_EVENf, &memfld); 1198 /* ODD */ 1199 phy_port = sch_info->tdm_ingress_schedule_pipe[pipe].tdm_schedule_slice[0].linerate_schedule[slot + 1]; 1200 if (phy_port == HX5_OVSB_TOKEN) { 1201 idb_port = HELIX5_TDM_IDB_OVSB_TOKEN; 1202 } else if (phy_port == HX5_IDL1_TOKEN) { 1203 idb_port = HELIX5_TDM_IDB_SBUS_TOKEN; 1204 } else if (phy_port == HX5_IDL2_TOKEN) { 1205 idb_port = HELIX5_TDM_IDB_OPT2_TOKEN; 1206 } else if (phy_port == HX5_NULL_TOKEN) { 1207 idb_port = HELIX5_TDM_IDB_NULL_TOKEN; 1208 } else if (phy_port == HX5_FAE_TOKEN) { 1209 idb_port = HELIX5_TDM_IDB_FAE_TOKEN; 1210 } else if (phy_port >= HX5_NUM_EXT_PORTS) { 1211 idb_port = HELIX5_TDM_IDB_UNUSED_TOKEN; 1212 } /* else if (phy_port == HX5_MGM1_TOKEN) { */ 1213 /* TDM code always allocates slots for management port. 1214 * If mgmt ports are omitted from config, this mapping 1215 * is not set up. 1216 */ 1217 /* idb_port = HELIX5_TDM_IDB_MGMT1_TOKEN; }*/ 1218 else { 1219 port = sch_info->out_port_map.port_p2l_mapping[phy_port]; 1220 idb_port = sch_info->out_port_map.port_l2i_mapping[port] & 0x7f; 1221 } 1222 if (idb_port > 68) { /* Not a general front panel port */ 1223 id = 0xf; 1224 } else { 1225 /* id = (phy_port - 1) / HELIX5_TDM_PORTS_PER_PBLK; */ 1226 id = _soc_hx5_tdm_get_cal_id((phy_port-1)); 1227 } 1228 memfld = idb_port & 0x7f; /* [0,69] && 127 */ 1229 soc_mem_field_set(unit, mem, entry, PORT_NUM_ODDf, &memfld); 1230 memfld = id & 0xf; 1231 soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_ODDf, &memfld); 1232 /* Memory entry */ 1233 mem_indx = slot / 2; 1234 SOC_IF_ERROR_RETURN 1235 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_indx, entry)); 1236 } 1237 1238 /* set for 2nd management port 1239 * if (_soc_hx5_tdm_check_2nd_mgmt_enable(unit, sch_info) == 1 && 1240 * pipe == (HELIX5_TDM_PIPES_PER_DEV - 1)) { 1241 * soc_reg_field_set(unit, reg, &rval, MGMT_2ND_PORT_ENABLEf, 1); 1242 * } 1243 */ 1244 soc_reg_field_set(unit, reg, &rval, cal_end_field, length-1); 1245 soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id); 1246 soc_reg_field_set(unit, reg, &rval, ENABLEf, 1); 1247 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1248 } 1249 1250 return SOC_E_NONE; 1251 } 1252 1253 1254 /*! @fn int _soc_hx5_tdm_set_idb_hsp( 1255 int unit, 1256 soc_port_schedule_state_t *sch_info) 1257 @param unit Chip unit number. 1258 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1259 @brief API to initialize the HX5 IDB HSP. 1260 */ 1261 int 1262 _soc_hx5_tdm_set_idb_hsp(int unit, soc_port_schedule_state_t *sch_info) 1263 { 1264 soc_reg_t reg; 1265 uint32 pipe_map; 1266 int port, mmu_port, phy_port; 1267 int port_speed; 1268 uint32 port_map[3]; 1269 uint32 rval = 0; 1270 1271 1272 /* IDB always configures PORT_BMPf field for idb_tdm_hsp regs 1273 * to 0xFFFF_FFFF_FFFF_FFFF, independent of the port's speed. 1274 */ 1275 1276 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1277 port_map[0] = 0; 1278 port_map[1] = 0; 1279 port_map[2] = 0; 1280 1281 for (port=0; port< 70 ; port++) { /* mmu logical ports */ 1282 port_speed = sch_info->out_port_map.log_port_speed[port]; 1283 if (port_speed > 0) { 1284 if (_soc_hx5_tdm_check_is_hsp_port_e(unit, port_speed) == 1) { 1285 phy_port = sch_info->out_port_map.port_l2p_mapping[port]; 1286 if ((phy_port >= 1) && 1287 (phy_port <= HELIX5_TDM_GPORTS_PER_DEV)) { 1288 mmu_port = sch_info->out_port_map.port_p2m_mapping[phy_port] & 0x7f; 1289 if (mmu_port < 32) { 1290 port_map[0] |= 1 << mmu_port; 1291 } 1292 else if (mmu_port < 64) { 1293 port_map[1] |= 1 << (mmu_port - 32); 1294 } 1295 else if (mmu_port > 63) { 1296 port_map[2] |= 1 << (mmu_port - 64); 1297 } 1298 } 1299 } 1300 } 1301 } 1302 1303 reg = IS_TDM_HSP_0_PIPE0r; 1304 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[0]); 1305 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1306 reg = IS_TDM_HSP_1_PIPE0r; 1307 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[1]); 1308 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1309 reg = IS_TDM_HSP_2_PIPE0r; 1310 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[2]); 1311 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, 0, 0, rval)); 1312 1313 return SOC_E_NONE; 1314 } 1315 1316 1317 /*! @fn int _soc_hx5_tdm_set_idb_ppe_credit( 1318 int unit, 1319 soc_port_schedule_state_t 1320 *sch_info, 1321 int full_credit_threshold_0, 1322 int opp_credit_threshold_0, 1323 int full_credit_threshold_1, 1324 int opp_credit_threshold_1 ) 1325 @param unit Chip unit number. 1326 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1327 @param full_credit_threshold_0 1328 @param opp_credit_threshold_0 1329 @param full_credit_threshold_1 1330 @param opp_credit_threshold_1 1331 @brief API to initialize the HX5 IDB PPE Credit Config register. 1332 Regs/Mems configured:PPE_CREDIT_CONFIG_PIPE<pipe> 1333 */ 1334 int 1335 _soc_hx5_tdm_set_idb_ppe_credit(int unit, 1336 soc_port_schedule_state_t *sch_info, 1337 int full_credit_threshold_0, 1338 int opp_credit_threshold_0, 1339 int full_credit_threshold_1, 1340 int opp_credit_threshold_1 ) 1341 { 1342 soc_reg_t reg; 1343 uint32 pipe_map; 1344 int pipe; 1345 uint32 rval = 0; 1346 static const soc_reg_t idb_ppe_credit[HELIX5_TDM_PIPES_PER_DEV] = { 1347 PPE_CREDIT_CONFIG_PIPE0r/* , PPE_CREDIT_CONFIG_PIPE1r */ 1348 }; 1349 1350 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1351 1352 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1353 if (!(pipe_map & (1 << pipe))) { 1354 continue; 1355 } 1356 reg = idb_ppe_credit[pipe]; 1357 rval = 0; 1358 /*SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));*/ 1359 soc_reg_field_set(unit, reg, &rval, FULL_CREDIT_THRESHOLD_0f, 1360 full_credit_threshold_0); 1361 soc_reg_field_set(unit, reg, &rval, OPP_CREDIT_THRESHOLD_0f, 1362 opp_credit_threshold_0); 1363 soc_reg_field_set(unit, reg, &rval, FULL_CREDIT_THRESHOLD_1f, 1364 full_credit_threshold_1); 1365 soc_reg_field_set(unit, reg, &rval, OPP_CREDIT_THRESHOLD_1f, 1366 opp_credit_threshold_1); 1367 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1368 } 1369 1370 return SOC_E_NONE; 1371 } 1372 1373 1374 /*! @fn int _soc_hx5_tdm_set_idb_opportunistic( 1375 int unit, 1376 soc_port_schedule_state_t *sch_info, 1377 int cpu_op_en, 1378 int lb_opp_en, 1379 int opp1_port_en, 1380 int opp2_port_en, 1381 int opp_ovr_sub_en) 1382 @param unit Chip unit number. 1383 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1384 @param cpu_op_en 1385 @param lb_opp_en 1386 @param opp1_port_en 1387 @param opp2_port_en 1388 @param opp_ovr_sub_en 1389 @brief API to initialize the HX5 IDB Opportunistic related registers 1390 Regs/Mems configured: IS_CPU_LB_OPP_CFG_PIPE<pipe> 1391 IS_OPP_SCHED_CFG_PIPE<pipe> 1392 */ 1393 int 1394 _soc_hx5_tdm_set_idb_opportunistic(int unit, 1395 soc_port_schedule_state_t *sch_info, 1396 int cpu_op_en, 1397 int lb_opp_en, 1398 int opp1_port_en, 1399 int opp2_port_en, 1400 int opp_ovr_sub_en) 1401 { 1402 soc_reg_t reg; 1403 uint32 pipe_map; 1404 int pipe; 1405 uint32 rval = 0; 1406 static const soc_reg_t idb_cpu_lb_opp_cfg[HELIX5_TDM_PIPES_PER_DEV] = { 1407 IS_CPU_LB_OPP_CFG_PIPE0r/* , IS_CPU_LB_OPP_CFG_PIPE1r */ 1408 }; 1409 static const soc_reg_t idb_opp_sched_cfg[HELIX5_TDM_PIPES_PER_DEV] = { 1410 IS_OPP_SCHED_CFG_PIPE0r/* , IS_OPP_SCHED_CFG_PIPE1r */ 1411 }; 1412 1413 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1414 1415 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1416 if ((pipe_map & (1 << pipe)) == 0) { 1417 /* Enable OPP1 to enable sbus access to the rest of IPIPE*/ 1418 reg = idb_opp_sched_cfg[pipe]; 1419 SOC_IF_ERROR_RETURN( 1420 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1421 soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, 1422 (opp1_port_en == 1) ? 1 : 0); 1423 soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 8); 1424 SOC_IF_ERROR_RETURN( 1425 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1426 continue; 1427 } 1428 1429 reg = idb_cpu_lb_opp_cfg[pipe]; 1430 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1431 soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, 1432 (cpu_op_en == 1) ? 1 : 0); 1433 soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, 1434 (lb_opp_en == 1) ? 1 : 0); 1435 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1436 1437 reg = idb_opp_sched_cfg[pipe]; 1438 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1439 soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, 1440 (opp1_port_en == 1) ? 1 : 0); 1441 soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 8); 1442 soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, 1443 (opp2_port_en == 1) ? 1 : 0); 1444 soc_reg_field_set(unit, reg, &rval, OPP2_SPACINGf, 0); 1445 soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, 1446 (opp_ovr_sub_en == 1) ? 1 : 0); 1447 soc_reg_field_set(unit, reg, &rval, OPP_STRICT_PRIf, 1); 1448 soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 73); /* NULL port */ 1449 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1450 } 1451 1452 return SOC_E_NONE; 1453 } 1454 1455 1456 /*! @fn int soc_hx5_tdm_set_idb_dpp_ctrl( 1457 int unit, 1458 soc_port_schedule_state_t *sch_info, 1459 int credits) 1460 @param unit Chip unit number. 1461 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1462 @param credits 1463 @brief API to initialize the HX5 IDB_DPP_CTRL register. 1464 */ 1465 int 1466 soc_hx5_tdm_set_idb_dpp_ctrl(int unit, 1467 soc_port_schedule_state_t *sch_info, 1468 int credits) 1469 { 1470 soc_reg_t reg; 1471 uint32 pipe_map; 1472 int pipe; 1473 uint32 rval = 0; 1474 static const soc_reg_t idb_dpp_ctrl[HELIX5_TDM_PIPES_PER_DEV] = { 1475 IDB_DPP_CTRL_PIPE0r/* , IDB_DPP_CTRL_PIPE1r */ 1476 }; 1477 1478 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1479 1480 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1481 if (!(pipe_map & (1 << pipe))) { 1482 continue; 1483 } 1484 reg = idb_dpp_ctrl[pipe]; 1485 rval = 0; 1486 /*SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));*/ 1487 soc_reg_field_set(unit, reg, &rval, MAX_REF_CNTf, 4); 1488 soc_reg_field_set(unit, reg, &rval, MAX_SBUS_CNTf, 4); 1489 soc_reg_field_set(unit, reg, &rval, CREDITSf, credits); 1490 soc_reg_field_set(unit, reg, &rval, DONEf, 0); 1491 soc_reg_field_set(unit, reg, &rval, STARTf, 1); 1492 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1493 } 1494 1495 return SOC_E_NONE; 1496 } 1497 1498 1499 /*! @fn int _soc_hx5_tdm_set_idb_pkt_calendar( 1500 int unit, 1501 soc_port_schedule_state_t *sch_info) 1502 @param unit Chip unit number. 1503 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1504 @brief API to initialize the HX5 IDB Packet Shaper calendar. 1505 Regs/Mems configured: IDB PKT_SCH_CALENDAR 1506 */ 1507 int 1508 _soc_hx5_tdm_set_idb_pkt_calendar(int unit, 1509 soc_port_schedule_state_t *sch_info) 1510 { 1511 uint32 pipe_map; 1512 soc_mem_t mem; 1513 int pipe, slot, hpipe; 1514 int port, phy_port, idb_port; 1515 uint32 memfld; 1516 uint32 entry[SOC_MAX_MEM_WORDS]; 1517 static const soc_mem_t idb_pkt_shaper_mems[HELIX5_TDM_PIPES_PER_DEV][2] = { 1518 {PKT_SCH_CALENDAR0_PIPE0m, PKT_SCH_CALENDAR1_PIPE0m}/* , 1519 {PKT_SCH_CALENDAR0_PIPE1m, PKT_SCH_CALENDAR1_PIPE1m} */ 1520 }; 1521 1522 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1523 1524 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1525 if (!(pipe_map & (1 << pipe))) { 1526 continue; 1527 } 1528 /* Configure packet shaper calendar */ 1529 for (hpipe = 0; hpipe < HELIX5_TDM_HPIPES_PER_PIPE; hpipe++) { 1530 mem = idb_pkt_shaper_mems[pipe][hpipe]; 1531 for (slot = 0; slot < HX5_SHAPING_GRP_LEN; slot ++) { 1532 phy_port = sch_info->tdm_ingress_schedule_pipe[pipe]. 1533 tdm_schedule_slice[hpipe].pkt_sch_or_ovs_space[0][slot]; 1534 if ((phy_port >= HX5_NUM_EXT_PORTS) || (phy_port <= 0)) { 1535 idb_port = HELIX5_TDM_IDB_UNUSED_TOKEN; 1536 } else { 1537 port = sch_info->in_port_map.port_p2l_mapping[phy_port]; 1538 idb_port = sch_info->in_port_map.port_l2i_mapping[port] & 1539 0x1f; 1540 } 1541 sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit, 1542 PKT_SCH_CALENDAR0_PIPE0m)); 1543 memfld = idb_port & 0x3f; 1544 soc_mem_field_set(unit, mem, entry, PORT_NUMf, &memfld); 1545 SOC_IF_ERROR_RETURN( 1546 soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot, entry)); 1547 } 1548 } 1549 } 1550 1551 return SOC_E_NONE; 1552 } 1553 1554 1555 /*! @fn int _soc_hx5_tdm_set_ovs_group_sel( 1556 int unit, 1557 soc_port_schedule_state_t *sch_info, 1558 int set_idb, 1559 int set_mmu) 1560 @param unit Chip unit number. 1561 @param sch_info : Pointer to a soc_port_schedule_state_t struct variable. 1562 @param set_idb if 1 then IDB OVS tables are configured 1563 @param set_mmu if 1 then MMU OVS tables are configured 1564 @brief API to initialize the HX5 MMU &/or IDB OVS tables. 1565 Regs/Mems configured: IDB HPIPE0/1_OVR_SUB_GRP_CFG, 1566 HPIPE0/1_OVR_SUB_GRP_CFG 1567 PBLK<n>_CALENDAR 1568 */ 1569 int 1570 _soc_hx5_tdm_set_ovs_group_sel(int unit, 1571 soc_port_schedule_state_t *sch_info, 1572 int set_idb, int set_mmu) 1573 { 1574 uint32 pipe_map, ovs_pipe_map; 1575 soc_reg_t reg, reg1; 1576 int pipe, hpipe, group, lane, slot, id = 0, mode; 1577 int port, phy_port, phy_port_base, idb_port, mmu_port, inst; 1578 int speed_max; 1579 uint32 rval = 0, rval1 = 0; 1580 int pblks[HELIX5_TDM_PIPES_PER_DEV][2][HELIX5_TDM_PBLKS_PER_HPIPE]; 1581 int pm_num, pblk_cal_idx; 1582 int pblk_valid; 1583 int port_speed_class, port_sister_spacing; 1584 1585 static const soc_reg_t idb_grp_cfg_regs[HELIX5_TDM_PIPES_PER_DEV][2] = { 1586 {IS_HPIPE0_OVR_SUB_GRP_CFG_PIPE0r, IS_HPIPE1_OVR_SUB_GRP_CFG_PIPE0r}/* , 1587 {IS_HPIPE0_OVR_SUB_GRP_CFG_PIPE1r, IS_HPIPE1_OVR_SUB_GRP_CFG_PIPE1r} */ 1588 }; 1589 1590 static const soc_reg_t mmu_grp_cfg_regs[2] = { 1591 HPIPE0_OVR_SUB_GRP_CFGr, HPIPE1_OVR_SUB_GRP_CFGr 1592 }; 1593 1594 static const soc_reg_t idb_grp_ovs_regs[HELIX5_TDM_PIPES_PER_DEV][2][6] = { 1595 { 1596 {IS_HPIPE0_OVR_SUB_GRP0_TBL_PIPE0r, IS_HPIPE0_OVR_SUB_GRP1_TBL_PIPE0r, 1597 IS_HPIPE0_OVR_SUB_GRP2_TBL_PIPE0r, IS_HPIPE0_OVR_SUB_GRP3_TBL_PIPE0r, 1598 IS_HPIPE0_OVR_SUB_GRP4_TBL_PIPE0r, IS_HPIPE0_OVR_SUB_GRP5_TBL_PIPE0r }, 1599 {IS_HPIPE1_OVR_SUB_GRP0_TBL_PIPE0r, IS_HPIPE1_OVR_SUB_GRP1_TBL_PIPE0r, 1600 IS_HPIPE1_OVR_SUB_GRP2_TBL_PIPE0r, IS_HPIPE1_OVR_SUB_GRP3_TBL_PIPE0r, 1601 IS_HPIPE1_OVR_SUB_GRP4_TBL_PIPE0r, IS_HPIPE1_OVR_SUB_GRP5_TBL_PIPE0r } 1602 }/* , 1603 { 1604 {IS_HPIPE0_OVR_SUB_GRP0_TBL_PIPE1r, IS_HPIPE0_OVR_SUB_GRP1_TBL_PIPE1r, 1605 IS_HPIPE0_OVR_SUB_GRP2_TBL_PIPE1r, IS_HPIPE0_OVR_SUB_GRP3_TBL_PIPE1r, 1606 IS_HPIPE0_OVR_SUB_GRP4_TBL_PIPE1r, IS_HPIPE0_OVR_SUB_GRP5_TBL_PIPE1r }, 1607 {IS_HPIPE1_OVR_SUB_GRP0_TBL_PIPE1r, IS_HPIPE1_OVR_SUB_GRP1_TBL_PIPE1r, 1608 IS_HPIPE1_OVR_SUB_GRP2_TBL_PIPE1r, IS_HPIPE1_OVR_SUB_GRP3_TBL_PIPE1r, 1609 IS_HPIPE1_OVR_SUB_GRP4_TBL_PIPE1r, IS_HPIPE1_OVR_SUB_GRP5_TBL_PIPE1r } 1610 } */ 1611 }; 1612 1613 static const soc_reg_t mmu_grp_ovs_regs[2][6] = { 1614 {HPIPE0_OVR_SUB_GRP0_TBLr, HPIPE0_OVR_SUB_GRP1_TBLr, 1615 HPIPE0_OVR_SUB_GRP2_TBLr, HPIPE0_OVR_SUB_GRP3_TBLr, 1616 HPIPE0_OVR_SUB_GRP4_TBLr, HPIPE0_OVR_SUB_GRP5_TBLr }, 1617 {HPIPE1_OVR_SUB_GRP0_TBLr, HPIPE1_OVR_SUB_GRP1_TBLr, 1618 HPIPE1_OVR_SUB_GRP2_TBLr, HPIPE1_OVR_SUB_GRP3_TBLr, 1619 HPIPE1_OVR_SUB_GRP4_TBLr, HPIPE1_OVR_SUB_GRP5_TBLr } 1620 }; 1621 1622 static const soc_reg_t idb_pblk_cal_regs[HELIX5_TDM_PIPES_PER_DEV][2][10] = { 1623 { 1624 {IS_HPIPE0_PBLK0_CALENDAR_PIPE0r, IS_HPIPE0_PBLK1_CALENDAR_PIPE0r, 1625 IS_HPIPE0_PBLK2_CALENDAR_PIPE0r, IS_HPIPE0_PBLK3_CALENDAR_PIPE0r, 1626 IS_HPIPE0_PBLK4_CALENDAR_PIPE0r, IS_HPIPE0_PBLK5_CALENDAR_PIPE0r, 1627 IS_HPIPE0_PBLK6_CALENDAR_PIPE0r, IS_HPIPE0_PBLK7_CALENDAR_PIPE0r}, 1628 {IS_HPIPE1_PBLK0_CALENDAR_PIPE0r, IS_HPIPE1_PBLK1_CALENDAR_PIPE0r, 1629 IS_HPIPE1_PBLK2_CALENDAR_PIPE0r, IS_HPIPE1_PBLK3_CALENDAR_PIPE0r, 1630 IS_HPIPE1_PBLK4_CALENDAR_PIPE0r, IS_HPIPE1_PBLK5_CALENDAR_PIPE0r, 1631 IS_HPIPE1_PBLK6_CALENDAR_PIPE0r, IS_HPIPE1_PBLK7_CALENDAR_PIPE0r 1632 } 1633 }/* , 1634 { 1635 {IS_HPIPE0_PBLK0_CALENDAR_PIPE1r, IS_HPIPE0_PBLK1_CALENDAR_PIPE1r, 1636 IS_HPIPE0_PBLK2_CALENDAR_PIPE1r, IS_HPIPE0_PBLK3_CALENDAR_PIPE1r, 1637 IS_HPIPE0_PBLK4_CALENDAR_PIPE1r, IS_HPIPE0_PBLK5_CALENDAR_PIPE1r, 1638 IS_HPIPE0_PBLK6_CALENDAR_PIPE1r, IS_HPIPE0_PBLK7_CALENDAR_PIPE1r }, 1639 {IS_HPIPE1_PBLK0_CALENDAR_PIPE1r, IS_HPIPE1_PBLK1_CALENDAR_PIPE1r, 1640 IS_HPIPE1_PBLK2_CALENDAR_PIPE1r, IS_HPIPE1_PBLK3_CALENDAR_PIPE1r, 1641 IS_HPIPE1_PBLK4_CALENDAR_PIPE1r, IS_HPIPE1_PBLK5_CALENDAR_PIPE1r, 1642 IS_HPIPE1_PBLK6_CALENDAR_PIPE1r, IS_HPIPE1_PBLK7_CALENDAR_PIPE1r } 1643 } */ 1644 }; 1645 1646 static const soc_reg_t mmu_pblk_cal_regs[2][10] = { 1647 {HPIPE0_PBLK0_CALENDARr, HPIPE0_PBLK1_CALENDARr, 1648 HPIPE0_PBLK2_CALENDARr, HPIPE0_PBLK3_CALENDARr, 1649 HPIPE0_PBLK4_CALENDARr, HPIPE0_PBLK5_CALENDARr, 1650 HPIPE0_PBLK6_CALENDARr, HPIPE0_PBLK7_CALENDARr}, 1651 {HPIPE1_PBLK0_CALENDARr, HPIPE1_PBLK1_CALENDARr, 1652 HPIPE1_PBLK2_CALENDARr, HPIPE1_PBLK3_CALENDARr, 1653 HPIPE1_PBLK4_CALENDARr, HPIPE1_PBLK5_CALENDARr, 1654 HPIPE1_PBLK6_CALENDARr, HPIPE1_PBLK7_CALENDARr} 1655 }; 1656 1657 static int pblk_slots[SOC_HX5_PORT_RATIO_COUNT][7] = { 1658 { 0, -1, 0, 0, -1, 0, -1 }, /* SOC_HX5_PORT_RATIO_SINGLE */ 1659 { 0, -1, 2, 0, -1, 2, -1 }, /* SOC_HX5_PORT_RATIO_DUAL_1_1 */ 1660 { 0, 0, 2, 0, 0, 2, -1 }, /* SOC_HX5_PORT_RATIO_DUAL_2_1 */ 1661 { 0, 2, 2, 0, 2, 2, -1 }, /* SOC_HX5_PORT_RATIO_DUAL_1_2 */ 1662 { 0, -1, 2, 0, -1, 3, -1 }, /* SOC_HX5_PORT_RATIO_TRI_023_2_1_1 */ 1663 { 0, 0, 2, 0, 0, 3, -1 }, /* SOC_HX5_PORT_RATIO_TRI_023_4_1_1 */ 1664 { 0, -1, 2, 1, -1, 2, -1 }, /* SOC_HX5_PORT_RATIO_TRI_012_1_1_2 */ 1665 { 0, 2, 2, 1, 2, 2, -1 }, /* SOC_HX5_PORT_RATIO_TRI_012_1_1_4 */ 1666 { 0, -1, 2, 1, -1, 3, -1 } /* SOC_HX5_PORT_RATIO_QUAD */ 1667 }; 1668 1669 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1670 _soc_hx5_tdm_get_ovs_pipe_map(unit, sch_info, &ovs_pipe_map); 1671 1672 /* OVS tables */ 1673 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1674 if (!(ovs_pipe_map & (1 << pipe))) { 1675 continue; 1676 } 1677 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 1678 for (hpipe = 0; hpipe < HELIX5_TDM_HPIPES_PER_PIPE; hpipe++) { 1679 for (group = 0; group < HELIX5_TDM_OVS_GROUPS_PER_HPIPE; group++) { 1680 1681 1682 for (slot = 0; slot < HELIX5_TDM_OVS_GROUP_LENGTH; slot++) { 1683 phy_port = sch_info->tdm_ingress_schedule_pipe[pipe]. 1684 tdm_schedule_slice[hpipe]. 1685 oversub_schedule[group][slot]; 1686 /* PORT_NUMf restricts port numbering within [0-31] & 0x3f 1687 * HPIPE0 port 0-31 maps to mmu/idb port 0-31 1688 * HPIPE1 port 0-31 maps to mmu/idb port 32-63 1689 * PHY_PORT_IDf restricts port block id within [0-9] 1690 */ 1691 if (phy_port > HX5_NUM_PHY_PORTS) { 1692 idb_port = 0x3f; 1693 mmu_port = 0x3f; 1694 id = 0x7; /* 0x7 */ 1695 } else { 1696 port = sch_info->in_port_map.port_p2l_mapping[phy_port]; 1697 idb_port = sch_info->in_port_map.port_l2i_mapping[ 1698 port] & 0x7f; 1699 idb_port = _soc_hx5_tdm_get_mport_2_hp_num(idb_port) ; 1700 mmu_port = sch_info->in_port_map.port_p2m_mapping[ 1701 phy_port] & 0x7f ; 1702 mmu_port = _soc_hx5_tdm_get_mport_2_hp_num(mmu_port) ; 1703 id = sch_info->out_port_map.port_p2PBLK_inst_mapping[ 1704 phy_port] & 0xf; 1705 /* id = _soc_hx5_tdm_get_cal_id((phy_port-1)) & 0xf; */ 1706 1707 } 1708 /* IDB OverSub Groups */ 1709 if (set_idb == 1) { 1710 rval = 0; 1711 reg = idb_grp_ovs_regs[pipe][hpipe][group]; 1712 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id); 1713 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port); 1714 SOC_IF_ERROR_RETURN( 1715 soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 1716 } 1717 /* MMU OverSub Groups */ 1718 if (set_mmu == 1) { 1719 rval = 0; 1720 reg = mmu_grp_ovs_regs[hpipe][group]; 1721 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id); 1722 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port); 1723 SOC_IF_ERROR_RETURN( 1724 soc_reg32_set(unit, reg, inst, slot, rval)); 1725 } 1726 } 1727 1728 /* Handle the case where the first element in the group 1729 * is invalid but other valid ports exist in the group. 1730 */ 1731 for (slot = 0; slot < HELIX5_TDM_OVS_GROUP_LENGTH; slot++) { 1732 phy_port = sch_info->tdm_ingress_schedule_pipe[pipe]. 1733 tdm_schedule_slice[hpipe]. 1734 oversub_schedule[group][slot]; 1735 if (phy_port < HX5_NUM_EXT_PORTS) { 1736 break; 1737 } 1738 } 1739 1740 /* No valid ports found, skip group */ 1741 if (HELIX5_TDM_OVS_GROUP_LENGTH == slot) { 1742 port_speed_class = 0; 1743 /* port_same_spacing = 0; */ 1744 port_sister_spacing = 0; 1745 } else { 1746 port = sch_info->in_port_map.port_p2l_mapping[phy_port]; 1747 speed_max = 25000 * sch_info->in_port_map.port_num_lanes[port]; 1748 if (speed_max > sch_info->in_port_map.log_port_speed[port]) { 1749 speed_max = sch_info->in_port_map.log_port_speed[port]; 1750 } 1751 port_speed_class = 1752 _soc_hx5_tdm_get_speed_ovs_class(unit, speed_max); 1753 /* port_same_spacing = 1754 * _soc_hx5_tdm_get_same_port_spacing_e(unit, speed_max); 1755 */ 1756 port_sister_spacing = 1757 _soc_hx5_tdm_get_sis_port_spacing_e(unit, phy_port); 1758 } 1759 if (set_idb == 1) { 1760 rval = 0; 1761 reg = idb_grp_cfg_regs[pipe][hpipe]; 1762 soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf, 6); /* on ingress, all ports have same spacing */ 1763 soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf, 1764 port_sister_spacing); 1765 soc_reg_field_set(unit, reg, &rval, SPEEDf, 1766 port_speed_class); 1767 SOC_IF_ERROR_RETURN( 1768 soc_reg32_set(unit, reg, REG_PORT_ANY, group, rval)); 1769 } 1770 if (set_mmu == 1) { 1771 rval = 0; 1772 reg = mmu_grp_cfg_regs[hpipe]; 1773 soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf, 1774 6); 1775 soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf, 1776 port_sister_spacing); 1777 soc_reg_field_set(unit, reg, &rval, SPEEDf, 1778 port_speed_class); 1779 SOC_IF_ERROR_RETURN( 1780 soc_reg32_set(unit, reg, inst, group, rval)); 1781 } 1782 } 1783 } 1784 } 1785 1786 /* 16 Port-blocks are supported, with each instance of Oversubscription 1787 * Cell Scheduler supports up to 8 Portblocks. */ 1788 1789 /* First get pblk_cal_idx to pm_num mapping from 1790 * pm_num to pblk_cal_idx 1791 * and **oversub_schedule 1792 */ 1793 /* sal_memset(pblks, -1, sizeof(pblks)); */ 1794 sal_memset(pblks, -1, sizeof(int) * HELIX5_TDM_PIPES_PER_DEV * 2 * 1795 HELIX5_TDM_PBLKS_PER_HPIPE); 1796 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1797 if (!(ovs_pipe_map & (1 << pipe))) { 1798 continue; 1799 } 1800 for (hpipe = 0; hpipe < HELIX5_TDM_HPIPES_PER_PIPE; hpipe++) { 1801 for (group = 0; group < HELIX5_TDM_OVS_GROUPS_PER_HPIPE; group++) { 1802 for (slot = 0; slot < HELIX5_TDM_OVS_GROUP_LENGTH; slot++) { 1803 phy_port = sch_info->tdm_ingress_schedule_pipe[pipe]. 1804 tdm_schedule_slice[hpipe]. 1805 oversub_schedule[group][slot]; 1806 if (phy_port < HX5_NUM_EXT_PORTS) { 1807 /* pm_num = (phy_port - 1) / HELIX5_TDM_PORTS_PER_PBLK; */ 1808 pm_num = _soc_hx5_tdm_get_cal_id((phy_port - 1)); 1809 pblk_cal_idx = sch_info->out_port_map. 1810 port_p2PBLK_inst_mapping[phy_port]; 1811 if (pblk_cal_idx >= 0 && 1812 pblk_cal_idx < HELIX5_TDM_PBLKS_PER_HPIPE) { 1813 pblks[pipe][hpipe][pblk_cal_idx] = pm_num; 1814 } else { 1815 return SOC_E_FAIL; /* invalid mapping */ 1816 } 1817 } 1818 } 1819 } 1820 } 1821 } 1822 1823 /* Configure PBLKs */ 1824 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1825 if (!(ovs_pipe_map & (1 << pipe))) { 1826 continue; 1827 } 1828 1829 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 1830 for (hpipe = 0; hpipe < HELIX5_TDM_HPIPES_PER_PIPE; hpipe++) { 1831 for (pblk_cal_idx = 0; pblk_cal_idx < HELIX5_TDM_PBLKS_PER_HPIPE; 1832 pblk_cal_idx++) { 1833 pm_num = pblks[pipe][hpipe][pblk_cal_idx]; 1834 /*phy_port_base = 1 + (pm_num * HELIX5_TDM_PORTS_PER_PBLK); */ 1835 phy_port_base = _soc_hx5_tdm_get_phy_port_base(pm_num); 1836 /* Get port ratio for this Port Macro */ 1837 soc_hx5_tdm_get_port_ratio(unit, sch_info, pm_num, &mode, 1); 1838 reg = idb_pblk_cal_regs[pipe][hpipe][pblk_cal_idx]; 1839 reg1 = mmu_pblk_cal_regs[hpipe][pblk_cal_idx]; 1840 /* Write PBLK regs 1841 * Only first 6 out of 7 slots could be valid 1842 */ 1843 if ((pm_num < 0) || (pm_num > HELIX5_TDM_PBLKS_PER_DEV)) { 1844 /* To speed-up init this branch could be skipped */ 1845 for (slot = 0; slot < 6; slot++) { 1846 rval = 0; 1847 rval1 = 0; 1848 if (set_idb == 1) { 1849 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 1850 0x3f); 1851 SOC_IF_ERROR_RETURN( 1852 soc_reg32_set(unit, reg, REG_PORT_ANY, slot, 1853 rval)); 1854 } 1855 if (set_mmu == 1) { 1856 soc_reg_field_set(unit, reg1, &rval1, PORT_NUMf, 1857 0x3f); 1858 SOC_IF_ERROR_RETURN( 1859 soc_reg32_set(unit, reg1, inst, slot, rval1)); 1860 } 1861 } 1862 } else { 1863 for (slot = 0; slot < 6; slot++) { 1864 rval = 0; 1865 rval1 = 0; 1866 lane = pblk_slots[mode][slot]; 1867 if (lane == -1) { 1868 pblk_valid = 0; 1869 idb_port = 0x3f; 1870 mmu_port = 0x3f; 1871 } else { 1872 pblk_valid = 1; 1873 port = sch_info->in_port_map.port_p2l_mapping[ 1874 phy_port_base + lane]; 1875 idb_port = sch_info->in_port_map.port_l2i_mapping[ 1876 port] & 0x7f; 1877 idb_port = _soc_hx5_tdm_get_mport_2_hp_num(idb_port) ; 1878 mmu_port = sch_info->in_port_map.port_p2m_mapping[ 1879 (phy_port_base + lane)] & 0x7f; 1880 mmu_port = _soc_hx5_tdm_get_mport_2_hp_num(mmu_port) ; 1881 1882 speed_max = 25000 * 1883 sch_info->in_port_map.port_num_lanes[port]; 1884 if (speed_max > 1885 sch_info->in_port_map.log_port_speed[port]) { 1886 speed_max = 1887 sch_info->in_port_map.log_port_speed[port]; 1888 } 1889 port_speed_class = 1890 _soc_hx5_tdm_get_speed_ovs_class(unit, 1891 speed_max); 1892 } 1893 1894 soc_reg_field_set(unit, reg, &rval, VALIDf, pblk_valid); 1895 soc_reg_field_set(unit, reg, &rval, SPACINGf, 6); 1896 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 1897 idb_port); 1898 soc_reg_field_set(unit, reg1, &rval1, VALIDf, 1899 pblk_valid); 1900 soc_reg_field_set(unit, reg1, &rval1, SPACINGf, 1901 6); 1902 soc_reg_field_set(unit, reg1, &rval1, PORT_NUMf, 1903 mmu_port); 1904 if (set_idb == 1) { 1905 SOC_IF_ERROR_RETURN( 1906 soc_reg32_set(unit, reg, REG_PORT_ANY, slot, 1907 rval)); 1908 } 1909 if (set_mmu == 1) { 1910 SOC_IF_ERROR_RETURN( 1911 soc_reg32_set(unit, reg1, inst, slot, rval1)); 1912 } 1913 } 1914 } 1915 } 1916 } 1917 } 1918 1919 return SOC_E_NONE; 1920 } 1921 1922 1923 /*! @fn int _soc_hx5_tdm_set_ovs_group( 1924 int unit, 1925 soc_port_schedule_state_t *sch_info) 1926 @param unit Chip unit number. 1927 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1928 @brief API to initialize the HX5 MMU & IDB OVS tables. 1929 Regs/Mems configured: IDB HPIPE0/1_OVR_SUB_GRP_CFG 1930 HPIPE0/1_OVR_SUB_GRP_CFG 1931 PBLK<n>_CALENDAR 1932 */ 1933 int 1934 _soc_hx5_tdm_set_ovs_group(int unit, soc_port_schedule_state_t *sch_info) 1935 { 1936 return (_soc_hx5_tdm_set_ovs_group_sel(unit, sch_info, 1, 1)); 1937 } 1938 1939 1940 /*! @fn int _soc_hx5_tdm_set_mmu_calendar( 1941 int unit, 1942 soc_port_schedule_state_t *sch_info) 1943 @param unit Chip unit number. 1944 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 1945 @brief API to initialize the HX5 MMU main calendar. 1946 Regs/Mems configured: MMU TDM_CALENDAR 1947 TDM_CONFIG 1948 */ 1949 int 1950 _soc_hx5_tdm_set_mmu_calendar(int unit, soc_port_schedule_state_t *sch_info) 1951 { 1952 uint32 pipe_map; 1953 uint32 cal_len; 1954 soc_mem_t mem; 1955 soc_reg_t reg; 1956 soc_field_t cal_end_field; 1957 int pipe, slot, id, length, calendar_id; 1958 int phy_port, mmu_port, inst; 1959 uint32 rval = 0; 1960 uint32 memfld; 1961 uint32 entry[SOC_MAX_MEM_WORDS]; 1962 uint32 mem_indx; 1963 static const soc_mem_t calendar_mems[] = { 1964 TDM_CALENDAR0_PIPE0m, 1965 /* TDM_CALENDAR0_PIPE1m, */ 1966 TDM_CALENDAR1_PIPE0m/* , 1967 TDM_CALENDAR1_PIPE1m */ 1968 }; 1969 static const soc_field_t calendar_end_fields[] = { 1970 CAL0_ENDf, CAL1_ENDf 1971 }; 1972 1973 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 1974 sal_memset(entry, 0, sizeof(uint32) * soc_mem_entry_words(unit, 1975 TDM_CALENDAR0_PIPE0m)); 1976 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 1977 if (!(pipe_map & (1 << pipe))) { 1978 continue; 1979 } 1980 1981 /* Determine calendar_id: 0 or 1 */ 1982 reg = TDM_CONFIGr; 1983 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 1984 if (sch_info->is_flexport == 1) { /* choose "the other one" */ 1985 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval)); 1986 calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1; 1987 } else { 1988 calendar_id = 0; /* At init use calendar_id=0 */ 1989 rval = 0; 1990 } 1991 mem = calendar_mems[(calendar_id * HELIX5_TDM_PIPES_PER_DEV) + pipe]; 1992 cal_end_field = calendar_end_fields[calendar_id]; 1993 1994 /* TDM Calendar is always taken from slice 0 */ 1995 cal_len = sch_info->tdm_egress_schedule_pipe[pipe]. 1996 tdm_schedule_slice[0].cal_len; 1997 for (length = cal_len; length > 0; length--) { 1998 if (sch_info->tdm_egress_schedule_pipe[pipe]. 1999 tdm_schedule_slice[0]. 2000 linerate_schedule[length - 1] != HX5_NUM_EXT_PORTS) { 2001 break; 2002 } 2003 } 2004 for (slot = 0; slot < length; slot += 2) { 2005 /* EVEN */ 2006 phy_port = sch_info->tdm_egress_schedule_pipe[ 2007 pipe].tdm_schedule_slice[0].linerate_schedule[slot]; 2008 if (phy_port == HX5_OVSB_TOKEN) { 2009 mmu_port = HELIX5_TDM_MMU_OVSB_TOKEN; 2010 } else if (phy_port == HX5_IDL1_TOKEN) { 2011 mmu_port = HELIX5_TDM_MMU_PURG_TOKEN; 2012 } else if (phy_port == HX5_IDL2_TOKEN) { 2013 mmu_port = HELIX5_TDM_MMU_UNUSED_TOKEN; 2014 } else if (phy_port == HX5_NULL_TOKEN) { 2015 mmu_port = HELIX5_TDM_MMU_NULL_TOKEN; 2016 } else if (phy_port >= HX5_NUM_EXT_PORTS) { 2017 mmu_port = HELIX5_TDM_MMU_UNUSED_TOKEN; 2018 } 2019 else { 2020 /* [0,69] && 127 */ 2021 mmu_port = sch_info->out_port_map.port_p2m_mapping[phy_port] & 2022 0x7f; 2023 } 2024 if (mmu_port > 68) { 2025 id = 0xf; 2026 } else { 2027 /* id = (phy_port - 1) / HELIX5_TDM_PORTS_PER_PBLK; */ 2028 id = _soc_hx5_tdm_get_cal_id((phy_port-1)); 2029 } 2030 memfld = mmu_port & 0x7f; 2031 soc_mem_field_set(unit, mem, entry, PORT_NUM_EVENf, &memfld); 2032 memfld = id & 0xf; 2033 soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_EVENf, &memfld); 2034 /* ODD */ 2035 phy_port = sch_info->tdm_egress_schedule_pipe[ 2036 pipe].tdm_schedule_slice[0].linerate_schedule[slot + 1]; 2037 if (phy_port == HX5_OVSB_TOKEN) { 2038 mmu_port = HELIX5_TDM_MMU_OVSB_TOKEN; 2039 } else if (phy_port == HX5_IDL1_TOKEN) { 2040 mmu_port = HELIX5_TDM_MMU_PURG_TOKEN; 2041 } else if (phy_port == HX5_IDL2_TOKEN) { 2042 mmu_port = HELIX5_TDM_MMU_UNUSED_TOKEN; 2043 } else if (phy_port == HX5_NULL_TOKEN) { 2044 mmu_port = HELIX5_TDM_MMU_NULL_TOKEN; 2045 } else if (phy_port >= HX5_NUM_EXT_PORTS) { 2046 mmu_port = HELIX5_TDM_MMU_UNUSED_TOKEN; 2047 } 2048 else { 2049 /* [0,69] && 127 */ 2050 mmu_port = sch_info->out_port_map.port_p2m_mapping[ 2051 phy_port] & 0x7f; 2052 } 2053 if (mmu_port > 68) { 2054 id = 0xf; 2055 } else { 2056 /*id = (phy_port - 1) / HELIX5_TDM_PORTS_PER_PBLK; */ 2057 id = _soc_hx5_tdm_get_cal_id((phy_port-1)); 2058 } 2059 memfld = mmu_port & 0x7f; 2060 soc_mem_field_set(unit, mem, entry, PORT_NUM_ODDf, &memfld); 2061 memfld = id & 0xf; 2062 soc_mem_field_set(unit, mem, entry, PHY_PORT_ID_ODDf, &memfld); 2063 /* Memory entry */ 2064 mem_indx = slot / 2; 2065 SOC_IF_ERROR_RETURN 2066 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_indx, entry)); 2067 } 2068 2069 /* set for 2nd management port 2070 * if (_soc_hx5_tdm_check_2nd_mgmt_enable(unit, sch_info) == 1 && 2071 * pipe == (HELIX5_TDM_PIPES_PER_DEV - 1)) { 2072 * soc_reg_field_set(unit, reg, &rval, MGMT_2ND_PORT_ENABLEf, 1); 2073 * } 2074 */ 2075 soc_reg_field_set(unit, reg, &rval, cal_end_field, length-1); 2076 soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id); 2077 soc_reg_field_set(unit, reg, &rval, ENABLEf, 1); 2078 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 2079 } 2080 2081 return SOC_E_NONE; 2082 } 2083 2084 2085 /*! @fn int _soc_hx5_tdm_set_mmu_hsp( 2086 int unit, 2087 soc_port_schedule_state_t *sch_info) 2088 @param unit Chip unit number. 2089 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 2090 @brief API to initialize the HX5 MMU HSP. 2091 Regs/Mems configured: TDM_HSP_PIPE 2092 */ 2093 int 2094 _soc_hx5_tdm_set_mmu_hsp(int unit, 2095 soc_port_schedule_state_t *sch_info) 2096 { 2097 soc_reg_t reg; 2098 uint32 pipe_map; 2099 int port, mmu_port, phy_port; 2100 int port_speed; 2101 uint32 port_map[3]; 2102 uint32 rval = 0; 2103 2104 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 2105 2106 port_map[0] = 0; 2107 port_map[1] = 0; 2108 port_map[2] = 0; 2109 2110 for (port=0; port< 70 ; port++) { /* mmu logical ports */ 2111 port_speed = sch_info->out_port_map.log_port_speed[port]; 2112 if (port_speed > 0) { 2113 if (_soc_hx5_tdm_check_is_hsp_port_e(unit, port_speed) == 1) { 2114 phy_port = sch_info->out_port_map.port_l2p_mapping[port]; 2115 if ((phy_port >= 1) && 2116 (phy_port <= HELIX5_TDM_GPORTS_PER_DEV)) { 2117 mmu_port = sch_info->out_port_map.port_p2m_mapping[phy_port] & 0x7f; 2118 if (mmu_port < 32) { 2119 port_map[0] |= 1 << mmu_port; 2120 } 2121 else if (mmu_port < 64) { 2122 port_map[1] |= 1 << (mmu_port - 32); 2123 } 2124 else if (mmu_port > 63) { 2125 port_map[2] |= 1 << (mmu_port - 64); 2126 } 2127 } 2128 } 2129 } 2130 } 2131 2132 reg = TDM_HSP_0r; 2133 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[0]); 2134 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, 0, 0, rval)); 2135 2136 reg = TDM_HSP_1r; 2137 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[1]); 2138 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, 0, 0, rval)); 2139 reg = TDM_HSP_2r; 2140 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[2]); 2141 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, 0, 0, rval)); 2142 return SOC_E_NONE; 2143 } 2144 2145 2146 /*! @fn int _soc_hx5_tdm_set_mmu_opportunistic( 2147 int unit, 2148 soc_port_schedule_state_t *sch_info, 2149 int cpu_op_en, 2150 int lb_opp_en, 2151 int opp1_port_en, 2152 int opp2_port_en, 2153 int opp_ovr_sub_en) 2154 @param unit Chip unit number. 2155 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 2156 @param cpu_op_en 2157 @param lb_opp_en 2158 @param opp1_port_en 2159 @param opp2_port_en 2160 @param opp_ovr_sub_en 2161 @brief API to initialize the HX5 MMU Opportunistic related registers 2162 Regs/Mems configured: CPU_LB_OPP_CFG 2163 OPP_SCHED_CFG 2164 */ 2165 int 2166 _soc_hx5_tdm_set_mmu_opportunistic(int unit, 2167 soc_port_schedule_state_t *sch_info, 2168 int cpu_op_en, 2169 int lb_opp_en, 2170 int opp1_port_en, 2171 int opp2_port_en, 2172 int opp_ovr_sub_en) 2173 { 2174 uint32 pipe_map; 2175 soc_reg_t reg; 2176 int pipe; 2177 int inst; 2178 uint32 rval = 0; 2179 2180 _soc_hx5_tdm_get_pipe_map(unit, sch_info, &pipe_map); 2181 2182 for (pipe = 0; pipe < HELIX5_TDM_PIPES_PER_DEV; pipe++) { 2183 if (!(pipe_map & (1 << pipe))) { 2184 continue; 2185 } 2186 2187 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 2188 2189 reg = CPU_LB_OPP_CFGr; 2190 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval)); 2191 soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, 2192 (cpu_op_en == 1) ? 1 : 0); 2193 soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, 2194 (lb_opp_en == 1) ? 1 : 0); 2195 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 2196 2197 reg = OPP_SCHED_CFGr; 2198 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval)); 2199 soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, 2200 (opp1_port_en == 1) ? 1 : 0); 2201 soc_reg_field_set(unit, reg, &rval, OPP1_SPACINGf, 6); 2202 soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, 2203 (opp2_port_en == 1) ? 1 : 0); 2204 soc_reg_field_set(unit, reg, &rval, OPP2_SPACINGf, 0); 2205 soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, 2206 (opp_ovr_sub_en == 1) ? 1 : 0); 2207 soc_reg_field_set(unit, reg, &rval, OPP_STRICT_PRIf, 0); 2208 soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 73); 2209 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 2210 } 2211 2212 return SOC_E_NONE; 2213 } 2214 2215 2216 /*! @fn int soc_hx5_tdm_init( 2217 int unit, 2218 soc_port_schedule_state_t *sch_info) 2219 @param unit Chip unit number. 2220 @param sch_info Pointer to a soc_port_schedule_state_t struct variable. 2221 @brief Main API for TDM init 2222 */ 2223 int soc_hx5_tdm_init(int unit, soc_port_schedule_state_t *sch_info) 2224 { 2225 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_calculation(unit, sch_info)); 2226 2227 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_idb_calendar(unit, sch_info)); 2228 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_idb_hsp(unit, sch_info)); 2229 /* SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_idb_pkt_calendar(unit, sch_info)); */ 2230 /* SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_idb_ppe_credit(unit, sch_info, 16, 8, 16, 8)); */ 2231 /* SOC_IF_ERROR_RETURN(soc_hx5_tdm_set_idb_dpp_ctrl(unit, sch_info, 32)); */ 2232 /* IDB opp1_port_en should always be 1 to enable sbus access to the rest of IPIPE*/ 2233 if (!soc_property_get(unit, "disable_opportunistic_scheduling", 0)) { 2234 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_idb_opportunistic(unit, sch_info, 2235 1, 1, 1, 1, 1)); 2236 } else { 2237 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_idb_opportunistic(unit, sch_info, 2238 0, 0, 0, 0, 0)); 2239 } 2240 2241 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_ovs_group(unit, sch_info)); 2242 2243 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_mmu_calendar(unit, sch_info)); 2244 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_mmu_hsp(unit, sch_info)); 2245 if (!soc_property_get(unit, "disable_opportunistic_scheduling", 0)) { 2246 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_mmu_opportunistic(unit, sch_info, 2247 1, 1, 1, 1, 1)); 2248 } else { 2249 SOC_IF_ERROR_RETURN(_soc_hx5_tdm_set_mmu_opportunistic(unit, sch_info, 2250 0, 0, 0, 0, 0)); 2251 } 2252 2253 return SOC_E_NONE; 2254 } 2255 2256 /*! @fn int soc_helix5_port_speed_higig2eth(int speed) 2257 * @param int speed 2258 * @brief Map port speed to ETH bitrates 2259 */ 2260 static int 2261 soc_helix5_port_speed_higig2eth(int speed) 2262 { 2263 switch (speed) { 2264 case 11000: 2265 /* 10G */ 2266 return 10000; 2267 case 21000: 2268 /* 20G */ 2269 return 20000; 2270 case 27000: 2271 /* 25G */ 2272 return 25000; 2273 case 42000: 2274 /* 40G */ 2275 return 40000; 2276 case 53000: 2277 /* 50G */ 2278 return 50000; 2279 case 106000: 2280 /* 100G */ 2281 return 100000; 2282 default: 2283 return speed; 2284 } 2285 } 2286 2287 /*! @fn void soc_helix5_port_schedule_speed_remap(int unit, 2288 * soc_port_schedule_state_t *port_schedule_state) 2289 * @param unit Chip unit number. 2290 * @param port_schedule_state Pointer to a soc_port_schedule_state_t struct 2291 * variable. 2292 * @brief API to remap speeds to ETH bitrates 2293 */ 2294 void 2295 soc_helix5_port_schedule_speed_remap( 2296 int unit, 2297 soc_port_schedule_state_t *port_schedule_state) 2298 { 2299 int i, port; 2300 2301 /* Speed remap for in_port_map*/ 2302 for (port=0; port < SOC_MAX_NUM_PORTS; port++) { 2303 port_schedule_state->in_port_map.log_port_speed[port] = 2304 soc_helix5_port_speed_higig2eth( 2305 port_schedule_state->in_port_map.log_port_speed[port]); 2306 } 2307 2308 if (port_schedule_state->is_flexport == 1) { 2309 /* Speed remap for out_port_map*/ 2310 for (port=0; port < SOC_MAX_NUM_PORTS; port++) { 2311 port_schedule_state->out_port_map.log_port_speed[port] = 2312 soc_helix5_port_speed_higig2eth( 2313 port_schedule_state->out_port_map.log_port_speed[port]); 2314 } 2315 /* Speed remap for resource */ 2316 for (i = 0; i < port_schedule_state->nport; i++) { 2317 if (-1 != port_schedule_state->resource[i].physical_port) { /* that is, port up */ 2318 port_schedule_state->resource[i].speed = 2319 soc_helix5_port_speed_higig2eth( 2320 port_schedule_state->resource[i].speed); 2321 } 2322 } 2323 } 2324 } 2325 2326 /*** END SDK API COMMON CODE ***/ 2327 2328 #endif /* BCM_HELIX5_SUPPORT */