cmice_dma.c (15648B)
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: CMICE 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 21 #ifdef INCLUDE_KNET 22 #include <soc/knet.h> 23 #endif 24 25 #ifdef BCM_CMIC_SUPPORT 26 27 /* Static Driver Functions */ 28 29 /* 30 * Function: 31 * cmice_dma_ctrl_init 32 * Purpose: 33 * Reset the CMICE DMA Control to a known good state for 34 * the specified SOC unit. 35 * Parameters: 36 * unit - SOC unit # 37 * Returns: 38 * SOC_E_NONE - success 39 * SOC_E_XXXX - error code 40 * Notes: 41 */ 42 static int 43 cmice_dma_ctrl_init(int unit) 44 { 45 int rv = SOC_E_NONE; 46 47 soc_pci_write(unit, CMIC_DMA_CTRL, 0); /* Known good state */ 48 49 return rv; 50 } 51 52 /* 53 * Function: 54 * cmice_dma_init 55 * Purpose: 56 * Initialize the CMICE DMA for the specified SOC unit. 57 * Parameters: 58 * unit - SOC unit # 59 * Returns: 60 * SOC_E_NONE - success 61 * SOC_E_XXXX - error code 62 * Notes: 63 */ 64 static int 65 cmice_dma_init(int unit) 66 { 67 int rv = SOC_E_NONE; 68 69 cmice_dma_ctrl_init(unit); 70 71 return rv; 72 } 73 74 /* 75 * Function: 76 * cmice_dma_chan_config 77 * Purpose: 78 * Configure the CMICE DMA channel for the specified SOC unit. 79 * Parameters: 80 * unit - SOC unit # 81 * chan - channel # 82 * type - tx or rx 83 * f_intr - interrupt flags 84 * Returns: 85 * SOC_E_NONE - success 86 * SOC_E_XXXX - error code 87 * Notes: 88 */ 89 static int 90 cmice_dma_chan_config(int unit, int chan, dvt_t type, uint32 flags) 91 { 92 int rv = SOC_E_NONE; 93 soc_control_t *soc = SOC_CONTROL(unit); 94 sdc_t *sc = &soc->soc_channels[chan]; 95 uint32 bits, cr; 96 97 /* Define locals and turn flags into easy to use things */ 98 int f_mbm = (flags & SOC_DMA_F_MBM) != 0; 99 int f_interrupt = (flags & SOC_DMA_F_POLL) == 0; 100 int f_drop = (flags & SOC_DMA_F_TX_DROP) != 0; 101 int f_default = (flags & SOC_DMA_F_DEFAULT) != 0; 102 int f_desc_intr = (flags & SOC_DMA_F_INTR_ON_DESC) != 0; 103 int init_hw = TRUE; 104 105 #ifdef INCLUDE_KNET 106 if (SOC_KNET_MODE(unit) && SOC_WARM_BOOT(unit) && 107 soc_property_get(unit, spn_WARMBOOT_KNET_SHUTDOWN_MODE, 0)) { 108 init_hw = FALSE; 109 } 110 #endif 111 112 /* Initial state of channel */ 113 sc->sc_flags = 0; /* Clear flags to start */ 114 if (init_hw) { 115 (void)soc_intr_disable(unit, IRQ_DESC_DONE(chan) | IRQ_CHAIN_DONE(chan)); 116 soc_pci_write(unit, CMIC_DMA_STAT, DS_DMA_EN_CLR(chan)); 117 soc_pci_write(unit, CMIC_DMA_STAT, DS_DESC_DONE_CLR(chan)); 118 soc_pci_write(unit, CMIC_DMA_STAT, DS_CHAIN_DONE_CLR(chan)); 119 } 120 121 /* Setup new mode */ 122 bits = f_mbm ? DC_MOD_BITMAP(chan) : DC_NO_MOD_BITMAP(chan); 123 bits |= f_drop ? DC_DROP_TX(chan) : DC_NO_DROP_TX(chan); 124 bits |= f_desc_intr ? DC_INTR_ON_DESC(chan) : DC_INTR_ON_PKT(chan); 125 126 if (type == DV_TX) { 127 bits |= DC_MEM_TO_SOC(chan); 128 if (f_default) { 129 soc->soc_dma_default_tx = sc; 130 } 131 } else if (type == DV_RX) { 132 bits |= DC_SOC_TO_MEM(chan); 133 if (f_default) { 134 soc->soc_dma_default_rx = sc; 135 } 136 } else if (type == DV_NONE) { 137 f_interrupt = FALSE; /* Force off */ 138 } else { 139 assert(0); 140 } 141 #ifdef INCLUDE_KNET 142 if (SOC_KNET_MODE(unit)) { 143 /* Interrupt are handled by kernel */ 144 f_interrupt = FALSE; 145 } 146 #endif 147 if (f_interrupt) { 148 (void)soc_intr_enable(unit, 149 IRQ_DESC_DONE(chan) | IRQ_CHAIN_DONE(chan)); 150 } 151 sc->sc_type = type; 152 153 if (init_hw) { 154 cr = soc_pci_read(unit, CMIC_DMA_CTRL); 155 cr &= ~DC_CHAN_MASK(chan); /* Clear this channels bits */ 156 cr |= bits; /* Set new values */ 157 soc_pci_write(unit, CMIC_DMA_CTRL, cr); 158 } 159 160 return rv; 161 } 162 163 /* 164 * Function: 165 * cmice_dma_chan_start 166 * Purpose: 167 * Start the CMICE DMA channel for the specified SOC unit. 168 * Parameters: 169 * unit - SOC unit # 170 * sc - SOC channel data structure pointer 171 * Returns: 172 * SOC_E_NONE - success 173 * SOC_E_XXXX - error code 174 * Notes: 175 */ 176 static int 177 cmice_dma_chan_start(int unit, sdc_t *sc) 178 { 179 int rv = SOC_E_NONE; 180 dv_t *dv; 181 182 if ((dv = sc->sc_dv_active = sc->sc_q) == NULL) { 183 sc->sc_q_tail = NULL; 184 return rv; 185 } 186 187 #ifdef INCLUDE_KNET 188 if (SOC_KNET_MODE(unit)) { 189 return rv; 190 } 191 #endif 192 193 /* Set up DMA descriptor address */ 194 soc_pci_write(unit, CMIC_DMA_DESC(sc->sc_channel), 195 soc_cm_l2p(unit, sc->sc_q->dv_dcb)); 196 /* Start DMA (Actually starts when the done bit is cleared below) */ 197 soc_pci_write(unit, CMIC_DMA_STAT, 198 DS_DMA_EN_SET(sc->sc_channel)); 199 200 SDK_CONFIG_MEMORY_BARRIER; 201 202 /* 203 * Clear CHAIN_DONE if required, and re-enable the 204 * interrupt. This is required to support multiple DMA 205 */ 206 if (sc->sc_flags & SOC_DMA_F_CLR_CHN_DONE) { 207 soc_pci_write(unit, CMIC_DMA_STAT, 208 DS_CHAIN_DONE_CLR(sc->sc_channel)); 209 } else { 210 sc->sc_flags |= SOC_DMA_F_CLR_CHN_DONE; 211 } 212 if (!(sc->sc_flags & SOC_DMA_F_POLL)) { 213 (void)soc_intr_enable(unit, IRQ_CHAIN_DONE(sc->sc_channel)); 214 } 215 216 return rv; 217 } 218 219 /* 220 * Function: 221 * cmice_dma_chan_dv_start 222 * Purpose: 223 * Adds DV to the ready queue for CMICE DMA for the specified SOC unit. 224 * Parameters: 225 * unit - SOC unit # 226 * chan - channel # 227 * Returns: 228 * SOC_E_NONE - success 229 * SOC_E_XXXX - error code 230 * Notes: 231 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 232 */ 233 static int 234 cmice_dma_chan_dv_start(int unit, sdc_t *sc, dv_t *dv_chain) 235 { 236 int rv = SOC_E_NONE; 237 238 dv_chain->dv_next = NULL; 239 if (sc->sc_q_cnt != 0) { 240 sc->sc_q_tail->dv_next = dv_chain; 241 } else { 242 sc->sc_q = dv_chain; 243 } 244 sc->sc_q_tail = dv_chain; 245 sc->sc_q_cnt++; 246 if (sc->sc_dv_active == NULL) { /* Start DMA if channel not active */ 247 rv = cmice_dma_chan_start(unit, sc); 248 } 249 250 return rv; 251 } 252 253 /* 254 * Function: 255 * cmice_dma_chan_poll 256 * Purpose: 257 * Poll the CMICE DMA channel for the specified SOC unit. 258 * Parameters: 259 * unit - SOC unit # 260 * chan - channel # 261 * type - poll type (chain done or desc done) 262 * detected - poll result pointer to be updated 263 * Returns: 264 * SOC_E_NONE - success 265 * SOC_E_XXXX - error code 266 * Notes: 267 * Assumes that SOC_DMA_LOCK is held when called. 268 */ 269 static int 270 cmice_dma_chan_poll(int unit, 271 int chan, 272 soc_dma_poll_type_t type, 273 int *detected) 274 { 275 int rv = SOC_E_NONE; 276 277 switch (type) { 278 case SOC_DMA_POLL_DESC_DONE: 279 *detected = ( soc_pci_read(unit, CMIC_DMA_STAT) 280 & DS_DESC_DONE_TST(chan) ); 281 break; 282 case SOC_DMA_POLL_CHAIN_DONE: 283 *detected = ( soc_pci_read(unit, CMIC_DMA_STAT) 284 & DS_CHAIN_DONE_TST(chan) ); 285 break; 286 default: 287 break; 288 } 289 290 return rv; 291 } 292 293 /* 294 * Function: 295 * cmice_dma_chan_abort 296 * Purpose: 297 * Aborts active DMA on the CMICE DMA channel for the specified SOC unit. 298 * Parameters: 299 * unit - SOC unit # 300 * chan - channel # 301 * Returns: 302 * SOC_E_NONE - Success 303 * SOC_E_TIMEOUT - failed (Timeout) 304 * Notes: 305 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 306 */ 307 static int 308 cmice_dma_chan_abort(int unit, int chan) 309 { 310 int to; 311 uint32 ctrl; 312 int rv = SOC_E_NONE; 313 314 soc_pci_write(unit, CMIC_DMA_STAT, DS_DMA_EN_CLR(chan)); 315 316 SDK_CONFIG_MEMORY_BARRIER; 317 318 ctrl = soc_pci_read(unit, CMIC_DMA_CTRL); 319 assert((ctrl & DC_ABORT_DMA(chan)) == 0); 320 soc_pci_write(unit, CMIC_DMA_CTRL, ctrl | DC_ABORT_DMA(chan)); 321 322 SDK_CONFIG_MEMORY_BARRIER; 323 324 to = soc_property_get(unit, spn_PDMA_TIMEOUT_USEC, 500000); 325 326 while ((to >= 0) && 327 ((soc_pci_read(unit, CMIC_DMA_STAT) & DS_DMA_ACTIVE(chan)) != 0)) { 328 sal_udelay(1000); 329 to -= 1000; 330 } 331 332 if ((soc_pci_read(unit, CMIC_DMA_STAT) & DS_DMA_ACTIVE(chan)) != 0) { 333 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 334 (BSL_META_U(unit, 335 "soc_dma_abort_channel unit %d: " 336 "channel %d abort timeout\n"), 337 unit, chan)); 338 rv = SOC_E_TIMEOUT; 339 if (SOC_WARM_BOOT(unit)) { 340 return rv; 341 } 342 } 343 344 soc_pci_write(unit, CMIC_DMA_CTRL, ctrl); 345 soc_pci_write(unit, CMIC_DMA_STAT, DS_DESC_DONE_CLR(chan)); 346 soc_pci_write(unit, CMIC_DMA_STAT, DS_CHAIN_DONE_CLR(chan)); 347 348 SDK_CONFIG_MEMORY_BARRIER; 349 350 return rv; 351 } 352 353 /* 354 * Function: 355 * cmice_dma_chan_tx_purge 356 * Purpose: 357 * Aborts active DMA on the CMICE DMA channel for the specified SOC unit. 358 * Parameters: 359 * unit - SOC unit # 360 * chan - channel # 361 * Returns: 362 * SOC_E_NONE - Success 363 * SOC_E_TIMEOUT - failed (Timeout) 364 * Notes: 365 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 366 */ 367 static int 368 cmice_dma_chan_tx_purge(int unit, int chan, dv_t *dv) 369 { 370 sal_usecs_t start_time; 371 int diff_time; 372 uint32 dma_stat; 373 uint32 dma_state; 374 uint32 ctrl; 375 int rv = SOC_E_NONE; 376 377 ctrl = soc_pci_read(unit, CMIC_DMA_CTRL); 378 soc_pci_write(unit, CMIC_DMA_CTRL, ctrl | DC_MEM_TO_SOC(chan)); 379 soc_pci_write(unit, CMIC_DMA_DESC(chan), 380 soc_cm_l2p(unit, dv->dv_dcb)); 381 /* Start DMA */ 382 soc_pci_write(unit, CMIC_DMA_STAT, DS_DMA_EN_SET(chan)); 383 384 start_time = sal_time_usecs(); 385 diff_time = 0; 386 dma_state = (DS_DESC_DONE_TST(chan) | DS_CHAIN_DONE_TST(chan)); 387 do { 388 sal_udelay(SAL_BOOT_SIMULATION ? 1000 : 10); 389 dma_stat = soc_pci_read(unit, CMIC_DMA_STAT) & 390 (DS_DESC_DONE_TST(chan) | DS_CHAIN_DONE_TST(chan)); 391 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 392 if (diff_time > DMA_ABORT_TIMEOUT) { /* 10 Sec(QT)/10 msec */ 393 rv = SOC_E_TIMEOUT; 394 break; 395 } else if (diff_time < 0) { 396 /* Restart in case system time changed */ 397 start_time = sal_time_usecs(); 398 } 399 } while (dma_stat != dma_state); 400 /* Clear CHAIN_DONE and DESC_DONE */ 401 soc_pci_write(unit, CMIC_DMA_STAT, DS_DMA_EN_CLR(chan)); 402 soc_pci_write(unit, CMIC_DMA_STAT, DS_DESC_DONE_CLR(chan)); 403 soc_pci_write(unit, CMIC_DMA_STAT, DS_CHAIN_DONE_CLR(chan)); 404 soc_pci_write(unit, CMIC_DMA_CTRL, ctrl); 405 406 return rv; 407 } 408 409 /* 410 * Function: 411 * cmice_dma_chan_desc_done_intr_enable 412 * Purpose: 413 * Clears desc done on the CMICE DMA channel for the specified SOC unit. 414 * Parameters: 415 * unit - SOC unit # 416 * chan - channel # 417 * Returns: 418 * SOC_E_NONE - success 419 * SOC_E_XXXX - error code 420 * Notes: 421 * INTERRUPT LEVEL ROUTINE. 422 */ 423 static int 424 cmice_dma_chan_desc_done_intr_enable(int unit, int chan) 425 { 426 int rv = SOC_E_NONE; 427 428 (void)soc_intr_enable(unit, IRQ_DESC_DONE(chan)); 429 430 return rv; 431 } 432 433 /* 434 * Function: 435 * cmice_dma_chan_desc_done 436 * Purpose: 437 * Clears desc done on the CMICE DMA channel for the specified SOC unit. 438 * Parameters: 439 * unit - SOC unit # 440 * chan - channel # 441 * Returns: 442 * SOC_E_NONE - success 443 * SOC_E_XXXX - error code 444 * Notes: 445 * INTERRUPT LEVEL ROUTINE. 446 */ 447 static int 448 cmice_dma_chan_desc_done(int unit, int chan) 449 { 450 int rv = SOC_E_NONE; 451 452 soc_pci_write(unit, CMIC_DMA_STAT, DS_DESC_DONE_CLR(chan)); 453 454 /* Flush posted writes from PCI bridge */ 455 (void)soc_pci_read(unit, CMIC_DMA_STAT); 456 457 return rv; 458 } 459 460 /* 461 * Function: 462 * cmice_dma_chan_chain_done 463 * Purpose: 464 * on the CMICE DMA channel for the specified SOC unit. 465 * Parameters: 466 * unit - SOC unit # 467 * chan - channel # 468 * mitigation - >0 = interrupt mitigation on 469 * Returns: 470 * SOC_E_NONE - success 471 * SOC_E_XXXX - error code 472 * Notes: 473 * INTERRUPT LEVEL ROUTINE. 474 */ 475 static int 476 cmice_dma_chan_chain_done(int unit, int chan, int mitigation) 477 { 478 int rv = SOC_E_NONE; 479 480 if (mitigation) { 481 (void)soc_intr_disable(unit, 482 IRQ_DESC_DONE(chan) 483 | IRQ_CHAIN_DONE(chan)); 484 } else { 485 (void)soc_intr_disable(unit, IRQ_CHAIN_DONE(chan)); 486 } 487 /* Enable DMA */ 488 soc_pci_write(unit, CMIC_DMA_STAT, DS_DMA_EN_CLR(chan)); 489 490 /* Clear the descriptor done stat bit */ 491 soc_pci_write(unit, CMIC_DMA_STAT, DS_DESC_DONE_CLR(chan)); 492 493 /* Flush posted writes from PCI bridge */ 494 (void)soc_pci_read(unit, CMIC_DMA_STAT); 495 496 return rv; 497 } 498 499 /* 500 * Function: 501 * cmice_dma_max_rx_channels_get 502 * Purpose: 503 * obtain maximum number of dma channels that can be used for BCM RX 504 * Parameters: 505 * unit - SOC unit # 506 * max_rx_channels - maximum rx channels that can be used 507 * Returns: 508 * SOC_E_NONE - success 509 * SOC_E_XXXX - error 510 */ 511 512 static int 513 cmice_dma_max_rx_channels_get(int unit, uint32 *max_rx_channels) 514 { 515 int rv = SOC_E_NONE; 516 517 /* 518 * Only CMC0 is used for BCM RX hence we can have 519 * N_DMA_CHAN number of maximum rx channels 520 */ 521 522 *max_rx_channels = N_DMA_CHAN; 523 524 return rv; 525 } 526 527 /* Public Functions */ 528 529 /* 530 * Function: 531 * soc_cmice_dma_drv_init 532 * Purpose: 533 * Initialize the CMICE DMA driver for the specified SOC unit. 534 * Assign function pointers for SOC DMA driver interface. 535 * Parameters: 536 * unit - SOC unit # 537 * Returns: 538 * SOC_E_NONE - success 539 * SOC_E_XXXX - error code 540 * Notes: 541 */ 542 int 543 soc_cmice_dma_drv_init(int unit, soc_cmic_dma_drv_t *drv) 544 { 545 int rv = SOC_E_NONE; 546 547 drv->init = cmice_dma_init; 548 drv->ctrl_init = cmice_dma_ctrl_init; 549 drv->chan_config = cmice_dma_chan_config; 550 drv->chan_dv_start = cmice_dma_chan_dv_start; 551 drv->chan_start = cmice_dma_chan_start; 552 drv->chan_poll = cmice_dma_chan_poll; 553 drv->chan_abort = cmice_dma_chan_abort; 554 drv->chan_tx_purge = cmice_dma_chan_tx_purge; 555 drv->chan_desc_done_intr_enable = cmice_dma_chan_desc_done_intr_enable; 556 drv->chan_desc_done = cmice_dma_chan_desc_done; 557 drv->chan_chain_done = cmice_dma_chan_chain_done; 558 drv->chan_reload_done = NULL; 559 drv->chan_counter_get = NULL; 560 drv->chan_counter_clear = NULL; 561 drv->chan_cos_ctrl_get = NULL; 562 drv->chan_cos_ctrl_set = NULL; 563 drv->chan_cos_ctrl_queue_get = NULL; 564 drv->chan_cos_ctrl_reg_addr_get = NULL; 565 drv->chan_status_get = NULL; 566 drv->chan_status_clear = NULL; 567 drv->chan_halt_get = NULL; 568 drv->chan_ctrl_reg_get = NULL; 569 drv->chan_ctrl_reg_set = NULL; 570 drv->chan_rxbuf_threshold_cfg = NULL; 571 drv->cmc_rxbuf_threshold_cfg = NULL; 572 drv->cmc_counter_get = NULL; 573 drv->cmc_counter_clear = NULL; 574 drv->loopback_config = NULL; 575 drv->masks_get = NULL; 576 drv->header_size_get = NULL; 577 drv->max_rx_channels_get = cmice_dma_max_rx_channels_get; 578 drv->pci_timeout_handle = NULL; 579 580 return rv; 581 } 582 583 #endif /* BCM_CMIC_SUPPORT */