1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2018-2022 Marvell International Ltd.
4 */
5
6#include <errno.h>
7#include <i2c.h>
8#include <log.h>
9#include <malloc.h>
10#include <linux/delay.h>
11#include <display_options.h>
12
13#include <mach/cvmx-regs.h>
14#include <mach/cvmx-csr.h>
15#include <mach/cvmx-bootmem.h>
16#include <mach/octeon-model.h>
17#include <mach/cvmx-fuse.h>
18#include <mach/octeon-feature.h>
19#include <mach/cvmx-qlm.h>
20#include <mach/octeon_qlm.h>
21#include <mach/cvmx-pcie.h>
22#include <mach/cvmx-coremask.h>
23
24#include <mach/cvmx-helper.h>
25#include <mach/cvmx-helper-board.h>
26#include <mach/cvmx-helper-fdt.h>
27#include <mach/cvmx-helper-cfg.h>
28#include <mach/cvmx-helper-gpio.h>
29#include <mach/cvmx-helper-util.h>
30
31extern void octeon_i2c_unblock(int bus);
32
33static struct cvmx_fdt_sfp_info *sfp_list;
34
35/**
36 * Local allocator to handle both SE and U-Boot that also zeroes out memory
37 *
38 * @param	size	number of bytes to allocate
39 *
40 * @return	pointer to allocated memory or NULL if out of memory.
41 *		Alignment is set to 8-bytes.
42 */
43static void *cvm_sfp_alloc(size_t size)
44{
45	return calloc(size, 1);
46}
47
48/**
49 * Free allocated memory.
50 *
51 * @param	ptr	pointer to memory to free
52 *
53 * NOTE: This only works in U-Boot since SE does not really have a freeing
54 *	 mechanism.  In SE the memory is zeroed out and not freed so this
55 *	 is a memory leak if errors occur.
56 */
57static inline void cvm_sfp_free(void *ptr, size_t size)
58{
59	free(ptr);
60}
61
62/**
63 * Select a QSFP device before accessing the EEPROM
64 *
65 * @param	sfp	handle for sfp/qsfp connector
66 * @param	enable	Set true to select, false to deselect
67 *
68 * @return	0 on success or if SFP or no select GPIO, -1 on GPIO error
69 */
70static int cvmx_qsfp_select(const struct cvmx_fdt_sfp_info *sfp, bool enable)
71{
72	/* Select is only needed for QSFP modules */
73	if (!sfp->is_qsfp) {
74		debug("%s(%s, %d): not QSFP\n", __func__, sfp->name, enable);
75		return 0;
76	}
77
78	if (dm_gpio_is_valid(&sfp->select)) {
79		/* Note that select is active low */
80		return dm_gpio_set_value(&sfp->select, !enable);
81	}
82
83	debug("%s: select GPIO unknown\n", __func__);
84	return 0;
85}
86
87static int cvmx_sfp_parse_sfp_buffer(struct cvmx_sfp_mod_info *sfp_info,
88				     const uint8_t *buffer)
89{
90	u8 csum = 0;
91	bool csum_good = false;
92	int i;
93
94	/* Validate the checksum */
95	for (i = 0; i < 0x3f; i++)
96		csum += buffer[i];
97	csum_good = csum == buffer[0x3f];
98	debug("%s: Lower checksum: 0x%02x, expected: 0x%02x\n", __func__, csum,
99	      buffer[0x3f]);
100	csum = 0;
101	for (i = 0x40; i < 0x5f; i++)
102		csum += buffer[i];
103	debug("%s: Upper checksum: 0x%02x, expected: 0x%02x\n", __func__, csum,
104	      buffer[0x5f]);
105	if (csum != buffer[0x5f] || !csum_good) {
106		debug("Error: SFP EEPROM checksum information is incorrect\n");
107		return -1;
108	}
109
110	sfp_info->conn_type = buffer[0];
111	if (buffer[1] < 1 || buffer[1] > 7) { /* Extended ID */
112		debug("Error: Unknown SFP extended identifier 0x%x\n",
113		      buffer[1]);
114		return -1;
115	}
116	if (buffer[1] != 4) {
117		debug("Module is not SFP/SFP+/SFP28/QSFP+\n");
118		return -1;
119	}
120	sfp_info->mod_type = buffer[2];
121	sfp_info->eth_comp = buffer[3] & 0xf0;
122	sfp_info->cable_comp = buffer[0x24];
123
124	/* There are several ways a cable can be marked as active or
125	 * passive.  8.[2-3] specify the SFP+ cable technology.  Some
126	 * modules also use 3.[0-1] for Infiniband, though it's
127	 * redundant.
128	 */
129	if ((buffer[8] & 0x0C) == 0x08) {
130		sfp_info->limiting = true;
131		sfp_info->active_cable = true;
132	} else if ((buffer[8] & 0xC) == 0x4) {
133		sfp_info->limiting = false;
134		sfp_info->active_cable = false;
135	}
136	if ((buffer[3] & 3) == 2) {
137		sfp_info->active_cable = true;
138		sfp_info->limiting = true;
139	}
140
141	switch (sfp_info->mod_type) {
142	case CVMX_SFP_MOD_OPTICAL_LC:
143	case CVMX_SFP_MOD_OPTICAL_PIGTAIL:
144		sfp_info->copper_cable = false;
145		break;
146	case CVMX_SFP_MOD_COPPER_PIGTAIL:
147		sfp_info->copper_cable = true;
148		break;
149	case CVMX_SFP_MOD_NO_SEP_CONN:
150		switch (sfp_info->cable_comp) {
151		case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_HIGH_BER:
152		case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_LOW_BER:
153		case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_LOW_BER:
154			sfp_info->copper_cable = false;
155			sfp_info->limiting = true;
156			sfp_info->active_cable = true;
157			break;
158
159		case CVMX_SFP_CABLE_100G_SR4_25G_SR:
160		case CVMX_SFP_CABLE_100G_LR4_25G_LR:
161		case CVMX_SFP_CABLE_100G_ER4_25G_ER:
162		case CVMX_SFP_CABLE_100G_SR10:
163		case CVMX_SFP_CABLE_100G_CWDM4_MSA:
164		case CVMX_SFP_CABLE_100G_PSM4:
165		case CVMX_SFP_CABLE_100G_CWDM4:
166		case CVMX_SFP_CABLE_40G_ER4:
167		case CVMX_SFP_CABLE_4X10G_SR:
168		case CVMX_SFP_CABLE_G959_1_P1I1_2D1:
169		case CVMX_SFP_CABLE_G959_1_P1S1_2D2:
170		case CVMX_SFP_CABLE_G959_1_P1L1_2D2:
171		case CVMX_SFP_CABLE_100G_CLR4:
172		case CVMX_SFP_CABLE_100G_2_LAMBDA_DWDM:
173		case CVMX_SFP_CABLE_40G_SWDM4:
174		case CVMX_SFP_CABLE_100G_SWDM4:
175		case CVMX_SFP_CABLE_100G_PAM4_BIDI:
176			sfp_info->copper_cable = false;
177			break;
178
179		case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_HIGH_BER:
180		case CVMX_SFP_CABLE_10GBASE_T:
181		case CVMX_SFP_CABLE_10GBASE_T_SR:
182		case CVMX_SFP_CABLE_5GBASE_T:
183		case CVMX_SFP_CABLE_2_5GBASE_T:
184			sfp_info->copper_cable = true;
185			sfp_info->limiting = true;
186			sfp_info->active_cable = true;
187			break;
188
189		case CVMX_SFP_CABLE_100G_CR4_25G_CR_CA_L:
190		case CVMX_SFP_CABLE_25G_CR_CA_S:
191		case CVMX_SFP_CABLE_25G_CR_CA_N:
192		case CVMX_SFP_CABLE_40G_PSM4:
193			sfp_info->copper_cable = true;
194			break;
195
196		default:
197			switch (sfp_info->eth_comp) {
198			case CVMX_SFP_CABLE_10GBASE_ER:
199			case CVMX_SFP_CABLE_10GBASE_LRM:
200			case CVMX_SFP_CABLE_10GBASE_LR:
201			case CVMX_SFP_CABLE_10GBASE_SR:
202				sfp_info->copper_cable = false;
203				break;
204			}
205			break;
206		}
207		break;
208
209	case CVMX_SFP_MOD_RJ45:
210		debug("%s: RJ45 adapter\n", __func__);
211		sfp_info->copper_cable = true;
212		sfp_info->active_cable = true;
213		sfp_info->limiting = true;
214		break;
215	case CVMX_SFP_MOD_UNKNOWN:
216		/* The Avago 1000Base-X to 1000Base-T module reports that it
217		 * is an unknown module type but the Ethernet compliance code
218		 * says it is 1000Base-T.  We'll change the reporting to RJ45.
219		 */
220		if (buffer[6] & 8) {
221			debug("RJ45 gigabit module detected\n");
222			sfp_info->mod_type = CVMX_SFP_MOD_RJ45;
223			sfp_info->copper_cable = false;
224			sfp_info->limiting = true;
225			sfp_info->active_cable = true;
226			sfp_info->max_copper_cable_len = buffer[0x12];
227			sfp_info->rate = CVMX_SFP_RATE_1G;
228		} else {
229			debug("Unknown module type 0x%x\n", sfp_info->mod_type);
230		}
231		sfp_info->limiting = true;
232		break;
233	case CVMX_SFP_MOD_MXC_2X16:
234		debug("%s: MXC 2X16\n", __func__);
235		break;
236	default:
237		sfp_info->limiting = true;
238		break;
239	}
240
241	if (sfp_info->copper_cable)
242		sfp_info->max_copper_cable_len = buffer[0x12];
243	else
244		sfp_info->max_50um_om4_cable_length = buffer[0x12] * 10;
245
246	if (buffer[0xe])
247		sfp_info->max_single_mode_cable_length = buffer[0xe] * 1000;
248	else
249		sfp_info->max_single_mode_cable_length = buffer[0xf] * 100000;
250
251	sfp_info->max_50um_om2_cable_length = buffer[0x10] * 10;
252	sfp_info->max_62_5um_om1_cable_length = buffer[0x11] * 10;
253	sfp_info->max_50um_om3_cable_length = buffer[0x13] * 10;
254
255	if (buffer[0xc] == 0xff) {
256		if (buffer[0x42] >= 255)
257			sfp_info->rate = CVMX_SFP_RATE_100G;
258		else if (buffer[0x42] >= 160)
259			sfp_info->rate = CVMX_SFP_RATE_40G;
260		else if (buffer[0x42] >= 100)
261			sfp_info->rate = CVMX_SFP_RATE_25G;
262		else
263			sfp_info->rate = CVMX_SFP_RATE_UNKNOWN;
264	} else if (buffer[0xc] >= 100) {
265		sfp_info->rate = CVMX_SFP_RATE_10G;
266	} else if (buffer[0xc] >= 10) {
267		sfp_info->rate = CVMX_SFP_RATE_1G;
268	} else {
269		sfp_info->rate = CVMX_SFP_RATE_UNKNOWN;
270	}
271
272	if (sfp_info->rate == CVMX_SFP_RATE_UNKNOWN) {
273		switch (sfp_info->cable_comp) {
274		case CVMX_SFP_CABLE_100G_SR10:
275		case CVMX_SFP_CABLE_100G_CWDM4_MSA:
276		case CVMX_SFP_CABLE_100G_PSM4:
277		case CVMX_SFP_CABLE_100G_CWDM4:
278		case CVMX_SFP_CABLE_100G_CLR4:
279		case CVMX_SFP_CABLE_100G_2_LAMBDA_DWDM:
280		case CVMX_SFP_CABLE_100G_SWDM4:
281		case CVMX_SFP_CABLE_100G_PAM4_BIDI:
282			sfp_info->rate = CVMX_SFP_RATE_100G;
283			break;
284		case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_HIGH_BER:
285		case CVMX_SFP_CABLE_100G_SR4_25G_SR:
286		case CVMX_SFP_CABLE_100G_LR4_25G_LR:
287		case CVMX_SFP_CABLE_100G_ER4_25G_ER:
288		case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_HIGH_BER:
289		case CVMX_SFP_CABLE_100G_CR4_25G_CR_CA_L:
290		case CVMX_SFP_CABLE_25G_CR_CA_S:
291		case CVMX_SFP_CABLE_25G_CR_CA_N:
292		case CVMX_SFP_CABLE_100G_25GAUI_C2M_AOC_LOW_BER:
293		case CVMX_SFP_CABLE_100G_25GAUI_C2M_ACC_LOW_BER:
294			sfp_info->rate = CVMX_SFP_RATE_25G;
295			break;
296		case CVMX_SFP_CABLE_40G_ER4:
297		case CVMX_SFP_CABLE_4X10G_SR:
298		case CVMX_SFP_CABLE_40G_PSM4:
299		case CVMX_SFP_CABLE_40G_SWDM4:
300			sfp_info->rate = CVMX_SFP_RATE_40G;
301			break;
302		case CVMX_SFP_CABLE_G959_1_P1I1_2D1:
303		case CVMX_SFP_CABLE_G959_1_P1S1_2D2:
304		case CVMX_SFP_CABLE_G959_1_P1L1_2D2:
305		case CVMX_SFP_CABLE_10GBASE_T:
306		case CVMX_SFP_CABLE_10GBASE_T_SR:
307		case CVMX_SFP_CABLE_5GBASE_T:
308		case CVMX_SFP_CABLE_2_5GBASE_T:
309			sfp_info->rate = CVMX_SFP_RATE_10G;
310			break;
311		default:
312			switch (sfp_info->eth_comp) {
313			case CVMX_SFP_CABLE_10GBASE_ER:
314			case CVMX_SFP_CABLE_10GBASE_LRM:
315			case CVMX_SFP_CABLE_10GBASE_LR:
316			case CVMX_SFP_CABLE_10GBASE_SR:
317				sfp_info->rate = CVMX_SFP_RATE_10G;
318				break;
319			default:
320				sfp_info->rate = CVMX_SFP_RATE_UNKNOWN;
321				break;
322			}
323			break;
324		}
325	}
326
327	if (buffer[0xc] < 0xff)
328		sfp_info->bitrate_max = buffer[0xc] * 100;
329	else
330		sfp_info->bitrate_max = buffer[0x42] * 250;
331
332	if ((buffer[8] & 0xc) == 8) {
333		if (buffer[0x3c] & 0x4)
334			sfp_info->limiting = true;
335	}
336
337	/* Currently we only set this for 25G.  FEC is required for CA-S cables
338	 * and for cable lengths >= 5M as of this writing.
339	 */
340	if ((sfp_info->rate == CVMX_SFP_RATE_25G &&
341	     sfp_info->copper_cable) &&
342	    (sfp_info->cable_comp == CVMX_SFP_CABLE_25G_CR_CA_S ||
343	     sfp_info->max_copper_cable_len >= 5))
344		sfp_info->fec_required = true;
345
346	/* copy strings and vendor info, strings will be automatically NUL
347	 * terminated.
348	 */
349	memcpy(sfp_info->vendor_name, &buffer[0x14], 16);
350	memcpy(sfp_info->vendor_oui, &buffer[0x25], 3);
351	memcpy(sfp_info->vendor_pn, &buffer[0x28], 16);
352	memcpy(sfp_info->vendor_rev, &buffer[0x38], 4);
353	memcpy(sfp_info->vendor_sn, &buffer[0x44], 16);
354	memcpy(sfp_info->date_code, &buffer[0x54], 8);
355
356	sfp_info->cooled_laser = !!(buffer[0x40] & 4);
357	sfp_info->internal_cdr = !!(buffer[0x40] & 8);
358
359	if (buffer[0x40] & 0x20)
360		sfp_info->power_level = 3;
361	else
362		sfp_info->power_level = (buffer[0x40] & 2) ? 2 : 1;
363
364	sfp_info->diag_paging = !!(buffer[0x40] & 0x10);
365	sfp_info->linear_rx_output = !(buffer[0x40] & 1);
366	sfp_info->los_implemented = !!(buffer[0x41] & 2);
367	sfp_info->los_inverted = !!(buffer[0x41] & 4);
368	sfp_info->tx_fault_implemented = !!(buffer[0x41] & 8);
369	sfp_info->tx_disable_implemented = !!(buffer[0x41] & 0x10);
370	sfp_info->rate_select_implemented = !!(buffer[0x41] & 0x20);
371	sfp_info->tuneable_transmitter = !!(buffer[0x41] & 0x40);
372	sfp_info->rx_decision_threshold_implemented = !!(buffer[0x41] & 0x80);
373
374	sfp_info->diag_monitoring = !!(buffer[0x5c] & 0x40);
375	sfp_info->diag_rx_power_averaged = !!(buffer[0x5c] & 0x8);
376	sfp_info->diag_externally_calibrated = !!(buffer[0x5c] & 0x10);
377	sfp_info->diag_internally_calibrated = !!(buffer[0x5c] & 0x20);
378	sfp_info->diag_addr_change_required = !!(buffer[0x5c] & 0x4);
379	sfp_info->diag_soft_rate_select_control = !!(buffer[0x5d] & 2);
380	sfp_info->diag_app_select_control = !!(buffer[0x5d] & 4);
381	sfp_info->diag_soft_rate_select_control = !!(buffer[0x5d] & 8);
382	sfp_info->diag_soft_rx_los_implemented = !!(buffer[0x5d] & 0x10);
383	sfp_info->diag_soft_tx_fault_implemented = !!(buffer[0x5d] & 0x20);
384	sfp_info->diag_soft_tx_disable_implemented = !!(buffer[0x5d] & 0x40);
385	sfp_info->diag_alarm_warning_flags_implemented =
386		!!(buffer[0x5d] & 0x80);
387	sfp_info->diag_rev = buffer[0x5e];
388
389	return 0;
390}
391
392static int cvmx_sfp_parse_qsfp_buffer(struct cvmx_sfp_mod_info *sfp_info,
393				      const uint8_t *buffer)
394{
395	u8 csum = 0;
396	bool csum_good = false;
397	int i;
398
399	/* Validate the checksum */
400	for (i = 0x80; i < 0xbf; i++)
401		csum += buffer[i];
402	csum_good = csum == buffer[0xbf];
403	debug("%s: Lower checksum: 0x%02x, expected: 0x%02x\n", __func__, csum,
404	      buffer[0xbf]);
405	csum = 0;
406	for (i = 0xc0; i < 0xdf; i++)
407		csum += buffer[i];
408	debug("%s: Upper checksum: 0x%02x, expected: 0x%02x\n", __func__, csum,
409	      buffer[0xdf]);
410	if (csum != buffer[0xdf] || !csum_good) {
411		debug("Error: SFP EEPROM checksum information is incorrect\n");
412		return -1;
413	}
414
415	sfp_info->conn_type = buffer[0x80];
416	sfp_info->mod_type = buffer[0x82];
417	sfp_info->eth_comp = buffer[0x83] & 0xf0;
418	sfp_info->cable_comp = buffer[0xa4];
419
420	switch (sfp_info->mod_type) {
421	case CVMX_SFP_MOD_COPPER_PIGTAIL:
422	case CVMX_SFP_MOD_NO_SEP_CONN:
423		debug("%s: copper pigtail or no separable cable\n", __func__);
424		/* There are several ways a cable can be marked as active or
425		 * passive.  8.[2-3] specify the SFP+ cable technology.  Some
426		 * modules also use 3.[0-1] for Infiniband, though it's
427		 * redundant.
428		 */
429		sfp_info->copper_cable = true;
430		if ((buffer[0x88] & 0x0C) == 0x08) {
431			sfp_info->limiting = true;
432			sfp_info->active_cable = true;
433		} else if ((buffer[0x88] & 0xC) == 0x4) {
434			sfp_info->limiting = false;
435			sfp_info->active_cable = false;
436		}
437		if ((buffer[0x83] & 3) == 2) {
438			sfp_info->active_cable = true;
439			sfp_info->limiting = true;
440		}
441		break;
442	case CVMX_SFP_MOD_RJ45:
443		debug("%s: RJ45 adapter\n", __func__);
444		sfp_info->copper_cable = true;
445		sfp_info->active_cable = true;
446		sfp_info->limiting = true;
447		break;
448	case CVMX_SFP_MOD_UNKNOWN:
449		debug("Unknown module type\n");
450		/* The Avago 1000Base-X to 1000Base-T module reports that it
451		 * is an unknown module type but the Ethernet compliance code
452		 * says it is 1000Base-T.  We'll change the reporting to RJ45.
453		 */
454		if (buffer[0x86] & 8) {
455			sfp_info->mod_type = CVMX_SFP_MOD_RJ45;
456			sfp_info->copper_cable = false;
457			sfp_info->limiting = true;
458			sfp_info->active_cable = true;
459			sfp_info->max_copper_cable_len = buffer[0x92];
460			sfp_info->rate = CVMX_SFP_RATE_1G;
461		}
462		fallthrough;
463	default:
464		sfp_info->limiting = true;
465		break;
466	}
467
468	if (sfp_info->copper_cable)
469		sfp_info->max_copper_cable_len = buffer[0x92];
470	else
471		sfp_info->max_50um_om4_cable_length = buffer[0x92] * 10;
472
473	debug("%s: copper cable: %d, max copper cable len: %d\n", __func__,
474	      sfp_info->copper_cable, sfp_info->max_copper_cable_len);
475	if (buffer[0xe])
476		sfp_info->max_single_mode_cable_length = buffer[0x8e] * 1000;
477	else
478		sfp_info->max_single_mode_cable_length = buffer[0x8f] * 100000;
479
480	sfp_info->max_50um_om2_cable_length = buffer[0x90] * 10;
481	sfp_info->max_62_5um_om1_cable_length = buffer[0x91] * 10;
482	sfp_info->max_50um_om3_cable_length = buffer[0x93] * 10;
483
484	if (buffer[0x8c] == 12) {
485		sfp_info->rate = CVMX_SFP_RATE_1G;
486	} else if (buffer[0x8c] == 103) {
487		sfp_info->rate = CVMX_SFP_RATE_10G;
488	} else if (buffer[0x8c] == 0xff) {
489		if (buffer[0xc2] == 103)
490			sfp_info->rate = CVMX_SFP_RATE_100G;
491	}
492
493	if (buffer[0x8c] < 0xff)
494		sfp_info->bitrate_max = buffer[0x8c] * 100;
495	else
496		sfp_info->bitrate_max = buffer[0xc2] * 250;
497
498	if ((buffer[0x88] & 0xc) == 8) {
499		if (buffer[0xbc] & 0x4)
500			sfp_info->limiting = true;
501	}
502
503	/* Currently we only set this for 25G.  FEC is required for CA-S cables
504	 * and for cable lengths >= 5M as of this writing.
505	 */
506	/* copy strings and vendor info, strings will be automatically NUL
507	 * terminated.
508	 */
509	memcpy(sfp_info->vendor_name, &buffer[0x94], 16);
510	memcpy(sfp_info->vendor_oui, &buffer[0xa5], 3);
511	memcpy(sfp_info->vendor_pn, &buffer[0xa8], 16);
512	memcpy(sfp_info->vendor_rev, &buffer[0xb8], 4);
513	memcpy(sfp_info->vendor_sn, &buffer[0xc4], 16);
514	memcpy(sfp_info->date_code, &buffer[0xd4], 8);
515
516	sfp_info->linear_rx_output = !!(buffer[0xc0] & 1);
517	sfp_info->cooled_laser = !!(buffer[0xc0] & 4);
518	sfp_info->internal_cdr = !!(buffer[0xc0] & 8);
519
520	if (buffer[0xc0] & 0x20)
521		sfp_info->power_level = 3;
522	else
523		sfp_info->power_level = (buffer[0xc0] & 2) ? 2 : 1;
524
525	sfp_info->diag_paging = !!(buffer[0xc0] & 0x10);
526	sfp_info->los_implemented = !!(buffer[0xc1] & 2);
527	sfp_info->los_inverted = !!(buffer[0xc1] & 4);
528	sfp_info->tx_fault_implemented = !!(buffer[0xc1] & 8);
529	sfp_info->tx_disable_implemented = !!(buffer[0xc1] & 0x10);
530	sfp_info->rate_select_implemented = !!(buffer[0xc1] & 0x20);
531	sfp_info->tuneable_transmitter = !!(buffer[0xc1] & 0x40);
532	sfp_info->rx_decision_threshold_implemented = !!(buffer[0xc1] & 0x80);
533
534	sfp_info->diag_monitoring = !!(buffer[0xdc] & 0x40);
535	sfp_info->diag_rx_power_averaged = !!(buffer[0xdc] & 0x8);
536	sfp_info->diag_externally_calibrated = !!(buffer[0xdc] & 0x10);
537	sfp_info->diag_internally_calibrated = !!(buffer[0xdc] & 0x20);
538	sfp_info->diag_addr_change_required = !!(buffer[0xdc] & 0x4);
539	sfp_info->diag_soft_rate_select_control = !!(buffer[0xdd] & 2);
540	sfp_info->diag_app_select_control = !!(buffer[0xdd] & 4);
541	sfp_info->diag_soft_rate_select_control = !!(buffer[0xdd] & 8);
542	sfp_info->diag_soft_rx_los_implemented = !!(buffer[0xdd] & 0x10);
543	sfp_info->diag_soft_tx_fault_implemented = !!(buffer[0xdd] & 0x20);
544	sfp_info->diag_soft_tx_disable_implemented = !!(buffer[0xdd] & 0x40);
545	sfp_info->diag_alarm_warning_flags_implemented =
546		!!(buffer[0xdd] & 0x80);
547	sfp_info->diag_rev = buffer[0xde];
548
549	return 0;
550}
551
552static bool sfp_verify_checksum(const uint8_t *buffer)
553{
554	u8 csum = 0;
555	u8 offset;
556	bool csum_good = false;
557	int i;
558
559	switch (buffer[0]) {
560	case CVMX_SFP_CONN_QSFP:
561	case CVMX_SFP_CONN_QSFPP:
562	case CVMX_SFP_CONN_QSFP28:
563	case CVMX_SFP_CONN_MICRO_QSFP:
564	case CVMX_SFP_CONN_QSFP_DD:
565		offset = 0x80;
566		break;
567	default:
568		offset = 0;
569		break;
570	}
571	for (i = offset; i < offset + 0x3f; i++)
572		csum += buffer[i];
573	csum_good = csum == buffer[offset + 0x3f];
574	if (!csum_good) {
575		debug("%s: Lower checksum bad, got 0x%x, expected 0x%x\n",
576		      __func__, csum, buffer[offset + 0x3f]);
577		return false;
578	}
579	csum = 0;
580	for (i = offset + 0x40; i < offset + 0x5f; i++)
581		csum += buffer[i];
582	if (csum != buffer[offset + 0x5f]) {
583		debug("%s: Upper checksum bad, got 0x%x, expected 0x%x\n",
584		      __func__, csum, buffer[offset + 0x5f]);
585		return false;
586	}
587	return true;
588}
589
590/**
591 * Reads and parses SFP/QSFP EEPROM
592 *
593 * @param	sfp	sfp handle to read
594 *
595 * @return	0 for success, -1 on error.
596 */
597int cvmx_sfp_read_i2c_eeprom(struct cvmx_fdt_sfp_info *sfp)
598{
599	const struct cvmx_fdt_i2c_bus_info *bus = sfp->i2c_bus;
600	int oct_bus = cvmx_fdt_i2c_get_root_bus(bus);
601	struct udevice *dev;
602	u8 buffer[256];
603	bool is_qsfp;
604	int retry;
605	int err;
606
607	if (!bus) {
608		debug("%s(%s): Error: i2c bus undefined for eeprom\n", __func__,
609		      sfp->name);
610		return -1;
611	}
612
613	is_qsfp = (sfp->sfp_info.conn_type == CVMX_SFP_CONN_QSFP ||
614		   sfp->sfp_info.conn_type == CVMX_SFP_CONN_QSFPP ||
615		   sfp->sfp_info.conn_type == CVMX_SFP_CONN_QSFP28 ||
616		   sfp->sfp_info.conn_type == CVMX_SFP_CONN_MICRO_QSFP) ||
617		  sfp->is_qsfp;
618
619	err = cvmx_qsfp_select(sfp, true);
620	if (err) {
621		debug("%s: Error selecting SFP/QSFP slot\n", __func__);
622		return err;
623	}
624
625	debug("%s: Reading eeprom from i2c address %d:0x%x\n", __func__,
626	      oct_bus, sfp->i2c_eeprom_addr);
627	for (retry = 0; retry < 3; retry++) {
628		err = i2c_get_chip(bus->i2c_bus, sfp->i2c_eeprom_addr, 1, &dev);
629		if (err) {
630			debug("Cannot find I2C device: %d\n", err);
631			goto error;
632		}
633
634		err = dm_i2c_read(dev, 0, buffer, 256);
635		if (err || !sfp_verify_checksum(buffer)) {
636			debug("%s: Error %d reading eeprom at 0x%x, bus %d\n",
637			      __func__, err, sfp->i2c_eeprom_addr, oct_bus);
638			debug("%s: Retry %d\n", __func__, retry + 1);
639			mdelay(1000);
640		} else {
641			break;
642		}
643	}
644	if (err) {
645		debug("%s: Error reading eeprom from SFP %s\n", __func__,
646		      sfp->name);
647		return -1;
648	}
649#ifdef DEBUG
650	print_buffer(0, buffer, 1, 256, 0);
651#endif
652	memset(&sfp->sfp_info, 0, sizeof(struct cvmx_sfp_mod_info));
653
654	switch (buffer[0]) {
655	case CVMX_SFP_CONN_SFP:
656		err = cvmx_sfp_parse_sfp_buffer(&sfp->sfp_info, buffer);
657		break;
658	case CVMX_SFP_CONN_QSFP:
659	case CVMX_SFP_CONN_QSFPP:
660	case CVMX_SFP_CONN_QSFP28:
661	case CVMX_SFP_CONN_MICRO_QSFP:
662		err = cvmx_sfp_parse_qsfp_buffer(&sfp->sfp_info, buffer);
663		break;
664	default:
665		debug("%s: Unknown SFP transceiver type 0x%x\n", __func__,
666		      buffer[0]);
667		err = -1;
668		break;
669	}
670
671error:
672	if (is_qsfp)
673		err |= cvmx_qsfp_select(sfp, false);
674
675	if (!err) {
676		sfp->valid = true;
677		sfp->sfp_info.valid = true;
678	} else {
679		sfp->valid = false;
680		sfp->sfp_info.valid = false;
681	}
682
683	return err;
684}
685
686/**
687 * Function called to check and return the status of the mod_abs pin or
688 * mod_pres pin for QSFPs.
689 *
690 * @param	sfp	Handle to SFP information.
691 * @param	data	User-defined data passed to the function
692 *
693 * @return	0 if absent, 1 if present, -1 on error
694 */
695int cvmx_sfp_check_mod_abs(struct cvmx_fdt_sfp_info *sfp, void *data)
696{
697	int val;
698	int err = 0;
699	int mode;
700
701	if (!dm_gpio_is_valid(&sfp->mod_abs)) {
702		debug("%s: Error: mod_abs not set for %s\n", __func__,
703		      sfp->name);
704		return -1;
705	}
706	val = dm_gpio_get_value(&sfp->mod_abs);
707	debug("%s(%s, %p) mod_abs: %d\n", __func__, sfp->name, data, val);
708	if (val >= 0 && val != sfp->last_mod_abs && sfp->mod_abs_changed) {
709		err = 0;
710		if (!val) {
711			err = cvmx_sfp_read_i2c_eeprom(sfp);
712			if (err)
713				debug("%s: Error reading SFP %s EEPROM\n",
714				      __func__, sfp->name);
715		}
716		err = sfp->mod_abs_changed(sfp, val, sfp->mod_abs_changed_data);
717	}
718	debug("%s(%s (%p)): Last mod_abs: %d, current: %d, changed: %p, rc: %d, next: %p, caller: %p\n",
719	      __func__, sfp->name, sfp, sfp->last_mod_abs, val,
720	      sfp->mod_abs_changed, err, sfp->next_iface_sfp,
721	      __builtin_return_address(0));
722
723	if (err >= 0) {
724		sfp->last_mod_abs = val;
725		mode = cvmx_helper_interface_get_mode(sfp->xiface);
726		cvmx_sfp_validate_module(sfp, mode);
727	} else {
728		debug("%s: mod_abs_changed for %s returned error\n", __func__,
729		      sfp->name);
730	}
731
732	return err < 0 ? err : val;
733}
734
735/**
736 * Reads the EEPROMs of all SFP modules.
737 *
738 * @return 0 for success
739 */
740int cvmx_sfp_read_all_modules(void)
741{
742	struct cvmx_fdt_sfp_info *sfp;
743	int val;
744	bool error = false;
745	int rc;
746
747	for (sfp = sfp_list; sfp; sfp = sfp->next) {
748		if (dm_gpio_is_valid(&sfp->mod_abs)) {
749			/* Check if module absent */
750			val = dm_gpio_get_value(&sfp->mod_abs);
751			sfp->last_mod_abs = val;
752			if (val)
753				continue;
754		}
755		rc = cvmx_sfp_read_i2c_eeprom(sfp);
756		if (rc) {
757			debug("%s: Error reading eeprom from SFP %s\n",
758			      __func__, sfp->name);
759			error = true;
760		}
761	}
762
763	return error ? -1 : 0;
764}
765
766/**
767 * Registers a function to be called whenever the mod_abs/mod_pres signal
768 * changes.
769 *
770 * @param	sfp		Handle to SFP data structure
771 * @param	mod_abs_changed	Function called whenever mod_abs is changed
772 *				or NULL to remove.
773 * @param	mod_abs_changed_data	User-defined data passed to
774 *					mod_abs_changed
775 *
776 * @return	0 for success
777 *
778 * @NOTE: If multiple SFP slots are linked together, all subsequent slots
779 *	  will also be registered for the same handler.
780 */
781int cvmx_sfp_register_mod_abs_changed(struct cvmx_fdt_sfp_info *sfp,
782				      int (*mod_abs_changed)(struct cvmx_fdt_sfp_info *sfp,
783							     int val, void *data),
784				      void *mod_abs_changed_data)
785{
786	sfp->mod_abs_changed = mod_abs_changed;
787	sfp->mod_abs_changed_data = mod_abs_changed_data;
788
789	sfp->last_mod_abs = -2; /* undefined */
790
791	return 0;
792}
793
794/**
795 * Parses a SFP slot from the device tree
796 *
797 * @param	sfp		SFP handle to store data in
798 * @param	fdt_addr	Address of flat device tree
799 * @param	of_offset	Node in device tree for SFP slot
800 *
801 * @return	0 on success, -1 on error
802 */
803static int cvmx_sfp_parse_sfp(struct cvmx_fdt_sfp_info *sfp, ofnode node)
804{
805	struct ofnode_phandle_args phandle;
806	int err;
807
808	sfp->name = ofnode_get_name(node);
809	sfp->of_offset = ofnode_to_offset(node);
810
811	err = gpio_request_by_name_nodev(node, "tx_disable", 0,
812					 &sfp->tx_disable, GPIOD_IS_OUT);
813	if (err) {
814		printf("%s: tx_disable not found in DT!\n", __func__);
815		return -ENODEV;
816	}
817	dm_gpio_set_value(&sfp->tx_disable, 0);
818
819	err = gpio_request_by_name_nodev(node, "mod_abs", 0,
820					 &sfp->mod_abs, GPIOD_IS_IN);
821	if (err) {
822		printf("%s: mod_abs not found in DT!\n", __func__);
823		return -ENODEV;
824	}
825
826	err = gpio_request_by_name_nodev(node, "tx_error", 0,
827					 &sfp->tx_error, GPIOD_IS_IN);
828	if (err) {
829		printf("%s: tx_error not found in DT!\n", __func__);
830		return -ENODEV;
831	}
832
833	err = gpio_request_by_name_nodev(node, "rx_los", 0,
834					 &sfp->rx_los, GPIOD_IS_IN);
835	if (err) {
836		printf("%s: rx_los not found in DT!\n", __func__);
837		return -ENODEV;
838	}
839
840	err = ofnode_parse_phandle_with_args(node, "eeprom", NULL, 0, 0,
841					     &phandle);
842	if (!err) {
843		sfp->i2c_eeprom_addr = ofnode_get_addr(phandle.node);
844		debug("%s: eeprom address: 0x%x\n", __func__,
845		      sfp->i2c_eeprom_addr);
846
847		debug("%s: Getting eeprom i2c bus for %s\n", __func__,
848		      sfp->name);
849		sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node));
850	}
851
852	err = ofnode_parse_phandle_with_args(node, "diag", NULL, 0, 0,
853					     &phandle);
854	if (!err) {
855		sfp->i2c_diag_addr = ofnode_get_addr(phandle.node);
856		if (!sfp->i2c_bus)
857			sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node));
858	}
859
860	sfp->last_mod_abs = -2;
861	sfp->last_rx_los = -2;
862
863	if (!sfp->i2c_bus) {
864		debug("%s(%s): Error: could not get i2c bus from device tree\n",
865		      __func__, sfp->name);
866		err = -1;
867	}
868
869	if (err) {
870		dm_gpio_free(sfp->tx_disable.dev, &sfp->tx_disable);
871		dm_gpio_free(sfp->mod_abs.dev, &sfp->mod_abs);
872		dm_gpio_free(sfp->tx_error.dev, &sfp->tx_error);
873		dm_gpio_free(sfp->rx_los.dev, &sfp->rx_los);
874	} else {
875		sfp->valid = true;
876	}
877
878	return err;
879}
880
881/**
882 * Parses a QSFP slot from the device tree
883 *
884 * @param	sfp		SFP handle to store data in
885 * @param	fdt_addr	Address of flat device tree
886 * @param	of_offset	Node in device tree for SFP slot
887 *
888 * @return	0 on success, -1 on error
889 */
890static int cvmx_sfp_parse_qsfp(struct cvmx_fdt_sfp_info *sfp, ofnode node)
891{
892	struct ofnode_phandle_args phandle;
893	int err;
894
895	sfp->is_qsfp = true;
896	sfp->name = ofnode_get_name(node);
897	sfp->of_offset = ofnode_to_offset(node);
898
899	err = gpio_request_by_name_nodev(node, "lp_mode", 0,
900					 &sfp->lp_mode, GPIOD_IS_OUT);
901	if (err) {
902		printf("%s: lp_mode not found in DT!\n", __func__);
903		return -ENODEV;
904	}
905
906	err = gpio_request_by_name_nodev(node, "mod_prs", 0,
907					 &sfp->mod_abs, GPIOD_IS_IN);
908	if (err) {
909		printf("%s: mod_prs not found in DT!\n", __func__);
910		return -ENODEV;
911	}
912
913	err = gpio_request_by_name_nodev(node, "select", 0,
914					 &sfp->select, GPIOD_IS_IN);
915	if (err) {
916		printf("%s: select not found in DT!\n", __func__);
917		return -ENODEV;
918	}
919
920	err = gpio_request_by_name_nodev(node, "reset", 0,
921					 &sfp->reset, GPIOD_IS_OUT);
922	if (err) {
923		printf("%s: reset not found in DT!\n", __func__);
924		return -ENODEV;
925	}
926
927	err = gpio_request_by_name_nodev(node, "interrupt", 0,
928					 &sfp->interrupt, GPIOD_IS_IN);
929	if (err) {
930		printf("%s: interrupt not found in DT!\n", __func__);
931		return -ENODEV;
932	}
933
934	err = ofnode_parse_phandle_with_args(node, "eeprom", NULL, 0, 0,
935					     &phandle);
936	if (!err) {
937		sfp->i2c_eeprom_addr = ofnode_get_addr(phandle.node);
938		sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node));
939	}
940
941	err = ofnode_parse_phandle_with_args(node, "diag", NULL, 0, 0,
942					     &phandle);
943	if (!err) {
944		sfp->i2c_diag_addr = ofnode_get_addr(phandle.node);
945		if (!sfp->i2c_bus)
946			sfp->i2c_bus = cvmx_ofnode_get_i2c_bus(ofnode_get_parent(phandle.node));
947	}
948
949	sfp->last_mod_abs = -2;
950	sfp->last_rx_los = -2;
951
952	if (!sfp->i2c_bus) {
953		cvmx_printf("%s(%s): Error: could not get i2c bus from device tree\n",
954			    __func__, sfp->name);
955		err = -1;
956	}
957
958	if (err) {
959		dm_gpio_free(sfp->lp_mode.dev, &sfp->lp_mode);
960		dm_gpio_free(sfp->mod_abs.dev, &sfp->mod_abs);
961		dm_gpio_free(sfp->select.dev, &sfp->select);
962		dm_gpio_free(sfp->reset.dev, &sfp->reset);
963		dm_gpio_free(sfp->interrupt.dev, &sfp->interrupt);
964	} else {
965		sfp->valid = true;
966	}
967
968	return err;
969}
970
971/**
972 * Parses the device tree for SFP and QSFP slots
973 *
974 * @param	fdt_addr	Address of flat device-tree
975 *
976 * @return	0 for success, -1 on error
977 */
978int cvmx_sfp_parse_device_tree(const void *fdt_addr)
979{
980	struct cvmx_fdt_sfp_info *sfp, *first_sfp = NULL, *last_sfp = NULL;
981	ofnode node;
982	int err = 0;
983	int reg;
984	static bool parsed;
985
986	debug("%s(%p): Parsing...\n", __func__, fdt_addr);
987	if (parsed) {
988		debug("%s(%p): Already parsed\n", __func__, fdt_addr);
989		return 0;
990	}
991
992	ofnode_for_each_compatible_node(node, "ethernet,sfp-slot") {
993		if (!ofnode_valid(node))
994			continue;
995
996		sfp = cvm_sfp_alloc(sizeof(*sfp));
997		if (!sfp)
998			return -1;
999
1000		err = cvmx_sfp_parse_sfp(sfp, node);
1001		if (!err) {
1002			if (!sfp_list)
1003				sfp_list = sfp;
1004			if (last_sfp)
1005				last_sfp->next = sfp;
1006			sfp->prev = last_sfp;
1007			last_sfp = sfp;
1008			debug("%s: parsed %s\n", __func__, sfp->name);
1009		} else {
1010			debug("%s: Error parsing SFP at node %s\n",
1011			      __func__, ofnode_get_name(node));
1012			return err;
1013		}
1014	}
1015
1016	ofnode_for_each_compatible_node(node, "ethernet,qsfp-slot") {
1017		if (!ofnode_valid(node))
1018			continue;
1019
1020		sfp = cvm_sfp_alloc(sizeof(*sfp));
1021		if (!sfp)
1022			return -1;
1023
1024		err = cvmx_sfp_parse_qsfp(sfp, node);
1025		if (!err) {
1026			if (!sfp_list)
1027				sfp_list = sfp;
1028			if (last_sfp)
1029				last_sfp->next = sfp;
1030			sfp->prev = last_sfp;
1031			last_sfp = sfp;
1032			debug("%s: parsed %s\n", __func__, sfp->name);
1033		} else {
1034			debug("%s: Error parsing QSFP at node %s\n",
1035			      __func__, ofnode_get_name(node));
1036			return err;
1037		}
1038	}
1039
1040	if (!octeon_has_feature(OCTEON_FEATURE_BGX))
1041		return 0;
1042
1043	err = 0;
1044	ofnode_for_each_compatible_node(node, "cavium,octeon-7890-bgx-port") {
1045		int sfp_nodes[4];
1046		ofnode sfp_ofnodes[4];
1047		int num_sfp_nodes;
1048		u64 reg_addr;
1049		struct cvmx_xiface xi;
1050		int xiface, index;
1051		cvmx_helper_interface_mode_t mode;
1052		int i;
1053		int rc;
1054
1055		if (!ofnode_valid(node))
1056			break;
1057
1058		num_sfp_nodes = ARRAY_SIZE(sfp_nodes);
1059		rc = cvmx_ofnode_lookup_phandles(node, "sfp-slot",
1060						 &num_sfp_nodes, sfp_ofnodes);
1061		if (rc != 0 || num_sfp_nodes < 1)
1062			rc = cvmx_ofnode_lookup_phandles(node, "qsfp-slot",
1063							 &num_sfp_nodes,
1064							 sfp_ofnodes);
1065		/* If no SFP or QSFP slot found, go to next port */
1066		if (rc < 0)
1067			continue;
1068
1069		last_sfp = NULL;
1070		for (i = 0; i < num_sfp_nodes; i++) {
1071			sfp = cvmx_sfp_find_slot_by_fdt_node(ofnode_to_offset(sfp_ofnodes[i]));
1072			debug("%s: Adding sfp %s (%p) to BGX port\n",
1073			      __func__, sfp->name, sfp);
1074			if (last_sfp)
1075				last_sfp->next_iface_sfp = sfp;
1076			else
1077				first_sfp = sfp;
1078			last_sfp = sfp;
1079		}
1080		if (!first_sfp) {
1081			debug("%s: Error: could not find SFP slot for BGX port %s\n",
1082			      __func__,
1083			      fdt_get_name(fdt_addr, sfp_nodes[0],
1084					   NULL));
1085			err = -1;
1086			break;
1087		}
1088
1089		/* Get the port index */
1090		reg = ofnode_get_addr(node);
1091		if (reg < 0) {
1092			debug("%s: Error: could not get BGX port reg value\n",
1093			      __func__);
1094			err = -1;
1095			break;
1096		}
1097		index = reg;
1098
1099		/* Get BGX node and address */
1100		reg_addr = ofnode_get_addr(ofnode_get_parent(node));
1101		/* Extrace node */
1102		xi.node = cvmx_csr_addr_to_node(reg_addr);
1103		/* Extract reg address */
1104		reg_addr = cvmx_csr_addr_strip_node(reg_addr);
1105		if ((reg_addr & 0xFFFFFFFFF0000000) !=
1106		    0x00011800E0000000) {
1107			debug("%s: Invalid BGX address 0x%llx\n",
1108			      __func__, (unsigned long long)reg_addr);
1109			xi.node = -1;
1110			err = -1;
1111			break;
1112		}
1113
1114		/* Extract interface from address */
1115		xi.interface = (reg_addr >> 24) & 0x0F;
1116		/* Convert to xiface */
1117		xiface = cvmx_helper_node_interface_to_xiface(xi.node,
1118							      xi.interface);
1119		debug("%s: Parsed %d SFP slots for interface 0x%x, index %d\n",
1120		      __func__, num_sfp_nodes, xiface, index);
1121
1122		mode = cvmx_helper_interface_get_mode(xiface);
1123		for (sfp = first_sfp; sfp; sfp = sfp->next_iface_sfp) {
1124			sfp->xiface = xiface;
1125			sfp->index = index;
1126			/* Convert to IPD port */
1127			sfp->ipd_port[0] =
1128				cvmx_helper_get_ipd_port(xiface, index);
1129			debug("%s: sfp %s (%p) xi: 0x%x, index: 0x%x, node: %d, mode: 0x%x, next: %p\n",
1130			      __func__, sfp->name, sfp, sfp->xiface,
1131			      sfp->index, xi.node, mode,
1132			      sfp->next_iface_sfp);
1133			if (mode == CVMX_HELPER_INTERFACE_MODE_XLAUI ||
1134			    mode == CVMX_HELPER_INTERFACE_MODE_40G_KR4)
1135				for (i = 1; i < 4; i++)
1136					sfp->ipd_port[i] = -1;
1137			else
1138				for (i = 1; i < 4; i++)
1139					sfp->ipd_port[i] =
1140						cvmx_helper_get_ipd_port(
1141							xiface, i);
1142		}
1143		cvmx_helper_cfg_set_sfp_info(xiface, index, first_sfp);
1144	}
1145
1146	if (!err) {
1147		parsed = true;
1148		cvmx_sfp_read_all_modules();
1149	}
1150
1151	return err;
1152}
1153
1154/**
1155 * Given a fdt node offset find the corresponding SFP or QSFP slot
1156 *
1157 * @param	of_offset	flat device tree node offset
1158 *
1159 * @return	pointer to SFP data structure or NULL if not found
1160 */
1161struct cvmx_fdt_sfp_info *cvmx_sfp_find_slot_by_fdt_node(int of_offset)
1162{
1163	struct cvmx_fdt_sfp_info *sfp = sfp_list;
1164
1165	while (sfp) {
1166		if (sfp->of_offset == of_offset)
1167			return sfp;
1168		sfp = sfp->next;
1169	}
1170	return NULL;
1171}
1172
1173static bool cvmx_sfp_validate_quad(struct cvmx_fdt_sfp_info *sfp,
1174				   struct cvmx_phy_gpio_leds *leds)
1175{
1176	bool multi_led = leds && (leds->next);
1177	bool error = false;
1178	int mod_abs;
1179
1180	do {
1181		/* Skip missing modules */
1182		if (dm_gpio_is_valid(&sfp->mod_abs))
1183			mod_abs = dm_gpio_get_value(&sfp->mod_abs);
1184		else
1185			mod_abs = 0;
1186		if (!mod_abs) {
1187			if (cvmx_sfp_read_i2c_eeprom(sfp)) {
1188				debug("%s: Error reading eeprom for %s\n",
1189				      __func__, sfp->name);
1190			}
1191			if (sfp->sfp_info.rate < CVMX_SFP_RATE_10G) {
1192				cvmx_helper_leds_show_error(leds, true);
1193				error = true;
1194			} else if (sfp->sfp_info.rate >= CVMX_SFP_RATE_10G) {
1195				/* We don't support 10GBase-T modules in
1196				 * this mode.
1197				 */
1198				switch (sfp->sfp_info.cable_comp) {
1199				case CVMX_SFP_CABLE_10GBASE_T:
1200				case CVMX_SFP_CABLE_10GBASE_T_SR:
1201				case CVMX_SFP_CABLE_5GBASE_T:
1202				case CVMX_SFP_CABLE_2_5GBASE_T:
1203					cvmx_helper_leds_show_error(leds, true);
1204					error = true;
1205					break;
1206				default:
1207					break;
1208				}
1209			}
1210		} else if (multi_led) {
1211			cvmx_helper_leds_show_error(leds, false);
1212		}
1213
1214		if (multi_led && leds->next)
1215			leds = leds->next;
1216		sfp = sfp->next_iface_sfp;
1217	} while (sfp);
1218
1219	if (!multi_led)
1220		cvmx_helper_leds_show_error(leds, error);
1221
1222	return error;
1223}
1224
1225/**
1226 * Validates if the module is correct for the specified port
1227 *
1228 * @param[in]	sfp	SFP port to check
1229 * @param	xiface	interface
1230 * @param	index	port index
1231 * @param	speed	link speed, -1 if unknown
1232 * @param	mode	interface mode
1233 *
1234 * @return	true if module is valid, false if invalid
1235 * NOTE: This will also toggle the error LED, if present
1236 */
1237bool cvmx_sfp_validate_module(struct cvmx_fdt_sfp_info *sfp, int mode)
1238{
1239	const struct cvmx_sfp_mod_info *mod_info = &sfp->sfp_info;
1240	int xiface = sfp->xiface;
1241	int index = sfp->index;
1242	struct cvmx_phy_gpio_leds *leds;
1243	bool error = false;
1244	bool quad_mode = false;
1245
1246	debug("%s(%s, 0x%x, 0x%x, 0x%x)\n", __func__, sfp->name, xiface, index,
1247	      mode);
1248	if (!sfp) {
1249		debug("%s: Error: sfp is NULL\n", __func__);
1250		return false;
1251	}
1252	/* No module is valid */
1253	leds = cvmx_helper_get_port_phy_leds(xiface, index);
1254	if (!leds)
1255		debug("%s: No leds for 0x%x:0x%x\n", __func__, xiface, index);
1256
1257	if (mode != CVMX_HELPER_INTERFACE_MODE_XLAUI &&
1258	    mode != CVMX_HELPER_INTERFACE_MODE_40G_KR4 && !sfp->is_qsfp &&
1259	    sfp->last_mod_abs && leds) {
1260		cvmx_helper_leds_show_error(leds, false);
1261		debug("%s: %s: last_mod_abs: %d, no error\n", __func__,
1262		      sfp->name, sfp->last_mod_abs);
1263		return true;
1264	}
1265
1266	switch (mode) {
1267	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1268	case CVMX_HELPER_INTERFACE_MODE_GMII:
1269	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1270	case CVMX_HELPER_INTERFACE_MODE_QSGMII:
1271	case CVMX_HELPER_INTERFACE_MODE_AGL:
1272	case CVMX_HELPER_INTERFACE_MODE_SPI:
1273		if ((mod_info->active_cable &&
1274		     mod_info->rate != CVMX_SFP_RATE_1G) ||
1275		    mod_info->rate < CVMX_SFP_RATE_1G)
1276			error = true;
1277		break;
1278	case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1279	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1280	case CVMX_HELPER_INTERFACE_MODE_10G_KR:
1281	case CVMX_HELPER_INTERFACE_MODE_XFI:
1282		if ((mod_info->active_cable &&
1283		     mod_info->rate != CVMX_SFP_RATE_10G) ||
1284		    mod_info->rate < CVMX_SFP_RATE_10G)
1285			error = true;
1286		break;
1287	case CVMX_HELPER_INTERFACE_MODE_XLAUI:
1288	case CVMX_HELPER_INTERFACE_MODE_40G_KR4:
1289		if (!sfp->is_qsfp) {
1290			quad_mode = true;
1291			error = cvmx_sfp_validate_quad(sfp, leds);
1292		} else {
1293			if ((mod_info->active_cable &&
1294			     mod_info->rate != CVMX_SFP_RATE_40G) ||
1295			    mod_info->rate < CVMX_SFP_RATE_25G)
1296				error = true;
1297		}
1298		break;
1299	default:
1300		debug("%s: Unsupported interface mode %d on xiface 0x%x\n",
1301		      __func__, mode, xiface);
1302		return false;
1303	}
1304	debug("%s: %s: error: %d\n", __func__, sfp->name, error);
1305	if (leds && !quad_mode)
1306		cvmx_helper_leds_show_error(leds, error);
1307
1308	return !error;
1309}
1310