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