/*-1* Copyright (c) 2015,2016 Annapurna Labs Ltd. and affiliates2* All rights reserved.3*4* Developed by Semihalf.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728/**29* Ethernet30* @{31* @file al_init_eth_lm.h32*33* @brief ethernet link management common utilities34*35* Common operation example:36* @code37* int main()38* {39* struct al_eth_lm_context lm_context;40* struct al_eth_lm_init_params lm_params;41* enum al_eth_lm_link_mode old_mode;42* enum al_eth_lm_link_mode new_mode;43* al_bool fault;44* al_bool link_up;45* int rc = 0;46*47* lm_params.adapter = hal_adapter;48* lm_params.serdes_obj = serdes;49* lm_params.grp = grp;50* lm_params.lane = lane;51* lm_params.sfp_detection = true;52* lm_params.link_training = true;53* lm_params.rx_equal = true54* lm_params.static_values = true;55* lm_params.kr_fec_enable = false;56* lm_params.eeprom_read = &my_eeprom_read;57* lm_params.eeprom_context = context;58* lm_params.get_random_byte = &my_rand_byte;59* lm_params.default_mode = AL_ETH_LM_MODE_10G_DA;60*61* al_eth_lm_init(&lm_context, &lm_params);62*63* rc = al_eth_lm_link_detection(&lm_context, &fault, &old_mode, &new_mode);64* if (fault == false)65* return; // in this case the link is still up66*67* if (rc) {68* printf("link detection failed on error\n");69* return;70* }71*72* if (old_mode != new_mode) {73* // perform serdes configuration if needed74*75* // mac stop / start / config if needed76* }77*78* spin_lock(lock);79* rc = al_eth_lm_link_establish($lm_context, &link_up);80* spin_unlock(lock);81* if (rc) {82* printf("establish link failed\n");83* return;84* }85*86* if (link_up)87* printf("Link established successfully\n");88* else89* printf("No signal found. probably the link partner is disconnected\n");90* }91* @endcode92*93*/9495#ifndef __AL_INIT_ETH_LM_H__96#define __AL_INIT_ETH_LM_H__9798#include <al_serdes.h>99#include <al_hal_eth.h>100#include "al_init_eth_kr.h"101102enum al_eth_lm_link_mode {103AL_ETH_LM_MODE_DISCONNECTED,104AL_ETH_LM_MODE_10G_OPTIC,105AL_ETH_LM_MODE_10G_DA,106AL_ETH_LM_MODE_1G,107AL_ETH_LM_MODE_25G,108};109110enum al_eth_lm_max_speed {111AL_ETH_LM_MAX_SPEED_MAX,112AL_ETH_LM_MAX_SPEED_25G,113AL_ETH_LM_MAX_SPEED_10G,114AL_ETH_LM_MAX_SPEED_1G,115};116117enum al_eth_lm_link_state {118AL_ETH_LM_LINK_DOWN,119AL_ETH_LM_LINK_DOWN_RF,120AL_ETH_LM_LINK_UP,121};122123enum al_eth_lm_led_config_speed {124AL_ETH_LM_LED_CONFIG_1G,125AL_ETH_LM_LED_CONFIG_10G,126AL_ETH_LM_LED_CONFIG_25G,127};128129struct al_eth_lm_led_config_data {130enum al_eth_lm_led_config_speed speed;131};132133struct al_eth_lm_context {134struct al_hal_eth_adapter *adapter;135struct al_serdes_grp_obj *serdes_obj;136enum al_serdes_lane lane;137138uint32_t link_training_failures;139140bool tx_param_dirty;141bool serdes_tx_params_valid;142struct al_serdes_adv_tx_params tx_params_override;143bool rx_param_dirty;144bool serdes_rx_params_valid;145struct al_serdes_adv_rx_params rx_params_override;146147struct al_eth_an_adv local_adv;148struct al_eth_an_adv partner_adv;149150enum al_eth_lm_link_mode mode;151uint8_t da_len;152bool debug;153154/* configurations */155bool sfp_detection;156uint8_t sfp_bus_id;157uint8_t sfp_i2c_addr;158159enum al_eth_lm_link_mode default_mode;160uint8_t default_dac_len;161bool link_training;162bool rx_equal;163bool static_values;164165bool retimer_exist;166enum al_eth_retimer_type retimer_type;167uint8_t retimer_bus_id;168uint8_t retimer_i2c_addr;169enum al_eth_retimer_channel retimer_channel;170171/* services */172int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,173uint8_t reg_addr, uint8_t *val);174int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,175uint8_t reg_addr, uint8_t val);176void *i2c_context;177uint8_t (*get_random_byte)(void);178179int (*gpio_get)(unsigned int gpio);180uint32_t gpio_present;181182enum al_eth_retimer_channel retimer_tx_channel;183bool retimer_configured;184185enum al_eth_lm_max_speed max_speed;186187bool sfp_detect_force_mode;188189enum al_eth_lm_link_state link_state;190bool new_port;191192bool (*lm_pause)(void *handle);193194void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);195};196197struct al_eth_lm_init_params {198/* pointer to HAL context */199struct al_hal_eth_adapter *adapter;200/* pointer to serdes object */201struct al_serdes_grp_obj *serdes_obj;202/* serdes lane for this port */203enum al_serdes_lane lane;204205/*206* set to true to perform sfp detection if the link is down.207* when set to true, eeprom_read below should NOT be NULL.208*/209bool sfp_detection;210/* i2c bus id of the SFP for this port */211uint8_t sfp_bus_id;212/* i2c addr of the SFP for this port */213uint8_t sfp_i2c_addr;214/*215* default mode, and dac length will be used in case sfp_detection216* is not set or in case the detection failed.217*/218enum al_eth_lm_link_mode default_mode;219uint8_t default_dac_len;220221/* the i2c bus id and addr of the retimer in case it exist */222uint8_t retimer_bus_id;223uint8_t retimer_i2c_addr;224/* retimer channel connected to this port */225enum al_eth_retimer_channel retimer_channel;226enum al_eth_retimer_channel retimer_tx_channel;227/* retimer type if exist */228enum al_eth_retimer_type retimer_type;229230/*231* the following parameters control what mechanisms to run232* on link_establish with the following steps:233* - if retimer_exist is set, the retimer will be configured based on DA len.234* - if link_training is set and DA detected run link training. if succeed return 0235* - if rx_equal is set serdes equalization will be run to configure the rx parameters.236* - if static_values is set, tx and rx values will be set based on static values.237*/238bool retimer_exist;239bool link_training;240bool rx_equal;241bool static_values;242243/* enable / disable fec capabilities in AN */244bool kr_fec_enable;245246/*247* pointer to function that's read 1 byte from eeprom248* in case no eeprom is connected should return -ETIMEDOUT249*/250int (*i2c_read)(void *handle, uint8_t bus_id, uint8_t i2c_addr,251uint8_t reg_addr, uint8_t *val);252int (*i2c_write)(void *handle, uint8_t bus_id, uint8_t i2c_addr,253uint8_t reg_addr, uint8_t val);254void *i2c_context;255/* pointer to function that return 1 rand byte */256uint8_t (*get_random_byte)(void);257258/* pointer to function that gets GPIO value - if NULL gpio present won't be used */259int (*gpio_get)(unsigned int gpio);260/* gpio number connected to the SFP present pin */261uint32_t gpio_present;262263enum al_eth_lm_max_speed max_speed;264265/* in case force mode is true - the default mode will be set regardless to266* the SFP EEPROM content */267bool sfp_detect_force_mode;268269/* lm pause callback - in case it return true the LM will try to preserve270* the current link status and will not try to establish new link (and will not271* access to i2c bus) */272bool (*lm_pause)(void *handle);273274/* config ethernet LEDs according to data. can be NULL if no configuration needed */275void (*led_config)(void *handle, struct al_eth_lm_led_config_data *data);276};277278/**279* initialize link management context and set configuration280*281* @param lm_context pointer to link management context282* @param params parameters passed from upper layer283*284* @return 0 in case of success. otherwise on failure.285*/286int al_eth_lm_init(struct al_eth_lm_context *lm_context,287struct al_eth_lm_init_params *params);288289/**290* perform link status check. in case link is down perform sfp detection291*292* @param lm_context pointer to link management context293* @param link_fault indicate if the link is down294* @param old_mode the last working mode295* @param new_mode the new mode detected in this call296*297* @return 0 in case of success. otherwise on failure.298*/299int al_eth_lm_link_detection(struct al_eth_lm_context *lm_context,300bool *link_fault, enum al_eth_lm_link_mode *old_mode,301enum al_eth_lm_link_mode *new_mode);302303/**304* run LT, rx equalization and static values override according to configuration305* This function MUST be called inside a lock as it using common serdes registers306*307* @param lm_context pointer to link management context308* @param link_up set to true in case link is establish successfully309*310* @return < 0 in case link was failed to be established311*/312int al_eth_lm_link_establish(struct al_eth_lm_context *lm_context,313bool *link_up);314315/**316* override the default static parameters317*318* @param lm_context pointer to link management context319* @param tx_params pointer to new tx params320* @param rx_params pointer to new rx params321*322* @return 0 in case of success. otherwise on failure.323**/324int al_eth_lm_static_parameters_override(struct al_eth_lm_context *lm_context,325struct al_serdes_adv_tx_params *tx_params,326struct al_serdes_adv_rx_params *rx_params);327328/**329* disable serdes parameters override330*331* @param lm_context pointer to link management context332* @param tx_params set to true to disable override of tx params333* @param rx_params set to true to disable override of rx params334*335* @return 0 in case of success. otherwise on failure.336**/337int al_eth_lm_static_parameters_override_disable(struct al_eth_lm_context *lm_context,338bool tx_params, bool rx_params);339340/**341* get the static parameters that are being used342* if the parameters was override - return the override values343* else return the current values of the parameters344*345* @param lm_context pointer to link management context346* @param tx_params pointer to new tx params347* @param rx_params pointer to new rx params348*349* @return 0 in case of success. otherwise on failure.350*/351int al_eth_lm_static_parameters_get(struct al_eth_lm_context *lm_context,352struct al_serdes_adv_tx_params *tx_params,353struct al_serdes_adv_rx_params *rx_params);354355/**356* convert link management mode to string357*358* @param val link management mode359*360* @return string of the mode361*/362const char *al_eth_lm_mode_convert_to_str(enum al_eth_lm_link_mode val);363364/**365* print all debug messages366*367* @param lm_context pointer to link management context368* @param enable set to true to enable debug mode369*/370void al_eth_lm_debug_mode_set(struct al_eth_lm_context *lm_context,371bool enable);372#endif373374375