Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/al_eth/al_init_eth_lm.c
39507 views
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
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
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
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
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
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
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
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
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
&reg);
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
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
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
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
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
&reg);
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
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
&reg);
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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
1533