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/igc/igc_phy.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 2021 Intel Corp
    3  * Copyright 2021 Rubicon Communications, LLC (Netgate)
    4  * SPDX-License-Identifier: BSD-3-Clause
    5  */
    6 
    7 #include <sys/cdefs.h>
    8 __FBSDID("$FreeBSD$");
    9 
   10 #include "igc_api.h"
   11 
   12 static s32 igc_wait_autoneg(struct igc_hw *hw);
   13 
   14 /**
   15  *  igc_init_phy_ops_generic - Initialize PHY function pointers
   16  *  @hw: pointer to the HW structure
   17  *
   18  *  Setups up the function pointers to no-op functions
   19  **/
   20 void igc_init_phy_ops_generic(struct igc_hw *hw)
   21 {
   22         struct igc_phy_info *phy = &hw->phy;
   23         DEBUGFUNC("igc_init_phy_ops_generic");
   24 
   25         /* Initialize function pointers */
   26         phy->ops.init_params = igc_null_ops_generic;
   27         phy->ops.acquire = igc_null_ops_generic;
   28         phy->ops.check_reset_block = igc_null_ops_generic;
   29         phy->ops.force_speed_duplex = igc_null_ops_generic;
   30         phy->ops.get_info = igc_null_ops_generic;
   31         phy->ops.set_page = igc_null_set_page;
   32         phy->ops.read_reg = igc_null_read_reg;
   33         phy->ops.read_reg_locked = igc_null_read_reg;
   34         phy->ops.read_reg_page = igc_null_read_reg;
   35         phy->ops.release = igc_null_phy_generic;
   36         phy->ops.reset = igc_null_ops_generic;
   37         phy->ops.set_d0_lplu_state = igc_null_lplu_state;
   38         phy->ops.set_d3_lplu_state = igc_null_lplu_state;
   39         phy->ops.write_reg = igc_null_write_reg;
   40         phy->ops.write_reg_locked = igc_null_write_reg;
   41         phy->ops.write_reg_page = igc_null_write_reg;
   42         phy->ops.power_up = igc_null_phy_generic;
   43         phy->ops.power_down = igc_null_phy_generic;
   44 }
   45 
   46 /**
   47  *  igc_null_set_page - No-op function, return 0
   48  *  @hw: pointer to the HW structure
   49  *  @data: dummy variable
   50  **/
   51 s32 igc_null_set_page(struct igc_hw IGC_UNUSEDARG *hw,
   52                         u16 IGC_UNUSEDARG data)
   53 {
   54         DEBUGFUNC("igc_null_set_page");
   55         return IGC_SUCCESS;
   56 }
   57 
   58 /**
   59  *  igc_null_read_reg - No-op function, return 0
   60  *  @hw: pointer to the HW structure
   61  *  @offset: dummy variable
   62  *  @data: dummy variable
   63  **/
   64 s32 igc_null_read_reg(struct igc_hw IGC_UNUSEDARG *hw,
   65                         u32 IGC_UNUSEDARG offset, u16 IGC_UNUSEDARG *data)
   66 {
   67         DEBUGFUNC("igc_null_read_reg");
   68         return IGC_SUCCESS;
   69 }
   70 
   71 /**
   72  *  igc_null_phy_generic - No-op function, return void
   73  *  @hw: pointer to the HW structure
   74  **/
   75 void igc_null_phy_generic(struct igc_hw IGC_UNUSEDARG *hw)
   76 {
   77         DEBUGFUNC("igc_null_phy_generic");
   78         return;
   79 }
   80 
   81 /**
   82  *  igc_null_lplu_state - No-op function, return 0
   83  *  @hw: pointer to the HW structure
   84  *  @active: dummy variable
   85  **/
   86 s32 igc_null_lplu_state(struct igc_hw IGC_UNUSEDARG *hw,
   87                           bool IGC_UNUSEDARG active)
   88 {
   89         DEBUGFUNC("igc_null_lplu_state");
   90         return IGC_SUCCESS;
   91 }
   92 
   93 /**
   94  *  igc_null_write_reg - No-op function, return 0
   95  *  @hw: pointer to the HW structure
   96  *  @offset: dummy variable
   97  *  @data: dummy variable
   98  **/
   99 s32 igc_null_write_reg(struct igc_hw IGC_UNUSEDARG *hw,
  100                          u32 IGC_UNUSEDARG offset, u16 IGC_UNUSEDARG data)
  101 {
  102         DEBUGFUNC("igc_null_write_reg");
  103         return IGC_SUCCESS;
  104 }
  105 
  106 /**
  107  *  igc_check_reset_block_generic - Check if PHY reset is blocked
  108  *  @hw: pointer to the HW structure
  109  *
  110  *  Read the PHY management control register and check whether a PHY reset
  111  *  is blocked.  If a reset is not blocked return IGC_SUCCESS, otherwise
  112  *  return IGC_BLK_PHY_RESET (12).
  113  **/
  114 s32 igc_check_reset_block_generic(struct igc_hw *hw)
  115 {
  116         u32 manc;
  117 
  118         DEBUGFUNC("igc_check_reset_block");
  119 
  120         manc = IGC_READ_REG(hw, IGC_MANC);
  121 
  122         return (manc & IGC_MANC_BLK_PHY_RST_ON_IDE) ?
  123                IGC_BLK_PHY_RESET : IGC_SUCCESS;
  124 }
  125 
  126 /**
  127  *  igc_get_phy_id - Retrieve the PHY ID and revision
  128  *  @hw: pointer to the HW structure
  129  *
  130  *  Reads the PHY registers and stores the PHY ID and possibly the PHY
  131  *  revision in the hardware structure.
  132  **/
  133 s32 igc_get_phy_id(struct igc_hw *hw)
  134 {
  135         struct igc_phy_info *phy = &hw->phy;
  136         s32 ret_val = IGC_SUCCESS;
  137         u16 phy_id;
  138 
  139         DEBUGFUNC("igc_get_phy_id");
  140 
  141         if (!phy->ops.read_reg)
  142                 return IGC_SUCCESS;
  143 
  144         ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
  145         if (ret_val)
  146                 return ret_val;
  147 
  148         phy->id = (u32)(phy_id << 16);
  149         usec_delay(200);
  150         ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
  151         if (ret_val)
  152                 return ret_val;
  153 
  154         phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
  155         phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
  156 
  157         return IGC_SUCCESS;
  158 }
  159 
  160 /**
  161  *  igc_read_phy_reg_mdic - Read MDI control register
  162  *  @hw: pointer to the HW structure
  163  *  @offset: register offset to be read
  164  *  @data: pointer to the read data
  165  *
  166  *  Reads the MDI control register in the PHY at offset and stores the
  167  *  information read to data.
  168  **/
  169 s32 igc_read_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 *data)
  170 {
  171         struct igc_phy_info *phy = &hw->phy;
  172         u32 i, mdic = 0;
  173 
  174         DEBUGFUNC("igc_read_phy_reg_mdic");
  175 
  176         if (offset > MAX_PHY_REG_ADDRESS) {
  177                 DEBUGOUT1("PHY Address %d is out of range\n", offset);
  178                 return -IGC_ERR_PARAM;
  179         }
  180 
  181         /* Set up Op-code, Phy Address, and register offset in the MDI
  182          * Control register.  The MAC will take care of interfacing with the
  183          * PHY to retrieve the desired data.
  184          */
  185         mdic = ((offset << IGC_MDIC_REG_SHIFT) |
  186                 (phy->addr << IGC_MDIC_PHY_SHIFT) |
  187                 (IGC_MDIC_OP_READ));
  188 
  189         IGC_WRITE_REG(hw, IGC_MDIC, mdic);
  190 
  191         /* Poll the ready bit to see if the MDI read completed
  192          * Increasing the time out as testing showed failures with
  193          * the lower time out
  194          */
  195         for (i = 0; i < (IGC_GEN_POLL_TIMEOUT * 3); i++) {
  196                 usec_delay_irq(50);
  197                 mdic = IGC_READ_REG(hw, IGC_MDIC);
  198                 if (mdic & IGC_MDIC_READY)
  199                         break;
  200         }
  201         if (!(mdic & IGC_MDIC_READY)) {
  202                 DEBUGOUT("MDI Read did not complete\n");
  203                 return -IGC_ERR_PHY;
  204         }
  205         if (mdic & IGC_MDIC_ERROR) {
  206                 DEBUGOUT("MDI Error\n");
  207                 return -IGC_ERR_PHY;
  208         }
  209         if (((mdic & IGC_MDIC_REG_MASK) >> IGC_MDIC_REG_SHIFT) != offset) {
  210                 DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n",
  211                           offset,
  212                           (mdic & IGC_MDIC_REG_MASK) >> IGC_MDIC_REG_SHIFT);
  213                 return -IGC_ERR_PHY;
  214         }
  215         *data = (u16) mdic;
  216 
  217         return IGC_SUCCESS;
  218 }
  219 
  220 /**
  221  *  igc_write_phy_reg_mdic - Write MDI control register
  222  *  @hw: pointer to the HW structure
  223  *  @offset: register offset to write to
  224  *  @data: data to write to register at offset
  225  *
  226  *  Writes data to MDI control register in the PHY at offset.
  227  **/
  228 s32 igc_write_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 data)
  229 {
  230         struct igc_phy_info *phy = &hw->phy;
  231         u32 i, mdic = 0;
  232 
  233         DEBUGFUNC("igc_write_phy_reg_mdic");
  234 
  235         if (offset > MAX_PHY_REG_ADDRESS) {
  236                 DEBUGOUT1("PHY Address %d is out of range\n", offset);
  237                 return -IGC_ERR_PARAM;
  238         }
  239 
  240         /* Set up Op-code, Phy Address, and register offset in the MDI
  241          * Control register.  The MAC will take care of interfacing with the
  242          * PHY to retrieve the desired data.
  243          */
  244         mdic = (((u32)data) |
  245                 (offset << IGC_MDIC_REG_SHIFT) |
  246                 (phy->addr << IGC_MDIC_PHY_SHIFT) |
  247                 (IGC_MDIC_OP_WRITE));
  248 
  249         IGC_WRITE_REG(hw, IGC_MDIC, mdic);
  250 
  251         /* Poll the ready bit to see if the MDI read completed
  252          * Increasing the time out as testing showed failures with
  253          * the lower time out
  254          */
  255         for (i = 0; i < (IGC_GEN_POLL_TIMEOUT * 3); i++) {
  256                 usec_delay_irq(50);
  257                 mdic = IGC_READ_REG(hw, IGC_MDIC);
  258                 if (mdic & IGC_MDIC_READY)
  259                         break;
  260         }
  261         if (!(mdic & IGC_MDIC_READY)) {
  262                 DEBUGOUT("MDI Write did not complete\n");
  263                 return -IGC_ERR_PHY;
  264         }
  265         if (mdic & IGC_MDIC_ERROR) {
  266                 DEBUGOUT("MDI Error\n");
  267                 return -IGC_ERR_PHY;
  268         }
  269         if (((mdic & IGC_MDIC_REG_MASK) >> IGC_MDIC_REG_SHIFT) != offset) {
  270                 DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n",
  271                           offset,
  272                           (mdic & IGC_MDIC_REG_MASK) >> IGC_MDIC_REG_SHIFT);
  273                 return -IGC_ERR_PHY;
  274         }
  275 
  276         return IGC_SUCCESS;
  277 }
  278 
  279 /**
  280  *  igc_phy_setup_autoneg - Configure PHY for auto-negotiation
  281  *  @hw: pointer to the HW structure
  282  *
  283  *  Reads the MII auto-neg advertisement register and/or the 1000T control
  284  *  register and if the PHY is already setup for auto-negotiation, then
  285  *  return successful.  Otherwise, setup advertisement and flow control to
  286  *  the appropriate values for the wanted auto-negotiation.
  287  **/
  288 static s32 igc_phy_setup_autoneg(struct igc_hw *hw)
  289 {
  290         struct igc_phy_info *phy = &hw->phy;
  291         s32 ret_val;
  292         u16 mii_autoneg_adv_reg;
  293         u16 mii_1000t_ctrl_reg = 0;
  294         u16 aneg_multigbt_an_ctrl = 0;
  295 
  296         DEBUGFUNC("igc_phy_setup_autoneg");
  297 
  298         phy->autoneg_advertised &= phy->autoneg_mask;
  299 
  300         /* Read the MII Auto-Neg Advertisement Register (Address 4). */
  301         ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
  302         if (ret_val)
  303                 return ret_val;
  304 
  305         if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
  306                 /* Read the MII 1000Base-T Control Register (Address 9). */
  307                 ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
  308                                             &mii_1000t_ctrl_reg);
  309                 if (ret_val)
  310                         return ret_val;
  311         }
  312 
  313         if (phy->autoneg_mask & ADVERTISE_2500_FULL) {
  314                 /* Read the MULTI GBT AN Control Register - reg 7.32 */
  315                 ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
  316                                             MMD_DEVADDR_SHIFT) |
  317                                             ANEG_MULTIGBT_AN_CTRL,
  318                                             &aneg_multigbt_an_ctrl);
  319 
  320                 if (ret_val)
  321                         return ret_val;
  322         }
  323 
  324         /* Need to parse both autoneg_advertised and fc and set up
  325          * the appropriate PHY registers.  First we will parse for
  326          * autoneg_advertised software override.  Since we can advertise
  327          * a plethora of combinations, we need to check each bit
  328          * individually.
  329          */
  330 
  331         /* First we clear all the 10/100 mb speed bits in the Auto-Neg
  332          * Advertisement Register (Address 4) and the 1000 mb speed bits in
  333          * the  1000Base-T Control Register (Address 9).
  334          */
  335         mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
  336                                  NWAY_AR_100TX_HD_CAPS |
  337                                  NWAY_AR_10T_FD_CAPS   |
  338                                  NWAY_AR_10T_HD_CAPS);
  339         mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
  340 
  341         DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised);
  342 
  343         /* Do we want to advertise 10 Mb Half Duplex? */
  344         if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
  345                 DEBUGOUT("Advertise 10mb Half duplex\n");
  346                 mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
  347         }
  348 
  349         /* Do we want to advertise 10 Mb Full Duplex? */
  350         if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
  351                 DEBUGOUT("Advertise 10mb Full duplex\n");
  352                 mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
  353         }
  354 
  355         /* Do we want to advertise 100 Mb Half Duplex? */
  356         if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
  357                 DEBUGOUT("Advertise 100mb Half duplex\n");
  358                 mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
  359         }
  360 
  361         /* Do we want to advertise 100 Mb Full Duplex? */
  362         if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
  363                 DEBUGOUT("Advertise 100mb Full duplex\n");
  364                 mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
  365         }
  366 
  367         /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
  368         if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
  369                 DEBUGOUT("Advertise 1000mb Half duplex request denied!\n");
  370 
  371         /* Do we want to advertise 1000 Mb Full Duplex? */
  372         if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
  373                 DEBUGOUT("Advertise 1000mb Full duplex\n");
  374                 mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
  375         }
  376 
  377         /* We do not allow the Phy to advertise 2500 Mb Half Duplex */
  378         if (phy->autoneg_advertised & ADVERTISE_2500_HALF)
  379                 DEBUGOUT("Advertise 2500mb Half duplex request denied!\n");
  380 
  381         /* Do we want to advertise 2500 Mb Full Duplex? */
  382         if (phy->autoneg_advertised & ADVERTISE_2500_FULL) {
  383                 DEBUGOUT("Advertise 2500mb Full duplex\n");
  384                 aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;
  385         } else {
  386                 aneg_multigbt_an_ctrl &= ~CR_2500T_FD_CAPS;
  387         }
  388 
  389         /* Check for a software override of the flow control settings, and
  390          * setup the PHY advertisement registers accordingly.  If
  391          * auto-negotiation is enabled, then software will have to set the
  392          * "PAUSE" bits to the correct value in the Auto-Negotiation
  393          * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
  394          * negotiation.
  395          *
  396          * The possible values of the "fc" parameter are:
  397          *      0:  Flow control is completely disabled
  398          *      1:  Rx flow control is enabled (we can receive pause frames
  399          *          but not send pause frames).
  400          *      2:  Tx flow control is enabled (we can send pause frames
  401          *          but we do not support receiving pause frames).
  402          *      3:  Both Rx and Tx flow control (symmetric) are enabled.
  403          *  other:  No software override.  The flow control configuration
  404          *          in the EEPROM is used.
  405          */
  406         switch (hw->fc.current_mode) {
  407         case igc_fc_none:
  408                 /* Flow control (Rx & Tx) is completely disabled by a
  409                  * software over-ride.
  410                  */
  411                 mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
  412                 break;
  413         case igc_fc_rx_pause:
  414                 /* Rx Flow control is enabled, and Tx Flow control is
  415                  * disabled, by a software over-ride.
  416                  *
  417                  * Since there really isn't a way to advertise that we are
  418                  * capable of Rx Pause ONLY, we will advertise that we
  419                  * support both symmetric and asymmetric Rx PAUSE.  Later
  420                  * (in igc_config_fc_after_link_up) we will disable the
  421                  * hw's ability to send PAUSE frames.
  422                  */
  423                 mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
  424                 break;
  425         case igc_fc_tx_pause:
  426                 /* Tx Flow control is enabled, and Rx Flow control is
  427                  * disabled, by a software over-ride.
  428                  */
  429                 mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
  430                 mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
  431                 break;
  432         case igc_fc_full:
  433                 /* Flow control (both Rx and Tx) is enabled by a software
  434                  * over-ride.
  435                  */
  436                 mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
  437                 break;
  438         default:
  439                 DEBUGOUT("Flow control param set incorrectly\n");
  440                 return -IGC_ERR_CONFIG;
  441         }
  442 
  443         ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
  444         if (ret_val)
  445                 return ret_val;
  446 
  447         DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
  448 
  449         if (phy->autoneg_mask & ADVERTISE_1000_FULL)
  450                 ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
  451                                              mii_1000t_ctrl_reg);
  452 
  453         if (phy->autoneg_mask & ADVERTISE_2500_FULL)
  454                 ret_val = phy->ops.write_reg(hw,
  455                                              (STANDARD_AN_REG_MASK <<
  456                                              MMD_DEVADDR_SHIFT) |
  457                                              ANEG_MULTIGBT_AN_CTRL,
  458                                              aneg_multigbt_an_ctrl);
  459 
  460         return ret_val;
  461 }
  462 
  463 /**
  464  *  igc_copper_link_autoneg - Setup/Enable autoneg for copper link
  465  *  @hw: pointer to the HW structure
  466  *
  467  *  Performs initial bounds checking on autoneg advertisement parameter, then
  468  *  configure to advertise the full capability.  Setup the PHY to autoneg
  469  *  and restart the negotiation process between the link partner.  If
  470  *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
  471  **/
  472 static s32 igc_copper_link_autoneg(struct igc_hw *hw)
  473 {
  474         struct igc_phy_info *phy = &hw->phy;
  475         s32 ret_val;
  476         u16 phy_ctrl;
  477 
  478         DEBUGFUNC("igc_copper_link_autoneg");
  479 
  480         /* Perform some bounds checking on the autoneg advertisement
  481          * parameter.
  482          */
  483         phy->autoneg_advertised &= phy->autoneg_mask;
  484 
  485         /* If autoneg_advertised is zero, we assume it was not defaulted
  486          * by the calling code so we set to advertise full capability.
  487          */
  488         if (!phy->autoneg_advertised)
  489                 phy->autoneg_advertised = phy->autoneg_mask;
  490 
  491         DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
  492         ret_val = igc_phy_setup_autoneg(hw);
  493         if (ret_val) {
  494                 DEBUGOUT("Error Setting up Auto-Negotiation\n");
  495                 return ret_val;
  496         }
  497         DEBUGOUT("Restarting Auto-Neg\n");
  498 
  499         /* Restart auto-negotiation by setting the Auto Neg Enable bit and
  500          * the Auto Neg Restart bit in the PHY control register.
  501          */
  502         ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
  503         if (ret_val)
  504                 return ret_val;
  505 
  506         phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
  507         ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
  508         if (ret_val)
  509                 return ret_val;
  510 
  511         /* Does the user want to wait for Auto-Neg to complete here, or
  512          * check at a later time (for example, callback routine).
  513          */
  514         if (phy->autoneg_wait_to_complete) {
  515                 ret_val = igc_wait_autoneg(hw);
  516                 if (ret_val) {
  517                         DEBUGOUT("Error while waiting for autoneg to complete\n");
  518                         return ret_val;
  519                 }
  520         }
  521 
  522         hw->mac.get_link_status = true;
  523 
  524         return ret_val;
  525 }
  526 
  527 /**
  528  *  igc_setup_copper_link_generic - Configure copper link settings
  529  *  @hw: pointer to the HW structure
  530  *
  531  *  Calls the appropriate function to configure the link for auto-neg or forced
  532  *  speed and duplex.  Then we check for link, once link is established calls
  533  *  to configure collision distance and flow control are called.  If link is
  534  *  not established, we return -IGC_ERR_PHY (-2).
  535  **/
  536 s32 igc_setup_copper_link_generic(struct igc_hw *hw)
  537 {
  538         s32 ret_val;
  539         bool link;
  540 
  541         DEBUGFUNC("igc_setup_copper_link_generic");
  542 
  543         if (hw->mac.autoneg) {
  544                 /* Setup autoneg and flow control advertisement and perform
  545                  * autonegotiation.
  546                  */
  547                 ret_val = igc_copper_link_autoneg(hw);
  548                 if (ret_val)
  549                         return ret_val;
  550         } else {
  551                 /* PHY will be set to 10H, 10F, 100H or 100F
  552                  * depending on user settings.
  553                  */
  554                 DEBUGOUT("Forcing Speed and Duplex\n");
  555                 ret_val = hw->phy.ops.force_speed_duplex(hw);
  556                 if (ret_val) {
  557                         DEBUGOUT("Error Forcing Speed and Duplex\n");
  558                         return ret_val;
  559                 }
  560         }
  561 
  562         /* Check link status. Wait up to 100 microseconds for link to become
  563          * valid.
  564          */
  565         ret_val = igc_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
  566                                              &link);
  567         if (ret_val)
  568                 return ret_val;
  569 
  570         if (link) {
  571                 DEBUGOUT("Valid link established!!!\n");
  572                 hw->mac.ops.config_collision_dist(hw);
  573                 ret_val = igc_config_fc_after_link_up_generic(hw);
  574         } else {
  575                 DEBUGOUT("Unable to establish link!!!\n");
  576         }
  577 
  578         return ret_val;
  579 }
  580 
  581 /**
  582  *  igc_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex
  583  *  @hw: pointer to the HW structure
  584  *  @phy_ctrl: pointer to current value of PHY_CONTROL
  585  *
  586  *  Forces speed and duplex on the PHY by doing the following: disable flow
  587  *  control, force speed/duplex on the MAC, disable auto speed detection,
  588  *  disable auto-negotiation, configure duplex, configure speed, configure
  589  *  the collision distance, write configuration to CTRL register.  The
  590  *  caller must write to the PHY_CONTROL register for these settings to
  591  *  take effect.
  592  **/
  593 void igc_phy_force_speed_duplex_setup(struct igc_hw *hw, u16 *phy_ctrl)
  594 {
  595         struct igc_mac_info *mac = &hw->mac;
  596         u32 ctrl;
  597 
  598         DEBUGFUNC("igc_phy_force_speed_duplex_setup");
  599 
  600         /* Turn off flow control when forcing speed/duplex */
  601         hw->fc.current_mode = igc_fc_none;
  602 
  603         /* Force speed/duplex on the mac */
  604         ctrl = IGC_READ_REG(hw, IGC_CTRL);
  605         ctrl |= (IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
  606         ctrl &= ~IGC_CTRL_SPD_SEL;
  607 
  608         /* Disable Auto Speed Detection */
  609         ctrl &= ~IGC_CTRL_ASDE;
  610 
  611         /* Disable autoneg on the phy */
  612         *phy_ctrl &= ~MII_CR_AUTO_NEG_EN;
  613 
  614         /* Forcing Full or Half Duplex? */
  615         if (mac->forced_speed_duplex & IGC_ALL_HALF_DUPLEX) {
  616                 ctrl &= ~IGC_CTRL_FD;
  617                 *phy_ctrl &= ~MII_CR_FULL_DUPLEX;
  618                 DEBUGOUT("Half Duplex\n");
  619         } else {
  620                 ctrl |= IGC_CTRL_FD;
  621                 *phy_ctrl |= MII_CR_FULL_DUPLEX;
  622                 DEBUGOUT("Full Duplex\n");
  623         }
  624 
  625         /* Forcing 10mb or 100mb? */
  626         if (mac->forced_speed_duplex & IGC_ALL_100_SPEED) {
  627                 ctrl |= IGC_CTRL_SPD_100;
  628                 *phy_ctrl |= MII_CR_SPEED_100;
  629                 *phy_ctrl &= ~MII_CR_SPEED_1000;
  630                 DEBUGOUT("Forcing 100mb\n");
  631         } else {
  632                 ctrl &= ~(IGC_CTRL_SPD_1000 | IGC_CTRL_SPD_100);
  633                 *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
  634                 DEBUGOUT("Forcing 10mb\n");
  635         }
  636 
  637         hw->mac.ops.config_collision_dist(hw);
  638 
  639         IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
  640 }
  641 
  642 /**
  643  *  igc_set_d3_lplu_state_generic - Sets low power link up state for D3
  644  *  @hw: pointer to the HW structure
  645  *  @active: boolean used to enable/disable lplu
  646  *
  647  *  Success returns 0, Failure returns 1
  648  *
  649  *  The low power link up (lplu) state is set to the power management level D3
  650  *  and SmartSpeed is disabled when active is true, else clear lplu for D3
  651  *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
  652  *  is used during Dx states where the power conservation is most important.
  653  *  During driver activity, SmartSpeed should be enabled so performance is
  654  *  maintained.
  655  **/
  656 s32 igc_set_d3_lplu_state_generic(struct igc_hw *hw, bool active)
  657 {
  658         struct igc_phy_info *phy = &hw->phy;
  659         s32 ret_val;
  660         u16 data;
  661 
  662         DEBUGFUNC("igc_set_d3_lplu_state_generic");
  663 
  664         if (!hw->phy.ops.read_reg)
  665                 return IGC_SUCCESS;
  666 
  667         ret_val = phy->ops.read_reg(hw, IGP02IGC_PHY_POWER_MGMT, &data);
  668         if (ret_val)
  669                 return ret_val;
  670 
  671         if (!active) {
  672                 data &= ~IGP02IGC_PM_D3_LPLU;
  673                 ret_val = phy->ops.write_reg(hw, IGP02IGC_PHY_POWER_MGMT,
  674                                              data);
  675                 if (ret_val)
  676                         return ret_val;
  677                 /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
  678                  * during Dx states where the power conservation is most
  679                  * important.  During driver activity we should enable
  680                  * SmartSpeed, so performance is maintained.
  681                  */
  682                 if (phy->smart_speed == igc_smart_speed_on) {
  683                         ret_val = phy->ops.read_reg(hw,
  684                                                     IGP01IGC_PHY_PORT_CONFIG,
  685                                                     &data);
  686                         if (ret_val)
  687                                 return ret_val;
  688 
  689                         data |= IGP01IGC_PSCFR_SMART_SPEED;
  690                         ret_val = phy->ops.write_reg(hw,
  691                                                      IGP01IGC_PHY_PORT_CONFIG,
  692                                                      data);
  693                         if (ret_val)
  694                                 return ret_val;
  695                 } else if (phy->smart_speed == igc_smart_speed_off) {
  696                         ret_val = phy->ops.read_reg(hw,
  697                                                     IGP01IGC_PHY_PORT_CONFIG,
  698                                                     &data);
  699                         if (ret_val)
  700                                 return ret_val;
  701 
  702                         data &= ~IGP01IGC_PSCFR_SMART_SPEED;
  703                         ret_val = phy->ops.write_reg(hw,
  704                                                      IGP01IGC_PHY_PORT_CONFIG,
  705                                                      data);
  706                         if (ret_val)
  707                                 return ret_val;
  708                 }
  709         } else if ((phy->autoneg_advertised == IGC_ALL_SPEED_DUPLEX) ||
  710                    (phy->autoneg_advertised == IGC_ALL_NOT_GIG) ||
  711                    (phy->autoneg_advertised == IGC_ALL_10_SPEED)) {
  712                 data |= IGP02IGC_PM_D3_LPLU;
  713                 ret_val = phy->ops.write_reg(hw, IGP02IGC_PHY_POWER_MGMT,
  714                                              data);
  715                 if (ret_val)
  716                         return ret_val;
  717 
  718                 /* When LPLU is enabled, we should disable SmartSpeed */
  719                 ret_val = phy->ops.read_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
  720                                             &data);
  721                 if (ret_val)
  722                         return ret_val;
  723 
  724                 data &= ~IGP01IGC_PSCFR_SMART_SPEED;
  725                 ret_val = phy->ops.write_reg(hw, IGP01IGC_PHY_PORT_CONFIG,
  726                                              data);
  727         }
  728 
  729         return ret_val;
  730 }
  731 
  732 /**
  733  *  igc_check_downshift_generic - Checks whether a downshift in speed occurred
  734  *  @hw: pointer to the HW structure
  735  *
  736  *  Success returns 0, Failure returns 1
  737  *
  738  *  A downshift is detected by querying the PHY link health.
  739  **/
  740 s32 igc_check_downshift_generic(struct igc_hw *hw)
  741 {
  742         struct igc_phy_info *phy = &hw->phy;
  743         s32 ret_val;
  744 
  745         DEBUGFUNC("igc_check_downshift_generic");
  746 
  747         switch (phy->type) {
  748         case igc_phy_i225:
  749         default:
  750                 /* speed downshift not supported */
  751                 phy->speed_downgraded = false;
  752                 return IGC_SUCCESS;
  753         }
  754 
  755         return ret_val;
  756 }
  757 
  758 /**
  759  *  igc_wait_autoneg - Wait for auto-neg completion
  760  *  @hw: pointer to the HW structure
  761  *
  762  *  Waits for auto-negotiation to complete or for the auto-negotiation time
  763  *  limit to expire, which ever happens first.
  764  **/
  765 static s32 igc_wait_autoneg(struct igc_hw *hw)
  766 {
  767         s32 ret_val = IGC_SUCCESS;
  768         u16 i, phy_status;
  769 
  770         DEBUGFUNC("igc_wait_autoneg");
  771 
  772         if (!hw->phy.ops.read_reg)
  773                 return IGC_SUCCESS;
  774 
  775         /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
  776         for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
  777                 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
  778                 if (ret_val)
  779                         break;
  780                 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
  781                 if (ret_val)
  782                         break;
  783                 if (phy_status & MII_SR_AUTONEG_COMPLETE)
  784                         break;
  785                 msec_delay(100);
  786         }
  787 
  788         /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
  789          * has completed.
  790          */
  791         return ret_val;
  792 }
  793 
  794 /**
  795  *  igc_phy_has_link_generic - Polls PHY for link
  796  *  @hw: pointer to the HW structure
  797  *  @iterations: number of times to poll for link
  798  *  @usec_interval: delay between polling attempts
  799  *  @success: pointer to whether polling was successful or not
  800  *
  801  *  Polls the PHY status register for link, 'iterations' number of times.
  802  **/
  803 s32 igc_phy_has_link_generic(struct igc_hw *hw, u32 iterations,
  804                                u32 usec_interval, bool *success)
  805 {
  806         s32 ret_val = IGC_SUCCESS;
  807         u16 i, phy_status;
  808 
  809         DEBUGFUNC("igc_phy_has_link_generic");
  810 
  811         if (!hw->phy.ops.read_reg)
  812                 return IGC_SUCCESS;
  813 
  814         for (i = 0; i < iterations; i++) {
  815                 /* Some PHYs require the PHY_STATUS register to be read
  816                  * twice due to the link bit being sticky.  No harm doing
  817                  * it across the board.
  818                  */
  819                 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
  820                 if (ret_val) {
  821                         /* If the first read fails, another entity may have
  822                          * ownership of the resources, wait and try again to
  823                          * see if they have relinquished the resources yet.
  824                          */
  825                         if (usec_interval >= 1000)
  826                                 msec_delay(usec_interval/1000);
  827                         else
  828                                 usec_delay(usec_interval);
  829                 }
  830                 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
  831                 if (ret_val)
  832                         break;
  833                 if (phy_status & MII_SR_LINK_STATUS)
  834                         break;
  835                 if (usec_interval >= 1000)
  836                         msec_delay(usec_interval/1000);
  837                 else
  838                         usec_delay(usec_interval);
  839         }
  840 
  841         *success = (i < iterations);
  842 
  843         return ret_val;
  844 }
  845 
  846 /**
  847  *  igc_phy_hw_reset_generic - PHY hardware reset
  848  *  @hw: pointer to the HW structure
  849  *
  850  *  Verify the reset block is not blocking us from resetting.  Acquire
  851  *  semaphore (if necessary) and read/set/write the device control reset
  852  *  bit in the PHY.  Wait the appropriate delay time for the device to
  853  *  reset and release the semaphore (if necessary).
  854  **/
  855 s32 igc_phy_hw_reset_generic(struct igc_hw *hw)
  856 {
  857         struct igc_phy_info *phy = &hw->phy;
  858         s32 ret_val;
  859         u32 ctrl, timeout = 10000, phpm = 0;
  860 
  861         DEBUGFUNC("igc_phy_hw_reset_generic");
  862 
  863         if (phy->ops.check_reset_block) {
  864                 ret_val = phy->ops.check_reset_block(hw);
  865                 if (ret_val)
  866                         return IGC_SUCCESS;
  867         }
  868 
  869         ret_val = phy->ops.acquire(hw);
  870         if (ret_val)
  871                 return ret_val;
  872 
  873         phpm = IGC_READ_REG(hw, IGC_I225_PHPM);
  874 
  875         ctrl = IGC_READ_REG(hw, IGC_CTRL);
  876         IGC_WRITE_REG(hw, IGC_CTRL, ctrl | IGC_CTRL_PHY_RST);
  877         IGC_WRITE_FLUSH(hw);
  878 
  879         usec_delay(phy->reset_delay_us);
  880 
  881         IGC_WRITE_REG(hw, IGC_CTRL, ctrl);
  882         IGC_WRITE_FLUSH(hw);
  883 
  884         usec_delay(150);
  885 
  886         do {
  887                 phpm = IGC_READ_REG(hw, IGC_I225_PHPM);
  888                 timeout--;
  889                 usec_delay(1);
  890         } while (!(phpm & IGC_I225_PHPM_RST_COMPL) && timeout);
  891 
  892         if (!timeout)
  893                 DEBUGOUT("Timeout expired after a phy reset\n");
  894 
  895         phy->ops.release(hw);
  896 
  897         return ret_val;
  898 }
  899 
  900 /**
  901  * igc_power_up_phy_copper - Restore copper link in case of PHY power down
  902  * @hw: pointer to the HW structure
  903  *
  904  * In the case of a PHY power down to save power, or to turn off link during a
  905  * driver unload, or wake on lan is not enabled, restore the link to previous
  906  * settings.
  907  **/
  908 void igc_power_up_phy_copper(struct igc_hw *hw)
  909 {
  910         u16 mii_reg = 0;
  911 
  912         /* The PHY will retain its settings across a power down/up cycle */
  913         hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
  914         mii_reg &= ~MII_CR_POWER_DOWN;
  915         hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
  916         usec_delay(300);
  917 }
  918 
  919 /**
  920  * igc_power_down_phy_copper - Restore copper link in case of PHY power down
  921  * @hw: pointer to the HW structure
  922  *
  923  * In the case of a PHY power down to save power, or to turn off link during a
  924  * driver unload, or wake on lan is not enabled, restore the link to previous
  925  * settings.
  926  **/
  927 void igc_power_down_phy_copper(struct igc_hw *hw)
  928 {
  929         u16 mii_reg = 0;
  930 
  931         /* The PHY will retain its settings across a power down/up cycle */
  932         hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
  933         mii_reg |= MII_CR_POWER_DOWN;
  934         hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
  935         msec_delay(1);
  936 }
  937 /**
  938  *  igc_write_phy_reg_gpy - Write GPY PHY register
  939  *  @hw: pointer to the HW structure
  940  *  @offset: register offset to write to
  941  *  @data: data to write at register offset
  942  *
  943  *  Acquires semaphore, if necessary, then writes the data to PHY register
  944  *  at the offset.  Release any acquired semaphores before exiting.
  945  **/
  946 s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data)
  947 {
  948         s32 ret_val;
  949         u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT;
  950 
  951         DEBUGFUNC("igc_write_phy_reg_gpy");
  952 
  953         offset = offset & GPY_REG_MASK;
  954 
  955         if (!dev_addr) {
  956                 ret_val = hw->phy.ops.acquire(hw);
  957                 if (ret_val)
  958                         return ret_val;
  959                 ret_val = igc_write_phy_reg_mdic(hw, offset, data);
  960                 if (ret_val)
  961                         return ret_val;
  962                 hw->phy.ops.release(hw);
  963         } else {
  964                 ret_val = igc_write_xmdio_reg(hw, (u16)offset, dev_addr,
  965                                                 data);
  966         }
  967         return ret_val;
  968 }
  969 
  970 /**
  971  *  igc_read_phy_reg_gpy - Read GPY PHY register
  972  *  @hw: pointer to the HW structure
  973  *  @offset: lower half is register offset to read to
  974  *     upper half is MMD to use.
  975  *  @data: data to read at register offset
  976  *
  977  *  Acquires semaphore, if necessary, then reads the data in the PHY register
  978  *  at the offset.  Release any acquired semaphores before exiting.
  979  **/
  980 s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data)
  981 {
  982         s32 ret_val;
  983         u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT;
  984 
  985         DEBUGFUNC("igc_read_phy_reg_gpy");
  986 
  987         offset = offset & GPY_REG_MASK;
  988 
  989         if (!dev_addr) {
  990                 ret_val = hw->phy.ops.acquire(hw);
  991                 if (ret_val)
  992                         return ret_val;
  993                 ret_val = igc_read_phy_reg_mdic(hw, offset, data);
  994                 if (ret_val)
  995                         return ret_val;
  996                 hw->phy.ops.release(hw);
  997         } else {
  998                 ret_val = igc_read_xmdio_reg(hw, (u16)offset, dev_addr,
  999                                                data);
 1000         }
 1001         return ret_val;
 1002 }
 1003 
 1004 
 1005 /**
 1006  *  __igc_access_xmdio_reg - Read/write XMDIO register
 1007  *  @hw: pointer to the HW structure
 1008  *  @address: XMDIO address to program
 1009  *  @dev_addr: device address to program
 1010  *  @data: pointer to value to read/write from/to the XMDIO address
 1011  *  @read: boolean flag to indicate read or write
 1012  **/
 1013 static s32 __igc_access_xmdio_reg(struct igc_hw *hw, u16 address,
 1014                                     u8 dev_addr, u16 *data, bool read)
 1015 {
 1016         s32 ret_val;
 1017 
 1018         DEBUGFUNC("__igc_access_xmdio_reg");
 1019 
 1020         ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, dev_addr);
 1021         if (ret_val)
 1022                 return ret_val;
 1023 
 1024         ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, address);
 1025         if (ret_val)
 1026                 return ret_val;
 1027 
 1028         ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, IGC_MMDAC_FUNC_DATA |
 1029                                         dev_addr);
 1030         if (ret_val)
 1031                 return ret_val;
 1032 
 1033         if (read)
 1034                 ret_val = hw->phy.ops.read_reg(hw, IGC_MMDAAD, data);
 1035         else
 1036                 ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, *data);
 1037         if (ret_val)
 1038                 return ret_val;
 1039 
 1040         /* Recalibrate the device back to 0 */
 1041         ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, 0);
 1042         if (ret_val)
 1043                 return ret_val;
 1044 
 1045         return ret_val;
 1046 }
 1047 
 1048 /**
 1049  *  igc_read_xmdio_reg - Read XMDIO register
 1050  *  @hw: pointer to the HW structure
 1051  *  @addr: XMDIO address to program
 1052  *  @dev_addr: device address to program
 1053  *  @data: value to be read from the EMI address
 1054  **/
 1055 s32 igc_read_xmdio_reg(struct igc_hw *hw, u16 addr, u8 dev_addr, u16 *data)
 1056 {
 1057         DEBUGFUNC("igc_read_xmdio_reg");
 1058 
 1059         return __igc_access_xmdio_reg(hw, addr, dev_addr, data, true);
 1060 }
 1061 
 1062 /**
 1063  *  igc_write_xmdio_reg - Write XMDIO register
 1064  *  @hw: pointer to the HW structure
 1065  *  @addr: XMDIO address to program
 1066  *  @dev_addr: device address to program
 1067  *  @data: value to be written to the XMDIO address
 1068  **/
 1069 s32 igc_write_xmdio_reg(struct igc_hw *hw, u16 addr, u8 dev_addr, u16 data)
 1070 {
 1071         DEBUGFUNC("igc_write_xmdio_reg");
 1072 
 1073         return __igc_access_xmdio_reg(hw, addr, dev_addr, &data, false);
 1074 }

Cache object: cd711e9e0809dcf78a99b3a9b4bacaf2


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