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