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

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