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

l2.c (10225B)


      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:        l2.c
      8  * Purpose:     Hurricane2 L2 functions
      9  */
     10 
     11 #include <soc/drv.h>
     12 #include <bcm/error.h>
     13 #include <shared/bsl.h>
     14 #ifdef BCM_CMICM_SUPPORT
     15 #include <soc/cmicm.h>
     16 #endif
     17 #ifdef BCM_HURRICANE2_SUPPORT
     18 #include <soc/hurricane2.h>
     19 #endif
     20 
     21 
     22 #if defined(BCM_HURRICANE2_SUPPORT) && defined(BCM_CMICM_SUPPORT)
     23 
     24 #define RD_DMA_CFG_REG                   0
     25 #define RD_DMA_HOTMEM_THRESHOLD_REG      1
     26 #define RD_DMA_STAT                      2
     27 #define RD_DMA_STAT_CLR                  3
     28 
     29 int
     30 _soc_mem_hu2_fifo_dma_get_read_ptr(int unit, int chan, void **host_ptr, int *count)
     31 {
     32     soc_reg_t cfg_reg, stat_reg;
     33     int host_entries, data_beats;
     34     soc_field_t overflow_field;
     35     uint32 addr, rval, stat, hostmem_addr, read_ptr, write_ptr;
     36     int cmc = SOC_PCI_CMC(unit);
     37     
     38     if (chan < 0 || chan > 3 || host_ptr == NULL) {
     39         return SOC_E_PARAM;
     40     }
     41 
     42     if(!soc_feature(unit, soc_feature_cmicm)) {
     43         return BCM_E_UNAVAIL;
     44     }
     45 
     46     read_ptr = 0;
     47     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_READ_PTR_OFFSET(cmc, chan);
     48     soc_pci_getreg(unit, addr, &read_ptr);
     49 
     50     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_WRITE_PTR_OFFSET(cmc, chan);
     51     write_ptr = 0;
     52     soc_pci_getreg(unit, addr, &write_ptr);
     53 
     54     if (write_ptr == 0) {
     55         return SOC_E_EMPTY;
     56     }
     57 
     58     switch(chan) {
     59     case 1: overflow_field = FIFO_CH1_DMA_HOSTMEM_OVERFLOWf; break;
     60     case 2: overflow_field = FIFO_CH2_DMA_HOSTMEM_OVERFLOWf; break;
     61     case 3: overflow_field = FIFO_CH3_DMA_HOSTMEM_OVERFLOWf; break;
     62     default: overflow_field = FIFO_CH0_DMA_HOSTMEM_OVERFLOWf; break;
     63     }
     64 
     65     if (read_ptr == write_ptr) {
     66         addr = CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_OFFSET(cmc, chan);
     67         stat = 0;
     68         soc_pci_getreg(unit, addr, &stat);
     69         stat_reg = _soc_hu2_fifo_reg_get (unit, cmc, chan, RD_DMA_STAT);
     70         if (!soc_reg_field_get(unit, stat_reg, stat, overflow_field)) {
     71             return SOC_E_EMPTY;
     72         }
     73 
     74         /* Re-read write pointer */
     75         addr = CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_WRITE_PTR_OFFSET(cmc, chan);
     76         write_ptr = 0;
     77         soc_pci_getreg(unit, addr, &write_ptr);
     78     }
     79 
     80     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_OFFSET(cmc, chan);
     81     hostmem_addr = 0;
     82     soc_pci_getreg(unit, addr, &hostmem_addr);
     83 
     84     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(cmc, chan);
     85     rval = 0;
     86     soc_pci_getreg(unit, addr, &rval);
     87 
     88     cfg_reg = _soc_hu2_fifo_reg_get (unit, cmc, chan, RD_DMA_CFG_REG);
     89     data_beats = soc_reg_field_get(unit, cfg_reg, rval, BEAT_COUNTf);
     90     if (data_beats <= 0) {
     91         LOG_ERROR(BSL_LS_BCM_L2,
     92                   (BSL_META_U(unit,
     93                               "Invalid BEAT_COUNT (%d) in "
     94                               "CMIC_CMC%d_FIFO_CH%d_RD_DMA_CFG \n"), data_beats, cmc, chan));
     95         return SOC_E_CONFIG;
     96     }
     97 
     98     switch (soc_reg_field_get(unit, cfg_reg, rval, HOST_NUM_ENTRIES_SELf)) {
     99     case 0:  host_entries = 64;    break;
    100     case 1:  host_entries = 128;   break;
    101     case 2:  host_entries = 256;   break;
    102     case 3:  host_entries = 512;   break;
    103     case 4:  host_entries = 1024;  break;
    104     case 5:  host_entries = 2048;  break;
    105     case 6:  host_entries = 4096;  break;
    106     case 7:  host_entries = 8192;  break;
    107     case 8:  host_entries = 16384; break;
    108     case 9:  host_entries = 32768; break;
    109     case 10: host_entries = 65536; break;
    110     default: return SOC_E_CONFIG;
    111     }
    112 
    113     *host_ptr = soc_cm_p2l(unit, read_ptr);
    114     if (read_ptr >= write_ptr) {
    115         *count = host_entries -
    116             (read_ptr - hostmem_addr) / data_beats / sizeof(uint32);
    117     } else {
    118         *count = (write_ptr - read_ptr) / data_beats / sizeof(uint32);
    119     }
    120 
    121     return (*count) ? SOC_E_NONE : SOC_E_EMPTY;
    122 }
    123 
    124 int
    125 _soc_mem_hu2_fifo_dma_advance_read_ptr(int unit, int chan, int count)
    126 {
    127     soc_reg_t cfg_reg, statclr_reg;
    128     soc_field_t overflow_field;
    129     int host_entries, data_beats;
    130     uint32 addr, rval, statclr;
    131     uint32 *host_buf, *read_ptr;
    132     int cmc = SOC_PCI_CMC(unit);
    133 
    134     if (chan < 0 || chan > 3) {
    135         return SOC_E_PARAM;
    136     }
    137 
    138     if(!soc_feature(unit, soc_feature_cmicm)) {
    139         return BCM_E_UNAVAIL;
    140     }
    141 
    142     cfg_reg = _soc_hu2_fifo_reg_get (unit, cmc, chan, RD_DMA_CFG_REG);
    143     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_CFG_OFFSET(cmc, chan);
    144     rval = 0;
    145     soc_pci_getreg(unit, addr, &rval);
    146     data_beats = soc_reg_field_get(unit, cfg_reg, rval, BEAT_COUNTf);
    147 
    148     switch (soc_reg_field_get(unit, cfg_reg, rval, HOST_NUM_ENTRIES_SELf)) {
    149     case 0:  host_entries = 64;    break;
    150     case 1:  host_entries = 128;   break;
    151     case 2:  host_entries = 256;   break;
    152     case 3:  host_entries = 512;   break;
    153     case 4:  host_entries = 1024;  break;
    154     case 5:  host_entries = 2048;  break;
    155     case 6:  host_entries = 4096;  break;
    156     case 7:  host_entries = 8192;  break;
    157     case 8:  host_entries = 16384; break;
    158     case 9:  host_entries = 32768; break;
    159     case 10: host_entries = 65536; break;
    160     default: return SOC_E_CONFIG;
    161     }
    162 
    163     if (count < 0 || count >= host_entries) {
    164         return SOC_E_PARAM;
    165     }
    166 
    167     /* Clear threshold overflow_field bit */
    168     switch(chan) {
    169     case 1: overflow_field = FIFO_CH1_DMA_HOSTMEM_OVERFLOWf; break;
    170     case 2: overflow_field = FIFO_CH2_DMA_HOSTMEM_OVERFLOWf; break;
    171     case 3: overflow_field = FIFO_CH3_DMA_HOSTMEM_OVERFLOWf; break;
    172     default: overflow_field = FIFO_CH0_DMA_HOSTMEM_OVERFLOWf; break;
    173     }
    174 
    175     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_STAT_CLR_OFFSET(cmc, chan);
    176     statclr_reg = _soc_hu2_fifo_reg_get (unit, cmc, chan, RD_DMA_STAT_CLR);
    177     statclr = 0;
    178     soc_reg_field_set(unit, statclr_reg, &statclr, overflow_field, 1);
    179     soc_pci_write(unit, addr, statclr);
    180 
    181     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_START_ADDRESS_OFFSET(cmc, chan);
    182     rval = 0;
    183     soc_pci_getreg(unit, addr, &rval);
    184     host_buf = soc_cm_p2l(unit, rval);
    185 
    186     addr = CMIC_CMCx_FIFO_CHy_RD_DMA_HOSTMEM_READ_PTR_OFFSET(cmc, chan);
    187     rval = 0;
    188     soc_pci_getreg(unit, addr, &rval);
    189     read_ptr = soc_cm_p2l(unit, rval);
    190 
    191     read_ptr += count * data_beats;
    192     if (read_ptr >= &host_buf[host_entries * data_beats]) {
    193         read_ptr -= host_entries * data_beats;
    194     }
    195     rval = soc_cm_l2p(unit, read_ptr);
    196     soc_pci_write(unit, addr, rval);
    197 
    198     return SOC_E_NONE;
    199 }
    200 
    201 soc_reg_t
    202 _soc_hu2_fifo_reg_get(int unit, int cmc, int chan, int type)
    203 {
    204     switch(type) {
    205     case RD_DMA_HOTMEM_THRESHOLD_REG:
    206         switch((cmc << 4) + chan) {
    207         case 0x00: return CMIC_CMC0_FIFO_CH0_RD_DMA_HOSTMEM_THRESHOLDr;
    208         case 0x01: return CMIC_CMC0_FIFO_CH1_RD_DMA_HOSTMEM_THRESHOLDr;
    209         case 0x02: return CMIC_CMC0_FIFO_CH2_RD_DMA_HOSTMEM_THRESHOLDr;
    210         case 0x03: return CMIC_CMC0_FIFO_CH3_RD_DMA_HOSTMEM_THRESHOLDr;
    211         case 0x10: return CMIC_CMC1_FIFO_CH0_RD_DMA_HOSTMEM_THRESHOLDr;
    212         case 0x11: return CMIC_CMC1_FIFO_CH1_RD_DMA_HOSTMEM_THRESHOLDr;
    213         case 0x12: return CMIC_CMC1_FIFO_CH2_RD_DMA_HOSTMEM_THRESHOLDr;
    214         case 0x13: return CMIC_CMC1_FIFO_CH3_RD_DMA_HOSTMEM_THRESHOLDr;
    215         case 0x20: return CMIC_CMC2_FIFO_CH0_RD_DMA_HOSTMEM_THRESHOLDr;
    216         case 0x21: return CMIC_CMC2_FIFO_CH1_RD_DMA_HOSTMEM_THRESHOLDr;
    217         case 0x22: return CMIC_CMC2_FIFO_CH2_RD_DMA_HOSTMEM_THRESHOLDr;
    218         case 0x23: return CMIC_CMC2_FIFO_CH3_RD_DMA_HOSTMEM_THRESHOLDr;
    219         default: return CMIC_CMC0_FIFO_CH0_RD_DMA_HOSTMEM_THRESHOLDr;
    220         }
    221         break;
    222     case RD_DMA_CFG_REG:
    223         switch((cmc << 4) + chan) {
    224         case 0x00: return CMIC_CMC0_FIFO_CH0_RD_DMA_CFGr;
    225         case 0x01: return CMIC_CMC0_FIFO_CH1_RD_DMA_CFGr;
    226         case 0x02: return CMIC_CMC0_FIFO_CH2_RD_DMA_CFGr;
    227         case 0x03: return CMIC_CMC0_FIFO_CH3_RD_DMA_CFGr;
    228         case 0x10: return CMIC_CMC1_FIFO_CH0_RD_DMA_CFGr;
    229         case 0x11: return CMIC_CMC1_FIFO_CH1_RD_DMA_CFGr;
    230         case 0x12: return CMIC_CMC1_FIFO_CH2_RD_DMA_CFGr;
    231         case 0x13: return CMIC_CMC1_FIFO_CH3_RD_DMA_CFGr;
    232         case 0x20: return CMIC_CMC2_FIFO_CH0_RD_DMA_CFGr;
    233         case 0x21: return CMIC_CMC2_FIFO_CH1_RD_DMA_CFGr;
    234         case 0x22: return CMIC_CMC2_FIFO_CH2_RD_DMA_CFGr;
    235         case 0x23: return CMIC_CMC2_FIFO_CH3_RD_DMA_CFGr;
    236         default: return CMIC_CMC0_FIFO_CH0_RD_DMA_CFGr;
    237         }
    238     case RD_DMA_STAT:
    239         switch((cmc << 4) + chan) {
    240         case 0x00: return CMIC_CMC0_FIFO_CH0_RD_DMA_STATr;
    241         case 0x01: return CMIC_CMC0_FIFO_CH1_RD_DMA_STATr;
    242         case 0x02: return CMIC_CMC0_FIFO_CH2_RD_DMA_STATr;
    243         case 0x03: return CMIC_CMC0_FIFO_CH3_RD_DMA_STATr;
    244         case 0x10: return CMIC_CMC1_FIFO_CH0_RD_DMA_STATr;
    245         case 0x11: return CMIC_CMC1_FIFO_CH1_RD_DMA_STATr;
    246         case 0x12: return CMIC_CMC1_FIFO_CH2_RD_DMA_STATr;
    247         case 0x13: return CMIC_CMC1_FIFO_CH3_RD_DMA_STATr;
    248         case 0x20: return CMIC_CMC2_FIFO_CH0_RD_DMA_STATr;
    249         case 0x21: return CMIC_CMC2_FIFO_CH1_RD_DMA_STATr;
    250         case 0x22: return CMIC_CMC2_FIFO_CH2_RD_DMA_STATr;
    251         case 0x23: return CMIC_CMC2_FIFO_CH3_RD_DMA_STATr;
    252         default: return CMIC_CMC0_FIFO_CH0_RD_DMA_STATr;
    253         }
    254     case RD_DMA_STAT_CLR:
    255         switch((cmc << 4) + chan) {
    256         case 0x00: return CMIC_CMC0_FIFO_CH0_RD_DMA_STAT_CLRr;
    257         case 0x01: return CMIC_CMC0_FIFO_CH1_RD_DMA_STAT_CLRr;
    258         case 0x02: return CMIC_CMC0_FIFO_CH2_RD_DMA_STAT_CLRr;
    259         case 0x03: return CMIC_CMC0_FIFO_CH3_RD_DMA_STAT_CLRr;
    260         case 0x10: return CMIC_CMC1_FIFO_CH0_RD_DMA_STAT_CLRr;
    261         case 0x11: return CMIC_CMC1_FIFO_CH1_RD_DMA_STAT_CLRr;
    262         case 0x12: return CMIC_CMC1_FIFO_CH2_RD_DMA_STAT_CLRr;
    263         case 0x13: return CMIC_CMC1_FIFO_CH3_RD_DMA_STAT_CLRr;
    264         case 0x20: return CMIC_CMC2_FIFO_CH0_RD_DMA_STAT_CLRr;
    265         case 0x21: return CMIC_CMC2_FIFO_CH1_RD_DMA_STAT_CLRr;
    266         case 0x22: return CMIC_CMC2_FIFO_CH2_RD_DMA_STAT_CLRr;
    267         case 0x23: return CMIC_CMC2_FIFO_CH3_RD_DMA_STAT_CLRr;
    268         default: return CMIC_CMC0_FIFO_CH0_RD_DMA_STAT_CLRr;
    269         }
    270     default: return INVALIDr; break;
    271     }
    272 }
    273 
    274 #endif /*BCM_HURRICANE2_SUPPORT*/