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 (9823B)


      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_ENDURO_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/enduro.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_en_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_en_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_en_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 
     99     si = &SOC_INFO(unit);
    100 
    101     to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) :
    102                                    (10 * MILLISECOND_USEC);
    103 
    104     if (!SOC_PORT_VALID(unit, port)) {
    105         return BCM_E_PORT;
    106     }
    107     if ((port != 26) && (port != 27) && (port != 28) && (port != 29)) {
    108         return BCM_E_PORT;
    109     }
    110     if ((value != 1) && (value != 4)) {
    111         return BCM_E_PARAM;
    112     }
    113     BCM_IF_ERROR_RETURN(_bcm_en_port_lanes_get(unit, port, &old_value));
    114 
    115 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \
    116     si->ptype.num = 0; \
    117     si->ptype.min = si->ptype.max = -1; \
    118     PBMP_ITER(si->ptype.bitmap, it_port) { \
    119         si->ptype.port[si->ptype.num++] = it_port; \
    120         if (si->ptype.min < 0) { \
    121             si->ptype.min = it_port; \
    122         } \
    123         if (it_port > si->ptype.max) { \
    124             si->ptype.max = it_port; \
    125         } \
    126     }
    127 
    128     /* Step 1: Change the SOC bitmaps */
    129     if ((value == 1) && (old_value == 4)) {
    130         /* The block was originally a single high-speed port */
    131         SOC_CONTROL_LOCK(unit);
    132         if (IS_HG_PORT(unit, port)) {
    133             SOC_PBMP_PORT_REMOVE(si->st.bitmap, port);
    134             SOC_PBMP_PORT_REMOVE(si->hg.bitmap, port);
    135             SOC_PBMP_PORT_ADD(si->ether.bitmap, port);
    136         } else {
    137             SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port);
    138         }
    139         SOC_PBMP_PORT_ADD(si->ge.bitmap, port);
    140         si->port_speed_max[port] = 2500;
    141         soc_port_cmap_set(unit, port, SOC_CTR_TYPE_GE);
    142         
    143         RECONFIGURE_PORT_TYPE_INFO(ether);
    144         RECONFIGURE_PORT_TYPE_INFO(st);
    145         RECONFIGURE_PORT_TYPE_INFO(hg);
    146         RECONFIGURE_PORT_TYPE_INFO(xe);
    147         RECONFIGURE_PORT_TYPE_INFO(ge);
    148 
    149         SOC_CONTROL_UNLOCK(unit);
    150         BCM_IF_ERROR_RETURN(_bcm_en_port_tab_set(unit, port, PORT_TYPEf, 0));
    151         BCM_IF_ERROR_RETURN
    152             (soc_reg_field32_modify(unit, EGR_PORTr, port, PORT_TYPEf, 0));
    153 
    154     } else if ((value == 4) && (old_value == 1)) {
    155         /* The block originally had 4 GE ports */
    156         SOC_CONTROL_LOCK(unit);
    157         SOC_PBMP_PORT_ADD(si->st.bitmap, port);
    158         SOC_PBMP_PORT_ADD(si->hg.bitmap, port);
    159         SOC_PBMP_PORT_REMOVE(si->ether.bitmap, port);
    160         SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port);
    161         si->port_speed_max[port] = 13000;
    162         soc_port_cmap_set(unit, port, SOC_CTR_TYPE_XE);
    163         RECONFIGURE_PORT_TYPE_INFO(ether);
    164         RECONFIGURE_PORT_TYPE_INFO(st);
    165         RECONFIGURE_PORT_TYPE_INFO(hg);
    166         RECONFIGURE_PORT_TYPE_INFO(ge);
    167         SOC_CONTROL_UNLOCK(unit);
    168         BCM_IF_ERROR_RETURN(_bcm_en_port_tab_set(unit, port, PORT_TYPEf, 1));
    169         BCM_IF_ERROR_RETURN
    170             (soc_reg_field32_modify(unit, EGR_PORTr, port, PORT_TYPEf, 1));
    171     }
    172 #undef RECONFIGURE_PORT_TYPE_INFO
    173 
    174     soc_dport_map_update(unit);
    175 
    176     /* Step 2: Perform necessary block-level reset and initialization */
    177     /* Egress disable */
    178     rval = 0;
    179     soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 0);
    180     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval));
    181 
    182     /* Hold the XQPORT hotswap reset */
    183     switch (port) {
    184     case 26:
    185         ep_port_rst = EGR_XQP0_PORT_INT_RESETf;
    186         ep_mmu_rst = EGR_XQP0_MMU_INT_RESETf;
    187         xq_rst2 = XQ0_HOTSWAP_RST_Lf;
    188         break;
    189     case 27:
    190         ep_port_rst = EGR_XQP1_PORT_INT_RESETf;
    191         ep_mmu_rst = EGR_XQP1_MMU_INT_RESETf;
    192         xq_rst2 = XQ1_HOTSWAP_RST_Lf;
    193         break;
    194     case 28:
    195         ep_port_rst = EGR_XQP2_PORT_INT_RESETf;
    196         ep_mmu_rst = EGR_XQP2_MMU_INT_RESETf;
    197         xq_rst2 = XQ2_HOTSWAP_RST_Lf;
    198         break;
    199     case 29:
    200         ep_port_rst = EGR_XQP3_PORT_INT_RESETf;
    201         ep_mmu_rst = EGR_XQP3_MMU_INT_RESETf;
    202         xq_rst2 = XQ3_HOTSWAP_RST_Lf;
    203         break;
    204     }
    205 
    206     /* coverity[result_independent_of_operands] */  
    207     SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(unit, &val2));
    208     soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &val2, 
    209                       xq_rst2, 0);
    210     /* coverity[result_independent_of_operands] */  
    211     SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(unit, val2));
    212     sal_usleep(to_usec);
    213 
    214     /* Clear the ECRC register */
    215     if (SOC_REG_IS_VALID(unit,ECRCr)) {
    216         SOC_IF_ERROR_RETURN(WRITE_ECRCr(unit, port, 0));
    217     } else if (SOC_REG_IS_VALID(unit,EGRESSCELLREQUESTCOUNTr)) {
    218 		SOC_IF_ERROR_RETURN(WRITE_EGRESSCELLREQUESTCOUNTr(unit, port, 0));
    219 	}
    220     /* Reset the EP */
    221     SOC_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &val2));
    222     soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    223                       ep_port_rst, 1);
    224     soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    225                       ep_mmu_rst, 1);
    226     SOC_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, val2));
    227     sal_usleep(to_usec);
    228 
    229     SOC_IF_ERROR_RETURN(READ_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, &val2));
    230     soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    231                       ep_port_rst, 0);
    232     soc_reg_field_set(unit, EDATABUF_XQP_FLEXPORT_CONFIGr, &val2, 
    233                       ep_mmu_rst, 0);
    234     SOC_IF_ERROR_RETURN(WRITE_EDATABUF_XQP_FLEXPORT_CONFIGr(unit, val2));
    235     sal_usleep(to_usec);
    236 
    237     /* Bring the XQPORT block out of reset */
    238     /* coverity[result_independent_of_operands] */  
    239     SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(unit, &val2));
    240     soc_reg_field_set(unit, CMIC_SOFT_RESET_REGr, &val2, 
    241                       xq_rst2, 1);
    242     /* coverity[result_independent_of_operands] */  
    243     SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(unit, val2));
    244     sal_usleep(to_usec);
    245 
    246     /* Bring the hyperlite out of reset */
    247     soc_xgxs_reset(unit, port);
    248     SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XQPORT_XGXS_NEWCTL_REGr, 
    249                                                port, TXD1G_FIFO_RSTBf, 0xf));
    250 
    251     /* Change the XQPORT block mode */
    252     mode = (value == 4) ? 2 : 1; /* 2 = high-speed, 1 = GE */
    253     SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval));
    254     soc_reg_field_set(unit, XQPORT_MODE_REGr, &rval, 
    255                       XQPORT_MODE_BITSf, mode);
    256     SOC_IF_ERROR_RETURN(WRITE_XQPORT_MODE_REGr(unit, port, rval));
    257 
    258     if (value == 4) {
    259         rval = 0;
    260         soc_reg_field_set(unit, XPORT_CONFIGr, &rval, XPORT_ENf, 1);
    261         soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 1);
    262         SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval));
    263     }
    264 
    265     /* Egress Enable */
    266     rval = 0;
    267     soc_reg_field_set(unit, EGR_ENABLEr, &rval, PRT_ENABLEf, 1);
    268     SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, rval));
    269 
    270     /* Step 3: Port probe and initialization */
    271     BCM_IF_ERROR_RETURN(_bcm_port_probe(unit, port, &okay));
    272     if (!okay) {
    273         return BCM_E_INTERNAL;
    274     }
    275 
    276     BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, TRUE));
    277 
    278     if (value == 4) {
    279         /* Need to reset the Bigmac to make registers accessible */
    280         SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macd));
    281         SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &rval64));
    282         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, TXRESETf, 0);
    283         soc_reg64_field32_set(unit, MAC_CTRLr, &rval64, RXRESETf, 0);
    284         SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, rval64));
    285         SOC_IF_ERROR_RETURN(MAC_INIT(macd, unit, port));
    286         BCM_IF_ERROR_RETURN(_bcm_port_mode_setup(unit, port, TRUE));
    287     }
    288 
    289     return rv;
    290 }
    291 #endif