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/cxgb/common/cxgb_tn1010.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 SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3 
    4 Copyright (c) 2008, Chelsio Inc.
    5 All rights reserved.
    6 
    7 Redistribution and use in source and binary forms, with or without
    8 modification, are permitted provided that the following conditions are met:
    9 
   10  1. Redistributions of source code must retain the above copyright notice,
   11     this list of conditions and the following disclaimer.
   12 
   13  2. Neither the name of the Chelsio Corporation nor the names of its
   14     contributors may be used to endorse or promote products derived from
   15     this software without specific prior written permission.
   16 
   17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27 POSSIBILITY OF SUCH DAMAGE.
   28 
   29 ***************************************************************************/
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <cxgb_include.h>
   35 
   36 #undef msleep
   37 #define msleep t3_os_sleep
   38 
   39 /* TN1010 PHY specific registers. */
   40 enum {
   41         TN1010_VEND1_STAT = 1,
   42 };
   43 
   44 /* IEEE auto-negotiation 10GBASE-T registers */
   45 enum {
   46         ANEG_ADVER    = 16,
   47         ANEG_LPA      = 19,
   48         ANEG_10G_CTRL = 32,
   49         ANEG_10G_STAT = 33
   50 };
   51 
   52 #define ADVERTISE_ENPAGE      (1 << 12)
   53 #define ADVERTISE_10000FULL   (1 << 12)
   54 #define ADVERTISE_LOOP_TIMING (1 << 0)
   55 
   56 /* vendor specific status register fields */
   57 #define F_XS_LANE_ALIGN_STAT (1 << 0)
   58 #define F_PCS_BLK_LOCK       (1 << 1)
   59 #define F_PMD_SIGNAL_OK      (1 << 2)
   60 #define F_LINK_STAT          (1 << 3)
   61 #define F_ANEG_SPEED_1G      (1 << 4)
   62 #define F_ANEG_MASTER        (1 << 5)
   63 
   64 #define S_ANEG_STAT    6
   65 #define M_ANEG_STAT    0x3
   66 #define G_ANEG_STAT(x) (((x) >> S_ANEG_STAT) & M_ANEG_STAT)
   67 
   68 enum {                        /* autonegotiation status */
   69         ANEG_IN_PROGR = 0,
   70         ANEG_COMPLETE = 1,
   71         ANEG_FAILED   = 3
   72 };
   73 
   74 /*
   75  * Reset the PHY.  May take up to 500ms to complete.
   76  */
   77 static int tn1010_reset(struct cphy *phy, int wait)
   78 {
   79         int err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
   80         msleep(500);
   81         return err;
   82 }
   83 
   84 static int tn1010_power_down(struct cphy *phy, int enable)
   85 {
   86         return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
   87                                    BMCR_PDOWN, enable ? BMCR_PDOWN : 0);
   88 }
   89 
   90 static int tn1010_autoneg_enable(struct cphy *phy)
   91 {
   92         int err;
   93 
   94         err = tn1010_power_down(phy, 0);
   95         if (!err)
   96                 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR, 0,
   97                                           BMCR_ANENABLE | BMCR_ANRESTART);
   98         return err;
   99 }
  100 
  101 static int tn1010_autoneg_restart(struct cphy *phy)
  102 {
  103         int err;
  104 
  105         err = tn1010_power_down(phy, 0);
  106         if (!err)
  107                 err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR, 0,
  108                                           BMCR_ANRESTART);
  109         return err;
  110 }
  111 
  112 static int tn1010_advertise(struct cphy *phy, unsigned int advert)
  113 {
  114         int err, val;
  115 
  116         if (!(advert & ADVERTISED_1000baseT_Full))
  117                 return -EINVAL;               /* PHY can't disable 1000BASE-T */
  118 
  119         val = ADVERTISE_CSMA | ADVERTISE_ENPAGE | ADVERTISE_NPAGE;
  120         if (advert & ADVERTISED_Pause)
  121                 val |= ADVERTISE_PAUSE_CAP;
  122         if (advert & ADVERTISED_Asym_Pause)
  123                 val |= ADVERTISE_PAUSE_ASYM;
  124         err = mdio_write(phy, MDIO_DEV_ANEG, ANEG_ADVER, val);
  125         if (err)
  126                 return err;
  127 
  128         val = (advert & ADVERTISED_10000baseT_Full) ? ADVERTISE_10000FULL : 0;
  129         return mdio_write(phy, MDIO_DEV_ANEG, ANEG_10G_CTRL, val |
  130                           ADVERTISE_LOOP_TIMING);
  131 }
  132 
  133 static int tn1010_get_link_status(struct cphy *phy, int *link_state,
  134                                   int *speed, int *duplex, int *fc)
  135 {
  136         unsigned int status, lpa, adv;
  137         int err, sp = -1, pause = 0;
  138 
  139         err = mdio_read(phy, MDIO_DEV_VEND1, TN1010_VEND1_STAT, &status);
  140         if (err)
  141                 return err;
  142 
  143         if (link_state)
  144                 *link_state = status & F_LINK_STAT ? PHY_LINK_UP :
  145                     PHY_LINK_DOWN;
  146 
  147         if (G_ANEG_STAT(status) == ANEG_COMPLETE) {
  148                 sp = (status & F_ANEG_SPEED_1G) ? SPEED_1000 : SPEED_10000;
  149 
  150                 if (fc) {
  151                         err = mdio_read(phy, MDIO_DEV_ANEG, ANEG_LPA, &lpa);
  152                         if (!err)
  153                                 err = mdio_read(phy, MDIO_DEV_ANEG, ANEG_ADVER,
  154                                                 &adv);
  155                         if (err)
  156                                 return err;
  157 
  158                         if (lpa & adv & ADVERTISE_PAUSE_CAP)
  159                                 pause = PAUSE_RX | PAUSE_TX;
  160                         else if ((lpa & ADVERTISE_PAUSE_CAP) &&
  161                                  (lpa & ADVERTISE_PAUSE_ASYM) &&
  162                                  (adv & ADVERTISE_PAUSE_ASYM))
  163                                 pause = PAUSE_TX;
  164                         else if ((lpa & ADVERTISE_PAUSE_ASYM) &&
  165                                  (adv & ADVERTISE_PAUSE_CAP))
  166                                 pause = PAUSE_RX;
  167                 }
  168         }
  169         if (speed)
  170                 *speed = sp;
  171         if (duplex)
  172                 *duplex = DUPLEX_FULL;
  173         if (fc)
  174                 *fc = pause;
  175         return 0;
  176 }
  177 
  178 static int tn1010_set_speed_duplex(struct cphy *phy, int speed, int duplex)
  179 {
  180         return -EINVAL;    /* require autoneg */
  181 }
  182 
  183 #ifdef C99_NOT_SUPPORTED
  184 static struct cphy_ops tn1010_ops = {
  185         tn1010_reset,
  186         t3_phy_lasi_intr_enable,
  187         t3_phy_lasi_intr_disable,
  188         t3_phy_lasi_intr_clear,
  189         t3_phy_lasi_intr_handler,
  190         tn1010_autoneg_enable,
  191         tn1010_autoneg_restart,
  192         tn1010_advertise,
  193         NULL,
  194         tn1010_set_speed_duplex,
  195         tn1010_get_link_status,
  196         tn1010_power_down,
  197 };
  198 #else
  199 static struct cphy_ops tn1010_ops = {
  200         .reset             = tn1010_reset,
  201         .intr_enable       = t3_phy_lasi_intr_enable,
  202         .intr_disable      = t3_phy_lasi_intr_disable,
  203         .intr_clear        = t3_phy_lasi_intr_clear,
  204         .intr_handler      = t3_phy_lasi_intr_handler,
  205         .autoneg_enable    = tn1010_autoneg_enable,
  206         .autoneg_restart   = tn1010_autoneg_restart,
  207         .advertise         = tn1010_advertise,
  208         .set_speed_duplex  = tn1010_set_speed_duplex,
  209         .get_link_status   = tn1010_get_link_status,
  210         .power_down        = tn1010_power_down,
  211 };
  212 #endif
  213 
  214 int t3_tn1010_phy_prep(pinfo_t *pinfo, int phy_addr,
  215                        const struct mdio_ops *mdio_ops)
  216 {
  217         cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &tn1010_ops, mdio_ops,
  218                   SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
  219                   SUPPORTED_Autoneg | SUPPORTED_AUI | SUPPORTED_TP,
  220                   "1000/10GBASE-T");
  221         msleep(500);    /* PHY needs up to 500ms to start responding to MDIO */
  222         return 0;
  223 }

Cache object: 1e30e84ae818c88bad7ad5dc6d77952c


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