cmicx_schan.c (24827B)
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 * S-Channel (internal command bus) support 8 */ 9 10 #include <shared/bsl.h> 11 #include <sal/core/libc.h> 12 #include <sal/core/boot.h> 13 #include <soc/debug.h> 14 #include <soc/cm.h> 15 #include <soc/error.h> 16 #include <sal/core/sync.h> 17 #include <soc/util.h> 18 #include <soc/cmic.h> 19 20 #ifdef BCM_CMICX_SUPPORT 21 #include <soc/cmicx.h> 22 #include <soc/intr_cmicx.h> 23 #include <soc/schanmsg_internal.h> 24 25 #ifdef BCM_SAND_SUPPORT 26 #include <soc/sand/sand_aux_access.h> 27 #endif 28 29 #define SOC_SCHAN_POLL_WAIT_TIMEOUT 100 30 31 32 typedef struct intr_data_s { 33 sal_sem_t schanIntr; 34 int ch; 35 }intr_data_t; 36 37 typedef struct soc_cmicx_schan_s { 38 sal_spinlock_t lock; 39 int timeout; 40 int ch_map; 41 intr_data_t intr[CMIC_SCHAN_NUM_MAX]; 42 }soc_cmicx_schan_t; 43 44 45 STATIC soc_cmicx_schan_t _soc_cmicx_schan[SOC_MAX_NUM_DEVICES]; 46 47 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE 48 STATIC int _adjust_2nd_core_sbus_access(schan_header_t *header, uint32 blk) 49 { 50 switch(header->v4.opcode) { 51 case READ_REGISTER_CMD_MSG: 52 /* No need for header->v4.opcode = READ_REGISTER_ACK_MSG; as a register is read */ 53 break; 54 case READ_MEMORY_CMD_MSG: 55 /* No need for header->v4.opcode = READ_MEMORY_ACK_MSG; as a memory is read*/ 56 break; 57 /* writes that are not really performed do not require setting a returned opcode */ 58 default: 59 header->v4.err = 0; 60 return TRUE; 61 } 62 header->v4.dst_blk = blk >> 4; 63 header->v4.acc_type = (blk & 0xf) << 1; 64 return FALSE; 65 } 66 67 #define SET_V4_HEADER_DST_BLK_TYPE(blk_value_) \ 68 exit_now = _adjust_2nd_core_sbus_access(header, blk_value_); \ 69 break; 70 71 #endif /* defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE */ 72 73 74 /******************************************* 75 * @function _soc_cmicx_schan_reset 76 * purposeResets the CMICX S-Channel interface. 77 * 78 * @param unit [in] unit # 79 * @param cmc [in] cmc number 0 80 * @param ch [in] channel number 0-4 81 * 82 * @returns SOC_E_BUSY 83 * @returns SOC_E_NONE 84 * 85 * @end 86 */ 87 88 STATIC void 89 _soc_cmicx_schan_reset(int unit, int cmc, int ch) 90 { 91 uint32 val; 92 93 COMPILER_REFERENCE(cmc); 94 95 val = soc_pci_read(unit, CMIC_COMMON_POOL_SCHAN_CHx_CTRL(ch)); 96 /* Toggle S-Channel abort bit in CMIC_SCHAN_CTRL register */ 97 soc_pci_write(unit, CMIC_COMMON_POOL_SCHAN_CHx_CTRL(ch), 98 val | SC_CHx_SCHAN_ABORT); 99 SDK_CONFIG_MEMORY_BARRIER; 100 soc_pci_write(unit, CMIC_COMMON_POOL_SCHAN_CHx_CTRL(ch), val); 101 SDK_CONFIG_MEMORY_BARRIER; 102 103 if (SAL_BOOT_QUICKTURN) { 104 /* Give Quickturn at least 2 cycles */ 105 sal_usleep(10 * MILLISECOND_USEC); 106 } 107 } 108 109 110 /******************************************* 111 * @function _soc_cmicx_schan_get 112 * purpose get idle channel 113 * 114 * @param unit [in] unit # 115 * @param ch [out] channel number 0-4 116 * 117 * @returns SOC_E_BUSY 118 * @returns SOC_E_NONE 119 * 120 * @end 121 */ 122 STATIC int _soc_cmicx_schan_get(int unit, int *ch) 123 { 124 int i; 125 int rv = SOC_E_BUSY; 126 127 soc_timeout_t to; 128 129 soc_timeout_init(&to, _soc_cmicx_schan[unit].timeout, 100); 130 131 do { 132 sal_spinlock_lock(_soc_cmicx_schan[unit].lock); 133 for ( i = 0; i < CMIC_SCHAN_NUM_MAX; i++) { 134 if (_soc_cmicx_schan[unit].ch_map & 0x01 << i) { 135 rv = SOC_E_NONE; 136 *ch = i; 137 _soc_cmicx_schan[unit].ch_map &= ~(0x01 << i); 138 break; 139 } 140 } 141 sal_spinlock_unlock(_soc_cmicx_schan[unit].lock); 142 if (rv == SOC_E_NONE) 143 break; 144 145 } while (!soc_timeout_check(&to)); 146 return rv; 147 } 148 149 150 /******************************************* 151 * @function _soc_cmicx_schan_put 152 * purpose get idle channel 153 * 154 * @param unit [in] unit # 155 * @param ch [in] channel number 0-4 156 * 157 * @returns SOC_E_PARAM 158 * @returns SOC_E_NONE 159 160 * 161 * @end 162 */ 163 STATIC int _soc_cmicx_schan_put(int unit, int ch) 164 { 165 int rv = SOC_E_NONE; 166 167 if ((ch < 0) || (ch > CMIC_SCHAN_NUM_MAX -1)) { 168 rv = SOC_E_PARAM; 169 return rv; 170 } 171 sal_spinlock_lock(_soc_cmicx_schan[unit].lock); 172 _soc_cmicx_schan[unit].ch_map |= (0x01 << ch); 173 sal_spinlock_unlock(_soc_cmicx_schan[unit].lock); 174 175 return rv; 176 } 177 178 /******************************************* 179 * @function _soc_cmicx_schan_cmic_err_handle 180 * purpose Handle schan cimicx error 181 * 182 * @param unit [in] unit 183 * @param schanCtrl [in] schan control word 184 * @param ch [in] channel 185 * 186 * @returns SOC_E_XXX 187 * @returns SOC_E_NONE 188 * 189 * @end 190 */ 191 192 STATIC int 193 _soc_cmicx_schan_err_handle(int unit, int schanCtrl, int ch) 194 { 195 int rv = SOC_E_NONE; 196 uint32 schan_err = 0; 197 198 if (schanCtrl & SC_CHx_MSG_NAK) { 199 LOG_VERBOSE(BSL_LS_SOC_SCHAN, 200 (BSL_META_U(unit, 201 "NAK received from SCHAN.\n"))); 202 rv = SOC_E_FAIL; 203 } 204 205 if (schanCtrl & SC_CHx_MSG_SER_CHECK_FAIL) { 206 LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit, 207 "SER Parity Check Error.\n"))); 208 rv = SOC_E_FAIL; 209 } 210 211 if (soc_feature(unit, soc_feature_schan_hw_timeout)) { 212 if (schanCtrl & SC_CHx_MSG_TIMEOUT_TST) { 213 LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit, 214 "Hardware Timeout Error.\n"))); 215 rv = SOC_E_TIMEOUT; 216 } 217 } 218 219 if (soc_feature(unit, soc_feature_schan_err_check)) { 220 221 if (schanCtrl & SC_CHx_MSG_SCHAN_ERR) { 222 uint32 err_code, data_len, src_port, dst_port, op_code; 223 224 schan_err = soc_pci_read(unit, CMIC_COMMON_POOL_SCHAN_CHx_ERR(ch)); 225 226 rv = SOC_E_FAIL; 227 228 if (schan_err & SC_CHx_SCHAN_ERR_ERR_BIT) { 229 rv = SOC_E_TIMEOUT; 230 LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit, 231 " block timeout: ERRBIT received in CMIC_SCHAN_ERR.\n"))); 232 } 233 234 if (schan_err & SC_CHx_SCHAN_ERR_NACK_BIT) { 235 LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit, 236 " NACK received in CMIC_SCHAN_ERR.\n"))); 237 } 238 239 /* dump error data */ 240 err_code = soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_CH0_ERRr, schan_err, ERR_CODEf); 241 data_len = soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_CH0_ERRr, schan_err, DATA_LENf); 242 src_port = soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_CH0_ERRr, schan_err, SRC_PORTf); 243 dst_port = soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_CH0_ERRr, schan_err, DST_PORTf); 244 op_code = soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_CH0_ERRr, schan_err, OP_CODEf); 245 246 LOG_ERROR(BSL_LS_SOC_SCHAN, (BSL_META_U(unit,"CMIC_SCHAN_ERR data dump: " 247 "err_code=%u, data_len=%u, src_port=%u, dst_port=%u, op_code=%u\n"), 248 err_code, data_len, src_port, dst_port, op_code)); 249 } 250 251 soc_pci_write(unit, CMIC_COMMON_POOL_SCHAN_CHx_CTRL(ch), SC_CHx_MSG_CLR); 252 } 253 254 return rv; 255 } 256 257 /******************************************* 258 * @function _soc_cmicx_schan_intr_wait 259 * purpose On CMICX chips with schan interrupts 260 * 261 * @param unit [in] unit 262 * @param ch [in] channel number 0-4 263 * 264 * @returns SOC_E_XXX 265 * @returns SOC_E_XXX 266 * 267 * Commnet: Called when CMICX chips with schan interrupts 268 * enabled, wait on a schan interrupt. 269 * When schan interrupts are disabled, 270 * _soc_cmicx_schan_poll_wait is called instead. 271 272 * @end 273 */ 274 STATIC int 275 _soc_cmicx_schan_intr_wait(int unit, int ch) 276 { 277 int rv = SOC_E_NONE; 278 uint32 schanCtrl; 279 intr_data_t *int_data; 280 281 soc_cmic_intr_enable(unit, INTR_SCHAN(ch)); 282 int_data = &_soc_cmicx_schan[unit].intr[ch]; 283 if (sal_sem_take(int_data->schanIntr, 284 SOC_CONTROL(unit)->schanTimeout) != 0) { 285 soc_cmic_intr_disable(unit, INTR_SCHAN(ch)); 286 rv = SOC_E_TIMEOUT; 287 } 288 289 if (rv != SOC_E_TIMEOUT) { 290 LOG_VERBOSE(BSL_LS_SOC_SCHAN, 291 (BSL_META_U(unit, 292 " Interrupt Done\n"))); 293 schanCtrl = soc_pci_read(unit, CMIC_COMMON_POOL_SCHAN_CHx_CTRL(ch)); 294 rv = _soc_cmicx_schan_err_handle(unit, schanCtrl, ch); 295 } 296 return rv; 297 } 298 299 /******************************************* 300 * @function _soc_cmicx_schan_poll_wait 301 * purpose On CMICX chips with no schan interrupts 302 * 303 * @param unit [in] unit 304 * @param msg [in] message <schan_msg_t> 305 * @param ch [in] channel number 0-4 306 * 307 * @returns SOC_E_XXX 308 * @returns SOC_E_XXX 309 * 310 * Commnet: Called when CMICX chips with schan interrupts 311 * disabled, wait on a schan interrupt. 312 * When schan interrupts are enabled, 313 * _soc_cmicx_schan_intr_wait is called instead. 314 315 * @end 316 */ 317 318 STATIC int 319 _soc_cmicx_schan_poll_wait(int unit, schan_msg_t *msg, int ch) 320 { 321 int rv = SOC_E_NONE; 322 soc_timeout_t to; 323 uint32 schanCtrl; 324 325 soc_timeout_init(&to, SOC_CONTROL(unit)->schanTimeout, 326 SOC_SCHAN_POLL_WAIT_TIMEOUT); 327 328 LOG_VERBOSE(BSL_LS_SOC_SCHAN, 329 (BSL_META_U(unit, 330 " Timeout= %d usec\n"), 331 SOC_CONTROL(unit)->schanTimeout)); 332 333 while (((schanCtrl = soc_pci_read(unit, CMIC_COMMON_POOL_SCHAN_CHx_CTRL(ch))) & 334 SC_CHx_MSG_DONE) == 0) { 335 if (soc_timeout_check(&to)) { 336 rv = SOC_E_TIMEOUT; 337 LOG_VERBOSE(BSL_LS_SOC_SCHAN, (BSL_META_U(unit, 338 " schan control value 0x%x after timeout in %d polls\n"), schanCtrl, to.polls)); 339 break; 340 } 341 } 342 /* Polling finished no timeout , check other errors */ 343 if (rv == SOC_E_NONE) { 344 LOG_VERBOSE(BSL_LS_SOC_SCHAN, 345 (BSL_META_U(unit, 346 " Done in %d polls\n"), to.polls)); 347 rv = _soc_cmicx_schan_err_handle(unit, schanCtrl, ch); 348 } 349 350 return rv; 351 } 352 353 /******************************************* 354 * @function _soc_cmicx_schan_wait 355 * purpose This waits for either interrupt or poll 356 * 357 * @param handle [in] unit 358 * @param msg [in] SCHAN message pointer 359 * @param dwc_write [in] Number of messages to write 360 * @param dwc_read [in] Number of messages to read 361 * @param intr [in] Interrupt 362 * @param ch [in] channel number 0-4 363 * 364 * @returns SOC_E_NONE 365 * @returns SOC_E_XXX 366 * 367 * @end 368 */ 369 370 STATIC int _soc_cmicx_schan_wait(int unit, 371 schan_msg_t *msg, 372 int dwc_write, 373 int dwc_read, 374 int intr, 375 int ch) 376 { 377 int i, rv; 378 379 LOG_VERBOSE(BSL_LS_SOC_SCHAN, 380 (BSL_META_U(unit, 381 " Enter\n"))); 382 do { 383 384 /* Wait for completion using either the interrupt or polling method */ 385 if (intr && *(SOC_SCHAN_CONTROL(unit).schanIntrEnb)) { 386 rv = _soc_cmicx_schan_intr_wait(unit, ch); 387 } else { 388 rv = _soc_cmicx_schan_poll_wait(unit, msg, ch); 389 } 390 391 if (soc_schan_timeout_check(unit, &rv, msg, -1, ch) == TRUE) { 392 break; 393 } 394 395 /* Read in data from S-Channel buffer space, if any */ 396 for (i = 0; i < dwc_read; i++) { 397 msg->dwords[i] = 398 soc_pci_read(unit, CMIC_COMMON_POOL_SCHAN_CHx_MESSAGEn(ch, i)); 399 } 400 401 if (LOG_CHECK(BSL_LS_SOC_SCHAN | BSL_VERBOSE)) { 402 soc_schan_dump(unit, msg, dwc_read); 403 } 404 405 } while(0); 406 407 if (rv == SOC_E_TIMEOUT) { 408 if (LOG_CHECK(BSL_LS_SOC_SCHAN | BSL_ERROR)) { 409 LOG_ERROR(BSL_LS_SOC_SCHAN, 410 (BSL_META_U(unit, 411 "soc_cmicx_schan_op operation timed out\n"))); 412 soc_schan_dump(unit, msg, dwc_read); 413 } 414 } 415 416 return rv; 417 } 418 419 /******************************************* 420 * @function soc_cmicx_schan_op 421 * purpose SDK-6 API used to initiate the schan operation 422 * 423 * @param handle [in] unit 424 * @param msg [in] SCHAN message pointer 425 * @param dwc_write [in] Number of messages to write 426 * @param dwc_read [in] Number of messages to read 427 * @param intr [in] Interrupt 428 * 429 * @returns SOC_E_NONE 430 * @returns SOC_E_XXX 431 * 432 * @end 433 */ 434 STATIC int 435 _soc_cmicx_schan_op( 436 int unit, 437 schan_msg_t *msg, 438 int dwc_write, 439 int dwc_read, 440 int intr) 441 442 { 443 int i, rv; 444 int ch; 445 446 LOG_VERBOSE(BSL_LS_SOC_SCHAN, 447 (BSL_META_U(unit, 448 " Enter\n"))); 449 450 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE 451 if (SOC_IS_JERICHO_2_A0(unit) && (soc_sand_is_emulation_system(unit)!= 0)) { 452 uint32 sbus_blk_id; 453 int exit_now = 0; 454 schan_header_t *header = &(msg->header); 455 sbus_blk_id = (header->v4.dst_blk << 4) |(header->v4.acc_type>>1); 456 switch(sbus_blk_id) { 457 /* core 1 doesn't exist, redirect to core 0 when reading, return OK when writing */ 458 case 97: SET_V4_HEADER_DST_BLK_TYPE(96 )/* KAPS1 */ 459 case 155: SET_V4_HEADER_DST_BLK_TYPE(36) /* IPPA1 */ 460 case 156: SET_V4_HEADER_DST_BLK_TYPE(37) /* IPPB1 */ 461 case 157: SET_V4_HEADER_DST_BLK_TYPE(38) /* IPPC1 */ 462 case 158: SET_V4_HEADER_DST_BLK_TYPE(39) /* IPPD1 */ 463 case 159: SET_V4_HEADER_DST_BLK_TYPE(40) /* IPPE1 */ 464 case 160: SET_V4_HEADER_DST_BLK_TYPE(41) /* IPPF1 */ 465 case 120: SET_V4_HEADER_DST_BLK_TYPE(51) /* CDUM1 */ 466 /* Should not be really needed */ 467 case 121: SET_V4_HEADER_DST_BLK_TYPE(53) /* CDU5 */ 468 case 122: SET_V4_HEADER_DST_BLK_TYPE(53) /* CDU6 */ 469 case 123: SET_V4_HEADER_DST_BLK_TYPE(53) /* CDU7 */ 470 case 124: SET_V4_HEADER_DST_BLK_TYPE(53) /* CDU8 */ 471 case 125: SET_V4_HEADER_DST_BLK_TYPE(53) /* CDU9 */ 472 case 151: SET_V4_HEADER_DST_BLK_TYPE(32) /* PEM4 */ 473 case 152: SET_V4_HEADER_DST_BLK_TYPE(33) /* PEM5 */ 474 case 153: SET_V4_HEADER_DST_BLK_TYPE(34) /* PEM6 */ 475 case 154: SET_V4_HEADER_DST_BLK_TYPE(35) /* PEM7 */ 476 #ifdef JR2_PREVENT_ACCESS_TO_ADDITIONAL_BLOCKS 477 case 384: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD3 */ 478 case 432: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD4 */ 479 case 480: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD5 */ 480 case 528: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD6 */ 481 case 576: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD7 */ 482 case 624: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD8 */ 483 case 672: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD9 */ 484 case 720: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD10 */ 485 case 768: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD11 */ 486 case 816: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD12 */ 487 case 864: SET_V4_HEADER_DST_BLK_TYPE(240) /* FSRD13 */ 488 case 352: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC6 */ 489 case 368: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC7 */ 490 case 400: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC8 */ 491 case 416: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC9 */ 492 case 448: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC10 */ 493 case 464: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC11 */ 494 case 496: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC12 */ 495 case 512: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC13 */ 496 case 544: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC14 */ 497 case 560: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC15 */ 498 case 592: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC16 */ 499 case 608: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC17 */ 500 case 640: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC18 */ 501 case 656: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC19 */ 502 case 688: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC20 */ 503 case 704: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC21 */ 504 case 736: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC22 */ 505 case 752: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC23 */ 506 case 784: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC24 */ 507 case 800: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC25 */ 508 case 832: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC26 */ 509 case 848: SET_V4_HEADER_DST_BLK_TYPE(208) /* FMAC27 */ 510 case 1792: SET_V4_HEADER_DST_BLK_TYPE(1072) /* CDMAC12, CDMAC13, CDPORT6 */ 511 case 1808: SET_V4_HEADER_DST_BLK_TYPE(1072) /* CDMAC14, CDMAC15, CDPORT7 */ 512 case 1824: SET_V4_HEADER_DST_BLK_TYPE(1072) /* CDMAC16, CDMAC17, CDPORT8 */ 513 case 1840: SET_V4_HEADER_DST_BLK_TYPE(1072) /* CDMAC18, CDMAC19, CDPORT9 */ 514 case 1856: SET_V4_HEADER_DST_BLK_TYPE(1072) /* CDMAC20, CDMAC20, CDPORT10 */ 515 case 1872: SET_V4_HEADER_DST_BLK_TYPE(1072) /* CDMAC22, CDMAC23, CDPORT11 */ 516 #endif /* JR2_PREVENT_ACCESS_TO_ADDITIONAL_BLOCKS */ 517 case 99: SET_V4_HEADER_DST_BLK_TYPE(98) /* TCAM1 */ 518 case 131: SET_V4_HEADER_DST_BLK_TYPE(68) /* IQM1 */ 519 case 161: SET_V4_HEADER_DST_BLK_TYPE(42) /* ITPPD1 */ 520 case 162: SET_V4_HEADER_DST_BLK_TYPE(43) /* ITPP1 */ 521 case 164: SET_V4_HEADER_DST_BLK_TYPE(45) /* ETPPA1 */ 522 case 165: SET_V4_HEADER_DST_BLK_TYPE(46) /* ETPPB1 */ 523 case 166: SET_V4_HEADER_DST_BLK_TYPE(47) /* ETPPC1 */ 524 case 163: SET_V4_HEADER_DST_BLK_TYPE(44) /* ERPP1 */ 525 case 150: SET_V4_HEADER_DST_BLK_TYPE(31) /* EDB1 */ 526 case 132: SET_V4_HEADER_DST_BLK_TYPE(69) /* DQM1 */ 527 case 136: SET_V4_HEADER_DST_BLK_TYPE(17) /* CRPS1 */ 528 case 127: SET_V4_HEADER_DST_BLK_TYPE(64) /* MRPS1 */ 529 case 143: SET_V4_HEADER_DST_BLK_TYPE(24) /* EPNI1 */ 530 case 144: SET_V4_HEADER_DST_BLK_TYPE(25) /* EPRE1 */ 531 case 145: SET_V4_HEADER_DST_BLK_TYPE(26) /* ECGM1 */ 532 case 139: SET_V4_HEADER_DST_BLK_TYPE(20) /* CGM1 */ 533 case 141: SET_V4_HEADER_DST_BLK_TYPE(22) /* FDR1 */ 534 case 129: SET_V4_HEADER_DST_BLK_TYPE(66) /* MCP1 */ 535 case 881: SET_V4_HEADER_DST_BLK_TYPE(880) /* OCB1 */ 536 case 118: SET_V4_HEADER_DST_BLK_TYPE(48) /* ILE1 */ 537 case 167: SET_V4_HEADER_DST_BLK_TYPE(63) /* SCH1 */ 538 case 138: SET_V4_HEADER_DST_BLK_TYPE(19) /* IPT1 */ 539 case 137: SET_V4_HEADER_DST_BLK_TYPE(18) /* IPS1 */ 540 case 134: SET_V4_HEADER_DST_BLK_TYPE(71) /* IRE1 */ 541 case 119: SET_V4_HEADER_DST_BLK_TYPE(49) /* NMG1 */ 542 case 149: SET_V4_HEADER_DST_BLK_TYPE(30) /* EPS1 */ 543 case 148: SET_V4_HEADER_DST_BLK_TYPE(29) /* FQP1 */ 544 case 146: SET_V4_HEADER_DST_BLK_TYPE(27) /* RQP1 */ 545 case 147: SET_V4_HEADER_DST_BLK_TYPE(28) /* PQP1 */ 546 case 133: SET_V4_HEADER_DST_BLK_TYPE(70) /* SQM1 */ 547 case 135: SET_V4_HEADER_DST_BLK_TYPE(16) /* SPB1 */ 548 case 128: SET_V4_HEADER_DST_BLK_TYPE(65) /* DDP1 */ 549 case 130: SET_V4_HEADER_DST_BLK_TYPE(67) /* PDM1 */ 550 case 140: SET_V4_HEADER_DST_BLK_TYPE(21) /* BDM1 */ 551 case 126: SET_V4_HEADER_DST_BLK_TYPE(62) /* SIF1 */ 552 default: 553 break; 554 } 555 if (exit_now) { 556 return SOC_E_NONE; 557 } 558 } 559 #endif /* defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE */ 560 561 if (soc_schan_op_sanity_check(unit, msg, 562 dwc_write, dwc_read, &rv) == TRUE) { 563 return rv; 564 } 565 566 /* Get the free channel */ 567 rv = _soc_cmicx_schan_get(unit, &ch); 568 569 if (rv != SOC_E_NONE) { 570 LOG_ERROR(BSL_LS_SOC_SCHAN, 571 (BSL_META_U(unit, 572 " Unable to assign channel\n"))); 573 return rv; 574 575 } 576 577 LOG_VERBOSE(BSL_LS_SOC_SCHAN, 578 (BSL_META_U(unit, 579 " Assign channel = %d\n"), ch)); 580 581 do { 582 /* Write raw S-Channel Data: dwc_write words */ 583 for (i = 0; i < dwc_write; i++) { 584 soc_pci_write(unit, CMIC_COMMON_POOL_SCHAN_CHx_MESSAGEn(ch, i), 585 msg->dwords[i]); 586 } 587 588 /* Tell CMIC to start */ 589 soc_pci_write(unit, CMIC_COMMON_POOL_SCHAN_CHx_CTRL(ch), 590 SC_CHx_MSG_START); 591 } while(0); 592 593 rv = _soc_cmicx_schan_wait(unit, msg, dwc_write, dwc_read, intr, ch); 594 595 _soc_cmicx_schan_put(unit, ch); 596 597 return rv; 598 } 599 600 /******************************************* 601 * @function _cmicx_schan_ch_done 602 * Interrupt handler for schan channel done 603 * 604 * @param unit [in] unit 605 * @param data [in] pointer provided during registration 606 * 607 * 608 * @end 609 */ 610 STATIC void 611 _cmicx_schan_ch_done(int unit, void *data) 612 { 613 soc_control_t *soc = SOC_CONTROL(unit); 614 intr_data_t *in_d = (intr_data_t *)data; 615 616 if (soc->schanIntrEnb) { 617 soc_cmic_intr_disable(unit, INTR_SCHAN(in_d->ch)); 618 sal_sem_give(in_d->schanIntr); 619 } 620 } 621 622 /******************************************* 623 * @function _cmicx_schan_intr_deinit 624 * purpose API to de-Initialize SCHAN interrupts 625 * 626 * @param unit [in] unit 627 * 628 * @returns SOC_E_NONE 629 * @returns SOC_E_XXX 630 * 631 * @end 632 */ 633 STATIC int 634 _cmicx_schan_intr_deinit(int unit) 635 { 636 int ch; 637 intr_data_t *int_data; 638 for (ch = 0; ch < CMIC_SCHAN_NUM_MAX; ch++) { 639 int_data = &_soc_cmicx_schan[unit].intr[ch]; 640 if (int_data->schanIntr) { 641 sal_sem_destroy(int_data->schanIntr); 642 } 643 } 644 645 return SOC_E_NONE; 646 } 647 648 /******************************************* 649 * @function _cmicx_schan_intr_init 650 * purpose API to Initialize SCHAN interrupts 651 * 652 * @param unit [in] unit 653 * 654 * @returns SOC_E_NONE 655 * @returns SOC_E_XXX 656 * 657 * @end 658 */ 659 STATIC int 660 _cmicx_schan_intr_init(int unit) 661 { 662 int ch; 663 soc_cmic_intr_handler_t *handle; 664 soc_cmic_intr_handler_t *hitr; 665 intr_data_t *int_data; 666 int rv = SOC_E_NONE; 667 668 669 /* Register interrupts */ 670 handle = sal_alloc(CMIC_SCHAN_NUM_MAX * sizeof(soc_cmic_intr_handler_t), 671 "schan_interrupt"); 672 if (handle == NULL) { 673 return SOC_E_MEMORY; 674 } 675 676 hitr = handle; 677 for (ch = 0; ch < CMIC_SCHAN_NUM_MAX; ch++) { 678 int_data = &_soc_cmicx_schan[unit].intr[ch]; 679 int_data->schanIntr = 680 sal_sem_create("SCHAN interrupt", 681 sal_sem_BINARY, 0); 682 if (int_data->schanIntr == NULL) { 683 _cmicx_schan_intr_deinit(unit); 684 rv = SOC_E_MEMORY; 685 goto error; 686 } 687 int_data->ch = ch; 688 hitr->num = INTR_SCHAN(ch); 689 hitr->intr_fn = _cmicx_schan_ch_done; 690 hitr->intr_data = int_data; 691 hitr++; 692 } 693 rv = soc_cmic_intr_register(unit, handle, CMIC_SCHAN_NUM_MAX); 694 error: 695 sal_free(handle); 696 697 return rv; 698 } 699 700 701 /******************************************* 702 * @function _soc_cmicx_schan_deinit 703 * purpose API to de-Initialize SCHAN 704 * 705 * @param unit [in] unit 706 * 707 * @returns SOC_E_NONE 708 * @returns SOC_E_XXX 709 * 710 * @end 711 */ 712 STATIC int 713 _soc_cmicx_schan_deinit(int unit) 714 { 715 int ch; 716 717 _cmicx_schan_intr_deinit(unit); 718 719 /* reset all th schan channels */ 720 for (ch = 0 ; ch < CMIC_SCHAN_NUM_MAX; ch++) { 721 _soc_cmicx_schan_reset(unit, -1, ch); 722 } 723 sal_spinlock_destroy(_soc_cmicx_schan[unit].lock); 724 725 return SOC_E_NONE; 726 } 727 728 /******************************************* 729 * @function soc_cmicx_schan_init 730 * purpose API to Initialize cmicx SCHAN 731 * 732 * @param unit [in] unit 733 * @param drv [out] soc_cmic_schan_drv_t pointer 734 * 735 * @returns SOC_E_NONE 736 * @returns SOC_E_XXX 737 * 738 * @end 739 */ 740 int soc_cmicx_schan_init(int unit, soc_cmic_schan_drv_t *drv) 741 742 { 743 int rv = SOC_E_NONE; 744 745 #if defined(PLISIM) && (defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)) 746 if (SAL_BOOT_PLISIM && (SOC_IS_DNX(unit)|| SOC_IS_DNXF(unit))) { 747 /* Use CMICM simulation instead of CMICX simulation */ 748 return soc_cmicm_schan_init(unit, drv); 749 } 750 #endif 751 752 sal_memset(&_soc_cmicx_schan[unit], 0, sizeof(soc_cmicx_schan_t)); 753 _soc_cmicx_schan[unit].lock = sal_spinlock_create("schan Lock"); 754 755 if (_soc_cmicx_schan[unit].lock == NULL) { 756 return SOC_E_MEMORY; 757 } 758 759 _soc_cmicx_schan[unit].ch_map = (0x01 << CMIC_SCHAN_NUM_MAX) -1; 760 _soc_cmicx_schan[unit].timeout = SOC_CONTROL(unit)->schanTimeout; 761 /* program SBUS_RING_MAP registers */ 762 763 /* Program SCHAN ARB Weighted priority 764 * CMIC_TOP_SBUS_RING_ARB_CTRL_SCHAN_BASE 12'h04c */ 765 766 /* Configure CMIC_SBUS_TIMEOUT */ 767 rv = _cmicx_schan_intr_init(unit); 768 769 if (SOC_FAILURE(rv)) { 770 _soc_cmicx_schan_deinit(unit); 771 return rv; 772 } 773 774 drv->soc_schan_deinit = _soc_cmicx_schan_deinit; 775 drv->soc_schan_op = _soc_cmicx_schan_op; 776 drv->soc_schan_reset = _soc_cmicx_schan_reset; 777 778 return rv; 779 } 780 781 782 #endif /* BCM_CMICX_SUPPORT */