devices/e1000/e1000_hw-3.6-ethercat.c
author Edouard Tisserant <edouard.tisserant@gmail.com>
Fri, 14 Sep 2018 23:37:19 +0200
branchstable-1.5
changeset 2711 a5c4ccc02285
parent 2583 fe5687a0a322
permissions -rw-r--r--
Fixed rtdmnet.c PFX and removed useless commented code.
2545
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     1
/*******************************************************************************
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     2
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     3
  Intel PRO/1000 Linux driver
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     4
  Copyright(c) 1999 - 2006 Intel Corporation.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     5
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     6
  This program is free software; you can redistribute it and/or modify it
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     7
  under the terms and conditions of the GNU General Public License,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     8
  version 2, as published by the Free Software Foundation.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
     9
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    10
  This program is distributed in the hope it will be useful, but WITHOUT
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    11
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    12
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    13
  more details.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    14
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    15
  You should have received a copy of the GNU General Public License along with
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    16
  this program; if not, write to the Free Software Foundation, Inc.,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    17
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    18
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    19
  The full GNU General Public License is included in this distribution in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    20
  the file called "COPYING".
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    21
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    22
  Contact Information:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    23
  Linux NICS <linux.nics@intel.com>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    24
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    25
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    26
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    27
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    28
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    29
/* e1000_hw.c
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    30
 * Shared functions for accessing and configuring the MAC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    31
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    32
2583
fe5687a0a322 Fixed wrong version e1000 includes.
Florian Pose <fp@igh-essen.com>
parents: 2545
diff changeset
    33
#include "e1000-3.6-ethercat.h"
2545
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    34
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    35
static s32 e1000_check_downshift(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    36
static s32 e1000_check_polarity(struct e1000_hw *hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    37
				e1000_rev_polarity *polarity);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    38
static void e1000_clear_hw_cntrs(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    39
static void e1000_clear_vfta(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    40
static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    41
					      bool link_up);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    42
static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    43
static s32 e1000_detect_gig_phy(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    44
static s32 e1000_get_auto_rd_done(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    45
static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    46
				  u16 *max_length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    47
static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    48
static s32 e1000_id_led_init(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    49
static void e1000_init_rx_addrs(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    50
static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    51
				  struct e1000_phy_info *phy_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    52
static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    53
				  struct e1000_phy_info *phy_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    54
static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    55
static s32 e1000_wait_autoneg(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    56
static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    57
static s32 e1000_set_phy_type(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    58
static void e1000_phy_init_script(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    59
static s32 e1000_setup_copper_link(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    60
static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    61
static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    62
static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    63
static s32 e1000_config_mac_to_phy(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    64
static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    65
static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    66
static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    67
static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    68
static s32 e1000_phy_reset_dsp(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    69
static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    70
				  u16 words, u16 *data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    71
static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    72
					u16 words, u16 *data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    73
static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    74
static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    75
static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    76
static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    77
static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    78
				  u16 phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    79
static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    80
				 u16 *phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    81
static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    82
static s32 e1000_acquire_eeprom(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    83
static void e1000_release_eeprom(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    84
static void e1000_standby_eeprom(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    85
static s32 e1000_set_vco_speed(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    86
static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    87
static s32 e1000_set_phy_mode(struct e1000_hw *hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    88
static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    89
				u16 *data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    90
static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    91
				 u16 *data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    92
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    93
/* IGP cable length table */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    94
static const
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    95
u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    96
	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    97
	5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    98
	25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
    99
	40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   100
	60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   101
	90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   102
	    100,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   103
	100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   104
	    110, 110,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   105
	110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   106
	    120, 120
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   107
};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   108
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   109
static DEFINE_SPINLOCK(e1000_eeprom_lock);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   110
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   111
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   112
 * e1000_set_phy_type - Set the phy type member in the hw struct.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   113
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   114
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   115
static s32 e1000_set_phy_type(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   116
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   117
	e_dbg("e1000_set_phy_type");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   118
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   119
	if (hw->mac_type == e1000_undefined)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   120
		return -E1000_ERR_PHY_TYPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   121
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   122
	switch (hw->phy_id) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   123
	case M88E1000_E_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   124
	case M88E1000_I_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   125
	case M88E1011_I_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   126
	case M88E1111_I_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   127
	case M88E1118_E_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   128
		hw->phy_type = e1000_phy_m88;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   129
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   130
	case IGP01E1000_I_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   131
		if (hw->mac_type == e1000_82541 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   132
		    hw->mac_type == e1000_82541_rev_2 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   133
		    hw->mac_type == e1000_82547 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   134
		    hw->mac_type == e1000_82547_rev_2)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   135
			hw->phy_type = e1000_phy_igp;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   136
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   137
	case RTL8211B_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   138
		hw->phy_type = e1000_phy_8211;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   139
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   140
	case RTL8201N_PHY_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   141
		hw->phy_type = e1000_phy_8201;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   142
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   143
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   144
		/* Should never have loaded on this device */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   145
		hw->phy_type = e1000_phy_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   146
		return -E1000_ERR_PHY_TYPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   147
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   148
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   149
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   150
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   151
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   152
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   153
 * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   154
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   155
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   156
static void e1000_phy_init_script(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   157
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   158
	u32 ret_val __attribute__ ((unused));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   159
	u16 phy_saved_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   160
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   161
	e_dbg("e1000_phy_init_script");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   162
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   163
	if (hw->phy_init_script) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   164
		msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   165
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   166
		/* Save off the current value of register 0x2F5B to be restored at
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   167
		 * the end of this routine. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   168
		ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   169
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   170
		/* Disabled the PHY transmitter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   171
		e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   172
		msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   173
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   174
		e1000_write_phy_reg(hw, 0x0000, 0x0140);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   175
		msleep(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   176
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   177
		switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   178
		case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   179
		case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   180
			e1000_write_phy_reg(hw, 0x1F95, 0x0001);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   181
			e1000_write_phy_reg(hw, 0x1F71, 0xBD21);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   182
			e1000_write_phy_reg(hw, 0x1F79, 0x0018);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   183
			e1000_write_phy_reg(hw, 0x1F30, 0x1600);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   184
			e1000_write_phy_reg(hw, 0x1F31, 0x0014);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   185
			e1000_write_phy_reg(hw, 0x1F32, 0x161C);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   186
			e1000_write_phy_reg(hw, 0x1F94, 0x0003);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   187
			e1000_write_phy_reg(hw, 0x1F96, 0x003F);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   188
			e1000_write_phy_reg(hw, 0x2010, 0x0008);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   189
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   190
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   191
		case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   192
		case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   193
			e1000_write_phy_reg(hw, 0x1F73, 0x0099);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   194
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   195
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   196
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   197
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   198
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   199
		e1000_write_phy_reg(hw, 0x0000, 0x3300);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   200
		msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   201
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   202
		/* Now enable the transmitter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   203
		e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   204
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   205
		if (hw->mac_type == e1000_82547) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   206
			u16 fused, fine, coarse;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   207
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   208
			/* Move to analog registers page */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   209
			e1000_read_phy_reg(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   210
					   IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   211
					   &fused);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   212
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   213
			if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   214
				e1000_read_phy_reg(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   215
						   IGP01E1000_ANALOG_FUSE_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   216
						   &fused);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   217
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   218
				fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   219
				coarse =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   220
				    fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   221
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   222
				if (coarse >
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   223
				    IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   224
					coarse -=
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   225
					    IGP01E1000_ANALOG_FUSE_COARSE_10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   226
					fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   227
				} else if (coarse ==
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   228
					   IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   229
					fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   230
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   231
				fused =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   232
				    (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   233
				    (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   234
				    (coarse &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   235
				     IGP01E1000_ANALOG_FUSE_COARSE_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   236
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   237
				e1000_write_phy_reg(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   238
						    IGP01E1000_ANALOG_FUSE_CONTROL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   239
						    fused);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   240
				e1000_write_phy_reg(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   241
						    IGP01E1000_ANALOG_FUSE_BYPASS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   242
						    IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   243
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   244
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   245
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   246
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   247
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   248
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   249
 * e1000_set_mac_type - Set the mac type member in the hw struct.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   250
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   251
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   252
s32 e1000_set_mac_type(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   253
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   254
	e_dbg("e1000_set_mac_type");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   255
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   256
	switch (hw->device_id) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   257
	case E1000_DEV_ID_82542:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   258
		switch (hw->revision_id) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   259
		case E1000_82542_2_0_REV_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   260
			hw->mac_type = e1000_82542_rev2_0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   261
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   262
		case E1000_82542_2_1_REV_ID:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   263
			hw->mac_type = e1000_82542_rev2_1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   264
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   265
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   266
			/* Invalid 82542 revision ID */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   267
			return -E1000_ERR_MAC_TYPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   268
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   269
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   270
	case E1000_DEV_ID_82543GC_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   271
	case E1000_DEV_ID_82543GC_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   272
		hw->mac_type = e1000_82543;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   273
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   274
	case E1000_DEV_ID_82544EI_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   275
	case E1000_DEV_ID_82544EI_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   276
	case E1000_DEV_ID_82544GC_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   277
	case E1000_DEV_ID_82544GC_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   278
		hw->mac_type = e1000_82544;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   279
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   280
	case E1000_DEV_ID_82540EM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   281
	case E1000_DEV_ID_82540EM_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   282
	case E1000_DEV_ID_82540EP:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   283
	case E1000_DEV_ID_82540EP_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   284
	case E1000_DEV_ID_82540EP_LP:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   285
		hw->mac_type = e1000_82540;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   286
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   287
	case E1000_DEV_ID_82545EM_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   288
	case E1000_DEV_ID_82545EM_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   289
		hw->mac_type = e1000_82545;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   290
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   291
	case E1000_DEV_ID_82545GM_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   292
	case E1000_DEV_ID_82545GM_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   293
	case E1000_DEV_ID_82545GM_SERDES:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   294
		hw->mac_type = e1000_82545_rev_3;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   295
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   296
	case E1000_DEV_ID_82546EB_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   297
	case E1000_DEV_ID_82546EB_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   298
	case E1000_DEV_ID_82546EB_QUAD_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   299
		hw->mac_type = e1000_82546;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   300
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   301
	case E1000_DEV_ID_82546GB_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   302
	case E1000_DEV_ID_82546GB_FIBER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   303
	case E1000_DEV_ID_82546GB_SERDES:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   304
	case E1000_DEV_ID_82546GB_PCIE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   305
	case E1000_DEV_ID_82546GB_QUAD_COPPER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   306
	case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   307
		hw->mac_type = e1000_82546_rev_3;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   308
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   309
	case E1000_DEV_ID_82541EI:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   310
	case E1000_DEV_ID_82541EI_MOBILE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   311
	case E1000_DEV_ID_82541ER_LOM:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   312
		hw->mac_type = e1000_82541;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   313
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   314
	case E1000_DEV_ID_82541ER:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   315
	case E1000_DEV_ID_82541GI:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   316
	case E1000_DEV_ID_82541GI_LF:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   317
	case E1000_DEV_ID_82541GI_MOBILE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   318
		hw->mac_type = e1000_82541_rev_2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   319
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   320
	case E1000_DEV_ID_82547EI:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   321
	case E1000_DEV_ID_82547EI_MOBILE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   322
		hw->mac_type = e1000_82547;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   323
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   324
	case E1000_DEV_ID_82547GI:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   325
		hw->mac_type = e1000_82547_rev_2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   326
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   327
	case E1000_DEV_ID_INTEL_CE4100_GBE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   328
		hw->mac_type = e1000_ce4100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   329
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   330
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   331
		/* Should never have loaded on this device */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   332
		return -E1000_ERR_MAC_TYPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   333
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   334
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   335
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   336
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   337
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   338
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   339
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   340
		hw->asf_firmware_present = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   341
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   342
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   343
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   344
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   345
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   346
	/* The 82543 chip does not count tx_carrier_errors properly in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   347
	 * FD mode
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   348
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   349
	if (hw->mac_type == e1000_82543)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   350
		hw->bad_tx_carr_stats_fd = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   351
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   352
	if (hw->mac_type > e1000_82544)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   353
		hw->has_smbus = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   354
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   355
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   356
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   357
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   358
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   359
 * e1000_set_media_type - Set media type and TBI compatibility.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   360
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   361
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   362
void e1000_set_media_type(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   363
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   364
	u32 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   365
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   366
	e_dbg("e1000_set_media_type");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   367
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   368
	if (hw->mac_type != e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   369
		/* tbi_compatibility is only valid on 82543 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   370
		hw->tbi_compatibility_en = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   371
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   372
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   373
	switch (hw->device_id) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   374
	case E1000_DEV_ID_82545GM_SERDES:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   375
	case E1000_DEV_ID_82546GB_SERDES:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   376
		hw->media_type = e1000_media_type_internal_serdes;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   377
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   378
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   379
		switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   380
		case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   381
		case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   382
			hw->media_type = e1000_media_type_fiber;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   383
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   384
		case e1000_ce4100:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   385
			hw->media_type = e1000_media_type_copper;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   386
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   387
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   388
			status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   389
			if (status & E1000_STATUS_TBIMODE) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   390
				hw->media_type = e1000_media_type_fiber;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   391
				/* tbi_compatibility not valid on fiber */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   392
				hw->tbi_compatibility_en = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   393
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   394
				hw->media_type = e1000_media_type_copper;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   395
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   396
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   397
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   398
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   399
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   400
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   401
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   402
 * e1000_reset_hw - reset the hardware completely
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   403
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   404
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   405
 * Reset the transmit and receive units; mask and clear all interrupts.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   406
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   407
s32 e1000_reset_hw(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   408
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   409
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   410
	u32 ctrl_ext;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   411
	u32 icr __attribute__ ((unused));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   412
	u32 manc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   413
	u32 led_ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   414
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   415
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   416
	e_dbg("e1000_reset_hw");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   417
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   418
	/* For 82542 (rev 2.0), disable MWI before issuing a device reset */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   419
	if (hw->mac_type == e1000_82542_rev2_0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   420
		e_dbg("Disabling MWI on 82542 rev 2.0\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   421
		e1000_pci_clear_mwi(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   422
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   423
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   424
	/* Clear interrupt mask to stop board from generating interrupts */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   425
	e_dbg("Masking off all interrupts\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   426
	ew32(IMC, 0xffffffff);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   427
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   428
	/* Disable the Transmit and Receive units.  Then delay to allow
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   429
	 * any pending transactions to complete before we hit the MAC with
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   430
	 * the global reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   431
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   432
	ew32(RCTL, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   433
	ew32(TCTL, E1000_TCTL_PSP);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   434
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   435
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   436
	/* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   437
	hw->tbi_compatibility_on = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   438
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   439
	/* Delay to allow any outstanding PCI transactions to complete before
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   440
	 * resetting the device
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   441
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   442
	msleep(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   443
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   444
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   445
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   446
	/* Must reset the PHY before resetting the MAC */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   447
	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   448
		ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   449
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   450
		msleep(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   451
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   452
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   453
	/* Issue a global reset to the MAC.  This will reset the chip's
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   454
	 * transmit, receive, DMA, and link units.  It will not effect
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   455
	 * the current PCI configuration.  The global reset bit is self-
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   456
	 * clearing, and should clear within a microsecond.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   457
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   458
	e_dbg("Issuing a global reset to MAC\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   459
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   460
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   461
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   462
	case e1000_82540:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   463
	case e1000_82545:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   464
	case e1000_82546:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   465
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   466
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   467
		/* These controllers can't ack the 64-bit write when issuing the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   468
		 * reset, so use IO-mapping as a workaround to issue the reset */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   469
		E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   470
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   471
	case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   472
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   473
		/* Reset is performed on a shadow of the control register */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   474
		ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   475
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   476
	case e1000_ce4100:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   477
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   478
		ew32(CTRL, (ctrl | E1000_CTRL_RST));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   479
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   480
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   481
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   482
	/* After MAC reset, force reload of EEPROM to restore power-on settings to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   483
	 * device.  Later controllers reload the EEPROM automatically, so just wait
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   484
	 * for reload to complete.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   485
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   486
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   487
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   488
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   489
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   490
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   491
		/* Wait for reset to complete */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   492
		udelay(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   493
		ctrl_ext = er32(CTRL_EXT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   494
		ctrl_ext |= E1000_CTRL_EXT_EE_RST;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   495
		ew32(CTRL_EXT, ctrl_ext);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   496
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   497
		/* Wait for EEPROM reload */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   498
		msleep(2);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   499
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   500
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   501
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   502
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   503
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   504
		/* Wait for EEPROM reload */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   505
		msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   506
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   507
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   508
		/* Auto read done will delay 5ms or poll based on mac type */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   509
		ret_val = e1000_get_auto_rd_done(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   510
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   511
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   512
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   513
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   514
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   515
	/* Disable HW ARPs on ASF enabled adapters */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   516
	if (hw->mac_type >= e1000_82540) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   517
		manc = er32(MANC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   518
		manc &= ~(E1000_MANC_ARP_EN);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   519
		ew32(MANC, manc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   520
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   521
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   522
	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   523
		e1000_phy_init_script(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   524
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   525
		/* Configure activity LED after PHY reset */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   526
		led_ctrl = er32(LEDCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   527
		led_ctrl &= IGP_ACTIVITY_LED_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   528
		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   529
		ew32(LEDCTL, led_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   530
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   531
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   532
	/* Clear interrupt mask to stop board from generating interrupts */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   533
	e_dbg("Masking off all interrupts\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   534
	ew32(IMC, 0xffffffff);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   535
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   536
	/* Clear any pending interrupt events. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   537
	icr = er32(ICR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   538
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   539
	/* If MWI was previously enabled, reenable it. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   540
	if (hw->mac_type == e1000_82542_rev2_0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   541
		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   542
			e1000_pci_set_mwi(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   543
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   544
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   545
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   546
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   547
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   548
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   549
 * e1000_init_hw - Performs basic configuration of the adapter.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   550
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   551
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   552
 * Assumes that the controller has previously been reset and is in a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   553
 * post-reset uninitialized state. Initializes the receive address registers,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   554
 * multicast table, and VLAN filter table. Calls routines to setup link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   555
 * configuration and flow control settings. Clears all on-chip counters. Leaves
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   556
 * the transmit and receive units disabled and uninitialized.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   557
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   558
s32 e1000_init_hw(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   559
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   560
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   561
	u32 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   562
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   563
	u32 mta_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   564
	u32 ctrl_ext;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   565
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   566
	e_dbg("e1000_init_hw");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   567
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   568
	/* Initialize Identification LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   569
	ret_val = e1000_id_led_init(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   570
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   571
		e_dbg("Error Initializing Identification LED\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   572
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   573
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   574
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   575
	/* Set the media type and TBI compatibility */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   576
	e1000_set_media_type(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   577
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   578
	/* Disabling VLAN filtering. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   579
	e_dbg("Initializing the IEEE VLAN\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   580
	if (hw->mac_type < e1000_82545_rev_3)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   581
		ew32(VET, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   582
	e1000_clear_vfta(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   583
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   584
	/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   585
	if (hw->mac_type == e1000_82542_rev2_0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   586
		e_dbg("Disabling MWI on 82542 rev 2.0\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   587
		e1000_pci_clear_mwi(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   588
		ew32(RCTL, E1000_RCTL_RST);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   589
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   590
		msleep(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   591
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   592
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   593
	/* Setup the receive address. This involves initializing all of the Receive
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   594
	 * Address Registers (RARs 0 - 15).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   595
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   596
	e1000_init_rx_addrs(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   597
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   598
	/* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   599
	if (hw->mac_type == e1000_82542_rev2_0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   600
		ew32(RCTL, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   601
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   602
		msleep(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   603
		if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   604
			e1000_pci_set_mwi(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   605
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   606
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   607
	/* Zero out the Multicast HASH table */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   608
	e_dbg("Zeroing the MTA\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   609
	mta_size = E1000_MC_TBL_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   610
	for (i = 0; i < mta_size; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   611
		E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   612
		/* use write flush to prevent Memory Write Block (MWB) from
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   613
		 * occurring when accessing our register space */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   614
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   615
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   616
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   617
	/* Set the PCI priority bit correctly in the CTRL register.  This
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   618
	 * determines if the adapter gives priority to receives, or if it
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   619
	 * gives equal priority to transmits and receives.  Valid only on
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   620
	 * 82542 and 82543 silicon.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   621
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   622
	if (hw->dma_fairness && hw->mac_type <= e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   623
		ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   624
		ew32(CTRL, ctrl | E1000_CTRL_PRIOR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   625
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   626
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   627
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   628
	case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   629
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   630
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   631
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   632
		/* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   633
		if (hw->bus_type == e1000_bus_type_pcix
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   634
		    && e1000_pcix_get_mmrbc(hw) > 2048)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   635
			e1000_pcix_set_mmrbc(hw, 2048);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   636
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   637
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   638
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   639
	/* Call a subroutine to configure the link and setup flow control. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   640
	ret_val = e1000_setup_link(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   641
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   642
	/* Set the transmit descriptor write-back policy */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   643
	if (hw->mac_type > e1000_82544) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   644
		ctrl = er32(TXDCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   645
		ctrl =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   646
		    (ctrl & ~E1000_TXDCTL_WTHRESH) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   647
		    E1000_TXDCTL_FULL_TX_DESC_WB;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   648
		ew32(TXDCTL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   649
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   650
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   651
	/* Clear all of the statistics registers (clear on read).  It is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   652
	 * important that we do this after we have tried to establish link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   653
	 * because the symbol error count will increment wildly if there
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   654
	 * is no link.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   655
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   656
	e1000_clear_hw_cntrs(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   657
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   658
	if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   659
	    hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   660
		ctrl_ext = er32(CTRL_EXT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   661
		/* Relaxed ordering must be disabled to avoid a parity
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   662
		 * error crash in a PCI slot. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   663
		ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   664
		ew32(CTRL_EXT, ctrl_ext);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   665
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   666
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   667
	return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   668
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   669
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   670
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   671
 * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   672
 * @hw: Struct containing variables accessed by shared code.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   673
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   674
static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   675
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   676
	u16 eeprom_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   677
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   678
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   679
	e_dbg("e1000_adjust_serdes_amplitude");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   680
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   681
	if (hw->media_type != e1000_media_type_internal_serdes)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   682
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   683
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   684
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   685
	case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   686
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   687
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   688
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   689
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   690
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   691
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   692
	ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   693
	                            &eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   694
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   695
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   696
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   697
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   698
	if (eeprom_data != EEPROM_RESERVED_WORD) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   699
		/* Adjust SERDES output amplitude only. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   700
		eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   701
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   702
		    e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   703
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   704
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   705
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   706
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   707
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   708
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   709
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   710
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   711
 * e1000_setup_link - Configures flow control and link settings.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   712
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   713
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   714
 * Determines which flow control settings to use. Calls the appropriate media-
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   715
 * specific link configuration function. Configures the flow control settings.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   716
 * Assuming the adapter has a valid link partner, a valid link should be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   717
 * established. Assumes the hardware has previously been reset and the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   718
 * transmitter and receiver are not enabled.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   719
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   720
s32 e1000_setup_link(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   721
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   722
	u32 ctrl_ext;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   723
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   724
	u16 eeprom_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   725
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   726
	e_dbg("e1000_setup_link");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   727
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   728
	/* Read and store word 0x0F of the EEPROM. This word contains bits
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   729
	 * that determine the hardware's default PAUSE (flow control) mode,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   730
	 * a bit that determines whether the HW defaults to enabling or
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   731
	 * disabling auto-negotiation, and the direction of the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   732
	 * SW defined pins. If there is no SW over-ride of the flow
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   733
	 * control setting, then the variable hw->fc will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   734
	 * be initialized based on a value in the EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   735
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   736
	if (hw->fc == E1000_FC_DEFAULT) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   737
		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   738
					    1, &eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   739
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   740
			e_dbg("EEPROM Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   741
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   742
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   743
		if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   744
			hw->fc = E1000_FC_NONE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   745
		else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) ==
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   746
			 EEPROM_WORD0F_ASM_DIR)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   747
			hw->fc = E1000_FC_TX_PAUSE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   748
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   749
			hw->fc = E1000_FC_FULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   750
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   751
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   752
	/* We want to save off the original Flow Control configuration just
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   753
	 * in case we get disconnected and then reconnected into a different
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   754
	 * hub or switch with different Flow Control capabilities.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   755
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   756
	if (hw->mac_type == e1000_82542_rev2_0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   757
		hw->fc &= (~E1000_FC_TX_PAUSE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   758
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   759
	if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   760
		hw->fc &= (~E1000_FC_RX_PAUSE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   761
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   762
	hw->original_fc = hw->fc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   763
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   764
	e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   765
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   766
	/* Take the 4 bits from EEPROM word 0x0F that determine the initial
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   767
	 * polarity value for the SW controlled pins, and setup the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   768
	 * Extended Device Control reg with that info.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   769
	 * This is needed because one of the SW controlled pins is used for
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   770
	 * signal detection.  So this should be done before e1000_setup_pcs_link()
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   771
	 * or e1000_phy_setup() is called.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   772
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   773
	if (hw->mac_type == e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   774
		ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   775
					    1, &eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   776
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   777
			e_dbg("EEPROM Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   778
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   779
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   780
		ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) <<
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   781
			    SWDPIO__EXT_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   782
		ew32(CTRL_EXT, ctrl_ext);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   783
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   784
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   785
	/* Call the necessary subroutine to configure the link. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   786
	ret_val = (hw->media_type == e1000_media_type_copper) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   787
	    e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   788
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   789
	/* Initialize the flow control address, type, and PAUSE timer
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   790
	 * registers to their default values.  This is done even if flow
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   791
	 * control is disabled, because it does not hurt anything to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   792
	 * initialize these registers.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   793
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   794
	e_dbg("Initializing the Flow Control address, type and timer regs\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   795
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   796
	ew32(FCT, FLOW_CONTROL_TYPE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   797
	ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   798
	ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   799
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   800
	ew32(FCTTV, hw->fc_pause_time);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   801
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   802
	/* Set the flow control receive threshold registers.  Normally,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   803
	 * these registers will be set to a default threshold that may be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   804
	 * adjusted later by the driver's runtime code.  However, if the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   805
	 * ability to transmit pause frames in not enabled, then these
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   806
	 * registers will be set to 0.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   807
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   808
	if (!(hw->fc & E1000_FC_TX_PAUSE)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   809
		ew32(FCRTL, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   810
		ew32(FCRTH, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   811
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   812
		/* We need to set up the Receive Threshold high and low water marks
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   813
		 * as well as (optionally) enabling the transmission of XON frames.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   814
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   815
		if (hw->fc_send_xon) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   816
			ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   817
			ew32(FCRTH, hw->fc_high_water);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   818
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   819
			ew32(FCRTL, hw->fc_low_water);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   820
			ew32(FCRTH, hw->fc_high_water);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   821
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   822
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   823
	return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   824
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   825
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   826
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   827
 * e1000_setup_fiber_serdes_link - prepare fiber or serdes link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   828
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   829
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   830
 * Manipulates Physical Coding Sublayer functions in order to configure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   831
 * link. Assumes the hardware has been previously reset and the transmitter
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   832
 * and receiver are not enabled.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   833
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   834
static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   835
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   836
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   837
	u32 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   838
	u32 txcw = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   839
	u32 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   840
	u32 signal = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   841
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   842
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   843
	e_dbg("e1000_setup_fiber_serdes_link");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   844
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   845
	/* On adapters with a MAC newer than 82544, SWDP 1 will be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   846
	 * set when the optics detect a signal. On older adapters, it will be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   847
	 * cleared when there is a signal.  This applies to fiber media only.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   848
	 * If we're on serdes media, adjust the output amplitude to value
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   849
	 * set in the EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   850
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   851
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   852
	if (hw->media_type == e1000_media_type_fiber)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   853
		signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   854
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   855
	ret_val = e1000_adjust_serdes_amplitude(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   856
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   857
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   858
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   859
	/* Take the link out of reset */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   860
	ctrl &= ~(E1000_CTRL_LRST);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   861
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   862
	/* Adjust VCO speed to improve BER performance */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   863
	ret_val = e1000_set_vco_speed(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   864
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   865
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   866
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   867
	e1000_config_collision_dist(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   868
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   869
	/* Check for a software override of the flow control settings, and setup
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   870
	 * the device accordingly.  If auto-negotiation is enabled, then software
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   871
	 * will have to set the "PAUSE" bits to the correct value in the Tranmsit
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   872
	 * Config Word Register (TXCW) and re-start auto-negotiation.  However, if
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   873
	 * auto-negotiation is disabled, then software will have to manually
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   874
	 * configure the two flow control enable bits in the CTRL register.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   875
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   876
	 * The possible values of the "fc" parameter are:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   877
	 *      0:  Flow control is completely disabled
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   878
	 *      1:  Rx flow control is enabled (we can receive pause frames, but
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   879
	 *          not send pause frames).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   880
	 *      2:  Tx flow control is enabled (we can send pause frames but we do
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   881
	 *          not support receiving pause frames).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   882
	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   883
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   884
	switch (hw->fc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   885
	case E1000_FC_NONE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   886
		/* Flow control is completely disabled by a software over-ride. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   887
		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   888
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   889
	case E1000_FC_RX_PAUSE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   890
		/* RX Flow control is enabled and TX Flow control is disabled by a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   891
		 * software over-ride. Since there really isn't a way to advertise
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   892
		 * that we are capable of RX Pause ONLY, we will advertise that we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   893
		 * support both symmetric and asymmetric RX PAUSE. Later, we will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   894
		 *  disable the adapter's ability to send PAUSE frames.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   895
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   896
		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   897
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   898
	case E1000_FC_TX_PAUSE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   899
		/* TX Flow control is enabled, and RX Flow control is disabled, by a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   900
		 * software over-ride.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   901
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   902
		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   903
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   904
	case E1000_FC_FULL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   905
		/* Flow control (both RX and TX) is enabled by a software over-ride. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   906
		txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   907
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   908
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   909
		e_dbg("Flow control param set incorrectly\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   910
		return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   911
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   912
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   913
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   914
	/* Since auto-negotiation is enabled, take the link out of reset (the link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   915
	 * will be in reset, because we previously reset the chip). This will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   916
	 * restart auto-negotiation.  If auto-negotiation is successful then the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   917
	 * link-up status bit will be set and the flow control enable bits (RFCE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   918
	 * and TFCE) will be set according to their negotiated value.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   919
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   920
	e_dbg("Auto-negotiation enabled\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   921
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   922
	ew32(TXCW, txcw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   923
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   924
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   925
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   926
	hw->txcw = txcw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   927
	msleep(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   928
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   929
	/* If we have a signal (the cable is plugged in) then poll for a "Link-Up"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   930
	 * indication in the Device Status Register.  Time-out if a link isn't
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   931
	 * seen in 500 milliseconds seconds (Auto-negotiation should complete in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   932
	 * less than 500 milliseconds even if the other end is doing it in SW).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   933
	 * For internal serdes, we just assume a signal is present, then poll.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   934
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   935
	if (hw->media_type == e1000_media_type_internal_serdes ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   936
	    (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   937
		e_dbg("Looking for Link\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   938
		for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   939
			msleep(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   940
			status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   941
			if (status & E1000_STATUS_LU)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   942
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   943
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   944
		if (i == (LINK_UP_TIMEOUT / 10)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   945
			e_dbg("Never got a valid link from auto-neg!!!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   946
			hw->autoneg_failed = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   947
			/* AutoNeg failed to achieve a link, so we'll call
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   948
			 * e1000_check_for_link. This routine will force the link up if
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   949
			 * we detect a signal. This will allow us to communicate with
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   950
			 * non-autonegotiating link partners.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   951
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   952
			ret_val = e1000_check_for_link(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   953
			if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   954
				e_dbg("Error while checking for link\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   955
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   956
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   957
			hw->autoneg_failed = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   958
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   959
			hw->autoneg_failed = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   960
			e_dbg("Valid Link Found\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   961
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   962
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   963
		e_dbg("No Signal Detected\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   964
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   965
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   966
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   967
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   968
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   969
 * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   970
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   971
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   972
 * Commits changes to PHY configuration by calling e1000_phy_reset().
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   973
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   974
static s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   975
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   976
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   977
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   978
	/* SW reset the PHY so all changes take effect */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   979
	ret_val = e1000_phy_reset(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   980
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   981
		e_dbg("Error Resetting the PHY\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   982
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   983
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   984
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   985
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   986
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   987
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   988
static s32 gbe_dhg_phy_setup(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   989
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   990
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   991
	u32 ctrl_aux;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   992
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   993
	switch (hw->phy_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   994
	case e1000_phy_8211:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   995
		ret_val = e1000_copper_link_rtl_setup(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   996
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   997
			e_dbg("e1000_copper_link_rtl_setup failed!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   998
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
   999
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1000
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1001
	case e1000_phy_8201:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1002
		/* Set RMII mode */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1003
		ctrl_aux = er32(CTL_AUX);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1004
		ctrl_aux |= E1000_CTL_AUX_RMII;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1005
		ew32(CTL_AUX, ctrl_aux);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1006
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1007
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1008
		/* Disable the J/K bits required for receive */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1009
		ctrl_aux = er32(CTL_AUX);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1010
		ctrl_aux |= 0x4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1011
		ctrl_aux &= ~0x2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1012
		ew32(CTL_AUX, ctrl_aux);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1013
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1014
		ret_val = e1000_copper_link_rtl_setup(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1015
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1016
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1017
			e_dbg("e1000_copper_link_rtl_setup failed!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1018
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1019
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1020
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1021
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1022
		e_dbg("Error Resetting the PHY\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1023
		return E1000_ERR_PHY_TYPE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1024
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1025
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1026
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1027
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1028
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1029
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1030
 * e1000_copper_link_preconfig - early configuration for copper
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1031
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1032
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1033
 * Make sure we have a valid PHY and change PHY mode before link setup.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1034
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1035
static s32 e1000_copper_link_preconfig(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1036
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1037
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1038
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1039
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1040
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1041
	e_dbg("e1000_copper_link_preconfig");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1042
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1043
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1044
	/* With 82543, we need to force speed and duplex on the MAC equal to what
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1045
	 * the PHY speed and duplex configuration is. In addition, we need to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1046
	 * perform a hardware reset on the PHY to take it out of reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1047
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1048
	if (hw->mac_type > e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1049
		ctrl |= E1000_CTRL_SLU;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1050
		ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1051
		ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1052
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1053
		ctrl |=
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1054
		    (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1055
		ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1056
		ret_val = e1000_phy_hw_reset(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1057
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1058
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1059
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1060
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1061
	/* Make sure we have a valid PHY */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1062
	ret_val = e1000_detect_gig_phy(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1063
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1064
		e_dbg("Error, did not detect valid phy.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1065
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1066
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1067
	e_dbg("Phy ID = %x\n", hw->phy_id);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1068
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1069
	/* Set PHY to class A mode (if necessary) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1070
	ret_val = e1000_set_phy_mode(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1071
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1072
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1073
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1074
	if ((hw->mac_type == e1000_82545_rev_3) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1075
	    (hw->mac_type == e1000_82546_rev_3)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1076
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1077
		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1078
		phy_data |= 0x00000008;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1079
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1080
		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1081
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1082
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1083
	if (hw->mac_type <= e1000_82543 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1084
	    hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1085
	    hw->mac_type == e1000_82541_rev_2
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1086
	    || hw->mac_type == e1000_82547_rev_2)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1087
		hw->phy_reset_disable = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1088
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1089
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1090
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1091
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1092
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1093
 * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1094
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1095
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1096
static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1097
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1098
	u32 led_ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1099
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1100
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1101
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1102
	e_dbg("e1000_copper_link_igp_setup");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1103
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1104
	if (hw->phy_reset_disable)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1105
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1106
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1107
	ret_val = e1000_phy_reset(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1108
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1109
		e_dbg("Error Resetting the PHY\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1110
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1111
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1112
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1113
	/* Wait 15ms for MAC to configure PHY from eeprom settings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1114
	msleep(15);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1115
	/* Configure activity LED after PHY reset */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1116
	led_ctrl = er32(LEDCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1117
	led_ctrl &= IGP_ACTIVITY_LED_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1118
	led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1119
	ew32(LEDCTL, led_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1120
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1121
	/* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1122
	if (hw->phy_type == e1000_phy_igp) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1123
		/* disable lplu d3 during driver init */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1124
		ret_val = e1000_set_d3_lplu_state(hw, false);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1125
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1126
			e_dbg("Error Disabling LPLU D3\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1127
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1128
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1129
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1130
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1131
	/* Configure mdi-mdix settings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1132
	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1133
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1134
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1135
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1136
	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1137
		hw->dsp_config_state = e1000_dsp_config_disabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1138
		/* Force MDI for earlier revs of the IGP PHY */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1139
		phy_data &=
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1140
		    ~(IGP01E1000_PSCR_AUTO_MDIX |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1141
		      IGP01E1000_PSCR_FORCE_MDI_MDIX);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1142
		hw->mdix = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1143
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1144
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1145
		hw->dsp_config_state = e1000_dsp_config_enabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1146
		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1147
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1148
		switch (hw->mdix) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1149
		case 1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1150
			phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1151
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1152
		case 2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1153
			phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1154
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1155
		case 0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1156
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1157
			phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1158
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1159
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1160
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1161
	ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1162
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1163
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1164
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1165
	/* set auto-master slave resolution settings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1166
	if (hw->autoneg) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1167
		e1000_ms_type phy_ms_setting = hw->master_slave;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1168
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1169
		if (hw->ffe_config_state == e1000_ffe_config_active)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1170
			hw->ffe_config_state = e1000_ffe_config_enabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1171
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1172
		if (hw->dsp_config_state == e1000_dsp_config_activated)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1173
			hw->dsp_config_state = e1000_dsp_config_enabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1174
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1175
		/* when autonegotiation advertisement is only 1000Mbps then we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1176
		 * should disable SmartSpeed and enable Auto MasterSlave
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1177
		 * resolution as hardware default. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1178
		if (hw->autoneg_advertised == ADVERTISE_1000_FULL) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1179
			/* Disable SmartSpeed */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1180
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1181
			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1182
					       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1183
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1184
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1185
			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1186
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1187
			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1188
						phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1189
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1190
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1191
			/* Set auto Master/Slave resolution process */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1192
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1193
			    e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1194
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1195
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1196
			phy_data &= ~CR_1000T_MS_ENABLE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1197
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1198
			    e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1199
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1200
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1201
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1202
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1203
		ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1204
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1205
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1206
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1207
		/* load defaults for future use */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1208
		hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1209
		    ((phy_data & CR_1000T_MS_VALUE) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1210
		     e1000_ms_force_master :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1211
		     e1000_ms_force_slave) : e1000_ms_auto;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1212
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1213
		switch (phy_ms_setting) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1214
		case e1000_ms_force_master:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1215
			phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1216
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1217
		case e1000_ms_force_slave:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1218
			phy_data |= CR_1000T_MS_ENABLE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1219
			phy_data &= ~(CR_1000T_MS_VALUE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1220
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1221
		case e1000_ms_auto:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1222
			phy_data &= ~CR_1000T_MS_ENABLE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1223
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1224
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1225
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1226
		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1227
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1228
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1229
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1230
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1231
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1232
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1233
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1234
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1235
 * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1236
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1237
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1238
static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1239
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1240
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1241
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1242
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1243
	e_dbg("e1000_copper_link_mgp_setup");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1244
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1245
	if (hw->phy_reset_disable)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1246
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1247
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1248
	/* Enable CRS on TX. This must be set for half-duplex operation. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1249
	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1250
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1251
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1252
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1253
	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1254
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1255
	/* Options:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1256
	 *   MDI/MDI-X = 0 (default)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1257
	 *   0 - Auto for all speeds
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1258
	 *   1 - MDI mode
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1259
	 *   2 - MDI-X mode
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1260
	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1261
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1262
	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1263
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1264
	switch (hw->mdix) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1265
	case 1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1266
		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1267
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1268
	case 2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1269
		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1270
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1271
	case 3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1272
		phy_data |= M88E1000_PSCR_AUTO_X_1000T;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1273
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1274
	case 0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1275
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1276
		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1277
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1278
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1279
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1280
	/* Options:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1281
	 *   disable_polarity_correction = 0 (default)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1282
	 *       Automatic Correction for Reversed Cable Polarity
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1283
	 *   0 - Disabled
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1284
	 *   1 - Enabled
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1285
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1286
	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1287
	if (hw->disable_polarity_correction == 1)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1288
		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1289
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1290
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1291
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1292
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1293
	if (hw->phy_revision < M88E1011_I_REV_4) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1294
		/* Force TX_CLK in the Extended PHY Specific Control Register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1295
		 * to 25MHz clock.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1296
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1297
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1298
		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1299
				       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1300
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1301
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1302
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1303
		phy_data |= M88E1000_EPSCR_TX_CLK_25;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1304
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1305
		if ((hw->phy_revision == E1000_REVISION_2) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1306
		    (hw->phy_id == M88E1111_I_PHY_ID)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1307
			/* Vidalia Phy, set the downshift counter to 5x */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1308
			phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1309
			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1310
			ret_val = e1000_write_phy_reg(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1311
						      M88E1000_EXT_PHY_SPEC_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1312
						      phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1313
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1314
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1315
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1316
			/* Configure Master and Slave downshift values */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1317
			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1318
				      M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1319
			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1320
				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1321
			ret_val = e1000_write_phy_reg(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1322
						      M88E1000_EXT_PHY_SPEC_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1323
						      phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1324
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1325
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1326
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1327
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1328
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1329
	/* SW Reset the PHY so all changes take effect */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1330
	ret_val = e1000_phy_reset(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1331
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1332
		e_dbg("Error Resetting the PHY\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1333
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1334
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1335
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1336
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1337
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1338
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1339
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1340
 * e1000_copper_link_autoneg - setup auto-neg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1341
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1342
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1343
 * Setup auto-negotiation and flow control advertisements,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1344
 * and then perform auto-negotiation.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1345
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1346
static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1347
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1348
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1349
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1350
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1351
	e_dbg("e1000_copper_link_autoneg");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1352
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1353
	/* Perform some bounds checking on the hw->autoneg_advertised
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1354
	 * parameter.  If this variable is zero, then set it to the default.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1355
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1356
	hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1357
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1358
	/* If autoneg_advertised is zero, we assume it was not defaulted
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1359
	 * by the calling code so we set to advertise full capability.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1360
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1361
	if (hw->autoneg_advertised == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1362
		hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1363
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1364
	/* IFE/RTL8201N PHY only supports 10/100 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1365
	if (hw->phy_type == e1000_phy_8201)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1366
		hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1367
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1368
	e_dbg("Reconfiguring auto-neg advertisement params\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1369
	ret_val = e1000_phy_setup_autoneg(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1370
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1371
		e_dbg("Error Setting up Auto-Negotiation\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1372
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1373
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1374
	e_dbg("Restarting Auto-Neg\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1375
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1376
	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1377
	 * the Auto Neg Restart bit in the PHY control register.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1378
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1379
	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1380
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1381
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1382
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1383
	phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1384
	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1385
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1386
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1387
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1388
	/* Does the user want to wait for Auto-Neg to complete here, or
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1389
	 * check at a later time (for example, callback routine).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1390
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1391
	if (hw->wait_autoneg_complete) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1392
		ret_val = e1000_wait_autoneg(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1393
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1394
			e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1395
			    ("Error while waiting for autoneg to complete\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1396
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1397
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1398
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1399
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1400
	hw->get_link_status = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1401
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1402
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1403
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1404
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1405
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1406
 * e1000_copper_link_postconfig - post link setup
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1407
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1408
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1409
 * Config the MAC and the PHY after link is up.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1410
 *   1) Set up the MAC to the current PHY speed/duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1411
 *      if we are on 82543.  If we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1412
 *      are on newer silicon, we only need to configure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1413
 *      collision distance in the Transmit Control Register.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1414
 *   2) Set up flow control on the MAC to that established with
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1415
 *      the link partner.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1416
 *   3) Config DSP to improve Gigabit link quality for some PHY revisions.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1417
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1418
static s32 e1000_copper_link_postconfig(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1419
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1420
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1421
	e_dbg("e1000_copper_link_postconfig");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1422
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1423
	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1424
		e1000_config_collision_dist(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1425
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1426
		ret_val = e1000_config_mac_to_phy(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1427
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1428
			e_dbg("Error configuring MAC to PHY settings\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1429
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1430
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1431
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1432
	ret_val = e1000_config_fc_after_link_up(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1433
	if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1434
		e_dbg("Error Configuring Flow Control\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1435
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1436
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1437
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1438
	/* Config DSP to improve Giga link quality */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1439
	if (hw->phy_type == e1000_phy_igp) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1440
		ret_val = e1000_config_dsp_after_link_change(hw, true);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1441
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1442
			e_dbg("Error Configuring DSP after link up\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1443
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1444
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1445
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1446
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1447
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1448
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1449
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1450
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1451
 * e1000_setup_copper_link - phy/speed/duplex setting
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1452
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1453
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1454
 * Detects which PHY is present and sets up the speed and duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1455
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1456
static s32 e1000_setup_copper_link(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1457
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1458
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1459
	u16 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1460
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1461
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1462
	e_dbg("e1000_setup_copper_link");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1463
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1464
	/* Check if it is a valid PHY and set PHY mode if necessary. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1465
	ret_val = e1000_copper_link_preconfig(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1466
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1467
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1468
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1469
	if (hw->phy_type == e1000_phy_igp) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1470
		ret_val = e1000_copper_link_igp_setup(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1471
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1472
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1473
	} else if (hw->phy_type == e1000_phy_m88) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1474
		ret_val = e1000_copper_link_mgp_setup(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1475
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1476
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1477
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1478
		ret_val = gbe_dhg_phy_setup(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1479
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1480
			e_dbg("gbe_dhg_phy_setup failed!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1481
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1482
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1483
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1484
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1485
	if (hw->autoneg) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1486
		/* Setup autoneg and flow control advertisement
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1487
		 * and perform autonegotiation */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1488
		ret_val = e1000_copper_link_autoneg(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1489
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1490
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1491
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1492
		/* PHY will be set to 10H, 10F, 100H,or 100F
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1493
		 * depending on value from forced_speed_duplex. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1494
		e_dbg("Forcing speed and duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1495
		ret_val = e1000_phy_force_speed_duplex(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1496
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1497
			e_dbg("Error Forcing Speed and Duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1498
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1499
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1500
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1501
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1502
	/* Check link status. Wait up to 100 microseconds for link to become
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1503
	 * valid.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1504
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1505
	for (i = 0; i < 10; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1506
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1507
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1508
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1509
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1510
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1511
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1512
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1513
		if (phy_data & MII_SR_LINK_STATUS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1514
			/* Config the MAC and PHY after link is up */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1515
			ret_val = e1000_copper_link_postconfig(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1516
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1517
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1518
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1519
			e_dbg("Valid link established!!!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1520
			return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1521
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1522
		udelay(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1523
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1524
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1525
	e_dbg("Unable to establish link!!!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1526
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1527
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1528
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1529
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1530
 * e1000_phy_setup_autoneg - phy settings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1531
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1532
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1533
 * Configures PHY autoneg and flow control advertisement settings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1534
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1535
s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1536
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1537
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1538
	u16 mii_autoneg_adv_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1539
	u16 mii_1000t_ctrl_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1540
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1541
	e_dbg("e1000_phy_setup_autoneg");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1542
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1543
	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1544
	ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1545
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1546
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1547
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1548
	/* Read the MII 1000Base-T Control Register (Address 9). */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1549
	ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1550
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1551
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1552
	else if (hw->phy_type == e1000_phy_8201)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1553
		mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1554
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1555
	/* Need to parse both autoneg_advertised and fc and set up
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1556
	 * the appropriate PHY registers.  First we will parse for
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1557
	 * autoneg_advertised software override.  Since we can advertise
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1558
	 * a plethora of combinations, we need to check each bit
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1559
	 * individually.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1560
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1561
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1562
	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1563
	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1564
	 * the  1000Base-T Control Register (Address 9).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1565
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1566
	mii_autoneg_adv_reg &= ~REG4_SPEED_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1567
	mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1568
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1569
	e_dbg("autoneg_advertised %x\n", hw->autoneg_advertised);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1570
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1571
	/* Do we want to advertise 10 Mb Half Duplex? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1572
	if (hw->autoneg_advertised & ADVERTISE_10_HALF) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1573
		e_dbg("Advertise 10mb Half duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1574
		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1575
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1576
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1577
	/* Do we want to advertise 10 Mb Full Duplex? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1578
	if (hw->autoneg_advertised & ADVERTISE_10_FULL) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1579
		e_dbg("Advertise 10mb Full duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1580
		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1581
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1582
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1583
	/* Do we want to advertise 100 Mb Half Duplex? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1584
	if (hw->autoneg_advertised & ADVERTISE_100_HALF) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1585
		e_dbg("Advertise 100mb Half duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1586
		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1587
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1588
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1589
	/* Do we want to advertise 100 Mb Full Duplex? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1590
	if (hw->autoneg_advertised & ADVERTISE_100_FULL) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1591
		e_dbg("Advertise 100mb Full duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1592
		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1593
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1594
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1595
	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1596
	if (hw->autoneg_advertised & ADVERTISE_1000_HALF) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1597
		e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1598
		    ("Advertise 1000mb Half duplex requested, request denied!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1599
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1600
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1601
	/* Do we want to advertise 1000 Mb Full Duplex? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1602
	if (hw->autoneg_advertised & ADVERTISE_1000_FULL) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1603
		e_dbg("Advertise 1000mb Full duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1604
		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1605
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1606
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1607
	/* Check for a software override of the flow control settings, and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1608
	 * setup the PHY advertisement registers accordingly.  If
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1609
	 * auto-negotiation is enabled, then software will have to set the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1610
	 * "PAUSE" bits to the correct value in the Auto-Negotiation
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1611
	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-negotiation.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1612
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1613
	 * The possible values of the "fc" parameter are:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1614
	 *      0:  Flow control is completely disabled
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1615
	 *      1:  Rx flow control is enabled (we can receive pause frames
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1616
	 *          but not send pause frames).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1617
	 *      2:  Tx flow control is enabled (we can send pause frames
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1618
	 *          but we do not support receiving pause frames).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1619
	 *      3:  Both Rx and TX flow control (symmetric) are enabled.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1620
	 *  other:  No software override.  The flow control configuration
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1621
	 *          in the EEPROM is used.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1622
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1623
	switch (hw->fc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1624
	case E1000_FC_NONE:	/* 0 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1625
		/* Flow control (RX & TX) is completely disabled by a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1626
		 * software over-ride.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1627
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1628
		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1629
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1630
	case E1000_FC_RX_PAUSE:	/* 1 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1631
		/* RX Flow control is enabled, and TX Flow control is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1632
		 * disabled, by a software over-ride.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1633
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1634
		/* Since there really isn't a way to advertise that we are
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1635
		 * capable of RX Pause ONLY, we will advertise that we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1636
		 * support both symmetric and asymmetric RX PAUSE.  Later
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1637
		 * (in e1000_config_fc_after_link_up) we will disable the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1638
		 *hw's ability to send PAUSE frames.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1639
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1640
		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1641
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1642
	case E1000_FC_TX_PAUSE:	/* 2 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1643
		/* TX Flow control is enabled, and RX Flow control is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1644
		 * disabled, by a software over-ride.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1645
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1646
		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1647
		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1648
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1649
	case E1000_FC_FULL:	/* 3 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1650
		/* Flow control (both RX and TX) is enabled by a software
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1651
		 * over-ride.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1652
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1653
		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1654
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1655
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1656
		e_dbg("Flow control param set incorrectly\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1657
		return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1658
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1659
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1660
	ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1661
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1662
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1663
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1664
	e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1665
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1666
	if (hw->phy_type == e1000_phy_8201) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1667
		mii_1000t_ctrl_reg = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1668
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1669
		ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1670
		                              mii_1000t_ctrl_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1671
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1672
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1673
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1674
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1675
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1676
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1677
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1678
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1679
 * e1000_phy_force_speed_duplex - force link settings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1680
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1681
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1682
 * Force PHY speed and duplex settings to hw->forced_speed_duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1683
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1684
static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1685
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1686
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1687
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1688
	u16 mii_ctrl_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1689
	u16 mii_status_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1690
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1691
	u16 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1692
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1693
	e_dbg("e1000_phy_force_speed_duplex");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1694
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1695
	/* Turn off Flow control if we are forcing speed and duplex. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1696
	hw->fc = E1000_FC_NONE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1697
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1698
	e_dbg("hw->fc = %d\n", hw->fc);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1699
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1700
	/* Read the Device Control Register. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1701
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1702
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1703
	/* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1704
	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1705
	ctrl &= ~(DEVICE_SPEED_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1706
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1707
	/* Clear the Auto Speed Detect Enable bit. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1708
	ctrl &= ~E1000_CTRL_ASDE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1709
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1710
	/* Read the MII Control Register. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1711
	ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1712
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1713
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1714
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1715
	/* We need to disable autoneg in order to force link and duplex. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1716
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1717
	mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1718
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1719
	/* Are we forcing Full or Half Duplex? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1720
	if (hw->forced_speed_duplex == e1000_100_full ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1721
	    hw->forced_speed_duplex == e1000_10_full) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1722
		/* We want to force full duplex so we SET the full duplex bits in the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1723
		 * Device and MII Control Registers.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1724
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1725
		ctrl |= E1000_CTRL_FD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1726
		mii_ctrl_reg |= MII_CR_FULL_DUPLEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1727
		e_dbg("Full Duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1728
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1729
		/* We want to force half duplex so we CLEAR the full duplex bits in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1730
		 * the Device and MII Control Registers.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1731
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1732
		ctrl &= ~E1000_CTRL_FD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1733
		mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1734
		e_dbg("Half Duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1735
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1736
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1737
	/* Are we forcing 100Mbps??? */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1738
	if (hw->forced_speed_duplex == e1000_100_full ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1739
	    hw->forced_speed_duplex == e1000_100_half) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1740
		/* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1741
		ctrl |= E1000_CTRL_SPD_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1742
		mii_ctrl_reg |= MII_CR_SPEED_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1743
		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1744
		e_dbg("Forcing 100mb ");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1745
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1746
		/* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1747
		ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1748
		mii_ctrl_reg |= MII_CR_SPEED_10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1749
		mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1750
		e_dbg("Forcing 10mb ");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1751
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1752
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1753
	e1000_config_collision_dist(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1754
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1755
	/* Write the configured values back to the Device Control Reg. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1756
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1757
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1758
	if (hw->phy_type == e1000_phy_m88) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1759
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1760
		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1761
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1762
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1763
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1764
		/* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1765
		 * forced whenever speed are duplex are forced.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1766
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1767
		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1768
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1769
		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1770
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1771
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1772
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1773
		e_dbg("M88E1000 PSCR: %x\n", phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1774
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1775
		/* Need to reset the PHY or these changes will be ignored */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1776
		mii_ctrl_reg |= MII_CR_RESET;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1777
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1778
		/* Disable MDI-X support for 10/100 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1779
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1780
		/* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1781
		 * forced whenever speed or duplex are forced.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1782
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1783
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1784
		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1785
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1786
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1787
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1788
		phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1789
		phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1790
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1791
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1792
		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1793
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1794
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1795
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1796
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1797
	/* Write back the modified PHY MII control register. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1798
	ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1799
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1800
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1801
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1802
	udelay(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1803
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1804
	/* The wait_autoneg_complete flag may be a little misleading here.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1805
	 * Since we are forcing speed and duplex, Auto-Neg is not enabled.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1806
	 * But we do want to delay for a period while forcing only so we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1807
	 * don't generate false No Link messages.  So we will wait here
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1808
	 * only if the user has set wait_autoneg_complete to 1, which is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1809
	 * the default.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1810
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1811
	if (hw->wait_autoneg_complete) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1812
		/* We will wait for autoneg to complete. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1813
		e_dbg("Waiting for forced speed/duplex link.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1814
		mii_status_reg = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1815
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1816
		/* We will wait for autoneg to complete or 4.5 seconds to expire. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1817
		for (i = PHY_FORCE_TIME; i > 0; i--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1818
			/* Read the MII Status Register and wait for Auto-Neg Complete bit
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1819
			 * to be set.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1820
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1821
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1822
			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1823
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1824
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1825
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1826
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1827
			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1828
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1829
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1830
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1831
			if (mii_status_reg & MII_SR_LINK_STATUS)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1832
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1833
			msleep(100);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1834
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1835
		if ((i == 0) && (hw->phy_type == e1000_phy_m88)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1836
			/* We didn't get link.  Reset the DSP and wait again for link. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1837
			ret_val = e1000_phy_reset_dsp(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1838
			if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1839
				e_dbg("Error Resetting PHY DSP\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1840
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1841
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1842
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1843
		/* This loop will early-out if the link condition has been met.  */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1844
		for (i = PHY_FORCE_TIME; i > 0; i--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1845
			if (mii_status_reg & MII_SR_LINK_STATUS)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1846
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1847
			msleep(100);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1848
			/* Read the MII Status Register and wait for Auto-Neg Complete bit
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1849
			 * to be set.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1850
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1851
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1852
			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1853
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1854
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1855
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1856
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1857
			    e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1858
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1859
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1860
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1861
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1862
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1863
	if (hw->phy_type == e1000_phy_m88) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1864
		/* Because we reset the PHY above, we need to re-force TX_CLK in the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1865
		 * Extended PHY Specific Control Register to 25MHz clock.  This value
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1866
		 * defaults back to a 2.5MHz clock when the PHY is reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1867
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1868
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1869
		    e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1870
				       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1871
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1872
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1873
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1874
		phy_data |= M88E1000_EPSCR_TX_CLK_25;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1875
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1876
		    e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1877
					phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1878
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1879
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1880
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1881
		/* In addition, because of the s/w reset above, we need to enable CRS on
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1882
		 * TX.  This must be set for both full and half duplex operation.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1883
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1884
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1885
		    e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1886
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1887
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1888
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1889
		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1890
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1891
		    e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1892
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1893
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1894
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1895
		if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1896
		    && (!hw->autoneg)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1897
		    && (hw->forced_speed_duplex == e1000_10_full
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1898
			|| hw->forced_speed_duplex == e1000_10_half)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1899
			ret_val = e1000_polarity_reversal_workaround(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1900
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1901
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1902
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1903
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1904
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1905
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1906
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1907
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1908
 * e1000_config_collision_dist - set collision distance register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1909
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1910
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1911
 * Sets the collision distance in the Transmit Control register.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1912
 * Link should have been established previously. Reads the speed and duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1913
 * information from the Device Status register.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1914
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1915
void e1000_config_collision_dist(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1916
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1917
	u32 tctl, coll_dist;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1918
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1919
	e_dbg("e1000_config_collision_dist");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1920
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1921
	if (hw->mac_type < e1000_82543)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1922
		coll_dist = E1000_COLLISION_DISTANCE_82542;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1923
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1924
		coll_dist = E1000_COLLISION_DISTANCE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1925
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1926
	tctl = er32(TCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1927
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1928
	tctl &= ~E1000_TCTL_COLD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1929
	tctl |= coll_dist << E1000_COLD_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1930
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1931
	ew32(TCTL, tctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1932
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1933
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1934
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1935
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1936
 * e1000_config_mac_to_phy - sync phy and mac settings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1937
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1938
 * @mii_reg: data to write to the MII control register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1939
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1940
 * Sets MAC speed and duplex settings to reflect the those in the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1941
 * The contents of the PHY register containing the needed information need to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1942
 * be passed in.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1943
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1944
static s32 e1000_config_mac_to_phy(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1945
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1946
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1947
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1948
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1949
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1950
	e_dbg("e1000_config_mac_to_phy");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1951
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1952
	/* 82544 or newer MAC, Auto Speed Detection takes care of
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1953
	 * MAC speed/duplex configuration.*/
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1954
	if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1955
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1956
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1957
	/* Read the Device Control Register and set the bits to Force Speed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1958
	 * and Duplex.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1959
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1960
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1961
	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1962
	ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1963
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1964
	switch (hw->phy_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1965
	case e1000_phy_8201:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1966
		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1967
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1968
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1969
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1970
		if (phy_data & RTL_PHY_CTRL_FD)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1971
			ctrl |= E1000_CTRL_FD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1972
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1973
			ctrl &= ~E1000_CTRL_FD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1974
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1975
		if (phy_data & RTL_PHY_CTRL_SPD_100)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1976
			ctrl |= E1000_CTRL_SPD_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1977
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1978
			ctrl |= E1000_CTRL_SPD_10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1979
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1980
		e1000_config_collision_dist(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1981
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1982
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1983
		/* Set up duplex in the Device Control and Transmit Control
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1984
		 * registers depending on negotiated values.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1985
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1986
		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1987
		                             &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1988
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1989
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1990
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1991
		if (phy_data & M88E1000_PSSR_DPLX)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1992
			ctrl |= E1000_CTRL_FD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1993
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1994
			ctrl &= ~E1000_CTRL_FD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1995
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1996
		e1000_config_collision_dist(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1997
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1998
		/* Set up speed in the Device Control register depending on
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  1999
		 * negotiated values.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2000
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2001
		if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2002
			ctrl |= E1000_CTRL_SPD_1000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2003
		else if ((phy_data & M88E1000_PSSR_SPEED) ==
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2004
		         M88E1000_PSSR_100MBS)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2005
			ctrl |= E1000_CTRL_SPD_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2006
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2007
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2008
	/* Write the configured values back to the Device Control Reg. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2009
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2010
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2011
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2012
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2013
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2014
 * e1000_force_mac_fc - force flow control settings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2015
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2016
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2017
 * Forces the MAC's flow control settings.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2018
 * Sets the TFCE and RFCE bits in the device control register to reflect
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2019
 * the adapter settings. TFCE and RFCE need to be explicitly set by
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2020
 * software when a Copper PHY is used because autonegotiation is managed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2021
 * by the PHY rather than the MAC. Software must also configure these
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2022
 * bits when link is forced on a fiber connection.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2023
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2024
s32 e1000_force_mac_fc(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2025
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2026
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2027
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2028
	e_dbg("e1000_force_mac_fc");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2029
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2030
	/* Get the current configuration of the Device Control Register */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2031
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2032
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2033
	/* Because we didn't get link via the internal auto-negotiation
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2034
	 * mechanism (we either forced link or we got link via PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2035
	 * auto-neg), we have to manually enable/disable transmit an
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2036
	 * receive flow control.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2037
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2038
	 * The "Case" statement below enables/disable flow control
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2039
	 * according to the "hw->fc" parameter.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2040
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2041
	 * The possible values of the "fc" parameter are:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2042
	 *      0:  Flow control is completely disabled
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2043
	 *      1:  Rx flow control is enabled (we can receive pause
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2044
	 *          frames but not send pause frames).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2045
	 *      2:  Tx flow control is enabled (we can send pause frames
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2046
	 *          frames but we do not receive pause frames).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2047
	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2048
	 *  other:  No other values should be possible at this point.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2049
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2050
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2051
	switch (hw->fc) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2052
	case E1000_FC_NONE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2053
		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2054
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2055
	case E1000_FC_RX_PAUSE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2056
		ctrl &= (~E1000_CTRL_TFCE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2057
		ctrl |= E1000_CTRL_RFCE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2058
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2059
	case E1000_FC_TX_PAUSE:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2060
		ctrl &= (~E1000_CTRL_RFCE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2061
		ctrl |= E1000_CTRL_TFCE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2062
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2063
	case E1000_FC_FULL:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2064
		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2065
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2066
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2067
		e_dbg("Flow control param set incorrectly\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2068
		return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2069
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2070
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2071
	/* Disable TX Flow Control for 82542 (rev 2.0) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2072
	if (hw->mac_type == e1000_82542_rev2_0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2073
		ctrl &= (~E1000_CTRL_TFCE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2074
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2075
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2076
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2077
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2078
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2079
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2080
 * e1000_config_fc_after_link_up - configure flow control after autoneg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2081
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2082
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2083
 * Configures flow control settings after link is established
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2084
 * Should be called immediately after a valid link has been established.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2085
 * Forces MAC flow control settings if link was forced. When in MII/GMII mode
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2086
 * and autonegotiation is enabled, the MAC flow control settings will be set
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2087
 * based on the flow control negotiated by the PHY. In TBI mode, the TFCE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2088
 * and RFCE bits will be automatically set to the negotiated flow control mode.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2089
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2090
static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2091
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2092
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2093
	u16 mii_status_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2094
	u16 mii_nway_adv_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2095
	u16 mii_nway_lp_ability_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2096
	u16 speed;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2097
	u16 duplex;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2098
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2099
	e_dbg("e1000_config_fc_after_link_up");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2100
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2101
	/* Check for the case where we have fiber media and auto-neg failed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2102
	 * so we had to force link.  In this case, we need to force the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2103
	 * configuration of the MAC to match the "fc" parameter.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2104
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2105
	if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2106
	    || ((hw->media_type == e1000_media_type_internal_serdes)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2107
		&& (hw->autoneg_failed))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2108
	    || ((hw->media_type == e1000_media_type_copper)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2109
		&& (!hw->autoneg))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2110
		ret_val = e1000_force_mac_fc(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2111
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2112
			e_dbg("Error forcing flow control settings\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2113
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2114
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2115
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2116
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2117
	/* Check for the case where we have copper media and auto-neg is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2118
	 * enabled.  In this case, we need to check and see if Auto-Neg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2119
	 * has completed, and if so, how the PHY and link partner has
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2120
	 * flow control configured.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2121
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2122
	if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2123
		/* Read the MII Status Register and check to see if AutoNeg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2124
		 * has completed.  We read this twice because this reg has
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2125
		 * some "sticky" (latched) bits.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2126
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2127
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2128
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2129
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2130
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2131
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2132
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2133
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2134
		if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2135
			/* The AutoNeg process has completed, so we now need to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2136
			 * read both the Auto Negotiation Advertisement Register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2137
			 * (Address 4) and the Auto_Negotiation Base Page Ability
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2138
			 * Register (Address 5) to determine how flow control was
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2139
			 * negotiated.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2140
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2141
			ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2142
						     &mii_nway_adv_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2143
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2144
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2145
			ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2146
						     &mii_nway_lp_ability_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2147
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2148
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2149
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2150
			/* Two bits in the Auto Negotiation Advertisement Register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2151
			 * (Address 4) and two bits in the Auto Negotiation Base
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2152
			 * Page Ability Register (Address 5) determine flow control
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2153
			 * for both the PHY and the link partner.  The following
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2154
			 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2155
			 * 1999, describes these PAUSE resolution bits and how flow
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2156
			 * control is determined based upon these settings.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2157
			 * NOTE:  DC = Don't Care
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2158
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2159
			 *   LOCAL DEVICE  |   LINK PARTNER
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2160
			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2161
			 *-------|---------|-------|---------|--------------------
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2162
			 *   0   |    0    |  DC   |   DC    | E1000_FC_NONE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2163
			 *   0   |    1    |   0   |   DC    | E1000_FC_NONE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2164
			 *   0   |    1    |   1   |    0    | E1000_FC_NONE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2165
			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2166
			 *   1   |    0    |   0   |   DC    | E1000_FC_NONE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2167
			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2168
			 *   1   |    1    |   0   |    0    | E1000_FC_NONE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2169
			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2170
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2171
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2172
			/* Are both PAUSE bits set to 1?  If so, this implies
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2173
			 * Symmetric Flow Control is enabled at both ends.  The
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2174
			 * ASM_DIR bits are irrelevant per the spec.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2175
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2176
			 * For Symmetric Flow Control:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2177
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2178
			 *   LOCAL DEVICE  |   LINK PARTNER
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2179
			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2180
			 *-------|---------|-------|---------|--------------------
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2181
			 *   1   |   DC    |   1   |   DC    | E1000_FC_FULL
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2182
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2183
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2184
			if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2185
			    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2186
				/* Now we need to check if the user selected RX ONLY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2187
				 * of pause frames.  In this case, we had to advertise
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2188
				 * FULL flow control because we could not advertise RX
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2189
				 * ONLY. Hence, we must now check to see if we need to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2190
				 * turn OFF  the TRANSMISSION of PAUSE frames.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2191
				 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2192
				if (hw->original_fc == E1000_FC_FULL) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2193
					hw->fc = E1000_FC_FULL;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2194
					e_dbg("Flow Control = FULL.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2195
				} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2196
					hw->fc = E1000_FC_RX_PAUSE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2197
					e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2198
					    ("Flow Control = RX PAUSE frames only.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2199
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2200
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2201
			/* For receiving PAUSE frames ONLY.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2202
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2203
			 *   LOCAL DEVICE  |   LINK PARTNER
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2204
			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2205
			 *-------|---------|-------|---------|--------------------
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2206
			 *   0   |    1    |   1   |    1    | E1000_FC_TX_PAUSE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2207
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2208
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2209
			else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2210
				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2211
				 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2212
				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2213
			{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2214
				hw->fc = E1000_FC_TX_PAUSE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2215
				e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2216
				    ("Flow Control = TX PAUSE frames only.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2217
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2218
			/* For transmitting PAUSE frames ONLY.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2219
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2220
			 *   LOCAL DEVICE  |   LINK PARTNER
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2221
			 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2222
			 *-------|---------|-------|---------|--------------------
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2223
			 *   1   |    1    |   0   |    1    | E1000_FC_RX_PAUSE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2224
			 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2225
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2226
			else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2227
				 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2228
				 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2229
				 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2230
			{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2231
				hw->fc = E1000_FC_RX_PAUSE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2232
				e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2233
				    ("Flow Control = RX PAUSE frames only.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2234
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2235
			/* Per the IEEE spec, at this point flow control should be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2236
			 * disabled.  However, we want to consider that we could
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2237
			 * be connected to a legacy switch that doesn't advertise
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2238
			 * desired flow control, but can be forced on the link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2239
			 * partner.  So if we advertised no flow control, that is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2240
			 * what we will resolve to.  If we advertised some kind of
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2241
			 * receive capability (Rx Pause Only or Full Flow Control)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2242
			 * and the link partner advertised none, we will configure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2243
			 * ourselves to enable Rx Flow Control only.  We can do
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2244
			 * this safely for two reasons:  If the link partner really
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2245
			 * didn't want flow control enabled, and we enable Rx, no
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2246
			 * harm done since we won't be receiving any PAUSE frames
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2247
			 * anyway.  If the intent on the link partner was to have
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2248
			 * flow control enabled, then by us enabling RX only, we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2249
			 * can at least receive pause frames and process them.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2250
			 * This is a good idea because in most cases, since we are
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2251
			 * predominantly a server NIC, more times than not we will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2252
			 * be asked to delay transmission of packets than asking
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2253
			 * our link partner to pause transmission of frames.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2254
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2255
			else if ((hw->original_fc == E1000_FC_NONE ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2256
				  hw->original_fc == E1000_FC_TX_PAUSE) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2257
				 hw->fc_strict_ieee) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2258
				hw->fc = E1000_FC_NONE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2259
				e_dbg("Flow Control = NONE.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2260
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2261
				hw->fc = E1000_FC_RX_PAUSE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2262
				e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2263
				    ("Flow Control = RX PAUSE frames only.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2264
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2265
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2266
			/* Now we need to do one last check...  If we auto-
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2267
			 * negotiated to HALF DUPLEX, flow control should not be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2268
			 * enabled per IEEE 802.3 spec.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2269
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2270
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2271
			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2272
			if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2273
				e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2274
				    ("Error getting link speed and duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2275
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2276
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2277
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2278
			if (duplex == HALF_DUPLEX)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2279
				hw->fc = E1000_FC_NONE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2280
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2281
			/* Now we call a subroutine to actually force the MAC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2282
			 * controller to use the correct flow control settings.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2283
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2284
			ret_val = e1000_force_mac_fc(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2285
			if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2286
				e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2287
				    ("Error forcing flow control settings\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2288
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2289
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2290
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2291
			e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2292
			    ("Copper PHY and Auto Neg has not completed.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2293
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2294
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2295
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2296
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2297
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2298
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2299
 * e1000_check_for_serdes_link_generic - Check for link (Serdes)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2300
 * @hw: pointer to the HW structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2301
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2302
 * Checks for link up on the hardware.  If link is not up and we have
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2303
 * a signal, then we need to force link up.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2304
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2305
static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2306
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2307
	u32 rxcw;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2308
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2309
	u32 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2310
	s32 ret_val = E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2311
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2312
	e_dbg("e1000_check_for_serdes_link_generic");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2313
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2314
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2315
	status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2316
	rxcw = er32(RXCW);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2317
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2318
	/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2319
	 * If we don't have link (auto-negotiation failed or link partner
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2320
	 * cannot auto-negotiate), and our link partner is not trying to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2321
	 * auto-negotiate with us (we are receiving idles or data),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2322
	 * we need to force link up. We also need to give auto-negotiation
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2323
	 * time to complete.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2324
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2325
	/* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2326
	if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2327
		if (hw->autoneg_failed == 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2328
			hw->autoneg_failed = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2329
			goto out;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2330
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2331
		e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2332
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2333
		/* Disable auto-negotiation in the TXCW register */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2334
		ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2335
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2336
		/* Force link-up and also force full-duplex. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2337
		ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2338
		ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2339
		ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2340
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2341
		/* Configure Flow Control after forcing link up. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2342
		ret_val = e1000_config_fc_after_link_up(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2343
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2344
			e_dbg("Error configuring flow control\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2345
			goto out;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2346
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2347
	} else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2348
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2349
		 * If we are forcing link and we are receiving /C/ ordered
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2350
		 * sets, re-enable auto-negotiation in the TXCW register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2351
		 * and disable forced link in the Device Control register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2352
		 * in an attempt to auto-negotiate with our link partner.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2353
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2354
		e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2355
		ew32(TXCW, hw->txcw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2356
		ew32(CTRL, (ctrl & ~E1000_CTRL_SLU));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2357
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2358
		hw->serdes_has_link = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2359
	} else if (!(E1000_TXCW_ANE & er32(TXCW))) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2360
		/*
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2361
		 * If we force link for non-auto-negotiation switch, check
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2362
		 * link status based on MAC synchronization for internal
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2363
		 * serdes media type.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2364
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2365
		/* SYNCH bit and IV bit are sticky. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2366
		udelay(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2367
		rxcw = er32(RXCW);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2368
		if (rxcw & E1000_RXCW_SYNCH) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2369
			if (!(rxcw & E1000_RXCW_IV)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2370
				hw->serdes_has_link = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2371
				e_dbg("SERDES: Link up - forced.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2372
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2373
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2374
			hw->serdes_has_link = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2375
			e_dbg("SERDES: Link down - force failed.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2376
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2377
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2378
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2379
	if (E1000_TXCW_ANE & er32(TXCW)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2380
		status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2381
		if (status & E1000_STATUS_LU) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2382
			/* SYNCH bit and IV bit are sticky, so reread rxcw. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2383
			udelay(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2384
			rxcw = er32(RXCW);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2385
			if (rxcw & E1000_RXCW_SYNCH) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2386
				if (!(rxcw & E1000_RXCW_IV)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2387
					hw->serdes_has_link = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2388
					e_dbg("SERDES: Link up - autoneg "
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2389
						 "completed successfully.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2390
				} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2391
					hw->serdes_has_link = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2392
					e_dbg("SERDES: Link down - invalid"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2393
						 "codewords detected in autoneg.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2394
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2395
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2396
				hw->serdes_has_link = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2397
				e_dbg("SERDES: Link down - no sync.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2398
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2399
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2400
			hw->serdes_has_link = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2401
			e_dbg("SERDES: Link down - autoneg failed\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2402
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2403
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2404
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2405
      out:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2406
	return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2407
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2408
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2409
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2410
 * e1000_check_for_link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2411
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2412
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2413
 * Checks to see if the link status of the hardware has changed.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2414
 * Called by any function that needs to check the link status of the adapter.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2415
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2416
s32 e1000_check_for_link(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2417
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2418
	u32 rxcw __attribute__ ((unused)) = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2419
	u32 ctrl __attribute__ ((unused));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2420
	u32 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2421
	u32 rctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2422
	u32 icr;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2423
	u32 signal __attribute__ ((unused)) = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2424
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2425
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2426
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2427
	e_dbg("e1000_check_for_link");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2428
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2429
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2430
	status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2431
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2432
	/* On adapters with a MAC newer than 82544, SW Definable pin 1 will be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2433
	 * set when the optics detect a signal. On older adapters, it will be
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2434
	 * cleared when there is a signal.  This applies to fiber media only.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2435
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2436
	if ((hw->media_type == e1000_media_type_fiber) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2437
	    (hw->media_type == e1000_media_type_internal_serdes)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2438
		rxcw = er32(RXCW);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2439
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2440
		if (hw->media_type == e1000_media_type_fiber) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2441
			signal =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2442
			    (hw->mac_type >
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2443
			     e1000_82544) ? E1000_CTRL_SWDPIN1 : 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2444
			if (status & E1000_STATUS_LU)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2445
				hw->get_link_status = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2446
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2447
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2448
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2449
	/* If we have a copper PHY then we only want to go out to the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2450
	 * registers to see if Auto-Neg has completed and/or if our link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2451
	 * status has changed.  The get_link_status flag will be set if we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2452
	 * receive a Link Status Change interrupt or we have Rx Sequence
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2453
	 * Errors.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2454
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2455
	if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2456
		/* First we want to see if the MII Status Register reports
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2457
		 * link.  If so, then we want to get the current speed/duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2458
		 * of the PHY.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2459
		 * Read the register twice since the link bit is sticky.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2460
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2461
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2462
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2463
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2464
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2465
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2466
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2467
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2468
		if (phy_data & MII_SR_LINK_STATUS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2469
			hw->get_link_status = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2470
			/* Check if there was DownShift, must be checked immediately after
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2471
			 * link-up */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2472
			e1000_check_downshift(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2473
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2474
			/* If we are on 82544 or 82543 silicon and speed/duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2475
			 * are forced to 10H or 10F, then we will implement the polarity
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2476
			 * reversal workaround.  We disable interrupts first, and upon
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2477
			 * returning, place the devices interrupt state to its previous
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2478
			 * value except for the link status change interrupt which will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2479
			 * happen due to the execution of this workaround.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2480
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2481
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2482
			if ((hw->mac_type == e1000_82544
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2483
			     || hw->mac_type == e1000_82543) && (!hw->autoneg)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2484
			    && (hw->forced_speed_duplex == e1000_10_full
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2485
				|| hw->forced_speed_duplex == e1000_10_half)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2486
				ew32(IMC, 0xffffffff);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2487
				ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2488
				    e1000_polarity_reversal_workaround(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2489
				icr = er32(ICR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2490
				ew32(ICS, (icr & ~E1000_ICS_LSC));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2491
				ew32(IMS, IMS_ENABLE_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2492
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2493
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2494
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2495
			/* No link detected */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2496
			e1000_config_dsp_after_link_change(hw, false);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2497
			return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2498
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2499
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2500
		/* If we are forcing speed/duplex, then we simply return since
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2501
		 * we have already determined whether we have link or not.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2502
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2503
		if (!hw->autoneg)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2504
			return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2505
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2506
		/* optimize the dsp settings for the igp phy */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2507
		e1000_config_dsp_after_link_change(hw, true);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2508
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2509
		/* We have a M88E1000 PHY and Auto-Neg is enabled.  If we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2510
		 * have Si on board that is 82544 or newer, Auto
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2511
		 * Speed Detection takes care of MAC speed/duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2512
		 * configuration.  So we only need to configure Collision
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2513
		 * Distance in the MAC.  Otherwise, we need to force
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2514
		 * speed/duplex on the MAC to the current PHY speed/duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2515
		 * settings.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2516
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2517
		if ((hw->mac_type >= e1000_82544) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2518
		    (hw->mac_type != e1000_ce4100))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2519
			e1000_config_collision_dist(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2520
		else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2521
			ret_val = e1000_config_mac_to_phy(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2522
			if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2523
				e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2524
				    ("Error configuring MAC to PHY settings\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2525
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2526
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2527
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2528
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2529
		/* Configure Flow Control now that Auto-Neg has completed. First, we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2530
		 * need to restore the desired flow control settings because we may
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2531
		 * have had to re-autoneg with a different link partner.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2532
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2533
		ret_val = e1000_config_fc_after_link_up(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2534
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2535
			e_dbg("Error configuring flow control\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2536
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2537
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2538
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2539
		/* At this point we know that we are on copper and we have
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2540
		 * auto-negotiated link.  These are conditions for checking the link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2541
		 * partner capability register.  We use the link speed to determine if
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2542
		 * TBI compatibility needs to be turned on or off.  If the link is not
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2543
		 * at gigabit speed, then TBI compatibility is not needed.  If we are
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2544
		 * at gigabit speed, we turn on TBI compatibility.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2545
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2546
		if (hw->tbi_compatibility_en) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2547
			u16 speed, duplex;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2548
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2549
			    e1000_get_speed_and_duplex(hw, &speed, &duplex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2550
			if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2551
				e_dbg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2552
				    ("Error getting link speed and duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2553
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2554
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2555
			if (speed != SPEED_1000) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2556
				/* If link speed is not set to gigabit speed, we do not need
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2557
				 * to enable TBI compatibility.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2558
				 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2559
				if (hw->tbi_compatibility_on) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2560
					/* If we previously were in the mode, turn it off. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2561
					rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2562
					rctl &= ~E1000_RCTL_SBP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2563
					ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2564
					hw->tbi_compatibility_on = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2565
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2566
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2567
				/* If TBI compatibility is was previously off, turn it on. For
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2568
				 * compatibility with a TBI link partner, we will store bad
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2569
				 * packets. Some frames have an additional byte on the end and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2570
				 * will look like CRC errors to to the hardware.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2571
				 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2572
				if (!hw->tbi_compatibility_on) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2573
					hw->tbi_compatibility_on = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2574
					rctl = er32(RCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2575
					rctl |= E1000_RCTL_SBP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2576
					ew32(RCTL, rctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2577
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2578
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2579
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2580
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2581
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2582
	if ((hw->media_type == e1000_media_type_fiber) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2583
	    (hw->media_type == e1000_media_type_internal_serdes))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2584
		e1000_check_for_serdes_link_generic(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2585
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2586
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2587
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2588
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2589
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2590
 * e1000_get_speed_and_duplex
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2591
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2592
 * @speed: Speed of the connection
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2593
 * @duplex: Duplex setting of the connection
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2594
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2595
 * Detects the current speed and duplex settings of the hardware.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2596
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2597
s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2598
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2599
	u32 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2600
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2601
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2602
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2603
	e_dbg("e1000_get_speed_and_duplex");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2604
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2605
	if (hw->mac_type >= e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2606
		status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2607
		if (status & E1000_STATUS_SPEED_1000) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2608
			*speed = SPEED_1000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2609
			e_dbg("1000 Mbs, ");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2610
		} else if (status & E1000_STATUS_SPEED_100) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2611
			*speed = SPEED_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2612
			e_dbg("100 Mbs, ");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2613
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2614
			*speed = SPEED_10;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2615
			e_dbg("10 Mbs, ");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2616
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2617
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2618
		if (status & E1000_STATUS_FD) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2619
			*duplex = FULL_DUPLEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2620
			e_dbg("Full Duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2621
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2622
			*duplex = HALF_DUPLEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2623
			e_dbg(" Half Duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2624
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2625
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2626
		e_dbg("1000 Mbs, Full Duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2627
		*speed = SPEED_1000;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2628
		*duplex = FULL_DUPLEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2629
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2630
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2631
	/* IGP01 PHY may advertise full duplex operation after speed downgrade even
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2632
	 * if it is operating at half duplex.  Here we set the duplex settings to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2633
	 * match the duplex in the link partner's capabilities.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2634
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2635
	if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2636
		ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2637
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2638
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2639
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2640
		if (!(phy_data & NWAY_ER_LP_NWAY_CAPS))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2641
			*duplex = HALF_DUPLEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2642
		else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2643
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2644
			    e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2645
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2646
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2647
			if ((*speed == SPEED_100
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2648
			     && !(phy_data & NWAY_LPAR_100TX_FD_CAPS))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2649
			    || (*speed == SPEED_10
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2650
				&& !(phy_data & NWAY_LPAR_10T_FD_CAPS)))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2651
				*duplex = HALF_DUPLEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2652
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2653
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2654
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2655
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2656
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2657
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2658
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2659
 * e1000_wait_autoneg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2660
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2661
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2662
 * Blocks until autoneg completes or times out (~4.5 seconds)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2663
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2664
static s32 e1000_wait_autoneg(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2665
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2666
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2667
	u16 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2668
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2669
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2670
	e_dbg("e1000_wait_autoneg");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2671
	e_dbg("Waiting for Auto-Neg to complete.\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2672
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2673
	/* We will wait for autoneg to complete or 4.5 seconds to expire. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2674
	for (i = PHY_AUTO_NEG_TIME; i > 0; i--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2675
		/* Read the MII Status Register and wait for Auto-Neg
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2676
		 * Complete bit to be set.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2677
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2678
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2679
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2680
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2681
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2682
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2683
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2684
		if (phy_data & MII_SR_AUTONEG_COMPLETE) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2685
			return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2686
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2687
		msleep(100);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2688
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2689
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2690
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2691
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2692
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2693
 * e1000_raise_mdi_clk - Raises the Management Data Clock
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2694
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2695
 * @ctrl: Device control register's current value
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2696
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2697
static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2698
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2699
	/* Raise the clock input to the Management Data Clock (by setting the MDC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2700
	 * bit), and then delay 10 microseconds.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2701
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2702
	ew32(CTRL, (*ctrl | E1000_CTRL_MDC));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2703
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2704
	udelay(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2705
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2706
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2707
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2708
 * e1000_lower_mdi_clk - Lowers the Management Data Clock
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2709
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2710
 * @ctrl: Device control register's current value
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2711
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2712
static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2713
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2714
	/* Lower the clock input to the Management Data Clock (by clearing the MDC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2715
	 * bit), and then delay 10 microseconds.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2716
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2717
	ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2718
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2719
	udelay(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2720
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2721
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2722
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2723
 * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2724
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2725
 * @data: Data to send out to the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2726
 * @count: Number of bits to shift out
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2727
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2728
 * Bits are shifted out in MSB to LSB order.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2729
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2730
static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2731
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2732
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2733
	u32 mask;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2734
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2735
	/* We need to shift "count" number of bits out to the PHY. So, the value
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2736
	 * in the "data" parameter will be shifted out to the PHY one bit at a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2737
	 * time. In order to do this, "data" must be broken down into bits.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2738
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2739
	mask = 0x01;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2740
	mask <<= (count - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2741
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2742
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2743
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2744
	/* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2745
	ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2746
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2747
	while (mask) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2748
		/* A "1" is shifted out to the PHY by setting the MDIO bit to "1" and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2749
		 * then raising and lowering the Management Data Clock. A "0" is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2750
		 * shifted out to the PHY by setting the MDIO bit to "0" and then
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2751
		 * raising and lowering the clock.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2752
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2753
		if (data & mask)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2754
			ctrl |= E1000_CTRL_MDIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2755
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2756
			ctrl &= ~E1000_CTRL_MDIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2757
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2758
		ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2759
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2760
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2761
		udelay(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2762
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2763
		e1000_raise_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2764
		e1000_lower_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2765
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2766
		mask = mask >> 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2767
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2768
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2769
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2770
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2771
 * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2772
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2773
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2774
 * Bits are shifted in in MSB to LSB order.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2775
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2776
static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2777
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2778
	u32 ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2779
	u16 data = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2780
	u8 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2781
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2782
	/* In order to read a register from the PHY, we need to shift in a total
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2783
	 * of 18 bits from the PHY. The first two bit (turnaround) times are used
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2784
	 * to avoid contention on the MDIO pin when a read operation is performed.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2785
	 * These two bits are ignored by us and thrown away. Bits are "shifted in"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2786
	 * by raising the input to the Management Data Clock (setting the MDC bit),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2787
	 * and then reading the value of the MDIO bit.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2788
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2789
	ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2790
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2791
	/* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2792
	ctrl &= ~E1000_CTRL_MDIO_DIR;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2793
	ctrl &= ~E1000_CTRL_MDIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2794
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2795
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2796
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2797
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2798
	/* Raise and Lower the clock before reading in the data. This accounts for
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2799
	 * the turnaround bits. The first clock occurred when we clocked out the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2800
	 * last bit of the Register Address.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2801
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2802
	e1000_raise_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2803
	e1000_lower_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2804
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2805
	for (data = 0, i = 0; i < 16; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2806
		data = data << 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2807
		e1000_raise_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2808
		ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2809
		/* Check to see if we shifted in a "1". */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2810
		if (ctrl & E1000_CTRL_MDIO)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2811
			data |= 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2812
		e1000_lower_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2813
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2814
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2815
	e1000_raise_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2816
	e1000_lower_mdi_clk(hw, &ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2817
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2818
	return data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2819
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2820
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2821
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2822
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2823
 * e1000_read_phy_reg - read a phy register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2824
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2825
 * @reg_addr: address of the PHY register to read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2826
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2827
 * Reads the value from a PHY register, if the value is on a specific non zero
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2828
 * page, sets the page first.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2829
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2830
s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2831
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2832
	u32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2833
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2834
	e_dbg("e1000_read_phy_reg");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2835
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2836
	if ((hw->phy_type == e1000_phy_igp) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2837
	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2838
		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2839
						 (u16) reg_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2840
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2841
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2842
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2843
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2844
	ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2845
					phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2846
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2847
	return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2848
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2849
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2850
static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2851
				 u16 *phy_data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2852
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2853
	u32 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2854
	u32 mdic = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2855
	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2856
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2857
	e_dbg("e1000_read_phy_reg_ex");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2858
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2859
	if (reg_addr > MAX_PHY_REG_ADDRESS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2860
		e_dbg("PHY Address %d is out of range\n", reg_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2861
		return -E1000_ERR_PARAM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2862
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2863
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2864
	if (hw->mac_type > e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2865
		/* Set up Op-code, Phy Address, and register address in the MDI
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2866
		 * Control register.  The MAC will take care of interfacing with the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2867
		 * PHY to retrieve the desired data.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2868
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2869
		if (hw->mac_type == e1000_ce4100) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2870
			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2871
				(phy_addr << E1000_MDIC_PHY_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2872
				(INTEL_CE_GBE_MDIC_OP_READ) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2873
				(INTEL_CE_GBE_MDIC_GO));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2874
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2875
			writel(mdic, E1000_MDIO_CMD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2876
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2877
			/* Poll the ready bit to see if the MDI read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2878
			 * completed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2879
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2880
			for (i = 0; i < 64; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2881
				udelay(50);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2882
				mdic = readl(E1000_MDIO_CMD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2883
				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2884
					break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2885
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2886
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2887
			if (mdic & INTEL_CE_GBE_MDIC_GO) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2888
				e_dbg("MDI Read did not complete\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2889
				return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2890
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2891
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2892
			mdic = readl(E1000_MDIO_STS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2893
			if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2894
				e_dbg("MDI Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2895
				return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2896
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2897
			*phy_data = (u16) mdic;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2898
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2899
			mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2900
				(phy_addr << E1000_MDIC_PHY_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2901
				(E1000_MDIC_OP_READ));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2902
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2903
			ew32(MDIC, mdic);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2904
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2905
			/* Poll the ready bit to see if the MDI read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2906
			 * completed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2907
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2908
			for (i = 0; i < 64; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2909
				udelay(50);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2910
				mdic = er32(MDIC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2911
				if (mdic & E1000_MDIC_READY)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2912
					break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2913
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2914
			if (!(mdic & E1000_MDIC_READY)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2915
				e_dbg("MDI Read did not complete\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2916
				return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2917
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2918
			if (mdic & E1000_MDIC_ERROR) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2919
				e_dbg("MDI Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2920
				return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2921
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2922
			*phy_data = (u16) mdic;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2923
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2924
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2925
		/* We must first send a preamble through the MDIO pin to signal the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2926
		 * beginning of an MII instruction.  This is done by sending 32
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2927
		 * consecutive "1" bits.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2928
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2929
		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2930
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2931
		/* Now combine the next few fields that are required for a read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2932
		 * operation.  We use this method instead of calling the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2933
		 * e1000_shift_out_mdi_bits routine five different times. The format of
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2934
		 * a MII read instruction consists of a shift out of 14 bits and is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2935
		 * defined as follows:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2936
		 *    <Preamble><SOF><Op Code><Phy Addr><Reg Addr>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2937
		 * followed by a shift in of 18 bits.  This first two bits shifted in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2938
		 * are TurnAround bits used to avoid contention on the MDIO pin when a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2939
		 * READ operation is performed.  These two bits are thrown away
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2940
		 * followed by a shift in of 16 bits which contains the desired data.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2941
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2942
		mdic = ((reg_addr) | (phy_addr << 5) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2943
			(PHY_OP_READ << 10) | (PHY_SOF << 12));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2944
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2945
		e1000_shift_out_mdi_bits(hw, mdic, 14);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2946
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2947
		/* Now that we've shifted out the read command to the MII, we need to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2948
		 * "shift in" the 16-bit value (18 total bits) of the requested PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2949
		 * register address.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2950
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2951
		*phy_data = e1000_shift_in_mdi_bits(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2952
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2953
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2954
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2955
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2956
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2957
 * e1000_write_phy_reg - write a phy register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2958
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2959
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2960
 * @reg_addr: address of the PHY register to write
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2961
 * @data: data to write to the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2962
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2963
 * Writes a value to a PHY register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2964
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2965
s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2966
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2967
	u32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2968
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2969
	e_dbg("e1000_write_phy_reg");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2970
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2971
	if ((hw->phy_type == e1000_phy_igp) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2972
	    (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2973
		ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2974
						 (u16) reg_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2975
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2976
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2977
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2978
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2979
	ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2980
					 phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2981
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2982
	return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2983
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2984
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2985
static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2986
				  u16 phy_data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2987
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2988
	u32 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2989
	u32 mdic = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2990
	const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2991
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2992
	e_dbg("e1000_write_phy_reg_ex");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2993
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2994
	if (reg_addr > MAX_PHY_REG_ADDRESS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2995
		e_dbg("PHY Address %d is out of range\n", reg_addr);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2996
		return -E1000_ERR_PARAM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2997
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2998
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  2999
	if (hw->mac_type > e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3000
		/* Set up Op-code, Phy Address, register address, and data
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3001
		 * intended for the PHY register in the MDI Control register.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3002
		 * The MAC will take care of interfacing with the PHY to send
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3003
		 * the desired data.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3004
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3005
		if (hw->mac_type == e1000_ce4100) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3006
			mdic = (((u32) phy_data) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3007
				(reg_addr << E1000_MDIC_REG_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3008
				(phy_addr << E1000_MDIC_PHY_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3009
				(INTEL_CE_GBE_MDIC_OP_WRITE) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3010
				(INTEL_CE_GBE_MDIC_GO));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3011
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3012
			writel(mdic, E1000_MDIO_CMD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3013
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3014
			/* Poll the ready bit to see if the MDI read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3015
			 * completed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3016
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3017
			for (i = 0; i < 640; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3018
				udelay(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3019
				mdic = readl(E1000_MDIO_CMD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3020
				if (!(mdic & INTEL_CE_GBE_MDIC_GO))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3021
					break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3022
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3023
			if (mdic & INTEL_CE_GBE_MDIC_GO) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3024
				e_dbg("MDI Write did not complete\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3025
				return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3026
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3027
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3028
			mdic = (((u32) phy_data) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3029
				(reg_addr << E1000_MDIC_REG_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3030
				(phy_addr << E1000_MDIC_PHY_SHIFT) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3031
				(E1000_MDIC_OP_WRITE));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3032
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3033
			ew32(MDIC, mdic);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3034
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3035
			/* Poll the ready bit to see if the MDI read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3036
			 * completed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3037
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3038
			for (i = 0; i < 641; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3039
				udelay(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3040
				mdic = er32(MDIC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3041
				if (mdic & E1000_MDIC_READY)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3042
					break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3043
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3044
			if (!(mdic & E1000_MDIC_READY)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3045
				e_dbg("MDI Write did not complete\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3046
				return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3047
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3048
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3049
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3050
		/* We'll need to use the SW defined pins to shift the write command
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3051
		 * out to the PHY. We first send a preamble to the PHY to signal the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3052
		 * beginning of the MII instruction.  This is done by sending 32
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3053
		 * consecutive "1" bits.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3054
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3055
		e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3056
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3057
		/* Now combine the remaining required fields that will indicate a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3058
		 * write operation. We use this method instead of calling the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3059
		 * e1000_shift_out_mdi_bits routine for each field in the command. The
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3060
		 * format of a MII write instruction is as follows:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3061
		 * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3062
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3063
		mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3064
			(PHY_OP_WRITE << 12) | (PHY_SOF << 14));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3065
		mdic <<= 16;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3066
		mdic |= (u32) phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3067
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3068
		e1000_shift_out_mdi_bits(hw, mdic, 32);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3069
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3070
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3071
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3072
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3073
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3074
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3075
 * e1000_phy_hw_reset - reset the phy, hardware style
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3076
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3077
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3078
 * Returns the PHY to the power-on reset state
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3079
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3080
s32 e1000_phy_hw_reset(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3081
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3082
	u32 ctrl, ctrl_ext;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3083
	u32 led_ctrl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3084
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3085
	e_dbg("e1000_phy_hw_reset");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3086
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3087
	e_dbg("Resetting Phy...\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3088
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3089
	if (hw->mac_type > e1000_82543) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3090
		/* Read the device control register and assert the E1000_CTRL_PHY_RST
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3091
		 * bit. Then, take it out of reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3092
		 * For e1000 hardware, we delay for 10ms between the assert
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3093
		 * and deassert.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3094
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3095
		ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3096
		ew32(CTRL, ctrl | E1000_CTRL_PHY_RST);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3097
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3098
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3099
		msleep(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3100
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3101
		ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3102
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3103
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3104
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3105
		/* Read the Extended Device Control Register, assert the PHY_RESET_DIR
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3106
		 * bit to put the PHY into reset. Then, take it out of reset.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3107
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3108
		ctrl_ext = er32(CTRL_EXT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3109
		ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3110
		ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3111
		ew32(CTRL_EXT, ctrl_ext);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3112
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3113
		msleep(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3114
		ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3115
		ew32(CTRL_EXT, ctrl_ext);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3116
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3117
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3118
	udelay(150);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3119
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3120
	if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3121
		/* Configure activity LED after PHY reset */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3122
		led_ctrl = er32(LEDCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3123
		led_ctrl &= IGP_ACTIVITY_LED_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3124
		led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3125
		ew32(LEDCTL, led_ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3126
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3127
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3128
	/* Wait for FW to finish PHY configuration. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3129
	return e1000_get_phy_cfg_done(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3130
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3131
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3132
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3133
 * e1000_phy_reset - reset the phy to commit settings
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3134
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3135
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3136
 * Resets the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3137
 * Sets bit 15 of the MII Control register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3138
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3139
s32 e1000_phy_reset(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3140
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3141
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3142
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3143
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3144
	e_dbg("e1000_phy_reset");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3145
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3146
	switch (hw->phy_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3147
	case e1000_phy_igp:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3148
		ret_val = e1000_phy_hw_reset(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3149
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3150
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3151
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3152
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3153
		ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3154
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3155
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3156
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3157
		phy_data |= MII_CR_RESET;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3158
		ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3159
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3160
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3161
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3162
		udelay(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3163
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3164
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3165
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3166
	if (hw->phy_type == e1000_phy_igp)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3167
		e1000_phy_init_script(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3168
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3169
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3170
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3171
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3172
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3173
 * e1000_detect_gig_phy - check the phy type
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3174
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3175
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3176
 * Probes the expected PHY address for known PHY IDs
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3177
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3178
static s32 e1000_detect_gig_phy(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3179
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3180
	s32 phy_init_status, ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3181
	u16 phy_id_high, phy_id_low;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3182
	bool match = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3183
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3184
	e_dbg("e1000_detect_gig_phy");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3185
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3186
	if (hw->phy_id != 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3187
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3188
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3189
	/* Read the PHY ID Registers to identify which PHY is onboard. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3190
	ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3191
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3192
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3193
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3194
	hw->phy_id = (u32) (phy_id_high << 16);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3195
	udelay(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3196
	ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3197
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3198
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3199
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3200
	hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3201
	hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3202
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3203
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3204
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3205
		if (hw->phy_id == M88E1000_E_PHY_ID)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3206
			match = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3207
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3208
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3209
		if (hw->phy_id == M88E1000_I_PHY_ID)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3210
			match = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3211
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3212
	case e1000_82540:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3213
	case e1000_82545:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3214
	case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3215
	case e1000_82546:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3216
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3217
		if (hw->phy_id == M88E1011_I_PHY_ID)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3218
			match = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3219
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3220
	case e1000_ce4100:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3221
		if ((hw->phy_id == RTL8211B_PHY_ID) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3222
		    (hw->phy_id == RTL8201N_PHY_ID) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3223
		    (hw->phy_id == M88E1118_E_PHY_ID))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3224
			match = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3225
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3226
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3227
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3228
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3229
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3230
		if (hw->phy_id == IGP01E1000_I_PHY_ID)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3231
			match = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3232
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3233
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3234
		e_dbg("Invalid MAC type %d\n", hw->mac_type);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3235
		return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3236
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3237
	phy_init_status = e1000_set_phy_type(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3238
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3239
	if ((match) && (phy_init_status == E1000_SUCCESS)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3240
		e_dbg("PHY ID 0x%X detected\n", hw->phy_id);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3241
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3242
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3243
	e_dbg("Invalid PHY ID 0x%X\n", hw->phy_id);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3244
	return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3245
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3246
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3247
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3248
 * e1000_phy_reset_dsp - reset DSP
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3249
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3250
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3251
 * Resets the PHY's DSP
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3252
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3253
static s32 e1000_phy_reset_dsp(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3254
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3255
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3256
	e_dbg("e1000_phy_reset_dsp");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3257
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3258
	do {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3259
		ret_val = e1000_write_phy_reg(hw, 29, 0x001d);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3260
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3261
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3262
		ret_val = e1000_write_phy_reg(hw, 30, 0x00c1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3263
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3264
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3265
		ret_val = e1000_write_phy_reg(hw, 30, 0x0000);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3266
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3267
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3268
		ret_val = E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3269
	} while (0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3270
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3271
	return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3272
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3273
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3274
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3275
 * e1000_phy_igp_get_info - get igp specific registers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3276
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3277
 * @phy_info: PHY information structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3278
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3279
 * Get PHY information from various PHY registers for igp PHY only.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3280
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3281
static s32 e1000_phy_igp_get_info(struct e1000_hw *hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3282
				  struct e1000_phy_info *phy_info)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3283
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3284
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3285
	u16 phy_data, min_length, max_length, average;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3286
	e1000_rev_polarity polarity;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3287
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3288
	e_dbg("e1000_phy_igp_get_info");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3289
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3290
	/* The downshift status is checked only once, after link is established,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3291
	 * and it stored in the hw->speed_downgraded parameter. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3292
	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3293
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3294
	/* IGP01E1000 does not need to support it. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3295
	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3296
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3297
	/* IGP01E1000 always correct polarity reversal */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3298
	phy_info->polarity_correction = e1000_polarity_reversal_enabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3299
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3300
	/* Check polarity status */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3301
	ret_val = e1000_check_polarity(hw, &polarity);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3302
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3303
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3304
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3305
	phy_info->cable_polarity = polarity;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3306
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3307
	ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3308
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3309
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3310
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3311
	phy_info->mdix_mode =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3312
	    (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3313
				 IGP01E1000_PSSR_MDIX_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3314
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3315
	if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3316
	    IGP01E1000_PSSR_SPEED_1000MBPS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3317
		/* Local/Remote Receiver Information are only valid at 1000 Mbps */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3318
		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3319
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3320
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3321
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3322
		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3323
				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3324
		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3325
		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3326
				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3327
		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3328
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3329
		/* Get cable length */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3330
		ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3331
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3332
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3333
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3334
		/* Translate to old method */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3335
		average = (max_length + min_length) / 2;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3336
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3337
		if (average <= e1000_igp_cable_length_50)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3338
			phy_info->cable_length = e1000_cable_length_50;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3339
		else if (average <= e1000_igp_cable_length_80)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3340
			phy_info->cable_length = e1000_cable_length_50_80;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3341
		else if (average <= e1000_igp_cable_length_110)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3342
			phy_info->cable_length = e1000_cable_length_80_110;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3343
		else if (average <= e1000_igp_cable_length_140)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3344
			phy_info->cable_length = e1000_cable_length_110_140;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3345
		else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3346
			phy_info->cable_length = e1000_cable_length_140;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3347
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3348
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3349
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3350
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3351
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3352
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3353
 * e1000_phy_m88_get_info - get m88 specific registers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3354
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3355
 * @phy_info: PHY information structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3356
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3357
 * Get PHY information from various PHY registers for m88 PHY only.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3358
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3359
static s32 e1000_phy_m88_get_info(struct e1000_hw *hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3360
				  struct e1000_phy_info *phy_info)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3361
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3362
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3363
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3364
	e1000_rev_polarity polarity;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3365
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3366
	e_dbg("e1000_phy_m88_get_info");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3367
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3368
	/* The downshift status is checked only once, after link is established,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3369
	 * and it stored in the hw->speed_downgraded parameter. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3370
	phy_info->downshift = (e1000_downshift) hw->speed_downgraded;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3371
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3372
	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3373
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3374
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3375
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3376
	phy_info->extended_10bt_distance =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3377
	    ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3378
	     M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3379
	    e1000_10bt_ext_dist_enable_lower :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3380
	    e1000_10bt_ext_dist_enable_normal;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3381
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3382
	phy_info->polarity_correction =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3383
	    ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3384
	     M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3385
	    e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3386
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3387
	/* Check polarity status */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3388
	ret_val = e1000_check_polarity(hw, &polarity);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3389
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3390
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3391
	phy_info->cable_polarity = polarity;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3392
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3393
	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3394
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3395
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3396
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3397
	phy_info->mdix_mode =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3398
	    (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3399
				 M88E1000_PSSR_MDIX_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3400
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3401
	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3402
		/* Cable Length Estimation and Local/Remote Receiver Information
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3403
		 * are only valid at 1000 Mbps.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3404
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3405
		phy_info->cable_length =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3406
		    (e1000_cable_length) ((phy_data &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3407
					   M88E1000_PSSR_CABLE_LENGTH) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3408
					  M88E1000_PSSR_CABLE_LENGTH_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3409
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3410
		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3411
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3412
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3413
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3414
		phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3415
				      SR_1000T_LOCAL_RX_STATUS_SHIFT) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3416
		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3417
		phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3418
				       SR_1000T_REMOTE_RX_STATUS_SHIFT) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3419
		    e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3420
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3421
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3422
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3423
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3424
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3425
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3426
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3427
 * e1000_phy_get_info - request phy info
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3428
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3429
 * @phy_info: PHY information structure
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3430
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3431
 * Get PHY information from various PHY registers
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3432
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3433
s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3434
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3435
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3436
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3437
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3438
	e_dbg("e1000_phy_get_info");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3439
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3440
	phy_info->cable_length = e1000_cable_length_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3441
	phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3442
	phy_info->cable_polarity = e1000_rev_polarity_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3443
	phy_info->downshift = e1000_downshift_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3444
	phy_info->polarity_correction = e1000_polarity_reversal_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3445
	phy_info->mdix_mode = e1000_auto_x_mode_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3446
	phy_info->local_rx = e1000_1000t_rx_status_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3447
	phy_info->remote_rx = e1000_1000t_rx_status_undefined;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3448
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3449
	if (hw->media_type != e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3450
		e_dbg("PHY info is only valid for copper media\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3451
		return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3452
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3453
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3454
	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3455
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3456
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3457
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3458
	ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3459
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3460
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3461
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3462
	if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3463
		e_dbg("PHY info is only valid if link is up\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3464
		return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3465
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3466
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3467
	if (hw->phy_type == e1000_phy_igp)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3468
		return e1000_phy_igp_get_info(hw, phy_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3469
	else if ((hw->phy_type == e1000_phy_8211) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3470
	         (hw->phy_type == e1000_phy_8201))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3471
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3472
	else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3473
		return e1000_phy_m88_get_info(hw, phy_info);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3474
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3475
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3476
s32 e1000_validate_mdi_setting(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3477
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3478
	e_dbg("e1000_validate_mdi_settings");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3479
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3480
	if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3481
		e_dbg("Invalid MDI setting detected\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3482
		hw->mdix = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3483
		return -E1000_ERR_CONFIG;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3484
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3485
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3486
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3487
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3488
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3489
 * e1000_init_eeprom_params - initialize sw eeprom vars
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3490
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3491
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3492
 * Sets up eeprom variables in the hw struct.  Must be called after mac_type
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3493
 * is configured.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3494
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3495
s32 e1000_init_eeprom_params(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3496
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3497
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3498
	u32 eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3499
	s32 ret_val = E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3500
	u16 eeprom_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3501
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3502
	e_dbg("e1000_init_eeprom_params");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3503
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3504
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3505
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3506
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3507
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3508
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3509
		eeprom->type = e1000_eeprom_microwire;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3510
		eeprom->word_size = 64;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3511
		eeprom->opcode_bits = 3;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3512
		eeprom->address_bits = 6;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3513
		eeprom->delay_usec = 50;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3514
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3515
	case e1000_82540:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3516
	case e1000_82545:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3517
	case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3518
	case e1000_82546:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3519
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3520
		eeprom->type = e1000_eeprom_microwire;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3521
		eeprom->opcode_bits = 3;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3522
		eeprom->delay_usec = 50;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3523
		if (eecd & E1000_EECD_SIZE) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3524
			eeprom->word_size = 256;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3525
			eeprom->address_bits = 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3526
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3527
			eeprom->word_size = 64;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3528
			eeprom->address_bits = 6;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3529
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3530
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3531
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3532
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3533
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3534
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3535
		if (eecd & E1000_EECD_TYPE) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3536
			eeprom->type = e1000_eeprom_spi;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3537
			eeprom->opcode_bits = 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3538
			eeprom->delay_usec = 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3539
			if (eecd & E1000_EECD_ADDR_BITS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3540
				eeprom->page_size = 32;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3541
				eeprom->address_bits = 16;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3542
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3543
				eeprom->page_size = 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3544
				eeprom->address_bits = 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3545
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3546
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3547
			eeprom->type = e1000_eeprom_microwire;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3548
			eeprom->opcode_bits = 3;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3549
			eeprom->delay_usec = 50;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3550
			if (eecd & E1000_EECD_ADDR_BITS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3551
				eeprom->word_size = 256;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3552
				eeprom->address_bits = 8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3553
			} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3554
				eeprom->word_size = 64;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3555
				eeprom->address_bits = 6;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3556
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3557
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3558
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3559
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3560
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3561
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3562
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3563
	if (eeprom->type == e1000_eeprom_spi) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3564
		/* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3565
		 * 32KB (incremented by powers of 2).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3566
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3567
		/* Set to default value for initial eeprom read. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3568
		eeprom->word_size = 64;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3569
		ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3570
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3571
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3572
		eeprom_size =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3573
		    (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3574
		/* 256B eeprom size was not supported in earlier hardware, so we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3575
		 * bump eeprom_size up one to ensure that "1" (which maps to 256B)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3576
		 * is never the result used in the shifting logic below. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3577
		if (eeprom_size)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3578
			eeprom_size++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3579
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3580
		eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3581
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3582
	return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3583
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3584
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3585
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3586
 * e1000_raise_ee_clk - Raises the EEPROM's clock input.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3587
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3588
 * @eecd: EECD's current value
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3589
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3590
static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3591
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3592
	/* Raise the clock input to the EEPROM (by setting the SK bit), and then
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3593
	 * wait <delay> microseconds.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3594
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3595
	*eecd = *eecd | E1000_EECD_SK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3596
	ew32(EECD, *eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3597
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3598
	udelay(hw->eeprom.delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3599
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3600
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3601
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3602
 * e1000_lower_ee_clk - Lowers the EEPROM's clock input.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3603
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3604
 * @eecd: EECD's current value
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3605
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3606
static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3607
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3608
	/* Lower the clock input to the EEPROM (by clearing the SK bit), and then
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3609
	 * wait 50 microseconds.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3610
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3611
	*eecd = *eecd & ~E1000_EECD_SK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3612
	ew32(EECD, *eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3613
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3614
	udelay(hw->eeprom.delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3615
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3616
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3617
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3618
 * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3619
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3620
 * @data: data to send to the EEPROM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3621
 * @count: number of bits to shift out
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3622
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3623
static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3624
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3625
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3626
	u32 eecd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3627
	u32 mask;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3628
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3629
	/* We need to shift "count" bits out to the EEPROM. So, value in the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3630
	 * "data" parameter will be shifted out to the EEPROM one bit at a time.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3631
	 * In order to do this, "data" must be broken down into bits.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3632
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3633
	mask = 0x01 << (count - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3634
	eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3635
	if (eeprom->type == e1000_eeprom_microwire) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3636
		eecd &= ~E1000_EECD_DO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3637
	} else if (eeprom->type == e1000_eeprom_spi) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3638
		eecd |= E1000_EECD_DO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3639
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3640
	do {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3641
		/* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1",
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3642
		 * and then raising and then lowering the clock (the SK bit controls
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3643
		 * the clock input to the EEPROM).  A "0" is shifted out to the EEPROM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3644
		 * by setting "DI" to "0" and then raising and then lowering the clock.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3645
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3646
		eecd &= ~E1000_EECD_DI;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3647
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3648
		if (data & mask)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3649
			eecd |= E1000_EECD_DI;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3650
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3651
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3652
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3653
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3654
		udelay(eeprom->delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3655
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3656
		e1000_raise_ee_clk(hw, &eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3657
		e1000_lower_ee_clk(hw, &eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3658
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3659
		mask = mask >> 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3660
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3661
	} while (mask);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3662
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3663
	/* We leave the "DI" bit set to "0" when we leave this routine. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3664
	eecd &= ~E1000_EECD_DI;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3665
	ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3666
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3667
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3668
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3669
 * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3670
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3671
 * @count: number of bits to shift in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3672
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3673
static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3674
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3675
	u32 eecd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3676
	u32 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3677
	u16 data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3678
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3679
	/* In order to read a register from the EEPROM, we need to shift 'count'
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3680
	 * bits in from the EEPROM. Bits are "shifted in" by raising the clock
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3681
	 * input to the EEPROM (setting the SK bit), and then reading the value of
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3682
	 * the "DO" bit.  During this "shifting in" process the "DI" bit should
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3683
	 * always be clear.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3684
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3685
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3686
	eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3687
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3688
	eecd &= ~(E1000_EECD_DO | E1000_EECD_DI);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3689
	data = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3690
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3691
	for (i = 0; i < count; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3692
		data = data << 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3693
		e1000_raise_ee_clk(hw, &eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3694
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3695
		eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3696
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3697
		eecd &= ~(E1000_EECD_DI);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3698
		if (eecd & E1000_EECD_DO)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3699
			data |= 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3700
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3701
		e1000_lower_ee_clk(hw, &eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3702
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3703
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3704
	return data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3705
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3706
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3707
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3708
 * e1000_acquire_eeprom - Prepares EEPROM for access
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3709
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3710
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3711
 * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3712
 * function should be called before issuing a command to the EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3713
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3714
static s32 e1000_acquire_eeprom(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3715
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3716
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3717
	u32 eecd, i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3718
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3719
	e_dbg("e1000_acquire_eeprom");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3720
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3721
	eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3722
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3723
	/* Request EEPROM Access */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3724
	if (hw->mac_type > e1000_82544) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3725
		eecd |= E1000_EECD_REQ;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3726
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3727
		eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3728
		while ((!(eecd & E1000_EECD_GNT)) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3729
		       (i < E1000_EEPROM_GRANT_ATTEMPTS)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3730
			i++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3731
			udelay(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3732
			eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3733
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3734
		if (!(eecd & E1000_EECD_GNT)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3735
			eecd &= ~E1000_EECD_REQ;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3736
			ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3737
			e_dbg("Could not acquire EEPROM grant\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3738
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3739
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3740
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3741
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3742
	/* Setup EEPROM for Read/Write */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3743
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3744
	if (eeprom->type == e1000_eeprom_microwire) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3745
		/* Clear SK and DI */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3746
		eecd &= ~(E1000_EECD_DI | E1000_EECD_SK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3747
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3748
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3749
		/* Set CS */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3750
		eecd |= E1000_EECD_CS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3751
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3752
	} else if (eeprom->type == e1000_eeprom_spi) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3753
		/* Clear SK and CS */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3754
		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3755
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3756
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3757
		udelay(1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3758
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3759
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3760
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3761
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3762
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3763
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3764
 * e1000_standby_eeprom - Returns EEPROM to a "standby" state
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3765
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3766
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3767
static void e1000_standby_eeprom(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3768
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3769
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3770
	u32 eecd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3771
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3772
	eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3773
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3774
	if (eeprom->type == e1000_eeprom_microwire) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3775
		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3776
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3777
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3778
		udelay(eeprom->delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3779
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3780
		/* Clock high */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3781
		eecd |= E1000_EECD_SK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3782
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3783
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3784
		udelay(eeprom->delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3785
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3786
		/* Select EEPROM */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3787
		eecd |= E1000_EECD_CS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3788
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3789
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3790
		udelay(eeprom->delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3791
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3792
		/* Clock low */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3793
		eecd &= ~E1000_EECD_SK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3794
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3795
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3796
		udelay(eeprom->delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3797
	} else if (eeprom->type == e1000_eeprom_spi) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3798
		/* Toggle CS to flush commands */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3799
		eecd |= E1000_EECD_CS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3800
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3801
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3802
		udelay(eeprom->delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3803
		eecd &= ~E1000_EECD_CS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3804
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3805
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3806
		udelay(eeprom->delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3807
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3808
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3809
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3810
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3811
 * e1000_release_eeprom - drop chip select
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3812
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3813
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3814
 * Terminates a command by inverting the EEPROM's chip select pin
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3815
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3816
static void e1000_release_eeprom(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3817
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3818
	u32 eecd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3819
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3820
	e_dbg("e1000_release_eeprom");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3821
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3822
	eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3823
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3824
	if (hw->eeprom.type == e1000_eeprom_spi) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3825
		eecd |= E1000_EECD_CS;	/* Pull CS high */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3826
		eecd &= ~E1000_EECD_SK;	/* Lower SCK */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3827
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3828
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3829
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3830
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3831
		udelay(hw->eeprom.delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3832
	} else if (hw->eeprom.type == e1000_eeprom_microwire) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3833
		/* cleanup eeprom */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3834
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3835
		/* CS on Microwire is active-high */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3836
		eecd &= ~(E1000_EECD_CS | E1000_EECD_DI);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3837
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3838
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3839
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3840
		/* Rising edge of clock */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3841
		eecd |= E1000_EECD_SK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3842
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3843
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3844
		udelay(hw->eeprom.delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3845
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3846
		/* Falling edge of clock */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3847
		eecd &= ~E1000_EECD_SK;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3848
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3849
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3850
		udelay(hw->eeprom.delay_usec);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3851
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3852
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3853
	/* Stop requesting EEPROM access */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3854
	if (hw->mac_type > e1000_82544) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3855
		eecd &= ~E1000_EECD_REQ;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3856
		ew32(EECD, eecd);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3857
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3858
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3859
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3860
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3861
 * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3862
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3863
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3864
static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3865
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3866
	u16 retry_count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3867
	u8 spi_stat_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3868
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3869
	e_dbg("e1000_spi_eeprom_ready");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3870
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3871
	/* Read "Status Register" repeatedly until the LSB is cleared.  The
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3872
	 * EEPROM will signal that the command has been completed by clearing
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3873
	 * bit 0 of the internal status register.  If it's not cleared within
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3874
	 * 5 milliseconds, then error out.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3875
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3876
	retry_count = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3877
	do {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3878
		e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3879
					hw->eeprom.opcode_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3880
		spi_stat_reg = (u8) e1000_shift_in_ee_bits(hw, 8);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3881
		if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3882
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3883
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3884
		udelay(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3885
		retry_count += 5;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3886
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3887
		e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3888
	} while (retry_count < EEPROM_MAX_RETRY_SPI);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3889
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3890
	/* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3891
	 * only 0-5mSec on 5V devices)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3892
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3893
	if (retry_count >= EEPROM_MAX_RETRY_SPI) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3894
		e_dbg("SPI EEPROM Status error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3895
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3896
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3897
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3898
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3899
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3900
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3901
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3902
 * e1000_read_eeprom - Reads a 16 bit word from the EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3903
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3904
 * @offset: offset of  word in the EEPROM to read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3905
 * @data: word read from the EEPROM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3906
 * @words: number of words to read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3907
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3908
s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3909
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3910
	s32 ret;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3911
	spin_lock(&e1000_eeprom_lock);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3912
	ret = e1000_do_read_eeprom(hw, offset, words, data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3913
	spin_unlock(&e1000_eeprom_lock);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3914
	return ret;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3915
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3916
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3917
static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3918
				u16 *data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3919
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3920
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3921
	u32 i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3922
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3923
	e_dbg("e1000_read_eeprom");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3924
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3925
	if (hw->mac_type == e1000_ce4100) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3926
		GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3927
		                      data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3928
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3929
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3930
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3931
	/* If eeprom is not yet detected, do so now */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3932
	if (eeprom->word_size == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3933
		e1000_init_eeprom_params(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3934
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3935
	/* A check for invalid values:  offset too large, too many words, and not
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3936
	 * enough words.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3937
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3938
	if ((offset >= eeprom->word_size)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3939
	    || (words > eeprom->word_size - offset) || (words == 0)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3940
		e_dbg("\"words\" parameter out of bounds. Words = %d,"
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3941
		      "size = %d\n", offset, eeprom->word_size);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3942
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3943
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3944
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3945
	/* EEPROM's that don't use EERD to read require us to bit-bang the SPI
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3946
	 * directly. In this case, we need to acquire the EEPROM so that
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3947
	 * FW or other port software does not interrupt.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3948
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3949
	/* Prepare the EEPROM for bit-bang reading */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3950
	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3951
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3952
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3953
	/* Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3954
	 * acquired the EEPROM at this point, so any returns should release it */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3955
	if (eeprom->type == e1000_eeprom_spi) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3956
		u16 word_in;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3957
		u8 read_opcode = EEPROM_READ_OPCODE_SPI;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3958
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3959
		if (e1000_spi_eeprom_ready(hw)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3960
			e1000_release_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3961
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3962
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3963
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3964
		e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3965
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3966
		/* Some SPI eeproms use the 8th address bit embedded in the opcode */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3967
		if ((eeprom->address_bits == 8) && (offset >= 128))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3968
			read_opcode |= EEPROM_A8_OPCODE_SPI;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3969
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3970
		/* Send the READ command (opcode + addr)  */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3971
		e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3972
		e1000_shift_out_ee_bits(hw, (u16) (offset * 2),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3973
					eeprom->address_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3974
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3975
		/* Read the data.  The address of the eeprom internally increments with
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3976
		 * each byte (spi) being read, saving on the overhead of eeprom setup
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3977
		 * and tear-down.  The address counter will roll over if reading beyond
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3978
		 * the size of the eeprom, thus allowing the entire memory to be read
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3979
		 * starting from any offset. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3980
		for (i = 0; i < words; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3981
			word_in = e1000_shift_in_ee_bits(hw, 16);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3982
			data[i] = (word_in >> 8) | (word_in << 8);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3983
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3984
	} else if (eeprom->type == e1000_eeprom_microwire) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3985
		for (i = 0; i < words; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3986
			/* Send the READ command (opcode + addr)  */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3987
			e1000_shift_out_ee_bits(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3988
						EEPROM_READ_OPCODE_MICROWIRE,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3989
						eeprom->opcode_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3990
			e1000_shift_out_ee_bits(hw, (u16) (offset + i),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3991
						eeprom->address_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3992
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3993
			/* Read the data.  For microwire, each word requires the overhead
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3994
			 * of eeprom setup and tear-down. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3995
			data[i] = e1000_shift_in_ee_bits(hw, 16);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3996
			e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3997
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3998
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  3999
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4000
	/* End this read operation */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4001
	e1000_release_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4002
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4003
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4004
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4005
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4006
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4007
 * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4008
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4009
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4010
 * Reads the first 64 16 bit words of the EEPROM and sums the values read.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4011
 * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4012
 * valid.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4013
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4014
s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4015
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4016
	u16 checksum = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4017
	u16 i, eeprom_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4018
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4019
	e_dbg("e1000_validate_eeprom_checksum");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4020
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4021
	for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4022
		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4023
			e_dbg("EEPROM Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4024
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4025
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4026
		checksum += eeprom_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4027
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4028
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4029
#ifdef CONFIG_PARISC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4030
	/* This is a signature and not a checksum on HP c8000 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4031
	if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4032
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4033
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4034
#endif
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4035
	if (checksum == (u16) EEPROM_SUM)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4036
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4037
	else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4038
		e_dbg("EEPROM Checksum Invalid\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4039
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4040
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4041
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4042
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4043
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4044
 * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4045
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4046
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4047
 * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4048
 * Writes the difference to word offset 63 of the EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4049
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4050
s32 e1000_update_eeprom_checksum(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4051
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4052
	u16 checksum = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4053
	u16 i, eeprom_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4054
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4055
	e_dbg("e1000_update_eeprom_checksum");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4056
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4057
	for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4058
		if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4059
			e_dbg("EEPROM Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4060
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4061
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4062
		checksum += eeprom_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4063
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4064
	checksum = (u16) EEPROM_SUM - checksum;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4065
	if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4066
		e_dbg("EEPROM Write Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4067
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4068
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4069
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4070
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4071
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4072
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4073
 * e1000_write_eeprom - write words to the different EEPROM types.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4074
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4075
 * @offset: offset within the EEPROM to be written to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4076
 * @words: number of words to write
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4077
 * @data: 16 bit word to be written to the EEPROM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4078
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4079
 * If e1000_update_eeprom_checksum is not called after this function, the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4080
 * EEPROM will most likely contain an invalid checksum.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4081
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4082
s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4083
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4084
	s32 ret;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4085
	spin_lock(&e1000_eeprom_lock);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4086
	ret = e1000_do_write_eeprom(hw, offset, words, data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4087
	spin_unlock(&e1000_eeprom_lock);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4088
	return ret;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4089
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4090
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4091
static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4092
				 u16 *data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4093
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4094
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4095
	s32 status = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4096
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4097
	e_dbg("e1000_write_eeprom");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4098
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4099
	if (hw->mac_type == e1000_ce4100) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4100
		GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4101
		                       data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4102
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4103
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4104
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4105
	/* If eeprom is not yet detected, do so now */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4106
	if (eeprom->word_size == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4107
		e1000_init_eeprom_params(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4108
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4109
	/* A check for invalid values:  offset too large, too many words, and not
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4110
	 * enough words.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4111
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4112
	if ((offset >= eeprom->word_size)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4113
	    || (words > eeprom->word_size - offset) || (words == 0)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4114
		e_dbg("\"words\" parameter out of bounds\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4115
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4116
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4117
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4118
	/* Prepare the EEPROM for writing  */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4119
	if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4120
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4121
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4122
	if (eeprom->type == e1000_eeprom_microwire) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4123
		status = e1000_write_eeprom_microwire(hw, offset, words, data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4124
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4125
		status = e1000_write_eeprom_spi(hw, offset, words, data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4126
		msleep(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4127
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4128
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4129
	/* Done with writing */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4130
	e1000_release_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4131
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4132
	return status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4133
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4134
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4135
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4136
 * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4137
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4138
 * @offset: offset within the EEPROM to be written to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4139
 * @words: number of words to write
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4140
 * @data: pointer to array of 8 bit words to be written to the EEPROM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4141
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4142
static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4143
				  u16 *data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4144
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4145
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4146
	u16 widx = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4147
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4148
	e_dbg("e1000_write_eeprom_spi");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4149
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4150
	while (widx < words) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4151
		u8 write_opcode = EEPROM_WRITE_OPCODE_SPI;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4152
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4153
		if (e1000_spi_eeprom_ready(hw))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4154
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4155
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4156
		e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4157
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4158
		/*  Send the WRITE ENABLE command (8 bit opcode )  */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4159
		e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4160
					eeprom->opcode_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4161
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4162
		e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4163
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4164
		/* Some SPI eeproms use the 8th address bit embedded in the opcode */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4165
		if ((eeprom->address_bits == 8) && (offset >= 128))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4166
			write_opcode |= EEPROM_A8_OPCODE_SPI;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4167
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4168
		/* Send the Write command (8-bit opcode + addr) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4169
		e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4170
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4171
		e1000_shift_out_ee_bits(hw, (u16) ((offset + widx) * 2),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4172
					eeprom->address_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4173
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4174
		/* Send the data */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4175
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4176
		/* Loop to allow for up to whole page write (32 bytes) of eeprom */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4177
		while (widx < words) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4178
			u16 word_out = data[widx];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4179
			word_out = (word_out >> 8) | (word_out << 8);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4180
			e1000_shift_out_ee_bits(hw, word_out, 16);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4181
			widx++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4182
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4183
			/* Some larger eeprom sizes are capable of a 32-byte PAGE WRITE
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4184
			 * operation, while the smaller eeproms are capable of an 8-byte
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4185
			 * PAGE WRITE operation.  Break the inner loop to pass new address
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4186
			 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4187
			if ((((offset + widx) * 2) % eeprom->page_size) == 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4188
				e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4189
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4190
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4191
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4192
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4193
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4194
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4195
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4196
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4197
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4198
 * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4199
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4200
 * @offset: offset within the EEPROM to be written to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4201
 * @words: number of words to write
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4202
 * @data: pointer to array of 8 bit words to be written to the EEPROM
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4203
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4204
static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4205
					u16 words, u16 *data)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4206
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4207
	struct e1000_eeprom_info *eeprom = &hw->eeprom;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4208
	u32 eecd;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4209
	u16 words_written = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4210
	u16 i = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4211
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4212
	e_dbg("e1000_write_eeprom_microwire");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4213
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4214
	/* Send the write enable command to the EEPROM (3-bit opcode plus
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4215
	 * 6/8-bit dummy address beginning with 11).  It's less work to include
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4216
	 * the 11 of the dummy address as part of the opcode than it is to shift
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4217
	 * it over the correct number of bits for the address.  This puts the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4218
	 * EEPROM into write/erase mode.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4219
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4220
	e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4221
				(u16) (eeprom->opcode_bits + 2));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4222
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4223
	e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4224
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4225
	/* Prepare the EEPROM */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4226
	e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4227
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4228
	while (words_written < words) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4229
		/* Send the Write command (3-bit opcode + addr) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4230
		e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4231
					eeprom->opcode_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4232
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4233
		e1000_shift_out_ee_bits(hw, (u16) (offset + words_written),
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4234
					eeprom->address_bits);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4235
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4236
		/* Send the data */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4237
		e1000_shift_out_ee_bits(hw, data[words_written], 16);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4238
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4239
		/* Toggle the CS line.  This in effect tells the EEPROM to execute
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4240
		 * the previous command.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4241
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4242
		e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4243
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4244
		/* Read DO repeatedly until it is high (equal to '1').  The EEPROM will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4245
		 * signal that the command has been completed by raising the DO signal.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4246
		 * If DO does not go high in 10 milliseconds, then error out.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4247
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4248
		for (i = 0; i < 200; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4249
			eecd = er32(EECD);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4250
			if (eecd & E1000_EECD_DO)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4251
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4252
			udelay(50);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4253
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4254
		if (i == 200) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4255
			e_dbg("EEPROM Write did not complete\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4256
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4257
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4258
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4259
		/* Recover from write */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4260
		e1000_standby_eeprom(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4261
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4262
		words_written++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4263
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4264
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4265
	/* Send the write disable command to the EEPROM (3-bit opcode plus
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4266
	 * 6/8-bit dummy address beginning with 10).  It's less work to include
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4267
	 * the 10 of the dummy address as part of the opcode than it is to shift
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4268
	 * it over the correct number of bits for the address.  This takes the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4269
	 * EEPROM out of write/erase mode.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4270
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4271
	e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4272
				(u16) (eeprom->opcode_bits + 2));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4273
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4274
	e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4275
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4276
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4277
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4278
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4279
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4280
 * e1000_read_mac_addr - read the adapters MAC from eeprom
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4281
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4282
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4283
 * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4284
 * second function of dual function devices
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4285
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4286
s32 e1000_read_mac_addr(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4287
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4288
	u16 offset;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4289
	u16 eeprom_data, i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4290
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4291
	e_dbg("e1000_read_mac_addr");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4292
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4293
	for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4294
		offset = i >> 1;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4295
		if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4296
			e_dbg("EEPROM Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4297
			return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4298
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4299
		hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4300
		hw->perm_mac_addr[i + 1] = (u8) (eeprom_data >> 8);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4301
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4302
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4303
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4304
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4305
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4306
	case e1000_82546:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4307
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4308
		if (er32(STATUS) & E1000_STATUS_FUNC_1)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4309
			hw->perm_mac_addr[5] ^= 0x01;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4310
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4311
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4312
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4313
	for (i = 0; i < NODE_ADDRESS_SIZE; i++)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4314
		hw->mac_addr[i] = hw->perm_mac_addr[i];
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4315
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4316
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4317
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4318
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4319
 * e1000_init_rx_addrs - Initializes receive address filters.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4320
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4321
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4322
 * Places the MAC address in receive address register 0 and clears the rest
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4323
 * of the receive address registers. Clears the multicast table. Assumes
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4324
 * the receiver is in reset when the routine is called.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4325
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4326
static void e1000_init_rx_addrs(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4327
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4328
	u32 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4329
	u32 rar_num;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4330
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4331
	e_dbg("e1000_init_rx_addrs");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4332
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4333
	/* Setup the receive address. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4334
	e_dbg("Programming MAC Address into RAR[0]\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4335
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4336
	e1000_rar_set(hw, hw->mac_addr, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4337
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4338
	rar_num = E1000_RAR_ENTRIES;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4339
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4340
	/* Zero out the other 15 receive addresses. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4341
	e_dbg("Clearing RAR[1-15]\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4342
	for (i = 1; i < rar_num; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4343
		E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4344
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4345
		E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4346
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4347
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4348
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4349
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4350
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4351
 * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4352
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4353
 * @mc_addr: the multicast address to hash
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4354
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4355
u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4356
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4357
	u32 hash_value = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4358
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4359
	/* The portion of the address that is used for the hash table is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4360
	 * determined by the mc_filter_type setting.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4361
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4362
	switch (hw->mc_filter_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4363
		/* [0] [1] [2] [3] [4] [5]
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4364
		 * 01  AA  00  12  34  56
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4365
		 * LSB                 MSB
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4366
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4367
	case 0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4368
		/* [47:36] i.e. 0x563 for above example address */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4369
		hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4370
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4371
	case 1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4372
		/* [46:35] i.e. 0xAC6 for above example address */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4373
		hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4374
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4375
	case 2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4376
		/* [45:34] i.e. 0x5D8 for above example address */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4377
		hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4378
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4379
	case 3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4380
		/* [43:32] i.e. 0x634 for above example address */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4381
		hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4382
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4383
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4384
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4385
	hash_value &= 0xFFF;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4386
	return hash_value;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4387
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4388
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4389
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4390
 * e1000_rar_set - Puts an ethernet address into a receive address register.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4391
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4392
 * @addr: Address to put into receive address register
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4393
 * @index: Receive address register to write
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4394
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4395
void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4396
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4397
	u32 rar_low, rar_high;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4398
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4399
	/* HW expects these in little endian so we reverse the byte order
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4400
	 * from network order (big endian) to little endian
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4401
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4402
	rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4403
		   ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4404
	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4405
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4406
	/* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4407
	 * unit hang.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4408
	 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4409
	 * Description:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4410
	 * If there are any Rx frames queued up or otherwise present in the HW
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4411
	 * before RSS is enabled, and then we enable RSS, the HW Rx unit will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4412
	 * hang.  To work around this issue, we have to disable receives and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4413
	 * flush out all Rx frames before we enable RSS. To do so, we modify we
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4414
	 * redirect all Rx traffic to manageability and then reset the HW.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4415
	 * This flushes away Rx frames, and (since the redirections to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4416
	 * manageability persists across resets) keeps new ones from coming in
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4417
	 * while we work.  Then, we clear the Address Valid AV bit for all MAC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4418
	 * addresses and undo the re-direction to manageability.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4419
	 * Now, frames are coming in again, but the MAC won't accept them, so
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4420
	 * far so good.  We now proceed to initialize RSS (if necessary) and
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4421
	 * configure the Rx unit.  Last, we re-enable the AV bits and continue
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4422
	 * on our merry way.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4423
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4424
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4425
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4426
		/* Indicate to hardware the Address is Valid. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4427
		rar_high |= E1000_RAH_AV;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4428
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4429
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4430
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4431
	E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4432
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4433
	E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4434
	E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4435
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4436
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4437
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4438
 * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4439
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4440
 * @offset: Offset in VLAN filer table to write
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4441
 * @value: Value to write into VLAN filter table
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4442
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4443
void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4444
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4445
	u32 temp;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4446
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4447
	if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4448
		temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4449
		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4450
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4451
		E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4452
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4453
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4454
		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4455
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4456
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4457
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4458
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4459
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4460
 * e1000_clear_vfta - Clears the VLAN filer table
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4461
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4462
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4463
static void e1000_clear_vfta(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4464
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4465
	u32 offset;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4466
	u32 vfta_value = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4467
	u32 vfta_offset = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4468
	u32 vfta_bit_in_reg = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4469
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4470
	for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4471
		/* If the offset we want to clear is the same offset of the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4472
		 * manageability VLAN ID, then clear all bits except that of the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4473
		 * manageability unit */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4474
		vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4475
		E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4476
		E1000_WRITE_FLUSH();
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4477
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4478
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4479
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4480
static s32 e1000_id_led_init(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4481
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4482
	u32 ledctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4483
	const u32 ledctl_mask = 0x000000FF;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4484
	const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4485
	const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4486
	u16 eeprom_data, i, temp;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4487
	const u16 led_mask = 0x0F;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4488
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4489
	e_dbg("e1000_id_led_init");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4490
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4491
	if (hw->mac_type < e1000_82540) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4492
		/* Nothing to do */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4493
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4494
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4495
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4496
	ledctl = er32(LEDCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4497
	hw->ledctl_default = ledctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4498
	hw->ledctl_mode1 = hw->ledctl_default;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4499
	hw->ledctl_mode2 = hw->ledctl_default;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4500
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4501
	if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4502
		e_dbg("EEPROM Read Error\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4503
		return -E1000_ERR_EEPROM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4504
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4505
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4506
	if ((eeprom_data == ID_LED_RESERVED_0000) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4507
	    (eeprom_data == ID_LED_RESERVED_FFFF)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4508
		eeprom_data = ID_LED_DEFAULT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4509
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4510
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4511
	for (i = 0; i < 4; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4512
		temp = (eeprom_data >> (i << 2)) & led_mask;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4513
		switch (temp) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4514
		case ID_LED_ON1_DEF2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4515
		case ID_LED_ON1_ON2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4516
		case ID_LED_ON1_OFF2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4517
			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4518
			hw->ledctl_mode1 |= ledctl_on << (i << 3);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4519
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4520
		case ID_LED_OFF1_DEF2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4521
		case ID_LED_OFF1_ON2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4522
		case ID_LED_OFF1_OFF2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4523
			hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4524
			hw->ledctl_mode1 |= ledctl_off << (i << 3);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4525
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4526
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4527
			/* Do nothing */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4528
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4529
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4530
		switch (temp) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4531
		case ID_LED_DEF1_ON2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4532
		case ID_LED_ON1_ON2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4533
		case ID_LED_OFF1_ON2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4534
			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4535
			hw->ledctl_mode2 |= ledctl_on << (i << 3);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4536
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4537
		case ID_LED_DEF1_OFF2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4538
		case ID_LED_ON1_OFF2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4539
		case ID_LED_OFF1_OFF2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4540
			hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4541
			hw->ledctl_mode2 |= ledctl_off << (i << 3);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4542
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4543
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4544
			/* Do nothing */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4545
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4546
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4547
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4548
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4549
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4550
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4551
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4552
 * e1000_setup_led
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4553
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4554
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4555
 * Prepares SW controlable LED for use and saves the current state of the LED.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4556
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4557
s32 e1000_setup_led(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4558
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4559
	u32 ledctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4560
	s32 ret_val = E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4561
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4562
	e_dbg("e1000_setup_led");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4563
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4564
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4565
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4566
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4567
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4568
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4569
		/* No setup necessary */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4570
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4571
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4572
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4573
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4574
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4575
		/* Turn off PHY Smart Power Down (if enabled) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4576
		ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4577
					     &hw->phy_spd_default);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4578
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4579
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4580
		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4581
					      (u16) (hw->phy_spd_default &
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4582
						     ~IGP01E1000_GMII_SPD));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4583
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4584
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4585
		/* Fall Through */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4586
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4587
		if (hw->media_type == e1000_media_type_fiber) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4588
			ledctl = er32(LEDCTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4589
			/* Save current LEDCTL settings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4590
			hw->ledctl_default = ledctl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4591
			/* Turn off LED0 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4592
			ledctl &= ~(E1000_LEDCTL_LED0_IVRT |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4593
				    E1000_LEDCTL_LED0_BLINK |
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4594
				    E1000_LEDCTL_LED0_MODE_MASK);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4595
			ledctl |= (E1000_LEDCTL_MODE_LED_OFF <<
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4596
				   E1000_LEDCTL_LED0_MODE_SHIFT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4597
			ew32(LEDCTL, ledctl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4598
		} else if (hw->media_type == e1000_media_type_copper)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4599
			ew32(LEDCTL, hw->ledctl_mode1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4600
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4601
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4602
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4603
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4604
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4605
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4606
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4607
 * e1000_cleanup_led - Restores the saved state of the SW controlable LED.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4608
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4609
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4610
s32 e1000_cleanup_led(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4611
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4612
	s32 ret_val = E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4613
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4614
	e_dbg("e1000_cleanup_led");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4615
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4616
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4617
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4618
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4619
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4620
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4621
		/* No cleanup necessary */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4622
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4623
	case e1000_82541:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4624
	case e1000_82547:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4625
	case e1000_82541_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4626
	case e1000_82547_rev_2:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4627
		/* Turn on PHY Smart Power Down (if previously enabled) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4628
		ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4629
					      hw->phy_spd_default);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4630
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4631
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4632
		/* Fall Through */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4633
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4634
		/* Restore LEDCTL settings */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4635
		ew32(LEDCTL, hw->ledctl_default);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4636
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4637
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4638
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4639
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4640
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4641
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4642
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4643
 * e1000_led_on - Turns on the software controllable LED
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4644
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4645
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4646
s32 e1000_led_on(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4647
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4648
	u32 ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4649
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4650
	e_dbg("e1000_led_on");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4651
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4652
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4653
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4654
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4655
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4656
		/* Set SW Defineable Pin 0 to turn on the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4657
		ctrl |= E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4658
		ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4659
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4660
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4661
		if (hw->media_type == e1000_media_type_fiber) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4662
			/* Set SW Defineable Pin 0 to turn on the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4663
			ctrl |= E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4664
			ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4665
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4666
			/* Clear SW Defineable Pin 0 to turn on the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4667
			ctrl &= ~E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4668
			ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4669
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4670
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4671
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4672
		if (hw->media_type == e1000_media_type_fiber) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4673
			/* Clear SW Defineable Pin 0 to turn on the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4674
			ctrl &= ~E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4675
			ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4676
		} else if (hw->media_type == e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4677
			ew32(LEDCTL, hw->ledctl_mode2);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4678
			return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4679
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4680
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4681
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4682
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4683
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4684
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4685
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4686
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4687
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4688
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4689
 * e1000_led_off - Turns off the software controllable LED
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4690
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4691
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4692
s32 e1000_led_off(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4693
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4694
	u32 ctrl = er32(CTRL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4695
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4696
	e_dbg("e1000_led_off");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4697
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4698
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4699
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4700
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4701
	case e1000_82543:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4702
		/* Clear SW Defineable Pin 0 to turn off the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4703
		ctrl &= ~E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4704
		ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4705
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4706
	case e1000_82544:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4707
		if (hw->media_type == e1000_media_type_fiber) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4708
			/* Clear SW Defineable Pin 0 to turn off the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4709
			ctrl &= ~E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4710
			ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4711
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4712
			/* Set SW Defineable Pin 0 to turn off the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4713
			ctrl |= E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4714
			ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4715
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4716
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4717
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4718
		if (hw->media_type == e1000_media_type_fiber) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4719
			/* Set SW Defineable Pin 0 to turn off the LED */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4720
			ctrl |= E1000_CTRL_SWDPIN0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4721
			ctrl |= E1000_CTRL_SWDPIO0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4722
		} else if (hw->media_type == e1000_media_type_copper) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4723
			ew32(LEDCTL, hw->ledctl_mode1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4724
			return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4725
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4726
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4727
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4728
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4729
	ew32(CTRL, ctrl);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4730
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4731
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4732
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4733
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4734
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4735
 * e1000_clear_hw_cntrs - Clears all hardware statistics counters.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4736
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4737
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4738
static void e1000_clear_hw_cntrs(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4739
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4740
	volatile u32 temp __attribute__ ((unused));
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4741
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4742
	temp = er32(CRCERRS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4743
	temp = er32(SYMERRS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4744
	temp = er32(MPC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4745
	temp = er32(SCC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4746
	temp = er32(ECOL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4747
	temp = er32(MCC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4748
	temp = er32(LATECOL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4749
	temp = er32(COLC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4750
	temp = er32(DC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4751
	temp = er32(SEC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4752
	temp = er32(RLEC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4753
	temp = er32(XONRXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4754
	temp = er32(XONTXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4755
	temp = er32(XOFFRXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4756
	temp = er32(XOFFTXC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4757
	temp = er32(FCRUC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4758
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4759
	temp = er32(PRC64);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4760
	temp = er32(PRC127);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4761
	temp = er32(PRC255);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4762
	temp = er32(PRC511);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4763
	temp = er32(PRC1023);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4764
	temp = er32(PRC1522);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4765
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4766
	temp = er32(GPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4767
	temp = er32(BPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4768
	temp = er32(MPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4769
	temp = er32(GPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4770
	temp = er32(GORCL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4771
	temp = er32(GORCH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4772
	temp = er32(GOTCL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4773
	temp = er32(GOTCH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4774
	temp = er32(RNBC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4775
	temp = er32(RUC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4776
	temp = er32(RFC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4777
	temp = er32(ROC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4778
	temp = er32(RJC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4779
	temp = er32(TORL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4780
	temp = er32(TORH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4781
	temp = er32(TOTL);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4782
	temp = er32(TOTH);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4783
	temp = er32(TPR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4784
	temp = er32(TPT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4785
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4786
	temp = er32(PTC64);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4787
	temp = er32(PTC127);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4788
	temp = er32(PTC255);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4789
	temp = er32(PTC511);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4790
	temp = er32(PTC1023);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4791
	temp = er32(PTC1522);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4792
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4793
	temp = er32(MPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4794
	temp = er32(BPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4795
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4796
	if (hw->mac_type < e1000_82543)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4797
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4798
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4799
	temp = er32(ALGNERRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4800
	temp = er32(RXERRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4801
	temp = er32(TNCRS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4802
	temp = er32(CEXTERR);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4803
	temp = er32(TSCTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4804
	temp = er32(TSCTFC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4805
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4806
	if (hw->mac_type <= e1000_82544)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4807
		return;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4808
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4809
	temp = er32(MGTPRC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4810
	temp = er32(MGTPDC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4811
	temp = er32(MGTPTC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4812
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4813
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4814
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4815
 * e1000_reset_adaptive - Resets Adaptive IFS to its default state.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4816
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4817
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4818
 * Call this after e1000_init_hw. You may override the IFS defaults by setting
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4819
 * hw->ifs_params_forced to true. However, you must initialize hw->
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4820
 * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4821
 * before calling this function.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4822
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4823
void e1000_reset_adaptive(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4824
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4825
	e_dbg("e1000_reset_adaptive");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4826
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4827
	if (hw->adaptive_ifs) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4828
		if (!hw->ifs_params_forced) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4829
			hw->current_ifs_val = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4830
			hw->ifs_min_val = IFS_MIN;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4831
			hw->ifs_max_val = IFS_MAX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4832
			hw->ifs_step_size = IFS_STEP;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4833
			hw->ifs_ratio = IFS_RATIO;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4834
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4835
		hw->in_ifs_mode = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4836
		ew32(AIT, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4837
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4838
		e_dbg("Not in Adaptive IFS mode!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4839
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4840
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4841
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4842
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4843
 * e1000_update_adaptive - update adaptive IFS
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4844
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4845
 * @tx_packets: Number of transmits since last callback
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4846
 * @total_collisions: Number of collisions since last callback
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4847
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4848
 * Called during the callback/watchdog routine to update IFS value based on
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4849
 * the ratio of transmits to collisions.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4850
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4851
void e1000_update_adaptive(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4852
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4853
	e_dbg("e1000_update_adaptive");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4854
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4855
	if (hw->adaptive_ifs) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4856
		if ((hw->collision_delta *hw->ifs_ratio) > hw->tx_packet_delta) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4857
			if (hw->tx_packet_delta > MIN_NUM_XMITS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4858
				hw->in_ifs_mode = true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4859
				if (hw->current_ifs_val < hw->ifs_max_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4860
					if (hw->current_ifs_val == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4861
						hw->current_ifs_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4862
						    hw->ifs_min_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4863
					else
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4864
						hw->current_ifs_val +=
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4865
						    hw->ifs_step_size;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4866
					ew32(AIT, hw->current_ifs_val);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4867
				}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4868
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4869
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4870
			if (hw->in_ifs_mode
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4871
			    && (hw->tx_packet_delta <= MIN_NUM_XMITS)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4872
				hw->current_ifs_val = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4873
				hw->in_ifs_mode = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4874
				ew32(AIT, 0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4875
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4876
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4877
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4878
		e_dbg("Not in Adaptive IFS mode!\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4879
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4880
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4881
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4882
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4883
 * e1000_tbi_adjust_stats
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4884
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4885
 * @frame_len: The length of the frame in question
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4886
 * @mac_addr: The Ethernet destination address of the frame in question
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4887
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4888
 * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4889
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4890
void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4891
			    u32 frame_len, u8 *mac_addr)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4892
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4893
	u64 carry_bit;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4894
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4895
	/* First adjust the frame length. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4896
	frame_len--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4897
	/* We need to adjust the statistics counters, since the hardware
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4898
	 * counters overcount this packet as a CRC error and undercount
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4899
	 * the packet as a good packet
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4900
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4901
	/* This packet should not be counted as a CRC error.    */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4902
	stats->crcerrs--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4903
	/* This packet does count as a Good Packet Received.    */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4904
	stats->gprc++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4905
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4906
	/* Adjust the Good Octets received counters             */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4907
	carry_bit = 0x80000000 & stats->gorcl;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4908
	stats->gorcl += frame_len;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4909
	/* If the high bit of Gorcl (the low 32 bits of the Good Octets
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4910
	 * Received Count) was one before the addition,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4911
	 * AND it is zero after, then we lost the carry out,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4912
	 * need to add one to Gorch (Good Octets Received Count High).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4913
	 * This could be simplified if all environments supported
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4914
	 * 64-bit integers.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4915
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4916
	if (carry_bit && ((stats->gorcl & 0x80000000) == 0))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4917
		stats->gorch++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4918
	/* Is this a broadcast or multicast?  Check broadcast first,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4919
	 * since the test for a multicast frame will test positive on
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4920
	 * a broadcast frame.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4921
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4922
	if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4923
		/* Broadcast packet */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4924
		stats->bprc++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4925
	else if (*mac_addr & 0x01)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4926
		/* Multicast packet */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4927
		stats->mprc++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4928
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4929
	if (frame_len == hw->max_frame_size) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4930
		/* In this case, the hardware has overcounted the number of
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4931
		 * oversize frames.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4932
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4933
		if (stats->roc > 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4934
			stats->roc--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4935
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4936
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4937
	/* Adjust the bin counters when the extra byte put the frame in the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4938
	 * wrong bin. Remember that the frame_len was adjusted above.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4939
	 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4940
	if (frame_len == 64) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4941
		stats->prc64++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4942
		stats->prc127--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4943
	} else if (frame_len == 127) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4944
		stats->prc127++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4945
		stats->prc255--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4946
	} else if (frame_len == 255) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4947
		stats->prc255++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4948
		stats->prc511--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4949
	} else if (frame_len == 511) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4950
		stats->prc511++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4951
		stats->prc1023--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4952
	} else if (frame_len == 1023) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4953
		stats->prc1023++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4954
		stats->prc1522--;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4955
	} else if (frame_len == 1522) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4956
		stats->prc1522++;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4957
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4958
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4959
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4960
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4961
 * e1000_get_bus_info
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4962
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4963
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4964
 * Gets the current PCI bus type, speed, and width of the hardware
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4965
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4966
void e1000_get_bus_info(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4967
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4968
	u32 status;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4969
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4970
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4971
	case e1000_82542_rev2_0:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4972
	case e1000_82542_rev2_1:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4973
		hw->bus_type = e1000_bus_type_pci;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4974
		hw->bus_speed = e1000_bus_speed_unknown;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4975
		hw->bus_width = e1000_bus_width_unknown;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4976
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4977
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4978
		status = er32(STATUS);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4979
		hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4980
		    e1000_bus_type_pcix : e1000_bus_type_pci;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4981
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4982
		if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4983
			hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4984
			    e1000_bus_speed_66 : e1000_bus_speed_120;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4985
		} else if (hw->bus_type == e1000_bus_type_pci) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4986
			hw->bus_speed = (status & E1000_STATUS_PCI66) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4987
			    e1000_bus_speed_66 : e1000_bus_speed_33;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4988
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4989
			switch (status & E1000_STATUS_PCIX_SPEED) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4990
			case E1000_STATUS_PCIX_SPEED_66:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4991
				hw->bus_speed = e1000_bus_speed_66;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4992
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4993
			case E1000_STATUS_PCIX_SPEED_100:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4994
				hw->bus_speed = e1000_bus_speed_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4995
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4996
			case E1000_STATUS_PCIX_SPEED_133:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4997
				hw->bus_speed = e1000_bus_speed_133;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4998
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  4999
			default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5000
				hw->bus_speed = e1000_bus_speed_reserved;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5001
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5002
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5003
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5004
		hw->bus_width = (status & E1000_STATUS_BUS64) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5005
		    e1000_bus_width_64 : e1000_bus_width_32;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5006
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5007
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5008
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5009
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5010
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5011
 * e1000_write_reg_io
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5012
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5013
 * @offset: offset to write to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5014
 * @value: value to write
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5015
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5016
 * Writes a value to one of the devices registers using port I/O (as opposed to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5017
 * memory mapped I/O). Only 82544 and newer devices support port I/O.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5018
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5019
static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5020
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5021
	unsigned long io_addr = hw->io_base;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5022
	unsigned long io_data = hw->io_base + 4;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5023
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5024
	e1000_io_write(hw, io_addr, offset);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5025
	e1000_io_write(hw, io_data, value);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5026
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5027
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5028
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5029
 * e1000_get_cable_length - Estimates the cable length.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5030
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5031
 * @min_length: The estimated minimum length
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5032
 * @max_length: The estimated maximum length
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5033
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5034
 * returns: - E1000_ERR_XXX
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5035
 *            E1000_SUCCESS
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5036
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5037
 * This function always returns a ranged length (minimum & maximum).
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5038
 * So for M88 phy's, this function interprets the one value returned from the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5039
 * register to the minimum and maximum range.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5040
 * For IGP phy's, the function calculates the range by the AGC registers.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5041
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5042
static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5043
				  u16 *max_length)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5044
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5045
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5046
	u16 agc_value = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5047
	u16 i, phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5048
	u16 cable_length;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5049
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5050
	e_dbg("e1000_get_cable_length");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5051
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5052
	*min_length = *max_length = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5053
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5054
	/* Use old method for Phy older than IGP */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5055
	if (hw->phy_type == e1000_phy_m88) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5056
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5057
		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5058
					     &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5059
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5060
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5061
		cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5062
		    M88E1000_PSSR_CABLE_LENGTH_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5063
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5064
		/* Convert the enum value to ranged values */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5065
		switch (cable_length) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5066
		case e1000_cable_length_50:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5067
			*min_length = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5068
			*max_length = e1000_igp_cable_length_50;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5069
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5070
		case e1000_cable_length_50_80:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5071
			*min_length = e1000_igp_cable_length_50;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5072
			*max_length = e1000_igp_cable_length_80;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5073
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5074
		case e1000_cable_length_80_110:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5075
			*min_length = e1000_igp_cable_length_80;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5076
			*max_length = e1000_igp_cable_length_110;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5077
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5078
		case e1000_cable_length_110_140:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5079
			*min_length = e1000_igp_cable_length_110;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5080
			*max_length = e1000_igp_cable_length_140;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5081
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5082
		case e1000_cable_length_140:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5083
			*min_length = e1000_igp_cable_length_140;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5084
			*max_length = e1000_igp_cable_length_170;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5085
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5086
		default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5087
			return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5088
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5089
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5090
	} else if (hw->phy_type == e1000_phy_igp) {	/* For IGP PHY */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5091
		u16 cur_agc_value;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5092
		u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5093
		static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5094
		       IGP01E1000_PHY_AGC_A,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5095
		       IGP01E1000_PHY_AGC_B,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5096
		       IGP01E1000_PHY_AGC_C,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5097
		       IGP01E1000_PHY_AGC_D
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5098
		};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5099
		/* Read the AGC registers for all channels */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5100
		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5101
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5102
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5103
			    e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5104
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5105
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5106
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5107
			cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5108
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5109
			/* Value bound check. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5110
			if ((cur_agc_value >=
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5111
			     IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5112
			    || (cur_agc_value == 0))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5113
				return -E1000_ERR_PHY;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5114
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5115
			agc_value += cur_agc_value;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5116
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5117
			/* Update minimal AGC value. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5118
			if (min_agc_value > cur_agc_value)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5119
				min_agc_value = cur_agc_value;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5120
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5121
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5122
		/* Remove the minimal AGC result for length < 50m */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5123
		if (agc_value <
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5124
		    IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5125
			agc_value -= min_agc_value;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5126
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5127
			/* Get the average length of the remaining 3 channels */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5128
			agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5129
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5130
			/* Get the average length of all the 4 channels. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5131
			agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5132
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5133
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5134
		/* Set the range of the calculated length. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5135
		*min_length = ((e1000_igp_cable_length_table[agc_value] -
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5136
				IGP01E1000_AGC_RANGE) > 0) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5137
		    (e1000_igp_cable_length_table[agc_value] -
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5138
		     IGP01E1000_AGC_RANGE) : 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5139
		*max_length = e1000_igp_cable_length_table[agc_value] +
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5140
		    IGP01E1000_AGC_RANGE;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5141
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5142
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5143
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5144
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5145
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5146
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5147
 * e1000_check_polarity - Check the cable polarity
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5148
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5149
 * @polarity: output parameter : 0 - Polarity is not reversed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5150
 *                               1 - Polarity is reversed.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5151
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5152
 * returns: - E1000_ERR_XXX
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5153
 *            E1000_SUCCESS
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5154
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5155
 * For phy's older than IGP, this function simply reads the polarity bit in the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5156
 * Phy Status register.  For IGP phy's, this bit is valid only if link speed is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5157
 * 10 Mbps.  If the link speed is 100 Mbps there is no polarity so this bit will
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5158
 * return 0.  If the link speed is 1000 Mbps the polarity status is in the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5159
 * IGP01E1000_PHY_PCS_INIT_REG.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5160
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5161
static s32 e1000_check_polarity(struct e1000_hw *hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5162
				e1000_rev_polarity *polarity)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5163
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5164
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5165
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5166
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5167
	e_dbg("e1000_check_polarity");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5168
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5169
	if (hw->phy_type == e1000_phy_m88) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5170
		/* return the Polarity bit in the Status register. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5171
		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5172
					     &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5173
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5174
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5175
		*polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5176
			     M88E1000_PSSR_REV_POLARITY_SHIFT) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5177
		    e1000_rev_polarity_reversed : e1000_rev_polarity_normal;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5178
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5179
	} else if (hw->phy_type == e1000_phy_igp) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5180
		/* Read the Status register to check the speed */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5181
		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5182
					     &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5183
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5184
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5185
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5186
		/* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5187
		 * find the polarity status */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5188
		if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5189
		    IGP01E1000_PSSR_SPEED_1000MBPS) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5190
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5191
			/* Read the GIG initialization PCS register (0x00B4) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5192
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5193
			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5194
					       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5195
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5196
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5197
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5198
			/* Check the polarity bits */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5199
			*polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5200
			    e1000_rev_polarity_reversed :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5201
			    e1000_rev_polarity_normal;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5202
		} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5203
			/* For 10 Mbps, read the polarity bit in the status register. (for
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5204
			 * 100 Mbps this bit is always 0) */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5205
			*polarity =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5206
			    (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ?
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5207
			    e1000_rev_polarity_reversed :
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5208
			    e1000_rev_polarity_normal;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5209
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5210
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5211
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5212
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5213
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5214
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5215
 * e1000_check_downshift - Check if Downshift occurred
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5216
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5217
 * @downshift: output parameter : 0 - No Downshift occurred.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5218
 *                                1 - Downshift occurred.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5219
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5220
 * returns: - E1000_ERR_XXX
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5221
 *            E1000_SUCCESS
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5222
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5223
 * For phy's older than IGP, this function reads the Downshift bit in the Phy
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5224
 * Specific Status register.  For IGP phy's, it reads the Downgrade bit in the
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5225
 * Link Health register.  In IGP this bit is latched high, so the driver must
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5226
 * read it immediately after link is established.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5227
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5228
static s32 e1000_check_downshift(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5229
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5230
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5231
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5232
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5233
	e_dbg("e1000_check_downshift");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5234
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5235
	if (hw->phy_type == e1000_phy_igp) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5236
		ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5237
					     &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5238
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5239
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5240
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5241
		hw->speed_downgraded =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5242
		    (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5243
	} else if (hw->phy_type == e1000_phy_m88) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5244
		ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5245
					     &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5246
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5247
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5248
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5249
		hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5250
		    M88E1000_PSSR_DOWNSHIFT_SHIFT;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5251
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5252
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5253
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5254
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5255
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5256
static const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5257
	IGP01E1000_PHY_AGC_PARAM_A,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5258
	IGP01E1000_PHY_AGC_PARAM_B,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5259
	IGP01E1000_PHY_AGC_PARAM_C,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5260
	IGP01E1000_PHY_AGC_PARAM_D
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5261
};
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5262
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5263
static s32 e1000_1000Mb_check_cable_length(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5264
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5265
	u16 min_length, max_length;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5266
	u16 phy_data, i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5267
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5268
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5269
	ret_val = e1000_get_cable_length(hw, &min_length, &max_length);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5270
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5271
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5272
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5273
	if (hw->dsp_config_state != e1000_dsp_config_enabled)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5274
		return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5275
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5276
	if (min_length >= e1000_igp_cable_length_50) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5277
		for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5278
			ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i],
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5279
						     &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5280
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5281
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5282
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5283
			phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5284
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5285
			ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i],
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5286
						      phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5287
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5288
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5289
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5290
		hw->dsp_config_state = e1000_dsp_config_activated;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5291
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5292
		u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5293
		u32 idle_errs = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5294
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5295
		/* clear previous idle error counts */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5296
		ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5297
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5298
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5299
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5300
		for (i = 0; i < ffe_idle_err_timeout; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5301
			udelay(1000);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5302
			ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5303
						     &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5304
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5305
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5306
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5307
			idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5308
			if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5309
				hw->ffe_config_state = e1000_ffe_config_active;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5310
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5311
				ret_val = e1000_write_phy_reg(hw,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5312
					      IGP01E1000_PHY_DSP_FFE,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5313
					      IGP01E1000_PHY_DSP_FFE_CM_CP);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5314
				if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5315
					return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5316
				break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5317
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5318
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5319
			if (idle_errs)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5320
				ffe_idle_err_timeout =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5321
					    FFE_IDLE_ERR_COUNT_TIMEOUT_100;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5322
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5323
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5324
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5325
	return 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5326
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5327
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5328
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5329
 * e1000_config_dsp_after_link_change
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5330
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5331
 * @link_up: was link up at the time this was called
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5332
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5333
 * returns: - E1000_ERR_PHY if fail to read/write the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5334
 *            E1000_SUCCESS at any other case.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5335
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5336
 * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5337
 * gigabit link is achieved to improve link quality.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5338
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5339
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5340
static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5341
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5342
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5343
	u16 phy_data, phy_saved_data, speed, duplex, i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5344
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5345
	e_dbg("e1000_config_dsp_after_link_change");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5346
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5347
	if (hw->phy_type != e1000_phy_igp)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5348
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5349
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5350
	if (link_up) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5351
		ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5352
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5353
			e_dbg("Error getting link speed and duplex\n");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5354
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5355
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5356
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5357
		if (speed == SPEED_1000) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5358
			ret_val = e1000_1000Mb_check_cable_length(hw);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5359
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5360
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5361
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5362
	} else {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5363
		if (hw->dsp_config_state == e1000_dsp_config_activated) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5364
			/* Save off the current value of register 0x2F5B to be restored at
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5365
			 * the end of the routines. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5366
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5367
			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5368
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5369
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5370
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5371
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5372
			/* Disable the PHY transmitter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5373
			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5374
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5375
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5376
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5377
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5378
			msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5379
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5380
			ret_val = e1000_write_phy_reg(hw, 0x0000,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5381
						      IGP01E1000_IEEE_FORCE_GIGA);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5382
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5383
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5384
			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5385
				ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5386
				    e1000_read_phy_reg(hw, dsp_reg_array[i],
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5387
						       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5388
				if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5389
					return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5390
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5391
				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5392
				phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5393
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5394
				ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5395
				    e1000_write_phy_reg(hw, dsp_reg_array[i],
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5396
							phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5397
				if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5398
					return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5399
			}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5400
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5401
			ret_val = e1000_write_phy_reg(hw, 0x0000,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5402
						      IGP01E1000_IEEE_RESTART_AUTONEG);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5403
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5404
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5405
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5406
			msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5407
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5408
			/* Now enable the transmitter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5409
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5410
			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5411
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5412
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5413
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5414
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5415
			hw->dsp_config_state = e1000_dsp_config_enabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5416
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5417
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5418
		if (hw->ffe_config_state == e1000_ffe_config_active) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5419
			/* Save off the current value of register 0x2F5B to be restored at
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5420
			 * the end of the routines. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5421
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5422
			    e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5423
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5424
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5425
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5426
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5427
			/* Disable the PHY transmitter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5428
			ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5429
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5430
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5431
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5432
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5433
			msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5434
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5435
			ret_val = e1000_write_phy_reg(hw, 0x0000,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5436
						      IGP01E1000_IEEE_FORCE_GIGA);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5437
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5438
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5439
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5440
			    e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5441
						IGP01E1000_PHY_DSP_FFE_DEFAULT);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5442
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5443
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5444
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5445
			ret_val = e1000_write_phy_reg(hw, 0x0000,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5446
						      IGP01E1000_IEEE_RESTART_AUTONEG);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5447
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5448
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5449
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5450
			msleep(20);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5451
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5452
			/* Now enable the transmitter */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5453
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5454
			    e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5455
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5456
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5457
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5458
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5459
			hw->ffe_config_state = e1000_ffe_config_enabled;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5460
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5461
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5462
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5463
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5464
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5465
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5466
 * e1000_set_phy_mode - Set PHY to class A mode
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5467
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5468
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5469
 * Assumes the following operations will follow to enable the new class mode.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5470
 *  1. Do a PHY soft reset
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5471
 *  2. Restart auto-negotiation or force link.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5472
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5473
static s32 e1000_set_phy_mode(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5474
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5475
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5476
	u16 eeprom_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5477
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5478
	e_dbg("e1000_set_phy_mode");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5479
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5480
	if ((hw->mac_type == e1000_82545_rev_3) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5481
	    (hw->media_type == e1000_media_type_copper)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5482
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5483
		    e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5484
				      &eeprom_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5485
		if (ret_val) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5486
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5487
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5488
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5489
		if ((eeprom_data != EEPROM_RESERVED_WORD) &&
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5490
		    (eeprom_data & EEPROM_PHY_CLASS_A)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5491
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5492
			    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5493
						0x000B);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5494
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5495
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5496
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5497
			    e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5498
						0x8104);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5499
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5500
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5501
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5502
			hw->phy_reset_disable = false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5503
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5504
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5505
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5506
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5507
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5508
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5509
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5510
 * e1000_set_d3_lplu_state - set d3 link power state
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5511
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5512
 * @active: true to enable lplu false to disable lplu.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5513
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5514
 * This function sets the lplu state according to the active flag.  When
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5515
 * activating lplu this function also disables smart speed and vise versa.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5516
 * lplu will not be activated unless the device autonegotiation advertisement
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5517
 * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5518
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5519
 * returns: - E1000_ERR_PHY if fail to read/write the PHY
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5520
 *            E1000_SUCCESS at any other case.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5521
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5522
static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5523
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5524
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5525
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5526
	e_dbg("e1000_set_d3_lplu_state");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5527
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5528
	if (hw->phy_type != e1000_phy_igp)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5529
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5530
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5531
	/* During driver activity LPLU should not be used or it will attain link
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5532
	 * from the lowest speeds starting from 10Mbps. The capability is used for
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5533
	 * Dx transitions and states */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5534
	if (hw->mac_type == e1000_82541_rev_2
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5535
	    || hw->mac_type == e1000_82547_rev_2) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5536
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5537
		    e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5538
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5539
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5540
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5541
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5542
	if (!active) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5543
		if (hw->mac_type == e1000_82541_rev_2 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5544
		    hw->mac_type == e1000_82547_rev_2) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5545
			phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5546
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5547
			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5548
						phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5549
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5550
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5551
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5552
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5553
		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used during
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5554
		 * Dx states where the power conservation is most important.  During
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5555
		 * driver activity we should enable SmartSpeed, so performance is
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5556
		 * maintained. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5557
		if (hw->smart_speed == e1000_smart_speed_on) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5558
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5559
			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5560
					       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5561
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5562
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5563
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5564
			phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5565
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5566
			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5567
						phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5568
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5569
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5570
		} else if (hw->smart_speed == e1000_smart_speed_off) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5571
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5572
			    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5573
					       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5574
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5575
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5576
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5577
			phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5578
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5579
			    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5580
						phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5581
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5582
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5583
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5584
	} else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5585
		   || (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5586
		   || (hw->autoneg_advertised ==
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5587
		       AUTONEG_ADVERTISE_10_100_ALL)) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5588
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5589
		if (hw->mac_type == e1000_82541_rev_2 ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5590
		    hw->mac_type == e1000_82547_rev_2) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5591
			phy_data |= IGP01E1000_GMII_FLEX_SPD;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5592
			ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5593
			    e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5594
						phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5595
			if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5596
				return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5597
		}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5598
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5599
		/* When LPLU is enabled we should disable SmartSpeed */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5600
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5601
		    e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5602
				       &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5603
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5604
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5605
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5606
		phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5607
		ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5608
		    e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5609
					phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5610
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5611
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5612
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5613
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5614
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5615
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5616
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5617
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5618
 * e1000_set_vco_speed
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5619
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5620
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5621
 * Change VCO speed register to improve Bit Error Rate performance of SERDES.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5622
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5623
static s32 e1000_set_vco_speed(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5624
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5625
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5626
	u16 default_page = 0;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5627
	u16 phy_data;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5628
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5629
	e_dbg("e1000_set_vco_speed");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5630
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5631
	switch (hw->mac_type) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5632
	case e1000_82545_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5633
	case e1000_82546_rev_3:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5634
		break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5635
	default:
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5636
		return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5637
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5638
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5639
	/* Set PHY register 30, page 5, bit 8 to 0 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5640
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5641
	ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5642
	    e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5643
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5644
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5645
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5646
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5647
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5648
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5649
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5650
	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5651
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5652
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5653
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5654
	phy_data &= ~M88E1000_PHY_VCO_REG_BIT8;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5655
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5656
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5657
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5658
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5659
	/* Set PHY register 30, page 4, bit 11 to 1 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5660
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5661
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5662
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5663
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5664
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5665
	ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5666
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5667
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5668
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5669
	phy_data |= M88E1000_PHY_VCO_REG_BIT11;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5670
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5671
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5672
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5673
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5674
	ret_val =
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5675
	    e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5676
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5677
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5678
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5679
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5680
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5681
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5682
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5683
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5684
 * e1000_enable_mng_pass_thru - check for bmc pass through
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5685
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5686
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5687
 * Verifies the hardware needs to allow ARPs to be processed by the host
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5688
 * returns: - true/false
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5689
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5690
u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5691
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5692
	u32 manc;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5693
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5694
	if (hw->asf_firmware_present) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5695
		manc = er32(MANC);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5696
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5697
		if (!(manc & E1000_MANC_RCV_TCO_EN) ||
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5698
		    !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5699
			return false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5700
		if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5701
			return true;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5702
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5703
	return false;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5704
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5705
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5706
static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5707
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5708
	s32 ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5709
	u16 mii_status_reg;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5710
	u16 i;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5711
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5712
	/* Polarity reversal workaround for forced 10F/10H links. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5713
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5714
	/* Disable the transmitter on the PHY */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5715
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5716
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5717
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5718
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5719
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5720
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5721
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5722
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5723
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5724
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5725
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5726
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5727
	/* This loop will early-out if the NO link condition has been met. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5728
	for (i = PHY_FORCE_TIME; i > 0; i--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5729
		/* Read the MII Status Register and wait for Link Status bit
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5730
		 * to be clear.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5731
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5732
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5733
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5734
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5735
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5736
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5737
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5738
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5739
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5740
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5741
		if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5742
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5743
		msleep(100);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5744
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5745
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5746
	/* Recommended delay time after link has been lost */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5747
	msleep(1000);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5748
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5749
	/* Now we will re-enable th transmitter on the PHY */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5750
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5751
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5752
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5753
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5754
	msleep(50);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5755
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5756
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5757
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5758
	msleep(50);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5759
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5760
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5761
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5762
	msleep(50);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5763
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5764
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5765
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5766
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5767
	ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5768
	if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5769
		return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5770
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5771
	/* This loop will early-out if the link condition has been met. */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5772
	for (i = PHY_FORCE_TIME; i > 0; i--) {
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5773
		/* Read the MII Status Register and wait for Link Status bit
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5774
		 * to be set.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5775
		 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5776
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5777
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5778
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5779
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5780
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5781
		ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5782
		if (ret_val)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5783
			return ret_val;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5784
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5785
		if (mii_status_reg & MII_SR_LINK_STATUS)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5786
			break;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5787
		msleep(100);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5788
	}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5789
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5790
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5791
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5792
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5793
 * e1000_get_auto_rd_done
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5794
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5795
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5796
 * Check for EEPROM Auto Read bit done.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5797
 * returns: - E1000_ERR_RESET if fail to reset MAC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5798
 *            E1000_SUCCESS at any other case.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5799
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5800
static s32 e1000_get_auto_rd_done(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5801
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5802
	e_dbg("e1000_get_auto_rd_done");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5803
	msleep(5);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5804
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5805
}
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5806
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5807
/**
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5808
 * e1000_get_phy_cfg_done
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5809
 * @hw: Struct containing variables accessed by shared code
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5810
 *
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5811
 * Checks if the PHY configuration is done
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5812
 * returns: - E1000_ERR_RESET if fail to reset MAC
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5813
 *            E1000_SUCCESS at any other case.
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5814
 */
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5815
static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw)
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5816
{
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5817
	e_dbg("e1000_get_phy_cfg_done");
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5818
	msleep(10);
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5819
	return E1000_SUCCESS;
80177f7aa836 Added e1000 driver for kernel 3.6.
Florian Pose <fp@igh-essen.com>
parents:
diff changeset
  5820
}