iproc_m0ssq.c (13700B)
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 #include <sal/core/boot.h> 8 #include <sal/core/libc.h> 9 #include <sal/core/sync.h> 10 #include <shared/alloc.h> 11 #include <shared/bsl.h> 12 13 #if defined(BCM_ESW_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) 14 #include <soc/mcm/cmicx.h> 15 #include <soc/mcm/intr_iproc.h> 16 #include <soc/mcm/memregs.h> 17 #include <soc/intr.h> 18 #include <soc/cm.h> 19 #include <soc/cmic.h> 20 #include <soc/drv.h> 21 #ifdef BCM_DNX_SUPPORT 22 #include <soc/dnx/dnx_err_recovery_manager_utils.h> 23 #endif 24 #ifdef BCM_CMICX_SUPPORT 25 #include <soc/iproc.h> 26 #include <soc/cmicx.h> 27 #include <shared/cmicfw/iproc_mbox.h> 28 #include <shared/cmicfw/cmicx_led.h> 29 #include <shared/cmicfw/cmicx_link.h> 30 31 int iproc_m0ssq_init_done[SOC_MAX_NUM_DEVICES] = {0}; 32 33 uint32 soc_iproc_percore_membase_get(int unit, int ucnum) 34 { 35 if (SOC_IS_HELIX5(unit)) { 36 return (IPROC_M0SSQ_TCAM_BASE_HX5 + (ucnum * IPROC_M0SSQ_TCAM_SIZE_HX5)); 37 } else { 38 return (IPROC_M0SSQ_TCAM_BASE + (ucnum * IPROC_M0SSQ_TCAM_SIZE)); 39 } 40 } 41 42 uint32 soc_iproc_percore_memsize_get(int unit, int ucnum) 43 { 44 if (SOC_IS_HELIX5(unit)) { 45 return IPROC_M0SSQ_TCAM_SIZE_HX5; 46 } else { 47 return IPROC_M0SSQ_TCAM_SIZE; 48 } 49 } 50 51 uint32 soc_iproc_sram_membase_get(int unit) 52 { 53 if (SOC_IS_HELIX5(unit)) { 54 return IPROC_M0SSQ_SRAM_BASE_HX5; 55 } else { 56 return IPROC_M0SSQ_SRAM_BASE; 57 } 58 } 59 60 61 /* 62 * Function: 63 * soc_iproc_m0ssq_reset_ucore 64 * Purpose: 65 * Reset Cortex-M0 in Iproc subsystem quad 66 * Parameters: 67 * unit number 68 * ucore number 69 * Returns: 70 * SOC_E_xxx 71 */ 72 int soc_iproc_m0ssq_reset_ucore(int unit, int ucore, int enable) 73 { 74 uint32 val = 0; 75 int rv = SOC_E_NONE; 76 77 LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit,"ucore 0x%x enable 0x%x\n"), ucore, enable)); 78 79 switch(ucore) { 80 case 0: 81 soc_iproc_getreg(unit, soc_reg_addr(unit, U0_M0SS_CONTROLr, REG_PORT_ANY, 0), &val); 82 soc_reg_field_set(unit, U0_M0SS_CONTROLr, &val, SOFT_RESETf, enable); 83 soc_iproc_setreg(unit, soc_reg_addr(unit, U0_M0SS_CONTROLr, REG_PORT_ANY, 0), val); 84 break; 85 case 1: 86 soc_iproc_getreg(unit, soc_reg_addr(unit, U1_M0SS_CONTROLr, REG_PORT_ANY, 0), &val); 87 soc_reg_field_set(unit, U1_M0SS_CONTROLr, &val, SOFT_RESETf, enable); 88 soc_iproc_setreg(unit, soc_reg_addr(unit, U1_M0SS_CONTROLr, REG_PORT_ANY, 0), val); 89 break; 90 case 2: 91 soc_iproc_getreg(unit, soc_reg_addr(unit, U2_M0SS_CONTROLr, REG_PORT_ANY, 0), &val); 92 soc_reg_field_set(unit, U2_M0SS_CONTROLr, &val, SOFT_RESETf, enable); 93 soc_iproc_setreg(unit, soc_reg_addr(unit, U2_M0SS_CONTROLr, REG_PORT_ANY, 0), val); 94 break; 95 case 3: 96 soc_iproc_getreg(unit, soc_reg_addr(unit, U3_M0SS_CONTROLr, REG_PORT_ANY, 0), &val); 97 soc_reg_field_set(unit, U3_M0SS_CONTROLr, &val, SOFT_RESETf, enable); 98 soc_iproc_setreg(unit, soc_reg_addr(unit, U3_M0SS_CONTROLr, REG_PORT_ANY, 0), val); 99 break; 100 default: 101 rv = SOC_E_PARAM; 102 } 103 104 return rv; 105 } 106 107 /* 108 * Function: 109 * soc_iproc_m0ssq_reset 110 * Purpose: 111 * Reset Iproc Cortex-M0 subsystem quad 112 * Parameters: 113 * unit number 114 * Returns: 115 * None 116 */ 117 void soc_iproc_m0ssq_reset(int unit, int enable) 118 { 119 int ucnum; 120 121 for(ucnum = 0; ucnum < MAX_UCORES; ucnum++) 122 (void)soc_iproc_m0ssq_reset_ucore(unit, ucnum, enable); 123 } 124 125 /* 126 * Function: 127 * soc_iproc_quad_event_thread 128 * Purpose: 129 * Thread to handle iproc Cortex-M0 subsystem events 130 * Parameters: 131 * unit number 132 * Returns: 133 * None 134 */ 135 void soc_iproc_quad_event_thread(void *unit_vp) 136 { 137 int unit = M0SSQ_DECODE_UNIT(unit_vp); 138 int ucnum = M0SSQ_DECODE_UCORE(unit_vp); 139 soc_control_t *soc = SOC_CONTROL(unit); 140 soc_iproc_m0ssq_control_t *iproc_m0ssq = &soc->iproc_m0ssq_ctrl[ucnum]; 141 142 #ifdef BCM_DNX_SUPPORT 143 if(SOC_IS_DNX(unit)) 144 { 145 DNX_ERR_RECOVERY_UTILS_EXCLUDED_THREAD_ADD(unit); 146 } 147 #endif 148 149 while (iproc_m0ssq->thread_interval != 0) { 150 LOG_DEBUG(BSL_LS_SOC_M0, (BSL_META_U(unit,"soc_iproc_quad_event_thread: sleep %d\n"), 151 iproc_m0ssq->thread_interval)); 152 153 (void) sal_sem_take(iproc_m0ssq->event_sema, sal_sem_FOREVER); 154 soc_cmic_intr_enable(unit, SW_PROG_INTR); 155 156 /* Interrupt Handler */ 157 soc_iproc_msgintr_handler(unit, NULL); 158 } 159 160 sal_sem_destroy(iproc_m0ssq->event_sema); 161 iproc_m0ssq->thread_interval = 0; 162 iproc_m0ssq->thread_pid = NULL; 163 164 #ifdef BCM_DNX_SUPPORT 165 if(SOC_IS_DNX(unit)) 166 { 167 DNX_ERR_RECOVERY_UTILS_EXCLUDED_THREAD_REMOVE(unit); 168 } 169 #endif 170 171 sal_thread_exit(0); 172 } 173 174 /* 175 * Function: 176 * soc_iproc_m0ssq_init 177 * Purpose: 178 * Initialize iproc Cortex-M0 subsystem 179 * Parameters: 180 * unit number 181 * Returns: 182 * None 183 */ 184 int soc_iproc_m0ssq_init(int unit) 185 { 186 int rv = SOC_E_NONE; 187 soc_control_t *soc = SOC_CONTROL(unit); 188 soc_iproc_m0ssq_control_t *iproc_m0ssq = NULL; 189 uint32 interval = IPROC_M0SSQ_THREAD_INTERVAL; 190 uint32 max_ucores, ucnum; 191 192 if (iproc_m0ssq_init_done[unit]) { 193 return rv; 194 } 195 196 /* Init max number of ucores enabled */ 197 _soc_iproc_fw_config(unit); 198 199 /* Init linkscan firmware config. */ 200 201 /* Get max ucores enabled */ 202 max_ucores = _soc_iproc_num_ucore_get(unit); 203 204 for (ucnum = 0; ucnum < max_ucores; ucnum++) { 205 iproc_m0ssq = &soc->iproc_m0ssq_ctrl[ucnum]; 206 207 iproc_m0ssq->event_sema = sal_sem_create("m0ssq_intr", sal_sem_BINARY, 0); 208 if (iproc_m0ssq->event_sema == NULL) { 209 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Iproc M0SSQ event sem create failed\n"))); 210 return SOC_E_MEMORY; 211 } 212 213 sal_snprintf(iproc_m0ssq->thread_name, sizeof(iproc_m0ssq->thread_name), 214 "IPROC_M0SSQ_EVENT.%d", unit); 215 iproc_m0ssq->thread_interval = interval; 216 iproc_m0ssq->thread_pid = sal_thread_create(iproc_m0ssq->thread_name, 217 SAL_THREAD_STKSZ, 218 soc_property_get(unit, 219 spn_LINKSCAN_THREAD_PRI, 220 IPROC_M0SSQ_THREAD_PRI), 221 (void (*)(void*))soc_iproc_quad_event_thread, 222 M0SSQ_ENCODE_UNIT_UCORE(unit, ucnum)); 223 224 if (iproc_m0ssq->thread_pid == SAL_THREAD_ERROR) { 225 iproc_m0ssq->thread_interval = 0; 226 sal_sem_destroy(iproc_m0ssq->event_sema); 227 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Iproc M0SSQ thread creation failed \n"))); 228 return SOC_E_MEMORY; 229 } 230 } 231 232 soc_cmic_intr_enable(unit, SW_PROG_INTR); 233 234 iproc_m0ssq_init_done[unit] = 1; 235 236 return rv; 237 } 238 239 /* 240 * Function: 241 * soc_iproc_m0ssq_exit 242 * Purpose: 243 * Exit iproc Cortex-M0 subsystem 244 * Parameters: 245 * unit number 246 * Returns: 247 * None 248 */ 249 int soc_iproc_m0ssq_exit(int unit) 250 { 251 int rv = SOC_E_NONE; 252 soc_control_t *soc = SOC_CONTROL(unit); 253 soc_iproc_m0ssq_control_t *iproc_m0ssq; 254 uint32 ucnum; 255 256 if (!iproc_m0ssq_init_done[unit]) { 257 return rv; 258 } 259 260 for (ucnum = 0; ucnum < MAX_UCORES; ucnum++) { 261 iproc_m0ssq = &soc->iproc_m0ssq_ctrl[ucnum]; 262 263 iproc_m0ssq->thread_interval = 0; 264 265 if (iproc_m0ssq->event_sema) { 266 sal_sem_give(iproc_m0ssq->event_sema); 267 } 268 } 269 270 soc_cmic_intr_disable(unit, SW_PROG_INTR); 271 272 iproc_m0ssq_init_done[unit] = 0; 273 274 return rv; 275 } 276 277 /* 278 * Function: 279 * soc_iproc_m0_init 280 * Purpose: 281 * Initialize iproc Cortex-M0 subsystem and mbox 282 * Parameters: 283 * unit number 284 * Returns: 285 * None 286 */ 287 int soc_iproc_m0_init(int unit) 288 { 289 int rv = SOC_E_NONE; 290 291 if (SOC_CONTROL(unit)->iproc_m0_init_done) { 292 return rv; 293 } 294 295 LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "IPROC M0 init\n"))); 296 297 /* Initialize Iproc ARM Cortex-M0 subsystem quad */ 298 rv = soc_iproc_m0ssq_init(unit); 299 if (rv != SOC_E_NONE) { 300 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Iproc M0SSQ init failed\n"))); 301 return rv; 302 } 303 304 /* Initialize Iproc ARM Cortex-M0 subsystem quad(M0SSQ) mailbox */ 305 rv = soc_iproc_mbox_init(unit); 306 if (rv != SOC_E_NONE) { 307 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Iproc mbox init failed\n"))); 308 return rv; 309 } 310 311 /* Initialize LED mailbox */ 312 rv = soc_cmicx_led_mbox_init(unit); 313 if (rv != SOC_E_NONE) { 314 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "LED mbox init failed\n"))); 315 return rv; 316 } 317 318 rv = soc_cmicx_link_fw_config_init(unit); 319 if (rv != SOC_E_NONE) { 320 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "LED mbox init failed\n"))); 321 return rv; 322 } 323 324 /* bring M0 core out of reset */ 325 /* uC0 for Linkscan/LED */ 326 (void)soc_iproc_m0ssq_reset_ucore(unit, 0, 0); 327 328 SOC_CONTROL(unit)->iproc_m0_init_done = 1; 329 330 return rv; 331 } 332 333 /* 334 * Function: 335 * soc_iproc_m0_exit 336 * Purpose: 337 * Exit iproc Cortex-M0 subsystem and mbox 338 * Parameters: 339 * unit number 340 * Returns: 341 * None 342 */ 343 int soc_iproc_m0_exit(int unit) 344 { 345 int rv = SOC_E_NONE; 346 347 LOG_VERBOSE(BSL_LS_SOC_M0, (BSL_META_U(unit, "IPROC M0 exit\n"))); 348 349 if (!SOC_CONTROL(unit)->iproc_m0_init_done) { 350 return rv; 351 } 352 353 /* Call LED deinit */ 354 rv = soc_cmicx_led_deinit(unit); 355 if (rv != SOC_E_NONE) { 356 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "cmicx led deinit failed\n"))); 357 return rv; 358 } 359 360 /* Call Linkscan deinit */ 361 rv = soc_cmicx_linkscan_hw_deinit(unit); 362 if (rv != SOC_E_NONE) { 363 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "cmicx linkscan deinit failed\n"))); 364 return rv; 365 } 366 367 /* Cleanup Iproc ARM Cortex-M0 subsystem quad(M0SSQ) mailbox */ 368 rv = soc_iproc_mbox_exit(unit); 369 if (rv != SOC_E_NONE) { 370 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Iproc mbox exit failed\n"))); 371 return rv; 372 } 373 374 /* Cleanup Iproc ARM Cortex-M0 subsystem quad */ 375 rv = soc_iproc_m0ssq_exit(unit); 376 if (rv != SOC_E_NONE) { 377 LOG_ERROR(BSL_LS_SOC_M0, (BSL_META_U(unit, "Iproc M0SSQ exit failed\n"))); 378 return rv; 379 } 380 381 (void)soc_iproc_m0ssq_reset(unit, M0SSQ_RESET_ENABLE); 382 383 SOC_CONTROL(unit)->iproc_m0_init_done = 0; 384 385 return rv; 386 } 387 388 /* 389 * Function: 390 * soc_iproc_m0ssq_shmem_get 391 * Purpose: 392 * Get shared memory object by name. 393 * Parameters: 394 * unit Device unit number. 395 * name Name of memory object. 396 * shmem Shared memory object. 397 * Returns: 398 * SOC_E_NONE if success, otherwise return SOC_E_XXX. 399 */ 400 int 401 soc_iproc_m0ssq_shmem_get(int unit, char *name, soc_iproc_m0ssq_shmem_t **pshmem) 402 { 403 if (pshmem == NULL) { 404 return SOC_E_PARAM; 405 } 406 407 if (sal_strncmp(name, "linkscan", 8) == 0) { 408 409 /* Static allocation of linkscan shmem. */ 410 *pshmem = sal_alloc(sizeof(soc_iproc_m0ssq_shmem_t), "SocIprocM0ssqShmem"); 411 if (*pshmem == NULL) { 412 return SOC_E_MEMORY; 413 } 414 415 (*pshmem)->size = CMICX_LS_SHMEM_SIZE; 416 (*pshmem)->base = soc_iproc_percore_membase_get(unit, 0) + 417 soc_iproc_percore_memsize_get(unit, 0) - 418 CMICX_LS_SHMEM_OFFSET_DEFAULT; 419 (*pshmem)->unit = unit; 420 return SOC_E_NONE; 421 } 422 423 return SOC_E_FAIL; 424 } 425 426 /* 427 * Function: 428 * soc_iproc_m0ssq_shmem_write32 429 * Purpose: 430 * Write 32bits data into shared memory. 431 * Parameters: 432 * shmem Shared memory object. 433 * offset Offset within memory object. 434 * value 32bits data. 435 * Returns: 436 * SOC_E_NONE if success, otherwise return SOC_E_XXX. 437 */ 438 int 439 soc_iproc_m0ssq_shmem_write32(soc_iproc_m0ssq_shmem_t *shmem, 440 uint32 offset, uint32 value) 441 { 442 uint32 addr; 443 444 if (shmem == NULL) { 445 return SOC_E_UNAVAIL; 446 } 447 448 if (offset >= shmem->size) { 449 return SOC_E_PARAM; 450 } 451 452 addr = shmem->base + offset; 453 soc_iproc_setreg(shmem->unit, addr, value); 454 455 return SOC_E_NONE; 456 } 457 458 459 /* 460 * Function: 461 * soc_iproc_m0ssq_shmem_read32 462 * Purpose: 463 * Read 32bits data from shared memory. 464 * Parameters: 465 * shmem Shared memory object. 466 * offset Offset within memory object. 467 * value 32bits data. 468 * Returns: 469 * SOC_E_NONE if success, otherwise return SOC_E_XXX. 470 */ 471 int 472 soc_iproc_m0ssq_shmem_read32(soc_iproc_m0ssq_shmem_t *shmem, 473 uint32 offset, uint32 *value) 474 { 475 uint32 addr; 476 477 if (shmem == NULL || 478 value == NULL) 479 { 480 return SOC_E_UNAVAIL; 481 } 482 483 if (offset >= shmem->size) { 484 return SOC_E_PARAM; 485 } 486 487 addr = shmem->base + offset; 488 489 soc_iproc_getreg(shmem->unit, addr, value); 490 491 return SOC_E_NONE; 492 } 493 494 /* 495 * Function: 496 * soc_iproc_m0ssq_shmem_clear 497 * Purpose: 498 * Clear shared memory object as zero. 499 * Parameters: 500 * shmem Shared memory object. 501 * Returns: 502 * SOC_E_NONE if success, otherwise return SOC_E_XXX. 503 */ 504 int 505 soc_iproc_m0ssq_shmem_clear(soc_iproc_m0ssq_shmem_t *pshmem) 506 { 507 int rv; 508 uint32 addr; 509 for (addr = 0; addr < pshmem->size; addr += 4) { 510 rv = soc_iproc_m0ssq_shmem_write32(pshmem, addr, 0); 511 if (SOC_FAILURE(rv)) { 512 return rv; 513 } 514 } 515 return SOC_E_NONE; 516 } 517 518 #endif /* BCM_CMICX_SUPPORT */ 519 #endif /* BCM_ESW_SUPPORT */