cmicx_fifodma.c (31966B)
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 * Purpose: CMICX FIFO DMA Driver 8 */ 9 10 #include <shared/bsl.h> 11 #include <shared/alloc.h> 12 #include <soc/drv.h> 13 #include <soc/debug.h> 14 #include <soc/cm.h> 15 #include <soc/fifodma_internal.h> 16 17 #if defined(BCM_CMICX_SUPPORT) 18 #include <soc/cmicx.h> 19 #include <soc/intr_cmicx.h> 20 21 #ifdef BCM_DNXF_SUPPORT 22 #include <soc/dnxf/cmn/dnxf_drv.h> 23 /*dnxf data*/ 24 #include <soc/dnxf/dnxf_data/auto_generated/dnxf_data_fabric.h> 25 #endif 26 27 #ifdef BCM_DNX_SUPPORT 28 #include <sal/core/dpc.h> 29 #include <soc/dnx/dnx_fifodma.h> 30 #endif 31 32 typedef struct fifodma_intr_data_s { 33 int cmc; 34 int ch; 35 }fifodma_intr_data_t; 36 37 static fifodma_intr_data_t _intr_data[CMIC_CMC_NUM_MAX][CMICX_N_FIFODMA_CHAN]; 38 39 /* 40 * Function: 41 * cmicx_fifodma_ch_endian_set 42 * Purpose: 43 * To set cmicx fifo dma channel endianness 44 * 45 * Parameters: 46 * unit - SOC unit # 47 * channel - channel number 48 * be - big_endian 49 * 50 * @returns SOC_E_NONE 51 */ 52 int 53 cmicx_fifodma_ch_endian_set(int unit, int channel, int be) { 54 uint32 val = 0; 55 56 val = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(channel)); 57 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &val, 58 ENDIANESSf, be); 59 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(channel), val); 60 return SOC_E_NONE; 61 } 62 63 /* 64 * Function: 65 * cmicx_ctr_evict_fifodma_done 66 * Purpose: 67 * The interrupt handler for fifodma channel interrupt 68 * 69 * Parameters: 70 * unit - SOC unit # 71 * *data - pointer provided during registration 72 */ 73 74 static void 75 cmicx_ctr_evict_fifodma_done(int unit, void *data) 76 { 77 soc_control_t *soc = SOC_CONTROL(unit); 78 fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data; 79 80 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 81 (BSL_META_U(unit, 82 "fifo dma done cmc = %d ch = %d\n"), 83 in_d->cmc, in_d->ch)); 84 85 soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch)); 86 87 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3); 88 89 if (soc->ctrEvictDmaIntrEnb) { 90 SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++; 91 sal_sem_give(soc->ctrEvictIntr); 92 } 93 } 94 95 /* 96 * Function: 97 * cmicx_l2_mod_fifodma_done 98 * Purpose: 99 * The interrupt handler for fifodma channel interrupt 100 * 101 * Parameters: 102 * unit - SOC unit # 103 * *data - pointer provided during registration 104 */ 105 106 static void 107 cmicx_l2_mod_fifodma_done(int unit, void *data) 108 { 109 soc_control_t *soc = SOC_CONTROL(unit); 110 fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data; 111 112 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 113 (BSL_META_U(unit, 114 "fifo dma done cmc = %d ch = %d\n"), 115 in_d->cmc, in_d->ch)); 116 117 soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch)); 118 119 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3); 120 121 if (soc->l2modDmaIntrEnb) { 122 SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++; 123 sal_sem_give(soc->arl_notify); 124 } 125 } 126 127 /* 128 * Function: 129 * cmicx_bsc_export_fifodma_done 130 * Purpose: 131 * The interrupt handler for fifodma channel interrupt 132 * 133 * Parameters: 134 * unit - SOC unit # 135 * *data - pointer provided during registration 136 */ 137 138 static void 139 cmicx_bsc_export_fifodma_done(int unit, void *data) 140 { 141 fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data; 142 143 #ifdef BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT 144 soc_control_t *soc = SOC_CONTROL(unit); 145 #endif /* BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT */ 146 147 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 148 (BSL_META_U(unit, 149 "fifo dma done cmc = %d ch = %d\n"), 150 in_d->cmc, in_d->ch)); 151 152 soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch)); 153 154 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3); 155 156 #ifdef BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT 157 if (soc->ftExportIntrEnb) { 158 SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++; 159 sal_sem_give(soc->ftExportIntr); 160 } 161 #endif /* BCM_FLOWTRACKER_EXPORT_FIFO_SUPPORT */ 162 } 163 164 165 #ifdef BCM_DNXF_SUPPORT 166 /* 167 * Function: 168 * cmicx_dnxf_fifodma_done 169 * Purpose: 170 * The interrupt handler for fifodma channel interrupt 171 * 172 * Parameters: 173 * unit - SOC unit # 174 * *data - pointer provided during registration 175 */ 176 static void 177 cmicx_dnxf_fifodma_done(int unit, void *data) 178 { 179 fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data; 180 181 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 182 (BSL_META_U(unit, 183 "fifo dma done cmc = %d ch = %d\n"), 184 in_d->cmc, in_d->ch)); 185 186 soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch)); 187 188 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3); 189 190 if (dnxf_data_fabric.cell.fifo_dma_enable_get(unit) && SOC_DNXF_CONTROL(unit)->rx_thread_fifo_dma_semaphore != NULL) { 191 SOC_CONTROL(unit)->stat.intr_fifo_dma[in_d->ch]++; 192 sal_sem_give(SOC_DNXF_CONTROL(unit)->rx_thread_fifo_dma_semaphore); 193 } 194 } 195 #endif 196 197 198 #ifdef BCM_DNX_SUPPORT 199 /* 200 * Function: 201 * cmicx_dnx_fifodma_done 202 * Purpose: 203 * The interrupt handler for dnx fifodma channel interrupt 204 * 205 * Parameters: 206 * unit - SOC unit # 207 * *data - pointer provided during registration 208 */ 209 210 static void 211 cmicx_dnx_fifodma_done(int unit, void *data) 212 { 213 int rv; 214 fifodma_intr_data_t *in_d = (fifodma_intr_data_t *)data; 215 216 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 217 (BSL_META_U(unit, 218 "fifo dma done cmc = %d ch = %d\n"), 219 in_d->cmc, in_d->ch)); 220 221 soc_cmic_intr_disable(unit, INTR_FIFO_DMA(in_d->ch)); 222 /** Clear HOSTMEM OVERFLOW and TIMEOUT interrupt */ 223 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(in_d->ch), 0x3); 224 /** Handle under sal_dpc in case this might be a long operation in the interrupt context */ 225 rv = sal_dpc(dnx_fifodma_intr_handler, INT_TO_PTR(unit), INT_TO_PTR(in_d->ch), NULL, NULL, NULL); 226 if (rv) 227 { 228 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 229 (BSL_META_U(unit, 230 "DPC failed to execute fifo dma handler for cmc = %d ch = %d\n"), 231 in_d->cmc, in_d->ch)); 232 233 /* 234 * Interrupt is enabled in dnx_fifodma_intr_handler. 235 * In the case of DPC failure, interrupt is disabled forerver, so enable it here. 236 */ 237 soc_cmic_intr_enable(unit, INTR_FIFO_DMA(in_d->ch)); 238 } 239 } 240 #endif 241 242 /** 243 * Function used to (partially) configure the DMA to 244 * write to a redirect writes from a register/memory 245 * to a host memory. 246 * 247 * 248 * @param unit 249 * @param ch - Channel used. should be between 0 and 3. 250 * @param is_mem 251 * @param mem -name of memory, if memory is used (0 otherwise). 252 * @param reg - name of register, if register used (0 otherwise). 253 * @param copyno 254 * @param force_entry_size - in a case that entry size does not match 255 * the register\memory size - ignore when equals to 0. 256 * @param host_entries - number of host entries used by the DMA. 257 * Must be a power of 2 between 64 and 16384. 258 * Note that only after host_entries writes does the DMA wrap around the host_buff. 259 * @param host_buff - local memory on which the DMA writes. should be big enough to 260 * allow host_entries writes, 261 * in other words whould be the size of host_entries * ( size of memory or 262 * register used, in bytes). 263 * 264 * Other register the caller may need to configure seperatly: 265 * CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_THRESHOLD - The amount of writes by the DMA until a 266 * threshold based interrupt occurs. 267 * 268 * TIMEOUT_COUNT field in CMIC_CMCx_FIFO_CHy_RD_DMA - Time between a DMA write and a 269 * timeout based interrupt. 270 * (May be set to 0 to disable timeout based interrupts). 271 * 272 * Endianess field in CMIC_CMCx_FIFO_CHy_RD_DMA. 273 * 274 * @return int - success or failure. 275 */ 276 277 static int 278 soc_fifo_dma_start_memreg(int unit, int ch, 279 int is_mem, soc_mem_t mem, soc_reg_t reg, 280 int copyno, int force_entry_size, 281 int host_entries, void *host_buff) 282 { 283 uint8 at; 284 uint32 rval, data_beats, sel; 285 int blk; 286 schan_msg_t msg; 287 int acc_type; 288 sal_paddr_t addr; 289 290 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 291 (BSL_META_U(unit, 292 "cmicx fifodma start for chan %d, host entries %d\n"), 293 ch, host_entries)); 294 295 if (ch < 0 || ch > 12 || host_buff == NULL) { 296 return SOC_E_PARAM; 297 } 298 299 switch (host_entries) { 300 case 64: sel = 0; break; 301 case 128: sel = 1; break; 302 case 256: sel = 2; break; 303 case 512: sel = 3; break; 304 case 1024: sel = 4; break; 305 case 2048: sel = 5; break; 306 case 4096: sel = 6; break; 307 case 8192: sel = 7; break; 308 case 16384: sel = 8; break; 309 default: 310 return SOC_E_PARAM; 311 } 312 313 /* Differentiate between reg and mem to get address, size and block */ 314 if ((!is_mem) && SOC_REG_IS_VALID(unit, reg)) { 315 data_beats = BYTES2WORDS(soc_reg_bytes(unit, reg)); 316 rval = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0, 317 SOC_REG_ADDR_OPTION_NONE, &blk, &at); 318 } else { 319 data_beats = soc_mem_entry_words(unit, mem); 320 if (copyno == MEM_BLOCK_ANY) { 321 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 322 } 323 rval = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at); 324 blk = SOC_BLOCK2SCH(unit, copyno); 325 } 326 327 /* Force entry size */ 328 if (force_entry_size > 0) 329 { 330 data_beats = BYTES2WORDS(force_entry_size); 331 } 332 333 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_SBUS_START_ADDRESS_OFFSET(ch), rval); 334 335 schan_msg_clear(&msg); 336 if (is_mem) { 337 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 338 } else { 339 acc_type = 0; 340 } 341 342 soc_schan_header_cmd_set(unit, &msg.header, FIFO_POP_CMD_MSG, blk, 0, 343 acc_type, 4, 0, 0); 344 /* Set 1st schan ctrl word as opcode */ 345 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_OPCODE_OFFSET(ch), msg.dwords[0]); 346 347 addr = soc_cm_l2p(unit, host_buff); 348 349 soc_pci_write(unit, 350 CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_LO_OFFSET(ch), 351 PTR_TO_INT(addr)); 352 if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) { 353 soc_pci_write(unit, 354 CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_HI_OFFSET(ch), 355 (CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(addr))); 356 } else { 357 soc_pci_write(unit, 358 CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_HI_OFFSET(ch), 359 (PTR_HI_TO_INT(addr))); 360 } 361 362 rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch)); 363 364 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, 365 BEAT_COUNTf, data_beats); 366 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, 367 HOST_NUM_ENTRIES_SELf, sel); 368 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, 369 ABORTf, 0); 370 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, 371 TIMEOUT_COUNTf, 1000); 372 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, 373 NACK_FATALf, 1); 374 375 if (soc_feature(unit, soc_feature_multi_sbus_cmds)) { 376 377 } 378 379 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval); 380 381 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_HOSTMEM_THRESHOLD_OFFSET(ch), 382 host_entries/10); 383 384 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, ENABLEf, 1); 385 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval); 386 387 return SOC_E_NONE; 388 } 389 390 /******************************************* 391 * @function _cmicx_fifodma_start 392 * purpose to start fifo dma channel 393 * 394 * @param unit [in] unit # 395 * @param ch [in] channel number 396 * 397 * @returns SOC_E_PARAM 398 * @returns SOC_E_NONE 399 * 400 * @end 401 */ 402 static int 403 _cmicx_fifodma_start(int unit, int ch, int is_mem, 404 soc_mem_t mem, soc_reg_t reg, 405 int copyno, int force_entry_size, 406 int host_entries, void *host_buff) 407 { 408 return soc_fifo_dma_start_memreg(unit, ch, 409 is_mem, mem, reg, 410 copyno, force_entry_size, host_entries, host_buff); 411 } 412 413 /******************************************* 414 * @function _cmicx_fifodma_stop 415 * purpose to stop fifo dma channel 416 * 417 * @param unit [in] unit # 418 * @param chan [in] channel number 419 * 420 * @returns SOC_E_BUSY 421 * @returns SOC_E_NONE 422 * 423 * @end 424 */ 425 static int 426 _cmicx_fifodma_stop(int unit, int ch) 427 { 428 int iter = 0; 429 uint32 rval; 430 int to = SAL_BOOT_QUICKTURN ? 30000000 : 10000000; 431 uint32 aborted = 0; 432 433 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 434 (BSL_META_U(unit, 435 "cmicx fifodma stop for chan %d\n"), ch)); 436 437 if (ch < 0 || ch > 12) { 438 return SOC_E_PARAM; 439 } 440 441 rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch)); 442 if (!soc_reg_field_get(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, rval, ENABLEf)) { 443 return SOC_E_NONE; 444 } 445 446 rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch)); 447 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, ABORTf, 1); 448 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval); 449 450 sal_udelay(1000); 451 rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_OFFSET(ch)); 452 aborted = soc_reg_field_get(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_STATr, 453 rval, ABORTEDf); 454 if (SAL_BOOT_BCMSIM) { 455 aborted = 1; 456 } 457 while (aborted == 0 && iter++ < to) { 458 sal_udelay(1000); 459 rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_OFFSET(ch)); 460 aborted = soc_reg_field_get(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_STATr, 461 rval, ABORTEDf); 462 } 463 464 rval = soc_pci_read(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch)); 465 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_CFGr, &rval, ENABLEf, 0); 466 soc_pci_write(unit, CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_CFG_OFFSET(ch), rval); 467 468 if (iter >= to) { 469 LOG_ERROR(BSL_LS_SOC_FIFODMA, 470 (BSL_META_U(unit, 471 "FIFO DMA abort failed !!\n"))); 472 return SOC_E_INTERNAL; 473 } 474 475 return SOC_E_NONE; 476 477 } 478 479 480 /******************************************* 481 * @function _cmicx_fifodma_intr_enable 482 * purpose to enable interrupt 483 * 484 * @param unit [in] unit # 485 * @param ch [in] channel 486 * 487 * @returns SOC_E_BUSY 488 * @returns SOC_E_NONE 489 * 490 * @end 491 */ 492 static int 493 _cmicx_fifodma_intr_enable(int unit, int ch) 494 { 495 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 496 (BSL_META_U(unit, 497 "cmicx fifodma interrupt enable for chan %d\n"), ch)); 498 499 soc_cmic_intr_enable(unit, INTR_FIFO_DMA(ch)); 500 501 return 0; 502 } 503 504 /******************************************* 505 * @function _cmicx_fifodma_intr_disable 506 * purpose to disable interrupt 507 * 508 * @param unit [in] unit # 509 * @param ch [in] channel 510 * 511 * @returns SOC_E_BUSY 512 * @returns SOC_E_NONE 513 * 514 * @end 515 */ 516 static int 517 _cmicx_fifodma_intr_disable(int unit, int ch) 518 { 519 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 520 (BSL_META_U(unit, 521 "cmicx fifodma interrupt disable for chan %d\n"), ch)); 522 523 soc_cmic_intr_disable(unit, INTR_FIFO_DMA(ch)); 524 525 return 0; 526 } 527 528 /******************************************* 529 * @function _cmicx_fifodma_get_read_ptr 530 * purpose to get read ptr 531 * 532 * @param unit [in] unit # 533 * 534 * @returns SOC_E_BUSY 535 * @returns SOC_E_NONE 536 * 537 * @end 538 */ 539 static int 540 _cmicx_fifodma_get_read_ptr(int unit, int chan, void **host_ptr, int *count) 541 { 542 return 0; 543 } 544 545 /******************************************* 546 * @function _cmicx_fifodma_advance_read_ptr 547 * purpose to advance read ptr 548 * 549 * @param unit [in] unit # 550 * 551 * @returns SOC_E_BUSY 552 * @returns SOC_E_NONE 553 * 554 * @end 555 */ 556 static int 557 _cmicx_fifodma_advance_read_ptr(int unit, int chan, int count) 558 { 559 return 0; 560 } 561 562 /******************************************* 563 * @function _cmicx_fifodma_set_entries_read 564 * purpose to read set entries 565 * 566 * @param unit [in] unit # 567 * 568 * @returns SOC_E_BUSY 569 * @returns SOC_E_NONE 570 * 571 * @end 572 */ 573 static int 574 _cmicx_fifodma_set_entries_read(int unit, int ch, uint32 num) 575 { 576 uint32 rval = 0; 577 578 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 579 (BSL_META_U(unit, 580 "cmicx fifodma set %d entries for chan %d\n"), num, ch)); 581 582 if (ch < 0 || ch > 12) { 583 return SOC_E_PARAM; 584 } 585 586 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_NUM_OF_ENTRIES_READ_FRM_HOSTMEMr, &rval, 587 ENTRYCOUNTf, num); 588 soc_reg_field_set(unit, CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_NUM_OF_ENTRIES_READ_FRM_HOSTMEMr, &rval, 589 WR_NUMBER_OF_ENTRIESf, 1); 590 591 soc_pci_write(unit, 592 CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_NUM_OF_ENTRIES_READ_FRM_HOSTMEM_OFFSET(ch), rval); 593 594 return SOC_E_NONE; 595 } 596 597 /******************************************* 598 * @function _cmicx_fifodma_num_entries_get 599 * purpose to get number of entries 600 * 601 * @param unit [in] unit # 602 * 603 * @returns SOC_E_BUSY 604 * @returns SOC_E_NONE 605 * 606 * @end 607 */ 608 static int 609 _cmicx_fifodma_num_entries_get(int unit, int ch, int *count) 610 { 611 uint32 val = 0; 612 613 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 614 (BSL_META_U(unit, 615 "cmicx fifodma entries get for chan %d\n"), ch)); 616 617 if (ch < 0 || ch > 12) { 618 return SOC_E_PARAM; 619 } 620 621 val = soc_pci_read(unit, 622 CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_NUM_OF_ENTRIES_VALID_IN_HOSTMEM_OFFSET(ch)); 623 624 *count = val; 625 626 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 627 (BSL_META_U(unit, 628 "cmicx fifodma %d entries get for chan %d\n"), val, ch)); 629 if (val) { 630 return SOC_E_NONE; 631 } 632 633 return SOC_E_EMPTY; 634 } 635 636 /******************************************* 637 * @function _cmicx_fifodma_status_clear 638 * purpose to clear fifo dma channel status 639 * 640 * @param unit [in] unit # 641 * @param chan [in] channel number 642 * 643 * @returns SOC_E_BUSY 644 * @returns SOC_E_NONE 645 * 646 * @end 647 */ 648 static int 649 _cmicx_fifodma_status_clear(int unit, int chan) 650 { 651 soc_reg_t stat_clr_reg; 652 uint32 stat_clr_addr; 653 uint32 stat_clr_mask; 654 655 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 656 (BSL_META_U(unit, 657 "cmicx fifodma status clear for chan %d\n"), chan)); 658 659 if (chan < 0 || chan > 12) { 660 return SOC_E_PARAM; 661 } 662 663 stat_clr_reg = CMIC_COMMON_POOL_FIFO_CH0_RD_DMA_STATr; 664 stat_clr_mask = 0; 665 soc_reg_field_set(unit, stat_clr_reg, &stat_clr_mask, HOSTMEM_TIMEOUTf, 1); 666 soc_reg_field_set(unit, stat_clr_reg, &stat_clr_mask, HOSTMEM_OVERFLOWf, 1); 667 668 stat_clr_addr = CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(chan); 669 670 soc_pci_write(unit, stat_clr_addr, stat_clr_mask); 671 672 return SOC_E_NONE; 673 } 674 675 /******************************************* 676 * @function _cmicx_fifodma_status_get 677 * purpose to obtain fifo dma channel status 678 * 679 * @param unit [in] unit # 680 * @param chan [in] channel number 681 * 682 * @returns SOC_E_BUSY 683 * @returns SOC_E_NONE 684 * 685 * @end 686 */ 687 static int 688 _cmicx_fifodma_status_get(int unit, int chan, uint32 *status) 689 { 690 uint32 stat_addr; 691 692 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 693 (BSL_META_U(unit, 694 "cmicx fifodma status get for chan %d\n"), chan)); 695 696 if (chan < 0 || chan > 12) { 697 return SOC_E_PARAM; 698 } 699 700 stat_addr = CMIC_COMMON_POOL_FIFO_CHy_RD_DMA_STAT_OFFSET(chan); 701 702 *status = soc_pci_read(unit, stat_addr); 703 704 return SOC_E_NONE; 705 } 706 707 /******************************************* 708 * @function _cmicx_fifodma_masks_get 709 * purpose to obtain fifodma masks 710 * 711 * @param unit [in] unit # 712 * @param chan [in] channel number 713 * 714 * @returns SOC_E_BUSY 715 * @returns SOC_E_NONE 716 * 717 * @end 718 */ 719 static int 720 _cmicx_fifodma_masks_get(int unit, uint32 *hostmem_timeout, uint32 *hostmem_overflow, uint32 *error, uint32 *done) 721 { 722 int rv = SOC_E_NONE; 723 724 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 725 (BSL_META_U(unit, 726 "cmicx fifodma masks get\n"))); 727 728 *hostmem_timeout = 1 << 3; 729 *hostmem_overflow = 1 << 2; 730 *error = 1 << 0; 731 *done = 1 << 4; 732 733 return rv; 734 } 735 736 /******************************************* 737 * @function _cmicx_l2mod_sbus_fifo_field_set 738 * obtain l2 mod sbus field set 739 * 740 * @param unit [in] unit # 741 * @param field [in] field 742 * @param enable [in] enable 743 * 744 * @returns SOC_E_BUSY 745 * @returns SOC_E_NONE 746 * 747 * @end 748 */ 749 static int 750 _cmicx_l2mod_sbus_fifo_field_set(int unit, soc_field_t field, int enable) 751 { 752 uint32 rval = 0; 753 uint32 fval = enable?1:0; 754 755 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 756 (BSL_META_U(unit, 757 "cmicx l2mod sbus fifo set\n"))); 758 759 if (SOC_IS_TRIDENT3X(unit)) { 760 if(soc_reg_field_valid(unit, L2_MOD_FIFO_ENABLEr, field)) { 761 SOC_IF_ERROR_RETURN(READ_L2_MOD_FIFO_ENABLEr(unit, &rval)); 762 763 soc_reg_field_set(unit, L2_MOD_FIFO_ENABLEr, &rval, field, fval); 764 765 SOC_IF_ERROR_RETURN(WRITE_L2_MOD_FIFO_ENABLEr(unit, rval)); 766 } 767 return SOC_E_NONE; 768 } 769 770 return SOC_E_UNAVAIL; 771 } 772 773 /******************************************* 774 * @function _cmicx_l2mod_sbus_fifo_field_get 775 * obtain l2 mod sbus field get 776 * 777 * @param unit [in] unit # 778 * @param field [in] field 779 * @param enable [in] enable 780 * 781 * @returns SOC_E_BUSY 782 * @returns SOC_E_NONE 783 * 784 * @end 785 */ 786 static int 787 _cmicx_l2mod_sbus_fifo_field_get(int unit, soc_field_t field, int *enable) 788 { 789 uint32 reg = 0; 790 uint32 fval = 0; 791 792 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 793 (BSL_META_U(unit, 794 "cmicx l2mod sbus fifo get\n"))); 795 796 797 if (SOC_IS_TRIDENT3X(unit)) { 798 if(soc_reg_field_valid(unit, L2_MOD_FIFO_ENABLEr, field)) { 799 SOC_IF_ERROR_RETURN(READ_L2_MOD_FIFO_ENABLEr(unit, ®)); 800 801 fval = soc_reg_field_get(unit, L2_MOD_FIFO_ENABLEr, reg, field); 802 } 803 *enable = fval?1:0; 804 return SOC_E_NONE; 805 } 806 807 return SOC_E_UNAVAIL; 808 } 809 810 /******************************************* 811 * @function cmicx_fifodma_init 812 * purpose API to Initialize cmicx FIFO DMA 813 * 814 * @param unit [in] unit 815 * @param drv [out] soc_fifodma_drv_t pointer 816 * 817 * @returns SOC_E_NONE 818 * @returns SOC_E_XXX 819 * 820 * @end 821 */ 822 int cmicx_fifodma_init(int unit, soc_fifodma_drv_t *drv) 823 { 824 int rv = SOC_E_NONE; 825 int cmc = 0; 826 soc_cmic_intr_handler_t *handle; 827 soc_cmic_intr_handler_t *hitr; 828 uint32 val, y; 829 int nof_channels = CMICX_N_FIFODMA_CHAN; 830 831 LOG_VERBOSE(BSL_LS_SOC_FIFODMA, 832 (BSL_META_U(unit, 833 "cmicx fifo dma init, registering interrupts\n"))); 834 835 /* Register the descriptor done interrupts */ 836 handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMICX_N_FIFODMA_CHAN, 837 "fifodma_interrupt"); 838 if (handle == NULL) { 839 return SOC_E_MEMORY; 840 } 841 842 hitr = handle; 843 844 #ifdef BCM_DNXF_SUPPORT 845 if (SOC_IS_DNXF(unit)) 846 { 847 int ch = 0; 848 849 /* Number of supported channels */ 850 nof_channels = dnxf_data_fabric.cell.fifo_dma_nof_channels_get(unit); 851 852 for (ch = 0; ch < nof_channels; ++ch) 853 { 854 _intr_data[cmc][0].cmc = cmc; 855 _intr_data[cmc][0].ch = ch; 856 hitr->num = INTR_FIFO_DMA(ch); 857 hitr->intr_fn = cmicx_dnxf_fifodma_done; 858 hitr->intr_data = &_intr_data[cmc][ch]; 859 hitr++; 860 } 861 } 862 else 863 #endif 864 #ifdef BCM_DNX_SUPPORT 865 if (SOC_IS_DNX(unit)) 866 { 867 int ch = 0; 868 /* Number of supported channels */ 869 for(ch = 0; ch < CMICX_N_FIFODMA_CHAN; ch++) { 870 _intr_data[cmc][ch].cmc = cmc; 871 _intr_data[cmc][ch].ch = ch; 872 hitr->num = INTR_FIFO_DMA(ch); 873 hitr->intr_fn = cmicx_dnx_fifodma_done; 874 hitr->intr_data = &_intr_data[cmc][ch]; 875 hitr++; 876 } 877 } 878 else 879 #endif 880 881 { 882 /* For Channel 0 */ 883 _intr_data[cmc][0].cmc = cmc; 884 _intr_data[cmc][0].ch = 0; 885 hitr->num = INTR_FIFO_DMA(0); 886 hitr->intr_fn = cmicx_l2_mod_fifodma_done; 887 hitr->intr_data = &_intr_data[cmc][0]; 888 hitr++; 889 /* For Channel 1 */ 890 _intr_data[cmc][1].cmc = cmc; 891 _intr_data[cmc][1].ch = 1; 892 hitr->num = INTR_FIFO_DMA(1); 893 hitr->intr_fn = cmicx_ctr_evict_fifodma_done; 894 hitr->intr_data = &_intr_data[cmc][1]; 895 hitr++; 896 897 /* For Channel 2 */ 898 _intr_data[cmc][2].cmc = cmc; 899 _intr_data[cmc][2].ch = 2; 900 hitr->num = INTR_FIFO_DMA(2); 901 hitr->intr_fn = cmicx_bsc_export_fifodma_done; 902 hitr->intr_data = &_intr_data[cmc][2]; 903 hitr++; 904 } 905 906 rv = soc_cmic_intr_register(unit, handle, 907 nof_channels); 908 sal_free(handle); 909 910 /* 911 * Set CMIC_COMMON_POOL_SHARED_CONFIG Register, 912 * FIFO DMA are sent through AXI master port of CMC0 913 */ 914 val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_CONFIG_OFFSET); 915 916 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_CONFIGr, 917 &val, MAP_FIFODMA_SLICE2_MEMWR_REQf, 918 MAP_FIFO_DMA_MEMWR_REQ_CMC0); 919 920 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_CONFIGr, 921 &val, MAP_FIFODMA_SLICE1_MEMWR_REQf, 922 MAP_FIFO_DMA_MEMWR_REQ_CMC0); 923 924 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_CONFIGr, 925 &val, MAP_FIFODMA_SLICE0_MEMWR_REQf, 926 MAP_FIFO_DMA_MEMWR_REQ_CMC0); 927 928 soc_pci_write(unit, CMIC_COMMON_POOL_SHARED_CONFIG_OFFSET, val); 929 930 /* 931 * Programming WRR (Arbitration) within CMC. Configure WRR weight 932 * for FIFO DMA channels. The defaults should work but still 933 * writing the defaults. 934 */ 935 val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRL_OFFSET); 936 937 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRLr, 938 &val, SLICE2_MEMWR_WRR_WEIGHTf, 939 CMICX_FIFO_DMA_MEMWR_WRR_WEIGHT); 940 941 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRLr, 942 &val, SLICE1_MEMWR_WRR_WEIGHTf, 943 CMICX_FIFO_DMA_MEMWR_WRR_WEIGHT); 944 945 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRLr, 946 &val, SLICE0_MEMWR_WRR_WEIGHTf, 947 CMICX_FIFO_DMA_MEMWR_WRR_WEIGHT); 948 949 soc_pci_write(unit, 950 CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_ARB_CTRL_OFFSET, 951 val); 952 953 val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_OFFSET); 954 955 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 956 &val, CHANNEL0_MEMWR_AXI_IDf, 957 CMICX_FIFO_DMA_AXI_ID); 958 959 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 960 &val, CHANNEL1_MEMWR_AXI_IDf, 961 CMICX_FIFO_DMA_AXI_ID); 962 963 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 964 &val, CHANNEL2_MEMWR_AXI_IDf, 965 CMICX_FIFO_DMA_AXI_ID); 966 967 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 968 &val, CHANNEL3_MEMWR_AXI_IDf, 969 CMICX_FIFO_DMA_AXI_ID); 970 971 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 972 &val, CHANNEL4_MEMWR_AXI_IDf, 973 CMICX_FIFO_DMA_AXI_ID); 974 975 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 976 &val, CHANNEL5_MEMWR_AXI_IDf, 977 CMICX_FIFO_DMA_AXI_ID); 978 979 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 980 &val, CHANNEL6_MEMWR_AXI_IDf, 981 CMICX_FIFO_DMA_AXI_ID); 982 983 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 984 &val, CHANNEL7_MEMWR_AXI_IDf, 985 CMICX_FIFO_DMA_AXI_ID); 986 987 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 988 &val, CHANNEL8_MEMWR_AXI_IDf, 989 CMICX_FIFO_DMA_AXI_ID); 990 991 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRLr, 992 &val, CHANNEL9_MEMWR_AXI_IDf, 993 CMICX_FIFO_DMA_AXI_ID); 994 995 soc_pci_write(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_OFFSET, val); 996 997 998 val = soc_pci_read(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1_OFFSET); 999 1000 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1r, 1001 &val, CHANNEL10_MEMWR_AXI_IDf, 1002 CMICX_FIFO_DMA_AXI_ID); 1003 1004 soc_reg_field_set(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1r, 1005 &val, CHANNEL11_MEMWR_AXI_IDf, 1006 CMICX_FIFO_DMA_AXI_ID); 1007 1008 soc_pci_write(unit, CMIC_COMMON_POOL_SHARED_FIFO_DMA_WRITE_AXI_MAP_CTRL_1_OFFSET, val); 1009 1010 for(y = 0; y < CMICX_N_FIFODMA_CHAN; y++) { 1011 cmicx_fifodma_ch_endian_set(unit, y, 0); 1012 } 1013 1014 drv->fifodma_start = _cmicx_fifodma_start; 1015 drv->fifodma_stop = _cmicx_fifodma_stop; 1016 drv->fifodma_intr_enable = _cmicx_fifodma_intr_enable; 1017 drv->fifodma_intr_disable = _cmicx_fifodma_intr_disable; 1018 drv->fifodma_get_read_ptr = _cmicx_fifodma_get_read_ptr; 1019 drv->fifodma_advance_read_ptr = _cmicx_fifodma_advance_read_ptr; 1020 drv->fifodma_set_entries_read = _cmicx_fifodma_set_entries_read; 1021 drv->fifodma_num_entries_get = _cmicx_fifodma_num_entries_get; 1022 drv->fifodma_status_clear = _cmicx_fifodma_status_clear; 1023 drv->fifodma_status_get = _cmicx_fifodma_status_get; 1024 drv->fifodma_masks_get = _cmicx_fifodma_masks_get; 1025 drv->l2mod_sbus_fifo_field_set = _cmicx_l2mod_sbus_fifo_field_set; 1026 drv->l2mod_sbus_fifo_field_get = _cmicx_l2mod_sbus_fifo_field_get; 1027 1028 return(rv); 1029 } 1030 1031 /******************************************* 1032 * @function cmicx_fifodma_deinit 1033 * purpose API to Deinitialize cmicx FIFO DMA 1034 * 1035 * @param unit [in] unit 1036 * @param drv [in] soc_fifodma_drv_t pointer 1037 * 1038 * @returns SOC_E_NONE 1039 1040 * 1041 * @end 1042 */ 1043 int cmicx_fifodma_deinit(int unit, soc_fifodma_drv_t *drv) 1044 { 1045 drv->fifodma_start = NULL; 1046 drv->fifodma_stop = NULL; 1047 drv->fifodma_intr_enable = NULL; 1048 drv->fifodma_intr_disable = NULL; 1049 drv->fifodma_get_read_ptr = NULL; 1050 drv->fifodma_advance_read_ptr = NULL; 1051 drv->fifodma_set_entries_read = NULL; 1052 drv->fifodma_num_entries_get = NULL; 1053 drv->fifodma_status_clear = NULL; 1054 drv->fifodma_status_get = NULL; 1055 drv->fifodma_masks_get = NULL; 1056 drv->l2mod_sbus_fifo_field_set = NULL; 1057 drv->l2mod_sbus_fifo_field_get = NULL; 1058 1059 return SOC_E_NONE; 1060 } 1061 1062 #endif /* BCM_CMICX_SUPPORT */ 1063