support 82567LM-3 Gigabit Network devices
authorS.Çağlar Onur <caglar@cs.princeton.edu>
Thu, 6 May 2010 03:01:26 +0000 (03:01 +0000)
committerS.Çağlar Onur <caglar@cs.princeton.edu>
Thu, 6 May 2010 03:01:26 +0000 (03:01 +0000)
kernel-2.6.spec
linux-2.6-010-e1000e-ich10lan.patch [new file with mode: 0644]

index 579bc6a..9cdf064 100644 (file)
@@ -145,6 +145,8 @@ Source30: %{kernelconfig}-%{kversion}-i686-xenU.config
 Patch000: ftp://ftp.kernel.org/pub/linux/kernel/v2.6/patch-%{rpmversion}.bz2
 %endif
 
+Patch010: linux-2.6-010-e1000e-ich10lan.patch
+
 Patch100: linux-2.6-100-build-nonintconfig.patch
 
 # Linux-VServer
@@ -348,6 +350,8 @@ KERNEL_PREVIOUS=vanilla
 %ApplyPatch 0
 %endif
 
+%ApplyPatch 010
+
 %ApplyPatch 100
 
 # vserver patch
diff --git a/linux-2.6-010-e1000e-ich10lan.patch b/linux-2.6-010-e1000e-ich10lan.patch
new file mode 100644 (file)
index 0000000..dd3ff79
--- /dev/null
@@ -0,0 +1,505 @@
+diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
+index 14b0e6c..4b21fa9 100644
+--- a/drivers/net/e1000e/defines.h
++++ b/drivers/net/e1000e/defines.h
+@@ -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
+diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
+index 4ee3d97..d5f8e8a 100644
+--- a/drivers/net/e1000e/e1000.h
++++ b/drivers/net/e1000e/e1000.h
+@@ -98,6 +98,7 @@ enum e1000_boards {
+       board_80003es2lan,
+       board_ich8lan,
+       board_ich9lan,
++      board_ich10lan,
+ };
+ struct e1000_queue_stats {
+@@ -381,6 +382,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);
+@@ -454,6 +456,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);
+diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
+index e2a30dd..5b7e6b5 100644
+--- a/drivers/net/e1000e/ethtool.c
++++ b/drivers/net/e1000e/ethtool.c
+@@ -788,6 +788,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:
+@@ -840,7 +841,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);
+@@ -912,12 +915,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
+diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
+index 74f263a..3005394 100644
+--- a/drivers/net/e1000e/hw.h
++++ b/drivers/net/e1000e/hw.h
+@@ -356,6 +356,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
+@@ -366,6 +368,7 @@ enum e1000_mac_type {
+       e1000_80003es2lan,
+       e1000_ich8lan,
+       e1000_ich9lan,
++      e1000_ich10lan,
+ };
+ enum e1000_media_type {
+diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
+index 79be768..d2acf48 100644
+--- a/drivers/net/e1000e/ich8lan.c
++++ b/drivers/net/e1000e/ich8lan.c
+@@ -171,12 +171,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)
+ {
+@@ -928,6 +931,56 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
+ }
+ /**
++ *  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
+  *  @offset: The offset (in bytes) of the word(s) to read.
+@@ -943,6 +996,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) ||
+@@ -955,10 +1009,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++) {
+@@ -1106,6 +1161,29 @@ static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
+ }
+ /**
++ *  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
+  *  @offset: The offset (in bytes) of the byte or word to read.
+@@ -1236,7 +1314,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;
+@@ -1256,7 +1334,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);
+@@ -2272,13 +2354,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;
+@@ -2336,6 +2419,39 @@ static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
+ }
+ /**
++ *  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
+  *
+@@ -2385,7 +2501,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,
+@@ -2440,3 +2556,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,
++};
+diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
+index c476982..c4287ca 100644
+--- a/drivers/net/e1000e/netdev.c
++++ b/drivers/net/e1000e/netdev.c
+@@ -58,6 +58,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
+       [board_80003es2lan]     = &e1000_es2_info,
+       [board_ich8lan]         = &e1000_ich8_info,
+       [board_ich9lan]         = &e1000_ich9_info,
++      [board_ich10lan]        = &e1000_ich10_info,
+ };
+ #ifdef DEBUG
+@@ -3211,6 +3212,27 @@ static void e1000_watchdog_task(struct work_struct *work)
+                                                  &adapter->link_duplex);
+                       e1000_print_link_info(adapter);
+                       /*
++                       * On supported PHYs, check for duplex mismatch only
++                       * if link has autonegotiated at 10/100 half
++                       */
++                      if ((hw->phy.type == e1000_phy_igp_3 ||
++                           hw->phy.type == e1000_phy_bm) &&
++                          (hw->mac.autoneg == true) &&
++                          (adapter->link_speed == SPEED_10 ||
++                           adapter->link_speed == SPEED_100) &&
++                          (adapter->link_duplex == HALF_DUPLEX)) {
++                              u16 autoneg_exp;
++
++                              e1e_rphy(hw, PHY_AUTONEG_EXP, &autoneg_exp);
++
++                              if (!(autoneg_exp & NWAY_ER_LP_NWAY_CAPS))
++                                      e_info("Autonegotiated half duplex but"
++                                             " link partner cannot autoneg. "
++                                             " Try forcing full duplex if "
++                                             "link gets many collisions.\n");
++                      }
++
++                      /*
+                        * tweak tx_queue_len according to speed/duplex
+                        * and adjust the timeout factor
+                        */
+@@ -4793,6 +4815,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan },
+       { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_V), board_ich9lan },
++      { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan },
++      { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan },
++
+       { }     /* terminate list */
+ };
+ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
+diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
+index b133dcf..16724f8 100644
+--- a/drivers/net/e1000e/phy.c
++++ b/drivers/net/e1000e/phy.c
+@@ -1720,6 +1720,91 @@ s32 e1000e_get_cfg_done(struct e1000_hw *hw)
+       return 0;
+ }
++/**
++ *  e1000e_phy_init_script_igp3 - Inits the IGP3 PHY
++ *  @hw: pointer to the HW structure
++ *
++ *  Initializes a Intel Gigabit PHY3 when an EEPROM is not present.
++ **/
++s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw)
++{
++      hw_dbg(hw, "Running IGP 3 PHY init script\n");
++
++      /* PHY init IGP 3 */
++      /* Enable rise/fall, 10-mode work in class-A */
++      e1e_wphy(hw, 0x2F5B, 0x9018);
++      /* Remove all caps from Replica path filter */
++      e1e_wphy(hw, 0x2F52, 0x0000);
++      /* Bias trimming for ADC, AFE and Driver (Default) */
++      e1e_wphy(hw, 0x2FB1, 0x8B24);
++      /* Increase Hybrid poly bias */
++      e1e_wphy(hw, 0x2FB2, 0xF8F0);
++      /* Add 4% to Tx amplitude in Gig mode */
++      e1e_wphy(hw, 0x2010, 0x10B0);
++      /* Disable trimming (TTT) */
++      e1e_wphy(hw, 0x2011, 0x0000);
++      /* Poly DC correction to 94.6% + 2% for all channels */
++      e1e_wphy(hw, 0x20DD, 0x249A);
++      /* ABS DC correction to 95.9% */
++      e1e_wphy(hw, 0x20DE, 0x00D3);
++      /* BG temp curve trim */
++      e1e_wphy(hw, 0x28B4, 0x04CE);
++      /* Increasing ADC OPAMP stage 1 currents to max */
++      e1e_wphy(hw, 0x2F70, 0x29E4);
++      /* Force 1000 ( required for enabling PHY regs configuration) */
++      e1e_wphy(hw, 0x0000, 0x0140);
++      /* Set upd_freq to 6 */
++      e1e_wphy(hw, 0x1F30, 0x1606);
++      /* Disable NPDFE */
++      e1e_wphy(hw, 0x1F31, 0xB814);
++      /* Disable adaptive fixed FFE (Default) */
++      e1e_wphy(hw, 0x1F35, 0x002A);
++      /* Enable FFE hysteresis */
++      e1e_wphy(hw, 0x1F3E, 0x0067);
++      /* Fixed FFE for short cable lengths */
++      e1e_wphy(hw, 0x1F54, 0x0065);
++      /* Fixed FFE for medium cable lengths */
++      e1e_wphy(hw, 0x1F55, 0x002A);
++      /* Fixed FFE for long cable lengths */
++      e1e_wphy(hw, 0x1F56, 0x002A);
++      /* Enable Adaptive Clip Threshold */
++      e1e_wphy(hw, 0x1F72, 0x3FB0);
++      /* AHT reset limit to 1 */
++      e1e_wphy(hw, 0x1F76, 0xC0FF);
++      /* Set AHT master delay to 127 msec */
++      e1e_wphy(hw, 0x1F77, 0x1DEC);
++      /* Set scan bits for AHT */
++      e1e_wphy(hw, 0x1F78, 0xF9EF);
++      /* Set AHT Preset bits */
++      e1e_wphy(hw, 0x1F79, 0x0210);
++      /* Change integ_factor of channel A to 3 */
++      e1e_wphy(hw, 0x1895, 0x0003);
++      /* Change prop_factor of channels BCD to 8 */
++      e1e_wphy(hw, 0x1796, 0x0008);
++      /* Change cg_icount + enable integbp for channels BCD */
++      e1e_wphy(hw, 0x1798, 0xD008);
++      /*
++       * Change cg_icount + enable integbp + change prop_factor_master
++       * to 8 for channel A
++       */
++      e1e_wphy(hw, 0x1898, 0xD918);
++      /* Disable AHT in Slave mode on channel A */
++      e1e_wphy(hw, 0x187A, 0x0800);
++      /*
++       * Enable LPLU and disable AN to 1000 in non-D0a states,
++       * Enable SPD+B2B
++       */
++      e1e_wphy(hw, 0x0019, 0x008D);
++      /* Enable restart AN on an1000_dis change */
++      e1e_wphy(hw, 0x001B, 0x2080);
++      /* Enable wh_fifo read clock in 10/100 modes */
++      e1e_wphy(hw, 0x0014, 0x0045);
++      /* Restart AN, Speed selection is 1000 */
++      e1e_wphy(hw, 0x0000, 0x1340);
++
++      return 0;
++}
++
+ /* Internal function pointers */
+ /**