cmicd_dma.c (27609B)
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: CMICDV2 interface drvier for SOC DMA 8 */ 9 10 #include <sal/core/boot.h> 11 #include <sal/core/libc.h> 12 #include <shared/alloc.h> 13 #include <shared/bsl.h> 14 15 #include <soc/debug.h> 16 #include <soc/cm.h> 17 #include <soc/dma.h> 18 #include <soc/drv.h> 19 #include <soc/dcb.h> 20 #include <soc/cmicm.h> 21 22 #ifdef INCLUDE_KNET 23 #include <soc/knet.h> 24 #endif 25 26 #ifdef BCM_CMICDV2_SUPPORT 27 28 #define DCB_LAST_DWORD 0xF 29 #define DCB_DONE_BIT 0x80000000 30 31 /* CMICD needs access to CMICM driver functions */ 32 soc_cmic_dma_drv_t soc_cmicm_dma_drv[SOC_MAX_NUM_DEVICES]; 33 34 /* Static Driver Functions */ 35 36 /* 37 * Function: 38 * cmicd_dma_ctrl_reset 39 * Purpose: 40 * Reset the CMICD DMA Control to a known good state for 41 * the specified SOC unit. 42 * Parameters: 43 * unit - SOC unit # 44 * Returns: 45 * SOC_E_NONE - success 46 * SOC_E_XXXX - error code 47 * Notes: 48 */ 49 50 int 51 cmicd_dma_ctrl_init(int unit) 52 { 53 return(soc_cmicm_dma_drv[unit].ctrl_init(unit)); 54 } 55 56 57 /* 58 * Function: 59 * cmicd_dma_chan_config 60 * Purpose: 61 * Initialize the CMICD DMA channel for the specified SOC unit. 62 * Parameters: 63 * unit - SOC unit # 64 * chan - channel # 65 * type - tx or rx 66 * f_intr - interrupt flags 67 * Returns: 68 * SOC_E_NONE - success 69 * SOC_E_XXXX - error code 70 * Notes: 71 */ 72 static int 73 cmicd_dma_chan_config(int unit, int vchan, dvt_t type, uint32 flags) 74 { 75 int rv = SOC_E_NONE; 76 soc_control_t *soc = SOC_CONTROL(unit); 77 sdc_t *sc = &soc->soc_channels[vchan]; 78 uint32 bits; 79 int cmc = vchan / N_DMA_CHAN; 80 int chan = vchan % N_DMA_CHAN; 81 uint32 cr; 82 83 /* Define locals and turn flags into easy to use things */ 84 /*int f_mbm = (flags & SOC_DMA_F_MBM) != 0; */ 85 int f_interrupt = (flags & SOC_DMA_F_POLL) == 0; 86 /*int f_drop = (flags & SOC_DMA_F_TX_DROP) != 0; */ 87 int f_default = (flags & SOC_DMA_F_DEFAULT) != 0; 88 int f_desc_intr = (flags & SOC_DMA_F_INTR_ON_DESC) != 0; 89 int init_hw = TRUE; 90 91 /* Set channel to Continuous Mode */ 92 SOC_DMA_MODE(unit) = SOC_DMA_MODE_CONTINUOUS; 93 94 /* Initial state of channel */ 95 sc->sc_flags = 0; /* Clear flags to start */ 96 97 #ifdef INCLUDE_KNET 98 if (SOC_KNET_MODE(unit) && SOC_WARM_BOOT(unit) && 99 soc_property_get(unit, spn_WARMBOOT_KNET_SHUTDOWN_MODE, 0)) { 100 init_hw = FALSE; 101 } 102 #endif 103 104 if (init_hw) { 105 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_DESC_DONE(chan) | 106 IRQ_CMCx_CNTLD_DESC_DONE(chan) | 107 IRQ_CMCx_CHAIN_DONE(chan)); 108 109 cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan)); 110 cr &= ~PKTDMA_ENABLE; /* clearing enable will also clear CHAIN_DONE */ 111 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), cr); 112 113 cr = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc)); 114 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 115 DS_CNTLD_DESC_CLR(chan)); 116 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), cr); 117 } 118 119 /* Setup new mode */ 120 /* MBM Deprecated in CMICm */ 121 /* DROP_TX Deprecated in CMICm */ 122 bits = f_desc_intr ? PKTDMA_SEL_INTR_ON_DESC_OR_PKT : 0; 123 124 if (type == DV_TX) { 125 bits |= PKTDMA_DIRECTION; 126 if (f_default) { 127 soc->soc_dma_default_tx = sc; 128 } 129 } else if (type == DV_RX) { 130 bits &= ~PKTDMA_DIRECTION; 131 if (f_default) { 132 soc->soc_dma_default_rx = sc; 133 } 134 } else if (type == DV_NONE) { 135 f_interrupt = FALSE; /* Force off */ 136 } else { 137 assert(0); 138 } 139 140 #ifdef INCLUDE_KNET 141 if (SOC_KNET_MODE(unit)) { 142 /* Interrupt are handled by kernel */ 143 f_interrupt = FALSE; 144 } 145 #endif 146 147 /* Only enable controlled descriptor 148 done interrupt for TX AND RX Continuous Mode */ 149 if (f_interrupt) { 150 (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_CNTLD_DESC_DONE(chan)); 151 } 152 153 sc->sc_type = type; 154 if (init_hw) { 155 cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan)); 156 157 /* Clear everything except Endianess */ 158 cr &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN); 159 cr |= bits; 160 161 /* Use Controlled Descriptor Interrupt Mode */ 162 cr |= PKTDMA_CNTLD_DESC_INTR_MODE; 163 164 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), cr); 165 } 166 167 return rv; 168 } 169 170 /* 171 * Function: 172 * cmicd_dma_chan_start 173 * Purpose: 174 * Start the CMICd DMA channel for the specified SOC unit. 175 * Parameters: 176 * unit - SOC unit # 177 * sc - SOC channel data structure pointer 178 * Returns: 179 * SOC_E_NONE - success 180 * SOC_E_XXXX - error code 181 * Notes: 182 */ 183 static int 184 cmicd_dma_chan_start(int unit, sdc_t *sc) 185 { 186 int rv = SOC_E_NONE; 187 dv_t *dv; 188 int cmc = sc->sc_channel / N_DMA_CHAN; 189 int chan = sc->sc_channel % N_DMA_CHAN; 190 uint32 val; 191 192 if ((dv = sc->sc_dv_active = sc->sc_q) == NULL) { 193 sc->sc_q_tail = NULL; 194 return rv; 195 } 196 197 #ifdef INCLUDE_KNET 198 if (SOC_KNET_MODE(unit)) { 199 return rv; 200 } 201 #endif 202 203 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 204 (BSL_META_U(unit, 205 "Starting channel %d\n"), 206 sc->sc_channel)); 207 208 /* Set up DMA descriptor address */ 209 soc_pci_write(unit, CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan), 210 soc_cm_l2p(unit, sc->sc_q->dv_dcb)); 211 212 /* Start DMA - Enable Continuous Mode for this channel */ 213 val = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 214 val |= (PKTDMA_ENABLE | PKTDMA_CONTINUOUS_ENABLE); 215 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val); 216 217 SDK_CONFIG_MEMORY_BARRIER; 218 219 if (!(sc->sc_flags & SOC_DMA_F_POLL)) { 220 (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, 221 IRQ_CMCx_CNTLD_DESC_DONE(chan)); 222 } 223 224 return rv; 225 } 226 227 /* 228 * Function: 229 * cmicd_dma_chan_poll 230 * Purpose: 231 * Poll the CMICD DMA channel for the specified SOC unit. 232 * Parameters: 233 * unit - SOC unit # 234 * chan - channel # 235 * type - poll type (chain done or desc done) 236 * detected - poll result pointer to be updated 237 * Returns: 238 * SOC_E_NONE - success 239 * SOC_E_XXXX - error code 240 * Notes: 241 * Assumes that SOC_DMA_LOCK is held when called. 242 */ 243 static int 244 cmicd_dma_chan_poll(int unit, 245 int vchan, 246 soc_dma_poll_type_t type, 247 int * detected) 248 { 249 return (soc_cmicm_dma_drv[unit].chan_poll(unit, vchan, type, detected)); 250 } 251 252 /* 253 * Function: 254 * cmicd_dma_chan_abort 255 * Purpose: 256 * Initialize the CMICD DMA channel for the specified SOC unit. 257 * Parameters: 258 * unit - SOC unit # 259 * chan - channel # 260 * type - tx or rx 261 * f_intr - interrupt flags 262 * Returns: 263 * SOC_E_NONE - Success 264 * SOC_E_TIMEOUT - failed (Timeout) 265 * Notes: 266 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 267 */ 268 static int 269 cmicd_dma_chan_abort(int unit, int vchan) 270 { 271 int rv = SOC_E_NONE; 272 int cmc = vchan / N_DMA_CHAN; 273 int chan = vchan % N_DMA_CHAN; 274 int to; 275 uint32 ctrl; 276 soc_control_t *soc = SOC_CONTROL(unit); 277 sdc_t *sc = &soc->soc_channels[chan]; 278 279 if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 280 & DS_CMCx_DMA_ACTIVE(chan)) != 0) { 281 ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 282 ctrl |= PKTDMA_ENABLE; 283 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl); 284 soc_pci_write(unit, 285 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), 286 ctrl | PKTDMA_ABORT); 287 SDK_CONFIG_MEMORY_BARRIER; 288 289 to = soc_property_get(unit, spn_PDMA_TIMEOUT_USEC, 500000); 290 while ((to >= 0) && 291 ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 292 & DS_CMCx_DMA_ACTIVE(chan)) != 0)) { 293 sal_udelay(1000); 294 to -= 1000; 295 } 296 if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 297 & DS_CMCx_DMA_ACTIVE(chan)) != 0) { 298 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 299 (BSL_META_U(unit, 300 "soc_dma_abort_channel unit %d: " 301 "channel %d abort timeout\n"), 302 unit, chan)); 303 rv = SOC_E_TIMEOUT; 304 if (SOC_WARM_BOOT(unit)) { 305 return rv; 306 } 307 } 308 } 309 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 310 (BSL_META_U(unit, 311 "soc_dma_abort_channel unit %d: " 312 "channel %d\n"), 313 unit, chan)); 314 315 ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 316 /* Clearing enable will also clear CHAIN_DONE */ 317 ctrl &= ~(PKTDMA_ENABLE|PKTDMA_ABORT); 318 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl); 319 320 soc_pci_write(unit, 321 CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 322 (DS_DESCRD_CMPLT_CLR(chan) | DS_CNTLD_DESC_CLR(chan))); 323 SDK_CONFIG_MEMORY_BARRIER; 324 325 /* Mark channel as not started */ 326 sc->sc_dma_started = 0; 327 328 return rv; 329 } 330 331 /* 332 * Function: 333 * cmicd_dma_chan_dv_start 334 * Purpose: 335 * Adds DV to the ready queue for CMICD DMA for the specified SOC unit. 336 * Parameters: 337 * unit - SOC unit # 338 * chan - channel # 339 * Returns: 340 * SOC_E_NONE - success 341 * SOC_E_XXXX - error code 342 * Notes: 343 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 344 */ 345 static int 346 cmicd_dma_chan_dv_start(int unit, sdc_t *sc, dv_t *dv_chain) 347 { 348 int rv = SOC_E_NONE; 349 int cmc = sc->sc_channel / N_DMA_CHAN; 350 int chan = sc->sc_channel % N_DMA_CHAN; 351 dcb_t *dcb; 352 sal_paddr_t reg_addr = 0; 353 sal_paddr_t reg_val = 0; 354 355 dv_chain->dv_next = NULL; 356 357 #ifdef INCLUDE_KNET 358 if (SOC_KNET_MODE(unit)) { 359 /* KNET handling of DV start */ 360 if (sc->sc_q_cnt != 0) { 361 sc->sc_q_tail->dv_next = dv_chain; 362 } else { 363 sc->sc_q = dv_chain; 364 } 365 sc->sc_q_tail = dv_chain; 366 sc->sc_q_cnt++; 367 if (sc->sc_dv_active == NULL) { 368 if (sc->sc_dma_started) { 369 sc->sc_dv_active = sc->sc_q; 370 } else { 371 /* Start DMA if channel not active */ 372 rv = cmicd_dma_chan_start(unit, sc); 373 sc->sc_dma_started = 1; 374 } 375 } 376 return rv; 377 } 378 #endif 379 380 if (sc->sc_q_cnt != 0) { 381 sc->sc_q_tail->dv_next = dv_chain; 382 /* Set the reload addr of tail to the address of the appended chain */ 383 dcb = SOC_DCB_IDX2PTR(unit, sc->sc_q_tail->dv_dcb, 384 sc->sc_q_tail->dv_vcnt - 1); 385 SOC_DCB_ADDR_SET(dv_chain->dv_unit, dcb, 386 (sal_vaddr_t)dv_chain->dv_dcb); 387 } else { 388 sc->sc_q = dv_chain; 389 } 390 sc->sc_q_tail = dv_chain; 391 sc->sc_q_cnt++; 392 393 /* Set the HW register for the new DESC_HALT_ADDR- new for CMICDV2 */ 394 /* Need logical to physical mapping for addr */ 395 /* If DMA is currently halted, writing the new rld addr starts it again */ 396 reg_addr = (sal_paddr_t)CMIC_CMCx_DMA_CHy_DESC_HALT_ADDR_OFFSET(cmc, chan); 397 398 reg_val = soc_cm_l2p(unit, 399 (void*)SOC_DCB_IDX2PTR(unit, dv_chain->dv_dcb, 400 (dv_chain->dv_vcnt - 1))); 401 soc_pci_write(unit, reg_addr, reg_val); 402 SDK_CONFIG_MEMORY_BARRIER; 403 404 /* Start DMA if channel not active */ 405 if ((sc->sc_dv_active == NULL) && (!sc->sc_dma_started)) { 406 rv = cmicd_dma_chan_start(unit, sc); 407 sc->sc_dma_started = 1; 408 } 409 410 return rv; 411 } 412 413 /* 414 * Function: 415 * cmicd_dma_chan_chain_done 416 * Purpose: 417 * on the CMICD DMA channel for the specified SOC unit. 418 * Parameters: 419 * unit - SOC unit # 420 * chan - channel # 421 * mitigation - >0 = interrupt mitigation on 422 * Returns: 423 * SOC_E_NONE - success 424 * SOC_E_XXXX - error code 425 * Notes: 426 * INTERRUPT LEVEL ROUTINE. 427 */ 428 static int 429 cmicd_dma_chan_chain_done(int unit, int vchan, int mitigation) 430 { 431 return (soc_cmicm_dma_drv[unit].chan_chain_done(unit, vchan, mitigation)); 432 } 433 434 /* 435 * Function: 436 * cmicd_dma_chan_desc_done 437 * Purpose: 438 * Clears desc done on the CMICD DMA channel for the specified SOC unit. 439 * Parameters: 440 * unit - SOC unit # 441 * chan - channel # 442 * Returns: 443 * SOC_E_NONE - success 444 * SOC_E_XXXX - error code 445 * Notes: 446 * INTERRUPT LEVEL ROUTINE. 447 */ 448 static int 449 cmicd_dma_chan_desc_done(int unit, int vchan) 450 { 451 int rv = SOC_E_NONE; 452 int cmc = vchan / N_DMA_CHAN; 453 int chan = vchan % N_DMA_CHAN; 454 455 /* 456 * Older CMIC devices required a read/write/modify to clear done 457 * interrupts. That does not work here for continuous DMA. Need only 458 * to set the bit for the corresponding interrupt to clear. 459 */ 460 soc_pci_write(unit, 461 CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 462 DS_CNTLD_DESC_CLR(chan)); 463 464 /* Flush posted writes from PCI bridge */ 465 (void)soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 466 467 return rv; 468 } 469 470 /* 471 * Function: 472 * cmicd_dma_chan_desc_done_intr_enable 473 * Purpose: 474 * Clears desc done on the CMICD DMA channel for the specified SOC unit. 475 * Parameters: 476 * unit - SOC unit # 477 * chan - channel # 478 * Returns: 479 * SOC_E_NONE - success 480 * SOC_E_XXXX - error code 481 * Notes: 482 * INTERRUPT LEVEL ROUTINE. 483 */ 484 static int 485 cmicd_dma_chan_desc_done_intr_enable(int unit, int vchan) 486 { 487 return (soc_cmicm_dma_drv[unit].chan_desc_done_intr_enable(unit, vchan)); 488 } 489 490 /* 491 * Function: 492 * cmicd_dma_chan_reload_done 493 * Purpose: 494 * Detect for reload descriptor completed 495 * Parameters: 496 * unit - SOC unit # 497 * sc - SOC channel data structure pointer 498 * Returns: 499 * SOC_E_NONE - success 500 * SOC_E_XXXX - error code 501 * Notes: 502 */ 503 static int 504 cmicd_dma_chan_reload_done(int unit, int vchan, dcb_t * dcb, int *rld_done) 505 { 506 int rv = SOC_E_NONE; 507 uint32 *rld_dcb; 508 509 *rld_done = 0; /* Default to not reload */ 510 511 /* There is no pkt data to process for a reload descriptor */ 512 if(SOC_DCB_RELOAD_GET(unit, dcb)) { 513 /* HW sets bit 31 in the dcb's last dword to indicate done */ 514 rld_dcb = (uint32 *)dcb; 515 if (rld_dcb[DCB_LAST_DWORD] & DCB_DONE_BIT) { 516 *rld_done = 1; 517 } 518 } 519 520 return rv; 521 } 522 523 /* 524 * Function: 525 * cmicd_dma_chan_tx_purge 526 * Purpose: 527 * Purge partial pkt left in the pipeline from TX DMA abort. 528 * Parameters: 529 * unit - SOC unit # 530 * chan - channel # 531 * Returns: 532 * SOC_E_NONE - Success 533 * SOC_E_TIMEOUT - failed (Timeout) 534 * Notes: 535 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 536 */ 537 static int 538 cmicd_dma_chan_tx_purge(int unit, int vchan, dv_t *dv) 539 { 540 return (soc_cmicm_dma_drv[unit].chan_tx_purge(unit, vchan, dv)); 541 } 542 543 /* 544 * Function: 545 * cmicd_dma_chan_counter_get 546 * Purpose: 547 * Obtain tx and rx counter values 548 * Parameters: 549 * unit - SOC unit # 550 * vchan - SOC virtual channel number 551 * Returns: 552 * SOC_E_NONE - success 553 * Notes: 554 */ 555 static int 556 cmicd_dma_chan_counter_get(int unit, int vchan, uint32 *tx_pkt, uint32 *rx_pkt) 557 { 558 return (soc_cmicm_dma_drv[unit].chan_counter_get(unit, vchan, tx_pkt, rx_pkt)); 559 } 560 561 /* 562 * Function: 563 * cmicd_dma_chan_counter_clear 564 * Purpose: 565 * clear tx and rx counter values 566 * Parameters: 567 * unit - SOC unit # 568 * vchan - SOC virtual channel number 569 * mask - to clear the appopriate counter 570 * Returns: 571 * SOC_E_NONE - success 572 * Notes: 573 */ 574 static int 575 cmicd_dma_chan_counter_clear(int unit, int vchan, uint32 mask) 576 { 577 return (soc_cmicm_dma_drv[unit].chan_counter_clear(unit, vchan, mask)); 578 } 579 580 /* 581 * Function: 582 * cmicd_dma_cmc_counter_get 583 * Purpose: 584 * Obtain tx and rx counter values 585 * Parameters: 586 * unit - SOC unit # 587 * cmc - cmc number 588 * Returns: 589 * SOC_E_NONE - success 590 * Notes: 591 */ 592 static int 593 cmicd_dma_cmc_counter_get(int unit, int cmc, uint32 *tx_pkt, uint32 *rx_pkt) 594 { 595 return (soc_cmicm_dma_drv[unit].cmc_counter_get(unit, cmc, tx_pkt, rx_pkt)); 596 } 597 598 /* 599 * Function: 600 * cmicd_dma_cmc_counter_clear 601 * Purpose: 602 * clear tx and rx counter values 603 * Parameters: 604 * unit - SOC unit # 605 * cmc - cmc number 606 * mask - to clear the appopriate counter 607 * Returns: 608 * SOC_E_NONE - success 609 * Notes: 610 */ 611 static int 612 cmicd_dma_cmc_counter_clear(int unit, int cmc, uint32 mask) 613 { 614 return (soc_cmicm_dma_drv[unit].cmc_counter_clear(unit, cmc, mask)); 615 } 616 617 /* 618 * Function: 619 * cmicd_dma_chan_status_get 620 * Purpose: 621 * get channel status 622 * Parameters: 623 * unit - SOC unit # 624 * vchan - channel # 625 * status - channel status 626 * 627 * Returns: 628 * SOC_E_NONE - success 629 * SOC_E_XXXX - error code 630 * Notes: 631 */ 632 633 int 634 cmicd_dma_chan_status_get(int unit, int vchan, uint32 mask, int *status) 635 { 636 int rv = SOC_E_NONE; 637 int cmc = vchan / N_DMA_CHAN; 638 639 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 640 (BSL_META_U(unit, 641 "channel status get\n"))); 642 643 if (mask & 0x1) { 644 *status = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 645 } else if (mask & 0x2) { 646 *status = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc)); 647 } 648 649 return rv; 650 } 651 652 /* 653 * Function: 654 * cmicd_dma_chan_status_clear 655 * Purpose: 656 * clear channel status 657 * Parameters: 658 * unit - SOC unit # 659 * vchan - channel # 660 * 661 * Returns: 662 * SOC_E_NONE - success 663 * SOC_E_XXXX - error code 664 * Notes: 665 */ 666 667 int 668 cmicd_dma_chan_status_clear(int unit, int vchan) 669 { 670 int rv = SOC_E_NONE; 671 int cmc = vchan / N_DMA_CHAN; 672 673 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 674 (BSL_META_U(unit, 675 "channel status clear\n"))); 676 677 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc), 0x0); 678 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc), 0x0); 679 680 return rv; 681 } 682 683 /* 684 * Function: 685 * cmicd_dma_chan_halt_get 686 * Purpose: 687 * get channel halt status 688 * Parameters: 689 * unit - SOC unit # 690 * vchan - channel # 691 * halt - channel halt status 692 * 693 * Returns: 694 * SOC_E_NONE - success 695 * SOC_E_XXXX - error code 696 * Notes: 697 */ 698 699 int 700 cmicd_dma_chan_halt_get(int unit, int vchan, uint32 mask, int *halt) 701 { 702 int rv = SOC_E_NONE; 703 int cmc = vchan / N_DMA_CHAN; 704 int chan = vchan % N_DMA_CHAN; 705 706 *halt = (soc_pci_read(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc)) 707 & DS_CMCx_DMA_IN_HALT(chan)); 708 709 return rv; 710 } 711 712 /* 713 * Function: 714 * cmicd_dma_chan_ctrl_reg_get 715 * Purpose: 716 * get channel ctrl reg value 717 * Parameters: 718 * unit - SOC unit # 719 * vchan - channel # 720 * value - channel ctrl reg value 721 * 722 * Returns: 723 * SOC_E_NONE - success 724 * SOC_E_XXXX - error code 725 * Notes: 726 */ 727 728 int 729 cmicd_dma_chan_ctrl_reg_get(int unit, int vchan, uint32 *val) 730 { 731 return (soc_cmicm_dma_drv[unit].chan_ctrl_reg_get(unit, vchan, val)); 732 } 733 734 /* 735 * Function: 736 * cmicd_dma_chan_ctrl_reg_set 737 * Purpose: 738 * set channel ctrl reg 739 * Parameters: 740 * unit - SOC unit # 741 * vchan - channel # 742 * value - channel ctrl reg value to set 743 * 744 * Returns: 745 * SOC_E_NONE - success 746 * SOC_E_XXXX - error code 747 * Notes: 748 */ 749 750 int 751 cmicd_dma_chan_ctrl_reg_set(int unit, int vchan, uint32 val) 752 { 753 return (soc_cmicm_dma_drv[unit].chan_ctrl_reg_set(unit, vchan, val)); 754 } 755 756 /* 757 * Function: 758 * cmicd_dma_chan_cos_ctrl_get 759 * Purpose: 760 * get cos ctrl for a channel 761 * Parameters: 762 * unit - SOC unit # 763 * cfg - to choose appropriate register 764 * Returns: 765 * SOC_E_NONE - success 766 * SOC_E_XXXX - error code 767 * Notes: 768 */ 769 770 int 771 cmicd_dma_chan_cos_ctrl_get(int unit, int vchan, uint32 cfg, uint32 *cos_ctrl) 772 { 773 return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_get(unit, vchan, cfg, cos_ctrl)); 774 } 775 776 /* 777 * Function: 778 * cmicd_dma_chan_cos_ctrl_set 779 * Purpose: 780 * get cos ctrl for a channel 781 * Parameters: 782 * unit - SOC unit # 783 * cfg - to choose appropriate register 784 * Returns: 785 * SOC_E_NONE - success 786 * SOC_E_XXXX - error code 787 * Notes: 788 */ 789 790 int 791 cmicd_dma_chan_cos_ctrl_set(int unit, int vchan, uint32 cfg, uint32 cos_ctrl) 792 { 793 return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_set(unit, vchan, cfg, cos_ctrl)); 794 } 795 796 /* 797 * Function: 798 * cmicd_dma_chan_cos_ctrl_queue_get 799 * Purpose: 800 * get cos ctrl for a channel based on queue 801 * Parameters: 802 * unit - SOC unit # 803 * cmc - CMC # 804 * chan - chan # 805 * queue - cos queue 806 * cos_ctrl - cos ctrl val 807 * Returns: 808 * SOC_E_NONE - success 809 * SOC_E_XXXX - error code 810 * Notes: 811 */ 812 813 int 814 cmicd_dma_chan_cos_ctrl_queue_get(int unit, int cmc, int chan, 815 int queue, uint32 *cos_ctrl) 816 { 817 return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_queue_get(unit, cmc, chan, queue, cos_ctrl)); 818 } 819 820 /* 821 * Function: 822 * cmicd_dma_chan_cos_ctrl_reg_addr_get 823 * Purpose: 824 * get cos ctrl for a channel based on queue 825 * Parameters: 826 * unit - SOC unit # 827 * cmc - CMC # 828 * chan - chan # 829 * queue - cos queue 830 * reg_addr - reg addr val 831 * Returns: 832 * SOC_E_NONE - success 833 * SOC_E_XXXX - error code 834 * Notes: 835 */ 836 837 int 838 cmicd_dma_chan_cos_ctrl_reg_addr_get(int unit, int cmc, int chan, 839 int queue, uint32 *reg_addr) 840 { 841 return (soc_cmicm_dma_drv[unit].chan_cos_ctrl_reg_addr_get(unit, cmc, chan, queue, reg_addr)); 842 } 843 844 /* 845 * Function: 846 * cmicd_dma_chan_rxbuf_threshold_config 847 * Purpose: 848 * appropriately set mmu back pressure 849 * Parameters: 850 * unit - SOC unit # 851 * vchan - channel # 852 * value - mmu backpressure settings 853 * 854 * Returns: 855 * SOC_E_NONE - success 856 * SOC_E_XXXX - error code 857 * Notes: 858 */ 859 860 int 861 cmicd_dma_chan_rxbuf_threshold_config(int unit, int vchan, uint32 val) 862 { 863 return (soc_cmicm_dma_drv[unit].chan_rxbuf_threshold_cfg(unit, vchan, val)); 864 } 865 866 /* 867 * Function: 868 * cmicd_dma_masks_get 869 * Purpose: 870 * obtain the individual big endian masks 871 * Parameters: 872 * unit - SOC unit # 873 * pkt_endian - pkt endian mask 874 * desc_endian - desc endian mask 875 * header_endian - header endian mask 876 * 877 * Returns: 878 * SOC_E_NONE - success 879 * SOC_E_XXXX - error code 880 * Notes: 881 */ 882 883 int 884 cmicd_dma_masks_get(int unit, uint32 *pkt_endian, uint32 *desc_endian, uint32 *header_endian) 885 { 886 return (soc_cmicm_dma_drv[unit].masks_get(unit, pkt_endian, desc_endian, header_endian)); 887 } 888 889 /* 890 * Function: 891 * cmicd_dma_header_size_get 892 * Purpose: 893 * obtain the ep to cpu header size 894 * Parameters: 895 * unit - SOC unit # 896 * hdr_size - return value of the ep to cpu header size 897 * 898 * Returns: 899 * SOC_E_NONE - success 900 * SOC_E_XXXX - error code 901 * Notes: 902 */ 903 904 int 905 cmicd_dma_header_size_get(int unit, uint32 *hdr_size) 906 { 907 return (soc_cmicm_dma_drv[unit].header_size_get(unit, hdr_size)); 908 } 909 910 /* 911 * Function: 912 * cmicd_dma_max_rx_channels_get 913 * Purpose: 914 * obtain maximum number of dma channels that can be used for BCM RX 915 * Parameters: 916 * unit - SOC unit # 917 * max_rx_channels - maximum rx channels that can be used 918 * Returns: 919 * SOC_E_NONE - success 920 * SOC_E_XXXX - error 921 */ 922 923 static int 924 cmicd_dma_max_rx_channels_get(int unit, uint32 *max_rx_channels) 925 { 926 return (soc_cmicm_dma_drv[unit].max_rx_channels_get(unit, max_rx_channels)); 927 } 928 929 /* 930 * Function: 931 * cmicd_dma_init 932 * Purpose: 933 * Initialize the CMICD DMA for the specified SOC unit. 934 * Parameters: 935 * unit - SOC unit # 936 * Returns: 937 * SOC_E_NONE - success 938 * SOC_E_XXXX - error code 939 * Notes: 940 */ 941 static int 942 cmicd_dma_init(int unit) 943 { 944 return (soc_cmicm_dma_drv[unit].init(unit)); 945 } 946 947 /* 948 * Function: 949 * cmicd_dma_pci_timeout_handle 950 * Purpose: 951 * Handle the PCI timeout error. 952 * Parameters: 953 * unit - SOC unit # 954 * sc - SOC channel data structure pointer 955 * Returns: 956 * SOC_E_NONE - success 957 * SOC_E_XXXX - error code 958 * Notes: 959 */ 960 static int 961 cmicd_dma_pci_timeout_handle(int unit) 962 { 963 return (soc_cmicm_dma_drv[unit].pci_timeout_handle(unit)); 964 } 965 966 967 968 /* Public Assignment Function */ 969 970 /* 971 * Function: 972 * soc_cmicd_dma_drv_init 973 * Purpose: 974 * Initialize the CMICD DMA driver for the specified SOC unit. 975 * Assign function pointers for SOC DMA driver interface. 976 * Parameters: 977 * unit - SOC unit # 978 * drv - pointer to the function vector list 979 * Returns: 980 * SOC_E_NONE - success 981 * SOC_E_XXXX - error code 982 * Notes: 983 */ 984 int 985 soc_cmicd_dma_drv_init(int unit, soc_cmic_dma_drv_t *drv) 986 { 987 int rv = SOC_E_NONE; 988 989 drv->init = cmicd_dma_init; 990 drv->ctrl_init = cmicd_dma_ctrl_init; 991 drv->chan_config = cmicd_dma_chan_config; 992 drv->chan_dv_start = cmicd_dma_chan_dv_start; 993 drv->chan_start = cmicd_dma_chan_start; 994 drv->chan_poll = cmicd_dma_chan_poll; 995 drv->chan_abort = cmicd_dma_chan_abort; 996 drv->chan_tx_purge = cmicd_dma_chan_tx_purge; 997 drv->chan_desc_done_intr_enable = cmicd_dma_chan_desc_done_intr_enable; 998 drv->chan_desc_done = cmicd_dma_chan_desc_done; 999 drv->chan_chain_done = cmicd_dma_chan_chain_done; 1000 drv->chan_reload_done = cmicd_dma_chan_reload_done; 1001 drv->chan_counter_get = cmicd_dma_chan_counter_get; 1002 drv->chan_counter_clear = cmicd_dma_chan_counter_clear; 1003 drv->chan_cos_ctrl_get = cmicd_dma_chan_cos_ctrl_get; 1004 drv->chan_cos_ctrl_set = cmicd_dma_chan_cos_ctrl_set; 1005 drv->chan_cos_ctrl_queue_get = cmicd_dma_chan_cos_ctrl_queue_get; 1006 drv->chan_cos_ctrl_reg_addr_get = cmicd_dma_chan_cos_ctrl_reg_addr_get; 1007 drv->chan_status_get = cmicd_dma_chan_status_get; 1008 drv->chan_status_clear = cmicd_dma_chan_status_clear; 1009 drv->chan_halt_get = cmicd_dma_chan_halt_get; 1010 drv->chan_ctrl_reg_get = cmicd_dma_chan_ctrl_reg_get; 1011 drv->chan_ctrl_reg_set = cmicd_dma_chan_ctrl_reg_set; 1012 drv->chan_rxbuf_threshold_cfg = cmicd_dma_chan_rxbuf_threshold_config; 1013 drv->cmc_rxbuf_threshold_cfg = NULL; 1014 drv->cmc_counter_get = cmicd_dma_cmc_counter_get; 1015 drv->cmc_counter_clear = cmicd_dma_cmc_counter_clear; 1016 drv->loopback_config = NULL; 1017 drv->masks_get = cmicd_dma_masks_get; 1018 drv->header_size_get = cmicd_dma_header_size_get; 1019 drv->max_rx_channels_get = cmicd_dma_max_rx_channels_get; 1020 drv->pci_timeout_handle = cmicd_dma_pci_timeout_handle; 1021 1022 soc_cmicm_dma_drv_init(unit, &soc_cmicm_dma_drv[unit]); 1023 1024 return rv; 1025 } 1026 1027 #endif /* BCM_CMICDV2_SUPPORT */