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
86static const uint32_t
87al_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
96static const uint32_t
97al_eth_retimer_boost_lens[RETIMER_LENS_MAX] = {0, 1, 2, 3, 5};
98
99static const uint32_t
100al_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
110struct retimer_config_reg {
111	uint8_t addr;
112	uint8_t value;
113	uint8_t mask;
114};
115
116static 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
149static 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
182static 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
207static int al_eth_lm_retimer_boost_config(struct al_eth_lm_context *lm_context);
208static int al_eth_lm_retimer_ds25_full_config(struct al_eth_lm_context *lm_context);
209static al_bool al_eth_lm_retimer_ds25_signal_detect(
210		struct al_eth_lm_context *lm_context, uint32_t channel);
211static int al_eth_lm_retimer_ds25_cdr_reset(struct al_eth_lm_context *lm_context, uint32_t channel);
212static al_bool al_eth_lm_retimer_ds25_cdr_lock(
213		struct al_eth_lm_context *lm_context, uint32_t channel);
214static int al_eth_lm_retimer_25g_rx_adaptation(struct al_eth_lm_context *lm_context);
215
216struct 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
224static 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
247static int
248al_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
348static int
349al_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
399static int
400al_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
440static 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
450static 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
464static 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
474static 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
488static void
489al_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
532static void
533al_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
577static int
578al_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
668static 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
732static 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
764static 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
786static 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
812config_error:
813	al_err("%s: failed to access to the retimer\n", __func__);
814
815	return (rc);
816}
817
818static 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
846config_error:
847	al_err("%s: failed to access to the retimer\n", __func__);
848
849	return rc;
850}
851
852static 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
876config_error:
877	al_err("%s: failed to access to the retimer\n", __func__);
878
879	return FALSE;
880}
881
882static 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
906config_error:
907	al_err("%s: failed to access to the retimer\n", __func__);
908
909	return FALSE;
910}
911
912static 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
932static 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
968static 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
1027static 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
1046static 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/*****************************************************************************/
1082int
1083al_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
1150int
1151al_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
1276int
1277al_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
1448int
1449al_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
1469int
1470al_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
1482int
1483al_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
1511const char *
1512al_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
1531void
1532al_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