Commit 4eb80801 authored by Sasha Neftin's avatar Sasha Neftin Committed by Jeff Kirsher

igc: Add setup link functionality

Add link establishment methods
Add auto negotiation methods
Add read MAC address method
Signed-off-by: default avatarSasha Neftin <sasha.neftin@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 5586838f
......@@ -314,6 +314,7 @@ struct igc_adapter {
struct work_struct reset_task;
struct work_struct watchdog_task;
struct work_struct dma_err_task;
bool fc_autoneg;
u8 tx_timeout_factor;
......
......@@ -177,6 +177,29 @@ static s32 igc_init_nvm_params_base(struct igc_hw *hw)
return 0;
}
/**
* igc_setup_copper_link_base - Configure copper link settings
* @hw: pointer to the HW structure
*
* Configures 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.
*/
static s32 igc_setup_copper_link_base(struct igc_hw *hw)
{
s32 ret_val = 0;
u32 ctrl;
ctrl = rd32(IGC_CTRL);
ctrl |= IGC_CTRL_SLU;
ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
wr32(IGC_CTRL, ctrl);
ret_val = igc_setup_copper_link(hw);
return ret_val;
}
/**
* igc_init_mac_params_base - Init MAC func ptrs.
* @hw: pointer to the HW structure
......@@ -200,6 +223,9 @@ static s32 igc_init_mac_params_base(struct igc_hw *hw)
if (mac->type == igc_i225)
dev_spec->clear_semaphore_once = true;
/* physical interface link setup */
mac->ops.setup_physical_interface = igc_setup_copper_link_base;
return 0;
}
......@@ -242,6 +268,8 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw)
if (ret_val)
return ret_val;
igc_check_for_link_base(hw);
/* Verify phy id and set remaining function pointers */
switch (phy->id) {
case I225_I_PHY_ID:
......@@ -258,10 +286,22 @@ static s32 igc_init_phy_params_base(struct igc_hw *hw)
static s32 igc_get_invariants_base(struct igc_hw *hw)
{
struct igc_mac_info *mac = &hw->mac;
u32 link_mode = 0;
u32 ctrl_ext = 0;
s32 ret_val = 0;
switch (hw->device_id) {
case IGC_DEV_ID_I225_LM:
case IGC_DEV_ID_I225_V:
mac->type = igc_i225;
break;
default:
return -IGC_ERR_MAC_INIT;
}
hw->phy.media_type = igc_media_type_copper;
ctrl_ext = rd32(IGC_CTRL_EXT);
link_mode = ctrl_ext & IGC_CTRL_EXT_LINK_MODE_MASK;
......
......@@ -13,6 +13,11 @@
/* Physical Func Reset Done Indication */
#define IGC_CTRL_EXT_LINK_MODE_MASK 0x00C00000
/* Loop limit on how long we wait for auto-negotiation to complete */
#define COPPER_LINK_UP_LIMIT 10
#define PHY_AUTO_NEG_LIMIT 45
#define PHY_FORCE_LIMIT 20
/* Number of 100 microseconds we wait for PCI Express master disable */
#define MASTER_DISABLE_TIMEOUT 800
/*Blocks new Master requests */
......@@ -54,6 +59,12 @@
#define IGC_CTRL_RST 0x04000000 /* Global reset */
#define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */
#define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
#define IGC_CTRL_FRCSPD 0x00000800 /* Force Speed */
#define IGC_CTRL_FRCDPX 0x00001000 /* Force Duplex */
#define IGC_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
#define IGC_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
/* PBA constants */
#define IGC_PBA_34K 0x0022
......@@ -66,6 +77,29 @@
#define IGC_SWFW_EEP_SM 0x1
#define IGC_SWFW_PHY0_SM 0x2
/* Autoneg Advertisement Register */
#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
/* Link Partner Ability Register (Base Page) */
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
/* 1000BASE-T Control Register */
#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */
#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
/* PHY GPY 211 registers */
#define STANDARD_AN_REG_MASK 0x0007 /* MMD */
#define ANEG_MULTIGBT_AN_CTRL 0x0020 /* MULTI GBT AN Control Register */
#define MMD_DEVADDR_SHIFT 16 /* Shift MMD to higher bits */
#define CR_2500T_FD_CAPS 0x0080 /* Advertise 2500T FD capability */
/* NVM Control */
/* Number of milliseconds for NVM auto read done after MAC reset. */
#define AUTO_READ_DONE_TIMEOUT 10
......@@ -318,6 +352,10 @@
#define PHY_STATUS 0x01 /* Status Register */
#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
/* Bit definitions for valid PHY IDs. I = Integrated E = External */
#define I225_I_PHY_ID 0x67C9DC00
......
This diff is collapsed.
......@@ -15,6 +15,8 @@
/* forward declaration */
s32 igc_disable_pcie_master(struct igc_hw *hw);
s32 igc_check_for_copper_link(struct igc_hw *hw);
s32 igc_config_fc_after_link_up(struct igc_hw *hw);
s32 igc_force_mac_fc(struct igc_hw *hw);
void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count);
s32 igc_setup_link(struct igc_hw *hw);
void igc_clear_hw_cntrs_base(struct igc_hw *hw);
......
......@@ -3403,6 +3403,25 @@ static int igc_probe(struct pci_dev *pdev,
netdev->min_mtu = ETH_MIN_MTU;
netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
/* before reading the NVM, reset the controller to put the device in a
* known good starting state
*/
hw->mac.ops.reset_hw(hw);
if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) {
/* copy the MAC address out of the NVM */
if (hw->mac.ops.read_mac_addr(hw))
dev_err(&pdev->dev, "NVM Read Error\n");
}
memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->dev_addr)) {
dev_err(&pdev->dev, "Invalid MAC Address\n");
err = -EIO;
goto err_eeprom;
}
/* configure RXPBSIZE and TXPBSIZE */
wr32(IGC_RXPBS, I225_RXPBSIZE_DEFAULT);
wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
......@@ -3411,6 +3430,14 @@ static int igc_probe(struct pci_dev *pdev,
INIT_WORK(&adapter->reset_task, igc_reset_task);
/* Initialize link properties that are user-changeable */
adapter->fc_autoneg = true;
hw->mac.autoneg = true;
hw->phy.autoneg_advertised = 0xaf;
hw->fc.requested_mode = igc_fc_default;
hw->fc.current_mode = igc_fc_default;
/* reset the hardware with the new settings */
igc_reset(adapter);
......@@ -3438,6 +3465,9 @@ static int igc_probe(struct pci_dev *pdev,
err_register:
igc_release_hw_control(adapter);
err_eeprom:
if (!igc_check_reset_block(hw))
igc_reset_phy(hw);
err_sw_init:
igc_clear_interrupt_scheme(adapter);
iounmap(adapter->io_addr);
......
This diff is collapsed.
......@@ -12,6 +12,7 @@ s32 igc_get_phy_id(struct igc_hw *hw);
s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations,
u32 usec_interval, bool *success);
s32 igc_check_downshift(struct igc_hw *hw);
s32 igc_setup_copper_link(struct igc_hw *hw);
void igc_power_up_phy_copper(struct igc_hw *hw);
void igc_power_down_phy_copper(struct igc_hw *hw);
s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment