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	} else if (lm_context->static_values != 0) {
555		lm_context->rx_param_dirty = 0;
556
557		if ((lm_context->serdes_obj->rx_advanced_params_set) == 0) {
558			al_err("rx_advanced_params_set is not supported for this serdes group\n");
559			return;
560		}
561
562		if ((lm_context->retimer_exist == 0) &&
563		    (lm_context->mode == AL_ETH_LM_MODE_10G_DA))
564			lm_context->serdes_obj->rx_advanced_params_set(
565						lm_context->serdes_obj,
566						lm_context->lane,
567						&da_rx_params);
568		else
569			lm_context->serdes_obj->rx_advanced_params_set(
570						lm_context->serdes_obj,
571						lm_context->lane,
572						&optic_rx_params);
573	}
574}
575
576static int
577al_eth_rx_equal_run(struct al_eth_lm_context *lm_context)
578{
579	struct al_serdes_adv_rx_params rx_params;
580	int dcgain;
581	int best_dcgain = -1;
582	int i;
583	int best_score  = -1;
584	int test_score = -1;
585
586	rx_params.override = FALSE;
587	lm_context->serdes_obj->rx_advanced_params_set(lm_context->serdes_obj,
588							lm_context->lane, &rx_params);
589
590	lm_debug("score | dcgain | dfe3db | dfegain | tap1 | tap2 | tap3 | "
591	    "tap4 | low freq | high freq\n");
592
593	for (dcgain = 0; dcgain < AL_ETH_LM_MAX_DCGAIN; dcgain++) {
594		lm_context->serdes_obj->dcgain_set(
595					lm_context->serdes_obj,
596					dcgain);
597
598		test_score = lm_context->serdes_obj->rx_equalization(
599					lm_context->serdes_obj,
600					lm_context->lane);
601
602		if (test_score < 0) {
603			al_warn("serdes rx equalization failed on error\n");
604			return (test_score);
605		}
606
607		if (test_score > best_score) {
608			best_score = test_score;
609			best_dcgain = dcgain;
610		}
611
612		lm_context->serdes_obj->rx_advanced_params_get(
613					lm_context->serdes_obj,
614					lm_context->lane,
615					&rx_params);
616
617		lm_debug("%6d|%8x|%8x|%9x|%6x|%6x|%6x|%6x|%10x|%10x|\n",
618		    test_score, rx_params.dcgain, rx_params.dfe_3db_freq,
619		    rx_params.dfe_gain, rx_params.dfe_first_tap_ctrl,
620		    rx_params.dfe_secound_tap_ctrl, rx_params.dfe_third_tap_ctrl,
621		    rx_params.dfe_fourth_tap_ctrl, rx_params.low_freq_agc_gain,
622		    rx_params.high_freq_agc_boost);
623	}
624
625	lm_context->serdes_obj->dcgain_set(
626					lm_context->serdes_obj,
627					best_dcgain);
628
629	best_score = -1;
630	for(i = 0; i < AL_ETH_LM_EQ_ITERATIONS; i++) {
631		test_score = lm_context->serdes_obj->rx_equalization(
632						lm_context->serdes_obj,
633						lm_context->lane);
634
635		if (test_score < 0) {
636			al_warn("serdes rx equalization failed on error\n");
637			return (test_score);
638		}
639
640		if (test_score > best_score) {
641			best_score = test_score;
642			lm_context->serdes_obj->rx_advanced_params_get(
643						lm_context->serdes_obj,
644						lm_context->lane,
645						&rx_params);
646		}
647	}
648
649	rx_params.precal_code_sel = 0;
650	rx_params.override = TRUE;
651	lm_context->serdes_obj->rx_advanced_params_set(
652					lm_context->serdes_obj,
653					lm_context->lane,
654					&rx_params);
655
656	lm_debug("-------------------- best dcgain %d ------------------------------------\n", best_dcgain);
657	lm_debug("%6d|%8x|%8x|%9x|%6x|%6x|%6x|%6x|%10x|%10x|\n",
658	    best_score, rx_params.dcgain, rx_params.dfe_3db_freq,
659	    rx_params.dfe_gain, rx_params.dfe_first_tap_ctrl,
660	    rx_params.dfe_secound_tap_ctrl, rx_params.dfe_third_tap_ctrl,
661	    rx_params.dfe_fourth_tap_ctrl, rx_params.low_freq_agc_gain,
662	    rx_params.high_freq_agc_boost);
663
664	return (0);
665}
666
667static int al_eth_lm_retimer_boost_config(struct al_eth_lm_context *lm_context)
668{
669	int i;
670	int rc = 0;
671	uint8_t boost = 0;
672	uint32_t boost_addr =
673	    al_eth_retimer_boost_addr[lm_context->retimer_channel][lm_context->retimer_type];
674
675	if (lm_context->mode != AL_ETH_LM_MODE_10G_DA) {
676		boost = al_eth_retimer_boost_value[0][lm_context->retimer_type];
677	} else {
678		for (i = 0; i < RETIMER_LENS_MAX; i++) {
679			if (lm_context->da_len <= al_eth_retimer_boost_lens[i]) {
680				boost = al_eth_retimer_boost_value[i][lm_context->retimer_type];
681				break;
682			}
683		}
684
685		if (i == RETIMER_LENS_MAX)
686			boost = al_eth_retimer_boost_value[RETIMER_LENS_MAX][lm_context->retimer_type];
687	}
688
689	lm_debug("config retimer boost in channel %d (addr %x) to 0x%x\n",
690	    lm_context->retimer_channel, boost_addr, boost);
691
692	rc = lm_context->i2c_write(lm_context->i2c_context,
693	    lm_context->retimer_bus_id, lm_context->retimer_i2c_addr,
694	    boost_addr, boost);
695
696	if (rc != 0) {
697		al_err("%s: Error occurred (%d) while writing retimer "
698		    "configuration (bus-id %x i2c-addr %x)\n",
699		    __func__, rc, lm_context->retimer_bus_id,
700		    lm_context->retimer_i2c_addr);
701		return (rc);
702	}
703
704	return (0);
705}
706
707/*******************************************************************************
708 ************************** retimer DS25 ***************************************
709 ******************************************************************************/
710#define LM_DS25_CHANNEL_EN_REG		0xff
711#define LM_DS25_CHANNEL_EN_MASK		0x03
712#define LM_DS25_CHANNEL_EN_VAL		0x01
713
714#define LM_DS25_CHANNEL_SEL_REG		0xfc
715#define LM_DS25_CHANNEL_SEL_MASK	0xff
716
717#define LM_DS25_CDR_RESET_REG		0x0a
718#define LM_DS25_CDR_RESET_MASK		0x0c
719#define LM_DS25_CDR_RESET_ASSERT	0x0c
720#define LM_DS25_CDR_RESET_RELEASE	0x00
721
722#define LM_DS25_SIGNAL_DETECT_REG	0x78
723#define LM_DS25_SIGNAL_DETECT_MASK	0x20
724
725#define LM_DS25_CDR_LOCK_REG		0x78
726#define LM_DS25_CDR_LOCK_MASK		0x10
727
728#define LM_DS25_DRV_PD_REG		0x15
729#define LM_DS25_DRV_PD_MASK		0x08
730
731static int al_eth_lm_retimer_ds25_write_reg(struct al_eth_lm_context	*lm_context,
732					    uint8_t			reg_addr,
733					    uint8_t			reg_mask,
734					    uint8_t			reg_value)
735{
736	uint8_t reg;
737	int rc;
738
739	rc = lm_context->i2c_read(lm_context->i2c_context,
740				  lm_context->retimer_bus_id,
741				  lm_context->retimer_i2c_addr,
742				  reg_addr,
743				  &reg);
744
745	if (rc != 0)
746		return (EIO);
747
748	reg &= ~(reg_mask);
749	reg |= reg_value;
750
751	rc = lm_context->i2c_write(lm_context->i2c_context,
752				   lm_context->retimer_bus_id,
753				   lm_context->retimer_i2c_addr,
754				   reg_addr,
755				   reg);
756
757	if (rc != 0)
758		return (EIO);
759
760	return (0);
761}
762
763static int al_eth_lm_retimer_ds25_channel_select(struct al_eth_lm_context	*lm_context,
764						 uint8_t			channel)
765{
766	int rc = 0;
767
768	/* Write to specific channel */
769	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
770					      LM_DS25_CHANNEL_EN_REG,
771					      LM_DS25_CHANNEL_EN_MASK,
772					      LM_DS25_CHANNEL_EN_VAL);
773
774	if (rc != 0)
775		return (rc);
776
777	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
778					      LM_DS25_CHANNEL_SEL_REG,
779					      LM_DS25_CHANNEL_SEL_MASK,
780					      (1 << channel));
781
782	return (rc);
783}
784
785static int al_eth_lm_retimer_ds25_channel_config(struct al_eth_lm_context	*lm_context,
786						 uint8_t			channel,
787						 struct retimer_config_reg	*config,
788						 uint8_t			config_size)
789{
790	uint8_t i;
791	int rc;
792
793	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
794	if (rc != 0)
795		goto config_error;
796
797	for (i = 0; i < config_size; i++) {
798		rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
799						      config[i].addr,
800						      config[i].mask,
801						      config[i].value);
802
803		if (rc != 0)
804			goto config_error;
805	}
806
807	lm_debug("%s: retimer channel config done for channel %d\n", __func__, channel);
808
809	return (0);
810
811config_error:
812	al_err("%s: failed to access to the retimer\n", __func__);
813
814	return (rc);
815}
816
817static int al_eth_lm_retimer_ds25_cdr_reset(struct al_eth_lm_context *lm_context, uint32_t channel)
818{
819	int rc;
820
821	lm_debug("Perform CDR reset to channel %d\n", channel);
822
823	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
824	if (rc)
825		goto config_error;
826
827	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
828					      LM_DS25_CDR_RESET_REG,
829					      LM_DS25_CDR_RESET_MASK,
830					      LM_DS25_CDR_RESET_ASSERT);
831
832	if (rc)
833		goto config_error;
834
835	rc = al_eth_lm_retimer_ds25_write_reg(lm_context,
836					      LM_DS25_CDR_RESET_REG,
837					      LM_DS25_CDR_RESET_MASK,
838					      LM_DS25_CDR_RESET_RELEASE);
839
840	if (rc)
841		goto config_error;
842
843	return 0;
844
845config_error:
846	al_err("%s: failed to access to the retimer\n", __func__);
847
848	return rc;
849}
850
851static boolean_t al_eth_lm_retimer_ds25_signal_detect(struct al_eth_lm_context *lm_context,
852						    uint32_t channel)
853{
854	int rc = 0;
855	uint8_t reg;
856
857	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
858	if (rc)
859		goto config_error;
860
861	rc = lm_context->i2c_read(lm_context->i2c_context,
862				  lm_context->retimer_bus_id,
863				  lm_context->retimer_i2c_addr,
864				  LM_DS25_SIGNAL_DETECT_REG,
865				  &reg);
866
867	if (rc)
868		goto config_error;
869
870	if (reg & LM_DS25_SIGNAL_DETECT_MASK)
871		return TRUE;
872
873	return FALSE;
874
875config_error:
876	al_err("%s: failed to access to the retimer\n", __func__);
877
878	return FALSE;
879}
880
881static boolean_t al_eth_lm_retimer_ds25_cdr_lock(struct al_eth_lm_context *lm_context,
882					       uint32_t channel)
883{
884	int rc = 0;
885	uint8_t reg;
886
887	rc = al_eth_lm_retimer_ds25_channel_select(lm_context, channel);
888	if (rc)
889		goto config_error;
890
891	rc = lm_context->i2c_read(lm_context->i2c_context,
892				  lm_context->retimer_bus_id,
893				  lm_context->retimer_i2c_addr,
894				  LM_DS25_CDR_LOCK_REG,
895				  &reg);
896
897	if (rc)
898		goto config_error;
899
900	if (reg & LM_DS25_CDR_LOCK_MASK)
901		return TRUE;
902
903	return FALSE;
904
905config_error:
906	al_err("%s: failed to access to the retimer\n", __func__);
907
908	return FALSE;
909}
910
911static boolean_t al_eth_lm_wait_for_lock(struct al_eth_lm_context	*lm_context,
912				       uint32_t			channel)
913{
914	uint32_t timeout = AL_ETH_LM_RETIMER_WAIT_FOR_LOCK;
915	al_bool lock = AL_FALSE;
916
917	while ((timeout > 0) && (lock == FALSE)) {
918		al_msleep(10);
919		timeout -= 10;
920
921		lock = retimer[lm_context->retimer_type].cdr_lock(lm_context, channel);
922	}
923
924	lm_debug("%s: %s to achieve CDR lock in %d msec\n",
925		 __func__, (lock) ? "succeed" : "FAILED",
926		 (AL_ETH_LM_RETIMER_WAIT_FOR_LOCK - timeout));
927
928	return lock;
929}
930
931static void al_eth_lm_retimer_signal_lock_check(struct al_eth_lm_context	*lm_context,
932						uint32_t			channel,
933						boolean_t			*ready)
934{
935	al_bool signal_detect = TRUE;
936	al_bool cdr_lock = TRUE;
937
938	if (retimer[lm_context->retimer_type].signal_detect) {
939		if (!retimer[lm_context->retimer_type].signal_detect(lm_context, channel)) {
940			lm_debug("no signal detected on retimer channel %d\n", channel);
941
942			signal_detect = AL_FALSE;
943		} else {
944			if (retimer[lm_context->retimer_type].cdr_lock) {
945				cdr_lock = retimer[lm_context->retimer_type].cdr_lock(
946									lm_context,
947									channel);
948				if (!cdr_lock) {
949					if (retimer[lm_context->retimer_type].reset) {
950						retimer[lm_context->retimer_type].reset(lm_context,
951											channel);
952
953						cdr_lock = al_eth_lm_wait_for_lock(lm_context,
954										   channel);
955					}
956				}
957			}
958		}
959	}
960
961	al_info("%s: (channel %d) signal %d cdr lock %d\n",
962		 __func__, channel, signal_detect, (signal_detect) ? cdr_lock : 0);
963
964	*ready = ((cdr_lock == TRUE) && (signal_detect == TRUE));
965}
966
967static int al_eth_lm_retimer_ds25_full_config(struct al_eth_lm_context *lm_context)
968{
969	int rc = 0;
970	al_bool ready;
971	struct retimer_config_reg *config_tx;
972	uint32_t config_tx_size;
973	struct retimer_config_reg *config_rx;
974	uint32_t config_rx_size;
975
976	if (lm_context->mode == AL_ETH_LM_MODE_25G) {
977		config_tx = retimer_ds25_25g_mode_tx_ch;
978		config_tx_size = AL_ARR_SIZE(retimer_ds25_25g_mode_tx_ch);
979
980		config_rx = retimer_ds25_25g_mode_rx_ch;
981		config_rx_size = AL_ARR_SIZE(retimer_ds25_25g_mode_rx_ch);
982
983	} else {
984		config_tx = retimer_ds25_10g_mode;
985		config_tx_size = AL_ARR_SIZE(retimer_ds25_10g_mode);
986
987		config_rx = retimer_ds25_10g_mode;
988		config_rx_size = AL_ARR_SIZE(retimer_ds25_10g_mode);
989	}
990
991	rc = al_eth_lm_retimer_ds25_channel_config(lm_context,
992					lm_context->retimer_channel,
993					config_rx,
994					config_rx_size);
995
996	if (rc)
997		return rc;
998
999	rc = al_eth_lm_retimer_ds25_channel_config(lm_context,
1000					lm_context->retimer_tx_channel,
1001					config_tx,
1002					config_tx_size);
1003
1004	if (rc)
1005		return rc;
1006
1007	if (lm_context->serdes_obj->type_get() == AL_SRDS_TYPE_25G) {
1008		lm_debug("%s: serdes 25G - perform tx and rx gearbox reset\n", __func__);
1009		al_eth_gearbox_reset(lm_context->adapter, TRUE, TRUE);
1010		DELAY(AL_ETH_LM_GEARBOX_RESET_DELAY);
1011	}
1012
1013	al_eth_lm_retimer_signal_lock_check(lm_context, lm_context->retimer_tx_channel, &ready);
1014
1015	if (!ready) {
1016		lm_debug("%s: Failed to lock tx channel!\n", __func__);
1017		return (1);
1018	}
1019
1020	lm_debug("%s: retimer full configuration done\n", __func__);
1021
1022	return rc;
1023}
1024
1025static int al_eth_lm_retimer_25g_rx_adaptation(struct al_eth_lm_context *lm_context)
1026{
1027	int rc = 0;
1028	al_bool ready;
1029
1030	al_eth_lm_retimer_signal_lock_check(lm_context, lm_context->retimer_channel, &ready);
1031
1032	if (!ready) {
1033		lm_debug("%s: no signal detected on retimer Rx channel (%d)\n",
1034			 __func__,  lm_context->retimer_channel);
1035
1036		return rc;
1037	}
1038
1039	al_msleep(AL_ETH_LM_SERDES_WAIT_FOR_LOCK);
1040
1041	return 0;
1042}
1043
1044static int al_eth_lm_check_for_link(struct al_eth_lm_context *lm_context, boolean_t *link_up)
1045{
1046	struct al_eth_link_status status;
1047	int ret = 0;
1048
1049	al_eth_link_status_clear(lm_context->adapter);
1050	al_eth_link_status_get(lm_context->adapter, &status);
1051
1052	if (status.link_up == AL_TRUE) {
1053		lm_debug("%s: >>>> Link state DOWN ==> UP\n", __func__);
1054		al_eth_led_set(lm_context->adapter, AL_TRUE);
1055		lm_context->link_state = AL_ETH_LM_LINK_UP;
1056		*link_up = AL_TRUE;
1057
1058		return 0;
1059	} else if (status.local_fault) {
1060		lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1061		al_eth_led_set(lm_context->adapter, AL_FALSE);
1062
1063		al_err("%s: Failed to establish link\n", __func__);
1064		ret = 1;
1065	} else {
1066		lm_debug("%s: >>>> Link state DOWN ==> DOWN_RF\n", __func__);
1067		lm_context->link_state = AL_ETH_LM_LINK_DOWN_RF;
1068		al_eth_led_set(lm_context->adapter, AL_FALSE);
1069
1070		ret = 0;
1071	}
1072
1073	*link_up = AL_FALSE;
1074	return ret;
1075}
1076
1077/*****************************************************************************/
1078/***************************** API functions *********************************/
1079/*****************************************************************************/
1080int
1081al_eth_lm_init(struct al_eth_lm_context	*lm_context,
1082    struct al_eth_lm_init_params *params)
1083{
1084
1085	lm_context->adapter = params->adapter;
1086	lm_context->serdes_obj = params->serdes_obj;
1087	lm_context->lane = params->lane;
1088	lm_context->sfp_detection = params->sfp_detection;
1089	lm_context->sfp_bus_id = params->sfp_bus_id;
1090	lm_context->sfp_i2c_addr = params->sfp_i2c_addr;
1091
1092	lm_context->retimer_exist = params->retimer_exist;
1093	lm_context->retimer_type = params->retimer_type;
1094	lm_context->retimer_bus_id = params->retimer_bus_id;
1095	lm_context->retimer_i2c_addr = params->retimer_i2c_addr;
1096	lm_context->retimer_channel = params->retimer_channel;
1097	lm_context->retimer_tx_channel = params->retimer_tx_channel;
1098
1099	lm_context->default_mode = params->default_mode;
1100	lm_context->default_dac_len = params->default_dac_len;
1101	lm_context->link_training = params->link_training;
1102	lm_context->rx_equal = params->rx_equal;
1103	lm_context->static_values = params->static_values;
1104	lm_context->i2c_read = params->i2c_read;
1105	lm_context->i2c_write = params->i2c_write;
1106	lm_context->i2c_context = params->i2c_context;
1107	lm_context->get_random_byte = params->get_random_byte;
1108
1109	/* eeprom_read must be provided if sfp_detection is true */
1110	al_assert((lm_context->sfp_detection == FALSE) ||
1111	    (lm_context->i2c_read != NULL));
1112
1113	al_assert((lm_context->retimer_exist == FALSE) ||
1114	    (lm_context->i2c_write != NULL));
1115
1116	lm_context->local_adv.selector_field = 1;
1117	lm_context->local_adv.capability = 0;
1118	lm_context->local_adv.remote_fault = 0;
1119	lm_context->local_adv.acknowledge = 0;
1120	lm_context->local_adv.next_page = 0;
1121	lm_context->local_adv.technology = AL_ETH_AN_TECH_10GBASE_KR;
1122	lm_context->local_adv.fec_capability = params->kr_fec_enable;
1123
1124	lm_context->mode = AL_ETH_LM_MODE_DISCONNECTED;
1125	lm_context->serdes_tx_params_valid = FALSE;
1126	lm_context->serdes_rx_params_valid = FALSE;
1127
1128	lm_context->rx_param_dirty = 1;
1129	lm_context->tx_param_dirty = 1;
1130
1131	lm_context->gpio_get = params->gpio_get;
1132	lm_context->gpio_present = params->gpio_present;
1133
1134	lm_context->max_speed = params->max_speed;
1135	lm_context->sfp_detect_force_mode = params->sfp_detect_force_mode;
1136
1137	lm_context->lm_pause = params->lm_pause;
1138
1139	lm_context->led_config = params->led_config;
1140
1141	lm_context->retimer_configured = FALSE;
1142
1143	lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1144
1145	return (0);
1146}
1147
1148int
1149al_eth_lm_link_detection(struct al_eth_lm_context *lm_context,
1150    boolean_t *link_fault, enum al_eth_lm_link_mode *old_mode,
1151    enum al_eth_lm_link_mode *new_mode)
1152{
1153	int err;
1154	struct al_eth_link_status status;
1155
1156	al_assert(lm_context != NULL);
1157	al_assert(old_mode != NULL);
1158	al_assert(new_mode != NULL);
1159
1160	/**
1161	 * if Link management is disabled, report no link fault in case the link was up
1162	 * before and set new mode to disconnected to avoid calling to link establish
1163	 * if the link wasn't up.
1164	 */
1165	if (lm_context->lm_pause != NULL) {
1166		boolean_t lm_pause = lm_context->lm_pause(lm_context->i2c_context);
1167		if (lm_pause == TRUE) {
1168			*new_mode = AL_ETH_LM_MODE_DISCONNECTED;
1169			if (link_fault != NULL) {
1170				if (lm_context->link_state == AL_ETH_LM_LINK_UP)
1171					*link_fault = FALSE;
1172				else
1173					*link_fault = TRUE;
1174			}
1175
1176			return 0;
1177		}
1178	}
1179
1180	*old_mode = lm_context->mode;
1181	*new_mode = lm_context->mode;
1182
1183	if (link_fault != NULL)
1184		*link_fault = TRUE;
1185
1186	switch (lm_context->link_state) {
1187	case AL_ETH_LM_LINK_UP:
1188		al_eth_link_status_get(lm_context->adapter, &status);
1189
1190		if (status.link_up) {
1191			if (link_fault != NULL)
1192				*link_fault = FALSE;
1193
1194			al_eth_led_set(lm_context->adapter, TRUE);
1195
1196			return (0);
1197		} else if (status.local_fault) {
1198			lm_debug("%s: >>>> Link state UP ==> DOWN\n", __func__);
1199			lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1200		} else {
1201			lm_debug("%s: >>>> Link state UP ==> DOWN_RF\n", __func__);
1202			lm_context->link_state = AL_ETH_LM_LINK_DOWN_RF;
1203		}
1204
1205		break;
1206	case AL_ETH_LM_LINK_DOWN_RF:
1207		al_eth_link_status_get(lm_context->adapter, &status);
1208
1209		if (status.local_fault) {
1210			lm_debug("%s: >>>> Link state DOWN_RF ==> DOWN\n", __func__);
1211			lm_context->link_state = AL_ETH_LM_LINK_DOWN;
1212
1213			break;
1214		} else if (status.remote_fault == FALSE) {
1215			lm_debug("%s: >>>> Link state DOWN_RF ==> UP\n", __func__);
1216			lm_context->link_state = AL_ETH_LM_LINK_UP;
1217		}
1218		/* in case of remote fault only no need to check SFP again */
1219		return (0);
1220	case AL_ETH_LM_LINK_DOWN:
1221		break;
1222	};
1223
1224	al_eth_led_set(lm_context->adapter, FALSE);
1225
1226	if (lm_context->sfp_detection) {
1227		err = al_eth_module_detect(lm_context, new_mode);
1228		if (err != 0) {
1229			al_err("module_detection failed!\n");
1230			return (err);
1231		}
1232
1233		lm_context->mode = *new_mode;
1234	} else {
1235		lm_context->mode = lm_context->default_mode;
1236		*new_mode = lm_context->mode;
1237	}
1238
1239	if (*old_mode != *new_mode) {
1240		al_info("%s: New SFP mode detected %s -> %s\n",
1241		    __func__, al_eth_lm_mode_convert_to_str(*old_mode),
1242		    al_eth_lm_mode_convert_to_str(*new_mode));
1243
1244		lm_context->rx_param_dirty = 1;
1245		lm_context->tx_param_dirty = 1;
1246
1247		lm_context->new_port = TRUE;
1248
1249		if ((*new_mode != AL_ETH_LM_MODE_DISCONNECTED) && (lm_context->led_config)) {
1250			struct al_eth_lm_led_config_data data = {0};
1251
1252			switch (*new_mode) {
1253			case AL_ETH_LM_MODE_10G_OPTIC:
1254			case AL_ETH_LM_MODE_10G_DA:
1255				data.speed = AL_ETH_LM_LED_CONFIG_10G;
1256				break;
1257			case AL_ETH_LM_MODE_1G:
1258				data.speed = AL_ETH_LM_LED_CONFIG_1G;
1259				break;
1260			case AL_ETH_LM_MODE_25G:
1261				data.speed = AL_ETH_LM_LED_CONFIG_25G;
1262				break;
1263			default:
1264				al_err("%s: unknown LM mode!\n", __func__);
1265			};
1266
1267			lm_context->led_config(lm_context->i2c_context, &data);
1268		}
1269	}
1270
1271	return (0);
1272}
1273
1274int
1275al_eth_lm_link_establish(struct al_eth_lm_context *lm_context, boolean_t *link_up)
1276{
1277	boolean_t signal_detected;
1278	int ret = 0;
1279
1280	switch (lm_context->link_state) {
1281	case AL_ETH_LM_LINK_UP:
1282		*link_up = TRUE;
1283		lm_debug("%s: return link up\n", __func__);
1284
1285		return (0);
1286	case AL_ETH_LM_LINK_DOWN_RF:
1287		*link_up = FALSE;
1288		lm_debug("%s: return link down (DOWN_RF)\n", __func__);
1289
1290		return (0);
1291	case AL_ETH_LM_LINK_DOWN:
1292		break;
1293	};
1294
1295	/**
1296	 * At this point we will get LM disable only if changed to disable after link detection
1297	 * finished. in this case link will not be established until LM will be enable again.
1298	 */
1299	if (lm_context->lm_pause) {
1300		boolean_t lm_pause = lm_context->lm_pause(lm_context->i2c_context);
1301		if (lm_pause == TRUE) {
1302			*link_up = FALSE;
1303
1304			return (0);
1305		}
1306	}
1307
1308	if ((lm_context->new_port) && (lm_context->retimer_exist)) {
1309		al_eth_serdes_static_rx_params_set(lm_context);
1310		al_eth_serdes_static_tx_params_set(lm_context);
1311#if 0
1312		al_eth_lm_retimer_config(lm_context);
1313		DELAY(AL_ETH_LM_RETIMER_LINK_STATUS_DELAY);
1314#endif
1315
1316		if (retimer[lm_context->retimer_type].config(lm_context)) {
1317			al_info("%s: failed to configure the retimer\n", __func__);
1318
1319			*link_up = FALSE;
1320			return (1);
1321		}
1322
1323		lm_context->new_port = FALSE;
1324
1325		DELAY(1000);
1326	}
1327
1328	if (lm_context->retimer_exist) {
1329		if (retimer[lm_context->retimer_type].rx_adaptation) {
1330			ret = retimer[lm_context->retimer_type].rx_adaptation(lm_context);
1331
1332			if (ret != 0) {
1333				lm_debug("retimer rx is not ready\n");
1334				*link_up = FALSE;
1335
1336				return (0);
1337			}
1338		}
1339	}
1340
1341	signal_detected = lm_context->serdes_obj->signal_is_detected(
1342					lm_context->serdes_obj,
1343					lm_context->lane);
1344
1345	if (signal_detected == FALSE) {
1346		/* if no signal detected there is nothing to do */
1347		lm_debug("serdes signal is down\n");
1348		*link_up = AL_FALSE;
1349		return 0;
1350	}
1351
1352	if (lm_context->serdes_obj->type_get() == AL_SRDS_TYPE_25G) {
1353		lm_debug("%s: serdes 25G - perform rx gearbox reset\n", __func__);
1354		al_eth_gearbox_reset(lm_context->adapter, FALSE, TRUE);
1355		DELAY(AL_ETH_LM_GEARBOX_RESET_DELAY);
1356	}
1357
1358	if (lm_context->retimer_exist) {
1359		DELAY(AL_ETH_LM_RETIMER_LINK_STATUS_DELAY);
1360
1361		ret = al_eth_lm_check_for_link(lm_context, link_up);
1362
1363		if (ret == 0) {
1364			lm_debug("%s: link is up with retimer\n", __func__);
1365			return 0;
1366		}
1367
1368		return ret;
1369	}
1370
1371	if ((lm_context->mode == AL_ETH_LM_MODE_10G_DA) && (lm_context->link_training)) {
1372		lm_context->local_adv.transmitted_nonce = lm_context->get_random_byte();
1373		lm_context->local_adv.transmitted_nonce &= 0x1f;
1374
1375		ret = al_eth_an_lt_execute(lm_context->adapter,
1376					   lm_context->serdes_obj,
1377					   lm_context->lane,
1378					   &lm_context->local_adv,
1379					   &lm_context->partner_adv);
1380
1381		lm_context->rx_param_dirty = 1;
1382		lm_context->tx_param_dirty = 1;
1383
1384		if (ret == 0) {
1385			al_info("%s: link training finished successfully\n", __func__);
1386			lm_context->link_training_failures = 0;
1387			ret = al_eth_lm_check_for_link(lm_context, link_up);
1388
1389			if (ret == 0) {
1390				lm_debug("%s: link is up with LT\n", __func__);
1391				return (0);
1392			}
1393		}
1394
1395		lm_context->link_training_failures++;
1396		if (lm_context->link_training_failures > AL_ETH_LT_FAILURES_TO_RESET) {
1397			lm_debug("%s: failed to establish LT %d times. reset serdes\n",
1398				 __func__, AL_ETH_LT_FAILURES_TO_RESET);
1399
1400			lm_context->serdes_obj->pma_hard_reset_lane(
1401						lm_context->serdes_obj,
1402						lm_context->lane,
1403						TRUE);
1404			lm_context->serdes_obj->pma_hard_reset_lane(
1405						lm_context->serdes_obj,
1406						lm_context->lane,
1407						FALSE);
1408			lm_context->link_training_failures = 0;
1409		}
1410	}
1411
1412	al_eth_serdes_static_tx_params_set(lm_context);
1413
1414	if ((lm_context->mode == AL_ETH_LM_MODE_10G_DA) &&
1415	    (lm_context->rx_equal)) {
1416		ret = al_eth_rx_equal_run(lm_context);
1417
1418		if (ret == 0) {
1419			DELAY(AL_ETH_LM_LINK_STATUS_DELAY);
1420			ret = al_eth_lm_check_for_link(lm_context, link_up);
1421
1422			if (ret == 0) {
1423				lm_debug("%s: link is up with Rx Equalization\n", __func__);
1424				return (0);
1425			}
1426		}
1427	}
1428
1429	al_eth_serdes_static_rx_params_set(lm_context);
1430
1431	DELAY(AL_ETH_LM_LINK_STATUS_DELAY);
1432
1433	ret = al_eth_lm_check_for_link(lm_context, link_up);
1434
1435	if (ret == 0) {
1436		lm_debug("%s: link is up with static parameters\n", __func__);
1437		return (0);
1438	}
1439
1440	*link_up = FALSE;
1441	return (1);
1442}
1443
1444int
1445al_eth_lm_static_parameters_override(struct al_eth_lm_context *lm_context,
1446    struct al_serdes_adv_tx_params *tx_params,
1447    struct al_serdes_adv_rx_params *rx_params)
1448{
1449
1450	if (tx_params != NULL) {
1451		lm_context->tx_params_override = *tx_params;
1452		lm_context->tx_param_dirty = 1;
1453		lm_context->serdes_tx_params_valid = TRUE;
1454	}
1455
1456	if (rx_params != NULL) {
1457		lm_context->rx_params_override = *rx_params;
1458		lm_context->rx_param_dirty = 1;
1459		lm_context->serdes_rx_params_valid = TRUE;
1460	}
1461
1462	return (0);
1463}
1464
1465int
1466al_eth_lm_static_parameters_override_disable(struct al_eth_lm_context *lm_context,
1467    boolean_t tx_params, boolean_t rx_params)
1468{
1469
1470	if (tx_params != 0)
1471		lm_context->serdes_tx_params_valid = FALSE;
1472	if (rx_params != 0)
1473		lm_context->serdes_tx_params_valid = FALSE;
1474
1475	return (0);
1476}
1477
1478int
1479al_eth_lm_static_parameters_get(struct al_eth_lm_context *lm_context,
1480    struct al_serdes_adv_tx_params *tx_params,
1481    struct al_serdes_adv_rx_params *rx_params)
1482{
1483
1484	if (tx_params != NULL) {
1485		if (lm_context->serdes_tx_params_valid)
1486			*tx_params = lm_context->tx_params_override;
1487		else
1488			lm_context->serdes_obj->tx_advanced_params_get(
1489							lm_context->serdes_obj,
1490							lm_context->lane,
1491							tx_params);
1492	}
1493
1494	if (rx_params != NULL) {
1495		if (lm_context->serdes_rx_params_valid)
1496			*rx_params = lm_context->rx_params_override;
1497		else
1498			lm_context->serdes_obj->rx_advanced_params_get(
1499							lm_context->serdes_obj,
1500							lm_context->lane,
1501							rx_params);
1502	}
1503
1504	return (0);
1505}
1506
1507const char *
1508al_eth_lm_mode_convert_to_str(enum al_eth_lm_link_mode val)
1509{
1510
1511	switch (val) {
1512	case AL_ETH_LM_MODE_DISCONNECTED:
1513		return ("AL_ETH_LM_MODE_DISCONNECTED");
1514	case AL_ETH_LM_MODE_10G_OPTIC:
1515		return ("AL_ETH_LM_MODE_10G_OPTIC");
1516	case AL_ETH_LM_MODE_10G_DA:
1517		return ("AL_ETH_LM_MODE_10G_DA");
1518	case AL_ETH_LM_MODE_1G:
1519		return ("AL_ETH_LM_MODE_1G");
1520	case AL_ETH_LM_MODE_25G:
1521		return ("AL_ETH_LM_MODE_25G");
1522	}
1523
1524	return ("N/A");
1525}
1526
1527void
1528al_eth_lm_debug_mode_set(struct al_eth_lm_context *lm_context,
1529    boolean_t enable)
1530{
1531
1532	lm_context->debug = enable;
1533}
1534