cmicm_sbusdma_common.c (9547B)
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 * Purpose: CMICM SBUS-DMA Common utility functions 8 */ 9 10 #include <shared/bsl.h> 11 #include <soc/debug.h> 12 #include <soc/cm.h> 13 #include <sal/core/sync.h> 14 #include <soc/util.h> 15 #include <soc/drv.h> 16 #include <soc/sbusdma_internal.h> 17 18 #if defined(BCM_CMICM_SUPPORT) && defined(BCM_SBUSDMA_SUPPORT) 19 #include <soc/cmicm.h> 20 21 22 typedef struct cmicm_sbusdma_ch_s { 23 sal_spinlock_t lock; 24 int timeout; 25 uint8 ch[SOC_MAX_NUM_DEVICES][CMIC_CMC_NUM_MAX]; 26 }cmicm_sbusdma_ch_t; 27 28 29 STATIC cmicm_sbusdma_ch_t _cmicm_sbusdma_ch; 30 31 32 /******************************************* 33 * @function cmicm_sbusdma_curr_op_details 34 * purpose Print operation details 35 * 36 * @param unit [in] unit 37 * @param cmc [in] cmc number 38 * @param ch [in] channel number 39 * 40 * @returns SOC_E_NONE 41 * @returns SOC_E_XXX 42 * 43 * @end 44 */ 45 void 46 cmicm_sbusdma_curr_op_details(int unit, int cmc, int ch) 47 { 48 uint32 rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_STATUS(cmc, ch)); 49 LOG_VERBOSE(BSL_LS_SOC_COMMON, 50 (BSL_META_U(unit, 51 "STATUS: 0x%08x\n"), rval)); 52 rval = soc_pci_read(unit, 53 CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_OPCODE(cmc, ch)); 54 LOG_VERBOSE(BSL_LS_SOC_COMMON, 55 (BSL_META_U(unit, 56 "OPCODE: 0x%08x\n"), rval)); 57 rval = soc_pci_read(unit, 58 CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSDMA_CONFIG_ADDR(cmc, ch)); 59 LOG_VERBOSE(BSL_LS_SOC_COMMON, 60 (BSL_META_U(unit, 61 "START ADDR: 0x%08x\n"), rval)); 62 rval = soc_pci_read(unit, CMIC_CMCx_SBUSDMA_CHy_CUR_SBUSADDR(cmc, ch)); 63 LOG_VERBOSE(BSL_LS_SOC_COMMON, 64 (BSL_META_U(unit, 65 "CUR ADDR: 0x%08x\n"), rval)); 66 } 67 68 /******************************************* 69 * @function cmicm_sbusdma_error_details 70 * purpose Print error details 71 * 72 * @param unit [in] unit 73 * @param rval [in] Error value 74 * 75 * @returns SOC_E_NONE 76 * @returns SOC_E_XXX 77 * 78 * @end 79 */ 80 void 81 cmicm_sbusdma_error_details(int unit, uint32 rval) 82 { 83 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 84 rval, DESCRD_ERRORf)) { 85 LOG_ERROR(BSL_LS_SOC_COMMON, 86 (BSL_META_U(unit, 87 "Error while reading descriptor from host memory.\n"))); 88 } 89 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 90 rval, SBUSACK_TIMEOUTf)) { 91 LOG_ERROR(BSL_LS_SOC_COMMON, 92 (BSL_META_U(unit, 93 "sbus ack not received within configured time.\n"))); 94 } 95 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 96 rval, SBUSACK_ERRORf)) { 97 LOG_ERROR(BSL_LS_SOC_COMMON, 98 (BSL_META_U(unit, 99 "H/W received sbus ack with error bit set.\n"))); 100 } 101 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 102 rval, SBUSACK_NACKf)) { 103 LOG_ERROR(BSL_LS_SOC_COMMON, 104 (BSL_META_U(unit, 105 "H/W received sbus nack with error bit set.\n"))); 106 } 107 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 108 rval, SBUSACK_WRONG_OPCODEf)) { 109 LOG_ERROR(BSL_LS_SOC_COMMON, 110 (BSL_META_U(unit, 111 "Received sbus ack has wrong opcode.\n"))); 112 } 113 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 114 rval, SBUSACK_WRONG_BEATCOUNTf)) { 115 LOG_ERROR(BSL_LS_SOC_COMMON, 116 (BSL_META_U(unit, 117 "Received sbus ack data size is not the same as in rep_words " 118 "fields.\n"))); 119 } 120 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 121 rval, SER_CHECK_FAILf)) { 122 LOG_ERROR(BSL_LS_SOC_COMMON, 123 (BSL_META_U(unit, 124 "Received sbus ack with SER_CHECK_FAIL set.\n"))); 125 } 126 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 127 rval, HOSTMEMRD_ERRORf)) { 128 LOG_ERROR(BSL_LS_SOC_COMMON, 129 (BSL_META_U(unit, 130 "Error while copying SBUSDMA data from Host Memory.\n"))); 131 } 132 if (soc_reg_field_get(unit, CMIC_CMC0_SBUSDMA_CH0_STATUSr, 133 rval, HOSTMEMWR_ERRORf)) { 134 LOG_ERROR(BSL_LS_SOC_COMMON, 135 (BSL_META_U(unit, 136 "DMA operation encountered a schan response error " 137 "or host side error.\n"))); 138 } 139 } 140 141 /******************************************* 142 * @function _cmicm_sbusdma_ch_get 143 * purpose get idle channel on cmc 144 * 145 * @param unit [in] unit # 146 * @param cmc [in] cmc number 0-2 147 * @param mask [in] mask for available channels 148 * @param ch [out] channel number 0-2 149 * 150 * @returns SOC_E_BUSY 151 * @returns SOC_E_NONE 152 * 153 * @end 154 */ 155 STATIC int 156 _cmicm_sbusdma_ch_get(int unit, int cmc, 157 uint8 mask, int *ch) 158 { 159 int rv = SOC_E_BUSY; 160 int i; 161 162 sal_spinlock_lock(_cmicm_sbusdma_ch.lock); 163 for (i = 0; i < CMIC_CMCx_SBUSDMA_CHAN_MAX; i++) { 164 if ((mask & 0x01 << i) && 165 (_cmicm_sbusdma_ch.ch[unit][cmc] & 0x01 << i)) { 166 rv = SOC_E_NONE; 167 *ch = i; 168 _cmicm_sbusdma_ch.ch[unit][cmc] &= ~(0x01 << i); 169 break; 170 } 171 } 172 sal_spinlock_unlock(_cmicm_sbusdma_ch.lock); 173 return rv; 174 } 175 176 /******************************************* 177 * @function cmicm_sbusdma_ch_get 178 * purpose get idle channel on cmc 179 * 180 * @param unit [in] unit # 181 * @param cmc [out] cmc number 0-2 182 * @param ch [out] channel number 0-2 183 * 184 * @returns SOC_E_BUSY 185 * @returns SOC_E_NONE 186 * 187 * @end 188 */ 189 int cmicm_sbusdma_ch_get(int unit, int *cmc, int *ch) 190 { 191 int rv; 192 193 soc_timeout_t to; 194 195 soc_timeout_init(&to, _cmicm_sbusdma_ch.timeout, 100); 196 197 do { 198 *cmc = CMC0; 199 rv = _cmicm_sbusdma_ch_get(unit, *cmc, 200 CMIC_CMC0_SBUSDMA_CH_MASK, ch); 201 if (rv == SOC_E_NONE) 202 break; 203 204 *cmc = CMC1; 205 rv = _cmicm_sbusdma_ch_get(unit, *cmc, 206 CMIC_CMC1_SBUSDMA_CH_MASK, ch); 207 if (rv == SOC_E_NONE) 208 break; 209 210 *cmc = CMC2; 211 rv = _cmicm_sbusdma_ch_get(unit, *cmc, 212 CMIC_CMC2_SBUSDMA_CH_MASK, ch); 213 if (rv == SOC_E_NONE) 214 break; 215 } while (!soc_timeout_check(&to)); 216 return rv; 217 } 218 219 /******************************************* 220 * @function cmicm_sbusdma_ch_try_get 221 * purpose get idle channel on cmc 222 * 223 * @param unit [in] unit # 224 * @param cmc [in] cmc number 0-2 225 * @param ch [in] channel number 0-2 226 * 227 * @returns SOC_E_BUSY 228 * @returns SOC_E_NONE 229 * 230 * @end 231 */ 232 int cmicm_sbusdma_ch_try_get(int unit, int cmc, int ch) 233 { 234 int rv = SOC_E_BUSY; 235 uint8 mask = 0; 236 237 soc_timeout_t to; 238 239 soc_timeout_init(&to, _cmicm_sbusdma_ch.timeout, 100); 240 241 if ((cmc < 0) || (cmc > CMIC_CMC_NUM_MAX - 1) || 242 (ch < 0) || (ch > CMIC_CMCx_SBUSDMA_CHAN_MAX - 1)) { 243 rv = SOC_E_PARAM; 244 return rv; 245 } 246 247 if (cmc == 0) { 248 mask = CMIC_CMC0_SBUSDMA_CH_MASK; 249 } else if (cmc == 1) { 250 mask = CMIC_CMC1_SBUSDMA_CH_MASK; 251 } else if (cmc == 2) { 252 mask = CMIC_CMC2_SBUSDMA_CH_MASK; 253 } 254 255 sal_spinlock_lock(_cmicm_sbusdma_ch.lock); 256 do { 257 if ((mask & (0x01 << ch)) && 258 (_cmicm_sbusdma_ch.ch[unit][cmc] & (0x01 << ch))) { 259 rv = SOC_E_NONE; 260 _cmicm_sbusdma_ch.ch[unit][cmc] &= ~(0x01 << ch); 261 break; 262 } 263 } while (!soc_timeout_check(&to)); 264 sal_spinlock_unlock(_cmicm_sbusdma_ch.lock); 265 266 return rv; 267 } 268 269 /******************************************* 270 * @function cmicm_sbusdma_ch_put 271 * purpose put back the freed channel on cmc 272 * 273 * @param cmc [in] cmc number 0-2 274 * @param ch [in] channel number 0-2 275 * 276 * @returns SOC_E_PARAM 277 * @returns SOC_E_NONE 278 * 279 * @end 280 */ 281 int cmicm_sbusdma_ch_put(int unit, int cmc, int ch) 282 { 283 int rv = SOC_E_NONE; 284 285 if ((cmc < 0) || (cmc > CMIC_CMC_NUM_MAX - 1) || 286 (ch < 0) || (ch > CMIC_CMCx_SBUSDMA_CHAN_MAX - 1)) { 287 rv = SOC_E_PARAM; 288 return rv; 289 } 290 sal_spinlock_lock(_cmicm_sbusdma_ch.lock); 291 _cmicm_sbusdma_ch.ch[unit][cmc] |= (0x01 << ch); 292 sal_spinlock_unlock(_cmicm_sbusdma_ch.lock); 293 294 return rv; 295 } 296 297 /******************************************* 298 * @function cmicm_sbusdma_ch_init 299 * purpose API to Initialize sbusdma channel seletion mechanism 300 * 301 * @param unit [in] unit 302 * @param timeout [in] int 303 * @param cmic_ch [out] pointer type soc_sbusdma_cmic_ch_t 304 * 305 * @returns SOC_E_NONE 306 * @returns SOC_E_XXX 307 * 308 * @end 309 */ 310 int cmicm_sbusdma_ch_init(int unit, int timeout, 311 soc_sbusdma_cmic_ch_t *cmic_ch) 312 313 { 314 int rv = SOC_E_NONE; 315 316 _cmicm_sbusdma_ch.lock = sal_spinlock_create("sbusdma Lock"); 317 318 if (_cmicm_sbusdma_ch.lock == NULL) { 319 return SOC_E_MEMORY; 320 } 321 /* Availability of channels */ 322 _cmicm_sbusdma_ch.ch[unit][0] = CMIC_CMC0_SBUSDMA_CH_MASK; 323 _cmicm_sbusdma_ch.ch[unit][1] = CMIC_CMC1_SBUSDMA_CH_MASK; 324 _cmicm_sbusdma_ch.ch[unit][2] = CMIC_CMC2_SBUSDMA_CH_MASK; 325 _cmicm_sbusdma_ch.timeout = timeout; 326 cmic_ch->soc_sbusdma_ch_try_get = cmicm_sbusdma_ch_try_get; 327 cmic_ch->soc_sbusdma_ch_put = cmicm_sbusdma_ch_put; 328 329 return rv; 330 } 331 332 333 #endif