Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/e1000/e1000_82575.c
Show First 20 Lines • Show All 1,229 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct e1000_phy_info *phy = &hw->phy; | struct e1000_phy_info *phy = &hw->phy; | ||||
s32 ret_val; | s32 ret_val; | ||||
u16 data; | u16 data; | ||||
u8 port = 0; | u8 port = 0; | ||||
DEBUGFUNC("e1000_check_for_link_media_swap"); | DEBUGFUNC("e1000_check_for_link_media_swap"); | ||||
/* Check the copper medium. */ | /* Check for copper. */ | ||||
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); | ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); | ||||
if (ret_val) | if (ret_val) | ||||
return ret_val; | return ret_val; | ||||
ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); | ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); | ||||
if (ret_val) | if (ret_val) | ||||
return ret_val; | return ret_val; | ||||
if (data & E1000_M88E1112_STATUS_LINK) | if (data & E1000_M88E1112_STATUS_LINK) | ||||
port = E1000_MEDIA_PORT_COPPER; | port = E1000_MEDIA_PORT_COPPER; | ||||
/* Check the other medium. */ | /* Check for other. */ | ||||
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); | ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); | ||||
if (ret_val) | if (ret_val) | ||||
return ret_val; | return ret_val; | ||||
ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); | ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); | ||||
if (ret_val) | if (ret_val) | ||||
return ret_val; | return ret_val; | ||||
/* reset page to 0 */ | |||||
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); | |||||
if (ret_val) | |||||
return ret_val; | |||||
if (data & E1000_M88E1112_STATUS_LINK) | if (data & E1000_M88E1112_STATUS_LINK) | ||||
port = E1000_MEDIA_PORT_OTHER; | port = E1000_MEDIA_PORT_OTHER; | ||||
/* Determine if a swap needs to happen. */ | /* Determine if a swap needs to happen. */ | ||||
if (port && (hw->dev_spec._82575.media_port != port)) { | if (port && (hw->dev_spec._82575.media_port != port)) { | ||||
hw->dev_spec._82575.media_port = port; | hw->dev_spec._82575.media_port = port; | ||||
hw->dev_spec._82575.media_changed = TRUE; | hw->dev_spec._82575.media_changed = TRUE; | ||||
} | |||||
if (port == E1000_MEDIA_PORT_COPPER) { | |||||
/* reset page to 0 */ | |||||
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); | |||||
if (ret_val) | |||||
return ret_val; | |||||
e1000_check_for_link_82575(hw); | |||||
} else { | } else { | ||||
ret_val = e1000_check_for_link_82575(hw); | e1000_check_for_link_82575(hw); | ||||
/* reset page to 0 */ | |||||
ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); | |||||
if (ret_val) | |||||
return ret_val; | |||||
} | } | ||||
return E1000_SUCCESS; | return E1000_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown | * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
▲ Show 20 Lines • Show All 850 Lines • ▼ Show 20 Lines | |||||
* function clears the fifos and flushes any packets that came in as rx was | * function clears the fifos and flushes any packets that came in as rx was | ||||
* being enabled. | * being enabled. | ||||
**/ | **/ | ||||
void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) | void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) | ||||
{ | { | ||||
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; | u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; | ||||
int i, ms_wait; | int i, ms_wait; | ||||
DEBUGFUNC("e1000_rx_fifo_workaround_82575"); | DEBUGFUNC("e1000_rx_fifo_flush_82575"); | ||||
/* disable IPv6 options as per hardware errata */ | |||||
rfctl = E1000_READ_REG(hw, E1000_RFCTL); | |||||
rfctl |= E1000_RFCTL_IPV6_EX_DIS; | |||||
E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); | |||||
if (hw->mac.type != e1000_82575 || | if (hw->mac.type != e1000_82575 || | ||||
!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) | !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) | ||||
return; | return; | ||||
/* Disable all Rx queues */ | /* Disable all Rx queues */ | ||||
for (i = 0; i < 4; i++) { | for (i = 0; i < 4; i++) { | ||||
rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); | rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); | ||||
E1000_WRITE_REG(hw, E1000_RXDCTL(i), | E1000_WRITE_REG(hw, E1000_RXDCTL(i), | ||||
Show All 11 Lines | void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) | ||||
if (ms_wait == 10) | if (ms_wait == 10) | ||||
DEBUGOUT("Queue disable timed out after 10ms\n"); | DEBUGOUT("Queue disable timed out after 10ms\n"); | ||||
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all | /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all | ||||
* incoming packets are rejected. Set enable and wait 2ms so that | * incoming packets are rejected. Set enable and wait 2ms so that | ||||
* any packet that was coming in as RCTL.EN was set is flushed | * any packet that was coming in as RCTL.EN was set is flushed | ||||
*/ | */ | ||||
rfctl = E1000_READ_REG(hw, E1000_RFCTL); | |||||
E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); | E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); | ||||
rlpml = E1000_READ_REG(hw, E1000_RLPML); | rlpml = E1000_READ_REG(hw, E1000_RLPML); | ||||
E1000_WRITE_REG(hw, E1000_RLPML, 0); | E1000_WRITE_REG(hw, E1000_RLPML, 0); | ||||
rctl = E1000_READ_REG(hw, E1000_RCTL); | rctl = E1000_READ_REG(hw, E1000_RCTL); | ||||
temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); | temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); | ||||
temp_rctl |= E1000_RCTL_LPE; | temp_rctl |= E1000_RCTL_LPE; | ||||
▲ Show 20 Lines • Show All 713 Lines • ▼ Show 20 Lines | s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) | ||||
msec_delay(1000); | msec_delay(1000); | ||||
out: | out: | ||||
return ret_val; | return ret_val; | ||||
} | } | ||||
/** | /** | ||||
* e1000_set_eee_i350 - Enable/disable EEE support | * e1000_set_eee_i350 - Enable/disable EEE support | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* @adv1g: boolean flag enabling 1G EEE advertisement | |||||
* @adv100m: boolean flag enabling 100M EEE advertisement | |||||
* | * | ||||
* Enable/disable EEE based on setting in dev_spec structure. | * Enable/disable EEE based on setting in dev_spec structure. | ||||
* | * | ||||
**/ | **/ | ||||
s32 e1000_set_eee_i350(struct e1000_hw *hw) | s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M) | ||||
{ | { | ||||
u32 ipcnfg, eeer; | u32 ipcnfg, eeer; | ||||
DEBUGFUNC("e1000_set_eee_i350"); | DEBUGFUNC("e1000_set_eee_i350"); | ||||
if ((hw->mac.type < e1000_i350) || | if ((hw->mac.type < e1000_i350) || | ||||
(hw->phy.media_type != e1000_media_type_copper)) | (hw->phy.media_type != e1000_media_type_copper)) | ||||
goto out; | goto out; | ||||
ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); | ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); | ||||
eeer = E1000_READ_REG(hw, E1000_EEER); | eeer = E1000_READ_REG(hw, E1000_EEER); | ||||
/* enable or disable per user setting */ | /* enable or disable per user setting */ | ||||
if (!(hw->dev_spec._82575.eee_disable)) { | if (!(hw->dev_spec._82575.eee_disable)) { | ||||
u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); | u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); | ||||
ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); | if (adv100M) | ||||
ipcnfg |= E1000_IPCNFG_EEE_100M_AN; | |||||
else | |||||
ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN; | |||||
if (adv1G) | |||||
ipcnfg |= E1000_IPCNFG_EEE_1G_AN; | |||||
else | |||||
ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN; | |||||
eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | | eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | | ||||
E1000_EEER_LPI_FC); | E1000_EEER_LPI_FC); | ||||
/* This bit should not be set in normal operation. */ | /* This bit should not be set in normal operation. */ | ||||
if (eee_su & E1000_EEE_SU_LPI_CLK_STP) | if (eee_su & E1000_EEE_SU_LPI_CLK_STP) | ||||
DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); | DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); | ||||
} else { | } else { | ||||
ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); | ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); | ||||
eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | | eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | | ||||
E1000_EEER_LPI_FC); | E1000_EEER_LPI_FC); | ||||
} | } | ||||
E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg); | E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg); | ||||
E1000_WRITE_REG(hw, E1000_EEER, eeer); | E1000_WRITE_REG(hw, E1000_EEER, eeer); | ||||
E1000_READ_REG(hw, E1000_IPCNFG); | E1000_READ_REG(hw, E1000_IPCNFG); | ||||
E1000_READ_REG(hw, E1000_EEER); | E1000_READ_REG(hw, E1000_EEER); | ||||
out: | out: | ||||
return E1000_SUCCESS; | return E1000_SUCCESS; | ||||
} | } | ||||
/** | /** | ||||
* e1000_set_eee_i354 - Enable/disable EEE support | * e1000_set_eee_i354 - Enable/disable EEE support | ||||
* @hw: pointer to the HW structure | * @hw: pointer to the HW structure | ||||
* @adv1g: boolean flag enabling 1G EEE advertisement | |||||
* @adv100m: boolean flag enabling 100M EEE advertisement | |||||
* | * | ||||
* Enable/disable EEE legacy mode based on setting in dev_spec structure. | * Enable/disable EEE legacy mode based on setting in dev_spec structure. | ||||
* | * | ||||
**/ | **/ | ||||
s32 e1000_set_eee_i354(struct e1000_hw *hw) | s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M) | ||||
{ | { | ||||
struct e1000_phy_info *phy = &hw->phy; | struct e1000_phy_info *phy = &hw->phy; | ||||
s32 ret_val = E1000_SUCCESS; | s32 ret_val = E1000_SUCCESS; | ||||
u16 phy_data; | u16 phy_data; | ||||
DEBUGFUNC("e1000_set_eee_i354"); | DEBUGFUNC("e1000_set_eee_i354"); | ||||
if ((hw->phy.media_type != e1000_media_type_copper) || | if ((hw->phy.media_type != e1000_media_type_copper) || | ||||
Show All 25 Lines | if (!hw->dev_spec._82575.eee_disable) { | ||||
/* Turn on EEE advertisement. */ | /* Turn on EEE advertisement. */ | ||||
ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, | ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, | ||||
E1000_EEE_ADV_DEV_I354, | E1000_EEE_ADV_DEV_I354, | ||||
&phy_data); | &phy_data); | ||||
if (ret_val) | if (ret_val) | ||||
goto out; | goto out; | ||||
phy_data |= E1000_EEE_ADV_100_SUPPORTED | | if (adv100M) | ||||
E1000_EEE_ADV_1000_SUPPORTED; | phy_data |= E1000_EEE_ADV_100_SUPPORTED; | ||||
else | |||||
phy_data &= ~E1000_EEE_ADV_100_SUPPORTED; | |||||
if (adv1G) | |||||
phy_data |= E1000_EEE_ADV_1000_SUPPORTED; | |||||
else | |||||
phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED; | |||||
ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, | ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, | ||||
E1000_EEE_ADV_DEV_I354, | E1000_EEE_ADV_DEV_I354, | ||||
phy_data); | phy_data); | ||||
} else { | } else { | ||||
/* Turn off EEE advertisement. */ | /* Turn off EEE advertisement. */ | ||||
ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, | ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, | ||||
E1000_EEE_ADV_DEV_I354, | E1000_EEE_ADV_DEV_I354, | ||||
&phy_data); | &phy_data); | ||||
▲ Show 20 Lines • Show All 646 Lines • Show Last 20 Lines |