1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
|
/*-
* Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates
* All rights reserved.
*
* Developed by Semihalf.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/**
* Ethernet
* @{
* @file al_init_eth_lm.h
*
* @brief ethernet link management common utilities
*
* Common operation example:
* @code
* int main()
* {
* struct al_eth_lm_context lm_context;
* struct al_eth_lm_init_params lm_params;
* enum al_eth_lm_link_mode old_mode;
* enum al_eth_lm_link_mode new_mode;
* al_bool fault;
* al_bool link_up;
* int rc = 0;
*
* lm_params.adapter = hal_adapter;
* lm_params.serdes_obj = serdes;
* lm_params.grp = grp;
* lm_params.lane = lane;
* lm_params.sfp_detection = true;
* lm_params.link_training = true;
* lm_params.rx_equal = true
* lm_params.static_values = true;
* lm_params.kr_fec_enable = false;
* lm_params.eeprom_read = &my_eeprom_read;
* lm_params.eeprom_context = context;
* lm_params.get_random_byte = &my_rand_byte;
* lm_params.default_mode = AL_ETH_LM_MODE_10G_DA;
*
* al_eth_lm_init(&lm_context, &lm_params);
*
* rc = al_eth_lm_link_detection(&lm_context, &fault, &old_mode, &new_mode);
* if (fault == false)
* return; // in this case the link is still up
*
* if (rc) {
* printf("link detection failed on error\n");
* return;
* }
*
* if (old_mode != new_mode) {
* // perform serdes configuration if needed
*
* // mac stop / start / config if needed
* }
*
* spin_lock(lock);
* rc = al_eth_lm_link_establish($lm_context, &link_up);
* spin_unlock(lock);
* if (rc) {
* printf("establish link failed\n");
* return;
* }
*
* if (link_up)
* printf("Link established successfully\n");
* else
* printf("No signal found. probably the link partner is disconnected\n");
* }
* @endcode
*
*/
#ifndef __AL_INIT_ETH_LM_H__
#define __AL_INIT_ETH_LM_H__
#include <al_serdes.h>
#include <al_hal_eth.h>
#include "al_init_eth_kr.h"
enum al_eth_lm_link_mode {
AL_ETH_LM_MODE_DISCONNECTED,
AL_ETH_LM_MODE_10G_OPTIC,
AL_ETH_LM_MODE_10G_DA,
AL_ETH_LM_MODE_1G,
AL_ETH_LM_MODE_25G,
};
enum al_eth_lm_max_speed {
AL_ETH_LM_MAX_SPEED_MAX,
AL_ETH_LM_MAX_SPEED_25G,
AL_ETH_LM_MAX_SPEED_10G,
AL_ETH_LM_MAX_SPEED_1G,
};
enum al_eth_lm_link_state {
AL_ETH_LM_LINK_DOWN,
AL_ETH_LM_LINK_DOWN_RF,
AL_ETH_LM_LINK_UP,
};
enum al_eth_lm_led_config_speed {
AL_ETH_LM_LED_CONFIG_1G,
AL_ETH_LM_LED_CONFIG_10G,
AL_ETH_LM_LED_CONFIG_25G,
};
struct al_eth_lm_led_config_data {
enum al_eth_lm_led_config_speed speed;
};
struct al_eth_lm_context {
struct al_hal_eth_adapter *adapter;
struct al_serdes_grp_obj *serdes_obj;
enum al_serdes_lane lane;
uint32_t link_training_failures;
bool tx_param_dirty;
bool serdes_tx_params_valid;
struct al_serdes_adv_tx_params tx_params_override;
bool rx_param_dirty;
bool serdes_rx_params_valid;
struct al_serdes_adv_rx_params rx_params_override;
struct al_eth_an_adv local_adv;
struct al_eth_an_adv partner_adv;
enum al_eth_lm_link_mode mode;
uint8_t da_len;
bool debug;
/* configurations */
bool sfp_detection;
uint8_t sfp_bus_id;
uint8_t sfp_i2c_addr;
enum al_eth_lm_link_mode default_mode;
uint8_t default_dac_len;
bool link_training;
bool rx_equal;
bool static_values;
bool retimer_exist;
enum al_eth_retimer_type retimer_type;
uint8_t retimer_bus_id;
uint8_t retimer_i2c_addr;
enum al_eth_retimer_channel retimer_channel;
/* services */
int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
uint8_t reg_addr, uint8_t *val);
int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
uint8_t reg_addr, uint8_t val);
void *i2c_context;
uint8_t (*get_random_byte)(void);
int (*gpio_get)(unsigned int gpio);
uint32_t gpio_present;
enum al_eth_retimer_channel retimer_tx_channel;
bool retimer_configured;
enum al_eth_lm_max_speed max_speed;
bool sfp_detect_force_mode;
enum al_eth_lm_link_state link_state;
bool new_port;
bool (*lm_pause)(void *handle);
void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);
};
struct al_eth_lm_init_params {
/* pointer to HAL context */
struct al_hal_eth_adapter *adapter;
/* pointer to serdes object */
struct al_serdes_grp_obj *serdes_obj;
/* serdes lane for this port */
enum al_serdes_lane lane;
/*
* set to true to perform sfp detection if the link is down.
* when set to true, eeprom_read below should NOT be NULL.
*/
bool sfp_detection;
/* i2c bus id of the SFP for this port */
uint8_t sfp_bus_id;
/* i2c addr of the SFP for this port */
uint8_t sfp_i2c_addr;
/*
* default mode, and dac length will be used in case sfp_detection
* is not set or in case the detection failed.
*/
enum al_eth_lm_link_mode default_mode;
uint8_t default_dac_len;
/* the i2c bus id and addr of the retimer in case it exist */
uint8_t retimer_bus_id;
uint8_t retimer_i2c_addr;
/* retimer channel connected to this port */
enum al_eth_retimer_channel retimer_channel;
enum al_eth_retimer_channel retimer_tx_channel;
/* retimer type if exist */
enum al_eth_retimer_type retimer_type;
/*
* the following parameters control what mechanisms to run
* on link_establish with the following steps:
* - if retimer_exist is set, the retimer will be configured based on DA len.
* - if link_training is set and DA detected run link training. if succeed return 0
* - if rx_equal is set serdes equalization will be run to configure the rx parameters.
* - if static_values is set, tx and rx values will be set based on static values.
*/
bool retimer_exist;
bool link_training;
bool rx_equal;
bool static_values;
/* enable / disable fec capabilities in AN */
bool kr_fec_enable;
/*
* pointer to function that's read 1 byte from eeprom
* in case no eeprom is connected should return -ETIMEDOUT
*/
int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
uint8_t reg_addr, uint8_t *val);
int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
uint8_t reg_addr, uint8_t val);
void *i2c_context;
/* pointer to function that return 1 rand byte */
uint8_t (*get_random_byte)(void);
/* pointer to function that gets GPIO value - if NULL gpio present won't be used */
int (*gpio_get)(unsigned int gpio);
/* gpio number connected to the SFP present pin */
uint32_t gpio_present;
enum al_eth_lm_max_speed max_speed;
/* in case force mode is true - the default mode will be set regardless to
* the SFP EEPROM content */
bool sfp_detect_force_mode;
/* lm pause callback - in case it return true the LM will try to preserve
* the current link status and will not try to establish new link (and will not
* access to i2c bus) */
bool (*lm_pause)(void *handle);
/* config ethernet LEDs according to data. can be NULL if no configuration needed */
void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);
};
/**
* initialize link management context and set configuration
*
* @param lm_context pointer to link management context
* @param params parameters passed from upper layer
*
* @return 0 in case of success. otherwise on failure.
*/
int al_eth_lm_init(struct al_eth_lm_context *lm_context,
struct al_eth_lm_init_params *params);
/**
* perform link status check. in case link is down perform sfp detection
*
* @param lm_context pointer to link management context
* @param link_fault indicate if the link is down
* @param old_mode the last working mode
* @param new_mode the new mode detected in this call
*
* @return 0 in case of success. otherwise on failure.
*/
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);
/**
* run LT, rx equalization and static values override according to configuration
* This function MUST be called inside a lock as it using common serdes registers
*
* @param lm_context pointer to link management context
* @param link_up set to true in case link is establish successfully
*
* @return < 0 in case link was failed to be established
*/
int al_eth_lm_link_establish(struct al_eth_lm_context *lm_context,
bool *link_up);
/**
* override the default static parameters
*
* @param lm_context pointer to link management context
* @param tx_params pointer to new tx params
* @param rx_params pointer to new rx params
*
* @return 0 in case of success. otherwise on failure.
**/
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);
/**
* disable serdes parameters override
*
* @param lm_context pointer to link management context
* @param tx_params set to true to disable override of tx params
* @param rx_params set to true to disable override of rx params
*
* @return 0 in case of success. otherwise on failure.
**/
int al_eth_lm_static_parameters_override_disable(struct al_eth_lm_context *lm_context,
bool tx_params, bool rx_params);
/**
* get the static parameters that are being used
* if the parameters was override - return the override values
* else return the current values of the parameters
*
* @param lm_context pointer to link management context
* @param tx_params pointer to new tx params
* @param rx_params pointer to new rx params
*
* @return 0 in case of success. otherwise on failure.
*/
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);
/**
* convert link management mode to string
*
* @param val link management mode
*
* @return string of the mode
*/
const char *al_eth_lm_mode_convert_to_str(enum al_eth_lm_link_mode val);
/**
* print all debug messages
*
* @param lm_context pointer to link management context
* @param enable set to true to enable debug mode
*/
void al_eth_lm_debug_mode_set(struct al_eth_lm_context *lm_context,
bool enable);
#endif
|