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