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/axgbe/xgbe-phy-v1.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  * AMD 10Gb Ethernet driver
    3  *
    4  * Copyright (c) 2020 Advanced Micro Devices, Inc.
    5  *
    6  * This file is available to you under your choice of the following two
    7  * licenses:
    8  *
    9  * License 1: GPLv2
   10  *
   11  * This file is free software; you may copy, redistribute and/or modify
   12  * it under the terms of the GNU General Public License as published by
   13  * the Free Software Foundation, either version 2 of the License, or (at
   14  * your option) any later version.
   15  *
   16  * This file is distributed in the hope that it will be useful, but
   17  * WITHOUT ANY WARRANTY; without even the implied warranty of
   18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   19  * General Public License for more details.
   20  *
   21  * You should have received a copy of the GNU General Public License
   22  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   23  *
   24  * This file incorporates work covered by the following copyright and
   25  * permission notice:
   26  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
   27  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
   28  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
   29  *     and you.
   30  *
   31  *     The Software IS NOT an item of Licensed Software or Licensed Product
   32  *     under any End User Software License Agreement or Agreement for Licensed
   33  *     Product with Synopsys or any supplement thereto.  Permission is hereby
   34  *     granted, free of charge, to any person obtaining a copy of this software
   35  *     annotated with this license and the Software, to deal in the Software
   36  *     without restriction, including without limitation the rights to use,
   37  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   38  *     of the Software, and to permit persons to whom the Software is furnished
   39  *     to do so, subject to the following conditions:
   40  *
   41  *     The above copyright notice and this permission notice shall be included
   42  *     in all copies or substantial portions of the Software.
   43  *
   44  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
   45  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   46  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   47  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
   48  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   49  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   50  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   51  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   52  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   53  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   54  *     THE POSSIBILITY OF SUCH DAMAGE.
   55  *
   56  *
   57  * License 2: Modified BSD
   58  *
   59  * Redistribution and use in source and binary forms, with or without
   60  * modification, are permitted provided that the following conditions are met:
   61  *     * Redistributions of source code must retain the above copyright
   62  *       notice, this list of conditions and the following disclaimer.
   63  *     * Redistributions in binary form must reproduce the above copyright
   64  *       notice, this list of conditions and the following disclaimer in the
   65  *       documentation and/or other materials provided with the distribution.
   66  *     * Neither the name of Advanced Micro Devices, Inc. nor the
   67  *       names of its contributors may be used to endorse or promote products
   68  *       derived from this software without specific prior written permission.
   69  *
   70  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   71  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   72  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   73  * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
   74  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   75  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   76  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   77  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   78  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   79  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   80  *
   81  * This file incorporates work covered by the following copyright and
   82  * permission notice:
   83  *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
   84  *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
   85  *     Inc. unless otherwise expressly agreed to in writing between Synopsys
   86  *     and you.
   87  *
   88  *     The Software IS NOT an item of Licensed Software or Licensed Product
   89  *     under any End User Software License Agreement or Agreement for Licensed
   90  *     Product with Synopsys or any supplement thereto.  Permission is hereby
   91  *     granted, free of charge, to any person obtaining a copy of this software
   92  *     annotated with this license and the Software, to deal in the Software
   93  *     without restriction, including without limitation the rights to use,
   94  *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
   95  *     of the Software, and to permit persons to whom the Software is furnished
   96  *     to do so, subject to the following conditions:
   97  *
   98  *     The above copyright notice and this permission notice shall be included
   99  *     in all copies or substantial portions of the Software.
  100  *
  101  *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
  102  *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  103  *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  104  *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
  105  *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  106  *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  107  *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  108  *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  109  *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  110  *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  111  *     THE POSSIBILITY OF SUCH DAMAGE.
  112  */
  113 
  114 #include <sys/cdefs.h>
  115 __FBSDID("$FreeBSD$");
  116 
  117 #include "xgbe.h"
  118 #include "xgbe-common.h"
  119 
  120 struct xgbe_phy_data {
  121         /* 1000/10000 vs 2500/10000 indicator */
  122         unsigned int speed_set;
  123 
  124         /* SerDes UEFI configurable settings.
  125          *   Switching between modes/speeds requires new values for some
  126          *   SerDes settings.  The values can be supplied as device
  127          *   properties in array format.  The first array entry is for
  128          *   1GbE, second for 2.5GbE and third for 10GbE
  129          */
  130         uint32_t blwc[XGBE_SPEEDS];
  131         uint32_t cdr_rate[XGBE_SPEEDS];
  132         uint32_t pq_skew[XGBE_SPEEDS];
  133         uint32_t tx_amp[XGBE_SPEEDS];
  134         uint32_t dfe_tap_cfg[XGBE_SPEEDS];
  135         uint32_t dfe_tap_ena[XGBE_SPEEDS];
  136 };
  137 
  138 static void
  139 xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
  140 {
  141         XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
  142 }
  143 
  144 static void
  145 xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
  146 {
  147         XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
  148 }
  149 
  150 static enum xgbe_mode
  151 xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
  152 {
  153         struct xgbe_phy_data *phy_data = pdata->phy_data;
  154         enum xgbe_mode mode;
  155         unsigned int ad_reg, lp_reg;
  156 
  157         XGBE_SET_LP_ADV(&pdata->phy, Autoneg);
  158         XGBE_SET_LP_ADV(&pdata->phy, Backplane);
  159 
  160         /* Compare Advertisement and Link Partner register 1 */
  161         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
  162         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
  163         if (lp_reg & 0x400)
  164                 XGBE_SET_LP_ADV(&pdata->phy, Pause);
  165         if (lp_reg & 0x800)
  166                 XGBE_SET_LP_ADV(&pdata->phy, Asym_Pause);
  167 
  168         axgbe_printf(1, "%s: pause_autoneg %d ad_reg 0x%x lp_reg 0x%x\n",
  169             __func__, pdata->phy.pause_autoneg, ad_reg, lp_reg);
  170 
  171         if (pdata->phy.pause_autoneg) {
  172                 /* Set flow control based on auto-negotiation result */
  173                 pdata->phy.tx_pause = 0;
  174                 pdata->phy.rx_pause = 0;
  175 
  176                 if (ad_reg & lp_reg & 0x400) {
  177                         pdata->phy.tx_pause = 1;
  178                         pdata->phy.rx_pause = 1;
  179                 } else if (ad_reg & lp_reg & 0x800) {
  180                         if (ad_reg & 0x400)
  181                                 pdata->phy.rx_pause = 1;
  182                         else if (lp_reg & 0x400)
  183                                 pdata->phy.tx_pause = 1;
  184                 }
  185         }
  186 
  187         /* Compare Advertisement and Link Partner register 2 */
  188         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
  189         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
  190         if (lp_reg & 0x80)
  191                 XGBE_SET_LP_ADV(&pdata->phy, 10000baseKR_Full);
  192         if (lp_reg & 0x20) {
  193                 if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
  194                         XGBE_SET_LP_ADV(&pdata->phy, 2500baseX_Full);
  195                 else
  196                         XGBE_SET_LP_ADV(&pdata->phy, 1000baseKX_Full);
  197         }
  198 
  199         ad_reg &= lp_reg;
  200         if (ad_reg & 0x80) {
  201                 pdata->phy.speed = SPEED_10000;
  202                 mode = XGBE_MODE_KR;
  203         } else if (ad_reg & 0x20) {
  204                 switch (pdata->speed_set) {
  205                 case XGBE_SPEEDSET_1000_10000:
  206                         pdata->phy.speed = SPEED_1000;
  207                         mode = XGBE_MODE_KX_1000;
  208                         break;
  209 
  210                 case XGBE_SPEEDSET_2500_10000:
  211                         pdata->phy.speed = SPEED_2500;
  212                         mode = XGBE_MODE_KX_2500;
  213                         break;
  214                 }
  215         } else {
  216                 mode = XGBE_MODE_UNKNOWN;
  217                 pdata->phy.speed = SPEED_UNKNOWN;
  218         }
  219 
  220         /* Compare Advertisement and Link Partner register 3 */
  221         ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
  222         lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
  223         if (lp_reg & 0xc000)
  224                 XGBE_SET_LP_ADV(&pdata->phy, 10000baseR_FEC);
  225 
  226         return (mode);
  227 }
  228 
  229 static void
  230 xgbe_phy_an_advertising(struct xgbe_prv_data *pdata, struct xgbe_phy *dphy)
  231 {
  232         XGBE_LM_COPY(dphy, advertising, &pdata->phy, advertising);
  233 }
  234 
  235 static int
  236 xgbe_phy_an_config(struct xgbe_prv_data *pdata)
  237 {
  238         /* Nothing uniquely required for an configuration */
  239         return (0);
  240 }
  241 
  242 static enum xgbe_an_mode
  243 xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
  244 {
  245         return (XGBE_AN_MODE_CL73);
  246 }
  247 
  248 static void
  249 xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
  250 {
  251         unsigned int reg;
  252 
  253         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
  254 
  255         reg |= MDIO_CTRL1_LPOWER;
  256         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
  257 
  258         DELAY(75);
  259 
  260         reg &= ~MDIO_CTRL1_LPOWER;
  261         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
  262 }
  263 
  264 static void
  265 xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
  266 {
  267         /* Assert Rx and Tx ratechange */
  268         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
  269 }
  270 
  271 static void
  272 xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
  273 {
  274         unsigned int wait;
  275         uint16_t status;
  276 
  277         /* Release Rx and Tx ratechange */
  278         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
  279 
  280         /* Wait for Rx and Tx ready */
  281         wait = XGBE_RATECHANGE_COUNT;
  282         while (wait--) {
  283                 DELAY(50);
  284 
  285                 status = XSIR0_IOREAD(pdata, SIR0_STATUS);
  286                 if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
  287                     XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
  288                         goto rx_reset;
  289         }
  290 
  291         axgbe_printf(2, "SerDes rx/tx not ready (%#hx)\n", status);
  292 
  293 rx_reset:
  294         /* Perform Rx reset for the DFE changes */
  295         XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
  296         XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
  297 }
  298 
  299 static void
  300 xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
  301 {
  302         struct xgbe_phy_data *phy_data = pdata->phy_data;
  303         unsigned int reg;
  304 
  305         /* Set PCS to KR/10G speed */
  306         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
  307         reg &= ~MDIO_PCS_CTRL2_TYPE;
  308         reg |= MDIO_PCS_CTRL2_10GBR;
  309         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
  310 
  311         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
  312         reg &= ~MDIO_CTRL1_SPEEDSEL;
  313         reg |= MDIO_CTRL1_SPEED10G;
  314         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
  315 
  316         xgbe_phy_pcs_power_cycle(pdata);
  317 
  318         /* Set SerDes to 10G speed */
  319         xgbe_phy_start_ratechange(pdata);
  320 
  321         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
  322         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
  323         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
  324 
  325         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
  326                            phy_data->cdr_rate[XGBE_SPEED_10000]);
  327         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
  328                            phy_data->tx_amp[XGBE_SPEED_10000]);
  329         XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
  330                            phy_data->blwc[XGBE_SPEED_10000]);
  331         XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
  332                            phy_data->pq_skew[XGBE_SPEED_10000]);
  333         XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
  334                            phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
  335         XRXTX_IOWRITE(pdata, RXTX_REG22,
  336                       phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
  337 
  338         xgbe_phy_complete_ratechange(pdata);
  339 
  340         axgbe_printf(2, "10GbE KR mode set\n");
  341 }
  342 
  343 static void
  344 xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
  345 {
  346         struct xgbe_phy_data *phy_data = pdata->phy_data;
  347         unsigned int reg;
  348 
  349         /* Set PCS to KX/1G speed */
  350         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
  351         reg &= ~MDIO_PCS_CTRL2_TYPE;
  352         reg |= MDIO_PCS_CTRL2_10GBX;
  353         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
  354 
  355         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
  356         reg &= ~MDIO_CTRL1_SPEEDSEL;
  357         reg |= MDIO_CTRL1_SPEED1G;
  358         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
  359 
  360         xgbe_phy_pcs_power_cycle(pdata);
  361 
  362         /* Set SerDes to 2.5G speed */
  363         xgbe_phy_start_ratechange(pdata);
  364 
  365         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
  366         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
  367         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
  368 
  369         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
  370                            phy_data->cdr_rate[XGBE_SPEED_2500]);
  371         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
  372                            phy_data->tx_amp[XGBE_SPEED_2500]);
  373         XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
  374                            phy_data->blwc[XGBE_SPEED_2500]);
  375         XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
  376                            phy_data->pq_skew[XGBE_SPEED_2500]);
  377         XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
  378                            phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
  379         XRXTX_IOWRITE(pdata, RXTX_REG22,
  380                       phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
  381 
  382         xgbe_phy_complete_ratechange(pdata);
  383 
  384         axgbe_printf(2, "2.5GbE KX mode set\n");
  385 }
  386 
  387 static void
  388 xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
  389 {
  390         struct xgbe_phy_data *phy_data = pdata->phy_data;
  391         unsigned int reg;
  392 
  393         /* Set PCS to KX/1G speed */
  394         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
  395         reg &= ~MDIO_PCS_CTRL2_TYPE;
  396         reg |= MDIO_PCS_CTRL2_10GBX;
  397         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
  398 
  399         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
  400         reg &= ~MDIO_CTRL1_SPEEDSEL;
  401         reg |= MDIO_CTRL1_SPEED1G;
  402         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
  403 
  404         xgbe_phy_pcs_power_cycle(pdata);
  405 
  406         /* Set SerDes to 1G speed */
  407         xgbe_phy_start_ratechange(pdata);
  408 
  409         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
  410         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
  411         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
  412 
  413         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
  414                            phy_data->cdr_rate[XGBE_SPEED_1000]);
  415         XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
  416                            phy_data->tx_amp[XGBE_SPEED_1000]);
  417         XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
  418                            phy_data->blwc[XGBE_SPEED_1000]);
  419         XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
  420                            phy_data->pq_skew[XGBE_SPEED_1000]);
  421         XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
  422                            phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
  423         XRXTX_IOWRITE(pdata, RXTX_REG22,
  424                       phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
  425 
  426         xgbe_phy_complete_ratechange(pdata);
  427 
  428         axgbe_printf(2, "1GbE KX mode set\n");
  429 }
  430 
  431 static enum xgbe_mode
  432 xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
  433 {
  434         struct xgbe_phy_data *phy_data = pdata->phy_data;
  435         enum xgbe_mode mode;
  436         unsigned int reg;
  437 
  438         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
  439         reg &= MDIO_PCS_CTRL2_TYPE;
  440 
  441         if (reg == MDIO_PCS_CTRL2_10GBR) {
  442                 mode = XGBE_MODE_KR;
  443         } else {
  444                 if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
  445                         mode = XGBE_MODE_KX_2500;
  446                 else
  447                         mode = XGBE_MODE_KX_1000;
  448         }
  449 
  450         return (mode);
  451 }
  452 
  453 static enum xgbe_mode
  454 xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
  455 {
  456         struct xgbe_phy_data *phy_data = pdata->phy_data;
  457         enum xgbe_mode mode;
  458 
  459         /* If we are in KR switch to KX, and vice-versa */
  460         if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
  461                 if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
  462                         mode = XGBE_MODE_KX_2500;
  463                 else
  464                         mode = XGBE_MODE_KX_1000;
  465         } else {
  466                 mode = XGBE_MODE_KR;
  467         }
  468 
  469         return (mode);
  470 }
  471 
  472 static enum xgbe_mode
  473 xgbe_phy_get_mode(struct xgbe_prv_data *pdata, int speed)
  474 {
  475         struct xgbe_phy_data *phy_data = pdata->phy_data;
  476 
  477         switch (speed) {
  478         case SPEED_1000:
  479                 return ((phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
  480                         ? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN);
  481         case SPEED_2500:
  482                 return ((phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
  483                         ? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN);
  484         case SPEED_10000:
  485                 return (XGBE_MODE_KR);
  486         default:
  487                 return (XGBE_MODE_UNKNOWN);
  488         }
  489 }
  490 
  491 static void
  492 xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
  493 {
  494         switch (mode) {
  495         case XGBE_MODE_KX_1000:
  496                 xgbe_phy_kx_1000_mode(pdata);
  497                 break;
  498         case XGBE_MODE_KX_2500:
  499                 xgbe_phy_kx_2500_mode(pdata);
  500                 break;
  501         case XGBE_MODE_KR:
  502                 xgbe_phy_kr_mode(pdata);
  503                 break;
  504         default:
  505                 break;
  506         }
  507 }
  508 
  509 static void
  510 xgbe_phy_get_type(struct xgbe_prv_data *pdata, struct ifmediareq * ifmr)
  511 {
  512 
  513         switch (pdata->phy.speed) {
  514         case SPEED_10000:
  515                 ifmr->ifm_active |= IFM_10G_KR;
  516                 break;
  517         case SPEED_2500:
  518                 ifmr->ifm_active |= IFM_2500_KX;
  519                 break;
  520         case SPEED_1000:
  521                 ifmr->ifm_active |= IFM_1000_KX;
  522                 break;
  523         default:
  524                 ifmr->ifm_active |= IFM_OTHER;
  525                 break;
  526         }
  527 }
  528 
  529 static bool
  530 xgbe_phy_check_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode, bool advert)
  531 {
  532 
  533         if (pdata->phy.autoneg == AUTONEG_ENABLE)
  534                 return (advert);
  535         else {
  536                 enum xgbe_mode cur_mode;
  537 
  538                 cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
  539                 if (cur_mode == mode)
  540                         return (true);
  541         }
  542 
  543         return (false);
  544 }
  545 
  546 static bool
  547 xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
  548 {
  549 
  550         switch (mode) {
  551         case XGBE_MODE_KX_1000:
  552                 return (xgbe_phy_check_mode(pdata, mode,
  553                     XGBE_ADV(&pdata->phy, 1000baseKX_Full)));
  554         case XGBE_MODE_KX_2500:
  555                 return (xgbe_phy_check_mode(pdata, mode,
  556                     XGBE_ADV(&pdata->phy, 2500baseX_Full)));
  557         case XGBE_MODE_KR:
  558                 return (xgbe_phy_check_mode(pdata, mode,
  559                     XGBE_ADV(&pdata->phy, 10000baseKR_Full)));
  560         default:
  561                 return (false);
  562         }
  563 }
  564 
  565 static bool
  566 xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
  567 {
  568         struct xgbe_phy_data *phy_data = pdata->phy_data;
  569 
  570         switch (speed) {
  571         case SPEED_1000:
  572                 if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
  573                         return (false);
  574                 return (true);
  575         case SPEED_2500:
  576                 if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
  577                         return (false);
  578                 return (true);
  579         case SPEED_10000:
  580                 return (true);
  581         default:
  582                 return (false);
  583         }
  584 }
  585 
  586 static int
  587 xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
  588 {
  589         unsigned int reg;
  590 
  591         *an_restart = 0;
  592 
  593         /* Link status is latched low, so read once to clear
  594          * and then read again to get current state
  595          */
  596         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
  597         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
  598 
  599         return ((reg & MDIO_STAT1_LSTATUS) ? 1 : 0);
  600 }
  601 
  602 static void
  603 xgbe_phy_stop(struct xgbe_prv_data *pdata)
  604 {
  605         /* Nothing uniquely required for stop */
  606 }
  607 
  608 static int
  609 xgbe_phy_start(struct xgbe_prv_data *pdata)
  610 {
  611         /* Nothing uniquely required for start */
  612         return (0);
  613 }
  614 
  615 static int
  616 xgbe_phy_reset(struct xgbe_prv_data *pdata)
  617 {
  618         unsigned int reg, count;
  619 
  620         /* Perform a software reset of the PCS */
  621         reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
  622         reg |= MDIO_CTRL1_RESET;
  623         XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
  624 
  625         count = 50;
  626         do {
  627                 DELAY(20);
  628                 reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
  629         } while ((reg & MDIO_CTRL1_RESET) && --count);
  630 
  631         if (reg & MDIO_CTRL1_RESET)
  632                 return (-ETIMEDOUT);
  633 
  634         return (0);
  635 }
  636 
  637 static void
  638 xgbe_phy_exit(struct xgbe_prv_data *pdata)
  639 {
  640         /* Nothing uniquely required for exit */
  641 }
  642 
  643 static int
  644 xgbe_phy_init(struct xgbe_prv_data *pdata)
  645 {
  646         struct xgbe_phy_data *phy_data;
  647 
  648         phy_data = malloc(sizeof(*phy_data), M_AXGBE, M_WAITOK | M_ZERO);
  649 
  650         /* Initialize supported features */
  651         XGBE_ZERO_SUP(&pdata->phy);
  652         XGBE_SET_SUP(&pdata->phy, Autoneg);
  653         XGBE_SET_SUP(&pdata->phy, Pause);
  654         XGBE_SET_SUP(&pdata->phy, Asym_Pause);
  655         XGBE_SET_SUP(&pdata->phy, Backplane);
  656         XGBE_SET_SUP(&pdata->phy, 10000baseKR_Full);
  657         switch (phy_data->speed_set) {
  658         case XGBE_SPEEDSET_1000_10000:
  659                 XGBE_SET_SUP(&pdata->phy, 1000baseKX_Full);
  660                 break;
  661         case XGBE_SPEEDSET_2500_10000:
  662                 XGBE_SET_SUP(&pdata->phy, 2500baseX_Full);
  663                 break;
  664         }
  665 
  666         if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
  667                 XGBE_SET_SUP(&pdata->phy, 10000baseR_FEC);
  668 
  669         pdata->phy_data = phy_data;
  670 
  671         return (0);
  672 }
  673 
  674 void
  675 xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
  676 {
  677         struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
  678 
  679         phy_impl->init                  = xgbe_phy_init;
  680         phy_impl->exit                  = xgbe_phy_exit;
  681 
  682         phy_impl->reset                 = xgbe_phy_reset;
  683         phy_impl->start                 = xgbe_phy_start;
  684         phy_impl->stop                  = xgbe_phy_stop;
  685 
  686         phy_impl->link_status           = xgbe_phy_link_status;
  687 
  688         phy_impl->valid_speed           = xgbe_phy_valid_speed;
  689 
  690         phy_impl->use_mode              = xgbe_phy_use_mode;
  691         phy_impl->set_mode              = xgbe_phy_set_mode;
  692         phy_impl->get_mode              = xgbe_phy_get_mode;
  693         phy_impl->switch_mode           = xgbe_phy_switch_mode;
  694         phy_impl->cur_mode              = xgbe_phy_cur_mode;
  695         phy_impl->get_type              = xgbe_phy_get_type;
  696 
  697         phy_impl->an_mode               = xgbe_phy_an_mode;
  698 
  699         phy_impl->an_config             = xgbe_phy_an_config;
  700 
  701         phy_impl->an_advertising        = xgbe_phy_an_advertising;
  702 
  703         phy_impl->an_outcome            = xgbe_phy_an_outcome;
  704 
  705         phy_impl->kr_training_pre       = xgbe_phy_kr_training_pre;
  706         phy_impl->kr_training_post      = xgbe_phy_kr_training_post;
  707 }

Cache object: a06cc322098c74e0973b450e934e2ec9


[ 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.