tdm_hx5_cmn.c (12467B)
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 * $All Rights Reserved.$ 7 * 8 * TDM chip-specific common facility functions 9 */ 10 #ifdef _TDM_STANDALONE 11 #include <tdm_top.h> 12 #else 13 #include <soc/tdm/core/tdm_top.h> 14 #endif 15 16 #define HX5_BUFF_SIZE 256 17 18 19 20 /** 21 @name: tdm_hx5_cmn_get_port_pm 22 @param: 23 24 Return Port Macro number of the given port 25 */ 26 int 27 tdm_hx5_cmn_get_port_pm(int port_token, tdm_mod_t *_tdm) 28 { 29 int port_pm; 30 31 if (_tdm->_chip_data.soc_pkg.pmap_num_lanes > 0 && 32 port_token >=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo && 33 port_token <=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) { 34 port_pm = (port_token - 1) / _tdm->_chip_data.soc_pkg.pmap_num_lanes ; 35 } else { 36 port_pm = _tdm->_chip_data.soc_pkg.pm_num_phy_modules; 37 } 38 39 return (port_pm); 40 /* 41 _tdm->_core_data.vars_pkg.port = port_token; 42 43 return (_tdm->_core_exec[TDM_CORE_EXEC__PM_SCAN](_tdm)); */ 44 } 45 46 47 /** 48 @name: tdm_hx5_cmn_get_port_pm 49 @param: 50 51 Return Port Macro number of the given port 52 */ 53 int 54 tdm_hx5_cmn_get_port_pm_chk(int port_token, tdm_mod_t *_tdm) 55 { 56 int port_pm; 57 58 if (_tdm->_chip_data.soc_pkg.pmap_num_lanes > 0 && 59 port_token >=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo && 60 port_token <=_tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) { 61 if(port_token > 48 ){ /* pm 4x10q sis port spacing is across 16 ports */ 62 port_pm = (port_token - 1) / _tdm->_chip_data.soc_pkg.pmap_num_lanes; 63 } 64 else 65 { 66 port_pm = (port_token - 1) / 16 ; 67 } 68 69 } else { 70 port_pm = _tdm->_chip_data.soc_pkg.pm_num_phy_modules; 71 } 72 73 return (port_pm); 74 /* 75 _tdm->_core_data.vars_pkg.port = port_token; 76 77 return (_tdm->_core_exec[TDM_CORE_EXEC__PM_SCAN](_tdm)); */ 78 } 79 80 81 82 83 /** 84 @name: tdm_hx5_cmn_get_port_speed 85 @param: 86 87 Return port speed of the given port 88 */ 89 int 90 tdm_hx5_cmn_get_port_speed(int port_token, tdm_mod_t *_tdm) 91 { 92 if (port_token >= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo && 93 port_token <= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) { 94 return (_tdm->_chip_data.soc_pkg.speed[port_token]); 95 } 96 97 return (SPEED_0); 98 } 99 100 101 /** 102 @name: tdm_hx5_cmn_get_port_state 103 @param: 104 105 Return port state of the given port 106 */ 107 int 108 tdm_hx5_cmn_get_port_state(int port_token, tdm_mod_t *_tdm) 109 { 110 if (port_token >= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo && 111 port_token <= _tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi) { 112 return (_tdm->_chip_data.soc_pkg.state[port_token-1]); 113 } 114 115 return (PORT_STATE__DISABLED); 116 } 117 118 119 /** 120 @name: tdm_hx5_cmn_get_speed_lanes 121 @param: 122 123 Return the number of lanes required by the given speed 124 (Chip-Specific) 125 */ 126 int 127 tdm_hx5_cmn_get_speed_lanes(int port_speed) 128 { 129 int lanes = 0; 130 131 switch(port_speed){ 132 case SPEED_1G: case SPEED_2p5G: 133 case SPEED_10G: case SPEED_11G: 134 case SPEED_20G: case SPEED_21G: 135 case SPEED_25G: case SPEED_27G: 136 lanes = 1; 137 break; 138 case SPEED_40G: case SPEED_42G: case SPEED_42G_HG2: 139 case SPEED_50G: case SPEED_53G: 140 lanes = 2; 141 break; 142 case SPEED_100G: case SPEED_106G: 143 lanes = 4; 144 break; 145 default: 146 break; 147 } 148 149 return (lanes); 150 } 151 152 153 /** 154 @name: tdm_hx5_cmn_get_speed_slots 155 @param: 156 157 Return the number of slots (2.5G per slot) of the given speed 158 (Chip-Specific) 159 */ 160 int 161 tdm_hx5_cmn_get_speed_slots(int port_speed) 162 { 163 int slot_num=0; 164 165 switch (port_speed) { 166 case SPEED_1G: 167 slot_num = 1; 168 break; 169 case SPEED_2G: case SPEED_2p5G: 170 slot_num = 2; 171 break; 172 case SPEED_10G: case SPEED_11G: 173 slot_num = 8; 174 break; 175 case SPEED_20G: case SPEED_21G: 176 slot_num = 16; 177 break; 178 case SPEED_25G: case SPEED_27G: 179 slot_num = 20; 180 break; 181 case SPEED_40G: case SPEED_42G: case SPEED_42G_HG2: 182 slot_num = 32; 183 break; 184 case SPEED_50G: case SPEED_53G: 185 slot_num = 40; 186 break; 187 case SPEED_100G: case SPEED_106G: 188 slot_num = 80; 189 break; 190 default: 191 TDM_ERROR4("%s, %s -- %dM (%dG)\n", 192 "[Port Speed]", 193 "invalid port speed", 194 port_speed, port_speed/1000); 195 break; 196 } 197 198 return (slot_num); 199 } 200 201 202 /** 203 @name: tdm_hx5_cmn_get_pipe_port_range 204 @param: 205 206 Return physical port number range of the given pipe 207 */ 208 void 209 tdm_hx5_cmn_get_pipe_port_range(int cal_id, int *phy_lo, int *phy_hi) 210 { 211 int prt_lo = 0, prt_hi = 0; 212 213 switch(cal_id){ 214 case 0: prt_lo = HX5_CAL_0_PORT_LO; prt_hi = HX5_CAL_0_PORT_HI; break; 215 case 1: prt_lo = HX5_CAL_1_PORT_LO; prt_hi = HX5_CAL_1_PORT_HI; break; 216 case 4: prt_lo = HX5_CAL_4_PORT_LO; prt_hi = HX5_CAL_4_PORT_HI; break; 217 case 5: prt_lo = HX5_CAL_5_PORT_LO; prt_hi = HX5_CAL_5_PORT_HI; break; 218 default: break; 219 } 220 if (phy_lo != NULL && phy_hi != NULL) { 221 *phy_lo = prt_lo; 222 *phy_hi = prt_hi; 223 } 224 } 225 226 227 /** 228 @name: tdm_hx5_cmn_get_pipe_ethernet 229 @param: 230 231 Return BOOL_TRUE if the given pipe has traffic entirely Ethernet; 232 otherwise, return BOOL_FALSE. 233 */ 234 int 235 tdm_hx5_cmn_get_pipe_ethernet(int cal_id, tdm_mod_t *_tdm) 236 { 237 int port_phy, phy_lo, phy_hi, result=BOOL_TRUE; 238 int param_phy_lo, param_phy_hi; 239 enum port_speed_e *param_speeds; 240 enum port_state_e *param_states; 241 242 param_phy_lo = _tdm->_chip_data.soc_pkg.soc_vars.fp_port_lo; 243 param_phy_hi = _tdm->_chip_data.soc_pkg.soc_vars.fp_port_hi; 244 param_speeds = _tdm->_chip_data.soc_pkg.speed; 245 param_states = _tdm->_chip_data.soc_pkg.state; 246 247 tdm_hx5_cmn_get_pipe_port_range(cal_id, &phy_lo, &phy_hi); 248 if (phy_lo >= param_phy_lo && phy_hi <= param_phy_hi) { 249 for (port_phy=phy_lo; port_phy<=phy_hi; port_phy++) { 250 if (param_speeds[port_phy] > SPEED_0) { 251 if (param_states[port_phy-1] == PORT_STATE__LINERATE_HG 252 ) { 253 result = BOOL_FALSE; 254 break; 255 } 256 } 257 } 258 } 259 260 return (result); 261 } 262 263 264 /** 265 @name: tdm_hx5_cmn_get_pipe_higig 266 @param: 267 268 Return BOOL_TRUE if the given pipe has HiGig traffic; 269 otherwise, return BOOL_FALSE. 270 (Chip-Specific) 271 */ 272 int 273 tdm_hx5_cmn_get_pipe_higig(int cal_id, tdm_mod_t *_tdm) 274 { 275 int result = BOOL_FALSE; 276 277 /* check regular ports */ 278 if (tdm_hx5_cmn_get_pipe_ethernet(cal_id, _tdm) == BOOL_FALSE) { 279 result = BOOL_TRUE; 280 } 281 282 return (result); 283 } 284 285 286 /** 287 @name: tdm_hx5_cmn_get_pipe_cal_len_max 288 @param: 289 290 Return the size of selected calendar (regardless of frequency/higig) 291 */ 292 int 293 tdm_hx5_cmn_get_pipe_cal_len_max(int cal_id, tdm_mod_t *_tdm) 294 { 295 int cal_len = 0; 296 297 switch (cal_id) { 298 case 0: cal_len = _tdm->_chip_data.cal_0.cal_len; break; 299 case 1: cal_len = _tdm->_chip_data.cal_1.cal_len; break; 300 case 2: cal_len = _tdm->_chip_data.cal_2.cal_len; break; 301 case 3: cal_len = _tdm->_chip_data.cal_3.cal_len; break; 302 case 4: cal_len = _tdm->_chip_data.cal_4.cal_len; break; 303 case 5: cal_len = _tdm->_chip_data.cal_5.cal_len; break; 304 case 6: cal_len = _tdm->_chip_data.cal_6.cal_len; break; 305 case 7: cal_len = _tdm->_chip_data.cal_7.cal_len; break; 306 default: break; 307 } 308 309 return (cal_len); 310 } 311 312 313 /** 314 @name: tdm_hx5_cmn_get_pipe_cal_len 315 @param: 316 317 Return valid length of selected calendar under frequency/higig constraint 318 (Chip-Specific) 319 */ 320 int 321 tdm_hx5_cmn_get_pipe_cal_len(int cal_id, tdm_mod_t *_tdm) 322 { 323 int cal_len = 0; 324 int param_freq; 325 326 param_freq = _tdm->_chip_data.soc_pkg.clk_freq; 327 328 /* get calendar length */ 329 if (tdm_hx5_cmn_get_pipe_higig(cal_id, _tdm) == BOOL_FALSE) { 330 switch (param_freq) { 331 case HX5_CLK_450MHZ: cal_len = HX5_LEN_450MHZ; break; 332 case HX5_CLK_400MHZ: cal_len = HX5_LEN_400MHZ; break; 333 case HX5_CLK_543MHZ: cal_len = HX5_LEN_543MHZ; break; 334 case HX5_CLK_587MHZ: cal_len = HX5_LEN_587MHZ; break; 335 case HX5_CLK_668MHZ: cal_len = HX5_LEN_668MHZ; break; 336 case HX5_CLK_812MHZ: cal_len = HX5_LEN_812MHZ; break; 337 case HX5_CLK_893MHZ: cal_len = HX5_LEN_893MHZ; break; 338 case HX5_CLK_931MHZ: cal_len = HX5_LEN_931MHZ; break; 339 default: break; 340 } 341 } else { 342 switch (param_freq) { 343 case HX5_CLK_450MHZ: cal_len = HX5_LEN_450HMHZ; break; 344 case HX5_CLK_400MHZ: cal_len = HX5_LEN_400HMHZ; break; 345 case HX5_CLK_543MHZ: cal_len = HX5_LEN_543MHZ; break; 346 case HX5_CLK_587MHZ: cal_len = HX5_LEN_587HMHZ; break; 347 case HX5_CLK_668MHZ: cal_len = HX5_LEN_668MHZ; break; 348 case HX5_CLK_812MHZ: cal_len = HX5_LEN_812MHZ; break; 349 case HX5_CLK_893MHZ: cal_len = HX5_LEN_893MHZ; break; 350 case HX5_CLK_931MHZ: cal_len = HX5_LEN_931MHZ; break; 351 default: break; 352 } 353 } 354 /* check validity of calendar length */ 355 if (cal_len == 0) { 356 TDM_ERROR1("Invalid core clock frequency %0d\n", param_freq); 357 } else if (cal_len > tdm_hx5_cmn_get_pipe_cal_len_max(cal_id, _tdm)) { 358 cal_len = 0; 359 TDM_ERROR1("Invalid calendar length %0d (overflow)\n", cal_len); 360 } 361 362 return (cal_len); 363 } 364 365 366 /** 367 @name: tdm_hx5_cmn_get_same_port_dist 368 @param: 369 */ 370 int 371 tdm_hx5_cmn_get_same_port_dist(int slot, int dir, int *cal_main, int cal_len) 372 { 373 int n, k, dist = 0; 374 375 if (slot < cal_len && cal_len > 0) { 376 if (dir == TDM_DIR_UP) { /* UP direction */ 377 for (n = 1; n < cal_len; n++) { 378 k = (slot + cal_len - n) % cal_len; 379 if (cal_main[k] == cal_main[slot]) { 380 dist = n; 381 break; 382 } 383 } 384 } else { /* DOWN direction */ 385 for (n = 1; n < cal_len; n++) { 386 k = (slot + n) % cal_len; 387 if (cal_main[k] == cal_main[slot]) { 388 dist = n; 389 break; 390 } 391 } 392 } 393 } 394 395 return (dist); 396 } 397 398 399 /** 400 @name: tdm_hx5_cmn_get_speed_jitter 401 @param: 402 */ 403 void 404 tdm_hx5_cmn_get_speed_jitter(int port_speed, int cal_len, int *space_min, int *space_max) 405 { 406 int slot_req, space_frac, jitter_range, jitter_min=0, jitter_max=0; 407 408 /* TDM_LOG_NORMAL("jitter compute for port_speed %d, cal_len %d ",port_speed , cal_len); */ 409 410 411 if (port_speed<SPEED_10G) { 412 slot_req = (port_speed/100)/25; 413 } else { 414 slot_req = ((port_speed/10000)*100)/25; 415 } 416 417 slot_req = slot_req * 2 ; 418 if(port_speed == SPEED_25G) 419 slot_req = slot_req + 4 ; 420 421 if (slot_req>0) { 422 space_frac = ((cal_len*10)/slot_req)%10; 423 jitter_range= (2*cal_len)/(slot_req*5); 424 jitter_range= ((((2*cal_len*10)/(slot_req*5))%10)<5)? 425 (jitter_range): 426 (jitter_range+1); 427 /* TDM_LOG_NORMAL("%d, space_frac %d, jitter_range , %d slot_req ",space_frac , jitter_range , slot_req); */ 428 429 if (space_frac<5){ 430 jitter_min = cal_len/slot_req - jitter_range/2; 431 jitter_max = cal_len/slot_req + jitter_range/2; 432 jitter_max = ((jitter_range%2)==0)? 433 (jitter_max): 434 (jitter_max+1); 435 } else { 436 jitter_min = cal_len/slot_req - jitter_range/2; 437 jitter_min = ((cal_len%slot_req)==0)? 438 (jitter_min): 439 (jitter_min+1); 440 jitter_min = ((jitter_range%2)==0)? 441 (jitter_min): 442 (jitter_min-1); 443 jitter_max = cal_len/slot_req + jitter_range/2; 444 jitter_max = ((cal_len%slot_req)==0)? 445 (jitter_max): 446 (jitter_max+1); 447 } 448 jitter_min = (jitter_min<1)? (1): (jitter_min); 449 jitter_max = (jitter_max<1)? (1): (jitter_max); 450 } 451 if (space_min != NULL && space_max != NULL) { 452 *space_min = jitter_min; 453 *space_max = jitter_max; 454 } 455 /* TDM_LOG_NORMAL("%d, port_speed %d, cal_len %d, jitter_min %d, jitter_max ",port_speed , cal_len ,jitter_min , jitter_max ); */ 456 }