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

switch.c (14396B)


      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  * SOC switch Utilities
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <soc/drv.h>
     13 #include <soc/error.h>
     14 #include <soc/scache.h>
     15 #include <shared/alloc.h>
     16 #include <soc/phy/phyctrl.h>
     17 
     18 #ifdef BCM_WARM_BOOT_SUPPORT
     19 
     20 #define SOC_CONTROL_WB_PART_0_VER_1_0       SOC_SCACHE_VERSION(1,0)
     21 #define SOC_CONTROL_WB_PART_0_DEFAULT_VER   SOC_CONTROL_WB_PART_0_VER_1_0
     22 
     23 /*
     24  * List of software-only switch controls that need to be recovered in Level 2.
     25  * There is no way to recover these controls in level 1 warmboot.
     26  *
     27  * The following enum is used to identify the boolean controls.
     28  */
     29 enum soc_wb_boolean_controls_0_e {
     30     socControlUseGport = 0,
     31     socControlL2PortBlocking = 1,
     32     socControlAbortOnError = 2,
     33     socControlCount = 3
     34 };
     35 
     36 #define SOC_CONTROL_WB_NUM_ELE_0 8
     37 static int soc_wb_boolean_controls_0[SOC_CONTROL_WB_NUM_ELE_0] =
     38 {
     39     socControlUseGport,
     40     socControlL2PortBlocking,
     41     socControlAbortOnError,
     42     -1,
     43     -1,
     44     -1,
     45     -1,
     46     -1
     47 };
     48 
     49 /*
     50  * Function:
     51  *      soc_switch_control_scache_size_get
     52  * Description:
     53  *      Get the size of scache size required for level 2 WarmBoot.
     54  * Parameters:
     55  *      unit -    (IN) SOC device number.
     56  *      part -    (IN) Warmboot partition number.
     57  *      version - (IN) WarmBoot Level 2 scache version for switch module.
     58  * Returns:
     59  *      Size of scache space required in bytes.
     60  */
     61 STATIC int
     62 soc_switch_control_scache_size_get(int unit, int part, int version)
     63 {
     64     int alloc_size = 0;
     65 
     66     if (part == SOC_SCACHE_SWITCH_CONTROL_PART0) {
     67         if (version >= SOC_CONTROL_WB_PART_0_VER_1_0) {
     68             alloc_size += 1;
     69         }
     70 
     71         /*
     72          * if (version >= SOC_CONTROL_WB_PART_0_VER_1_1) {
     73          *     // alloc_size += n;
     74          * }
     75  */
     76 
     77     }
     78 
     79     return alloc_size;
     80 }
     81 
     82 /*
     83  * Function:
     84  *      soc_switch_control_scache_init
     85  * Description:
     86  *      WarmBoot recovery procedure for recovering global switch controls.
     87  * Parameters:
     88  *      unit -    (IN) BCM device number.
     89  * Returns:
     90  *      BCM_E_XXX
     91  */
     92 int
     93 soc_switch_control_scache_init(int unit)
     94 {
     95     int rv = SOC_E_NONE;
     96     int i, arg, part;
     97     int stable_size;
     98     uint32 alloc_sz;
     99     uint8 *switch_scache;
    100     uint16 default_ver, recovered_ver;
    101     soc_scache_handle_t  scache_handle;
    102     int create = SOC_WARM_BOOT(unit) ? FALSE : TRUE;
    103 
    104     /* Limited scache mode unsupported */
    105     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
    106         return (SOC_E_NONE);
    107     }
    108 
    109     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    110     if (!stable_size) {
    111         /* stable not allocated */
    112         return SOC_E_NONE;
    113     }
    114 
    115     part = SOC_SCACHE_SWITCH_CONTROL_PART0;
    116     default_ver = SOC_CONTROL_WB_PART_0_DEFAULT_VER;
    117 
    118     alloc_sz = soc_switch_control_scache_size_get(unit, part, default_ver);
    119 
    120     SOC_SCACHE_ALIGN_SIZE(alloc_sz);
    121     alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE;
    122 
    123     SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_SWITCH_CONTROL, part);
    124 
    125     /* Get the pointer for the Level 2 cache */
    126     rv = soc_extended_scache_ptr_get(unit, scache_handle, create,
    127                                      create ? alloc_sz : 0,
    128                                      &switch_scache);
    129     if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    130         return rv;
    131     } else if (SOC_E_NOT_FOUND == rv && !create) {
    132         /* Not yet allocated in upgrade */
    133         rv = soc_extended_scache_ptr_get(unit, scache_handle, TRUE,
    134                                          alloc_sz,
    135                                          &switch_scache);
    136         if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
    137             return rv;
    138         }
    139     } else if (SOC_FAILURE(rv)) {
    140         return rv;
    141     }
    142 
    143     /* recover version info */
    144     sal_memcpy(&recovered_ver, switch_scache, sizeof(uint16));
    145 
    146     /* Advance over scache control info */
    147     switch_scache += SOC_WB_SCACHE_CONTROL_SIZE;
    148 
    149     /* If cold-booting or re-init in cold, return from here */
    150     if (!SOC_WARM_BOOT(unit)) {
    151         return SOC_E_NONE;
    152     }
    153 
    154     /* Scache Version 1.0 */
    155     if (recovered_ver >= SOC_CONTROL_WB_PART_0_VER_1_0) {
    156         for (i = 0; (i < SOC_CONTROL_WB_NUM_ELE_0); i++) {
    157             if (-1 != soc_wb_boolean_controls_0[i]) {
    158                 arg = !!(*switch_scache & (1 << i));
    159                 switch (i) {
    160                     case socControlUseGport:
    161                         SOC_USE_GPORT_SET(unit, arg);
    162                         break;
    163                     case socControlL2PortBlocking:
    164                         SOC_L2X_GROUP_ENABLE_SET(unit, arg);
    165                         break;
    166                     case socControlAbortOnError:
    167 #ifdef BCM_CB_ABORT_ON_ERR
    168                         SOC_CB_ABORT_ON_ERR(unit) = arg;
    169 #endif /* BCM_CB_ABORT_ON_ERR */
    170                         break;
    171                     default:
    172                         break;
    173                 }
    174             }
    175         }
    176         switch_scache++;
    177     }
    178 
    179     /*
    180      * if (recovered_ver >= SOC_CONTROL_WB_PART_0_VER_1_1) {
    181      *    // Recover state corresponding to WB version 1.1
    182      * }
    183  */
    184 
    185     return rv;
    186 }
    187 
    188 /*
    189  * Function:
    190  *      soc_switch_control_scache_sync
    191  * Description:
    192  *      Save golbal switch state to scache.
    193  * Parameters:
    194  *      unit -    (IN) BCM device number.
    195  * Returns:
    196  *      SOC_E_XXX
    197  */
    198 int
    199 soc_switch_control_scache_sync(int unit)
    200 {
    201     int                  i, arg;
    202     int                  rv = SOC_E_NONE;
    203     uint8                sc_map = 0;
    204     uint16               default_ver;
    205     uint32               alloc_get;
    206     uint8                *switch_scache;
    207     soc_scache_handle_t  scache_handle;
    208 
    209     /* Limited scache mode unsupported */
    210     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
    211         return SOC_E_NONE;
    212     }
    213 
    214     default_ver = SOC_CONTROL_WB_PART_0_DEFAULT_VER;
    215     SOC_SCACHE_HANDLE_SET(scache_handle, unit,
    216                           SOC_SCACHE_SWITCH_CONTROL,
    217                           SOC_SCACHE_SWITCH_CONTROL_PART0);
    218 
    219     /* Get the pointer for the Level 2 cache */
    220     rv = soc_scache_ptr_get(unit, scache_handle,
    221                             &switch_scache, &alloc_get);
    222 
    223     SOC_IF_ERROR_RETURN(rv);
    224 
    225     /* save default version */
    226     sal_memcpy(switch_scache, &default_ver, sizeof(uint16));
    227     switch_scache += SOC_WB_SCACHE_CONTROL_SIZE;
    228 
    229     /* Enable bits if the corresponding switch control is set */
    230     for (i = 0; (i < SOC_CONTROL_WB_NUM_ELE_0); i++) {
    231         if (-1 != soc_wb_boolean_controls_0[i]) {
    232             arg = 0;
    233             switch (i) {
    234                 case socControlUseGport:
    235                     arg = SOC_USE_GPORT(unit);
    236                     break;
    237                 case socControlL2PortBlocking:
    238                     arg = SOC_L2X_GROUP_ENABLE_GET(unit);
    239                     break;
    240                 case socControlAbortOnError:
    241 #ifdef BCM_CB_ABORT_ON_ERR
    242                     arg = SOC_CB_ABORT_ON_ERR(unit);
    243 #endif /* BCM_CB_ABORT_ON_ERR */
    244                     break;
    245                 default:
    246                     break;
    247             }
    248             if (arg) {
    249                 sc_map |= (1 << i);
    250             }
    251         }
    252     }
    253     *switch_scache = sc_map;
    254 
    255     switch_scache++;
    256 
    257     return rv;
    258 }
    259 
    260 #endif /* BCM_WARM_BOOT_SUPPORT */
    261 
    262 /*
    263  * Function:
    264  *      soc_switch_sync_mux_from_pbm
    265  * Description:
    266  *      Convert a port index to SyncE L1 recovered clock mux setting
    267  * Parameters:
    268  *      unit -    (IN)  BCM device number.
    269  *      port -    (IN)  Port index
    270  *      mux  -    (OUT) Mux setting corresponding to port
    271  * Returns:
    272  *      SOC_E_XXX
    273  */
    274 int
    275 soc_switch_sync_mux_from_port(int unit,
    276                               int port,
    277                               int *mux)
    278 {
    279     if (!SOC_PORT_VALID(unit, port) ||
    280         !SOC_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) {
    281         return SOC_E_PARAM;
    282     }
    283 
    284 #ifdef BCM_HURRICANE3_SUPPORT
    285     if (SOC_IS_HURRICANE3(unit)) {
    286         if (SOC_PORT_VALID(unit, port)) {
    287             int addr = soc_phy_addr_of_port(unit, port);
    288             /* See _hurricane3_phy_addr_default for values used below */
    289             if (addr >= 0x81 && addr <= 0x88) {
    290                 *mux = (16 + (addr - 0x81));
    291                 return SOC_E_NONE;
    292             }
    293             if (addr >= 0x89 && addr <= 0x90) {
    294                 *mux = (32 + (addr - 0x89));
    295                 return SOC_E_NONE;
    296             }
    297             if (addr == 0xa1) {
    298                 int lane = INT_PHY_SW_STATE(unit, port)->lane_num;
    299                 *mux = 4 + lane;
    300                 return SOC_E_NONE;
    301             }
    302             if (addr == 0xa5) {
    303                 int lane = INT_PHY_SW_STATE(unit, port)->lane_num;
    304                 *mux = 8 + lane;
    305                 return SOC_E_NONE;
    306             }
    307             if (addr == 0xa9) {
    308                 int lane = INT_PHY_SW_STATE(unit, port)->lane_num;
    309                 *mux = 24 + lane;
    310                 return SOC_E_NONE;
    311             }
    312             if (addr == 0xad) {
    313                 int lane = INT_PHY_SW_STATE(unit, port)->lane_num;
    314                 *mux = 40 + lane;
    315                 return SOC_E_NONE;
    316             }
    317         }
    318         return SOC_E_PARAM;
    319     }
    320 #endif /* BCM_HURRICANE3_SUPPORT */
    321 
    322     /* Default behavior: */
    323     *mux = port - 1;
    324 
    325     return SOC_E_NONE;
    326 }
    327 
    328 /*
    329  * Function:
    330  *      soc_switch_sync_mux_from_pbm
    331  * Description:
    332  *      Convert a PBM value to SyncE L1 recovered clock mux setting
    333  * Parameters:
    334  *      unit -    (IN)  BCM device number.
    335  *      pbm  -    (IN)  Port BitMap with desired port
    336  *      mux  -    (OUT) Mux setting corresponding to PBM
    337  * Returns:
    338  *      SOC_E_XXX
    339  */
    340 int
    341 soc_switch_sync_mux_from_pbm(int unit,
    342                              pbmp_t pbm,
    343                              int *mux)
    344 {
    345     int count, port;
    346 
    347     SOC_PBMP_COUNT(pbm, count);
    348 
    349     if (count != 1) {
    350         return SOC_E_PARAM;
    351     }
    352 
    353     SOC_PBMP_ITER(pbm, port) {
    354         SOC_IF_ERROR_RETURN(soc_switch_sync_mux_from_port(unit, port, mux));
    355     }
    356 
    357     return SOC_E_NONE;
    358 }
    359 
    360 /*
    361  * Function:
    362  *      soc_switch_sync_mux_from_pll
    363  * Description:
    364  *      Convert a port index to SyncE L1 recovered clock mux setting
    365  * Parameters:
    366  *      unit -    (IN)  BCM device number.
    367  *      pll  -    (IN)  PLL reference
    368  *      mux  -    (OUT) Mux setting corresponding to PLL
    369  * Returns:
    370  *      SOC_E_XXX
    371  */
    372 int
    373 soc_switch_sync_mux_from_pll(int unit,
    374                              soc_recov_clk_src_t src,
    375                              int *mux)
    376 {
    377 #ifdef BCM_KATANA_SUPPORT
    378     if (SOC_IS_KATANA(unit)) {
    379         switch (src) {
    380         case SOC_RCVR_CLK_SERDES_PLL:
    381             *mux = 34;
    382             return SOC_E_NONE;
    383         case SOC_RCVR_CLK_MASTER_PLL:
    384             *mux = 35;
    385             return SOC_E_NONE;
    386         default:
    387             return SOC_E_PARAM;
    388         }
    389     }
    390 #endif
    391 
    392 #ifdef BCM_KATANA2_SUPPORT
    393     if (SOC_IS_KATANA2(unit)) {
    394         switch (src) {
    395         case SOC_RCVR_CLK_SERDES_PLL:
    396             *mux = 40;
    397             return SOC_E_NONE;
    398         case SOC_RCVR_CLK_MASTER_PLL:
    399             *mux = 41;
    400             return SOC_E_NONE;
    401         case SOC_RCVR_CLK_EXT_PHY_0:
    402             *mux = 41;
    403             return SOC_E_NONE;
    404         default:
    405             return SOC_E_PARAM;
    406         }
    407     }
    408 #endif
    409 
    410 #ifdef BCM_SABER2_SUPPORT
    411     if (SOC_IS_SABER2(unit)) {
    412         switch (src) {
    413         case SOC_RCVR_CLK_SERDES_PLL:
    414             *mux = 28;
    415             return SOC_E_NONE;
    416         case SOC_RCVR_CLK_MASTER_PLL:
    417             *mux = 29;
    418             return SOC_E_NONE;
    419         case SOC_RCVR_CLK_EXT_PHY_0:
    420             *mux = 30;
    421             return SOC_E_NONE;
    422         default:
    423             return SOC_E_PARAM;
    424         }
    425     }
    426 #endif
    427 
    428 #ifdef BCM_HELIX4_SUPPORT
    429     if (SOC_IS_HELIX4(unit)) {
    430         switch (src) {
    431         case SOC_RCVR_CLK_XGPLL_0:
    432             *mux = 64;
    433             return SOC_E_NONE;
    434         case SOC_RCVR_CLK_XGPLL_1:
    435             *mux = 65;
    436             return SOC_E_NONE;
    437         default:
    438             return SOC_E_PARAM;
    439         }
    440     }
    441 #endif
    442 
    443 #ifdef BCM_HURRICANE2_SUPPORT
    444     if (SOC_IS_HURRICANE2(unit)) {
    445         switch (src) {
    446         case SOC_RCVR_CLK_XGPLL_0:
    447             *mux = 28;
    448             return SOC_E_NONE;
    449         case SOC_RCVR_CLK_XGPLL_1:
    450             *mux = 29;
    451             return SOC_E_NONE;
    452         case SOC_RCVR_CLK_EXT_PHY_0:
    453             *mux = 26;
    454             return SOC_E_NONE;
    455         case SOC_RCVR_CLK_EXT_PHY_1:
    456             *mux = 27;
    457             return SOC_E_NONE;
    458         default:
    459             return SOC_E_PARAM;
    460         }
    461     }
    462 #endif
    463 
    464 #ifdef BCM_HURRICANE3_SUPPORT
    465     if (SOC_IS_HURRICANE3(unit)) {
    466         switch (src) {
    467         case SOC_RCVR_CLK_XGPLL_0:
    468             *mux = 0;
    469             return SOC_E_NONE;
    470         case SOC_RCVR_CLK_XGPLL_1:
    471             *mux = 1;
    472             return SOC_E_NONE;
    473         case SOC_RCVR_CLK_EXT_PHY_0:
    474             *mux = 2;
    475             return SOC_E_NONE;
    476         case SOC_RCVR_CLK_EXT_PHY_1:
    477             *mux = 3;
    478             return SOC_E_NONE;
    479         default:
    480             return SOC_E_PARAM;
    481         }
    482     }
    483 #endif
    484 
    485 #ifdef BCM_GREYHOUND_SUPPORT
    486     if (SOC_IS_GREYHOUND(unit)) {
    487         switch (src) {
    488         case SOC_RCVR_CLK_XGPLL_0:
    489             *mux = 28;
    490             return SOC_E_NONE;
    491         case SOC_RCVR_CLK_XGPLL_1:
    492             *mux = 29;
    493             return SOC_E_NONE;
    494         case SOC_RCVR_CLK_EXT_PHY_0:
    495             *mux = 26;
    496             return SOC_E_NONE;
    497         case SOC_RCVR_CLK_EXT_PHY_1:
    498             *mux = 27;
    499             return SOC_E_NONE;
    500         default:
    501             return SOC_E_PARAM;
    502         }
    503     }
    504 #endif
    505 
    506 #if (defined(BCM_TOMAHAWK_SUPPORT) ||  \
    507      defined(BCM_APACHE_SUPPORT) ||    \
    508      defined(BCM_TRIDENT2X_SUPPORT))
    509 
    510     /* Note:  These chips have a separate mux to pick between port and
    511        a specific LCPLL.  We return the value for that mux here. */
    512 
    513     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_APACHE(unit) || SOC_IS_TRIDENT2X(unit)) {
    514         switch (src) {
    515         case SOC_RCVR_CLK_XGPLL_0:
    516             *mux = 1;
    517             return SOC_E_NONE;
    518         case SOC_RCVR_CLK_XGPLL_1:
    519             *mux = 2;
    520             return SOC_E_NONE;
    521         case SOC_RCVR_CLK_XGPLL_2:
    522             *mux = 3;
    523             return SOC_E_NONE;
    524         case SOC_RCVR_CLK_XGPLL_3:
    525             *mux = 4;
    526             return SOC_E_NONE;
    527         default:
    528             return SOC_E_PARAM;
    529         }
    530     }
    531 #endif /* TOMAHAWK / APACHE / TRIDENT2X */
    532 
    533     return SOC_E_UNAVAIL;
    534 }