src/dpdk/drivers/net/e1000/base/e1000_ich8lan.c
void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
	u32 phy_ctrl;
	s32 ret_val;

	DEBUGFUNC("e1000_suspend_workarounds_ich8lan");

	phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
	phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;

	if (hw->phy.type == e1000_phy_i217) {
		u16 phy_reg, device_id = hw->device_id;

		if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
		    (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
		    (device_id == E1000_DEV_ID_PCH_I218_LM3) ||
		    (device_id == E1000_DEV_ID_PCH_I218_V3) ||
		    (hw->mac.type >= e1000_pch_spt)) {
			u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);

			E1000_WRITE_REG(hw, E1000_FEXTNVM6,
					fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
		}

		ret_val = hw->phy.ops.acquire(hw);
		if (ret_val)
			goto out;

		if (!dev_spec->eee_disable) {
			u16 eee_advert;

			ret_val =
			    e1000_read_emi_reg_locked(hw,
						      I217_EEE_ADVERTISEMENT,
						      &eee_advert);
			if (ret_val)
				goto release;

			/* Disable LPLU if both link partners support 100BaseT
			 * EEE and 100Full is advertised on both ends of the
			 * link, and enable Auto Enable LPI since there will
			 * be no driver to enable LPI while in Sx.
			 */
			if ((eee_advert & I82579_EEE_100_SUPPORTED) &&
			    (dev_spec->eee_lp_ability &
			     I82579_EEE_100_SUPPORTED) &&
			    (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) {
				phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
					      E1000_PHY_CTRL_NOND0A_LPLU);

				/* Set Auto Enable LPI after link up */
				hw->phy.ops.read_reg_locked(hw,
							    I217_LPI_GPIO_CTRL,
							    &phy_reg);
				phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
				hw->phy.ops.write_reg_locked(hw,
							     I217_LPI_GPIO_CTRL,
							     phy_reg);
			}
		}

		/* For i217 Intel Rapid Start Technology support,
		 * when the system is going into Sx and no manageability engine
		 * is present, the driver must configure proxy to reset only on
		 * power good.  LPI (Low Power Idle) state must also reset only
		 * on power good, as well as the MTA (Multicast table array).
		 * The SMBus release must also be disabled on LCD reset.
		 */
		if (!(E1000_READ_REG(hw, E1000_FWSM) &
		      E1000_ICH_FWSM_FW_VALID)) {
			/* Enable proxy to reset only on power good. */
			hw->phy.ops.read_reg_locked(hw, I217_PROXY_CTRL,
						    &phy_reg);
			phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
			hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL,
						     phy_reg);

			/* Set bit enable LPI (EEE) to reset only on
			 * power good.
			*/
			hw->phy.ops.read_reg_locked(hw, I217_SxCTRL, &phy_reg);
			phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET;
			hw->phy.ops.write_reg_locked(hw, I217_SxCTRL, phy_reg);

			/* Disable the SMB release on LCD reset. */
			hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, &phy_reg);
			phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE;
			hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg);
		}

		/* Enable MTA to reset for Intel Rapid Start Technology
		 * Support
		 */
		hw->phy.ops.read_reg_locked(hw, I217_CGFREG, &phy_reg);
		phy_reg |= I217_CGFREG_ENABLE_MTA_RESET;
		hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg);

release:
		hw->phy.ops.release(hw);
	}
out:
	E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);

	if (hw->mac.type == e1000_ich8lan)
		e1000_gig_downshift_workaround_ich8lan(hw);

	if (hw->mac.type >= e1000_pchlan) {
		e1000_oem_bits_config_ich8lan(hw, false);

		/* Reset PHY to activate OEM bits on 82577/8 */
		if (hw->mac.type == e1000_pchlan)
			e1000_phy_hw_reset_generic(hw);

		ret_val = hw->phy.ops.acquire(hw);
		if (ret_val)
			return;
		e1000_write_smbus_addr(hw);
		hw->phy.ops.release(hw);
	}

	return;
}
/**
 *  e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
 *  @hw: pointer to the HW structure
 *
 *  During S0 to Sx transition, it is possible the link remains at gig
 *  instead of negotiating to a lower speed.  Before going to Sx, set
 *  'Gig Disable' to force link speed negotiation to a lower speed based on
 *  the LPLU setting in the NVM or custom setting.  For PCH and newer parts,
 *  the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
 *  needs to be written.
 *  Parts that support (and are linked to a partner which support) EEE in
 *  100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
 *  than 10Mbps w/o EEE.
 **/
workarounds needed during S0->Sx
@hw: pointer to the HW structure

During S0 to Sx transition, it is possible the link remains at gig
instead of negotiating to a lower speed.  Before going to Sx, set
'Gig Disable' to force link speed negotiation to a lower speed based on
the LPLU setting in the NVM or custom setting.  For PCH and newer parts,
the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
needs to be written.
Parts that support (and are linked to a partner which support) EEE in
100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
than 10Mbps w/o EEE.
workarounds needed during S0 - > Sx @hw : pointer to the HW structure During S0 to Sx transition it is possible the link remains at gig instead of negotiating to a lower speed . Before going to Sx set ' Gig Disable ' to force link speed negotiation to a lower speed based on the LPLU setting in the NVM or custom setting . For PCH and newer parts the OEM bits PHY register ( LED GbE disable and LPLU configurations ) also needs to be written . Parts that support ( and are linked to a partner which support ) EEE in 100Mbps should disable LPLU since 100Mbps w / EEE requires less power than 10Mbps w / o EEE .
void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
{
	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
	u32 phy_ctrl;
	s32 ret_val;
	DEBUGFUNC("e1000_suspend_workarounds_ich8lan");
	phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
	phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
	if (hw->phy.type == e1000_phy_i217) {
		u16 phy_reg, device_id = hw->device_id;
		if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
		    (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
		    (device_id == E1000_DEV_ID_PCH_I218_LM3) ||
		    (device_id == E1000_DEV_ID_PCH_I218_V3) ||
		    (hw->mac.type >= e1000_pch_spt)) {
			u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
			E1000_WRITE_REG(hw, E1000_FEXTNVM6,
					fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
		}
		ret_val = hw->phy.ops.acquire(hw);
		if (ret_val)
			goto out;
		if (!dev_spec->eee_disable) {
			u16 eee_advert;
			ret_val =
			    e1000_read_emi_reg_locked(hw,
						      I217_EEE_ADVERTISEMENT,
						      &eee_advert);
			if (ret_val)
				goto release;
			if ((eee_advert & I82579_EEE_100_SUPPORTED) &&
			    (dev_spec->eee_lp_ability &
			     I82579_EEE_100_SUPPORTED) &&
			    (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) {
				phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
					      E1000_PHY_CTRL_NOND0A_LPLU);
				hw->phy.ops.read_reg_locked(hw,
							    I217_LPI_GPIO_CTRL,
							    &phy_reg);
				phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
				hw->phy.ops.write_reg_locked(hw,
							     I217_LPI_GPIO_CTRL,
							     phy_reg);
			}
		}
		if (!(E1000_READ_REG(hw, E1000_FWSM) &
		      E1000_ICH_FWSM_FW_VALID)) {
			hw->phy.ops.read_reg_locked(hw, I217_PROXY_CTRL,
						    &phy_reg);
			phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
			hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL,
						     phy_reg);
			hw->phy.ops.read_reg_locked(hw, I217_SxCTRL, &phy_reg);
			phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET;
			hw->phy.ops.write_reg_locked(hw, I217_SxCTRL, phy_reg);
			hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, &phy_reg);
			phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE;
			hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg);
		}
		hw->phy.ops.read_reg_locked(hw, I217_CGFREG, &phy_reg);
		phy_reg |= I217_CGFREG_ENABLE_MTA_RESET;
		hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg);
release:
		hw->phy.ops.release(hw);
	}
out:
	E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
	if (hw->mac.type == e1000_ich8lan)
		e1000_gig_downshift_workaround_ich8lan(hw);
	if (hw->mac.type >= e1000_pchlan) {
		e1000_oem_bits_config_ich8lan(hw, false);
		if (hw->mac.type == e1000_pchlan)
			e1000_phy_hw_reset_generic(hw);
		ret_val = hw->phy.ops.acquire(hw);
		if (ret_val)
			return;
		e1000_write_smbus_addr(hw);
		hw->phy.ops.release(hw);
	}
	return;
}
void e1000_suspend_workarounds_ich8lan ( struct e1000_hw * hw ) { struct e1000_dev_spec_ich8lan * dev_spec = & hw -> dev_spec . ich8lan ; u32 phy_ctrl ; s32 ret_val ; DEBUGFUNC ( " " ) ; phy_ctrl = E1000_READ_REG ( hw , E1000_PHY_CTRL ) ; phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE ; if ( hw -> phy . type == e1000_phy_i217 ) { u16 phy_reg , device_id = hw -> device_id ; if ( ( device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM ) || ( device_id == E1000_DEV_ID_PCH_LPTLP_I218_V ) || ( device_id == E1000_DEV_ID_PCH_I218_LM3 ) || ( device_id == E1000_DEV_ID_PCH_I218_V3 ) || ( hw -> mac . type >= e1000_pch_spt ) ) { u32 fextnvm6 = E1000_READ_REG ( hw , E1000_FEXTNVM6 ) ; E1000_WRITE_REG ( hw , E1000_FEXTNVM6 , fextnvm6 & ~ E1000_FEXTNVM6_REQ_PLL_CLK ) ; } ret_val = hw -> phy . ops . acquire ( hw ) ; if ( ret_val ) goto out ; if ( ! dev_spec -> eee_disable ) { u16 eee_advert ; ret_val = e1000_read_emi_reg_locked ( hw , I217_EEE_ADVERTISEMENT , & eee_advert ) ; if ( ret_val ) goto release ; if ( ( eee_advert & I82579_EEE_100_SUPPORTED ) && ( dev_spec -> eee_lp_ability & I82579_EEE_100_SUPPORTED ) && ( hw -> phy . autoneg_advertised & ADVERTISE_100_FULL ) ) { phy_ctrl &= ~ ( E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_NOND0A_LPLU ) ; hw -> phy . ops . read_reg_locked ( hw , I217_LPI_GPIO_CTRL , & phy_reg ) ; phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI ; hw -> phy . ops . write_reg_locked ( hw , I217_LPI_GPIO_CTRL , phy_reg ) ; } } if ( ! ( E1000_READ_REG ( hw , E1000_FWSM ) & E1000_ICH_FWSM_FW_VALID ) ) { hw -> phy . ops . read_reg_locked ( hw , I217_PROXY_CTRL , & phy_reg ) ; phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE ; hw -> phy . ops . write_reg_locked ( hw , I217_PROXY_CTRL , phy_reg ) ; hw -> phy . ops . read_reg_locked ( hw , I217_SxCTRL , & phy_reg ) ; phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET ; hw -> phy . ops . write_reg_locked ( hw , I217_SxCTRL , phy_reg ) ; hw -> phy . ops . read_reg_locked ( hw , I217_MEMPWR , & phy_reg ) ; phy_reg &= ~ I217_MEMPWR_DISABLE_SMB_RELEASE ; hw -> phy . ops . write_reg_locked ( hw , I217_MEMPWR , phy_reg ) ; } hw -> phy . ops . read_reg_locked ( hw , I217_CGFREG , & phy_reg ) ; phy_reg |= I217_CGFREG_ENABLE_MTA_RESET ; hw -> phy . ops . write_reg_locked ( hw , I217_CGFREG , phy_reg ) ; release : hw -> phy . ops . release ( hw ) ; } out : E1000_WRITE_REG ( hw , E1000_PHY_CTRL , phy_ctrl ) ; if ( hw -> mac . type == e1000_ich8lan ) e1000_gig_downshift_workaround_ich8lan ( hw ) ; if ( hw -> mac . type >= e1000_pchlan ) { e1000_oem_bits_config_ich8lan ( hw , false ) ; if ( hw -> mac . type == e1000_pchlan ) e1000_phy_hw_reset_generic ( hw ) ; ret_val = hw -> phy . ops . acquire ( hw ) ; if ( ret_val ) return ; e1000_write_smbus_addr ( hw ) ; hw -> phy . ops . release ( hw ) ; } return ; }
e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
  @hw: pointer to the HW structure
e1000_suspend_workarounds_ich8lan - workarounds needed during S0 - > Sx @hw : pointer to the HW structure
/* Disable LPLU if both link partners support 100BaseT
			 * EEE and 100Full is advertised on both ends of the
			 * link, and enable Auto Enable LPI since there will
			 * be no driver to enable LPI while in Sx.
			 */ /* Set Auto Enable LPI after link up */ /* For i217 Intel Rapid Start Technology support,
		 * when the system is going into Sx and no manageability engine
		 * is present, the driver must configure proxy to reset only on
		 * power good.  LPI (Low Power Idle) state must also reset only
		 * on power good, as well as the MTA (Multicast table array).
		 * The SMBus release must also be disabled on LCD reset.
		 */ /* Enable proxy to reset only on power good. */ /* Set bit enable LPI (EEE) to reset only on
			 * power good.
			*/ /* Disable the SMB release on LCD reset. */ /* Enable MTA to reset for Intel Rapid Start Technology
		 * Support
		 */ /* Reset PHY to activate OEM bits on 82577/8 */