The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/al_eth/al_init_eth_lm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 5e63d8f0ced08e0fb897e0124cb620e0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.