Commit f4187b56 authored by Bruce Allan's avatar Bruce Allan Committed by Jeff Garzik
Browse files

e1000e: add support for 82567LM-3 and 82567LF-3 (ICH10D) parts



Add support for new LOM devices on the latest generation ICHx platforms.

Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent 2f15f9d6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -505,6 +505,7 @@
#define NWAY_LPAR_ASM_DIR        0x0800 /* LP Asymmetric Pause Direction bit */

/* Autoneg Expansion Register */
#define NWAY_ER_LP_NWAY_CAPS     0x0001 /* LP has Auto Neg Capability */

/* 1000BASE-T Control Register */
#define CR_1000T_HD_CAPS         0x0100 /* Advertise 1000T HD capability */
@@ -540,6 +541,7 @@
#define E1000_EECD_DO        0x00000008 /* NVM Data Out */
#define E1000_EECD_REQ       0x00000040 /* NVM Access Request */
#define E1000_EECD_GNT       0x00000080 /* NVM Access Grant */
#define E1000_EECD_PRES      0x00000100 /* NVM Present */
#define E1000_EECD_SIZE      0x00000200 /* NVM Size (0=64 word 1=256 word) */
/* NVM Addressing bits based on type (0-small, 1-large) */
#define E1000_EECD_ADDR_BITS 0x00000400
+3 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ enum e1000_boards {
	board_80003es2lan,
	board_ich8lan,
	board_ich9lan,
	board_ich10lan,
};

struct e1000_queue_stats {
@@ -374,6 +375,7 @@ extern struct e1000_info e1000_82572_info;
extern struct e1000_info e1000_82573_info;
extern struct e1000_info e1000_ich8_info;
extern struct e1000_info e1000_ich9_info;
extern struct e1000_info e1000_ich10_info;
extern struct e1000_info e1000_es2_info;

extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
@@ -446,6 +448,7 @@ extern s32 e1000e_get_cable_length_m88(struct e1000_hw *hw);
extern s32 e1000e_get_phy_info_m88(struct e1000_hw *hw);
extern s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw);
extern enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id);
extern s32 e1000e_determine_phy_address(struct e1000_hw *hw);
extern s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
+18 −4
Original line number Diff line number Diff line
@@ -781,6 +781,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
	case e1000_82573:
	case e1000_ich8lan:
	case e1000_ich9lan:
	case e1000_ich10lan:
		toggle = 0x7FFFF033;
		break;
	default:
@@ -833,7 +834,9 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
	REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF);
	for (i = 0; i < mac->rar_entry_count; i++)
		REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1),
				       0x8003FFFF, 0xFFFFFFFF);
				       ((mac->type == e1000_ich10lan) ?
					   0x8007FFFF : 0x8003FFFF),
				       0xFFFFFFFF);

	for (i = 0; i < mac->mta_reg_count; i++)
		REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF);
@@ -905,12 +908,23 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)

	/* Test each interrupt */
	for (i = 0; i < 10; i++) {
		if ((adapter->flags & FLAG_IS_ICH) && (i == 8))
			continue;

		/* Interrupt to test */
		mask = 1 << i;

		if (adapter->flags & FLAG_IS_ICH) {
			switch (mask) {
			case E1000_ICR_RXSEQ:
				continue;
			case 0x00000100:
				if (adapter->hw.mac.type == e1000_ich8lan ||
				    adapter->hw.mac.type == e1000_ich9lan)
					continue;
				break;
			default:
				break;
			}
		}

		if (!shared_int) {
			/*
			 * Disable the interrupt to be reported in
+3 −0
Original line number Diff line number Diff line
@@ -357,6 +357,8 @@ enum e1e_registers {
#define E1000_DEV_ID_ICH10_R_BM_LM		0x10CC
#define E1000_DEV_ID_ICH10_R_BM_LF		0x10CD
#define E1000_DEV_ID_ICH10_R_BM_V		0x10CE
#define E1000_DEV_ID_ICH10_D_BM_LM		0x10DE
#define E1000_DEV_ID_ICH10_D_BM_LF		0x10DF

#define E1000_FUNC_1 1

@@ -367,6 +369,7 @@ enum e1000_mac_type {
	e1000_80003es2lan,
	e1000_ich8lan,
	e1000_ich9lan,
	e1000_ich10lan,
};

enum e1000_media_type {
+144 −10
Original line number Diff line number Diff line
@@ -43,7 +43,8 @@
 * 82567LM-2 Gigabit Network Connection
 * 82567LF-2 Gigabit Network Connection
 * 82567V-2 Gigabit Network Connection
 * 82562GT-3 10/100 Network Connection
 * 82567LF-3 Gigabit Network Connection
 * 82567LM-3 Gigabit Network Connection
 * 82567LM-4 Gigabit Network Connection
 */

@@ -158,12 +159,15 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw);
static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
						u32 offset, u8 byte);
static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
					 u8 *data);
static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
					 u16 *data);
static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
					 u8 size, u16 *data);
static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);

static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
{
@@ -897,6 +901,56 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
	return 0;
}

/**
 *  e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1
 *  @hw: pointer to the HW structure
 *  @bank:  pointer to the variable that returns the active bank
 *
 *  Reads signature byte from the NVM using the flash access registers.
 **/
static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
{
	struct e1000_nvm_info *nvm = &hw->nvm;
	/* flash bank size is in words */
	u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
	u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
	u8 bank_high_byte = 0;

	if (hw->mac.type != e1000_ich10lan) {
		if (er32(EECD) & E1000_EECD_SEC1VAL)
			*bank = 1;
		else
			*bank = 0;
	} else {
		/*
		 * Make sure the signature for bank 0 is valid,
		 * if not check for bank1
		 */
		e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte);
		if ((bank_high_byte & 0xC0) == 0x80) {
			*bank = 0;
		} else {
			/*
			 * find if segment 1 is valid by verifying
			 * bit 15:14 = 10b in word 0x13
			 */
			e1000_read_flash_byte_ich8lan(hw,
						      act_offset + bank1_offset,
						      &bank_high_byte);

			/* bank1 has a valid signature equivalent to SEC1V */
			if ((bank_high_byte & 0xC0) == 0x80) {
				*bank = 1;
			} else {
				hw_dbg(hw, "ERROR: EEPROM not present\n");
				return -E1000_ERR_NVM;
			}
		}
	}

	return 0;
}

/**
 *  e1000_read_nvm_ich8lan - Read word(s) from the NVM
 *  @hw: pointer to the HW structure
@@ -913,6 +967,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
	u32 act_offset;
	s32 ret_val;
	u32 bank = 0;
	u16 i, word;

	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
@@ -925,10 +980,11 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
	if (ret_val)
		return ret_val;

	/* Start with the bank offset, then add the relative offset. */
	act_offset = (er32(EECD) & E1000_EECD_SEC1VAL)
		     ? nvm->flash_bank_size
		     : 0;
	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
	if (ret_val)
		return ret_val;

	act_offset = (bank) ? nvm->flash_bank_size : 0;
	act_offset += offset;

	for (i = 0; i < words; i++) {
@@ -1075,6 +1131,29 @@ static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
	return e1000_read_flash_data_ich8lan(hw, offset, 2, data);
}

/**
 *  e1000_read_flash_byte_ich8lan - Read byte from flash
 *  @hw: pointer to the HW structure
 *  @offset: The offset of the byte to read.
 *  @data: Pointer to a byte to store the value read.
 *
 *  Reads a single byte from the NVM using the flash access registers.
 **/
static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
					 u8 *data)
{
	s32 ret_val;
	u16 word = 0;

	ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
	if (ret_val)
		return ret_val;

	*data = (u8)word;

	return 0;
}

/**
 *  e1000_read_flash_data_ich8lan - Read byte or word from NVM
 *  @hw: pointer to the HW structure
@@ -1206,7 +1285,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
{
	struct e1000_nvm_info *nvm = &hw->nvm;
	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
	u32 i, act_offset, new_bank_offset, old_bank_offset;
	u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
	s32 ret_val;
	u16 data;

@@ -1226,7 +1305,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
	 * write to bank 0 etc.  We also need to erase the segment that
	 * is going to be written
	 */
	if (!(er32(EECD) & E1000_EECD_SEC1VAL)) {
	ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
	if (ret_val)
		return ret_val;

	if (bank == 0) {
		new_bank_offset = nvm->flash_bank_size;
		old_bank_offset = 0;
		e1000_erase_flash_bank_ich8lan(hw, 1);
@@ -2190,13 +2273,14 @@ void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
 *  'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
 *  to a lower speed.
 *
 *  Should only be called for ICH9 devices.
 *  Should only be called for ICH9 and ICH10 devices.
 **/
void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
{
	u32 phy_ctrl;

	if (hw->mac.type == e1000_ich9lan) {
	if ((hw->mac.type == e1000_ich10lan) ||
	    (hw->mac.type == e1000_ich9lan)) {
		phy_ctrl = er32(PHY_CTRL);
		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
		            E1000_PHY_CTRL_GBE_DISABLE;
@@ -2253,6 +2337,39 @@ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
	return 0;
}

/**
 *  e1000_get_cfg_done_ich8lan - Read config done bit
 *  @hw: pointer to the HW structure
 *
 *  Read the management control register for the config done bit for
 *  completion status.  NOTE: silicon which is EEPROM-less will fail trying
 *  to read the config done bit, so an error is *ONLY* logged and returns
 *  E1000_SUCCESS.  If we were to return with error, EEPROM-less silicon
 *  would not be able to be reset or change link.
 **/
static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
{
	u32 bank = 0;

	e1000e_get_cfg_done(hw);

	/* If EEPROM is not marked present, init the IGP 3 PHY manually */
	if (hw->mac.type != e1000_ich10lan) {
		if (((er32(EECD) & E1000_EECD_PRES) == 0) &&
		    (hw->phy.type == e1000_phy_igp_3)) {
			e1000e_phy_init_script_igp3(hw);
		}
	} else {
		if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
			/* Maybe we should do a basic PHY config */
			hw_dbg(hw, "EEPROM not present\n");
			return -E1000_ERR_CONFIG;
		}
	}

	return 0;
}

/**
 *  e1000_clear_hw_cntrs_ich8lan - Clear statistical counters
 *  @hw: pointer to the HW structure
@@ -2303,7 +2420,7 @@ static struct e1000_phy_operations ich8_phy_ops = {
	.check_reset_block	= e1000_check_reset_block_ich8lan,
	.commit_phy		= NULL,
	.force_speed_duplex	= e1000_phy_force_speed_duplex_ich8lan,
	.get_cfg_done		= e1000e_get_cfg_done,
	.get_cfg_done		= e1000_get_cfg_done_ich8lan,
	.get_cable_length	= e1000e_get_cable_length_igp_2,
	.get_phy_info		= e1000_get_phy_info_ich8lan,
	.read_phy_reg		= e1000e_read_phy_reg_igp,
@@ -2358,3 +2475,20 @@ struct e1000_info e1000_ich9_info = {
	.nvm_ops		= &ich8_nvm_ops,
};

struct e1000_info e1000_ich10_info = {
	.mac			= e1000_ich10lan,
	.flags			= FLAG_HAS_JUMBO_FRAMES
				  | FLAG_IS_ICH
				  | FLAG_HAS_WOL
				  | FLAG_RX_CSUM_ENABLED
				  | FLAG_HAS_CTRLEXT_ON_LOAD
				  | FLAG_HAS_AMT
				  | FLAG_HAS_ERT
				  | FLAG_HAS_FLASH
				  | FLAG_APME_IN_WUC,
	.pba			= 10,
	.get_variants		= e1000_get_variants_ich8lan,
	.mac_ops		= &ich8_mac_ops,
	.phy_ops		= &ich8_phy_ops,
	.nvm_ops		= &ich8_nvm_ops,
};
Loading