Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d3738bb8 authored by Bruce Allan's avatar Bruce Allan Committed by David S. Miller
Browse files

e1000e: initial support for 82579 LOMs

parent eb7700dc
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -359,6 +359,7 @@
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE       0x00000008
#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE       0x00000008
#define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
#define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
#define E1000_EXTCNF_CTRL_GATE_PHY_CFG           0x00000080
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK   0x0FFF0000
#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK   0x0FFF0000
@@ -714,6 +715,7 @@
#define BME1000_E_PHY_ID_R2  0x01410CB1
#define BME1000_E_PHY_ID_R2  0x01410CB1
#define I82577_E_PHY_ID      0x01540050
#define I82577_E_PHY_ID      0x01540050
#define I82578_E_PHY_ID      0x004DD040
#define I82578_E_PHY_ID      0x004DD040
#define I82579_E_PHY_ID      0x01540090


/* M88E1000 Specific Registers */
/* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
#define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
+4 −0
Original line number Original line Diff line number Diff line
@@ -164,6 +164,7 @@ enum e1000_boards {
	board_ich9lan,
	board_ich9lan,
	board_ich10lan,
	board_ich10lan,
	board_pchlan,
	board_pchlan,
	board_pch2lan,
};
};


struct e1000_queue_stats {
struct e1000_queue_stats {
@@ -477,6 +478,7 @@ extern struct e1000_info e1000_ich8_info;
extern struct e1000_info e1000_ich9_info;
extern struct e1000_info e1000_ich9_info;
extern struct e1000_info e1000_ich10_info;
extern struct e1000_info e1000_ich10_info;
extern struct e1000_info e1000_pch_info;
extern struct e1000_info e1000_pch_info;
extern struct e1000_info e1000_pch2_info;
extern struct e1000_info e1000_es2_info;
extern struct e1000_info e1000_es2_info;


extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
@@ -495,6 +497,8 @@ extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);


extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
+13 −0
Original line number Original line Diff line number Diff line
@@ -880,6 +880,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
	switch (mac->type) {
	switch (mac->type) {
	case e1000_ich10lan:
	case e1000_ich10lan:
	case e1000_pchlan:
	case e1000_pchlan:
	case e1000_pch2lan:
		mask |= (1 << 18);
		mask |= (1 << 18);
		break;
		break;
	default:
	default:
@@ -1321,6 +1322,17 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
		/* Workaround: K1 must be disabled for stable 1Gbps operation */
		/* Workaround: K1 must be disabled for stable 1Gbps operation */
		e1000_configure_k1_ich8lan(hw, false);
		e1000_configure_k1_ich8lan(hw, false);
		break;
		break;
	case e1000_phy_82579:
		/* Disable PHY energy detect power down */
		e1e_rphy(hw, PHY_REG(0, 21), &phy_reg);
		e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3));
		/* Disable full chip energy detect */
		e1e_rphy(hw, PHY_REG(776, 18), &phy_reg);
		e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1);
		/* Enable loopback on the PHY */
#define I82577_PHY_LBK_CTRL          19
		e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001);
		break;
	default:
	default:
		break;
		break;
	}
	}
@@ -1878,6 +1890,7 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)


	if ((hw->phy.type == e1000_phy_ife) ||
	if ((hw->phy.type == e1000_phy_ife) ||
	    (hw->mac.type == e1000_pchlan) ||
	    (hw->mac.type == e1000_pchlan) ||
	    (hw->mac.type == e1000_pch2lan) ||
	    (hw->mac.type == e1000_82583) ||
	    (hw->mac.type == e1000_82583) ||
	    (hw->mac.type == e1000_82574)) {
	    (hw->mac.type == e1000_82574)) {
		INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task);
		INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task);
+10 −2
Original line number Original line Diff line number Diff line
@@ -217,7 +217,10 @@ enum e1e_registers {
	E1000_SWSM      = 0x05B50, /* SW Semaphore */
	E1000_SWSM      = 0x05B50, /* SW Semaphore */
	E1000_FWSM      = 0x05B54, /* FW Semaphore */
	E1000_FWSM      = 0x05B54, /* FW Semaphore */
	E1000_SWSM2     = 0x05B58, /* Driver-only SW semaphore */
	E1000_SWSM2     = 0x05B58, /* Driver-only SW semaphore */
	E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */
	E1000_FFLT_DBG  = 0x05F04, /* Debug Register */
	E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */
#define E1000_PCH_RAICC(_n)	(E1000_PCH_RAICC_BASE + ((_n) * 4))
#define E1000_CRC_OFFSET	E1000_PCH_RAICC_BASE
	E1000_HICR      = 0x08F00, /* Host Interface Control */
	E1000_HICR      = 0x08F00, /* Host Interface Control */
};
};


@@ -303,13 +306,14 @@ enum e1e_registers {
#define E1000_KMRNCTRLSTA_OFFSET	0x001F0000
#define E1000_KMRNCTRLSTA_OFFSET	0x001F0000
#define E1000_KMRNCTRLSTA_OFFSET_SHIFT	16
#define E1000_KMRNCTRLSTA_OFFSET_SHIFT	16
#define E1000_KMRNCTRLSTA_REN		0x00200000
#define E1000_KMRNCTRLSTA_REN		0x00200000
#define E1000_KMRNCTRLSTA_CTRL_OFFSET	0x1    /* Kumeran Control */
#define E1000_KMRNCTRLSTA_DIAG_OFFSET	0x3    /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_DIAG_OFFSET	0x3    /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS	0x4    /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_TIMEOUTS	0x4    /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM	0x9    /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_INBAND_PARAM	0x9    /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK	0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK	0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG	0x7
#define E1000_KMRNCTRLSTA_K1_CONFIG	0x7
#define E1000_KMRNCTRLSTA_K1_ENABLE	0x140E
#define E1000_KMRNCTRLSTA_K1_ENABLE	0x140E
#define E1000_KMRNCTRLSTA_K1_DISABLE	0x1400
#define E1000_KMRNCTRLSTA_HD_CTRL	0x0002


#define IFE_PHY_EXTENDED_STATUS_CONTROL	0x10
#define IFE_PHY_EXTENDED_STATUS_CONTROL	0x10
#define IFE_PHY_SPECIAL_CONTROL		0x11 /* 100BaseTx PHY Special Control */
#define IFE_PHY_SPECIAL_CONTROL		0x11 /* 100BaseTx PHY Special Control */
@@ -387,6 +391,8 @@ enum e1e_registers {
#define E1000_DEV_ID_PCH_M_HV_LC		0x10EB
#define E1000_DEV_ID_PCH_M_HV_LC		0x10EB
#define E1000_DEV_ID_PCH_D_HV_DM		0x10EF
#define E1000_DEV_ID_PCH_D_HV_DM		0x10EF
#define E1000_DEV_ID_PCH_D_HV_DC		0x10F0
#define E1000_DEV_ID_PCH_D_HV_DC		0x10F0
#define E1000_DEV_ID_PCH2_LV_LM			0x1502
#define E1000_DEV_ID_PCH2_LV_V			0x1503


#define E1000_REVISION_4 4
#define E1000_REVISION_4 4


@@ -406,6 +412,7 @@ enum e1000_mac_type {
	e1000_ich9lan,
	e1000_ich9lan,
	e1000_ich10lan,
	e1000_ich10lan,
	e1000_pchlan,
	e1000_pchlan,
	e1000_pch2lan,
};
};


enum e1000_media_type {
enum e1000_media_type {
@@ -442,6 +449,7 @@ enum e1000_phy_type {
	e1000_phy_bm,
	e1000_phy_bm,
	e1000_phy_82578,
	e1000_phy_82578,
	e1000_phy_82577,
	e1000_phy_82577,
	e1000_phy_82579,
};
};


enum e1000_bus_width {
enum e1000_bus_width {
+311 −17
Original line number Original line Diff line number Diff line
@@ -52,6 +52,8 @@
 * 82577LC Gigabit Network Connection
 * 82577LC Gigabit Network Connection
 * 82578DM Gigabit Network Connection
 * 82578DM Gigabit Network Connection
 * 82578DC Gigabit Network Connection
 * 82578DC Gigabit Network Connection
 * 82579LM Gigabit Network Connection
 * 82579V Gigabit Network Connection
 */
 */


#include "e1000.h"
#include "e1000.h"
@@ -126,6 +128,9 @@
#define HV_SMB_ADDR_PEC_EN     0x0200
#define HV_SMB_ADDR_PEC_EN     0x0200
#define HV_SMB_ADDR_VALID      0x0080
#define HV_SMB_ADDR_VALID      0x0080


/* PHY Power Management Control */
#define HV_PM_CTRL		PHY_REG(770, 17)

/* Strapping Option Register - RO */
/* Strapping Option Register - RO */
#define E1000_STRAP                     0x0000C
#define E1000_STRAP                     0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK  0x00FE0000
#define E1000_STRAP_SMBUS_ADDRESS_MASK  0x00FE0000
@@ -279,13 +284,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
	phy->ops.power_down           = e1000_power_down_phy_copper_ich8lan;
	phy->ops.power_down           = e1000_power_down_phy_copper_ich8lan;
	phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
	phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;


	if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
	/*
	/*
	 * The MAC-PHY interconnect may still be in SMBus mode
	 * The MAC-PHY interconnect may still be in SMBus mode
		 * after Sx->S0.  Toggle the LANPHYPC Value bit to force
	 * after Sx->S0.  If the manageability engine (ME) is
		 * the interconnect to PCIe mode, but only if there is no
	 * disabled, then toggle the LANPHYPC Value bit to force
		 * firmware present otherwise firmware will have done it.
	 * the interconnect to PCIe mode.
	 */
	 */
	if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
		ctrl = er32(CTRL);
		ctrl = er32(CTRL);
		ctrl |=  E1000_CTRL_LANPHYPC_OVERRIDE;
		ctrl |=  E1000_CTRL_LANPHYPC_OVERRIDE;
		ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
		ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
@@ -326,6 +331,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)


	switch (phy->type) {
	switch (phy->type) {
	case e1000_phy_82577:
	case e1000_phy_82577:
	case e1000_phy_82579:
		phy->ops.check_polarity = e1000_check_polarity_82577;
		phy->ops.check_polarity = e1000_check_polarity_82577;
		phy->ops.force_speed_duplex =
		phy->ops.force_speed_duplex =
			e1000_phy_force_speed_duplex_82577;
			e1000_phy_force_speed_duplex_82577;
@@ -530,6 +536,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
		mac->ops.led_off = e1000_led_off_ich8lan;
		mac->ops.led_off = e1000_led_off_ich8lan;
		break;
		break;
	case e1000_pchlan:
	case e1000_pchlan:
	case e1000_pch2lan:
		/* check management mode */
		/* check management mode */
		mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
		mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
		/* ID LED init */
		/* ID LED init */
@@ -550,6 +557,14 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
	if (mac->type == e1000_ich8lan)
	if (mac->type == e1000_ich8lan)
		e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
		e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);


	/* Disable PHY configuration by hardware, config by software */
	if (mac->type == e1000_pch2lan) {
		u32 extcnf_ctrl = er32(EXTCNF_CTRL);

		extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
		ew32(EXTCNF_CTRL, extcnf_ctrl);
	}

	return 0;
	return 0;
}
}


@@ -653,10 +668,19 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
	if (rc)
	if (rc)
		return rc;
		return rc;


	if (hw->mac.type == e1000_pchlan)
	switch (hw->mac.type) {
		rc = e1000_init_phy_params_pchlan(hw);
	case e1000_ich8lan:
	else
	case e1000_ich9lan:
	case e1000_ich10lan:
		rc = e1000_init_phy_params_ich8lan(hw);
		rc = e1000_init_phy_params_ich8lan(hw);
		break;
	case e1000_pchlan:
	case e1000_pch2lan:
		rc = e1000_init_phy_params_pchlan(hw);
		break;
	default:
		break;
	}
	if (rc)
	if (rc)
		return rc;
		return rc;


@@ -861,6 +885,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
		}
		}
		/* Fall-thru */
		/* Fall-thru */
	case e1000_pchlan:
	case e1000_pchlan:
	case e1000_pch2lan:
		sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
		sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
		break;
		break;
	default:
	default:
@@ -880,8 +905,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
	 * extended configuration before SW configuration
	 * extended configuration before SW configuration
	 */
	 */
	data = er32(EXTCNF_CTRL);
	data = er32(EXTCNF_CTRL);
	if (!(hw->mac.type == e1000_pch2lan)) {
		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
			goto out;
			goto out;
	}


	cnf_size = er32(EXTCNF_SIZE);
	cnf_size = er32(EXTCNF_SIZE);
	cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
	cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
@@ -893,7 +920,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
	cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
	cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;


	if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
	if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
	    (hw->mac.type == e1000_pchlan)) {
	    ((hw->mac.type == e1000_pchlan) ||
	     (hw->mac.type == e1000_pch2lan))) {
		/*
		/*
		 * HW configures the SMBus address and LEDs when the
		 * HW configures the SMBus address and LEDs when the
		 * OEM and LCD Write Enable bits are set in the NVM.
		 * OEM and LCD Write Enable bits are set in the NVM.
@@ -1100,16 +1128,18 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
	u32 mac_reg;
	u32 mac_reg;
	u16 oem_reg;
	u16 oem_reg;


	if (hw->mac.type != e1000_pchlan)
	if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
		return ret_val;
		return ret_val;


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


	if (!(hw->mac.type == e1000_pch2lan)) {
		mac_reg = er32(EXTCNF_CTRL);
		mac_reg = er32(EXTCNF_CTRL);
		if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
		if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
			goto out;
			goto out;
	}


	mac_reg = er32(FEXTNVM);
	mac_reg = er32(FEXTNVM);
	if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
	if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
@@ -1249,6 +1279,243 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
	return ret_val;
	return ret_val;
}
}


/**
 *  e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY
 *  @hw:   pointer to the HW structure
 **/
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
{
	u32 mac_reg;
	u16 i;

	/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
	for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
		mac_reg = er32(RAL(i));
		e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
		e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
		mac_reg = er32(RAH(i));
		e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
		e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
	}
}

static u32 e1000_calc_rx_da_crc(u8 mac[])
{
	u32 poly = 0xEDB88320;	/* Polynomial for 802.3 CRC calculation */
	u32 i, j, mask, crc;

	crc = 0xffffffff;
	for (i = 0; i < 6; i++) {
		crc = crc ^ mac[i];
		for (j = 8; j > 0; j--) {
			mask = (crc & 1) * (-1);
			crc = (crc >> 1) ^ (poly & mask);
		}
	}
	return ~crc;
}

/**
 *  e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation
 *  with 82579 PHY
 *  @hw: pointer to the HW structure
 *  @enable: flag to enable/disable workaround when enabling/disabling jumbos
 **/
s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
{
	s32 ret_val = 0;
	u16 phy_reg, data;
	u32 mac_reg;
	u16 i;

	if (hw->mac.type != e1000_pch2lan)
		goto out;

	/* disable Rx path while enabling/disabling workaround */
	e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
	ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14));
	if (ret_val)
		goto out;

	if (enable) {
		/*
		 * Write Rx addresses (rar_entry_count for RAL/H, +4 for
		 * SHRAL/H) and initial CRC values to the MAC
		 */
		for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
			u8 mac_addr[ETH_ALEN] = {0};
			u32 addr_high, addr_low;

			addr_high = er32(RAH(i));
			if (!(addr_high & E1000_RAH_AV))
				continue;
			addr_low = er32(RAL(i));
			mac_addr[0] = (addr_low & 0xFF);
			mac_addr[1] = ((addr_low >> 8) & 0xFF);
			mac_addr[2] = ((addr_low >> 16) & 0xFF);
			mac_addr[3] = ((addr_low >> 24) & 0xFF);
			mac_addr[4] = (addr_high & 0xFF);
			mac_addr[5] = ((addr_high >> 8) & 0xFF);

			ew32(PCH_RAICC(i),
					e1000_calc_rx_da_crc(mac_addr));
		}

		/* Write Rx addresses to the PHY */
		e1000_copy_rx_addrs_to_phy_ich8lan(hw);

		/* Enable jumbo frame workaround in the MAC */
		mac_reg = er32(FFLT_DBG);
		mac_reg &= ~(1 << 14);
		mac_reg |= (7 << 15);
		ew32(FFLT_DBG, mac_reg);

		mac_reg = er32(RCTL);
		mac_reg |= E1000_RCTL_SECRC;
		ew32(RCTL, mac_reg);

		ret_val = e1000e_read_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_CTRL_OFFSET,
						&data);
		if (ret_val)
			goto out;
		ret_val = e1000e_write_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_CTRL_OFFSET,
						data | (1 << 0));
		if (ret_val)
			goto out;
		ret_val = e1000e_read_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_HD_CTRL,
						&data);
		if (ret_val)
			goto out;
		data &= ~(0xF << 8);
		data |= (0xB << 8);
		ret_val = e1000e_write_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_HD_CTRL,
						data);
		if (ret_val)
			goto out;

		/* Enable jumbo frame workaround in the PHY */
		e1e_rphy(hw, PHY_REG(769, 20), &data);
		ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
		if (ret_val)
			goto out;
		e1e_rphy(hw, PHY_REG(769, 23), &data);
		data &= ~(0x7F << 5);
		data |= (0x37 << 5);
		ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
		if (ret_val)
			goto out;
		e1e_rphy(hw, PHY_REG(769, 16), &data);
		data &= ~(1 << 13);
		data |= (1 << 12);
		ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
		if (ret_val)
			goto out;
		e1e_rphy(hw, PHY_REG(776, 20), &data);
		data &= ~(0x3FF << 2);
		data |= (0x1A << 2);
		ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
		if (ret_val)
			goto out;
		ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xFE00);
		if (ret_val)
			goto out;
		e1e_rphy(hw, HV_PM_CTRL, &data);
		ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10));
		if (ret_val)
			goto out;
	} else {
		/* Write MAC register values back to h/w defaults */
		mac_reg = er32(FFLT_DBG);
		mac_reg &= ~(0xF << 14);
		ew32(FFLT_DBG, mac_reg);

		mac_reg = er32(RCTL);
		mac_reg &= ~E1000_RCTL_SECRC;
		ew32(FFLT_DBG, mac_reg);

		ret_val = e1000e_read_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_CTRL_OFFSET,
						&data);
		if (ret_val)
			goto out;
		ret_val = e1000e_write_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_CTRL_OFFSET,
						data & ~(1 << 0));
		if (ret_val)
			goto out;
		ret_val = e1000e_read_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_HD_CTRL,
						&data);
		if (ret_val)
			goto out;
		data &= ~(0xF << 8);
		data |= (0xB << 8);
		ret_val = e1000e_write_kmrn_reg(hw,
						E1000_KMRNCTRLSTA_HD_CTRL,
						data);
		if (ret_val)
			goto out;

		/* Write PHY register values back to h/w defaults */
		e1e_rphy(hw, PHY_REG(769, 20), &data);
		ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
		if (ret_val)
			goto out;
		e1e_rphy(hw, PHY_REG(769, 23), &data);
		data &= ~(0x7F << 5);
		ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
		if (ret_val)
			goto out;
		e1e_rphy(hw, PHY_REG(769, 16), &data);
		data &= ~(1 << 12);
		data |= (1 << 13);
		ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
		if (ret_val)
			goto out;
		e1e_rphy(hw, PHY_REG(776, 20), &data);
		data &= ~(0x3FF << 2);
		data |= (0x8 << 2);
		ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
		if (ret_val)
			goto out;
		ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00);
		if (ret_val)
			goto out;
		e1e_rphy(hw, HV_PM_CTRL, &data);
		ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10));
		if (ret_val)
			goto out;
	}

	/* re-enable Rx path after enabling/disabling workaround */
	ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14));

out:
	return ret_val;
}

/**
 *  e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be
 *  done after every PHY reset.
 **/
static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
{
	s32 ret_val = 0;

	if (hw->mac.type != e1000_pch2lan)
		goto out;

	/* Set MDIO slow mode before any other MDIO access */
	ret_val = e1000_set_mdio_slow_mode_hv(hw);

out:
	return ret_val;
}

/**
/**
 *  e1000_lan_init_done_ich8lan - Check for PHY config completion
 *  e1000_lan_init_done_ich8lan - Check for PHY config completion
 *  @hw: pointer to the HW structure
 *  @hw: pointer to the HW structure
@@ -1300,12 +1567,17 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
		if (ret_val)
		if (ret_val)
			goto out;
			goto out;
		break;
		break;
	case e1000_pch2lan:
		ret_val = e1000_lv_phy_workarounds_ich8lan(hw);
		if (ret_val)
			goto out;
		break;
	default:
	default:
		break;
		break;
	}
	}


	/* Dummy read to clear the phy wakeup bit after lcd reset */
	/* Dummy read to clear the phy wakeup bit after lcd reset */
	if (hw->mac.type == e1000_pchlan)
	if (hw->mac.type >= e1000_pchlan)
		e1e_rphy(hw, BM_WUC, &reg);
		e1e_rphy(hw, BM_WUC, &reg);


	/* Configure the LCD with the extended configuration region in NVM */
	/* Configure the LCD with the extended configuration region in NVM */
@@ -2829,6 +3101,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)


	ew32(FCTTV, hw->fc.pause_time);
	ew32(FCTTV, hw->fc.pause_time);
	if ((hw->phy.type == e1000_phy_82578) ||
	if ((hw->phy.type == e1000_phy_82578) ||
	    (hw->phy.type == e1000_phy_82579) ||
	    (hw->phy.type == e1000_phy_82577)) {
	    (hw->phy.type == e1000_phy_82577)) {
		ew32(FCRTV_PCH, hw->fc.refresh_time);
		ew32(FCRTV_PCH, hw->fc.refresh_time);


@@ -2892,6 +3165,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
			return ret_val;
			return ret_val;
		break;
		break;
	case e1000_phy_82577:
	case e1000_phy_82577:
	case e1000_phy_82579:
		ret_val = e1000_copper_link_setup_82577(hw);
		ret_val = e1000_copper_link_setup_82577(hw);
		if (ret_val)
		if (ret_val)
			return ret_val;
			return ret_val;
@@ -3399,6 +3673,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)


	/* Clear PHY statistics registers */
	/* Clear PHY statistics registers */
	if ((hw->phy.type == e1000_phy_82578) ||
	if ((hw->phy.type == e1000_phy_82578) ||
	    (hw->phy.type == e1000_phy_82579) ||
	    (hw->phy.type == e1000_phy_82577)) {
	    (hw->phy.type == e1000_phy_82577)) {
		hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data);
		hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data);
		hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data);
		hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data);
@@ -3534,3 +3809,22 @@ struct e1000_info e1000_pch_info = {
	.phy_ops		= &ich8_phy_ops,
	.phy_ops		= &ich8_phy_ops,
	.nvm_ops		= &ich8_nvm_ops,
	.nvm_ops		= &ich8_nvm_ops,
};
};

struct e1000_info e1000_pch2_info = {
	.mac			= e1000_pch2lan,
	.flags			= FLAG_IS_ICH
				  | FLAG_HAS_WOL
				  | FLAG_RX_CSUM_ENABLED
				  | FLAG_HAS_CTRLEXT_ON_LOAD
				  | FLAG_HAS_AMT
				  | FLAG_HAS_FLASH
				  | FLAG_HAS_JUMBO_FRAMES
				  | FLAG_APME_IN_WUC,
	.flags2			= FLAG2_HAS_PHY_STATS,
	.pba			= 18,
	.max_hw_frame_size	= DEFAULT_JUMBO,
	.get_variants		= e1000_get_variants_ich8lan,
	.mac_ops		= &ich8_mac_ops,
	.phy_ops		= &ich8_phy_ops,
	.nvm_ops		= &ich8_nvm_ops,
};
Loading