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