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

phymod_sim.c (14026B)


      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 
      8 /*
      9  * PHY Simulator (requires PHYMOD library)
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <sal/types.h>
     15 #include <sal/core/spl.h>
     16 #include <soc/drv.h>
     17 #include <soc/error.h>
     18 #include <soc/scache.h>
     19 
     20 #ifndef PHY_NUM_SIMS
     21 #define PHY_NUM_SIMS            66
     22 #endif
     23 
     24 #if defined(PHYMOD_SUPPORT) && (PHY_NUM_SIMS > 0)
     25 #define PHY_SIM_SUPPORT
     26 #endif
     27 
     28 #ifdef BCM_WARM_BOOT_SUPPORT
     29 #define SOC_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     30 #define SOC_WB_DEFAULT_VERSION            SOC_WB_VERSION_1_0
     31 #endif
     32 
     33 #ifdef PHY_SIM_SUPPORT
     34 
     35 #include <phymod/phymod.h>
     36 #include <phymod/chip/eagle_sim.h>
     37 
     38 #include <phymod/chip/falcon_sim.h>
     39 #include <phymod/chip/tscf_sim.h>
     40 #include <phymod/chip/tsce_sim.h>
     41 #include <phymod/chip/qsgmiie_sim.h>
     42 #include <phymod/chip/viper_sim.h>
     43 #include <phymod/chip/tscf16_sim.h>
     44 #include <phymod/chip/tsce16_sim.h>
     45 #include <phymod/chip/qtce_sim.h>
     46 #include <phymod/chip/tscbh_sim.h>
     47 #include <phymod/chip/tscf_gen3_sim.h>
     48 #include <phymod/chip/tsce_dpll_sim.h>
     49 #include <phymod/chip/blackhawk_sim.h>
     50 #include <phymod/chip/qtce16_sim.h>
     51 
     52 #include <soc/phy/phymod_sim.h>
     53 
     54 #ifndef PHY_NUM_SIM_ENTRIES
     55 #define PHY_NUM_SIM_ENTRIES     400
     56 #endif
     57 
     58 typedef struct soc_phy_sim_s {
     59     phymod_sim_entry_t pms_entries[PHY_NUM_SIM_ENTRIES];
     60     phymod_sim_t pms;
     61     int unit;
     62     uint32 phy_id;
     63 } soc_phy_sim_t;
     64 
     65 static soc_phy_sim_t soc_phy_sim[PHY_NUM_SIMS];
     66 static int soc_phy_sims_used;
     67 
     68 
     69 STATIC soc_phy_sim_t *
     70 soc_physim_find(int unit, uint32 phy_id)
     71 {
     72     int idx;
     73     soc_phy_sim_t *psim;
     74 
     75     for (idx = 0; idx < soc_phy_sims_used; idx++) {
     76         psim = &soc_phy_sim[idx];
     77         if (psim->unit == unit && psim->phy_id == phy_id) {
     78             return psim;
     79         }
     80     }
     81     return NULL;
     82 }
     83 
     84 int
     85 soc_physim_add(int unit, uint32 phy_id, phymod_sim_drv_t *pms_drv)
     86 {
     87     int idx;
     88     soc_phy_sim_t *psim;
     89 
     90     /* Check if this simulator exists already */
     91     for (idx = 0; idx < soc_phy_sims_used; idx++) {
     92         psim = &soc_phy_sim[idx];
     93         if (psim->unit == unit && psim->phy_id == phy_id) {
     94             /* Reset simulator */
     95             SOC_IF_ERROR_RETURN(
     96                 phymod_sim_reset(&psim->pms));
     97             return SOC_E_NONE;
     98         }
     99     }
    100 
    101     /* Any free simulators? */
    102     if (soc_phy_sims_used >= PHY_NUM_SIMS) {
    103         LOG_ERROR(BSL_LS_SOC_PHY,
    104                   (BSL_META_U(unit,
    105                               "soc_physim_add: Out of resources for"
    106                               " unit=%d phy_id=0x%x\n"), unit, phy_id));
    107         return SOC_E_RESOURCE;
    108     }
    109 
    110     /* Add new simulator entry */
    111     psim = &soc_phy_sim[soc_phy_sims_used++];
    112     psim->unit = unit;
    113     psim->phy_id = phy_id;
    114     psim->pms.drv = pms_drv;
    115 
    116     /* Initialize and reset simulator */
    117     SOC_IF_ERROR_RETURN(
    118         phymod_sim_init(&psim->pms,
    119                         COUNTOF(psim->pms_entries), psim->pms_entries));
    120     SOC_IF_ERROR_RETURN(
    121         phymod_sim_reset(&psim->pms));
    122 
    123     return SOC_E_NONE;
    124 }
    125 
    126 #endif /* PHY_SIM_SUPPORT */
    127 
    128 int
    129 soc_physim_wrmask(int unit, uint32 phy_id,
    130                   uint32 phy_reg_addr, uint16 phy_wr_data, uint16 wr_mask)
    131 {
    132 #ifdef PHY_SIM_SUPPORT
    133     soc_phy_sim_t *psim = soc_physim_find(unit, phy_id);
    134     uint32 data32;
    135 
    136     if (psim == NULL) {
    137         return SOC_E_INIT;
    138     }
    139 
    140     data32 = wr_mask;
    141     data32 <<= 16;
    142     data32 |= phy_wr_data;
    143 
    144     SOC_IF_ERROR_RETURN(
    145         phymod_sim_write(&psim->pms, phy_reg_addr, data32));
    146 
    147     LOG_INFO(BSL_LS_SOC_PHYSIM,
    148              (BSL_META_U(unit,
    149                          "soc_physim_wrmask 0x%03x:0x%04x = 0x%04x/0x%04x\n"),
    150               phy_id, phy_reg_addr, phy_wr_data, wr_mask));
    151     return SOC_E_NONE;
    152 #else
    153     return SOC_E_UNAVAIL;
    154 #endif
    155 }
    156 
    157 int
    158 soc_physim_read(int unit, uint32 phy_id,
    159                 uint32 phy_reg_addr, uint16 *phy_rd_data)
    160 {
    161 #ifdef PHY_SIM_SUPPORT
    162     soc_phy_sim_t *psim = soc_physim_find(unit, phy_id);
    163     uint32 data32;
    164 
    165     if (psim == NULL) {
    166         return SOC_E_INIT;
    167     }
    168 
    169     SOC_IF_ERROR_RETURN(
    170         phymod_sim_read(&psim->pms, phy_reg_addr, &data32));
    171 
    172     *phy_rd_data = data32;
    173 
    174     LOG_INFO(BSL_LS_SOC_PHYSIM,
    175              (BSL_META_U(unit,
    176                          "soc_physim_read 0x%03x:0x%04x = 0x%04x\n"),
    177               phy_id, phy_reg_addr, *phy_rd_data));
    178     return SOC_E_NONE;
    179 #else
    180     return SOC_E_UNAVAIL;
    181 #endif
    182 }
    183 
    184 int
    185 soc_physim_write(int unit, uint32 phy_id,
    186                  uint32 phy_reg_addr, uint16 phy_wr_data)
    187 {
    188     return soc_physim_wrmask(unit, phy_id, phy_reg_addr, phy_wr_data, 0);
    189 }
    190 
    191 #ifdef PORTMOD_SUPPORT
    192 
    193 #include <soc/portmod/portmod.h>
    194 
    195 /* Default simulator bus */
    196 STATIC
    197 int sim_bus_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t* val){
    198     portmod_default_user_access_t *user_data;
    199     uint16_t tmp=0;
    200     int rv;
    201 
    202     if(user_acc == NULL){
    203         return SOC_E_PARAM;
    204     }
    205     user_data = (portmod_default_user_access_t*)user_acc;
    206 
    207     (*val) = 0;
    208     rv = soc_physim_read(user_data->unit, core_addr, reg_addr, &tmp);
    209     (*val) = tmp;
    210 
    211     return rv;
    212 }
    213 
    214 STATIC
    215 int sim_bus_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val){
    216     portmod_default_user_access_t *user_data;
    217     uint16_t tmp = 0;
    218     uint16_t msk = 0;
    219 
    220     if(user_acc == NULL){
    221         return SOC_E_PARAM;
    222     }
    223     user_data = (portmod_default_user_access_t*)user_acc;
    224 
    225     tmp = (val & 0xFFFF);
    226     msk = ((val >> 16) & 0xFFFF);
    227 
    228     return soc_physim_wrmask(user_data->unit, core_addr, reg_addr, tmp, msk);
    229 }
    230 
    231 phymod_bus_t sim_bus = {
    232     "portmod_phy_sim",
    233     sim_bus_read,
    234     sim_bus_write,
    235     NULL,
    236     NULL,
    237     NULL,
    238     NULL,
    239     NULL,
    240     0
    241 };
    242 
    243 void
    244 soc_physim_enable_get(int unit, int* is_sim)
    245 {
    246     int use_sim;
    247 
    248     use_sim = soc_property_get(unit, spn_PHY_SIMUL, 0) || soc_property_get(unit, spn_DIAG_EMULATOR_PARTIAL_INIT, 0);
    249 
    250     if (use_sim || SAL_BOOT_PLISIM) {
    251         (*is_sim) = 1;
    252     } else {
    253         (*is_sim) = 0;
    254     }
    255 
    256     return ;
    257 }
    258 
    259 /*
    260 addr_ident - in some cases the access->phy_id is the same for several PMs (which are accesses from diffrent blocks). 
    261 In this case addr_ident is ORed with the phy_id to distinguish between the cores.
    262 */
    263 int
    264 soc_physim_check_sim(int unit, phymod_dispatch_type_t type, phymod_access_t* access, uint32 addr_ident, int* is_sim)
    265 {
    266     int use_sim;
    267     phymod_sim_drv_t *sim = NULL;
    268 
    269     use_sim = soc_property_get(unit, spn_PHY_SIMUL, 0) || soc_property_get(unit, spn_DIAG_EMULATOR_PARTIAL_INIT, 0);
    270 
    271     if(use_sim || SAL_BOOT_PLISIM) {
    272         switch(type) {
    273             case phymodDispatchTypeEagle:
    274                 sim = &eagle_sim_drv;
    275                 break;
    276             case phymodDispatchTypeFalcon:
    277                 sim = &falcon_sim_drv;
    278                 break;
    279             case phymodDispatchTypeQsgmiie:
    280                 sim = &qsgmiie_sim_drv;
    281                 break;
    282             case phymodDispatchTypeTsce:
    283                 sim = &tsce_sim_drv;
    284                 break;
    285             case phymodDispatchTypeTscf:
    286                 sim = &tscf_sim_drv;
    287                 break;
    288             case phymodDispatchTypeViper:
    289                 if (SOC_IS_GREYHOUND2(unit)) {
    290                     sim = &viper_sp2_sim_drv;
    291                 }
    292                 else {
    293                     sim = &viper_sim_drv;
    294                 }
    295                 break;
    296             case phymodDispatchTypeTscf16:
    297                 sim = &tscf16_sim_drv;
    298                 break;
    299             case phymodDispatchTypeTscbh:
    300                 sim = &tscbh_sim_drv;
    301                 break;
    302             case phymodDispatchTypeTsce16:
    303                 sim = &tsce16_sim_drv;
    304                 break;
    305             case phymodDispatchTypeQtce:
    306                 sim = &qtce_sim_drv;
    307                 break;
    308             case phymodDispatchTypeBlackhawk:
    309                 sim = &blackhawk_sim_drv;
    310                 break;
    311             case phymodDispatchTypeTscf_gen3:
    312                 sim = &tscf_gen3_sim_drv;
    313                 break;
    314             case phymodDispatchTypeTsce_dpll:
    315                 sim = &tsce_dpll_sim_drv;
    316                 break;
    317             case phymodDispatchTypeQtce16:
    318                 sim = &qtce16_sim_drv;
    319                 break;
    320             default:
    321                 LOG_ERROR(BSL_LS_SOC_PHYSIM,
    322                          (BSL_META_U(unit,
    323                                      "Invalid simulator %d\n"), type));
    324                 return SOC_E_NOT_FOUND;
    325         }
    326 
    327         PHYMOD_ACC_ADDR(access) |= addr_ident;
    328         SOC_IF_ERROR_RETURN(soc_physim_add(unit, PHYMOD_ACC_ADDR(access), sim));
    329 
    330         PHYMOD_ACC_BUS(access) = &sim_bus;
    331         (*is_sim) = 1;
    332 
    333     } else {
    334         /* Not simulator - do nothing*/
    335         (*is_sim) = 0;
    336     }
    337 
    338     return SOC_E_NONE;
    339 }
    340 
    341 #ifdef BCM_WARM_BOOT_SUPPORT
    342 int
    343 soc_physim_scache_allocate(int unit)
    344 {
    345     int rv = SOC_E_NONE;
    346     uint8 *physim_scache_ptr;
    347     soc_scache_handle_t scache_handle;
    348     uint32 alloc_size = 0;
    349     int idx;
    350     int default_ver = SOC_WB_DEFAULT_VERSION;
    351 
    352     for (idx = 0; idx < soc_phy_sims_used; idx++) {
    353         alloc_size +=   sizeof(int) +   /* unit*/
    354                sizeof(int) +            /* phy_id */
    355                sizeof(int) +            /* num_entries */
    356                sizeof(int) +            /* entries_used */
    357                (sizeof(phymod_sim_entry_t) * PHY_NUM_SIM_ENTRIES); /* pms_entries */
    358     }
    359 
    360     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_PHYSIM_HANDLE, 0);
    361 
    362     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
    363                                           TRUE, &alloc_size,
    364                                           &physim_scache_ptr,
    365                                           default_ver,
    366                                           NULL);
    367     /* Proceed with Level 1 Warm Boot */
    368     if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    369         return rv;
    370     }
    371 
    372     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    373                 (BSL_META_U(unit,
    374                 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(),  __LINE__));
    375 
    376     return SOC_E_NONE;
    377 }
    378 
    379 int
    380 soc_physim_scache_sync(int unit)
    381 {
    382     uint8 *physim_scache_ptr;
    383     soc_scache_handle_t scache_handle;
    384     uint32 alloc_size = 0;
    385     int rv = 0;
    386     int idx, idx_pms;
    387     soc_phy_sim_t *psim;
    388     phymod_sim_entry_t *physim_entry_scache_p;
    389     uint32 *u32_scache_p;
    390 
    391     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_PHYSIM_HANDLE, 0);
    392     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
    393                         FALSE, &alloc_size,
    394                         &physim_scache_ptr,
    395                         SOC_WB_DEFAULT_VERSION,
    396                         NULL);
    397     /* Proceed with Level 1 Warm Boot */
    398     if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    399         return rv;
    400     }
    401 
    402     u32_scache_p = (uint32 *)physim_scache_ptr;
    403     for (idx = 0; idx < soc_phy_sims_used; idx++) {
    404         psim = &soc_phy_sim[idx];
    405 
    406         *u32_scache_p = psim->unit;     /* unit*/
    407         u32_scache_p++;
    408         *u32_scache_p = psim->phy_id;   /* phy_id */
    409         u32_scache_p++;
    410         *u32_scache_p = psim->pms.data.num_entries; /* num_entries */
    411         u32_scache_p++;
    412         *u32_scache_p = psim->pms.data.entries_used;/* entries_used */
    413         u32_scache_p++;
    414 
    415         /* pms_entries */
    416         physim_entry_scache_p = (phymod_sim_entry_t *)u32_scache_p;
    417         for (idx_pms = 0; idx_pms < psim->pms.data.entries_used; idx_pms++) {
    418             physim_entry_scache_p->flags = psim->pms_entries[idx_pms].flags;
    419             physim_entry_scache_p->addr = psim->pms_entries[idx_pms].addr;
    420             physim_entry_scache_p->data = psim->pms_entries[idx_pms].data;
    421             physim_entry_scache_p++;
    422         }
    423         u32_scache_p = (uint32 *)physim_entry_scache_p;
    424     }
    425 
    426     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    427                 (BSL_META_U(unit,
    428                  "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
    429 
    430     return SOC_E_NONE;
    431 }
    432 
    433 int
    434 soc_physim_scache_recovery(int unit)
    435 {
    436     uint8 *physim_scache_ptr;
    437     soc_scache_handle_t scache_handle;
    438     uint32 alloc_size = 0;
    439     int rv = 0;
    440     int idx, idx_pms;
    441     soc_phy_sim_t *psim;
    442     phymod_sim_entry_t *physim_entry_scache_p;
    443     uint32 *u32_scache_p;
    444     uint16  recovered_ver = 0;
    445 
    446     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_PHYSIM_HANDLE, 0);
    447     rv = soc_versioned_scache_ptr_get(unit, scache_handle,
    448                         FALSE, &alloc_size,
    449                         &physim_scache_ptr,
    450                         SOC_WB_DEFAULT_VERSION,
    451                         &recovered_ver);
    452     /* Proceed with Level 1 Warm Boot */
    453     if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    454         return rv;
    455     }
    456 
    457     if (recovered_ver >= SOC_WB_VERSION_1_0) {
    458         u32_scache_p = (uint32 *)physim_scache_ptr;
    459         for (idx = 0; idx < soc_phy_sims_used; idx++) {
    460             psim = &soc_phy_sim[idx];
    461 
    462             psim->unit = *u32_scache_p;     /* unit*/
    463             u32_scache_p++;
    464             psim->phy_id = *u32_scache_p;   /* phy_id */
    465             u32_scache_p++;
    466             psim->pms.data.num_entries = *u32_scache_p; /* num_entries */
    467             u32_scache_p++;
    468             psim->pms.data.entries_used = *u32_scache_p;/* entries_used */
    469             u32_scache_p++;
    470 
    471             /* pms_entries */
    472             physim_entry_scache_p = (phymod_sim_entry_t *)u32_scache_p;
    473             for (idx_pms = 0; idx_pms < psim->pms.data.entries_used; idx_pms++) {
    474                 psim->pms_entries[idx_pms].flags = physim_entry_scache_p->flags;
    475                 psim->pms_entries[idx_pms].addr = physim_entry_scache_p->addr;
    476                 psim->pms_entries[idx_pms].data = physim_entry_scache_p->data;
    477                 physim_entry_scache_p++;
    478             }
    479             u32_scache_p = (uint32 *)physim_entry_scache_p;
    480         }
    481     }
    482 
    483     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    484                 (BSL_META_U(unit,
    485                  "%s()[LINE:%d] \n"),FUNCTION_NAME(),  __LINE__));
    486 
    487     return SOC_E_NONE;
    488 }
    489 #endif /* BCM_WARM_BOOT_SUPPORT */
    490 
    491 #endif /* PORTMOD_SUPPORT */
    492