From d97755e69265e6afa030b4df92d218aa3d42c430 Mon Sep 17 00:00:00 2001 From: Ganesh Venkatesan Date: Tue, 13 Apr 2004 05:40:22 -0400 Subject: [PATCH] [PATCH] e1000: Set Attla PHY to Class A Some LOM implementation of our controllers pass IEEE tests (Tx distortion/Symmetry) while operating in Class A mode rather than in class AB mode. --- drivers/net/e1000/e1000_hw.c | 45 ++++++++++++++++++++++++++++++++++++ drivers/net/e1000/e1000_hw.h | 4 ++++ 2 files changed, 49 insertions(+) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 18e72beb7880d..cdf6b7eab9cd1 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -65,6 +65,7 @@ static void e1000_release_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); static int32_t e1000_id_led_init(struct e1000_hw * hw); static int32_t e1000_set_vco_speed(struct e1000_hw *hw); +static int32_t e1000_set_phy_mode(struct e1000_hw *hw); /* IGP cable length table */ static const @@ -899,6 +900,11 @@ e1000_setup_copper_link(struct e1000_hw *hw) } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); + /* Set PHY to class A mode (if necessary) */ + ret_val = e1000_set_phy_mode(hw); + if(ret_val) + return ret_val; + if(hw->mac_type <= e1000_82543 || hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) @@ -4905,6 +4911,45 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw, return E1000_SUCCESS; } +/***************************************************************************** + * Set PHY to class A mode + * Assumes the following operations will follow to enable the new class mode. + * 1. Do a PHY soft reset + * 2. Restart auto-negotiation or force link. + * + * hw - Struct containing variables accessed by shared code + ****************************************************************************/ +static int32_t +e1000_set_phy_mode(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t eeprom_data; + + DEBUGFUNC("e1000_set_phy_mode"); + + if((hw->mac_type == e1000_82545_rev_3) && + (hw->media_type == e1000_media_type_copper)) { + ret_val = e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, &eeprom_data); + if(ret_val) { + return ret_val; + } + + if((eeprom_data != EEPROM_RESERVED_WORD) && + (eeprom_data & EEPROM_PHY_CLASS_A)) { + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x000B); + if(ret_val) + return ret_val; + ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x8104); + if(ret_val) + return ret_val; + + hw->phy_reset_disable = FALSE; + } + } + + return E1000_SUCCESS; +} + /***************************************************************************** * * This function sets the lplu state according to the active flag. When diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index c2aaed1e6839f..4cdcf9b18785e 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1480,6 +1480,7 @@ struct e1000_hw { #define EEPROM_COMPAT 0x0003 #define EEPROM_ID_LED_SETTINGS 0x0004 #define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ +#define EEPROM_PHY_CLASS_WORD 0x0007 #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F #define EEPROM_INIT_CONTROL3_PORT_B 0x0014 @@ -1513,6 +1514,9 @@ struct e1000_hw { /* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */ #define EEPROM_SERDES_AMPLITUDE_MASK 0x000F +/* Mask bit for PHY class in Word 7 of the EEPROM */ +#define EEPROM_PHY_CLASS_A 0x8000 + /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 #define EEPROM_WORD0A_SWDPIO 0x01E0 -- 2.53.0