cmicx_dma.c (56419B)
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 interface driver 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/cmic.h> 21 22 #ifdef INCLUDE_KNET 23 #include <soc/knet.h> 24 #endif 25 26 #ifdef BCM_CMICX_SUPPORT 27 #include <soc/cmicx.h> 28 #include <soc/intr_cmicx.h> 29 #include <bcm_int/common/rx.h> 30 31 typedef struct pktdma_intr_data_s { 32 int cmc; 33 int ch; 34 } pktdma_intr_data_t; 35 36 static pktdma_intr_data_t _intr_data[CMIC_CMC_NUM_MAX][CMICX_N_DMA_CHAN]; 37 38 #define DCB_LAST_DWORD 3 39 #define DCB_DONE_BIT 0x80000000 40 41 #define CH_DESC_DONE 0 42 #define CH_CHAIN_DONE 1 43 #define CH_INTR_COALESCING_INTR 2 44 #define CH_DESC_CONTROLLED_INTR 3 45 46 void 47 soc_cmicx_pktdma_desc_endian_set(int unit, int cmc, int channel, int big_endian) 48 { 49 uint32 val = 0; 50 51 val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel)); 52 val &= ~PKTDMA_DESC_BIG_ENDIAN; 53 if (big_endian) { 54 val |= PKTDMA_DESC_BIG_ENDIAN; 55 } 56 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel), val); 57 } 58 59 void 60 soc_cmicx_pktdma_hdr_endian_set(int unit, int cmc, int channel, int big_endian) 61 { 62 uint32 val = 0; 63 64 val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel)); 65 val &= ~PKTDMA_HEADER_ENDIAN; 66 if (big_endian) { 67 val |= PKTDMA_HEADER_ENDIAN; 68 } 69 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel), val); 70 } 71 72 void 73 soc_cmicx_pktdma_data_endian_set(int unit, int cmc, int channel, int big_endian) 74 { 75 uint32 val = 0; 76 77 val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel)); 78 val &= ~PKTDMA_BIG_ENDIAN; 79 if (big_endian) { 80 val |= PKTDMA_BIG_ENDIAN; 81 } 82 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, channel), val); 83 } 84 85 uint32 86 soc_cmicx_pktdma_cos_ctrl_rx0_get(int unit, int cmc, int channel) 87 { 88 return soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, channel)); 89 } 90 91 uint32 92 soc_cmicx_pktdma_cos_ctrl_rx1_get(int unit, int cmc, int channel) 93 { 94 return soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, channel)); 95 } 96 97 uint32 98 soc_cmicx_pktdma_cos_ctrl_rx0_reg_addr_get(int unit, int cmc, int channel) 99 { 100 return CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, channel); 101 } 102 103 uint32 104 soc_cmicx_pktdma_cos_ctrl_rx1_reg_addr_get(int unit, int cmc, int channel) 105 { 106 return CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, channel); 107 } 108 109 uint32 110 soc_cmicx_pktdma_cos_ctrl_queue_id_get(int unit, int cmc, int channel, int queue) 111 { 112 uint32 reg_addr; 113 reg_addr = (queue < 32) ? 114 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, channel) : 115 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, channel); 116 117 return soc_pci_read(unit, reg_addr); 118 } 119 120 sal_vaddr_t 121 soc_cmicx_pktdma_desc_addr_get(int unit, int cmc, int channel) 122 { 123 uint32 val1; 124 sal_paddr_t paddr; 125 126 val1 = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_LO_OFFSET(cmc, channel)); 127 128 #if defined(COMPILER_OVERRIDE_NO_LONGLONG) || defined(__PEDANTIC__) 129 paddr = (sal_paddr_t)val1; 130 #else 131 if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) { 132 paddr = (((uint64)((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, channel))) 133 & ~(CMIC_PCIE_SO_OFFSET)) << 32) | val1); 134 } else { 135 paddr = (((uint64)((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, channel)))) << 32) | val1); 136 } 137 #endif 138 139 return (sal_vaddr_t)soc_cm_p2l(unit, paddr); 140 } 141 142 uint32 143 soc_cmicx_pktdma_header_size_get(int unit) 144 { 145 uint32 hdr_size = 0; 146 147 /* The header size is an encoded value from only the first 4 bits of 148 * the CMIC_TOP_EP_TO_CPU_HEADER_SIZE register. The actual header 149 * size is the encoded value multiplied by 8. 150 */ 151 hdr_size = ((soc_pci_read(unit, CMIC_TOP_EP_TO_CPU_HEADER_SIZE_OFFSET) & 0xf) * 8); 152 153 return hdr_size; 154 } 155 156 /* Static Driver Functions */ 157 158 /* 159 * Function: 160 * cmicx_dma_get_intr_base 161 * Purpose: 162 * The interrupt numbers are dependent on the cmc. 163 * This calculates the interrupt base number. 164 * Parameters: 165 * cmc - cmc# 166 * Returns: 167 * The appropriate interrupt base for associated cmc 168 * Notes: 169 */ 170 171 static uint32 172 cmicx_dma_get_intr_base(int cmc) 173 { 174 uint32 intr_base = 0; 175 176 intr_base = (cmc == 0)? CMC0_CH0_DESC_DONE: CMC1_CH0_DESC_DONE; 177 178 return intr_base; 179 } 180 181 /* 182 * Function: 183 * cmicx_pkdma_ch_desc_done 184 * Purpose: 185 * The interrupt handler for channel descriptor done 186 * 187 * Parameters: 188 * unit - SOC unit # 189 * *data - pointer provided during registration 190 */ 191 192 static void 193 cmicx_pktdma_ch_desc_done(int unit, void *data) 194 { 195 soc_control_t *soc = SOC_CONTROL(unit); 196 sdc_t *sc; 197 pktdma_intr_data_t *in_d = (pktdma_intr_data_t *)data; 198 int vchan = 0; 199 uint32 val = 0; 200 201 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 202 (BSL_META_U(unit, 203 "channel desc done cmc = %d ch = %d\n"), 204 in_d->cmc, in_d->ch)); 205 206 val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(in_d->cmc)); 207 208 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 209 (BSL_META_U(unit, 210 "shared irq stat0 val in desc done cb = %x\n"), val)); 211 212 val &= (DS_CMCx_CHy_DMA_DESC_DONE(in_d->ch) | DS_CMCx_CHy_DMA_CHAIN_DONE(in_d->ch) | 213 DS_CMCx_CHy_DESC_CONTROLLED_INTR(in_d->ch)); 214 215 vchan = (CMICX_N_DMA_CHAN * in_d->cmc) + in_d->ch; 216 sc = &soc->soc_channels[vchan]; 217 218 if (sc->sc_q_cnt > 0) { 219 soc_dma_cmicx_done_desc(unit, vchan); 220 } else { 221 soc_pci_write(unit, 222 CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(in_d->cmc), 223 val | (DS_CMCx_CHy_DMA_DESC_DONE(in_d->ch))); 224 } 225 } 226 227 /* 228 * Function: 229 * cmicx_pktdma_ch_chain_done 230 * Purpose: 231 * The interrupt handler for channel chain done 232 * 233 * Parameters: 234 * unit - SOC unit # 235 * *data - pointer provided during registration 236 */ 237 238 static void 239 cmicx_pktdma_ch_chain_done(int unit, void *data) 240 { 241 soc_control_t *soc = SOC_CONTROL(unit); 242 sdc_t *sc; 243 pktdma_intr_data_t *in_d = (pktdma_intr_data_t *)data; 244 int vchan = 0; 245 uint32 val = 0; 246 247 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 248 (BSL_META_U(unit, 249 "channel chain done cmc = %d ch = %d\n"), 250 in_d->cmc, in_d->ch)); 251 252 val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(in_d->cmc)); 253 254 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 255 (BSL_META_U(unit, 256 "shared irq stat0 val in chain done cb = %x\n"), val)); 257 258 val &= (DS_CMCx_CHy_DMA_DESC_DONE(in_d->ch) | DS_CMCx_CHy_DMA_CHAIN_DONE(in_d->ch) | 259 DS_CMCx_CHy_DESC_CONTROLLED_INTR(in_d->ch)); 260 261 vchan = (CMICX_N_DMA_CHAN * in_d->cmc) + in_d->ch; 262 sc = &soc->soc_channels[vchan]; 263 264 if (sc->sc_q_cnt > 0) { 265 soc_dma_done_chain(unit, vchan); 266 } else { 267 soc_pci_write(unit, 268 CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(in_d->cmc), 269 val | (DS_CMCx_CHy_DMA_CHAIN_DONE(in_d->ch))); 270 } 271 } 272 273 /* 274 * Function: 275 * cmicx_dma_ctrl_init 276 * Purpose: 277 * Initialize the CMICX DMA Control to a known good state for 278 * the specified SOC unit. 279 * Parameters: 280 * unit - SOC unit # 281 * Returns: 282 * SOC_E_NONE - success 283 * SOC_E_XXXX - error code 284 * Notes: 285 */ 286 287 int 288 cmicx_dma_ctrl_init(int unit) 289 { 290 int rv = SOC_E_NONE; 291 int cmc; 292 uint32 val, chan, vchan; 293 294 for(vchan=0; vchan < SOC_DCHAN_NUM(unit); vchan++) { 295 cmc = vchan / CMICX_N_DMA_CHAN; 296 chan = vchan % CMICX_N_DMA_CHAN; 297 298 val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 299 val &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN | PKTDMA_HEADER_ENDIAN); 300 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val); 301 } 302 303 /* 304 * This has to be done only once after both CMIC and EP blocks 305 * are out of reset. 306 */ 307 308 #ifdef BCM_TOMAHAWK3_SUPPORT 309 /* This is the SW WAR for TH3-3751. Since only 6 bits of 310 iproc_cmic_to_ep_credits[5:0] are being used, so we cannot set the 311 max credits to be released to EP to 64. Hence the SW WAR is to set the 312 max credits to 63 first and then release to EP and set to 1 and release 313 it again. 314 */ 315 if (SOC_IS_TOMAHAWK3(unit)) { 316 READ_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, &val); 317 318 soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr, 319 &val, WR_EP_INTF_CREDITSf, 0x1); 320 soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr, 321 &val, MAX_CREDITSf, 0x3F); 322 323 WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val); 324 325 soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1); 326 soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0); 327 328 READ_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, &val); 329 330 soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr, 331 &val, WR_EP_INTF_CREDITSf, 0x1); 332 soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr, 333 &val, MAX_CREDITSf, 0x1); 334 335 WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val); 336 337 soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1); 338 soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0); 339 } else 340 #endif 341 { 342 #ifdef BCM_HELIX5_SUPPORT 343 if(SOC_IS_HELIX5(unit)) { 344 345 READ_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, &val); 346 soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr, 347 &val, FLUSH_IP_INTF_BUFFERf, 1); 348 WRITE_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, val); 349 350 READ_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, &val); 351 soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr, 352 &val, FLUSH_IP_INTF_BUFFERf, 0); 353 soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr, 354 &val, IP_INTF_CREDITSf, 0x20); 355 WRITE_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, val); 356 357 READ_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, &val); 358 soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr, 359 &val, FLUSH_IP_INTF_BUFFERf, 0); 360 soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr, 361 &val, IP_INTF_CREDITSf, 0x20); 362 soc_reg_field_set(unit, CMIC_TOP_IPINTF_INTERFACE_CREDITSr, 363 &val, WR_IP_INTF_CREDITSf, 1); 364 WRITE_CMIC_TOP_IPINTF_INTERFACE_CREDITSr(unit, val); 365 } 366 #endif 367 READ_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, &val); 368 369 soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr, 370 &val, MAX_CREDITSf, 0x20); 371 372 WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val); 373 soc_reg_field_set(unit, CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr, 374 &val, WR_EP_INTF_CREDITSf, 1); 375 376 WRITE_CMIC_TOP_EPINTF_MAX_INTERFACE_CREDITSr(unit, val); 377 378 soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 0); 379 soc_pci_write(unit, CMIC_TOP_EPINTF_RELEASE_ALL_CREDITS_OFFSET, 1); 380 } 381 /* Set IP_INTERFACE_HEADER_ENDIANESS=1 */ 382 val = soc_pci_read(unit, CMIC_TOP_CONFIG_OFFSET); 383 val |= 0x80; 384 soc_pci_write(unit, CMIC_TOP_CONFIG_OFFSET, val); 385 return rv; 386 } 387 388 /* 389 * Function: 390 * cmicx_dma_chan_config 391 * Purpose: 392 * Initialize the CMICX DMA channel for the specified SOC unit. 393 * Parameters: 394 * unit - SOC unit # 395 * chan - channel # 396 * type - tx or rx 397 * f_intr - interrupt flags 398 * Returns: 399 * SOC_E_NONE - success 400 * SOC_E_XXXX - error code 401 * Notes: 402 */ 403 static int 404 cmicx_dma_chan_config(int unit, int vchan, dvt_t type, uint32 flags) 405 { 406 int rv = SOC_E_NONE; 407 soc_control_t *soc = SOC_CONTROL(unit); 408 sdc_t *sc = &soc->soc_channels[vchan]; 409 uint32 bits = 0; 410 int cmc = vchan / CMICX_N_DMA_CHAN; 411 int chan = vchan % CMICX_N_DMA_CHAN; 412 uint32 cr; 413 uint32 intr_base = 0; 414 415 int f_interrupt = (flags & SOC_DMA_F_POLL) == 0; 416 int f_default = (flags & SOC_DMA_F_DEFAULT) != 0; 417 int init_hw = TRUE; 418 419 /* Set channel to Continuous Mode */ 420 if (soc_property_get(unit, spn_PDMA_CONTINUOUS_MODE_ENABLE, 0)) { 421 SOC_DMA_MODE(unit) = SOC_DMA_MODE_CONTINUOUS; 422 } else { 423 SOC_DMA_MODE(unit) = SOC_DMA_MODE_CHAINED; 424 } 425 426 /* Initial state of channel */ 427 sc->sc_flags = 0; /* Clear flags to start */ 428 429 #ifdef INCLUDE_KNET 430 if (SOC_KNET_MODE(unit) && SOC_WARM_BOOT(unit) && 431 soc_property_get(unit, spn_WARMBOOT_KNET_SHUTDOWN_MODE, 0)) { 432 init_hw = FALSE; 433 } 434 #endif 435 436 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 437 (BSL_META_U(unit, 438 "channel config cmc = %d channel= %d type = %d\n"), 439 cmc, chan, type)); 440 441 intr_base = cmicx_dma_get_intr_base(cmc); 442 443 if (init_hw) { 444 soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_DESC_DONE); 445 soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE); 446 soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR); 447 448 cr = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc,chan)); 449 cr &= ~PKTDMA_ENABLE; 450 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), cr); 451 452 soc_pci_write(unit, CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc), 453 DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan)); 454 } 455 456 if (type == DV_TX) { 457 bits |= PKTDMA_DIRECTION; 458 if (f_default) { 459 soc->soc_dma_default_tx = sc; 460 } 461 } else if (type == DV_RX) { 462 bits &= ~PKTDMA_DIRECTION; 463 if (f_default) { 464 soc->soc_dma_default_rx = sc; 465 } 466 } else if (type == DV_NONE) { 467 f_interrupt = FALSE; /* Force off */ 468 } else { 469 assert(0); 470 } 471 472 #ifdef INCLUDE_KNET 473 if (SOC_KNET_MODE(unit)) { 474 /* Interrupt are handled by kernel */ 475 f_interrupt = FALSE; 476 } 477 #endif 478 479 if (f_interrupt) { 480 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 481 soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR); 482 } else { 483 soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_DONE); 484 soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE); 485 } 486 } 487 sc->sc_type = type; 488 489 if (init_hw) { 490 cr = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 491 492 /* Clear everything except Endianess */ 493 cr &= (PKTDMA_BIG_ENDIAN | PKTDMA_DESC_BIG_ENDIAN | PKTDMA_HEADER_ENDIAN); 494 cr |= bits; 495 496 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 497 cr |= PKTDMA_DESC_DONE_INTR_MODE; 498 } 499 500 if (soc_property_get(unit, spn_PDMA_DESCRIPTOR_PREFETCH_ENABLE, 0)) { 501 cr |= PKTDMA_CONTIGUOUS_DESCRIPTORS; 502 } 503 504 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), cr); 505 } 506 507 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 508 (BSL_META_U(unit, 509 "completed channel config\n"))); 510 511 return rv; 512 } 513 514 /* 515 * Function: 516 * cmicx_dma_chan_start 517 * Purpose: 518 * Start the CMICd DMA channel for the specified SOC unit. 519 * Parameters: 520 * unit - SOC unit # 521 * sc - SOC channel data structure pointer 522 * Returns: 523 * SOC_E_NONE - success 524 * SOC_E_XXXX - error code 525 * Notes: 526 */ 527 static int 528 cmicx_dma_chan_start(int unit, sdc_t *sc) 529 { 530 int rv = SOC_E_NONE; 531 dv_t *dv; 532 int cmc = sc->sc_channel / CMICX_N_DMA_CHAN; 533 int chan = sc->sc_channel % CMICX_N_DMA_CHAN; 534 uint32 val; 535 sal_paddr_t addr; 536 uint32 intr_base = 0; 537 538 if ((dv = sc->sc_dv_active = sc->sc_q) == NULL) { 539 sc->sc_q_tail = NULL; 540 return rv; 541 } 542 543 #ifdef INCLUDE_KNET 544 if (SOC_KNET_MODE(unit)) { 545 return rv; 546 } 547 #endif 548 549 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 550 (BSL_META_U(unit, 551 "Starting channel %d\n"), 552 sc->sc_channel)); 553 554 /* Set up DMA descriptor address */ 555 addr = soc_cm_l2p(unit, sc->sc_q->dv_dcb); 556 557 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_LO_OFFSET(cmc, chan), 558 PTR_TO_INT(addr)); 559 560 if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) { 561 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan), 562 (CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(addr))); 563 } else { 564 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan), PTR_HI_TO_INT(addr)); 565 } 566 567 if (SOC_DMA_MODE(unit) != SOC_DMA_MODE_CONTINUOUS) { 568 if (sc->sc_flags & SOC_DMA_F_CLR_CHN_DONE) { 569 val = soc_pci_read(unit, 570 CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 571 val &= ~PKTDMA_ENABLE; 572 soc_pci_write(unit, 573 CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), 574 val); 575 } else { 576 sc->sc_flags |= SOC_DMA_F_CLR_CHN_DONE; 577 } 578 } 579 580 /* Start DMA - Enable Continuous Mode for this channel */ 581 val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 582 val |= (PKTDMA_ENABLE); 583 584 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 585 val |= (PKTDMA_CONTINUOUS_ENABLE); 586 } 587 588 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val); 589 590 SDK_CONFIG_MEMORY_BARRIER; 591 592 if (!(sc->sc_flags & SOC_DMA_F_POLL)) { 593 intr_base = cmicx_dma_get_intr_base(cmc); 594 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 595 soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR); 596 } else { 597 soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE); 598 } 599 } 600 601 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 602 (BSL_META_U(unit, 603 "completed channel start\n"))); 604 605 return rv; 606 } 607 608 /* 609 * Function: 610 * cmicx_dma_chan_poll 611 * Purpose: 612 * Poll the CMICX DMA channel for the specified SOC unit. 613 * Parameters: 614 * unit - SOC unit # 615 * chan - channel # 616 * type - poll type (chain done or desc done) 617 * detected - poll result pointer to be updated 618 * Returns: 619 * SOC_E_NONE - success 620 * SOC_E_XXXX - error code 621 * Notes: 622 * Assumes that SOC_DMA_LOCK is held when called. 623 */ 624 static int 625 cmicx_dma_chan_poll(int unit, int vchan, soc_dma_poll_type_t type, int * detected) 626 { 627 int rv = SOC_E_NONE; 628 int cmc = vchan / CMICX_N_DMA_CHAN; 629 int chan = vchan % CMICX_N_DMA_CHAN; 630 631 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 632 (BSL_META_U(unit, 633 "channel poll cmc = %d channel = %d\n"), 634 cmc, chan)); 635 636 switch (type) { 637 case SOC_DMA_POLL_DESC_DONE: 638 *detected = (soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)) 639 & DS_CMCx_CHy_DMA_DESC_DONE(chan)); 640 break; 641 case SOC_DMA_POLL_CHAIN_DONE: 642 *detected = (soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)) 643 & DS_CMCx_CHy_DMA_CHAIN_DONE(chan)); 644 break; 645 default: 646 break; 647 } 648 649 return rv; 650 } 651 652 /* 653 * Function: 654 * cmicx_dma_chan_abort 655 * Purpose: 656 * Initialize the CMICX DMA channel for the specified SOC unit. 657 * Parameters: 658 * unit - SOC unit # 659 * chan - channel # 660 * type - tx or rx 661 * f_intr - interrupt flags 662 * Returns: 663 * SOC_E_NONE - Success 664 * SOC_E_TIMEOUT - failed (Timeout) 665 * Notes: 666 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 667 */ 668 static int 669 cmicx_dma_chan_abort(int unit, int vchan) 670 { 671 int rv = SOC_E_NONE; 672 int cmc = vchan / CMICX_N_DMA_CHAN; 673 int chan = vchan % CMICX_N_DMA_CHAN; 674 int to; 675 uint32 ctrl, val; 676 soc_control_t *soc = SOC_CONTROL(unit); 677 sdc_t *sc = &soc->soc_channels[chan]; 678 679 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 680 (BSL_META_U(unit, 681 "channel abort cmc = %d channel = %d\n"), 682 cmc, chan)); 683 684 if ((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan)) 685 & PKTDMA_CH_IS_ACTIVE) != 0) { 686 ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 687 ctrl |= PKTDMA_ENABLE; 688 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), ctrl); 689 soc_pci_write(unit, 690 CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), 691 ctrl | PKTDMA_ABORT); 692 SDK_CONFIG_MEMORY_BARRIER; 693 694 to = soc_property_get(unit, spn_PDMA_TIMEOUT_USEC, 1000000); 695 while ((to >= 0) && 696 ((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan)) 697 & PKTDMA_CH_IS_ACTIVE) != 0)) { 698 sal_udelay(10000); 699 to -= 1000; 700 } 701 if ((soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan)) 702 & PKTDMA_CH_IS_ACTIVE) != 0) { 703 LOG_ERROR(BSL_LS_SOC_PACKETDMA, 704 (BSL_META_U(unit, 705 "soc_dma_abort_channel unit %d: " 706 "channel %d abort timeout\n"), 707 unit, chan)); 708 rv = SOC_E_TIMEOUT; 709 if (SOC_WARM_BOOT(unit)) { 710 return rv; 711 } 712 } 713 } 714 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 715 (BSL_META_U(unit, 716 "soc_dma_abort_channel unit %d: " 717 "channel %d\n"), 718 unit, chan)); 719 720 ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 721 /* Clearing enable will also clear CHAIN_DONE */ 722 ctrl &= ~(PKTDMA_ENABLE | PKTDMA_ABORT); 723 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), ctrl); 724 725 val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)); 726 727 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 728 (BSL_META_U(unit, 729 "shared irq stat0 val = %x\n"), val)); 730 731 val &= (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan) | 732 DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan)); 733 734 soc_pci_write(unit, 735 CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc), 736 val | (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan) | 737 DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan))); 738 739 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 740 (BSL_META_U(unit, 741 "In channel abort val of ctrl reg = %x\n"), 742 ctrl)); 743 744 SDK_CONFIG_MEMORY_BARRIER; 745 746 /* Mark channel as not started */ 747 sc->sc_dma_started = 0; 748 749 return rv; 750 } 751 752 /* 753 * Function: 754 * cmicx_dma_chan_dv_start 755 * Purpose: 756 * Adds DV to the ready queue for CMICX DMA for the specified SOC unit. 757 * Parameters: 758 * unit - SOC unit # 759 * chan - channel # 760 * Returns: 761 * SOC_E_NONE - success 762 * SOC_E_XXXX - error code 763 * Notes: 764 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 765 */ 766 static int 767 cmicx_dma_chan_dv_start(int unit, sdc_t *sc, dv_t *dv_chain) 768 { 769 int rv = SOC_E_NONE; 770 int cmc = sc->sc_channel / CMICX_N_DMA_CHAN; 771 int chan = sc->sc_channel % CMICX_N_DMA_CHAN; 772 dcb_t *dcb; 773 sal_paddr_t reg_val = 0; 774 775 if (dv_chain == sc->sc_q) { 776 DV_STATE(dv_chain) = DV_S_FILLED; 777 return rv; 778 } 779 780 dv_chain->dv_next = NULL; 781 782 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 783 (BSL_META_U(unit, 784 "channel dv start cmc = %d channel = %d\n"), 785 cmc, chan)); 786 787 #ifdef INCLUDE_KNET 788 if (SOC_KNET_MODE(unit)) { 789 /* KNET handling of DV start */ 790 if (sc->sc_q_cnt != 0) { 791 sc->sc_q_tail->dv_next = dv_chain; 792 } else { 793 sc->sc_q = dv_chain; 794 } 795 sc->sc_q_tail = dv_chain; 796 sc->sc_q_cnt++; 797 if (sc->sc_dv_active == NULL) { 798 if (sc->sc_dma_started) { 799 sc->sc_dv_active = sc->sc_q; 800 } else { 801 /* Start DMA if channel not active */ 802 rv = cmicx_dma_chan_start(unit, sc); 803 sc->sc_dma_started = 1; 804 } 805 } 806 return rv; 807 } 808 #endif 809 810 if (sc->sc_q_cnt != 0) { 811 sc->sc_q_tail->dv_next = dv_chain; 812 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 813 /* Set the reload addr of tail 814 * to the address of the appended chain 815 */ 816 dcb = SOC_DCB_IDX2PTR(unit, sc->sc_q_tail->dv_dcb, 817 sc->sc_q_tail->dv_vcnt - 1); 818 SOC_DCB_ADDR_SET(dv_chain->dv_unit, dcb, 819 (sal_vaddr_t)dv_chain->dv_dcb); 820 } 821 } else { 822 sc->sc_q = dv_chain; 823 } 824 sc->sc_q_tail = dv_chain; 825 sc->sc_q_cnt++; 826 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 827 (BSL_META_U(unit, 828 "channel dv start sc_q_cnt = %d\n"), 829 sc->sc_q_cnt)); 830 831 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 832 /* Set the HW register for the new DESC_HALT_ADDR for CMICX 833 * Need logical to physical mapping for addr 834 * If DMA is currently halted, writing the new rld addr starts it again 835 */ 836 reg_val = soc_cm_l2p(unit, 837 (void*)SOC_DCB_IDX2PTR(unit, dv_chain->dv_dcb, 838 (dv_chain->dv_vcnt - 1))); 839 840 soc_pci_write(unit, 841 CMIC_CMCx_PKTDMA_CHy_DESC_HALT_ADDR_LO_OFFSET(cmc, chan), 842 PTR_TO_INT(reg_val)); 843 844 if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) { 845 soc_pci_write(unit, 846 CMIC_CMCx_PKTDMA_CHy_DESC_HALT_ADDR_HI_OFFSET(cmc, chan), 847 CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(reg_val)); 848 } else { 849 soc_pci_write(unit, 850 CMIC_CMCx_PKTDMA_CHy_DESC_HALT_ADDR_HI_OFFSET(cmc, chan), PTR_HI_TO_INT(reg_val)); 851 } 852 } 853 854 SDK_CONFIG_MEMORY_BARRIER; 855 856 /* Start DMA if channel not active */ 857 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 858 if ((sc->sc_dv_active == NULL) && (!sc->sc_dma_started)) { 859 rv = cmicx_dma_chan_start(unit, sc); 860 sc->sc_dma_started = 1; 861 } 862 } 863 864 if (SOC_DMA_MODE(unit) != SOC_DMA_MODE_CONTINUOUS) { 865 if (sc->sc_q_cnt == 1) { 866 rv = cmicx_dma_chan_start(unit, sc); 867 sc->sc_dma_started = 1; 868 } 869 } 870 871 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 872 (BSL_META_U(unit, 873 "end of channel dv start\n"))); 874 875 return rv; 876 } 877 878 /* 879 * Function: 880 * cmicx_dma_chan_chain_done 881 * Purpose: 882 * on the CMICX DMA channel for the specified SOC unit. 883 * Parameters: 884 * unit - SOC unit # 885 * chan - channel # 886 * mitigation - >0 = interrupt mitigation on 887 * Returns: 888 * SOC_E_NONE - success 889 * SOC_E_XXXX - error code 890 * Notes: 891 * INTERRUPT LEVEL ROUTINE. 892 */ 893 static int 894 cmicx_dma_chan_chain_done(int unit, int vchan, int mitigation) 895 { 896 int rv = SOC_E_NONE; 897 int cmc = vchan / CMICX_N_DMA_CHAN; 898 int chan = vchan % CMICX_N_DMA_CHAN; 899 uint32 val; 900 uint32 intr_base = 0; 901 902 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 903 (BSL_META_U(unit, 904 "channel chain done cmc = %d channel = %d " 905 "mitigation = %d\n"), 906 cmc, chan, mitigation)); 907 908 intr_base = cmicx_dma_get_intr_base(cmc); 909 910 if (mitigation) { 911 soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_DESC_DONE); 912 soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE); 913 } else { 914 soc_cmic_intr_disable(unit, intr_base + (4 * chan) + CH_CHAIN_DONE); 915 } 916 917 /* Disable DMA */ 918 val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 919 val &= ~PKTDMA_ENABLE; 920 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val); 921 922 soc_pci_write(unit, 923 CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc), 924 DS_CMCx_CHy_DMA_CHAIN_DONE(chan)); 925 926 /* Flush posted writes from PCI bridge */ 927 (void)soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc)); 928 929 val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)); 930 931 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 932 (BSL_META_U(unit, 933 "shared irq stat0 val at chain done = %x\n"), val)); 934 935 return rv; 936 } 937 938 /* 939 * Function: 940 * cmicx_dma_chan_desc_done 941 * Purpose: 942 * Clears desc done on the CMICX DMA channel for the specified SOC unit. 943 * Parameters: 944 * unit - SOC unit # 945 * chan - channel # 946 * Returns: 947 * SOC_E_NONE - success 948 * SOC_E_XXXX - error code 949 * Notes: 950 * INTERRUPT LEVEL ROUTINE. 951 */ 952 static int 953 cmicx_dma_chan_desc_done(int unit, int vchan) 954 { 955 int rv = SOC_E_NONE; 956 int cmc = vchan / CMICX_N_DMA_CHAN; 957 int chan = vchan % CMICX_N_DMA_CHAN; 958 uint32 val; 959 960 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 961 (BSL_META_U(unit, 962 "channel desc done cmc = %d channel = %d\n"), 963 cmc, chan)); 964 965 /* 966 * Older CMIC devices required a read/write/modify to clear done 967 * interrupts. That does not work here for continuous DMA. Need only 968 * to set the bit for the corresponding interrupt to clear. 969 */ 970 val = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)); 971 972 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 973 (BSL_META_U(unit, 974 "shared irq stat0 val = %x\n"), val)); 975 976 val &= (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan) | 977 DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan)); 978 979 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 980 soc_pci_write(unit, 981 CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc), 982 (DS_CMCx_CHy_DESC_CONTROLLED_INTR(chan))); 983 } else { 984 soc_pci_write(unit, 985 CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc), 986 (DS_CMCx_CHy_DMA_DESC_DONE(chan))); 987 } 988 989 /* Flush posted writes from PCI bridge */ 990 (void)soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc)); 991 992 return rv; 993 } 994 995 /* 996 * Function: 997 * cmicx_dma_chan_desc_done_intr_enable 998 * Purpose: 999 * Clears desc done on the CMICX DMA channel for the specified SOC unit. 1000 * Parameters: 1001 * unit - SOC unit # 1002 * chan - channel # 1003 * Returns: 1004 * SOC_E_NONE - success 1005 * SOC_E_XXXX - error code 1006 * Notes: 1007 * INTERRUPT LEVEL ROUTINE. 1008 */ 1009 static int 1010 cmicx_dma_chan_desc_done_intr_enable(int unit, int vchan) 1011 { 1012 int rv = SOC_E_NONE; 1013 int cmc = vchan / CMICX_N_DMA_CHAN; 1014 int chan = vchan % CMICX_N_DMA_CHAN; 1015 uint32 intr_base = 0; 1016 1017 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1018 (BSL_META_U(unit, 1019 "channel desc done intr enable cmc = %d channel = %d\n"), 1020 cmc, chan)); 1021 1022 intr_base = cmicx_dma_get_intr_base(cmc); 1023 1024 if (SOC_DMA_MODE(unit) == SOC_DMA_MODE_CONTINUOUS) { 1025 soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_CONTROLLED_INTR); 1026 } else { 1027 soc_cmic_intr_enable(unit, intr_base + (4 * chan) + CH_DESC_DONE); 1028 } 1029 1030 return rv; 1031 } 1032 1033 /* 1034 * Function: 1035 * cmicx_dma_chan_reload_done 1036 * Purpose: 1037 * Detect for reload descriptor completed 1038 * Parameters: 1039 * unit - SOC unit # 1040 * sc - SOC channel data structure pointer 1041 * Returns: 1042 * SOC_E_NONE - success 1043 * SOC_E_XXXX - error code 1044 * Notes: 1045 */ 1046 static int 1047 cmicx_dma_chan_reload_done(int unit, int vchan, dcb_t * dcb, int *rld_done) 1048 { 1049 int rv = SOC_E_NONE; 1050 uint32 *rld_dcb; 1051 1052 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1053 (BSL_META_U(unit, 1054 "channel reload done\n"))); 1055 1056 *rld_done = 0; /* Default to not reload */ 1057 1058 /* There is no pkt data to process for a reload descriptor */ 1059 if(SOC_DCB_RELOAD_GET(unit, dcb)) { 1060 /* HW sets bit 31 in the dcb's last dword to indicate done */ 1061 rld_dcb = (uint32 *)dcb; 1062 if (rld_dcb[DCB_LAST_DWORD] & DCB_DONE_BIT) { 1063 *rld_done = 1; 1064 } 1065 } 1066 1067 return rv; 1068 } 1069 1070 /* 1071 * Function: 1072 * cmicx_dma_chan_counter_get 1073 * Purpose: 1074 * Obtain tx and rx counter values 1075 * Parameters: 1076 * unit - SOC unit # 1077 * vchan - SOC virtual channel number 1078 * Returns: 1079 * SOC_E_NONE - success 1080 * Notes: 1081 */ 1082 static int 1083 cmicx_dma_chan_counter_get(int unit, int vchan, uint32 *tx_pkt, uint32 *rx_pkt) 1084 { 1085 int rv = SOC_E_NONE; 1086 int cmc = vchan / CMICX_N_DMA_CHAN; 1087 int chan = vchan % CMICX_N_DMA_CHAN; 1088 1089 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1090 (BSL_META_U(unit, 1091 "channel counter get\n"))); 1092 1093 *tx_pkt = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_TXPKT_OFFSET(cmc, chan)); 1094 *rx_pkt = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_OFFSET(cmc, chan)); 1095 #if 0 1096 /* keep this code ready and handy, just in case somebody needs it */ 1097 *rx_pkt_drop = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_DROP_OFFSET(cmc, chan)); 1098 #endif 1099 return rv; 1100 } 1101 1102 /* 1103 * Function: 1104 * cmicx_dma_chan_counter_clear 1105 * Purpose: 1106 * clear tx and rx counter values 1107 * Parameters: 1108 * unit - SOC unit # 1109 * vchan - SOC virtual channel number 1110 * mask - to clear the appopriate counter 1111 * Returns: 1112 * SOC_E_NONE - success 1113 * Notes: 1114 */ 1115 static int 1116 cmicx_dma_chan_counter_clear(int unit, int vchan, uint32 mask) 1117 { 1118 int rv = SOC_E_NONE; 1119 int cmc = vchan / CMICX_N_DMA_CHAN; 1120 int chan = vchan % CMICX_N_DMA_CHAN; 1121 1122 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1123 (BSL_META_U(unit, 1124 "channel counter clear\n"))); 1125 1126 if (mask & 0x1) { 1127 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_TXPKT_OFFSET(cmc, chan), 0); 1128 } 1129 1130 if (mask & 0x2) { 1131 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_OFFSET(cmc, chan), 0); 1132 } 1133 1134 /* Keep this code ready just in case apps start to use this feature of rx pkt drops */ 1135 if (mask & 0x4) { 1136 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_PKT_COUNT_RXPKT_DROP_OFFSET(cmc, chan), 0); 1137 } 1138 1139 return rv; 1140 } 1141 1142 /* 1143 * Function: 1144 * cmicx_dma_cmc_counter_get 1145 * Purpose: 1146 * Obtain tx and rx counter values 1147 * Parameters: 1148 * unit - SOC unit # 1149 * cmc - cmc number 1150 * Returns: 1151 * SOC_E_NONE - success 1152 * Notes: 1153 */ 1154 static int 1155 cmicx_dma_cmc_counter_get(int unit, int cmc, uint32 *tx_pkt, uint32 *rx_pkt) 1156 { 1157 int rv = SOC_E_NONE; 1158 1159 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1160 (BSL_META_U(unit, 1161 "cmc counter get\n"))); 1162 1163 *tx_pkt = soc_pci_read(unit, CMIC_CMCx_SHARED_PKT_COUNT_TXPKT_OFFSET(cmc)); 1164 *rx_pkt = soc_pci_read(unit, CMIC_CMCx_SHARED_PKT_COUNT_RXPKT_OFFSET(cmc)); 1165 1166 return rv; 1167 } 1168 1169 /* 1170 * Function: 1171 * cmicx_dma_cmc_counter_clear 1172 * Purpose: 1173 * clear tx and rx counter values 1174 * Parameters: 1175 * unit - SOC unit # 1176 * cmc - cmc number 1177 * mask - to clear the appopriate counter 1178 * Returns: 1179 * SOC_E_NONE - success 1180 * Notes: 1181 */ 1182 static int 1183 cmicx_dma_cmc_counter_clear(int unit, int cmc, uint32 mask) 1184 { 1185 int rv = SOC_E_NONE; 1186 1187 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1188 (BSL_META_U(unit, 1189 "cmc counter clear\n"))); 1190 1191 if (mask & 0x1) { 1192 soc_pci_write(unit, CMIC_CMCx_SHARED_PKT_COUNT_TXPKT_OFFSET(cmc), 0); 1193 } 1194 1195 if (mask & 0x2) { 1196 soc_pci_write(unit, CMIC_CMCx_SHARED_PKT_COUNT_RXPKT_OFFSET(cmc), 0); 1197 } 1198 1199 return rv; 1200 } 1201 1202 /* 1203 * Function: 1204 * cmicx_loopback_config 1205 * Purpose: 1206 * Set/reset cmicx in loopback mode 1207 * Parameters: 1208 * unit - SOC unit # 1209 * cfg - to set/reset 1210 * Returns: 1211 * SOC_E_NONE - success 1212 * SOC_E_XXXX - error code 1213 * Notes: 1214 */ 1215 1216 int 1217 cmicx_loopback_config(int unit, uint32 cfg) 1218 { 1219 int rv = SOC_E_NONE; 1220 uint32 val = 0; 1221 1222 val = soc_pci_read(unit, CMIC_TOP_CONFIG_OFFSET); 1223 val &= 0x3f; 1224 1225 if (cfg & 0x1) { 1226 val |= (1 << 1); 1227 soc_pci_write(unit, CMIC_TOP_CONFIG_OFFSET, val); 1228 } else { 1229 val &= ~(1 << 1); 1230 soc_pci_write(unit, CMIC_TOP_CONFIG_OFFSET, val); 1231 } 1232 1233 return rv; 1234 } 1235 1236 /* 1237 * Function: 1238 * cmicx_dma_header_size_get 1239 * Purpose: 1240 * obtain the ep to cpu header size 1241 * Parameters: 1242 * unit - SOC unit # 1243 * hdr_size - return value of the ep to cpu header size 1244 * 1245 * Returns: 1246 * SOC_E_NONE - success 1247 * SOC_E_XXXX - error code 1248 * Notes: 1249 */ 1250 1251 static int 1252 cmicx_dma_header_size_get(int unit, uint32 *hdr_size) 1253 { 1254 int rv = SOC_E_NONE; 1255 1256 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1257 (BSL_META_U(unit, 1258 "cmicx dma get header size\n"))); 1259 1260 *hdr_size = ((soc_pci_read(unit, CMIC_TOP_EP_TO_CPU_HEADER_SIZE_OFFSET) & 0xf) * 8); 1261 1262 return rv; 1263 } 1264 1265 /* 1266 * Function: 1267 * cmicx_dma_max_rx_channels_get 1268 * Purpose: 1269 * obtain maximum number of dma channels that can be used for BCM RX 1270 * Parameters: 1271 * unit - SOC unit # 1272 * max_rx_channels - maximum rx channels that can be used 1273 * Returns: 1274 * SOC_E_NONE - success 1275 * SOC_E_XXXX - error 1276 */ 1277 1278 int 1279 cmicx_dma_max_rx_channels_get(int unit, uint32 *max_rx_channels) 1280 { 1281 int rv = SOC_E_NONE; 1282 1283 /* 1284 * Only CMC0 is used for BCM RX hence we can have 1285 * CMICX_N_DMA_CHAN number of maximum rx channels 1286 */ 1287 1288 *max_rx_channels = CMICX_N_DMA_CHAN; 1289 1290 return rv; 1291 } 1292 1293 /* 1294 * Function: 1295 * cmicx_dma_chan_cos_ctrl_get 1296 * Purpose: 1297 * get cos ctrl for a channel 1298 * Parameters: 1299 * unit - SOC unit # 1300 * cfg - to choose appropriate register 1301 * Returns: 1302 * SOC_E_NONE - success 1303 * SOC_E_XXXX - error code 1304 * Notes: 1305 */ 1306 1307 int 1308 cmicx_dma_chan_cos_ctrl_get(int unit, int vchan, uint32 cfg, uint32 *cos_ctrl) 1309 { 1310 int rv = SOC_E_NONE; 1311 int cmc = vchan / CMICX_N_DMA_CHAN; 1312 int chan = vchan % CMICX_N_DMA_CHAN; 1313 1314 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1315 (BSL_META_U(unit, 1316 "channel cos ctrl get\n"))); 1317 1318 if (cfg & 0x1) { 1319 *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan)); 1320 } else if (cfg & 0x2) { 1321 *cos_ctrl = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan)); 1322 } 1323 1324 return rv; 1325 } 1326 1327 /* 1328 * Function: 1329 * cmicx_dma_chan_cos_ctrl_set 1330 * Purpose: 1331 * get cos ctrl for a channel 1332 * Parameters: 1333 * unit - SOC unit # 1334 * cfg - to choose appropriate register 1335 * Returns: 1336 * SOC_E_NONE - success 1337 * SOC_E_XXXX - error code 1338 * Notes: 1339 */ 1340 1341 int 1342 cmicx_dma_chan_cos_ctrl_set(int unit, int vchan, uint32 cfg, uint32 cos_ctrl) 1343 { 1344 int rv = SOC_E_NONE; 1345 int cmc = vchan / CMICX_N_DMA_CHAN; 1346 int chan = vchan % CMICX_N_DMA_CHAN; 1347 1348 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1349 (BSL_META_U(unit, 1350 "channel cos ctrl set\n"))); 1351 1352 if (cfg & 0x1) { 1353 soc_pci_write(unit, 1354 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan), 1355 cos_ctrl); 1356 } else if (cfg & 0x2) { 1357 soc_pci_write(unit, 1358 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan), 1359 cos_ctrl); 1360 } 1361 1362 return rv; 1363 } 1364 1365 /* 1366 * Function: 1367 * cmicx_dma_chan_cos_ctrl_queue_get 1368 * Purpose: 1369 * get cos ctrl for a channel based on queue 1370 * Parameters: 1371 * unit - SOC unit # 1372 * cmc - CMC # 1373 * chan - chan # 1374 * queue - cos queue 1375 * cos_ctrl - cos ctrl val 1376 * Returns: 1377 * SOC_E_NONE - success 1378 * SOC_E_XXXX - error code 1379 * Notes: 1380 */ 1381 1382 int 1383 cmicx_dma_chan_cos_ctrl_queue_get(int unit, int cmc, int chan, 1384 int queue, uint32 *cos_ctrl) 1385 { 1386 int rv = SOC_E_NONE; 1387 uint32 reg_addr; 1388 1389 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1390 (BSL_META_U(unit, 1391 "channel cos ctrl queue get\n"))); 1392 1393 reg_addr = (queue < 32) ? 1394 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) : 1395 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan); 1396 1397 *cos_ctrl = soc_pci_read(unit, reg_addr); 1398 1399 return rv; 1400 } 1401 1402 /* 1403 * Function: 1404 * cmicx_dma_chan_cos_ctrl_reg_addr_get 1405 * Purpose: 1406 * get cos ctrl for a channel based on queue 1407 * Parameters: 1408 * unit - SOC unit # 1409 * cmc - CMC # 1410 * chan - chan # 1411 * queue - cos queue 1412 * reg_addr - reg addr val 1413 * Returns: 1414 * SOC_E_NONE - success 1415 * SOC_E_XXXX - error code 1416 * Notes: 1417 */ 1418 1419 int 1420 cmicx_dma_chan_cos_ctrl_reg_addr_get(int unit, int cmc, int chan, 1421 int queue, uint32 *reg_addr) 1422 { 1423 int rv = SOC_E_NONE; 1424 1425 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1426 (BSL_META_U(unit, 1427 "channel cos ctrl reg addr get\n"))); 1428 1429 *reg_addr = (queue < 32) ? 1430 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_0_OFFSET(cmc, chan) : 1431 CMIC_CMCx_PKTDMA_CHy_COS_CTRL_RX_1_OFFSET(cmc, chan); 1432 1433 return rv; 1434 } 1435 1436 /* 1437 * Function: 1438 * cmicx_dma_chan_status_get 1439 * Purpose: 1440 * get channel status 1441 * Parameters: 1442 * unit - SOC unit # 1443 * vchan - channel # 1444 * status - channel status 1445 * 1446 * Returns: 1447 * SOC_E_NONE - success 1448 * SOC_E_XXXX - error code 1449 * Notes: 1450 */ 1451 1452 int 1453 cmicx_dma_chan_status_get(int unit, int vchan, uint32 mask, int *status) 1454 { 1455 int rv = SOC_E_NONE; 1456 int cmc = vchan / CMICX_N_DMA_CHAN; 1457 int chan = vchan % CMICX_N_DMA_CHAN; 1458 1459 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1460 (BSL_META_U(unit, 1461 "channel status get\n"))); 1462 1463 *status = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan)); 1464 1465 return rv; 1466 } 1467 1468 /* 1469 * Function: 1470 * cmicx_dma_chan_halt_get 1471 * Purpose: 1472 * get channel halt status 1473 * Parameters: 1474 * unit - SOC unit # 1475 * vchan - channel # 1476 * halt - channel halt status 1477 * 1478 * Returns: 1479 * SOC_E_NONE - success 1480 * SOC_E_XXXX - error code 1481 * Notes: 1482 */ 1483 1484 int 1485 cmicx_dma_chan_halt_get(int unit, int vchan, uint32 mask, int *halt) 1486 { 1487 int rv = SOC_E_NONE; 1488 int cmc = vchan / CMICX_N_DMA_CHAN; 1489 int chan = vchan % CMICX_N_DMA_CHAN; 1490 1491 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1492 (BSL_META_U(unit, 1493 "channel halt get\n"))); 1494 1495 *halt = (soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_STAT_OFFSET(cmc, chan)) 1496 & PKTDMA_CH_IN_HALT); 1497 1498 return rv; 1499 } 1500 1501 /* 1502 * Function: 1503 * cmicx_dma_chan_ctrl_reg_get 1504 * Purpose: 1505 * get channel ctrl reg value 1506 * Parameters: 1507 * unit - SOC unit # 1508 * vchan - channel # 1509 * value - channel ctrl reg value 1510 * 1511 * Returns: 1512 * SOC_E_NONE - success 1513 * SOC_E_XXXX - error code 1514 * Notes: 1515 */ 1516 1517 int 1518 cmicx_dma_chan_ctrl_reg_get(int unit, int vchan, uint32 *val) 1519 { 1520 int rv = SOC_E_NONE; 1521 int cmc = vchan / CMICX_N_DMA_CHAN; 1522 int chan = vchan % CMICX_N_DMA_CHAN; 1523 1524 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1525 (BSL_META_U(unit, 1526 "channel ctrl reg get\n"))); 1527 1528 *val = soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)); 1529 1530 return rv; 1531 } 1532 1533 /* 1534 * Function: 1535 * cmicx_dma_chan_ctrl_reg_set 1536 * Purpose: 1537 * set channel ctrl reg 1538 * Parameters: 1539 * unit - SOC unit # 1540 * vchan - channel # 1541 * value - channel ctrl reg value to set 1542 * 1543 * Returns: 1544 * SOC_E_NONE - success 1545 * SOC_E_XXXX - error code 1546 * Notes: 1547 */ 1548 1549 int 1550 cmicx_dma_chan_ctrl_reg_set(int unit, int vchan, uint32 val) 1551 { 1552 int rv = SOC_E_NONE; 1553 int cmc = vchan / CMICX_N_DMA_CHAN; 1554 int chan = vchan % CMICX_N_DMA_CHAN; 1555 1556 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1557 (BSL_META_U(unit, 1558 "channel ctrl reg get\n"))); 1559 1560 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), val); 1561 1562 return rv; 1563 } 1564 1565 /* 1566 * Function: 1567 * cmicx_dma_chan_rxbuf_threshold_config 1568 * Purpose: 1569 * appropriately set mmu back pressure per channel 1570 * Parameters: 1571 * unit - SOC unit # 1572 * vchan - channel # 1573 * value - mmu backpressure settings 1574 * 1575 * Returns: 1576 * SOC_E_NONE - success 1577 * SOC_E_XXXX - error code 1578 * Notes: 1579 */ 1580 1581 int 1582 cmicx_dma_chan_rxbuf_threshold_config(int unit, int vchan, uint32 val) 1583 { 1584 int rv = SOC_E_NONE; 1585 int cmc = vchan / CMICX_N_DMA_CHAN; 1586 int chan = vchan % CMICX_N_DMA_CHAN; 1587 1588 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1589 (BSL_META_U(unit, 1590 "channel rxbuf threshold config\n"))); 1591 1592 soc_pci_write(unit, CMIC_CMCx_PKTDMA_CHy_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc, chan), val); 1593 1594 return rv; 1595 } 1596 1597 /* 1598 * Function: 1599 * cmicx_dma_cmc_rxbuf_threshold_config 1600 * Purpose: 1601 * appropriately set mmu back pressure per cmc 1602 * Parameters: 1603 * unit - SOC unit # 1604 * cmc - cmc # 1605 * value - mmu backpressure settings 1606 * 1607 * Returns: 1608 * SOC_E_NONE - success 1609 * SOC_E_XXXX - error code 1610 * Notes: 1611 */ 1612 1613 int 1614 cmicx_dma_cmc_rxbuf_threshold_config(int unit, int cmc, uint32 val) 1615 { 1616 int rv = SOC_E_NONE; 1617 1618 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1619 (BSL_META_U(unit, 1620 "cmc rxbuf threshold config\n"))); 1621 1622 soc_pci_write(unit, CMIC_CMCx_SHARED_RXBUF_THRESHOLD_CONFIG_OFFSET(cmc), val); 1623 1624 return rv; 1625 } 1626 1627 /* 1628 * Function: 1629 * cmicx_dma_masks_get 1630 * Purpose: 1631 * obtain the individual big endian masks 1632 * Parameters: 1633 * unit - SOC unit # 1634 * pkt_endian - pkt endian mask 1635 * desc_endian - desc endian mask 1636 * header_endian - header endian mask 1637 * 1638 * Returns: 1639 * SOC_E_NONE - success 1640 * SOC_E_XXXX - error code 1641 * Notes: 1642 */ 1643 1644 int 1645 cmicx_dma_masks_get(int unit, uint32 *pkt_endian, uint32 *desc_endian, uint32 *header_endian) 1646 { 1647 int rv = SOC_E_NONE; 1648 1649 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1650 (BSL_META_U(unit, 1651 "cmicx dma get masks\n"))); 1652 1653 *pkt_endian = PKTDMA_BIG_ENDIAN; 1654 *desc_endian = PKTDMA_DESC_BIG_ENDIAN; 1655 *header_endian = PKTDMA_HEADER_ENDIAN; 1656 1657 return rv; 1658 } 1659 1660 /* 1661 * Function: 1662 * cmicx_dma_chan_tx_purge 1663 * Purpose: 1664 * Purge partial pkt left in the pipeline from TX DMA abort. 1665 * Parameters: 1666 * unit - SOC unit # 1667 * chan - channel # 1668 * Returns: 1669 * SOC_E_NONE - Success 1670 * SOC_E_TIMEOUT - failed (Timeout) 1671 * Notes: 1672 * Assumes SOC_DMA_LOCK is held for CMIC_DMA_CTRL manipulation. 1673 */ 1674 static int 1675 cmicx_dma_chan_tx_purge(int unit, int vchan, dv_t *dv) 1676 { 1677 int rv = SOC_E_NONE; 1678 int cmc = vchan / CMICX_N_DMA_CHAN; 1679 int chan = vchan % CMICX_N_DMA_CHAN; 1680 sal_usecs_t start_time; 1681 int diff_time; 1682 uint32 dma_stat; 1683 uint32 dma_state; 1684 sal_paddr_t addr; 1685 1686 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1687 (BSL_META_U(unit, 1688 "channel tx purge cmc = %d channel = %d\n"), 1689 cmc, chan)); 1690 1691 soc_pci_write(unit, 1692 CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), 1693 soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)) 1694 | PKTDMA_DIRECTION); 1695 1696 addr = soc_cm_l2p(unit, dv->dv_dcb); 1697 1698 soc_pci_write(unit, 1699 CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_LO_OFFSET(cmc, chan), 1700 PTR_TO_INT(addr)); 1701 if (soc_cm_get_bus_type(unit) & SOC_PCI_DEV_TYPE) { 1702 soc_pci_write(unit, 1703 CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan), 1704 (CMIC_PCIE_SO_OFFSET | PTR_HI_TO_INT(addr))); 1705 } else { 1706 soc_pci_write(unit, 1707 CMIC_CMCx_PKTDMA_CHy_DESC_ADDR_HI_OFFSET(cmc, chan), 1708 PTR_HI_TO_INT(addr)); 1709 } 1710 1711 /* Start DMA */ 1712 soc_pci_write(unit, 1713 CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), 1714 soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc ,chan)) 1715 | PKTDMA_ENABLE); 1716 1717 start_time = sal_time_usecs(); 1718 diff_time = 0; 1719 dma_state = (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan)); 1720 1721 do { 1722 sal_udelay(SAL_BOOT_SIMULATION ? 1000 : 10); 1723 dma_stat = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)) & 1724 (DS_CMCx_CHy_DMA_DESC_DONE(chan) | DS_CMCx_CHy_DMA_CHAIN_DONE(chan)); 1725 1726 diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time); 1727 1728 if (diff_time > DMA_ABORT_TIMEOUT) { /* 10 Sec(QT)/10 msec */ 1729 rv = SOC_E_TIMEOUT; 1730 break; 1731 } else if (diff_time < 0) { 1732 /* Restart in case system time changed */ 1733 start_time = sal_time_usecs(); 1734 } 1735 } while (dma_stat != dma_state); 1736 1737 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1738 (BSL_META_U(unit, 1739 "disabling dma\n"))); 1740 1741 /* Clear CHAIN_DONE and DESC_DONE */ 1742 soc_pci_write(unit, 1743 CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan), 1744 soc_pci_read(unit, CMIC_CMCx_PKTDMA_CHy_CTRL_OFFSET(cmc, chan)) 1745 & ~PKTDMA_ENABLE); 1746 1747 dma_stat = soc_pci_read(unit, CMIC_CMCx_SHARED_IRQ_STAT0_OFFSET(cmc)); 1748 soc_pci_write(unit, 1749 CMIC_CMCx_SHARED_IRQ_STAT_CLR0_OFFSET(cmc), 1750 (DS_CMCx_CHy_DMA_DESC_DONE(chan))); 1751 1752 return rv; 1753 } 1754 1755 1756 /* 1757 * Function: 1758 * cmicx_dma_init 1759 * Purpose: 1760 * Initialize the CMICX DMA for the specified SOC unit. 1761 * Parameters: 1762 * unit - SOC unit # 1763 * Returns: 1764 * SOC_E_NONE - success 1765 * SOC_E_XXXX - error code 1766 * Notes: 1767 */ 1768 static int 1769 cmicx_dma_init(int unit) 1770 { 1771 int cmc, ch; 1772 soc_cmic_intr_handler_t *handle; 1773 soc_cmic_intr_handler_t *hitr; 1774 int rv = SOC_E_NONE; 1775 uint32 intr_base = 0; 1776 1777 LOG_VERBOSE(BSL_LS_SOC_PACKETDMA, 1778 (BSL_META_U(unit, 1779 "cmicx dma init, registering interrupts\n"))); 1780 1781 /* Register the descriptor done interrupts */ 1782 handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMIC_CMC_NUM_MAX* 1783 CMICX_N_DMA_CHAN, "pktdma_desc_controlled_interrupt"); 1784 if (handle == NULL) { 1785 return SOC_E_MEMORY; 1786 } 1787 1788 hitr = handle; 1789 1790 for (cmc = 0; cmc < CMIC_CMC_NUM_MAX; cmc++) { 1791 intr_base = cmicx_dma_get_intr_base(cmc); 1792 for (ch = 0; ch < CMICX_N_DMA_CHAN; ch++) { 1793 _intr_data[cmc][ch].cmc = cmc; 1794 _intr_data[cmc][ch].ch = ch; 1795 hitr->num = intr_base + (4 * ch) + CH_DESC_CONTROLLED_INTR; 1796 hitr->intr_fn = cmicx_pktdma_ch_desc_done; 1797 hitr->intr_data = &_intr_data[cmc][ch]; 1798 hitr++; 1799 } 1800 } 1801 rv = soc_cmic_intr_register(unit, handle, 1802 CMIC_CMC_NUM_MAX*CMICX_N_DMA_CHAN); 1803 sal_free(handle); 1804 1805 /* Register the chain done interrupts */ 1806 handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMIC_CMC_NUM_MAX* 1807 CMICX_N_DMA_CHAN, "pktdma_chain_done_interrupt"); 1808 if (handle == NULL) { 1809 return SOC_E_MEMORY; 1810 } 1811 1812 hitr = handle; 1813 1814 for (cmc = 0; cmc < CMIC_CMC_NUM_MAX; cmc++) { 1815 intr_base = cmicx_dma_get_intr_base(cmc); 1816 for (ch = 0; ch < CMICX_N_DMA_CHAN; ch++) { 1817 _intr_data[cmc][ch].cmc = cmc; 1818 _intr_data[cmc][ch].ch = ch; 1819 hitr->num = intr_base + (4 * ch) + CH_CHAIN_DONE; 1820 hitr->intr_fn = cmicx_pktdma_ch_chain_done; 1821 hitr->intr_data = &_intr_data[cmc][ch]; 1822 hitr++; 1823 } 1824 } 1825 rv = soc_cmic_intr_register(unit, handle, 1826 CMIC_CMC_NUM_MAX*CMICX_N_DMA_CHAN); 1827 sal_free(handle); 1828 1829 /* Register the desc done interrupts */ 1830 handle = sal_alloc(sizeof(soc_cmic_intr_handler_t)*CMIC_CMC_NUM_MAX* 1831 CMICX_N_DMA_CHAN, "pktdma_descriptor_done_interrupt"); 1832 if (handle == NULL) { 1833 return SOC_E_MEMORY; 1834 } 1835 1836 hitr = handle; 1837 1838 for (cmc = 0; cmc < CMIC_CMC_NUM_MAX; cmc++) { 1839 intr_base = cmicx_dma_get_intr_base(cmc); 1840 for (ch = 0; ch < CMICX_N_DMA_CHAN; ch++) { 1841 _intr_data[cmc][ch].cmc = cmc; 1842 _intr_data[cmc][ch].ch = ch; 1843 hitr->num = intr_base + (4 * ch) + CH_DESC_DONE; 1844 hitr->intr_fn = cmicx_pktdma_ch_desc_done; 1845 hitr->intr_data = &_intr_data[cmc][ch]; 1846 hitr++; 1847 } 1848 } 1849 rv = soc_cmic_intr_register(unit, handle, 1850 CMIC_CMC_NUM_MAX*CMICX_N_DMA_CHAN); 1851 sal_free(handle); 1852 1853 return rv; 1854 } 1855 1856 /* Public Assignment Function */ 1857 1858 /* 1859 * Function: 1860 * soc_cmicx_dma_drv_init 1861 * Purpose: 1862 * Initialize the CMICX DMA driver for the specified SOC unit. 1863 * Assign function pointers for SOC DMA driver interface. 1864 * Parameters: 1865 * unit - SOC unit # 1866 * drv - pointer to the function vector list 1867 * Returns: 1868 * SOC_E_NONE - success 1869 * SOC_E_XXXX - error code 1870 * Notes: 1871 */ 1872 int 1873 soc_cmicx_dma_drv_init(int unit, soc_cmic_dma_drv_t *drv) 1874 { 1875 int rv = SOC_E_NONE; 1876 1877 drv->init = cmicx_dma_init; 1878 drv->ctrl_init = cmicx_dma_ctrl_init; 1879 drv->chan_config = cmicx_dma_chan_config; 1880 drv->chan_dv_start = cmicx_dma_chan_dv_start; 1881 drv->chan_start = cmicx_dma_chan_start; 1882 drv->chan_poll = cmicx_dma_chan_poll; 1883 drv->chan_abort = cmicx_dma_chan_abort; 1884 drv->chan_tx_purge = cmicx_dma_chan_tx_purge; 1885 drv->chan_desc_done_intr_enable = cmicx_dma_chan_desc_done_intr_enable; 1886 drv->chan_desc_done = cmicx_dma_chan_desc_done; 1887 drv->chan_chain_done = cmicx_dma_chan_chain_done; 1888 drv->chan_reload_done = cmicx_dma_chan_reload_done; 1889 drv->chan_counter_get = cmicx_dma_chan_counter_get; 1890 drv->chan_counter_clear = cmicx_dma_chan_counter_clear; 1891 drv->chan_cos_ctrl_get = cmicx_dma_chan_cos_ctrl_get; 1892 drv->chan_cos_ctrl_set = cmicx_dma_chan_cos_ctrl_set; 1893 drv->chan_cos_ctrl_queue_get = cmicx_dma_chan_cos_ctrl_queue_get; 1894 drv->chan_cos_ctrl_reg_addr_get = cmicx_dma_chan_cos_ctrl_reg_addr_get; 1895 drv->chan_halt_get = cmicx_dma_chan_halt_get; 1896 drv->chan_status_get = cmicx_dma_chan_status_get; 1897 drv->chan_status_clear = NULL; 1898 drv->chan_ctrl_reg_get = cmicx_dma_chan_ctrl_reg_get; 1899 drv->chan_ctrl_reg_set = cmicx_dma_chan_ctrl_reg_set; 1900 drv->chan_rxbuf_threshold_cfg = cmicx_dma_chan_rxbuf_threshold_config; 1901 drv->cmc_rxbuf_threshold_cfg = cmicx_dma_cmc_rxbuf_threshold_config; 1902 drv->cmc_counter_get = cmicx_dma_cmc_counter_get; 1903 drv->cmc_counter_clear = cmicx_dma_cmc_counter_clear; 1904 drv->loopback_config = cmicx_loopback_config; 1905 drv->masks_get = cmicx_dma_masks_get; 1906 drv->header_size_get = cmicx_dma_header_size_get; 1907 drv->max_rx_channels_get = cmicx_dma_max_rx_channels_get; 1908 drv->pci_timeout_handle = NULL; 1909 1910 return rv; 1911 } 1912 #endif /* BCM_CMICX_SUPPORT */