1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, v.1, (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://opensource.org/licenses/CDDL-1.0. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014-2017 Cavium, Inc. 24 * The contents of this file are subject to the terms of the Common Development 25 * and Distribution License, v.1, (the "License"). 26 27 * You may not use this file except in compliance with the License. 28 29 * You can obtain a copy of the License at available 30 * at http://opensource.org/licenses/CDDL-1.0 31 32 * See the License for the specific language governing permissions and 33 * limitations under the License. 34 */ 35 36 /* 37 * Copyright 2018 Joyent, Inc. 38 */ 39 40 #include "bcm_osal.h" 41 #include "ecore.h" 42 #include "reg_addr.h" 43 #include "ecore_hw.h" 44 #include "ecore_hsi_common.h" 45 #include "ecore_mcp.h" 46 #include "nvm_cfg.h" 47 #include "ecore_phy_api.h" 48 49 #define SERDESID 0x900e 50 51 52 enum _ecore_status_t ecore_phy_read(struct ecore_hwfn *p_hwfn, 53 struct ecore_ptt *p_ptt, u32 port, u32 lane, 54 u32 addr, u32 cmd, u8 *buf) 55 { 56 return ecore_mcp_phy_read(p_hwfn->p_dev, cmd, 57 addr | (lane << 16) | (1<<29) | (port << 30), buf, 8); 58 } 59 60 enum _ecore_status_t ecore_phy_write(struct ecore_hwfn *p_hwfn, 61 struct ecore_ptt *p_ptt, u32 port, 62 u32 lane, u32 addr, u32 data_lo, 63 u32 data_hi, u32 cmd) 64 { 65 u8 buf64[8] = {0}; 66 67 OSAL_MEMCPY(buf64, &data_lo, 4); 68 OSAL_MEMCPY(buf64 + 4, &data_hi, 4); 69 70 return ecore_mcp_phy_write(p_hwfn->p_dev, cmd, 71 addr | (lane << 16) | (1<<29) | (port << 30), 72 buf64, 8); 73 } 74 75 /* phy core write */ 76 int ecore_phy_core_write(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 77 u32 port, u32 addr, u32 data_lo, u32 data_hi, 78 char *p_phy_result_buf) 79 { 80 enum _ecore_status_t rc = ECORE_INVAL; 81 82 if (port > 3) { 83 OSAL_SPRINTF(p_phy_result_buf, 84 "ERROR! Port must be in range of 0..3\n"); 85 return rc; 86 } 87 88 /* write to address */ 89 rc = ecore_phy_write(p_hwfn, p_ptt, port, 0 /* lane */, addr, data_lo, 90 data_hi, ECORE_PHY_CORE_WRITE); 91 if (rc == ECORE_SUCCESS) 92 OSAL_SPRINTF(p_phy_result_buf, "0\n"); 93 else 94 OSAL_SPRINTF(p_phy_result_buf, 95 "Failed placing phy_core command\n"); 96 97 return rc; 98 } 99 100 /* phy core read */ 101 int ecore_phy_core_read(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 102 u32 port, u32 addr, char *p_phy_result_buf) 103 { 104 enum _ecore_status_t rc = ECORE_INVAL; 105 u8 buf64[8] = {0}; 106 u8 data_hi[4]; 107 u8 data_lo[4]; 108 109 if (port > 3) { 110 OSAL_SPRINTF(p_phy_result_buf, 111 "ERROR! Port must be in range of 0..3\n"); 112 return rc; 113 } 114 115 /* read from address */ 116 rc = ecore_phy_read(p_hwfn, p_ptt, port, 0 /* lane */ , addr, 117 ECORE_PHY_CORE_READ, buf64); 118 if (rc == ECORE_SUCCESS) { 119 OSAL_MEMCPY(data_lo, buf64, 4); 120 OSAL_MEMCPY(data_hi, (buf64 + 4), 4); 121 OSAL_SPRINTF(p_phy_result_buf, "0x%08x%08x\n", 122 *(u32 *)data_hi, *(u32 *)data_lo); 123 } 124 else 125 OSAL_SPRINTF(p_phy_result_buf, "Failed placing phy_core command\n"); 126 127 return rc; 128 } 129 130 /* phy raw write */ 131 int ecore_phy_raw_write(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 132 u32 port, u32 lane, u32 addr, u32 data_lo, 133 u32 data_hi, char *p_phy_result_buf) 134 { 135 enum _ecore_status_t rc = ECORE_INVAL; 136 137 /* check if the enterd port is in the range */ 138 if (port > 3) { 139 OSAL_SPRINTF(p_phy_result_buf, 140 "Port must be in range of 0..3\n"); 141 return rc; 142 } 143 144 /* check if the enterd lane is in the range */ 145 if (lane > 6) { 146 OSAL_SPRINTF(p_phy_result_buf, 147 "Lane must be in range of 0..6\n"); 148 return rc; 149 } 150 151 /* write to address*/ 152 rc = ecore_phy_write(p_hwfn,p_ptt, port, lane, addr, data_lo, 153 data_hi, ECORE_PHY_RAW_WRITE); 154 if (rc == ECORE_SUCCESS) 155 OSAL_SPRINTF(p_phy_result_buf, "0\n"); 156 else 157 OSAL_SPRINTF(p_phy_result_buf, 158 "Failed placing phy_core command\n"); 159 160 return rc; 161 } 162 163 /* phy raw read */ 164 int ecore_phy_raw_read(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 165 u32 port, u32 lane, u32 addr, char *p_phy_result_buf) 166 { 167 enum _ecore_status_t rc = ECORE_INVAL; 168 u8 buf64[8] = {0}; 169 u8 data_hi[4]; 170 u8 data_lo[4]; 171 172 /* check if the enterd port is in the range */ 173 if (port > 3) { 174 OSAL_SPRINTF(p_phy_result_buf, 175 "Port must be in range of 0..3\n"); 176 return rc; 177 } 178 179 /* check if the enterd lane is in the range */ 180 if (lane > 6) { 181 OSAL_SPRINTF(p_phy_result_buf, 182 "Lane must be in range of 0..6\n"); 183 return rc; 184 } 185 186 /* read from address */ 187 rc = ecore_phy_read(p_hwfn,p_ptt, port, lane, addr, ECORE_PHY_RAW_READ, 188 buf64); 189 if (rc == ECORE_SUCCESS) { 190 OSAL_MEMCPY(data_lo, buf64, 4); 191 OSAL_MEMCPY(data_hi, (buf64 + 4), 4); 192 OSAL_SPRINTF(p_phy_result_buf, "0x%08x%08x\n", 193 *(u32 *)data_hi, *(u32 *)data_lo); 194 } else { 195 OSAL_SPRINTF(p_phy_result_buf, 196 "Failed placing phy_core command\n"); 197 } 198 199 return rc; 200 } 201 202 static u32 ecore_phy_get_nvm_cfg1_addr(struct ecore_hwfn *p_hwfn, 203 struct ecore_ptt *p_ptt) 204 { 205 u32 nvm_cfg_addr, nvm_cfg1_offset; 206 207 nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt, MISC_REG_GEN_PURP_CR0); 208 nvm_cfg1_offset = ecore_rd(p_hwfn, p_ptt, nvm_cfg_addr + 209 offsetof(struct nvm_cfg, 210 sections_offset[NVM_CFG_SECTION_NVM_CFG1])); 211 return MCP_REG_SCRATCH + nvm_cfg1_offset; 212 } 213 214 /* get phy info */ 215 int ecore_phy_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 216 char *p_phy_result_buf) 217 { 218 u32 nvm_cfg1_addr = ecore_phy_get_nvm_cfg1_addr(p_hwfn, p_ptt); 219 u32 port_mode, port, max_ports, core_cfg, length = 0; 220 enum _ecore_status_t rc = ECORE_INVAL; 221 u8 buf64[8] = {0}; 222 u8 data_hi[4]; 223 u8 data_lo[4]; 224 225 u8 is_bb = ((ecore_rd(p_hwfn, p_ptt, MISCS_REG_CHIP_NUM) & 0x8070) 226 != 0x8070); 227 228 if (is_bb) 229 length += OSAL_SPRINTF(&p_phy_result_buf[length], 230 "Device: BB "); 231 else 232 length += OSAL_SPRINTF(&p_phy_result_buf[length], 233 "Device: AH "); 234 235 core_cfg = ecore_rd(p_hwfn, p_ptt, nvm_cfg1_addr + 236 offsetof(struct nvm_cfg1, glob.core_cfg)); 237 port_mode = (core_cfg & NVM_CFG1_GLOB_NETWORK_PORT_MODE_MASK) >> 238 NVM_CFG1_GLOB_NETWORK_PORT_MODE_OFFSET; 239 switch (port_mode) { 240 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_1X100G: 241 length += OSAL_SPRINTF(&p_phy_result_buf[length], "1x100G\n"); 242 max_ports = 1; 243 break; 244 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X40G: 245 length += OSAL_SPRINTF(&p_phy_result_buf[length], "1x40G\n"); 246 max_ports = 1; 247 break; 248 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_1X25G: 249 length += OSAL_SPRINTF(&p_phy_result_buf[length], "1x25G\n"); 250 max_ports = 1; 251 break; 252 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_2X40G: 253 length += OSAL_SPRINTF(&p_phy_result_buf[length], "2x40G\n"); 254 max_ports = 2; 255 break; 256 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X50G: 257 length += OSAL_SPRINTF(&p_phy_result_buf[length], "2x50G\n"); 258 max_ports = 2; 259 break; 260 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X25G: 261 length += OSAL_SPRINTF(&p_phy_result_buf[length], "2x25G\n"); 262 max_ports = 2; 263 break; 264 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_2X10G: 265 length += OSAL_SPRINTF(&p_phy_result_buf[length], "2x10G\n"); 266 max_ports = 2; 267 break; 268 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X10G_F: 269 length += OSAL_SPRINTF(&p_phy_result_buf[length], "4x10G\n"); 270 max_ports = 4; 271 break; 272 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X10G_E: 273 length += OSAL_SPRINTF(&p_phy_result_buf[length], "4x10G\n"); 274 max_ports = 4; 275 break; 276 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_BB_4X20G: 277 length += OSAL_SPRINTF(&p_phy_result_buf[length], "4x20G\n"); 278 max_ports = 4; 279 break; 280 case NVM_CFG1_GLOB_NETWORK_PORT_MODE_4X25G: 281 length += OSAL_SPRINTF(&p_phy_result_buf[length], "4x25G\n"); 282 max_ports = 4; 283 break; 284 default: 285 length += OSAL_SPRINTF(&p_phy_result_buf[length], 286 "Wrong port mode\n"); 287 return rc; 288 } 289 290 if (is_bb) { 291 for (port = 0; port < max_ports; port++) { 292 rc = ecore_phy_read(p_hwfn, p_ptt, port, 0, SERDESID, 293 DRV_MSG_CODE_PHY_RAW_READ, buf64); 294 if (rc == ECORE_SUCCESS) { 295 length += OSAL_SPRINTF( 296 &p_phy_result_buf[length], 297 "Port %d is in ", port); 298 OSAL_MEMCPY(data_lo, buf64, 4); 299 OSAL_MEMCPY(data_hi, (buf64 + 4), 4); 300 if ((data_lo[0] & 0x3f) == 0x14) 301 length += OSAL_SPRINTF( 302 &p_phy_result_buf[length], 303 "Falcon\n"); 304 else 305 length += OSAL_SPRINTF( 306 &p_phy_result_buf[length], 307 "Eagle\n"); 308 } 309 } 310 } else { 311 /* @@@TMP until ecore_phy_read() on AH is supported */ 312 for (port = 0; port < max_ports; port++) 313 length += OSAL_SPRINTF(&p_phy_result_buf[length], 314 "Port %d is in MPS25\n", port); 315 rc = ECORE_SUCCESS; 316 } 317 318 return rc; 319 } 320 321 struct tsc_stat { 322 u32 reg; 323 char *name; 324 char *desc; 325 }; 326 327 static struct tsc_stat ah_stat_regs[] = { 328 {0x000100, "ETHERSTATSOCTETS ", "total, good and bad"}, 329 /* {0x000104, "ETHERSTATSOCTETS_H ", "total, good and bad"},*/ 330 {0x000108, "OCTETSOK ", "total, good"}, 331 /* {0x00010c, "OCTETSOK_H ", "total, good"}, */ 332 {0x000110, "AALIGNMENTERRORS ", "Wrong SFD detected"}, 333 /* {0x000114, "AALIGNMENTERRORS_H ", "Wrong SFD detected"}, */ 334 {0x000118, "APAUSEMACCTRLFRAMES ", "Good Pause frames received"}, 335 /* {0x00011c, "APAUSEMACCTRLFRAMES_H ", "Good Pause frames received"}, */ 336 {0x000120, "FRAMESOK ", "Good frames received"}, 337 /* {0x000124, "FRAMESOK_H ", "Good frames received"}, */ 338 {0x000128, "CRCERRORS ", "wrong CRC and good length received"}, 339 /* {0x00012c, "CRCERRORS_H ", "wrong CRC and good length received"}, */ 340 {0x000130, "VLANOK ", "Good Frames with VLAN tag received"}, 341 /* {0x000134, "VLANOK_H ", "Good Frames with VLAN tag received"}, */ 342 {0x000138, "IFINERRORS ", "Errored frames received"}, 343 /* {0x00013c, "IFINERRORS_H ", "Errored frames received"}, */ 344 {0x000140, "IFINUCASTPKTS ", "Good Unicast received"}, 345 /* {0x000144, "IFINUCASTPKTS_H ", "Good Unicast received"}, */ 346 {0x000148, "IFINMCASTPKTS ", "Good Multicast received"}, 347 /* {0x00014c, "IFINMCASTPKTS_H ", "Good Multicast received"}, */ 348 {0x000150, "IFINBCASTPKTS ", "Good Broadcast received"}, 349 /* {0x000154, "IFINBCASTPKTS_H ", "Good Broadcast received"}, */ 350 {0x000158, "ETHERSTATSDROPEVENTS ", "Dropped frames"}, 351 /* {0x00015c, "ETHERSTATSDROPEVENTS_H ", "Dropped frames"}, */ 352 {0x000160, "ETHERSTATSPKTS ", "Frames received, good and bad"}, 353 /* {0x000164, "ETHERSTATSPKTS_H ", "Frames received, good and bad"}, */ 354 {0x000168, "ETHERSTATSUNDERSIZEPKTS ", "Frames received less 64 with good crc"}, 355 /* {0x00016c, "ETHERSTATSUNDERSIZEPKTS_H ", "Frames received less 64 with good crc"}, */ 356 {0x000170, "ETHERSTATSPKTS64 ", "Frames of 64 octets received"}, 357 /* {0x000174, "ETHERSTATSPKTS64_H ", "Frames of 64 octets received"}, */ 358 {0x000178, "ETHERSTATSPKTS65TO127 ", "Frames of 65 to 127 octets received"}, 359 /* {0x00017c, "ETHERSTATSPKTS65TO127_H ", "Frames of 65 to 127 octets received"}, */ 360 {0x000180, "ETHERSTATSPKTS128TO255 ", "Frames of 128 to 255 octets received"}, 361 /* {0x000184, "ETHERSTATSPKTS128TO255_H ", "Frames of 128 to 255 octets received"}, */ 362 {0x000188, "ETHERSTATSPKTS256TO511 ", "Frames of 256 to 511 octets received"}, 363 /* {0x00018c, "ETHERSTATSPKTS256TO511_H ", "Frames of 256 to 511 octets received"},*/ 364 {0x000190, "ETHERSTATSPKTS512TO1023 ", "Frames of 512 to 1023 octets received"}, 365 /* {0x000194, "ETHERSTATSPKTS512TO1023_H ", "Frames of 512 to 1023 octets received"},*/ 366 {0x000198, "ETHERSTATSPKTS1024TO1518 ", "Frames of 1024 to 1518 octets received"}, 367 /* {0x00019c, "ETHERSTATSPKTS1024TO1518_H ", "Frames of 1024 to 1518 octets received"},*/ 368 {0x0001a0, "ETHERSTATSPKTS1519TOMAX ", "Frames of 1519 to FRM_LENGTH octets received"}, 369 /* {0x0001a4, "ETHERSTATSPKTS1519TOMAX_H ", "Frames of 1519 to FRM_LENGTH octets received"},*/ 370 {0x0001a8, "ETHERSTATSPKTSOVERSIZE ", "Frames greater FRM_LENGTH and good CRC received"}, 371 /* {0x0001ac, "ETHERSTATSPKTSOVERSIZE_H ", "Frames greater FRM_LENGTH and good CRC received"},*/ 372 {0x0001b0, "ETHERSTATSJABBERS ", "Frames greater FRM_LENGTH and bad CRC received"}, 373 /* {0x0001b4, "ETHERSTATSJABBERS_H ", "Frames greater FRM_LENGTH and bad CRC received"},*/ 374 {0x0001b8, "ETHERSTATSFRAGMENTS ", "Frames less 64 and bad CRC received"}, 375 /* {0x0001bc, "ETHERSTATSFRAGMENTS_H ", "Frames less 64 and bad CRC received"},*/ 376 {0x0001c0, "AMACCONTROLFRAMES ", "Good frames received of type 0x8808 but not Pause"}, 377 /* {0x0001c4, "AMACCONTROLFRAMES_H ", "Good frames received of type 0x8808 but not Pause"},*/ 378 {0x0001c8, "AFRAMETOOLONG ", "Good and bad frames exceeding FRM_LENGTH received"}, 379 /* {0x0001cc, "AFRAMETOOLONG_H ", "Good and bad frames exceeding FRM_LENGTH received"},*/ 380 {0x0001d0, "AINRANGELENGTHERROR ", "Good frames with invalid length field (not supported)"}, 381 /* {0x0001d4, "AINRANGELENGTHERROR_H ", "Good frames with invalid length field (not supported)"},*/ 382 {0x000200, "TXETHERSTATSOCTETS ", "total, good and bad"}, 383 /* {0x000204, "TXETHERSTATSOCTETS_H ", "total, good and bad"},*/ 384 {0x000208, "TXOCTETSOK ", "total, good"}, 385 /* {0x00020c, "TXOCTETSOK_H ", "total, good"},*/ 386 {0x000218, "TXAPAUSEMACCTRLFRAMES ", "Good Pause frames transmitted"}, 387 /* {0x00021c, "TXAPAUSEMACCTRLFRAMES_H ", "Good Pause frames transmitted"},*/ 388 {0x000220, "TXFRAMESOK ", "Good frames transmitted"}, 389 /* {0x000224, "TXFRAMESOK_H ", "Good frames transmitted"},*/ 390 {0x000228, "TXCRCERRORS ", "wrong CRC transmitted"}, 391 /* {0x00022c, "TXCRCERRORS_H ", "wrong CRC transmitted"},*/ 392 {0x000230, "TXVLANOK ", "Good Frames with VLAN tag transmitted"}, 393 /* {0x000234, "TXVLANOK_H ", "Good Frames with VLAN tag transmitted"},*/ 394 {0x000238, "IFOUTERRORS ", "Errored frames transmitted"}, 395 /* {0x00023c, "IFOUTERRORS_H ", "Errored frames transmitted"},*/ 396 {0x000240, "IFOUTUCASTPKTS ", "Good Unicast transmitted"}, 397 /* {0x000244, "IFOUTUCASTPKTS_H ", "Good Unicast transmitted"},*/ 398 {0x000248, "IFOUTMCASTPKTS ", "Good Multicast transmitted"}, 399 /* {0x00024c, "IFOUTMCASTPKTS_H ", "Good Multicast transmitted"},*/ 400 {0x000250, "IFOUTBCASTPKTS ", "Good Broadcast transmitted"}, 401 /* {0x000254, "IFOUTBCASTPKTS_H ", "Good Broadcast transmitted"},*/ 402 {0x000258, "TXETHERSTATSDROPEVENTS ", "Dropped frames (unused, reserved)"}, 403 /* {0x00025c, "TXETHERSTATSDROPEVENTS_H ", "Dropped frames (unused, reserved)"},*/ 404 {0x000260, "TXETHERSTATSPKTS ", "Frames transmitted, good and bad"}, 405 /* {0x000264, "TXETHERSTATSPKTS_H ", "Frames transmitted, good and bad"},*/ 406 {0x000268, "TXETHERSTATSUNDERSIZEPKTS ", "Frames transmitted less 64"}, 407 /* {0x00026c, "TXETHERSTATSUNDERSIZEPKTS_H ", "Frames transmitted less 64"},*/ 408 {0x000270, "TXETHERSTATSPKTS64 ", "Frames of 64 octets transmitted"}, 409 /* {0x000274, "TXETHERSTATSPKTS64_H ", "Frames of 64 octets transmitted"},*/ 410 {0x000278, "TXETHERSTATSPKTS65TO127 ", "Frames of 65 to 127 octets transmitted"}, 411 /* {0x00027c, "TXETHERSTATSPKTS65TO127_H ", "Frames of 65 to 127 octets transmitted"},*/ 412 {0x000280, "TXETHERSTATSPKTS128TO255 ", "Frames of 128 to 255 octets transmitted"}, 413 /* {0x000284, "TXETHERSTATSPKTS128TO255_H ", "Frames of 128 to 255 octets transmitted"},*/ 414 {0x000288, "TXETHERSTATSPKTS256TO511 ", "Frames of 256 to 511 octets transmitted"}, 415 /* {0x00028c, "TXETHERSTATSPKTS256TO511_H ", "Frames of 256 to 511 octets transmitted"},*/ 416 {0x000290, "TXETHERSTATSPKTS512TO1023 ", "Frames of 512 to 1023 octets transmitted"}, 417 /* {0x000294, "TXETHERSTATSPKTS512TO1023_H ", "Frames of 512 to 1023 octets transmitted"},*/ 418 {0x000298, "TXETHERSTATSPKTS1024TO1518 ", "Frames of 1024 to 1518 octets transmitted"}, 419 /* {0x00029c, "TXETHERSTATSPKTS1024TO1518_H ", "Frames of 1024 to 1518 octets transmitted"},*/ 420 {0x0002a0, "TXETHERSTATSPKTS1519TOTX_MTU ", "Frames of 1519 to FRM_LENGTH.TX_MTU octets transmitted"}, 421 /* {0x0002a4, "TXETHERSTATSPKTS1519TOTX_MTU_H ", "Frames of 1519 to FRM_LENGTH.TX_MTU octets transmitted"},*/ 422 {0x0002c0, "TXAMACCONTROLFRAMES ", "Good frames transmitted of type 0x8808 but not Pause"}, 423 /* {0x0002c4, "TXAMACCONTROLFRAMES_H ", "Good frames transmitted of type 0x8808 but not Pause"},*/ 424 {0x000380, "ACBFCPAUSEFRAMESRECEIVED_0 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 425 /* {0x000384, "ACBFCPAUSEFRAMESRECEIVED_0_H ", "Upper 32bit of 64bit counter."},*/ 426 {0x000388, "ACBFCPAUSEFRAMESRECEIVED_1 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 427 /* {0x00038c, "ACBFCPAUSEFRAMESRECEIVED_1_H ", "Upper 32bit of 64bit counter."},*/ 428 {0x000390, "ACBFCPAUSEFRAMESRECEIVED_2 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 429 /* {0x000394, "ACBFCPAUSEFRAMESRECEIVED_2_H ", "Upper 32bit of 64bit counter."},*/ 430 {0x000398, "ACBFCPAUSEFRAMESRECEIVED_3 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 431 /* {0x00039c, "ACBFCPAUSEFRAMESRECEIVED_3_H ", "Upper 32bit of 64bit counter."},*/ 432 {0x0003a0, "ACBFCPAUSEFRAMESRECEIVED_4 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 433 /* {0x0003a4, "ACBFCPAUSEFRAMESRECEIVED_4_H ", "Upper 32bit of 64bit counter."},*/ 434 {0x0003a8, "ACBFCPAUSEFRAMESRECEIVED_5 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 435 /* {0x0003ac, "ACBFCPAUSEFRAMESRECEIVED_5_H ", "Upper 32bit of 64bit counter."},*/ 436 {0x0003b0, "ACBFCPAUSEFRAMESRECEIVED_6 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 437 /* {0x0003b4, "ACBFCPAUSEFRAMESRECEIVED_6_H ", "Upper 32bit of 64bit counter."},*/ 438 {0x0003b8, "ACBFCPAUSEFRAMESRECEIVED_7 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames received for each class."}, 439 /* {0x0003bc, "ACBFCPAUSEFRAMESRECEIVED_7_H ", "Upper 32bit of 64bit counter."},*/ 440 {0x0003c0, "ACBFCPAUSEFRAMESTRANSMITTED_0 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 441 /* {0x0003c4, "ACBFCPAUSEFRAMESTRANSMITTED_0_H", "Upper 32bit of 64bit counter."},*/ 442 {0x0003c8, "ACBFCPAUSEFRAMESTRANSMITTED_1 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 443 /* {0x0003cc, "ACBFCPAUSEFRAMESTRANSMITTED_1_H", "Upper 32bit of 64bit counter."},*/ 444 {0x0003d0, "ACBFCPAUSEFRAMESTRANSMITTED_2 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 445 /* {0x0003d4, "ACBFCPAUSEFRAMESTRANSMITTED_2_H", "Upper 32bit of 64bit counter."},*/ 446 {0x0003d8, "ACBFCPAUSEFRAMESTRANSMITTED_3 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 447 /* {0x0003dc, "ACBFCPAUSEFRAMESTRANSMITTED_3_H", "Upper 32bit of 64bit counter."},*/ 448 {0x0003e0, "ACBFCPAUSEFRAMESTRANSMITTED_4 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 449 /* {0x0003e4, "ACBFCPAUSEFRAMESTRANSMITTED_4_H", "Upper 32bit of 64bit counter."},*/ 450 {0x0003e8, "ACBFCPAUSEFRAMESTRANSMITTED_5 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 451 /* {0x0003ec, "ACBFCPAUSEFRAMESTRANSMITTED_5_H", "Upper 32bit of 64bit counter."},*/ 452 {0x0003f0, "ACBFCPAUSEFRAMESTRANSMITTED_6 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 453 /* {0x0003f4, "ACBFCPAUSEFRAMESTRANSMITTED_6_H", "Upper 32bit of 64bit counter."},*/ 454 {0x0003f8, "ACBFCPAUSEFRAMESTRANSMITTED_7 ", "Set of 8 objects recording the number of CBFC (Class Based Flow Control) pause frames transmitted for each class."}, 455 /* {0x0003fc, "ACBFCPAUSEFRAMESTRANSMITTED_7_H", "Upper 32bit of 64bit counter."}*/ 456 }; 457 static struct tsc_stat bb_stat_regs[] = { 458 {0x00000000, "GRX64","RX 64-byte frame counter" }, 459 {0x00000001, "GRX127","RX 65 to 127 byte frame counter" }, 460 {0x00000002, "GRX255","RX 128 to 255 byte frame counter" }, 461 {0x00000003, "GRX511","RX 256 to 511 byte frame counter" }, 462 {0x00000004, "GRX1023","RX 512 to 1023 byte frame counter" }, 463 {0x00000005, "GRX1518","RX 1024 to 1518 byte frame counter" }, 464 {0x00000006, "GRX1522","RX 1519 to 1522 byte VLAN-tagged frame counter" }, 465 {0x00000007, "GRX2047","RX 1519 to 2047 byte frame counter" }, 466 {0x00000008, "GRX4095","RX 2048 to 4095 byte frame counter" }, 467 {0x00000009, "GRX9216","RX 4096 to 9216 byte frame counter" }, 468 {0x0000000a, "GRX16383","RX 9217 to 16383 byte frame counter" }, 469 {0x0000000b, "GRXPKT","RX frame counter (all packets)" }, 470 {0x0000000c, "GRXUCA","RX UC frame counter" }, 471 {0x0000000d, "GRXMCA","RX MC frame counter" }, 472 {0x0000000e, "GRXBCA","RX BC frame counter" }, 473 {0x0000000f, "GRXFCS","RX FCS error frame counter" }, 474 {0x00000010, "GRXCF","RX control frame counter" }, 475 {0x00000011, "GRXPF","RX pause frame counter" }, 476 {0x00000012, "GRXPP","RX PFC frame counter" }, 477 {0x00000013, "GRXUO","RX unsupported opcode frame counter" }, 478 {0x00000014, "GRXUDA","RX unsupported DA for pause/PFC frame counter" }, 479 {0x00000015, "GRXWSA","RX incorrect SA counter" }, 480 {0x00000016, "GRXALN","RX alignment error counter" }, 481 {0x00000017, "GRXFLR","RX out-of-range length frame counter" }, 482 {0x00000018, "GRXFRERR","RX code error frame counter" }, 483 {0x00000019, "GRXFCR","RX false carrier counter" }, 484 {0x0000001a, "GRXOVR","RX oversized frame counter" }, 485 {0x0000001b, "GRXJBR","RX jabber frame counter" }, 486 {0x0000001c, "GRXMTUE","RX MTU check error frame counter" }, 487 {0x0000001d, "GRXMCRC", 488 "RX packet with 4-Byte CRC matching MACSEC_PROG_TX_CRC." }, 489 {0x0000001e, "GRXPRM","RX promiscuous packet counter" }, 490 {0x0000001f, "GRXVLN","RX single and double VLAN tagged frame counter" }, 491 {0x00000020, "GRXDVLN","RX double VLANG tagged frame counter" }, 492 {0x00000021, "GRXTRFU","RX truncated frame (due to RX FIFO full) counter" }, 493 {0x00000022, "GRXPOK","RX good frame (good CRC, not oversized, no ERROR)" }, 494 {0x00000023, "GRXPFCOFF0", 495 "RX PFC frame transition XON to XOFF for Priority0" }, 496 {0x00000024, "GRXPFCOFF1", 497 "RX PFC frame transition XON to XOFF for Priority1" }, 498 {0x00000025, "GRXPFCOFF2", 499 "RX PFC frame transition XON to XOFF for Priority2" }, 500 {0x00000026, "GRXPFCOFF3", 501 "RX PFC frame transition XON to XOFF for Priority3" }, 502 {0x00000027, "GRXPFCOFF4", 503 "RX PFC frame transition XON to XOFF for Priority4" }, 504 {0x00000028, "GRXPFCOFF5", 505 "RX PFC frame transition XON to XOFF for Priority5" }, 506 {0x00000029, "GRXPFCOFF6", 507 "RX PFC frame transition XON to XOFF for Priority6" }, 508 {0x0000002a, "GRXPFCOFF7", 509 "RX PFC frame transition XON to XOFF for Priority7" }, 510 {0x0000002b, "GRXPFCP0","RX PFC frame with enable bit set for Priority0" }, 511 {0x0000002c, "GRXPFCP1","RX PFC frame with enable bit set for Priority1" }, 512 {0x0000002d, "GRXPFCP2","RX PFC frame with enable bit set for Priority2" }, 513 {0x0000002e, "GRXPFCP3","RX PFC frame with enable bit set for Priority3" }, 514 {0x0000002f, "GRXPFCP4","RX PFC frame with enable bit set for Priority4" }, 515 {0x00000030, "GRXPFCP5","RX PFC frame with enable bit set for Priority5" }, 516 {0x00000031, "GRXPFCP6","RX PFC frame with enable bit set for Priority6" }, 517 {0x00000032, "GRXPFCP7","RX PFC frame with enable bit set for Priority7" }, 518 {0x00000033, "GRXSCHCRC","RX frame with SCH CRC error. For LH mode only" }, 519 {0x00000034, "GRXUND","RX undersized frame counter" }, 520 {0x00000035, "GRXFRG","RX fragment counter" }, 521 {0x00000036, "RXEEELPI", "RX EEE LPI counter"}, 522 {0x00000037, "RXEEELPIDU", "RX EEE LPI duration counter"}, 523 {0x00000038, "RXLLFCPHY", "RX LLFC PHY COUNTER"}, 524 {0x00000039, "RXLLFCLOG", "RX LLFC LOG COUNTER"}, 525 {0x0000003a, "RXLLFCCRC", "RX LLFC CRC COUNTER"}, 526 {0x0000003b, "RXHCFC", "RX HCFC COUNTER"}, 527 {0x0000003c, "RXHCFCCRC", "RX HCFC CRC COUNTER"}, 528 {0x0000003d, "GRXBYT", "RX byte counter"}, 529 {0x0000003e, "GRXRBYT", "RX runt byte counter"}, 530 {0x0000003f, "GRXRPKT", "RX packet counter"}, 531 {0x00000040, "GTX64", "TX 64-byte frame counter"}, 532 {0x00000041, "GTX127", "TX 65 to 127 byte frame counter"}, 533 {0x00000042, "GTX255", "TX 128 to 255 byte frame counter"}, 534 {0x00000043, "GTX511", "TX 256 to 511 byte frame counter"}, 535 {0x00000044, "GTX1023", "TX 512 to 1023 byte frame counter"}, 536 {0x00000045, "GTX1518", "TX 1024 to 1518 byte frame counter"}, 537 {0x00000046, "GTX1522", "TX 1519 to 1522 byte VLAN-tagged frame counter"}, 538 {0x00000047, "GTX2047", "TX 1519 to 2047 byte frame counter"}, 539 {0x00000048, "GTX4095", "TX 2048 to 4095 byte frame counte"}, 540 {0x00000049, "GTX9216", "TX 4096 to 9216 byte frame counter"}, 541 {0x0000004a, "GTX16383", "TX 9217 to 16383 byte frame counter"}, 542 {0x0000004b, "GTXPOK", "TX good frame counter"}, 543 {0x0000004c, "GTXPKT", "TX frame counter (all packets"}, 544 {0x0000004d, "GTXUCA", "TX UC frame counter"}, 545 {0x0000004e, "GTXMCA", "TX MC frame counter"}, 546 {0x0000004f, "GTXBCA", "TX BC frame counter"}, 547 {0x00000050, "GTXPF", "TX pause frame counter"}, 548 {0x00000051, "GTXPP", "TX PFC frame counter"}, 549 {0x00000052, "GTXJBR", "TX jabber counter"}, 550 {0x00000053, "GTXFCS", "TX FCS error counter"}, 551 {0x00000054, "GTXCF", "TX control frame counter"}, 552 {0x00000055, "GTXOVR", "TX oversize packet counter"}, 553 {0x00000056, "GTXDFR", "TX Single Deferral Frame Counter"}, 554 {0x00000057, "GTXEDF", "TX Multiple Deferral Frame Counter"}, 555 {0x00000058, "GTXSCL", "TX Single Collision Frame Counter"}, 556 {0x00000059, "GTXMCL", "TX Multiple Collision Frame Counter"}, 557 {0x0000005a, "GTXLCL", "TX Late Collision Frame Counter"}, 558 {0x0000005b, "GTXXCL", "TX Excessive Collision Frame Counter"}, 559 {0x0000005c, "GTXFRG", "TX fragment counter"}, 560 {0x0000005d, "GTXERR", "TX error (set by system) frame counter"}, 561 {0x0000005e, "GTXVLN", "TX VLAN Tag Frame Counter"}, 562 {0x0000005f, "GTXDVLN", "TX Double VLAN Tag Frame Counter"}, 563 {0x00000060, "GTXRPKT", "TX RUNT Frame Counter"}, 564 {0x00000061, "GTXUFL", "TX FIFO Underrun Counter"}, 565 {0x00000062, "GTXPFCP0", "TX PFC frame with enable bit set for Priority0"}, 566 {0x00000063, "GTXPFCP1", "TX PFC frame with enable bit set for Priority1"}, 567 {0x00000064, "GTXPFCP2", "TX PFC frame with enable bit set for Priority2"}, 568 {0x00000065, "GTXPFCP3", "TX PFC frame with enable bit set for Priority3"}, 569 {0x00000066, "GTXPFCP4", "TX PFC frame with enable bit set for Priority4"}, 570 {0x00000067, "GTXPFCP5", "TX PFC frame with enable bit set for Priority5"}, 571 {0x00000068, "GTXPFCP6", "TX PFC frame with enable bit set for Priority6"}, 572 {0x00000069, "GTXPFCP7", "TX PFC frame with enable bit set for Priority7"}, 573 {0x0000006a, "TXEEELPI", "TX EEE LPI Event Counter"}, 574 {0x0000006b, "TXEEELPIDU", "TX EEE LPI Duration Counter"}, 575 {0x0000006c, "TXLLFCLOG", "Transmit Logical Type LLFC message counter"}, 576 {0x0000006d, "TXHCFC", "Transmit Logical Type LLFC message counter"}, 577 {0x0000006e, "GTXNCL", "Transmit Total Collision Counter"}, 578 {0x0000006f, "GTXBYT", "TX byte counter"} 579 }; 580 581 /* get mac status */ 582 static int ecore_bb_phy_mac_stat(struct ecore_hwfn *p_hwfn, 583 struct ecore_ptt *p_ptt, 584 u32 port, char *p_phy_result_buf) 585 { 586 u8 buf64[8] = {0}, data_hi[4], data_lo[4]; 587 bool b_false_alarm = false; 588 u32 length, reg_id, addr; 589 enum _ecore_status_t rc = ECORE_INVAL; 590 591 length = OSAL_SPRINTF(p_phy_result_buf, 592 "MAC stats for port %d (only non-zero)\n", port); 593 594 for (reg_id = 0; reg_id < OSAL_ARRAY_SIZE(bb_stat_regs); reg_id++) { 595 addr = bb_stat_regs[reg_id].reg; 596 rc = ecore_phy_read(p_hwfn, p_ptt, port, 0 /*lane*/, addr, 597 ECORE_PHY_CORE_READ, buf64); 598 599 OSAL_MEMCPY(data_lo, buf64, 4); 600 OSAL_MEMCPY(data_hi, (buf64 + 4), 4); 601 602 if (rc == ECORE_SUCCESS) { 603 if (*(u32 *)data_lo != 0) { /* Only non-zero */ 604 length += OSAL_SPRINTF(&p_phy_result_buf[length], 605 "%-10s: 0x%08x (%s)\n", 606 bb_stat_regs[reg_id].name, 607 *(u32 *)data_lo, 608 bb_stat_regs[reg_id].desc); 609 if ((bb_stat_regs[reg_id].reg == 0x0000000f) || 610 (bb_stat_regs[reg_id].reg == 0x00000018) || 611 (bb_stat_regs[reg_id].reg == 0x00000035)) 612 b_false_alarm = true; 613 } 614 } else { 615 OSAL_SPRINTF(p_phy_result_buf, "Failed reading stat 0x%x\n\n", 616 addr); 617 } 618 } 619 620 if (b_false_alarm) 621 length += OSAL_SPRINTF(&p_phy_result_buf[length], 622 "Note: GRXFCS/GRXFRERR/GRXFRG may " 623 "increment when the port shuts down\n"); 624 625 return rc; 626 } 627 628 /* get mac status */ 629 static int ecore_ah_e5_phy_mac_stat(struct ecore_hwfn *p_hwfn, 630 struct ecore_ptt *p_ptt, u32 port, 631 char *p_phy_result_buf) 632 { 633 u32 length, reg_id, addr, data_hi __unused, data_lo; 634 635 length = OSAL_SPRINTF(p_phy_result_buf, 636 "MAC stats for port %d (only non-zero)\n", port); 637 638 for (reg_id = 0; reg_id < OSAL_ARRAY_SIZE(ah_stat_regs); reg_id++) { 639 addr = ah_stat_regs[reg_id].reg; 640 data_lo = ecore_rd(p_hwfn, p_ptt, 641 NWM_REG_MAC0_K2_E5 + 642 NWM_REG_MAC0_SIZE * 4 * port + 643 addr); 644 data_hi = ecore_rd(p_hwfn, p_ptt, 645 NWM_REG_MAC0_K2_E5 + 646 NWM_REG_MAC0_SIZE * 4 * port + 647 addr + 4); 648 649 if (data_lo) { /* Only non-zero */ 650 length += OSAL_SPRINTF(&p_phy_result_buf[length], 651 "%-10s: 0x%08x (%s)\n", 652 ah_stat_regs[reg_id].name, 653 data_lo, 654 ah_stat_regs[reg_id].desc); 655 } 656 } 657 658 return ECORE_SUCCESS; 659 } 660 661 int ecore_phy_mac_stat(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 662 u32 port, char *p_phy_result_buf) 663 { 664 int num_ports = ecore_device_num_ports(p_hwfn->p_dev); 665 666 if (port >= (u32)num_ports) { 667 OSAL_SPRINTF(p_phy_result_buf, 668 "Port must be in range of 0..%d\n", num_ports); 669 return ECORE_INVAL; 670 } 671 672 if (ECORE_IS_BB(p_hwfn->p_dev)) 673 return ecore_bb_phy_mac_stat(p_hwfn, p_ptt, port, 674 p_phy_result_buf); 675 else 676 return ecore_ah_e5_phy_mac_stat(p_hwfn, p_ptt, port, 677 p_phy_result_buf); 678 } 679 680 #define SFP_RX_LOS_OFFSET 110 681 #define SFP_TX_DISABLE_OFFSET 110 682 #define SFP_TX_FAULT_OFFSET 110 683 684 #define QSFP_RX_LOS_OFFSET 3 685 #define QSFP_TX_DISABLE_OFFSET 86 686 #define QSFP_TX_FAULT_OFFSET 4 687 688 /* Set SFP error string */ 689 static int ecore_sfp_set_error(enum _ecore_status_t rc, u32 offset, 690 char *p_phy_result_buf, char *p_err_str) 691 { 692 if (rc != ECORE_SUCCESS) { 693 if (rc == ECORE_NODEV) 694 OSAL_SPRINTF((char *)&p_phy_result_buf[offset], 695 "Transceiver is unplugged.\n"); 696 else 697 OSAL_SPRINTF((char *)&p_phy_result_buf[offset], "%s", 698 p_err_str); 699 700 return ECORE_UNKNOWN_ERROR; 701 } 702 703 return rc; 704 } 705 706 /* Validate SFP port */ 707 static int ecore_validate_sfp_port(struct ecore_hwfn *p_hwfn, 708 struct ecore_ptt *p_ptt, 709 u32 port, char *p_phy_result_buf) 710 { 711 /* Verify <port> field is between 0 and number of ports */ 712 u32 num_ports = ecore_device_num_ports(p_hwfn->p_dev); 713 714 if (port >= num_ports) { 715 if (num_ports == 1) 716 OSAL_SPRINTF(p_phy_result_buf, 717 "Bad port number, must be 0.\n"); 718 else 719 OSAL_SPRINTF(p_phy_result_buf, 720 "Bad port number, must be between 0 and %d.\n", 721 num_ports-1); 722 723 return ECORE_INVAL; 724 } 725 726 return ECORE_SUCCESS; 727 } 728 729 /* Validate SFP parameters */ 730 static int ecore_validate_sfp_parameters(struct ecore_hwfn *p_hwfn, 731 struct ecore_ptt *p_ptt, 732 u32 port, u32 addr, u32 offset, 733 u32 size, char *p_phy_result_buf) 734 { 735 enum _ecore_status_t rc; 736 737 /* Verify <port> field is between 0 and number of ports */ 738 rc = ecore_validate_sfp_port(p_hwfn, p_ptt, port, p_phy_result_buf); 739 if (rc != ECORE_SUCCESS) 740 return rc; 741 742 /* Verify <I2C> field is 0xA0 or 0xA2 */ 743 if ((addr != 0xA0) && (addr != 0xA2)) { 744 OSAL_SPRINTF(p_phy_result_buf, 745 "Bad I2C address, must be 0xA0 or 0xA2.\n"); 746 return ECORE_INVAL; 747 } 748 749 /* Verify <size> field is 1 - MAX_I2C_TRANSCEIVER_PAGE_SIZE */ 750 if ((size == 0) || (size > MAX_I2C_TRANSCEIVER_PAGE_SIZE)) { 751 OSAL_SPRINTF(p_phy_result_buf, 752 "Bad size, must be between 1 and %d.\n", 753 MAX_I2C_TRANSCEIVER_PAGE_SIZE); 754 return ECORE_INVAL; 755 } 756 757 /* Verify <offset> + <size> <= MAX_I2C_TRANSCEIVER_PAGE_SIZE */ 758 if (offset + size > MAX_I2C_TRANSCEIVER_PAGE_SIZE) { 759 OSAL_SPRINTF(p_phy_result_buf, 760 "Bad offset and size, must not exceed %d.\n", 761 MAX_I2C_TRANSCEIVER_PAGE_SIZE); 762 return ECORE_INVAL; 763 } 764 765 return rc; 766 } 767 768 /* Write to SFP */ 769 int ecore_phy_sfp_write(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 770 u32 port, u32 addr, u32 offset, u32 size, 771 u32 val, char *p_phy_result_buf) 772 { 773 enum _ecore_status_t rc; 774 775 rc = ecore_validate_sfp_parameters(p_hwfn, p_ptt, port, addr, 776 offset, size, p_phy_result_buf); 777 if (rc == ECORE_SUCCESS) 778 { 779 rc = ecore_mcp_phy_sfp_write(p_hwfn, p_ptt, port, addr, 780 offset, size, (u8 *)&val); 781 782 if (rc != ECORE_SUCCESS) 783 return ecore_sfp_set_error(rc, 0, p_phy_result_buf, 784 "Error writing to transceiver.\n"); 785 786 OSAL_SPRINTF(p_phy_result_buf, 787 "Written successfully to transceiver.\n"); 788 } 789 790 return rc; 791 } 792 793 /* Read from SFP */ 794 int ecore_phy_sfp_read(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 795 u32 port, u32 addr, u32 offset, 796 u32 size, char *p_phy_result_buf) 797 { 798 enum _ecore_status_t rc; 799 u32 i; 800 801 rc = ecore_validate_sfp_parameters(p_hwfn, p_ptt, port, addr, 802 offset, size, p_phy_result_buf); 803 if (rc == ECORE_SUCCESS) 804 { 805 int length = 0; 806 u8 buf[MAX_I2C_TRANSCEIVER_PAGE_SIZE]; 807 808 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, addr, 809 offset, size, buf); 810 if (rc != ECORE_SUCCESS) 811 return ecore_sfp_set_error(rc, 0, p_phy_result_buf, 812 "Error reading from transceiver.\n"); 813 for (i = 0; i < size; i++) 814 length += OSAL_SPRINTF( 815 (char *)&p_phy_result_buf[length], 816 "%02x ", buf[i]); 817 } 818 819 return rc; 820 } 821 822 static enum _ecore_status_t ecore_decode_sfp_info(struct ecore_hwfn *p_hwfn, 823 struct ecore_ptt *p_ptt, 824 u32 port, u32 length, 825 char *p_phy_result_buf) 826 { 827 /* SFP EEPROM contents are described in SFF-8024 and SFF-8472 */ 828 /***********************************************/ 829 /* SFP DATA and locations */ 830 /* get specification complianace bytes 3-10 */ 831 /* get signal rate byte 12 */ 832 /* get extended compliance code byte 36 */ 833 /* get vendor length bytes 14-19 */ 834 /* get vendor name bytes bytes 20-35 */ 835 /* get vendor OUI bytes 37-39 */ 836 /* get vendor PN bytes 40-55 */ 837 /* get vendor REV bytes 56-59 */ 838 /* validated */ 839 /***********************************************/ 840 enum _ecore_status_t rc; 841 u8 buf[32]; 842 843 /* Read byte 12 - signal rate, and if nothing matches */ 844 /* check byte 8 for 10G copper */ 845 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 846 12, 1, buf); 847 if (rc != ECORE_SUCCESS) 848 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 849 "Error reading specification compliance field.\n"); 850 851 length += OSAL_SPRINTF(&p_phy_result_buf[length], 852 "BYTE 12 signal rate: %d\n", buf[0]); 853 854 if (buf[0] >= 250) { 855 length += OSAL_SPRINTF(&p_phy_result_buf[length], 856 "25G signal rate: %d\n", buf[0]); 857 /* 25G - This should be copper - could double check */ 858 /* Read byte 3 - optics, and if nothing matches */ 859 /* check byte 8 for 10G copper */ 860 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 861 I2C_TRANSCEIVER_ADDR, 3, 1, buf); 862 if (rc != ECORE_SUCCESS) 863 return ecore_sfp_set_error(rc, length, 864 p_phy_result_buf, 865 "Error reading optics field.\n"); 866 867 switch (buf[0]) { 868 case 1: 869 length += OSAL_SPRINTF(&p_phy_result_buf[length], 870 "25G Passive copper detected\n"); 871 break; 872 case 2: 873 length += OSAL_SPRINTF(&p_phy_result_buf[length], 874 "25G Active copper detected\n"); 875 break; 876 default: 877 length += OSAL_SPRINTF(&p_phy_result_buf[length], 878 "UNKNOWN 25G cable detected: %x\n", 879 buf[0]); 880 break; 881 } 882 883 } else if (buf[3] >= 100) { 884 length += OSAL_SPRINTF(&p_phy_result_buf[length], 885 "10G signal rate: %d\n", buf[0]); 886 /* 10G - Read byte 3 for optics and byte 8 for copper, and */ 887 /* byte 2 for AOC */ 888 /* Read byte 3 - optics, and if nothing matches check byte */ 889 /* 8 for 10G copper */ 890 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 891 I2C_TRANSCEIVER_ADDR, 3, 1, buf); 892 if (rc != ECORE_SUCCESS) 893 return ecore_sfp_set_error(rc, length, 894 p_phy_result_buf, 895 "Error reading optics field.\n"); 896 897 switch (buf[0]) { 898 case 0x10: 899 /* 10G SR */ 900 length += OSAL_SPRINTF(&p_phy_result_buf[length], 901 "10G SR detected\n"); 902 break; 903 case 0x20: 904 /* 10G LR */ 905 length += OSAL_SPRINTF(&p_phy_result_buf[length], 906 "10G LR detected\n"); 907 break; 908 case 0x40: 909 /* 10G LRM */ 910 length += OSAL_SPRINTF(&p_phy_result_buf[length], 911 "10G LRM detected\n"); 912 break; 913 case 0x80: 914 length += OSAL_SPRINTF(&p_phy_result_buf[length], 915 "10G ER detected\n"); 916 break; 917 default: 918 length += OSAL_SPRINTF(&p_phy_result_buf[length], 919 "SFP/SFP+/SFP-28 transceiver type 0x%x not known... Check for 10G copper.\n", 920 buf[0]); 921 /* Read 3, check 8 too */ 922 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 923 I2C_TRANSCEIVER_ADDR, 924 8, 1, buf); 925 if (rc != ECORE_SUCCESS) 926 return ecore_sfp_set_error(rc, length, 927 p_phy_result_buf, 928 "Error reading 10G copper field.\n"); 929 930 switch (buf[0]) { 931 case 0x04: 932 case 0x84: 933 length += OSAL_SPRINTF( 934 &p_phy_result_buf[length], 935 "10G Passive copper detected\n"); 936 break; 937 case 0x08: 938 case 0x88: 939 length += OSAL_SPRINTF( 940 &p_phy_result_buf[length], 941 "10G Active copper detected\n"); 942 break; 943 default: 944 length += OSAL_SPRINTF( 945 &p_phy_result_buf[length], 946 "Unexpected SFP/SFP+/SFP-28 transceiver type 0x%x\n", 947 buf[3]); 948 break; 949 } /* switch byte 8 */ 950 951 } /* switch byte 3 */ 952 953 } else if (buf[0] >= 10) { 954 length += OSAL_SPRINTF(&p_phy_result_buf[length], 955 "1G signal rate: %d\n", buf[3]); 956 /* 1G - Read byte 6 for optics and byte 8 for copper */ 957 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 958 I2C_TRANSCEIVER_ADDR, 6, 1, buf); 959 if (rc != ECORE_SUCCESS) 960 return ecore_sfp_set_error(rc, length, 961 p_phy_result_buf, 962 "Error reading optics field.\n"); 963 964 switch (buf[0]) { 965 case 1: 966 length += OSAL_SPRINTF(&p_phy_result_buf[length], 967 "1G SX detected\n"); 968 break; 969 case 2: 970 length += OSAL_SPRINTF(&p_phy_result_buf[length], 971 "1G LX detected\n"); 972 break; 973 default: 974 length += OSAL_SPRINTF(&p_phy_result_buf[length], 975 "Assume 1G Passive copper detected\n"); 976 break; 977 } 978 } 979 980 /* get vendor length bytes 14-19 */ 981 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 982 14, 6, buf); 983 if (rc != ECORE_SUCCESS) 984 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 985 "Error reading vendor length bytes.\n"); 986 987 length += OSAL_SPRINTF(&p_phy_result_buf[length], 988 "Length (SMF, km) 0x%x\n", buf[0]); 989 length += OSAL_SPRINTF(&p_phy_result_buf[length], 990 "Length (SMF) 0x%x\n", buf[1]); 991 length += OSAL_SPRINTF(&p_phy_result_buf[length], 992 "Length (50 um) 0x%x\n", buf[2]); 993 length += OSAL_SPRINTF(&p_phy_result_buf[length], 994 "Length (62.5 um) 0x%x\n", buf[3]); 995 length += OSAL_SPRINTF(&p_phy_result_buf[length], 996 "Length (OM4 or copper cable) 0x%x\n", buf[4]); 997 length += OSAL_SPRINTF(&p_phy_result_buf[length], 998 "Length (OM3) 0x%x\n", buf[5]); 999 1000 /* get vendor name bytes bytes 20-35 */ 1001 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1002 20, 16, buf); 1003 if (rc != ECORE_SUCCESS) 1004 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1005 "Error reading vendor name.\n"); 1006 1007 buf[16] = 0; 1008 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1009 "Vendor name: %s\n", buf); 1010 1011 /* get vendor OUI bytes 37-39 */ 1012 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1013 37, 3, buf); 1014 if (rc != ECORE_SUCCESS) 1015 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1016 "Error reading vendor OUI.\n"); 1017 1018 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1019 "Vendor OUI: %02x%02x%02x\n", 1020 buf[0], buf[1], buf[2]); 1021 1022 /* get vendor PN bytes 40-55 */ 1023 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1024 40, 16, buf); 1025 if (rc != ECORE_SUCCESS) 1026 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1027 "Error reading vendor PN.\n"); 1028 1029 buf[16] = 0; 1030 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1031 "Vendor PN: %s\n", buf); 1032 1033 /* get vendor REV bytes 56-59 */ 1034 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1035 56, 4, buf); 1036 if (rc != ECORE_SUCCESS) 1037 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1038 "Error reading vendor rev.\n"); 1039 1040 buf[4] = 0; 1041 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1042 "Vendor rev: %s\n", buf); 1043 1044 return rc; 1045 } 1046 1047 static enum _ecore_status_t ecore_decode_qsfp_info(struct ecore_hwfn *p_hwfn, 1048 struct ecore_ptt *p_ptt, 1049 u32 port, u32 length, 1050 char *p_phy_result_buf) 1051 { 1052 /* QSFP EEPROM contents are described in SFF-8024 and SFF-8636 */ 1053 /***********************************************/ 1054 /* QSFP DATA and locations */ 1055 /* get specification complianace bytes 131-138 */ 1056 /* get extended rate select bytes 141 */ 1057 /* get vendor length bytes 142-146 */ 1058 /* get device technology byte 147 */ 1059 /* get vendor name bytes bytes 148-163 */ 1060 /* get vendor OUI bytes 165-167 */ 1061 /* get vendor PN bytes 168-183 */ 1062 /* get vendor REV bytes 184-185 */ 1063 /* validated */ 1064 /***********************************************/ 1065 enum _ecore_status_t rc; 1066 u8 buf[32]; 1067 1068 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1069 131, 1, buf); 1070 if (rc != ECORE_SUCCESS) 1071 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1072 "Error reading transceiver compliance code.\n"); 1073 1074 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1075 "Transceiver compliance code 0x%x\n", buf[0]); 1076 1077 switch (buf[0]) { 1078 case 0x1: 1079 /* 40G Active (XLPPI) */ 1080 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1081 "40G Active (XLPPI) detected.\n"); 1082 break; 1083 case 0x2: 1084 /* 40G LR-4 */ 1085 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1086 "40G LR-4 detected.\n"); 1087 break; 1088 case 0x4: 1089 /* 40G SR-4 */ 1090 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1091 "40G SR-4 detected.\n"); 1092 break; 1093 case 0x8: 1094 /* 40G CR-4 */ 1095 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1096 "40G CR-4 detected.\n"); 1097 break; 1098 case 0x10: 1099 /* 10G SR */ 1100 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1101 "10G SR detected.\n"); 1102 break; 1103 case 0x20: 1104 /* 10G LR */ 1105 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1106 "10G LR detected.\n"); 1107 break; 1108 case 0x40: 1109 /* 10G LRM */ 1110 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1111 "10G LRM detected.\n"); 1112 break; 1113 case 0x88: /* Could be 40G/100G CR4 cable, check 192 for 100G CR4 */ 1114 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1115 "Multi-rate transceiver: 40G CR-4 detected...\n"); 1116 break; 1117 case 0x80: 1118 /* Use extended technology field */ 1119 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1120 "Use extended technology field\n"); 1121 /* Byte 93 & 129 is supposed to have power info. During */ 1122 /* testing all reads 0. Ignore for now */ 1123 /* 0-127 is in the first page this in high region - */ 1124 /* see what page it is. */ 1125 /* buf[3] = 0; */ 1126 /* ret_val = read_transceiver_data(g_port, i2c_addr, 129, */ 1127 /* buf, 1); */ 1128 /* length += OSAL_SPRINTF(&p_phy_result_buf[length], */ 1129 /* "Read transceiver power data. Value read: 0x%hx\n\n", */ 1130 /* buf[3]); */ 1131 1132 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1133 I2C_TRANSCEIVER_ADDR, 192, 1, buf); 1134 if (rc != ECORE_SUCCESS) 1135 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1136 "Error reading technology compliance field.\n"); 1137 1138 switch (buf[0]) { 1139 case 0: 1140 /* Unspecified */ 1141 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1142 "Unspecified detected.\n"); 1143 break; 1144 case 0x1: 1145 /* 100G AOC (active optical cable) */ 1146 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1147 "100G AOC (active optical cable) detected\n"); 1148 break; 1149 case 0x2: 1150 /* 100G SR-4 */ 1151 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1152 "100G SR-4 detected\n"); 1153 break; 1154 case 0x3: 1155 /* 100G LR-4 */ 1156 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1157 "100G LR-4 detected\n"); 1158 break; 1159 case 0x4: 1160 /* 100G ER-4 */ 1161 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1162 "100G ER-4 detected\n"); 1163 break; 1164 case 0x8: 1165 /* 100G ACC (active copper cable) */ 1166 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1167 "100G ACC (active copper cable detected\n"); 1168 break; 1169 case 0xb: 1170 /* 100G CR-4 */ 1171 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1172 "100G CR-4 detected\n"); 1173 break; 1174 case 0x11: 1175 /* 4x10G SR */ 1176 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1177 "4x10G SR detected\n"); 1178 break; 1179 default: 1180 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1181 "Unexpected technology. NEW COMPLIANCE CODE TO SUPPORT 0x%x\n", 1182 buf[0]); 1183 break; 1184 } 1185 break; 1186 default: 1187 /* Unexpected technology compliance field */ 1188 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1189 "WARNING: Unexpected technology compliance field detected 0x%x\n", 1190 buf[0]); 1191 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1192 "Assume SR-4 detected\n"); 1193 break; 1194 } 1195 1196 /* get extended rate select bytes 141 */ 1197 /* get vendor length bytes 142-146 */ 1198 /* get device technology byte 147 */ 1199 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1200 141, 7, buf); 1201 if (rc != ECORE_SUCCESS) 1202 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1203 "Error reading extended rate select bytes.\n"); 1204 1205 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1206 "Extended rate select bytes 0x%x\n", buf[0]); 1207 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1208 "Length (SMF) 0x%x\n", buf[1]); 1209 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1210 "Length (OM3 50 um) 0x%x\n", buf[2]); 1211 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1212 "Length (OM2 50 um) 0x%x\n", buf[3]); 1213 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1214 "Length (OM1 62.5 um) 0x%x\n", buf[4]); 1215 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1216 "Length (Passive or active) 0x%x\n", buf[5]); 1217 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1218 "Device technology byte 0x%x\n", buf[6]); 1219 1220 /* get vendor name bytes bytes 148-163 */ 1221 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1222 148, 16, buf); 1223 if (rc != ECORE_SUCCESS) 1224 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1225 "Error reading vendor name.\n"); 1226 1227 buf[16] = 0; 1228 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1229 "Vendor name: %s\n", buf); 1230 1231 /* get vendor OUI bytes 165-167 */ 1232 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1233 165, 3, buf); 1234 if (rc != ECORE_SUCCESS) 1235 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1236 "Error reading vendor OUI.\n"); 1237 1238 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1239 "Vendor OUI: %02x%02x%02x\n", 1240 buf[0], buf[1], buf[2]); 1241 1242 /* get vendor PN bytes 168-183 */ 1243 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1244 168, 16, buf); 1245 if (rc != ECORE_SUCCESS) 1246 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1247 "Error reading vendor PN.\n"); 1248 1249 buf[16] = 0; 1250 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1251 "Vendor PN: %s\n", buf); 1252 1253 /* get vendor REV bytes 184-185 */ 1254 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1255 184, 2, buf); 1256 if (rc != ECORE_SUCCESS) 1257 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1258 "Error reading vendor rev.\n"); 1259 1260 buf[2] = 0; 1261 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1262 "Vendor rev: %s\n", buf); 1263 1264 return rc; 1265 } 1266 1267 /* Decode SFP information */ 1268 int ecore_phy_sfp_decode(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1269 u32 port, char *p_phy_result_buf) 1270 { 1271 enum _ecore_status_t rc; 1272 u32 length = 0; 1273 u8 buf[4]; 1274 1275 /* Verify <port> field is between 0 and number of ports */ 1276 rc = ecore_validate_sfp_port(p_hwfn, p_ptt, port, p_phy_result_buf); 1277 if (rc != ECORE_SUCCESS) 1278 return rc; 1279 1280 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1281 0, 1, buf); 1282 if (rc != ECORE_SUCCESS) 1283 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1284 "Error reading transceiver identification field.\n"); 1285 1286 switch (buf[0]) { 1287 case 0x3: /* SFP, SFP+, SFP-28 */ 1288 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1289 "SFP, SFP+ or SFP-28 inserted.\n"); 1290 rc = ecore_decode_sfp_info(p_hwfn, p_ptt, port, 1291 length, p_phy_result_buf); 1292 break; 1293 case 0xc: /* QSFP */ 1294 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1295 "QSFP inserted.\n"); 1296 rc = ecore_decode_qsfp_info(p_hwfn, p_ptt, port, 1297 length, p_phy_result_buf); 1298 break; 1299 case 0xd: /* QSFP+ */ 1300 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1301 "QSFP+ inserted.\n"); 1302 rc = ecore_decode_qsfp_info(p_hwfn, p_ptt, port, 1303 length, p_phy_result_buf); 1304 break; 1305 case 0x11: /* QSFP-28 */ 1306 length += OSAL_SPRINTF(&p_phy_result_buf[length], 1307 "QSFP-28 inserted.\n"); 1308 rc = ecore_decode_qsfp_info(p_hwfn, p_ptt, port, 1309 length, p_phy_result_buf); 1310 break; 1311 case 0x12: /* CXP2 (CXP-28) */ 1312 OSAL_SPRINTF(p_phy_result_buf, 1313 "CXP2 (CXP-28) inserted.\n"); 1314 rc = ECORE_UNKNOWN_ERROR; 1315 break; 1316 default: 1317 OSAL_SPRINTF(p_phy_result_buf, 1318 "Unknown transceiver type inserted.\n"); 1319 rc = ECORE_UNKNOWN_ERROR; 1320 break; 1321 } 1322 1323 return rc; 1324 } 1325 1326 /* Get SFP inserted status */ 1327 int ecore_phy_sfp_get_inserted(struct ecore_hwfn *p_hwfn, 1328 struct ecore_ptt *p_ptt, 1329 u32 port, char *p_phy_result_buf) 1330 { 1331 u32 transceiver_state; 1332 u32 addr = SECTION_OFFSIZE_ADDR(p_hwfn->mcp_info->public_base, 1333 PUBLIC_PORT); 1334 u32 mfw_mb_offsize = ecore_rd(p_hwfn, p_ptt, addr); 1335 u32 port_addr = SECTION_ADDR(mfw_mb_offsize, port); 1336 1337 transceiver_state = ecore_rd(p_hwfn, p_ptt, 1338 port_addr + 1339 offsetof(struct public_port, 1340 transceiver_data)); 1341 1342 transceiver_state = GET_FIELD(transceiver_state, ETH_TRANSCEIVER_STATE); 1343 1344 OSAL_SPRINTF(p_phy_result_buf, "%d", 1345 (transceiver_state == ETH_TRANSCEIVER_STATE_PRESENT)); 1346 1347 return ECORE_SUCCESS; 1348 } 1349 1350 /* Get SFP TX disable status */ 1351 int ecore_phy_sfp_get_txdisable(struct ecore_hwfn *p_hwfn, 1352 struct ecore_ptt *p_ptt, 1353 u32 port, char *p_phy_result_buf) 1354 { 1355 enum _ecore_status_t rc; 1356 u32 length = 0; 1357 u8 buf[4]; 1358 1359 /* Verify <port> field is between 0 and number of ports */ 1360 rc = ecore_validate_sfp_port(p_hwfn, p_ptt, port, p_phy_result_buf); 1361 if (rc != ECORE_SUCCESS) 1362 return rc; 1363 1364 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1365 0, 1, buf); 1366 if (rc != ECORE_SUCCESS) 1367 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1368 "Error reading transceiver identification field.\n"); 1369 1370 switch (buf[0]) { 1371 case 0x3: /* SFP, SFP+, SFP-28 */ 1372 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1373 I2C_TRANSCEIVER_ADDR, 110, 1, buf); 1374 if (rc != ECORE_SUCCESS) 1375 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1376 "Error reading transceiver tx disable status field.\n"); 1377 OSAL_SPRINTF(p_phy_result_buf, "%d", 1378 ((buf[0] & 0xC0) ? 1 : 0)); 1379 break; 1380 case 0xc: /* QSFP */ 1381 case 0xd: /* QSFP+ */ 1382 case 0x11: /* QSFP-28 */ 1383 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1384 I2C_TRANSCEIVER_ADDR, 86, 1, buf); 1385 if (rc != ECORE_SUCCESS) 1386 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1387 "Error reading transceiver tx disable status field.\n"); 1388 OSAL_SPRINTF(p_phy_result_buf, "%d", 1389 ((buf[0] & ((1 << port))) ? 1 : 0)); 1390 break; 1391 default: 1392 OSAL_SPRINTF(p_phy_result_buf, 1393 "Unknown transceiver type inserted.\n"); 1394 rc = ECORE_UNKNOWN_ERROR; 1395 break; 1396 } 1397 1398 return rc; 1399 } 1400 1401 /* Set SFP TX disable */ 1402 int ecore_phy_sfp_set_txdisable(struct ecore_hwfn *p_hwfn, 1403 struct ecore_ptt *p_ptt, 1404 u32 port, u8 txdisable, 1405 char *p_phy_result_buf) 1406 { 1407 enum _ecore_status_t rc; 1408 u32 length = 0; 1409 u8 buf[4]; 1410 1411 /* Verify <txdisable> field is between 0 and 1 */ 1412 if (txdisable > 1) { 1413 OSAL_SPRINTF(p_phy_result_buf, 1414 "Bad tx disable value, must be 0 or 1.\n"); 1415 return ECORE_INVAL; 1416 } 1417 1418 /* Verify <port> field is between 0 and number of ports */ 1419 rc = ecore_validate_sfp_port(p_hwfn, p_ptt, port, 1420 p_phy_result_buf); 1421 if (rc != ECORE_SUCCESS) 1422 return rc; 1423 1424 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1425 0, 1, buf); 1426 if (rc != ECORE_SUCCESS) 1427 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1428 "Error reading transceiver identification field.\n"); 1429 1430 switch (buf[0]) { 1431 case 0x3: /* SFP, SFP+, SFP-28 */ 1432 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1433 I2C_TRANSCEIVER_ADDR, 1434 SFP_TX_DISABLE_OFFSET, 1, buf); 1435 if (rc != ECORE_SUCCESS) 1436 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1437 "Error reading transceiver tx disable status field.\n"); 1438 1439 if (((buf[0] & 0x40) >> 6) != txdisable) { 1440 buf[0] ^= 0x40; 1441 rc = ecore_mcp_phy_sfp_write(p_hwfn, p_ptt, port, 1442 I2C_TRANSCEIVER_ADDR, 1443 SFP_TX_DISABLE_OFFSET, 1444 1, buf); 1445 if (rc != ECORE_SUCCESS) 1446 OSAL_SPRINTF(&p_phy_result_buf[length], 1447 "Error setting transceiver tx disable status field.\n"); 1448 } 1449 1450 if (((buf[0] & 0x80) >> 7) != txdisable) { 1451 u32 nvm_cfg_addr, nvm_cfg1_offset, port_cfg_addr; 1452 u16 gpio; 1453 1454 nvm_cfg_addr = ecore_rd(p_hwfn, p_ptt, 1455 MISC_REG_GEN_PURP_CR0); 1456 nvm_cfg1_offset = ecore_rd(p_hwfn, p_ptt, 1457 nvm_cfg_addr + 4); 1458 port_cfg_addr = MCP_REG_SCRATCH + nvm_cfg1_offset + 1459 offsetof(struct nvm_cfg1, port[port]); 1460 gpio = (u16)ecore_rd(p_hwfn, p_ptt, 1461 port_cfg_addr + 1462 offsetof(struct nvm_cfg1_port, 1463 transceiver_00)); 1464 gpio &= NVM_CFG1_PORT_TRANS_MODULE_ABS_MASK; 1465 rc = ecore_phy_gpio_write(p_hwfn, p_ptt, gpio, 1466 txdisable, 1467 p_phy_result_buf); 1468 if (rc != ECORE_SUCCESS) 1469 OSAL_SPRINTF(&p_phy_result_buf[length], 1470 "Error setting transceiver tx disable status field.\n"); 1471 } 1472 break; 1473 case 0xc: /* QSFP */ 1474 case 0xd: /* QSFP+ */ 1475 case 0x11: /* QSFP-28 */ 1476 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1477 I2C_TRANSCEIVER_ADDR, 1478 QSFP_TX_DISABLE_OFFSET, 1, buf); 1479 if (rc != ECORE_SUCCESS) 1480 return ecore_sfp_set_error(rc, length, 1481 p_phy_result_buf, 1482 "Error reading transceiver tx disable status field.\n"); 1483 if (((buf[0] & (1 << port)) >> port) != txdisable) { 1484 buf[0] ^= (1 << port); 1485 rc = ecore_mcp_phy_sfp_write(p_hwfn, p_ptt, port, 1486 I2C_TRANSCEIVER_ADDR, 1487 QSFP_TX_DISABLE_OFFSET, 1488 1, buf); 1489 if (rc != ECORE_SUCCESS) 1490 OSAL_SPRINTF(&p_phy_result_buf[length], 1491 "Error setting transceiver tx disable status field.\n"); 1492 } 1493 break; 1494 default: 1495 OSAL_SPRINTF(p_phy_result_buf, 1496 "Unknown transceiver type inserted.\n"); 1497 rc = ECORE_UNKNOWN_ERROR; 1498 break; 1499 } 1500 1501 return rc; 1502 } 1503 1504 /* Get SFP TX fault status */ 1505 int ecore_phy_sfp_get_txreset(struct ecore_hwfn *p_hwfn, 1506 struct ecore_ptt *p_ptt, 1507 u32 port, char *p_phy_result_buf) 1508 { 1509 enum _ecore_status_t rc; 1510 u32 length = 0; 1511 u8 buf[4]; 1512 1513 /* Verify <port> field is between 0 and number of ports */ 1514 rc = ecore_validate_sfp_port(p_hwfn, p_ptt, port, p_phy_result_buf); 1515 if (rc != ECORE_SUCCESS) 1516 return rc; 1517 1518 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1519 0, 1, buf); 1520 if (rc != ECORE_SUCCESS) 1521 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1522 "Error reading transceiver identification field.\n"); 1523 1524 switch (buf[0]) { 1525 case 0x3: /* SFP, SFP+, SFP-28 */ 1526 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1527 I2C_TRANSCEIVER_ADDR, 1528 SFP_TX_FAULT_OFFSET, 1, buf); 1529 if (rc != ECORE_SUCCESS) 1530 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1531 "Error reading transceiver tx fault status field.\n"); 1532 OSAL_SPRINTF(p_phy_result_buf, "%d", 1533 ((buf[0] & 0x02) ? 1 : 0)); 1534 break; 1535 case 0xc: /* QSFP */ 1536 case 0xd: /* QSFP+ */ 1537 case 0x11: /* QSFP-28 */ 1538 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1539 I2C_TRANSCEIVER_ADDR, 1540 QSFP_TX_FAULT_OFFSET, 1, buf); 1541 if (rc != ECORE_SUCCESS) 1542 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1543 "Error reading transceiver tx fault status field.\n"); 1544 OSAL_SPRINTF(p_phy_result_buf, "%d", 1545 ((buf[0] & (1 << port)) ? 1 : 0)); 1546 break; 1547 default: 1548 OSAL_SPRINTF(p_phy_result_buf, 1549 "Unknown transceiver type inserted.\n"); 1550 rc = ECORE_UNKNOWN_ERROR; 1551 break; 1552 } 1553 1554 return rc; 1555 } 1556 1557 /* Get SFP RX los status */ 1558 int ecore_phy_sfp_get_rxlos(struct ecore_hwfn *p_hwfn, 1559 struct ecore_ptt *p_ptt, 1560 u32 port, char *p_phy_result_buf) 1561 { 1562 enum _ecore_status_t rc; 1563 u32 length = 0; 1564 u8 buf[4]; 1565 1566 /* Verify <port> field is between 0 and number of ports */ 1567 rc = ecore_validate_sfp_port(p_hwfn, p_ptt, port, p_phy_result_buf); 1568 if (rc != ECORE_SUCCESS) 1569 return rc; 1570 1571 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1572 0, 1, buf); 1573 if (rc != ECORE_SUCCESS) 1574 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1575 "Error reading transceiver identification field.\n"); 1576 1577 switch (buf[0]) { 1578 case 0x3: /* SFP, SFP+, SFP-28 */ 1579 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1580 I2C_TRANSCEIVER_ADDR, 1581 SFP_RX_LOS_OFFSET, 1, buf); 1582 if (rc != ECORE_SUCCESS) 1583 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1584 "Error reading transceiver rx los status field.\n"); 1585 OSAL_SPRINTF(p_phy_result_buf, "%d", 1586 ((buf[0] & 0x01) ? 1 : 0)); 1587 break; 1588 case 0xc: /* QSFP */ 1589 case 0xd: /* QSFP+ */ 1590 case 0x11: /* QSFP-28 */ 1591 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, 1592 I2C_TRANSCEIVER_ADDR, 1593 QSFP_RX_LOS_OFFSET, 1, buf); 1594 if (rc != ECORE_SUCCESS) 1595 return ecore_sfp_set_error(rc, length, p_phy_result_buf, 1596 "Error reading transceiver rx los status field.\n"); 1597 OSAL_SPRINTF(p_phy_result_buf, "%d", 1598 ((buf[0] & (1 << port)) ? 1 : 0)); 1599 break; 1600 default: 1601 OSAL_SPRINTF(p_phy_result_buf, 1602 "Unknown transceiver type inserted.\n"); 1603 rc = ECORE_UNKNOWN_ERROR; 1604 break; 1605 } 1606 1607 return rc; 1608 } 1609 1610 /* Get SFP EEPROM memory dump */ 1611 int ecore_phy_sfp_get_eeprom(struct ecore_hwfn *p_hwfn, 1612 struct ecore_ptt *p_ptt, 1613 u32 port, char *p_phy_result_buf) 1614 { 1615 enum _ecore_status_t rc; 1616 u8 buf[4]; 1617 1618 /* Verify <port> field is between 0 and number of ports */ 1619 rc = ecore_validate_sfp_port(p_hwfn, p_ptt, port, p_phy_result_buf); 1620 if (rc != ECORE_SUCCESS) 1621 return rc; 1622 1623 rc = ecore_mcp_phy_sfp_read(p_hwfn, p_ptt, port, I2C_TRANSCEIVER_ADDR, 1624 0, 1, buf); 1625 if (rc != ECORE_SUCCESS) 1626 return ecore_sfp_set_error(rc, 0, p_phy_result_buf, 1627 "Error reading transceiver identification field.\n"); 1628 1629 switch (buf[0]) { 1630 case 0x3: /* SFP, SFP+, SFP-28 */ 1631 case 0xc: /* QSFP */ 1632 case 0xd: /* QSFP+ */ 1633 case 0x11: /* QSFP-28 */ 1634 rc = ecore_phy_sfp_read(p_hwfn, p_ptt, port, 1635 I2C_TRANSCEIVER_ADDR, 0, 1636 MAX_I2C_TRANSCEIVER_PAGE_SIZE, 1637 p_phy_result_buf); 1638 break; 1639 default: 1640 OSAL_SPRINTF(p_phy_result_buf, 1641 "Unknown transceiver type inserted.\n"); 1642 rc = ECORE_UNKNOWN_ERROR; 1643 break; 1644 } 1645 1646 return rc; 1647 } 1648 1649 /* Write to gpio */ 1650 int ecore_phy_gpio_write(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1651 u16 gpio, u16 gpio_val, char *p_phy_result_buf) 1652 { 1653 enum _ecore_status_t rc; 1654 1655 rc = ecore_mcp_gpio_write(p_hwfn, p_ptt, gpio, gpio_val); 1656 1657 if (rc == ECORE_SUCCESS) 1658 OSAL_SPRINTF(p_phy_result_buf, 1659 "Written successfully to gpio number %d.\n", 1660 gpio); 1661 else 1662 OSAL_SPRINTF(p_phy_result_buf, 1663 "Can't write to gpio %d\n", gpio); 1664 1665 return rc; 1666 } 1667 1668 /* Read from gpio */ 1669 int ecore_phy_gpio_read(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1670 u16 gpio, char *p_phy_result_buf) 1671 { 1672 enum _ecore_status_t rc; 1673 u32 param; 1674 1675 rc = ecore_mcp_gpio_read(p_hwfn, p_ptt, gpio, ¶m); 1676 1677 if (rc == ECORE_SUCCESS) 1678 OSAL_SPRINTF(p_phy_result_buf, "%x", param); 1679 else 1680 OSAL_SPRINTF(p_phy_result_buf, 1681 "Can't read from gpio %d\n", gpio); 1682 1683 return rc; 1684 } 1685 1686 /* Get information from gpio */ 1687 int ecore_phy_gpio_info(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1688 u16 gpio, char *p_phy_result_buf) 1689 { 1690 u32 direction, ctrl, length = 0; 1691 enum _ecore_status_t rc; 1692 1693 rc = ecore_mcp_gpio_info(p_hwfn, p_ptt, gpio, &direction, &ctrl); 1694 1695 if (rc != ECORE_SUCCESS) { 1696 OSAL_SPRINTF(p_phy_result_buf, 1697 "Can't get information for gpio %d\n", gpio); 1698 return rc; 1699 } 1700 1701 length = OSAL_SPRINTF(p_phy_result_buf, "Gpio %d is %s - ", 1702 gpio, 1703 ((direction == 0) ? "output" : "input")); 1704 switch (ctrl) { 1705 case 0: 1706 OSAL_SPRINTF(&p_phy_result_buf[length], 1707 "control is uninitialized\n"); 1708 break; 1709 case 1: 1710 OSAL_SPRINTF(&p_phy_result_buf[length], 1711 "control is path 0\n"); 1712 break; 1713 case 2: 1714 OSAL_SPRINTF(&p_phy_result_buf[length], 1715 "control is path 1\n"); 1716 break; 1717 case 3: 1718 OSAL_SPRINTF(&p_phy_result_buf[length], 1719 "control is shared\n"); 1720 break; 1721 default: 1722 OSAL_SPRINTF(&p_phy_result_buf[length], 1723 "\nError - control is invalid\n"); 1724 break; 1725 } 1726 1727 return ECORE_SUCCESS; 1728 } 1729 1730 /* Get information from gpio */ 1731 int ecore_phy_extphy_read(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1732 u16 port, u16 devad, u16 reg, char *p_phy_result_buf) 1733 { 1734 enum _ecore_status_t rc; 1735 u32 resp_cmd; 1736 u32 val; 1737 1738 rc = ecore_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_EXT_PHY_READ, 1739 ((port << DRV_MB_PARAM_PORT_SHIFT) | 1740 (devad << DRV_MB_PARAM_DEVAD_SHIFT) | 1741 (reg << DRV_MB_PARAM_ADDR_SHIFT)), 1742 &resp_cmd, 1743 &val); 1744 1745 if ((rc != ECORE_SUCCESS) || (resp_cmd != FW_MSG_CODE_PHY_OK)) { 1746 OSAL_SPRINTF(p_phy_result_buf, 1747 "Failed reading external PHY\n"); 1748 return rc; 1749 } 1750 OSAL_SPRINTF(p_phy_result_buf, "0x%04x\n", val); 1751 return ECORE_SUCCESS; 1752 } 1753 1754 /* Get information from gpio */ 1755 int ecore_phy_extphy_write(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, 1756 u16 port, u16 devad, u16 reg, u16 val, 1757 char *p_phy_result_buf) 1758 { 1759 enum _ecore_status_t rc; 1760 u32 resp_cmd; 1761 u32 fw_param; 1762 1763 rc = ecore_mcp_nvm_wr_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_EXT_PHY_WRITE, 1764 ((port << DRV_MB_PARAM_PORT_SHIFT) | 1765 (devad << DRV_MB_PARAM_DEVAD_SHIFT) | 1766 (reg << DRV_MB_PARAM_ADDR_SHIFT)), 1767 &resp_cmd, 1768 &fw_param, 1769 sizeof(u32), 1770 (u32 *)&val); 1771 1772 if ((rc != ECORE_SUCCESS) || (resp_cmd != FW_MSG_CODE_PHY_OK)) { 1773 OSAL_SPRINTF(p_phy_result_buf, 1774 "Failed writing external PHY\n"); 1775 return rc; 1776 } 1777 OSAL_SPRINTF(p_phy_result_buf, "0\n"); 1778 return ECORE_SUCCESS; 1779 } 1780