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