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 
31 extern void octeon_i2c_unblock(int bus);
32 
33 static 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  */
cvm_sfp_alloc(size_t size)43 static 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  */
cvm_sfp_free(void * ptr,size_t size)57 static 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  */
cvmx_qsfp_select(const struct cvmx_fdt_sfp_info * sfp,bool enable)70 static 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 
cvmx_sfp_parse_sfp_buffer(struct cvmx_sfp_mod_info * sfp_info,const uint8_t * buffer)87 static 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 
cvmx_sfp_parse_qsfp_buffer(struct cvmx_sfp_mod_info * sfp_info,const uint8_t * buffer)392 static 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 
sfp_verify_checksum(const uint8_t * buffer)552 static 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  */
cvmx_sfp_read_i2c_eeprom(struct cvmx_fdt_sfp_info * sfp)597 int 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 
671 error:
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  */
cvmx_sfp_check_mod_abs(struct cvmx_fdt_sfp_info * sfp,void * data)695 int 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  */
cvmx_sfp_read_all_modules(void)740 int 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  */
cvmx_sfp_register_mod_abs_changed(struct cvmx_fdt_sfp_info * sfp,int (* mod_abs_changed)(struct cvmx_fdt_sfp_info * sfp,int val,void * data),void * mod_abs_changed_data)781 int 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  */
cvmx_sfp_parse_sfp(struct cvmx_fdt_sfp_info * sfp,ofnode node)803 static 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  */
cvmx_sfp_parse_qsfp(struct cvmx_fdt_sfp_info * sfp,ofnode node)890 static 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  */
cvmx_sfp_parse_device_tree(const void * fdt_addr)978 int 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  */
cvmx_sfp_find_slot_by_fdt_node(int of_offset)1161 struct 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 
cvmx_sfp_validate_quad(struct cvmx_fdt_sfp_info * sfp,struct cvmx_phy_gpio_leds * leds)1173 static 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  */
cvmx_sfp_validate_module(struct cvmx_fdt_sfp_info * sfp,int mode)1237 bool 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