2007-09-17 12:30:59 -07:00
/*******************************************************************************
Intel PRO / 1000 Linux driver
2011-01-04 01:16:44 +00:00
Copyright ( c ) 1999 - 2011 Intel Corporation .
2007-09-17 12:30:59 -07:00
This program is free software ; you can redistribute it and / or modify it
under the terms and conditions of the GNU General Public License ,
version 2 , as published by the Free Software Foundation .
This program is distributed in the hope it will be useful , but WITHOUT
ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License for
more details .
You should have received a copy of the GNU General Public License along with
this program ; if not , write to the Free Software Foundation , Inc . ,
51 Franklin St - Fifth Floor , Boston , MA 02110 - 1301 USA .
The full GNU General Public License is included in this distribution in
the file called " COPYING " .
Contact Information :
Linux NICS < linux . nics @ intel . com >
e1000 - devel Mailing List < e1000 - devel @ lists . sourceforge . net >
Intel Corporation , 5200 N . E . Elam Young Parkway , Hillsboro , OR 97124 - 6497
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <linux/delay.h>
# include "e1000.h"
static s32 e1000_get_phy_cfg_done ( struct e1000_hw * hw ) ;
static s32 e1000_phy_force_speed_duplex ( struct e1000_hw * hw ) ;
static s32 e1000_set_d0_lplu_state ( struct e1000_hw * hw , bool active ) ;
static s32 e1000_wait_autoneg ( struct e1000_hw * hw ) ;
2008-04-29 09:16:05 -07:00
static u32 e1000_get_phy_addr_for_bm_page ( u32 page , u32 reg ) ;
static s32 e1000_access_phy_wakeup_reg_bm ( struct e1000_hw * hw , u32 offset ,
u16 * data , bool read ) ;
2009-06-02 11:29:18 +00:00
static u32 e1000_get_phy_addr_for_hv_page ( u32 page ) ;
static s32 e1000_access_phy_debug_regs_hv ( struct e1000_hw * hw , u32 offset ,
u16 * data , bool read ) ;
2007-09-17 12:30:59 -07:00
/* Cable length tables */
2010-12-11 05:53:42 +00:00
static const u16 e1000_m88_cable_length_table [ ] = {
0 , 50 , 80 , 110 , 140 , 140 , E1000_CABLE_LENGTH_UNDEFINED } ;
2009-12-01 15:47:02 +00:00
# define M88E1000_CABLE_LENGTH_TABLE_SIZE \
ARRAY_SIZE ( e1000_m88_cable_length_table )
2007-09-17 12:30:59 -07:00
2010-12-11 05:53:42 +00:00
static const u16 e1000_igp_2_cable_length_table [ ] = {
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 , 5 , 8 , 11 , 13 , 16 , 18 , 21 , 0 , 0 , 0 , 3 ,
6 , 10 , 13 , 16 , 19 , 23 , 26 , 29 , 32 , 35 , 38 , 41 , 6 , 10 , 14 , 18 , 22 ,
26 , 30 , 33 , 37 , 41 , 44 , 48 , 51 , 54 , 58 , 61 , 21 , 26 , 31 , 35 , 40 ,
44 , 49 , 53 , 57 , 61 , 65 , 68 , 72 , 75 , 79 , 82 , 40 , 45 , 51 , 56 , 61 ,
66 , 70 , 75 , 79 , 83 , 87 , 91 , 94 , 98 , 101 , 104 , 60 , 66 , 72 , 77 , 82 ,
87 , 92 , 96 , 100 , 104 , 108 , 111 , 114 , 117 , 119 , 121 , 83 , 89 , 95 ,
100 , 105 , 109 , 113 , 116 , 119 , 122 , 124 , 104 , 109 , 114 , 118 , 121 ,
124 } ;
2007-09-17 12:30:59 -07:00
# define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
2007-10-18 10:16:33 +02:00
ARRAY_SIZE ( e1000_igp_2_cable_length_table )
2007-09-17 12:30:59 -07:00
2009-06-02 11:29:18 +00:00
# define BM_PHY_REG_PAGE(offset) \
( ( u16 ) ( ( ( offset ) > > PHY_PAGE_SHIFT ) & 0xFFFF ) )
# define BM_PHY_REG_NUM(offset) \
( ( u16 ) ( ( ( offset ) & MAX_PHY_REG_ADDRESS ) | \
( ( ( offset ) > > ( PHY_UPPER_SHIFT - PHY_PAGE_SHIFT ) ) & \
~ MAX_PHY_REG_ADDRESS ) ) )
# define HV_INTC_FC_PAGE_START 768
# define I82578_ADDR_REG 29
# define I82577_ADDR_REG 16
# define I82577_CFG_REG 22
# define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15)
# define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift 100/10 */
# define I82577_CTRL_REG 23
/* 82577 specific PHY registers */
# define I82577_PHY_CTRL_2 18
# define I82577_PHY_STATUS_2 26
# define I82577_PHY_DIAG_STATUS 31
/* I82577 PHY Status 2 */
# define I82577_PHY_STATUS2_REV_POLARITY 0x0400
# define I82577_PHY_STATUS2_MDIX 0x0800
# define I82577_PHY_STATUS2_SPEED_MASK 0x0300
# define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200
/* I82577 PHY Control 2 */
# define I82577_PHY_CTRL2_AUTO_MDIX 0x0400
# define I82577_PHY_CTRL2_FORCE_MDI_MDIX 0x0200
/* I82577 PHY Diagnostics Status */
# define I82577_DSTATUS_CABLE_LENGTH 0x03FC
# define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
/* BM PHY Copper Specific Control 1 */
# define BM_CS_CTRL1 16
# define HV_MUX_DATA_CTRL PHY_REG(776, 16)
# define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400
# define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004
2007-09-17 12:30:59 -07:00
/**
* e1000e_check_reset_block_generic - Check if PHY reset is blocked
* @ hw : pointer to the HW structure
*
* Read the PHY management control register and check whether a PHY reset
* is blocked . If a reset is not blocked return 0 , otherwise
* return E1000_BLK_PHY_RESET ( 12 ) .
* */
s32 e1000e_check_reset_block_generic ( struct e1000_hw * hw )
{
u32 manc ;
manc = er32 ( MANC ) ;
return ( manc & E1000_MANC_BLK_PHY_RST_ON_IDE ) ?
E1000_BLK_PHY_RESET : 0 ;
}
/**
* e1000e_get_phy_id - Retrieve the PHY ID and revision
* @ hw : pointer to the HW structure
*
* Reads the PHY registers and stores the PHY ID and possibly the PHY
* revision in the hardware structure .
* */
s32 e1000e_get_phy_id ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
2009-06-02 11:29:18 +00:00
s32 ret_val = 0 ;
2007-09-17 12:30:59 -07:00
u16 phy_id ;
2009-06-02 11:29:18 +00:00
u16 retry_count = 0 ;
2007-09-17 12:30:59 -07:00
2009-11-20 23:25:26 +00:00
if ( ! ( phy - > ops . read_reg ) )
2009-06-02 11:29:18 +00:00
goto out ;
2007-09-17 12:30:59 -07:00
2009-06-02 11:29:18 +00:00
while ( retry_count < 2 ) {
ret_val = e1e_rphy ( hw , PHY_ID1 , & phy_id ) ;
if ( ret_val )
goto out ;
2007-09-17 12:30:59 -07:00
2009-06-02 11:29:18 +00:00
phy - > id = ( u32 ) ( phy_id < < 16 ) ;
udelay ( 20 ) ;
ret_val = e1e_rphy ( hw , PHY_ID2 , & phy_id ) ;
if ( ret_val )
goto out ;
2007-09-17 12:30:59 -07:00
2009-06-02 11:29:18 +00:00
phy - > id | = ( u32 ) ( phy_id & PHY_REVISION_MASK ) ;
phy - > revision = ( u32 ) ( phy_id & ~ PHY_REVISION_MASK ) ;
if ( phy - > id ! = 0 & & phy - > id ! = PHY_REVISION_MASK )
goto out ;
retry_count + + ;
}
out :
return ret_val ;
2007-09-17 12:30:59 -07:00
}
/**
* e1000e_phy_reset_dsp - Reset PHY DSP
* @ hw : pointer to the HW structure
*
* Reset the digital signal processor .
* */
s32 e1000e_phy_reset_dsp ( struct e1000_hw * hw )
{
s32 ret_val ;
ret_val = e1e_wphy ( hw , M88E1000_PHY_GEN_CONTROL , 0xC1 ) ;
if ( ret_val )
return ret_val ;
return e1e_wphy ( hw , M88E1000_PHY_GEN_CONTROL , 0 ) ;
}
/**
2008-04-23 11:09:14 -07:00
* e1000e_read_phy_reg_mdic - Read MDI control register
2007-09-17 12:30:59 -07:00
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
2008-02-21 15:11:07 -08:00
* Reads the MDI control register in the PHY at offset and stores the
2007-09-17 12:30:59 -07:00
* information read to data .
* */
2008-04-23 11:09:14 -07:00
s32 e1000e_read_phy_reg_mdic ( struct e1000_hw * hw , u32 offset , u16 * data )
2007-09-17 12:30:59 -07:00
{
struct e1000_phy_info * phy = & hw - > phy ;
u32 i , mdic = 0 ;
if ( offset > MAX_PHY_REG_ADDRESS ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " PHY Address %d is out of range \n " , offset ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_PARAM ;
}
2008-03-28 09:15:03 -07:00
/*
* Set up Op - code , Phy Address , and register offset in the MDI
2007-09-17 12:30:59 -07:00
* Control register . The MAC will take care of interfacing with the
* PHY to retrieve the desired data .
*/
mdic = ( ( offset < < E1000_MDIC_REG_SHIFT ) |
( phy - > addr < < E1000_MDIC_PHY_SHIFT ) |
( E1000_MDIC_OP_READ ) ) ;
ew32 ( MDIC , mdic ) ;
2008-03-28 09:15:03 -07:00
/*
* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
* the lower time out
*/
2008-04-23 11:09:14 -07:00
for ( i = 0 ; i < ( E1000_GEN_POLL_TIMEOUT * 3 ) ; i + + ) {
2007-09-17 12:30:59 -07:00
udelay ( 50 ) ;
mdic = er32 ( MDIC ) ;
if ( mdic & E1000_MDIC_READY )
break ;
}
if ( ! ( mdic & E1000_MDIC_READY ) ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " MDI Read did not complete \n " ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_PHY ;
}
if ( mdic & E1000_MDIC_ERROR ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " MDI Error \n " ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_PHY ;
}
* data = ( u16 ) mdic ;
2010-11-24 06:01:46 +00:00
/*
* Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction .
*/
if ( hw - > mac . type = = e1000_pch2lan )
udelay ( 100 ) ;
2007-09-17 12:30:59 -07:00
return 0 ;
}
/**
2008-04-23 11:09:14 -07:00
* e1000e_write_phy_reg_mdic - Write MDI control register
2007-09-17 12:30:59 -07:00
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write to register at offset
*
* Writes data to MDI control register in the PHY at offset .
* */
2008-04-23 11:09:14 -07:00
s32 e1000e_write_phy_reg_mdic ( struct e1000_hw * hw , u32 offset , u16 data )
2007-09-17 12:30:59 -07:00
{
struct e1000_phy_info * phy = & hw - > phy ;
u32 i , mdic = 0 ;
if ( offset > MAX_PHY_REG_ADDRESS ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " PHY Address %d is out of range \n " , offset ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_PARAM ;
}
2008-03-28 09:15:03 -07:00
/*
* Set up Op - code , Phy Address , and register offset in the MDI
2007-09-17 12:30:59 -07:00
* Control register . The MAC will take care of interfacing with the
* PHY to retrieve the desired data .
*/
mdic = ( ( ( u32 ) data ) |
( offset < < E1000_MDIC_REG_SHIFT ) |
( phy - > addr < < E1000_MDIC_PHY_SHIFT ) |
( E1000_MDIC_OP_WRITE ) ) ;
ew32 ( MDIC , mdic ) ;
2008-04-23 11:09:14 -07:00
/*
* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
* the lower time out
*/
for ( i = 0 ; i < ( E1000_GEN_POLL_TIMEOUT * 3 ) ; i + + ) {
udelay ( 50 ) ;
2007-09-17 12:30:59 -07:00
mdic = er32 ( MDIC ) ;
if ( mdic & E1000_MDIC_READY )
break ;
}
if ( ! ( mdic & E1000_MDIC_READY ) ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " MDI Write did not complete \n " ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_PHY ;
}
2008-04-23 11:09:14 -07:00
if ( mdic & E1000_MDIC_ERROR ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " MDI Error \n " ) ;
2008-04-23 11:09:14 -07:00
return - E1000_ERR_PHY ;
}
2007-09-17 12:30:59 -07:00
2010-11-24 06:01:46 +00:00
/*
* Allow some time after each MDIC transaction to avoid
* reading duplicate data in the next MDIC transaction .
*/
if ( hw - > mac . type = = e1000_pch2lan )
udelay ( 100 ) ;
2007-09-17 12:30:59 -07:00
return 0 ;
}
/**
* e1000e_read_phy_reg_m88 - Read m88 PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Acquires semaphore , if necessary , then reads the PHY register at offset
* and storing the retrieved information in data . Release any acquired
* semaphores before exiting .
* */
s32 e1000e_read_phy_reg_m88 ( struct e1000_hw * hw , u32 offset , u16 * data )
{
s32 ret_val ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
2008-04-23 11:09:14 -07:00
ret_val = e1000e_read_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
data ) ;
2007-09-17 12:30:59 -07:00
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2007-09-17 12:30:59 -07:00
return ret_val ;
}
/**
* e1000e_write_phy_reg_m88 - Write m88 PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Acquires semaphore , if necessary , then writes the data to PHY register
* at the offset . Release any acquired semaphores before exiting .
* */
s32 e1000e_write_phy_reg_m88 ( struct e1000_hw * hw , u32 offset , u16 data )
{
s32 ret_val ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
2008-04-23 11:09:14 -07:00
ret_val = e1000e_write_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
data ) ;
2007-09-17 12:30:59 -07:00
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2007-09-17 12:30:59 -07:00
return ret_val ;
}
/**
2009-10-26 11:24:02 +00:00
* __e1000e_read_phy_reg_igp - Read igp PHY register
2007-09-17 12:30:59 -07:00
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
2009-10-26 11:24:02 +00:00
* @ locked : semaphore has already been acquired or not
2007-09-17 12:30:59 -07:00
*
* Acquires semaphore , if necessary , then reads the PHY register at offset
2009-10-26 11:24:02 +00:00
* and stores the retrieved information in data . Release any acquired
2007-09-17 12:30:59 -07:00
* semaphores before exiting .
* */
2009-10-26 11:24:02 +00:00
static s32 __e1000e_read_phy_reg_igp ( struct e1000_hw * hw , u32 offset , u16 * data ,
bool locked )
2007-09-17 12:30:59 -07:00
{
2009-10-26 11:24:02 +00:00
s32 ret_val = 0 ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
if ( ! locked ) {
2009-11-20 23:25:26 +00:00
if ( ! ( hw - > phy . ops . acquire ) )
2009-10-26 11:24:02 +00:00
goto out ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto out ;
}
2007-09-17 12:30:59 -07:00
if ( offset > MAX_PHY_MULTI_PAGE_REG ) {
2008-04-23 11:09:14 -07:00
ret_val = e1000e_write_phy_reg_mdic ( hw ,
IGP01E1000_PHY_PAGE_SELECT ,
( u16 ) offset ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto release ;
2007-09-17 12:30:59 -07:00
}
2008-04-23 11:09:14 -07:00
ret_val = e1000e_read_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
2009-10-26 11:24:02 +00:00
data ) ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
release :
if ( ! locked )
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2009-10-26 11:24:02 +00:00
out :
2007-09-17 12:30:59 -07:00
return ret_val ;
}
2009-10-26 11:24:02 +00:00
/**
* e1000e_read_phy_reg_igp - Read igp PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Acquires semaphore then reads the PHY register at offset and stores the
* retrieved information in data .
* Release the acquired semaphore before exiting .
* */
s32 e1000e_read_phy_reg_igp ( struct e1000_hw * hw , u32 offset , u16 * data )
{
return __e1000e_read_phy_reg_igp ( hw , offset , data , false ) ;
}
/**
* e1000e_read_phy_reg_igp_locked - Read igp PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Reads the PHY register at offset and stores the retrieved information
* in data . Assumes semaphore already acquired .
* */
s32 e1000e_read_phy_reg_igp_locked ( struct e1000_hw * hw , u32 offset , u16 * data )
{
return __e1000e_read_phy_reg_igp ( hw , offset , data , true ) ;
}
2007-09-17 12:30:59 -07:00
/**
* e1000e_write_phy_reg_igp - Write igp PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
2009-10-26 11:24:02 +00:00
* @ locked : semaphore has already been acquired or not
2007-09-17 12:30:59 -07:00
*
* Acquires semaphore , if necessary , then writes the data to PHY register
* at the offset . Release any acquired semaphores before exiting .
* */
2009-10-26 11:24:02 +00:00
static s32 __e1000e_write_phy_reg_igp ( struct e1000_hw * hw , u32 offset , u16 data ,
bool locked )
2007-09-17 12:30:59 -07:00
{
2009-10-26 11:24:02 +00:00
s32 ret_val = 0 ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
if ( ! locked ) {
2009-11-20 23:25:26 +00:00
if ( ! ( hw - > phy . ops . acquire ) )
2009-10-26 11:24:02 +00:00
goto out ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto out ;
}
2007-09-17 12:30:59 -07:00
if ( offset > MAX_PHY_MULTI_PAGE_REG ) {
2008-04-23 11:09:14 -07:00
ret_val = e1000e_write_phy_reg_mdic ( hw ,
IGP01E1000_PHY_PAGE_SELECT ,
( u16 ) offset ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto release ;
2007-09-17 12:30:59 -07:00
}
2008-04-23 11:09:14 -07:00
ret_val = e1000e_write_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
data ) ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
release :
if ( ! locked )
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
out :
2007-09-17 12:30:59 -07:00
return ret_val ;
}
/**
2009-10-26 11:24:02 +00:00
* e1000e_write_phy_reg_igp - Write igp PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Acquires semaphore then writes the data to PHY register
* at the offset . Release any acquired semaphores before exiting .
* */
s32 e1000e_write_phy_reg_igp ( struct e1000_hw * hw , u32 offset , u16 data )
{
return __e1000e_write_phy_reg_igp ( hw , offset , data , false ) ;
}
/**
* e1000e_write_phy_reg_igp_locked - Write igp PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Writes the data to PHY register at the offset .
* Assumes semaphore already acquired .
* */
s32 e1000e_write_phy_reg_igp_locked ( struct e1000_hw * hw , u32 offset , u16 data )
{
return __e1000e_write_phy_reg_igp ( hw , offset , data , true ) ;
}
/**
* __e1000_read_kmrn_reg - Read kumeran register
2007-09-17 12:30:59 -07:00
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
2009-10-26 11:24:02 +00:00
* @ locked : semaphore has already been acquired or not
2007-09-17 12:30:59 -07:00
*
* Acquires semaphore , if necessary . Then reads the PHY register at offset
* using the kumeran interface . The information retrieved is stored in data .
* Release any acquired semaphores before exiting .
* */
2009-10-26 11:24:02 +00:00
static s32 __e1000_read_kmrn_reg ( struct e1000_hw * hw , u32 offset , u16 * data ,
bool locked )
2007-09-17 12:30:59 -07:00
{
u32 kmrnctrlsta ;
2009-10-26 11:24:02 +00:00
s32 ret_val = 0 ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
if ( ! locked ) {
2009-11-20 23:25:26 +00:00
if ( ! ( hw - > phy . ops . acquire ) )
2009-10-26 11:24:02 +00:00
goto out ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto out ;
}
2007-09-17 12:30:59 -07:00
kmrnctrlsta = ( ( offset < < E1000_KMRNCTRLSTA_OFFSET_SHIFT ) &
E1000_KMRNCTRLSTA_OFFSET ) | E1000_KMRNCTRLSTA_REN ;
ew32 ( KMRNCTRLSTA , kmrnctrlsta ) ;
udelay ( 2 ) ;
kmrnctrlsta = er32 ( KMRNCTRLSTA ) ;
* data = ( u16 ) kmrnctrlsta ;
2009-10-26 11:24:02 +00:00
if ( ! locked )
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
out :
2007-09-17 12:30:59 -07:00
return ret_val ;
}
/**
2009-10-26 11:24:02 +00:00
* e1000e_read_kmrn_reg - Read kumeran register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Acquires semaphore then reads the PHY register at offset using the
* kumeran interface . The information retrieved is stored in data .
* Release the acquired semaphore before exiting .
* */
s32 e1000e_read_kmrn_reg ( struct e1000_hw * hw , u32 offset , u16 * data )
{
return __e1000_read_kmrn_reg ( hw , offset , data , false ) ;
}
/**
2009-10-29 13:46:05 +00:00
* e1000e_read_kmrn_reg_locked - Read kumeran register
2009-10-26 11:24:02 +00:00
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Reads the PHY register at offset using the kumeran interface . The
* information retrieved is stored in data .
* Assumes semaphore already acquired .
* */
2009-10-29 13:46:05 +00:00
s32 e1000e_read_kmrn_reg_locked ( struct e1000_hw * hw , u32 offset , u16 * data )
2009-10-26 11:24:02 +00:00
{
return __e1000_read_kmrn_reg ( hw , offset , data , true ) ;
}
/**
* __e1000_write_kmrn_reg - Write kumeran register
2007-09-17 12:30:59 -07:00
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
2009-10-26 11:24:02 +00:00
* @ locked : semaphore has already been acquired or not
2007-09-17 12:30:59 -07:00
*
* Acquires semaphore , if necessary . Then write the data to PHY register
* at the offset using the kumeran interface . Release any acquired semaphores
* before exiting .
* */
2009-10-26 11:24:02 +00:00
static s32 __e1000_write_kmrn_reg ( struct e1000_hw * hw , u32 offset , u16 data ,
bool locked )
2007-09-17 12:30:59 -07:00
{
u32 kmrnctrlsta ;
2009-10-26 11:24:02 +00:00
s32 ret_val = 0 ;
2007-09-17 12:30:59 -07:00
2009-10-26 11:24:02 +00:00
if ( ! locked ) {
2009-11-20 23:25:26 +00:00
if ( ! ( hw - > phy . ops . acquire ) )
2009-10-26 11:24:02 +00:00
goto out ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto out ;
}
2007-09-17 12:30:59 -07:00
kmrnctrlsta = ( ( offset < < E1000_KMRNCTRLSTA_OFFSET_SHIFT ) &
E1000_KMRNCTRLSTA_OFFSET ) | data ;
ew32 ( KMRNCTRLSTA , kmrnctrlsta ) ;
udelay ( 2 ) ;
2009-10-26 11:24:02 +00:00
if ( ! locked )
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2009-10-26 11:24:02 +00:00
out :
2007-09-17 12:30:59 -07:00
return ret_val ;
}
2009-10-26 11:24:02 +00:00
/**
* e1000e_write_kmrn_reg - Write kumeran register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Acquires semaphore then writes the data to the PHY register at the offset
* using the kumeran interface . Release the acquired semaphore before exiting .
* */
s32 e1000e_write_kmrn_reg ( struct e1000_hw * hw , u32 offset , u16 data )
{
return __e1000_write_kmrn_reg ( hw , offset , data , false ) ;
}
/**
2009-10-29 13:46:05 +00:00
* e1000e_write_kmrn_reg_locked - Write kumeran register
2009-10-26 11:24:02 +00:00
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Write the data to PHY register at the offset using the kumeran interface .
* Assumes semaphore already acquired .
* */
2009-10-29 13:46:05 +00:00
s32 e1000e_write_kmrn_reg_locked ( struct e1000_hw * hw , u32 offset , u16 data )
2009-10-26 11:24:02 +00:00
{
return __e1000_write_kmrn_reg ( hw , offset , data , true ) ;
}
2009-06-02 11:29:18 +00:00
/**
* e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
* @ hw : pointer to the HW structure
*
* Sets up Carrier - sense on Transmit and downshift values .
* */
s32 e1000_copper_link_setup_82577 ( struct e1000_hw * hw )
{
s32 ret_val ;
u16 phy_data ;
2010-12-31 06:10:01 +00:00
/* Enable CRS on Tx. This must be set for half-duplex operation. */
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , I82577_CFG_REG , & phy_data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
phy_data | = I82577_CFG_ASSERT_CRS_ON_TX ;
/* Enable downshift */
phy_data | = I82577_CFG_ENABLE_DOWNSHIFT ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_wphy ( hw , I82577_CFG_REG , phy_data ) ;
2009-06-02 11:29:18 +00:00
out :
return ret_val ;
}
2007-09-17 12:30:59 -07:00
/**
* e1000e_copper_link_setup_m88 - Setup m88 PHY ' s for copper link
* @ hw : pointer to the HW structure
*
* Sets up MDI / MDI - X and polarity for m88 PHY ' s . If necessary , transmit clock
* and downshift values are set also .
* */
s32 e1000e_copper_link_setup_m88 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data ;
2008-03-28 09:15:03 -07:00
/* Enable CRS on Tx. This must be set for half-duplex operation. */
2007-09-17 12:30:59 -07:00
ret_val = e1e_rphy ( hw , M88E1000_PHY_SPEC_CTRL , & phy_data ) ;
if ( ret_val )
return ret_val ;
2009-06-02 11:29:18 +00:00
/* For BM PHY this bit is downshift enable */
if ( phy - > type ! = e1000_phy_bm )
2008-04-23 11:09:14 -07:00
phy_data | = M88E1000_PSCR_ASSERT_CRS_ON_TX ;
2007-09-17 12:30:59 -07:00
2008-03-28 09:15:03 -07:00
/*
* Options :
2007-09-17 12:30:59 -07:00
* MDI / MDI - X = 0 ( default )
* 0 - Auto for all speeds
* 1 - MDI mode
* 2 - MDI - X mode
* 3 - Auto for 1000 Base - T only ( MDI - X for 10 / 100 Base - T modes )
*/
phy_data & = ~ M88E1000_PSCR_AUTO_X_MODE ;
switch ( phy - > mdix ) {
case 1 :
phy_data | = M88E1000_PSCR_MDI_MANUAL_MODE ;
break ;
case 2 :
phy_data | = M88E1000_PSCR_MDIX_MANUAL_MODE ;
break ;
case 3 :
phy_data | = M88E1000_PSCR_AUTO_X_1000T ;
break ;
case 0 :
default :
phy_data | = M88E1000_PSCR_AUTO_X_MODE ;
break ;
}
2008-03-28 09:15:03 -07:00
/*
* Options :
2007-09-17 12:30:59 -07:00
* disable_polarity_correction = 0 ( default )
* Automatic Correction for Reversed Cable Polarity
* 0 - Disabled
* 1 - Enabled
*/
phy_data & = ~ M88E1000_PSCR_POLARITY_REVERSAL ;
if ( phy - > disable_polarity_correction = = 1 )
phy_data | = M88E1000_PSCR_POLARITY_REVERSAL ;
2008-04-29 09:16:05 -07:00
/* Enable downshift on BM (disabled by default) */
if ( phy - > type = = e1000_phy_bm )
phy_data | = BME1000_PSCR_ENABLE_DOWNSHIFT ;
2007-09-17 12:30:59 -07:00
ret_val = e1e_wphy ( hw , M88E1000_PHY_SPEC_CTRL , phy_data ) ;
if ( ret_val )
return ret_val ;
2008-08-26 18:37:06 -07:00
if ( ( phy - > type = = e1000_phy_m88 ) & &
( phy - > revision < E1000_REVISION_4 ) & &
( phy - > id ! = BME1000_E_PHY_ID_R2 ) ) {
2008-03-28 09:15:03 -07:00
/*
* Force TX_CLK in the Extended PHY Specific Control Register
2007-09-17 12:30:59 -07:00
* to 25 MHz clock .
*/
ret_val = e1e_rphy ( hw , M88E1000_EXT_PHY_SPEC_CTRL , & phy_data ) ;
if ( ret_val )
return ret_val ;
phy_data | = M88E1000_EPSCR_TX_CLK_25 ;
if ( ( phy - > revision = = 2 ) & &
( phy - > id = = M88E1111_I_PHY_ID ) ) {
/* 82573L PHY - set the downshift counter to 5x. */
phy_data & = ~ M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK ;
phy_data | = M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X ;
} else {
/* Configure Master and Slave downshift values */
phy_data & = ~ ( M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK ) ;
phy_data | = ( M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X ) ;
}
ret_val = e1e_wphy ( hw , M88E1000_EXT_PHY_SPEC_CTRL , phy_data ) ;
if ( ret_val )
return ret_val ;
}
2008-08-26 18:37:06 -07:00
if ( ( phy - > type = = e1000_phy_bm ) & & ( phy - > id = = BME1000_E_PHY_ID_R2 ) ) {
/* Set PHY page 0, register 29 to 0x0003 */
ret_val = e1e_wphy ( hw , 29 , 0x0003 ) ;
if ( ret_val )
return ret_val ;
/* Set PHY page 0, register 30 to 0x0000 */
ret_val = e1e_wphy ( hw , 30 , 0x0000 ) ;
if ( ret_val )
return ret_val ;
}
2007-09-17 12:30:59 -07:00
/* Commit the changes. */
ret_val = e1000e_commit_phy ( hw ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Error committing the PHY changes \n " ) ;
2009-06-02 11:29:18 +00:00
return ret_val ;
}
2007-09-17 12:30:59 -07:00
2009-06-02 11:29:18 +00:00
if ( phy - > type = = e1000_phy_82578 ) {
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , M88E1000_EXT_PHY_SPEC_CTRL , & phy_data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
return ret_val ;
/* 82578 PHY - set the downshift count to 1x. */
phy_data | = I82578_EPSCR_DOWNSHIFT_ENABLE ;
phy_data & = ~ I82578_EPSCR_DOWNSHIFT_COUNTER_MASK ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_wphy ( hw , M88E1000_EXT_PHY_SPEC_CTRL , phy_data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
return ret_val ;
}
return 0 ;
2007-09-17 12:30:59 -07:00
}
/**
* e1000e_copper_link_setup_igp - Setup igp PHY ' s for copper link
* @ hw : pointer to the HW structure
*
* Sets up LPLU , MDI / MDI - X , polarity , Smartspeed and Master / Slave config for
* igp PHY ' s .
* */
s32 e1000e_copper_link_setup_igp ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
ret_val = e1000_phy_hw_reset ( hw ) ;
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Error resetting the PHY. \n " ) ;
2007-09-17 12:30:59 -07:00
return ret_val ;
}
2008-04-23 11:09:14 -07:00
/*
* Wait 100 ms for MAC to configure PHY from NVM settings , to avoid
* timeout issues when LFS is enabled .
*/
msleep ( 100 ) ;
2007-09-17 12:30:59 -07:00
/* disable lplu d0 during driver init */
2009-11-20 23:26:44 +00:00
ret_val = e1000_set_d0_lplu_state ( hw , false ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Error Disabling LPLU D0 \n " ) ;
2007-09-17 12:30:59 -07:00
return ret_val ;
}
/* Configure mdi-mdix settings */
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_CTRL , & data ) ;
if ( ret_val )
return ret_val ;
data & = ~ IGP01E1000_PSCR_AUTO_MDIX ;
switch ( phy - > mdix ) {
case 1 :
data & = ~ IGP01E1000_PSCR_FORCE_MDI_MDIX ;
break ;
case 2 :
data | = IGP01E1000_PSCR_FORCE_MDI_MDIX ;
break ;
case 0 :
default :
data | = IGP01E1000_PSCR_AUTO_MDIX ;
break ;
}
ret_val = e1e_wphy ( hw , IGP01E1000_PHY_PORT_CTRL , data ) ;
if ( ret_val )
return ret_val ;
/* set auto-master slave resolution settings */
if ( hw - > mac . autoneg ) {
2008-03-28 09:15:03 -07:00
/*
* when autonegotiation advertisement is only 1000 Mbps then we
2007-09-17 12:30:59 -07:00
* should disable SmartSpeed and enable Auto MasterSlave
2008-03-28 09:15:03 -07:00
* resolution as hardware default .
*/
2007-09-17 12:30:59 -07:00
if ( phy - > autoneg_advertised = = ADVERTISE_1000_FULL ) {
/* Disable SmartSpeed */
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_CONFIG ,
2008-03-28 09:15:03 -07:00
& data ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
data & = ~ IGP01E1000_PSCFR_SMART_SPEED ;
ret_val = e1e_wphy ( hw , IGP01E1000_PHY_PORT_CONFIG ,
2008-03-28 09:15:03 -07:00
data ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
/* Set auto Master/Slave resolution process */
ret_val = e1e_rphy ( hw , PHY_1000T_CTRL , & data ) ;
if ( ret_val )
return ret_val ;
data & = ~ CR_1000T_MS_ENABLE ;
ret_val = e1e_wphy ( hw , PHY_1000T_CTRL , data ) ;
if ( ret_val )
return ret_val ;
}
ret_val = e1e_rphy ( hw , PHY_1000T_CTRL , & data ) ;
if ( ret_val )
return ret_val ;
/* load defaults for future use */
phy - > original_ms_type = ( data & CR_1000T_MS_ENABLE ) ?
( ( data & CR_1000T_MS_VALUE ) ?
e1000_ms_force_master :
e1000_ms_force_slave ) :
e1000_ms_auto ;
switch ( phy - > ms_type ) {
case e1000_ms_force_master :
data | = ( CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE ) ;
break ;
case e1000_ms_force_slave :
data | = CR_1000T_MS_ENABLE ;
data & = ~ ( CR_1000T_MS_VALUE ) ;
break ;
case e1000_ms_auto :
data & = ~ CR_1000T_MS_ENABLE ;
default :
break ;
}
ret_val = e1e_wphy ( hw , PHY_1000T_CTRL , data ) ;
}
return ret_val ;
}
/**
* e1000_phy_setup_autoneg - Configure PHY for auto - negotiation
* @ hw : pointer to the HW structure
*
* Reads the MII auto - neg advertisement register and / or the 1000 T control
* register and if the PHY is already setup for auto - negotiation , then
* return successful . Otherwise , setup advertisement and flow control to
* the appropriate values for the wanted auto - negotiation .
* */
static s32 e1000_phy_setup_autoneg ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 mii_autoneg_adv_reg ;
u16 mii_1000t_ctrl_reg = 0 ;
phy - > autoneg_advertised & = phy - > autoneg_mask ;
/* Read the MII Auto-Neg Advertisement Register (Address 4). */
ret_val = e1e_rphy ( hw , PHY_AUTONEG_ADV , & mii_autoneg_adv_reg ) ;
if ( ret_val )
return ret_val ;
if ( phy - > autoneg_mask & ADVERTISE_1000_FULL ) {
/* Read the MII 1000Base-T Control Register (Address 9). */
ret_val = e1e_rphy ( hw , PHY_1000T_CTRL , & mii_1000t_ctrl_reg ) ;
if ( ret_val )
return ret_val ;
}
2008-03-28 09:15:03 -07:00
/*
* Need to parse both autoneg_advertised and fc and set up
2007-09-17 12:30:59 -07:00
* the appropriate PHY registers . First we will parse for
* autoneg_advertised software override . Since we can advertise
* a plethora of combinations , we need to check each bit
* individually .
*/
2008-03-28 09:15:03 -07:00
/*
* First we clear all the 10 / 100 mb speed bits in the Auto - Neg
2007-09-17 12:30:59 -07:00
* Advertisement Register ( Address 4 ) and the 1000 mb speed bits in
* the 1000 Base - T Control Register ( Address 9 ) .
*/
mii_autoneg_adv_reg & = ~ ( NWAY_AR_100TX_FD_CAPS |
NWAY_AR_100TX_HD_CAPS |
NWAY_AR_10T_FD_CAPS |
NWAY_AR_10T_HD_CAPS ) ;
mii_1000t_ctrl_reg & = ~ ( CR_1000T_HD_CAPS | CR_1000T_FD_CAPS ) ;
2009-11-20 23:25:07 +00:00
e_dbg ( " autoneg_advertised %x \n " , phy - > autoneg_advertised ) ;
2007-09-17 12:30:59 -07:00
/* Do we want to advertise 10 Mb Half Duplex? */
if ( phy - > autoneg_advertised & ADVERTISE_10_HALF ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Advertise 10mb Half duplex \n " ) ;
2007-09-17 12:30:59 -07:00
mii_autoneg_adv_reg | = NWAY_AR_10T_HD_CAPS ;
}
/* Do we want to advertise 10 Mb Full Duplex? */
if ( phy - > autoneg_advertised & ADVERTISE_10_FULL ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Advertise 10mb Full duplex \n " ) ;
2007-09-17 12:30:59 -07:00
mii_autoneg_adv_reg | = NWAY_AR_10T_FD_CAPS ;
}
/* Do we want to advertise 100 Mb Half Duplex? */
if ( phy - > autoneg_advertised & ADVERTISE_100_HALF ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Advertise 100mb Half duplex \n " ) ;
2007-09-17 12:30:59 -07:00
mii_autoneg_adv_reg | = NWAY_AR_100TX_HD_CAPS ;
}
/* Do we want to advertise 100 Mb Full Duplex? */
if ( phy - > autoneg_advertised & ADVERTISE_100_FULL ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Advertise 100mb Full duplex \n " ) ;
2007-09-17 12:30:59 -07:00
mii_autoneg_adv_reg | = NWAY_AR_100TX_FD_CAPS ;
}
/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
if ( phy - > autoneg_advertised & ADVERTISE_1000_HALF )
2009-11-20 23:25:07 +00:00
e_dbg ( " Advertise 1000mb Half duplex request denied! \n " ) ;
2007-09-17 12:30:59 -07:00
/* Do we want to advertise 1000 Mb Full Duplex? */
if ( phy - > autoneg_advertised & ADVERTISE_1000_FULL ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Advertise 1000mb Full duplex \n " ) ;
2007-09-17 12:30:59 -07:00
mii_1000t_ctrl_reg | = CR_1000T_FD_CAPS ;
}
2008-03-28 09:15:03 -07:00
/*
* Check for a software override of the flow control settings , and
2007-09-17 12:30:59 -07:00
* setup the PHY advertisement registers accordingly . If
* auto - negotiation is enabled , then software will have to set the
* " PAUSE " bits to the correct value in the Auto - Negotiation
* Advertisement Register ( PHY_AUTONEG_ADV ) and re - start auto -
* negotiation .
*
* The possible values of the " fc " parameter are :
* 0 : Flow control is completely disabled
* 1 : Rx flow control is enabled ( we can receive pause frames
* but not send pause frames ) .
* 2 : Tx flow control is enabled ( we can send pause frames
* but we do not support receiving pause frames ) .
2008-03-28 09:15:03 -07:00
* 3 : Both Rx and Tx flow control ( symmetric ) are enabled .
2007-09-17 12:30:59 -07:00
* other : No software override . The flow control configuration
* in the EEPROM is used .
*/
2008-11-21 16:57:36 -08:00
switch ( hw - > fc . current_mode ) {
2007-09-17 12:30:59 -07:00
case e1000_fc_none :
2008-03-28 09:15:03 -07:00
/*
* Flow control ( Rx & Tx ) is completely disabled by a
2007-09-17 12:30:59 -07:00
* software over - ride .
*/
mii_autoneg_adv_reg & = ~ ( NWAY_AR_ASM_DIR | NWAY_AR_PAUSE ) ;
break ;
case e1000_fc_rx_pause :
2008-03-28 09:15:03 -07:00
/*
* Rx Flow control is enabled , and Tx Flow control is
2007-09-17 12:30:59 -07:00
* disabled , by a software over - ride .
2008-03-28 09:15:03 -07:00
*
* Since there really isn ' t a way to advertise that we are
* capable of Rx Pause ONLY , we will advertise that we
* support both symmetric and asymmetric Rx PAUSE . Later
2007-09-17 12:30:59 -07:00
* ( in e1000e_config_fc_after_link_up ) we will disable the
* hw ' s ability to send PAUSE frames .
*/
mii_autoneg_adv_reg | = ( NWAY_AR_ASM_DIR | NWAY_AR_PAUSE ) ;
break ;
case e1000_fc_tx_pause :
2008-03-28 09:15:03 -07:00
/*
* Tx Flow control is enabled , and Rx Flow control is
2007-09-17 12:30:59 -07:00
* disabled , by a software over - ride .
*/
mii_autoneg_adv_reg | = NWAY_AR_ASM_DIR ;
mii_autoneg_adv_reg & = ~ NWAY_AR_PAUSE ;
break ;
case e1000_fc_full :
2008-03-28 09:15:03 -07:00
/*
* Flow control ( both Rx and Tx ) is enabled by a software
2007-09-17 12:30:59 -07:00
* over - ride .
*/
mii_autoneg_adv_reg | = ( NWAY_AR_ASM_DIR | NWAY_AR_PAUSE ) ;
break ;
default :
2009-11-20 23:25:07 +00:00
e_dbg ( " Flow control param set incorrectly \n " ) ;
2007-09-17 12:30:59 -07:00
ret_val = - E1000_ERR_CONFIG ;
return ret_val ;
}
ret_val = e1e_wphy ( hw , PHY_AUTONEG_ADV , mii_autoneg_adv_reg ) ;
if ( ret_val )
return ret_val ;
2009-11-20 23:25:07 +00:00
e_dbg ( " Auto-Neg Advertising %x \n " , mii_autoneg_adv_reg ) ;
2007-09-17 12:30:59 -07:00
2010-12-11 05:53:47 +00:00
if ( phy - > autoneg_mask & ADVERTISE_1000_FULL )
2007-09-17 12:30:59 -07:00
ret_val = e1e_wphy ( hw , PHY_1000T_CTRL , mii_1000t_ctrl_reg ) ;
return ret_val ;
}
/**
* e1000_copper_link_autoneg - Setup / Enable autoneg for copper link
* @ hw : pointer to the HW structure
*
* Performs initial bounds checking on autoneg advertisement parameter , then
* configure to advertise the full capability . Setup the PHY to autoneg
* and restart the negotiation process between the link partner . If
2008-03-28 09:15:03 -07:00
* autoneg_wait_to_complete , then wait for autoneg to complete before exiting .
2007-09-17 12:30:59 -07:00
* */
static s32 e1000_copper_link_autoneg ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_ctrl ;
2008-03-28 09:15:03 -07:00
/*
* Perform some bounds checking on the autoneg advertisement
2007-09-17 12:30:59 -07:00
* parameter .
*/
phy - > autoneg_advertised & = phy - > autoneg_mask ;
2008-03-28 09:15:03 -07:00
/*
* If autoneg_advertised is zero , we assume it was not defaulted
2007-09-17 12:30:59 -07:00
* by the calling code so we set to advertise full capability .
*/
if ( phy - > autoneg_advertised = = 0 )
phy - > autoneg_advertised = phy - > autoneg_mask ;
2009-11-20 23:25:07 +00:00
e_dbg ( " Reconfiguring auto-neg advertisement params \n " ) ;
2007-09-17 12:30:59 -07:00
ret_val = e1000_phy_setup_autoneg ( hw ) ;
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Error Setting up Auto-Negotiation \n " ) ;
2007-09-17 12:30:59 -07:00
return ret_val ;
}
2009-11-20 23:25:07 +00:00
e_dbg ( " Restarting Auto-Neg \n " ) ;
2007-09-17 12:30:59 -07:00
2008-03-28 09:15:03 -07:00
/*
* Restart auto - negotiation by setting the Auto Neg Enable bit and
2007-09-17 12:30:59 -07:00
* the Auto Neg Restart bit in the PHY control register .
*/
ret_val = e1e_rphy ( hw , PHY_CONTROL , & phy_ctrl ) ;
if ( ret_val )
return ret_val ;
phy_ctrl | = ( MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG ) ;
ret_val = e1e_wphy ( hw , PHY_CONTROL , phy_ctrl ) ;
if ( ret_val )
return ret_val ;
2008-03-28 09:15:03 -07:00
/*
* Does the user want to wait for Auto - Neg to complete here , or
2007-09-17 12:30:59 -07:00
* check at a later time ( for example , callback routine ) .
*/
2008-03-28 09:15:16 -07:00
if ( phy - > autoneg_wait_to_complete ) {
2007-09-17 12:30:59 -07:00
ret_val = e1000_wait_autoneg ( hw ) ;
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Error while waiting for "
2007-09-17 12:30:59 -07:00
" autoneg to complete \n " ) ;
return ret_val ;
}
}
hw - > mac . get_link_status = 1 ;
return ret_val ;
}
/**
* e1000e_setup_copper_link - Configure copper link settings
* @ hw : pointer to the HW structure
*
* Calls the appropriate function to configure the link for auto - neg or forced
* speed and duplex . Then we check for link , once link is established calls
* to configure collision distance and flow control are called . If link is
* not established , we return - E1000_ERR_PHY ( - 2 ) .
* */
s32 e1000e_setup_copper_link ( struct e1000_hw * hw )
{
s32 ret_val ;
bool link ;
if ( hw - > mac . autoneg ) {
2008-03-28 09:15:03 -07:00
/*
* Setup autoneg and flow control advertisement and perform
* autonegotiation .
*/
2007-09-17 12:30:59 -07:00
ret_val = e1000_copper_link_autoneg ( hw ) ;
if ( ret_val )
return ret_val ;
} else {
2008-03-28 09:15:03 -07:00
/*
* PHY will be set to 10 H , 10F , 100 H or 100F
* depending on user settings .
*/
2009-11-20 23:25:07 +00:00
e_dbg ( " Forcing Speed and Duplex \n " ) ;
2007-09-17 12:30:59 -07:00
ret_val = e1000_phy_force_speed_duplex ( hw ) ;
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Error Forcing Speed and Duplex \n " ) ;
2007-09-17 12:30:59 -07:00
return ret_val ;
}
}
2008-03-28 09:15:03 -07:00
/*
* Check link status . Wait up to 100 microseconds for link to become
2007-09-17 12:30:59 -07:00
* valid .
*/
ret_val = e1000e_phy_has_link_generic ( hw ,
COPPER_LINK_UP_LIMIT ,
10 ,
& link ) ;
if ( ret_val )
return ret_val ;
if ( link ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Valid link established!!! \n " ) ;
2007-09-17 12:30:59 -07:00
e1000e_config_collision_dist ( hw ) ;
ret_val = e1000e_config_fc_after_link_up ( hw ) ;
} else {
2009-11-20 23:25:07 +00:00
e_dbg ( " Unable to establish link!!! \n " ) ;
2007-09-17 12:30:59 -07:00
}
return ret_val ;
}
/**
* e1000e_phy_force_speed_duplex_igp - Force speed / duplex for igp PHY
* @ hw : pointer to the HW structure
*
* Calls the PHY setup function to force speed and duplex . Clears the
* auto - crossover to force MDI manually . Waits for link and returns
* successful if link up is successful , else - E1000_ERR_PHY ( - 2 ) .
* */
s32 e1000e_phy_force_speed_duplex_igp ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data ;
bool link ;
ret_val = e1e_rphy ( hw , PHY_CONTROL , & phy_data ) ;
if ( ret_val )
return ret_val ;
e1000e_phy_force_speed_duplex_setup ( hw , & phy_data ) ;
ret_val = e1e_wphy ( hw , PHY_CONTROL , phy_data ) ;
if ( ret_val )
return ret_val ;
2008-03-28 09:15:03 -07:00
/*
* Clear Auto - Crossover to force MDI manually . IGP requires MDI
2007-09-17 12:30:59 -07:00
* forced whenever speed and duplex are forced .
*/
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_CTRL , & phy_data ) ;
if ( ret_val )
return ret_val ;
phy_data & = ~ IGP01E1000_PSCR_AUTO_MDIX ;
phy_data & = ~ IGP01E1000_PSCR_FORCE_MDI_MDIX ;
ret_val = e1e_wphy ( hw , IGP01E1000_PHY_PORT_CTRL , phy_data ) ;
if ( ret_val )
return ret_val ;
2009-11-20 23:25:07 +00:00
e_dbg ( " IGP PSCR: %X \n " , phy_data ) ;
2007-09-17 12:30:59 -07:00
udelay ( 1 ) ;
2008-03-28 09:15:16 -07:00
if ( phy - > autoneg_wait_to_complete ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Waiting for forced speed/duplex link on IGP phy. \n " ) ;
2007-09-17 12:30:59 -07:00
ret_val = e1000e_phy_has_link_generic ( hw ,
PHY_FORCE_LIMIT ,
100000 ,
& link ) ;
if ( ret_val )
return ret_val ;
if ( ! link )
2009-11-20 23:25:07 +00:00
e_dbg ( " Link taking longer than expected. \n " ) ;
2007-09-17 12:30:59 -07:00
/* Try once more */
ret_val = e1000e_phy_has_link_generic ( hw ,
PHY_FORCE_LIMIT ,
100000 ,
& link ) ;
if ( ret_val )
return ret_val ;
}
return ret_val ;
}
/**
* e1000e_phy_force_speed_duplex_m88 - Force speed / duplex for m88 PHY
* @ hw : pointer to the HW structure
*
* Calls the PHY setup function to force speed and duplex . Clears the
* auto - crossover to force MDI manually . Resets the PHY to commit the
* changes . If time expires while waiting for link up , we reset the DSP .
2008-03-28 09:15:03 -07:00
* After reset , TX_CLK and CRS on Tx must be set . Return successful upon
2007-09-17 12:30:59 -07:00
* successful completion , else return corresponding error code .
* */
s32 e1000e_phy_force_speed_duplex_m88 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data ;
bool link ;
2008-03-28 09:15:03 -07:00
/*
* Clear Auto - Crossover to force MDI manually . M88E1000 requires MDI
2007-09-17 12:30:59 -07:00
* forced whenever speed and duplex are forced .
*/
ret_val = e1e_rphy ( hw , M88E1000_PHY_SPEC_CTRL , & phy_data ) ;
if ( ret_val )
return ret_val ;
phy_data & = ~ M88E1000_PSCR_AUTO_X_MODE ;
ret_val = e1e_wphy ( hw , M88E1000_PHY_SPEC_CTRL , phy_data ) ;
if ( ret_val )
return ret_val ;
2009-11-20 23:25:07 +00:00
e_dbg ( " M88E1000 PSCR: %X \n " , phy_data ) ;
2007-09-17 12:30:59 -07:00
ret_val = e1e_rphy ( hw , PHY_CONTROL , & phy_data ) ;
if ( ret_val )
return ret_val ;
e1000e_phy_force_speed_duplex_setup ( hw , & phy_data ) ;
ret_val = e1e_wphy ( hw , PHY_CONTROL , phy_data ) ;
if ( ret_val )
return ret_val ;
2008-11-21 16:49:53 -08:00
/* Reset the phy to commit changes. */
ret_val = e1000e_commit_phy ( hw ) ;
if ( ret_val )
return ret_val ;
2007-09-17 12:30:59 -07:00
2008-03-28 09:15:16 -07:00
if ( phy - > autoneg_wait_to_complete ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Waiting for forced speed/duplex link on M88 phy. \n " ) ;
2007-09-17 12:30:59 -07:00
ret_val = e1000e_phy_has_link_generic ( hw , PHY_FORCE_LIMIT ,
100000 , & link ) ;
if ( ret_val )
return ret_val ;
if ( ! link ) {
2009-12-02 17:03:18 +00:00
if ( hw - > phy . type ! = e1000_phy_m88 ) {
e_dbg ( " Link taking longer than expected. \n " ) ;
} else {
/*
* We didn ' t get link .
* Reset the DSP and cross our fingers .
*/
2011-01-06 14:29:49 +00:00
ret_val = e1e_wphy ( hw , M88E1000_PHY_PAGE_SELECT ,
0x001d ) ;
2009-12-02 17:03:18 +00:00
if ( ret_val )
return ret_val ;
ret_val = e1000e_phy_reset_dsp ( hw ) ;
if ( ret_val )
return ret_val ;
}
2007-09-17 12:30:59 -07:00
}
/* Try once more */
ret_val = e1000e_phy_has_link_generic ( hw , PHY_FORCE_LIMIT ,
100000 , & link ) ;
if ( ret_val )
return ret_val ;
}
2009-12-02 17:03:18 +00:00
if ( hw - > phy . type ! = e1000_phy_m88 )
return 0 ;
2007-09-17 12:30:59 -07:00
ret_val = e1e_rphy ( hw , M88E1000_EXT_PHY_SPEC_CTRL , & phy_data ) ;
if ( ret_val )
return ret_val ;
2008-03-28 09:15:03 -07:00
/*
* Resetting the phy means we need to re - force TX_CLK in the
2007-09-17 12:30:59 -07:00
* Extended PHY Specific Control Register to 25 MHz clock from
* the reset value of 2.5 MHz .
*/
phy_data | = M88E1000_EPSCR_TX_CLK_25 ;
ret_val = e1e_wphy ( hw , M88E1000_EXT_PHY_SPEC_CTRL , phy_data ) ;
if ( ret_val )
return ret_val ;
2008-03-28 09:15:03 -07:00
/*
* In addition , we must re - enable CRS on Tx for both half and full
2007-09-17 12:30:59 -07:00
* duplex .
*/
ret_val = e1e_rphy ( hw , M88E1000_PHY_SPEC_CTRL , & phy_data ) ;
if ( ret_val )
return ret_val ;
phy_data | = M88E1000_PSCR_ASSERT_CRS_ON_TX ;
ret_val = e1e_wphy ( hw , M88E1000_PHY_SPEC_CTRL , phy_data ) ;
return ret_val ;
}
2009-12-02 17:03:18 +00:00
/**
* e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex
* @ hw : pointer to the HW structure
*
* Forces the speed and duplex settings of the PHY .
* This is a function pointer entry point only called by
* PHY setup routines .
* */
s32 e1000_phy_force_speed_duplex_ife ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
bool link ;
ret_val = e1e_rphy ( hw , PHY_CONTROL , & data ) ;
if ( ret_val )
goto out ;
e1000e_phy_force_speed_duplex_setup ( hw , & data ) ;
ret_val = e1e_wphy ( hw , PHY_CONTROL , data ) ;
if ( ret_val )
goto out ;
/* Disable MDI-X support for 10/100 */
ret_val = e1e_rphy ( hw , IFE_PHY_MDIX_CONTROL , & data ) ;
if ( ret_val )
goto out ;
data & = ~ IFE_PMC_AUTO_MDIX ;
data & = ~ IFE_PMC_FORCE_MDIX ;
ret_val = e1e_wphy ( hw , IFE_PHY_MDIX_CONTROL , data ) ;
if ( ret_val )
goto out ;
e_dbg ( " IFE PMC: %X \n " , data ) ;
udelay ( 1 ) ;
if ( phy - > autoneg_wait_to_complete ) {
e_dbg ( " Waiting for forced speed/duplex link on IFE phy. \n " ) ;
ret_val = e1000e_phy_has_link_generic ( hw ,
PHY_FORCE_LIMIT ,
100000 ,
& link ) ;
if ( ret_val )
goto out ;
if ( ! link )
e_dbg ( " Link taking longer than expected. \n " ) ;
/* Try once more */
ret_val = e1000e_phy_has_link_generic ( hw ,
PHY_FORCE_LIMIT ,
100000 ,
& link ) ;
if ( ret_val )
goto out ;
}
out :
return ret_val ;
}
2007-09-17 12:30:59 -07:00
/**
* e1000e_phy_force_speed_duplex_setup - Configure forced PHY speed / duplex
* @ hw : pointer to the HW structure
* @ phy_ctrl : pointer to current value of PHY_CONTROL
*
* Forces speed and duplex on the PHY by doing the following : disable flow
* control , force speed / duplex on the MAC , disable auto speed detection ,
* disable auto - negotiation , configure duplex , configure speed , configure
* the collision distance , write configuration to CTRL register . The
* caller must write to the PHY_CONTROL register for these settings to
* take affect .
* */
void e1000e_phy_force_speed_duplex_setup ( struct e1000_hw * hw , u16 * phy_ctrl )
{
struct e1000_mac_info * mac = & hw - > mac ;
u32 ctrl ;
/* Turn off flow control when forcing speed/duplex */
2008-11-21 16:57:36 -08:00
hw - > fc . current_mode = e1000_fc_none ;
2007-09-17 12:30:59 -07:00
/* Force speed/duplex on the mac */
ctrl = er32 ( CTRL ) ;
ctrl | = ( E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX ) ;
ctrl & = ~ E1000_CTRL_SPD_SEL ;
/* Disable Auto Speed Detection */
ctrl & = ~ E1000_CTRL_ASDE ;
/* Disable autoneg on the phy */
* phy_ctrl & = ~ MII_CR_AUTO_NEG_EN ;
/* Forcing Full or Half Duplex? */
if ( mac - > forced_speed_duplex & E1000_ALL_HALF_DUPLEX ) {
ctrl & = ~ E1000_CTRL_FD ;
* phy_ctrl & = ~ MII_CR_FULL_DUPLEX ;
2009-11-20 23:25:07 +00:00
e_dbg ( " Half Duplex \n " ) ;
2007-09-17 12:30:59 -07:00
} else {
ctrl | = E1000_CTRL_FD ;
* phy_ctrl | = MII_CR_FULL_DUPLEX ;
2009-11-20 23:25:07 +00:00
e_dbg ( " Full Duplex \n " ) ;
2007-09-17 12:30:59 -07:00
}
/* Forcing 10mb or 100mb? */
if ( mac - > forced_speed_duplex & E1000_ALL_100_SPEED ) {
ctrl | = E1000_CTRL_SPD_100 ;
* phy_ctrl | = MII_CR_SPEED_100 ;
* phy_ctrl & = ~ ( MII_CR_SPEED_1000 | MII_CR_SPEED_10 ) ;
2009-11-20 23:25:07 +00:00
e_dbg ( " Forcing 100mb \n " ) ;
2007-09-17 12:30:59 -07:00
} else {
ctrl & = ~ ( E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100 ) ;
* phy_ctrl | = MII_CR_SPEED_10 ;
* phy_ctrl & = ~ ( MII_CR_SPEED_1000 | MII_CR_SPEED_100 ) ;
2009-11-20 23:25:07 +00:00
e_dbg ( " Forcing 10mb \n " ) ;
2007-09-17 12:30:59 -07:00
}
e1000e_config_collision_dist ( hw ) ;
ew32 ( CTRL , ctrl ) ;
}
/**
* e1000e_set_d3_lplu_state - Sets low power link up state for D3
* @ hw : pointer to the HW structure
* @ active : boolean used to enable / disable lplu
*
* Success returns 0 , Failure returns 1
*
* The low power link up ( lplu ) state is set to the power management level D3
* and SmartSpeed is disabled when active is true , else clear lplu for D3
* and enable Smartspeed . LPLU and Smartspeed are mutually exclusive . LPLU
* is used during Dx states where the power conservation is most important .
* During driver activity , SmartSpeed should be enabled so performance is
* maintained .
* */
s32 e1000e_set_d3_lplu_state ( struct e1000_hw * hw , bool active )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
ret_val = e1e_rphy ( hw , IGP02E1000_PHY_POWER_MGMT , & data ) ;
if ( ret_val )
return ret_val ;
if ( ! active ) {
data & = ~ IGP02E1000_PM_D3_LPLU ;
2008-04-23 11:09:14 -07:00
ret_val = e1e_wphy ( hw , IGP02E1000_PHY_POWER_MGMT , data ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
2008-03-28 09:15:03 -07:00
/*
* LPLU and SmartSpeed are mutually exclusive . LPLU is used
2007-09-17 12:30:59 -07:00
* during Dx states where the power conservation is most
* important . During driver activity we should enable
2008-03-28 09:15:03 -07:00
* SmartSpeed , so performance is maintained .
*/
2007-09-17 12:30:59 -07:00
if ( phy - > smart_speed = = e1000_smart_speed_on ) {
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_CONFIG ,
2008-03-28 09:15:03 -07:00
& data ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
data | = IGP01E1000_PSCFR_SMART_SPEED ;
ret_val = e1e_wphy ( hw , IGP01E1000_PHY_PORT_CONFIG ,
2008-03-28 09:15:03 -07:00
data ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
} else if ( phy - > smart_speed = = e1000_smart_speed_off ) {
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_CONFIG ,
2008-03-28 09:15:03 -07:00
& data ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
data & = ~ IGP01E1000_PSCFR_SMART_SPEED ;
ret_val = e1e_wphy ( hw , IGP01E1000_PHY_PORT_CONFIG ,
2008-03-28 09:15:03 -07:00
data ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
}
} else if ( ( phy - > autoneg_advertised = = E1000_ALL_SPEED_DUPLEX ) | |
( phy - > autoneg_advertised = = E1000_ALL_NOT_GIG ) | |
( phy - > autoneg_advertised = = E1000_ALL_10_SPEED ) ) {
data | = IGP02E1000_PM_D3_LPLU ;
ret_val = e1e_wphy ( hw , IGP02E1000_PHY_POWER_MGMT , data ) ;
if ( ret_val )
return ret_val ;
/* When LPLU is enabled, we should disable SmartSpeed */
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_CONFIG , & data ) ;
if ( ret_val )
return ret_val ;
data & = ~ IGP01E1000_PSCFR_SMART_SPEED ;
ret_val = e1e_wphy ( hw , IGP01E1000_PHY_PORT_CONFIG , data ) ;
}
return ret_val ;
}
/**
2008-02-21 15:11:07 -08:00
* e1000e_check_downshift - Checks whether a downshift in speed occurred
2007-09-17 12:30:59 -07:00
* @ hw : pointer to the HW structure
*
* Success returns 0 , Failure returns 1
*
* A downshift is detected by querying the PHY link health .
* */
s32 e1000e_check_downshift ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data , offset , mask ;
switch ( phy - > type ) {
case e1000_phy_m88 :
case e1000_phy_gg82563 :
2009-12-01 15:53:48 +00:00
case e1000_phy_bm :
2009-06-02 11:29:18 +00:00
case e1000_phy_82578 :
2007-09-17 12:30:59 -07:00
offset = M88E1000_PHY_SPEC_STATUS ;
mask = M88E1000_PSSR_DOWNSHIFT ;
break ;
case e1000_phy_igp_2 :
case e1000_phy_igp_3 :
offset = IGP01E1000_PHY_LINK_HEALTH ;
mask = IGP01E1000_PLHR_SS_DOWNGRADE ;
break ;
default :
/* speed downshift not supported */
2009-11-20 23:26:44 +00:00
phy - > speed_downgraded = false ;
2007-09-17 12:30:59 -07:00
return 0 ;
}
ret_val = e1e_rphy ( hw , offset , & phy_data ) ;
if ( ! ret_val )
phy - > speed_downgraded = ( phy_data & mask ) ;
return ret_val ;
}
/**
* e1000_check_polarity_m88 - Checks the polarity .
* @ hw : pointer to the HW structure
*
* Success returns 0 , Failure returns - E1000_ERR_PHY ( - 2 )
*
* Polarity is determined based on the PHY specific status register .
* */
2009-12-02 17:03:18 +00:00
s32 e1000_check_polarity_m88 ( struct e1000_hw * hw )
2007-09-17 12:30:59 -07:00
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
ret_val = e1e_rphy ( hw , M88E1000_PHY_SPEC_STATUS , & data ) ;
if ( ! ret_val )
phy - > cable_polarity = ( data & M88E1000_PSSR_REV_POLARITY )
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal ;
return ret_val ;
}
/**
* e1000_check_polarity_igp - Checks the polarity .
* @ hw : pointer to the HW structure
*
* Success returns 0 , Failure returns - E1000_ERR_PHY ( - 2 )
*
* Polarity is determined based on the PHY port status register , and the
* current speed ( since there is no polarity at 100 Mbps ) .
* */
2009-12-02 17:03:18 +00:00
s32 e1000_check_polarity_igp ( struct e1000_hw * hw )
2007-09-17 12:30:59 -07:00
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data , offset , mask ;
2008-03-28 09:15:03 -07:00
/*
* Polarity is determined based on the speed of
* our connection .
*/
2007-09-17 12:30:59 -07:00
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_STATUS , & data ) ;
if ( ret_val )
return ret_val ;
if ( ( data & IGP01E1000_PSSR_SPEED_MASK ) = =
IGP01E1000_PSSR_SPEED_1000MBPS ) {
offset = IGP01E1000_PHY_PCS_INIT_REG ;
mask = IGP01E1000_PHY_POLARITY_MASK ;
} else {
2008-03-28 09:15:03 -07:00
/*
* This really only applies to 10 Mbps since
2007-09-17 12:30:59 -07:00
* there is no polarity for 100 Mbps ( always 0 ) .
*/
offset = IGP01E1000_PHY_PORT_STATUS ;
mask = IGP01E1000_PSSR_POLARITY_REVERSED ;
}
ret_val = e1e_rphy ( hw , offset , & data ) ;
if ( ! ret_val )
phy - > cable_polarity = ( data & mask )
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal ;
return ret_val ;
}
2009-12-02 17:03:18 +00:00
/**
* e1000_check_polarity_ife - Check cable polarity for IFE PHY
* @ hw : pointer to the HW structure
*
* Polarity is determined on the polarity reversal feature being enabled .
* */
s32 e1000_check_polarity_ife ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data , offset , mask ;
/*
* Polarity is determined based on the reversal feature being enabled .
*/
if ( phy - > polarity_correction ) {
offset = IFE_PHY_EXTENDED_STATUS_CONTROL ;
mask = IFE_PESC_POLARITY_REVERSED ;
} else {
offset = IFE_PHY_SPECIAL_CONTROL ;
mask = IFE_PSC_FORCE_POLARITY ;
}
ret_val = e1e_rphy ( hw , offset , & phy_data ) ;
if ( ! ret_val )
phy - > cable_polarity = ( phy_data & mask )
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal ;
return ret_val ;
}
2007-09-17 12:30:59 -07:00
/**
2008-03-28 09:15:03 -07:00
* e1000_wait_autoneg - Wait for auto - neg completion
2007-09-17 12:30:59 -07:00
* @ hw : pointer to the HW structure
*
* Waits for auto - negotiation to complete or for the auto - negotiation time
* limit to expire , which ever happens first .
* */
static s32 e1000_wait_autoneg ( struct e1000_hw * hw )
{
s32 ret_val = 0 ;
u16 i , phy_status ;
/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
for ( i = PHY_AUTO_NEG_LIMIT ; i > 0 ; i - - ) {
ret_val = e1e_rphy ( hw , PHY_STATUS , & phy_status ) ;
if ( ret_val )
break ;
ret_val = e1e_rphy ( hw , PHY_STATUS , & phy_status ) ;
if ( ret_val )
break ;
if ( phy_status & MII_SR_AUTONEG_COMPLETE )
break ;
msleep ( 100 ) ;
}
2008-03-28 09:15:03 -07:00
/*
* PHY_AUTO_NEG_TIME expiration doesn ' t guarantee auto - negotiation
2007-09-17 12:30:59 -07:00
* has completed .
*/
return ret_val ;
}
/**
* e1000e_phy_has_link_generic - Polls PHY for link
* @ hw : pointer to the HW structure
* @ iterations : number of times to poll for link
* @ usec_interval : delay between polling attempts
* @ success : pointer to whether polling was successful or not
*
* Polls the PHY status register for link , ' iterations ' number of times .
* */
s32 e1000e_phy_has_link_generic ( struct e1000_hw * hw , u32 iterations ,
u32 usec_interval , bool * success )
{
s32 ret_val = 0 ;
u16 i , phy_status ;
for ( i = 0 ; i < iterations ; i + + ) {
2008-03-28 09:15:03 -07:00
/*
* Some PHYs require the PHY_STATUS register to be read
2007-09-17 12:30:59 -07:00
* twice due to the link bit being sticky . No harm doing
* it across the board .
*/
ret_val = e1e_rphy ( hw , PHY_STATUS , & phy_status ) ;
if ( ret_val )
2009-07-01 13:28:50 +00:00
/*
* If the first read fails , another entity may have
* ownership of the resources , wait and try again to
* see if they have relinquished the resources yet .
*/
udelay ( usec_interval ) ;
2007-09-17 12:30:59 -07:00
ret_val = e1e_rphy ( hw , PHY_STATUS , & phy_status ) ;
if ( ret_val )
break ;
if ( phy_status & MII_SR_LINK_STATUS )
break ;
if ( usec_interval > = 1000 )
mdelay ( usec_interval / 1000 ) ;
else
udelay ( usec_interval ) ;
}
* success = ( i < iterations ) ;
return ret_val ;
}
/**
* e1000e_get_cable_length_m88 - Determine cable length for m88 PHY
* @ hw : pointer to the HW structure
*
* Reads the PHY specific status register to retrieve the cable length
* information . The cable length is determined by averaging the minimum and
* maximum values to get the " average " cable length . The m88 PHY has four
* possible cable length values , which are :
* Register Value Cable Length
* 0 < 50 meters
* 1 50 - 80 meters
* 2 80 - 110 meters
* 3 110 - 140 meters
* 4 > 140 meters
* */
s32 e1000e_get_cable_length_m88 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data , index ;
ret_val = e1e_rphy ( hw , M88E1000_PHY_SPEC_STATUS , & phy_data ) ;
if ( ret_val )
2009-12-01 15:47:02 +00:00
goto out ;
2007-09-17 12:30:59 -07:00
index = ( phy_data & M88E1000_PSSR_CABLE_LENGTH ) > >
2009-12-01 15:47:02 +00:00
M88E1000_PSSR_CABLE_LENGTH_SHIFT ;
if ( index > = M88E1000_CABLE_LENGTH_TABLE_SIZE - 1 ) {
ret_val = - E1000_ERR_PHY ;
goto out ;
}
2007-09-17 12:30:59 -07:00
phy - > min_cable_length = e1000_m88_cable_length_table [ index ] ;
2009-12-01 15:47:02 +00:00
phy - > max_cable_length = e1000_m88_cable_length_table [ index + 1 ] ;
2007-09-17 12:30:59 -07:00
phy - > cable_length = ( phy - > min_cable_length + phy - > max_cable_length ) / 2 ;
2009-12-01 15:47:02 +00:00
out :
2007-09-17 12:30:59 -07:00
return ret_val ;
}
/**
* e1000e_get_cable_length_igp_2 - Determine cable length for igp2 PHY
* @ hw : pointer to the HW structure
*
* The automatic gain control ( agc ) normalizes the amplitude of the
* received signal , adjusting for the attenuation produced by the
2008-02-21 15:11:07 -08:00
* cable . By reading the AGC registers , which represent the
2009-12-01 15:51:11 +00:00
* combination of coarse and fine gain value , the value can be put
2007-09-17 12:30:59 -07:00
* into a lookup table to obtain the approximate cable length
* for each channel .
* */
s32 e1000e_get_cable_length_igp_2 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data , i , agc_value = 0 ;
u16 cur_agc_index , max_agc_index = 0 ;
u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1 ;
2010-12-01 19:59:50 +00:00
static const u16 agc_reg_array [ IGP02E1000_PHY_CHANNEL_NUM ] = {
IGP02E1000_PHY_AGC_A ,
IGP02E1000_PHY_AGC_B ,
IGP02E1000_PHY_AGC_C ,
IGP02E1000_PHY_AGC_D
} ;
2007-09-17 12:30:59 -07:00
/* Read the AGC registers for all channels */
for ( i = 0 ; i < IGP02E1000_PHY_CHANNEL_NUM ; i + + ) {
ret_val = e1e_rphy ( hw , agc_reg_array [ i ] , & phy_data ) ;
if ( ret_val )
return ret_val ;
2008-03-28 09:15:03 -07:00
/*
* Getting bits 15 : 9 , which represent the combination of
2009-12-01 15:51:11 +00:00
* coarse and fine gain values . The result is a number
2007-09-17 12:30:59 -07:00
* that can be put into the lookup table to obtain the
2008-03-28 09:15:03 -07:00
* approximate cable length .
*/
2007-09-17 12:30:59 -07:00
cur_agc_index = ( phy_data > > IGP02E1000_AGC_LENGTH_SHIFT ) &
IGP02E1000_AGC_LENGTH_MASK ;
/* Array index bound check. */
if ( ( cur_agc_index > = IGP02E1000_CABLE_LENGTH_TABLE_SIZE ) | |
( cur_agc_index = = 0 ) )
return - E1000_ERR_PHY ;
/* Remove min & max AGC values from calculation. */
if ( e1000_igp_2_cable_length_table [ min_agc_index ] >
e1000_igp_2_cable_length_table [ cur_agc_index ] )
min_agc_index = cur_agc_index ;
if ( e1000_igp_2_cable_length_table [ max_agc_index ] <
e1000_igp_2_cable_length_table [ cur_agc_index ] )
max_agc_index = cur_agc_index ;
agc_value + = e1000_igp_2_cable_length_table [ cur_agc_index ] ;
}
agc_value - = ( e1000_igp_2_cable_length_table [ min_agc_index ] +
e1000_igp_2_cable_length_table [ max_agc_index ] ) ;
agc_value / = ( IGP02E1000_PHY_CHANNEL_NUM - 2 ) ;
/* Calculate cable length with the error range of +/- 10 meters. */
phy - > min_cable_length = ( ( agc_value - IGP02E1000_AGC_RANGE ) > 0 ) ?
( agc_value - IGP02E1000_AGC_RANGE ) : 0 ;
phy - > max_cable_length = agc_value + IGP02E1000_AGC_RANGE ;
phy - > cable_length = ( phy - > min_cable_length + phy - > max_cable_length ) / 2 ;
return ret_val ;
}
/**
* e1000e_get_phy_info_m88 - Retrieve PHY information
* @ hw : pointer to the HW structure
*
* Valid for only copper links . Read the PHY status register ( sticky read )
* to verify that link is up . Read the PHY special control register to
* determine the polarity and 10 base - T extended distance . Read the PHY
* special status register to determine MDI / MDIx and current speed . If
* speed is 1000 , then determine cable length , local and remote receiver .
* */
s32 e1000e_get_phy_info_m88 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data ;
bool link ;
2009-12-02 17:03:18 +00:00
if ( phy - > media_type ! = e1000_media_type_copper ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Phy info is only valid for copper media \n " ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_CONFIG ;
}
ret_val = e1000e_phy_has_link_generic ( hw , 1 , 0 , & link ) ;
if ( ret_val )
return ret_val ;
if ( ! link ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Phy info is only valid if link is up \n " ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_CONFIG ;
}
ret_val = e1e_rphy ( hw , M88E1000_PHY_SPEC_CTRL , & phy_data ) ;
if ( ret_val )
return ret_val ;
phy - > polarity_correction = ( phy_data &
M88E1000_PSCR_POLARITY_REVERSAL ) ;
ret_val = e1000_check_polarity_m88 ( hw ) ;
if ( ret_val )
return ret_val ;
ret_val = e1e_rphy ( hw , M88E1000_PHY_SPEC_STATUS , & phy_data ) ;
if ( ret_val )
return ret_val ;
phy - > is_mdix = ( phy_data & M88E1000_PSSR_MDIX ) ;
if ( ( phy_data & M88E1000_PSSR_SPEED ) = = M88E1000_PSSR_1000MBS ) {
ret_val = e1000_get_cable_length ( hw ) ;
if ( ret_val )
return ret_val ;
ret_val = e1e_rphy ( hw , PHY_1000T_STATUS , & phy_data ) ;
if ( ret_val )
return ret_val ;
phy - > local_rx = ( phy_data & SR_1000T_LOCAL_RX_STATUS )
? e1000_1000t_rx_status_ok
: e1000_1000t_rx_status_not_ok ;
phy - > remote_rx = ( phy_data & SR_1000T_REMOTE_RX_STATUS )
? e1000_1000t_rx_status_ok
: e1000_1000t_rx_status_not_ok ;
} else {
/* Set values to "undefined" */
phy - > cable_length = E1000_CABLE_LENGTH_UNDEFINED ;
phy - > local_rx = e1000_1000t_rx_status_undefined ;
phy - > remote_rx = e1000_1000t_rx_status_undefined ;
}
return ret_val ;
}
/**
* e1000e_get_phy_info_igp - Retrieve igp PHY information
* @ hw : pointer to the HW structure
*
* Read PHY status to determine if link is up . If link is up , then
* set / determine 10 base - T extended distance and polarity correction . Read
* PHY port status to determine MDI / MDIx and speed . Based on the speed ,
* determine on the cable length , local and remote receiver .
* */
s32 e1000e_get_phy_info_igp ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
bool link ;
ret_val = e1000e_phy_has_link_generic ( hw , 1 , 0 , & link ) ;
if ( ret_val )
return ret_val ;
if ( ! link ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Phy info is only valid if link is up \n " ) ;
2007-09-17 12:30:59 -07:00
return - E1000_ERR_CONFIG ;
}
2009-11-20 23:26:44 +00:00
phy - > polarity_correction = true ;
2007-09-17 12:30:59 -07:00
ret_val = e1000_check_polarity_igp ( hw ) ;
if ( ret_val )
return ret_val ;
ret_val = e1e_rphy ( hw , IGP01E1000_PHY_PORT_STATUS , & data ) ;
if ( ret_val )
return ret_val ;
phy - > is_mdix = ( data & IGP01E1000_PSSR_MDIX ) ;
if ( ( data & IGP01E1000_PSSR_SPEED_MASK ) = =
IGP01E1000_PSSR_SPEED_1000MBPS ) {
ret_val = e1000_get_cable_length ( hw ) ;
if ( ret_val )
return ret_val ;
ret_val = e1e_rphy ( hw , PHY_1000T_STATUS , & data ) ;
if ( ret_val )
return ret_val ;
phy - > local_rx = ( data & SR_1000T_LOCAL_RX_STATUS )
? e1000_1000t_rx_status_ok
: e1000_1000t_rx_status_not_ok ;
phy - > remote_rx = ( data & SR_1000T_REMOTE_RX_STATUS )
? e1000_1000t_rx_status_ok
: e1000_1000t_rx_status_not_ok ;
} else {
phy - > cable_length = E1000_CABLE_LENGTH_UNDEFINED ;
phy - > local_rx = e1000_1000t_rx_status_undefined ;
phy - > remote_rx = e1000_1000t_rx_status_undefined ;
}
return ret_val ;
}
2009-12-02 17:03:18 +00:00
/**
* e1000_get_phy_info_ife - Retrieves various IFE PHY states
* @ hw : pointer to the HW structure
*
* Populates " phy " structure with various feature states .
* */
s32 e1000_get_phy_info_ife ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
bool link ;
ret_val = e1000e_phy_has_link_generic ( hw , 1 , 0 , & link ) ;
if ( ret_val )
goto out ;
if ( ! link ) {
e_dbg ( " Phy info is only valid if link is up \n " ) ;
ret_val = - E1000_ERR_CONFIG ;
goto out ;
}
ret_val = e1e_rphy ( hw , IFE_PHY_SPECIAL_CONTROL , & data ) ;
if ( ret_val )
goto out ;
phy - > polarity_correction = ( data & IFE_PSC_AUTO_POLARITY_DISABLE )
? false : true ;
if ( phy - > polarity_correction ) {
ret_val = e1000_check_polarity_ife ( hw ) ;
if ( ret_val )
goto out ;
} else {
/* Polarity is forced */
phy - > cable_polarity = ( data & IFE_PSC_FORCE_POLARITY )
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal ;
}
ret_val = e1e_rphy ( hw , IFE_PHY_MDIX_CONTROL , & data ) ;
if ( ret_val )
goto out ;
phy - > is_mdix = ( data & IFE_PMC_MDIX_STATUS ) ? true : false ;
/* The following parameters are undefined for 10/100 operation. */
phy - > cable_length = E1000_CABLE_LENGTH_UNDEFINED ;
phy - > local_rx = e1000_1000t_rx_status_undefined ;
phy - > remote_rx = e1000_1000t_rx_status_undefined ;
out :
return ret_val ;
}
2007-09-17 12:30:59 -07:00
/**
* e1000e_phy_sw_reset - PHY software reset
* @ hw : pointer to the HW structure
*
* Does a software reset of the PHY by reading the PHY control register and
* setting / write the control register reset bit to the PHY .
* */
s32 e1000e_phy_sw_reset ( struct e1000_hw * hw )
{
s32 ret_val ;
u16 phy_ctrl ;
ret_val = e1e_rphy ( hw , PHY_CONTROL , & phy_ctrl ) ;
if ( ret_val )
return ret_val ;
phy_ctrl | = MII_CR_RESET ;
ret_val = e1e_wphy ( hw , PHY_CONTROL , phy_ctrl ) ;
if ( ret_val )
return ret_val ;
udelay ( 1 ) ;
return ret_val ;
}
/**
* e1000e_phy_hw_reset_generic - PHY hardware reset
* @ hw : pointer to the HW structure
*
* Verify the reset block is not blocking us from resetting . Acquire
* semaphore ( if necessary ) and read / set / write the device control reset
* bit in the PHY . Wait the appropriate delay time for the device to
2008-02-21 15:11:07 -08:00
* reset and release the semaphore ( if necessary ) .
2007-09-17 12:30:59 -07:00
* */
s32 e1000e_phy_hw_reset_generic ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u32 ctrl ;
ret_val = e1000_check_reset_block ( hw ) ;
if ( ret_val )
return 0 ;
2009-11-20 23:25:26 +00:00
ret_val = phy - > ops . acquire ( hw ) ;
2007-09-17 12:30:59 -07:00
if ( ret_val )
return ret_val ;
ctrl = er32 ( CTRL ) ;
ew32 ( CTRL , ctrl | E1000_CTRL_PHY_RST ) ;
e1e_flush ( ) ;
udelay ( phy - > reset_delay_us ) ;
ew32 ( CTRL , ctrl ) ;
e1e_flush ( ) ;
udelay ( 150 ) ;
2009-11-20 23:25:26 +00:00
phy - > ops . release ( hw ) ;
2007-09-17 12:30:59 -07:00
return e1000_get_phy_cfg_done ( hw ) ;
}
/**
* e1000e_get_cfg_done - Generic configuration done
* @ hw : pointer to the HW structure
*
* Generic function to wait 10 milli - seconds for configuration to complete
* and return success .
* */
s32 e1000e_get_cfg_done ( struct e1000_hw * hw )
{
mdelay ( 10 ) ;
return 0 ;
}
2008-08-26 18:36:50 -07:00
/**
* e1000e_phy_init_script_igp3 - Inits the IGP3 PHY
* @ hw : pointer to the HW structure
*
* Initializes a Intel Gigabit PHY3 when an EEPROM is not present .
* */
s32 e1000e_phy_init_script_igp3 ( struct e1000_hw * hw )
{
2009-11-20 23:25:07 +00:00
e_dbg ( " Running IGP 3 PHY init script \n " ) ;
2008-08-26 18:36:50 -07:00
/* PHY init IGP 3 */
/* Enable rise/fall, 10-mode work in class-A */
e1e_wphy ( hw , 0x2F5B , 0x9018 ) ;
/* Remove all caps from Replica path filter */
e1e_wphy ( hw , 0x2F52 , 0x0000 ) ;
/* Bias trimming for ADC, AFE and Driver (Default) */
e1e_wphy ( hw , 0x2FB1 , 0x8B24 ) ;
/* Increase Hybrid poly bias */
e1e_wphy ( hw , 0x2FB2 , 0xF8F0 ) ;
/* Add 4% to Tx amplitude in Gig mode */
e1e_wphy ( hw , 0x2010 , 0x10B0 ) ;
/* Disable trimming (TTT) */
e1e_wphy ( hw , 0x2011 , 0x0000 ) ;
/* Poly DC correction to 94.6% + 2% for all channels */
e1e_wphy ( hw , 0x20DD , 0x249A ) ;
/* ABS DC correction to 95.9% */
e1e_wphy ( hw , 0x20DE , 0x00D3 ) ;
/* BG temp curve trim */
e1e_wphy ( hw , 0x28B4 , 0x04CE ) ;
/* Increasing ADC OPAMP stage 1 currents to max */
e1e_wphy ( hw , 0x2F70 , 0x29E4 ) ;
/* Force 1000 ( required for enabling PHY regs configuration) */
e1e_wphy ( hw , 0x0000 , 0x0140 ) ;
/* Set upd_freq to 6 */
e1e_wphy ( hw , 0x1F30 , 0x1606 ) ;
/* Disable NPDFE */
e1e_wphy ( hw , 0x1F31 , 0xB814 ) ;
/* Disable adaptive fixed FFE (Default) */
e1e_wphy ( hw , 0x1F35 , 0x002A ) ;
/* Enable FFE hysteresis */
e1e_wphy ( hw , 0x1F3E , 0x0067 ) ;
/* Fixed FFE for short cable lengths */
e1e_wphy ( hw , 0x1F54 , 0x0065 ) ;
/* Fixed FFE for medium cable lengths */
e1e_wphy ( hw , 0x1F55 , 0x002A ) ;
/* Fixed FFE for long cable lengths */
e1e_wphy ( hw , 0x1F56 , 0x002A ) ;
/* Enable Adaptive Clip Threshold */
e1e_wphy ( hw , 0x1F72 , 0x3FB0 ) ;
/* AHT reset limit to 1 */
e1e_wphy ( hw , 0x1F76 , 0xC0FF ) ;
/* Set AHT master delay to 127 msec */
e1e_wphy ( hw , 0x1F77 , 0x1DEC ) ;
/* Set scan bits for AHT */
e1e_wphy ( hw , 0x1F78 , 0xF9EF ) ;
/* Set AHT Preset bits */
e1e_wphy ( hw , 0x1F79 , 0x0210 ) ;
/* Change integ_factor of channel A to 3 */
e1e_wphy ( hw , 0x1895 , 0x0003 ) ;
/* Change prop_factor of channels BCD to 8 */
e1e_wphy ( hw , 0x1796 , 0x0008 ) ;
/* Change cg_icount + enable integbp for channels BCD */
e1e_wphy ( hw , 0x1798 , 0xD008 ) ;
/*
* Change cg_icount + enable integbp + change prop_factor_master
* to 8 for channel A
*/
e1e_wphy ( hw , 0x1898 , 0xD918 ) ;
/* Disable AHT in Slave mode on channel A */
e1e_wphy ( hw , 0x187A , 0x0800 ) ;
/*
* Enable LPLU and disable AN to 1000 in non - D0a states ,
* Enable SPD + B2B
*/
e1e_wphy ( hw , 0x0019 , 0x008D ) ;
/* Enable restart AN on an1000_dis change */
e1e_wphy ( hw , 0x001B , 0x2080 ) ;
/* Enable wh_fifo read clock in 10/100 modes */
e1e_wphy ( hw , 0x0014 , 0x0045 ) ;
/* Restart AN, Speed selection is 1000 */
e1e_wphy ( hw , 0x0000 , 0x1340 ) ;
return 0 ;
}
2007-09-17 12:30:59 -07:00
/* Internal function pointers */
/**
* e1000_get_phy_cfg_done - Generic PHY configuration done
* @ hw : pointer to the HW structure
*
* Return success if silicon family did not implement a family specific
* get_cfg_done function .
* */
static s32 e1000_get_phy_cfg_done ( struct e1000_hw * hw )
{
if ( hw - > phy . ops . get_cfg_done )
return hw - > phy . ops . get_cfg_done ( hw ) ;
return 0 ;
}
/**
* e1000_phy_force_speed_duplex - Generic force PHY speed / duplex
* @ hw : pointer to the HW structure
*
* When the silicon family has not implemented a forced speed / duplex
* function for the PHY , simply return 0.
* */
static s32 e1000_phy_force_speed_duplex ( struct e1000_hw * hw )
{
if ( hw - > phy . ops . force_speed_duplex )
return hw - > phy . ops . force_speed_duplex ( hw ) ;
return 0 ;
}
/**
* e1000e_get_phy_type_from_id - Get PHY type from id
* @ phy_id : phy_id read from the phy
*
* Returns the phy type from the id .
* */
enum e1000_phy_type e1000e_get_phy_type_from_id ( u32 phy_id )
{
enum e1000_phy_type phy_type = e1000_phy_unknown ;
switch ( phy_id ) {
case M88E1000_I_PHY_ID :
case M88E1000_E_PHY_ID :
case M88E1111_I_PHY_ID :
case M88E1011_I_PHY_ID :
phy_type = e1000_phy_m88 ;
break ;
case IGP01E1000_I_PHY_ID : /* IGP 1 & 2 share this */
phy_type = e1000_phy_igp_2 ;
break ;
case GG82563_E_PHY_ID :
phy_type = e1000_phy_gg82563 ;
break ;
case IGP03E1000_E_PHY_ID :
phy_type = e1000_phy_igp_3 ;
break ;
case IFE_E_PHY_ID :
case IFE_PLUS_E_PHY_ID :
case IFE_C_E_PHY_ID :
phy_type = e1000_phy_ife ;
break ;
2008-04-29 09:16:05 -07:00
case BME1000_E_PHY_ID :
case BME1000_E_PHY_ID_R2 :
phy_type = e1000_phy_bm ;
break ;
2009-06-02 11:29:18 +00:00
case I82578_E_PHY_ID :
phy_type = e1000_phy_82578 ;
break ;
case I82577_E_PHY_ID :
phy_type = e1000_phy_82577 ;
break ;
2010-06-16 13:27:28 +00:00
case I82579_E_PHY_ID :
phy_type = e1000_phy_82579 ;
break ;
2007-09-17 12:30:59 -07:00
default :
phy_type = e1000_phy_unknown ;
break ;
}
return phy_type ;
}
2008-04-29 09:16:05 -07:00
/**
* e1000e_determine_phy_address - Determines PHY address .
* @ hw : pointer to the HW structure
*
* This uses a trial and error method to loop through possible PHY
* addresses . It tests each by reading the PHY ID registers and
* checking for a match .
* */
s32 e1000e_determine_phy_address ( struct e1000_hw * hw )
{
s32 ret_val = - E1000_ERR_PHY_TYPE ;
2009-12-02 17:02:43 +00:00
u32 phy_addr = 0 ;
u32 i ;
2008-04-29 09:16:05 -07:00
enum e1000_phy_type phy_type = e1000_phy_unknown ;
2009-12-02 17:02:43 +00:00
hw - > phy . id = phy_type ;
for ( phy_addr = 0 ; phy_addr < E1000_MAX_PHY_ADDR ; phy_addr + + ) {
hw - > phy . addr = phy_addr ;
i = 0 ;
do {
2008-04-29 09:16:05 -07:00
e1000e_get_phy_id ( hw ) ;
phy_type = e1000e_get_phy_type_from_id ( hw - > phy . id ) ;
2009-12-02 17:02:43 +00:00
/*
2008-04-29 09:16:05 -07:00
* If phy_type is valid , break - we found our
* PHY address
*/
if ( phy_type ! = e1000_phy_unknown ) {
ret_val = 0 ;
2009-12-02 17:02:43 +00:00
goto out ;
2008-04-29 09:16:05 -07:00
}
2011-03-19 00:27:20 +00:00
usleep_range ( 1000 , 2000 ) ;
2009-12-02 17:02:43 +00:00
i + + ;
} while ( i < 10 ) ;
}
2008-04-29 09:16:05 -07:00
2009-12-02 17:02:43 +00:00
out :
2008-04-29 09:16:05 -07:00
return ret_val ;
}
/**
* e1000_get_phy_addr_for_bm_page - Retrieve PHY page address
* @ page : page to access
*
* Returns the phy address for the page requested .
* */
static u32 e1000_get_phy_addr_for_bm_page ( u32 page , u32 reg )
{
u32 phy_addr = 2 ;
if ( ( page > = 768 ) | | ( page = = 0 & & reg = = 25 ) | | ( reg = = 31 ) )
phy_addr = 1 ;
return phy_addr ;
}
/**
* e1000e_write_phy_reg_bm - Write BM PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Acquires semaphore , if necessary , then writes the data to PHY register
* at the offset . Release any acquired semaphores before exiting .
* */
s32 e1000e_write_phy_reg_bm ( struct e1000_hw * hw , u32 offset , u16 data )
{
s32 ret_val ;
u32 page = offset > > IGP_PAGE_SHIFT ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
return ret_val ;
2008-04-29 09:16:05 -07:00
/* Page 800 works differently than the rest so it has its own func */
if ( page = = BM_WUC_PAGE ) {
ret_val = e1000_access_phy_wakeup_reg_bm ( hw , offset , & data ,
false ) ;
goto out ;
}
hw - > phy . addr = e1000_get_phy_addr_for_bm_page ( page , offset ) ;
if ( offset > MAX_PHY_MULTI_PAGE_REG ) {
2011-01-06 07:02:53 +00:00
u32 page_shift , page_select ;
2008-04-29 09:16:05 -07:00
/*
* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
* phy address 1.
*/
if ( hw - > phy . addr = = 1 ) {
page_shift = IGP_PAGE_SHIFT ;
page_select = IGP01E1000_PHY_PAGE_SELECT ;
} else {
page_shift = 0 ;
page_select = BM_PHY_PAGE_SELECT ;
}
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic ( hw , page_select ,
( page < < page_shift ) ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
2008-04-29 09:16:05 -07:00
goto out ;
}
ret_val = e1000e_write_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
data ) ;
out :
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2008-04-29 09:16:05 -07:00
return ret_val ;
}
/**
* e1000e_read_phy_reg_bm - Read BM PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Acquires semaphore , if necessary , then reads the PHY register at offset
* and storing the retrieved information in data . Release any acquired
* semaphores before exiting .
* */
s32 e1000e_read_phy_reg_bm ( struct e1000_hw * hw , u32 offset , u16 * data )
{
s32 ret_val ;
u32 page = offset > > IGP_PAGE_SHIFT ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
return ret_val ;
2008-04-29 09:16:05 -07:00
/* Page 800 works differently than the rest so it has its own func */
if ( page = = BM_WUC_PAGE ) {
ret_val = e1000_access_phy_wakeup_reg_bm ( hw , offset , data ,
true ) ;
goto out ;
}
hw - > phy . addr = e1000_get_phy_addr_for_bm_page ( page , offset ) ;
if ( offset > MAX_PHY_MULTI_PAGE_REG ) {
2011-01-06 07:02:53 +00:00
u32 page_shift , page_select ;
2008-04-29 09:16:05 -07:00
/*
* Page select is register 31 for phy address 1 and 22 for
* phy address 2 and 3. Page select is shifted only for
* phy address 1.
*/
if ( hw - > phy . addr = = 1 ) {
page_shift = IGP_PAGE_SHIFT ;
page_select = IGP01E1000_PHY_PAGE_SELECT ;
} else {
page_shift = 0 ;
page_select = BM_PHY_PAGE_SELECT ;
}
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic ( hw , page_select ,
( page < < page_shift ) ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
2008-04-29 09:16:05 -07:00
goto out ;
}
ret_val = e1000e_read_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
data ) ;
out :
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2008-04-29 09:16:05 -07:00
return ret_val ;
}
2008-08-26 18:37:06 -07:00
/**
* e1000e_read_phy_reg_bm2 - Read BM PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Acquires semaphore , if necessary , then reads the PHY register at offset
* and storing the retrieved information in data . Release any acquired
* semaphores before exiting .
* */
s32 e1000e_read_phy_reg_bm2 ( struct e1000_hw * hw , u32 offset , u16 * data )
{
s32 ret_val ;
u16 page = ( u16 ) ( offset > > IGP_PAGE_SHIFT ) ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
return ret_val ;
2008-08-26 18:37:06 -07:00
/* Page 800 works differently than the rest so it has its own func */
if ( page = = BM_WUC_PAGE ) {
ret_val = e1000_access_phy_wakeup_reg_bm ( hw , offset , data ,
true ) ;
2009-10-26 11:24:02 +00:00
goto out ;
2008-08-26 18:37:06 -07:00
}
hw - > phy . addr = 1 ;
if ( offset > MAX_PHY_MULTI_PAGE_REG ) {
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic ( hw , BM_PHY_PAGE_SELECT ,
page ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto out ;
2008-08-26 18:37:06 -07:00
}
ret_val = e1000e_read_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
data ) ;
2009-10-26 11:24:02 +00:00
out :
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2008-08-26 18:37:06 -07:00
return ret_val ;
}
/**
* e1000e_write_phy_reg_bm2 - Write BM PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Acquires semaphore , if necessary , then writes the data to PHY register
* at the offset . Release any acquired semaphores before exiting .
* */
s32 e1000e_write_phy_reg_bm2 ( struct e1000_hw * hw , u32 offset , u16 data )
{
s32 ret_val ;
u16 page = ( u16 ) ( offset > > IGP_PAGE_SHIFT ) ;
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
return ret_val ;
2008-08-26 18:37:06 -07:00
/* Page 800 works differently than the rest so it has its own func */
if ( page = = BM_WUC_PAGE ) {
ret_val = e1000_access_phy_wakeup_reg_bm ( hw , offset , & data ,
false ) ;
2009-10-26 11:24:02 +00:00
goto out ;
2008-08-26 18:37:06 -07:00
}
hw - > phy . addr = 1 ;
if ( offset > MAX_PHY_MULTI_PAGE_REG ) {
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic ( hw , BM_PHY_PAGE_SELECT ,
page ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
goto out ;
2008-08-26 18:37:06 -07:00
}
ret_val = e1000e_write_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & offset ,
data ) ;
2009-10-26 11:24:02 +00:00
out :
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2008-08-26 18:37:06 -07:00
return ret_val ;
}
2008-04-29 09:16:05 -07:00
/**
* e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read or written
* @ data : pointer to the data to read or write
* @ read : determines if operation is read or write
*
* Acquires semaphore , if necessary , then reads the PHY register at offset
* and storing the retrieved information in data . Release any acquired
* semaphores before exiting . Note that procedure to read the wakeup
* registers are different . It works as such :
* 1 ) Set page 769 , register 17 , bit 2 = 1
* 2 ) Set page to 800 for host ( 801 if we were manageability )
* 3 ) Write the address using the address opcode ( 0x11 )
* 4 ) Read or write the data using the data opcode ( 0x12 )
* 5 ) Restore 769 _17 .2 to its original value
2009-10-26 11:24:02 +00:00
*
* Assumes semaphore already acquired .
2008-04-29 09:16:05 -07:00
* */
static s32 e1000_access_phy_wakeup_reg_bm ( struct e1000_hw * hw , u32 offset ,
u16 * data , bool read )
{
s32 ret_val ;
2009-06-02 11:29:18 +00:00
u16 reg = BM_PHY_REG_NUM ( offset ) ;
2008-04-29 09:16:05 -07:00
u16 phy_reg = 0 ;
2009-06-02 11:29:18 +00:00
/* Gig must be disabled for MDIO accesses to page 800 */
if ( ( hw - > mac . type = = e1000_pchlan ) & &
( ! ( er32 ( PHY_CTRL ) & E1000_PHY_CTRL_GBE_DISABLE ) ) )
2009-12-01 15:53:07 +00:00
e_dbg ( " Attempting to access page 800 while gig enabled. \n " ) ;
2009-06-02 11:29:18 +00:00
2008-04-29 09:16:05 -07:00
/* All operations in this function are phy address 1 */
hw - > phy . addr = 1 ;
/* Set page 769 */
e1000e_write_phy_reg_mdic ( hw , IGP01E1000_PHY_PAGE_SELECT ,
( BM_WUC_ENABLE_PAGE < < IGP_PAGE_SHIFT ) ) ;
ret_val = e1000e_read_phy_reg_mdic ( hw , BM_WUC_ENABLE_REG , & phy_reg ) ;
2009-12-01 15:53:07 +00:00
if ( ret_val ) {
e_dbg ( " Could not read PHY page 769 \n " ) ;
2008-04-29 09:16:05 -07:00
goto out ;
2009-12-01 15:53:07 +00:00
}
2008-04-29 09:16:05 -07:00
/* First clear bit 4 to avoid a power state change */
phy_reg & = ~ ( BM_WUC_HOST_WU_BIT ) ;
ret_val = e1000e_write_phy_reg_mdic ( hw , BM_WUC_ENABLE_REG , phy_reg ) ;
2009-12-01 15:53:07 +00:00
if ( ret_val ) {
e_dbg ( " Could not clear PHY page 769 bit 4 \n " ) ;
2008-04-29 09:16:05 -07:00
goto out ;
2009-12-01 15:53:07 +00:00
}
2008-04-29 09:16:05 -07:00
/* Write bit 2 = 1, and clear bit 4 to 769_17 */
ret_val = e1000e_write_phy_reg_mdic ( hw , BM_WUC_ENABLE_REG ,
phy_reg | BM_WUC_ENABLE_BIT ) ;
2009-12-01 15:53:07 +00:00
if ( ret_val ) {
e_dbg ( " Could not write PHY page 769 bit 2 \n " ) ;
2008-04-29 09:16:05 -07:00
goto out ;
2009-12-01 15:53:07 +00:00
}
2008-04-29 09:16:05 -07:00
/* Select page 800 */
ret_val = e1000e_write_phy_reg_mdic ( hw , IGP01E1000_PHY_PAGE_SELECT ,
( BM_WUC_PAGE < < IGP_PAGE_SHIFT ) ) ;
/* Write the page 800 offset value using opcode 0x11 */
ret_val = e1000e_write_phy_reg_mdic ( hw , BM_WUC_ADDRESS_OPCODE , reg ) ;
2009-12-01 15:53:07 +00:00
if ( ret_val ) {
e_dbg ( " Could not write address opcode to page 800 \n " ) ;
2008-04-29 09:16:05 -07:00
goto out ;
2009-12-01 15:53:07 +00:00
}
2008-04-29 09:16:05 -07:00
if ( read ) {
/* Read the page 800 value using opcode 0x12 */
ret_val = e1000e_read_phy_reg_mdic ( hw , BM_WUC_DATA_OPCODE ,
data ) ;
} else {
2009-12-01 15:51:11 +00:00
/* Write the page 800 value using opcode 0x12 */
2008-04-29 09:16:05 -07:00
ret_val = e1000e_write_phy_reg_mdic ( hw , BM_WUC_DATA_OPCODE ,
* data ) ;
}
2009-12-01 15:53:07 +00:00
if ( ret_val ) {
e_dbg ( " Could not access data value from page 800 \n " ) ;
2008-04-29 09:16:05 -07:00
goto out ;
2009-12-01 15:53:07 +00:00
}
2008-04-29 09:16:05 -07:00
/*
* Restore 769 _17 .2 to its original value
* Set page 769
*/
e1000e_write_phy_reg_mdic ( hw , IGP01E1000_PHY_PAGE_SELECT ,
( BM_WUC_ENABLE_PAGE < < IGP_PAGE_SHIFT ) ) ;
/* Clear 769_17.2 */
ret_val = e1000e_write_phy_reg_mdic ( hw , BM_WUC_ENABLE_REG , phy_reg ) ;
2009-12-01 15:53:07 +00:00
if ( ret_val ) {
e_dbg ( " Could not clear PHY page 769 bit 2 \n " ) ;
goto out ;
}
2008-04-29 09:16:05 -07:00
out :
return ret_val ;
}
2009-12-01 15:47:22 +00:00
/**
* e1000_power_up_phy_copper - Restore copper link in case of PHY power down
* @ hw : pointer to the HW structure
*
* In the case of a PHY power down to save power , or to turn off link during a
* driver unload , or wake on lan is not enabled , restore the link to previous
* settings .
* */
void e1000_power_up_phy_copper ( struct e1000_hw * hw )
{
u16 mii_reg = 0 ;
/* The PHY will retain its settings across a power down/up cycle */
e1e_rphy ( hw , PHY_CONTROL , & mii_reg ) ;
mii_reg & = ~ MII_CR_POWER_DOWN ;
e1e_wphy ( hw , PHY_CONTROL , mii_reg ) ;
}
/**
* e1000_power_down_phy_copper - Restore copper link in case of PHY power down
* @ hw : pointer to the HW structure
*
* In the case of a PHY power down to save power , or to turn off link during a
* driver unload , or wake on lan is not enabled , restore the link to previous
* settings .
* */
void e1000_power_down_phy_copper ( struct e1000_hw * hw )
{
u16 mii_reg = 0 ;
/* The PHY will retain its settings across a power down/up cycle */
e1e_rphy ( hw , PHY_CONTROL , & mii_reg ) ;
mii_reg | = MII_CR_POWER_DOWN ;
e1e_wphy ( hw , PHY_CONTROL , mii_reg ) ;
2011-03-19 00:27:20 +00:00
usleep_range ( 1000 , 2000 ) ;
2009-12-01 15:47:22 +00:00
}
2007-09-17 12:30:59 -07:00
/**
* e1000e_commit_phy - Soft PHY reset
* @ hw : pointer to the HW structure
*
* Performs a soft PHY reset on those that apply . This is a function pointer
* entry point called by drivers .
* */
s32 e1000e_commit_phy ( struct e1000_hw * hw )
{
2009-11-20 23:25:26 +00:00
if ( hw - > phy . ops . commit )
return hw - > phy . ops . commit ( hw ) ;
2007-09-17 12:30:59 -07:00
return 0 ;
}
/**
* e1000_set_d0_lplu_state - Sets low power link up state for D0
* @ hw : pointer to the HW structure
* @ active : boolean used to enable / disable lplu
*
* Success returns 0 , Failure returns 1
*
* The low power link up ( lplu ) state is set to the power management level D0
* and SmartSpeed is disabled when active is true , else clear lplu for D0
* and enable Smartspeed . LPLU and Smartspeed are mutually exclusive . LPLU
* is used during Dx states where the power conservation is most important .
* During driver activity , SmartSpeed should be enabled so performance is
* maintained . This is a function pointer entry point called by drivers .
* */
static s32 e1000_set_d0_lplu_state ( struct e1000_hw * hw , bool active )
{
if ( hw - > phy . ops . set_d0_lplu_state )
return hw - > phy . ops . set_d0_lplu_state ( hw , active ) ;
return 0 ;
}
2009-06-02 11:29:18 +00:00
/**
2009-10-26 11:24:02 +00:00
* __e1000_read_phy_reg_hv - Read HV PHY register
2009-06-02 11:29:18 +00:00
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
2009-10-26 11:24:02 +00:00
* @ locked : semaphore has already been acquired or not
2009-06-02 11:29:18 +00:00
*
* Acquires semaphore , if necessary , then reads the PHY register at offset
2009-10-26 11:24:02 +00:00
* and stores the retrieved information in data . Release any acquired
2009-06-02 11:29:18 +00:00
* semaphore before exiting .
* */
2009-10-26 11:24:02 +00:00
static s32 __e1000_read_phy_reg_hv ( struct e1000_hw * hw , u32 offset , u16 * data ,
bool locked )
2009-06-02 11:29:18 +00:00
{
s32 ret_val ;
u16 page = BM_PHY_REG_PAGE ( offset ) ;
u16 reg = BM_PHY_REG_NUM ( offset ) ;
2009-10-26 11:24:02 +00:00
if ( ! locked ) {
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
return ret_val ;
}
2009-06-02 11:29:18 +00:00
/* Page 800 works differently than the rest so it has its own func */
if ( page = = BM_WUC_PAGE ) {
ret_val = e1000_access_phy_wakeup_reg_bm ( hw , offset ,
data , true ) ;
goto out ;
}
if ( page > 0 & & page < HV_INTC_FC_PAGE_START ) {
ret_val = e1000_access_phy_debug_regs_hv ( hw , offset ,
data , true ) ;
goto out ;
}
hw - > phy . addr = e1000_get_phy_addr_for_hv_page ( page ) ;
if ( page = = HV_INTC_FC_PAGE_START )
page = 0 ;
if ( reg > MAX_PHY_MULTI_PAGE_REG ) {
2009-11-19 12:34:40 +00:00
u32 phy_addr = hw - > phy . addr ;
2009-06-02 11:29:18 +00:00
2009-11-19 12:34:40 +00:00
hw - > phy . addr = 1 ;
2009-06-02 11:29:18 +00:00
2009-11-19 12:34:40 +00:00
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic ( hw ,
IGP01E1000_PHY_PAGE_SELECT ,
( page < < IGP_PAGE_SHIFT ) ) ;
hw - > phy . addr = phy_addr ;
if ( ret_val )
goto out ;
2009-06-02 11:29:18 +00:00
}
ret_val = e1000e_read_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & reg ,
data ) ;
out :
2009-10-26 11:24:02 +00:00
if ( ! locked )
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2009-10-26 11:24:02 +00:00
2009-06-02 11:29:18 +00:00
return ret_val ;
}
/**
2009-10-26 11:24:02 +00:00
* e1000_read_phy_reg_hv - Read HV PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Acquires semaphore then reads the PHY register at offset and stores
* the retrieved information in data . Release the acquired semaphore
* before exiting .
* */
s32 e1000_read_phy_reg_hv ( struct e1000_hw * hw , u32 offset , u16 * data )
{
return __e1000_read_phy_reg_hv ( hw , offset , data , false ) ;
}
/**
* e1000_read_phy_reg_hv_locked - Read HV PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to be read
* @ data : pointer to the read data
*
* Reads the PHY register at offset and stores the retrieved information
* in data . Assumes semaphore already acquired .
* */
s32 e1000_read_phy_reg_hv_locked ( struct e1000_hw * hw , u32 offset , u16 * data )
{
return __e1000_read_phy_reg_hv ( hw , offset , data , true ) ;
}
/**
* __e1000_write_phy_reg_hv - Write HV PHY register
2009-06-02 11:29:18 +00:00
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
2009-10-26 11:24:02 +00:00
* @ locked : semaphore has already been acquired or not
2009-06-02 11:29:18 +00:00
*
* Acquires semaphore , if necessary , then writes the data to PHY register
* at the offset . Release any acquired semaphores before exiting .
* */
2009-10-26 11:24:02 +00:00
static s32 __e1000_write_phy_reg_hv ( struct e1000_hw * hw , u32 offset , u16 data ,
bool locked )
2009-06-02 11:29:18 +00:00
{
s32 ret_val ;
u16 page = BM_PHY_REG_PAGE ( offset ) ;
u16 reg = BM_PHY_REG_NUM ( offset ) ;
2009-10-26 11:24:02 +00:00
if ( ! locked ) {
2009-11-20 23:25:26 +00:00
ret_val = hw - > phy . ops . acquire ( hw ) ;
2009-10-26 11:24:02 +00:00
if ( ret_val )
return ret_val ;
}
2009-06-02 11:29:18 +00:00
/* Page 800 works differently than the rest so it has its own func */
if ( page = = BM_WUC_PAGE ) {
ret_val = e1000_access_phy_wakeup_reg_bm ( hw , offset ,
& data , false ) ;
goto out ;
}
if ( page > 0 & & page < HV_INTC_FC_PAGE_START ) {
ret_val = e1000_access_phy_debug_regs_hv ( hw , offset ,
& data , false ) ;
goto out ;
}
hw - > phy . addr = e1000_get_phy_addr_for_hv_page ( page ) ;
if ( page = = HV_INTC_FC_PAGE_START )
page = 0 ;
/*
* Workaround MDIO accesses being disabled after entering IEEE Power
* Down ( whenever bit 11 of the PHY Control register is set )
*/
if ( ( hw - > phy . type = = e1000_phy_82578 ) & &
( hw - > phy . revision > = 1 ) & &
( hw - > phy . addr = = 2 ) & &
( ( MAX_PHY_REG_ADDRESS & reg ) = = 0 ) & &
( data & ( 1 < < 11 ) ) ) {
u16 data2 = 0x7EFF ;
ret_val = e1000_access_phy_debug_regs_hv ( hw , ( 1 < < 6 ) | 0x3 ,
& data2 , false ) ;
if ( ret_val )
goto out ;
}
if ( reg > MAX_PHY_MULTI_PAGE_REG ) {
2009-11-19 12:34:40 +00:00
u32 phy_addr = hw - > phy . addr ;
2009-06-02 11:29:18 +00:00
2009-11-19 12:34:40 +00:00
hw - > phy . addr = 1 ;
2009-06-02 11:29:18 +00:00
2009-11-19 12:34:40 +00:00
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic ( hw ,
IGP01E1000_PHY_PAGE_SELECT ,
( page < < IGP_PAGE_SHIFT ) ) ;
hw - > phy . addr = phy_addr ;
if ( ret_val )
goto out ;
2009-06-02 11:29:18 +00:00
}
ret_val = e1000e_write_phy_reg_mdic ( hw , MAX_PHY_REG_ADDRESS & reg ,
data ) ;
out :
2009-10-26 11:24:02 +00:00
if ( ! locked )
2009-11-20 23:25:26 +00:00
hw - > phy . ops . release ( hw ) ;
2009-10-26 11:24:02 +00:00
2009-06-02 11:29:18 +00:00
return ret_val ;
}
2009-10-26 11:24:02 +00:00
/**
* e1000_write_phy_reg_hv - Write HV PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Acquires semaphore then writes the data to PHY register at the offset .
* Release the acquired semaphores before exiting .
* */
s32 e1000_write_phy_reg_hv ( struct e1000_hw * hw , u32 offset , u16 data )
{
return __e1000_write_phy_reg_hv ( hw , offset , data , false ) ;
}
/**
* e1000_write_phy_reg_hv_locked - Write HV PHY register
* @ hw : pointer to the HW structure
* @ offset : register offset to write to
* @ data : data to write at register offset
*
* Writes the data to PHY register at the offset . Assumes semaphore
* already acquired .
* */
s32 e1000_write_phy_reg_hv_locked ( struct e1000_hw * hw , u32 offset , u16 data )
{
return __e1000_write_phy_reg_hv ( hw , offset , data , true ) ;
}
2009-06-02 11:29:18 +00:00
/**
tree-wide: fix comment/printk typos
"gadget", "through", "command", "maintain", "maintain", "controller", "address",
"between", "initiali[zs]e", "instead", "function", "select", "already",
"equal", "access", "management", "hierarchy", "registration", "interest",
"relative", "memory", "offset", "already",
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
2010-11-01 15:38:34 -04:00
* e1000_get_phy_addr_for_hv_page - Get PHY address based on page
2009-06-02 11:29:18 +00:00
* @ page : page to be accessed
* */
static u32 e1000_get_phy_addr_for_hv_page ( u32 page )
{
u32 phy_addr = 2 ;
if ( page > = HV_INTC_FC_PAGE_START )
phy_addr = 1 ;
return phy_addr ;
}
/**
* e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers
* @ hw : pointer to the HW structure
* @ offset : register offset to be read or written
* @ data : pointer to the data to be read or written
* @ read : determines if operation is read or written
*
2009-10-26 11:24:02 +00:00
* Reads the PHY register at offset and stores the retreived information
* in data . Assumes semaphore already acquired . Note that the procedure
* to read these regs uses the address port and data port to read / write .
2009-06-02 11:29:18 +00:00
* */
static s32 e1000_access_phy_debug_regs_hv ( struct e1000_hw * hw , u32 offset ,
u16 * data , bool read )
{
s32 ret_val ;
u32 addr_reg = 0 ;
u32 data_reg = 0 ;
/* This takes care of the difference with desktop vs mobile phy */
addr_reg = ( hw - > phy . type = = e1000_phy_82578 ) ?
I82578_ADDR_REG : I82577_ADDR_REG ;
data_reg = addr_reg + 1 ;
/* All operations in this function are phy address 2 */
hw - > phy . addr = 2 ;
/* masking with 0x3F to remove the page from offset */
ret_val = e1000e_write_phy_reg_mdic ( hw , addr_reg , ( u16 ) offset & 0x3F ) ;
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Could not write PHY the HV address register \n " ) ;
2009-06-02 11:29:18 +00:00
goto out ;
}
/* Read or write the data value next */
if ( read )
ret_val = e1000e_read_phy_reg_mdic ( hw , data_reg , data ) ;
else
ret_val = e1000e_write_phy_reg_mdic ( hw , data_reg , * data ) ;
if ( ret_val ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Could not read data value from HV data register \n " ) ;
2009-06-02 11:29:18 +00:00
goto out ;
}
out :
return ret_val ;
}
/**
* e1000_link_stall_workaround_hv - Si workaround
* @ hw : pointer to the HW structure
*
* This function works around a Si bug where the link partner can get
* a link up indication before the PHY does . If small packets are sent
* by the link partner they can be placed in the packet buffer without
* being properly accounted for by the PHY and will stall preventing
* further packets from being received . The workaround is to clear the
* packet buffer after the PHY detects link up .
* */
s32 e1000_link_stall_workaround_hv ( struct e1000_hw * hw )
{
s32 ret_val = 0 ;
u16 data ;
if ( hw - > phy . type ! = e1000_phy_82578 )
goto out ;
2009-07-01 13:27:31 +00:00
/* Do not apply workaround if in PHY loopback bit 14 set */
2011-01-06 14:29:49 +00:00
e1e_rphy ( hw , PHY_CONTROL , & data ) ;
2009-07-01 13:27:31 +00:00
if ( data & PHY_CONTROL_LB )
goto out ;
2009-06-02 11:29:18 +00:00
/* check if link is up and at 1Gbps */
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , BM_CS_STATUS , & data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
data & = BM_CS_STATUS_LINK_UP |
BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_MASK ;
if ( data ! = ( BM_CS_STATUS_LINK_UP |
BM_CS_STATUS_RESOLVED |
BM_CS_STATUS_SPEED_1000 ) )
goto out ;
mdelay ( 200 ) ;
/* flush the packets in the fifo buffer */
2011-01-06 14:29:49 +00:00
ret_val = e1e_wphy ( hw , HV_MUX_DATA_CTRL , HV_MUX_DATA_CTRL_GEN_TO_MAC |
HV_MUX_DATA_CTRL_FORCE_SPEED ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_wphy ( hw , HV_MUX_DATA_CTRL , HV_MUX_DATA_CTRL_GEN_TO_MAC ) ;
2009-06-02 11:29:18 +00:00
out :
return ret_val ;
}
/**
* e1000_check_polarity_82577 - Checks the polarity .
* @ hw : pointer to the HW structure
*
* Success returns 0 , Failure returns - E1000_ERR_PHY ( - 2 )
*
* Polarity is determined based on the PHY specific status register .
* */
s32 e1000_check_polarity_82577 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , I82577_PHY_STATUS_2 , & data ) ;
2009-06-02 11:29:18 +00:00
if ( ! ret_val )
phy - > cable_polarity = ( data & I82577_PHY_STATUS2_REV_POLARITY )
? e1000_rev_polarity_reversed
: e1000_rev_polarity_normal ;
return ret_val ;
}
/**
* e1000_phy_force_speed_duplex_82577 - Force speed / duplex for I82577 PHY
* @ hw : pointer to the HW structure
*
2010-05-10 15:01:30 +00:00
* Calls the PHY setup function to force speed and duplex .
2009-06-02 11:29:18 +00:00
* */
s32 e1000_phy_force_speed_duplex_82577 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data ;
bool link ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , PHY_CONTROL , & phy_data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
e1000e_phy_force_speed_duplex_setup ( hw , & phy_data ) ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_wphy ( hw , PHY_CONTROL , phy_data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
udelay ( 1 ) ;
if ( phy - > autoneg_wait_to_complete ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Waiting for forced speed/duplex link on 82577 phy \n " ) ;
2009-06-02 11:29:18 +00:00
ret_val = e1000e_phy_has_link_generic ( hw ,
PHY_FORCE_LIMIT ,
100000 ,
& link ) ;
if ( ret_val )
goto out ;
if ( ! link )
2009-11-20 23:25:07 +00:00
e_dbg ( " Link taking longer than expected. \n " ) ;
2009-06-02 11:29:18 +00:00
/* Try once more */
ret_val = e1000e_phy_has_link_generic ( hw ,
PHY_FORCE_LIMIT ,
100000 ,
& link ) ;
if ( ret_val )
goto out ;
}
out :
return ret_val ;
}
/**
* e1000_get_phy_info_82577 - Retrieve I82577 PHY information
* @ hw : pointer to the HW structure
*
* Read PHY status to determine if link is up . If link is up , then
* set / determine 10 base - T extended distance and polarity correction . Read
* PHY port status to determine MDI / MDIx and speed . Based on the speed ,
* determine on the cable length , local and remote receiver .
* */
s32 e1000_get_phy_info_82577 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 data ;
bool link ;
ret_val = e1000e_phy_has_link_generic ( hw , 1 , 0 , & link ) ;
if ( ret_val )
goto out ;
if ( ! link ) {
2009-11-20 23:25:07 +00:00
e_dbg ( " Phy info is only valid if link is up \n " ) ;
2009-06-02 11:29:18 +00:00
ret_val = - E1000_ERR_CONFIG ;
goto out ;
}
phy - > polarity_correction = true ;
ret_val = e1000_check_polarity_82577 ( hw ) ;
if ( ret_val )
goto out ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , I82577_PHY_STATUS_2 , & data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
phy - > is_mdix = ( data & I82577_PHY_STATUS2_MDIX ) ? true : false ;
if ( ( data & I82577_PHY_STATUS2_SPEED_MASK ) = =
I82577_PHY_STATUS2_SPEED_1000MBPS ) {
ret_val = hw - > phy . ops . get_cable_length ( hw ) ;
if ( ret_val )
goto out ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , PHY_1000T_STATUS , & data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
phy - > local_rx = ( data & SR_1000T_LOCAL_RX_STATUS )
? e1000_1000t_rx_status_ok
: e1000_1000t_rx_status_not_ok ;
phy - > remote_rx = ( data & SR_1000T_REMOTE_RX_STATUS )
? e1000_1000t_rx_status_ok
: e1000_1000t_rx_status_not_ok ;
} else {
phy - > cable_length = E1000_CABLE_LENGTH_UNDEFINED ;
phy - > local_rx = e1000_1000t_rx_status_undefined ;
phy - > remote_rx = e1000_1000t_rx_status_undefined ;
}
out :
return ret_val ;
}
/**
* e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
* @ hw : pointer to the HW structure
*
* Reads the diagnostic status register and verifies result is valid before
* placing it in the phy_cable_length field .
* */
s32 e1000_get_cable_length_82577 ( struct e1000_hw * hw )
{
struct e1000_phy_info * phy = & hw - > phy ;
s32 ret_val ;
u16 phy_data , length ;
2011-01-06 14:29:49 +00:00
ret_val = e1e_rphy ( hw , I82577_PHY_DIAG_STATUS , & phy_data ) ;
2009-06-02 11:29:18 +00:00
if ( ret_val )
goto out ;
length = ( phy_data & I82577_DSTATUS_CABLE_LENGTH ) > >
I82577_DSTATUS_CABLE_LENGTH_SHIFT ;
if ( length = = E1000_CABLE_LENGTH_UNDEFINED )
2009-11-20 23:23:53 +00:00
ret_val = - E1000_ERR_PHY ;
2009-06-02 11:29:18 +00:00
phy - > cable_length = length ;
out :
return ret_val ;
}