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