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
al_eth_sfp_detect(struct al_eth_lm_context * lm_context,enum al_eth_lm_link_mode * new_mode)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
al_eth_qsfp_detect(struct al_eth_lm_context * lm_context,enum al_eth_lm_link_mode * new_mode)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
al_eth_module_detect(struct al_eth_lm_context * lm_context,enum al_eth_lm_link_mode * new_mode)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
al_eth_serdes_static_tx_params_set(struct al_eth_lm_context * lm_context)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
al_eth_serdes_static_rx_params_set(struct al_eth_lm_context * lm_context)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
al_eth_rx_equal_run(struct al_eth_lm_context * lm_context)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
al_eth_lm_retimer_boost_config(struct al_eth_lm_context * lm_context)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
al_eth_lm_retimer_ds25_write_reg(struct al_eth_lm_context * lm_context,uint8_t reg_addr,uint8_t reg_mask,uint8_t reg_value)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 ®);
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
al_eth_lm_retimer_ds25_channel_select(struct al_eth_lm_context * lm_context,uint8_t channel)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
al_eth_lm_retimer_ds25_channel_config(struct al_eth_lm_context * lm_context,uint8_t channel,struct retimer_config_reg * config,uint8_t config_size)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
al_eth_lm_retimer_ds25_cdr_reset(struct al_eth_lm_context * lm_context,uint32_t channel)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
al_eth_lm_retimer_ds25_signal_detect(struct al_eth_lm_context * lm_context,uint32_t channel)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 ®);
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
al_eth_lm_retimer_ds25_cdr_lock(struct al_eth_lm_context * lm_context,uint32_t channel)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 ®);
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
al_eth_lm_wait_for_lock(struct al_eth_lm_context * lm_context,uint32_t channel)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
al_eth_lm_retimer_signal_lock_check(struct al_eth_lm_context * lm_context,uint32_t channel,boolean_t * ready)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
al_eth_lm_retimer_ds25_full_config(struct al_eth_lm_context * lm_context)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
al_eth_lm_retimer_25g_rx_adaptation(struct al_eth_lm_context * lm_context)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
al_eth_lm_check_for_link(struct al_eth_lm_context * lm_context,boolean_t * link_up)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
al_eth_lm_init(struct al_eth_lm_context * lm_context,struct al_eth_lm_init_params * params)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
al_eth_lm_link_detection(struct al_eth_lm_context * lm_context,boolean_t * link_fault,enum al_eth_lm_link_mode * old_mode,enum al_eth_lm_link_mode * new_mode)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
al_eth_lm_link_establish(struct al_eth_lm_context * lm_context,boolean_t * link_up)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
al_eth_lm_static_parameters_override(struct al_eth_lm_context * lm_context,struct al_serdes_adv_tx_params * tx_params,struct al_serdes_adv_rx_params * rx_params)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
al_eth_lm_static_parameters_override_disable(struct al_eth_lm_context * lm_context,boolean_t tx_params,boolean_t rx_params)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
al_eth_lm_static_parameters_get(struct al_eth_lm_context * lm_context,struct al_serdes_adv_tx_params * tx_params,struct al_serdes_adv_rx_params * rx_params)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 *
al_eth_lm_mode_convert_to_str(enum al_eth_lm_link_mode val)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
al_eth_lm_debug_mode_set(struct al_eth_lm_context * lm_context,boolean_t enable)1532 al_eth_lm_debug_mode_set(struct al_eth_lm_context *lm_context,
1533 boolean_t enable)
1534 {
1535
1536 lm_context->debug = enable;
1537 }
1538