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
ecore_phy_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 lane,u32 addr,u32 cmd,u8 * buf)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
ecore_phy_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 lane,u32 addr,u32 data_lo,u32 data_hi,u32 cmd)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 */
ecore_phy_core_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 data_lo,u32 data_hi,char * p_phy_result_buf)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 */
ecore_phy_core_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,char * p_phy_result_buf)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 */
ecore_phy_raw_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 lane,u32 addr,u32 data_lo,u32 data_hi,char * p_phy_result_buf)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 */
ecore_phy_raw_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 lane,u32 addr,char * p_phy_result_buf)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
ecore_phy_get_nvm_cfg1_addr(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt)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 */
ecore_phy_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,char * p_phy_result_buf)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 */
ecore_bb_phy_mac_stat(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_ah_e5_phy_mac_stat(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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
ecore_phy_mac_stat(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_sfp_set_error(enum _ecore_status_t rc,u32 offset,char * p_phy_result_buf,char * p_err_str)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 */
ecore_validate_sfp_port(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_validate_sfp_parameters(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 offset,u32 size,char * p_phy_result_buf)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 */
ecore_phy_sfp_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 offset,u32 size,u32 val,char * p_phy_result_buf)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 */
ecore_phy_sfp_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 addr,u32 offset,u32 size,char * p_phy_result_buf)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
ecore_decode_sfp_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 length,char * p_phy_result_buf)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
ecore_decode_qsfp_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u32 length,char * p_phy_result_buf)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 */
ecore_phy_sfp_decode(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_phy_sfp_get_inserted(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_phy_sfp_get_txdisable(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_phy_sfp_set_txdisable(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,u8 txdisable,char * p_phy_result_buf)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 */
ecore_phy_sfp_get_txreset(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_phy_sfp_get_rxlos(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_phy_sfp_get_eeprom(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u32 port,char * p_phy_result_buf)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 */
ecore_phy_gpio_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,u16 gpio_val,char * p_phy_result_buf)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 */
ecore_phy_gpio_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,char * p_phy_result_buf)1669 int ecore_phy_gpio_read(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt,
1670 u16 gpio, char *p_phy_result_buf)
1671 {
1672 enum _ecore_status_t rc;
1673 u32 param;
1674
1675 rc = ecore_mcp_gpio_read(p_hwfn, p_ptt, gpio, ¶m);
1676
1677 if (rc == ECORE_SUCCESS)
1678 OSAL_SPRINTF(p_phy_result_buf, "%x", param);
1679 else
1680 OSAL_SPRINTF(p_phy_result_buf,
1681 "Can't read from gpio %d\n", gpio);
1682
1683 return rc;
1684 }
1685
1686 /* Get information from gpio */
ecore_phy_gpio_info(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 gpio,char * p_phy_result_buf)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 */
ecore_phy_extphy_read(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 port,u16 devad,u16 reg,char * p_phy_result_buf)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 */
ecore_phy_extphy_write(struct ecore_hwfn * p_hwfn,struct ecore_ptt * p_ptt,u16 port,u16 devad,u16 reg,u16 val,char * p_phy_result_buf)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