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