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