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

pli.c (17328B)


      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  * File:        pli.c
      8  *
      9  * Provides:
     10  *      pli_reset_service
     11  *      pli_getreg_service
     12  *      pli_setreg_service
     13  *
     14  * Requires:
     15  *      soc_internal_reset
     16  *      soc_internal_<mem>
     17  *      soc_internal_send_int
     18  *      pcid_dma_stat_write
     19  *      pcid_dma_ctrl_write
     20  *      soc_internal_arl_init
     21  */
     22 
     23 #include <shared/bsl.h>
     24 
     25 #include <sys/types.h>
     26 #include <unistd.h>
     27 #include <stdlib.h>
     28 #include <sys/socket.h>
     29 
     30 #include <sys/time.h>
     31 #include <netinet/in.h>
     32 #include <arpa/inet.h>
     33 #include <memory.h>
     34 
     35 #include <soc/debug.h>
     36 #include <sal/appl/io.h>
     37 #include <bde/pli/verinet.h>
     38 
     39 #include "pcid.h"
     40 #include "mem.h"
     41 #include "cmicsim.h"
     42 #include "dma.h"
     43 #include "pli.h"
     44 
     45 #include <soc/cmic.h>
     46 #ifdef BCM_CMICM_SUPPORT
     47 #include <soc/cmicm.h>
     48 #endif
     49 #ifdef BCM_CMICX_SUPPORT
     50 #include "cmicx.h"
     51 #endif /* BCM_CMICX_SUPPORT */
     52 
     53 /*
     54  * pli_reset_service
     55  *
     56  * Set PCI memory state to reset defaults
     57  */
     58 int pli_reset_service(pcid_info_t *pcid_info)
     59 {
     60     soc_internal_reset(pcid_info);
     61     return 0;
     62 }
     63 
     64 
     65 
     66 /*
     67  * PLI protocol compatible "get register" routines
     68  */
     69 
     70 #ifdef BCM_CMICX_SUPPORT
     71 /* cmicx getreg service */
     72 STATIC void
     73 pli_cmicx_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
     74                          uint32 regnum, uint32 *value)
     75 {
     76     uint32 r;
     77     switch (type) {
     78 
     79         case SOC_INTERNAL:
     80             soc_internal_read_reg(pcid_info, regnum, value);
     81             break;
     82 
     83         case PCI_CONFIG:
     84             r = regnum & 0xfff;
     85             if (r < PCIC_SIZE) {
     86                 *value = PCIC(pcid_info, r);
     87             }
     88             break;
     89 
     90         case PCI_MEMORY:
     91 
     92             /*
     93             printf("reading CMICx reg!!!!!\n");
     94             printf("0x%08X \n",regnum & 0xFFFFF);
     95             */
     96 
     97             /* normal cmicx register read */
     98             cmicx_pcid_register_read(regnum,value);
     99             break;
    100 
    101     }
    102 }
    103 #endif /* BCM_CMICX_SUPPORT */
    104 
    105 uint32 pli_cmice_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
    106                          uint32 regnum, uint32 *value)
    107 {
    108     uint32 r;
    109     switch (type) {
    110     case PCI_CONFIG:
    111         r = regnum & 0xfff;
    112         if (r < PCIC_SIZE) {
    113             *value = PCIC(pcid_info, r);
    114         }
    115         break;
    116     case PCI_MEMORY:
    117         if (pcid_info->regmem_cb) {
    118             if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_READ,
    119                                       regnum, value,
    120                                       BYTES2BITS(sizeof(uint32)))) == 0)
    121                 break;
    122         }
    123         r = regnum & 0xffff;
    124         if (r == CMIC_LED_CTRL || r == CMIC_LED_STATUS) {
    125             *value = 0;
    126         } else if (r < PCIM_SIZE(unit)) {
    127             *value = PCIM(pcid_info, r);
    128         } else {
    129             *value = 0xdeadbeef;
    130         }
    131         break;
    132     case I2C_CONFIG:
    133         break;
    134     case PLI_CONFIG:
    135         break;
    136     case JTAG_CONFIG:
    137         break;
    138 
    139     case SOC_INTERNAL:
    140         soc_internal_read_reg(pcid_info, regnum, value);
    141         break;
    142     }
    143 
    144     return 0;
    145 }
    146 
    147 #ifdef BCM_CMICM_SUPPORT
    148 STATIC void
    149 pli_cmicm_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
    150                          uint32 regnum, uint32 *value)
    151 {
    152     uint32 r;
    153     switch (type) {
    154     case PCI_CONFIG:
    155         r = regnum & 0xfff;
    156         if (r < PCIC_SIZE) {
    157             *value = PCIC(pcid_info, r);
    158         }
    159         break;
    160     case PCI_MEMORY:
    161         if (pcid_info->regmem_cb) {
    162             if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_READ,
    163                                       regnum, value,
    164                                       BYTES2BITS(sizeof(uint32)))) == 0)
    165                 break;
    166         }
    167         r = regnum & 0xfffff;
    168         if (r < PCIM_CMICM_SIZE) {
    169             *value = PCIM(pcid_info, r);
    170         } else {
    171             *value = 0xdeadbeef;
    172         }
    173         break;
    174     case I2C_CONFIG:
    175         break;
    176     case PLI_CONFIG:
    177         break;
    178     case JTAG_CONFIG:
    179         break;
    180 
    181     case SOC_INTERNAL:
    182         soc_internal_read_reg(pcid_info, regnum, value);
    183         break;
    184     }
    185 }
    186 #endif /* BCM_CMICM_SUPPORT */
    187 
    188 /* general getreg service */
    189 uint32
    190 pli_getreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
    191                    uint32 regnum)
    192 {
    193     char            buffer[35];
    194     uint32          value, rv;
    195     uint32          data[2];
    196 
    197     PCID_MEM_LOCK(pcid_info);
    198 
    199     pcid_type_name(buffer, type);
    200 
    201     if ((regnum & 3) && type != SOC_INTERNAL) {
    202         sal_printf("pli_getreg_service: unaligned access, "
    203                "type=0x%x addr=0x%x\n", type, regnum);
    204         regnum &= ~3;
    205     }
    206 
    207     value = 0xffffffff;                /* Default value */
    208     data[0] = 0xffffffff;
    209     data[1] = 0xffffffff;
    210 
    211 
    212  {
    213        /* we have an error here - only BCM56870_A0 and BCM56980_A0 supports cmicx as of right now */
    214     }
    215 
    216 
    217     /* non-cmicx case */
    218 #ifdef BCM_CMICM_SUPPORT
    219     if (pcid_info->cmicm >= CMC0) {
    220         /* coverity[overrun-buffer-val] */
    221         pli_cmicm_getreg_service(pcid_info, unit, type, regnum, data);
    222         value = data[0];
    223     } else
    224 #endif
    225 #ifdef BCM_CMICX_SUPPORT
    226     /* if we are dealing with the cmicx, do special stuff */
    227     if (soc_feature(pcid_info->unit, soc_feature_cmicx)) {
    228         pli_cmicx_getreg_service(pcid_info, unit, type, regnum, data);
    229         value = data[0];
    230     } else
    231 #endif /* BCM_CMICX_SUPPORT */
    232     {
    233         pli_cmice_getreg_service(pcid_info, unit, type, regnum, data);
    234         value = data[0];
    235     }
    236 
    237     if (pcid_info->opt_pli_verbose) {
    238         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    239                     (BSL_META_U(unit,
    240                                 "%s READ @0x%x => 0x%x\n"), buffer, regnum, value));
    241     }
    242 
    243     rv = soc_internal_endian_swap(pcid_info, value, MF_ES_PIO);
    244 
    245     PCID_MEM_UNLOCK(pcid_info);
    246 
    247     return rv;
    248 }
    249 
    250 
    251 
    252 /*
    253  * PLI protocol compatible "set register" routines
    254  */
    255 
    256 #ifdef BCM_CMICX_SUPPORT
    257 /* cmicx setreg service */
    258 STATIC void
    259 pli_cmicx_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
    260                          uint32 regnum, uint32 value)
    261 {
    262     uint32    r;
    263     uint32    data[2];
    264 
    265     switch (type) {
    266 
    267         case SOC_INTERNAL:
    268             data[0] = value;
    269             data[1] = 0;
    270             soc_internal_write_reg(pcid_info, regnum, data);
    271             break;
    272 
    273         case PCI_CONFIG:
    274             r = regnum & 0xfff;
    275             if (r < PCIC_SIZE) {
    276                 PCIC(pcid_info, r) = value;
    277             }
    278             break;
    279 
    280         /* this is where we perform a normal register access with the cmicx sim */
    281         case PCI_MEMORY:
    282 
    283             /*
    284             printf("writing CMICx reg!!!!!\n");
    285             printf("0x%08X \n",regnum & 0xFFFFF);
    286             */
    287 
    288             cmicx_pcid_register_write(regnum,value);
    289             break;
    290 
    291     }
    292 
    293 }
    294 #endif /* BCM_CMICX_SUPPORT */
    295 
    296 uint32 pli_cmice_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
    297                          uint32 regnum, uint32 value)
    298 {
    299     uint32    r;
    300     uint32    data[2];
    301 
    302     switch (type) {
    303     case SOC_INTERNAL:
    304         data[0] = value;
    305         data[1] = 0;
    306         soc_internal_write_reg(pcid_info, regnum, data);
    307         break;
    308 
    309     case PCI_CONFIG:
    310         r = regnum & 0xfff;
    311         if (r < PCIC_SIZE) {
    312             PCIC(pcid_info, r) = value;
    313         }
    314         break;
    315     case PCI_MEMORY:
    316         r = regnum & 0xffff;
    317 
    318         if (pcid_info->i2crom_fp) {
    319             fputc((r >> 8) & 0xff, pcid_info->i2crom_fp);
    320             fputc((r >> 0) & 0xff, pcid_info->i2crom_fp);
    321             fputc((value >> 24) & 0xff, pcid_info->i2crom_fp);
    322             fputc((value >> 16) & 0xff, pcid_info->i2crom_fp);
    323             fputc((value >> 8) & 0xff, pcid_info->i2crom_fp);
    324             fputc((value >> 0) & 0xff, pcid_info->i2crom_fp);
    325         }
    326         if (pcid_info->regmem_cb) {
    327             if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_WRITE,
    328                                       regnum, &value,
    329                                       BYTES2BITS(sizeof(uint32)))) == 0)
    330                 break;
    331         }
    332         switch (r) {
    333         case CMIC_SCHAN_CTRL:
    334             soc_internal_schan_ctrl_write(pcid_info, value);
    335             break;
    336         case CMIC_CONFIG:
    337             if (value & CC_RESET_CPS) {
    338                 soc_internal_reset(pcid_info);
    339             } else {
    340                 PCIM(pcid_info, r) = value;
    341             }
    342             break;
    343         case CMIC_IRQ_MASK:
    344             PCIM(pcid_info, r) = value;
    345             soc_internal_send_int(pcid_info);       /* Send int if pending */
    346             break;
    347         case CMIC_DMA_STAT:
    348             pcid_dma_stat_write(pcid_info, value);
    349             break;
    350         case CMIC_DMA_CTRL:
    351             pcid_dma_ctrl_write(pcid_info, value);
    352             break;
    353         case CMIC_TABLE_DMA_CFG:
    354             PCIM(pcid_info, r) = value;
    355             soc_internal_xgs3_table_dma(pcid_info);
    356             break;
    357         case CMIC_SLAM_DMA_CFG:
    358             PCIM(pcid_info, r) = value;
    359             soc_internal_xgs3_tslam_dma(pcid_info);
    360             break;
    361         case CMIC_LED_CTRL:
    362         case CMIC_LED_STATUS:
    363             break;
    364         default:
    365             if (r < PCIM_SIZE(unit)) {
    366                 PCIM(pcid_info, r) = value;
    367                 if (soc_feature(unit, soc_feature_schmsg_alias)) {
    368                     if (r < 0x50) {
    369                         PCIM(pcid_info, r + 0x800) = value;
    370                     } else if (r >= 0x800 && r < 0x850) {
    371                         PCIM(pcid_info, r - 0x800) = value;
    372                     }
    373                 }
    374             }
    375             break;
    376         }
    377         break;
    378     case I2C_CONFIG:
    379         break;
    380     case PLI_CONFIG:
    381         break;
    382     case JTAG_CONFIG:
    383         break;
    384     }
    385 
    386     return 0;
    387 }
    388 
    389 #ifdef BCM_CMICM_SUPPORT
    390 STATIC void
    391 pli_cmicm_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
    392                          uint32 regnum, uint32 value)
    393 {
    394     uint32    r;
    395     uint32    data[2];
    396 
    397     switch (type) {
    398     case SOC_INTERNAL:
    399         data[0] = value;
    400         data[1] = 0;
    401         soc_internal_write_reg(pcid_info, regnum, data);
    402         break;
    403 
    404     case PCI_CONFIG:
    405         r = regnum & 0xfff;
    406         if (r < PCIC_SIZE) {
    407             PCIC(pcid_info, r) = value;
    408         }
    409         break;
    410 
    411     case PCI_MEMORY:
    412         r = regnum & 0xfffff;
    413         if (pcid_info->i2crom_fp) {
    414             fputc((r >> 8) & 0xff, pcid_info->i2crom_fp);
    415             fputc((r >> 0) & 0xff, pcid_info->i2crom_fp);
    416             fputc((value >> 24) & 0xff, pcid_info->i2crom_fp);
    417             fputc((value >> 16) & 0xff, pcid_info->i2crom_fp);
    418             fputc((value >> 8) & 0xff, pcid_info->i2crom_fp);
    419             fputc((value >> 0) & 0xff, pcid_info->i2crom_fp);
    420         }
    421         if (pcid_info->regmem_cb) {
    422             if ((pcid_info->regmem_cb(pcid_info, BCMSIM_PCI_MEM_WRITE,
    423                                       regnum, &value,
    424                                       BYTES2BITS(sizeof(uint32)))) == 0)
    425                 break;
    426         }
    427         switch (r) {
    428         case CMIC_CMC0_SCHAN_CTRL_OFFSET:
    429             soc_internal_cmicm_schan_ctrl_write(pcid_info, regnum, value);
    430             break;
    431         case CMIC_CPS_RESET_OFFSET:
    432             if (value & CMIC_CPS_RESET) {
    433                 soc_internal_reset(pcid_info);
    434             } else {
    435                 PCIM(pcid_info, r) = value;
    436             }
    437             break;
    438         case CMIC_CMC0_PCIE_IRQ_MASK0_OFFSET:
    439         case CMIC_CMC0_PCIE_IRQ_MASK1_OFFSET:
    440         case CMIC_CMC0_PCIE_IRQ_MASK2_OFFSET:
    441             PCIM(pcid_info, r) = value;
    442             soc_internal_cmicm_send_int(pcid_info, r); /* Send int if pending */
    443             break;
    444         case CMIC_CMC0_CH0_DMA_CTRL_OFFSET:
    445         case CMIC_CMC0_CH1_DMA_CTRL_OFFSET:
    446         case CMIC_CMC0_CH2_DMA_CTRL_OFFSET:
    447         case CMIC_CMC0_CH3_DMA_CTRL_OFFSET:
    448             pcid_dma_cmicm_ctrl_write(pcid_info, r, value);
    449             break;
    450         case CMIC_CMC0_DMA_STAT_CLR_OFFSET:
    451             if (value & 0xf) {
    452                 PCIM(pcid_info, CMIC_CMC0_DMA_STAT_OFFSET) &= ~(value & 0xf);
    453                 switch (value & 0xf) {
    454                 case 1:
    455 /*                   PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(0)); */
    456                    pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(0));
    457                    break;
    458                 case 2:
    459 /*                   PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(1)); */
    460                    pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(1));
    461                     break;
    462                 case 4:
    463 /*                   PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(2)); */
    464                    pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(2));
    465                     break;
    466                 case 8:
    467 /*                   PCIM(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET) &= ~(IRQ_CMCx_DESC_DONE(3)); */
    468                    pcid_reg_and_write(pcid_info, CMIC_CMC0_IRQ_STAT0_OFFSET, IRQ_CMCx_DESC_DONE(3));
    469                 }
    470             }
    471             break;
    472         case CMIC_CMC0_TABLE_DMA_CFG_OFFSET:
    473             PCIM(pcid_info, r) = value;
    474             soc_internal_xgs3_cmicm_table_dma(pcid_info);
    475             break;
    476         case CMIC_CMC0_SLAM_DMA_CFG_OFFSET:
    477             PCIM(pcid_info, r) = value;
    478             soc_internal_xgs3_cmicm_tslam_dma(pcid_info);
    479             break;
    480         case CMIC_CMCx_SBUSDMA_CH0_CONTROL_OFFSET(0):
    481         case CMIC_CMCx_SBUSDMA_CH0_CONTROL_OFFSET(1):
    482         case CMIC_CMCx_SBUSDMA_CH0_CONTROL_OFFSET(2):
    483         case CMIC_CMCx_SBUSDMA_CH1_CONTROL_OFFSET(0):
    484         case CMIC_CMCx_SBUSDMA_CH1_CONTROL_OFFSET(1):
    485         case CMIC_CMCx_SBUSDMA_CH1_CONTROL_OFFSET(2):
    486         case CMIC_CMCx_SBUSDMA_CH2_CONTROL_OFFSET(0):
    487         case CMIC_CMCx_SBUSDMA_CH2_CONTROL_OFFSET(1):
    488         case CMIC_CMCx_SBUSDMA_CH2_CONTROL_OFFSET(2):
    489             PCIM(pcid_info, r) = value;
    490             soc_internal_cmicm_sbusdma(pcid_info, r);
    491             break;
    492         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,0):
    493         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,0):
    494         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,0):
    495         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,1):
    496         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,1):
    497         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,1):
    498         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,2):
    499         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,2):
    500         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,2):
    501         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(0,3):
    502         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(1,3):
    503         case CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(2,3):
    504             PCIM(pcid_info, r) = value;
    505             do {
    506                 int cmc, ch;
    507                 uint32 done = 0x10;   /* bit[4:4]: DONEf */
    508                 cmc = (r - CMIC_CMC0_FIFO_CH0_RD_DMA_CFG_OFFSET) / 0x1000;
    509                 ch  = (r & 0xf) / 4;
    510 
    511                 if ((value & 0x80000001) == 0x80000001) { /* bit[31:31]: ABORTf */
    512                     pcid_reg_or_write(pcid_info, 
    513                         CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, ch), done);
    514                 } else if ((value & 0x1) == 0) { /* bit[0:0]: ENABLEf */
    515                     pcid_reg_and_write(pcid_info, 
    516                         CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, ch), done);
    517                 }
    518             } while(0);
    519             break;
    520         default:
    521             if (r < PCIM_CMICM_SIZE) {
    522                 PCIM(pcid_info, r) = value;
    523             }
    524             break;
    525         }
    526         break;
    527     case I2C_CONFIG:
    528         break;
    529     case PLI_CONFIG:
    530         break;
    531     case JTAG_CONFIG:
    532         break;
    533     }
    534 
    535 }
    536 #endif /* BCM_CMICM_SUPPORT */
    537 
    538 /* setreg service */
    539 uint32
    540 pli_setreg_service(pcid_info_t * pcid_info, int unit, uint32 type,
    541                    uint32 regnum, uint32 value)
    542 {
    543     char            buffer[35];
    544 
    545     PCID_MEM_LOCK(pcid_info);
    546 
    547     pcid_type_name(buffer, type);
    548 
    549     value = soc_internal_endian_swap(pcid_info, value, MF_ES_PIO);
    550 
    551     if ((regnum & 3) && type != SOC_INTERNAL) {
    552         sal_printf("pli_setreg_service: unaligned access, "
    553                "type=0x%x addr=0x%x value=0x%x\n", type, regnum, value);
    554         regnum &= ~3;
    555     }
    556 
    557 #if 0
    558     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    559                 (BSL_META_U(unit,
    560                             "%s WRITE @0x%x <= 0x%x\n"), buffer, regnum, value));
    561 #endif
    562 
    563     if (pcid_info->opt_pli_verbose) {
    564         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    565                     (BSL_META_U(unit,
    566                                 "%s WRITE @0x%x <= 0x%x\n"), buffer, regnum, value));
    567     }
    568 
    569     /* this is the old code that existed before adding the cmicx stuff */
    570 #ifdef BCM_CMICM_SUPPORT
    571     if (pcid_info->cmicm >= CMC0) {
    572         pli_cmicm_setreg_service(pcid_info, unit, type, regnum, value);
    573     } else
    574 #endif
    575 #ifdef BCM_CMICX_SUPPORT
    576     /* if we are dealing with the cmicx, do special stuff */
    577     if (soc_feature(pcid_info->unit, soc_feature_cmicx)) {
    578         pli_cmicx_setreg_service(pcid_info, unit, type, regnum, value);
    579     } else
    580 #endif /* BCM_CMICX_SUPPORT */
    581     {
    582         pli_cmice_setreg_service(pcid_info, unit, type, regnum, value);
    583     }
    584 
    585     PCID_MEM_UNLOCK(pcid_info);
    586 
    587     return 0;
    588 }