xref: /illumos-gate/usr/src/uts/common/io/qede/579xx/drivers/ecore/ecore_phy.c (revision b68ddc76a8be9a9b8d7a1eae3a3613b6bce942e5)
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, &param);
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