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

port.c (12582B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  */
      8 
      9 #include <soc/defs.h>
     10 
     11 #include <assert.h>
     12 
     13 #include <sal/core/libc.h>
     14 #if defined(BCM_HURRICANE_SUPPORT)
     15 
     16 #include <shared/util.h>
     17 #include <soc/mem.h>
     18 #include <soc/cm.h>
     19 #include <soc/drv.h>
     20 #include <soc/register.h>
     21 #include <soc/memory.h>
     22 #include <bcm/error.h>
     23 #include <bcm_int/esw/hurricane.h>
     24 #include <bcm_int/esw/port.h>
     25 #include <bcm_int/esw/firebolt.h>
     26 #include <bcm_int/esw/trx.h>
     27 #include <bcm_int/esw/xgs3.h>
     28 
     29 #include <bcm_int/esw_dispatch.h>
     30 
     31 /* Helper functions for bcmPortControlLanes 
     32  * Used for flex-port support
     33  */
     34 int 
     35 _bcm_hu_port_lanes_get(int unit, bcm_port_t port, int *value)
     36 {
     37     int speed = 0;
     38     int rv = BCM_E_NONE;
     39     /*    coverity[new_values]    */
     40     if (!SOC_PORT_VALID(unit, port)) {
     41         return BCM_E_PORT;
     42     }
     43     if ((port != 26) && (port != 27) && (port != 28) && (port != 29)) {
     44         return BCM_E_PORT;
     45     }
     46 
     47     BCM_IF_ERROR_RETURN(bcm_esw_port_speed_max(unit, port, &speed));
     48     
     49     if (speed >= 10000) {
     50         *value = 4;
     51     } else {
     52         *value = 1;
     53     }
     54     return rv;
     55 }
     56 
     57 /* Port table field programming - assumes PORT_LOCK is taken */
     58 int
     59 _bcm_hu_port_tab_set(int unit, bcm_port_t port, 
     60                       soc_field_t field, int value)
     61 
     62 {
     63     port_tab_entry_t pent;
     64     soc_mem_t mem;
     65     int rv, cur_val;
     66 
     67     mem = SOC_PORT_MEM_TAB(unit, port);
     68     if (!SOC_MEM_FIELD_VALID(unit, mem, field)) {
     69         return (BCM_E_UNAVAIL);
     70     }
     71     sal_memset(&pent, 0, sizeof(port_tab_entry_t));
     72     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
     73                       SOC_PORT_MOD_OFFSET(unit, port), &pent);
     74 
     75     if (BCM_SUCCESS(rv)) {
     76         cur_val = soc_PORT_TABm_field32_get(unit, &pent, field);
     77         if (value != cur_val) {
     78             soc_PORT_TABm_field32_set(unit, &pent, field, value);
     79             rv = soc_mem_write(unit, mem,
     80                                MEM_BLOCK_ALL, port, &pent);
     81         }
     82     }
     83     return rv;
     84 }
     85 
     86 int 
     87 _bcm_hu_port_lanes_set(int unit, bcm_port_t port, int value)
     88 {
     89     int okay, old_value, rv = BCM_E_NONE;
     90     uint32 rval, val2, to_usec, mode;
     91     uint64 rval64;
     92     soc_info_t *si;
     93     soc_field_t xq_rst2 = INVALIDf;
     94     soc_field_t ep_port_rst = INVALIDf;
     95     soc_field_t ep_mmu_rst = INVALIDf;
     96     bcm_port_t it_port;
     97     mac_driver_t *macd;
     98     egr_enable_entry_t egnt;
     99 
    100     si = &SOC_INFO(unit);
    101 
    102     to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) :
    103                                    (10 * MILLISECOND_USEC);
    104 
    105     if (!SOC_PORT_VALID(unit, port)) {
    106         return BCM_E_PORT;
    107     }
    108     if ((port != 26) && (port != 27) && (port != 28) && (port != 29)) {
    109         return BCM_E_PORT;
    110     }
    111     if ((value != 1) && (value != 4)) {
    112         return BCM_E_PARAM;
    113     }
    114     BCM_IF_ERROR_RETURN(_bcm_hu_port_lanes_get(unit, port, &old_value));
    115 
    116 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \
    117     si->ptype.num = 0; \
    118     si->ptype.min = si->ptype.max = -1; \
    119     PBMP_ITER(si->ptype.bitmap, it_port) { \
    120         si->ptype.port[si->ptype.num++] = it_port; \
    121         if (si->ptype.min < 0) { \
    122             si->ptype.min = it_port; \
    123         } \
    124         if (it_port > si->ptype.max) { \
    125             si->ptype.max = it_port; \
    126         } \
    127     }
    128 
    129     /* Step 1: Change the SOC bitmaps */
    130     if ((value == 1) && (old_value == 4)) {
    131         /* The block was originally a single high-speed port */
    132         SOC_CONTROL_LOCK(unit);
    133         if (IS_HG_PORT(unit, port)) {
    134             SOC_PBMP_PORT_REMOVE(si->st.bitmap, port);
    135             SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port);
    136             SOC_PBMP_PORT_ADD(si->ether.bitmap, port);
    137         } else {
    138             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
    139         }
    140         SOC_PBMP_PORT_ADD(si->ge.bitmap, port);
    141         si->port_speed_max[port] = 2500;
    142         soc_port_cmap_set(unit, port, SOC_CTR_TYPE_GE);
    143         
    144         RECONFIGURE_PORT_TYPE_INFO(ether);
    145         RECONFIGURE_PORT_TYPE_INFO(st);
    146         RECONFIGURE_PORT_TYPE_INFO(hg);
    147         RECONFIGURE_PORT_TYPE_INFO(xe);
    148         RECONFIGURE_PORT_TYPE_INFO(ge);
    149 
    150         SOC_CONTROL_UNLOCK(unit);
    151         BCM_IF_ERROR_RETURN(_bcm_hu_port_tab_set(unit, port, PORT_TYPEf, 0));
    152         BCM_IF_ERROR_RETURN
    153             (soc_reg_field32_modify(unit, EGR_PORTr, port, PORT_TYPEf, 0));
    154 
    155     } else if ((value == 4) && (old_value == 1)) {
    156         /* The block originally had 4 GE ports */
    157         SOC_CONTROL_LOCK(unit);
    158         SOC_PBMP_PORT_ADD(si->st.bitmap, port);
    159         SOC_PBMP_PORT_ADD(si->hg.bitmap, port);
    160         SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port);
    161         SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port);
    162         si->port_speed_max[port] = 13000;
    163         soc_port_cmap_set(unit, port, SOC_CTR_TYPE_XE);
    164         RECONFIGURE_PORT_TYPE_INFO(ether);
    165         RECONFIGURE_PORT_TYPE_INFO(st);
    166         RECONFIGURE_PORT_TYPE_INFO(hg);
    167         RECONFIGURE_PORT_TYPE_INFO(ge);
    168         SOC_CONTROL_UNLOCK(unit);
    169         BCM_IF_ERROR_RETURN(_bcm_hu_port_tab_set(unit, port, PORT_TYPEf, 1));
    170         BCM_IF_ERROR_RETURN
    171             (soc_reg_field32_modify(unit, EGR_PORTr, port, PORT_TYPEf, 1));
    172     }
    173 #undef RECONFIGURE_PORT_TYPE_INFO
    174 
    175     soc_dport_map_update(unit);
    176 
    177     /* Step 2: Perform necessary block-level reset and initialization */
    178     /* Egress disable */
    179 
    180    
    181    if (SOC_IS_HURRICANE2(unit)) {
    182       soc_EGR_ENABLEm_field32_set(unit, &egnt, PRT_ENABLEf, 0);
    183       rv = soc_mem_write(unit, EGR_ENABLEm,
    184                                MEM_BLOCK_ALL, port, &egnt);
    185       if (BCM_FAILURE(rv)) {
    186           return rv;
    187       }
    188    } else  {
    189       rval = 0;
    190       if (SOC_REG_IS_VALID(unit,EGR_ENABLEr)) {
    191          soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 0);
    192          SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval));
    193      }
    194    }
    195 
    196     /* Hold the XQPORT hotswap reset */
    197     switch (port) {
    198     case 26:
    199         ep_port_rst = EGR_XQP0_PORT_INT_RESETf;
    200         ep_mmu_rst = EGR_XQP0_MMU_INT_RESETf;
    201         xq_rst2 = XQ0_HOTSWAP_RST_Lf;
    202         break;
    203     case 27:
    204         ep_port_rst = EGR_XQP1_PORT_INT_RESETf;
    205         ep_mmu_rst = EGR_XQP1_MMU_INT_RESETf;
    206         xq_rst2 = XQ1_HOTSWAP_RST_Lf;
    207         break;
    208     case 28:
    209         ep_port_rst = EGR_XQP2_PORT_INT_RESETf;
    210         ep_mmu_rst = EGR_XQP2_MMU_INT_RESETf;
    211         xq_rst2 = XQ2_HOTSWAP_RST_Lf;
    212         break;
    213     case 29:
    214         ep_port_rst = EGR_XQP3_PORT_INT_RESETf;
    215         ep_mmu_rst = EGR_XQP3_MMU_INT_RESETf;
    216         xq_rst2 = XQ3_HOTSWAP_RST_Lf;
    217         break;
    218     default:
    219         return SOC_E_PORT;
    220     }
    221 
    222     if (SOC_REG_IS_VALID(unit,CMIC_SOFT_RESET_REGr)) {
    223        SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(unit, &val2));
    224        soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &val2, 
    225                       xq_rst2, 0);
    226        SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(unit, val2));
    227     }
    228     sal_usleep(to_usec);
    229 
    230 
    231 #if 0 /* Carryover from Endiro.. Does Hurricane need this? */
    232     /* Program the ingress and MMU TDMs */
    233     count = -1;
    234     for (i = 0; i < soc_mem_index_count(unit, ARB_TDM_TABLEm); i++) {
    235         BCM_IF_ERROR_RETURN
    236             (READ_ARB_TDM_TABLEm(unit, MEM_BLOCK_ANY, i, &arb_tdm));
    237         BCM_IF_ERROR_RETURN
    238             (READ_IARB_TDM_TABLEm(unit, MEM_BLOCK_ANY, i, &iarb_tdm));
    239         it_port = soc_ARB_TDM_TABLEm_field32_get(unit, &arb_tdm, PORT_NUMf);
    240         /* First set to disabled - 63 */
    241         if (old_value == value) {
    242             continue;
    243         } else if (old_value == 4 && value == 1) {
    244             if (port != it_port) {
    245                 continue;
    246             }
    247         } else {
    248             if ((it_port != port) && (it_port != port + 1) && 
    249                 (it_port != port + 2) && (it_port != port + 3)) {
    250                 continue;
    251             }
    252         }
    253         soc_ARB_TDM_TABLEm_field32_set(unit, &arb_tdm, PORT_NUMf, 63);
    254         soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, 63);
    255         BCM_IF_ERROR_RETURN(WRITE_IARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    256                                                   &iarb_tdm));
    257         BCM_IF_ERROR_RETURN(WRITE_ARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    258                                                  &arb_tdm));
    259         /* Then program the desired value */
    260         if (old_value == 4 && value == 1) {
    261             count++;
    262             soc_ARB_TDM_TABLEm_field32_set(unit, &arb_tdm, PORT_NUMf, 
    263                                            port + (count % 4));
    264             soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, 
    265                                             port + (count % 4));
    266         } else {
    267             soc_ARB_TDM_TABLEm_field32_set(unit, &arb_tdm, PORT_NUMf, port);
    268             soc_IARB_TDM_TABLEm_field32_set(unit, &iarb_tdm, PORT_NUMf, port);
    269         }
    270         BCM_IF_ERROR_RETURN(WRITE_IARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    271                                                   &iarb_tdm));
    272         BCM_IF_ERROR_RETURN(WRITE_ARB_TDM_TABLEm(unit, MEM_BLOCK_ALL, i, 
    273                                                  &arb_tdm));
    274         if (soc_ARB_TDM_TABLEm_field32_get(unit, &arb_tdm, WRAP_ENf)) {
    275             break;
    276         }
    277     }
    278 #endif
    279 
    280     /* Clear the ECRC register */
    281     if (SOC_REG_IS_VALID(unit,ECRCr)) {
    282         SOC_IF_ERROR_RETURN(WRITE_ECRCr(unit, port, 0));
    283     } else if (SOC_REG_IS_VALID(unit,EGRESSCELLREQUESTCOUNTr)) {
    284 		SOC_IF_ERROR_RETURN(WRITE_EGRESSCELLREQUESTCOUNTr(unit, port, 0));
    285 	}
    286     /* Reset the EP */
    287     if (SOC_REG_IS_VALID(unit,EDATABUF_XQP_FLEXPORT_CONFIGr)) {
    288        SOC_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &val2));
    289        soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    290                         ep_port_rst, 1);
    291        soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    292                         ep_mmu_rst, 1);
    293        SOC_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, val2));
    294        sal_usleep(to_usec);
    295 
    296        SOC_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &val2));
    297        soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    298                         ep_port_rst, 0);
    299        soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    300                         ep_mmu_rst, 0);
    301        SOC_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, val2));
    302     }
    303     sal_usleep(to_usec);
    304     
    305 
    306     /* Bring the XQPORT block out of reset */
    307     /* coverity[result_independent_of_operands] */  
    308     SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(unit, &val2));
    309     soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &val2, 
    310                       xq_rst2, 1);
    311     /* coverity[result_independent_of_operands] */  
    312     SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(unit, val2));
    313     sal_usleep(to_usec);
    314     
    315 
    316     /* Bring the hyperlite out of reset */
    317     soc_xgxs_reset(unit, port);
    318     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XQPORT_XGXS_NEWCTL_REGr, 
    319                                                port, TXD1G_FIFO_RSTBf, 0xf));
    320 
    321     /* Change the XQPORT block mode */
    322     mode = (value == 4) ? 2 : 1; /* 2 = high-speed, 1 = GE */
    323     SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval));
    324     soc_reg_field_set(unit, XQPORT_MODE_REGr, &rval, 
    325                       XQPORT_MODE_BITSf, mode);
    326     SOC_IF_ERROR_RETURN(WRITE_XQPORT_MODE_REGr(unit, port, rval));
    327 
    328     if (value == 4) {
    329         rval = 0;
    330         soc_reg_field_set(unit, XPORT_CONFIGr, &rval, XPORT_ENf, 1);
    331         soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 1);
    332         SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval));
    333     }
    334 
    335     /* Egress Enable */
    336     rval = 0;
    337     soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 1);
    338     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval));
    339 
    340     /* Step 3: Port probe and initialization */
    341     BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port, &okay));
    342     if (!okay) {
    343         return BCM_E_INTERNAL;
    344     }
    345 
    346     BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, TRUE));
    347 
    348     if (value == 4) {
    349         /* Need to reset the Bigmac to make registers accessible */
    350         SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macd));
    351         SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &rval64));
    352         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, TXRESETf, 0);
    353         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, RXRESETf, 0);
    354         SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, rval64));
    355         SOC_IF_ERROR_RETURN(MAC_INIT(macd, unit, port));
    356         BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, TRUE));
    357     }
    358 
    359     return rv;
    360 }
    361 #endif