📄 e1000_80003es2lan.c
字号:
page_select = GG82563_PHY_PAGE_SELECT; } else { /* * Use Alternative Page Select register to access * registers 30 and 31 */ page_select = GG82563_PHY_PAGE_SELECT_ALT; } temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); if (ret_val) { e1000_release_phy_80003es2lan(hw); goto out; } /* * The "ready" bit in the MDIC register may be incorrectly set * before the device has completed the "Page Select" MDI * transaction. So we wait 200us after each MDI command... */ udelay(200); /* ...and verify the command was successful. */ ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { ret_val = -E1000_ERR_PHY; e1000_release_phy_80003es2lan(hw); goto out; } udelay(200); ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); udelay(200); e1000_release_phy_80003es2lan(hw);out: return ret_val;}/** * e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register * @hw: pointer to the HW structure * @offset: offset of the register to read * @data: value to write to the register * * Write to the GG82563 PHY register. **/static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data){ s32 ret_val; u32 page_select; u16 temp; ret_val = e1000_acquire_phy_80003es2lan(hw); if (ret_val) goto out; /* Select Configuration Page */ if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { page_select = GG82563_PHY_PAGE_SELECT; } else { /* * Use Alternative Page Select register to access * registers 30 and 31 */ page_select = GG82563_PHY_PAGE_SELECT_ALT; } temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); if (ret_val) { e1000_release_phy_80003es2lan(hw); goto out; } /* * The "ready" bit in the MDIC register may be incorrectly set * before the device has completed the "Page Select" MDI * transaction. So we wait 200us after each MDI command... */ udelay(200); /* ...and verify the command was successful. */ ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { ret_val = -E1000_ERR_PHY; e1000_release_phy_80003es2lan(hw); goto out; } udelay(200); ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, data); udelay(200); e1000_release_phy_80003es2lan(hw);out: return ret_val;}/** * e1000_write_nvm_80003es2lan - Write to ESB2 NVM * @hw: pointer to the HW structure * @offset: offset of the register to read * @words: number of words to write * @data: buffer of data to write to the NVM * * Write "words" of data to the ESB2 NVM. **/static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, u16 words, u16 *data){ return e1000e_write_nvm_spi(hw, offset, words, data);}/** * e1000_get_cfg_done_80003es2lan - Wait for configuration to complete * @hw: pointer to the HW structure * * Wait a specific amount of time for manageability processes to complete. * This is a function pointer entry point called by the phy module. **/static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw){ s32 timeout = PHY_CFG_TIMEOUT; s32 ret_val = E1000_SUCCESS; u32 mask = E1000_NVM_CFG_DONE_PORT_0; if (hw->bus.func == 1) mask = E1000_NVM_CFG_DONE_PORT_1; while (timeout) { if (er32(EEMNGCTL) & mask) break; msleep(1); timeout--; } if (!timeout) { e_dbg("MNG configuration cycle has not completed.\n"); ret_val = -E1000_ERR_RESET; goto out; }out: return ret_val;}/** * e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex * @hw: pointer to the HW structure * * Force the speed and duplex settings onto the PHY. This is a * function pointer entry point called by the phy module. **/static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw){ s32 ret_val = E1000_SUCCESS; u16 phy_data; bool link; if (!(hw->phy.ops.read_reg)) goto out; /* * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed and duplex are forced. */ ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); if (ret_val) goto out; phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO; ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, phy_data); if (ret_val) goto out; e_dbg("GG82563 PSCR: %X\n", phy_data); ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_data); if (ret_val) goto out; e1000e_phy_force_speed_duplex_setup(hw, &phy_data); /* Reset the phy to commit changes. */ phy_data |= MII_CR_RESET; ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data); if (ret_val) goto out; udelay(1); if (hw->phy.autoneg_wait_to_complete) { e_dbg("Waiting for forced speed/duplex link " "on GG82563 phy.\n"); ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) goto out; if (!link) { /* * We didn't get link. * Reset the DSP and cross our fingers. */ ret_val = e1000e_phy_reset_dsp(hw); if (ret_val) goto out; } /* Try once more */ ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, 100000, &link); if (ret_val) goto out; } ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); if (ret_val) goto out; /* * Resetting the phy means we need to verify the TX_CLK corresponds * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. */ phy_data &= ~GG82563_MSCR_TX_CLK_MASK; if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED) phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5; else phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; /* * In addition, we must re-enable CRS on Tx for both half and full * duplex. */ phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data);out: return ret_val;}/** * e1000_get_cable_length_80003es2lan - Set approximate cable length * @hw: pointer to the HW structure * * Find the approximate cable length as measured by the GG82563 PHY. * This is a function pointer entry point called by the phy module. **/static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw){ struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; u16 phy_data, index; if (!(hw->phy.ops.read_reg)) goto out; ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); if (ret_val) goto out; index = phy_data & GG82563_DSPD_CABLE_LENGTH; if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE + 5) { ret_val = E1000_ERR_PHY; goto out; } phy->min_cable_length = e1000_gg82563_cable_length_table[index]; phy->max_cable_length = e1000_gg82563_cable_length_table[index+5]; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;out: return ret_val;}/** * e1000_get_link_up_info_80003es2lan - Report speed and duplex * @hw: pointer to the HW structure * @speed: pointer to speed buffer * @duplex: pointer to duplex buffer * * Retrieve the current speed and duplex configuration. **/static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, u16 *duplex){ s32 ret_val; if (hw->phy.media_type == e1000_media_type_copper) { ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); hw->phy.ops.cfg_on_link_up(hw); } else { ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, speed, duplex); } return ret_val;}/** * e1000_reset_hw_80003es2lan - Reset the ESB2 controller * @hw: pointer to the HW structure * * Perform a global reset to the ESB2 controller. **/static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw){ u32 ctrl, icr; s32 ret_val; /* * Prevent the PCI-E bus from sticking if there is no TLP connection * on the last TLP read/write transaction when MAC is reset. */ ret_val = e1000e_disable_pcie_master(hw); if (ret_val) e_dbg("PCI-E Master disable polling has failed.\n"); e_dbg("Masking off all interrupts\n"); ew32(IMC, 0xffffffff); ew32(RCTL, 0); ew32(TCTL, E1000_TCTL_PSP); e1e_flush(); msleep(10); ctrl = er32(CTRL); ret_val = e1000_acquire_phy_80003es2lan(hw); e_dbg("Issuing a global reset to MAC\n"); ew32(CTRL, ctrl | E1000_CTRL_RST); e1000_release_phy_80003es2lan(hw); ret_val = e1000e_get_auto_rd_done(hw); if (ret_val) /* We don't want to continue accessing MAC registers. */ goto out; /* Clear any pending interrupt events. */ ew32(IMC, 0xffffffff); icr = er32(ICR); e1000_check_alt_mac_addr_generic(hw);out: return ret_val;}/** * e1000_init_hw_80003es2lan - Initialize the ESB2 controller * @hw: pointer to the HW structure * * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. **/static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw){ struct e1000_mac_info *mac = &hw->mac; u32 reg_data; s32 ret_val; u16 i; e1000_initialize_hw_bits_80003es2lan(hw); /* Initialize identification LED */ ret_val = mac->ops.id_led_init(hw); if (ret_val) { e_dbg("Error initializing identification LED\n"); /* This is not fatal and we should not stop init due to this */ } /* Disabling VLAN filtering */ e_dbg("Initializing the IEEE VLAN\n"); e1000e_clear_vfta(hw); /* Setup the receive address. */ e1000e_init_rx_addrs(hw, mac->rar_entry_count); /* Zero out the Multicast HASH table */ e_dbg("Zeroing the MTA\n"); for (i = 0; i < mac->mta_reg_count; i++) E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); /* Setup link and flow control */ ret_val = mac->ops.setup_link(hw); /* Set the transmit descriptor write-back policy */ reg_data = er32(TXDCTL(0)); reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; ew32(TXDCTL(0), reg_data); /* ...for both queues. */ reg_data = er32(TXDCTL(1)); reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC; ew32(TXDCTL(1), reg_data); /* Enable retransmit on late collisions */ reg_data = er32(TCTL); reg_data |= E1000_TCTL_RTLC; ew32(TCTL, reg_data); /* Configure Gigabit Carry Extend Padding */ reg_data = er32(TCTL_EXT); reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN; ew32(TCTL_EXT, reg_data); /* Configure Transmit Inter-Packet Gap */ reg_data = er32(TIPG); reg_data &= ~E1000_TIPG_IPGT_MASK; reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; ew32(TIPG, reg_data); reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001); reg_data &= ~0x00100000; E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); /* * Clear all of the statistics registers (clear on read). It is * important that we do this after we have tried to establish link * because the symbol error count will increment wildly if there * is no link. */ e1000_clear_hw_cntrs_80003es2lan(hw); return ret_val;}/** * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2 * @hw: pointer to the HW structure * * Initializes required hardware-dependent bits needed for normal operation. **/static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw){ u32 reg; /* Transmit Descriptor Control 0 */ reg = er32(TXDCTL(0)); reg |= (1 << 22); ew32(TXDCTL(0), reg); /* Transmit Descriptor Control 1 */ reg = er32(TXDCTL(1)); reg |= (1 << 22); ew32(TXDCTL(1), reg); /* Transmit Arbitration Control 0 */ reg = er32(TARC(0)); reg &= ~(0xF << 27); /* 30:27 */ if (hw->phy.media_type != e1000_media_type_copper) reg &= ~(1 << 20); ew32(TARC(0), reg); /* Transmit Arbitration Control 1 */ reg = er32(TARC(1)); if (er32(TCTL) & E1000_TCTL_MULR) reg &= ~(1 << 28); else reg |= (1 << 28); ew32(TARC(1), reg); return;}/** * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -