intr_cmicx.c (22600B)
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 * SOC CMICX Interrupt Handlers 8 * 9 * NOTE: These handlers are called from an interrupt context, so their 10 * actions are restricted accordingly. 11 */ 12 13 #include <shared/bsl.h> 14 15 #include <sal/core/libc.h> 16 #include <shared/alloc.h> 17 #include <sal/core/spl.h> 18 #include <sal/core/sync.h> 19 #include <sal/core/dpc.h> 20 21 #include <soc/debug.h> 22 #include <soc/drv.h> 23 #include <soc/feature.h> 24 #include <soc/mem.h> 25 #include <soc/iproc.h> 26 27 #ifdef BCM_CMICX_SUPPORT 28 #include <soc/intr_cmicx.h> 29 30 #define INTC_REMAP_BITPOS_BASE (INTC_REMAP_BITPOS_REG0r) 31 #define INTC_REMAP_BITPOS_NUM (5) 32 #define INTC_REMAP_BITS_NUM (6) 33 #define INTC_REMAP_BITPOS_OFFSET(intr) \ 34 ((intr / INTC_REMAP_BITPOS_NUM) + INTC_REMAP_BITPOS_BASE) 35 #define INTC_REMAP_BITPOS_SHIFT(intr) \ 36 ((intr % INTC_REMAP_BITPOS_NUM) * INTC_REMAP_BITS_NUM) 37 38 39 #define IRQ_CMC_NUM (CMC1_CH0_DESC_DONE - CMC0_CH0_DESC_DONE) 40 #define IS_UNIT_VALID(u) (u >= 0 && u < SOC_MAX_NUM_DEVICES) 41 #define IS_IRQ_VALID(intr) (intr < CMIC_INTERRUPT_NUM_MAX) 42 #define CMIC_INTR_HANDLE(u, n) (&_cmicx_handler[u].intr_handler[n]) 43 #define IRQ_MASK(u, i) (_irq_mask[u].mask[i]) 44 #define IRQ_MASK_SET(u, i, m) { \ 45 _irq_mask[u].mask[i] = m; \ 46 WRITE_INTC_INTR(u, _irq_reg_map[i].enable, m); \ 47 } 48 #define IHOST_ENABLE_IRQ(u, i, m, b) { \ 49 _irq_mask[u].mask[i] = m; \ 50 WRITE_INTC_INTR(u, _ihost_irq_reg_map[i].enable, b); \ 51 } 52 #define IHOST_DISABLE_IRQ(u, i, m, b) { \ 53 _irq_mask[u].mask[i] = m; \ 54 WRITE_INTC_INTR(u, _ihost_irq_reg_map[i].disable, b); \ 55 } 56 #define IRQ_BIT(intr) (intr % (sizeof(uint32)*8)) 57 #define IRQ_MASK_INDEX(intr) (intr / (sizeof(uint32)*8)) 58 59 60 #define READ_INTC_INTR(unit, reg, rvp) \ 61 soc_iproc_getreg(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0), rvp) 62 #define WRITE_INTC_INTR(unit, reg, rv) \ 63 soc_iproc_setreg(unit, soc_reg_addr(unit, reg, REG_PORT_ANY, 0), rv) 64 65 66 typedef struct cmicx_intr_handler_s { 67 soc_cmic_intr_handler_t intr_handler[CMIC_INTERRUPT_NUM_MAX]; 68 }cmicx_intr_handler_t; 69 70 typedef struct cmicx_intr_mask_s { 71 uint32 mask[CMICX_INTR_REG_NUM]; 72 }cmicx_irq_mask_t; 73 74 typedef struct cmicx_intr_reg_map_s { 75 uint32 enable; 76 uint32 stat; 77 char stat_nm[50]; 78 } cmicx_intr_reg_map_t; 79 80 typedef struct ihost_cmicx_intr_reg_map_s { 81 uint32 enable; 82 uint32 disable; 83 } ihost_cmicx_intr_reg_map_t; 84 85 /* local variable */ 86 87 STATIC cmicx_intr_handler_t _cmicx_handler[SOC_MAX_NUM_DEVICES]; 88 89 STATIC cmicx_irq_mask_t _irq_mask[SOC_MAX_NUM_DEVICES]; 90 91 STATIC cmicx_intr_reg_map_t _irq_reg_map[] = { 92 {INTC_INTR_ENABLE_REG0r, INTC_INTR_RAW_STATUS_REG0r, "INTR_RAW_STATUS_REG0r"}, 93 {INTC_INTR_ENABLE_REG1r, INTC_INTR_RAW_STATUS_REG1r, "INTR_RAW_STATUS_REG1r"}, 94 {INTC_INTR_ENABLE_REG2r, INTC_INTR_RAW_STATUS_REG2r, "INTR_RAW_STATUS_REG2r"}, 95 {INTC_INTR_ENABLE_REG3r, INTC_INTR_RAW_STATUS_REG3r, "INTR_RAW_STATUS_REG3r"}, 96 {INTC_INTR_ENABLE_REG4r, INTC_INTR_RAW_STATUS_REG4r, "INTR_RAW_STATUS_REG4r"}, 97 {INTC_INTR_ENABLE_REG5r, INTC_INTR_RAW_STATUS_REG5r, "INTR_RAW_STATUS_REG5r"}, 98 {INTC_INTR_ENABLE_REG6r, INTC_INTR_RAW_STATUS_REG6r, "INTR_RAW_STATUS_REG6r"}, 99 {INTC_INTR_ENABLE_REG7r, INTC_INTR_RAW_STATUS_REG7r, "INTR_RAW_STATUS_REG7r"}, 100 }; 101 102 STATIC ihost_cmicx_intr_reg_map_t _ihost_irq_reg_map[] = { 103 {IHOST_GIC_GIC400_GICD_ISENABLERN_1r, IHOST_GIC_GIC400_GICD_ICENABLERN_1r}, 104 {IHOST_GIC_GIC400_GICD_ISENABLERN_2r, IHOST_GIC_GIC400_GICD_ICENABLERN_2r}, 105 {IHOST_GIC_GIC400_GICD_ISENABLERN_3r, IHOST_GIC_GIC400_GICD_ICENABLERN_3r}, 106 {IHOST_GIC_GIC400_GICD_ISENABLERN_4r, IHOST_GIC_GIC400_GICD_ICENABLERN_4r}, 107 {IHOST_GIC_GIC400_GICD_ISENABLERN_5r, IHOST_GIC_GIC400_GICD_ICENABLERN_5r}, 108 {IHOST_GIC_GIC400_GICD_ISENABLERN_6r, IHOST_GIC_GIC400_GICD_ICENABLERN_6r}, 109 {IHOST_GIC_GIC400_GICD_ISENABLERN_7r, IHOST_GIC_GIC400_GICD_ICENABLERN_7r}, 110 {IHOST_GIC_GIC400_GICD_ISENABLERN_8r, IHOST_GIC_GIC400_GICD_ICENABLERN_8r}, 111 }; 112 113 /******************************************* 114 * @function _irq_least_bit_set 115 * purpose function to identify rightmost bit set 116 * 117 * @param unit [in] uint32 number 118 * 119 * @returns right most bit set 120 * @returns -1 if no bit is set 121 * 122 * @end 123 */ 124 125 STATIC int 126 _irq_least_bit_set(uint32 n) 127 { 128 uint32 bit = 0; 129 130 if (n == 0) { 131 return -1; 132 } 133 134 if ((n & 0x0000FFFF) == 0) { 135 bit = bit + 16; 136 n = n >> 16; 137 } 138 if ((n & 0x000000FF) == 0) { 139 bit = bit + 8; 140 n = n >> 8; 141 } 142 if ((n & 0x0000000F) == 0) { 143 bit = bit + 4; 144 n = n >> 4; 145 } 146 if ((n & 0x00000003) == 0) { 147 bit = bit + 2; 148 n = n >> 2; 149 } 150 if ((n & 0x00000001) == 0) { 151 bit = bit + 1; 152 } 153 154 return bit; 155 } 156 157 158 /******************************************* 159 * @function _soc_cmicx_intr_enable 160 * purpose Enable a particular interrupt 161 * 162 * @param unit [in] unit 163 * @param param [in] intr_num_t, IRQ Number 164 * 165 * @returns SOC_E_NONE 166 * @returns SOC_E_XXX 167 * 168 * @end 169 */ 170 STATIC int 171 _soc_cmicx_intr_enable(int unit, intr_num_t intr) 172 { 173 uint32 oldMask; 174 uint32 newMask; 175 int s, ind; 176 177 if (!IS_UNIT_VALID(unit)) { 178 return SOC_E_PARAM; 179 } 180 181 if (!IS_IRQ_VALID(intr)) { 182 return SOC_E_PARAM; 183 } 184 185 s = sal_splhi(); 186 ind = IRQ_MASK_INDEX(intr); 187 188 oldMask = IRQ_MASK(unit, ind); 189 newMask = 0x01 << IRQ_BIT(intr); 190 newMask |= oldMask; 191 192 /* In polled mode, the hardware IRQ mask is always zero */ 193 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 194 newMask = 0; 195 } 196 LOG_VERBOSE(BSL_LS_SOC_INTR, 197 (BSL_META_U(unit, 198 "%s:unit %d, intr %u\n"), 199 __func__, unit, intr)); 200 201 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 202 IHOST_ENABLE_IRQ(unit, ind, newMask, 0x01 << IRQ_BIT(intr)); 203 } else { 204 IRQ_MASK_SET(unit, ind, newMask); 205 } 206 207 /* In polling mode, keep the mask value */ 208 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 209 newMask = (uint32)0x01 << IRQ_BIT(intr); 210 newMask |= oldMask; 211 IRQ_MASK(unit, ind) = newMask; 212 } 213 214 sal_spl(s); 215 216 return SOC_E_NONE; 217 } 218 219 /******************************************* 220 * @function _soc_cmicx_intr_disable 221 * purpose Enable a particular interrupt 222 * 223 * @param unit [in] unit 224 * @param param [in] intr_num_t, IRQ Number 225 * 226 * @returns SOC_E_NONE 227 * @returns SOC_E_XXX 228 * 229 * @end 230 */ 231 STATIC int 232 _soc_cmicx_intr_disable(int unit, intr_num_t intr) 233 { 234 uint32 oldMask; 235 uint32 newMask; 236 int s, ind; 237 238 if (!IS_UNIT_VALID(unit)) { 239 return SOC_E_PARAM; 240 } 241 242 if (!IS_IRQ_VALID(intr)) { 243 return SOC_E_PARAM; 244 } 245 s = sal_splhi(); 246 247 ind = IRQ_MASK_INDEX(intr); 248 249 oldMask = IRQ_MASK(unit, ind); 250 newMask = 0x01 << IRQ_BIT(intr); 251 newMask = oldMask & ~newMask; 252 253 /* In polled mode, the hardware IRQ mask is always zero */ 254 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 255 newMask = 0; 256 } 257 LOG_VERBOSE(BSL_LS_SOC_INTR, 258 (BSL_META_U(unit, 259 "%s: unit %d, intr %u\n"), 260 __func__, unit, intr)); 261 262 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 263 IHOST_DISABLE_IRQ(unit, ind, newMask, 0x01 << IRQ_BIT(intr)); 264 } else { 265 IRQ_MASK_SET(unit, ind, newMask); 266 } 267 268 /* In polling mode, mask value be kept */ 269 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 270 newMask = (uint32)0x01 << IRQ_BIT(intr); 271 newMask = oldMask & ~newMask; 272 IRQ_MASK(unit, ind) = newMask; 273 } 274 275 sal_spl(s); 276 277 return SOC_E_NONE; 278 } 279 280 /******************************************* 281 * @function soc_cmic_intr_dump 282 * purpose dump registers particular interrupt 283 * 284 * @param unit [in] unit 285 * @param param [in] intr_num_t, Interrupt Number 286 * 287 * @returns SOC_E_NONE 288 * @returns SOC_E_XXX 289 * 290 * @end 291 */ 292 STATIC int 293 _soc_cmicx_intr_dump(int unit, intr_num_t intr) 294 { 295 uint32 mask, irqStat; 296 uint32 irqMask; 297 int i, s; 298 299 if (!IS_UNIT_VALID(unit)) { 300 return SOC_E_PARAM; 301 } 302 303 if (!IS_IRQ_VALID(intr)) { 304 return SOC_E_PARAM; 305 } 306 s = sal_splhi(); 307 308 i = IRQ_MASK_INDEX(intr); 309 mask = 0x01 << IRQ_BIT(intr); 310 311 READ_INTC_INTR(unit, _irq_reg_map[i].stat, &irqStat); 312 READ_INTC_INTR(unit, _irq_reg_map[i].enable, &irqMask); 313 314 LOG_WARN(BSL_LS_SOC_INTR, 315 (BSL_META_U(unit, 316 "%s:unit=%d, intr=%u, enable=%d, status=%d\n"), 317 __func__, unit, intr, 318 (irqMask & mask) ? 1 : 0, (irqStat & mask)? 1 : 0)); 319 320 sal_spl(s); 321 322 return SOC_E_NONE; 323 } 324 325 326 /******************************************* 327 * @function _soc_cmicx_intr_all_enable 328 * purpose Enable a particular interrupt 329 * 330 * @param unit [in] unit 331 * 332 * @returns SOC_E_NONE 333 * @returns SOC_E_XXX 334 * 335 * @end 336 */ 337 STATIC int 338 _soc_cmicx_intr_all_enable(int unit) 339 { 340 int i, s; 341 342 s = sal_splhi(); 343 344 for (i = 0; i < CMICX_INTR_REG_NUM; i++) { 345 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 346 if (i < IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY)) { 347 _irq_mask[unit].mask[i] = 0; 348 continue; 349 } 350 if (i == IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY)) { 351 IHOST_ENABLE_IRQ(unit, i, 0x01 << IRQ_BIT(CHIP_INTR_LOW_PRIORITY), 352 0x01 << IRQ_BIT(CHIP_INTR_LOW_PRIORITY)); 353 } else { 354 IHOST_ENABLE_IRQ(unit, i, ~0, ~0); 355 } 356 } else { 357 IRQ_MASK_SET(unit, i, ~0); 358 } 359 } 360 sal_spl(s); 361 362 return SOC_E_NONE; 363 } 364 365 /******************************************* 366 * @function _soc_cmicx_intr_all_disable 367 * purpose Enable a particular interrupt 368 * 369 * @param unit [in] unit 370 * 371 * @returns SOC_E_NONE 372 * @returns SOC_E_XXX 373 * 374 * @end 375 */ 376 STATIC int 377 _soc_cmicx_intr_all_disable(int unit) 378 { 379 int i, s; 380 381 s = sal_splhi(); 382 for (i = 0; i < CMICX_INTR_REG_NUM; i++) { 383 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 384 if (i < IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY)) { 385 _irq_mask[unit].mask[i] = 0; 386 continue; 387 } 388 if (i == IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY)) { 389 IHOST_DISABLE_IRQ(unit, i, 0, 0x01 << IRQ_BIT(CHIP_INTR_LOW_PRIORITY)); 390 } else { 391 IHOST_DISABLE_IRQ(unit, i, 0, ~0); 392 } 393 } else { 394 IRQ_MASK_SET(unit, i, 0); 395 } 396 } 397 sal_spl(s); 398 399 return SOC_E_NONE; 400 } 401 402 /******************************************* 403 * @function _soc_cmicx_intr_is_mask 404 * purpose Get specific interrupt mask status 405 * 406 * @param unit [in] unit 407 * @param param [in] intr_num_t, Interrupt Number 408 * 409 * @returns SOC_E_NONE 410 * @returns SOC_E_XXX 411 * 412 * @end 413 */ 414 STATIC int 415 _soc_cmicx_intr_is_mask(int unit, intr_num_t intr, int *mask) 416 { 417 uint32 oldMask; 418 uint32 newMask; 419 int s, ind; 420 421 if (mask == NULL) { 422 return SOC_E_PARAM; 423 } 424 425 if (!IS_UNIT_VALID(unit)) { 426 return SOC_E_PARAM; 427 } 428 429 if (!IS_IRQ_VALID(intr)) { 430 return SOC_E_PARAM; 431 } 432 433 s = sal_splhi(); 434 ind = IRQ_MASK_INDEX(intr); 435 436 oldMask = IRQ_MASK(unit, ind); 437 newMask = (uint32)0x01 << IRQ_BIT(intr); 438 *mask = (oldMask & newMask) ? 0 : 1; 439 440 sal_spl(s); 441 return SOC_E_NONE; 442 } 443 444 /******************************************* 445 * @function _soc_cmicx_intr_register 446 * purpose Register the interrupt handler 447 * 448 * @param unit [in] unit 449 * @param param [in] soc_cmic_intr_handler_t pointer 450 * @param param [in] int, size of the array elements 451 * 452 * @returns SOC_E_NONE 453 * @returns SOC_E_XXX 454 * 455 * @end 456 */ 457 STATIC int 458 _soc_cmicx_intr_register(int unit, soc_cmic_intr_handler_t *handle, int size) 459 { 460 int i, s; 461 462 if (!IS_UNIT_VALID(unit)) { 463 return SOC_E_UNIT; 464 } 465 466 if (!handle) { 467 return SOC_E_PARAM; 468 } 469 470 for (i = 0 ; i < size ; i++) { 471 if (!IS_IRQ_VALID(handle[i].num)) { 472 return SOC_E_PARAM; 473 } 474 475 if (!handle[i].intr_fn) { 476 return SOC_E_PARAM; 477 } 478 s = sal_splhi(); 479 sal_memcpy(CMIC_INTR_HANDLE(unit, handle[i].num), &handle[i], 480 sizeof(soc_cmic_intr_handler_t)); 481 sal_spl(s); 482 } 483 484 return SOC_E_NONE; 485 } 486 487 /******************************************* 488 * @function _soc_cmicx_intr_map 489 * purpose Map CMICX interrupts 490 * 491 * @param unit [in] unit 492 * @param cmic_start [in] int, cmic interrupt start 493 * @param cmic_end [in] int, cmic interrupt end 494 * @param msi_vec [in] int, MSI interrupt vector 495 * @returns SOC_E_NONE 496 * @returns SOC_E_XXX 497 * 498 * @end 499 */ 500 STATIC int 501 _soc_cmicx_intr_map(int unit, int cmic_start, int cmic_end, int msi_vec) 502 { 503 int i; 504 soc_reg_t reg; 505 uint32 val; 506 uint32 mask; 507 508 if (!IS_UNIT_VALID(unit)) { 509 return SOC_E_PARAM; 510 } 511 512 if (!IS_IRQ_VALID(cmic_start)) { 513 return SOC_E_PARAM; 514 } 515 516 if (!IS_IRQ_VALID(cmic_end)) { 517 return SOC_E_PARAM; 518 } 519 520 for (i = cmic_start; i <= cmic_end; i++) { 521 /* 6 bit mask, each interrupt is represented by */ 522 mask = ((0x01 << INTC_REMAP_BITS_NUM) - 1); 523 reg = INTC_REMAP_BITPOS_OFFSET(i); 524 READ_INTC_INTR(unit, reg, &val); 525 mask <<= INTC_REMAP_BITPOS_SHIFT(i); 526 val &= ~mask; 527 val |= msi_vec << INTC_REMAP_BITPOS_SHIFT(i); 528 WRITE_INTC_INTR(unit, reg, val); 529 } 530 531 return SOC_E_NONE; 532 } 533 534 /******************************************* 535 * @function soc_cmicx_intr_init 536 * purpose initialize CMICX interrupt framework 537 * 538 * @param unit [in] unit 539 * @param unit [out] soc_cmic_intr_op_t pointer 540 * @returns SOC_E_NONE 541 * @returns SOC_E_XXX 542 * 543 * @end 544 */ 545 int 546 soc_cmicx_intr_init(int unit, soc_cmic_intr_op_t *intr_op) 547 { 548 if (!IS_UNIT_VALID(unit)) { 549 return SOC_E_UNIT; 550 } 551 552 sal_memset(&_cmicx_handler[unit], 0, sizeof(cmicx_intr_handler_t)); 553 sal_memset(&_irq_mask[unit], 0, sizeof(cmicx_irq_mask_t)); 554 555 /* 556 * Since linux BDE currently supports only one bit MSI interrupt vector 557 * All interrupts will be currntly assigned to bit 0. We need to 558 * Identify the use cases how interrupts can be grouped and 559 * partitioned based on performance requirement along with BDE changes 560 * to support multiple MSI/MSIX interrupt requests. 561 */ 562 563 /*Map Non CMIC interrupt */ 564 _soc_cmicx_intr_map(unit, WDOG_INTR, 565 CHIP_INTR_LOW_PRIORITY, 0); 566 567 /* Map CMIC interrupts */ 568 _soc_cmicx_intr_map(unit, CMC0_CH0_DESC_DONE, 569 SCHAN_FIFO_CH1_DONE, 0); 570 571 /* Set MSI mode to SW clear vs auto clear */ 572 WRITE_PAXB_0_PAXB_IC_INTRCLR_MODE_0r(unit, 0); 573 WRITE_PAXB_0_PAXB_IC_INTRCLR_MODE_1r(unit, 0); 574 575 intr_op->soc_cmic_intr_enable = _soc_cmicx_intr_enable; 576 intr_op->soc_cmic_intr_disable = _soc_cmicx_intr_disable; 577 intr_op->soc_cmic_intr_dump = _soc_cmicx_intr_dump; 578 intr_op->soc_cmic_intr_all_enable = _soc_cmicx_intr_all_enable; 579 intr_op->soc_cmic_intr_all_disable = _soc_cmicx_intr_all_disable; 580 intr_op->soc_cmic_intr_is_mask = _soc_cmicx_intr_is_mask; 581 intr_op->soc_cmic_intr_register = _soc_cmicx_intr_register; 582 583 return SOC_E_NONE; 584 } 585 586 /******************************************* 587 * @function soc_cmicx_intr 588 * purpose SOC CMICX Interrupt Service Routine 589 * 590 * @param unit [in] unit 591 * 592 * 593 * @end 594 */ 595 void 596 soc_cmicx_intr(void *_unit) 597 { 598 soc_control_t *soc; 599 uint32 irqStat, irqMask, mask; 600 #ifdef BROADCOM_DEBUG 601 uint32 irqEnable; 602 #endif 603 int unit = PTR_TO_INT(_unit); 604 int i = 0; 605 int intr, s; 606 607 s = sal_splhi(); 608 609 /* Clear MSI interrupts immediately to prevent spurious interrupts */ 610 WRITE_PAXB_0_PAXB_IC_INTRCLR_0r(unit, 0xFFFFFFFF); 611 WRITE_PAXB_0_PAXB_IC_INTRCLR_1r(unit, 0xFFFFFFFF); 612 soc = SOC_CONTROL(unit); 613 614 if (soc == NULL || (soc->soc_flags & SOC_F_BUSY) || 615 !(soc->soc_flags & SOC_F_ATTACHED)) { 616 sal_spl(s); 617 return; 618 } 619 620 soc->stat.intr++; /* Update count */ 621 622 for (i = 0; i < CMICX_INTR_REG_NUM; i++) { 623 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 624 if (i == IRQ_MASK_INDEX(CMC0_CH0_DESC_DONE)) 625 { 626 /** Bypass Packet DMA Interrupts */ 627 continue; 628 } 629 #endif 630 #ifdef INCLUDE_KNET 631 if (SOC_KNET_MODE(unit) && i == IRQ_MASK_INDEX(CMC0_CH0_DESC_DONE)) { 632 continue; 633 } 634 #endif 635 636 if ((soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) && 637 (i < IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY))) { 638 continue; 639 } 640 641 READ_INTC_INTR(unit, _irq_reg_map[i].stat, &irqStat); 642 643 if ((soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) && 644 (i == IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY))) { 645 irqStat &= 0x01 << IRQ_BIT(CHIP_INTR_LOW_PRIORITY); 646 } 647 648 irqMask = IRQ_MASK(unit, i); 649 650 /* Re-Enable Enabled-but-Unserviced interrupts */ 651 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 652 IRQ_MASK(unit, i) = (irqMask & ~irqStat); 653 } else { 654 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 655 IHOST_ENABLE_IRQ(unit, i, (irqMask & ~irqStat), (irqMask & ~irqStat)); 656 } else { 657 IRQ_MASK_SET(unit, i, (irqMask & ~irqStat)); 658 } 659 } 660 LOG_VERBOSE(BSL_LS_SOC_INTR, 661 (BSL_META_U(unit, 662 "%s:unit %d, stat reg %s, val = 0x%x mask = 0x%x prog-enable = 0x%x\n"), 663 __func__, unit, _irq_reg_map[i].stat_nm, irqStat, irqMask, (irqMask & ~irqStat))); 664 665 #ifdef BROADCOM_DEBUG 666 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 667 READ_INTC_INTR(unit, _ihost_irq_reg_map[i].enable, &irqEnable); 668 } else { 669 READ_INTC_INTR(unit, _irq_reg_map[i].enable, &irqEnable); 670 } 671 LOG_VERBOSE(BSL_LS_SOC_INTR, (BSL_META_U(unit, 672 "%s:unit %d, enable reg %s 0x%x\n"), 673 __func__, unit, _irq_reg_map[i].stat_nm, irqEnable)); 674 #endif 675 676 while (irqStat) { 677 intr = _irq_least_bit_set(irqStat); 678 mask = 0x01 << intr; 679 intr += i * (sizeof(uint32) << 3); 680 if ((irqMask & mask) && IS_IRQ_VALID(intr)) { 681 if ((CMIC_INTR_HANDLE(unit, intr)->num == intr) && 682 (CMIC_INTR_HANDLE(unit, intr)->intr_fn != NULL)) { 683 684 LOG_VERBOSE(BSL_LS_SOC_INTR, (BSL_META_U(unit, 685 "%s:unit %d, intr %u\n"), 686 __func__, unit, intr)); 687 688 CMIC_INTR_HANDLE(unit, intr)->intr_fn(unit, 689 CMIC_INTR_HANDLE(unit, intr)->intr_data); 690 } 691 } 692 irqStat = irqStat & ~mask; 693 } 694 } 695 696 sal_spl(s); 697 698 } 699 700 #ifdef SEPARATE_PKTDMA_INTR_HANDLER 701 /******************************************* 702 * @function soc_cmicx_pktdma_intr 703 * purpose SOC CMICX Interrupt Service Routine 704 * 705 * @param unit [in] unit 706 * 707 * 708 * @end 709 */ 710 void 711 soc_cmicx_pktdma_intr(void *_unit) 712 { 713 soc_control_t *soc; 714 uint32 irqStat, irqMask, mask; 715 #ifdef BROADCOM_DEBUG 716 uint32 irqEnable; 717 #endif 718 int unit = PTR_TO_INT(_unit); 719 int i = 0; 720 int intr, s; 721 722 s = sal_splhi(); 723 724 /* Clear MSI interrupts immediately to prevent spurious interrupts */ 725 WRITE_PAXB_0_PAXB_IC_INTRCLR_0r(unit, 0xFFFFFFFF); 726 WRITE_PAXB_0_PAXB_IC_INTRCLR_1r(unit, 0xFFFFFFFF); 727 soc = SOC_CONTROL(unit); 728 729 if (soc == NULL || (soc->soc_flags & SOC_F_BUSY) || 730 !(soc->soc_flags & SOC_F_ATTACHED)) { 731 sal_spl(s); 732 return; 733 } 734 735 soc->stat.intr++; /* Update count */ 736 737 i = IRQ_MASK_INDEX(CMC0_CH0_DESC_DONE); 738 739 #ifdef INCLUDE_KNET 740 if (SOC_KNET_MODE(unit) && i == IRQ_MASK_INDEX(CMC0_CH0_DESC_DONE)) { 741 return; 742 } 743 #endif 744 745 if ((soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) && 746 (i < IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY))) { 747 return; 748 } 749 750 READ_INTC_INTR(unit, _irq_reg_map[i].stat, &irqStat); 751 752 if ((soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) && 753 (i == IRQ_MASK_INDEX(CHIP_INTR_LOW_PRIORITY))) { 754 irqStat &= 0x01 << IRQ_BIT(CHIP_INTR_LOW_PRIORITY); 755 } 756 757 irqMask = IRQ_MASK(unit, i); 758 759 /* Re-Enable Enabled-but-Unserviced interrupts */ 760 if (SOC_CONTROL(unit)->soc_flags & SOC_F_POLLED) { 761 IRQ_MASK(unit, i) = (irqMask & ~irqStat); 762 } else { 763 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 764 IHOST_ENABLE_IRQ(unit, i, (irqMask & ~irqStat), (irqMask & ~irqStat)); 765 } else { 766 IRQ_MASK_SET(unit, i, (irqMask & ~irqStat)); 767 } 768 } 769 LOG_VERBOSE(BSL_LS_SOC_INTR, 770 (BSL_META_U(unit, 771 "%s:unit %d, stat reg %s, val = 0x%x mask = 0x%x prog-enable = 0x%x\n"), 772 __func__, unit, _irq_reg_map[i].stat_nm, irqStat, irqMask, (irqMask & ~irqStat))); 773 774 #ifdef BROADCOM_DEBUG 775 if (soc_cm_get_bus_type(unit) & SOC_AXI_DEV_TYPE) { 776 READ_INTC_INTR(unit, _ihost_irq_reg_map[i].enable, &irqEnable); 777 } else { 778 READ_INTC_INTR(unit, _irq_reg_map[i].enable, &irqEnable); 779 } 780 LOG_VERBOSE(BSL_LS_SOC_INTR, (BSL_META_U(unit, 781 "%s:unit %d, enable reg %s 0x%x\n"), 782 __func__, unit, _irq_reg_map[i].stat_nm, irqEnable)); 783 #endif 784 785 while (irqStat) { 786 intr = _irq_least_bit_set(irqStat); 787 mask = 0x01 << intr; 788 intr += i * (sizeof(uint32) << 3); 789 if ((irqMask & mask) && IS_IRQ_VALID(intr)) { 790 if ((CMIC_INTR_HANDLE(unit, intr)->num == intr) && 791 (CMIC_INTR_HANDLE(unit, intr)->intr_fn != NULL)) { 792 793 LOG_VERBOSE(BSL_LS_SOC_INTR, (BSL_META_U(unit, 794 "%s:unit %d, intr %u\n"), 795 __func__, unit, intr)); 796 797 CMIC_INTR_HANDLE(unit, intr)->intr_fn(unit, 798 CMIC_INTR_HANDLE(unit, intr)->intr_data); 799 } 800 } 801 irqStat = irqStat & ~mask; 802 } 803 804 sal_spl(s); 805 } 806 807 #endif 808 809 #endif /* CMICX Support */