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