openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 */