src/dpdk/drivers/net/e1000/base/e1000_ich8lan.c
s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
{
	u32 mac_reg;
	s32 ret_val = E1000_SUCCESS;
	u16 phy_reg;
	u16 oem_reg = 0;

	if ((hw->mac.type < e1000_pch_lpt) ||
	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) ||
	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_V) ||
	    (hw->device_id == E1000_DEV_ID_PCH_I218_LM2) ||
	    (hw->device_id == E1000_DEV_ID_PCH_I218_V2) ||
	    (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_on))
		return 0;

	if (!to_sx) {
		int i = 0;
		/* Poll up to 5 seconds for Cable Disconnected indication */
		while (!(E1000_READ_REG(hw, E1000_FEXT) &
			 E1000_FEXT_PHY_CABLE_DISCONNECTED)) {
			/* Bail if link is re-acquired */
			if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)
				return -E1000_ERR_PHY;
			if (i++ == 100)
				break;

			msec_delay(50);
		}
		DEBUGOUT2("CABLE_DISCONNECTED %s set after %dmsec\n",
			  (E1000_READ_REG(hw, E1000_FEXT) &
			   E1000_FEXT_PHY_CABLE_DISCONNECTED) ? "" : "not",
			  i * 50);
		if (!(E1000_READ_REG(hw, E1000_FEXT) &
		    E1000_FEXT_PHY_CABLE_DISCONNECTED))
			return 0;
	}

	if (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID) {
		/* Request ME configure ULP mode in the PHY */
		mac_reg = E1000_READ_REG(hw, E1000_H2ME);
		mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS;
		E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);

		goto out;
	}

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

	/* During S0 Idle keep the phy in PCI-E mode */
	if (hw->dev_spec.ich8lan.smbus_disable)
		goto skip_smbus;

	/* Force SMBus mode in PHY */
	ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
	if (ret_val)
		goto release;
	phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
	e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);

	/* Force SMBus mode in MAC */
	mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
	mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
	E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);

	/* Si workaround for ULP entry flow on i127/rev6 h/w.  Enable
	 * LPLU and disable Gig speed when entering ULP
	 */
	if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
		ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
						       &oem_reg);
		if (ret_val)
			goto release;

		phy_reg = oem_reg;
		phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;

		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
							phy_reg);

		if (ret_val)
			goto release;
	}

skip_smbus:
	if (!to_sx) {
		/* Change the 'Link Status Change' interrupt to trigger
		 * on 'Cable Status Change'
		 */
		ret_val = e1000_read_kmrn_reg_locked(hw,
						     E1000_KMRNCTRLSTA_OP_MODES,
						     &phy_reg);
		if (ret_val)
			goto release;
		phy_reg |= E1000_KMRNCTRLSTA_OP_MODES_LSC2CSC;
		e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_OP_MODES,
					    phy_reg);
	}

	/* Set Inband ULP Exit, Reset to SMBus mode and
	 * Disable SMBus Release on PERST# in PHY
	 */
	ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg);
	if (ret_val)
		goto release;
	phy_reg |= (I218_ULP_CONFIG1_RESET_TO_SMBUS |
		    I218_ULP_CONFIG1_DISABLE_SMB_PERST);
	if (to_sx) {
		if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC)
			phy_reg |= I218_ULP_CONFIG1_WOL_HOST;
		else
			phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;

		phy_reg |= I218_ULP_CONFIG1_STICKY_ULP;
		phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT;
	} else {
		phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT;
		phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP;
		phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
	}
	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);

	/* Set Disable SMBus Release on PERST# in MAC */
	mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7);
	mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST;
	E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg);

	/* Commit ULP changes in PHY by starting auto ULP configuration */
	phy_reg |= I218_ULP_CONFIG1_START;
	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);

	if (!to_sx) {
		/* Disable Tx so that the MAC doesn't send any (buffered)
		 * packets to the PHY.
		 */
		mac_reg = E1000_READ_REG(hw, E1000_TCTL);
		mac_reg &= ~E1000_TCTL_EN;
		E1000_WRITE_REG(hw, E1000_TCTL, mac_reg);
	}

	if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) &&
	    to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
							oem_reg);
		if (ret_val)
			goto release;
	}

release:
	hw->phy.ops.release(hw);
out:
	if (ret_val)
		DEBUGOUT1("Error in ULP enable flow: %d\n", ret_val);
	else
		hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on;

	return ret_val;
}
/**
 *  e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP
 *  @hw: pointer to the HW structure
 *  @to_sx: boolean indicating a system power state transition to Sx
 *
 *  When link is down, configure ULP mode to significantly reduce the power
 *  to the PHY.  If on a Manageability Engine (ME) enabled system, tell the
 *  ME firmware to start the ULP configuration.  If not on an ME enabled
 *  system, configure the ULP mode by software.
 */
configure Ultra Low Power mode for LynxPoint-LP
@hw: pointer to the HW structure
@to_sx: boolean indicating a system power state transition to Sx

When link is down, configure ULP mode to significantly reduce the power
to the PHY.  If on a Manageability Engine (ME) enabled system, tell the
ME firmware to start the ULP configuration.  If not on an ME enabled
system, configure the ULP mode by software.
configure Ultra Low Power mode for LynxPoint - LP @hw : pointer to the HW structure @to_sx : boolean indicating a system power state transition to Sx When link is down configure ULP mode to significantly reduce the power to the PHY . If on a Manageability Engine ( ME ) enabled system tell the ME firmware to start the ULP configuration . If not on an ME enabled system configure the ULP mode by software .
s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
{
	u32 mac_reg;
	s32 ret_val = E1000_SUCCESS;
	u16 phy_reg;
	u16 oem_reg = 0;
	if ((hw->mac.type < e1000_pch_lpt) ||
	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) ||
	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_V) ||
	    (hw->device_id == E1000_DEV_ID_PCH_I218_LM2) ||
	    (hw->device_id == E1000_DEV_ID_PCH_I218_V2) ||
	    (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_on))
		return 0;
	if (!to_sx) {
		int i = 0;
		while (!(E1000_READ_REG(hw, E1000_FEXT) &
			 E1000_FEXT_PHY_CABLE_DISCONNECTED)) {
			if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)
				return -E1000_ERR_PHY;
			if (i++ == 100)
				break;
			msec_delay(50);
		}
		DEBUGOUT2("CABLE_DISCONNECTED %s set after %dmsec\n",
			  (E1000_READ_REG(hw, E1000_FEXT) &
			   E1000_FEXT_PHY_CABLE_DISCONNECTED) ? "" : "not",
			  i * 50);
		if (!(E1000_READ_REG(hw, E1000_FEXT) &
		    E1000_FEXT_PHY_CABLE_DISCONNECTED))
			return 0;
	}
	if (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID) {
		mac_reg = E1000_READ_REG(hw, E1000_H2ME);
		mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS;
		E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);
		goto out;
	}
	ret_val = hw->phy.ops.acquire(hw);
	if (ret_val)
		goto out;
	if (hw->dev_spec.ich8lan.smbus_disable)
		goto skip_smbus;
	ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
	if (ret_val)
		goto release;
	phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
	e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
	mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
	mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
	E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
	if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
		ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
						       &oem_reg);
		if (ret_val)
			goto release;
		phy_reg = oem_reg;
		phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
							phy_reg);
		if (ret_val)
			goto release;
	}
skip_smbus:
	if (!to_sx) {
		ret_val = e1000_read_kmrn_reg_locked(hw,
						     E1000_KMRNCTRLSTA_OP_MODES,
						     &phy_reg);
		if (ret_val)
			goto release;
		phy_reg |= E1000_KMRNCTRLSTA_OP_MODES_LSC2CSC;
		e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_OP_MODES,
					    phy_reg);
	}
	ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg);
	if (ret_val)
		goto release;
	phy_reg |= (I218_ULP_CONFIG1_RESET_TO_SMBUS |
		    I218_ULP_CONFIG1_DISABLE_SMB_PERST);
	if (to_sx) {
		if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC)
			phy_reg |= I218_ULP_CONFIG1_WOL_HOST;
		else
			phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
		phy_reg |= I218_ULP_CONFIG1_STICKY_ULP;
		phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT;
	} else {
		phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT;
		phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP;
		phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
	}
	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
	mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7);
	mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST;
	E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg);
	phy_reg |= I218_ULP_CONFIG1_START;
	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
	if (!to_sx) {
		mac_reg = E1000_READ_REG(hw, E1000_TCTL);
		mac_reg &= ~E1000_TCTL_EN;
		E1000_WRITE_REG(hw, E1000_TCTL, mac_reg);
	}
	if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) &&
	    to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
							oem_reg);
		if (ret_val)
			goto release;
	}
release:
	hw->phy.ops.release(hw);
out:
	if (ret_val)
		DEBUGOUT1("Error in ULP enable flow: %d\n", ret_val);
	else
		hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on;
	return ret_val;
}
s32 e1000_enable_ulp_lpt_lp ( struct e1000_hw * hw , bool to_sx ) { u32 mac_reg ; s32 ret_val = E1000_SUCCESS ; u16 phy_reg ; u16 oem_reg = 0 ; if ( ( hw -> mac . type < e1000_pch_lpt ) || ( hw -> device_id == E1000_DEV_ID_PCH_LPT_I217_LM ) || ( hw -> device_id == E1000_DEV_ID_PCH_LPT_I217_V ) || ( hw -> device_id == E1000_DEV_ID_PCH_I218_LM2 ) || ( hw -> device_id == E1000_DEV_ID_PCH_I218_V2 ) || ( hw -> dev_spec . ich8lan . ulp_state == e1000_ulp_state_on ) ) return 0 ; if ( ! to_sx ) { int i = 0 ; while ( ! ( E1000_READ_REG ( hw , E1000_FEXT ) & E1000_FEXT_PHY_CABLE_DISCONNECTED ) ) { if ( E1000_READ_REG ( hw , E1000_STATUS ) & E1000_STATUS_LU ) return - E1000_ERR_PHY ; if ( i ++ == 100 ) break ; msec_delay ( 50 ) ; } DEBUGOUT2 ( " \n " , ( E1000_READ_REG ( hw , E1000_FEXT ) & E1000_FEXT_PHY_CABLE_DISCONNECTED ) ? " " : " " , i * 50 ) ; if ( ! ( E1000_READ_REG ( hw , E1000_FEXT ) & E1000_FEXT_PHY_CABLE_DISCONNECTED ) ) return 0 ; } if ( E1000_READ_REG ( hw , E1000_FWSM ) & E1000_ICH_FWSM_FW_VALID ) { mac_reg = E1000_READ_REG ( hw , E1000_H2ME ) ; mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS ; E1000_WRITE_REG ( hw , E1000_H2ME , mac_reg ) ; goto out ; } ret_val = hw -> phy . ops . acquire ( hw ) ; if ( ret_val ) goto out ; if ( hw -> dev_spec . ich8lan . smbus_disable ) goto skip_smbus ; ret_val = e1000_read_phy_reg_hv_locked ( hw , CV_SMB_CTRL , & phy_reg ) ; if ( ret_val ) goto release ; phy_reg |= CV_SMB_CTRL_FORCE_SMBUS ; e1000_write_phy_reg_hv_locked ( hw , CV_SMB_CTRL , phy_reg ) ; mac_reg = E1000_READ_REG ( hw , E1000_CTRL_EXT ) ; mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS ; E1000_WRITE_REG ( hw , E1000_CTRL_EXT , mac_reg ) ; if ( ( hw -> phy . type == e1000_phy_i217 ) && ( hw -> phy . revision == 6 ) ) { ret_val = e1000_read_phy_reg_hv_locked ( hw , HV_OEM_BITS , & oem_reg ) ; if ( ret_val ) goto release ; phy_reg = oem_reg ; phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS ; ret_val = e1000_write_phy_reg_hv_locked ( hw , HV_OEM_BITS , phy_reg ) ; if ( ret_val ) goto release ; } skip_smbus : if ( ! to_sx ) { ret_val = e1000_read_kmrn_reg_locked ( hw , E1000_KMRNCTRLSTA_OP_MODES , & phy_reg ) ; if ( ret_val ) goto release ; phy_reg |= E1000_KMRNCTRLSTA_OP_MODES_LSC2CSC ; e1000_write_kmrn_reg_locked ( hw , E1000_KMRNCTRLSTA_OP_MODES , phy_reg ) ; } ret_val = e1000_read_phy_reg_hv_locked ( hw , I218_ULP_CONFIG1 , & phy_reg ) ; if ( ret_val ) goto release ; phy_reg |= ( I218_ULP_CONFIG1_RESET_TO_SMBUS | I218_ULP_CONFIG1_DISABLE_SMB_PERST ) ; if ( to_sx ) { if ( E1000_READ_REG ( hw , E1000_WUFC ) & E1000_WUFC_LNKC ) phy_reg |= I218_ULP_CONFIG1_WOL_HOST ; else phy_reg &= ~ I218_ULP_CONFIG1_WOL_HOST ; phy_reg |= I218_ULP_CONFIG1_STICKY_ULP ; phy_reg &= ~ I218_ULP_CONFIG1_INBAND_EXIT ; } else { phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT ; phy_reg &= ~ I218_ULP_CONFIG1_STICKY_ULP ; phy_reg &= ~ I218_ULP_CONFIG1_WOL_HOST ; } e1000_write_phy_reg_hv_locked ( hw , I218_ULP_CONFIG1 , phy_reg ) ; mac_reg = E1000_READ_REG ( hw , E1000_FEXTNVM7 ) ; mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST ; E1000_WRITE_REG ( hw , E1000_FEXTNVM7 , mac_reg ) ; phy_reg |= I218_ULP_CONFIG1_START ; e1000_write_phy_reg_hv_locked ( hw , I218_ULP_CONFIG1 , phy_reg ) ; if ( ! to_sx ) { mac_reg = E1000_READ_REG ( hw , E1000_TCTL ) ; mac_reg &= ~ E1000_TCTL_EN ; E1000_WRITE_REG ( hw , E1000_TCTL , mac_reg ) ; } if ( ( hw -> phy . type == e1000_phy_i217 ) && ( hw -> phy . revision == 6 ) && to_sx && ( E1000_READ_REG ( hw , E1000_STATUS ) & E1000_STATUS_LU ) ) { ret_val = e1000_write_phy_reg_hv_locked ( hw , HV_OEM_BITS , oem_reg ) ; if ( ret_val ) goto release ; } release : hw -> phy . ops . release ( hw ) ; out : if ( ret_val ) DEBUGOUT1 ( " \n " , ret_val ) ; else hw -> dev_spec . ich8lan . ulp_state = e1000_ulp_state_on ; return ret_val ; }
e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP
  @hw: pointer to the HW structure
  @to_sx: boolean indicating a system power state transition to Sx
e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint - LP @hw : pointer to the HW structure @to_sx : boolean indicating a system power state transition to Sx
/* Poll up to 5 seconds for Cable Disconnected indication */ /* Bail if link is re-acquired */ /* Request ME configure ULP mode in the PHY */ /* During S0 Idle keep the phy in PCI-E mode */ /* Force SMBus mode in PHY */ /* Force SMBus mode in MAC */ /* Si workaround for ULP entry flow on i127/rev6 h/w.  Enable
	 * LPLU and disable Gig speed when entering ULP
	 */ /* Change the 'Link Status Change' interrupt to trigger
		 * on 'Cable Status Change'
		 */ /* Set Inband ULP Exit, Reset to SMBus mode and
	 * Disable SMBus Release on PERST# in PHY
	 */ /* Set Disable SMBus Release on PERST# in MAC */ /* Commit ULP changes in PHY by starting auto ULP configuration */ /* Disable Tx so that the MAC doesn't send any (buffered)
		 * packets to the PHY.
		 */