xref: /freebsd/sys/dev/al_eth/al_init_eth_lm.c (revision 076ad2f8)
1 /*-
2  * Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates
3  * All rights reserved.
4  *
5  * Developed by Semihalf.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include "al_init_eth_lm.h"
33 #include "al_serdes.h"
34 #include "al_hal_eth.h"
35 #include "al_init_eth_kr.h"
36 
37 /**
38  *  @{
39  * @file   al_init_eth_lm.c
40  *
41  * @brief ethernet link management common utilities
42  *
43  */
44 
45 /* delay before checking link status with new serdes parameters (uSec) */
46 #define	AL_ETH_LM_LINK_STATUS_DELAY	1000
47 /* delay before checking link status after reconfiguring the retimer (uSec) */
48 #define	AL_ETH_LM_RETIMER_LINK_STATUS_DELAY 50000
49 
50 #define	AL_ETH_LM_EQ_ITERATIONS		15
51 #define	AL_ETH_LM_MAX_DCGAIN		8
52 
53 /* num of link training failures till serdes reset */
54 #define	AL_ETH_LT_FAILURES_TO_RESET	10
55 
56 #define	MODULE_IDENTIFIER_IDX		0
57 #define	MODULE_IDENTIFIER_SFP		0x3
58 #define	MODULE_IDENTIFIER_QSFP		0xd
59 
60 #define	SFP_PRESENT			0
61 #define	SFP_NOT_PRESENT			1
62 
63 /* SFP+ module */
64 #define	SFP_I2C_HEADER_10G_IDX		3
65 #define	SFP_I2C_HEADER_10G_DA_IDX	8
66 #define	SFP_I2C_HEADER_10G_DA_LEN_IDX	18
67 #define	SFP_I2C_HEADER_1G_IDX		6
68 #define	SFP_I2C_HEADER_SIGNAL_RATE	12 /* Nominal signaling rate, units of 100MBd. */
69 
70 #define	SFP_MIN_SIGNAL_RATE_25G		250
71 #define	SFP_MIN_SIGNAL_RATE_10G		100
72 
73 /* QSFP+ module */
74 #define	QSFP_COMPLIANCE_CODE_IDX	131
75 /* 40GBASE-LR4 and 40GBASE-SR4 are optic modules */
76 #define	QSFP_COMPLIANCE_CODE_OPTIC	((1 << 1) | (1 << 2))
77 #define	QSFP_COMPLIANCE_CODE_DAC	(1 << 3)
78 #define	QSFP_CABLE_LEN_IDX		146
79 
80 /* TODO: need to check the necessary delay */
81 #define	AL_ETH_LM_RETIMER_WAIT_FOR_LOCK	500 /* delay after retimer reset to lock (mSec) */
82 #define	AL_ETH_LM_SERDES_WAIT_FOR_LOCK	50 /* delay after signal detect to lock (mSec) */
83 
84 #define AL_ETH_LM_GEARBOX_RESET_DELAY	1000 /* (uSec) */
85 
86 static const uint32_t
87 al_eth_retimer_boost_addr[AL_ETH_RETIMER_CHANNEL_MAX][AL_ETH_RETIMER_TYPE_MAX] = {
88 					/* BR_210  |  BR_410 */
89 	/* AL_ETH_RETIMER_CHANNEL_A */	{0xf,		0x1a},
90 	/* AL_ETH_RETIMER_CHANNEL_B */	{0x16,		0x18},
91 	/* AL_ETH_RETIMER_CHANNEL_C */	{0x0,		0x16},
92 	/* AL_ETH_RETIMER_CHANNEL_D */	{0x0,		0x14},
93 };
94 
95 #define	RETIMER_LENS_MAX		5
96 static const uint32_t
97 al_eth_retimer_boost_lens[RETIMER_LENS_MAX] = {0, 1, 2, 3, 5};
98 
99 static const uint32_t
100 al_eth_retimer_boost_value[RETIMER_LENS_MAX + 1][AL_ETH_RETIMER_TYPE_MAX] = {
101 		/* BR_210  |  BR_410 */
102 	/* 0 */	{0x0,		0x0},
103 	/* 1 */	{0x1,		0x1},
104 	/* 2 */	{0x2,		0x1},
105 	/* 3 */	{0x3,		0x3},
106 	/* 5 */	{0x7,		0x3},
107 	/* 5+ */{0xb,		0x7},
108 };
109 
110 struct retimer_config_reg {
111 	uint8_t addr;
112 	uint8_t value;
113 	uint8_t mask;
114 };
115 
116 static struct retimer_config_reg retimer_ds25_25g_mode_tx_ch[] = {
117 	{.addr = 0x0A, .value = 0x0C, .mask = 0xff },
118 	{.addr = 0x2F, .value = 0x54, .mask = 0xff },
119 	{.addr = 0x31, .value = 0x20, .mask = 0xff },
120 	{.addr = 0x1E, .value = 0xE9, .mask = 0xff },
121 	{.addr = 0x1F, .value = 0x0B, .mask = 0xff },
122 	{.addr = 0xA6, .value = 0x43, .mask = 0xff },
123 	{.addr = 0x2A, .value = 0x5A, .mask = 0xff },
124 	{.addr = 0x2B, .value = 0x0A, .mask = 0xff },
125 	{.addr = 0x2C, .value = 0xF6, .mask = 0xff },
126 	{.addr = 0x70, .value = 0x05, .mask = 0xff },
127 	{.addr = 0x6A, .value = 0x21, .mask = 0xff },
128 	{.addr = 0x35, .value = 0x0F, .mask = 0xff },
129 	{.addr = 0x12, .value = 0x83, .mask = 0xff },
130 	{.addr = 0x9C, .value = 0x24, .mask = 0xff },
131 	{.addr = 0x98, .value = 0x00, .mask = 0xff },
132 	{.addr = 0x42, .value = 0x50, .mask = 0xff },
133 	{.addr = 0x44, .value = 0x90, .mask = 0xff },
134 	{.addr = 0x45, .value = 0xC0, .mask = 0xff },
135 	{.addr = 0x46, .value = 0xD0, .mask = 0xff },
136 	{.addr = 0x47, .value = 0xD1, .mask = 0xff },
137 	{.addr = 0x48, .value = 0xD5, .mask = 0xff },
138 	{.addr = 0x49, .value = 0xD8, .mask = 0xff },
139 	{.addr = 0x4A, .value = 0xEA, .mask = 0xff },
140 	{.addr = 0x4B, .value = 0xF7, .mask = 0xff },
141 	{.addr = 0x4C, .value = 0xFD, .mask = 0xff },
142 	{.addr = 0x8E, .value = 0x00, .mask = 0xff },
143 	{.addr = 0x3D, .value = 0x94, .mask = 0xff },
144 	{.addr = 0x3F, .value = 0x40, .mask = 0xff },
145 	{.addr = 0x3E, .value = 0x43, .mask = 0xff },
146 	{.addr = 0x0A, .value = 0x00, .mask = 0xff },
147 };
148 
149 static struct retimer_config_reg retimer_ds25_25g_mode_rx_ch[] = {
150 	{.addr = 0x0A, .value = 0x0C, .mask = 0xff},
151 	{.addr = 0x2F, .value = 0x54, .mask = 0xff},
152 	{.addr = 0x31, .value = 0x40, .mask = 0xff},
153 	{.addr = 0x1E, .value = 0xE3, .mask = 0xff},
154 	{.addr = 0x1F, .value = 0x0B, .mask = 0xff},
155 	{.addr = 0xA6, .value = 0x43, .mask = 0xff},
156 	{.addr = 0x2A, .value = 0x5A, .mask = 0xff},
157 	{.addr = 0x2B, .value = 0x0A, .mask = 0xff},
158 	{.addr = 0x2C, .value = 0xF6, .mask = 0xff},
159 	{.addr = 0x70, .value = 0x05, .mask = 0xff},
160 	{.addr = 0x6A, .value = 0x21, .mask = 0xff},
161 	{.addr = 0x35, .value = 0x0F, .mask = 0xff},
162 	{.addr = 0x12, .value = 0x83, .mask = 0xff},
163 	{.addr = 0x9C, .value = 0x24, .mask = 0xff},
164 	{.addr = 0x98, .value = 0x00, .mask = 0xff},
165 	{.addr = 0x42, .value = 0x50, .mask = 0xff},
166 	{.addr = 0x44, .value = 0x90, .mask = 0xff},
167 	{.addr = 0x45, .value = 0xC0, .mask = 0xff},
168 	{.addr = 0x46, .value = 0xD0, .mask = 0xff},
169 	{.addr = 0x47, .value = 0xD1, .mask = 0xff},
170 	{.addr = 0x48, .value = 0xD5, .mask = 0xff},
171 	{.addr = 0x49, .value = 0xD8, .mask = 0xff},
172 	{.addr = 0x4A, .value = 0xEA, .mask = 0xff},
173 	{.addr = 0x4B, .value = 0xF7, .mask = 0xff},
174 	{.addr = 0x4C, .value = 0xFD, .mask = 0xff},
175 	{.addr = 0x8E, .value = 0x00, .mask = 0xff},
176 	{.addr = 0x3D, .value = 0x94, .mask = 0xff},
177 	{.addr = 0x3F, .value = 0x40, .mask = 0xff},
178 	{.addr = 0x3E, .value = 0x43, .mask = 0xff},
179 	{.addr = 0x0A, .value = 0x00, .mask = 0xff},
180 };
181 
182 static struct retimer_config_reg retimer_ds25_10g_mode[] = {
183 	/* Assert CDR reset (6.3) */
184 	{.addr = 0x0A, .value = 0x0C, .mask = 0x0C},
185 	/* Select 10.3125Gbps standard rate mode (6.6) */
186 	{.addr = 0x2F, .value = 0x00, .mask = 0xF0},
187 	/* Enable loop filter auto-adjust */
188 	{.addr = 0x1F, .value = 0x08, .mask = 0x08},
189 	/* Set Adapt Mode 1 (6.13) */
190 	{.addr = 0x31, .value = 0x20, .mask = 0x60},
191 	/* Disable the DFE since most applications do not need it (6.18) */
192 	{.addr = 0x1E, .value = 0x08, .mask = 0x08},
193 	/* Release CDR reset (6.4) */
194 	{.addr = 0x0A, .value = 0x00, .mask = 0x0C},
195 	/* Enable FIR (6.12) */
196 	{.addr = 0x3D, .value = 0x80, .mask = 0x80},
197 	/* Set Main-cursor tap sign to positive (6.12) */
198 	{.addr = 0x3D, .value = 0x00, .mask = 0x40},
199 	/* Set Post-cursor tap sign to negative (6.12) */
200 	{.addr = 0x3F, .value = 0x40, .mask = 0x40},
201 	/* Set Pre-cursor tap sign to negative (6.12) */
202 	{.addr = 0x3E, .value = 0x40, .mask = 0x40},
203 	/* Set Main-cursor tap magnitude to 13 (6.12) */
204 	{.addr = 0x3D, .value = 0x0D, .mask = 0x1F},
205 };
206 
207 static int al_eth_lm_retimer_boost_config(struct al_eth_lm_context *lm_context);
208 static int al_eth_lm_retimer_ds25_full_config(struct al_eth_lm_context *lm_context);
209 static al_bool al_eth_lm_retimer_ds25_signal_detect(
210 		struct al_eth_lm_context *lm_context, uint32_t channel);
211 static int al_eth_lm_retimer_ds25_cdr_reset(struct al_eth_lm_context *lm_context, uint32_t channel);
212 static al_bool al_eth_lm_retimer_ds25_cdr_lock(
213 		struct al_eth_lm_context *lm_context, uint32_t channel);
214 static int al_eth_lm_retimer_25g_rx_adaptation(struct al_eth_lm_context *lm_context);
215 
216 struct al_eth_lm_retimer {
217 	int (*config)(struct al_eth_lm_context *lm_context);
218 	int (*reset)(struct al_eth_lm_context *lm_context, uint32_t channel);
219 	int (*signal_detect)(struct al_eth_lm_context *lm_context, uint32_t channel);
220 	int (*cdr_lock)(struct al_eth_lm_context *lm_context, uint32_t channel);
221 	int (*rx_adaptation)(struct al_eth_lm_context *lm_context);
222 };
223 
224 static struct al_eth_lm_retimer retimer[] = {
225 	{.config = al_eth_lm_retimer_boost_config, .signal_detect = NULL,
226 		.reset = NULL, .cdr_lock = NULL, .rx_adaptation = NULL},
227 	{.config = al_eth_lm_retimer_boost_config, .signal_detect = NULL,
228 		.reset = NULL, .cdr_lock = NULL, .rx_adaptation = NULL},
229 	{.config = al_eth_lm_retimer_ds25_full_config,
230 		.signal_detect = al_eth_lm_retimer_ds25_signal_detect,
231 		.reset = al_eth_lm_retimer_ds25_cdr_reset,
232 		.cdr_lock = al_eth_lm_retimer_ds25_cdr_lock,
233 		.rx_adaptation = al_eth_lm_retimer_25g_rx_adaptation},
234 };
235 
236 #define SFP_10G_DA_ACTIVE		0x8
237 #define SFP_10G_DA_PASSIVE		0x4
238 
239 #define lm_debug(...)				\
240 	do {					\
241 		if (lm_context->debug)		\
242 			al_warn(__VA_ARGS__);	\
243 		else				\
244 			al_dbg(__VA_ARGS__);	\
245 	} while (0)
246 
247 static int
248 al_eth_sfp_detect(struct al_eth_lm_context *lm_context,
249     enum al_eth_lm_link_mode *new_mode)
250 {
251 	int rc = 0;
252 	uint8_t sfp_10g;
253 	uint8_t sfp_1g;
254 	uint8_t sfp_cable_tech;
255 	uint8_t sfp_da_len;
256 	uint8_t signal_rate;
257 
258 	do {
259 		rc = lm_context->i2c_read(lm_context->i2c_context,
260 		    lm_context->sfp_bus_id, lm_context->sfp_i2c_addr,
261 		    SFP_I2C_HEADER_10G_IDX, &sfp_10g);
262 		if (rc != 0)
263 			break;
264 
265 		rc = lm_context->i2c_read(lm_context->i2c_context,
266 		    lm_context->sfp_bus_id, lm_context->sfp_i2c_addr,
267 		    SFP_I2C_HEADER_1G_IDX, &sfp_1g);
268 		if (rc != 0)
269 			break;
270 
271 		rc = lm_context->i2c_read(lm_context->i2c_context,
272 		    lm_context->sfp_bus_id, lm_context->sfp_i2c_addr,
273 		    SFP_I2C_HEADER_10G_DA_IDX, &sfp_cable_tech);
274 		if (rc != 0)
275 			break;
276 
277 		rc = lm_context->i2c_read(lm_context->i2c_context,
278 		    lm_context->sfp_bus_id, lm_context->sfp_i2c_addr,
279 		    SFP_I2C_HEADER_10G_DA_LEN_IDX, &sfp_da_len);
280 		if (rc != 0)
281 			break;
282 
283 		rc = lm_context->i2c_read(lm_context->i2c_context,
284 					  lm_context->sfp_bus_id,
285 					  lm_context->sfp_i2c_addr,
286 					  SFP_I2C_HEADER_SIGNAL_RATE,
287 					  &signal_rate);
288 	} while (0);
289 
290 	if (rc != 0) {
291 		if (rc == ETIMEDOUT) {
292 			/* ETIMEDOUT is returned when no SFP is connected */
293 			if (lm_context->mode != AL_ETH_LM_MODE_DISCONNECTED)
294 				lm_debug("%s: SFP Disconnected\n", __func__);
295 			*new_mode = AL_ETH_LM_MODE_DISCONNECTED;
296 		} else {
297 			return (rc);
298 		}
299 	} else if ((sfp_cable_tech & (SFP_10G_DA_PASSIVE | SFP_10G_DA_ACTIVE)) != 0) {
300 		if ((signal_rate >= SFP_MIN_SIGNAL_RATE_25G) &&
301 			((lm_context->max_speed == AL_ETH_LM_MAX_SPEED_25G) ||
302 			(lm_context->max_speed == AL_ETH_LM_MAX_SPEED_MAX)))
303 			*new_mode = AL_ETH_LM_MODE_25G;
304 		else if ((signal_rate >= SFP_MIN_SIGNAL_RATE_10G) &&
305 			((lm_context->max_speed == AL_ETH_LM_MAX_SPEED_10G) ||
306 			(lm_context->max_speed == AL_ETH_LM_MAX_SPEED_MAX)))
307 			*new_mode = AL_ETH_LM_MODE_10G_DA;
308 		else
309 			*new_mode = AL_ETH_LM_MODE_1G;
310 
311 		lm_debug("%s: %s DAC (%d M) detected (max signal rate %d)\n",
312 			 __func__,
313 			 (sfp_cable_tech & SFP_10G_DA_PASSIVE) ? "Passive" : "Active",
314 			  sfp_da_len,
315 			  signal_rate);
316 
317 		/* for active direct attached need to use len 0 in the retimer configuration */
318 		lm_context->da_len = (sfp_cable_tech & SFP_10G_DA_PASSIVE) ? sfp_da_len : 0;
319 	} else if (sfp_10g != 0) {
320 		lm_debug("%s: 10 SFP detected\n", __func__);
321 		*new_mode = AL_ETH_LM_MODE_10G_OPTIC;
322 	} else if (sfp_1g != 0) {
323 		lm_debug("%s: 1G SFP detected\n", __func__);
324 		*new_mode = AL_ETH_LM_MODE_1G;
325 	} else {
326 		al_warn("%s: unknown SFP inserted. eeprom content: 10G compliance 0x%x,"
327 		    " 1G compliance 0x%x, sfp+cable 0x%x. default to %s\n",
328 		    __func__, sfp_10g, sfp_1g, sfp_cable_tech,
329 		    al_eth_lm_mode_convert_to_str(lm_context->default_mode));
330 		*new_mode = lm_context->default_mode;
331 		lm_context->da_len = lm_context->default_dac_len;
332 	}
333 
334 	if ((lm_context->sfp_detect_force_mode) && (*new_mode != AL_ETH_LM_MODE_DISCONNECTED) &&
335 	    (*new_mode != lm_context->default_mode)) {
336 		al_warn("%s: Force mode to default (%s). mode based of the SFP EEPROM %s\n",
337 			__func__, al_eth_lm_mode_convert_to_str(lm_context->default_mode),
338 			al_eth_lm_mode_convert_to_str(*new_mode));
339 
340 		*new_mode = lm_context->default_mode;
341 	}
342 
343 	lm_context->mode = *new_mode;
344 
345 	return (0);
346 }
347 
348 static int
349 al_eth_qsfp_detect(struct al_eth_lm_context *lm_context,
350     enum al_eth_lm_link_mode *new_mode)
351 {
352 	int rc = 0;
353 	uint8_t qsfp_comp_code;
354 	uint8_t qsfp_da_len;
355 
356 	do {
357 		rc = lm_context->i2c_read(lm_context->i2c_context,
358 		    lm_context->sfp_bus_id, lm_context->sfp_i2c_addr,
359 		    QSFP_COMPLIANCE_CODE_IDX, &qsfp_comp_code);
360 		if (rc != 0)
361 			break;
362 
363 		rc = lm_context->i2c_read(lm_context->i2c_context,
364 		    lm_context->sfp_bus_id, lm_context->sfp_i2c_addr,
365 		    QSFP_CABLE_LEN_IDX, &qsfp_da_len);
366 		if (rc != 0)
367 			break;
368 	} while (0);
369 
370 	if (rc != 0) {
371 		if (rc == ETIMEDOUT) {
372 			/* ETIMEDOUT is returned when no SFP is connected */
373 			lm_debug("%s: SFP Disconnected\n", __func__);
374 			*new_mode = AL_ETH_LM_MODE_DISCONNECTED;
375 		} else {
376 			return (rc);
377 		}
378 	} else if ((qsfp_comp_code & QSFP_COMPLIANCE_CODE_DAC) != 0) {
379 		lm_debug("%s: 10G passive DAC (%d M) detected\n",
380 		    __func__, qsfp_da_len);
381 		*new_mode = AL_ETH_LM_MODE_10G_DA;
382 		lm_context->da_len = qsfp_da_len;
383 	} else if ((qsfp_comp_code & QSFP_COMPLIANCE_CODE_OPTIC) != 0) {
384 		lm_debug("%s: 10G optic module detected\n", __func__);
385 		*new_mode = AL_ETH_LM_MODE_10G_OPTIC;
386 	} else {
387 		al_warn("%s: unknown QSFP inserted. eeprom content: 10G "
388 		    "compliance 0x%x default to %s\n", __func__, qsfp_comp_code,
389 		    al_eth_lm_mode_convert_to_str(lm_context->default_mode));
390 		*new_mode = lm_context->default_mode;
391 		lm_context->da_len = lm_context->default_dac_len;
392 	}
393 
394 	lm_context->mode = *new_mode;
395 
396 	return (0);
397 }
398 
399 static int
400 al_eth_module_detect(struct al_eth_lm_context *lm_context,
401     enum al_eth_lm_link_mode *new_mode)
402 {
403 	int rc = 0;
404 	uint8_t module_idx;
405 	int sfp_present = SFP_PRESENT;
406 
407 	if ((lm_context->gpio_get) && (lm_context->gpio_present != 0))
408 		sfp_present = lm_context->gpio_get(lm_context->gpio_present);
409 
410 	if (sfp_present == SFP_NOT_PRESENT) {
411 		lm_debug("%s: SFP not exist\n", __func__);
412 		*new_mode = AL_ETH_LM_MODE_DISCONNECTED;
413 
414 		return 0;
415 	}
416 
417 	rc = lm_context->i2c_read(lm_context->i2c_context,
418 	    lm_context->sfp_bus_id, lm_context->sfp_i2c_addr,
419 	    MODULE_IDENTIFIER_IDX, &module_idx);
420 	if (rc != 0) {
421 		if (rc == ETIMEDOUT) {
422 			/* ETIMEDOUT is returned when no SFP is connected */
423 			if (lm_context->mode != AL_ETH_LM_MODE_DISCONNECTED)
424 				lm_debug("%s: SFP Disconnected\n", __func__);
425 			*new_mode = AL_ETH_LM_MODE_DISCONNECTED;
426 			return (0);
427 		} else {
428 			return (rc);
429 		}
430 	}
431 
432 	if (module_idx == MODULE_IDENTIFIER_QSFP)
433 		return (al_eth_qsfp_detect(lm_context, new_mode));
434 	else
435 		return (al_eth_sfp_detect(lm_context, new_mode));
436 
437 	return (0);
438 }
439 
440 static struct al_serdes_adv_tx_params da_tx_params = {
441 	.override		= TRUE,
442 	.amp			= 0x1,
443 	.total_driver_units	= 0x13,
444 	.c_plus_1		= 0x2,
445 	.c_plus_2		= 0,
446 	.c_minus_1		= 0x2,
447 	.slew_rate		= 0,
448 };
449 
450 static struct al_serdes_adv_rx_params da_rx_params = {
451 	.override		= TRUE,
452 	.dcgain			= 0x4,
453 	.dfe_3db_freq		= 0x4,
454 	.dfe_gain		= 0x3,
455 	.dfe_first_tap_ctrl	= 0x5,
456 	.dfe_secound_tap_ctrl	= 0x1,
457 	.dfe_third_tap_ctrl	= 0x8,
458 	.dfe_fourth_tap_ctrl	= 0x1,
459 	.low_freq_agc_gain	= 0x7,
460 	.precal_code_sel	= 0,
461 	.high_freq_agc_boost	= 0x1d,
462 };
463 
464 static struct al_serdes_adv_tx_params optic_tx_params = {
465 	.override		= TRUE,
466 	.amp			= 0x1,
467 	.total_driver_units	= 0x13,
468 	.c_plus_1		= 0x2,
469 	.c_plus_2		= 0,
470 	.c_minus_1		= 0,
471 	.slew_rate		= 0,
472 };
473 
474 static struct al_serdes_adv_rx_params optic_rx_params = {
475 	.override		= TRUE,
476 	.dcgain			= 0x0,
477 	.dfe_3db_freq		= 0x7,
478 	.dfe_gain		= 0x0,
479 	.dfe_first_tap_ctrl	= 0x0,
480 	.dfe_secound_tap_ctrl	= 0x8,
481 	.dfe_third_tap_ctrl	= 0x0,
482 	.dfe_fourth_tap_ctrl	= 0x8,
483 	.low_freq_agc_gain	= 0x7,
484 	.precal_code_sel	= 0,
485 	.high_freq_agc_boost	= 0x4,
486 };
487 
488 static void
489 al_eth_serdes_static_tx_params_set(struct al_eth_lm_context *lm_context)
490 {
491 
492 	if (lm_context->tx_param_dirty == 0)
493 		return;
494 
495 	if (lm_context->serdes_tx_params_valid != 0) {
496 		lm_context->tx_param_dirty = 0;
497 
498 		lm_context->tx_params_override.override = TRUE;
499 
500 		if ((lm_context->serdes_obj->tx_advanced_params_set) == 0) {
501 			al_err("tx_advanced_params_set is not supported for this serdes group\n");
502 			return;
503 		}
504 
505 		lm_context->serdes_obj->tx_advanced_params_set(
506 					lm_context->serdes_obj,
507 					lm_context->lane,
508 					&lm_context->tx_params_override);
509 
510 	} else if (lm_context->static_values != 0) {
511 		lm_context->tx_param_dirty = 0;
512 
513 		if ((lm_context->serdes_obj->tx_advanced_params_set) == 0) {
514 			al_err("tx_advanced_params_set is not supported for this serdes group\n");
515 			return;
516 		}
517 
518 		if ((lm_context->retimer_exist == 0) &&
519 		    (lm_context->mode == AL_ETH_LM_MODE_10G_DA))
520 			lm_context->serdes_obj->tx_advanced_params_set(
521 						lm_context->serdes_obj,
522 						lm_context->lane,
523 						&da_tx_params);
524 		else
525 			lm_context->serdes_obj->tx_advanced_params_set(
526 						lm_context->serdes_obj,
527 						lm_context->lane,
528 						&optic_tx_params);
529 	}
530 }
531 
532 static void
533 al_eth_serdes_static_rx_params_set(struct al_eth_lm_context *lm_context)
534 {
535 
536 	if (lm_context->rx_param_dirty == 0)
537 		return;
538 
539 	if (lm_context->serdes_rx_params_valid != 0) {
540 		lm_context->rx_param_dirty = 0;
541 
542 		lm_context->rx_params_override.override = TRUE;
543 
544 		if ((lm_context->serdes_obj->rx_advanced_params_set) == 0) {
545 			al_err("rx_advanced_params_set is not supported for this serdes group\n");
546 			return;
547 		}
548 
549 		lm_context->serdes_obj->rx_advanced_params_set(
550 					lm_context->serdes_obj,
551 					lm_context->lane,
552 					&lm_context->rx_params_override);
553 
554 
555 	} else if (lm_context->static_values != 0) {
556 		lm_context->rx_param_dirty = 0;
557 
558 		if ((lm_context->serdes_obj->rx_advanced_params_set) == 0) {
559 			al_err("rx_advanced_params_set is not supported for this serdes group\n");
560 			return;
561 		}
562 
563 		if ((lm_context->retimer_exist == 0) &&
564 		    (lm_context->mode == AL_ETH_LM_MODE_10G_DA))
565 			lm_context->serdes_obj->rx_advanced_params_set(
566 						lm_context->serdes_obj,
567 						lm_context->lane,
568 						&da_rx_params);
569 		else
570 			lm_context->serdes_obj->rx_advanced_params_set(
571 						lm_context->serdes_obj,
572 						lm_context->lane,
573 						&optic_rx_params);
574 	}
575 }
576 
577 static int
578 al_eth_rx_equal_run(struct al_eth_lm_context *lm_context)
579 {
580 	struct al_serdes_adv_rx_params rx_params;
581 	int dcgain;
582 	int best_dcgain = -1;
583 	int i;
584 	int best_score  = -1;
585 	int test_score = -1;
586 
587 	rx_params.override = FALSE;
588 	lm_context->serdes_obj->rx_advanced_params_set(lm_context->serdes_obj,
589 							lm_context->lane, &rx_params);
590 
591 	lm_debug("score | dcgain | dfe3db | dfegain | tap1 | tap2 | tap3 | "
592 	    "tap4 | low freq | high freq\n");
593 
594 	for (dcgain = 0; dcgain < AL_ETH_LM_MAX_DCGAIN; dcgain++) {
595 		lm_context->serdes_obj->dcgain_set(
596 					lm_context->serdes_obj,
597 					dcgain);
598 
599 		test_score = lm_context->serdes_obj->rx_equalization(
600 					lm_context->serdes_obj,
601 					lm_context->lane);
602 
603 		if (test_score < 0) {
604 			al_warn("serdes rx equalization failed on error\n");
605 			return (test_score);
606 		}
607 
608 		if (test_score > best_score) {
609 			best_score = test_score;
610 			best_dcgain = dcgain;
611 		}
612 
613 		lm_context->serdes_obj->rx_advanced_params_get(
614 					lm_context->serdes_obj,
615 					lm_context->lane,
616 					&rx_params);
617 
618 		lm_debug("%6d|%8x|%8x|%9x|%6x|%6x|%6x|%6x|%10x|%10x|\n",
619 		    test_score, rx_params.dcgain, rx_params.dfe_3db_freq,
620 		    rx_params.dfe_gain, rx_params.dfe_first_tap_ctrl,
621 		    rx_params.dfe_secound_tap_ctrl, rx_params.dfe_third_tap_ctrl,
622 		    rx_params.dfe_fourth_tap_ctrl, rx_params.low_freq_agc_gain,
623 		    rx_params.high_freq_agc_boost);
624 	}
625 
626 	lm_context->serdes_obj->dcgain_set(
627 					lm_context->serdes_obj,
628 					best_dcgain);
629 
630 	best_score = -1;
631 	for(i = 0; i < AL_ETH_LM_EQ_ITERATIONS; i++) {
632 		test_score = lm_context->serdes_obj->rx_equalization(
633 						lm_context->serdes_obj,
634 						lm_context->lane);
635 
636 		if (test_score < 0) {
637 			al_warn("serdes rx equalization failed on error\n");
638 			return (test_score);
639 		}
640 
641 		if (test_score > best_score) {
642 			best_score = test_score;
643 			lm_context->serdes_obj->rx_advanced_params_get(
644 						lm_context->serdes_obj,
645 						lm_context->lane,
646 						&rx_params);
647 		}
648 	}
649 
650 	rx_params.precal_code_sel = 0;
651 	rx_params.override = TRUE;
652 	lm_context->serdes_obj->rx_advanced_params_set(
653 					lm_context->serdes_obj,
654 					lm_context->lane,
655 					&rx_params);
656 
657 	lm_debug("-------------------- best dcgain %d ------------------------------------\n", best_dcgain);
658 	lm_debug("%6d|%8x|%8x|%9x|%6x|%6x|%6x|%6x|%10x|%10x|\n",
659 	    best_score, rx_params.dcgain, rx_params.dfe_3db_freq,
660 	    rx_params.dfe_gain, rx_params.dfe_first_tap_ctrl,
661 	    rx_params.dfe_secound_tap_ctrl, rx_params.dfe_third_tap_ctrl,
662 	    rx_params.dfe_fourth_tap_ctrl, rx_params.low_freq_agc_gain,
663 	    rx_params.high_freq_agc_boost);
664 
665 	return (0);
666 }
667 
668 static int al_eth_lm_retimer_boost_config(struct al_eth_lm_context *lm_context)
669 {
670 	int i;
671 	int rc = 0;
672 	uint8_t boost = 0;
673 	uint32_t boost_addr =
674 	    al_eth_retimer_boost_addr[lm_context->retimer_channel][lm_context->retimer_type];
675 
676 	if (lm_context->mode != AL_ETH_LM_MODE_10G_DA) {
677 		boost = al_eth_retimer_boost_value[0][lm_context->retimer_type];
678 	} else {
679 		for (i = 0; i < RETIMER_LENS_MAX; i++) {
680 			if (lm_context->da_len <= al_eth_retimer_boost_lens[i]) {
681 				boost = al_eth_retimer_boost_value[i][lm_context->retimer_type];
682 				break;
683 			}
684 		}
685 
686 		if (i == RETIMER_LENS_MAX)
687 			boost = al_eth_retimer_boost_value[RETIMER_LENS_MAX][lm_context->retimer_type];
688 	}
689 
690 	lm_debug("config retimer boost in channel %d (addr %x) to 0x%x\n",
691 	    lm_context->retimer_channel, boost_addr, boost);
692 
693 	rc = lm_context->i2c_write(lm_context->i2c_context,
694 	    lm_context->retimer_bus_id, lm_context->retimer_i2c_addr,
695 	    boost_addr, boost);
696 
697 	if (rc != 0) {
698 		al_err("%s: Error occurred (%d) while writing retimer "
699 		    "configuration (bus-id %x i2c-addr %x)\n",
700 		    __func__, rc, lm_context->retimer_bus_id,
701 		    lm_context->retimer_i2c_addr);
702 		return (rc);
703 	}
704 
705 	return (0);
706 }
707 
708 /*******************************************************************************
709  ************************** retimer DS25 ***************************************
710  ******************************************************************************/
711 #define LM_DS25_CHANNEL_EN_REG		0xff
712 #define LM_DS25_CHANNEL_EN_MASK		0x03
713 #define LM_DS25_CHANNEL_EN_VAL		0x01
714 
715 #define LM_DS25_CHANNEL_SEL_REG		0xfc
716 #define LM_DS25_CHANNEL_SEL_MASK	0xff
717 
718 #define LM_DS25_CDR_RESET_REG		0x0a
719 #define LM_DS25_CDR_RESET_MASK		0x0c
720 #define LM_DS25_CDR_RESET_ASSERT	0x0c
721 #define LM_DS25_CDR_RESET_RELEASE	0x00
722 
723 #define LM_DS25_SIGNAL_DETECT_REG	0x78
724 #define LM_DS25_SIGNAL_DETECT_MASK	0x20
725 
726 #define LM_DS25_CDR_LOCK_REG		0x78
727 #define LM_DS25_CDR_LOCK_MASK		0x10
728 
729 #define LM_DS25_DRV_PD_REG		0x15
730 #define LM_DS25_DRV_PD_MASK		0x08
731 
732 static int al_eth_lm_retimer_ds25_write_reg(struct al_eth_lm_context	*lm_context,
733 					    uint8_t			reg_addr,
734 					    uint8_t			reg_mask,
735 					    uint8_t			reg_value)
736 {
737 	uint8_t reg;
738 	int rc;
739 
740 	rc = lm_context->i2c_read(lm_context->i2c_context,
741 				  lm_context->retimer_bus_id,
742 				  lm_context->retimer_i2c_addr,
743 				  reg_addr,
744 				  &reg);
745 
746 	if (rc != 0)
747 		return (EIO);
748 
749 	reg &= ~(reg_mask);
750 	reg |= reg_value;
751 
752 	rc = lm_context->i2c_write(lm_context->i2c_context,
753 				   lm_context->retimer_bus_id,
754 				   lm_context->retimer_i2c_addr,
755 				   reg_addr,
756 				   reg);
757 
758 	if (rc != 0)
759 		return (EIO);
760 
761 	return (0);
762 }
763 
764 static int al_eth_lm_retimer_ds25_channel_select(struct al_eth_lm_context	*lm_context,
765 						 uint8_t			channel)
766 {
767 	int rc = 0;
768 
769 	/* Write to specific channel */
770 	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
771 					      LM_DS25_CHANNEL_EN_REG,
772 					      LM_DS25_CHANNEL_EN_MASK,
773 					      LM_DS25_CHANNEL_EN_VAL);
774 
775 	if (rc != 0)
776 		return (rc);
777 
778 	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
779 					      LM_DS25_CHANNEL_SEL_REG,
780 					      LM_DS25_CHANNEL_SEL_MASK,
781 					      (1 << channel));
782 
783 	return (rc);
784 }
785 
786 static int al_eth_lm_retimer_ds25_channel_config(struct al_eth_lm_context	*lm_context,
787 						 uint8_t			channel,
788 						 struct retimer_config_reg	*config,
789 						 uint8_t			config_size)
790 {
791 	uint8_t i;
792 	int rc;
793 
794 	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
795 	if (rc != 0)
796 		goto config_error;
797 
798 	for (i = 0; i < config_size; i++) {
799 		rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
800 						      config[i].addr,
801 						      config[i].mask,
802 						      config[i].value);
803 
804 		if (rc != 0)
805 			goto config_error;
806 	}
807 
808 	lm_debug("%s: retimer channel config done for channel %d\n", __func__, channel);
809 
810 	return (0);
811 
812 config_error:
813 	al_err("%s: failed to access to the retimer\n", __func__);
814 
815 	return (rc);
816 }
817 
818 static int al_eth_lm_retimer_ds25_cdr_reset(struct al_eth_lm_context *lm_context, uint32_t channel)
819 {
820 	int rc;
821 
822 	lm_debug("Perform CDR reset to channel %d\n", channel);
823 
824 	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
825 	if (rc)
826 		goto config_error;
827 
828 	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
829 					      LM_DS25_CDR_RESET_REG,
830 					      LM_DS25_CDR_RESET_MASK,
831 					      LM_DS25_CDR_RESET_ASSERT);
832 
833 	if (rc)
834 		goto config_error;
835 
836 	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
837 					      LM_DS25_CDR_RESET_REG,
838 					      LM_DS25_CDR_RESET_MASK,
839 					      LM_DS25_CDR_RESET_RELEASE);
840 
841 	if (rc)
842 		goto config_error;
843 
844 	return 0;
845 
846 config_error:
847 	al_err("%s: failed to access to the retimer\n", __func__);
848 
849 	return rc;
850 }
851 
852 static boolean_t al_eth_lm_retimer_ds25_signal_detect(struct al_eth_lm_context *lm_context,
853 						    uint32_t channel)
854 {
855 	int rc = 0;
856 	uint8_t reg;
857 
858 	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
859 	if (rc)
860 		goto config_error;
861 
862 	rc = lm_context->i2c_read(lm_context->i2c_context,
863 				  lm_context->retimer_bus_id,
864 				  lm_context->retimer_i2c_addr,
865 				  LM_DS25_SIGNAL_DETECT_REG,
866 				  &reg);
867 
868 	if (rc)
869 		goto config_error;
870 
871 	if (reg & LM_DS25_SIGNAL_DETECT_MASK)
872 		return TRUE;
873 
874 	return FALSE;
875 
876 config_error:
877 	al_err("%s: failed to access to the retimer\n", __func__);
878 
879 	return FALSE;
880 }
881 
882 static boolean_t al_eth_lm_retimer_ds25_cdr_lock(struct al_eth_lm_context *lm_context,
883 					       uint32_t channel)
884 {
885 	int rc = 0;
886 	uint8_t reg;
887 
888 	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
889 	if (rc)
890 		goto config_error;
891 
892 	rc = lm_context->i2c_read(lm_context->i2c_context,
893 				  lm_context->retimer_bus_id,
894 				  lm_context->retimer_i2c_addr,
895 				  LM_DS25_CDR_LOCK_REG,
896 				  &reg);
897 
898 	if (rc)
899 		goto config_error;
900 
901 	if (reg & LM_DS25_CDR_LOCK_MASK)
902 		return TRUE;
903 
904 	return FALSE;
905 
906 config_error:
907 	al_err("%s: failed to access to the retimer\n", __func__);
908 
909 	return FALSE;
910 }
911 
912 static boolean_t al_eth_lm_wait_for_lock(struct al_eth_lm_context	*lm_context,
913 				       uint32_t			channel)
914 {
915 	uint32_t timeout = AL_ETH_LM_RETIMER_WAIT_FOR_LOCK;
916 	al_bool lock = AL_FALSE;
917 
918 	while ((timeout > 0) && (lock == FALSE)) {
919 		al_msleep(10);
920 		timeout -= 10;
921 
922 		lock = retimer[lm_context->retimer_type].cdr_lock(lm_context, channel);
923 	}
924 
925 	lm_debug("%s: %s to achieve CDR lock in %d msec\n",
926 		 __func__, (lock) ? "succeed" : "FAILED",
927 		 (AL_ETH_LM_RETIMER_WAIT_FOR_LOCK - timeout));
928 
929 	return lock;
930 }
931 
932 static void al_eth_lm_retimer_signal_lock_check(struct al_eth_lm_context	*lm_context,
933 						uint32_t			channel,
934 						boolean_t			*ready)
935 {
936 	al_bool signal_detect = TRUE;
937 	al_bool cdr_lock = TRUE;
938 
939 	if (retimer[lm_context->retimer_type].signal_detect) {
940 		if (!retimer[lm_context->retimer_type].signal_detect(lm_context, channel)) {
941 			lm_debug("no signal detected on retimer channel %d\n", channel);
942 
943 			signal_detect = AL_FALSE;
944 		} else {
945 			if (retimer[lm_context->retimer_type].cdr_lock) {
946 				cdr_lock = retimer[lm_context->retimer_type].cdr_lock(
947 									lm_context,
948 									channel);
949 				if (!cdr_lock) {
950 					if (retimer[lm_context->retimer_type].reset) {
951 						retimer[lm_context->retimer_type].reset(lm_context,
952 											channel);
953 
954 						cdr_lock = al_eth_lm_wait_for_lock(lm_context,
955 										   channel);
956 					}
957 				}
958 			}
959 		}
960 	}
961 
962 	al_info("%s: (channel %d) signal %d cdr lock %d\n",
963 		 __func__, channel, signal_detect, (signal_detect) ? cdr_lock : 0);
964 
965 	*ready = ((cdr_lock == TRUE) && (signal_detect == TRUE));
966 }
967 
968 static int al_eth_lm_retimer_ds25_full_config(struct al_eth_lm_context *lm_context)
969 {
970 	int rc = 0;
971 	al_bool ready;
972 	struct retimer_config_reg *config_tx;
973 	uint32_t config_tx_size;
974 	struct retimer_config_reg *config_rx;
975 	uint32_t config_rx_size;
976 
977 	if (lm_context->mode == AL_ETH_LM_MODE_25G) {
978 		config_tx = retimer_ds25_25g_mode_tx_ch;
979 		config_tx_size = AL_ARR_SIZE(retimer_ds25_25g_mode_tx_ch);
980 
981 		config_rx = retimer_ds25_25g_mode_rx_ch;
982 		config_rx_size = AL_ARR_SIZE(retimer_ds25_25g_mode_rx_ch);
983 
984 	} else {
985 		config_tx = retimer_ds25_10g_mode;
986 		config_tx_size = AL_ARR_SIZE(retimer_ds25_10g_mode);
987 
988 		config_rx = retimer_ds25_10g_mode;
989 		config_rx_size = AL_ARR_SIZE(retimer_ds25_10g_mode);
990 	}
991 
992 
993 	rc = al_eth_lm_retimer_ds25_channel_config(lm_context,
994 					lm_context->retimer_channel,
995 					config_rx,
996 					config_rx_size);
997 
998 	if (rc)
999 		return rc;
1000 
1001 	rc = al_eth_lm_retimer_ds25_channel_config(lm_context,
1002 					lm_context->retimer_tx_channel,
1003 					config_tx,
1004 					config_tx_size);
1005 
1006 	if (rc)
1007 		return rc;
1008 
1009 	if (lm_context->serdes_obj->type_get() == AL_SRDS_TYPE_25G) {
1010 		lm_debug("%s: serdes 25G - perform tx and rx gearbox reset\n", __func__);
1011 		al_eth_gearbox_reset(lm_context->adapter, TRUE, TRUE);
1012 		DELAY(AL_ETH_LM_GEARBOX_RESET_DELAY);
1013 	}
1014 
1015 	al_eth_lm_retimer_signal_lock_check(lm_context, lm_context->retimer_tx_channel, &ready);
1016 
1017 	if (!ready) {
1018 		lm_debug("%s: Failed to lock tx channel!\n", __func__);
1019 		return (1);
1020 	}
1021 
1022 	lm_debug("%s: retimer full configuration done\n", __func__);
1023 
1024 	return rc;
1025 }
1026 
1027 static int al_eth_lm_retimer_25g_rx_adaptation(struct al_eth_lm_context *lm_context)
1028 {
1029 	int rc = 0;
1030 	al_bool ready;
1031 
1032 	al_eth_lm_retimer_signal_lock_check(lm_context, lm_context->retimer_channel, &ready);
1033 
1034 	if (!ready) {
1035 		lm_debug("%s: no signal detected on retimer Rx channel (%d)\n",
1036 			 __func__,  lm_context->retimer_channel);
1037 
1038 		return rc;
1039 	}
1040 
1041 	al_msleep(AL_ETH_LM_SERDES_WAIT_FOR_LOCK);
1042 
1043 	return 0;
1044 }
1045 
1046 static int al_eth_lm_check_for_link(struct al_eth_lm_context *lm_context, boolean_t *link_up)
1047 {
1048 	struct al_eth_link_status status;
1049 	int ret = 0;
1050 
1051 	al_eth_link_status_clear(lm_context->adapter);
1052 	al_eth_link_status_get(lm_context->adapter, &status);
1053 
1054 	if (status.link_up == AL_TRUE) {
1055 		lm_debug("%s: >>>> Link state DOWN ==> UP\n", __func__);
1056 		al_eth_led_set(lm_context->adapter, AL_TRUE);
1057 		lm_context->link_state = AL_ETH_LM_LINK_UP;
1058 		*link_up = AL_TRUE;
1059 
1060 		return 0;
1061 	} else if (status.local_fault) {
1062 		lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1063 		al_eth_led_set(lm_context->adapter, AL_FALSE);
1064 
1065 		al_err("%s: Failed to establish link\n", __func__);
1066 		ret = 1;
1067 	} else {
1068 		lm_debug("%s: >>>> Link state DOWN ==> DOWN_RF\n", __func__);
1069 		lm_context->link_state = AL_ETH_LM_LINK_DOWN_RF;
1070 		al_eth_led_set(lm_context->adapter, AL_FALSE);
1071 
1072 		ret = 0;
1073 	}
1074 
1075 	*link_up = AL_FALSE;
1076 	return ret;
1077 }
1078 
1079 /*****************************************************************************/
1080 /***************************** API functions *********************************/
1081 /*****************************************************************************/
1082 int
1083 al_eth_lm_init(struct al_eth_lm_context	*lm_context,
1084     struct al_eth_lm_init_params *params)
1085 {
1086 
1087 	lm_context->adapter = params->adapter;
1088 	lm_context->serdes_obj = params->serdes_obj;
1089 	lm_context->lane = params->lane;
1090 	lm_context->sfp_detection = params->sfp_detection;
1091 	lm_context->sfp_bus_id = params->sfp_bus_id;
1092 	lm_context->sfp_i2c_addr = params->sfp_i2c_addr;
1093 
1094 	lm_context->retimer_exist = params->retimer_exist;
1095 	lm_context->retimer_type = params->retimer_type;
1096 	lm_context->retimer_bus_id = params->retimer_bus_id;
1097 	lm_context->retimer_i2c_addr = params->retimer_i2c_addr;
1098 	lm_context->retimer_channel = params->retimer_channel;
1099 	lm_context->retimer_tx_channel = params->retimer_tx_channel;
1100 
1101 	lm_context->default_mode = params->default_mode;
1102 	lm_context->default_dac_len = params->default_dac_len;
1103 	lm_context->link_training = params->link_training;
1104 	lm_context->rx_equal = params->rx_equal;
1105 	lm_context->static_values = params->static_values;
1106 	lm_context->i2c_read = params->i2c_read;
1107 	lm_context->i2c_write = params->i2c_write;
1108 	lm_context->i2c_context = params->i2c_context;
1109 	lm_context->get_random_byte = params->get_random_byte;
1110 
1111 	/* eeprom_read must be provided if sfp_detection is true */
1112 	al_assert((lm_context->sfp_detection == FALSE) ||
1113 	    (lm_context->i2c_read != NULL));
1114 
1115 	al_assert((lm_context->retimer_exist == FALSE) ||
1116 	    (lm_context->i2c_write != NULL));
1117 
1118 	lm_context->local_adv.selector_field = 1;
1119 	lm_context->local_adv.capability = 0;
1120 	lm_context->local_adv.remote_fault = 0;
1121 	lm_context->local_adv.acknowledge = 0;
1122 	lm_context->local_adv.next_page = 0;
1123 	lm_context->local_adv.technology = AL_ETH_AN_TECH_10GBASE_KR;
1124 	lm_context->local_adv.fec_capability = params->kr_fec_enable;
1125 
1126 	lm_context->mode = AL_ETH_LM_MODE_DISCONNECTED;
1127 	lm_context->serdes_tx_params_valid = FALSE;
1128 	lm_context->serdes_rx_params_valid = FALSE;
1129 
1130 	lm_context->rx_param_dirty = 1;
1131 	lm_context->tx_param_dirty = 1;
1132 
1133 	lm_context->gpio_get = params->gpio_get;
1134 	lm_context->gpio_present = params->gpio_present;
1135 
1136 	lm_context->max_speed = params->max_speed;
1137 	lm_context->sfp_detect_force_mode = params->sfp_detect_force_mode;
1138 
1139 	lm_context->lm_pause = params->lm_pause;
1140 
1141 	lm_context->led_config = params->led_config;
1142 
1143 	lm_context->retimer_configured = FALSE;
1144 
1145 	lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1146 
1147 	return (0);
1148 }
1149 
1150 int
1151 al_eth_lm_link_detection(struct al_eth_lm_context *lm_context,
1152     boolean_t *link_fault, enum al_eth_lm_link_mode *old_mode,
1153     enum al_eth_lm_link_mode *new_mode)
1154 {
1155 	int err;
1156 	struct al_eth_link_status status;
1157 
1158 	al_assert(lm_context != NULL);
1159 	al_assert(old_mode != NULL);
1160 	al_assert(new_mode != NULL);
1161 
1162 	/**
1163 	 * if Link management is disabled, report no link fault in case the link was up
1164 	 * before and set new mode to disconnected to avoid calling to link establish
1165 	 * if the link wasn't up.
1166 	 */
1167 	if (lm_context->lm_pause != NULL) {
1168 		boolean_t lm_pause = lm_context->lm_pause(lm_context->i2c_context);
1169 		if (lm_pause == TRUE) {
1170 			*new_mode = AL_ETH_LM_MODE_DISCONNECTED;
1171 			if (link_fault != NULL) {
1172 				if (lm_context->link_state == AL_ETH_LM_LINK_UP)
1173 					*link_fault = FALSE;
1174 				else
1175 					*link_fault = TRUE;
1176 			}
1177 
1178 			return 0;
1179 		}
1180 	}
1181 
1182 	*old_mode = lm_context->mode;
1183 	*new_mode = lm_context->mode;
1184 
1185 	if (link_fault != NULL)
1186 		*link_fault = TRUE;
1187 
1188 	switch (lm_context->link_state) {
1189 	case AL_ETH_LM_LINK_UP:
1190 		al_eth_link_status_get(lm_context->adapter, &status);
1191 
1192 		if (status.link_up) {
1193 			if (link_fault != NULL)
1194 				*link_fault = FALSE;
1195 
1196 			al_eth_led_set(lm_context->adapter, TRUE);
1197 
1198 			return (0);
1199 		} else if (status.local_fault) {
1200 			lm_debug("%s: >>>> Link state UP ==> DOWN\n", __func__);
1201 			lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1202 		} else {
1203 			lm_debug("%s: >>>> Link state UP ==> DOWN_RF\n", __func__);
1204 			lm_context->link_state = AL_ETH_LM_LINK_DOWN_RF;
1205 		}
1206 
1207 		break;
1208 	case AL_ETH_LM_LINK_DOWN_RF:
1209 		al_eth_link_status_get(lm_context->adapter, &status);
1210 
1211 		if (status.local_fault) {
1212 			lm_debug("%s: >>>> Link state DOWN_RF ==> DOWN\n", __func__);
1213 			lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1214 
1215 			break;
1216 		} else if (status.remote_fault == FALSE) {
1217 			lm_debug("%s: >>>> Link state DOWN_RF ==> UP\n", __func__);
1218 			lm_context->link_state = AL_ETH_LM_LINK_UP;
1219 		}
1220 		/* in case of remote fault only no need to check SFP again */
1221 		return (0);
1222 	case AL_ETH_LM_LINK_DOWN:
1223 		break;
1224 	};
1225 
1226 	al_eth_led_set(lm_context->adapter, FALSE);
1227 
1228 	if (lm_context->sfp_detection) {
1229 		err = al_eth_module_detect(lm_context, new_mode);
1230 		if (err != 0) {
1231 			al_err("module_detection failed!\n");
1232 			return (err);
1233 		}
1234 
1235 		lm_context->mode = *new_mode;
1236 	} else {
1237 		lm_context->mode = lm_context->default_mode;
1238 		*new_mode = lm_context->mode;
1239 	}
1240 
1241 	if (*old_mode != *new_mode) {
1242 		al_info("%s: New SFP mode detected %s -> %s\n",
1243 		    __func__, al_eth_lm_mode_convert_to_str(*old_mode),
1244 		    al_eth_lm_mode_convert_to_str(*new_mode));
1245 
1246 		lm_context->rx_param_dirty = 1;
1247 		lm_context->tx_param_dirty = 1;
1248 
1249 		lm_context->new_port = TRUE;
1250 
1251 		if ((*new_mode != AL_ETH_LM_MODE_DISCONNECTED) && (lm_context->led_config)) {
1252 			struct al_eth_lm_led_config_data data = {0};
1253 
1254 			switch (*new_mode) {
1255 			case AL_ETH_LM_MODE_10G_OPTIC:
1256 			case AL_ETH_LM_MODE_10G_DA:
1257 				data.speed = AL_ETH_LM_LED_CONFIG_10G;
1258 				break;
1259 			case AL_ETH_LM_MODE_1G:
1260 				data.speed = AL_ETH_LM_LED_CONFIG_1G;
1261 				break;
1262 			case AL_ETH_LM_MODE_25G:
1263 				data.speed = AL_ETH_LM_LED_CONFIG_25G;
1264 				break;
1265 			default:
1266 				al_err("%s: unknown LM mode!\n", __func__);
1267 			};
1268 
1269 			lm_context->led_config(lm_context->i2c_context, &data);
1270 		}
1271 	}
1272 
1273 	return (0);
1274 }
1275 
1276 int
1277 al_eth_lm_link_establish(struct al_eth_lm_context *lm_context, boolean_t *link_up)
1278 {
1279 	boolean_t signal_detected;
1280 	int ret = 0;
1281 
1282 	switch (lm_context->link_state) {
1283 	case AL_ETH_LM_LINK_UP:
1284 		*link_up = TRUE;
1285 		lm_debug("%s: return link up\n", __func__);
1286 
1287 		return (0);
1288 	case AL_ETH_LM_LINK_DOWN_RF:
1289 		*link_up = FALSE;
1290 		lm_debug("%s: return link down (DOWN_RF)\n", __func__);
1291 
1292 		return (0);
1293 	case AL_ETH_LM_LINK_DOWN:
1294 		break;
1295 	};
1296 
1297 	/**
1298 	 * At this point we will get LM disable only if changed to disable after link detection
1299 	 * finished. in this case link will not be established until LM will be enable again.
1300 	 */
1301 	if (lm_context->lm_pause) {
1302 		boolean_t lm_pause = lm_context->lm_pause(lm_context->i2c_context);
1303 		if (lm_pause == TRUE) {
1304 			*link_up = FALSE;
1305 
1306 			return (0);
1307 		}
1308 	}
1309 
1310 	if ((lm_context->new_port) && (lm_context->retimer_exist)) {
1311 		al_eth_serdes_static_rx_params_set(lm_context);
1312 		al_eth_serdes_static_tx_params_set(lm_context);
1313 #if 0
1314 		al_eth_lm_retimer_config(lm_context);
1315 		DELAY(AL_ETH_LM_RETIMER_LINK_STATUS_DELAY);
1316 #endif
1317 
1318 		if (retimer[lm_context->retimer_type].config(lm_context)) {
1319 			al_info("%s: failed to configure the retimer\n", __func__);
1320 
1321 			*link_up = FALSE;
1322 			return (1);
1323 		}
1324 
1325 		lm_context->new_port = FALSE;
1326 
1327 		DELAY(1000);
1328 	}
1329 
1330 	if (lm_context->retimer_exist) {
1331 		if (retimer[lm_context->retimer_type].rx_adaptation) {
1332 			ret = retimer[lm_context->retimer_type].rx_adaptation(lm_context);
1333 
1334 			if (ret != 0) {
1335 				lm_debug("retimer rx is not ready\n");
1336 				*link_up = FALSE;
1337 
1338 				return (0);
1339 			}
1340 		}
1341 	}
1342 
1343 	signal_detected = lm_context->serdes_obj->signal_is_detected(
1344 					lm_context->serdes_obj,
1345 					lm_context->lane);
1346 
1347 	if (signal_detected == FALSE) {
1348 		/* if no signal detected there is nothing to do */
1349 		lm_debug("serdes signal is down\n");
1350 		*link_up = AL_FALSE;
1351 		return 0;
1352 	}
1353 
1354 	if (lm_context->serdes_obj->type_get() == AL_SRDS_TYPE_25G) {
1355 		lm_debug("%s: serdes 25G - perform rx gearbox reset\n", __func__);
1356 		al_eth_gearbox_reset(lm_context->adapter, FALSE, TRUE);
1357 		DELAY(AL_ETH_LM_GEARBOX_RESET_DELAY);
1358 	}
1359 
1360 
1361 	if (lm_context->retimer_exist) {
1362 		DELAY(AL_ETH_LM_RETIMER_LINK_STATUS_DELAY);
1363 
1364 		ret = al_eth_lm_check_for_link(lm_context, link_up);
1365 
1366 		if (ret == 0) {
1367 			lm_debug("%s: link is up with retimer\n", __func__);
1368 			return 0;
1369 		}
1370 
1371 		return ret;
1372 	}
1373 
1374 	if ((lm_context->mode == AL_ETH_LM_MODE_10G_DA) && (lm_context->link_training)) {
1375 		lm_context->local_adv.transmitted_nonce = lm_context->get_random_byte();
1376 		lm_context->local_adv.transmitted_nonce &= 0x1f;
1377 
1378 		ret = al_eth_an_lt_execute(lm_context->adapter,
1379 					   lm_context->serdes_obj,
1380 					   lm_context->lane,
1381 					   &lm_context->local_adv,
1382 					   &lm_context->partner_adv);
1383 
1384 		lm_context->rx_param_dirty = 1;
1385 		lm_context->tx_param_dirty = 1;
1386 
1387 		if (ret == 0) {
1388 			al_info("%s: link training finished successfully\n", __func__);
1389 			lm_context->link_training_failures = 0;
1390 			ret = al_eth_lm_check_for_link(lm_context, link_up);
1391 
1392 			if (ret == 0) {
1393 				lm_debug("%s: link is up with LT\n", __func__);
1394 				return (0);
1395 			}
1396 
1397 		}
1398 
1399 		lm_context->link_training_failures++;
1400 		if (lm_context->link_training_failures > AL_ETH_LT_FAILURES_TO_RESET) {
1401 			lm_debug("%s: failed to establish LT %d times. reset serdes\n",
1402 				 __func__, AL_ETH_LT_FAILURES_TO_RESET);
1403 
1404 			lm_context->serdes_obj->pma_hard_reset_lane(
1405 						lm_context->serdes_obj,
1406 						lm_context->lane,
1407 						TRUE);
1408 			lm_context->serdes_obj->pma_hard_reset_lane(
1409 						lm_context->serdes_obj,
1410 						lm_context->lane,
1411 						FALSE);
1412 			lm_context->link_training_failures = 0;
1413 		}
1414 	}
1415 
1416 	al_eth_serdes_static_tx_params_set(lm_context);
1417 
1418 	if ((lm_context->mode == AL_ETH_LM_MODE_10G_DA) &&
1419 	    (lm_context->rx_equal)) {
1420 		ret = al_eth_rx_equal_run(lm_context);
1421 
1422 		if (ret == 0) {
1423 			DELAY(AL_ETH_LM_LINK_STATUS_DELAY);
1424 			ret = al_eth_lm_check_for_link(lm_context, link_up);
1425 
1426 			if (ret == 0) {
1427 				lm_debug("%s: link is up with Rx Equalization\n", __func__);
1428 				return (0);
1429 			}
1430 		}
1431 	}
1432 
1433 	al_eth_serdes_static_rx_params_set(lm_context);
1434 
1435 	DELAY(AL_ETH_LM_LINK_STATUS_DELAY);
1436 
1437 	ret = al_eth_lm_check_for_link(lm_context, link_up);
1438 
1439 	if (ret == 0) {
1440 		lm_debug("%s: link is up with static parameters\n", __func__);
1441 		return (0);
1442 	}
1443 
1444 	*link_up = FALSE;
1445 	return (1);
1446 }
1447 
1448 int
1449 al_eth_lm_static_parameters_override(struct al_eth_lm_context *lm_context,
1450     struct al_serdes_adv_tx_params *tx_params,
1451     struct al_serdes_adv_rx_params *rx_params)
1452 {
1453 
1454 	if (tx_params != NULL) {
1455 		lm_context->tx_params_override = *tx_params;
1456 		lm_context->tx_param_dirty = 1;
1457 		lm_context->serdes_tx_params_valid = TRUE;
1458 	}
1459 
1460 	if (rx_params != NULL) {
1461 		lm_context->rx_params_override = *rx_params;
1462 		lm_context->rx_param_dirty = 1;
1463 		lm_context->serdes_rx_params_valid = TRUE;
1464 	}
1465 
1466 	return (0);
1467 }
1468 
1469 int
1470 al_eth_lm_static_parameters_override_disable(struct al_eth_lm_context *lm_context,
1471     boolean_t tx_params, boolean_t rx_params)
1472 {
1473 
1474 	if (tx_params != 0)
1475 		lm_context->serdes_tx_params_valid = FALSE;
1476 	if (rx_params != 0)
1477 		lm_context->serdes_tx_params_valid = FALSE;
1478 
1479 	return (0);
1480 }
1481 
1482 int
1483 al_eth_lm_static_parameters_get(struct al_eth_lm_context *lm_context,
1484     struct al_serdes_adv_tx_params *tx_params,
1485     struct al_serdes_adv_rx_params *rx_params)
1486 {
1487 
1488 	if (tx_params != NULL) {
1489 		if (lm_context->serdes_tx_params_valid)
1490 			*tx_params = lm_context->tx_params_override;
1491 		else
1492 			lm_context->serdes_obj->tx_advanced_params_get(
1493 							lm_context->serdes_obj,
1494 							lm_context->lane,
1495 							tx_params);
1496 	}
1497 
1498 	if (rx_params != NULL) {
1499 		if (lm_context->serdes_rx_params_valid)
1500 			*rx_params = lm_context->rx_params_override;
1501 		else
1502 			lm_context->serdes_obj->rx_advanced_params_get(
1503 							lm_context->serdes_obj,
1504 							lm_context->lane,
1505 							rx_params);
1506 	}
1507 
1508 	return (0);
1509 }
1510 
1511 const char *
1512 al_eth_lm_mode_convert_to_str(enum al_eth_lm_link_mode val)
1513 {
1514 
1515 	switch (val) {
1516 	case AL_ETH_LM_MODE_DISCONNECTED:
1517 		return ("AL_ETH_LM_MODE_DISCONNECTED");
1518 	case AL_ETH_LM_MODE_10G_OPTIC:
1519 		return ("AL_ETH_LM_MODE_10G_OPTIC");
1520 	case AL_ETH_LM_MODE_10G_DA:
1521 		return ("AL_ETH_LM_MODE_10G_DA");
1522 	case AL_ETH_LM_MODE_1G:
1523 		return ("AL_ETH_LM_MODE_1G");
1524 	case AL_ETH_LM_MODE_25G:
1525 		return ("AL_ETH_LM_MODE_25G");
1526 	}
1527 
1528 	return ("N/A");
1529 }
1530 
1531 void
1532 al_eth_lm_debug_mode_set(struct al_eth_lm_context *lm_context,
1533     boolean_t enable)
1534 {
1535 
1536 	lm_context->debug = enable;
1537 }
1538