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