cmicm_dma.c (42912B)
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: CMICM 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 #include <soc/iproc.h> 22 23 #ifdef INCLUDE_KNET 24 #include <soc/knet.h> 25 #endif 26 27 #ifdef BCM_CMICM_SUPPORT 28 29 /* Static Driver Functions */ 30 31 /*! 32 * Dump registers for a channel 33 */ 34 static void 35 cmicm_pdma_chan_reg_dump(int unit, int vchan) 36 { 37 uint32 val = 0, val2 = 0; 38 int cmc, chan; 39 40 cmc = vchan / N_DMA_CHAN; 41 chan = vchan % N_DMA_CHAN; 42 43 val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 44 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 45 (BSL_META_U(unit, 46 "CMIC_CMC%d_CH%d_DMA_CTRL: 0x%08x\n"), 47 cmc, chan, val)); 48 49 val = soc_pci_read(unit, CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan)); 50 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 51 (BSL_META_U(unit, 52 "CMIC_CMC%d_DMA_DESC%d: 0x%08x\n"), 53 cmc, chan, val)); 54 55 val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CURR_DESC_OFFSET(cmc, chan)); 56 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 57 (BSL_META_U(unit, 58 "CMIC_CMC%d_CH%d_DMA_CURR_DESC: 0x%08x\n"), 59 cmc, chan, val)); 60 61 val = soc_pci_read(unit, 62 CMIC_CMCx_DMA_CHy_DESC_HALT_ADDR_OFFSET(cmc, chan)); 63 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 64 (BSL_META_U(unit, 65 "CMIC_CMC%d_DMA_CH%d_DESC_HALT_ADDR: 0x%08x\n"), 66 cmc, chan, val)); 67 68 val = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan)); 69 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 70 (BSL_META_U(unit, 71 "CMIC_CMC%d_CH%d_COS_CTRL_RX_0: 0x%08x\n"), 72 cmc, chan, val)); 73 74 val = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan)); 75 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 76 (BSL_META_U(unit, 77 "CMIC_CMC%d_CH%d_COS_CTRL_RX_1: 0x%08x\n"), 78 cmc, chan, val)); 79 80 val = soc_pci_read(unit, CMIC_CMCx_PROGRAMMABLE_COS_MASK0_OFFSET(cmc)); 81 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 82 (BSL_META_U(unit, 83 "CMIC_CMC%d_PROGRAMMABLE_COS_MASK0: 0x%08x\n"), 84 cmc, val)); 85 86 val = soc_pci_read(unit, CMIC_CMCx_PROGRAMMABLE_COS_MASK1_OFFSET(cmc)); 87 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 88 (BSL_META_U(unit, 89 "CMIC_CMC%d_PROGRAMMABLE_COS_MASK1: 0x%08x\n"), 90 cmc, val)); 91 92 val = soc_pci_read(unit, CMIC_CMCx_DMA_CHy_INTR_COAL_OFFSET(cmc, chan)); 93 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 94 (BSL_META_U(unit, 95 "CMIC_CMC%d_DMA_CH%d_INTR_COAL: 0x%08x\n"), 96 cmc, chan, val)); 97 switch (chan) { 98 case 0: 99 val = soc_pci_read(unit, 100 CMIC_CMCx_CH0_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc)); 101 break; 102 case 1: 103 val = soc_pci_read(unit, 104 CMIC_CMCx_CH1_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc)); 105 break; 106 case 2: 107 val = soc_pci_read(unit, 108 CMIC_CMCx_CH2_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc)); 109 break; 110 case 3: 111 val = soc_pci_read(unit, 112 CMIC_CMCx_CH3_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc)); 113 break; 114 default: 115 break; 116 } 117 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 118 (BSL_META_U(unit, 119 "CMIC_CMC%d_CH%d_RXBUF_THRESHOLD_CONFIG:" 120 " 0x%08x\n"), 121 cmc, chan, val)); 122 123 val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 124 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 125 (BSL_META_U(unit, 126 "CMIC_CMC%d_DMA_STAT: 0x%08x\n"), 127 cmc, val)); 128 129 val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_HI_OFFSET(cmc)); 130 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 131 (BSL_META_U(unit, 132 "CMIC_CMC%d_DMA_STAT_HI: 0x%08x\n"), 133 cmc, val)); 134 135 val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc)); 136 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 137 (BSL_META_U(unit, 138 "CMIC_CMC%d_DMA_STAT_CLR: 0x%08x\n"), 139 cmc, val)); 140 switch (chan) { 141 case 0: 142 val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH0_RXPKT_OFFSET(cmc)); 143 val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH0_TXPKT_OFFSET(cmc)); 144 break; 145 case 1: 146 val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH1_RXPKT_OFFSET(cmc)); 147 val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH1_TXPKT_OFFSET(cmc)); 148 break; 149 case 2: 150 val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH2_RXPKT_OFFSET(cmc)); 151 val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH2_TXPKT_OFFSET(cmc)); 152 break; 153 case 3: 154 val = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH3_RXPKT_OFFSET(cmc)); 155 val2 = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CH3_TXPKT_OFFSET(cmc)); 156 break; 157 default: 158 break; 159 } 160 if (chan < N_DMA_CHAN) { 161 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 162 (BSL_META_U(unit, 163 "CMIC_CMC%d_PKT_COUNT_CH%d_RXPKT: 0x%08x\n"), 164 cmc, chan, val)); 165 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 166 (BSL_META_U(unit, 167 "CMIC_CMC%d_PKT_COUNT_CH%d_TXPKT: 0x%08x\n"), 168 cmc, chan, val2)); 169 } 170 171 val = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 172 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 173 (BSL_META_U(unit, 174 "CMIC_CMC%d_IRQ_STAT0: 0x%08x\n"), 175 cmc, val)); 176 177 val = soc_pci_read(unit, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc)); 178 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 179 (BSL_META_U(unit, 180 "CMIC_CMC%d_PCIE_IRQ_MASK0: 0x%08x\n"), 181 cmc, val)); 182 } 183 184 /* 185 * Function: 186 * cmicm_dma_chan_config 187 * Purpose: 188 * Initialize the CMICM DMA channel for the specified SOC unit. 189 * Parameters: 190 * unit - SOC unit # 191 * chan - channel # 192 * type - tx or rx 193 * f_intr - interrupt flags 194 * Returns: 195 * SOC_E_NONE - success 196 * SOC_E_XXXX - error code 197 * Notes: 198 */ 199 static int 200 cmicm_dma_chan_config(int unit, int vchan, dvt_t type, uint32 flags) 201 { 202 int rv = SOC_E_NONE; 203 soc_control_t *soc = SOC_CONTROL(unit); 204 sdc_t *sc = &soc->soc_channels[vchan]; 205 uint32 bits; 206 int cmc = vchan / N_DMA_CHAN; 207 int chan = vchan % N_DMA_CHAN; 208 uint32 cr; 209 210 /* Define locals and turn flags into easy to use things */ 211 /*int f_mbm = (flags & SOC_DMA_F_MBM) != 0; */ 212 int f_interrupt = (flags & SOC_DMA_F_POLL) == 0; 213 /*int f_drop = (flags & SOC_DMA_F_TX_DROP) != 0; */ 214 int f_default = (flags & SOC_DMA_F_DEFAULT) != 0; 215 int f_desc_intr = (flags & SOC_DMA_F_INTR_ON_DESC) != 0; 216 int init_hw = TRUE; 217 218 /* Initial state of channel */ 219 sc->sc_flags = 0; /* Clear flags to start */ 220 221 #ifdef INCLUDE_KNET 222 if (SOC_KNET_MODE(unit) && SOC_WARM_BOOT(unit) && 223 soc_property_get(unit, spn_WARMBOOT_KNET_SHUTDOWN_MODE, 0)) { 224 init_hw = FALSE; 225 } 226 #endif 227 228 if (init_hw) { 229 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_DESC_DONE(chan) | 230 IRQ_CMCx_CHAIN_DONE(chan)); 231 232 cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan)); 233 cr &= ~PKTDMA_ENABLE; /* clearing enable will also clear CHAIN_DONE */ 234 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan), cr); 235 236 cr = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc)); 237 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 238 (cr | DS_DESCRD_CMPLT_CLR(chan))); 239 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), cr); 240 } 241 /* Setup new mode */ 242 /* MBM Deprecated in CMICm */ 243 /* DROP_TX Deprecated in CMICm */ 244 bits = f_desc_intr ? PKTDMA_SEL_INTR_ON_DESC_OR_PKT : 0; 245 246 if (type == DV_TX) { 247 bits |= PKTDMA_DIRECTION; 248 if (f_default) { 249 soc->soc_dma_default_tx = sc; 250 } 251 } else if (type == DV_RX) { 252 bits &= ~PKTDMA_DIRECTION; 253 if (f_default) { 254 soc->soc_dma_default_rx = sc; 255 } 256 } else if (type == DV_NONE) { 257 f_interrupt = FALSE; /* Force off */ 258 } else { 259 assert(0); 260 } 261 262 #ifdef INCLUDE_KNET 263 if (SOC_KNET_MODE(unit)) { 264 /* Interrupt are handled by kernel */ 265 f_interrupt = FALSE; 266 } 267 #endif 268 269 if (f_interrupt) { 270 (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_DESC_DONE(chan) 271 | IRQ_CMCx_CHAIN_DONE(chan)); 272 } 273 274 sc->sc_type = type; 275 if (init_hw) { 276 cr = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan)); 277 /* clear everything except Endianess */ 278 cr &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN); 279 cr |= bits; 280 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), cr); 281 } 282 283 return rv; 284 } 285 286 /* 287 * Function: 288 * cmicm_dma_chan_start 289 * Purpose: 290 * Start the CMICM DMA channel for the specified SOC unit. 291 * Parameters: 292 * unit - SOC unit # 293 * sc - SOC channel data structure pointer 294 * Returns: 295 * SOC_E_NONE - success 296 * SOC_E_XXXX - error code 297 * Notes: 298 */ 299 static int 300 cmicm_dma_chan_start(int unit, sdc_t *sc) 301 { 302 int rv = SOC_E_NONE; 303 dv_t *dv; 304 int cmc = sc->sc_channel / N_DMA_CHAN; 305 int chan = sc->sc_channel % N_DMA_CHAN; 306 uint32 val; 307 308 if ((dv = sc->sc_dv_active = sc->sc_q) == NULL) { 309 sc->sc_q_tail = NULL; 310 return rv; 311 } 312 313 #ifdef INCLUDE_KNET 314 if (SOC_KNET_MODE(unit)) { 315 return rv; 316 } 317 #endif 318 319 /* Set up DMA descriptor address */ 320 soc_pci_write(unit, CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan), 321 soc_cm_l2p(unit, sc->sc_q->dv_dcb)); 322 323 if (sc->sc_flags & SOC_DMA_F_CLR_CHN_DONE) { 324 /* Clearing CMIC_CMC(0..2)_CH(0..3)_DMA_CTRL.ENABLE will 325 * clear CMIC_CMC(0..2)_DMA_STAT.CHAIN_DONE bit. 326 */ 327 val = soc_pci_read(unit, 328 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 329 val &= ~PKTDMA_ENABLE; 330 soc_pci_write(unit, 331 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), 332 val); 333 } else { 334 sc->sc_flags |= SOC_DMA_F_CLR_CHN_DONE; 335 } 336 337 /* Start DMA */ 338 if (bsl_check(bslLayerSoc, bslSourcePacketdma, bslSeverityNormal, unit)) { 339 cmicm_pdma_chan_reg_dump(unit ,sc->sc_channel); 340 } 341 val = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 342 val |= PKTDMA_ENABLE; 343 344 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val); 345 346 SDK_CONFIG_MEMORY_BARRIER; 347 348 if (!(sc->sc_flags & SOC_DMA_F_POLL)) { 349 (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_CHAIN_DONE(chan)); 350 } 351 352 return rv; 353 } 354 355 /* 356 * Function: 357 * cmicm_dma_chan_dv_start 358 * Purpose: 359 * Adds DV to the ready queue for CMICM DMA for the specified SOC unit. 360 * Parameters: 361 * unit - SOC unit # 362 * chan - channel # 363 * Returns: 364 * SOC_E_NONE - success 365 * SOC_E_XXXX - error code 366 * Notes: 367 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 368 */ 369 static int 370 cmicm_dma_chan_dv_start(int unit, sdc_t *sc, dv_t *dv_chain) 371 { 372 int rv = SOC_E_NONE; 373 #define DV_CHAINS_MAX 9 374 static dv_t *dcs[N_DMA_CHAN][DV_CHAINS_MAX]; 375 static int di[N_DMA_CHAN] = {0}; 376 int ch; 377 378 dv_chain->dv_next = NULL; 379 if (sc->sc_q_cnt != 0) { 380 sc->sc_q_tail->dv_next = dv_chain; 381 } else { 382 sc->sc_q = dv_chain; 383 } 384 sc->sc_q_tail = dv_chain; 385 sc->sc_q_cnt++; 386 387 /* WAR: fix chain done interrupt lost issue caused by BCMSIM */ 388 if (SAL_BOOT_BCMSIM) { 389 ch = sc->sc_channel % N_DMA_CHAN; 390 dcs[ch][di[ch]] = dv_chain; 391 di[ch] = (di[ch] + 1) % DV_CHAINS_MAX; 392 if (sc->sc_dv_active == NULL && sc->sc_q_cnt > 1) { 393 sc->sc_q = dcs[ch][(di[ch] - sc->sc_q_cnt + 1 + DV_CHAINS_MAX) % DV_CHAINS_MAX]; 394 sc->sc_q_cnt--; 395 return cmicm_dma_chan_start(unit, sc); 396 } 397 } 398 399 if (sc->sc_q_cnt == 1) { /* Start DMA if channel not active */ 400 rv = cmicm_dma_chan_start(unit, sc); 401 } 402 403 return rv; 404 } 405 406 /* 407 * Function: 408 * cmicm_dma_chan_poll 409 * Purpose: 410 * Poll the CMICM DMA channel for the specified SOC unit. 411 * Parameters: 412 * unit - SOC unit # 413 * chan - channel # 414 * type - poll type (chain done or desc done) 415 * detected - poll result pointer to be updated 416 * Returns: 417 * SOC_E_NONE - success 418 * SOC_E_XXXX - error code 419 * Notes: 420 * Assumes that SOC_DMA_LOCK is held when called. 421 */ 422 int 423 cmicm_dma_chan_poll(int unit, 424 int vchan, 425 soc_dma_poll_type_t type, 426 int * detected) 427 { 428 int rv = SOC_E_NONE; 429 int cmc = vchan / N_DMA_CHAN; 430 int chan = vchan % N_DMA_CHAN; 431 432 switch (type) { 433 case SOC_DMA_POLL_DESC_DONE: 434 *detected = ( soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 435 & DS_CMCx_DMA_DESC_DONE(chan) ); 436 break; 437 case SOC_DMA_POLL_CHAIN_DONE: 438 *detected = ( soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 439 & DS_CMCx_DMA_CHAIN_DONE(chan) ); 440 break; 441 default: 442 break; 443 } 444 445 return rv; 446 } 447 448 /* 449 * Function: 450 * cmicm_dma_chan_abort 451 * Purpose: 452 * Initialize the CMICM DMA channel for the specified SOC unit. 453 * Parameters: 454 * unit - SOC unit # 455 * chan - channel # 456 * type - tx or rx 457 * f_intr - interrupt flags 458 * Returns: 459 * SOC_E_NONE - Success 460 * SOC_E_TIMEOUT - failed (Timeout) 461 * Notes: 462 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 463 */ 464 static int 465 cmicm_dma_chan_abort(int unit, int vchan) 466 { 467 int rv = SOC_E_NONE; 468 469 int cmc = vchan / N_DMA_CHAN; 470 int chan = vchan % N_DMA_CHAN; 471 int to; 472 uint32 ctrl; 473 uint32 val; 474 475 if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 476 & DS_CMCx_DMA_ACTIVE(chan)) != 0) { 477 ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 478 ctrl |= PKTDMA_ENABLE; 479 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl); 480 soc_pci_write(unit, 481 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), 482 ctrl | PKTDMA_ABORT); 483 SDK_CONFIG_MEMORY_BARRIER; 484 485 to = soc_property_get(unit, spn_PDMA_TIMEOUT_USEC, 500000); 486 while ((to >= 0) && 487 ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 488 & DS_CMCx_DMA_ACTIVE(chan)) != 0)) { 489 sal_udelay(1000); 490 to -= 1000; 491 } 492 if ((soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) 493 & DS_CMCx_DMA_ACTIVE(chan)) != 0) { 494 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 495 (BSL_META_U(unit, 496 "soc_dma_abort_channel unit %d: " 497 "channel %d abort timeout\n"), 498 unit, chan)); 499 rv = SOC_E_TIMEOUT; 500 if (SOC_WARM_BOOT(unit)) { 501 return rv; 502 } 503 } 504 } 505 ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 506 /* Clearing enable will also clear CHAIN_DONE */ 507 ctrl &= ~(PKTDMA_ENABLE|PKTDMA_ABORT); 508 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), ctrl); 509 510 val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc)); 511 soc_pci_write(unit, 512 CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 513 (val | DS_DESCRD_CMPLT_CLR(chan))); 514 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), val); 515 SDK_CONFIG_MEMORY_BARRIER; 516 517 return rv; 518 } 519 520 /* 521 * Function: 522 * cmicm_dma_chan_desc_done 523 * Purpose: 524 * Clears desc done on the CMICM DMA channel for the specified SOC unit. 525 * Parameters: 526 * unit - SOC unit # 527 * chan - channel # 528 * Returns: 529 * SOC_E_NONE - success 530 * SOC_E_XXXX - error code 531 * Notes: 532 * INTERRUPT LEVEL ROUTINE. 533 */ 534 static int 535 cmicm_dma_chan_desc_done(int unit, int vchan) 536 { 537 int rv = SOC_E_NONE; 538 int cmc = vchan / N_DMA_CHAN; 539 int chan = vchan % N_DMA_CHAN; 540 uint32 val; 541 542 /* Do we still need to generate an edge for CMICm and newer devices? */ 543 val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc)); 544 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 545 (val | DS_DESCRD_CMPLT_CLR(chan))); 546 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), val); 547 548 /* Flush posted writes from PCI bridge */ 549 (void)soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 550 551 return rv; 552 } 553 554 /* 555 * Function: 556 * cmicm_dma_ctrl_init 557 * Purpose: 558 * Initialize the CMICM DMA Control to a known good state for 559 * the specified SOC unit. 560 * Parameters: 561 * unit - SOC unit # 562 * Returns: 563 * SOC_E_NONE - success 564 * SOC_E_XXXX - error code 565 * Notes: 566 */ 567 568 static int 569 cmicm_dma_ctrl_init(int unit) 570 { 571 int rv = SOC_E_NONE; 572 int cmc; 573 uint32 val, chan, vchan; 574 575 for(vchan=0; vchan < SOC_DCHAN_NUM(unit); vchan++) { 576 cmc = vchan / N_DMA_CHAN; 577 chan = vchan % N_DMA_CHAN; 578 val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 579 val &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN); 580 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val); 581 } 582 583 /* Set to Legacy Mode */ 584 SOC_DMA_MODE(unit) = SOC_DMA_MODE_CHAINED; 585 586 /* 587 * This has to be done only once after both CMIC and EP blocks 588 * are out of reset. 589 */ 590 soc_pci_write(unit, CMIC_RXBUF_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0); 591 soc_pci_write(unit, CMIC_RXBUF_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1); 592 593 return rv; 594 } 595 596 /* 597 * Function: 598 * cmicm_dma_init 599 * Purpose: 600 * Initialize the CMICM DMA for the specified SOC unit. 601 * Parameters: 602 * unit - SOC unit # 603 * Returns: 604 * SOC_E_NONE - success 605 * SOC_E_XXXX - error code 606 * Notes: 607 */ 608 609 static int 610 cmicm_dma_init(int unit) 611 { 612 int rv = SOC_E_NONE; 613 #ifdef BCM_TOMAHAWK_SUPPORT 614 615 int cmc = 0; 616 uint32 mask; 617 618 /* Enable PCI completion time out recovery only for Tomahawk */ 619 if (SOC_IS_TOMAHAWK(unit)) { 620 /*Clear all PAXB interrupts */ 621 (void)READ_PAXB_0_PAXB_INTR_CLEARr(unit, &mask); 622 mask = ~(uint32)0x0; 623 (void)WRITE_PAXB_0_PAXB_INTR_CLEARr(unit, mask); 624 625 /* Only enable PCIE_CMPL_TIMEOUT_INTR */ 626 mask = PCIE_CMPL_TIMEOUT_INTR_MASK; 627 (void)WRITE_PAXB_0_PAXB_INTR_ENr(unit, mask); 628 629 /* Enabling PCIe completion timeout interrupt */ 630 for(cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) { 631 soc_cmicm_cmcx_intr2_enable(unit, cmc, IRQ_CMCx_PCI_CMPL_MASK); 632 } 633 } 634 #endif 635 return rv; 636 } 637 638 /* 639 * Function: 640 * cmicd_dma_pci_timeout_handle 641 * Purpose: 642 * Handle the PCI timeout error. 643 * Parameters: 644 * unit - SOC unit # 645 * sc - SOC channel data structure pointer 646 * Returns: 647 * SOC_E_NONE - success 648 * SOC_E_XXXX - error code 649 * Notes: 650 */ 651 static int 652 cmicm_dma_pci_timeout_handle(int unit) 653 { 654 int rv = SOC_E_NONE; 655 #ifdef BCM_TOMAHAWK_SUPPORT 656 int cmc = 0; 657 int chan; 658 uint32 stat, stat_paxb, clr_pxab; 659 uint32 val; 660 soc_control_t *soc = SOC_CONTROL(unit); 661 sdc_t *sc; 662 dcb_t *dcb; 663 int intr_clr = 0; 664 665 if (SOC_IS_TOMAHAWK(unit)) { 666 (void)READ_PAXB_0_PAXB_INTR_STATUSr(unit, &stat_paxb); 667 /* Check CMIC_CMC0_IRQ_STAT2.bit[19] is set */ 668 for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) { 669 stat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 670 if (stat & IRQ_CMCx_PCI_CMPL_MASK) { 671 /* Check if PAXB PCI complete timeout bit is set */ 672 if (stat_paxb & PCIE_CMPL_TIMEOUT_INTR_MASK) { 673 /* Check if address decode err is set. */ 674 stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 675 for (chan = 0; chan < N_DMA_CHAN; chan++) { 676 /* If set, issue s/w abort to that channel */ 677 if (DS_CMCx_DMA_ADDR_DECODE_ERR(chan) & stat) { 678 int vchan = cmc * N_DMA_CHAN + chan; 679 rv = cmicm_dma_chan_abort(unit, vchan); 680 /*Clear PCIe completion timeout interrupt, before starting DMA */ 681 (void)READ_PAXB_0_PAXB_INTR_CLEARr(unit, &clr_pxab); 682 clr_pxab |= PCIE_CMPL_TIMEOUT_INTR_MASK; 683 (void)WRITE_PAXB_0_PAXB_INTR_CLEARr(unit, clr_pxab); 684 soc->stat.pci_cmpl_timeout++; 685 intr_clr = 1; 686 sc = &soc->soc_channels[vchan]; 687 if (sc->sc_dv_active->dv_op == DV_RX) { 688 dcb = SOC_DCB_IDX2PTR(unit, sc->sc_dv_active->dv_dcb, 689 sc->sc_dv_active->dv_dcnt); 690 soc_pci_write(unit, 691 CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan), 692 soc_cm_l2p(unit, dcb)); 693 } 694 val = soc_pci_read(unit, 695 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 696 val |= PKTDMA_ENABLE; 697 soc_pci_write(unit, 698 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val); 699 } 700 } 701 } 702 } 703 } 704 /* In case interrupt is not handled print status registers , clear PCI timeout interrupt*/ 705 if (!intr_clr) { 706 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 707 (BSL_META_U(unit, "Unhandled interrupt\n"))); 708 (void)READ_PAXB_0_PAXB_INTR_STATUSr(unit, &stat); 709 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 710 (BSL_META_U(unit, "PAXB_0_PAXB_INTR_STATUS = 0x%x\n"), stat)); 711 for (cmc = 0; cmc < SOC_PCI_CMCS_NUM(unit); cmc++) { 712 stat = soc_pci_read(unit, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 713 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 714 (BSL_META_U(unit, "CMIC_CMCx_IRQ_STAT2_OFFSET[%d] = 0x%x\n"), 715 cmc, stat)); 716 stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 717 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 718 (BSL_META_U(unit, "CMIC_CMCx_DMA_STAT_OFFSET[%d] = 0x%x\n"), 719 cmc, stat)); 720 } 721 /* Clear PCIe completion timeout interrupt */ 722 (void)READ_PAXB_0_PAXB_INTR_CLEARr(unit, &clr_pxab); 723 clr_pxab |= PCIE_CMPL_TIMEOUT_INTR_MASK; 724 (void)WRITE_PAXB_0_PAXB_INTR_CLEARr(unit, clr_pxab); 725 soc->stat.pci_cmpl_timeout++; 726 } 727 } 728 #endif 729 return rv; 730 } 731 732 /* 733 * Function: 734 * cmicm_dma_chan_chain_done 735 * Purpose: 736 * on the CMICM DMA channel for the specified SOC unit. 737 * Parameters: 738 * unit - SOC unit # 739 * chan - channel # 740 * mitigation - >0 = interrupt mitigation on 741 * Returns: 742 * SOC_E_NONE - success 743 * SOC_E_XXXX - error code 744 * Notes: 745 * INTERRUPT LEVEL ROUTINE. 746 */ 747 static int 748 cmicm_dma_chan_chain_done(int unit, int vchan, int mitigation) 749 { 750 int rv = SOC_E_NONE; 751 int cmc = vchan / N_DMA_CHAN; 752 int chan = vchan % N_DMA_CHAN; 753 uint32 val; 754 755 if (mitigation) { 756 (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, 757 IRQ_CMCx_DESC_DONE(chan) 758 | IRQ_CMCx_CHAIN_DONE(chan)); 759 } else { 760 (void)soc_cmicm_cmcx_intr0_disable(unit, 761 cmc, IRQ_CMCx_CHAIN_DONE(chan)); 762 } 763 /* Enable DMA */ 764 val = soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan)); 765 val &= ~PKTDMA_ENABLE; 766 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan), val); 767 768 /* Clear the descriptor read complete stat bit */ 769 val = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc)); 770 soc_pci_write(unit, 771 CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 772 (val | DS_DESCRD_CMPLT_CLR(chan))); 773 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), val); 774 775 /* Flush posted writes from PCI bridge */ 776 (void)soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 777 778 return rv; 779 } 780 781 /* 782 * Function: 783 * cmicm_dma_chan_counter_get 784 * Purpose: 785 * Obtain tx and rx counter values 786 * Parameters: 787 * unit - SOC unit # 788 * vchan - SOC virtual channel number 789 * Returns: 790 * SOC_E_NONE - success 791 * Notes: 792 */ 793 static int 794 cmicm_dma_chan_counter_get(int unit, int vchan, uint32 *tx_pkt, uint32 *rx_pkt) 795 { 796 int rv = SOC_E_NONE; 797 int cmc = vchan / N_DMA_CHAN; 798 int chan = vchan % N_DMA_CHAN; 799 800 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 801 (BSL_META_U(unit, 802 "channel counter get\n"))); 803 804 *tx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CHy_TXPKT_OFFSET(cmc, chan)); 805 *rx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_CHy_RXPKT_OFFSET(cmc, chan)); 806 807 return rv; 808 } 809 810 /* 811 * Function: 812 * cmicm_dma_chan_counter_clear 813 * Purpose: 814 * clear tx and rx counter values 815 * Parameters: 816 * unit - SOC unit # 817 * vchan - SOC virtual channel number 818 * mask - to clear the appopriate counter 819 * Returns: 820 * SOC_E_NONE - success 821 * Notes: 822 */ 823 static int 824 cmicm_dma_chan_counter_clear(int unit, int vchan, uint32 mask) 825 { 826 int rv = SOC_E_NONE; 827 int cmc = vchan / N_DMA_CHAN; 828 int chan = vchan % N_DMA_CHAN; 829 830 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 831 (BSL_META_U(unit, 832 "channel counter clear\n"))); 833 834 if (mask & 0x1) { 835 soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_CHy_TXPKT_OFFSET(cmc, chan), 0); 836 } 837 838 if (mask & 0x2) { 839 soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_CHy_RXPKT_OFFSET(cmc, chan), 0); 840 } 841 842 return rv; 843 } 844 845 /* 846 * Function: 847 * cmicm_dma_cmc_counter_get 848 * Purpose: 849 * Obtain tx and rx counter values 850 * Parameters: 851 * unit - SOC unit # 852 * cmc - cmc number 853 * Returns: 854 * SOC_E_NONE - success 855 * Notes: 856 */ 857 static int 858 cmicm_dma_cmc_counter_get(int unit, int cmc, uint32 *tx_pkt, uint32 *rx_pkt) 859 { 860 int rv = SOC_E_NONE; 861 862 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 863 (BSL_META_U(unit, 864 "cmc counter get\n"))); 865 866 *tx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_TXPKT_OFFSET(cmc)); 867 *rx_pkt = soc_pci_read(unit, CMIC_CMCx_PKT_COUNT_RXPKT_OFFSET(cmc)); 868 869 return rv; 870 } 871 872 /* 873 * Function: 874 * cmicm_dma_cmc_counter_clear 875 * Purpose: 876 * clear tx and rx counter values 877 * Parameters: 878 * unit - SOC unit # 879 * cmc - cmc number 880 * mask - to clear the appopriate counter 881 * Returns: 882 * SOC_E_NONE - success 883 * Notes: 884 */ 885 static int 886 cmicm_dma_cmc_counter_clear(int unit, int cmc, uint32 mask) 887 { 888 int rv = SOC_E_NONE; 889 890 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 891 (BSL_META_U(unit, 892 "cmc counter clear\n"))); 893 894 if (mask & 0x1) { 895 soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_TXPKT_OFFSET(cmc), 0); 896 } 897 898 if (mask & 0x2) { 899 soc_pci_write(unit, CMIC_CMCx_PKT_COUNT_RXPKT_OFFSET(cmc), 0); 900 } 901 902 return rv; 903 } 904 905 /* 906 * Function: 907 * cmicm_dma_chan_cos_ctrl_get 908 * Purpose: 909 * get cos ctrl for a channel 910 * Parameters: 911 * unit - SOC unit # 912 * cfg - to choose appropriate register 913 * Returns: 914 * SOC_E_NONE - success 915 * SOC_E_XXXX - error code 916 * Notes: 917 */ 918 919 int 920 cmicm_dma_chan_cos_ctrl_get(int unit, int vchan, uint32 cfg, uint32 *cos_ctrl) 921 { 922 int rv = SOC_E_NONE; 923 int cmc = vchan / N_DMA_CHAN; 924 int chan = vchan % N_DMA_CHAN; 925 926 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 927 (BSL_META_U(unit, 928 "channel cos ctrl get\n"))); 929 930 if (cfg & 0x1) { 931 *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan)); 932 } else if (cfg & 0x2) { 933 *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan)); 934 } 935 936 return rv; 937 } 938 939 /* 940 * Function: 941 * cmicm_dma_chan_cos_ctrl_set 942 * Purpose: 943 * get cos ctrl for a channel 944 * Parameters: 945 * unit - SOC unit # 946 * cfg - to choose appropriate register 947 * Returns: 948 * SOC_E_NONE - success 949 * SOC_E_XXXX - error code 950 * Notes: 951 */ 952 953 int 954 cmicm_dma_chan_cos_ctrl_set(int unit, int vchan, uint32 cfg, uint32 cos_ctrl) 955 { 956 int rv = SOC_E_NONE; 957 int cmc = vchan / N_DMA_CHAN; 958 int chan = vchan % N_DMA_CHAN; 959 960 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 961 (BSL_META_U(unit, 962 "channel cos ctrl set\n"))); 963 964 if (cfg & 0x1) { 965 soc_pci_write(unit, 966 CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan), 967 cos_ctrl); 968 } else if (cfg & 0x2) { 969 soc_pci_write(unit, 970 CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan), 971 cos_ctrl); 972 } 973 974 return rv; 975 } 976 977 /* 978 * Function: 979 * cmicm_dma_chan_cos_ctrl_queue_get 980 * Purpose: 981 * get cos ctrl for a channel based on queue 982 * Parameters: 983 * unit - SOC unit # 984 * cmc - CMC # 985 * chan - chan # 986 * queue - cos queue 987 * cos_ctrl - cos ctrl val 988 * Returns: 989 * SOC_E_NONE - success 990 * SOC_E_XXXX - error code 991 * Notes: 992 */ 993 994 int 995 cmicm_dma_chan_cos_ctrl_queue_get(int unit, int cmc, int chan, 996 int queue, uint32 *cos_ctrl) 997 { 998 int rv = SOC_E_NONE; 999 uint32 reg_addr; 1000 1001 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1002 (BSL_META_U(unit, 1003 "channel cos ctrl queue get\n"))); 1004 1005 reg_addr = (queue < 32) ? 1006 CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) : 1007 CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan); 1008 1009 *cos_ctrl = soc_pci_read(unit, reg_addr); 1010 1011 return rv; 1012 } 1013 1014 /* 1015 * Function: 1016 * cmicm_dma_chan_cos_ctrl_reg_addr_get 1017 * Purpose: 1018 * get cos ctrl reg addr for a channel based on queue 1019 * Parameters: 1020 * unit - SOC unit # 1021 * cmc - CMC # 1022 * chan - chan # 1023 * queue - cos queue 1024 * reg addr - reg addr val 1025 * Returns: 1026 * SOC_E_NONE - success 1027 * SOC_E_XXXX - error code 1028 * Notes: 1029 */ 1030 1031 int 1032 cmicm_dma_chan_cos_ctrl_reg_addr_get(int unit, int cmc, int chan, 1033 int queue, uint32 *reg_addr) 1034 { 1035 int rv = SOC_E_NONE; 1036 1037 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1038 (BSL_META_U(unit, 1039 "channel cos ctrl reg addr get\n"))); 1040 1041 *reg_addr = (queue < 32) ? 1042 CMIC_CMCx_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) : 1043 CMIC_CMCx_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan); 1044 1045 return rv; 1046 } 1047 1048 /* 1049 * Function: 1050 * cmicm_dma_chan_status_get 1051 * Purpose: 1052 * get channel status 1053 * Parameters: 1054 * unit - SOC unit # 1055 * vchan - channel # 1056 * status - channel status 1057 * 1058 * Returns: 1059 * SOC_E_NONE - success 1060 * SOC_E_XXXX - error code 1061 * Notes: 1062 */ 1063 1064 int 1065 cmicm_dma_chan_status_get(int unit, int vchan, uint32 mask, int *status) 1066 { 1067 int rv = SOC_E_NONE; 1068 int cmc = vchan / N_DMA_CHAN; 1069 1070 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1071 (BSL_META_U(unit, 1072 "channel status get\n"))); 1073 1074 *status = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)); 1075 1076 return rv; 1077 } 1078 1079 /* 1080 * Function: 1081 * cmicm_dma_chan_status_clear 1082 * Purpose: 1083 * clear channel status 1084 * Parameters: 1085 * unit - SOC unit # 1086 * vchan - channel # 1087 * 1088 * Returns: 1089 * SOC_E_NONE - success 1090 * SOC_E_XXXX - error code 1091 * Notes: 1092 */ 1093 1094 int 1095 cmicm_dma_chan_status_clear(int unit, int vchan) 1096 { 1097 int rv = SOC_E_NONE; 1098 int cmc = vchan / N_DMA_CHAN; 1099 1100 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1101 (BSL_META_U(unit, 1102 "channel status clear\n"))); 1103 1104 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc), 0x0); 1105 1106 return rv; 1107 } 1108 1109 /* 1110 * Function: 1111 * cmicm_dma_chan_ctrl_reg_get 1112 * Purpose: 1113 * get channel ctrl reg value 1114 * Parameters: 1115 * unit - SOC unit # 1116 * vchan - channel # 1117 * value - channel ctrl reg value 1118 * 1119 * Returns: 1120 * SOC_E_NONE - success 1121 * SOC_E_XXXX - error code 1122 * Notes: 1123 */ 1124 1125 int 1126 cmicm_dma_chan_ctrl_reg_get(int unit, int vchan, uint32 *val) 1127 { 1128 int rv = SOC_E_NONE; 1129 int cmc = vchan / N_DMA_CHAN; 1130 int chan = vchan % N_DMA_CHAN; 1131 1132 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1133 (BSL_META_U(unit, 1134 "channel ctrl reg get\n"))); 1135 1136 *val = soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)); 1137 1138 return rv; 1139 } 1140 1141 /* 1142 * Function: 1143 * cmicm_dma_chan_ctrl_reg_set 1144 * Purpose: 1145 * set channel ctrl reg 1146 * Parameters: 1147 * unit - SOC unit # 1148 * vchan - channel # 1149 * value - channel ctrl reg value to set 1150 * 1151 * Returns: 1152 * SOC_E_NONE - success 1153 * SOC_E_XXXX - error code 1154 * Notes: 1155 */ 1156 1157 int 1158 cmicm_dma_chan_ctrl_reg_set(int unit, int vchan, uint32 val) 1159 { 1160 int rv = SOC_E_NONE; 1161 int cmc = vchan / N_DMA_CHAN; 1162 int chan = vchan % N_DMA_CHAN; 1163 1164 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1165 (BSL_META_U(unit, 1166 "channel ctrl reg get\n"))); 1167 1168 soc_pci_write(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), val); 1169 1170 return rv; 1171 } 1172 1173 /* 1174 * Function: 1175 * cmicm_dma_chan_rxbuf_threshold_config 1176 * Purpose: 1177 * appropriately set mmu back pressure 1178 * Parameters: 1179 * unit - SOC unit # 1180 * vchan - channel # 1181 * value - mmu backpressure settings 1182 * 1183 * Returns: 1184 * SOC_E_NONE - success 1185 * SOC_E_XXXX - error code 1186 * Notes: 1187 */ 1188 1189 int 1190 cmicm_dma_chan_rxbuf_threshold_config(int unit, int vchan, uint32 val) 1191 { 1192 int rv = SOC_E_NONE; 1193 int cmc = vchan / N_DMA_CHAN; 1194 int chan = vchan % N_DMA_CHAN; 1195 1196 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1197 (BSL_META_U(unit, 1198 "channel rxbuf threshold config\n"))); 1199 1200 soc_pci_write(unit, CMIC_CMCx_CHy_RXBUF_THRESHOLD_CONFIG(cmc, chan), val); 1201 1202 return rv; 1203 } 1204 1205 /* 1206 * Function: 1207 * cmicm_dma_chan_tx_purge 1208 * Purpose: 1209 * Purge partial pkt left in the pipeline from TX DMA abort. 1210 * Parameters: 1211 * unit - SOC unit # 1212 * chan - channel # 1213 * Returns: 1214 * SOC_E_NONE - Success 1215 * SOC_E_TIMEOUT - failed (Timeout) 1216 * Notes: 1217 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 1218 */ 1219 static int 1220 cmicm_dma_chan_tx_purge(int unit, int vchan, dv_t *dv) 1221 { 1222 int rv = SOC_E_NONE; 1223 int cmc = vchan / N_DMA_CHAN; 1224 int chan = vchan % N_DMA_CHAN; 1225 sal_usecs_t start_time; 1226 int diff_time; 1227 uint32 dma_stat; 1228 uint32 dma_state; 1229 1230 soc_pci_write(unit, 1231 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), 1232 soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc,chan)) 1233 | PKTDMA_DIRECTION); 1234 soc_pci_write(unit, 1235 CMIC_CMCx_DMA_DESCy_OFFSET(cmc, chan), 1236 soc_cm_l2p(unit, dv->dv_dcb)); 1237 /* Start DMA */ 1238 soc_pci_write(unit, 1239 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), 1240 soc_pci_read(unit, CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc ,chan)) 1241 | PKTDMA_ENABLE); 1242 1243 start_time = sal_time_usecs(); 1244 diff_time = 0; 1245 dma_state = (DS_CMCx_DMA_DESC_DONE(chan) | DS_CMCx_DMA_CHAIN_DONE(chan)); 1246 do { 1247 sal_udelay(SAL_BOOT_SIMULATION ? 1000 : 10); 1248 dma_stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_OFFSET(cmc)) & 1249 (DS_CMCx_DMA_DESC_DONE(chan) | DS_CMCx_DMA_CHAIN_DONE(chan)); 1250 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 1251 if (diff_time > DMA_ABORT_TIMEOUT) { /* 10 Sec(QT)/10 msec */ 1252 rv = SOC_E_TIMEOUT; 1253 break; 1254 } else if (diff_time < 0) { 1255 /* Restart in case system time changed */ 1256 start_time = sal_time_usecs(); 1257 } 1258 } while (dma_stat != dma_state); 1259 /* Clear CHAIN_DONE and DESC_DONE */ 1260 soc_pci_write(unit, 1261 CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan), 1262 soc_pci_read(unit,CMIC_CMCx_CHy_DMA_CTRL_OFFSET(cmc, chan)) 1263 & ~PKTDMA_ENABLE); 1264 1265 dma_stat = soc_pci_read(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc)); 1266 soc_pci_write(unit, 1267 CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), 1268 (dma_stat | DS_DESCRD_CMPLT_CLR(chan))); 1269 soc_pci_write(unit, CMIC_CMCx_DMA_STAT_CLR_OFFSET(cmc), dma_stat); 1270 return rv; 1271 } 1272 1273 /* 1274 * Function: 1275 * cmicm_dma_chan_desc_done_intr_enable 1276 * Purpose: 1277 * Clears desc done on the CMICM DMA channel for the specified SOC unit. 1278 * Parameters: 1279 * unit - SOC unit # 1280 * chan - channel # 1281 * Returns: 1282 * SOC_E_NONE - success 1283 * SOC_E_XXXX - error code 1284 * Notes: 1285 * INTERRUPT LEVEL ROUTINE. 1286 */ 1287 static int 1288 cmicm_dma_chan_desc_done_intr_enable(int unit, int vchan) 1289 { 1290 int rv = SOC_E_NONE; 1291 int cmc = vchan / N_DMA_CHAN; 1292 int chan = vchan % N_DMA_CHAN; 1293 1294 (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_DESC_DONE(chan)); 1295 return rv; 1296 } 1297 1298 /* 1299 * Function: 1300 * cmicm_dma_masks_get 1301 * Purpose: 1302 * obtain the individual big endian masks 1303 * Parameters: 1304 * unit - SOC unit # 1305 * pkt_endian - pkt endian mask 1306 * desc_endian - desc endian mask 1307 * header_endian - header endian mask 1308 * 1309 * Returns: 1310 * SOC_E_NONE - success 1311 * SOC_E_XXXX - error code 1312 * Notes: 1313 */ 1314 1315 int 1316 cmicm_dma_masks_get(int unit, uint32 *pkt_endian, uint32 *desc_endian, uint32 *header_endian) 1317 { 1318 int rv = SOC_E_NONE; 1319 1320 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1321 (BSL_META_U(unit, 1322 "cmicm dma get masks\n"))); 1323 1324 *pkt_endian = PKTDMA_BIG_ENDIAN; 1325 *desc_endian = PKTDMA_DESC_BIG_ENDIAN; 1326 1327 return rv; 1328 } 1329 1330 /* 1331 * Function: 1332 * cmicm_dma_header_size_get 1333 * Purpose: 1334 * obtain the ep to cpu header size 1335 * Parameters: 1336 * unit - SOC unit # 1337 * hdr_size - return value of the ep to cpu header size 1338 * 1339 * Returns: 1340 * SOC_E_NONE - success 1341 * SOC_E_XXXX - error code 1342 * Notes: 1343 */ 1344 1345 int 1346 cmicm_dma_header_size_get(int unit, uint32 *hdr_size) 1347 { 1348 int rv = SOC_E_NONE; 1349 1350 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1351 (BSL_META_U(unit, 1352 "cmicm dma get header size\n"))); 1353 1354 *hdr_size = 0; 1355 1356 return rv; 1357 } 1358 1359 /* 1360 * Function: 1361 * cmicm_dma_max_rx_channels_get 1362 * Purpose: 1363 * obtain maximum number of dma channels that can be used for BCM RX 1364 * Parameters: 1365 * unit - SOC unit # 1366 * max_rx_channels - maximum rx channels that can be used 1367 * Returns: 1368 * SOC_E_NONE - success 1369 * SOC_E_XXXX - error 1370 */ 1371 1372 static int 1373 cmicm_dma_max_rx_channels_get(int unit, uint32 *max_rx_channels) 1374 { 1375 int rv = SOC_E_NONE; 1376 1377 /* 1378 * Only CMC0 is used for BCM RX hence we can have 1379 * N_DMA_CHAN number of maximum rx channels 1380 */ 1381 1382 *max_rx_channels = N_DMA_CHAN; 1383 1384 return rv; 1385 } 1386 1387 /* Public Functions */ 1388 1389 /* 1390 * Function: 1391 * soc_cmicm_dma_drv_init 1392 * Purpose: 1393 * Initialize the CMICM DMA driver for the specified SOC unit. 1394 * Assign function pointers for SOC DMA driver interface. 1395 * Parameters: 1396 * unit - SOC unit # 1397 * drv - pointer to the function vector list 1398 * Returns: 1399 * SOC_E_NONE - success 1400 * SOC_E_XXXX - error code 1401 * Notes: 1402 */ 1403 int 1404 soc_cmicm_dma_drv_init(int unit, soc_cmic_dma_drv_t *drv) 1405 { 1406 int rv = SOC_E_NONE; 1407 1408 drv->init = cmicm_dma_init; 1409 drv->ctrl_init = cmicm_dma_ctrl_init; 1410 drv->chan_config = cmicm_dma_chan_config; 1411 drv->chan_dv_start = cmicm_dma_chan_dv_start; 1412 drv->chan_start = cmicm_dma_chan_start; 1413 drv->chan_poll = cmicm_dma_chan_poll; 1414 drv->chan_abort = cmicm_dma_chan_abort; 1415 drv->chan_tx_purge = cmicm_dma_chan_tx_purge; 1416 drv->chan_desc_done_intr_enable = cmicm_dma_chan_desc_done_intr_enable; 1417 drv->chan_desc_done = cmicm_dma_chan_desc_done; 1418 drv->chan_chain_done = cmicm_dma_chan_chain_done; 1419 drv->chan_reload_done = NULL; 1420 drv->chan_counter_get = cmicm_dma_chan_counter_get; 1421 drv->chan_counter_clear = cmicm_dma_chan_counter_clear; 1422 drv->chan_cos_ctrl_get = cmicm_dma_chan_cos_ctrl_get; 1423 drv->chan_cos_ctrl_set = cmicm_dma_chan_cos_ctrl_set; 1424 drv->chan_cos_ctrl_queue_get = cmicm_dma_chan_cos_ctrl_queue_get; 1425 drv->chan_cos_ctrl_reg_addr_get = cmicm_dma_chan_cos_ctrl_reg_addr_get; 1426 drv->chan_status_get = cmicm_dma_chan_status_get; 1427 drv->chan_status_clear = cmicm_dma_chan_status_clear; 1428 drv->chan_halt_get = NULL; 1429 drv->chan_ctrl_reg_get = cmicm_dma_chan_ctrl_reg_get; 1430 drv->chan_ctrl_reg_set = cmicm_dma_chan_ctrl_reg_set; 1431 drv->chan_rxbuf_threshold_cfg = cmicm_dma_chan_rxbuf_threshold_config; 1432 drv->cmc_rxbuf_threshold_cfg = NULL; 1433 drv->cmc_counter_get = cmicm_dma_cmc_counter_get; 1434 drv->cmc_counter_clear = cmicm_dma_cmc_counter_clear; 1435 drv->loopback_config = NULL; 1436 drv->masks_get = cmicm_dma_masks_get; 1437 drv->header_size_get = cmicm_dma_header_size_get; 1438 drv->max_rx_channels_get = cmicm_dma_max_rx_channels_get; 1439 drv->pci_timeout_handle = cmicm_dma_pci_timeout_handle; 1440 1441 return rv; 1442 } 1443 1444 #endif /* BCM_CMICM_SUPPORT */