Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (c)  2018 Intel Corporation */
0003 
0004 #include "igc_phy.h"
0005 
0006 /**
0007  * igc_check_reset_block - Check if PHY reset is blocked
0008  * @hw: pointer to the HW structure
0009  *
0010  * Read the PHY management control register and check whether a PHY reset
0011  * is blocked.  If a reset is not blocked return 0, otherwise
0012  * return IGC_ERR_BLK_PHY_RESET (12).
0013  */
0014 s32 igc_check_reset_block(struct igc_hw *hw)
0015 {
0016     u32 manc;
0017 
0018     manc = rd32(IGC_MANC);
0019 
0020     return (manc & IGC_MANC_BLK_PHY_RST_ON_IDE) ?
0021         IGC_ERR_BLK_PHY_RESET : 0;
0022 }
0023 
0024 /**
0025  * igc_get_phy_id - Retrieve the PHY ID and revision
0026  * @hw: pointer to the HW structure
0027  *
0028  * Reads the PHY registers and stores the PHY ID and possibly the PHY
0029  * revision in the hardware structure.
0030  */
0031 s32 igc_get_phy_id(struct igc_hw *hw)
0032 {
0033     struct igc_phy_info *phy = &hw->phy;
0034     s32 ret_val = 0;
0035     u16 phy_id;
0036 
0037     ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
0038     if (ret_val)
0039         goto out;
0040 
0041     phy->id = (u32)(phy_id << 16);
0042     usleep_range(200, 500);
0043     ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
0044     if (ret_val)
0045         goto out;
0046 
0047     phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
0048     phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
0049 
0050 out:
0051     return ret_val;
0052 }
0053 
0054 /**
0055  * igc_phy_has_link - Polls PHY for link
0056  * @hw: pointer to the HW structure
0057  * @iterations: number of times to poll for link
0058  * @usec_interval: delay between polling attempts
0059  * @success: pointer to whether polling was successful or not
0060  *
0061  * Polls the PHY status register for link, 'iterations' number of times.
0062  */
0063 s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations,
0064              u32 usec_interval, bool *success)
0065 {
0066     u16 i, phy_status;
0067     s32 ret_val = 0;
0068 
0069     for (i = 0; i < iterations; i++) {
0070         /* Some PHYs require the PHY_STATUS register to be read
0071          * twice due to the link bit being sticky.  No harm doing
0072          * it across the board.
0073          */
0074         ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
0075         if (ret_val && usec_interval > 0) {
0076             /* If the first read fails, another entity may have
0077              * ownership of the resources, wait and try again to
0078              * see if they have relinquished the resources yet.
0079              */
0080             if (usec_interval >= 1000)
0081                 mdelay(usec_interval / 1000);
0082             else
0083                 udelay(usec_interval);
0084         }
0085         ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
0086         if (ret_val)
0087             break;
0088         if (phy_status & MII_SR_LINK_STATUS)
0089             break;
0090         if (usec_interval >= 1000)
0091             mdelay(usec_interval / 1000);
0092         else
0093             udelay(usec_interval);
0094     }
0095 
0096     *success = (i < iterations) ? true : false;
0097 
0098     return ret_val;
0099 }
0100 
0101 /**
0102  * igc_power_up_phy_copper - Restore copper link in case of PHY power down
0103  * @hw: pointer to the HW structure
0104  *
0105  * In the case of a PHY power down to save power, or to turn off link during a
0106  * driver unload, restore the link to previous settings.
0107  */
0108 void igc_power_up_phy_copper(struct igc_hw *hw)
0109 {
0110     u16 mii_reg = 0;
0111 
0112     /* The PHY will retain its settings across a power down/up cycle */
0113     hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
0114     mii_reg &= ~MII_CR_POWER_DOWN;
0115     hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
0116 }
0117 
0118 /**
0119  * igc_power_down_phy_copper - Power down copper PHY
0120  * @hw: pointer to the HW structure
0121  *
0122  * Power down PHY to save power when interface is down and wake on lan
0123  * is not enabled.
0124  */
0125 void igc_power_down_phy_copper(struct igc_hw *hw)
0126 {
0127     u16 mii_reg = 0;
0128 
0129     /* The PHY will retain its settings across a power down/up cycle */
0130     hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
0131     mii_reg |= MII_CR_POWER_DOWN;
0132 
0133     /* Temporary workaround - should be removed when PHY will implement
0134      * IEEE registers as properly
0135      */
0136     /* hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);*/
0137     usleep_range(1000, 2000);
0138 }
0139 
0140 /**
0141  * igc_check_downshift - Checks whether a downshift in speed occurred
0142  * @hw: pointer to the HW structure
0143  *
0144  * A downshift is detected by querying the PHY link health.
0145  */
0146 void igc_check_downshift(struct igc_hw *hw)
0147 {
0148     struct igc_phy_info *phy = &hw->phy;
0149 
0150     /* speed downshift not supported */
0151     phy->speed_downgraded = false;
0152 }
0153 
0154 /**
0155  * igc_phy_hw_reset - PHY hardware reset
0156  * @hw: pointer to the HW structure
0157  *
0158  * Verify the reset block is not blocking us from resetting.  Acquire
0159  * semaphore (if necessary) and read/set/write the device control reset
0160  * bit in the PHY.  Wait the appropriate delay time for the device to
0161  * reset and release the semaphore (if necessary).
0162  */
0163 s32 igc_phy_hw_reset(struct igc_hw *hw)
0164 {
0165     struct igc_phy_info *phy = &hw->phy;
0166     u32 phpm = 0, timeout = 10000;
0167     s32  ret_val;
0168     u32 ctrl;
0169 
0170     ret_val = igc_check_reset_block(hw);
0171     if (ret_val) {
0172         ret_val = 0;
0173         goto out;
0174     }
0175 
0176     ret_val = phy->ops.acquire(hw);
0177     if (ret_val)
0178         goto out;
0179 
0180     phpm = rd32(IGC_I225_PHPM);
0181 
0182     ctrl = rd32(IGC_CTRL);
0183     wr32(IGC_CTRL, ctrl | IGC_CTRL_PHY_RST);
0184     wrfl();
0185 
0186     udelay(phy->reset_delay_us);
0187 
0188     wr32(IGC_CTRL, ctrl);
0189     wrfl();
0190 
0191     /* SW should guarantee 100us for the completion of the PHY reset */
0192     usleep_range(100, 150);
0193     do {
0194         phpm = rd32(IGC_I225_PHPM);
0195         timeout--;
0196         udelay(1);
0197     } while (!(phpm & IGC_PHY_RST_COMP) && timeout);
0198 
0199     if (!timeout)
0200         hw_dbg("Timeout is expired after a phy reset\n");
0201 
0202     usleep_range(100, 150);
0203 
0204     phy->ops.release(hw);
0205 
0206 out:
0207     return ret_val;
0208 }
0209 
0210 /**
0211  * igc_phy_setup_autoneg - Configure PHY for auto-negotiation
0212  * @hw: pointer to the HW structure
0213  *
0214  * Reads the MII auto-neg advertisement register and/or the 1000T control
0215  * register and if the PHY is already setup for auto-negotiation, then
0216  * return successful.  Otherwise, setup advertisement and flow control to
0217  * the appropriate values for the wanted auto-negotiation.
0218  */
0219 static s32 igc_phy_setup_autoneg(struct igc_hw *hw)
0220 {
0221     struct igc_phy_info *phy = &hw->phy;
0222     u16 aneg_multigbt_an_ctrl = 0;
0223     u16 mii_1000t_ctrl_reg = 0;
0224     u16 mii_autoneg_adv_reg;
0225     s32 ret_val;
0226 
0227     phy->autoneg_advertised &= phy->autoneg_mask;
0228 
0229     /* Read the MII Auto-Neg Advertisement Register (Address 4). */
0230     ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
0231     if (ret_val)
0232         return ret_val;
0233 
0234     if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
0235         /* Read the MII 1000Base-T Control Register (Address 9). */
0236         ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
0237                         &mii_1000t_ctrl_reg);
0238         if (ret_val)
0239             return ret_val;
0240     }
0241 
0242     if (phy->autoneg_mask & ADVERTISE_2500_FULL) {
0243         /* Read the MULTI GBT AN Control Register - reg 7.32 */
0244         ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
0245                         MMD_DEVADDR_SHIFT) |
0246                         ANEG_MULTIGBT_AN_CTRL,
0247                         &aneg_multigbt_an_ctrl);
0248 
0249         if (ret_val)
0250             return ret_val;
0251     }
0252 
0253     /* Need to parse both autoneg_advertised and fc and set up
0254      * the appropriate PHY registers.  First we will parse for
0255      * autoneg_advertised software override.  Since we can advertise
0256      * a plethora of combinations, we need to check each bit
0257      * individually.
0258      */
0259 
0260     /* First we clear all the 10/100 mb speed bits in the Auto-Neg
0261      * Advertisement Register (Address 4) and the 1000 mb speed bits in
0262      * the  1000Base-T Control Register (Address 9).
0263      */
0264     mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
0265                  NWAY_AR_100TX_HD_CAPS |
0266                  NWAY_AR_10T_FD_CAPS   |
0267                  NWAY_AR_10T_HD_CAPS);
0268     mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
0269 
0270     hw_dbg("autoneg_advertised %x\n", phy->autoneg_advertised);
0271 
0272     /* Do we want to advertise 10 Mb Half Duplex? */
0273     if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
0274         hw_dbg("Advertise 10mb Half duplex\n");
0275         mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
0276     }
0277 
0278     /* Do we want to advertise 10 Mb Full Duplex? */
0279     if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
0280         hw_dbg("Advertise 10mb Full duplex\n");
0281         mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
0282     }
0283 
0284     /* Do we want to advertise 100 Mb Half Duplex? */
0285     if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
0286         hw_dbg("Advertise 100mb Half duplex\n");
0287         mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
0288     }
0289 
0290     /* Do we want to advertise 100 Mb Full Duplex? */
0291     if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
0292         hw_dbg("Advertise 100mb Full duplex\n");
0293         mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
0294     }
0295 
0296     /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
0297     if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
0298         hw_dbg("Advertise 1000mb Half duplex request denied!\n");
0299 
0300     /* Do we want to advertise 1000 Mb Full Duplex? */
0301     if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
0302         hw_dbg("Advertise 1000mb Full duplex\n");
0303         mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
0304     }
0305 
0306     /* We do not allow the Phy to advertise 2500 Mb Half Duplex */
0307     if (phy->autoneg_advertised & ADVERTISE_2500_HALF)
0308         hw_dbg("Advertise 2500mb Half duplex request denied!\n");
0309 
0310     /* Do we want to advertise 2500 Mb Full Duplex? */
0311     if (phy->autoneg_advertised & ADVERTISE_2500_FULL) {
0312         hw_dbg("Advertise 2500mb Full duplex\n");
0313         aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;
0314     } else {
0315         aneg_multigbt_an_ctrl &= ~CR_2500T_FD_CAPS;
0316     }
0317 
0318     /* Check for a software override of the flow control settings, and
0319      * setup the PHY advertisement registers accordingly.  If
0320      * auto-negotiation is enabled, then software will have to set the
0321      * "PAUSE" bits to the correct value in the Auto-Negotiation
0322      * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
0323      * negotiation.
0324      *
0325      * The possible values of the "fc" parameter are:
0326      *      0:  Flow control is completely disabled
0327      *      1:  Rx flow control is enabled (we can receive pause frames
0328      *          but not send pause frames).
0329      *      2:  Tx flow control is enabled (we can send pause frames
0330      *          but we do not support receiving pause frames).
0331      *      3:  Both Rx and Tx flow control (symmetric) are enabled.
0332      *  other:  No software override.  The flow control configuration
0333      *          in the EEPROM is used.
0334      */
0335     switch (hw->fc.current_mode) {
0336     case igc_fc_none:
0337         /* Flow control (Rx & Tx) is completely disabled by a
0338          * software over-ride.
0339          */
0340         mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
0341         break;
0342     case igc_fc_rx_pause:
0343         /* Rx Flow control is enabled, and Tx Flow control is
0344          * disabled, by a software over-ride.
0345          *
0346          * Since there really isn't a way to advertise that we are
0347          * capable of Rx Pause ONLY, we will advertise that we
0348          * support both symmetric and asymmetric Rx PAUSE.  Later
0349          * (in igc_config_fc_after_link_up) we will disable the
0350          * hw's ability to send PAUSE frames.
0351          */
0352         mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
0353         break;
0354     case igc_fc_tx_pause:
0355         /* Tx Flow control is enabled, and Rx Flow control is
0356          * disabled, by a software over-ride.
0357          */
0358         mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
0359         mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
0360         break;
0361     case igc_fc_full:
0362         /* Flow control (both Rx and Tx) is enabled by a software
0363          * over-ride.
0364          */
0365         mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
0366         break;
0367     default:
0368         hw_dbg("Flow control param set incorrectly\n");
0369         return -IGC_ERR_CONFIG;
0370     }
0371 
0372     ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
0373     if (ret_val)
0374         return ret_val;
0375 
0376     hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
0377 
0378     if (phy->autoneg_mask & ADVERTISE_1000_FULL)
0379         ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
0380                          mii_1000t_ctrl_reg);
0381 
0382     if (phy->autoneg_mask & ADVERTISE_2500_FULL)
0383         ret_val = phy->ops.write_reg(hw,
0384                          (STANDARD_AN_REG_MASK <<
0385                          MMD_DEVADDR_SHIFT) |
0386                          ANEG_MULTIGBT_AN_CTRL,
0387                          aneg_multigbt_an_ctrl);
0388 
0389     return ret_val;
0390 }
0391 
0392 /**
0393  * igc_wait_autoneg - Wait for auto-neg completion
0394  * @hw: pointer to the HW structure
0395  *
0396  * Waits for auto-negotiation to complete or for the auto-negotiation time
0397  * limit to expire, which ever happens first.
0398  */
0399 static s32 igc_wait_autoneg(struct igc_hw *hw)
0400 {
0401     u16 i, phy_status;
0402     s32 ret_val = 0;
0403 
0404     /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
0405     for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
0406         ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
0407         if (ret_val)
0408             break;
0409         ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
0410         if (ret_val)
0411             break;
0412         if (phy_status & MII_SR_AUTONEG_COMPLETE)
0413             break;
0414         msleep(100);
0415     }
0416 
0417     /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
0418      * has completed.
0419      */
0420     return ret_val;
0421 }
0422 
0423 /**
0424  * igc_copper_link_autoneg - Setup/Enable autoneg for copper link
0425  * @hw: pointer to the HW structure
0426  *
0427  * Performs initial bounds checking on autoneg advertisement parameter, then
0428  * configure to advertise the full capability.  Setup the PHY to autoneg
0429  * and restart the negotiation process between the link partner.  If
0430  * autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
0431  */
0432 static s32 igc_copper_link_autoneg(struct igc_hw *hw)
0433 {
0434     struct igc_phy_info *phy = &hw->phy;
0435     u16 phy_ctrl;
0436     s32 ret_val;
0437 
0438     /* Perform some bounds checking on the autoneg advertisement
0439      * parameter.
0440      */
0441     phy->autoneg_advertised &= phy->autoneg_mask;
0442 
0443     /* If autoneg_advertised is zero, we assume it was not defaulted
0444      * by the calling code so we set to advertise full capability.
0445      */
0446     if (phy->autoneg_advertised == 0)
0447         phy->autoneg_advertised = phy->autoneg_mask;
0448 
0449     hw_dbg("Reconfiguring auto-neg advertisement params\n");
0450     ret_val = igc_phy_setup_autoneg(hw);
0451     if (ret_val) {
0452         hw_dbg("Error Setting up Auto-Negotiation\n");
0453         goto out;
0454     }
0455     hw_dbg("Restarting Auto-Neg\n");
0456 
0457     /* Restart auto-negotiation by setting the Auto Neg Enable bit and
0458      * the Auto Neg Restart bit in the PHY control register.
0459      */
0460     ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
0461     if (ret_val)
0462         goto out;
0463 
0464     phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
0465     ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
0466     if (ret_val)
0467         goto out;
0468 
0469     /* Does the user want to wait for Auto-Neg to complete here, or
0470      * check at a later time (for example, callback routine).
0471      */
0472     if (phy->autoneg_wait_to_complete) {
0473         ret_val = igc_wait_autoneg(hw);
0474         if (ret_val) {
0475             hw_dbg("Error while waiting for autoneg to complete\n");
0476             goto out;
0477         }
0478     }
0479 
0480     hw->mac.get_link_status = true;
0481 
0482 out:
0483     return ret_val;
0484 }
0485 
0486 /**
0487  * igc_setup_copper_link - Configure copper link settings
0488  * @hw: pointer to the HW structure
0489  *
0490  * Calls the appropriate function to configure the link for auto-neg or forced
0491  * speed and duplex.  Then we check for link, once link is established calls
0492  * to configure collision distance and flow control are called.  If link is
0493  * not established, we return -IGC_ERR_PHY (-2).
0494  */
0495 s32 igc_setup_copper_link(struct igc_hw *hw)
0496 {
0497     s32 ret_val = 0;
0498     bool link;
0499 
0500     if (hw->mac.autoneg) {
0501         /* Setup autoneg and flow control advertisement and perform
0502          * autonegotiation.
0503          */
0504         ret_val = igc_copper_link_autoneg(hw);
0505         if (ret_val)
0506             goto out;
0507     } else {
0508         /* PHY will be set to 10H, 10F, 100H or 100F
0509          * depending on user settings.
0510          */
0511         hw_dbg("Forcing Speed and Duplex\n");
0512         ret_val = hw->phy.ops.force_speed_duplex(hw);
0513         if (ret_val) {
0514             hw_dbg("Error Forcing Speed and Duplex\n");
0515             goto out;
0516         }
0517     }
0518 
0519     /* Check link status. Wait up to 100 microseconds for link to become
0520      * valid.
0521      */
0522     ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link);
0523     if (ret_val)
0524         goto out;
0525 
0526     if (link) {
0527         hw_dbg("Valid link established!!!\n");
0528         igc_config_collision_dist(hw);
0529         ret_val = igc_config_fc_after_link_up(hw);
0530     } else {
0531         hw_dbg("Unable to establish link!!!\n");
0532     }
0533 
0534 out:
0535     return ret_val;
0536 }
0537 
0538 /**
0539  * igc_read_phy_reg_mdic - Read MDI control register
0540  * @hw: pointer to the HW structure
0541  * @offset: register offset to be read
0542  * @data: pointer to the read data
0543  *
0544  * Reads the MDI control register in the PHY at offset and stores the
0545  * information read to data.
0546  */
0547 static s32 igc_read_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 *data)
0548 {
0549     struct igc_phy_info *phy = &hw->phy;
0550     u32 i, mdic = 0;
0551     s32 ret_val = 0;
0552 
0553     if (offset > MAX_PHY_REG_ADDRESS) {
0554         hw_dbg("PHY Address %d is out of range\n", offset);
0555         ret_val = -IGC_ERR_PARAM;
0556         goto out;
0557     }
0558 
0559     /* Set up Op-code, Phy Address, and register offset in the MDI
0560      * Control register.  The MAC will take care of interfacing with the
0561      * PHY to retrieve the desired data.
0562      */
0563     mdic = ((offset << IGC_MDIC_REG_SHIFT) |
0564         (phy->addr << IGC_MDIC_PHY_SHIFT) |
0565         (IGC_MDIC_OP_READ));
0566 
0567     wr32(IGC_MDIC, mdic);
0568 
0569     /* Poll the ready bit to see if the MDI read completed
0570      * Increasing the time out as testing showed failures with
0571      * the lower time out
0572      */
0573     for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
0574         udelay(50);
0575         mdic = rd32(IGC_MDIC);
0576         if (mdic & IGC_MDIC_READY)
0577             break;
0578     }
0579     if (!(mdic & IGC_MDIC_READY)) {
0580         hw_dbg("MDI Read did not complete\n");
0581         ret_val = -IGC_ERR_PHY;
0582         goto out;
0583     }
0584     if (mdic & IGC_MDIC_ERROR) {
0585         hw_dbg("MDI Error\n");
0586         ret_val = -IGC_ERR_PHY;
0587         goto out;
0588     }
0589     *data = (u16)mdic;
0590 
0591 out:
0592     return ret_val;
0593 }
0594 
0595 /**
0596  * igc_write_phy_reg_mdic - Write MDI control register
0597  * @hw: pointer to the HW structure
0598  * @offset: register offset to write to
0599  * @data: data to write to register at offset
0600  *
0601  * Writes data to MDI control register in the PHY at offset.
0602  */
0603 static s32 igc_write_phy_reg_mdic(struct igc_hw *hw, u32 offset, u16 data)
0604 {
0605     struct igc_phy_info *phy = &hw->phy;
0606     u32 i, mdic = 0;
0607     s32 ret_val = 0;
0608 
0609     if (offset > MAX_PHY_REG_ADDRESS) {
0610         hw_dbg("PHY Address %d is out of range\n", offset);
0611         ret_val = -IGC_ERR_PARAM;
0612         goto out;
0613     }
0614 
0615     /* Set up Op-code, Phy Address, and register offset in the MDI
0616      * Control register.  The MAC will take care of interfacing with the
0617      * PHY to write the desired data.
0618      */
0619     mdic = (((u32)data) |
0620         (offset << IGC_MDIC_REG_SHIFT) |
0621         (phy->addr << IGC_MDIC_PHY_SHIFT) |
0622         (IGC_MDIC_OP_WRITE));
0623 
0624     wr32(IGC_MDIC, mdic);
0625 
0626     /* Poll the ready bit to see if the MDI read completed
0627      * Increasing the time out as testing showed failures with
0628      * the lower time out
0629      */
0630     for (i = 0; i < IGC_GEN_POLL_TIMEOUT; i++) {
0631         udelay(50);
0632         mdic = rd32(IGC_MDIC);
0633         if (mdic & IGC_MDIC_READY)
0634             break;
0635     }
0636     if (!(mdic & IGC_MDIC_READY)) {
0637         hw_dbg("MDI Write did not complete\n");
0638         ret_val = -IGC_ERR_PHY;
0639         goto out;
0640     }
0641     if (mdic & IGC_MDIC_ERROR) {
0642         hw_dbg("MDI Error\n");
0643         ret_val = -IGC_ERR_PHY;
0644         goto out;
0645     }
0646 
0647 out:
0648     return ret_val;
0649 }
0650 
0651 /**
0652  * __igc_access_xmdio_reg - Read/write XMDIO register
0653  * @hw: pointer to the HW structure
0654  * @address: XMDIO address to program
0655  * @dev_addr: device address to program
0656  * @data: pointer to value to read/write from/to the XMDIO address
0657  * @read: boolean flag to indicate read or write
0658  */
0659 static s32 __igc_access_xmdio_reg(struct igc_hw *hw, u16 address,
0660                   u8 dev_addr, u16 *data, bool read)
0661 {
0662     s32 ret_val;
0663 
0664     ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, dev_addr);
0665     if (ret_val)
0666         return ret_val;
0667 
0668     ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, address);
0669     if (ret_val)
0670         return ret_val;
0671 
0672     ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, IGC_MMDAC_FUNC_DATA |
0673                     dev_addr);
0674     if (ret_val)
0675         return ret_val;
0676 
0677     if (read)
0678         ret_val = hw->phy.ops.read_reg(hw, IGC_MMDAAD, data);
0679     else
0680         ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAAD, *data);
0681     if (ret_val)
0682         return ret_val;
0683 
0684     /* Recalibrate the device back to 0 */
0685     ret_val = hw->phy.ops.write_reg(hw, IGC_MMDAC, 0);
0686     if (ret_val)
0687         return ret_val;
0688 
0689     return ret_val;
0690 }
0691 
0692 /**
0693  * igc_read_xmdio_reg - Read XMDIO register
0694  * @hw: pointer to the HW structure
0695  * @addr: XMDIO address to program
0696  * @dev_addr: device address to program
0697  * @data: value to be read from the EMI address
0698  */
0699 static s32 igc_read_xmdio_reg(struct igc_hw *hw, u16 addr,
0700                   u8 dev_addr, u16 *data)
0701 {
0702     return __igc_access_xmdio_reg(hw, addr, dev_addr, data, true);
0703 }
0704 
0705 /**
0706  * igc_write_xmdio_reg - Write XMDIO register
0707  * @hw: pointer to the HW structure
0708  * @addr: XMDIO address to program
0709  * @dev_addr: device address to program
0710  * @data: value to be written to the XMDIO address
0711  */
0712 static s32 igc_write_xmdio_reg(struct igc_hw *hw, u16 addr,
0713                    u8 dev_addr, u16 data)
0714 {
0715     return __igc_access_xmdio_reg(hw, addr, dev_addr, &data, false);
0716 }
0717 
0718 /**
0719  * igc_write_phy_reg_gpy - Write GPY PHY register
0720  * @hw: pointer to the HW structure
0721  * @offset: register offset to write to
0722  * @data: data to write at register offset
0723  *
0724  * Acquires semaphore, if necessary, then writes the data to PHY register
0725  * at the offset. Release any acquired semaphores before exiting.
0726  */
0727 s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data)
0728 {
0729     u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT;
0730     s32 ret_val;
0731 
0732     offset = offset & GPY_REG_MASK;
0733 
0734     if (!dev_addr) {
0735         ret_val = hw->phy.ops.acquire(hw);
0736         if (ret_val)
0737             return ret_val;
0738         ret_val = igc_write_phy_reg_mdic(hw, offset, data);
0739         hw->phy.ops.release(hw);
0740     } else {
0741         ret_val = igc_write_xmdio_reg(hw, (u16)offset, dev_addr,
0742                           data);
0743     }
0744 
0745     return ret_val;
0746 }
0747 
0748 /**
0749  * igc_read_phy_reg_gpy - Read GPY PHY register
0750  * @hw: pointer to the HW structure
0751  * @offset: lower half is register offset to read to
0752  * upper half is MMD to use.
0753  * @data: data to read at register offset
0754  *
0755  * Acquires semaphore, if necessary, then reads the data in the PHY register
0756  * at the offset. Release any acquired semaphores before exiting.
0757  */
0758 s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data)
0759 {
0760     u8 dev_addr = (offset & GPY_MMD_MASK) >> GPY_MMD_SHIFT;
0761     s32 ret_val;
0762 
0763     offset = offset & GPY_REG_MASK;
0764 
0765     if (!dev_addr) {
0766         ret_val = hw->phy.ops.acquire(hw);
0767         if (ret_val)
0768             return ret_val;
0769         ret_val = igc_read_phy_reg_mdic(hw, offset, data);
0770         hw->phy.ops.release(hw);
0771     } else {
0772         ret_val = igc_read_xmdio_reg(hw, (u16)offset, dev_addr,
0773                          data);
0774     }
0775 
0776     return ret_val;
0777 }
0778 
0779 /**
0780  * igc_read_phy_fw_version - Read gPHY firmware version
0781  * @hw: pointer to the HW structure
0782  */
0783 u16 igc_read_phy_fw_version(struct igc_hw *hw)
0784 {
0785     struct igc_phy_info *phy = &hw->phy;
0786     u16 gphy_version = 0;
0787     u16 ret_val;
0788 
0789     /* NVM image version is reported as firmware version for i225 device */
0790     ret_val = phy->ops.read_reg(hw, IGC_GPHY_VERSION, &gphy_version);
0791     if (ret_val)
0792         hw_dbg("igc_phy: read wrong gphy version\n");
0793 
0794     return gphy_version;
0795 }