2 * Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates
5 * Developed by Semihalf.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
34 * @file al_init_eth_lm.h
36 * @brief ethernet link management common utilities
38 * Common operation example:
42 * struct al_eth_lm_context lm_context;
43 * struct al_eth_lm_init_params lm_params;
44 * enum al_eth_lm_link_mode old_mode;
45 * enum al_eth_lm_link_mode new_mode;
50 * lm_params.adapter = hal_adapter;
51 * lm_params.serdes_obj = serdes;
52 * lm_params.grp = grp;
53 * lm_params.lane = lane;
54 * lm_params.sfp_detection = true;
55 * lm_params.link_training = true;
56 * lm_params.rx_equal = true
57 * lm_params.static_values = true;
58 * lm_params.kr_fec_enable = false;
59 * lm_params.eeprom_read = &my_eeprom_read;
60 * lm_params.eeprom_context = context;
61 * lm_params.get_random_byte = &my_rand_byte;
62 * lm_params.default_mode = AL_ETH_LM_MODE_10G_DA;
64 * al_eth_lm_init(&lm_context, &lm_params);
66 * rc = al_eth_lm_link_detection(&lm_context, &fault, &old_mode, &new_mode);
68 * return; // in this case the link is still up
71 * printf("link detection failed on error\n");
75 * if (old_mode != new_mode) {
76 * // perform serdes configuration if needed
78 * // mac stop / start / config if needed
82 * rc = al_eth_lm_link_establish($lm_context, &link_up);
85 * printf("establish link failed\n");
90 * printf("Link established successfully\n");
92 * printf("No signal found. probably the link partner is disconnected\n");
98 #ifndef __AL_INIT_ETH_LM_H__
99 #define __AL_INIT_ETH_LM_H__
101 #include <al_serdes.h>
102 #include <al_hal_eth.h>
103 #include "al_init_eth_kr.h"
105 enum al_eth_lm_link_mode {
106 AL_ETH_LM_MODE_DISCONNECTED,
107 AL_ETH_LM_MODE_10G_OPTIC,
108 AL_ETH_LM_MODE_10G_DA,
113 enum al_eth_lm_max_speed {
114 AL_ETH_LM_MAX_SPEED_MAX,
115 AL_ETH_LM_MAX_SPEED_25G,
116 AL_ETH_LM_MAX_SPEED_10G,
117 AL_ETH_LM_MAX_SPEED_1G,
120 enum al_eth_lm_link_state {
122 AL_ETH_LM_LINK_DOWN_RF,
126 enum al_eth_lm_led_config_speed {
127 AL_ETH_LM_LED_CONFIG_1G,
128 AL_ETH_LM_LED_CONFIG_10G,
129 AL_ETH_LM_LED_CONFIG_25G,
132 struct al_eth_lm_led_config_data {
133 enum al_eth_lm_led_config_speed speed;
137 struct al_eth_lm_context {
138 struct al_hal_eth_adapter *adapter;
139 struct al_serdes_grp_obj *serdes_obj;
140 enum al_serdes_lane lane;
142 uint32_t link_training_failures;
144 boolean_t tx_param_dirty;
145 boolean_t serdes_tx_params_valid;
146 struct al_serdes_adv_tx_params tx_params_override;
147 boolean_t rx_param_dirty;
148 boolean_t serdes_rx_params_valid;
149 struct al_serdes_adv_rx_params rx_params_override;
151 struct al_eth_an_adv local_adv;
152 struct al_eth_an_adv partner_adv;
154 enum al_eth_lm_link_mode mode;
159 boolean_t sfp_detection;
161 uint8_t sfp_i2c_addr;
163 enum al_eth_lm_link_mode default_mode;
164 uint8_t default_dac_len;
165 boolean_t link_training;
167 boolean_t static_values;
169 boolean_t retimer_exist;
170 enum al_eth_retimer_type retimer_type;
171 uint8_t retimer_bus_id;
172 uint8_t retimer_i2c_addr;
173 enum al_eth_retimer_channel retimer_channel;
176 int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
177 uint8_t reg_addr, uint8_t *val);
178 int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
179 uint8_t reg_addr, uint8_t val);
181 uint8_t (*get_random_byte)(void);
183 int (*gpio_get)(unsigned int gpio);
184 uint32_t gpio_present;
186 enum al_eth_retimer_channel retimer_tx_channel;
187 boolean_t retimer_configured;
189 enum al_eth_lm_max_speed max_speed;
191 boolean_t sfp_detect_force_mode;
193 enum al_eth_lm_link_state link_state;
196 boolean_t (*lm_pause)(void *handle);
198 void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);
201 struct al_eth_lm_init_params {
202 /* pointer to HAL context */
203 struct al_hal_eth_adapter *adapter;
204 /* pointer to serdes object */
205 struct al_serdes_grp_obj *serdes_obj;
206 /* serdes lane for this port */
207 enum al_serdes_lane lane;
210 * set to true to perform sfp detection if the link is down.
211 * when set to true, eeprom_read below should NOT be NULL.
213 boolean_t sfp_detection;
214 /* i2c bus id of the SFP for this port */
216 /* i2c addr of the SFP for this port */
217 uint8_t sfp_i2c_addr;
219 * default mode, and dac length will be used in case sfp_detection
220 * is not set or in case the detection failed.
222 enum al_eth_lm_link_mode default_mode;
223 uint8_t default_dac_len;
225 /* the i2c bus id and addr of the retimer in case it exist */
226 uint8_t retimer_bus_id;
227 uint8_t retimer_i2c_addr;
228 /* retimer channel connected to this port */
229 enum al_eth_retimer_channel retimer_channel;
230 enum al_eth_retimer_channel retimer_tx_channel;
231 /* retimer type if exist */
232 enum al_eth_retimer_type retimer_type;
235 * the following parameters control what mechanisms to run
236 * on link_establish with the following steps:
237 * - if retimer_exist is set, the retimer will be configured based on DA len.
238 * - if link_training is set and DA detected run link training. if succeed return 0
239 * - if rx_equal is set serdes equalization will be run to configure the rx parameters.
240 * - if static_values is set, tx and rx values will be set based on static values.
242 boolean_t retimer_exist;
243 boolean_t link_training;
245 boolean_t static_values;
247 /* enable / disable fec capabilities in AN */
248 boolean_t kr_fec_enable;
251 * pointer to function that's read 1 byte from eeprom
252 * in case no eeprom is connected should return -ETIMEDOUT
254 int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
255 uint8_t reg_addr, uint8_t *val);
256 int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,
257 uint8_t reg_addr, uint8_t val);
259 /* pointer to function that return 1 rand byte */
260 uint8_t (*get_random_byte)(void);
262 /* pointer to function that gets GPIO value - if NULL gpio present won't be used */
263 int (*gpio_get)(unsigned int gpio);
264 /* gpio number connected to the SFP present pin */
265 uint32_t gpio_present;
267 enum al_eth_lm_max_speed max_speed;
269 /* in case force mode is true - the default mode will be set regardless to
270 * the SFP EEPROM content */
271 boolean_t sfp_detect_force_mode;
273 /* lm pause callback - in case it return true the LM will try to preserve
274 * the current link status and will not try to establish new link (and will not
275 * access to i2c bus) */
276 boolean_t (*lm_pause)(void *handle);
278 /* config ethernet LEDs according to data. can be NULL if no configuration needed */
279 void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);
283 * initialize link management context and set configuration
285 * @param lm_context pointer to link management context
286 * @param params parameters passed from upper layer
288 * @return 0 in case of success. otherwise on failure.
290 int al_eth_lm_init(struct al_eth_lm_context *lm_context,
291 struct al_eth_lm_init_params *params);
294 * perform link status check. in case link is down perform sfp detection
296 * @param lm_context pointer to link management context
297 * @param link_fault indicate if the link is down
298 * @param old_mode the last working mode
299 * @param new_mode the new mode detected in this call
301 * @return 0 in case of success. otherwise on failure.
303 int al_eth_lm_link_detection(struct al_eth_lm_context *lm_context,
304 boolean_t *link_fault, enum al_eth_lm_link_mode *old_mode,
305 enum al_eth_lm_link_mode *new_mode);
308 * run LT, rx equalization and static values override according to configuration
309 * This function MUST be called inside a lock as it using common serdes registers
311 * @param lm_context pointer to link management context
312 * @param link_up set to true in case link is establish successfully
314 * @return < 0 in case link was failed to be established
316 int al_eth_lm_link_establish(struct al_eth_lm_context *lm_context,
320 * override the default static parameters
322 * @param lm_context pointer to link management context
323 * @param tx_params pointer to new tx params
324 * @param rx_params pointer to new rx params
326 * @return 0 in case of success. otherwise on failure.
328 int al_eth_lm_static_parameters_override(struct al_eth_lm_context *lm_context,
329 struct al_serdes_adv_tx_params *tx_params,
330 struct al_serdes_adv_rx_params *rx_params);
333 * disable serdes parameters override
335 * @param lm_context pointer to link management context
336 * @param tx_params set to true to disable override of tx params
337 * @param rx_params set to true to disable override of rx params
339 * @return 0 in case of success. otherwise on failure.
341 int al_eth_lm_static_parameters_override_disable(struct al_eth_lm_context *lm_context,
342 boolean_t tx_params, boolean_t rx_params);
345 * get the static parameters that are being used
346 * if the parameters was override - return the override values
347 * else return the current values of the parameters
349 * @param lm_context pointer to link management context
350 * @param tx_params pointer to new tx params
351 * @param rx_params pointer to new rx params
353 * @return 0 in case of success. otherwise on failure.
355 int al_eth_lm_static_parameters_get(struct al_eth_lm_context *lm_context,
356 struct al_serdes_adv_tx_params *tx_params,
357 struct al_serdes_adv_rx_params *rx_params);
360 * convert link management mode to string
362 * @param val link management mode
364 * @return string of the mode
366 const char *al_eth_lm_mode_convert_to_str(enum al_eth_lm_link_mode val);
369 * print all debug messages
371 * @param lm_context pointer to link management context
372 * @param enable set to true to enable debug mode
374 void al_eth_lm_debug_mode_set(struct al_eth_lm_context *lm_context,