cmicx_schan_fifo.c (33292B)
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 * CMCIX SCHAN FIFO low level driver 8 */ 9 10 #include <shared/bsl.h> 11 #include <sal/core/libc.h> 12 #include <sal/core/boot.h> 13 #include <soc/drv.h> 14 #include <soc/debug.h> 15 #include <soc/cm.h> 16 #include <soc/error.h> 17 #include <sal/core/sync.h> 18 #include <soc/soc_schan_fifo_internal.h> 19 #include <soc/ccmdma.h> 20 21 #ifdef BCM_CMICX_SUPPORT 22 #include <soc/cmicx.h> 23 #include <soc/intr_cmicx.h> 24 #include <soc/schanmsg.h> 25 26 /* CMIC base address */ 27 #define CMIC_BASE_ADDR 0x3200000 28 #define HX5_CMIC_BASE_ADDR 0x10100000 29 30 /* This structure is used for the SCHAN FIFO interrupt control */ 31 32 typedef enum { 33 CHAN_FREE = 0, 34 CHAN_CMD, 35 CHAN_PROG, 36 CHAN_EXEC 37 }schan_state_t; 38 39 typedef struct soc_schan_fifo_ch_s { 40 sal_sem_t schanIntr; 41 int ch; 42 schan_state_t state; 43 }soc_schan_fifo_ch_t; 44 45 /* This struture is used for SCHAN FIFO driver control */ 46 typedef struct soc_schan_fifo_control_s { 47 int ch_map; 48 sal_spinlock_t lock; /* used in channel selection */ 49 int num; 50 soc_schan_fifo_ch_t chan[CMIC_SCHAN_FIFO_NUM_MAX]; 51 uint16 *summary_buff[CMIC_SCHAN_FIFO_NUM_MAX]; 52 soc_schan_fifo_config_t config; 53 }soc_schan_fifo_control_t; 54 55 STATIC soc_schan_fifo_control_t _soc_cmicx_schan_fifo[SOC_MAX_NUM_DEVICES]; 56 #define SOC_SCHAN_FIFO_CONTROL(unit) (&_soc_cmicx_schan_fifo[unit]) 57 58 59 /* 60 * Dump SCHAN FIFO message for debugging 61 */ 62 63 STATIC void 64 _soc_cmicx_schan_fifo_dump(int unit, schan_fifo_cmd_t *cmd, int size) 65 { 66 int i; 67 68 for (i = 0 ; i < size; i++) { 69 LOG_CLI((BSL_META_U(unit, 70 " DW[%2d]=0x%08x"), i, ((uint32 *)cmd)[i])); 71 } 72 } 73 74 /******************************************* 75 * @function _soc_cmicx_schan_fifo_chstate_get 76 * purpose: Get channel state 77 * 78 * @param unit [in] unit # 79 * @param ch [in] channel number 0-1 80 * 81 * @returns SOC_E_BUSY 82 * @returns SOC_E_NONE 83 * 84 * @end 85 */ 86 STATIC schan_state_t 87 _soc_cmicx_schan_fifo_chstate_get(int unit, int ch) 88 { 89 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 90 91 return schan_fifo->chan[ch].state; 92 } 93 94 /******************************************* 95 * @function _soc_cmicx_schan_fifo_chstate_set 96 * purpose: Set channel state 97 * 98 * @param unit [in] unit # 99 * @param ch [in] channel number 0-1 100 * 101 * @returns SOC_E_BUSY 102 * @returns SOC_E_NONE 103 * 104 * @end 105 */ 106 STATIC void 107 _soc_cmicx_schan_fifo_chstate_set(int unit, int ch, schan_state_t st) 108 { 109 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 110 111 schan_fifo->chan[ch].state = st; 112 113 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 114 (BSL_META_U(unit, 115 "channel = %d, state = %d\n"), 116 ch, st)); 117 118 } 119 120 /******************************************* 121 * @function _soc_cmicx_schan_fifo_ch_start 122 * purpose: Start the channel 123 * 124 * @param unit [in] unit # 125 * @param ch [in] channel number 0-1 126 * 127 * @returns SOC_E_BUSY 128 * @returns SOC_E_NONE 129 * 130 * @end 131 */ 132 STATIC void 133 _soc_cmicx_schan_fifo_ch_start(int unit, int ch) 134 { 135 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 136 soc_schan_fifo_config_t *cfg = &schan_fifo->config; 137 uint32 val; 138 139 val = soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch)); 140 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 141 &val, STARTf, 1); 142 if (cfg->intrEnb) { 143 soc_cmic_intr_enable(unit, INTR_SCHAN_FIFO(ch)); 144 } 145 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 146 (BSL_META_U(unit, 147 "CMIC_SCHAN_FIFO_CHx_CTRL= 0x%x\n"), val)); 148 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch), val); 149 _soc_cmicx_schan_fifo_chstate_set(unit, ch, CHAN_EXEC); 150 } 151 152 /******************************************* 153 * @function _soc_cmicx_schan_fifo_ch_stop 154 * purpose: Stop the channel 155 * 156 * @param unit [in] unit # 157 * @param ch [in] channel number 0-1 158 * 159 * @returns SOC_E_BUSY 160 * @returns SOC_E_NONE 161 * 162 * @end 163 */ 164 STATIC void 165 _soc_cmicx_schan_fifo_ch_stop(int unit, int ch) 166 { 167 uint32 val; 168 169 val = soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch)); 170 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 171 &val, STARTf, 0); 172 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch), val); 173 _soc_cmicx_schan_fifo_chstate_set(unit, ch, CHAN_FREE); 174 } 175 176 177 /******************************************* 178 * @function _soc_cmicx_schan_fifo_get 179 * purpose get idle channel 180 * 181 * @param unit [in] unit # 182 * @param ch [out] channel number 0-1 183 * 184 * @returns SOC_E_BUSY 185 * @returns SOC_E_NONE 186 * 187 * @end 188 */ 189 STATIC int _soc_cmicx_schan_fifo_get(int unit, int *ch) 190 { 191 int i; 192 int rv = SOC_E_BUSY; 193 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 194 soc_schan_fifo_config_t *cfg = &schan_fifo->config; 195 soc_timeout_t to; 196 197 soc_timeout_init(&to, cfg->timeout, 100); 198 199 do { 200 sal_spinlock_lock(schan_fifo->lock); 201 for ( i = 0; i < CMIC_SCHAN_FIFO_NUM_MAX; i++) { 202 if (schan_fifo->ch_map & 0x01 << i) { 203 rv = SOC_E_NONE; 204 *ch = i; 205 schan_fifo->ch_map &= ~(0x01 << i); 206 break; 207 } 208 } 209 sal_spinlock_unlock(schan_fifo->lock); 210 if (rv == SOC_E_NONE) 211 break; 212 213 } while (!soc_timeout_check(&to)); 214 return rv; 215 } 216 217 /******************************************* 218 * @function _soc_cmicx_schan_fifo_put 219 * purpose get idle channel 220 * 221 * @param unit [in] unit # 222 * @param ch [in] channel number 0-1 223 * 224 * @returns SOC_E_PARAM 225 * @returns SOC_E_NONE 226 227 * 228 * @end 229 */ 230 STATIC int _soc_cmicx_schan_fifo_put(int unit, int ch) 231 { 232 int rv = SOC_E_NONE; 233 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 234 235 if ((ch < 0) || (ch > CMIC_SCHAN_FIFO_NUM_MAX - 1)) { 236 rv = SOC_E_PARAM; 237 return rv; 238 } 239 sal_spinlock_lock(schan_fifo->lock); 240 schan_fifo->ch_map |= (0x01 << ch); 241 sal_spinlock_unlock(schan_fifo->lock); 242 243 return rv; 244 } 245 246 /******************************************* 247 * @function _soc_cmicx_schan_fifo_cmic_err_handle 248 * purpose Handle schan cimicx error 249 * 250 * @param unit [in] unit 251 * @param schanStat [in] schan channel status 252 * @param ch [in] channel 253 * 254 * @returns SOC_E_XXX 255 * @returns SOC_E_NONE 256 * 257 * @end 258 */ 259 260 STATIC int 261 _soc_cmicx_schan_fifo_err_handle(int unit, uint32 schanStat, int ch) 262 { 263 uint32 num; 264 uint32 reg; 265 266 if (!soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 267 schanStat, ERRORf)) { 268 return SOC_E_NONE; 269 } 270 271 num = soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 272 schanStat, CURR_SBUS_CMD_NUMf); 273 274 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 275 "ch = %d , cmd num = %u\n"), ch, num)); 276 277 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 278 schanStat, ERR_TYPE_AXI_SLAVE_ABORTf)) { 279 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 280 "Axi Slave Abort.\n"))); 281 } 282 283 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 284 schanStat, ERR_TYPE_AXI_RESP_ERRf)) { 285 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 286 "AXI response error.\n"))); 287 } 288 289 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 290 schanStat, ERR_TYPE_ACK_DATA_BEAT_GT20f)) { 291 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 292 "Data beats was greater than 20.\n"))); 293 } 294 295 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 296 schanStat, ERR_TYPE_SBUS_TIMEOUTf)) { 297 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 298 "SBUS Transaction timed out.\n"))); 299 } 300 301 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 302 schanStat, ERR_TYPE_CMD_DLEN_IS_INVALIDf)) { 303 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 304 "SBUS Command DLEN is invalid.\n"))); 305 } 306 307 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 308 schanStat, ERR_TYPE_CMD_OPCODE_IS_INVALIDf)) { 309 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 310 "SBUS Command OPCODE is invalid.\n"))); 311 } 312 313 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 314 schanStat, ERR_TYPE_RESP_MEM_ECC_ERRf)) { 315 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 316 "ECC error was received from Response Memory.\n"))); 317 } 318 319 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 320 schanStat, ERR_TYPE_CMD_MEM_ECC_ERRf)) { 321 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 322 "ECC error was received from command Memory.\n"))); 323 } 324 325 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 326 schanStat, ERR_TYPE_ACK_OPCODE_MISMATCHf)) { 327 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 328 "ACK Opcode received was not proper.\n"))); 329 } 330 331 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 332 schanStat, ERR_TYPE_MESSAGE_ERR_CODEf)) { 333 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 334 "Message error code.\n"))); 335 } 336 337 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 338 schanStat, ERR_TYPE_MESSAGE_ERRf)) { 339 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 340 "Message error was received.\n"))); 341 } 342 343 if (soc_reg_field_get(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_STATUSr, 344 schanStat, ERR_TYPE_NACKf)) { 345 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 346 "NACK was received .\n"))); 347 } 348 349 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 350 "SCHAN FIFO STATUS = 0x%x\n"), schanStat)); 351 352 reg = soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch)); 353 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 354 "SCHAN FIFO CTRL = 0x%x\n"), reg)); 355 356 reg= soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_RESP_ADDR_LOWER(ch)); 357 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 358 "SCHAN FIFO RESP ADDR LOWER = 0x%x\n"), reg)); 359 360 reg= soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_RESP_ADDR_UPPER(ch)); 361 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 362 "SCHAN FIFO RESP ADDR UPPER = 0x%x\n"), reg)); 363 364 reg= soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_SUMMARY_ADDR_LOWER(ch)); 365 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 366 "SCHAN FIFO SUMMARY ADDR LOWER = 0x%x\n"), reg)); 367 368 reg= soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_SUMMARY_ADDR_UPPER(ch)); 369 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, (BSL_META_U(unit, 370 "SCHAN FIFO SUMMARY ADDR UPPER = 0x%x\n"), reg)); 371 372 return SOC_E_FAIL; 373 } 374 375 /******************************************* 376 * @function _soc_cmicx_schan_fifo_intr_wait 377 * purpose On CMICX chips with schan interrupts 378 * 379 * @param unit [in] unit 380 * @param ch [in] channel number 0-4 381 * 382 * @returns SOC_E_XXX 383 * @returns SOC_E_XXX 384 * 385 * Commnet: Called when CMICX chips with schan interrupts 386 * enabled, wait on a schan interrupt. 387 * When schan interrupts are disabled, 388 * _soc_cmicx_schan_fifo_poll_wait is called instead. 389 390 * @end 391 */ 392 STATIC int 393 _soc_cmicx_schan_fifo_intr_wait(int unit, int ch) 394 { 395 int rv = SOC_E_NONE; 396 uint32 schanStat; 397 soc_schan_fifo_ch_t *int_data; 398 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 399 soc_schan_fifo_config_t *cfg = &schan_fifo->config; 400 401 int_data = &schan_fifo->chan[ch]; 402 if (sal_sem_take(int_data->schanIntr, 403 cfg->timeout) != 0) { 404 rv = SOC_E_TIMEOUT; 405 } 406 407 if (rv != SOC_E_TIMEOUT) { 408 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 409 (BSL_META_U(unit, 410 " Interrupt Done\n"))); 411 schanStat = soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_STATUS(ch)); 412 rv = _soc_cmicx_schan_fifo_err_handle(unit, schanStat, ch); 413 } 414 415 return rv; 416 } 417 418 /******************************************* 419 * @function _soc_cmicx_schan_fifo_poll_wait 420 * purpose On CMICX chips with no schan interrupts 421 * 422 * @param unit [in] unit 423 * @param msg [in] message <schan_msg_t> 424 * @param ch [in] channel number 0-4 425 * 426 * @returns SOC_E_XXX 427 * @returns SOC_E_XXX 428 * 429 * Commnet: Called when CMICX chips with schan interrupts 430 * disabled, wait on a schan interrupt. 431 * When schan interrupts are enabled, 432 * _soc_cmicx_schan_fifo_intr_wait is called instead. 433 434 * @end 435 */ 436 437 STATIC int 438 _soc_cmicx_schan_fifo_poll_wait(int unit, int ch) 439 { 440 int rv = SOC_E_NONE; 441 soc_timeout_t to; 442 uint32 schanStat; 443 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 444 soc_schan_fifo_config_t *cfg = &schan_fifo->config; 445 446 soc_timeout_init(&to, cfg->timeout, 100); 447 448 while (((schanStat = 449 soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_STATUS(ch))) & 450 SCHAN_FIFO_MSG_DONE) == 0) { 451 if (soc_timeout_check(&to)) { 452 rv = SOC_E_TIMEOUT; 453 } 454 } 455 /* Polling finished no timeout , check other errors */ 456 if (rv == SOC_E_NONE) { 457 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 458 (BSL_META_U(unit, 459 " Done in %d polls\n"), to.polls)); 460 rv = _soc_cmicx_schan_fifo_err_handle(unit, schanStat, ch); 461 } 462 463 return rv; 464 } 465 /******************************************* 466 * @function _soc_cmicx_schan_fifo_abort 467 * purposeResets the CMICX S-Channel interface. 468 * 469 * @param unit [in] unit # 470 * @param ch [in] channel number 0-1 471 * 472 * @returns SOC_E_BUSY 473 * @returns SOC_E_NONE 474 * 475 * @end 476 */ 477 STATIC void 478 _soc_cmicx_schan_fifo_abort(int unit, int ch) 479 { 480 481 uint32 val; 482 483 /* Skip abort if no schan fifo operation is in progress */ 484 if (((soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_STATUS(ch))) & 485 SCHAN_FIFO_MSG_DONE) == 0) { 486 return; 487 } 488 489 val = soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch)); 490 /* Toggle S-Channel abort bit in control register */ 491 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 492 &val, STARTf, 1); 493 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 494 &val, ABORTf, 1); 495 SDK_CONFIG_MEMORY_BARRIER; 496 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch), val); 497 SDK_CONFIG_MEMORY_BARRIER; 498 499 if (SAL_BOOT_QUICKTURN) { 500 /* Give Quickturn at least 2 cycles */ 501 sal_usleep(10 * MILLISECOND_USEC); 502 } 503 504 /* Wait for Abort to finish */ 505 if (SOC_FAILURE(_soc_cmicx_schan_fifo_poll_wait(unit, ch))) { 506 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, 507 (BSL_META_U(unit,"Abort of channel [%d] Failed\n"), ch)); 508 } 509 } 510 511 512 /******************************************* 513 * @function _soc_cmicx_schan_fifo_control 514 * purpose API to control SCHAN FIFO 515 * 516 * @param unit [in] unit 517 * @param ctl [in] schan_fifo_ctl_t 518 * @param data [in, out] pointer to int 519 * 520 * @returns SOC_E_NONE 521 * 522 * @end 523 */ 524 STATIC int 525 _soc_cmicx_schan_fifo_control(int unit, 526 schan_fifo_ctl_t ctl, void *data) 527 { 528 int rv = SOC_E_NONE; 529 schan_fifo_alloc_t *alloc; 530 531 switch (ctl) { 532 case CTL_FIFO_ABORT: 533 _soc_cmicx_schan_fifo_abort(unit, 0); 534 _soc_cmicx_schan_fifo_abort(unit, 1); 535 break; 536 537 case CTL_FIFO_MAX_MSG_GET: 538 *(int *)data = CMIC_SCHAN_FIFO_CMD_SIZE_MAX; 539 break; 540 case CTL_FIFO_RESP_ALLOC: 541 alloc = (schan_fifo_alloc_t *)data; 542 if ((alloc != NULL) && (alloc->num > 0)) { 543 alloc->resp = soc_cm_salloc(unit, 544 (sizeof(schan_fifo_resp_t) * alloc->num), 545 "schan_fifo_response"); 546 if (alloc->resp == NULL) { 547 rv = SOC_E_MEMORY; 548 } 549 } else { 550 rv = SOC_E_PARAM; 551 } 552 break; 553 case CTL_FIFO_RESP_FREE: 554 if (data != NULL) { 555 soc_cm_sfree(unit, data); 556 } else { 557 rv = SOC_E_PARAM; 558 } 559 break; 560 default: 561 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 562 (BSL_META_U(unit,":undefined command = %d\n"), ctl)); 563 rv = SOC_E_PARAM; 564 break; 565 } 566 567 return rv; 568 } 569 570 /******************************************* 571 * @function _soc_cmicx_schan_fifo_resp_config 572 * purpose Read response buffer configuration 573 * 574 * @param unit [in] unit 575 * @param ch [in] channel number 0-1 576 * @param msg [out] SCHAN FIFO message pointer 577 * 578 * @returns SOC_E_NONE 579 * @returns SOC_E_XXX 580 * 581 * @end 582 */ 583 STATIC int 584 _soc_cmicx_schan_fifo_resp_config( 585 int unit, 586 int ch, 587 soc_schan_fifo_msg_t *msg, 588 uint32 *val) 589 { 590 /* Set up Response Register */ 591 if (msg->resp != NULL) { 592 /* write response Lo address */ 593 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_RESP_ADDR_LOWER(ch), 594 PTR_TO_INT(soc_cm_l2p(unit, msg->resp))); 595 /* write response Hi address */ 596 if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) { 597 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_RESP_ADDR_UPPER(ch), 598 (PTR_HI_TO_INT(soc_cm_l2p(unit, msg->resp)) | 599 CMIC_PCIE_SO_OFFSET)); 600 } else { 601 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_RESP_ADDR_UPPER(ch), 602 PTR_HI_TO_INT(soc_cm_l2p(unit, msg->resp))); 603 } 604 605 /* Enable the response write */ 606 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 607 val, RESPONSE_WRITE_DISABLEf, 0); 608 } else { 609 /* disable the response write */ 610 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 611 val, RESPONSE_WRITE_DISABLEf, 1); 612 } 613 614 return SOC_E_NONE; 615 } 616 617 /******************************************* 618 * @function _soc_cmicx_schan_fifo_cmd_complete 619 * purpose wait for command transfer via CCMDMA 620 * 621 * @param unit [in] unit 622 * @param ch [in] channel number 0-1 623 * @param msg [out] SCHAN FIFO message pointer 624 * 625 * @returns SOC_E_NONE 626 * @returns SOC_E_XXX 627 * 628 * @end 629 */ 630 STATIC int 631 _soc_cmicx_schan_fifo_cmd_complete( 632 int unit, 633 int ch) 634 { 635 int rv = SOC_E_NONE; 636 schan_state_t state; 637 638 state = _soc_cmicx_schan_fifo_chstate_get(unit, ch); 639 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 640 (BSL_META_U(unit, 641 " channel = %d, State = %d\n"), ch, state)); 642 643 switch(state) { 644 case CHAN_CMD: 645 #ifdef BCM_CCMDMA_SUPPORT 646 rv = soc_ccmdma_copy_wait(unit, ch); 647 #endif 648 if (rv == SOC_E_NONE) { 649 _soc_cmicx_schan_fifo_chstate_set(unit, ch, CHAN_PROG); 650 } else { 651 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, 652 (BSL_META_U(unit,"Error in CCMDMA command = %d\n"), rv)); 653 return rv; 654 } 655 state = CHAN_PROG; 656 _soc_cmicx_schan_fifo_ch_start(unit, ch); 657 break; 658 case CHAN_PROG: 659 _soc_cmicx_schan_fifo_ch_start(unit, ch); 660 break; 661 default: 662 return rv; 663 } 664 665 return rv; 666 667 } 668 669 /******************************************* 670 * @function _soc_cmicx_schan_fifo_op_complete 671 * purpose This waits for either interrupt or poll 672 * 673 * @param handle [in] unit 674 * @param msg [in] SCHAN message pointer 675 * @param dwc_write [in] Number of messages to write 676 * @param dwc_read [in] Number of messages to read 677 * @param intr [in] Interrupt 678 * @param ch [in] channel number 0-4 679 * 680 * @returns SOC_E_NONE 681 * @returns SOC_E_XXX 682 * 683 * @end 684 */ 685 686 STATIC int _soc_cmicx_schan_fifo_op_complete(int unit, 687 void *data, void *wparam) 688 { 689 int rv = SOC_E_NONE; 690 int ch = ((soc_schan_fifo_wparam_t *)wparam)->ch; 691 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 692 soc_schan_fifo_config_t *cfg = &schan_fifo->config; 693 694 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 695 (BSL_META_U(unit, 696 " Enter: _soc_cmicx_schan_fifo_op_complete\n"))); 697 698 /* Current channel program is complete */ 699 _soc_cmicx_schan_fifo_cmd_complete(unit, ch); 700 /*Set to start the other channel */ 701 _soc_cmicx_schan_fifo_cmd_complete(unit, (ch ^ 1)); 702 703 do { 704 /* Wait for completion using either the interrupt or polling method */ 705 if (cfg->intrEnb) { 706 rv = _soc_cmicx_schan_fifo_intr_wait(unit, ch); 707 } else { 708 rv = _soc_cmicx_schan_fifo_poll_wait(unit, ch); 709 } 710 711 if (rv != SOC_E_NONE) { 712 break; 713 } 714 } while(0); 715 716 if (rv == SOC_E_TIMEOUT) { 717 /* Abort the curent operation */ 718 _soc_cmicx_schan_fifo_abort(unit, ch); 719 } 720 /* Release the channel */ 721 _soc_cmicx_schan_fifo_ch_stop(unit, ch); 722 _soc_cmicx_schan_fifo_put(unit, ch); 723 724 return rv; 725 } 726 727 /******************************************* 728 * @function _soc_cmicx_schan_fifo_op_prog 729 * purpose initiate the schan FIFO operation 730 * 731 * @param handle [in] unit 732 * @param data [in] SCHAN message pointer 733 * @param wparam [in, out] message parameter 734 * 735 * @returns SOC_E_NONE 736 * @returns SOC_E_XXX 737 * 738 * @end 739 */ 740 STATIC int 741 _soc_cmicx_schan_fifo_op_prog( 742 int unit, 743 void *data, void *wparam) 744 745 { 746 int rv = SOC_E_NONE; 747 soc_schan_fifo_msg_t *msg = (soc_schan_fifo_msg_t *)data; 748 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 749 int ch, i; 750 uint32 val; 751 #ifdef BCM_CCMDMA_SUPPORT 752 sal_paddr_t *baddr; 753 #endif 754 755 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 756 (BSL_META_U(unit, 757 " Enter: _soc_cmicx_schan_fifo_op_prog\n"))); 758 759 /* Get the free channel */ 760 rv = _soc_cmicx_schan_fifo_get(unit, &ch); 761 762 if (rv != SOC_E_NONE) { 763 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, 764 (BSL_META_U(unit, 765 " Unable to assign channel\n"))); 766 return rv; 767 768 } 769 770 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 771 (BSL_META_U(unit, 772 "channel = %d, commands = %d, size =%u\n"), 773 ch, msg->num, (unsigned int)msg->size)); 774 ((soc_schan_fifo_wparam_t *)wparam)->ch = ch; 775 776 /* Wait for cmd program to complete or start the other channel if programmed */ 777 _soc_cmicx_schan_fifo_cmd_complete(unit, (ch ^ 1)); 778 779 if (LOG_CHECK(BSL_LS_SOC_SCHAN | BSL_VERBOSE)) { 780 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 781 (BSL_META_U(unit, 782 "SCHANFIFO %s: (unit %d)\n"), 783 soc_schan_op_name(msg->cmd->header.v4.opcode), unit)); 784 _soc_cmicx_schan_fifo_dump(unit, msg->cmd, msg->size); 785 } 786 787 if (schan_fifo->config.dma == 1) { 788 #ifdef BCM_CCMDMA_SUPPORT 789 #ifdef BCM_HELIX5_SUPPORT 790 if (SOC_IS_HELIX5(unit)) 791 { 792 #ifdef PTRS_ARE_64BITS 793 baddr = (sal_paddr_t *)((uint64)HX5_CMIC_BASE_ADDR + 794 CMIC_SCHAN_FIFO_CHx_COMMAND(ch, 0)); 795 #else 796 baddr = (sal_paddr_t *)(HX5_CMIC_BASE_ADDR + 797 CMIC_SCHAN_FIFO_CHx_COMMAND(ch, 0)); 798 #endif 799 } 800 else 801 #endif 802 { 803 #ifdef PTRS_ARE_64BITS 804 baddr = (sal_paddr_t *)((uint64)CMIC_BASE_ADDR + 805 CMIC_SCHAN_FIFO_CHx_COMMAND(ch, 0)); 806 #else 807 baddr = (sal_paddr_t *)(CMIC_BASE_ADDR + 808 CMIC_SCHAN_FIFO_CHx_COMMAND(ch, 0)); 809 #endif 810 } 811 812 LOG_VERBOSE(BSL_LS_SOC_SCHANFIFO, 813 (BSL_META_U(unit, 814 "Using CCMDMA\n"))); 815 816 rv = soc_ccmdma_copy(unit, (sal_paddr_t *)(msg->cmd), baddr, 817 0, 1, msg->size, 4, ch); 818 819 if (rv != SOC_E_NONE) { 820 LOG_ERROR(BSL_LS_SOC_SCHANFIFO, 821 (BSL_META_U(unit, 822 "CCM DMA failed with error 0x%x\n"), rv)); 823 return rv; 824 } 825 #endif 826 _soc_cmicx_schan_fifo_chstate_set(unit, ch, CHAN_CMD); 827 } else { 828 for (i = 0; i < msg->size; i++) { 829 val = ((uint32 *)msg->cmd)[i]; 830 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_COMMAND(ch, i), 831 val); 832 } 833 _soc_cmicx_schan_fifo_chstate_set(unit, ch, CHAN_PROG); 834 } 835 836 /* program number of commands and update interval 837 * for update interval value -1, set it to max limit 838 */ 839 val = soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch)); 840 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 841 &val, NUMB_OF_COMMANDSf, (msg->num)); 842 if ((msg->interval < 0) || 843 (msg->interval > SCHAN_FIFO_SUMMARY_UPDATE_INTERVAL)) { 844 msg->interval = SCHAN_FIFO_SUMMARY_UPDATE_INTERVAL; 845 } 846 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 847 &val, SUMMARY_UPDATE_INTERVALf, msg->interval); 848 849 (void)_soc_cmicx_schan_fifo_resp_config(unit, ch, msg, &val); 850 851 852 (void)soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch), val); 853 854 return rv; 855 } 856 857 /******************************************* 858 * @function _cmicx_schan_fifo_ch_done 859 * Interrupt handler for schan channel done 860 * 861 * @param unit [in] unit 862 * @param data [in] pointer provided during registration 863 * 864 * 865 * @end 866 */ 867 STATIC void 868 _cmicx_schan_fifo_ch_done(int unit, void *data) 869 { 870 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 871 soc_schan_fifo_config_t *cfg = &schan_fifo->config; 872 soc_schan_fifo_ch_t *in_d = (soc_schan_fifo_ch_t *)data; 873 874 soc_cmic_intr_disable(unit, INTR_SCHAN_FIFO(in_d->ch)); 875 if (cfg->intrEnb) { 876 sal_sem_give(in_d->schanIntr); 877 } 878 } 879 880 /******************************************* 881 * @function _cmicx_schan_fifo_intr_deinit 882 * purpose API to de-Initialize SCHAN interrupts 883 * 884 * @param unit [in] unit 885 * 886 * @returns SOC_E_NONE 887 * @returns SOC_E_XXX 888 * 889 * @end 890 */ 891 STATIC int 892 _cmicx_schan_fifo_intr_deinit(int unit) 893 { 894 int ch; 895 soc_schan_fifo_ch_t *int_data; 896 for (ch = 0; ch < CMIC_SCHAN_FIFO_NUM_MAX; ch++) { 897 int_data = &_soc_cmicx_schan_fifo[unit].chan[ch]; 898 if (int_data->schanIntr) { 899 sal_sem_destroy(int_data->schanIntr); 900 } 901 } 902 903 return SOC_E_NONE; 904 } 905 906 /******************************************* 907 * @function _cmicx_schan_fifo_intr_init 908 * purpose API to Initialize SCHAN interrupts 909 * 910 * @param unit [in] unit 911 * 912 * @returns SOC_E_NONE 913 * @returns SOC_E_XXX 914 * 915 * @end 916 */ 917 STATIC int 918 _cmicx_schan_fifo_intr_init(int unit) 919 { 920 int ch; 921 soc_cmic_intr_handler_t *handle; 922 soc_cmic_intr_handler_t *hitr; 923 soc_schan_fifo_ch_t *int_data; 924 int rv = SOC_E_NONE; 925 926 927 /* Register interrupts */ 928 handle = 929 sal_alloc(CMIC_SCHAN_FIFO_NUM_MAX * sizeof(soc_cmic_intr_handler_t), 930 "schan_fifo_interrupt"); 931 if (handle == NULL) { 932 return SOC_E_MEMORY; 933 } 934 935 hitr = handle; 936 for (ch = 0; ch < CMIC_SCHAN_FIFO_NUM_MAX; ch++) { 937 int_data = &_soc_cmicx_schan_fifo[unit].chan[ch]; 938 int_data->schanIntr = 939 sal_sem_create("SCHAN_FIFO interrupt", 940 sal_sem_BINARY, 0); 941 if (int_data->schanIntr == NULL) { 942 _cmicx_schan_fifo_intr_deinit(unit); 943 rv = SOC_E_MEMORY; 944 goto error; 945 } 946 int_data->ch = ch; 947 hitr->num = INTR_SCHAN_FIFO(ch); 948 hitr->intr_fn = _cmicx_schan_fifo_ch_done; 949 hitr->intr_data = int_data; 950 hitr++; 951 } 952 rv = soc_cmic_intr_register(unit, handle, CMIC_SCHAN_FIFO_NUM_MAX); 953 error: 954 sal_free(handle); 955 956 return rv; 957 } 958 /******************************************* 959 * @function _cmicx_schan_fifo_endian_config 960 * purpose Configure endianess of sbus dma descriptor 961 * 962 * @param unit [in] unit 963 * @param val [in] uint32 pointer 964 * 965 * @returns None 966 * @end 967 */ 968 STATIC void 969 _cmicx_schan_fifo_endian_config(int unit, uint32 *val) 970 { 971 int big_pio, big_packet, big_other; 972 973 soc_endian_get(unit, &big_pio, &big_packet, &big_other); 974 975 if (big_other) { 976 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 977 val, SUMMARY_ENDIANESSf, 1); 978 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 979 val, RESPONSE_ENDIANESSf, 1); 980 } 981 } 982 983 984 /******************************************* 985 * @function _soc_cmicx_schan_fifo_deinit 986 * purpose API to de-Initialize SCHAN 987 * 988 * @param unit [in] unit 989 * 990 * @returns NONE 991 * 992 * @end 993 */ 994 STATIC void 995 _soc_cmicx_schan_fifo_deinit(int unit) 996 { 997 int ch; 998 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 999 1000 _cmicx_schan_fifo_intr_deinit(unit); 1001 1002 /* reset all th schan channels */ 1003 for (ch = 0 ; ch < CMIC_SCHAN_FIFO_NUM_MAX; ch++) { 1004 _soc_cmicx_schan_fifo_abort(unit, ch); 1005 if (schan_fifo->summary_buff[ch]) { 1006 soc_cm_sfree(unit, schan_fifo->summary_buff[ch]); 1007 schan_fifo->summary_buff[ch] = NULL; 1008 } 1009 } 1010 sal_spinlock_destroy(schan_fifo->lock); 1011 1012 } 1013 1014 /******************************************* 1015 * @function soc_cmicx_schan_fifo_init 1016 * purpose API to Initialize cmicx SCHAN FIFO 1017 * 1018 * @param unit [in] unit 1019 * @param drv [out] soc_schan_fifo_drv_op_t pointer 1020 * @param config [in] pointer to soc_schan_fifo_config_t 1021 * 1022 * @returns SOC_E_NONE 1023 * @returns SOC_E_XXX 1024 * 1025 * @end 1026 */ 1027 extern int soc_cmicx_schan_fifo_init(int unit, 1028 soc_schan_fifo_drv_op_t *drv, 1029 soc_schan_fifo_config_t *config) 1030 1031 { 1032 int rv = SOC_E_NONE; 1033 uint32 val; 1034 soc_schan_fifo_control_t *schan_fifo = SOC_SCHAN_FIFO_CONTROL(unit); 1035 int ch, idx = 0; 1036 1037 sal_memset(schan_fifo, 0, sizeof(soc_schan_fifo_control_t)); 1038 1039 /* Set CMIC_COMMON_POOL_SHARED_CONFIG Register, 1040 * SCHAN FIFO are sent through AXI master port of CMC0 1041 */ 1042 val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_CONFIG_OFFSET); 1043 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_CONFIGr, 1044 &val, MAP_SCHAN_FIFO_MEMWR_REQf, 1045 MAP_SCHAN_FIFO_MEMWR_REQ_CMC0); 1046 soc_pci_write(unit, CMIC_COMMON_POOL_SHARED_CONFIG_OFFSET, val); 1047 1048 /* Programming WRR (Arbitration) within CMC. Configure WRR weight 1049 * for FIFO DMA channels 1050 */ 1051 soc_pci_write(unit, 1052 CMIC_COMMON_POOL_SHARED_SCHAN_FIFO_WRITE_ARB_CTRL_OFFSET, 1053 SCHAN_FIFO_MEMWR_WRR_WEIGHT); 1054 1055 /* This can be dependent upon CMIC Version */ 1056 schan_fifo->num = CMIC_SCHAN_FIFO_NUM_MAX; 1057 1058 schan_fifo->lock = sal_spinlock_create("schan_fifo Lock"); 1059 1060 if (schan_fifo->lock == NULL) { 1061 return SOC_E_MEMORY; 1062 } 1063 1064 schan_fifo->ch_map = (0x01 << CMIC_SCHAN_FIFO_NUM_MAX) - 1; 1065 sal_memcpy(&schan_fifo->config, 1066 config, sizeof(soc_schan_fifo_config_t)); 1067 1068 /* perform hardware initialization */ 1069 1070 for (ch = 0 ; ch < CMIC_SCHAN_FIFO_NUM_MAX; ch++) { 1071 /* Configure AXI ID for SCHAN FIFO */ 1072 val = soc_pci_read(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch)); 1073 soc_reg_field_set(unit, CMIC_COMMON_POOL_SCHAN_FIFO_0_CH0_CTRLr, 1074 &val, AXI_IDf, SCHAN_FIFO_AXI_ID); 1075 _cmicx_schan_fifo_endian_config(unit, &val); 1076 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_CTRL(ch), val); 1077 1078 /* Set up summary Register */ 1079 schan_fifo->summary_buff[ch] = soc_cm_salloc(unit, 1080 (CMIC_SCHAN_FIFO_CMD_SIZE_MAX * 2), "schan_fifo_summary"); 1081 if (schan_fifo->summary_buff[ch] == NULL) { 1082 rv = SOC_E_MEMORY; 1083 break; 1084 } 1085 1086 /* write summary Lo address */ 1087 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_SUMMARY_ADDR_LOWER(ch), 1088 PTR_TO_INT(soc_cm_l2p(unit, schan_fifo->summary_buff[ch]))); 1089 /* write summary Hi address */ 1090 if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) { 1091 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_SUMMARY_ADDR_UPPER(ch), 1092 (PTR_HI_TO_INT(soc_cm_l2p(unit, schan_fifo->summary_buff[ch])) | 1093 CMIC_PCIE_SO_OFFSET)); 1094 } else { 1095 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_SUMMARY_ADDR_UPPER(ch), 1096 PTR_HI_TO_INT(soc_cm_l2p(unit, schan_fifo->summary_buff[ch]))); 1097 } 1098 } 1099 1100 if (SOC_FAILURE(rv)) { 1101 _soc_cmicx_schan_fifo_deinit(unit); 1102 return rv; 1103 } 1104 1105 /* interrupt initialization */ 1106 rv = _cmicx_schan_fifo_intr_init(unit); 1107 1108 if (SOC_FAILURE(rv)) { 1109 _soc_cmicx_schan_fifo_deinit(unit); 1110 return rv; 1111 } 1112 1113 /* Initialize the SCHAN FIFO command memories */ 1114 for (ch = 0; ch < CMIC_SCHAN_FIFO_NUM_MAX; ch++) { 1115 for (idx = 0; 1116 idx < (CMIC_SCHAN_FIFO_CMD_SIZE_MAX * (CMIC_SCHAN_WORDS(unit))); 1117 idx++) { 1118 soc_pci_write(unit, CMIC_SCHAN_FIFO_CHx_COMMAND(ch, idx), 0); 1119 } 1120 } 1121 1122 drv->soc_schan_fifo_op_prog = _soc_cmicx_schan_fifo_op_prog; 1123 drv->soc_schan_fifo_op_complete = _soc_cmicx_schan_fifo_op_complete; 1124 drv->soc_schan_fifo_control = _soc_cmicx_schan_fifo_control; 1125 drv->soc_schan_fifo_deinit = _soc_cmicx_schan_fifo_deinit; 1126 1127 return rv; 1128 } 1129 1130 1131 #endif /* BCM_CMICX_SUPPORT */ 1132