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